//------------------------------------------------// // Decompressor and Recompressor: GDLeen ver 1.0 // // // // Coded By: John C. ( Bongo` ) // // Feb 15th, 2005 // // Revised: Sept 7th, 2008 // // Compiled with [ PROJECT ] Borland C++ Builder 3// // Compiled with [ SOURCE ONLY ] Turbo C++ 3.0 // //------------------------------------------------// #include #include #include #include #include #define LRAM( x ) *(LONG *)&ram[ x ] #define WRAM( x ) *(WORD *)&ram[ x ] char ram[0x30000]; BYTE *comp; BYTE *buffer; LONG iOffset; WORD iLoop; WORD iHeader; char fil1[260] = "gdleen.smc"; char fil2[260] = { 0 }; FILE *f1; FILE *f2; char Decompress( WORD value ); char Recompress( WORD value ); LONG Snes2Pc( LONG Offset ); LONG FileSize( FILE *tf ); //------------------------// // // //------------------------// int main( ) { clrscr( ); // Start coding printf( "Select process... \n" " [1] - Decompress \n" " [2] - Recompress \n" " [3] - End Program\n" ); // Switch thru data while( !ram[ 0x00 ] ) { // ram[ 0x00 ] = getch( ); switch( ram[ 0x00 ] ) { //--------------------------- case '1': iLoop = -1; while( ++iLoop < 0x100 ) Decompress( iLoop ); // break; //--------------------------- case '2': Recompress( 0x0F ); ram[ 0x00 ] = 2; break; case '3': case 27 : ram[ 0x00 ] = 3; break; default : ram[ 0x00 ] = 0; break; } } return 0; } //------------------------------// // // // Decompress the ROM data // // // //------------------------------// char Decompress( WORD value ) { // Open the file(s) f1 = fopen( fil1, "rb" ); if ( !f1 ) { // fcloseall( ); printf( "Error opening SOURCE file..." ); return -1; }// END IF // Does the ROM have a header? iHeader = FileSize( f1 ) & 0x0200; // Make the file name sprintf( fil2, "GD_%03d.dat", value ); f2 = fopen( fil2, "wb" ); if ( !f2 ) { // fcloseall( ); printf( "Error opening DESTINATION file..." ); return -1; }// END IF // Print it printf( "Dumping...%s\n", fil2 ); // Load to the pointer data [offset] fseek( f1, Snes2Pc( 0xE674 + value ), SEEK_SET ); // iOffset = fgetc(f1); iOffset <<= 16; fseek( f1, Snes2Pc( 0xE724 + value ), SEEK_SET ); // WRAM(0x14) = fgetc(f1); WRAM(0x14) <<= 1; // Y index into pointer table // Set the ROM address conversion fseek( f1, Snes2Pc( iOffset + (0x8000 + WRAM(0x14)) ), SEEK_SET ); fread( &ram[0x14], 1, 2, f1 ); iOffset += ( WRAM(0x14) + 0x8000 ); iOffset = Snes2Pc( iOffset ); fseek( f1, iOffset, SEEK_SET ); // Init start of compresion buffer WRAM(0x00) = 0; // Where the decompressed data goes. comp = &ram[0x10000]; // Load the data size, 16-bits fread( &ram[0xF100], 1, 2, f1 ); // Negative value test // BMI $56 [$E663] iOffset = ftell( f1 ); ram[ 0x10 ] = fgetc( f1 ); //------------------------------------// // Deternmine which routine is wanted // //------------------------------------// if ( ram[ 0x10 ] < 0 ) { // Store all static data to file while( WRAM(0xF100) ) { comp[ WRAM(0x00) ] = fgetc( f1 ); WRAM(0x00) += 1; WRAM(0xF100) -= 1; } } else { // Hight BIT was NOT set! // Get back to the data fseek( f1, iOffset, SEEK_SET ); //--------------------------// // Loop through the routine // //--------------------------// while( WRAM(0x00) < WRAM(0xF100) ) { ram[ 0xF104 ] = 8; // counter ram[ 0xF106 ] = fgetc( f1 ); // test BYTE // Loop through 8 BITS while( ram[ 0xF104 ]-- ) { // Test for compression if ( !(ram[ 0xF106 ] & 0x80) ) { // We DON'T have compression comp[ WRAM(0x00) ] = fgetc( f1 ); WRAM(0x00) += 1; } else { // We have compression ram[ 0x10 ] = fgetc( f1 ); // Get starting BYTE ram[ 0xF105 ] = (ram[ 0x10 ] & 0x0F) + 3; // Set copy amount // Get the high BYTE of copy offset // Original routine: LSR x 4, XBA WRAM(0x12) = (ram[ 0x10 ] & 0xF0); WRAM(0x12) <<= 4; // XBA WRAM(0x12) += fgetc( f1 ); WRAM(0x12) ^= 0xFFFF; WRAM(0x12) += WRAM(0x00); // Copy the data while ( ram[ 0xF105 ]-- ) { // comp[ WRAM(0x00) ] = comp[ WRAM(0x12) ]; WRAM(0x00) += 1; WRAM(0x12) += 1; } } // if ( !(ram[ 0xF106 ] & 0x80) ) // Shift and adjust Test BYTE ram[ 0xF106 ] <<= 1; } // while( ram[ 0xF104 ]-- ) }// while( WRAM(0x00) < WRAM(0xF100) ) } // if ( ram[ 0x10 ] < 0 ) //-----------------------------// // Store the data to the file // //-----------------------------// fwrite( comp, 1, WRAM(0x00), f2 ); fcloseall( ); // return 0; } // char Decompress( WORD value ) //------------------------------// // // // Recompress the ROM data // // // //------------------------------// char Recompress( WORD value ) { WORD cmpMax, cmpMaxPosi, cmpMost; BYTE *bit_ptr; // Open the file(s) f1 = fopen( fil1, "rb+" ); if ( !f1 ) { fcloseall( ); printf( "Error opening DESTINATION file..." ); return -1; } // Make the file name sprintf( fil2, "GD_03d.dat", value ); f2 = fopen( fil2,"rb" ); if ( !f2 ) { // fcloseall( ); printf( "Error opening SOURCE file..." ); return -1; } // Print it printf( "Now inserting...%s", fil2 ); // Load to the pointer data [offset] fseek( f1, Snes2Pc( 0xE674 + value ), SEEK_SET ); // iOffset = fgetc(f1); iOffset <<= 16; fseek( f1, Snes2Pc( 0xE724 + value ), SEEK_SET ); // WRAM(0x14) = fgetc(f1); WRAM(0x14) <<= 1; // Y index into pointer table // Set the ROM address conversion fseek( f1, Snes2Pc( iOffset + (0x8000 + WRAM(0x14)) ), SEEK_SET ); fread( &ram[0x14], 1, 2, f1 ); iOffset += ( WRAM(0x14) + 0x8000 ); iOffset = Snes2Pc( iOffset ); fseek( f1, iOffset, SEEK_SET ); // Init start of compresion buffer WRAM(0x00) = 0; WRAM(0x02) = 0; // Where the decompressed data goes. comp = &ram[0x10000]; buffer = &ram[0x20000]; // bit_ptr is the position of each control code // that is compiled for each 8-bit stream of data // compressed or not. bit_ptr = &buffer[ WRAM(0x02) ]; // where data is stored for the ROM WRAM(0x02) += 1; // Load the data size WRAM(0xF100) = FileSize( f2 ) & 0xFFFF; // I don't like -1 values returned to me if ( WRAM(0xF100) == 0xFFFF ) return -1; //--------------------------------------// // Ok, now load up the data to compress // //--------------------------------------// memset( comp, 0, 0xFFFF ); // Clear the data and ROM buffers memset( buffer, 0, 0xFFFF ); // load up the data fread( comp, 1, WRAM(0xF100), f2 ); fclose( f2 ); //---------------------------// // Loop through the routine // //---------------------------// while ( WRAM(0x00) < WRAM(0xF100) ) { // ram[ 0xF104 ] = 8; // counter // Do the compression testing! // Loop through 8 BITS while( ram[ 0xF104 ]-- ) { // Test for compression capabilities! if ( WRAM(0x00) >= 0xFFF ) cmpMax = (WRAM(0x00) - 0xFFF); else cmpMax = 0; // The best possible match found cmpMost = 0; // Test for compression // If you have ever done a "search" for a data string // match in a hex editor or what have you, this is basically // the same thing while( cmpMax < WRAM(0x00) ) { // if ( comp[ cmpMax ] == comp[ WRAM(0x00) ] ) { // WRAM(0x10) = 0; // Loop through the matches while( comp[ cmpMax + WRAM(0x10)] == comp[ WRAM(0x00) + WRAM(0x10) ] && WRAM(0x10) < 18 && (WRAM(0x00) + WRAM(0x10)) < WRAM(0xF100) ) { WRAM(0x10) += 1; } // Test for best finds if ( WRAM(0x10) > cmpMost ) { // cmpMost = WRAM(0x10); cmpMaxPosi = cmpMax; // Do we already have a max find? if ( cmpMost >= 18 ) { // cmpMost = 18; break; } } // if ( WRAM(0x10) > cmpMost ) } // if ( comp[ cmpMax ] == comp[ WRAM(0x00) ] ) // Increment test position cmpMax++; } // while( cmpMax < WRAM(0x00) ) //--------------------------------------------// // Compress what we have or store Static data // //--------------------------------------------// if ( cmpMost > 2 ) { // We can compress this data! // It takes 2 bytes to form a compression pointer // Anything 2 bytes or less is a waste of time compressing //------------------- // Calculate offsets! WRAM(0x04) = cmpMaxPosi - WRAM(0x00); WRAM(0x04) ^= 0xFFFF; ram[0x06] = WRAM(0x04) >> 8; ram[0x06] = (ram[0x06] << 4) + (cmpMost - 3); WRAM(0x04) &= 0xFF; // buffer[ WRAM(0x02) ] = ram[ 0x06 ]; WRAM(0x02) += 1; buffer[ WRAM(0x02) ] = WRAM(0x04); WRAM(0x02) += 1; // Get past the compressed data WRAM(0x00) += cmpMost; // Adjust the control code *bit_ptr <<= 1; *bit_ptr |= 1; } else { // It's static data... buffer[ WRAM(0x02) ] = comp[ WRAM(0x00) ]; WRAM(0x02) += 1; WRAM(0x00) += 1; // Adjust the control code *bit_ptr <<= 1; } } // while( ram[ 0xF104 ]-- ) // Set a new control code location bit_ptr = &buffer[ WRAM(0x02) ]; WRAM(0x02) += 1; } // while ( WRAM(0x00) < WRAM(0xF100) ) //-----------------------------// // Store the data to the file // //-----------------------------// // // Test to see if it was worth compressing! // If the RAW size is better than the compressed size if ( WRAM(0x02) > WRAM(0xF100) ) { // Store all static data if ( (iOffset + WRAM(0x02)) <= 0xAA8F2 ) // <- Change this value to a variable used per data block { // fseek( f1, iOffset, SEEK_SET ); // Start of data fwrite( &ram[0xF100], 1, 2, f1 ); // Store data size fputc( 0xFF, f1 ); // store RAW data flag fwrite( comp, 1, WRAM(0xF100), f1 ); // store RAW data } else printf( "Error: Data size greater than ROM allows...\n" " Data will not be compressed!" ); } else { // Store compressed data if ( (iOffset + WRAM(0x02)) <= 0xAA8F2 ) // <- Change this value to a variable used per data block { // fseek( f1, iOffset, SEEK_SET ); // start of the data fwrite( &ram[0xF100], 1, 2, f1 ); // Store data size fwrite( buffer, 1, WRAM(0x02), f1 ); // store to ROM } else printf( "Error: Data size greater than ROM allows...\n" " Data will not be compressed!" ); } // if ( WRAM(0x02) > WRAM(0xF100) ) // fcloseall( ); return 0; }// char Recompress( WORD value ) //-----------------------------// // Load the program data Bank // //-----------------------------// LONG Snes2Pc( LONG Offset ) { LONG snesOffset; // SNES to ROM snesOffset = (((Offset | 0x800000) - 0x800000) & 0xFF0000) >> 1; snesOffset += ((Offset & 0xFFFF) - 0x8000) + iHeader; return snesOffset; }// LONG Snes2Pc( LONG Offset ) //-----------------------------// // Get the length of the file // //-----------------------------// LONG FileSize( FILE *tf ) { LONG fileSize; LONG offset; // Test file if ( !tf ) return -1; // Get orinal offset offset = ftell( tf ); // Get size fseek( tf, 0, SEEK_END ); fileSize = ftell( tf ); fseek( tf, offset, SEEK_SET ); return fileSize; }// LONG FileSize( FILE *tf )