#include <stdio.h>
#include <stdlib.h>

unsigned char buffer[16384];
unsigned char linebuf[550];

void error( const char* msg );
int findfield( unsigned char byte, const unsigned char* buffer );

int main(int argc, char *argv[])
{
    FILE * app;
    FILE * patch;
    FILE * outfile;
    int i;
    int bufptr;
    unsigned int numbytes,rectype,temp,size;

    printf("Patcher by James Montelongo\n");

    /* open files */
    if (!(app = fopen(argv[1],"rb"))) error("Could not open app file.");
    if (!(patch = fopen(argv[2],"rb"))) error("Could not open patch file.");
    if (!(outfile = fopen("temp.bin","wb"))) error("Could not open out file.");


    /* clear */
    for(i=0;i<16384;i++) buffer[i]=0;
    
    
    fseek(app,0,SEEK_END);
    if (ftell(app)<78) error("Size is all wrong.");
    fseek(app,78,SEEK_SET);
    
    /* set infile to buffer */
    rectype =0;
    while (rectype!=1 && fgets(linebuf,548,app)) {
        sscanf(linebuf,":%02X%04X%02X%*s",&numbytes,&bufptr,&rectype);
        bufptr -= 0x4000; 
        if (rectype==0) {
            for(i=0;i<numbytes;i++) {
                sscanf(linebuf+9+(i*2),"%02X",&temp);
                buffer[bufptr++]= temp;
            }
        }
    }


    /* get size */
    if ( (buffer[0]!=0x80) || (buffer[1]!=0x0F) ) error("This app seems to be incorrect!");
    size = ( buffer[2] * 16777216 ) + ( buffer[3] * 65536 ) + ( buffer[4] * 256 ) + buffer[5] + 6;

    for(i=size;i<16384;i++) buffer[i]=0;
    
    /* Program Type Field: Must be present and shareware (0104) */
    bufptr = findfield(0x12, buffer);
    if (!bufptr || ( buffer[bufptr++]!=1) || (buffer[bufptr]!=4) ) 
        error("Program type field missing or not free (0104).");

    /* Patch over current buffer */
    rectype =0;
    while (rectype!=1 && fgets(linebuf,548,patch)) {
        sscanf(linebuf,":%02X%04X%02X%*s",&numbytes,&bufptr,&rectype);
        bufptr -= 0x4000; 
        if (rectype==0) {
            for(i=0;i<numbytes;i++) {
                sscanf(linebuf+9+(i*2),"%02X",&temp);
                buffer[bufptr++]= temp;
            }
        }
    }
    /* write bin */
    fwrite(buffer,1,size,outfile);
    /* all done*/
    puts("All Done!!");
    fclose(app);
    fclose(patch);
    fclose(outfile);
    return 0;
}
/* easy error code */
void error( const char* msg ) {
    printf("Error: %s\n",msg);
    exit(1);
}

/* Starting from 0006 searches for a field
 * in the in file buffer. */
int findfield( unsigned char byte, const unsigned char* buffer ) {
    int pnt=6;
    while (buffer[pnt++] == 0x80) {
        if (buffer[pnt] == byte) {
            pnt++;
            return pnt;
        } else
            pnt += (buffer[pnt]&0x0F);
        pnt++;
    }
    return 0;
}
