Board logo

标题: 写了个HD-COPY IMG转普通IMA格式软盘镜像的软件 [打印本页]

作者: rgwan     时间: 2018-3-20 00:22    标题: 写了个HD-COPY IMG转普通IMA格式软盘镜像的软件

废话少说,放源码!

https://github.com/rgwan/hdcopy-tools

编译好的程序下载:

http://upload.cn-dos.net/img/2357.zip

另外求UCDOS3.1版的扩充字库!感激不尽!打算做一些压缩和优化,使得它们继续发挥余热!

[ Last edited by rgwan on 2018-3-20 at 00:23 ]
作者: LoggerVick     时间: 2018-3-20 00:31
不过可能你的附件会很少有人下载,我先顶一下。
作者: LoggerVick     时间: 2018-3-20 00:36


  Quote:
Originally posted by rgwan at 2018-3-20 00:22:
废话少说,放源码!

https://github.com/rgwan/hdcopy-tools

编译好的程序下载:

http://upload.cn-dos.net/img/2357.zip

另外求UCDOS3.1版的扩 ...

我已经向我加的联盟群询问字库了,有的话应该会提示你去那个群下载。

[ Last edited by LoggerVick on 2018-3-20 at 00:46 ]
作者: rgwan     时间: 2018-3-20 08:46
http://www.cn-dos.net/forum/viewth ... =%E6%B1%87%E9%BE%99

已经找到啦,感谢mys先生!
作者: crshen     时间: 2018-3-20 12:19
程序不错,英文语句稍有点不统一,前面是decompress,后面是Decode,两者有点区别的。
另外提个小建议,这种DOS程序最好使用TC或者BC,DOS文本格式,GCC对很多初入门者有点复杂。C99标准比较晚,而程序中只用了stdint.h中的数据类型,如果改成老标准C89更方便大家学习。
作者: crshen     时间: 2018-3-20 13:25
刚转换到TC2.0,编译后DOS下测试发现严重问题,看来对hd-copy的img格式分析还不全面。确认为hd-copy 2.0a的img居然解压不出,只写出个32k的头。再测试gcc编译版本,完全不支持DOS,cmd下可以运行,但是解压img却出错退出。
作者: crshen     时间: 2018-3-20 13:38
既然源码是牛X的WTFPL开源协议,我就乱改了
DOS版源码请看后面第14楼层,下载地址在15楼。





[ Last edited by crshen on 2018-3-21 at 16:24 ]
作者: rgwan     时间: 2018-3-20 18:59
能否将出错的Image发给我?另外的,这个程序其实并不运行在DOS环境下。设计上是配合Windows/Linux,给虚拟机使用的。

