#include "cruncher.h" #include //#define DEBUG #define max_offs 0x129f // 12bit offset limit. $129f #define max_offs_short 0x054f // 10bit offset limit. $054f uint offsTab[4] = {5,2,2,3}; uint offsTabShort[4] = {4,2,2,2}; byte *ibuf; byte obuf[memSize]; uint ibufSize; int get; //points to in[] uint put; //points to out[] _bool copyFlag; byte curByte; byte curCnt; uint plainLen; _bool errorFlag; #define cleanDecrLen 0x110 byte cleanDecrCode[cleanDecrLen] = { 0x0B, 0x08, 0x00, 0x00, 0x9E, 0x32, 0x30, 0x36, 0x31, 0x00, 0x00, 0x00, 0x78, 0xA9, 0x34, 0x85, 0x01, 0xA2, 0x3D, 0xBD, 0x1F, 0x08, 0x95, 0x06, 0xCA, 0x10, 0xF8, 0x4C, 0x08, 0x00, 0x00, 0x00, 0xA0, 0xFF, 0xB9, 0x00, 0x00, 0x99, 0x00, 0xFF, 0x88, 0xD0, 0xF7, 0xB1, 0x0B, 0x91, 0x0E, 0xC6, 0x0F, 0xC6, 0x0C, 0xA5, 0x0C, 0xC9, 0x08, 0xB0, 0xE7, 0xB9, 0x5D, 0x08, 0x99, 0x34, 0x03, 0xC8, 0xC0, 0xB4, 0x90, 0xF5, 0xA0, 0x02, 0xB1, 0x06, 0x99, 0x03, 0x00, 0x88, 0x10, 0xF8, 0x18, 0xA9, 0x03, 0x65, 0x06, 0x85, 0x06, 0x90, 0x02, 0xE6, 0x07, 0x4C, 0x34, 0x03, 0x20, 0xB8, 0x03, 0x08, 0xA9, 0x01, 0x20, 0xB8, 0x03, 0x90, 0x06, 0x20, 0xB8, 0x03, 0x2A, 0x10, 0xF5, 0x28, 0xB0, 0x18, 0x85, 0x02, 0xA0, 0x00, 0xB1, 0x06, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x02, 0x20, 0xD1, 0x03, 0xC8, 0xF0, 0xD7, 0x38, 0xB0, 0xD7, 0x69, 0x00, 0xF0, 0x4C, 0x85, 0x02, 0xC9, 0x03, 0xA9, 0x00, 0x85, 0x08, 0x85, 0x09, 0x2A, 0x20, 0xB8, 0x03, 0x2A, 0x20, 0xB8, 0x03, 0x2A, 0xAA, 0xBC, 0xE0, 0x03, 0x20, 0xB8, 0x03, 0x26, 0x08, 0x26, 0x09, 0x88, 0xD0, 0xF6, 0x8A, 0xCA, 0x29, 0x03, 0xF0, 0x08, 0xE6, 0x08, 0xD0, 0xE9, 0xE6, 0x09, 0xD0, 0xE5, 0x38, 0xA5, 0x04, 0xE5, 0x08, 0x85, 0x08, 0xA5, 0x05, 0xE5, 0x09, 0x85, 0x09, 0xB1, 0x08, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x00, 0x20, 0xD1, 0x03, 0x30, 0x84, 0xA9, 0x37, 0x85, 0x01, 0x58, 0x4C, 0x00, 0x00, 0x06, 0x03, 0xD0, 0x14, 0x48, 0x98, 0x48, 0xA0, 0x00, 0xB1, 0x06, 0xE6, 0x06, 0xD0, 0x02, 0xE6, 0x07, 0x38, 0x2A, 0x85, 0x03, 0x68, 0xA8, 0x68, 0x60, 0x18, 0x98, 0x75, 0x04, 0x95, 0x04, 0x90, 0x02, 0xF6, 0x05, 0xCA, 0xCA, 0x10, 0xF2, 0x60, 0x04, 0x02, 0x02, 0x02, 0x05, 0x02, 0x02, 0x03 }; #define normalDecrLen 0x11a byte normalDecrCode[normalDecrLen] = { 0x0B, 0x08, 0x00, 0x00, 0x9E, 0x32, 0x30, 0x36, 0x31, 0x00, 0x00, 0x00, 0x78, 0xA9, 0x34, 0x85, 0x01, 0xA2, 0x3B, 0xBD, 0x1F, 0x08, 0x95, 0x06, 0xCA, 0x10, 0xF8, 0x4C, 0x08, 0x00, 0x00, 0x00, 0xA0, 0xFF, 0xB9, 0x00, 0x00, 0x99, 0x00, 0xFF, 0x88, 0xD0, 0xF7, 0xB1, 0x0B, 0x91, 0x0E, 0xC6, 0x0F, 0xC6, 0x0C, 0xA5, 0x0C, 0xC9, 0x08, 0xB0, 0xE7, 0xB9, 0x5B, 0x08, 0x99, 0x34, 0x03, 0xC8, 0xD0, 0xF7, 0xA0, 0x02, 0xB1, 0x06, 0x99, 0x03, 0x00, 0x88, 0x10, 0xF8, 0x18, 0xA9, 0x03, 0x65, 0x06, 0x85, 0x06, 0x90, 0x02, 0xE6, 0x07, 0x4C, 0x34, 0x03, 0x20, 0xB8, 0x03, 0x08, 0xA9, 0x01, 0x20, 0xB8, 0x03, 0x90, 0x06, 0x20, 0xB8, 0x03, 0x2A, 0x10, 0xF5, 0x28, 0xB0, 0x18, 0x85, 0x02, 0xA0, 0x00, 0xB1, 0x06, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x02, 0x20, 0xDD, 0x03, 0xC8, 0xF0, 0xD7, 0x38, 0xB0, 0xD7, 0x69, 0x00, 0xF0, 0x4C, 0x85, 0x02, 0xC9, 0x03, 0xA9, 0x00, 0x85, 0x08, 0x85, 0x09, 0x2A, 0x20, 0xB8, 0x03, 0x2A, 0x20, 0xB8, 0x03, 0x2A, 0xAA, 0xBC, 0xEC, 0x03, 0x20, 0xB8, 0x03, 0x26, 0x08, 0x26, 0x09, 0x88, 0xD0, 0xF6, 0x8A, 0xCA, 0x29, 0x03, 0xF0, 0x08, 0xE6, 0x08, 0xD0, 0xE9, 0xE6, 0x09, 0xD0, 0xE5, 0x38, 0xA5, 0x04, 0xE5, 0x08, 0x85, 0x08, 0xA5, 0x05, 0xE5, 0x09, 0x85, 0x09, 0xB1, 0x08, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x00, 0x20, 0xDD, 0x03, 0x30, 0x84, 0xA9, 0x37, 0x85, 0x01, 0x58, 0x4C, 0x00, 0x00, 0x06, 0x03, 0xD0, 0x20, 0x48, 0x98, 0x48, 0xA0, 0x00, 0xB1, 0x06, 0xE6, 0x06, 0xD0, 0x02, 0xE6, 0x07, 0x38, 0x2A, 0x85, 0x03, 0xA9, 0x05, 0xE6, 0x01, 0x8D, 0x20, 0xD0, 0x8C, 0x20, 0xD0, 0xC6, 0x01, 0x68, 0xA8, 0x68, 0x60, 0x18, 0x98, 0x75, 0x04, 0x95, 0x04, 0x90, 0x02, 0xF6, 0x05, 0xCA, 0xCA, 0x10, 0xF2, 0x60, 0x04, 0x02, 0x02, 0x02, 0x05, 0x02, 0x02, 0x03 }; #define loadInitDecrLen 0x168 byte loadInitDecrCode[loadInitDecrLen] = { 0x0B, 0x08, 0x00, 0x00, 0x9E, 0x32, 0x30, 0x36, 0x34, 0x00, 0x00, 0x00, 0x4c, 0x3c, 0x08, 0xa5, 0xba, 0x20, 0xb1, 0xff, 0xa9, 0x6f, 0x20, 0x93, 0xff, 0xa9, 0x49, 0x20, 0xa8, 0xff, 0x20, 0xae, 0xff, 0xa5, 0xba, 0x20, 0xb1, 0xff, 0xa9, 0x6f, 0x20, 0x93, 0xff, 0xa2, 0x00, 0xbd, 0x43, 0x09, 0x20, 0xa8, 0xff, 0xe8, 0xe0, 0x26, 0x90, 0xf5, 0x20, 0xae, 0xff, 0xa9, 0x00, 0x8d, 0x11, 0xd0, 0x8d, 0x20, 0xd0, 0x78, 0xA9, 0x34, 0x85, 0x01, 0xA2, 0x3B, 0xBD, 0x56, 0x08, 0x95, 0x06, 0xCA, 0x10, 0xF8, 0x4C, 0x08, 0x00, 0x00, 0x00, 0xA0, 0xFF, 0xB9, 0x00, 0x00, 0x99, 0x00, 0xFF, 0x88, 0xD0, 0xF7, 0xB1, 0x0B, 0x91, 0x0E, 0xC6, 0x0F, 0xC6, 0x0C, 0xA5, 0x0C, 0xC9, 0x08, 0xB0, 0xE7, 0xB9, 0x92, 0x08, 0x99, 0x34, 0x03, 0xC8, 0xD0, 0xF7, 0xA0, 0x02, 0xB1, 0x06, 0x99, 0x03, 0x00, 0x88, 0x10, 0xF8, 0x18, 0xA9, 0x03, 0x65, 0x06, 0x85, 0x06, 0x90, 0x02, 0xE6, 0x07, 0x4C, 0x34, 0x03, 0x20, 0xB5, 0x03, 0x08, 0xA9, 0x01, 0x20, 0xB5, 0x03, 0x90, 0x06, 0x20, 0xB5, 0x03, 0x2A, 0x10, 0xF5, 0x28, 0xB0, 0x18, 0x85, 0x02, 0xA0, 0x00, 0xB1, 0x06, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x02, 0x20, 0xce, 0x03, 0xC8, 0xF0, 0xD7, 0x38, 0xB0, 0xD7, 0x69, 0x00, 0xF0, 0x4C, 0x85, 0x02, 0xC9, 0x03, 0xA9, 0x00, 0x85, 0x08, 0x85, 0x09, 0x2A, 0x20, 0xB5, 0x03, 0x2A, 0x20, 0xB5, 0x03, 0x2A, 0xAA, 0xBC, 0xdd, 0x03, 0x20, 0xB5, 0x03, 0x26, 0x08, 0x26, 0x09, 0x88, 0xD0, 0xF6, 0x8A, 0xCA, 0x29, 0x03, 0xF0, 0x08, 0xE6, 0x08, 0xD0, 0xE9, 0xE6, 0x09, 0xD0, 0xE5, 0x38, 0xA5, 0x04, 0xE5, 0x08, 0x85, 0x08, 0xA5, 0x05, 0xE5, 0x09, 0x85, 0x09, 0xB1, 0x08, 0x91, 0x04, 0xC8, 0xC4, 0x02, 0xD0, 0xF7, 0xA2, 0x00, 0x20, 0xce, 0x03, 0x30, 0x84, 0xe6, 0x01, 0x4C, 0x00, 0x00, 0x06, 0x03, 0xD0, 0x14, 0x48, 0x98, 0x48, 0xA0, 0x00, 0xB1, 0x06, 0xE6, 0x06, 0xD0, 0x02, 0xE6, 0x07, 0x38, 0x2A, 0x85, 0x03, 0x68, 0xA8, 0x68, 0x60, 0x18, 0x98, 0x75, 0x04, 0x95, 0x04, 0x90, 0x02, 0xF6, 0x05, 0xCA, 0xCA, 0x10, 0xF2, 0x60, 0x04, 0x02, 0x02, 0x02, 0x05, 0x02, 0x02, 0x03, 0x4d, 0x2d, 0x45, 0x0f, 0x02, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x0f, 0xa2, 0x09, 0xbd, 0x05, 0x02, 0x95, 0x00, 0xca, 0x10, 0xf8, 0xa9, 0x01, 0xaa, 0xd5, 0x00, 0xd0, 0xfc, 0xca, 0x10, 0xf9, 0x4c, 0x73, 0x03 }; void init(File *aSource) { get = ibufSize - 1; put = memSize - 1; curByte = 0; curCnt = 8; plainLen = 0; } inline void out(byte b) { #ifdef DEBUG printf("%i", b); #endif curByte >>= 1; curByte |= (b << 7); if((--curCnt) == 0) { #ifdef DEBUG printf("|"); #endif obuf[put] = curByte; if(put == 0) { printf("Error (C-1): Packed file too large.\n"); put = memSize - 1; // Avoid more damage.. errorFlag = _true; } --put; curCnt = 8; curByte = 0; } } inline void outLen(byte b) { #ifdef DEBUG printf(";"); #endif if(b < 0x80) out(0); while(b > 1) { out(b & 1); out(1); b >>= 1; } } inline void outCopyFlag() { if(copyFlag == 1) { out(1); copyFlag = 0; } } _bool scan(uint *theMatchLen, uint *theMatchOffset) { uint scn; uint matchLen = 0; uint matchOffset = 0; if(get < 2) { return _false; } scn = get - 1; register byte first = ibuf[get]; register byte second = ibuf[get - 1]; while(((get - scn) <= max_offs) && (scn > 0)){ if((ibuf[scn] == first) && (ibuf[scn - 1] == second)) { uint len = 2; while((len < 255) && (scn >= len) && (ibuf[scn - len] == ibuf[get - len])) { ++len; }; if(len > matchLen) { matchLen = len; matchOffset = get - scn; } } --scn; }; if((matchLen > 2) || ((matchLen == 2) && (matchOffset <= max_offs_short))) { *theMatchLen = matchLen; *theMatchOffset = matchOffset; return _true; } else { return _false; } } void copy(uint matchLen, uint matchOffset) { uint i = 0; copyFlag = 1; #ifdef DEBUG printf("C(%i, %i) ", matchLen, matchOffset); #endif // Put copy offset. while(i < 4) { uint b; if(matchLen == 2) { b = offsTabShort[i]; } else { b = offsTab[i]; } while(b > 0) { out(matchOffset & 1); matchOffset >>= 1; --b; }; if(matchOffset == 0) break; --matchOffset; ++i; }; // Put copy offset size. out(i & 1); out((i >> 1) & 1); // Put copy length. outLen(matchLen - 1); get -= matchLen; } void flush() { // Exit if there is nothing to flush. if(plainLen == 0) { outCopyFlag(); return; } #ifdef DEBUG printf("P(%i) ", plainLen); #endif // Put extra copy-bit if necessary. if((plainLen % 255) == 0) { outCopyFlag(); } // Put plain data. while(plainLen > 0) { uint i; uint len = ((plainLen - 1) % 255) + 1; if(put < len) { printf("Error (C-2): Packed file too large.\n"); put = memSize - 1; // Avoid more damage.. errorFlag = _true; } // Copy the data. for(i = 0; i < len; ++i) { obuf[put - i] = ibuf[get + plainLen - i]; } plainLen -= len; put -= len; // Put plain length. outLen(len); // Put plain-bit. out(0); }; plainLen = 0; } _bool crunch(File *aSource, File *aTarget, uint startAdress, uint theDecrType, _bool isRelocated) { uint i; uint theMatchLen, theMatchOffset; uint packLen, decrLen; byte *target; _bool attachDecr; errorFlag = _false; switch(theDecrType) { case noDecr: attachDecr = _false; decrLen = 0; break; case normalDecr: attachDecr = _true; decrLen = normalDecrLen; break; case cleanDecr: attachDecr = _true; decrLen = cleanDecrLen; break; case loadInitDecr: attachDecr = _true; decrLen = loadInitDecrLen; break; } ibufSize = aSource->size - 2; ibuf = (byte *)malloc(ibufSize); for(i = 0; i < ibufSize; ++i) { ibuf[i] = aSource->data[i + 2]; } init(aSource); outLen(0xff); // Put end of file. copyFlag = 1; #ifdef DEBUG printf("."); #endif while(get >= 0) { if(scan(&theMatchLen, &theMatchOffset)) { flush(); copy(theMatchLen, theMatchOffset); } else { ++plainLen; --get; } }; flush(); if(errorFlag == _true) { return _false; } //Copy obuf into aTarget!! packLen = memSize - put - 1; #ifdef DEBUG printf("\nsize = %i\n", packLen); #endif aTarget->size = packLen + decrLen + 5; aTarget->data = (byte *)malloc(aTarget->size); if(aTarget->data == NULL) { printf("Error (C-3): Out of memory.\n"); return _false; } target = aTarget->data + decrLen + 2; target[0] = (curByte | (1 << (curCnt - 1))); target[1] = aSource->data[0]; target[2] = aSource->data[1]; for(i = 0; i < packLen; ++i) { target[i + 3] = obuf[put + i + 1]; } switch(theDecrType) { case noDecr: { uint packStart; if(isRelocated) packStart = startAdress; else packStart = 0xfffa; packStart -= (packLen + 3); aTarget->data[0] = packStart & 0xff; aTarget->data[1] = packStart >> 8; break; } case cleanDecr: { uint packStart = 0xfffd - packLen; uint trnsStart = 0x0814 + packLen; cleanDecrCode[0x1e] = packStart & 0xff; cleanDecrCode[0x1f] = packStart >> 8; cleanDecrCode[0x23] = trnsStart & 0xff; cleanDecrCode[0x24] = trnsStart >> 8; cleanDecrCode[0xde] = startAdress & 0xff; cleanDecrCode[0xdf] = startAdress >> 8; target = aTarget->data + 2; for(i = 0; i < decrLen; ++i) { target[i] = cleanDecrCode[i]; } aTarget->data[0] = 0x01; aTarget->data[1] = 0x08; break; } case normalDecr: { uint packStart = 0xfffd - packLen; uint trnsStart = 0x081e + packLen; normalDecrCode[0x1e] = packStart & 0xff; normalDecrCode[0x1f] = packStart >> 8; normalDecrCode[0x23] = trnsStart & 0xff; normalDecrCode[0x24] = trnsStart >> 8; normalDecrCode[0xdc] = startAdress & 0xff; normalDecrCode[0xdd] = startAdress >> 8; target = aTarget->data + 2; for(i = 0; i < decrLen; ++i) { target[i] = normalDecrCode[i]; } aTarget->data[0] = 0x01; aTarget->data[1] = 0x08; break; } case loadInitDecr: { uint packStart = 0xfffd - packLen; uint trnsStart = 0x086c + packLen; loadInitDecrCode[0x55] = packStart & 0xff; loadInitDecrCode[0x56] = packStart >> 8; loadInitDecrCode[0x5a] = trnsStart & 0xff; loadInitDecrCode[0x5b] = trnsStart >> 8; loadInitDecrCode[0x110] = startAdress & 0xff; loadInitDecrCode[0x111] = startAdress >> 8; target = aTarget->data + 2; for(i = 0; i < decrLen; ++i) { target[i] = loadInitDecrCode[i]; } aTarget->data[0] = 0x01; aTarget->data[1] = 0x08; break; } } free(ibuf); return _true; }