First, thank rgwan for sharing the source code. Here is the DOS version I modified, which can be compiled with TC2.0 or BC3.1.
Due to the memory limitations of DOS, it's impossible to directly apply for a large amount of memory like in protected mode. Therefore, data decoding needs to frequently perform file reads and writes. The disk IO speed is naturally not as fast as memory, and the efficiency is worse than the CMD version.
#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);
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, "rb");
if (!fpin)
{
fprintf(stderr, "Can't open source HD-COPY image!\n");
exit(-1);
}
fpout = fopen(argv, "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 == 0xff && buffer == 0x18)
{
printf("Source img is an HD-COPY 2.0 Image\n");
nActualImgAddr = 14; /* Skip the file header marked with the volume label */
nImgDataAddr = nActualImgAddr + 2 + 168; /* Start of track data */
}
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; /* total tracks - 1 */
nSecPerTrack = buffer;
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); /* Capacity of a standard track */
hdcopy = malloc(nBytesPerTrack); /* Store compressed track data */
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 != 0x01) /* The mapping is an empty track */
{
memset(plain, 0x00, nBytesPerTrack);
fwrite(plain, nBytesPerTrack, 1, fpout);
continue;
}
fseek(fpin, nFinPos, SEEK_SET);
fread(buffer, 2, 1, fpin);
nDataLen = buffer + (buffer << 8); /* little endian */
memset(hdcopy, 0x00, nBytesPerTrack);
fread(hdcopy, nDataLen, 1, fpin);
nFinPos = nFinPos + 2 + nDataLen;
escByte = hdcopy;
for (k = 1; k < nDataLen; k++) /* Decompress the track content compressed by RLE */
{
if (hdcopy == escByte)
{
k++;
repeatByte = hdcopy;
repeat = hdcopy;
for (r = 0; r < repeat; r++)
{
*(plain++) = repeatByte;
}
}
else
{
*(plain++) = hdcopy;
}
}
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 ]