此外,我做了一些修复,不知对于您的Image是否奏效。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(int argc, char *argv[])
{
        FILE *fp;
        uint8_t *hdcopy;
        uint8_t *plain;
        uint32_t length;
        uint32_t fit_size = 0;

        int i, j, k, r;

        if(argc != 3 && argc != 4)
        {
                fprintf(stderr, "Usage: %s <HD-COPY Image> <IMA plain floppy image> [size]\n\n", argv[0]);
                fprintf(stderr, "This small tool can decompress HD-COPY image to plain floppy image.\n");
                fprintf(stderr, "It can help you to use old HD-COPY image on modern PC,\nespecially on Virtual Machine to test out old-school softwares.\n\n");
                fprintf(stderr, "Zhiyuan Wan <h@iloli.bid> 2018, License WTFPL.\nAlgorithm analyze from <https://github.com/ciel-yu/devnotes>. Thanks him!\n");
                exit(-1);
        }
        if(argc == 4)
        {
                fit_size = atoi(argv[3]);
        }
        fp = fopen(argv[1], "rb");
        if(!fp)
        {
                fprintf(stderr, "Can't open source HD-COPY image!\n");
                exit(-1);
        }
        fseek(fp, 0, SEEK_END);
        length = ftell(fp);

        hdcopy = malloc(length);
        plain = malloc(0x168000);

        fseek(fp, 0, SEEK_SET);

        fread(hdcopy, length, 1, fp);

        printf("Decompressing HD-COPY Image\nInput size = %d\n", length);
        fclose(fp);

        uint8_t *actualimage;

        uint8_t *payload;

        if(hdcopy[0] == 0xff && hdcopy[1] == 0x18)
        {
                printf("That is an HD-COPY 2.0 Image\n");
                actualimage = hdcopy + 0x0e; /* 跳过标有卷标的文件头 */
                payload = actualimage + 2 + 168; /* 载荷段 */
        }
        else
        {
                printf("That is an HD-COPY 1.7 Image\n");
                actualimage = hdcopy;
                payload = actualimage + 2 + 164;
        }
        /* 开始解码 */
        int maxTrackCount = actualimage[0];
        int secPerTrack = actualimage[1];

        printf("maxTrackCount = %d, secPerTrack = %d\n", maxTrackCount, secPerTrack);
        uint8_t *dataTrack = actualimage + 2; /* 有数据的磁道表 */

        uint8_t *decomp_p = plain;

        memset(plain, 0x00, 0x168000);

        for(i = 0; i < maxTrackCount; i++)
        {
                for(j = 0; j < 2; j++)
                {
                        if(dataTrack[(i * 2) + j] != 0x01)
                        {
                                decomp_p += 512 * secPerTrack;
                                continue;
                        }
                        int dataLen = payload[0] + (payload[1] << 8);
                        payload += 2;
                        uint8_t escByte; /* RLE 压缩 */
                        for(k = 0; k < dataLen; k++)
                        {
                                if(k == 0)
                                {
                                        escByte = payload[0];
                                }
                                else
                                {
                                        if(payload[k] == escByte)
                                        {
                                                k++;
                                                uint8_t repeatByte = payload[k++];
                                                int repeat = payload[k];

                                                for(r = 0; r < repeat; r++)
                                                {
                                                        *(decomp_p++) = repeatByte;
                                                }
                                        }
                                        else
                                        {
                                                *(decomp_p++) = payload[k];
                                        }
                                }
                        }
                        payload += dataLen;
                }
        }
        uint16_t secCount = plain[0x13] + (plain[0x14] << 8);
        printf("Floppy sector count = %d, fitting to %d bytes\n",
                   secCount, fit_size > 0 ? fit_size : secCount * 512);
        printf("Decompress operation completed, write it to file\n");
        fp = fopen(argv[2], "wb+");
        if(!fp)
        {
                fprintf(stderr, "Can't save plain floppy image!\n");
                goto deal;
        }
        fseek(fp, 0, SEEK_SET);
        fwrite(plain, fit_size > 0 ? fit_size : (secCount * 512 > 0 ? secCount * 512 : 0x168000), 1, fp);
        fclose(fp);

deal:
        free(hdcopy);
        free(plain);
        return 0;
}
[ Last edited by rgwan on 2018-3-20 at 19:01 ]
作者: LoggerVick     时间: 2018-3-20 22:11


  Quote:
Originally posted by rgwan at 2018-3-20 18:59:
能否将出错的Image发给我?另外的,这个程序其实并不运行在DOS环境下。设计上是配合Windows/Linux,给虚拟机使用的。

此外,我做了一些修复,不知对 ...

他qq不加好友,你加入群可以搜索一下crshen然后他看到就能给你。
作者: LoggerVick     时间: 2018-3-20 22:38
或者试试新dos时代纪念光盘crshen留的email
作者: LoggerVick     时间: 2018-3-20 23:06
crshen:@[论坛]Willard 知道,我今天单位夜班,没法回他,一晚不睡,明天要睡一天,估计明下午4点后回复他吧。
作者: crshen     时间: 2018-3-21 15:36
回复rgwan:
经测试,程序已基本能解压HD-copy的img,但是源码中存在些瑕疵:
1、i 的 for 循环明显错误,查看img格式文档,byte    tracks; // total tracks - 1,这里是以0起计数的,80道显示为79,故要改for (i = 0; i <= maxTrackCount; i++),否则在一些比较满的磁盘会缺一个磁道数据。
2、对 for(k = 0; k < dataLen; k++) 中k==0的判断,几乎每个磁道将进行上万次,影响效率,可改:
escByte = payload[0];
            for (k = 1; k < dataLen; k++){}
作者: crshen     时间: 2018-3-21 15:44
软件测试环境:
1、Ubuntu 16.04 ,gcc编译,命令行下运行正常;
2、Win7 x64 + CodeBlocks 17.12 mingw,cmd环境运行正常;
3、XP + cfree5.0默认gcc3.45,cmd环境运行正常;
4、DOS 6.22 + Turbo C 2.0,运行正常,拷贝到win98,command下运行正常。

