Gsrle
Jump to navigation
Jump to search
ZZT
This program will perform simple RLE optimizations of GameShark codes (up to 2048 lines in length, but hey if you want longer just alter the heap size in the source) by means of repeater codes.
Source
#include <stdio.h> #include <stdlib.h> struct gsc_t { unsigned address; unsigned value; }; struct gsc_t * heap[2048]; unsigned count; static int gsccompare ( const void * a, const void * b ) { const struct gsc_t * c1, * c2; c1 = *(const struct gsc_t **)a; c2 = *(const struct gsc_t **)b; if( c1->address < c2->address ) return -1; else if( c1->address == c2->address ) return 0; else return 1; } int main ( int argc, char ** argv ) { int i, step, valstep, have, amount; unsigned address, value; step = valstep = have = amount = 0; /* Read in gameshark codes */ while( !feof(stdin) ) { if( scanf("%08X %04X\n", &address, &value) != 2 ) continue; heap[count] = calloc( sizeof(struct gsc_t), 1 ); heap[count]->address = address; heap[count]->value = value; count++; } /* Sort */ qsort( heap, count, sizeof(struct gsc_t*), gsccompare ); /* Seek duplicates */ for( i = 0; i < count; i++ ) { int k, inc; inc = 0; /* Check for last code */ if( i + 1 == count ) goto just_print; amount = 1; step = heap[i+1]->address - heap[i]->address; valstep = heap[i+1]->value - heap[i]->value; /* Search for pattern */ for( k = i + 1; k < count; k++ ) { if( (heap[k]->address - heap[k-1]->address) == step && (heap[k]->value - heap[k-1]->value) == valstep ) { /* printf( "%08X %04X:%08X %04X - %X - %X == %X(%2i, %u)\n", heap[k]->address, heap[k]->value, heap[k-1]->address, heap[k-1]->value, heap[k]->value, heap[k-1]->value, valstep, k, step ); */ amount++; } else break; } /* Checks */ if( step < 0 || amount > 255 || step > 255 ) { amount = 0; step = 0; } /* Found pattern? */ if( amount > 2 ) { /* Print repeater code */ printf( "5000%02X%02X %04X\n", amount, step, ((unsigned)valstep) & 0xFFFF ); /* Update heap pointer past repeated codes */ inc = amount - 1; } just_print: ; /* Print original code */ printf( "%08X %04X\n", heap[i]->address, heap[i]->value ); /* Update heap pointer */ i += inc; } return 0; }
On Display
For example, it reduced my code to put the beta Blue Fairy in Ocarina of Time to 64 lines. Fancy that, huh?
Before:
813165F8 0001 813164F0 0000 813164F2 0000 813164F4 0000 813164F6 0000 813164F8 0000 813164FA 0000 813164FC 0000 813164FE 0000 81316500 0000 81316502 0000 81316504 0000 81316506 0000 81316508 0000 8131650A 0000 8131650C 0000 8131650E 0000 81316510 0000 81316512 0000 81316514 0000 81316516 0000 81316518 0000 8131651A 0000 8131651C 0000 8131651E 0000 81316520 0000 81316522 0000 81316524 0000 81316526 0000 81316528 0000 8131652A 0000 8131652C 0000 8131652E 0000 81316530 0000 81316532 0000 81316534 0000 81316536 0000 81316538 0000 8131653A 0000 8131653C 0000 8131653E 0000 81316540 0000 81329BC0 0000 81329BC2 0000 81329BC4 0000 81329BC6 0000 81329BC8 DF00 81329BCA 0000 81329BCC 0000 81329BCE 0000 81332798 0600 8133279A D1B0 813327A6 36D0 813327B2 36D0 813327BE 36D0 813327CA 36D0 813327D6 36D0 813327E2 36D0 813327EE 36D0 813327FA 36D0 81332806 36D0 81332812 36D0 8133281E 36D0 8133282A 36D0 81332836 36D0 81332842 36D0 8133284E 36D0 8133285A 36D0 81332866 36D0 81332872 36D0 8133287E 36D0 8133288A 36D0 81332896 36D0 813328A2 36D0 813328AE 36D0 813328BA 36D0 813328C6 36D0 813328D2 36D0 81333A04 0001 81333A08 0600 81333A0A 0000 81333A0C 0600 81333A0E 0060 8131EB88 0001 8131EB8C 0600 8131EB8E 0000 8131EB90 0600 8131EB92 0060 8131E198 0001 8131E19C 0600 8131E19E 0000 8131E1A0 0600 8131E1A2 0060 8131CED8 0001 8131CEDC 0600 8131CEDE 0000 8131CEE0 0600 8131CEE2 0060 8131C350 0001 8131C354 0600 8131C356 0000 8131C358 0600 8131C35A 0060 8131BD00 0001 8131BD04 0600 8131BD06 0000 8131BD08 0600 8131BD0A 0060 8131A834 0001 8131A838 0600 8131A83A 0000 8131A83C 0600 8131A83E 0060 813196B0 0001 813196B4 0600 813196B6 0000 813196B8 0600 813196BA 0060 813182E0 0001 813182E4 0600 813182E6 0000 813182E8 0600 813182EA 0060 81316E1C 0001 81316E20 0600 81316E22 0000 81316E24 0600 81316E26 0060 801E63CA 003C 811E63C8 3E0F
After:
801E63CA 003C 811E63C8 3E0F 50002902 0000 813164F0 0000 813165F8 0001 81316E1C 0001 81316E20 0600 81316E22 0000 81316E24 0600 81316E26 0060 813182E0 0001 813182E4 0600 813182E6 0000 813182E8 0600 813182EA 0060 813196B0 0001 813196B4 0600 813196B6 0000 813196B8 0600 813196BA 0060 8131A834 0001 8131A838 0600 8131A83A 0000 8131A83C 0600 8131A83E 0060 8131BD00 0001 8131BD04 0600 8131BD06 0000 8131BD08 0600 8131BD0A 0060 8131C350 0001 8131C354 0600 8131C356 0000 8131C358 0600 8131C35A 0060 8131CED8 0001 8131CEDC 0600 8131CEDE 0000 8131CEE0 0600 8131CEE2 0060 8131E198 0001 8131E19C 0600 8131E19E 0000 8131E1A0 0600 8131E1A2 0060 8131EB88 0001 8131EB8C 0600 8131EB8E 0000 8131EB90 0600 8131EB92 0060 50000402 0000 81329BC0 0000 81329BC8 DF00 50000302 0000 81329BCA 0000 81332798 0600 8133279A D1B0 50001A0C 0000 813327A6 36D0 81333A04 0001 81333A08 0600 81333A0A 0000 81333A0C 0600 81333A0E 0060
Magic! There are perhaps more aggressive optimizations that are possible.
Strangers to UNIX need not apply.