summaryrefslogtreecommitdiff
path: root/tools/make_shim.c
diff options
context:
space:
mode:
authorPikalaxALT <pikalaxalt@gmail.com>2018-06-02 20:16:37 -0400
committerPikalaxALT <pikalaxalt@gmail.com>2018-06-02 20:16:37 -0400
commit956d010d59ad225bea768aec172ccb56977b1775 (patch)
tree4385f7c50ebb09e747f9e2cac4bc900d925060d4 /tools/make_shim.c
parent513028a98e6225e39c53ea64e4f9c483b3abd55b (diff)
Make the repository build all four ROMs
Diffstat (limited to 'tools/make_shim.c')
-rw-r--r--tools/make_shim.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/tools/make_shim.c b/tools/make_shim.c
new file mode 100644
index 0000000..8fdd0e7
--- /dev/null
+++ b/tools/make_shim.c
@@ -0,0 +1,163 @@
+#include <stdio.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct Section {
+ unsigned short end;
+ bool invalid;
+ char * name;
+ bool banked;
+};
+
+typedef struct Section section_t;
+
+// These functions are like strspn and strcspn, but from the right of the string rather than the left.
+size_t strrspn(const char *s1, const char *s2) {
+ const char * _s1 = s1;
+ const char * _s2;
+
+ while (*_s1++);
+ _s1--;
+ while (_s1 > s1) {
+ for (_s2 = s2; *_s2; _s2++) {
+ if (_s1[-1] == *_s2) {
+ break;
+ }
+ }
+ if (*_s2 == 0)
+ break;
+ _s1--;
+ }
+
+ return _s1 - s1;
+}
+
+size_t strrcspn(const char *s1, const char *s2) {
+ const char * _s1 = s1;
+ const char * _s2;
+
+ while (*_s1++);
+ _s1--;
+ while (_s1 > s1) {
+ for (_s2 = s2; *_s2; _s2++) {
+ if (_s1[-1] == *_s2)
+ break;
+ }
+ if (*_s2)
+ break;
+ _s1--;
+ }
+
+ return _s1 - s1;
+}
+
+#define RIP(errmsg) { \
+ errno = EIO; \
+ perror(errmsg); \
+ if (file) fclose(file); \
+ if (line) free(line); \
+ return 1; \
+}
+
+int main(int argc, char * argv[]) {
+ int ch;
+ size_t lsize = 0;
+ char * line = NULL;
+
+ section_t section_list[] = {
+ {0x4000, false, "ROM0", false},
+ {0x8000, false, "ROMX", true},
+ {0xA000, false, "VRAM", true},
+ {0xC000, false, "SRAM", true},
+ {0xD000, false, "WRAM0", false},
+ {0xE000, false, "WRAMX", true},
+ {0xFE00, true, "Echo RAM", false},
+ {0xFEA0, false, "OAM", false},
+ {0xFF80, true, "FEXX / IO", false},
+ {0xFFFF, false, "HRAM", false},
+ {}
+ };
+
+ while ((ch = getopt(argc, argv, "wdt")) != -1) {
+ switch (ch) {
+ case 'w':
+ case 'd':
+ section_list[4].end = 0xE000;
+ break;
+ case 't':
+ section_list[0].end = 0x8000;
+ break;
+ }
+ }
+
+ for (int arg_idx = optind; arg_idx < argc; arg_idx++) {
+ FILE * file = fopen(argv[arg_idx], "r");
+ if (file == NULL)
+ RIP("file io");
+ while (getline(&line, &lsize, file) > 0) {
+ unsigned short bank = 0;
+ unsigned short pointer = 0;
+ char * symbol = NULL;
+ char * end;
+ char * addr_p;
+
+ // line = line.split(";")[0].strip()
+ line += strspn(line, " \t\n");
+ end = strchr(line, ';');
+ if (end) *end = 0;
+ line[strrspn(line, " \t\n")] = 0;
+ if (!*line)
+ continue;
+
+ // Get the bank, address, and symbol
+ end = line + strcspn(line, " \t\n");
+ symbol = end + strspn(end, " \t\n");
+ if (!*symbol)
+ RIP("parse");
+ *end = 0;
+ addr_p = strchr(line, ':');
+ if (!addr_p)
+ RIP("parse");
+ *addr_p++ = 0;
+ pointer = strtoul(addr_p, &end, 16);
+ if (pointer == 0 && end == addr_p)
+ RIP("parse");
+ bank = strtoul(line, &end, 16);
+ if (bank == 0 && end == line)
+ RIP("parse");
+
+ // Main loop
+ const char * section = NULL;
+ section_t * section_type;
+
+ for (section_type = section_list; section_type->end; section_type++) {
+ if (pointer < section_type->end) {
+ if (section_type->invalid) {
+ fprintf(stderr, "Warning: cannot shim '%s' in section type '%s'\n", symbol, section_type->name);
+ } else {
+ section = section_type->name;
+ if (!section_type->banked)
+ bank = 0;
+ }
+ break;
+ }
+ }
+
+ if (section == NULL)
+ // Found section, but cannot shim it
+ continue;
+
+ printf("SECTION \"Shim for %s\", %s[$%04X]", symbol, section, pointer);
+ if (bank)
+ printf(", BANK[$%04X]", bank);
+ printf("\n%s::\n\n", symbol);
+ fflush(stdout);
+ }
+ fclose(file);
+ }
+ free(line);
+ return 0;
+}