测试方法:
1、磁盘映像,选用mys的起步DOS网站下10个HD-COPY img,包括1.44M和1.2M;
2、单命令行执行;
3、批处理执行:for %i in (dir *.img) do dehd.exe %i dest\%i (将当前目录下所有HD-COPY格式img 转换到 标准格式img,保存至dest目录下同名文件)。
作者: crshen     时间: 2018-3-21 15:51
首先感谢rgwan分享源码,这里是我修改的DOS版本,可用TC2.0或BC3.1编译。

由于DOS内存限制,不可能像保护模式下那样直接申请一个大内存,故数据解码需频繁进行文件读写,磁盘IO速度自然比不上内存,效率较CMD版要差些。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE *fpin, *fpout;
    unsigned char *buffer, *hdcopy, *plain, *pnDataTrkMap;
    int nTrackCount, nSecPerTrack, nBytesPerTrack, nActualImgAddr, nImgDataAddr, escByte, repeatByte, repeat;
    unsigned int nDataLen;
    unsigned long nFinPos;
    int i, j, k, r;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <HD-COPY Image> <IMA plain floppy image>\n\n", argv[0]);
        fprintf(stderr, "This small tool decompress HD-COPY image to plain floppy image.\n");
        fprintf(stderr, "Therefore, you can use old HD-COPY img on modern PC or Virtual Machine.\n\n");
        fprintf(stderr, "Zhiyuan Wan <h@iloli.bid> 2018, License WTFPL.\nAlgorithm analyze from <https://github.com/ciel-yu/devnotes>. Thanks him!\n");
        fprintf(stderr, "Modified to suit old DOS by crshen <crshen@qq.com>.\n\n");
        exit(-1);
    }
    fpin = fopen(argv[1], "rb");
    if (!fpin)
    {
        fprintf(stderr, "Can't open source HD-COPY image!\n");
        exit(-1);
    }

    fpout = fopen(argv[2], "wb+");
    if (!fpout)
    {
        fprintf(stderr, "Can't save plain floppy image!\n");
        exit(-1);
    }

    buffer = malloc(2);

    fseek(fpin, 0, SEEK_SET);
    fread(buffer, 2, 1, fpin);
    if (buffer[0] == 0xff && buffer[1] == 0x18)
    {
        printf("Source img is an HD-COPY 2.0 Image\n");
        nActualImgAddr = 14; /* 跳过标有卷标的文件头 */
        nImgDataAddr = nActualImgAddr + 2 + 168; /* 磁道数据起始 */
    }
    else
    {
        printf("Source img may be an HD-COPY 1.7 Image\n");
        nActualImgAddr = 0;
        nImgDataAddr = nActualImgAddr + 2 + 164;
    }

    fseek(fpin, nActualImgAddr, SEEK_SET);
    fread(buffer, 2, 1, fpin);
    nTrackCount = buffer[0];   /* total tracks - 1 */
    nSecPerTrack = buffer[1];
    nBytesPerTrack = 512 * nSecPerTrack;
    printf("nTrackCount = %d, nSecPerTrack = %d\n", nTrackCount, nSecPerTrack);

    pnDataTrkMap = malloc(2 * (nTrackCount + 1));
    fseek(fpin, nActualImgAddr + 2, SEEK_SET);  /* tracks_map */
    fread(pnDataTrkMap, 2 * (nTrackCount + 1), 1, fpin);

    plain = malloc(nBytesPerTrack); /* 一个标准磁道容量 */
    hdcopy = malloc(nBytesPerTrack); /* 存放压缩磁道数据 */
    nFinPos = nImgDataAddr;
    printf("Working hard,please wait...\n");
    fseek(fpout, 0, SEEK_SET);
    for (i = 0; i <= nTrackCount; i++)
    {
        for (j = 0; j < 2; j++)
        {
            if (pnDataTrkMap[(i * 2) + j] != 0x01) /* 映射为空磁道 */
            {
                memset(plain, 0x00, nBytesPerTrack);
                fwrite(plain, nBytesPerTrack, 1, fpout);
                continue;
            }
            fseek(fpin, nFinPos, SEEK_SET);
            fread(buffer, 2, 1, fpin);
            nDataLen = buffer[0] + (buffer[1] << 8); /* little endian */
            memset(hdcopy, 0x00, nBytesPerTrack);
            fread(hdcopy, nDataLen, 1, fpin);
            nFinPos = nFinPos + 2 + nDataLen;
            escByte = hdcopy[0];
            for (k = 1; k < nDataLen; k++)  /* RLE压缩的磁道内容解压 */
            {
                if (hdcopy[k] == escByte)
                {
                    k++;
                    repeatByte = hdcopy[k++];
                    repeat = hdcopy[k];
                    for (r = 0; r < repeat; r++)
                    {
                        *(plain++) = repeatByte;
                    }
                }
                else
                {
                    *(plain++) = hdcopy[k];
                }
            }
            plain -= nBytesPerTrack;
            fwrite(plain, nBytesPerTrack, 1, fpout);            
        }
    }

    fclose(fpin);
    fclose(fpout);
    free(hdcopy);
    free(buffer);
    free(pnDataTrkMap);
    free(plain);
    printf("Decompress operation completed.\n");
    return 0;
}
[ Last edited by crshen on 2018-3-21 at 16:27 ]
作者: crshen     时间: 2018-3-21 16:08
源码文件和已经预编译的程序可到百度网盘下载:
DOS软件共享\解压HD-COPY映像到标准img.rar

