diff options
| author | Rangi <remy.oukaour+rangi42@gmail.com> | 2022-10-02 22:42:26 -0400 |
|---|---|---|
| committer | Rangi <remy.oukaour+rangi42@gmail.com> | 2022-10-02 22:42:26 -0400 |
| commit | 7dd9d7dc80dcd57ce079d0f365257035e9df4614 (patch) | |
| tree | 3807ecb72443ecf12feb4faa0e4d811bad279458 /tools | |
| parent | Merge remote-tracking branch 'remotes/pokered/master' (diff) | |
| parent | Require rgbds 0.6.0 (diff) | |
| download | pokeyellow-7dd9d7dc80dcd57ce079d0f365257035e9df4614.tar.gz pokeyellow-7dd9d7dc80dcd57ce079d0f365257035e9df4614.tar.xz pokeyellow-7dd9d7dc80dcd57ce079d0f365257035e9df4614.zip | |
Merge remote-tracking branch 'remotes/pokered/master'
Diffstat (limited to 'tools')
| -rwxr-xr-x | tools/free_space.awk | 2 | ||||
| -rwxr-xr-x | tools/free_space.py | 69 | ||||
| -rw-r--r-- | tools/mapreader.py | 173 | ||||
| -rwxr-xr-x | tools/used_space.py | 64 |
4 files changed, 1 insertions, 307 deletions
diff --git a/tools/free_space.awk b/tools/free_space.awk index 587ac123..e47f35c1 100755 --- a/tools/free_space.awk +++ b/tools/free_space.awk @@ -39,7 +39,7 @@ function register_bank(amount) { } } -rom_bank && toupper($0) ~ /^[ \t]*EMPTY/ { +rom_bank && toupper($0) ~ /^[ \t]*EMPTY$/ { # Empty bank register_bank(16384) } diff --git a/tools/free_space.py b/tools/free_space.py deleted file mode 100755 index 4194f826..00000000 --- a/tools/free_space.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Usage: python3 free_space.py [BANK=none] [pokeyellow.map] - -Calculate the free space in the ROM or its individual banks. - -The BANK argument allows printing free space in one, all, or none of the ROM's banks. -Valid arguments are numbers (in decimal "42" or hexadecimal "0x2A"), "all" or "none". -If not specified, defaults to "none". -""" - -import sys - -from mapreader import MapReader - -def main(): - print_bank = 'none' - filename = 'pokeyellow.map' - - for arg in sys.argv[1:]: - if arg.startswith('BANK='): - print_bank = arg.split('=', 1)[-1] - else: - filename = arg - - if print_bank not in {'all', 'none'}: - try: - print_bank = (int(print_bank[2:], 16) - if print_bank.startswith('0x') or print_bank.startswith('0X') - else int(print_bank)) - except ValueError: - error = f'Error: invalid BANK: {print_bank}' - if print_bank.isalnum(): - error += f' (did you mean: 0x{print_bank}?)' - print(error, file=sys.stderr) - sys.exit(1) - - num_banks = 0x80 - bank_size = 0x4000 # bytes - total_size = num_banks * bank_size - - reader = MapReader() - with open(filename, 'r', encoding='utf-8') as file: - reader.read_map_data(file.readlines()) - - free_space = 0 - per_bank = [] - default_bank_data = {'sections': [], 'used': 0, 'slack': bank_size} - for bank in range(num_banks): - bank_data = reader.bank_data['ROM0 bank' if bank == 0 else 'ROMX bank'] - data = bank_data.get(bank, default_bank_data) - used, slack = data['used'], data['slack'] - per_bank.append((used, slack)) - free_space += slack - - free_percent = 100 * free_space / total_size - print(f'Free space: {free_space}/{total_size} ({free_percent:.2f}%)') - if print_bank != 'none': - print() - print('bank, used, free') - for bank in range(num_banks): - used, slack = per_bank[bank] - if print_bank in {'all', bank}: - print(f'${bank:02X}, {used}, {slack}') - -if __name__ == '__main__': - main() diff --git a/tools/mapreader.py b/tools/mapreader.py deleted file mode 100644 index 6d3528c9..00000000 --- a/tools/mapreader.py +++ /dev/null @@ -1,173 +0,0 @@ -# -*- coding: utf-8 -*- - -# A library for parsing the pokeyellow.map file output by rgbds. - -import re - -class MapReader: - - # {'ROM Bank': { 0: { 'sections': [ { 'beg': 1234, - # 'end': 5678, - # 'name': 'Section001', - # 'symbols': [ { 'symbol': 'Function1234', - # 'address: 1234, - # }, - # ] - # }, - # ], - # 'used': 1234, - # 'slack': 4567, - # }, - # }, - # 'OAM': { 'sections': [ { 'beg': 1234, - # 'end': 5678, - # 'name': 'Section002', - # 'symbols': [ { 'symbol': 'Data1234', - # 'address: 1234, - # }, - # ] - # }, - # ], - # 'used': 1234, - # 'slack': 4567, - # }, - # } - # - bank_data = {} - - bank_types = { - 'HRAM' : { 'size': 0x80, 'banked': False, }, - 'OAM' : { 'size': 0xA0, 'banked': False, }, - 'ROM0 bank': { 'size': 0x4000, 'banked': True, }, - 'ROMX bank': { 'size': 0x4000, 'banked': True, }, - 'SRAM bank': { 'size': 0x2000, 'banked': True, }, - 'VRAM bank': { 'size': 0x1000, 'banked': True, }, - 'WRAM bank': { 'size': 0x2000, 'banked': True, }, - } - - # FSM states - INIT, BANK, SECTION = range(3) - - # $506D-$519A ($012E bytes) ["Type Matchups"] - section_header_regex = re.compile('\$([0-9A-Fa-f]{4})-\$([0-9A-Fa-f]{4}) \(.*\) \["(.*)"\]') - # $506D = TypeMatchups - section_data_regex = re.compile('\$([0-9A-Fa-f]{4}) = (.*)') - # $3ED2 bytes - slack_regex = re.compile('\$([0-9A-Fa-f]{4}) bytes?') - - def __init__(self, *args, **kwargs): - self.__dict__.update(kwargs) - - def _parse_init(self, line): - - line = line.split(':', 1)[0] - parts = line.split(' #', 1) - - if (parts[0] in self.bank_types): - self._cur_bank_name = parts[0] - self._cur_bank_type = self.bank_types[self._cur_bank_name] - if (self._cur_bank_type['banked'] and len(parts) > 1): - parts[1] = parts[1].split(':', 1)[0] - parts[1] = parts[1].split(' ', 1)[0] - self._cur_bank = int(parts[1], 10) - if self._cur_bank_name not in self.bank_data: - self.bank_data[self._cur_bank_name] = {} - if self._cur_bank_type['banked']: - if self._cur_bank not in self.bank_data[self._cur_bank_name]: - self.bank_data[self._cur_bank_name][self._cur_bank] = {} - self._cur_data = self.bank_data[self._cur_bank_name][self._cur_bank] - else: - self._cur_data = self.bank_data[self._cur_bank_name] - - if ({} == self._cur_data): - self._cur_data['sections'] = [] - self._cur_data['used'] = 0 - self._cur_data['slack'] = self._cur_bank_type['size'] - return True - - return False - - def _parse_section_header(self, header): - - section_data = self.section_header_regex.match(header) - if section_data is not None: - beg = int(section_data.group(1), 16) - end = int(section_data.group(2), 16) - name = section_data.group(3) - self._cur_section = {'beg': beg, 'end': end, 'name': name, 'symbols': []} - self._cur_data['sections'].append(self._cur_section) - return True - return False - - def _parse_slack(self, data): - - slack_data = self.slack_regex.match(data) - slack_bytes = int(slack_data.group(1), 16) - self._cur_data['slack'] = slack_bytes - - used_bytes = 0 - - for s in self._cur_data['sections']: - used_bytes += s['end'] - s['beg'] + 1 - - self._cur_data['used'] = used_bytes - - def read_map_data(self, map): - - if type(map) is str: - map = map.split('\n') - - self._state = MapReader.INIT - self._cur_bank_name = '' - self._cur_bank_type = {} - self._cur_bank = 0 - self._cur_data = {} - - for line in map: - - line = line.rstrip() - if (MapReader.INIT == self._state): - - if (self._parse_init(line)): - self._state = MapReader.BANK - - elif (MapReader.BANK == self._state or MapReader.SECTION == self._state): - - if ('' == line): - self._state = MapReader.INIT - else: - - line = line.lstrip() - parts = line.split(': ', 1) - - if (MapReader.SECTION == self._state): - section_data = self.section_data_regex.match(parts[0]) - if section_data is not None: - address = int(section_data.group(1), 16) - name = section_data.group(2) - self._cur_section['symbols'].append({'name': name, 'address': address}) - continue - - if ('SECTION' == parts[0]): - if (self._parse_section_header(parts[1])): - self._state = MapReader.SECTION - elif ('SLACK' == parts[0]): - self._parse_slack(parts[1]) - self._state = MapReader.INIT - elif ('EMPTY' == parts[0]): - self._cur_data = {'sections': [], 'used': 0, 'slack': self._cur_bank_type['size']} - self._state = MapReader.INIT - - else: - pass - - for k, v in self.bank_data.items(): - if (self.bank_types[k]['banked']): - for _, vv in v.items(): - vv['sections'].sort(key=lambda x: x['beg']) - for vvv in vv['sections']: - vvv['symbols'].sort(key=lambda x: x['address']) - else: - v['sections'].sort(key=lambda x: x['beg']) - for vv in v['sections']: - vv['symbols'].sort(key=lambda x: x['address']) diff --git a/tools/used_space.py b/tools/used_space.py deleted file mode 100755 index 53946b87..00000000 --- a/tools/used_space.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Usage: python used_space.py [pokeyellow.map] [used_space.png] - -Generate a PNG visualizing the space used by each bank in the ROM. -""" - -import sys -from colorsys import hls_to_rgb - -import png -from mapreader import MapReader - -def main(): - mapfile = sys.argv[1] if len(sys.argv) >= 2 else 'pokeyellow.map' - outfile = sys.argv[2] if len(sys.argv) >= 3 else 'used_space.png' - - num_banks = 0x80 - bank_mask = 0x3FFF - bank_size = 0x4000 # bytes - - bpp = 8 # bytes per pixel - height = 256 # pixels - assert bank_size % bpp == 0 and (bank_size // bpp) % height == 0 - - pixels_per_bank = bank_size // bpp # 2048 pixels - bank_width = pixels_per_bank // height # 8 pixels - width = bank_width * num_banks # 1024 pixels - - reader = MapReader() - with open(mapfile, 'r', encoding='utf-8') as file: - reader.read_map_data(file.readlines()) - - hit_data = [] - default_bank_data = {'sections': [], 'used': 0, 'slack': bank_size} - for bank in range(num_banks): - hits = [0] * pixels_per_bank - bank_data = reader.bank_data['ROM0 bank' if bank == 0 else 'ROMX bank'] - data = bank_data.get(bank, default_bank_data) - for s in data['sections']: - beg = s['beg'] & bank_mask - end = s['end'] & bank_mask - for i in range(beg, end + 1): - hits[i // bpp] += 1 - hit_data.append(hits) - - pixels = [[(0xFF, 0xFF, 0xFF)] * width for _ in range(height)] - for bank, hits in enumerate(hit_data): - hue = 0 if bank == 0 else 210 if bank % 2 else 270 - for i, hit in enumerate(hits): - x, y = i % bank_width + bank * bank_width, i // bank_width - hls = (hue / 360, 1 - (85 * hit / bpp) / 100, 1) - rgb = tuple(int(c * 0xFF) for c in hls_to_rgb(*hls)) - pixels[y][x] = rgb - - png_data = [tuple(c for pixel in row for c in pixel) for row in pixels] - with open(outfile, 'wb') as file: - writer = png.Writer(width, height, greyscale=False, bitdepth=8, compression=9) - writer.write(file, png_data) - -if __name__ == '__main__': - main() |
