From c1db41e39b70da6358752df6353c4ad780763292 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 28 Sep 2018 13:03:26 +0100 Subject: [PATCH] tools: add cartman Tool to build our MSX cartridge --- Kernel/tools/cartman.c | 146 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 Kernel/tools/cartman.c diff --git a/Kernel/tools/cartman.c b/Kernel/tools/cartman.c new file mode 100644 index 00000000..9a11e3e0 --- /dev/null +++ b/Kernel/tools/cartman.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include + +/* This code has probably killed Kenny.... */ + +static unsigned char buf[65536]; +static unsigned char out[65536]; + +static unsigned int s__CODE, s__INITIALIZER, s__DATA, + s__INITIALIZED, s__INITIALIZER, s__COMMONMEM, l__INITIALIZED, + l__COMMONMEM, l__CODE, l__DATA; + + +static void ProcessMap(FILE * fp) +{ + char buf[512]; + + while (fgets(buf, 511, fp)) { + char *p1 = strtok(buf, " \t\n"); + char *p2 = NULL; + + if (p1) + p2 = strtok(NULL, " \t\n"); + + if (p1 == NULL || p2 == NULL) + continue; + + if (strcmp(p2, "s__CODE") == 0) + sscanf(p1, "%x", &s__CODE); + if (strcmp(p2, "l__CODE") == 0) + sscanf(p1, "%x", &l__CODE); + if (strcmp(p2, "s__DATA") == 0) + sscanf(p1, "%x", &s__DATA); + if (strcmp(p2, "l__DATA") == 0) + sscanf(p1, "%x", &l__DATA); + if (strcmp(p2, "s__INITIALIZED") == 0) + sscanf(p1, "%x", &s__INITIALIZED); + if (strcmp(p2, "s__INITIALIZER") == 0) + sscanf(p1, "%x", &s__INITIALIZER); + if (strcmp(p2, "l__INITIALIZED") == 0) + sscanf(p1, "%x", &l__INITIALIZED); + if (strcmp(p2, "s__COMMONMEM") == 0) + sscanf(p1, "%x", &s__COMMONMEM); + if (strcmp(p2, "l__COMMONMEM") == 0) + sscanf(p1, "%x", &l__COMMONMEM); + } +} + + +int main(int argc, char *argv[]) +{ + FILE *map, *bin; + int tail = 0; + int start; + unsigned int end = 0; + int reloc = 0; + int pack_discard = 0; + int no_pack = 0; + int base; + + if (argc != 4) { + fprintf(stderr, "%s: [binary] [map] [output]\n", argv[0]); + exit(1); + } + bin = fopen(argv[1], "r"); + if (bin == NULL) { + perror(argv[1]); + exit(1); + } + if (fread(buf, 1, 65536, bin) == 0) { + fprintf(stderr, "%s: read error on %s\n", argv[0], + argv[1]); + exit(1); + } + fclose(bin); + + /* Start with the output matching the input */ + memcpy(out, buf, 65536); + + map = fopen(argv[2], "r"); + if (map == NULL) { + perror(argv[2]); + exit(1); + } + ProcessMap(map); + fclose(map); + + /* The packing for an MSX cartridge is not dissimilar to the usual + but has different constaints and because it's ROM we actually + have to pack difering bits */ + + printf("Scanning data from 0x%x to 0x%x\n", + s__DATA, s__DATA + l__DATA); + base = s__DATA; + while (base < s__DATA + l__DATA) { + if (buf[base] && buf[base] != 0xFF) { + fprintf(stderr, "0x%04x:0x%02x\n", + base, (unsigned char)buf[base]); + } + base++; + } + + /* Our standard layout begins with the code */ + start = s__CODE; + + if (s__CODE != 0 || l__CODE > 0x4000) { + fprintf(stderr, "Segment CODE must start at 0 and be under 16K long (%04X %04X).\n", + s__CODE, l__CODE); + exit(1); + } + /* We need to pack the writable stuff. We use the same basic model as + the other packers. */ + + /* Our prepared image ends with initializer in ROM to go to INITIALIZED + Append the common on the end of it */ + end = s__INITIALIZER + l__INITIALIZED; + memcpy(out + end, buf + s__COMMONMEM, l__COMMONMEM); + + printf("Commonmem packed at %04X for %04X bytes.\n", + end, l__COMMONMEM); + end += l__COMMONMEM; + printf("Image ends at %04X\n", end); + + if (end >= 0xC000) { + /* One day we may have to put discard in the top 16K and + juggle it into RAM */ + fprintf(stderr, "Image does not fit in 48K of cartridge.\n"); + exit(1); + } + + bin = fopen(argv[3], "w"); + if (bin == NULL) { + perror(argv[3]); + exit(1); + } + printf("Image file: %04X to %04X\n", start, end); + if (fwrite(out, 65536, 1, bin) != 1) { + perror(argv[3]); + exit(1); + } + fclose(bin); + exit(0); +} + -- 2.34.1