pan.baidu.com/s/1toVeHvm1PHUL1d-dstROmA
密码:b5n5


或者加 QQ群:中華DOS聯盟(8393170),到群文件中下载。

[ Last edited by crshen on 2018-3-21 at 16:25 ]
作者: rgwan     时间: 2018-3-22 09:56


  Quote:
Originally posted by crshen at 2018-3-21 15:36:
回复rgwan:
经测试,程序已基本能解压HD-copy的img,但是源码中存在些瑕疵:
1、i 的 for 循环明显错误,查看img格式文档,byte    tracks; // total tracks - 1 ...

感谢指出错误.已改并重新发布到GitHub....因为我手上的镜像较少,加上这东西一直属于临时工具的状态,因此便没有过多在意代码效率和无法复现的错误问题。

另外对于比较新的GCC,escByte的判断其实会被优化展开到外部。没有细想就写下了这样的代码。

向大家表示抱歉。
作者: rgwan     时间: 2018-3-22 10:11


  Quote:
Originally posted by crshen at 2018-3-21 15:51:
首先感谢rgwan分享源码,这里是我修改的DOS版本,可用TC2.0或BC3.1编译。

由于DOS内存限制,不可能像保护模式下那样直接申请一个大内存,故 ...

另外我也将您修改后的代码发上GitHub分享啦。
作者: zhiguo7908     时间: 2018-12-23 10:15
不能这么说
作者: TurboY     时间: 2020-3-26 20:28
真不错!
最近正好遇到个HD-COPY的映像文件,没有找到undisk,结果找到了这个。
作者: kmcc123     时间: 2020-4-16 14:33
if not exist "dest" (md "dest")

for /f "tokens=*" %%i in ('dir/s/b/a-d *.img') do dehd-cmd.exe "dest\%%i"

写任意目批处理,新建一个bat,与dehd-cmd同一目录
期待出个支持64位、支持IMG内置目录(有些老软件解出没有原目录),能批处理

[ Last edited by kmcc123 on 2020-4-16 at 14:35 ]
作者: mongnewer     时间: 2023-9-23 22:15    标题: 基于dehd-cmd.exe的壳程序,可在WIN10上运行。

dehd-cmd.exe解压程序可以顺利解压 HDCPY 方式的IMG文件,谢谢辛苦写码并分享,正想办法要查一些DOS的东西呢它就来了。为了方便在WIN10上查看并选择性地解压出需要的文件,做了个WIN10运行的壳程序放在站上了,第2430号。
程序在WIN10上添加了右键菜单,当鼠标右键选中某个IMG后点击,会启动壳程序,壳程序将选中的程序解压到临时目录,然后交给7z程序打开临时文件夹中的 IMA 文件,用户可查看解压等。当关闭7z窗口时,删除临时文件。 由于自己需要,草草写了几句,VB6的console程序,自己用着还行。压缩包里有安装和使用说明 Readme.pdf
作者: mongnewer     时间: 2023-9-25 10:49    标题: 基于dehd-cmd.exe代码改写的VisualFreeBASIC5.8.11代码

