summaryrefslogtreecommitdiff
path: root/sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c
diff options
context:
space:
mode:
Diffstat (limited to 'sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c')
-rw-r--r--sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c b/sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c
new file mode 100644
index 00000000..3c732a39
--- /dev/null
+++ b/sid/sidplay-libs-2.1.0/libsidplay/src/reloc65.c
@@ -0,0 +1,232 @@
+/*
+ xa65 - 6502 cross assembler and utility suite
+ reloc65 - relocates 'o65' files
+ Copyright (C) 1997 André 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.
+*/
+
+/*
+ Modified by Dag Lem <resid@nimrod.no>
+ Relocate and extract text segment from memory buffer instead of file.
+ For use with VICE VSID.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#define BUF (9*2+8) /* 16 bit header */
+
+typedef struct {
+ char *fname;
+ size_t fsize;
+ unsigned char *buf;
+ int tbase, tlen, dbase, dlen, bbase, blen, zbase, zlen;
+ int tdiff, ddiff, bdiff, zdiff;
+ unsigned char *segt;
+ unsigned char *segd;
+ unsigned char *utab;
+ unsigned char *rttab;
+ unsigned char *rdtab;
+ unsigned char *extab;
+} 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[] = { 1, 0, 'o', '6', '5' };
+
+int reloc65(unsigned char** buf, int* fsize, int addr)
+{
+ int mode, hlen;
+
+ int tflag=0, dflag=0, bflag=0, zflag=0;
+ int tbase=0, dbase=0, bbase=0, zbase=0;
+ int extract = 0;
+
+ file.buf = *buf;
+ file.fsize = *fsize;
+ tflag= 1;
+ tbase = addr;
+ extract = 1;
+
+ if (memcmp(file.buf, cmp, 5) != 0) {
+ return 0;
+ }
+
+ mode=file.buf[7]*256+file.buf[6];
+ if(mode & 0x2000) {
+ return 0;
+ } else if(mode & 0x4000) {
+ return 0;
+ }
+
+ 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) {
+ file.buf[ 9]= (tbase>>8)&255;
+ file.buf[ 8]= tbase & 255;
+ }
+ if(dflag) {
+ file.buf[13]= (dbase>>8)&255;
+ file.buf[12]= dbase & 255;
+ }
+ if(bflag) {
+ file.buf[17]= (bbase>>8)&255;
+ file.buf[16]= bbase & 255;
+ }
+ if(zflag) {
+ file.buf[21]= (zbase>>8)&255;
+ file.buf[20]= zbase & 255;
+ }
+
+ switch(extract) {
+ case 0: /* whole file */
+ return 1;
+ case 1: /* text segment */
+ *buf = file.segt;
+ *fsize = file.tlen;
+ return 1;
+ case 2:
+ *buf = file.segd;
+ *fsize = file.dlen;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+int read_options(unsigned char *buf) {
+ int c, l=0;
+
+ c=buf[0];
+ while(c && c!=EOF) {
+ c&=255;
+ l+=c;
+ c=buf[l];
+ }
+ return ++l;
+}
+
+int read_undef(unsigned char *buf) {
+ int n, l = 2;
+
+ n = buf[0] + 256*buf[1];
+ while(n){
+ n--;
+ while(!buf[l++]);
+ }
+ return l;
+}
+
+#define reldiff(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) {
+ 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) {
+ if((*rtab & 255) == 255) {
+ adr += 254;
+ rtab++;
+ } else {
+ 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) {
+ 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;
+ }
+ if(seg==0) rtab+=2;
+ }
+ }
+ if(adr > len) {
+/*
+ fprintf(stderr,"reloc65: %s: Warning: relocation table entries past segment end!\n",
+ fp->fname);
+*/
+ }
+ return ++rtab;
+}
+
+unsigned char *reloc_globals(unsigned char *buf, file65 *fp) {
+ int n, old, new, seg;
+
+ n = buf[0] + 256*buf[1];
+ buf +=2;
+
+ while(n) {
+/*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--;
+ }
+ return buf;
+}