From 33c8e4147c9a188b677a0995e8f9ce0760a2d60e Mon Sep 17 00:00:00 2001 From: yenatch Date: Sun, 15 Sep 2013 15:46:26 -0400 Subject: map_editor: red: read tileset gfx filenames from source --- pokemontools/map_editor.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 92e4a63..208cc49 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -348,11 +348,27 @@ class Tileset: self.get_blocks() self.get_tiles() + def get_tileset_gfx_filename(self): + filename = None + + if version == 'red': + tileset_defs = open(os.path.join(conf.path, 'main.asm'), 'r').read() + incbin = asm_at_label(tileset_defs, 'Tset%.2X_GFX' % self.id) + print incbin + filename = read_header_macros(incbin, ['filename'], ['INCBIN'])[0][0].replace('"','').replace('.2bpp','.png') + filename = os.path.join(conf.path, filename) + print filename + + if not filename: + filename = os.path.join( + gfx_dir, + to_gfx_name(self.id) + '.png' + ) + + return filename + def get_tiles(self): - filename = os.path.join( - gfx_dir, - to_gfx_name(self.id) + '.png' - ) + filename = self.get_tileset_gfx_filename() self.img = Image.open(filename) self.img.width, self.img.height = self.img.size self.tiles = [] -- cgit v1.2.3 From 918adb82ba054477dacbc4c088f0acfe9961ac24 Mon Sep 17 00:00:00 2001 From: yenatch Date: Tue, 24 Sep 2013 03:24:29 -0400 Subject: script commands wildon and wildoff got mixed up this was a mistake in the original pksv spec and tauwasser's notes --- pokemontools/crystal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 8a12dad..25ad6f7 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2743,8 +2743,8 @@ pksv_crystal_more = { 0x34: ["checkbit2", ["bit_number", MultiByteParam]], 0x35: ["clearbit2", ["bit_number", MultiByteParam]], 0x36: ["setbit2", ["bit_number", MultiByteParam]], - 0x37: ["wildoff"], - 0x38: ["wildon"], + 0x37: ["wildon"], + 0x38: ["wildoff"], 0x39: ["xycompare", ["pointer", MultiByteParam]], 0x3A: ["warpmod", ["warp_id", SingleByteParam], ["map_group", MapGroupParam], ["map_id", MapIdParam]], 0x3B: ["blackoutmod", ["map_group", MapGroupParam], ["map_id", MapIdParam]], -- cgit v1.2.3 From 46f1a2e1c3f4d1feeeeb3214f59fccf635415f8f Mon Sep 17 00:00:00 2001 From: yenatch Date: Tue, 24 Sep 2013 03:28:55 -0400 Subject: rename bit1/bit2 script commands to event/flag --- pokemontools/crystal.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 25ad6f7..d93540b 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2737,12 +2737,12 @@ pksv_crystal_more = { 0x2E: ["giveegg", ["pkmn", PokemonParam], ["level", DecimalParam]], 0x2F: ["givepokeitem", ["pointer", PointerParamToItemAndLetter]], 0x30: ["checkpokeitem", ["pointer", PointerParamToItemAndLetter]], # not pksv - 0x31: ["checkbit1", ["bit_number", MultiByteParam]], - 0x32: ["clearbit1", ["bit_number", MultiByteParam]], - 0x33: ["setbit1", ["bit_number", MultiByteParam]], - 0x34: ["checkbit2", ["bit_number", MultiByteParam]], - 0x35: ["clearbit2", ["bit_number", MultiByteParam]], - 0x36: ["setbit2", ["bit_number", MultiByteParam]], + 0x31: ["checkevent", ["bit_number", MultiByteParam]], + 0x32: ["clearevent", ["bit_number", MultiByteParam]], + 0x33: ["setevent", ["bit_number", MultiByteParam]], + 0x34: ["checkflag", ["bit_number", MultiByteParam]], + 0x35: ["clearflag", ["bit_number", MultiByteParam]], + 0x36: ["setflag", ["bit_number", MultiByteParam]], 0x37: ["wildon"], 0x38: ["wildoff"], 0x39: ["xycompare", ["pointer", MultiByteParam]], -- cgit v1.2.3 From 5f0bd7a2fefbb9354301a3926b011d055e650c56 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 01:57:29 -0400 Subject: use config instead of configuration this was kind of overzealous --- pokemontools/map_editor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 208cc49..9cd29ea 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -6,12 +6,12 @@ from ttk import Frame, Style import PIL from PIL import Image, ImageTk -import configuration -conf = configuration.Config() +import config +conf = config.Config() -version = 'crystal' -#version = 'red' +#version = 'crystal' +version = 'red' if version == 'crystal': map_dir = os.path.join(conf.path, 'maps/') -- cgit v1.2.3 From 9bea14db798eedcb262d17562a37b1f337fb67eb Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 01:04:51 -0500 Subject: tabs to spaces (pep8) --- pokemontools/map_editor.py | 1078 ++++++++++++++++++++++---------------------- 1 file changed, 539 insertions(+), 539 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 92e4a63..d30d3d2 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -14,609 +14,609 @@ version = 'crystal' #version = 'red' if version == 'crystal': - map_dir = os.path.join(conf.path, 'maps/') - gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') - to_gfx_name = lambda x : '%.2d' % x - block_dir = os.path.join(conf.path, 'tilesets/') - block_ext = '_metatiles.bin' + map_dir = os.path.join(conf.path, 'maps/') + gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') + to_gfx_name = lambda x : '%.2d' % x + block_dir = os.path.join(conf.path, 'tilesets/') + block_ext = '_metatiles.bin' - palettes_on = True - palmap_dir = os.path.join(conf.path, 'tilesets/') - palette_dir = os.path.join(conf.path, 'tilesets/') + palettes_on = True + palmap_dir = os.path.join(conf.path, 'tilesets/') + palette_dir = os.path.join(conf.path, 'tilesets/') - asm_dir = os.path.join(conf.path, 'maps/') + asm_dir = os.path.join(conf.path, 'maps/') - constants_dir = os.path.join(conf.path, 'constants/') - constants_filename = os.path.join(constants_dir, 'map_constants.asm') + constants_dir = os.path.join(conf.path, 'constants/') + constants_filename = os.path.join(constants_dir, 'map_constants.asm') - header_dir = os.path.join(conf.path, 'maps/') + header_dir = os.path.join(conf.path, 'maps/') - # todo - display_connections = False + # todo + display_connections = False elif version == 'red': - map_dir = os.path.join(conf.path, 'maps/') - gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') - to_gfx_name = lambda x : '%.2x' % x - block_dir = os.path.join(conf.path, 'gfx/blocksets/') - block_ext = '.bst' + map_dir = os.path.join(conf.path, 'maps/') + gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') + to_gfx_name = lambda x : '%.2x' % x + block_dir = os.path.join(conf.path, 'gfx/blocksets/') + block_ext = '.bst' - palettes_on = False + palettes_on = False - asm_path = os.path.join(conf.path, 'main.asm') + asm_path = os.path.join(conf.path, 'main.asm') - constants_filename = os.path.join(conf.path, 'constants.asm') + constants_filename = os.path.join(conf.path, 'constants.asm') - header_path = os.path.join(conf.path, 'main.asm') + header_path = os.path.join(conf.path, 'main.asm') - # todo - display_connections = False + # todo + display_connections = False else: - raise Exception, 'version must be "crystal" or "red"' + raise Exception, 'version must be "crystal" or "red"' def get_constants(): - lines = open(constants_filename, 'r').readlines() - for line in lines: - if ' EQU ' in line: - name, value = [s.strip() for s in line.split(' EQU ')] - globals()[name] = eval(value.split(';')[0].replace('$','0x').replace('%','0b')) + lines = open(constants_filename, 'r').readlines() + for line in lines: + if ' EQU ' in line: + name, value = [s.strip() for s in line.split(' EQU ')] + globals()[name] = eval(value.split(';')[0].replace('$','0x').replace('%','0b')) get_constants() class Application(Frame): - def __init__(self, master=None): - Frame.__init__(self, master) - self.grid() - Style().configure("TFrame", background="#444") - self.paint_tile = 1 - self.init_ui() - - def init_ui(self): - self.connections = {} - self.button_frame = Frame(self) - self.button_frame.grid(row=0, column=0, columnspan=2) - self.map_frame = Frame(self) - self.map_frame.grid(row=1, column=0, padx=5, pady=5) - self.picker_frame = Frame(self) - self.picker_frame.grid(row=1, column=1) - - self.new = Button(self.button_frame) - self.new["text"] = "New" - self.new["command"] = self.new_map - self.new.grid(row=0, column=0, padx=2) - - self.open = Button(self.button_frame) - self.open["text"] = "Open" - self.open["command"] = self.open_map - self.open.grid(row=0, column=1, padx=2) - - self.save = Button(self.button_frame) - self.save["text"] = "Save" - self.save["command"] = self.save_map - self.save.grid(row=0, column=2, padx=2) - - self.get_map_list() - self.map_list.grid(row=0, column=3, padx=2) - - - def get_map_list(self): - self.available_maps = sorted(m for m in get_available_maps()) - self.map_list = ttk.Combobox(self.button_frame, height=24, width=24, values=self.available_maps) - if len(self.available_maps): - self.map_list.set(self.available_maps[0]) - - def new_map(self): - self.map_name = None - self.init_map() - self.map.blockdata = [self.paint_tile] * 20 * 20 - self.map.width = 20 - self.map.height = 20 - self.draw_map() - self.init_picker() - - def open_map(self): - self.map_name = self.map_list.get() - self.init_map() - self.draw_map() - self.init_picker() - - def save_map(self): - if hasattr(self, 'map'): - if self.map.blockdata_filename: - with open(self.map.blockdata_filename, 'wb') as save: - save.write(self.map.blockdata) - print 'blockdata saved as %s' % self.map.blockdata_filename - else: - print 'dunno how to save this' - else: - print 'nothing to save' - - def init_map(self): - if hasattr(self, 'map'): - self.map.kill_canvas() - self.map = Map(self.map_frame, self.map_name) - self.init_map_connections() - - def draw_map(self): - self.map.init_canvas(self.map_frame) - self.map.canvas.pack() #.grid(row=1,column=1) - self.map.draw() - self.map.canvas.bind('', self.paint) - self.map.canvas.bind('', self.paint) - - def init_picker(self): - - self.current_tile = Map(self.button_frame, tileset_id=self.map.tileset_id) - self.current_tile.blockdata = [self.paint_tile] - self.current_tile.width = 1 - self.current_tile.height = 1 - self.current_tile.init_canvas() - self.current_tile.draw() - self.current_tile.canvas.grid(row=0, column=4, padx=4) - - if hasattr(self, 'picker'): - self.picker.kill_canvas() - self.picker = Map(self, tileset_id=self.map.tileset_id) - self.picker.blockdata = range(len(self.picker.tileset.blocks)) - self.picker.width = 4 - self.picker.height = len(self.picker.blockdata) / self.picker.width - self.picker.init_canvas(self.picker_frame) - - if hasattr(self.picker_frame, 'vbar'): - self.picker_frame.vbar.destroy() - self.picker_frame.vbar = Scrollbar(self.picker_frame, orient=VERTICAL) - self.picker_frame.vbar.pack(side=RIGHT, fill=Y) - self.picker_frame.vbar.config(command=self.picker.canvas.yview) - - - self.picker.canvas.config(scrollregion=(0,0,self.picker.canvas_width, self.picker.canvas_height)) - self.map_frame.update() - self.picker.canvas.config(height=self.map_frame.winfo_height()) - self.picker.canvas.config(yscrollcommand=self.picker_frame.vbar.set) - self.picker.canvas.pack(side=LEFT, expand=True) - - self.picker.canvas.bind('<4>', lambda event : self.scroll_picker(event)) - self.picker.canvas.bind('<5>', lambda event : self.scroll_picker(event)) - self.picker_frame.vbar.bind('<4>', lambda event : self.scroll_picker(event)) - self.picker_frame.vbar.bind('<5>', lambda event : self.scroll_picker(event)) - - self.picker.draw() - self.picker.canvas.bind('', self.pick_block) - - def scroll_picker(self, event): - if event.num == 4: - self.picker.canvas.yview('scroll', -1, 'units') - elif event.num == 5: - self.picker.canvas.yview('scroll', 1, 'units') - - - def pick_block(self, event): - block_x = int(self.picker.canvas.canvasx(event.x)) / (self.picker.tileset.block_width * self.picker.tileset.tile_width) - block_y = int(self.picker.canvas.canvasy(event.y)) / (self.picker.tileset.block_height * self.picker.tileset.tile_height) - i = block_y * self.picker.width + block_x - self.paint_tile = self.picker.blockdata[i] - - self.current_tile.blockdata = [self.paint_tile] - self.current_tile.draw() - - def paint(self, event): - block_x = event.x / (self.map.tileset.block_width * self.map.tileset.tile_width) - block_y = event.y / (self.map.tileset.block_height * self.map.tileset.tile_height) - i = block_y * self.map.width + block_x - if 0 <= i < len(self.map.blockdata): - self.map.blockdata[i] = self.paint_tile - self.map.draw_block(block_x, block_y) - - def init_map_connections(self): - if not display_connections: - return - for direction in self.map.connections.keys(): - if direction in self.connections.keys(): - if hasattr(self.connections[direction], 'canvas'): - self.connections[direction].kill_canvas() - if self.map.connections[direction] == {}: - self.connections[direction] = {} - continue - self.connections[direction] = Map(self, self.map.connections[direction]['map_name']) - - if direction in ['north', 'south']: - x1 = 0 - y1 = 0 - x2 = x1 + eval(self.map.connections[direction]['strip_length']) - y2 = y1 + 3 - else: # east, west - x1 = 0 - y1 = 0 - x2 = x1 + 3 - y2 = y1 + eval(self.map.connections[direction]['strip_length']) - - self.connections[direction].crop(x1, y1, x2, y2) - self.connections[direction].init_canvas(self.map_frame) - self.connections[direction].canvas.pack(side={'west':LEFT,'east':RIGHT}[direction]) - self.connections[direction].draw() + def __init__(self, master=None): + Frame.__init__(self, master) + self.grid() + Style().configure("TFrame", background="#444") + self.paint_tile = 1 + self.init_ui() + + def init_ui(self): + self.connections = {} + self.button_frame = Frame(self) + self.button_frame.grid(row=0, column=0, columnspan=2) + self.map_frame = Frame(self) + self.map_frame.grid(row=1, column=0, padx=5, pady=5) + self.picker_frame = Frame(self) + self.picker_frame.grid(row=1, column=1) + + self.new = Button(self.button_frame) + self.new["text"] = "New" + self.new["command"] = self.new_map + self.new.grid(row=0, column=0, padx=2) + + self.open = Button(self.button_frame) + self.open["text"] = "Open" + self.open["command"] = self.open_map + self.open.grid(row=0, column=1, padx=2) + + self.save = Button(self.button_frame) + self.save["text"] = "Save" + self.save["command"] = self.save_map + self.save.grid(row=0, column=2, padx=2) + + self.get_map_list() + self.map_list.grid(row=0, column=3, padx=2) + + + def get_map_list(self): + self.available_maps = sorted(m for m in get_available_maps()) + self.map_list = ttk.Combobox(self.button_frame, height=24, width=24, values=self.available_maps) + if len(self.available_maps): + self.map_list.set(self.available_maps[0]) + + def new_map(self): + self.map_name = None + self.init_map() + self.map.blockdata = [self.paint_tile] * 20 * 20 + self.map.width = 20 + self.map.height = 20 + self.draw_map() + self.init_picker() + + def open_map(self): + self.map_name = self.map_list.get() + self.init_map() + self.draw_map() + self.init_picker() + + def save_map(self): + if hasattr(self, 'map'): + if self.map.blockdata_filename: + with open(self.map.blockdata_filename, 'wb') as save: + save.write(self.map.blockdata) + print 'blockdata saved as %s' % self.map.blockdata_filename + else: + print 'dunno how to save this' + else: + print 'nothing to save' + + def init_map(self): + if hasattr(self, 'map'): + self.map.kill_canvas() + self.map = Map(self.map_frame, self.map_name) + self.init_map_connections() + + def draw_map(self): + self.map.init_canvas(self.map_frame) + self.map.canvas.pack() #.grid(row=1,column=1) + self.map.draw() + self.map.canvas.bind('', self.paint) + self.map.canvas.bind('', self.paint) + + def init_picker(self): + + self.current_tile = Map(self.button_frame, tileset_id=self.map.tileset_id) + self.current_tile.blockdata = [self.paint_tile] + self.current_tile.width = 1 + self.current_tile.height = 1 + self.current_tile.init_canvas() + self.current_tile.draw() + self.current_tile.canvas.grid(row=0, column=4, padx=4) + + if hasattr(self, 'picker'): + self.picker.kill_canvas() + self.picker = Map(self, tileset_id=self.map.tileset_id) + self.picker.blockdata = range(len(self.picker.tileset.blocks)) + self.picker.width = 4 + self.picker.height = len(self.picker.blockdata) / self.picker.width + self.picker.init_canvas(self.picker_frame) + + if hasattr(self.picker_frame, 'vbar'): + self.picker_frame.vbar.destroy() + self.picker_frame.vbar = Scrollbar(self.picker_frame, orient=VERTICAL) + self.picker_frame.vbar.pack(side=RIGHT, fill=Y) + self.picker_frame.vbar.config(command=self.picker.canvas.yview) + + + self.picker.canvas.config(scrollregion=(0,0,self.picker.canvas_width, self.picker.canvas_height)) + self.map_frame.update() + self.picker.canvas.config(height=self.map_frame.winfo_height()) + self.picker.canvas.config(yscrollcommand=self.picker_frame.vbar.set) + self.picker.canvas.pack(side=LEFT, expand=True) + + self.picker.canvas.bind('<4>', lambda event : self.scroll_picker(event)) + self.picker.canvas.bind('<5>', lambda event : self.scroll_picker(event)) + self.picker_frame.vbar.bind('<4>', lambda event : self.scroll_picker(event)) + self.picker_frame.vbar.bind('<5>', lambda event : self.scroll_picker(event)) + + self.picker.draw() + self.picker.canvas.bind('', self.pick_block) + + def scroll_picker(self, event): + if event.num == 4: + self.picker.canvas.yview('scroll', -1, 'units') + elif event.num == 5: + self.picker.canvas.yview('scroll', 1, 'units') + + + def pick_block(self, event): + block_x = int(self.picker.canvas.canvasx(event.x)) / (self.picker.tileset.block_width * self.picker.tileset.tile_width) + block_y = int(self.picker.canvas.canvasy(event.y)) / (self.picker.tileset.block_height * self.picker.tileset.tile_height) + i = block_y * self.picker.width + block_x + self.paint_tile = self.picker.blockdata[i] + + self.current_tile.blockdata = [self.paint_tile] + self.current_tile.draw() + + def paint(self, event): + block_x = event.x / (self.map.tileset.block_width * self.map.tileset.tile_width) + block_y = event.y / (self.map.tileset.block_height * self.map.tileset.tile_height) + i = block_y * self.map.width + block_x + if 0 <= i < len(self.map.blockdata): + self.map.blockdata[i] = self.paint_tile + self.map.draw_block(block_x, block_y) + + def init_map_connections(self): + if not display_connections: + return + for direction in self.map.connections.keys(): + if direction in self.connections.keys(): + if hasattr(self.connections[direction], 'canvas'): + self.connections[direction].kill_canvas() + if self.map.connections[direction] == {}: + self.connections[direction] = {} + continue + self.connections[direction] = Map(self, self.map.connections[direction]['map_name']) + + if direction in ['north', 'south']: + x1 = 0 + y1 = 0 + x2 = x1 + eval(self.map.connections[direction]['strip_length']) + y2 = y1 + 3 + else: # east, west + x1 = 0 + y1 = 0 + x2 = x1 + 3 + y2 = y1 + eval(self.map.connections[direction]['strip_length']) + + self.connections[direction].crop(x1, y1, x2, y2) + self.connections[direction].init_canvas(self.map_frame) + self.connections[direction].canvas.pack(side={'west':LEFT,'east':RIGHT}[direction]) + self.connections[direction].draw() class Map: - def __init__(self, parent, name=None, width=20, height=20, tileset_id=2, blockdata_filename=None): - self.parent = parent - - self.name = name - - self.blockdata_filename = blockdata_filename - if not self.blockdata_filename and self.name: - self.blockdata_filename = os.path.join(map_dir, self.name + '.blk') - elif not self.blockdata_filename: - self.blockdata_filename = '' - - asm_filename = '' - if self.name: - if 'asm_dir' in globals().keys(): - asm_filename = os.path.join(asm_dir, self.name + '.asm') - elif 'asm_path' in globals().keys(): - asm_filename = asm_path - - if os.path.exists(asm_filename): - for props in [map_header(self.name), second_map_header(self.name)]: - self.__dict__.update(props) - self.asm = open(asm_filename, 'r').read() - self.events = event_header(self.asm, self.name) - self.scripts = script_header(self.asm, self.name) - - self.tileset_id = eval(self.tileset_id) - - self.width = eval(self.width) - self.height = eval(self.height) - - else: - self.width = width - self.height = height - self.tileset_id = tileset_id - - if self.blockdata_filename: - self.blockdata = bytearray(open(self.blockdata_filename, 'rb').read()) - else: - self.blockdata = [] - - self.tileset = Tileset(self.tileset_id) - - def init_canvas(self, parent=None): - if parent == None: - parent = self.parent - if not hasattr(self, 'canvas'): - self.canvas_width = self.width * 32 - self.canvas_height = self.height * 32 - self.canvas = Canvas(parent, width=self.canvas_width, height=self.canvas_height) - self.canvas.xview_moveto(0) - self.canvas.yview_moveto(0) - - def kill_canvas(self): - if hasattr(self, 'canvas'): - self.canvas.destroy() - - def crop(self, x1, y1, x2, y2): - blockdata = self.blockdata - start = y1 * self.width + x1 - width = x2 - x1 - height = y2 - y1 - self.blockdata = [] - for y in xrange(height): - for x in xrange(width): - self.blockdata += [blockdata[start + y * self.width + x]] - self.blockdata = bytearray(self.blockdata) - self.width = width - self.height = height - - def draw(self): - for i in xrange(len(self.blockdata)): - block_x = i % self.width - block_y = i / self.width - self.draw_block(block_x, block_y) - - def draw_block(self, block_x, block_y): - # the canvas starts at 4, 4 for some reason - # probably something to do with a border - index, indey = 4, 4 - - # Draw one block (4x4 tiles) - block = self.blockdata[block_y * self.width + block_x] - for j, tile in enumerate(self.tileset.blocks[block]): - # Tile gfx are split in half to make vram mapping easier - if tile >= 0x80: - tile -= 0x20 - tile_x = block_x * 32 + (j % 4) * 8 - tile_y = block_y * 32 + (j / 4) * 8 - self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) + def __init__(self, parent, name=None, width=20, height=20, tileset_id=2, blockdata_filename=None): + self.parent = parent + + self.name = name + + self.blockdata_filename = blockdata_filename + if not self.blockdata_filename and self.name: + self.blockdata_filename = os.path.join(map_dir, self.name + '.blk') + elif not self.blockdata_filename: + self.blockdata_filename = '' + + asm_filename = '' + if self.name: + if 'asm_dir' in globals().keys(): + asm_filename = os.path.join(asm_dir, self.name + '.asm') + elif 'asm_path' in globals().keys(): + asm_filename = asm_path + + if os.path.exists(asm_filename): + for props in [map_header(self.name), second_map_header(self.name)]: + self.__dict__.update(props) + self.asm = open(asm_filename, 'r').read() + self.events = event_header(self.asm, self.name) + self.scripts = script_header(self.asm, self.name) + + self.tileset_id = eval(self.tileset_id) + + self.width = eval(self.width) + self.height = eval(self.height) + + else: + self.width = width + self.height = height + self.tileset_id = tileset_id + + if self.blockdata_filename: + self.blockdata = bytearray(open(self.blockdata_filename, 'rb').read()) + else: + self.blockdata = [] + + self.tileset = Tileset(self.tileset_id) + + def init_canvas(self, parent=None): + if parent == None: + parent = self.parent + if not hasattr(self, 'canvas'): + self.canvas_width = self.width * 32 + self.canvas_height = self.height * 32 + self.canvas = Canvas(parent, width=self.canvas_width, height=self.canvas_height) + self.canvas.xview_moveto(0) + self.canvas.yview_moveto(0) + + def kill_canvas(self): + if hasattr(self, 'canvas'): + self.canvas.destroy() + + def crop(self, x1, y1, x2, y2): + blockdata = self.blockdata + start = y1 * self.width + x1 + width = x2 - x1 + height = y2 - y1 + self.blockdata = [] + for y in xrange(height): + for x in xrange(width): + self.blockdata += [blockdata[start + y * self.width + x]] + self.blockdata = bytearray(self.blockdata) + self.width = width + self.height = height + + def draw(self): + for i in xrange(len(self.blockdata)): + block_x = i % self.width + block_y = i / self.width + self.draw_block(block_x, block_y) + + def draw_block(self, block_x, block_y): + # the canvas starts at 4, 4 for some reason + # probably something to do with a border + index, indey = 4, 4 + + # Draw one block (4x4 tiles) + block = self.blockdata[block_y * self.width + block_x] + for j, tile in enumerate(self.tileset.blocks[block]): + # Tile gfx are split in half to make vram mapping easier + if tile >= 0x80: + tile -= 0x20 + tile_x = block_x * 32 + (j % 4) * 8 + tile_y = block_y * 32 + (j / 4) * 8 + self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) class Tileset: - def __init__(self, tileset_id=0): - self.id = tileset_id - - self.tile_width = 8 - self.tile_height = 8 - self.block_width = 4 - self.block_height = 4 - - self.alpha = 255 - - if palettes_on: - self.get_palettes() - self.get_palette_map() - - self.get_blocks() - self.get_tiles() - - def get_tiles(self): - filename = os.path.join( - gfx_dir, - to_gfx_name(self.id) + '.png' - ) - self.img = Image.open(filename) - self.img.width, self.img.height = self.img.size - self.tiles = [] - cur_tile = 0 - for y in xrange(0, self.img.height, self.tile_height): - for x in xrange(0, self.img.width, self.tile_width): - tile = self.img.crop((x, y, x + self.tile_width, y + self.tile_height)) - - if hasattr(self, 'palette_map') and hasattr(self, 'palettes'): - # Palette maps are padded to make vram mapping easier. - pal = self.palette_map[cur_tile + 0x20 if cur_tile >= 0x60 else cur_tile] & 0x7 - tile = self.colorize_tile(tile, self.palettes[pal]) - - self.tiles += [ImageTk.PhotoImage(tile)] - cur_tile += 1 - - def colorize_tile(self, tile, palette): - width, height = tile.size - tile = tile.convert("RGB") - px = tile.load() - for y in xrange(height): - for x in xrange(width): - # assume greyscale - which_color = 3 - (px[x, y][0] / 0x55) - r, g, b = [v * 8 for v in palette[which_color]] - px[x, y] = (r, g, b) - return tile - - def get_blocks(self): - filename = os.path.join( - block_dir, - to_gfx_name(self.id) + block_ext - ) - self.blocks = [] - block_length = self.block_width * self.block_height - blocks = bytearray(open(filename, 'rb').read()) - for block in xrange(len(blocks) / (block_length)): - i = block * block_length - self.blocks += [blocks[i : i + block_length]] - - def get_palette_map(self): - filename = os.path.join( - palmap_dir, - str(self.id).zfill(2) + '_palette_map.bin' - ) - self.palette_map = [] - palmap = bytearray(open(filename, 'rb').read()) - for i in xrange(len(palmap)): - self.palette_map += [palmap[i] & 0xf] - self.palette_map += [(palmap[i] >> 4) & 0xf] - - def get_palettes(self): - filename = os.path.join( - palette_dir, - ['morn', 'day', 'nite'][time_of_day] + '.pal' - ) - self.palettes = get_palettes(filename) + def __init__(self, tileset_id=0): + self.id = tileset_id + + self.tile_width = 8 + self.tile_height = 8 + self.block_width = 4 + self.block_height = 4 + + self.alpha = 255 + + if palettes_on: + self.get_palettes() + self.get_palette_map() + + self.get_blocks() + self.get_tiles() + + def get_tiles(self): + filename = os.path.join( + gfx_dir, + to_gfx_name(self.id) + '.png' + ) + self.img = Image.open(filename) + self.img.width, self.img.height = self.img.size + self.tiles = [] + cur_tile = 0 + for y in xrange(0, self.img.height, self.tile_height): + for x in xrange(0, self.img.width, self.tile_width): + tile = self.img.crop((x, y, x + self.tile_width, y + self.tile_height)) + + if hasattr(self, 'palette_map') and hasattr(self, 'palettes'): + # Palette maps are padded to make vram mapping easier. + pal = self.palette_map[cur_tile + 0x20 if cur_tile >= 0x60 else cur_tile] & 0x7 + tile = self.colorize_tile(tile, self.palettes[pal]) + + self.tiles += [ImageTk.PhotoImage(tile)] + cur_tile += 1 + + def colorize_tile(self, tile, palette): + width, height = tile.size + tile = tile.convert("RGB") + px = tile.load() + for y in xrange(height): + for x in xrange(width): + # assume greyscale + which_color = 3 - (px[x, y][0] / 0x55) + r, g, b = [v * 8 for v in palette[which_color]] + px[x, y] = (r, g, b) + return tile + + def get_blocks(self): + filename = os.path.join( + block_dir, + to_gfx_name(self.id) + block_ext + ) + self.blocks = [] + block_length = self.block_width * self.block_height + blocks = bytearray(open(filename, 'rb').read()) + for block in xrange(len(blocks) / (block_length)): + i = block * block_length + self.blocks += [blocks[i : i + block_length]] + + def get_palette_map(self): + filename = os.path.join( + palmap_dir, + str(self.id).zfill(2) + '_palette_map.bin' + ) + self.palette_map = [] + palmap = bytearray(open(filename, 'rb').read()) + for i in xrange(len(palmap)): + self.palette_map += [palmap[i] & 0xf] + self.palette_map += [(palmap[i] >> 4) & 0xf] + + def get_palettes(self): + filename = os.path.join( + palette_dir, + ['morn', 'day', 'nite'][time_of_day] + '.pal' + ) + self.palettes = get_palettes(filename) time_of_day = 1 def get_palettes(filename): - pals = bytearray(open(filename, 'rb').read()) + pals = bytearray(open(filename, 'rb').read()) - num_colors = 4 - color_length = 2 + num_colors = 4 + color_length = 2 - palette_length = num_colors * color_length + palette_length = num_colors * color_length - num_pals = len(pals) / palette_length + num_pals = len(pals) / palette_length - palettes = [] - for pal in xrange(num_pals): - palettes += [[]] + palettes = [] + for pal in xrange(num_pals): + palettes += [[]] - for color in xrange(num_colors): - i = pal * palette_length - i += color * color_length - word = pals[i] + pals[i+1] * 0x100 - palettes[pal] += [[ - c & 0x1f for c in [ - word >> 0, - word >> 5, - word >> 10, - ] - ]] - return palettes + for color in xrange(num_colors): + i = pal * palette_length + i += color * color_length + word = pals[i] + pals[i+1] * 0x100 + palettes[pal] += [[ + c & 0x1f for c in [ + word >> 0, + word >> 5, + word >> 10, + ] + ]] + return palettes def get_available_maps(): - for root, dirs, files in os.walk(map_dir): - for filename in files: - base_name, ext = os.path.splitext(filename) - if ext == '.blk': - yield base_name + for root, dirs, files in os.walk(map_dir): + for filename in files: + base_name, ext = os.path.splitext(filename) + if ext == '.blk': + yield base_name def map_header(name): - if version == 'crystal': - headers = open(os.path.join(header_dir, 'map_headers.asm'), 'r').read() - label = name + '_MapHeader' - header = asm_at_label(headers, label) - macros = [ 'db', 'dw', 'db' ] - attributes = [ - 'bank', - 'tileset_id', - 'permission', - 'second_map_header', - 'world_map_location', - 'music', - 'time_of_day', - 'fishing_group', - ] - values, l = read_header_macros(header, attributes, macros) - attrs = dict(zip(attributes, values)) - return attrs - - elif version == 'red': - headers = open(header_path, 'r').read() - - # there has to be a better way to do this - lower_label = name + '_h' - i = headers.lower().find(lower_label) - if i == -1: - return {} - label = headers[i:i+len(lower_label)] - - header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dw', 'db' ] - attributes = [ - 'tileset_id', - 'height', - 'width', - 'blockdata_label', - 'text_label', - 'script_label', - 'which_connections', - ] - values, l = read_header_macros(header, attributes, macros) - - attrs = dict(zip(attributes, values)) - attrs['connections'], l = connections(attrs['which_connections'], header, l) - - macros = [ 'dw' ] - attributes = [ - 'object_label', - ] - values, l = read_header_macros(header[l:], attributes, macros) - attrs.update(dict(zip(attributes, values))) - - return attrs - - return {} + if version == 'crystal': + headers = open(os.path.join(header_dir, 'map_headers.asm'), 'r').read() + label = name + '_MapHeader' + header = asm_at_label(headers, label) + macros = [ 'db', 'dw', 'db' ] + attributes = [ + 'bank', + 'tileset_id', + 'permission', + 'second_map_header', + 'world_map_location', + 'music', + 'time_of_day', + 'fishing_group', + ] + values, l = read_header_macros(header, attributes, macros) + attrs = dict(zip(attributes, values)) + return attrs + + elif version == 'red': + headers = open(header_path, 'r').read() + + # there has to be a better way to do this + lower_label = name + '_h' + i = headers.lower().find(lower_label) + if i == -1: + return {} + label = headers[i:i+len(lower_label)] + + header = asm_at_label(headers, label) + macros = [ 'db', 'db', 'dw', 'db' ] + attributes = [ + 'tileset_id', + 'height', + 'width', + 'blockdata_label', + 'text_label', + 'script_label', + 'which_connections', + ] + values, l = read_header_macros(header, attributes, macros) + + attrs = dict(zip(attributes, values)) + attrs['connections'], l = connections(attrs['which_connections'], header, l) + + macros = [ 'dw' ] + attributes = [ + 'object_label', + ] + values, l = read_header_macros(header[l:], attributes, macros) + attrs.update(dict(zip(attributes, values))) + + return attrs + + return {} def second_map_header(name): - if version == 'crystal': - headers = open(os.path.join(header_dir, 'second_map_headers.asm'), 'r').read() - label = name + '_SecondMapHeader' - header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dbw', 'dbw', 'dw', 'db' ] - attributes = [ - 'border_block', - 'height', - 'width', - 'blockdata_bank', - 'blockdata_label', - 'script_header_bank', - 'script_header_label', - 'map_event_header_label', - 'which_connections', - ] - - values, l = read_header_macros(header, attributes, macros) - attrs = dict(zip(attributes, values)) - attrs['connections'], l = connections(attrs['which_connections'], header, l) - return attrs - - return {} + if version == 'crystal': + headers = open(os.path.join(header_dir, 'second_map_headers.asm'), 'r').read() + label = name + '_SecondMapHeader' + header = asm_at_label(headers, label) + macros = [ 'db', 'db', 'dbw', 'dbw', 'dw', 'db' ] + attributes = [ + 'border_block', + 'height', + 'width', + 'blockdata_bank', + 'blockdata_label', + 'script_header_bank', + 'script_header_label', + 'map_event_header_label', + 'which_connections', + ] + + values, l = read_header_macros(header, attributes, macros) + attrs = dict(zip(attributes, values)) + attrs['connections'], l = connections(attrs['which_connections'], header, l) + return attrs + + return {} def connections(which_connections, header, l=0): - directions = { 'north': {}, 'south': {}, 'west': {}, 'east': {} } - macros = [ 'db', 'dw', 'dw', 'db', 'db', 'dw' ] - - if version == 'crystal': - attributes = [ - 'map_group', - 'map_no', - ] - - elif version == 'red': - attributes = [ - 'map_id', - ] - - attributes += [ - 'strip_pointer', - 'strip_destination', - 'strip_length', - 'map_width', - 'y_offset', - 'x_offset', - 'window', - ] - for d in directions.keys(): - if d.upper() in which_connections: - values, l = read_header_macros(header, attributes, macros) - header = header[l:] - directions[d] = dict(zip(attributes, values)) - if version == 'crystal': - directions[d]['map_name'] = directions[d]['map_group'].replace('GROUP_', '').title().replace('_','') - elif version == 'red': - directions[d]['map_name'] = directions[d]['map_id'].title().replace('_','') - return directions, l + directions = { 'north': {}, 'south': {}, 'west': {}, 'east': {} } + macros = [ 'db', 'dw', 'dw', 'db', 'db', 'dw' ] + + if version == 'crystal': + attributes = [ + 'map_group', + 'map_no', + ] + + elif version == 'red': + attributes = [ + 'map_id', + ] + + attributes += [ + 'strip_pointer', + 'strip_destination', + 'strip_length', + 'map_width', + 'y_offset', + 'x_offset', + 'window', + ] + for d in directions.keys(): + if d.upper() in which_connections: + values, l = read_header_macros(header, attributes, macros) + header = header[l:] + directions[d] = dict(zip(attributes, values)) + if version == 'crystal': + directions[d]['map_name'] = directions[d]['map_group'].replace('GROUP_', '').title().replace('_','') + elif version == 'red': + directions[d]['map_name'] = directions[d]['map_id'].title().replace('_','') + return directions, l def read_header_macros(header, attributes, macros): - values = [] - i = 0 - l = 0 - for l, (asm, comment) in enumerate(header): - if asm.strip() != '': - values += macro_values(asm, macros[i]) - i += 1 - if len(values) >= len(attributes): - l += 1 - break - return values, l + values = [] + i = 0 + l = 0 + for l, (asm, comment) in enumerate(header): + if asm.strip() != '': + values += macro_values(asm, macros[i]) + i += 1 + if len(values) >= len(attributes): + l += 1 + break + return values, l def event_header(asm, name): - return {} + return {} def script_header(asm, name): - return {} + return {} def macro_values(line, macro): - values = line[line.find(macro) + len(macro):].split(',') - return [v.replace('$','0x').strip() for v in values] + values = line[line.find(macro) + len(macro):].split(',') + return [v.replace('$','0x').strip() for v in values] def db_value(line): - macro = 'db' - return macro_values(line, macro) + macro = 'db' + return macro_values(line, macro) def db_values(line): - macro = 'db' - return macro_values(line, macro) + macro = 'db' + return macro_values(line, macro) from preprocessor import separate_comment def asm_at_label(asm, label): - label_def = label + ':' - start = asm.find(label_def) + len(label_def) - lines = asm[start:].split('\n') - # go until the next label - content = [] - for line in lines: - l, comment = separate_comment(line + '\n') - if ':' in l: - break - content += [[l, comment]] - return content + label_def = label + ':' + start = asm.find(label_def) + len(label_def) + lines = asm[start:].split('\n') + # go until the next label + content = [] + for line in lines: + l, comment = separate_comment(line + '\n') + if ':' in l: + break + content += [[l, comment]] + return content root = Tk() @@ -624,12 +624,12 @@ root.wm_title("MAP EDITOR") app = Application(master=root) try: - app.mainloop() + app.mainloop() except KeyboardInterrupt: - pass + pass try: - root.destroy() + root.destroy() except TclError: - pass + pass -- cgit v1.2.3 From e4b2d2e4d24d09b719712bf3793a655307fa60d8 Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 01:05:23 -0500 Subject: minor formatting fix --- pokemontools/map_editor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index d30d3d2..c6f9f16 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -147,7 +147,6 @@ class Application(Frame): self.map.canvas.bind('', self.paint) def init_picker(self): - self.current_tile = Map(self.button_frame, tileset_id=self.map.tileset_id) self.current_tile.blockdata = [self.paint_tile] self.current_tile.width = 1 -- cgit v1.2.3 From 3f28232f0d7ad1a3c6a72c603c5f8318a57fba64 Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 01:06:19 -0500 Subject: put the tk loop into __main__ --- pokemontools/map_editor.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index c6f9f16..11bfb4b 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -617,18 +617,23 @@ def asm_at_label(asm, label): content += [[l, comment]] return content - -root = Tk() -root.wm_title("MAP EDITOR") -app = Application(master=root) - -try: - app.mainloop() -except KeyboardInterrupt: - pass - -try: - root.destroy() -except TclError: - pass - +def main(): + """ + Launches the map editor. + """ + root = Tk() + root.wm_title("MAP EDITOR") + app = Application(master=root) + + try: + app.mainloop() + except KeyboardInterrupt: + pass + + try: + root.destroy() + except TclError: + pass + +if __name__ == "__main__": + main() -- cgit v1.2.3 From 9d1a68cce57a9e4ac4111853c1597a646866a6af Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 01:09:50 -0500 Subject: refactor a global constant to be set in __init__ --- pokemontools/map_editor.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 11bfb4b..13c3b49 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -31,9 +31,6 @@ if version == 'crystal': header_dir = os.path.join(conf.path, 'maps/') - # todo - display_connections = False - elif version == 'red': map_dir = os.path.join(conf.path, 'maps/') gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') @@ -49,9 +46,6 @@ elif version == 'red': header_path = os.path.join(conf.path, 'main.asm') - # todo - display_connections = False - else: raise Exception, 'version must be "crystal" or "red"' @@ -67,6 +61,8 @@ get_constants() class Application(Frame): def __init__(self, master=None): + self.display_connections = False + Frame.__init__(self, master) self.grid() Style().configure("TFrame", background="#444") @@ -209,7 +205,7 @@ class Application(Frame): self.map.draw_block(block_x, block_y) def init_map_connections(self): - if not display_connections: + if not self.display_connections: return for direction in self.map.connections.keys(): if direction in self.connections.keys(): -- cgit v1.2.3 From cff5ce9bc81c78d8f841570480f1716fb91c1fac Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 01:24:13 -0500 Subject: Revert "tabs to spaces (pep8)" This reverts commit 9bea14db798eedcb262d17562a37b1f337fb67eb. Conflicts: pokemontools/map_editor.py --- pokemontools/map_editor.py | 1064 ++++++++++++++++++++++---------------------- 1 file changed, 532 insertions(+), 532 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 13c3b49..d4b5047 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -14,604 +14,604 @@ version = 'crystal' #version = 'red' if version == 'crystal': - map_dir = os.path.join(conf.path, 'maps/') - gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') - to_gfx_name = lambda x : '%.2d' % x - block_dir = os.path.join(conf.path, 'tilesets/') - block_ext = '_metatiles.bin' + map_dir = os.path.join(conf.path, 'maps/') + gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') + to_gfx_name = lambda x : '%.2d' % x + block_dir = os.path.join(conf.path, 'tilesets/') + block_ext = '_metatiles.bin' - palettes_on = True - palmap_dir = os.path.join(conf.path, 'tilesets/') - palette_dir = os.path.join(conf.path, 'tilesets/') + palettes_on = True + palmap_dir = os.path.join(conf.path, 'tilesets/') + palette_dir = os.path.join(conf.path, 'tilesets/') - asm_dir = os.path.join(conf.path, 'maps/') + asm_dir = os.path.join(conf.path, 'maps/') - constants_dir = os.path.join(conf.path, 'constants/') - constants_filename = os.path.join(constants_dir, 'map_constants.asm') + constants_dir = os.path.join(conf.path, 'constants/') + constants_filename = os.path.join(constants_dir, 'map_constants.asm') - header_dir = os.path.join(conf.path, 'maps/') + header_dir = os.path.join(conf.path, 'maps/') elif version == 'red': - map_dir = os.path.join(conf.path, 'maps/') - gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') - to_gfx_name = lambda x : '%.2x' % x - block_dir = os.path.join(conf.path, 'gfx/blocksets/') - block_ext = '.bst' + map_dir = os.path.join(conf.path, 'maps/') + gfx_dir = os.path.join(conf.path, 'gfx/tilesets/') + to_gfx_name = lambda x : '%.2x' % x + block_dir = os.path.join(conf.path, 'gfx/blocksets/') + block_ext = '.bst' - palettes_on = False + palettes_on = False - asm_path = os.path.join(conf.path, 'main.asm') + asm_path = os.path.join(conf.path, 'main.asm') - constants_filename = os.path.join(conf.path, 'constants.asm') + constants_filename = os.path.join(conf.path, 'constants.asm') - header_path = os.path.join(conf.path, 'main.asm') + header_path = os.path.join(conf.path, 'main.asm') else: - raise Exception, 'version must be "crystal" or "red"' + raise Exception, 'version must be "crystal" or "red"' def get_constants(): - lines = open(constants_filename, 'r').readlines() - for line in lines: - if ' EQU ' in line: - name, value = [s.strip() for s in line.split(' EQU ')] - globals()[name] = eval(value.split(';')[0].replace('$','0x').replace('%','0b')) + lines = open(constants_filename, 'r').readlines() + for line in lines: + if ' EQU ' in line: + name, value = [s.strip() for s in line.split(' EQU ')] + globals()[name] = eval(value.split(';')[0].replace('$','0x').replace('%','0b')) get_constants() class Application(Frame): - def __init__(self, master=None): - self.display_connections = False - - Frame.__init__(self, master) - self.grid() - Style().configure("TFrame", background="#444") - self.paint_tile = 1 - self.init_ui() - - def init_ui(self): - self.connections = {} - self.button_frame = Frame(self) - self.button_frame.grid(row=0, column=0, columnspan=2) - self.map_frame = Frame(self) - self.map_frame.grid(row=1, column=0, padx=5, pady=5) - self.picker_frame = Frame(self) - self.picker_frame.grid(row=1, column=1) - - self.new = Button(self.button_frame) - self.new["text"] = "New" - self.new["command"] = self.new_map - self.new.grid(row=0, column=0, padx=2) - - self.open = Button(self.button_frame) - self.open["text"] = "Open" - self.open["command"] = self.open_map - self.open.grid(row=0, column=1, padx=2) - - self.save = Button(self.button_frame) - self.save["text"] = "Save" - self.save["command"] = self.save_map - self.save.grid(row=0, column=2, padx=2) - - self.get_map_list() - self.map_list.grid(row=0, column=3, padx=2) - - - def get_map_list(self): - self.available_maps = sorted(m for m in get_available_maps()) - self.map_list = ttk.Combobox(self.button_frame, height=24, width=24, values=self.available_maps) - if len(self.available_maps): - self.map_list.set(self.available_maps[0]) - - def new_map(self): - self.map_name = None - self.init_map() - self.map.blockdata = [self.paint_tile] * 20 * 20 - self.map.width = 20 - self.map.height = 20 - self.draw_map() - self.init_picker() - - def open_map(self): - self.map_name = self.map_list.get() - self.init_map() - self.draw_map() - self.init_picker() - - def save_map(self): - if hasattr(self, 'map'): - if self.map.blockdata_filename: - with open(self.map.blockdata_filename, 'wb') as save: - save.write(self.map.blockdata) - print 'blockdata saved as %s' % self.map.blockdata_filename - else: - print 'dunno how to save this' - else: - print 'nothing to save' - - def init_map(self): - if hasattr(self, 'map'): - self.map.kill_canvas() - self.map = Map(self.map_frame, self.map_name) - self.init_map_connections() - - def draw_map(self): - self.map.init_canvas(self.map_frame) - self.map.canvas.pack() #.grid(row=1,column=1) - self.map.draw() - self.map.canvas.bind('', self.paint) - self.map.canvas.bind('', self.paint) - - def init_picker(self): - self.current_tile = Map(self.button_frame, tileset_id=self.map.tileset_id) - self.current_tile.blockdata = [self.paint_tile] - self.current_tile.width = 1 - self.current_tile.height = 1 - self.current_tile.init_canvas() - self.current_tile.draw() - self.current_tile.canvas.grid(row=0, column=4, padx=4) - - if hasattr(self, 'picker'): - self.picker.kill_canvas() - self.picker = Map(self, tileset_id=self.map.tileset_id) - self.picker.blockdata = range(len(self.picker.tileset.blocks)) - self.picker.width = 4 - self.picker.height = len(self.picker.blockdata) / self.picker.width - self.picker.init_canvas(self.picker_frame) - - if hasattr(self.picker_frame, 'vbar'): - self.picker_frame.vbar.destroy() - self.picker_frame.vbar = Scrollbar(self.picker_frame, orient=VERTICAL) - self.picker_frame.vbar.pack(side=RIGHT, fill=Y) - self.picker_frame.vbar.config(command=self.picker.canvas.yview) - - - self.picker.canvas.config(scrollregion=(0,0,self.picker.canvas_width, self.picker.canvas_height)) - self.map_frame.update() - self.picker.canvas.config(height=self.map_frame.winfo_height()) - self.picker.canvas.config(yscrollcommand=self.picker_frame.vbar.set) - self.picker.canvas.pack(side=LEFT, expand=True) - - self.picker.canvas.bind('<4>', lambda event : self.scroll_picker(event)) - self.picker.canvas.bind('<5>', lambda event : self.scroll_picker(event)) - self.picker_frame.vbar.bind('<4>', lambda event : self.scroll_picker(event)) - self.picker_frame.vbar.bind('<5>', lambda event : self.scroll_picker(event)) - - self.picker.draw() - self.picker.canvas.bind('', self.pick_block) - - def scroll_picker(self, event): - if event.num == 4: - self.picker.canvas.yview('scroll', -1, 'units') - elif event.num == 5: - self.picker.canvas.yview('scroll', 1, 'units') - - - def pick_block(self, event): - block_x = int(self.picker.canvas.canvasx(event.x)) / (self.picker.tileset.block_width * self.picker.tileset.tile_width) - block_y = int(self.picker.canvas.canvasy(event.y)) / (self.picker.tileset.block_height * self.picker.tileset.tile_height) - i = block_y * self.picker.width + block_x - self.paint_tile = self.picker.blockdata[i] - - self.current_tile.blockdata = [self.paint_tile] - self.current_tile.draw() - - def paint(self, event): - block_x = event.x / (self.map.tileset.block_width * self.map.tileset.tile_width) - block_y = event.y / (self.map.tileset.block_height * self.map.tileset.tile_height) - i = block_y * self.map.width + block_x - if 0 <= i < len(self.map.blockdata): - self.map.blockdata[i] = self.paint_tile - self.map.draw_block(block_x, block_y) - - def init_map_connections(self): - if not self.display_connections: - return - for direction in self.map.connections.keys(): - if direction in self.connections.keys(): - if hasattr(self.connections[direction], 'canvas'): - self.connections[direction].kill_canvas() - if self.map.connections[direction] == {}: - self.connections[direction] = {} - continue - self.connections[direction] = Map(self, self.map.connections[direction]['map_name']) - - if direction in ['north', 'south']: - x1 = 0 - y1 = 0 - x2 = x1 + eval(self.map.connections[direction]['strip_length']) - y2 = y1 + 3 - else: # east, west - x1 = 0 - y1 = 0 - x2 = x1 + 3 - y2 = y1 + eval(self.map.connections[direction]['strip_length']) - - self.connections[direction].crop(x1, y1, x2, y2) - self.connections[direction].init_canvas(self.map_frame) - self.connections[direction].canvas.pack(side={'west':LEFT,'east':RIGHT}[direction]) - self.connections[direction].draw() + def __init__(self, master=None): + self.display_connections = False + Frame.__init__(self, master) + self.grid() + Style().configure("TFrame", background="#444") + self.paint_tile = 1 + self.init_ui() + + def init_ui(self): + self.connections = {} + self.button_frame = Frame(self) + self.button_frame.grid(row=0, column=0, columnspan=2) + self.map_frame = Frame(self) + self.map_frame.grid(row=1, column=0, padx=5, pady=5) + self.picker_frame = Frame(self) + self.picker_frame.grid(row=1, column=1) + + self.new = Button(self.button_frame) + self.new["text"] = "New" + self.new["command"] = self.new_map + self.new.grid(row=0, column=0, padx=2) + + self.open = Button(self.button_frame) + self.open["text"] = "Open" + self.open["command"] = self.open_map + self.open.grid(row=0, column=1, padx=2) + + self.save = Button(self.button_frame) + self.save["text"] = "Save" + self.save["command"] = self.save_map + self.save.grid(row=0, column=2, padx=2) + + self.get_map_list() + self.map_list.grid(row=0, column=3, padx=2) + + + def get_map_list(self): + self.available_maps = sorted(m for m in get_available_maps()) + self.map_list = ttk.Combobox(self.button_frame, height=24, width=24, values=self.available_maps) + if len(self.available_maps): + self.map_list.set(self.available_maps[0]) + + def new_map(self): + self.map_name = None + self.init_map() + self.map.blockdata = [self.paint_tile] * 20 * 20 + self.map.width = 20 + self.map.height = 20 + self.draw_map() + self.init_picker() + + def open_map(self): + self.map_name = self.map_list.get() + self.init_map() + self.draw_map() + self.init_picker() + + def save_map(self): + if hasattr(self, 'map'): + if self.map.blockdata_filename: + with open(self.map.blockdata_filename, 'wb') as save: + save.write(self.map.blockdata) + print 'blockdata saved as %s' % self.map.blockdata_filename + else: + print 'dunno how to save this' + else: + print 'nothing to save' + + def init_map(self): + if hasattr(self, 'map'): + self.map.kill_canvas() + self.map = Map(self.map_frame, self.map_name) + self.init_map_connections() + + def draw_map(self): + self.map.init_canvas(self.map_frame) + self.map.canvas.pack() #.grid(row=1,column=1) + self.map.draw() + self.map.canvas.bind('', self.paint) + self.map.canvas.bind('', self.paint) + + def init_picker(self): + + self.current_tile = Map(self.button_frame, tileset_id=self.map.tileset_id) + self.current_tile.blockdata = [self.paint_tile] + self.current_tile.width = 1 + self.current_tile.height = 1 + self.current_tile.init_canvas() + self.current_tile.draw() + self.current_tile.canvas.grid(row=0, column=4, padx=4) + + if hasattr(self, 'picker'): + self.picker.kill_canvas() + self.picker = Map(self, tileset_id=self.map.tileset_id) + self.picker.blockdata = range(len(self.picker.tileset.blocks)) + self.picker.width = 4 + self.picker.height = len(self.picker.blockdata) / self.picker.width + self.picker.init_canvas(self.picker_frame) + + if hasattr(self.picker_frame, 'vbar'): + self.picker_frame.vbar.destroy() + self.picker_frame.vbar = Scrollbar(self.picker_frame, orient=VERTICAL) + self.picker_frame.vbar.pack(side=RIGHT, fill=Y) + self.picker_frame.vbar.config(command=self.picker.canvas.yview) + + + self.picker.canvas.config(scrollregion=(0,0,self.picker.canvas_width, self.picker.canvas_height)) + self.map_frame.update() + self.picker.canvas.config(height=self.map_frame.winfo_height()) + self.picker.canvas.config(yscrollcommand=self.picker_frame.vbar.set) + self.picker.canvas.pack(side=LEFT, expand=True) + + self.picker.canvas.bind('<4>', lambda event : self.scroll_picker(event)) + self.picker.canvas.bind('<5>', lambda event : self.scroll_picker(event)) + self.picker_frame.vbar.bind('<4>', lambda event : self.scroll_picker(event)) + self.picker_frame.vbar.bind('<5>', lambda event : self.scroll_picker(event)) + + self.picker.draw() + self.picker.canvas.bind('', self.pick_block) + + def scroll_picker(self, event): + if event.num == 4: + self.picker.canvas.yview('scroll', -1, 'units') + elif event.num == 5: + self.picker.canvas.yview('scroll', 1, 'units') + + + def pick_block(self, event): + block_x = int(self.picker.canvas.canvasx(event.x)) / (self.picker.tileset.block_width * self.picker.tileset.tile_width) + block_y = int(self.picker.canvas.canvasy(event.y)) / (self.picker.tileset.block_height * self.picker.tileset.tile_height) + i = block_y * self.picker.width + block_x + self.paint_tile = self.picker.blockdata[i] + + self.current_tile.blockdata = [self.paint_tile] + self.current_tile.draw() + + def paint(self, event): + block_x = event.x / (self.map.tileset.block_width * self.map.tileset.tile_width) + block_y = event.y / (self.map.tileset.block_height * self.map.tileset.tile_height) + i = block_y * self.map.width + block_x + if 0 <= i < len(self.map.blockdata): + self.map.blockdata[i] = self.paint_tile + self.map.draw_block(block_x, block_y) + + def init_map_connections(self): + if not display_connections: + return + for direction in self.map.connections.keys(): + if direction in self.connections.keys(): + if hasattr(self.connections[direction], 'canvas'): + self.connections[direction].kill_canvas() + if self.map.connections[direction] == {}: + self.connections[direction] = {} + continue + self.connections[direction] = Map(self, self.map.connections[direction]['map_name']) + + if direction in ['north', 'south']: + x1 = 0 + y1 = 0 + x2 = x1 + eval(self.map.connections[direction]['strip_length']) + y2 = y1 + 3 + else: # east, west + x1 = 0 + y1 = 0 + x2 = x1 + 3 + y2 = y1 + eval(self.map.connections[direction]['strip_length']) + + self.connections[direction].crop(x1, y1, x2, y2) + self.connections[direction].init_canvas(self.map_frame) + self.connections[direction].canvas.pack(side={'west':LEFT,'east':RIGHT}[direction]) + self.connections[direction].draw() class Map: - def __init__(self, parent, name=None, width=20, height=20, tileset_id=2, blockdata_filename=None): - self.parent = parent - - self.name = name - - self.blockdata_filename = blockdata_filename - if not self.blockdata_filename and self.name: - self.blockdata_filename = os.path.join(map_dir, self.name + '.blk') - elif not self.blockdata_filename: - self.blockdata_filename = '' - - asm_filename = '' - if self.name: - if 'asm_dir' in globals().keys(): - asm_filename = os.path.join(asm_dir, self.name + '.asm') - elif 'asm_path' in globals().keys(): - asm_filename = asm_path - - if os.path.exists(asm_filename): - for props in [map_header(self.name), second_map_header(self.name)]: - self.__dict__.update(props) - self.asm = open(asm_filename, 'r').read() - self.events = event_header(self.asm, self.name) - self.scripts = script_header(self.asm, self.name) - - self.tileset_id = eval(self.tileset_id) - - self.width = eval(self.width) - self.height = eval(self.height) - - else: - self.width = width - self.height = height - self.tileset_id = tileset_id - - if self.blockdata_filename: - self.blockdata = bytearray(open(self.blockdata_filename, 'rb').read()) - else: - self.blockdata = [] - - self.tileset = Tileset(self.tileset_id) - - def init_canvas(self, parent=None): - if parent == None: - parent = self.parent - if not hasattr(self, 'canvas'): - self.canvas_width = self.width * 32 - self.canvas_height = self.height * 32 - self.canvas = Canvas(parent, width=self.canvas_width, height=self.canvas_height) - self.canvas.xview_moveto(0) - self.canvas.yview_moveto(0) - - def kill_canvas(self): - if hasattr(self, 'canvas'): - self.canvas.destroy() - - def crop(self, x1, y1, x2, y2): - blockdata = self.blockdata - start = y1 * self.width + x1 - width = x2 - x1 - height = y2 - y1 - self.blockdata = [] - for y in xrange(height): - for x in xrange(width): - self.blockdata += [blockdata[start + y * self.width + x]] - self.blockdata = bytearray(self.blockdata) - self.width = width - self.height = height - - def draw(self): - for i in xrange(len(self.blockdata)): - block_x = i % self.width - block_y = i / self.width - self.draw_block(block_x, block_y) - - def draw_block(self, block_x, block_y): - # the canvas starts at 4, 4 for some reason - # probably something to do with a border - index, indey = 4, 4 - - # Draw one block (4x4 tiles) - block = self.blockdata[block_y * self.width + block_x] - for j, tile in enumerate(self.tileset.blocks[block]): - # Tile gfx are split in half to make vram mapping easier - if tile >= 0x80: - tile -= 0x20 - tile_x = block_x * 32 + (j % 4) * 8 - tile_y = block_y * 32 + (j / 4) * 8 - self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) + def __init__(self, parent, name=None, width=20, height=20, tileset_id=2, blockdata_filename=None): + self.parent = parent + + self.name = name + + self.blockdata_filename = blockdata_filename + if not self.blockdata_filename and self.name: + self.blockdata_filename = os.path.join(map_dir, self.name + '.blk') + elif not self.blockdata_filename: + self.blockdata_filename = '' + + asm_filename = '' + if self.name: + if 'asm_dir' in globals().keys(): + asm_filename = os.path.join(asm_dir, self.name + '.asm') + elif 'asm_path' in globals().keys(): + asm_filename = asm_path + + if os.path.exists(asm_filename): + for props in [map_header(self.name), second_map_header(self.name)]: + self.__dict__.update(props) + self.asm = open(asm_filename, 'r').read() + self.events = event_header(self.asm, self.name) + self.scripts = script_header(self.asm, self.name) + + self.tileset_id = eval(self.tileset_id) + + self.width = eval(self.width) + self.height = eval(self.height) + + else: + self.width = width + self.height = height + self.tileset_id = tileset_id + + if self.blockdata_filename: + self.blockdata = bytearray(open(self.blockdata_filename, 'rb').read()) + else: + self.blockdata = [] + + self.tileset = Tileset(self.tileset_id) + + def init_canvas(self, parent=None): + if parent == None: + parent = self.parent + if not hasattr(self, 'canvas'): + self.canvas_width = self.width * 32 + self.canvas_height = self.height * 32 + self.canvas = Canvas(parent, width=self.canvas_width, height=self.canvas_height) + self.canvas.xview_moveto(0) + self.canvas.yview_moveto(0) + + def kill_canvas(self): + if hasattr(self, 'canvas'): + self.canvas.destroy() + + def crop(self, x1, y1, x2, y2): + blockdata = self.blockdata + start = y1 * self.width + x1 + width = x2 - x1 + height = y2 - y1 + self.blockdata = [] + for y in xrange(height): + for x in xrange(width): + self.blockdata += [blockdata[start + y * self.width + x]] + self.blockdata = bytearray(self.blockdata) + self.width = width + self.height = height + + def draw(self): + for i in xrange(len(self.blockdata)): + block_x = i % self.width + block_y = i / self.width + self.draw_block(block_x, block_y) + + def draw_block(self, block_x, block_y): + # the canvas starts at 4, 4 for some reason + # probably something to do with a border + index, indey = 4, 4 + + # Draw one block (4x4 tiles) + block = self.blockdata[block_y * self.width + block_x] + for j, tile in enumerate(self.tileset.blocks[block]): + # Tile gfx are split in half to make vram mapping easier + if tile >= 0x80: + tile -= 0x20 + tile_x = block_x * 32 + (j % 4) * 8 + tile_y = block_y * 32 + (j / 4) * 8 + self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) class Tileset: - def __init__(self, tileset_id=0): - self.id = tileset_id - - self.tile_width = 8 - self.tile_height = 8 - self.block_width = 4 - self.block_height = 4 - - self.alpha = 255 - - if palettes_on: - self.get_palettes() - self.get_palette_map() - - self.get_blocks() - self.get_tiles() - - def get_tiles(self): - filename = os.path.join( - gfx_dir, - to_gfx_name(self.id) + '.png' - ) - self.img = Image.open(filename) - self.img.width, self.img.height = self.img.size - self.tiles = [] - cur_tile = 0 - for y in xrange(0, self.img.height, self.tile_height): - for x in xrange(0, self.img.width, self.tile_width): - tile = self.img.crop((x, y, x + self.tile_width, y + self.tile_height)) - - if hasattr(self, 'palette_map') and hasattr(self, 'palettes'): - # Palette maps are padded to make vram mapping easier. - pal = self.palette_map[cur_tile + 0x20 if cur_tile >= 0x60 else cur_tile] & 0x7 - tile = self.colorize_tile(tile, self.palettes[pal]) - - self.tiles += [ImageTk.PhotoImage(tile)] - cur_tile += 1 - - def colorize_tile(self, tile, palette): - width, height = tile.size - tile = tile.convert("RGB") - px = tile.load() - for y in xrange(height): - for x in xrange(width): - # assume greyscale - which_color = 3 - (px[x, y][0] / 0x55) - r, g, b = [v * 8 for v in palette[which_color]] - px[x, y] = (r, g, b) - return tile - - def get_blocks(self): - filename = os.path.join( - block_dir, - to_gfx_name(self.id) + block_ext - ) - self.blocks = [] - block_length = self.block_width * self.block_height - blocks = bytearray(open(filename, 'rb').read()) - for block in xrange(len(blocks) / (block_length)): - i = block * block_length - self.blocks += [blocks[i : i + block_length]] - - def get_palette_map(self): - filename = os.path.join( - palmap_dir, - str(self.id).zfill(2) + '_palette_map.bin' - ) - self.palette_map = [] - palmap = bytearray(open(filename, 'rb').read()) - for i in xrange(len(palmap)): - self.palette_map += [palmap[i] & 0xf] - self.palette_map += [(palmap[i] >> 4) & 0xf] - - def get_palettes(self): - filename = os.path.join( - palette_dir, - ['morn', 'day', 'nite'][time_of_day] + '.pal' - ) - self.palettes = get_palettes(filename) + def __init__(self, tileset_id=0): + self.id = tileset_id + + self.tile_width = 8 + self.tile_height = 8 + self.block_width = 4 + self.block_height = 4 + + self.alpha = 255 + + if palettes_on: + self.get_palettes() + self.get_palette_map() + + self.get_blocks() + self.get_tiles() + + def get_tiles(self): + filename = os.path.join( + gfx_dir, + to_gfx_name(self.id) + '.png' + ) + self.img = Image.open(filename) + self.img.width, self.img.height = self.img.size + self.tiles = [] + cur_tile = 0 + for y in xrange(0, self.img.height, self.tile_height): + for x in xrange(0, self.img.width, self.tile_width): + tile = self.img.crop((x, y, x + self.tile_width, y + self.tile_height)) + + if hasattr(self, 'palette_map') and hasattr(self, 'palettes'): + # Palette maps are padded to make vram mapping easier. + pal = self.palette_map[cur_tile + 0x20 if cur_tile >= 0x60 else cur_tile] & 0x7 + tile = self.colorize_tile(tile, self.palettes[pal]) + + self.tiles += [ImageTk.PhotoImage(tile)] + cur_tile += 1 + + def colorize_tile(self, tile, palette): + width, height = tile.size + tile = tile.convert("RGB") + px = tile.load() + for y in xrange(height): + for x in xrange(width): + # assume greyscale + which_color = 3 - (px[x, y][0] / 0x55) + r, g, b = [v * 8 for v in palette[which_color]] + px[x, y] = (r, g, b) + return tile + + def get_blocks(self): + filename = os.path.join( + block_dir, + to_gfx_name(self.id) + block_ext + ) + self.blocks = [] + block_length = self.block_width * self.block_height + blocks = bytearray(open(filename, 'rb').read()) + for block in xrange(len(blocks) / (block_length)): + i = block * block_length + self.blocks += [blocks[i : i + block_length]] + + def get_palette_map(self): + filename = os.path.join( + palmap_dir, + str(self.id).zfill(2) + '_palette_map.bin' + ) + self.palette_map = [] + palmap = bytearray(open(filename, 'rb').read()) + for i in xrange(len(palmap)): + self.palette_map += [palmap[i] & 0xf] + self.palette_map += [(palmap[i] >> 4) & 0xf] + + def get_palettes(self): + filename = os.path.join( + palette_dir, + ['morn', 'day', 'nite'][time_of_day] + '.pal' + ) + self.palettes = get_palettes(filename) time_of_day = 1 def get_palettes(filename): - pals = bytearray(open(filename, 'rb').read()) + pals = bytearray(open(filename, 'rb').read()) - num_colors = 4 - color_length = 2 + num_colors = 4 + color_length = 2 - palette_length = num_colors * color_length + palette_length = num_colors * color_length - num_pals = len(pals) / palette_length + num_pals = len(pals) / palette_length - palettes = [] - for pal in xrange(num_pals): - palettes += [[]] + palettes = [] + for pal in xrange(num_pals): + palettes += [[]] - for color in xrange(num_colors): - i = pal * palette_length - i += color * color_length - word = pals[i] + pals[i+1] * 0x100 - palettes[pal] += [[ - c & 0x1f for c in [ - word >> 0, - word >> 5, - word >> 10, - ] - ]] - return palettes + for color in xrange(num_colors): + i = pal * palette_length + i += color * color_length + word = pals[i] + pals[i+1] * 0x100 + palettes[pal] += [[ + c & 0x1f for c in [ + word >> 0, + word >> 5, + word >> 10, + ] + ]] + return palettes def get_available_maps(): - for root, dirs, files in os.walk(map_dir): - for filename in files: - base_name, ext = os.path.splitext(filename) - if ext == '.blk': - yield base_name + for root, dirs, files in os.walk(map_dir): + for filename in files: + base_name, ext = os.path.splitext(filename) + if ext == '.blk': + yield base_name def map_header(name): - if version == 'crystal': - headers = open(os.path.join(header_dir, 'map_headers.asm'), 'r').read() - label = name + '_MapHeader' - header = asm_at_label(headers, label) - macros = [ 'db', 'dw', 'db' ] - attributes = [ - 'bank', - 'tileset_id', - 'permission', - 'second_map_header', - 'world_map_location', - 'music', - 'time_of_day', - 'fishing_group', - ] - values, l = read_header_macros(header, attributes, macros) - attrs = dict(zip(attributes, values)) - return attrs - - elif version == 'red': - headers = open(header_path, 'r').read() - - # there has to be a better way to do this - lower_label = name + '_h' - i = headers.lower().find(lower_label) - if i == -1: - return {} - label = headers[i:i+len(lower_label)] - - header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dw', 'db' ] - attributes = [ - 'tileset_id', - 'height', - 'width', - 'blockdata_label', - 'text_label', - 'script_label', - 'which_connections', - ] - values, l = read_header_macros(header, attributes, macros) - - attrs = dict(zip(attributes, values)) - attrs['connections'], l = connections(attrs['which_connections'], header, l) - - macros = [ 'dw' ] - attributes = [ - 'object_label', - ] - values, l = read_header_macros(header[l:], attributes, macros) - attrs.update(dict(zip(attributes, values))) - - return attrs - - return {} + if version == 'crystal': + headers = open(os.path.join(header_dir, 'map_headers.asm'), 'r').read() + label = name + '_MapHeader' + header = asm_at_label(headers, label) + macros = [ 'db', 'dw', 'db' ] + attributes = [ + 'bank', + 'tileset_id', + 'permission', + 'second_map_header', + 'world_map_location', + 'music', + 'time_of_day', + 'fishing_group', + ] + values, l = read_header_macros(header, attributes, macros) + attrs = dict(zip(attributes, values)) + return attrs + + elif version == 'red': + headers = open(header_path, 'r').read() + + # there has to be a better way to do this + lower_label = name + '_h' + i = headers.lower().find(lower_label) + if i == -1: + return {} + label = headers[i:i+len(lower_label)] + + header = asm_at_label(headers, label) + macros = [ 'db', 'db', 'dw', 'db' ] + attributes = [ + 'tileset_id', + 'height', + 'width', + 'blockdata_label', + 'text_label', + 'script_label', + 'which_connections', + ] + values, l = read_header_macros(header, attributes, macros) + + attrs = dict(zip(attributes, values)) + attrs['connections'], l = connections(attrs['which_connections'], header, l) + + macros = [ 'dw' ] + attributes = [ + 'object_label', + ] + values, l = read_header_macros(header[l:], attributes, macros) + attrs.update(dict(zip(attributes, values))) + + return attrs + + return {} def second_map_header(name): - if version == 'crystal': - headers = open(os.path.join(header_dir, 'second_map_headers.asm'), 'r').read() - label = name + '_SecondMapHeader' - header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dbw', 'dbw', 'dw', 'db' ] - attributes = [ - 'border_block', - 'height', - 'width', - 'blockdata_bank', - 'blockdata_label', - 'script_header_bank', - 'script_header_label', - 'map_event_header_label', - 'which_connections', - ] - - values, l = read_header_macros(header, attributes, macros) - attrs = dict(zip(attributes, values)) - attrs['connections'], l = connections(attrs['which_connections'], header, l) - return attrs - - return {} + if version == 'crystal': + headers = open(os.path.join(header_dir, 'second_map_headers.asm'), 'r').read() + label = name + '_SecondMapHeader' + header = asm_at_label(headers, label) + macros = [ 'db', 'db', 'dbw', 'dbw', 'dw', 'db' ] + attributes = [ + 'border_block', + 'height', + 'width', + 'blockdata_bank', + 'blockdata_label', + 'script_header_bank', + 'script_header_label', + 'map_event_header_label', + 'which_connections', + ] + + values, l = read_header_macros(header, attributes, macros) + attrs = dict(zip(attributes, values)) + attrs['connections'], l = connections(attrs['which_connections'], header, l) + return attrs + + return {} def connections(which_connections, header, l=0): - directions = { 'north': {}, 'south': {}, 'west': {}, 'east': {} } - macros = [ 'db', 'dw', 'dw', 'db', 'db', 'dw' ] - - if version == 'crystal': - attributes = [ - 'map_group', - 'map_no', - ] - - elif version == 'red': - attributes = [ - 'map_id', - ] - - attributes += [ - 'strip_pointer', - 'strip_destination', - 'strip_length', - 'map_width', - 'y_offset', - 'x_offset', - 'window', - ] - for d in directions.keys(): - if d.upper() in which_connections: - values, l = read_header_macros(header, attributes, macros) - header = header[l:] - directions[d] = dict(zip(attributes, values)) - if version == 'crystal': - directions[d]['map_name'] = directions[d]['map_group'].replace('GROUP_', '').title().replace('_','') - elif version == 'red': - directions[d]['map_name'] = directions[d]['map_id'].title().replace('_','') - return directions, l + directions = { 'north': {}, 'south': {}, 'west': {}, 'east': {} } + macros = [ 'db', 'dw', 'dw', 'db', 'db', 'dw' ] + + if version == 'crystal': + attributes = [ + 'map_group', + 'map_no', + ] + + elif version == 'red': + attributes = [ + 'map_id', + ] + + attributes += [ + 'strip_pointer', + 'strip_destination', + 'strip_length', + 'map_width', + 'y_offset', + 'x_offset', + 'window', + ] + for d in directions.keys(): + if d.upper() in which_connections: + values, l = read_header_macros(header, attributes, macros) + header = header[l:] + directions[d] = dict(zip(attributes, values)) + if version == 'crystal': + directions[d]['map_name'] = directions[d]['map_group'].replace('GROUP_', '').title().replace('_','') + elif version == 'red': + directions[d]['map_name'] = directions[d]['map_id'].title().replace('_','') + return directions, l def read_header_macros(header, attributes, macros): - values = [] - i = 0 - l = 0 - for l, (asm, comment) in enumerate(header): - if asm.strip() != '': - values += macro_values(asm, macros[i]) - i += 1 - if len(values) >= len(attributes): - l += 1 - break - return values, l + values = [] + i = 0 + l = 0 + for l, (asm, comment) in enumerate(header): + if asm.strip() != '': + values += macro_values(asm, macros[i]) + i += 1 + if len(values) >= len(attributes): + l += 1 + break + return values, l def event_header(asm, name): - return {} + return {} def script_header(asm, name): - return {} + return {} def macro_values(line, macro): - values = line[line.find(macro) + len(macro):].split(',') - return [v.replace('$','0x').strip() for v in values] + values = line[line.find(macro) + len(macro):].split(',') + return [v.replace('$','0x').strip() for v in values] def db_value(line): - macro = 'db' - return macro_values(line, macro) + macro = 'db' + return macro_values(line, macro) def db_values(line): - macro = 'db' - return macro_values(line, macro) + macro = 'db' + return macro_values(line, macro) from preprocessor import separate_comment def asm_at_label(asm, label): - label_def = label + ':' - start = asm.find(label_def) + len(label_def) - lines = asm[start:].split('\n') - # go until the next label - content = [] - for line in lines: - l, comment = separate_comment(line + '\n') - if ':' in l: - break - content += [[l, comment]] - return content + label_def = label + ':' + start = asm.find(label_def) + len(label_def) + lines = asm[start:].split('\n') + # go until the next label + content = [] + for line in lines: + l, comment = separate_comment(line + '\n') + if ':' in l: + break + content += [[l, comment]] + return content def main(): """ -- cgit v1.2.3 From 96574a08ee25c6118d4e1e5cb8ff334b118817f2 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 02:26:09 -0400 Subject: map_editor: more flexible macro handling makes less assumptions about the structure of a header --- pokemontools/map_editor.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 9cd29ea..0a02cb0 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -473,7 +473,7 @@ def map_header(name): headers = open(os.path.join(header_dir, 'map_headers.asm'), 'r').read() label = name + '_MapHeader' header = asm_at_label(headers, label) - macros = [ 'db', 'dw', 'db' ] + macros = [ 'db', 'db', 'db', 'dw', 'db', 'db', 'db', 'db' ] attributes = [ 'bank', 'tileset_id', @@ -499,7 +499,7 @@ def map_header(name): label = headers[i:i+len(lower_label)] header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dw', 'db' ] + macros = [ 'db', 'db', 'db', 'dw', 'dw', 'dw', 'db' ] attributes = [ 'tileset_id', 'height', @@ -530,7 +530,7 @@ def second_map_header(name): headers = open(os.path.join(header_dir, 'second_map_headers.asm'), 'r').read() label = name + '_SecondMapHeader' header = asm_at_label(headers, label) - macros = [ 'db', 'db', 'dbw', 'dbw', 'dw', 'db' ] + macros = [ 'db', 'db', 'db', 'db', 'dw', 'db', 'dw', 'dw', 'db' ] attributes = [ 'border_block', 'height', @@ -552,19 +552,21 @@ def second_map_header(name): def connections(which_connections, header, l=0): directions = { 'north': {}, 'south': {}, 'west': {}, 'east': {} } - macros = [ 'db', 'dw', 'dw', 'db', 'db', 'dw' ] if version == 'crystal': + macros = [ 'db', 'db' ] attributes = [ 'map_group', 'map_no', ] elif version == 'red': + macros = [ 'db' ] attributes = [ 'map_id', ] + macros += [ 'dw', 'dw', 'db', 'db', 'db', 'db', 'dw' ] attributes += [ 'strip_pointer', 'strip_destination', @@ -591,8 +593,9 @@ def read_header_macros(header, attributes, macros): l = 0 for l, (asm, comment) in enumerate(header): if asm.strip() != '': - values += macro_values(asm, macros[i]) - i += 1 + mvalues = macro_values(asm, macros[i]) + values += mvalues + i += len(mvalues) if len(values) >= len(attributes): l += 1 break @@ -608,7 +611,10 @@ def script_header(asm, name): def macro_values(line, macro): values = line[line.find(macro) + len(macro):].split(',') - return [v.replace('$','0x').strip() for v in values] + values = [v.replace('$','0x').strip() for v in values] + if values[0] == 'w': # dbw + values = values[1:] + return values def db_value(line): macro = 'db' @@ -623,8 +629,12 @@ from preprocessor import separate_comment def asm_at_label(asm, label): label_def = label + ':' - start = asm.find(label_def) + len(label_def) - lines = asm[start:].split('\n') + lines = asm.split('\n') + for line in lines: + if line.startswith(label_def): + lines = lines[lines.index(line):] + lines[0] = lines[0][len(label_def):] + break # go until the next label content = [] for line in lines: -- cgit v1.2.3 From 92eeee28dd0633655d331e658cdd3a5c6b5c6fab Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 02:49:37 -0400 Subject: map_editor: skip any nonexistent tiles in map rendering --- pokemontools/map_editor.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index 0a02cb0..efd9678 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -322,12 +322,15 @@ class Map: # Draw one block (4x4 tiles) block = self.blockdata[block_y * self.width + block_x] for j, tile in enumerate(self.tileset.blocks[block]): - # Tile gfx are split in half to make vram mapping easier - if tile >= 0x80: - tile -= 0x20 - tile_x = block_x * 32 + (j % 4) * 8 - tile_y = block_y * 32 + (j / 4) * 8 - self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) + try: + # Tile gfx are split in half to make vram mapping easier + if tile >= 0x80: + tile -= 0x20 + tile_x = block_x * 32 + (j % 4) * 8 + tile_y = block_y * 32 + (j / 4) * 8 + self.canvas.create_image(index + tile_x, indey + tile_y, image=self.tileset.tiles[tile]) + except: + pass class Tileset: -- cgit v1.2.3 From 001b6bc850b25f6cbd4d7a7cfa540c62cada88f6 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 02:52:45 -0400 Subject: map_editor: create any pngs that don't exist yet --- pokemontools/map_editor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pokemontools/map_editor.py b/pokemontools/map_editor.py index efd9678..4970d9e 100644 --- a/pokemontools/map_editor.py +++ b/pokemontools/map_editor.py @@ -372,6 +372,9 @@ class Tileset: def get_tiles(self): filename = self.get_tileset_gfx_filename() + if not os.path.exists(filename): + import gfx + gfx.to_png(filename.replace('.png','.2bpp'), filename) self.img = Image.open(filename) self.img.width, self.img.height = self.img.size self.tiles = [] -- cgit v1.2.3 From 3496b81eb3b5af6fa7d694cbac1610b5ff2c85f2 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 03:13:15 -0400 Subject: crystal.py: no more relative paths --- pokemontools/crystal.py | 53 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 8a12dad..089f694 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -61,6 +61,9 @@ import item_constants import wram import exceptions +import config +conf = config.Config() + from map_names import map_names # ---- script_parse_table explanation ---- @@ -106,17 +109,21 @@ def map_name_cleaner(input): rom = romstr.RomStr(None) -def direct_load_rom(filename="../baserom.gbc"): +def direct_load_rom(filename=None): """loads bytes into memory""" + if filename == None: + filename = os.path.join(conf.path, "baserom.gbc") global rom file_handler = open(filename, "rb") rom = romstr.RomStr(file_handler.read()) file_handler.close() return rom -def load_rom(filename="../baserom.gbc"): +def load_rom(filename=None): """checks that the loaded rom matches the path and then loads the rom if necessary.""" + if filename == None: + filename = os.path.join(conf.path, "baserom.gbc") global rom if rom != romstr.RomStr(None) and rom != None: return rom @@ -125,14 +132,18 @@ def load_rom(filename="../baserom.gbc"): elif os.lstat(filename).st_size != len(rom): return direct_load_rom(filename) -def direct_load_asm(filename="../main.asm"): +def direct_load_asm(filename=None): + if filename == None: + filename = os.path.join(conf.path, "main.asm") """returns asm source code (AsmList) from a file""" asm = open(filename, "r").read().split("\n") asm = romstr.AsmList(asm) return asm -def load_asm(filename="../main.asm"): +def load_asm(filename=None): """returns asm source code (AsmList) from a file (uses a global)""" + if filename == None: + filename = os.path.join(conf.path, "main.asm") global asm asm = direct_load_asm(filename=filename) return asm @@ -3185,7 +3196,9 @@ effect_classes = create_effect_command_classes() -def generate_macros(filename="../script_macros.asm"): +def generate_macros(filename=None): + if filename == None: + filename = os.path.join(conf.path, "script_macros.asm") """generates all macros based on commands this is dumped into script_macros.asm""" output = "; This file is generated by generate_macros.\n" @@ -5985,7 +5998,7 @@ def old_parse_second_map_header_at(address, map_group=None, map_id=None, debug=T class MapBlockData: base_label = "MapBlockData_" - maps_path = os.path.realpath(os.path.join(os.path.realpath("."), "../maps")) + maps_path = os.path.realpath(os.path.join(conf.path, "maps")) def __init__(self, address, map_group=None, map_id=None, debug=True, bank=None, label=None, width=None, height=None): self.address = address @@ -6887,9 +6900,11 @@ def reset_incbins(): isolate_incbins(asm=asm) process_incbins() -def find_incbin_to_replace_for(address, debug=False, rom_file="../baserom.gbc"): +def find_incbin_to_replace_for(address, debug=False, rom_file=None): """returns a line number for which incbin to edit if you were to insert bytes into main.asm""" + if rom_file == None: + rom_file = os.path.join(conf.path, "baserom.gbc") if type(address) == str: address = int(address, 16) if not (0 <= address <= os.lstat(rom_file).st_size): raise IndexError("address is out of bounds") @@ -6917,7 +6932,7 @@ def find_incbin_to_replace_for(address, debug=False, rom_file="../baserom.gbc"): return incbin_key return None -def split_incbin_line_into_three(line, start_address, byte_count, rom_file="../baserom.gbc"): +def split_incbin_line_into_three(line, start_address, byte_count, rom_file=None): """ splits an incbin line into three pieces. you can replace the middle one with the new content of length bytecount @@ -6925,6 +6940,8 @@ def split_incbin_line_into_three(line, start_address, byte_count, rom_file="../b start_address: where you want to start inserting bytes byte_count: how many bytes you will be inserting """ + if rom_file == None: + rom_file = os.path.join(conf.path, "baserom.gbc") if type(start_address) == str: start_address = int(start_address, 16) if not (0 <= start_address <= os.lstat(rom_file).st_size): raise IndexError("start_address is out of bounds") @@ -6984,9 +7001,9 @@ def generate_diff_insert(line_number, newline, debug=False): CalledProcessError = None try: - diffcontent = subprocess.check_output("diff -u ../main.asm " + newfile_filename, shell=True) + diffcontent = subprocess.check_output("diff -u " + os.path.join(conf.path, "main.asm") + " " + newfile_filename, shell=True) except (AttributeError, CalledProcessError): - p = subprocess.Popen(["diff", "-u", "../main.asm", newfile_filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + p = subprocess.Popen(["diff", "-u", os.path.join(conf.path, "main.asm"), newfile_filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() diffcontent = out @@ -7006,8 +7023,8 @@ def apply_diff(diff, try_fixing=True, do_compile=True): fh.close() # apply the patch - os.system("cp ../main.asm ../main1.asm") - os.system("patch ../main.asm temp.patch") + os.system("cp " + os.path.join(conf.path, "main.asm") + " " + os.path.join(conf.path, "main1.asm")) + os.system("patch " + os.path.join(conf.path, "main.asm") + " " + "temp.patch") # remove the patch os.system("rm temp.patch") @@ -7015,11 +7032,11 @@ def apply_diff(diff, try_fixing=True, do_compile=True): # confirm it's working if do_compile: try: - subprocess.check_call("cd ../; make clean; make", shell=True) + subprocess.check_call("cd " + conf.path + "; make clean; make", shell=True) return True except Exception, exc: if try_fixing: - os.system("mv ../main1.asm ../main.asm") + os.system("mv " + os.path.join(conf.path, "main1.asm") + " " + os.path.join(conf.path, "main.asm")) return False class AsmLine: @@ -7151,8 +7168,10 @@ class AsmSection: return self.line new_asm = None -def load_asm2(filename="../main.asm", force=False): +def load_asm2(filename=None, force=False): """loads the asm source code into memory""" + if filename == None: + filename = os.path.join(conf.path, "main.asm") global new_asm if new_asm == None or force: new_asm = Asm(filename=filename) @@ -7160,7 +7179,9 @@ def load_asm2(filename="../main.asm", force=False): class Asm: """controls the overall asm output""" - def __init__(self, filename="../main.asm", debug=True): + def __init__(self, filename=None, debug=True): + if filename == None: + filename = os.path.join(conf.path, "main.asm") self.parts = [] self.labels = [] self.filename = filename -- cgit v1.2.3 From 97fdec37ec9d1319f914b648d44dee385e03148b Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 17:17:18 -0500 Subject: fix crystal.py configuration Ugh, it's still a global? --- pokemontools/crystal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 7acb160..be02576 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -67,8 +67,8 @@ is_valid_address = addresses.is_valid_address import old_text_script OldTextScript = old_text_script -import config -conf = config.Config() +import configiguration +conf = configuration.Config() from map_names import map_names -- cgit v1.2.3 From f7b6808797afd31812b3168ca41c640bd8005e67 Mon Sep 17 00:00:00 2001 From: Bryan Bishop Date: Thu, 26 Sep 2013 17:18:46 -0500 Subject: fix configuration typo --- pokemontools/crystal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index be02576..7bd8a30 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -67,7 +67,7 @@ is_valid_address = addresses.is_valid_address import old_text_script OldTextScript = old_text_script -import configiguration +import configuration conf = configuration.Config() from map_names import map_names -- cgit v1.2.3 From f4b04ff8e90f49a8ad021b7b7229a9a47a087c06 Mon Sep 17 00:00:00 2001 From: yenatch Date: Thu, 26 Sep 2013 18:22:27 -0400 Subject: if_greater_than and if_less_than commands were swapped --- pokemontools/crystal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index d93540b..bf67ee5 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2695,8 +2695,8 @@ pksv_crystal_more = { 0x07: ["if not equal", ["byte", SingleByteParam], ["pointer", ScriptPointerLabelParam]], 0x08: ["iffalse", ["pointer", ScriptPointerLabelParam]], 0x09: ["iftrue", ["pointer", ScriptPointerLabelParam]], - 0x0A: ["if less than", ["byte", SingleByteParam], ["pointer", ScriptPointerLabelParam]], - 0x0B: ["if greater than", ["byte", SingleByteParam], ["pointer", ScriptPointerLabelParam]], + 0x0A: ["if greater than", ["byte", SingleByteParam], ["pointer", ScriptPointerLabelParam]], + 0x0B: ["if less than", ["byte", SingleByteParam], ["pointer", ScriptPointerLabelParam]], 0x0C: ["jumpstd", ["predefined_script", MultiByteParam]], 0x0D: ["callstd", ["predefined_script", MultiByteParam]], 0x0E: ["3callasm", ["asm", AsmPointerParam]], -- cgit v1.2.3 From 7268b91c23ec6a2c98348022a0d91ab3d881b153 Mon Sep 17 00:00:00 2001 From: yenatch Date: Mon, 30 Sep 2013 20:41:16 -0400 Subject: fix up the last few event scirpt commands --- pokemontools/crystal.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index bf67ee5..06d9139 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2857,10 +2857,10 @@ pksv_crystal_more = { 0xA2: ["credits"], 0xA3: ["warpfacing", ["facing", SingleByteParam], ["map_group", MapGroupParam], ["map_id", MapIdParam], ["x", SingleByteParam], ["y", SingleByteParam]], 0xA4: ["storetext", ["pointer", PointerLabelBeforeBank], ["memory", SingleByteParam]], - 0xA5: ["displaylocation", ["id", SingleByteParam]], - 0xA6: ["unknown0xa6"], - 0xA7: ["unknown0xa7"], - 0xA8: ["unknown0xa8", ["unknown", SingleByteParam]], + 0xA5: ["displaylocation", ["id", SingleByteParam], ["memory", SingleByteParam]], + 0xA6: ["trainerclassname", ["id", SingleByteParam]], + 0xA7: ["name", ["type", SingleByteParam], ["id", SingleByteParam]], + 0xA8: ["waitframes", ["unknown", SingleByteParam]], 0xA9: ["unknown0xa9"], 0xAA: ["unknown0xaa"], } -- cgit v1.2.3 From a0397cad2854ce3a2eb1861d23c552596e4e9802 Mon Sep 17 00:00:00 2001 From: yenatch Date: Mon, 30 Sep 2013 20:41:44 -0400 Subject: event script command 0xaa doesnt exist --- pokemontools/crystal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 06d9139..ca44965 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2862,7 +2862,6 @@ pksv_crystal_more = { 0xA7: ["name", ["type", SingleByteParam], ["id", SingleByteParam]], 0xA8: ["waitframes", ["unknown", SingleByteParam]], 0xA9: ["unknown0xa9"], - 0xAA: ["unknown0xaa"], } def create_command_classes(debug=False): """creates some classes for each command byte""" -- cgit v1.2.3 From bcb3295dbd4bcc063e0f6f59a8cf2de9eb53e981 Mon Sep 17 00:00:00 2001 From: yenatch Date: Tue, 1 Oct 2013 00:36:39 -0400 Subject: use 'wait' for events instead of move effects --- pokemontools/crystal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index ca44965..c95b705 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -2860,7 +2860,7 @@ pksv_crystal_more = { 0xA5: ["displaylocation", ["id", SingleByteParam], ["memory", SingleByteParam]], 0xA6: ["trainerclassname", ["id", SingleByteParam]], 0xA7: ["name", ["type", SingleByteParam], ["id", SingleByteParam]], - 0xA8: ["waitframes", ["unknown", SingleByteParam]], + 0xA8: ["wait", ["unknown", SingleByteParam]], 0xA9: ["unknown0xa9"], } def create_command_classes(debug=False): @@ -3142,7 +3142,7 @@ effect_commands = { 0xa7: ['effect0xa7'], 0xa8: ['effect0xa8'], 0xa9: ['clearmissdamage'], - 0xaa: ['wait'], + 0xaa: ['movedelay'], 0xab: ['hittarget'], 0xac: ['tristatuschance'], 0xad: ['supereffectivelooptext'], -- cgit v1.2.3