--- /dev/null
+/*
+ * Banked ihx processor
+ *
+ * Split the ihx file into base and bank blocks
+ * Perform the patch ups on the file
+ * Write the stubs
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+FILE *fseg[10];
+static char fbuf[64];
+
+void open_fseg(int n)
+{
+ if (n == 0)
+ sprintf(fbuf, "common.ihx");
+ else
+ sprintf(fbuf, "bank%d.ihx", n);
+ fseg[n] = fopen(fbuf, "w");
+ if (fseg[n] == NULL) {
+ perror(fbuf);
+ exit(1);
+ }
+}
+
+void put_seg(int n, char *bp)
+{
+ if (fseg[n] == NULL)
+ open_fseg(n);
+ fputs(bp, fseg[n]);
+}
+
+void put_all_segs(char *bp)
+{
+ int i;
+ for (i = 0; i < 10; i++) {
+ if (fseg[i])
+ fputs(bp, fseg[i]);
+ }
+}
+
+void close_segs(void)
+{
+ int i;
+ for (i = 0; i < 10; i++) {
+ if (fseg[i])
+ if(fclose(fseg[i]))
+ perror("fclose");
+ }
+}
+
+void bin_segs(void)
+{
+ int i;
+ system("makebin -s 65536 -p common.ihx >common.bin\n");
+ for (i = 1; i < 10; i++) {
+ if (fseg[i]) {
+ snprintf(fbuf, 64, "makebin -s 65536 -p bank%d.ihx >bank%d.bin\n",
+ i, i);
+ system(fbuf);
+ }
+ }
+}
+
+void save_patch_rule(FILE *fr, char *buf)
+{
+ fputs(buf, fr);
+}
+
+void split_bihx(char *name)
+{
+ int n;
+ char buf[256];
+ FILE *fp = fopen(name, "r");
+ FILE *fr;
+
+ if (fp == NULL) {
+ perror(name);
+ exit(1);
+ }
+
+ fr = fopen("relocs.dat", "w");
+ if (fr == NULL) {
+ perror("relocs.dat");
+ exit(1);
+ }
+
+ while(fgets(buf, 256, fp)) {
+ /* Leading hex means ihx data for this target */
+ if (isdigit(*buf)) {
+ sscanf(buf, "%x", &n);
+ put_seg(n, buf + 2);
+ } else if (*buf == ':') /* ihx for all (end marker) */
+ put_all_segs(buf);
+ else if (*buf == ';')
+ continue;
+ else if (*buf == 'B')
+ save_patch_rule(fr, buf);
+ else
+ fprintf(stderr, "%s: invalid bihx line.\n", name, buf);
+ }
+ fclose(fp);
+ fclose(fr);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "%s bihxfile\n", argv[0]);
+ exit(1);
+ }
+ split_bihx(argv[1]);
+ close_segs();
+ bin_segs();
+}
+
+
+
\ No newline at end of file
--- /dev/null
+/*
+ * Fix up the given binary block with the reloc data
+ *
+ * Patch RST lines into the relevant places, generate stub info
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define NBANKS 4
+
+unsigned char buf[NBANKS][65536];
+unsigned int size[NBANKS];
+FILE *fptr[NBANKS];
+int v;
+static int nextfix = 0xFE00; /* FIXME */
+static int lastfix = 0x10000;
+
+struct stubmap {
+ struct stubmap *next;
+ int bank;
+ uint16_t addr;
+ uint16_t target;
+};
+
+struct stubmap *stubs;
+static int stubct = 0;
+static int stubdup = 0;
+
+unsigned int resize(int b)
+{
+ unsigned char *bp = buf[b] + 65535;
+ while(*bp == 0)
+ bp--;
+ bp++;
+ if (bp - buf[b] > size[b])
+ return bp - buf[b];
+ return size[b];
+}
+
+/* FIXME: */
+int stubmap(uint16_t v, int bank)
+{
+ struct stubmap *s = stubs;
+ struct stubmap **p = &stubs;
+
+ while(s) {
+ if (s->bank == bank && s->addr == v) {
+ stubdup++;
+ return s->target;
+ }
+ p = &s->next;
+ s = *p;
+ }
+ s = malloc(sizeof(struct stubmap));
+ if (s == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+ }
+ *p = s;
+ s->next = NULL;
+ s->bank = bank;
+ s->addr = v;
+ s->target = nextfix;
+ if (nextfix == lastfix) {
+ fprintf(stderr, "Out of fix space (%d stubs used).\n", stubct);
+ exit(1);
+ }
+ buf[0][nextfix++] = 0xC7 + 8 * bank; /* RST */
+ buf[0][nextfix++] = v & 0xFF; /* Target */
+ buf[0][nextfix++] = v >> 8;
+ buf[0][nextfix++] = 0xC9; /* RET */
+ stubct++;
+ return s->target;
+}
+
+void code_reloc(uint8_t sbank, uint16_t ptr, uint8_t dbank)
+{
+ int da;
+ if (ptr == 0) {
+ fprintf(stderr, "Nonsense zero based code relocation.\n");
+ exit(1);
+ }
+ if (dbank == 0 || dbank >= NBANKS) {
+ fprintf(stderr, "Invalid bank %d\n", dbank);
+ exit(1);
+ }
+ switch(buf[sbank][ptr-1]) {
+ case 0xC3: /* JP - needs stub */
+ if (v)
+ printf("Converting JP at %04x to RST/RET stub\n", ptr);
+ da = stubmap(buf[sbank][ptr] + (buf[sbank][ptr+1] << 8), dbank);
+ buf[sbank][ptr] = da & 0xFF;
+ buf[sbank][ptr+1] = da >> 8;
+ break;
+ case 0xCD: /* CALL */
+ if (v)
+ printf("Converting CALL at %04x to RST\n", ptr);
+ buf[sbank][ptr-1] = 0xC7 + 8 * dbank; /* RST 8/16/24 */
+ break;
+ case 0xC7: /* RST */
+ case 0xCF:
+ case 0xD7:
+ case 0xDF:
+ fprintf(stderr, "File already processed!\n");
+ exit(1);
+ default:
+ fprintf(stderr, "Bad relocation in code %04X: %02X\n",
+ ptr-1, buf[sbank][ptr-1]);
+ }
+}
+
+void data_reloc(uint8_t sbank, uint16_t ptr, uint8_t dbank)
+{
+ int na;
+ uint16_t n;
+
+ /* Get the target */
+ n = buf[sbank][ptr] + (buf[sbank][ptr+1]<<8);
+
+ if (v)
+ printf("Stubhooking %04x for data reference.\n", ptr);
+ /* Find the stub for it */
+ na = stubmap(n, dbank);
+ if (na == -1) {
+ fprintf(stderr, "No stub match: stubs stale\n");
+ exit(1);
+ }
+ /* Patch in the revised destination address */
+ buf[sbank][ptr] = na & 255;
+ buf[sbank][ptr+1] = na >> 8;
+}
+
+int stub_code(char *name)
+{
+ if(strncmp(name, "_CODE", 5) == 0)
+ return 1;
+ if(strcmp(name, "_VIDEO") == 0)
+ return 1;
+ if(strcmp(name, "_COMMONMEM") == 0)
+ return 1;
+ if(strcmp(name, "_DISCARD") == 0)
+ return 1;
+ /* Data */
+ if(strcmp(name, "_INITIALIZER") == 0)
+ return 0;
+ if(strcmp(name, "_DATA") == 0)
+ return 0;
+ if(strcmp(name, "_FONT") == 0)
+ return 0;
+ if(strcmp(name , "_CONST") == 0)
+ return 0;
+ fprintf(stderr, "Unknown bank name %s\n", name);
+ exit(1);
+}
+
+static void process_stub(char *p)
+{
+ int b1, b2, addr;
+ char name[65];
+ if (sscanf(p, "%02x %04x %02x %64s", &b1, &addr, &b2, name) != 4) {
+ fprintf(stderr, "Invalid relocation link %s\n", p);
+ exit(1);
+ }
+ if (stub_code(name))
+ code_reloc(b1, addr, b2);
+ else
+ data_reloc(b1, addr, b2);
+}
+
+
+int main(int argc, char *argv[])
+{
+ FILE *r;
+ char in[256];
+ char bin[64];
+ int banks;
+
+ if (argv[1] && strcmp(argv[1], "-v") == 0)
+ v = 1;
+ if (argc != 1 + v) {
+ fprintf(stderr, "%s -v\n", argv[0]);
+ exit(1);
+ }
+
+ r = fopen("relocs.dat", "r");
+ if (r == NULL) {
+ perror("relocs.dat");
+ exit(1);
+ }
+
+ for (banks = 0; banks < 4; banks ++) {
+ if (banks == 0)
+ strcpy(bin, "common.bin");
+ else
+ sprintf(bin, "bank%d.bin", banks);
+ fptr[banks] = fopen(bin, "r+");
+ if (fptr[banks] == NULL) {
+ if (errno != ENOENT) {
+ perror(bin);
+ exit(1);
+ }
+ } else {
+ size[banks] = fread(buf[banks], 1, 65536, fptr[banks]);
+ if (size[banks] < 1) {
+ perror(bin);
+ exit(1);
+ }
+ rewind(fptr[banks]);
+ }
+ }
+
+ while(fgets(in, 256, r)) {
+ if (*in != 'B') {
+ fprintf(stderr, "Bad record: %s", in);
+ exit(1);
+ }
+ if (v)
+ printf("|%s", in);
+ process_stub(in + 1);
+ }
+ fclose(r);
+
+ for (banks = 0; banks < 4; banks++) {
+ if (fptr[banks]) {
+ /* Just conceivably we might reloc a trailing zero byte and need to grow the
+ file */
+ size[banks] = resize(banks);
+ if (fwrite(buf[banks], size[banks], 1, fptr[banks]) != 1) {
+ perror("fwrite");
+ exit(1);
+ }
+ fclose(fptr[banks]);
+ }
+ }
+ printf("%d stub relocations using %d bytes, %d duplicates\n",
+ stubct, stubct * 4, stubdup);
+ exit(0);
+}