diff --git a/.gitignore b/.gitignore index a03e315..b189bfc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,7 @@ *.log *.tlog *.aps +*.user .vs/ +debug/ diff --git a/TapCompressionTool/C64TapCompression/C64TapCompression.vcxproj b/TapCompressionTool/C64TapCompression/C64TapCompression.vcxproj index 8d8a14e..69155b1 100644 --- a/TapCompressionTool/C64TapCompression/C64TapCompression.vcxproj +++ b/TapCompressionTool/C64TapCompression/C64TapCompression.vcxproj @@ -142,9 +142,6 @@ true - - - diff --git a/TapCompressionTool/C64TapCompression/ReadMe.txt b/TapCompressionTool/C64TapCompression/ReadMe.txt deleted file mode 100644 index b4b342c..0000000 --- a/TapCompressionTool/C64TapCompression/ReadMe.txt +++ /dev/null @@ -1,40 +0,0 @@ -======================================================================== - CONSOLE APPLICATION : C64TapCompression Project Overview -======================================================================== - -AppWizard has created this C64TapCompression application for you. - -This file contains a summary of what you will find in each of the files that -make up your C64TapCompression application. - - -C64TapCompression.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -C64TapCompression.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -C64TapCompression.cpp - This is the main application source file. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named C64TapCompression.pch and a precompiled types file named StdAfx.obj. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" comments to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/TapCompressionTool/C64TapCompression/Release/Resource.res b/TapCompressionTool/C64TapCompression/Release/Resource.res index bec3c1d..2de4029 100644 Binary files a/TapCompressionTool/C64TapCompression/Release/Resource.res and b/TapCompressionTool/C64TapCompression/Release/Resource.res differ diff --git a/TapCompressionTool/C64TapCompression/Resource.rc b/TapCompressionTool/C64TapCompression/Resource.rc index 5887a5d..a20dbc3 100644 Binary files a/TapCompressionTool/C64TapCompression/Resource.rc and b/TapCompressionTool/C64TapCompression/Resource.rc differ diff --git a/TapCompressionTool/C64TapCompression/TapCompression.cpp b/TapCompressionTool/C64TapCompression/TapCompression.cpp index 55e4157..17be1f2 100644 --- a/TapCompressionTool/C64TapCompression/TapCompression.cpp +++ b/TapCompressionTool/C64TapCompression/TapCompression.cpp @@ -1,9 +1,6 @@ - #include "stdafx.h" - #include #include - #include #include @@ -12,354 +9,21 @@ using namespace std; -#define BITS_INDEX 8 // 8,9 or 10 good value is 10 -#define BITS_REPEAT (16 - BITS_INDEX) -#define WINDOW_SIZE (1<> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - a &= REPEAT_MASK; - for (int i = 0; i <= a; i++) { - u8 v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - fputc(v, fileWrite); - } - } - } - fclose(fileWrite); - fclose(fileRead); -} - - -#define FAT_BUF_SIZE 128 - -u8 g_fat_buffer[FAT_BUF_SIZE]; - -void LZLikeDecodeToFile2(const char* fileName) -{ - - memset(g_fat_buffer,0, FAT_BUF_SIZE); - memset(window, 0, FAT_BUF_SIZE); - - FILE* fileRead; - fopen_s(&fileRead, fileName, "rb"); - fseek(fileRead, 0, SEEK_END); - long size = ftell(fileRead); - fseek(fileRead, 0, SEEK_SET); - FILE* fileWrite; - fopen_s(&fileWrite, "C:\\Users\\Admin\\Desktop\\New folder\\temp.tap", "wb"); - - - printf("FAT_BUF_SIZE %d\n", FAT_BUF_SIZE); - printf("size %d\n", size); - printf("size/FAT_BUF_SIZE %d\n", size/ FAT_BUF_SIZE); - - uint32_t head = 0; - for (uint32_t i = 0; i> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - a &= REPEAT_MASK; - for (uint16_t i = 0; i <= a; i++) { - uint8_t v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - size_t r = fwrite(&v, 1, 1, fileWrite); - } - } - } - } - - - u16 leftover = size % FAT_BUF_SIZE; - if (leftover) { - - size_t r = fread(&g_fat_buffer[0], leftover, 1, fileRead); - - for (uint8_t k = 0; k> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - a &= REPEAT_MASK; - for (uint16_t i = 0; i <= a; i++) { - uint8_t v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - size_t r = fwrite(&v, 1, 1, fileWrite); - } - } - } - - } - - fclose(fileWrite); - fclose(fileRead); -} - - -u8 writeCache[16]; - -void LZLikeDecodeToFile3(const char* fileName) -{ - - memset(g_fat_buffer, 0, FAT_BUF_SIZE); - memset(window, 0, WINDOW_SIZE); - memset(writeCache, 0, 16); - - FILE* fileRead; - fopen_s(&fileRead, fileName, "rb"); - fseek(fileRead, 0, SEEK_END); - long size = ftell(fileRead); - fseek(fileRead, 0, SEEK_SET); - FILE* fileWrite; - fopen_s(&fileWrite, "C:\\Users\\Admin\\Desktop\\New folder\\temp.tap", "wb"); - - - printf("FAT_BUF_SIZE %d\n", FAT_BUF_SIZE); - printf("size %d\n", size); - printf("size/FAT_BUF_SIZE %d\n", size / FAT_BUF_SIZE); - - uint32_t head = 0; - u16 amount = 0; - for (uint32_t i = 0; i> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - g_fat_buffer[k + 0] &= REPEAT_MASK; - for (uint16_t i = 0; i <= g_fat_buffer[k + 0]; i++) { - uint8_t v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - writeCache[amount] = v; - amount++; - if (amount == 16) { - fwrite(&writeCache[0], 16, 1, fileWrite); - amount = 0; - } - } - } - } - } - - u16 leftover = size % FAT_BUF_SIZE; - if (leftover) { - size_t r = fread(&g_fat_buffer[0], leftover, 1, fileRead); - for (uint8_t k = 0; k> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - g_fat_buffer[k + 0] &= REPEAT_MASK; - for (uint16_t i = 0; i <= g_fat_buffer[k + 0]; i++) { - uint8_t v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - writeCache[amount] = v; - amount++; - if (amount == 16) { - fwrite(&writeCache[0], 16, 1, fileWrite); - amount = 0; - } - } - } - } - } - - if (amount > 0) { - fwrite(&writeCache[0], amount, 1, fileWrite); - } - - fclose(fileWrite); - fclose(fileRead); -} - - -//uint16_t head = 0; -u8 amount = 0; // write cache will be small (well under a byte !! 16bytes maybe , 32 tops ) -//FILE* fileRead; -//FILE* fileWrite; - -void decodeSection( /* FILE* fileRead, FILE* FileWrite ,*/ u16 amountToRead) { - size_t r = fread(&g_fat_buffer[0], amountToRead, 1, fileRead); - for (uint8_t k = 0; k> (8 - SHIFT)) << 8)) + WINDOW_SIZE; - g_fat_buffer[k + 0] &= REPEAT_MASK; - for (uint16_t i = 0; i <= g_fat_buffer[k + 0]; i++) { - uint8_t v = window[(idx + i)&(WINDOW_SIZE - 1)]; - window[(head++)&(WINDOW_SIZE - 1)] = v; - writeCache[amount++] = v; - if (amount == 16) { - fwrite(&writeCache[0], 16, 1, fileWrite); - amount = 0; - } - } - } - } -} - - -void LZLikeDecodeToFile4(const char* fileName) { - - head = 0; - amount = 0; - - //FILE* fileRead; - fopen_s(&fileRead, fileName, "rb"); - fseek(fileRead, 0, SEEK_END); - long size = ftell(fileRead); - fseek(fileRead, 0, SEEK_SET); -// FILE* fileWrite; - fopen_s(&fileWrite, "C:\\Users\\Admin\\Desktop\\New folder\\temp.tap", "wb"); - - printf("FAT_BUF_SIZE %d\n", FAT_BUF_SIZE); - printf("size %d\n", size); - printf("size/FAT_BUF_SIZE %d\n", size / FAT_BUF_SIZE); - - for (uint32_t i = 0; i 0) { - fwrite(&writeCache[0], amount, 1, fileWrite); - } - - fclose(fileWrite); - fclose(fileRead); -} - +#define FAT_BUF_SIZE (128) +u8 window[WINDOW_SIZE]; u8* LZLikeDecode(u8 *out, u8 *in, u8 *end) { u16 head = 0; @@ -367,16 +31,12 @@ u8* LZLikeDecode(u8 *out, u8 *in, u8 *end) { u8 a = *(in++); u8 b = *(in++); if (a == 0) { - // no special repetition, cache and output disgarding 2nd byte + // no special repetition, recreate history window[(head++)&(WINDOW_SIZE - 1)] = b; *(out++) = b; } else { - // index : example 2 bits from 'a' and 8 bits from 'b' - - u16 idx = head - 1 - (b + ((a >> (8-SHIFT)) << 8)) + WINDOW_SIZE; - a &= REPEAT_MASK; // use the (say 6) bits left over - + u16 idx = head - 1 - b + WINDOW_SIZE; for (int i = 0; i <= a; i++) { u8 v = window[(idx + i)&(WINDOW_SIZE - 1)]; window[(head++)&(WINDOW_SIZE - 1)] = v; @@ -387,15 +47,11 @@ u8* LZLikeDecode(u8 *out, u8 *in, u8 *end) { return out; } - - u8* LZLikeEncode(u8 *out, u8 *in, u8 *end) { -// int i = 0; u8* pcurrentBlockStart = in; while (pcurrentBlockStart < end) { - u16 byteOrOffset = *pcurrentBlockStart; + u8 offset = *pcurrentBlockStart; u16 repetitionLength = 1; - // for (int wi = 0; wi < WINDOW_SIZE; wi++) { for (int wi = WINDOW_SIZE-1; wi > 0; wi--) { u8* psearchIndex = pcurrentBlockStart; if (psearchIndex > in + wi) { @@ -407,27 +63,21 @@ u8* LZLikeEncode(u8 *out, u8 *in, u8 *end) { } if (len > repetitionLength) { repetitionLength = len; // found a sequence in the past - byteOrOffset = wi; // distance we looked back in bytes - // i++; - + offset = wi; // distance we looked back in bytes if (len == REPEAT_LIMIT) break; } } } - - u8 v = (repetitionLength - 1) | ((byteOrOffset & 0xFF00) >> SHIFT); - - // * No sequence: writes [0],[byte] - // * Found sequence: writes [no# repetitions 6bits + 2bits offset],[8bits offset] - // WINDOW_SIZE uses 1024 in the case of 2^10bits - *(out++) = v; - *(out++) = byteOrOffset & 0xff; + // - No sequence: writes [0],[byte] + // - Found sequence: writes [8 repetitions bits],[8 offset bits] + // Remember an Arduino has to decode all this with its 2KB of dynamic memory to run the whole microcontroller. + // Even just using one extra bit on offset from repetitions, so 9 bits will eat 512bytes (and 10bits will eat 1024bytes) + // (8 is just doable at 256bytes without giving the Tapuino code a big facelift) + *(out++) = repetitionLength - 1; // how many repeating occurrences discovered + *(out++) = offset; // where to start history playback pcurrentBlockStart += repetitionLength; } - - //printf("%d\n", i); - return out; } @@ -437,49 +87,24 @@ u8* LZLikeEncode(u8 *out, u8 *in, u8 *end) { int main(int argc, char **argv) { string folder = ""; - if (argc == 2) { - folder = argv[1]; // "C:\\Users\\Admin\\Desktop\\New folder\\taps2compress\\"; - - // printf("%s\n", argv[1]); + folder = argv[1]; } else { - printf("ERROR: Missing command line pramater - please provide a path to your TAP files\n\n"); - - printf("This tool finds and compresses all TAP files inside a folder\n"); + printf("Help : This tool finds and compresses all TAP files inside a given folder\n"); printf(" - Orignal TAP files will not deleted\n"); printf(" - Compressed files will be created with a ZAP file extension\n\n"); - - printf("Example usage: Compresses tap files found in the... \n"); - printf(" TAPCOMPRESSION [.\\] tools run path\n"); - printf(" TAPCOMPRESSION [yourTaps\\] relative folder\n"); - printf(" TAPCOMPRESSION [c:\\data\\c64\\yourTaps\\] absolute path\n"); + printf("Example usage:\n"); + printf(" TAPCOMPRESSION [.\\] (tools run path)\n"); + printf(" TAPCOMPRESSION [yourTaps\\] (relative folder)\n"); + printf(" TAPCOMPRESSION [c:\\data\\c64\\yourTaps\\] (absolute path)\n"); getchar(); return 0; } -// printf("WINDOW_SIZE=%d\n", WINDOW_SIZE); - - - ////LZLikeDecodeToFile((folder + "180.zap").c_str()); - ////LZLikeDecodeToFile4((folder + "180.zap").c_str()); - // - //LZLikeReset(); - - //for (int i = 0; i < 1000; i++) { - // ReadDecodeAmount(g_fat_buffer, 128); - // fwrite(g_fat_buffer, 128, 1, fileWrite); - //} - //fclose(fileWrite); - - //fclose(fileRead); - //return 0; - WIN32_FIND_DATAA ffd; - printf("%s\n" , folder.c_str()); - -// todo missing end will crash \\ + printf("Packing all tap files found here: %s\n\n" , folder.c_str()); HANDLE hFind = FindFirstFileA((folder + "*.tap").c_str(), &ffd); @@ -488,8 +113,6 @@ int main(int argc, char **argv) return 0; } - int filesize = 0; - vector files; do { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -504,11 +127,12 @@ int main(int argc, char **argv) int totalOriginal = 0; int totalCompressed = 0; - + int passed = 0; for (vector::iterator it = files.begin(); it != files.end(); it++) { string fileName = *it; - printf("PROCESSING: %s\n", fileName.c_str()); + std::string inFilename = fileName.substr(fileName.find_last_of("/\\") + 1); + printf("%d) %s found, ", passed+1 , inFilename.c_str() ); FILE *f; fopen_s(&f, fileName.c_str(), "rb"); @@ -521,13 +145,15 @@ int main(int argc, char **argv) fclose(f); u8 *out = (u8*)malloc(2 * size); // worst case u8 *eout = LZLikeEncode(out, data, data + size); - printf("Compressed from %d to %d bytes...", (int)size, (int)(eout - out)); + printf("packed %d -> %d bytes, ", (int)size, (int)(eout - out)); totalOriginal += size; - totalCompressed += (eout - out); + totalCompressed += (int)(eout - out); //---------- string newfilename = fileName.substr(0, fileName.find_last_of('.')) + ".zap"; + std::string base_filename = newfilename.substr(newfilename.find_last_of("/\\") + 1); + printf("%s saved, ", base_filename.c_str()); // if (remove(newfilename.c_str())==-1) @@ -553,164 +179,20 @@ int main(int argc, char **argv) return 1; } else { - printf("verify OK\n"); + passed++; + printf("verify Passed\n"); } free(data); - free(dest); } } - printf("=========================\n"); - printf("Original Total : %d\n", totalOriginal); - printf("Compression Total: %d\n", totalCompressed); - printf("saving %d bytes, %dKB, %dMB \n", totalOriginal - totalCompressed, (totalOriginal - totalCompressed)/1024, (totalOriginal - totalCompressed)/1024/1024); - printf("=========================\n"); - getchar(); + printf("\nStats:\n%d bytes total for original taps\n", totalOriginal); + printf("%d bytes total for compressed\n", totalCompressed); + printf("saving %d bytes, %dKB, %dMB (%d files)\n", totalOriginal - totalCompressed, (totalOriginal - totalCompressed)/1024, (totalOriginal - totalCompressed)/1024/1024,passed); - -} - -int main2(int argc, char **argv) -{ - - printf(" BITS_INDEX:%d\n", BITS_INDEX); - printf(" BITS_REPEAT: %d\n", BITS_REPEAT); - printf(" WINDOW_SIZE: %d\n", WINDOW_SIZE); - printf(" SHIFT: %d\n", SHIFT); - printf(" REPEAT_LIMIT: %d\n", REPEAT_LIMIT); - printf(" REPEAT_MASK: %02x\n", REPEAT_MASK); - - if (argc != 3) - { - printf("Usage: c64convert source.tap dest.tpz\n"); - return 1; - } - FILE *f; - fopen_s(&f, argv[1], "rb"); - if (f) - { - fseek(f, 0, SEEK_END); - long size = ftell(f); - printf("Loaded %s (%d bytes)\n", argv[1], (int)size); - fseek(f, 0, SEEK_SET); - u8 *data = (u8*)malloc(size); - fread(data, 1, size, f); - fclose(f); - printf("Read done\n"); - u8 *out = (u8*)malloc(2 * size); // worst case - u8 *eout = LZLikeEncode(out, data, data + size); - printf("Compressed:%d/%d\n", (int)(eout - out), (int)size); - FILE *g; - fopen_s(&g, argv[2], "wb"); - if (g) - { - fwrite(out, 1, eout - out, g); - fclose(g); - } - else - { - printf("Couldn't open '%s' for write\n", argv[2]); - return 1; - } - u8 *dest = (u8*)malloc(size); - u8 *edest = LZLikeDecode(dest, out, eout); - - - // LZLikeDecodeToFile("_180.tap", out, eout); - - - if (memcmp(dest, data, size) != 0) - { - printf("Decompress error %d/%d\n", (int)(edest - dest), (int)size); - return 1; - } - } - else - { - printf("Couldn't open '%s' for read\n", argv[1]); - return 1; - } - return 0; + +// getchar(); } - - -//u8* LZLikeEncode(u8 *out, u8 *in, u8 *end) { -// int inDataSize = (int)(end - in); -// int currentBlockStart = 0; -// while (currentBlockStart < inDataSize) { -// int byteOrDistance = in[currentBlockStart]; -// int repetitionLength = 1; -// for (int wi = 0; wi < WINDOW_SIZE; wi++) { -// u8* psearchIndex = &in[currentBlockStart]; -// if (psearchIndex > in + wi) { -// int len = 0; -// while (*psearchIndex == *(psearchIndex - 1 - wi) && len < 64 && psearchIndex < end) { -// len++; -// psearchIndex++; -// } -// if (len > repetitionLength) { -// repetitionLength = len; // found more repetition in the past -// byteOrDistance = wi; // how far did we look back in bytes -// } -// } -// } -// -// int v = (repetitionLength - 1) | ((byteOrDistance >> 8) << 6); -// *(out++) = v; -// *(out++) = byteOrDistance; -// currentBlockStart += repetitionLength; -// } -// return out; -//} - -// -// -// -//u8* LZLikeEncode(u8 *out, u8 *in, u8 *end) { -// int inDataSize = (int)(end - in); -// int currentBlockStart = 0; -// while (currentBlockStart < inDataSize) { -// int byteOrDistance = in[currentBlockStart]; -// int repetitionLength = 1; -// for (int wi = 0; wi < WINDOW_SIZE; wi++) { -// int searchIndex = currentBlockStart; -// -// -// if (searchIndex - 1 - wi >= 0) { -// int len = 0; -// while (in[searchIndex] == in[searchIndex - 1 - wi] && len < 64 && searchIndex < inDataSize) { -// len++; -// searchIndex++; -// } -// if (len > repetitionLength) { -// repetitionLength = len; // found more repetition in the past -// byteOrDistance = wi; // how far did we look back in bytes -// } -// } -// } -// -// int v = (repetitionLength - 1) | ((byteOrDistance >> 8) << 6); -// *(out++) = v; -// *(out++) = byteOrDistance; -// currentBlockStart += repetitionLength; -// } -// return out; -//} -// -//void printBits(size_t const size, void const * const ptr) -//{ -// unsigned char *b = (unsigned char*)ptr; -// unsigned char byte; -// int i, j; -// -// for (i = size - 1; i >= 0; i--) { -// for (j = 7; j >= 0; j--) { -// byte = (b[i] >> j) & 1; -// printf("%u", byte); -// } -// } -// puts(""); -//} \ No newline at end of file