home *** CD-ROM | disk | FTP | other *** search
-
- /*
- XA65 - 6502 CROSS ASSEMBLER AND UTILITY SUITE
- RELOC65 - RELOCATES 'O65' FILES
- cOPYRIGHT (c) 1997 aNDR{$e9} fACHAT (A.FACHAT@PHYSIK.TU-CHEMNITZ.DE)
-
- tHIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
- IT UNDER THE TERMS OF THE gnu gENERAL pUBLIC lICENSE AS PUBLISHED BY
- THE fREE sOFTWARE fOUNDATION; EITHER VERSION 2 OF THE lICENSE, OR
- (AT YOUR OPTION) ANY LATER VERSION.
-
- tHIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
- BUT without any warranty; WITHOUT EVEN THE IMPLIED WARRANTY OF
- merchantability OR fitness for a particular purpose. sEE THE
- gnu gENERAL pUBLIC lICENSE FOR MORE DETAILS.
-
- yOU SHOULD HAVE RECEIVED A COPY OF THE gnu gENERAL pUBLIC lICENSE
- ALONG WITH THIS PROGRAM; IF NOT, WRITE TO THE fREE sOFTWARE
- fOUNDATION, iNC., 675 mASS aVE, cAMBRIDGE, ma 02139, usa.
- */
-
- #INCLUDE <STDIO.H>
- #INCLUDE <STDLIB.H>
- #INCLUDE <SYS/STAT.H>
- #INCLUDE <UNISTD.H>
- #INCLUDE <ERRNO.H>
- #INCLUDE <STRING.H>
-
- #DEFINEbuf(9*2+8)/* 16 BIT HEADER */
-
- TYPEDEF STRUCT {$7b}
- CHAR *FNAME;
- SIZE_T FSIZE;
- UNSIGNED CHAR*BUF;
- INTTBASE, TLEN, DBASE, DLEN, BBASE, BLEN, ZBASE, ZLEN;
- INTTDIFF, DDIFF, BDIFF, ZDIFF;
- UNSIGNED CHAR*SEGT;
- UNSIGNED CHAR*SEGD;
- UNSIGNED CHAR *UTAB;
- UNSIGNED CHAR *RTTAB;
- UNSIGNED CHAR *RDTAB;
- UNSIGNED CHAR *EXTAB;
- {$7d} FILE65;
-
-
- INT READ_OPTIONS(UNSIGNED CHAR *F);
- INT READ_UNDEF(UNSIGNED CHAR *F);
- UNSIGNED CHAR *RELOC_SEG(UNSIGNED CHAR *F, INT LEN, UNSIGNED CHAR *RTAB, FILE65 *FP);
- UNSIGNED CHAR *RELOC_GLOBALS(UNSIGNED CHAR *, FILE65 *FP);
-
- FILE65 FILE;
- UNSIGNED CHAR CMP[] = {$7b} 1, 0, 'O', '6', '5' {$7d};
-
- VOID USAGE(VOID) {$7b}
- PRINTF("RELOC65: RELOCATES 'O65' FILES\N"
- " RELOC65 [OPTIONS] [FILENAMES...]\N"
- "OPTIONS:\N"
- " -V = PRINT VERSION NUMBER\N"
- " -H, -? = PRINT THIS HELP\N"
- " -B? ADR = RELOCATES SEGMENT '?' (I.E. 'T' FOR TEXT SEGMENT,\N"
- " 'D' FOR DATA, 'B' FOR BSS AND 'Z' FOR ZEROPAGE) TO THE NEW\N"
- " ADDRESS 'ADR'.\N"
- " -O FILE = USES 'FILE' AS OUTPUT FILE. OTHERWISE WRITE TO 'A.O65'.\N"
- " -X? = EXTRACTS TEXT '?'='T' OR DATA '?'='D' SEGMENT FROM FILE\N"
- " INSTEAD OF WRITING BACK THE WHOLE FILE\N"
- );
- EXIT(0);
- {$7d}
-
- INT MAIN(INT ARGC, CHAR *ARGV[]) {$7b}
- INT I = 1, MODE, HLEN;
- SIZE_T N;
- file *FP;
- INT TFLAG=0, DFLAG=0, BFLAG=0, ZFLAG=0;
- INT TBASE, DBASE, BBASE, ZBASE;
- CHAR *OUTFILE = "A.O65";
- INT EXTRACT = 0;
-
- IF(ARGC<=1) USAGE();
-
- WHILE(I<ARGC) {$7b}
- IF(ARGV[I][0]=='-') {$7b}
- /* PROCESS OPTIONS */
- SWITCH(ARGV[I][1]) {$7b}
- CASE 'V':
- PRINTF("RELOC65 VERSION 0.2 (C) 1997 A.FACHAT\N");
- BREAK;
- CASE 'O':
- IF(ARGV[I][2]) OUTFILE=ARGV[I]+2;
- ELSE OUTFILE=ARGV[++I];
- BREAK;
- CASE 'B':
- SWITCH(ARGV[I][2]) {$7b}
- CASE 'T':
- TFLAG= 1;
- IF(ARGV[I][3]) TBASE = ATOI(ARGV[I]+3);
- ELSE TBASE = ATOI(ARGV[++I]);
- BREAK;
- CASE 'D':
- DFLAG= 1;
- IF(ARGV[I][3]) DBASE = ATOI(ARGV[I]+3);
- ELSE DBASE = ATOI(ARGV[++I]);
- BREAK;
- CASE 'B':
- BFLAG= 1;
- IF(ARGV[I][3]) BBASE = ATOI(ARGV[I]+3);
- ELSE BBASE = ATOI(ARGV[++I]);
- BREAK;
- CASE 'Z':
- ZFLAG= 1;
- IF(ARGV[I][3]) ZBASE = ATOI(ARGV[I]+3);
- ELSE ZBASE = ATOI(ARGV[++I]);
- BREAK;
- DEFAULT:
- PRINTF("uNKNOWN SEGMENT TYPE '%C' - IGNORED!\N", ARGV[I][2]);
- BREAK;
- {$7d}
- BREAK;
- CASE 'X':/* EXTRACT SEGMENT */
- SWITCH(ARGV[I][2]) {$7b}
- CASE 'T':
- EXTRACT = 1;
- BREAK;
- CASE 'D':
- EXTRACT = 2;
- BREAK;
- CASE 'Z':
- CASE 'B':
- PRINTF("cANNOT EXTRACT SEGMENT TYPE '%C' - IGNORED!\N", ARGV[I][2]);
- BREAK;
- DEFAULT:
- PRINTF("uNKNOWN SEGMENT TYPE '%C' - IGNORED!\N", ARGV[I][2]);
- BREAK;
- {$7d}
- BREAK;
- CASE 'H':
- CASE '?':
- USAGE();
- DEFAULT:
- FPRINTF(STDERR,"RELOC65: %S UNKNOWN OPTION, USE '-?' FOR HELP\N",ARGV[I]);
- BREAK;
- {$7d}
- {$7d} ELSE {$7b}
- STRUCT STAT FS;
- FILE.FNAME=ARGV[I];
- STAT(ARGV[I], &FS);
- FILE.FSIZE=FS.ST_SIZE;
- FILE.BUF=MALLOC(FILE.FSIZE);
- IF(!FILE.BUF) {$7b}
- FPRINTF(STDERR,"oOPS, NO MORE MEMORY!\N");
- EXIT(1);
- {$7d}
- PRINTF("RELOC65: READ FILE %S -> %S\N",ARGV[I],OUTFILE);
- FP = FOPEN(ARGV[I],"RB");
- IF(FP) {$7b}
- N = FREAD(FILE.BUF, 1, FILE.FSIZE, FP);
- FCLOSE(FP);
- IF((N>=FILE.FSIZE) && (!MEMCMP(FILE.BUF, CMP, 5))) {$7b}
- MODE=FILE.BUF[7]*256+FILE.BUF[6];
- IF(MODE & 0X2000) {$7b}
- FPRINTF(STDERR,"RELOC65: %S: 32 BIT SIZE NOT SUPPORTED\N", ARGV[I]);
- {$7d} ELSE
- IF(MODE & 0X4000) {$7b}
- FPRINTF(STDERR,"RELOC65: %S: PAGEWISE RELOCATION NOT SUPPORTED\N", ARGV[I]);
- {$7d} ELSE {$7b}
- HLEN = buf+READ_OPTIONS(FILE.BUF+buf);
-
- FILE.TBASE = FILE.BUF[ 9]*256+FILE.BUF[ 8];
- FILE.TLEN = FILE.BUF[11]*256+FILE.BUF[10];
- FILE.TDIFF = TFLAG? TBASE - FILE.TBASE : 0;
- FILE.DBASE = FILE.BUF[13]*256+FILE.BUF[12];
- FILE.DLEN = FILE.BUF[15]*256+FILE.BUF[14];
- FILE.DDIFF = DFLAG? DBASE - FILE.DBASE : 0;
- FILE.BBASE = FILE.BUF[17]*256+FILE.BUF[16];
- FILE.BLEN = FILE.BUF[19]*256+FILE.BUF[18];
- FILE.BDIFF = BFLAG? BBASE - FILE.BBASE : 0;
- FILE.ZBASE = FILE.BUF[21]*256+FILE.BUF[20];
- FILE.ZLEN = FILE.BUF[23]*256+FILE.BUF[21];
- FILE.ZDIFF = ZFLAG? ZBASE - FILE.ZBASE : 0;
-
- FILE.SEGT = FILE.BUF + HLEN;
- FILE.SEGD = FILE.SEGT + FILE.TLEN;
- FILE.UTAB = FILE.SEGD + FILE.DLEN;
-
- FILE.RTTAB = FILE.UTAB + READ_UNDEF(FILE.UTAB);
-
- FILE.RDTAB = RELOC_SEG(FILE.SEGT, FILE.TLEN, FILE.RTTAB, &FILE);
- FILE.EXTAB = RELOC_SEG(FILE.SEGD, FILE.DLEN, FILE.RDTAB, &FILE);
-
- RELOC_GLOBALS(FILE.EXTAB, &FILE);
-
- IF(TFLAG) {$7b}
- FILE.BUF[ 9]= (TBASE>>8)&255;
- FILE.BUF[ 8]= TBASE & 255;
- {$7d}
- IF(DFLAG) {$7b}
- FILE.BUF[13]= (DBASE>>8)&255;
- FILE.BUF[12]= DBASE & 255;
- {$7d}
- IF(BFLAG) {$7b}
- FILE.BUF[17]= (BBASE>>8)&255;
- FILE.BUF[16]= BBASE & 255;
- {$7d}
- IF(ZFLAG) {$7b}
- FILE.BUF[21]= (ZBASE>>8)&255;
- FILE.BUF[20]= ZBASE & 255;
- {$7d}
-
- FP = FOPEN(OUTFILE, "WB");
- IF(FP) {$7b}
- SWITCH(EXTRACT) {$7b}
- CASE 0:/* WHOLE FILE */
- FWRITE(FILE.BUF, 1, FILE.FSIZE, FP);
- BREAK;
- CASE 1:/* TEXT SEGMENT */
- FWRITE(FILE.SEGT, 1, FILE.TLEN, FP);
- BREAK;
- CASE 2:
- FWRITE(FILE.SEGD, 1, FILE.DLEN, FP);
- BREAK;
- {$7d}
- FCLOSE(FP);
- {$7d} ELSE {$7b}
- FPRINTF(STDERR,"RELOC65: WRITE '%S': %S\N",
- OUTFILE, STRERROR(ERRNO));
- {$7d}
- {$7d}
- {$7d} ELSE {$7b}
- FPRINTF(STDERR,"RELOC65: %S: NOT AN O65 FILE!\N", ARGV[I]);
- IF(FILE.BUF[0]==1 && FILE.BUF[1]==8 && FILE.BUF[3]==8) {$7b}
- PRINTF("%S: c64 basic EXECUTABLE (START ADDRESS $0801)?\N", ARGV[I]);
- {$7d} ELSE
- IF(FILE.BUF[0]==1 && FILE.BUF[1]==4 && FILE.BUF[3]==4) {$7b}
- PRINTF("%S: cbm pet basic EXECUTABLE (START ADDRESS $0401)?\N", ARGV[I]);
- {$7d}
- {$7d}
- {$7d} ELSE {$7b}
- FPRINTF(STDERR,"RELOC65: READ '%S': %S\N",
- ARGV[I], STRERROR(ERRNO));
- {$7d}
- {$7d}
- I++;
- {$7d}
- EXIT(0);
- {$7d}
-
-
- INT READ_OPTIONS(UNSIGNED CHAR *BUF) {$7b}
- INT C, L=0;
-
- C=BUF[0];
- WHILE(C && C!=eof) {$7b}
- C&=255;
- L+=C;
- C=BUF[L];
- {$7d}
- RETURN ++L;
- {$7d}
-
- INT READ_UNDEF(UNSIGNED CHAR *BUF) {$7b}
- INT N, L = 2;
-
- N = BUF[0] + 256*BUF[1];
- WHILE(N){$7b}
- N--;
- WHILE(!BUF[L++]);
- {$7d}
- RETURN L;
- {$7d}
-
- #DEFINERELDIFF(S)(((S)==2)?FP->TDIFF:(((S)==3)?FP->DDIFF:(((S)==4)?FP->BDIFF:(((S)==5)?FP->ZDIFF:0))))
-
- UNSIGNED CHAR *RELOC_SEG(UNSIGNED CHAR *BUF, INT LEN, UNSIGNED CHAR *RTAB, FILE65 *FP) {$7b}
- INT ADR = -1;
- INT TYPE, SEG, OLD, NEW;
- /*PRINTF("TDIFF=%04X, DDIFF=%04X, BDIFF=%04X, ZDIFF=%04X\N",
- FP->TDIFF, FP->DDIFF, FP->BDIFF, FP->ZDIFF);*/
- WHILE(*RTAB) {$7b}
- IF((*RTAB & 255) == 255) {$7b}
- ADR += 254;
- RTAB++;
- {$7d} ELSE {$7b}
- ADR += *RTAB & 255;
- RTAB++;
- TYPE = *RTAB & 0XE0;
- SEG = *RTAB & 0X07;
- /*PRINTF("RELOC ENTRY @ RTAB=%P (OFFSET=%D), ADR=%04X, TYPE=%02X, SEG=%D\N",RTAB-1, *(RTAB-1), ADR, TYPE, SEG);*/
- RTAB++;
- SWITCH(TYPE) {$7b}
- CASE 0X80:
- OLD = BUF[ADR] + 256*BUF[ADR+1];
- NEW = OLD + RELDIFF(SEG);
- BUF[ADR] = NEW & 255;
- BUF[ADR+1] = (NEW>>8)&255;
- BREAK;
- CASE 0X40:
- OLD = BUF[ADR]*256 + *RTAB;
- NEW = OLD + RELDIFF(SEG);
- BUF[ADR] = (NEW>>8)&255;
- *RTAB = NEW & 255;
- RTAB++;
- BREAK;
- CASE 0X20:
- OLD = BUF[ADR];
- NEW = OLD + RELDIFF(SEG);
- BUF[ADR] = NEW & 255;
- BREAK;
- {$7d}
- IF(SEG==0) RTAB+=2;
- {$7d}
- {$7d}
- IF(ADR > LEN) {$7b}
- FPRINTF(STDERR,"RELOC65: %S: wARNING: RELOCATION TABLE ENTRIES PAST SEGMENT END!\N",
- FP->FNAME);
- {$7d}
- RETURN ++RTAB;
- {$7d}
-
- UNSIGNED CHAR *RELOC_GLOBALS(UNSIGNED CHAR *BUF, FILE65 *FP) {$7b}
- INT N, OLD, NEW, SEG;
-
- N = BUF[0] + 256*BUF[1];
- BUF +=2;
-
- WHILE(N) {$7b}
- /*PRINTF("RELOCATING %S, ", BUF);*/
- WHILE(*(BUF++));
- SEG = *BUF;
- OLD = BUF[1] + 256*BUF[2];
- NEW = OLD + RELDIFF(SEG);
- /*PRINTF("OLD=%04X, SEG=%D, REL=%04X, NEW=%04X\N", OLD, SEG, RELDIFF(SEG), NEW);*/
- BUF[1] = NEW & 255;
- BUF[2] = (NEW>>8) & 255;
- BUF +=3;
- N--;
- {$7d}
- RETURN BUF;
- {$7d}
-
-