diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 3 | ||||
-rw-r--r-- | tools/make_shim.c | 163 | ||||
-rw-r--r-- | tools/make_shim.py | 102 |
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: |