summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile3
-rw-r--r--tools/make_shim.c163
-rw-r--r--tools/make_shim.py102
3 files changed, 206 insertions, 62 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 6c49ccb..c591d9c 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -4,7 +4,8 @@ CFLAGS := -O3 -std=c99 -Wall -Wextra
tools := \
pkmncompress \
- gfx
+ gfx \
+ make_shim
all: $(tools)
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;
+}
diff --git a/tools/make_shim.py b/tools/make_shim.py
index d5e6e00..65d9362 100644
--- a/tools/make_shim.py
+++ b/tools/make_shim.py
@@ -1,60 +1,40 @@
#!/usr/bin/env python
from __future__ import print_function
-from sys import argv, stderr, exit
-
-
-section_list = [
- {'end': 0x4000, 'invalid': False, 'name': "ROM0", 'banked': False},
- {'end': 0x8000, 'invalid': False, 'name': "ROMX", 'banked': True},
- {'end': 0xA000, 'invalid': False, 'name': "VRAM", 'banked': True},
- {'end': 0xC000, 'invalid': False, 'name': "SRAM", 'banked': True},
- {'end': 0xD000, 'invalid': False, 'name': "WRAM0", 'banked': False},
- {'end': 0xE000, 'invalid': False, 'name': "WRAMX", 'banked': True},
- {'end': 0xFE00, 'invalid': True , 'name': "Echo RAM"},
- {'end': 0xFEA0, 'invalid': False, 'name': "OAM", 'banked': False},
- {'end': 0xFF80, 'invalid': True , 'name': "FEXX / IO"},
- {'end': 0xFFFF, 'invalid': False, 'name': "HRAM", 'banked': False}
-]
-
-
-argv_id = 1
-file_list = []
-options = []
-while argv_id < len(argv):
- arg = argv[argv_id]
-
- if arg[0] != '-':
- file_list.append(arg)
- argv_id += 1
- continue
-
- # An empty '--' stops parsing arguments
- if arg == '--':
- argv_id += 1
- break
-
- if arg[1] == '-':
- options.append(option[2:])
- elif arg[1] != '-':
- for option in arg[1:]:
- options.append(option)
-
- argv_id += 1
-
-# Add remaining files to the list
-for arg in argv[argv_id:]:
- file_list.append(arg)
-
-
-if 'w' in options or 'd' in options:
- section_list[4]['end'] = 0xE000
-
-if 't' in options:
- section_list[0]['end'] = 0x8000
-
-
-for file_name in file_list:
+import argparse
+from sys import stderr
+from collections import OrderedDict, namedtuple
+
+Section = namedtuple('Section', ('end', 'invalud', 'banked'))
+section_list = OrderedDict(
+ ROM0=Section(0x4000, False, False),
+ ROMX=Section(0x8000, False, True),
+ VRAM=Section(0xA000, False, True),
+ SRAM=Section(0xC000, False, True),
+ WRAM0=Section(0xD000, False, False),
+ WRAMX=Section(0xE000, False, True),
+ EchoRAM=Section(0xFE00, True, False),
+ OAM=Section(0xFEA0, False, False),
+ IO=Section(0xFF80, True, False),
+ HRAM=Section(0xFFFF, False, False)
+)
+
+parser = argparse.ArgumentParser()
+parser.add_argument('files', nargs='+', type=argparse.FileType())
+parser.add_argument('-w', action='store_true')
+parser.add_argument('-d', action='store_true')
+parser.add_argument('-t', action='store_true')
+args = parser.parse_args()
+
+
+if args.w or args.d:
+ section_list['WRAM0'].end = 0xE000
+
+if args.t:
+ section_list['ROM0'].end = 0x8000
+
+
+for file_name in args.files:
for line in open(file_name, "rt"):
# Strip out the comment
@@ -68,19 +48,19 @@ for file_name in file_list:
bank, pointer = address.split(":")
bank = int(bank, 16)
pointer = int(pointer, 16)
- except:
+ except ValueError:
print("Error: Cannot parse line: %s" % line, file=stderr)
- exit(1)
+ raise from None
section = None
- for section_type in section_list:
- if pointer < section_type['end']:
- if section_type['invalid']:
+ for name, section_type in section_list.items():
+ if pointer < section_type.end:
+ if section_type.invalid:
print("Warning: cannot shim '%s' in section type '%s'" % (symbol, section_type['name']), file=stderr)
section = False
else:
- section = section_type['name']
- if not section_type['banked']:
+ section = name
+ if not section_type.banked:
bank = None
break
else: