Gsrle

From en64 wiki
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.