diff options
author | Rangi <remy.oukaour+rangi42@gmail.com> | 2020-06-14 18:08:43 -0400 |
---|---|---|
committer | Rangi <remy.oukaour+rangi42@gmail.com> | 2020-06-14 18:08:43 -0400 |
commit | 94a70b63cf7f1a9dbfc14fcee8e390791fc17a1b (patch) | |
tree | d1b2bb44621d8c2ebae4a613669eb75e37e507ad | |
parent | 7f6bc3d3826fe7727bdc8714aa0295a712a548c3 (diff) |
Sync tools with pokecrystal (fixes warnings when building lzcomp)
palette.c and png_dimensions.c will be synced when they are used.
-rw-r--r-- | Makefile | 37 | ||||
-rw-r--r-- | gfx/pics_silver.asm | 2 | ||||
-rw-r--r-- | tools/free_space.awk | 70 | ||||
-rw-r--r-- | tools/free_space.py | 73 | ||||
-rw-r--r-- | tools/gfx.c | 12 | ||||
-rw-r--r-- | tools/gfx.py | 417 | ||||
-rw-r--r-- | tools/lz/nullcomp.c | 2 | ||||
-rw-r--r-- | tools/lz/output.c | 12 | ||||
-rw-r--r-- | tools/lz/packing.c | 1 | ||||
-rw-r--r-- | tools/lz/repcomp.c | 2 | ||||
-rw-r--r-- | tools/lz/spcomp.c | 6 | ||||
-rw-r--r-- | tools/lz/uncomp.c | 4 | ||||
-rw-r--r-- | tools/pokemontools/gfx.py | 170 | ||||
-rw-r--r-- | tools/pokemontools/lz.py | 30 | ||||
-rw-r--r-- | tools/pokemontools/png.py | 6 | ||||
-rwxr-xr-x | tools/unnamed.py | 16 | ||||
-rw-r--r-- | tools/used_space.py | 2 |
17 files changed, 381 insertions, 481 deletions
@@ -38,20 +38,17 @@ RGBFIX ?= $(RGBDS)rgbfix RGBGFX ?= $(RGBDS)rgbgfx RGBLINK ?= $(RGBDS)rgblink -PYTHON := python -gfx := $(PYTHON) tools/gfx.py - ### Build targets .SUFFIXES: -.PHONY: all gold silver clean tidy pngs compare tools +.PHONY: all gold silver clean tidy compare tools .SECONDEXPANSION: .PRECIOUS: .SECONDARY: all: $(roms) -gold: pokegold.gbc +gold: pokegold.gbc silver: pokesilver.gbc clean: @@ -110,11 +107,11 @@ endif pokegold.gbc: $(gold_obj) layout.link $(RGBLINK) -n pokegold.sym -m pokegold.map -l layout.link -o $@ $(gold_obj) - $(RGBFIX) -cjsv -i AAUE -k 01 -l 0x33 -m 0x10 -p 0 -r 3 -t "POKEMON_GLD" $@ + $(RGBFIX) -cjsv -t POKEMON_GLD -i AAUE -k 01 -l 0x33 -m 0x10 -r 3 -p 0 $@ pokesilver.gbc: $(silver_obj) layout.link $(RGBLINK) -n pokesilver.sym -m pokesilver.map -l layout.link -o $@ $(silver_obj) - $(RGBFIX) -cjsv -i AAXE -k 01 -l 0x33 -m 0x10 -p 0 -r 3 -t "POKEMON_SLV" $@ + $(RGBFIX) -cjsv -t POKEMON_SLV -i AAXE -k 01 -l 0x33 -m 0x10 -r 3 -p 0 $@ ### LZ compression rules @@ -136,6 +133,16 @@ gfx/pokemon/%/back.2bpp: rgbgfx += -h gfx/pokemon/%/back_gold.2bpp: rgbgfx += -h gfx/pokemon/%/back_silver.2bpp: rgbgfx += -h +gfx/pokemon/%/back_gold.2bpp: gfx/pokemon/%/back.png + $(RGBGFX) $(rgbgfx) -o $@ $< + $(if $(tools/gfx),\ + tools/gfx $(tools/gfx) -o $@ $@) + +gfx/pokemon/%/back_silver.2bpp: gfx/pokemon/%/back.png + $(RGBGFX) $(rgbgfx) -o $@ $< + $(if $(tools/gfx),\ + tools/gfx $(tools/gfx) -o $@ $@) + gfx/trainers/%.2bpp: rgbgfx += -h gfx/new_game/shrink1.2bpp: rgbgfx += -h @@ -205,16 +212,6 @@ gfx/sgb/silver_border.2bpp: tools/gfx += --trim-whitespace ### Catch-all graphics rules -gfx/pokemon/%/back_gold.2bpp: gfx/pokemon/%/back.png - $(RGBGFX) $(rgbgfx) -o $@ $< - $(if $(tools/gfx),\ - tools/gfx $(tools/gfx) -o $@ $@) - -gfx/pokemon/%/back_silver.2bpp: gfx/pokemon/%/back.png - $(RGBGFX) $(rgbgfx) -o $@ $< - $(if $(tools/gfx),\ - tools/gfx $(tools/gfx) -o $@ $@) - %.2bpp: %.png $(RGBGFX) $(rgbgfx) -o $@ $< $(if $(tools/gfx),\ @@ -224,9 +221,3 @@ gfx/pokemon/%/back_silver.2bpp: gfx/pokemon/%/back.png $(RGBGFX) $(rgbgfx) -d1 -o $@ $< $(if $(tools/gfx),\ tools/gfx $(tools/gfx) -d1 -o $@ $@) - -pngs: - find gfx -iname "*.lz" -exec $(gfx) unlz {} + - find gfx -iname "*.[12]bpp" -exec $(gfx) png {} + - find gfx -iname "*.[12]bpp" -exec touch {} + - find gfx -iname "*.lz" -exec touch {} + diff --git a/gfx/pics_silver.asm b/gfx/pics_silver.asm index b3bed876..e8140f5a 100644 --- a/gfx/pics_silver.asm +++ b/gfx/pics_silver.asm @@ -2,7 +2,7 @@ INCLUDE "constants.asm" ; PokemonPicPointers and UnownPicPointers are assumed to start at the same -; address, but in different banks. This is enforced in pokesilver.link. +; address, but in different banks. This is enforced in layout.link. SECTION "Pic Pointers", ROMX diff --git a/tools/free_space.awk b/tools/free_space.awk new file mode 100644 index 00000000..45984ca7 --- /dev/null +++ b/tools/free_space.awk @@ -0,0 +1,70 @@ +#!/usr/bin/gawk -f + +# Usage: tools/free_space.awk [BANK=<bank_spec>] pokegold.map + +# 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". +# The `BANK` argument MUST be before the map file name, otherwise it has no effect! +# Yes: tools/free_space.awk BANK=all pokegold.map +# No: tools/free_space.awk pokegold.map BANK=42 + +# Copyright (c) 2020, Eldred Habert. +# SPDX-License-Identifier: MIT + +BEGIN { + nb_banks = 0 + free = 0 + rom_bank = 0 # Safety net for malformed files + + # Default settings + # Variables assigned via the command-line (except through `-v`) are *after* `BEGIN` + BANK="none" +} + +# Only accept ROM banks, ignore everything else +toupper($0) ~ /^[ \t]*ROM[0X][ \t]+BANK[ \t]+#/ { + nb_banks++ + rom_bank = 1 + split($0, fields, /[ \t]/) + bank_num = strtonum(substr(fields[3], 2)) +} + +function register_bank(amount) { + free += amount + rom_bank = 0 # Reject upcoming banks by default + + if (BANK ~ /all/ || BANK == bank_num) { + printf "Bank %3d: %5d/16384 (%.2f%%)\n", bank_num, amount, amount * 100 / 16384 + } +} + +rom_bank && toupper($0) ~ /^[ \t]*EMPTY/ { + # Empty bank + register_bank(16384) +} +rom_bank && toupper($0) ~ /^[ \t]*SLACK:[ \t]/ { + if ($2 ~ /\$[0-9A-F]+/) { + register_bank(strtonum("0x" substr($2, 2))) + } else { + printf "Malformed slack line? \"%s\" does not start with '$'\n", $2 + } +} + +END { + # Determine number of banks, by rounding to upper power of 2 + total_banks = 2 # Smallest size is 2 banks + while (total_banks < nb_banks) { + total_banks *= 2 + } + + # RGBLINK omits "trailing" ROM banks, so fake them + bank_num = nb_banks + while (bank_num < total_banks) { + register_bank(16384) + bank_num++ + } + + total = total_banks * 16384 + printf "Free space: %5d/%5d (%.2f%%)\n", free, total, free * 100 / total +} diff --git a/tools/free_space.py b/tools/free_space.py new file mode 100644 index 00000000..d6af522f --- /dev/null +++ b/tools/free_space.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Usage: python3 free_space.py [BANK=none] [pokegold.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' + mapfile = 'pokegold.map' + + if len(sys.argv) >= 2 and sys.argv[1].startswith('BANK='): + print_bank = sys.argv[1].split('=', 1)[-1] + if len(sys.argv) >= 3: + mapfile = sys.argv[2] + elif len(sys.argv) >= 3 and sys.argv[2].startswith('BANK='): + print_bank = sys.argv[2].split('=', 1)[-1] + mapfile = sys.argv[1] + + if print_bank not in {'all', 'none'}: + try: + if print_bank.startswith('0x') or print_bank.startswith('0X'): + print_bank = int(print_bank[2:], 16) + else: + print_bank = int(print_bank) + except ValueError: + error = 'Error: invalid BANK: %s' % print_bank + if print_bank.isalnum(): + error += ' (did you mean: 0x%s?)' % print_bank + print(error, file=sys.stderr) + sys.exit(1) + + num_banks = 0x80 + bank_size = 0x4000 # bytes + total_size = num_banks * bank_size + + r = MapReader() + with open(mapfile, 'r', encoding='utf-8') as f: + l = f.readlines() + r.read_map_data(l) + + free_space = 0 + per_bank = [] + default_bank_data = {'sections': [], 'used': 0, 'slack': bank_size} + for bank in range(num_banks): + bank_data = r.bank_data['ROM0 bank'] if bank == 0 else r.bank_data['ROMX bank'] + data = bank_data.get(bank, default_bank_data) + used = data['used'] + slack = data['slack'] + per_bank.append((used, slack)) + free_space += slack + + print('Free space: %d/%d (%.2f%%)' % (free_space, total_size, free_space * 100.0 / total_size)) + 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('$%02X, %d, %d' % (bank, used, slack)) + +if __name__ == '__main__': + main() diff --git a/tools/gfx.c b/tools/gfx.c index d7be9a81..6dad2f1a 100644 --- a/tools/gfx.c +++ b/tools/gfx.c @@ -132,10 +132,10 @@ void trim_whitespace(struct Graphic *graphic) { void remove_whitespace(struct Graphic *graphic) { int tile_size = Options.depth * 8; if (Options.interleave) tile_size *= 2; - + // Make sure we have a whole number of tiles, round down if required graphic->size &= ~(tile_size - 1); - + int i = 0; for (int j = 0, d = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { while (j < graphic->size && is_whitespace(&graphic->data[j], tile_size) && !is_preserved(j / tile_size - d)) { @@ -172,10 +172,10 @@ void remove_duplicates(struct Graphic *graphic) { int tile_size = Options.depth * 8; if (Options.interleave) tile_size *= 2; int num_tiles = 0; - + // Make sure we have a whole number of tiles, round down if required graphic->size &= ~(tile_size - 1); - + for (int i = 0, j = 0, d = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { while (j < graphic->size && tile_exists(&graphic->data[j], graphic->data, tile_size, num_tiles)) { if ((Options.keep_whitespace && is_whitespace(&graphic->data[j], tile_size)) || is_preserved(j / tile_size - d)) { @@ -226,10 +226,10 @@ void remove_flip(struct Graphic *graphic, bool xflip, bool yflip) { int tile_size = Options.depth * 8; if (Options.interleave) tile_size *= 2; int num_tiles = 0; - + // Make sure we have a whole number of tiles, round down if required graphic->size &= ~(tile_size - 1); - + for (int i = 0, j = 0, d = 0; i < graphic->size && j < graphic->size; i += tile_size, j += tile_size) { while (j < graphic->size && flip_exists(&graphic->data[j], graphic->data, tile_size, num_tiles, xflip, yflip)) { if ((Options.keep_whitespace && is_whitespace(&graphic->data[j], tile_size)) || is_preserved(j / tile_size - d)) { diff --git a/tools/gfx.py b/tools/gfx.py index 7007d37e..a3d95562 100644 --- a/tools/gfx.py +++ b/tools/gfx.py @@ -1,6 +1,9 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + """Supplementary scripts for graphics conversion.""" -import os, re +import os import argparse from pokemontools import gfx, lz @@ -28,42 +31,109 @@ base_stats = None def get_base_stats(): global base_stats if not base_stats: - base_stats = recursive_read('data/pokemon/base_stats.asm') + base_stats = recursive_read('data/base_stats.asm') return base_stats -def get_pokemon_dimensions(name): +def get_pokemon_dimensions(path): try: - if name == 'egg': - return 5, 5 - if name == 'questionmark': - return 7, 7 - if name.startswith('unown_'): - name = 'unown' - base_stats = get_base_stats() - # hack for pidgeot/mew (previously caught by being substrings of pidgeotto/mewtwo) - pattern = re.compile('\s+db {0}\s+'.format(name.upper())) - start = pattern.search(base_stats).start() - start = base_stats.find('\tdn ', start) - end = base_stats.find('\n', start) - line = base_stats[start:end].replace(',', ' ') - w, h = map(int, line.split()[1:3]) - return w, h + byte = bytearray(open(path, 'rb').read())[0] + width = byte & 0xf + height = (byte >> 8) & 0xf + return width, height except: - return 7, 7 - -mail_px8 = ['eon_mail_border_2', 'grass', 'lovely_mail_border', 'lovely_mail_underline', - 'morph_mail_border', 'morph_mail_divider', 'portrail_mail_border', - 'portraitmail_border', 'portraitmail_underline', 'small_heart', 'small_note', - 'small_pokeball', 'small_triangle', 'wave'] -mail_px16 = ['eon_mail_border_1', 'flower_1', 'flower_2', 'large_circle', 'large_heart', - 'large_pokeball', 'large_triangle', 'morph_mail_corner','music_mail_border', 'oddish', - 'sentret', 'unused_grass'] -mail_px24 = ['cloud', 'ditto', 'dratini', 'eevee', 'lapras', 'mew', 'natu', 'poliwag'] -mail_border_stretch = ['surf_mail_border', 'flower_mail_border', 'litebluemail_border'] - -overworld_px8 = ['boulder_dust', 'fishing_rod', 'grass_rustle', 'heal_machine', 'shadow', - 'trainer_battle_pokeball_tiles'] -overworld_px16 = ['chris_fish', 'cut_grass', 'cut_tree', 'headbutt_tree'] + return None + + +def get_animation_frames(path=None, w=7, h=7, bitmask_path=None, frame_path=None): + """Retrieve animation frame tilemaps from generated frame/bitmask data.""" + if not path: + path = bitmask_path + if not path: + path = frame_path + if not path: + raise Exception("need at least one of path, bitmask_path or frame_path") + + if not bitmask_path: + bitmask_path = os.path.join(os.path.split(path)[0], 'bitmask.asm') + if not frame_path: + frame_path = os.path.join(os.path.split(path)[0], 'frames.asm') + bitmask_lines = open(bitmask_path).readlines() + frame_lines = open(frame_path).readlines() + + bitmask_length = w * h + + bitmasks = [] + bitmask = [] + for line in bitmask_lines: + if '\tdb ' in line: + value = line.split('\tdb ')[1].strip().replace('%', '0b') + value = int(value, 0) + #print line.strip(), value, len(bitmasks), len(bitmask) + for bit in xrange(8): + bitmask += [(value >> bit) & 1] + if len(bitmask) >= bitmask_length: + bitmasks += [bitmask] + bitmask = [] + break + if bitmask: + bitmasks += [bitmask] + + frames = [] + frame_labels = [] + i = 0 + for line in frame_lines: + if '\tdw ' in line: + frame_labels += [line.split('\tdw ')[1].strip()] + else: + for part in line.split(): + part = part.strip() + if part in frame_labels: + frames += [(part, i)] + i += 1 + + results = [] + + for label, i in frames: + result = [] + + # get the bitmask and tile ids for each frame + # don't care if we read past bounds, so just read the rest of the file + values = [] + for line in frame_lines[i:]: + if '\tdb ' in line: + values += line.split('\tdb ')[1].split(';')[0].split(',') + + #print bitmasks + #print values[0] + #print int(values[0].replace('$', '0x'), 0) + bitmask = bitmasks[int(values[0].replace('$', '0x'), 0)] + tiles = values[1:] + k = 0 + j = 0 + for bit in bitmask: + if bit: + result += [int(tiles[k].replace('$', '0x'), 0)] + k += 1 + else: + result += [j] + j += 1 + + results += [result] + + return results + +def get_animated_graphics(path, w=7, h=7, bitmask_path=None, frame_path=None): + frames = get_animation_frames(path, w, h, bitmask_path, frame_path) + new_path = path.replace('.animated.2bpp', '.2bpp') + tiles = gfx.get_tiles(bytearray(open(path, 'rb').read())) + new_tiles = tiles[:w * h] + for frame in frames: + for tile in frame: + new_tiles += [tiles[tile]] + new_graphic = gfx.connect(new_tiles) + print new_path, list(new_graphic) + open(new_path, 'wb').write(bytearray(new_graphic)) + return new_path def filepath_rules(filepath): """Infer attributes of certain graphics by their location in the filesystem.""" @@ -85,251 +155,23 @@ def filepath_rules(filepath): index = filedir.find(pokemon_name) if index != -1: filedir = filedir[:index + len('unown')] + filedir[index + len('unown_a'):] - # startswith to handle front_gold / front_silver - if name.startswith('front'): + if name == 'front' or name == 'front.animated': args['pal_file'] = os.path.join(filedir, 'normal.pal') args['pic'] = True - # TODO: way to handle Crystal and Gold/Silver simultaneously? - # args['animate'] = True - # startswith to handle back_gold / back_silver - elif name.startswith('back'): + args['animate'] = True + elif name == 'back': args['pal_file'] = os.path.join(filedir, 'normal.pal') args['pic'] = True elif 'gfx/trainers' in filedir: - trainer_name = filedir.split('/')[-1] - args['pal_file'] = os.path.join(filedir, name + '.pal') args['pic'] = True - elif 'gfx/battle' in filedir: - if name == 'dude': - args['pic_dimensions'] = 6, 6 - elif name in ['balls', 'enemy_hp_bar_border']: - args['width'] = 32 - elif name == 'expbar': - args['width'] = 72 - elif name == 'hp_exp_bar_border': - args['width'] = 48 - - elif 'gfx/card_flip' in filedir: - if name == 'card_flip_1': - args['width'] = 128 - elif name == 'card_flip_2': - args['width'] = 24 - args['rows'] = [ - (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), (0, 2), - (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3), (0, 3) - ] - - elif 'gfx/credits' in filedir: - if name in ['bellossom', 'togepi', 'elekid', 'sentret']: - args['width'] = 32 - elif name == 'theend': - args['width'] = 64 - elif name == 'border': - args['width'] = 72 - - elif 'gfx/debug' in filedir: - if name == 'color_test': - args['width'] = 176 - - elif 'gfx/diploma' in filedir: - if name == 'diploma': - args['width'] = 128 - - elif 'gfx/dummy_game' in filedir: - if name == 'dummy_game': - args['width'] = 16 - - elif 'gfx/font' in filedir: - if name in ['font', 'font_inversed', 'font_battle_extra', 'font_extra']: - args['width'] = 128 - elif name == 'unused_bold_font': - args['width'] = 256 - - elif 'gfx/frames' in filedir: - args['width'] = 24 - - elif 'gfx/icons' in filedir: - if name == 'mail_big': - args['width'] = 16 - - elif 'gfx/intro' in filedir: - if name == 'logo_star': - args['width'] = 8 - elif name in ['gamefreak_logo', 'logo_sparkle']: - args['width'] = 24 - elif name == 'gamefreak_presents': - args['width'] = 104 - elif name == 'copyright': - args['width'] = 240 - elif name == 'charizard1': - args['width'] = 72 - args['rows'] = [ - (1, 8), (1, 8), (1, 8), (1, 8), (1, 8), (1, 8), (1, 8), (1, 8), - (0, 9), (0, 9), (0, 9), (0, 9), (0, 9), (0, 9), (0, 9) - ] - elif name == 'charizard2': - args['width'] = 72 - args['pad_indices'] = [0] - elif name == 'charizard3': - args['width'] = 64 - args['rows'] = [ - (0, 8), (0, 8), (0, 0), (1, 6), (1, 6), (1, 6), (1, 6), (1, 6), (1, 6), - (1, 6), (1, 6), (1, 6), (1, 6), (1, 6), (1, 6), (1, 6), (1, 6) - ] - elif name in ['grass1', 'grass2', 'water1', 'water2']: - args['width'] = 128 - - elif 'gfx/mail' in filedir: - if name in mail_px8: - args['width'] = 8 - elif name in mail_px16: - args['width'] = 16 - elif name in mail_px24: - args['width'] = 24 - elif name in mail_border_stretch: - args['width'] = 24 - args['pad_indices'] = [4] - elif name == 'large_note': - args['width'] = 16 - args['rows'] = [(1, 1), (0, 2)] - elif name == 'dragonite': - args['width'] = 56 - args['rows'] = [(0, 6), (1, 6), (2, 6)] - - elif 'gfx/naming_screen' in filedir: - args['width'] = 8 - - elif 'gfx/new_game' in filedir: - if name in ['shrink1', 'shrink2']: - args['width'] = 56 - args['pic_dimensions'] = 7, 7 - - elif 'gfx/overworld' in filedir: - if name == 'heal_machine': - args['width'] = 8 - elif name in overworld_px8: - args['width'] = 8 - elif name in overworld_px16: - args['width'] = 16 - - elif 'gfx/pack' in filedir: - if name == 'pack': - args['width'] = 40 - elif name == 'pack_menu': - args['width'] = 128 - - elif 'gfx/player' in filedir: - if name == 'chris_back': - args['pic_dimensions'] = 6, 6 - - elif 'gfx/pokedex' in filedir: - if name in ['slowpoke', 'pokedex', 'pokedex_sgb']: - args['width'] = 128 - - elif name == 'question_mark': - args['width'] = 56 - args['pic_dimensions'] = 7, 7 - - elif 'gfx/pokegear' in filedir: - if name == 'pokegear_sprites': - args['width'] = 16 - - elif name in ['pokegear', 'town_map']: - args['width'] = 128 - - elif 'gfx/mystery_gift' in filedir: - if name == 'mystery_gift': - args['width'] = 128 - args['rows'] = [(0, 15), (0, 15), (0, 2)] - elif name == 'mystery_gift_2': - args['width'] = 128 - # TODO: this is incomplete - elif name == 'question_mark': - args['width'] = 40 - args['rows'] = [(1, 4), (0, 0), (0, 0), (2, 3), (2, 1)] - elif name == 'border': - args['width'] = 56 - - elif 'gfx/sgb' in filedir: - args['width'] = 128 - #args['pal_file'] = os.path.join(filedir, name + '.pal') - - elif 'gfx/slots' in filedir: - if name == 'slots_1': - args['width'] = 16 - elif name == 'slots_2': - args['width'] = 16 - args['pic_dimensions'] = 2, 2 - # TODO: this is incomplete - elif name == 'slots_3': - args['width'] = 24 - - elif 'gfx/sprites' in filedir: - # TODO: this is incomplete - if name == 'big_onix': - args['width'] = 32 - args['rows'] = [(0, 4), (0, 4), (1, 2), (1, 2)] - else: - args['width'] = 16 - - elif 'gfx/stats' in filedir: - if name == 'stats_tiles': - args['width'] = 136 - - elif 'gfx/tilesets' in filedir: - if filedir == 'gfx/tilesets/roofs': - args['width'] = 24 - elif filedir != 'gfx/tilesets': - args['width'] = 8 - else: - args['tileset'] = True - - elif 'gfx/title' in filedir: - if name in ['logo_bottom_gold', 'logo_bottom_silver', 'logo_top_gold', 'logo_top_silver']: - args['width'] = 160 - elif name == 'lugia_silver': - args['width'] = 64 - args['pic_dimensions'] = 8, 4 - elif name == 'hooh_gold': - args['width'] = 64 - args['pic_dimensions'] = 8, 6 - elif name in ['title_trail_gold', 'title_trail_silver']: - args['width'] = 32 - - elif 'gfx/trainer_card' in filedir: - if name in ['badges', 'trainer_card']: - args['width'] = 16 - elif name == 'card_status': - args['width'] = 48 - elif name == 'chris_card': - args['width'] = 40 - elif name == 'leaders': - args['width'] = 80 - - elif 'gfx/trade' in filedir: - if name in ['arrow_left', 'arrow_right', 'cable']: - args['width'] = 8 - elif name in ['bubble', 'poof']: - args['width'] = 16 - elif name == 'ball': - args['width'] = 16 - args['rows'] = [(0, 1), (0, 1), (0, 2), (0, 2)] - elif name == 'border_tiles': - args['width'] = 24 - elif name == 'game_boy': - args['width'] = 56 - - elif 'gfx/unown_puzzle' in filedir: - if name == 'start_cancel': - args['width'] = 152 - elif name == 'tile_borders': - args['width'] = 64 - elif os.path.join(filedir, name) in pics: args['pic'] = True + elif filedir == 'gfx/tilesets': + args['tileset'] = True + if args.get('pal_file'): if os.path.exists(args['pal_file']): args['palout'] = args['pal_file'] @@ -342,12 +184,10 @@ def filepath_rules(filepath): w = min(w/8, h/8) args['pic_dimensions'] = w, w elif ext == '.2bpp': - # startswith to handle front_gold / front_silver - if pokemon_name and name.startswith('front'): - w, h = get_pokemon_dimensions(pokemon_name) + if pokemon_name and name == 'front' or name == 'front.animated': + w, h = get_pokemon_dimensions(filepath.replace(ext, '.dimensions')) or (7, 7) args['pic_dimensions'] = w, w - # startswith to handle back_gold / back_silver - elif pokemon_name and name.startswith('back'): + elif pokemon_name and name == 'back': args['pic_dimensions'] = 6, 6 else: args['pic_dimensions'] = 7, 7 @@ -377,31 +217,12 @@ def to_2bpp(filename, **kwargs): def to_png(filename, **kwargs): name, ext = os.path.splitext(filename) - if ext == '.1bpp': - basedir, basename = os.path.split(filename) - name, ext = os.path.splitext(basename) - # Ignoring these for convenience only - if basedir in ['gfx/footprints', 'gfx/font']: - return - # Ignoring these for convenience only - if name in ['hp_exp_bar_border']: - return - gfx.export_1bpp_to_png(filename, **kwargs) - elif ext == '.2bpp': - basedir, basename = os.path.split(filename) - name, ext = os.path.splitext(basename) - # TODO: how to actually make big_onix/slots_3 pngs (reusing one from pokecrystal for now) - if name in ['big_onix', 'slots_3']: - return - # TODO: same question for most/all battle anims - if basedir == 'gfx/battle_anims': - return - # Ignoring these for convenience only - if basedir == 'gfx/font': - return - if name in ['back_gold', 'back_silver']: - kwargs['fileout'] = os.path.join(basedir, 'back.png') - gfx.export_2bpp_to_png(filename, **kwargs) + if ext == '.1bpp': gfx.export_1bpp_to_png(filename, **kwargs) + elif ext == '.2bpp' and name.endswith('.animated'): + w, h = kwargs.get('pic_dimensions') or (7, 7) + new_path = get_animated_graphics(filename, w=w, h=h) + return to_png(new_path, **kwargs) + elif ext == '.2bpp': gfx.export_2bpp_to_png(filename, **kwargs) elif ext == '.png': pass elif ext == '.lz': decompress(filename, **kwargs) @@ -415,8 +236,6 @@ def compress(filename, **kwargs): def decompress(filename, **kwargs): lz_data = open(filename, 'rb').read() data = lz.Decompressed(lz_data).output - # hack to work for Alakazam's silver backsprite; needs to be multiple of 8 anyway - data = data[:len(data)//8*8] name, ext = os.path.splitext(filename) open(name, 'wb').write(bytearray(data)) diff --git a/tools/lz/nullcomp.c b/tools/lz/nullcomp.c index 33d0b726..d4535bd3 100644 --- a/tools/lz/nullcomp.c +++ b/tools/lz/nullcomp.c @@ -6,7 +6,7 @@ Flags values: 0 = split a trailing 33-to-64-byte block at the end into two short blocks; 1 = don't */ -struct command * store_uncompressed (const unsigned char * data, const unsigned char * bitflipped, unsigned short * size, unsigned flags) { +struct command * store_uncompressed (__attribute__((unused)) const unsigned char * data, __attribute__((unused)) const unsigned char * bitflipped, unsigned short * size, unsigned flags) { unsigned short position, block, remainder = *size; struct command * result = NULL; *size = 0; diff --git a/tools/lz/output.c b/tools/lz/output.c index 484a9516..43e7ba92 100644 --- a/tools/lz/output.c +++ b/tools/lz/output.c @@ -28,16 +28,8 @@ void write_commands_and_padding_to_textfile (const char * file, const struct com if (fputs("\tlzend\n", fp) < 0) error_exit(1, "could not write terminator to compressed output"); if (padding_size) { input_stream += padding_offset; - int rv = 0; - unsigned pos; - const char * prefix = "\tdb"; - for (pos = 0; (rv >= 0) && (pos < padding_size); pos ++) { - if (input_stream[pos]) - rv = fprintf(fp, "%s $%02hhx", prefix, input_stream[pos]); - else - rv = fprintf(fp, "%s 0", prefix); - prefix = ","; - } + int rv = fprintf(fp, "\tdb $%02hhx", *(input_stream ++)); + while ((rv >= 0) && (-- padding_size)) rv = fprintf(fp, ", $%02hhx", *(input_stream ++)); if (rv >= 0) rv = -(putc('\n', fp) == EOF); if (rv < 0) error_exit(1, "could not write padding to compressed output"); } diff --git a/tools/lz/packing.c b/tools/lz/packing.c index 3623be96..0cb9fae9 100644 --- a/tools/lz/packing.c +++ b/tools/lz/packing.c @@ -31,6 +31,7 @@ void optimize (struct command * commands, unsigned short count) { break; case 1: if (commands -> value != next -> value) break; + // fallthrough case 3: if ((commands -> count + next -> count) <= MAX_COMMAND_COUNT) { commands -> count += next -> count; diff --git a/tools/lz/repcomp.c b/tools/lz/repcomp.c index 754529e8..f2bbad8a 100644 --- a/tools/lz/repcomp.c +++ b/tools/lz/repcomp.c @@ -7,7 +7,7 @@ (lowest bit to highest: repeat single byte (1), repeat two bytes (2), repeat zeros (3)). */ -struct command * try_compress_repetitions (const unsigned char * data, const unsigned char * bitflipped, unsigned short * size, unsigned flags) { +struct command * try_compress_repetitions (const unsigned char * data, __attribute__((unused)) const unsigned char * bitflipped, unsigned short * size, unsigned flags) { unsigned short pos = 0, skipped = 0; struct command * result = malloc(*size * sizeof(struct command)); struct command * current = result; diff --git a/tools/lz/spcomp.c b/tools/lz/spcomp.c index ab33dbbc..b6184836 100644 --- a/tools/lz/spcomp.c +++ b/tools/lz/spcomp.c @@ -62,11 +62,11 @@ struct command find_best_copy (const unsigned char * data, unsigned short positi struct command simple = {.command = 7}; struct command flipped = simple, backwards = simple; short count, offset; - if (count = scan_forwards(data + position, length - position, data, position, &offset)) + if ((count = scan_forwards(data + position, length - position, data, position, &offset))) simple = (struct command) {.command = 4, .count = count, .value = offset}; - if (count = scan_forwards(data + position, length - position, bitflipped, position, &offset)) + if ((count = scan_forwards(data + position, length - position, bitflipped, position, &offset))) flipped = (struct command) {.command = 5, .count = count, .value = offset}; - if (count = scan_backwards(data, length - position, position, &offset)) + if ((count = scan_backwards(data, length - position, position, &offset))) backwards = (struct command) {.command = 6, .count = count, .value = offset}; struct command command; switch (flags / 24) { diff --git a/tools/lz/uncomp.c b/tools/lz/uncomp.c index b22fc75f..3544cd93 100644 --- a/tools/lz/uncomp.c +++ b/tools/lz/uncomp.c @@ -49,7 +49,7 @@ struct command * get_commands_from_file (const unsigned char * data, unsigned sh } if (slack) *slack = *size - (rp - data); *size = current - result; - return realloc(result, (*size ? *size : 1) * sizeof(struct command)); + return realloc(result, *size * sizeof(struct command)); error: free(result); return NULL; @@ -88,5 +88,5 @@ unsigned char * get_uncompressed_data (const struct command * commands, const un } } *size = current - result; - return realloc(result, *size ? *size : 1); + return result; } diff --git a/tools/pokemontools/gfx.py b/tools/pokemontools/gfx.py index f4f2ae3e..2979b5a7 100644 --- a/tools/pokemontools/gfx.py +++ b/tools/pokemontools/gfx.py @@ -2,20 +2,19 @@ import os import sys -import io -from . import png +import png from math import sqrt, floor, ceil import argparse import operator -from .lz import Compressed, Decompressed +from lz import Compressed, Decompressed def split(list_, interval): """ Split a list by length. """ - for i in range(0, len(list_), interval): + for i in xrange(0, len(list_), interval): j = min(i + interval, len(list_)) yield list_[i:j] @@ -67,7 +66,7 @@ def transpose(tiles, width=None): """ if width == None: width = int(sqrt(len(tiles))) # assume square image - tiles = sorted(enumerate(tiles), key= lambda i_tile: i_tile[0] % width) + tiles = sorted(enumerate(tiles), key= lambda (i, tile): i % width) return [tile for i, tile in tiles] def transpose_tiles(image, width=None): @@ -90,7 +89,7 @@ def interleave(tiles, width): def deinterleave(tiles, width): """ - 00 02 04 06 08 0a 00 01 02 03 04 05 + 00 02 04 06 08 0a 00 01 02 03 04 05 01 03 05 07 09 0b 06 07 08 09 0a 0b 0c 0e 10 12 14 16 --> 0c 0d 0e 0f 10 11 0d 0f 11 13 15 17 12 13 14 15 16 17 @@ -171,16 +170,16 @@ def test_condense_tiles_to_map(): def to_file(filename, data): """ - Apparently io.open(filename, 'wb').write(bytearray(data)) won't work. + Apparently open(filename, 'wb').write(bytearray(data)) won't work. """ - file = io.open(filename, 'wb') + file = open(filename, 'wb') for byte in data: file.write('%c' % byte) file.close() def decompress_file(filein, fileout=None): - image = bytearray(io.open(filein).read()) + image = bytearray(open(filein).read()) de = Decompressed(image) if fileout == None: @@ -189,7 +188,7 @@ def decompress_file(filein, fileout=None): def compress_file(filein, fileout=None): - image = bytearray(io.open(filein).read()) + image = bytearray(open(filein).read()) lz = Compressed(image) if fileout == None: @@ -206,7 +205,7 @@ def bin_to_rgb(word): return (red, green, blue) def convert_binary_pal_to_text_by_filename(filename): - pal = bytearray(io.open(filename).read()) + pal = bytearray(open(filename).read()) return convert_binary_pal_to_text(pal) def convert_binary_pal_to_text(pal): @@ -232,7 +231,7 @@ def read_rgb_macros(lines): def rewrite_binary_pals_to_text(filenames): for filename in filenames: pal_text = convert_binary_pal_to_text_by_filename(filename) - with io.open(filename, 'w') as out: + with open(filename, 'w') as out: out.write(pal_text) @@ -245,7 +244,7 @@ def flatten(planar): bottom = bottom top = top strip = [] - for i in range(7,-1,-1): + for i in xrange(7,-1,-1): color = ( (bottom >> i & 1) + (top *2 >> i & 2) @@ -260,14 +259,14 @@ def to_lines(image, width): """ tile_width = 8 tile_height = 8 - num_columns = width // tile_width - height = len(image) // width + num_columns = width / tile_width + height = len(image) / width lines = [] - for cur_line in range(height): - tile_row = cur_line // tile_height + for cur_line in xrange(height): + tile_row = cur_line / tile_height line = [] - for column in range(num_columns): + for column in xrange(num_columns): anchor = ( num_columns * tile_row * tile_width * tile_height + column * tile_width * tile_height + @@ -288,7 +287,7 @@ def dmg2rgb(word): value >>= 5 word = shift(word) # distribution is less even w/ << 3 - red, green, blue = [int(color * 8.25) for color in [word.next() for _ in range(3)]] + red, green, blue = [int(color * 8.25) for color in [word.next() for _ in xrange(3)]] alpha = 255 return (red, green, blue, alpha) @@ -307,7 +306,7 @@ def pal_to_png(filename): """ Interpret a .pal file as a png palette. """ - with io.open(filename) as rgbs: + with open(filename) as rgbs: colors = read_rgb_macros(rgbs.readlines()) a = 255 palette = [] @@ -381,7 +380,7 @@ def export_2bpp_to_png(filein, fileout=None, pal_file=None, height=0, width=0, t if fileout == None: fileout = os.path.splitext(filein)[0] + '.png' - image = io.open(filein, 'rb').read() + image = open(filein, 'rb').read() arguments = { 'width': width, @@ -389,14 +388,12 @@ def export_2bpp_to_png(filein, fileout=None, pal_file=None, height=0, width=0, t 'pal_file': pal_file, 'tile_padding': tile_padding, 'pic_dimensions': pic_dimensions, - 'pad_indices': kwargs.get('pad_indices', None), - 'rows': kwargs.get('rows', None) } arguments.update(read_filename_arguments(filein)) - #if pal_file == None: - # if os.path.exists(os.path.splitext(fileout)[0]+'.pal'): - # arguments['pal_file'] = os.path.splitext(fileout)[0]+'.pal' + if pal_file == None: + if os.path.exists(os.path.splitext(fileout)[0]+'.pal'): + arguments['pal_file'] = os.path.splitext(fileout)[0]+'.pal' result = convert_2bpp_to_png(image, **arguments) width, height, palette, greyscale, bitdepth, px_map = result @@ -409,7 +406,7 @@ def export_2bpp_to_png(filein, fileout=None, pal_file=None, height=0, width=0, t greyscale=greyscale, bitdepth=bitdepth ) - with io.open(fileout, 'wb') as f: + with open(fileout, 'wb') as f: w.write(f, px_map) @@ -428,12 +425,10 @@ def convert_2bpp_to_png(image, **kwargs): pic_dimensions = kwargs.get('pic_dimensions', None) pal_file = kwargs.get('pal_file', None) interleave = kwargs.get('interleave', False) - pad_indices = kwargs.get('pad_indices', None) - rows = kwargs.get('rows', None) # Width must be specified to interleave. if interleave and width: - image = interleave_tiles(image, width // 8) + image = interleave_tiles(image, width / 8) # Pad the image by a given number of tiles if asked. image += pad_color * 0x10 * tile_padding @@ -448,66 +443,34 @@ def convert_2bpp_to_png(image, **kwargs): trailing = len(image) % pic_length pic = [] - for i in range(0, len(image) - trailing, pic_length): + for i in xrange(0, len(image) - trailing, pic_length): pic += transpose_tiles(image[i:i+pic_length], h) image = bytearray(pic) + image[len(image) - trailing:] # Pad out trailing lines. - image += pad_color * 0x10 * ((w - (len(image) // 0x10) % h) % w) + image += pad_color * 0x10 * ((w - (len(image) / 0x10) % h) % w) def px_length(img): return len(img) * 4 def tile_length(img): - return len(img) * 4 // (8*8) + return len(img) * 4 / (8*8) if width and height: - tile_width = width // 8 + tile_width = width / 8 more_tile_padding = (tile_width - (tile_length(image) % tile_width or tile_width)) image += pad_color * 0x10 * more_tile_padding - # Manually define at which tile indices padding tiles should be inserted - elif width and pad_indices: - padding = pad_color * 0x10 - cur_offset = 0 - cur_idx = 0 - for idx in pad_indices: - next_offset = cur_offset + 0x10 * (idx - cur_idx) - image = image[cur_offset:next_offset] + padding + image[next_offset:] - cur_offset = next_offset + 0x10 - cur_idx = idx - - # Define width in pixels, and an array of (left_offset, tile_width) pairs - elif width and rows: - newimage = bytearray([]) - padding = pad_color * 0x10 - height = len(rows) * 8 - cur_index = 0 - for left_offset, tile_width in rows: - # add padding if the row is offset from the leftmost tile - newimage += padding * left_offset - - # add number of tiles to place horizontally, from base image - next_index = min(len(image), cur_index + 0x10 * tile_width) - newimage += image[cur_index:next_index] - cur_index = next_index - - # add padding if there are more tiles in the row - right_offset = max(0, width//8 - left_offset - tile_width) - newimage += padding * right_offset - - image = newimage - elif width and not height: - tile_width = width // 8 + tile_width = width / 8 more_tile_padding = (tile_width - (tile_length(image) % tile_width or tile_width)) image += pad_color * 0x10 * more_tile_padding - height = px_length(image) // width + height = px_length(image) / width elif height and not width: - tile_height = height // 8 + tile_height = height / 8 more_tile_padding = (tile_height - (tile_length(image) % tile_height or tile_height)) image += pad_color * 0x10 * more_tile_padding - width = px_length(image) // height + width = px_length(image) / height # at least one dimension should be given if width * height != px_length(image): @@ -515,15 +478,15 @@ def convert_2bpp_to_png(image, **kwargs): matches = [] # Height need not be divisible by 8, but width must. # See pokered gfx/minimize_pic.1bpp. - for w in range(8, px_length(image) // 2 + 1, 8): - h = px_length(image) // w + for w in range(8, px_length(image) / 2 + 1, 8): + h = px_length(image) / w if w * h == px_length(image): matches += [(w, h)] # go for the most square image if len(matches): - width, height = sorted(matches, key=lambda w_h: (w_h[1] % 8 != 0, w_h[1] + w_h[0]))[0] # favor height + width, height = sorted(matches, key= lambda (w, h): (h % 8 != 0, w + h))[0] # favor height else: - raise Exception('Image can\'t be divided into tiles ({} px)!'.format(px_length(image))) + raise Exception, 'Image can\'t be divided into tiles (%d px)!' % (px_length(image)) # convert tiles to lines lines = to_lines(flatten(image), width) @@ -554,7 +517,7 @@ def get_pic_animation(tmap, w, h): base = frames.pop(0) bitmasks = [] - for i in range(len(frames)): + for i in xrange(len(frames)): frame_text += '\tdw .frame{}\n'.format(i + 1) for i, frame in enumerate(frames): @@ -606,7 +569,7 @@ def export_png_to_2bpp(filein, fileout=None, palout=None, **kwargs): frame_text, bitmask_text = get_pic_animation(tmap, *arguments['pic_dimensions']) frames_path = os.path.join(os.path.split(fileout)[0], 'frames.asm') - with io.open(frames_path, 'w') as out: + with open(frames_path, 'w') as out: out.write(frame_text) bitmask_path = os.path.join(os.path.split(fileout)[0], 'bitmask.asm') @@ -618,7 +581,7 @@ def export_png_to_2bpp(filein, fileout=None, palout=None, **kwargs): bitmasks[-1] = bitmasks[-1].replace('1', '0') bitmask_text = ';'.join(bitmasks) - with io.open(bitmask_path, 'w') as out: + with open(bitmask_path, 'w') as out: out.write(bitmask_text) elif tmap != None and arguments.get('tilemap', False): @@ -668,9 +631,9 @@ def png_to_2bpp(filein, **kwargs): arguments.update(kwargs) if type(filein) is str: - filein = io.open(filein) + filein = open(filein) - assert hasattr(filein, 'read') + assert type(filein) is file width, height, rgba, info = png.Reader(filein).asRGBA8() @@ -680,16 +643,16 @@ def png_to_2bpp(filein, **kwargs): palette = [] for line in rgba: newline = [] - for px in range(0, len(line), len_px): + for px in xrange(0, len(line), len_px): color = dict(zip('rgba', line[px:px+len_px])) if color not in palette: if len(palette) < 4: palette += [color] else: # TODO Find the nearest match - print('WARNING: %s: Color %s truncated to' % (filein, color)) + print 'WARNING: %s: Color %s truncated to' % (filein, color), color = sorted(palette, key=lambda x: sum(x.values()))[0] - print(color) + print color newline += [color] image += [newline] @@ -736,11 +699,11 @@ def png_to_2bpp(filein, **kwargs): num_rows = max(height, tile_height) / tile_height image = [] - for row in range(num_rows): - for column in range(num_columns): + for row in xrange(num_rows): + for column in xrange(num_columns): # Split it up into strips to convert to planar data - for strip in range(min(tile_height, height)): + for strip in xrange(min(tile_height, height)): anchor = ( row * num_columns * tile_width * tile_height + column * tile_width + @@ -766,13 +729,13 @@ def png_to_2bpp(filein, **kwargs): tiles = get_tiles(image) pic_length = w * h - tile_width = width // 8 + tile_width = width / 8 trailing = len(tiles) % pic_length new_image = [] - for block in range(len(tiles) // pic_length): - offset = (h * tile_width) * ((block * w) // tile_width) + ((block * w) % tile_width) + for block in xrange(len(tiles) / pic_length): + offset = (h * tile_width) * ((block * w) / tile_width) + ((block * w) % tile_width) pic = [] - for row in range(h): + for row in xrange(h): index = offset + (row * tile_width) pic += tiles[index:index + w] new_image += transpose(pic, w) @@ -807,7 +770,7 @@ def export_palette(palette, filename): if os.path.exists(filename): # Pic palettes are 2 colors (black/white are added later). - with io.open(filename) as rgbs: + with open(filename) as rgbs: colors = read_rgb_macros(rgbs.readlines()) if len(colors) == 2: @@ -823,7 +786,7 @@ def png_to_lz(filein): name = os.path.splitext(filein)[0] export_png_to_2bpp(filein) - image = io.open(name+'.2bpp', 'rb').read() + image = open(name+'.2bpp', 'rb').read() to_file(name+'.2bpp'+'.lz', Compressed(image).output) @@ -845,33 +808,32 @@ def convert_1bpp_to_2bpp(data): def export_2bpp_to_1bpp(filename): name, extension = os.path.splitext(filename) - image = io.open(filename, 'rb').read() + image = open(filename, 'rb').read() image = convert_2bpp_to_1bpp(image) to_file(name + '.1bpp', image) def export_1bpp_to_2bpp(filename): name, extension = os.path.splitext(filename) - image = io.open(filename, 'rb').read() + image = open(filename, 'rb').read() image = convert_1bpp_to_2bpp(image) to_file(name + '.2bpp', image) -def export_1bpp_to_png(filename, fileout=None, **arguments): +def export_1bpp_to_png(filename, fileout=None): if fileout == None: fileout = os.path.splitext(filename)[0] + '.png' - if arguments is None : - arguments = read_filename_arguments(filename) + arguments = read_filename_arguments(filename) - image = io.open(filename, 'rb').read() + image = open(filename, 'rb').read() image = convert_1bpp_to_2bpp(image) result = convert_2bpp_to_png(image, **arguments) width, height, palette, greyscale, bitdepth, px_map = result w = png.Writer(width, height, palette=palette, compression=9, greyscale=greyscale, bitdepth=bitdepth) - with io.open(fileout, 'wb') as f: + with open(fileout, 'wb') as f: w.write(f, px_map) @@ -900,7 +862,7 @@ def convert_to_2bpp(filenames=[]): elif extension == '.png': export_png_to_2bpp(filename) else: - raise Exception("Don't know how to convert {} to 2bpp!".format(filename)) + raise Exception, "Don't know how to convert {} to 2bpp!".format(filename) def convert_to_1bpp(filenames=[]): for filename in filenames: @@ -912,7 +874,7 @@ def convert_to_1bpp(filenames=[]): elif extension == '.png': export_png_to_1bpp(filename) else: - raise Exception("Don't know how to convert {} to 1bpp!".format(filename)) + raise Exception, "Don't know how to convert {} to 1bpp!".format(filename) def convert_to_png(filenames=[]): for filename in filenames: @@ -924,18 +886,18 @@ def convert_to_png(filenames=[]): elif extension == '.png': pass else: - raise Exception("Don't know how to convert {} to png!".format(filename)) + raise Exception, "Don't know how to convert {} to png!".format(filename) def compress(filenames=[]): for filename in filenames: - data = io.open(filename, 'rb').read() + data = open(filename, 'rb').read() lz_data = Compressed(data).output to_file(filename + '.lz', lz_data) def decompress(filenames=[]): for filename in filenames: name, extension = os.path.splitext(filename) - lz_data = io.open(filename, 'rb').read() + lz_data = open(filename, 'rb').read() data = Decompressed(lz_data).output to_file(name, data) @@ -968,7 +930,7 @@ def main(): }.get(args.mode, None) if method == None: - raise Exception("Unknown conversion method!") + raise Exception, "Unknown conversion method!" method(args.filenames) diff --git a/tools/pokemontools/lz.py b/tools/pokemontools/lz.py index f48be45c..aef5c641 100644 --- a/tools/pokemontools/lz.py +++ b/tools/pokemontools/lz.py @@ -44,8 +44,8 @@ lz_end = 0xff bit_flipped = [ - sum(((byte >> i) & 1) << (7 - i) for i in range(8)) - for byte in range(0x100) + sum(((byte >> i) & 1) << (7 - i) for i in xrange(8)) + for byte in xrange(0x100) ] @@ -189,7 +189,7 @@ class Compressed: ) for method in self.lookback_methods: min_score = self.min_scores[method] - for address in range(self.address+1, self.address+best_score): + for address in xrange(self.address+1, self.address+best_score): length, index = self.find_lookback(method, address) if length > max(min_score, best_score): # BUG: lookbacks can reduce themselves. This appears to be a bug in the target also. @@ -211,7 +211,7 @@ class Compressed: def find_lookback(self, method, address=None): """Temporarily stubbed, because the real function doesn't run in polynomial time.""" - return 0, None + return 0, None def broken_find_lookback(self, method, address=None): if address is None: @@ -315,15 +315,15 @@ class Compressed: def do_winner(self): winners = filter( - lambda method_score: - method_score[1] - > self.min_scores[method_score[0]] + int(method_score[1] > lowmax), + lambda (method, score): + score + > self.min_scores[method] + int(score > lowmax), self.scores.iteritems() ) winners.sort( - key = lambda method_score: ( - -(method_score[1] - self.min_scores[method_score[0]] - int(method_score[1] > lowmax)), - self.preference.index(method_score[0]) + key = lambda (method, score): ( + -(score - self.min_scores[method] - int(score > lowmax)), + self.preference.index(method) ) ) winner, score = winners[0] @@ -368,11 +368,11 @@ class Compressed: output += [offset / 0x100, offset % 0x100] # big endian if self.debug: - print(' '.join(map(str, [ + print ' '.join(map(str, [ cmd, length, '\t', ' '.join(map('{:02x}'.format, output)), self.data[start_address:start_address+length] if cmd in self.lookback_methods else '', - ]))) + ])) self.output += output @@ -414,7 +414,7 @@ class Decompressed: if self.lz is not None: self.decompress() - if self.debug: print(self.command_list()) + if self.debug: print self.command_list() def command_list(self): @@ -543,7 +543,7 @@ class Decompressed: Write alternating bytes. """ alts = [self.next(), self.next()] - self.output += [ alts[x & 1] for x in range(self.length) ] + self.output += [ alts[x & 1] for x in xrange(self.length) ] def blank(self): """ @@ -575,6 +575,6 @@ class Decompressed: self.get_offset() self.direction = direction # Note: appends must be one at a time (this way, repeats can draw from themselves if required) - for i in range(self.length): + for i in xrange(self.length): byte = self.output[ self.offset + i * direction ] self.output.append( table[byte] if table else byte ) diff --git a/tools/pokemontools/png.py b/tools/pokemontools/png.py index 3d6934a9..db6da128 100644 --- a/tools/pokemontools/png.py +++ b/tools/pokemontools/png.py @@ -646,9 +646,9 @@ class Writer: # http://www.w3.org/TR/PNG/#11IHDR write_chunk(outfile, b'IHDR', - struct.pack("!2I5B", int(self.width), int(self.height), - self.bitdepth, int(self.color_type), - 0, 0, int(self.interlace))) + struct.pack("!2I5B", self.width, self.height, + self.bitdepth, self.color_type, + 0, 0, self.interlace)) # See :chunk:order # http://www.w3.org/TR/PNG/#11gAMA diff --git a/tools/unnamed.py b/tools/unnamed.py index 1c66a36d..54a1473f 100755 --- a/tools/unnamed.py +++ b/tools/unnamed.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 -import os, re from sys import stderr, exit from subprocess import Popen, PIPE from struct import unpack, calcsize @@ -31,25 +30,18 @@ signal(SIGPIPE,SIG_DFL) import argparse parser = argparse.ArgumentParser(description="Parse the symfile to find unnamed symbols") -parser.add_argument('symfile', type=str, help="the filename with the list of symbols") +parser.add_argument('symfile', type=argparse.FileType('r'), help="the list of symbols") parser.add_argument('-r', '--rootdir', type=str, help="scan the output files to obtain a list of files with unnamed symbols (NOTE: will rebuild objects as necessary)") args = parser.parse_args() # Get list of object files objects = None -obj_suffix = '_obj := ' -m = re.match('poke(.*)\.sym', args.symfile) -sym_game = m.group(1) -def match_obj(game, line): - return (sym_game == game) and line.startswith(game + obj_suffix) if args.rootdir: for line in Popen(["make", "-C", args.rootdir, "-s", "-p"], stdout=PIPE).stdout.read().decode().split("\n"): - if match_obj('gold', line) or match_obj('silver', line): - offset = len(sym_game) + len(obj_suffix) - objects = line[offset:].strip().split() + if line.startswith("crystal_obj := "): + objects = line[15:].strip().split() break - else: print("Error: Object files not found!", file=stderr) exit(1) @@ -57,7 +49,7 @@ if args.rootdir: # Scan all unnamed symbols from the symfile symbols_total = 0 symbols = set() -for line in open(args.symfile, 'r'): +for line in args.symfile: line = line.split(";")[0].strip() split = line.split(" ") if len(split) < 2: diff --git a/tools/used_space.py b/tools/used_space.py index 73ece93d..6d313cf6 100644 --- a/tools/used_space.py +++ b/tools/used_space.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ -Usage: python3 used_space.py [pokecrystal.map] [used_space.png] +Usage: python3 used_space.py [pokegold.map] [used_space.png] Generate a PNG visualizing the space used by each bank in the ROM. """ |