Sub Form1_Command1_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd)
   Command1.Enabled = False
   Dim sBuffer As String
   Dim pnDataTrkMap As String
   Dim splain As String     '/* 一个标准磁道容量 */
   Dim plain As Integer
   Dim shdcopy As String    '/* 存放压缩磁道数据 */
   Dim hdcopy As Integer
   Dim nFinPos As Unsigned Long
   Dim nDataLen As Unsigned Integer
   Dim stempString As String
   Dim iContFlag As Integer
   Dim nTrackCount As Integer, nSecPerTrack As Integer, nBytesPerTrack As Integer _
       ,nActualImgAddr As Integer, nImgDataAddr As Integer, escByte As Integer, repeatByte As Integer, repeat As Integer
   
   Open "1.IMG" For Binary Access Read As #1
   Open "11.IMA" For Binary Access Write As #2
   
   Seek #1, 1
   sBuffer = Input(2, #1)
      
   If ((sBuffer[0] = &Hff) And (sBuffer[1] = &H18)) Then
      'Source img is an HD-COPY 2.0 Image
      nActualImgAddr = 14                       'skip volume label
      nImgDataAddr = nActualImgAddr + 2 + 168   'Start position of data
   Else
      'Source img may be an HD-COPY 1.7 Image
      nActualImgAddr = 0
      nImgDataAddr = nActualImgAddr + 2 + 164
   End If
   
   Seek #1, nActualImgAddr + 1
   sBuffer = Input(2, #1)
   
   nTrackCount = sBuffer[0]   'Readout is (actual overall tracks - 1) e.g. (80-1) = 79
   nSecPerTrack = sBuffer[1]
   nBytesPerTrack = 512 * nSecPerTrack
   
   'Debug.Print "nTrackCount and nSecPerTrack", nTrackCount, nSecPerTrack
   'for a example, nSecPerTrack=15, and nBytesPerTrack = 512*nSecPerTrack, total disk = 512*nSecPerTrack*nTrackCount
   
   Seek #1, nActualImgAddr + 2 + 1     '/* tracks_map */
   pnDataTrkMap = Input(2 * (nTrackCount + 1), #1)
   
   'Debug.Print Len(pnDataTrkMap)
      
   plain = 0
   hdcopy = 0
   iContFlag = 0
   splain  = String(nBytesPerTrack, &H00)       '/* 一个标准磁道容量 */
   shdcopy = String(nBytesPerTrack, &H00)       '/* 存放压缩磁道数据 */
   
   nFinPos = nImgDataAddr
   'Debug.Print("Working hard,please wait...")
   Seek #2, 1
   
   For i As Integer = 0 To nTrackCount
      For j As Integer = 0 To 1
         iContFlag = 0
         If (pnDataTrkMap[(i * 2) + j] <> &H01) Then     '/* 映射为空磁道 */
            splain = String(nBytesPerTrack, &H00)
            Put #2,, splain
            
            'Continue in C, but set a flag in FreeBASIC for Continue purpose
            iContFlag = 1
         End If
         
         If iContFlag = 0 Then
            Seek #1, nFinPos + 1
            sBuffer = Input(2, #1)
            nDataLen = sBuffer[0] + (sBuffer[1] Shl 8)    '/* little endian */
            shdcopy = Input(nDataLen, #1)
   
            nFinPos = nFinPos + 2 + nDataLen
            escByte = shdcopy[0]
            
           For k As Integer = 1 To nDataLen - 1            '/* RLE压缩的磁道内容解压 */
                If shdcopy[k] = escByte Then
                    k = k +1
                    repeatByte = shdcopy[k]: k = k +1
                    repeat = shdcopy[k]
                    For r As Integer = 0 To repeat - 1
                        splain[plain] = repeatByte: plain = plain + 1
                    Next r
                Else
                    splain[plain] = shdcopy[k]: plain = plain + 1
                End If
           Next k
           plain- = nBytesPerTrack
           Put #2,, splain
         End If
      Next j
      'Debug.Print i   
   Next i

   Close #1
   Close #2
   MsgBox("Conversion completed!", "Information", MB_OK Or MB_ICONINFORMATION)
   Command1.Enabled = True
End Sub
作者: mongnewer     时间: 2023-9-25 12:21    标题: 基于dehd-cmd.exe代码改写的VC6代码

'The rewritten codes uses dehd-cmd.exe originall codes,
'in addition, one minor error skipped off when continue
'occurs at the final track by JUST close the files and
'return 0 to force the program to END for Completion.
'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE *fpin, *fpout;
        unsigned int nBytesPerTrack;
        unsigned char repeatByte;
    unsigned char *buffer, *hdcopy, *plain, *pnDataTrkMap;
    unsigned long nTrackCount, nSecPerTrack, nActualImgAddr, nImgDataAddr, escByte, repeat;
    unsigned long nDataLen;
    unsigned long nFinPos;
    unsigned long i, j, k, r;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <HD-COPY Image> <IMA plain floppy image>\n\n", argv[0]);
        fprintf(stderr, "This small tool decompress HD-COPY image to plain floppy image.\n");
        fprintf(stderr, "Therefore, you can use old HD-COPY img on modern PC or Virtual Machine.\n\n");
        fprintf(stderr, "Zhiyuan Wan <h@iloli.bid> 2018, License WTFPL.\nAlgorithm analyze from <https://github.com/ciel-yu/devnotes>. Thanks him!\n");
        fprintf(stderr, "Modified to suit old DOS by crshen <crshen@qq.com>.\n\n");
        exit(-1);
    }
   
        fpin = fopen(argv[1], "rb");
    if (!fpin)
    {
        fprintf(stderr, "Can't open source HD-COPY image!\n");
        exit(-1);
    }

    fpout = fopen(argv[2], "wb+");
    if (!fpout)
    {
        fprintf(stderr, "Can't save plain floppy image!\n");
        exit(-1);
    }

    buffer = (unsigned char *)malloc(2);

    fseek(fpin, 0, SEEK_SET);
    fread(buffer, 2, 1, fpin);
    if (buffer[0] == 0xff && buffer[1] == 0x18)
    {
        printf("Source img is an HD-COPY 2.0 Image\n");
        nActualImgAddr = 14; /* 跳过标有卷标的文件头 */
        nImgDataAddr = nActualImgAddr + 2 + 168; /* 磁道数据起始 */
    }
    else
    {
        printf("Source img may be an HD-COPY 1.7 Image\n");
        nActualImgAddr = 0;
        nImgDataAddr = nActualImgAddr + 2 + 164;
    }

    fseek(fpin, nActualImgAddr, SEEK_SET);
    fread(buffer, 2, 1, fpin);
    nTrackCount = buffer[0];   /* total tracks - 1 */
    nSecPerTrack = buffer[1];
    nBytesPerTrack = 512 * nSecPerTrack;
    printf("nTrackCount = %d, nSecPerTrack = %d\n", nTrackCount, nSecPerTrack);

    pnDataTrkMap = (unsigned char *)malloc(2 * (nTrackCount + 1));
    fseek(fpin, nActualImgAddr + 2, SEEK_SET);  /* tracks_map */
    fread(pnDataTrkMap, 2 * (nTrackCount + 1), 1, fpin);

    plain = (unsigned char *)malloc(nBytesPerTrack); /* 一个标准磁道容量 */
    hdcopy = (unsigned char *)malloc(nBytesPerTrack); /* 存放压缩磁道数据 */
    nFinPos = nImgDataAddr;
    printf("Working hard,please wait...\n");
    fseek(fpout, 0, SEEK_SET);

                        for (i = 0; i <= nTrackCount; i++)
                        {
                                for (j = 0; j < 2; j++)
                                {
                                        if (pnDataTrkMap[(i * 2) + j] != 0x01) /* 映射为空磁道 */
                                        {
                                                memset(plain, 0x00, nBytesPerTrack);
                                                fwrite(plain, nBytesPerTrack, 1, fpout);
                                                if (i==nTrackCount)
                                                        {
                                                                fclose(fpin);
                                                                fclose(fpout);
                                                                return 0;
                                                        }
                                                else{   continue;}
                                        }
                                       
                                        fseek(fpin, nFinPos, SEEK_SET);
                                        fread(buffer, 2, 1, fpin);
                                        nDataLen = buffer[0] + (buffer[1] << 8); /* little endian */
                                        memset(hdcopy, 0x00, nBytesPerTrack);
                                        fread(hdcopy, nDataLen, 1, fpin);
                                        nFinPos = nFinPos + 2 + nDataLen;
                                        escByte = hdcopy[0];
                                        for (k = 1; k < nDataLen; k++)  /* RLE压缩的磁道内容解压 */
                                        {
                                                if (hdcopy[k] == escByte)
                                                {
                                                        k++;
                                                        repeatByte = hdcopy[k++];
                                                        repeat = hdcopy[k];
                                                        for (r = 0; r < repeat; r++)
                                                        {
                                                                *(plain++) = repeatByte;
                                                        }
                                                }
                                                else
                                                {
                                                        *(plain++) = hdcopy[k];
                                                }
                                        }
                                        plain -= nBytesPerTrack;
                                        fwrite(plain, nBytesPerTrack, 1, fpout);            
                                }
                        }

    fclose(fpin);
    fclose(fpout);
    free(hdcopy);
    free(buffer);
    free(pnDataTrkMap);
    free(plain);
    printf("Decompress operation completed.\n");
    return 0;
}