def _write_compressed_block(rom, compressed_block, pointer): compressed_block.compress() new_offset = rom.allocate(data=compressed_block) write_asm_pointer( block=rom, offset=pointer, pointer=to_snes_address(new_offset) ) return new_offset
def write_background_data_to_rom(self, rom): # Write the background tileset data block_size = self.bg_tileset.block_size(bpp=BG_TILESET_BPP) with EbCompressibleBlock(block_size) as block: self.bg_tileset.to_block(block=block, offset=0, bpp=BG_TILESET_BPP) self._write_compressed_block(rom, block, BG_TILESET_POINTER) # Write the background tile arrangement data block_size = self.bg_arrangement.block_size() with EbCompressibleBlock(block_size) as block: self.bg_arrangement.to_block(block=block, offset=0) self._write_compressed_block(rom, block, BG_ARRANGEMENT_POINTER) # Write the background palette data # There is an additional pointer to this location, so change that one # too block_size = self.bg_palette.block_size() with EbCompressibleBlock(block_size) as block: self.bg_palette.to_block(block=block, offset=0) new_offset = self._write_compressed_block(rom, block, BG_PALETTE_POINTER) write_asm_pointer(block=rom, offset=BG_PALETTE_POINTER_SECONDARY, pointer=to_snes_address(new_offset)) # Write the background animated palette data block_size = self.bg_anim_palette.block_size() with EbCompressibleBlock(block_size) as block: self.bg_anim_palette.to_block(block=block, offset=0) self._write_compressed_block(rom, block, BG_ANIM_PALETTE_POINTER)
def write_background_data_to_rom(self, rom): # Write the background tileset data block_size = self.bg_tileset.block_size(bpp=BG_TILESET_BPP) with EbCompressibleBlock(block_size) as block: self.bg_tileset.to_block(block=block, offset=0, bpp=BG_TILESET_BPP) self._write_compressed_block(rom, block, BG_TILESET_POINTER) # Write the background tile arrangement data block_size = self.bg_arrangement.block_size() with EbCompressibleBlock(block_size) as block: self.bg_arrangement.to_block(block=block, offset=0) self._write_compressed_block(rom, block, BG_ARRANGEMENT_POINTER) # Write the background palette data # There is an additional pointer to this location, so change that one # too block_size = self.bg_palette.block_size() with EbCompressibleBlock(block_size) as block: self.bg_palette.to_block(block=block, offset=0) new_offset = self._write_compressed_block( rom, block, BG_PALETTE_POINTER ) write_asm_pointer( block=rom, offset=BG_PALETTE_POINTER_SECONDARY, pointer=to_snes_address(new_offset) ) # Write the background animated palette data block_size = self.bg_anim_palette.block_size() with EbCompressibleBlock(block_size) as block: self.bg_anim_palette.to_block(block=block, offset=0) self._write_compressed_block(rom, block, BG_ANIM_PALETTE_POINTER)
def write_to_rom(self, rom): self.enemy_config_table.to_block( block=rom, offset=from_snes_address(ENEMY_CONFIGURATION_TABLE_DEFAULT_OFFSET)) self.enemy_group_bg_table.to_block( block=rom, offset=from_snes_address( ENEMY_GROUP_BACKGROUND_TABLE_DEFAULT_OFFSET)) # Write the sprites self.graphics_pointer_table.recreate(num_rows=len(self.battle_sprites)) for i, battle_sprite in enumerate(self.battle_sprites): self.graphics_pointer_table[i] = [None, battle_sprite.size()] with EbCompressibleBlock( size=battle_sprite.block_size()) as compressed_block: battle_sprite.to_block(block=compressed_block, offset=0) compressed_block.compress() graphics_offset = rom.allocate(data=compressed_block) self.graphics_pointer_table[i][0] = to_snes_address( graphics_offset) graphics_pointer_table_offset = rom.allocate( size=self.graphics_pointer_table.size) self.graphics_pointer_table.to_block( block=rom, offset=graphics_pointer_table_offset) write_asm_pointer( block=rom, offset=GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSET, pointer=to_snes_address(graphics_pointer_table_offset)) for pointer_offset in GRAPHICS_POINTER_TABLE_POINTER_OFFSETS: rom.write_multi( pointer_offset, item=to_snes_address(graphics_pointer_table_offset), size=3) # Write the palettes if self.palettes: palettes_offset = rom.allocate(size=self.palettes[0].block_size() * len(self.palettes)) write_asm_pointer(block=rom, offset=PALETTES_ASM_POINTER_OFFSET, pointer=to_snes_address(palettes_offset)) for palette in self.palettes: palette.to_block(block=rom, offset=palettes_offset) palettes_offset += palette.block_size() # Write the groups for i, group in enumerate(self.enemy_groups): offset = rom.allocate( size=(len(group) * EnemyGroupTableEntry.size + 1)) self.enemy_group_table[i][0] = to_snes_address(offset) for group_entry in group: EnemyGroupTableEntry.to_block(block=rom, offset=offset, value=group_entry) offset += EnemyGroupTableEntry.size rom[offset] = 0xff self.enemy_group_table.to_block( block=rom, offset=from_snes_address(ENEMY_GROUP_TABLE_DEFAULT_OFFSET))
def _write_compressed_block(rom, compressed_block, pointer): compressed_block.compress() new_offset = rom.allocate(data=compressed_block) write_asm_pointer(block=rom, offset=pointer, pointer=to_snes_address(new_offset)) return new_offset
def write_gfx_to_rom(self, rom, offset, gfx): graphics_offset, arrangement_offset, palette_offsets = gfx.to_block( block=rom) write_asm_pointer(block=rom, offset=offset, pointer=to_snes_address(graphics_offset)) gfx.palettes[0].to_block(block=rom, offset=CAST_GRAPHICS_PALETTE_OFFSET)
def to_block(self, block, tileset_asm_pointer_offset, palette_offset): tileset_block_size = self.tileset.block_size(bpp=2) with EbCompressibleBlock(tileset_block_size) as compressed_block: self.tileset.to_block(block=compressed_block, offset=0, bpp=2) compressed_block.compress() tileset_offset = block.allocate(data=compressed_block) write_asm_pointer(block=block, offset=tileset_asm_pointer_offset, pointer=to_snes_address(tileset_offset)) self.palette.to_block(block=block, offset=palette_offset)
def write_to_rom(self, rom): tileset_block_size = self.tileset.block_size(bpp=4) with EbCompressibleBlock(tileset_block_size) as compressed_block: self.tileset.to_block(block=compressed_block, offset=0, bpp=4) compressed_block.compress() tileset_offset = rom.allocate(data=compressed_block) write_asm_pointer(block=rom, offset=GRAPHICS_ASM_POINTER_OFFSET, pointer=to_snes_address(tileset_offset)) self.palette.to_block(block=rom, offset=PALETTE_OFFSET)
def write_town_map_icons_to_rom(self, rom): log.debug("Writing town map icons") graphics_offset, arrangement_offset, palette_offsets = self.town_map_icons.to_block(rom) write_asm_pointer(block=rom, offset=TOWN_MAP_ICON_GRAPHICS_ASM_POINTER_OFFSET, pointer=to_snes_address(graphics_offset)) write_asm_pointer(block=rom, offset=TOWN_MAP_ICON_PALETTE_ASM_POINTER_OFFSET, pointer=to_snes_address(palette_offsets[0]))
def write_to_rom(self, rom): if self.mode != 'prefix': self.get_patch(self.mode, rom.type).apply(rom) loc = rom.allocate(size=self.table_entry.to_block_size(self.text)) addr = to_snes_address(loc) write_asm_pointer(block=rom, offset=self.asm_pointer_offset, pointer=addr) self.table_entry.to_block(rom, loc, self.text) if self.mode == 'prefix': self.get_patch(self.mode, rom.type).apply(rom) rom.write_multi(self.custom_asm_offset + 9, addr & 0xFFFF, 2) rom.write_multi(self.custom_asm_offset + 14, (addr >> 16) & 0xFF, 2) rom.write_multi(self.custom_asm_offset + 26, len(self.text), 2)
def write_to_rom(self, rom): self.enemy_config_table.to_block(block=rom, offset=from_snes_address(ENEMY_CONFIGURATION_TABLE_DEFAULT_OFFSET)) self.enemy_group_bg_table.to_block(block=rom, offset=from_snes_address(ENEMY_GROUP_BACKGROUND_TABLE_DEFAULT_OFFSET)) # Write the sprites self.graphics_pointer_table.recreate(num_rows=len(self.battle_sprites)) for i, battle_sprite in enumerate(self.battle_sprites): self.graphics_pointer_table[i] = [None, battle_sprite.size()] with EbCompressibleBlock(size=battle_sprite.block_size()) as compressed_block: battle_sprite.to_block(block=compressed_block, offset=0) compressed_block.compress() graphics_offset = rom.allocate(data=compressed_block) self.graphics_pointer_table[i][0] = to_snes_address(graphics_offset) graphics_pointer_table_offset = rom.allocate(size=self.graphics_pointer_table.size) self.graphics_pointer_table.to_block(block=rom, offset=graphics_pointer_table_offset) write_asm_pointer(block=rom, offset=GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSET, pointer=to_snes_address(graphics_pointer_table_offset)) for pointer_offset in GRAPHICS_POINTER_TABLE_POINTER_OFFSETS: rom.write_multi(pointer_offset, item=to_snes_address(graphics_pointer_table_offset), size=3) # Write the palettes if self.palettes: palettes_offset = rom.allocate(size=self.palettes[0].block_size() * len(self.palettes)) write_asm_pointer(block=rom, offset=PALETTES_ASM_POINTER_OFFSET, pointer=to_snes_address(palettes_offset)) for palette in self.palettes: palette.to_block(block=rom, offset=palettes_offset) palettes_offset += palette.block_size() # Write the groups for i, group in enumerate(self.enemy_groups): offset = rom.allocate(size=(len(group) * EnemyGroupTableEntry.size + 1)) self.enemy_group_table[i] = [to_snes_address(offset)] for group_entry in group: EnemyGroupTableEntry.to_block(block=rom, offset=offset, value=group_entry) offset += EnemyGroupTableEntry.size rom[offset] = 0xff self.enemy_group_table.to_block(block=rom, offset=from_snes_address(ENEMY_GROUP_TABLE_DEFAULT_OFFSET))
def write_to_rom(self, rom): graphics_1_block_size = self.graphics_1.block_size(bpp=2) with EbCompressibleBlock(graphics_1_block_size) as compressed_block: self.graphics_1.to_block(block=compressed_block, offset=0, bpp=2) compressed_block.compress() graphics_1_offset = rom.allocate(data=compressed_block) write_asm_pointer(block=rom, offset=GRAPHICS_1_ASM_POINTER_OFFSET, pointer=to_snes_address(graphics_1_offset)) graphics_2_block_size = self.graphics_2.block_size(bpp=2) with EbCompressibleBlock(graphics_2_block_size) as compressed_block: self.graphics_2.to_block(block=compressed_block, offset=0, bpp=2) compressed_block.compress() graphics_2_offset = rom.allocate(data=compressed_block) write_asm_pointer(block=rom, offset=GRAPHICS_2_ASM_POINTER_OFFSET, pointer=to_snes_address(graphics_2_offset)) # Write palettes offset = FLAVOR_PALETTES_OFFSET for palette in self.flavor_palettes: palette.to_block(block=rom, offset=offset) offset += 64 # Write names for asm_pointer_offset in FLAVOR_NAME_ASM_POINTER_OFFSETS: name = self.flavor_names[asm_pointer_offset] offset = rom.allocate(size=FLAVOR_NAME_ENTRY.size) FLAVOR_NAME_ENTRY.to_block(block=rom, offset=offset, value=name) write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(offset))
def write_logos_to_rom(self, rom, logos, infos): for info, logo in zip(infos, logos): graphics_offset, arrangement_offset, palette_offsets = logo.to_block(rom) for asm_pointer_offset in info.graphics_asm_pointer_offsets: write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(graphics_offset)) for asm_pointer_offset in info.arrangement_asm_pointer_offsets: write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(arrangement_offset)) for offset, asm_pointer_offset in zip(palette_offsets, info.palette_asm_pointer_offsets): write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(offset))
def write_to_rom(self, rom): # Write the data table self.bg_table.to_block(block=rom, offset=from_snes_address(BACKGROUND_TABLE_OFFSET)) self.scroll_table.to_block(block=rom, offset=from_snes_address(SCROLL_TABLE_OFFSET)) self.distortion_table.to_block(block=rom, offset=from_snes_address(DISTORTION_TABLE_OFFSET)) # Write graphics and arrangements self.graphics_pointer_table.recreate(num_rows=len(self.backgrounds)) self.arrangement_pointer_table.recreate(num_rows=len(self.backgrounds)) for i, (tileset, color_depth, arrangement) in enumerate(self.backgrounds): with EbCompressibleBlock(size=tileset.block_size(bpp=color_depth)) as compressed_block: tileset.to_block(block=compressed_block, offset=0, bpp=color_depth) compressed_block.compress() tileset_offset = rom.allocate(data=compressed_block) self.graphics_pointer_table[i] = [to_snes_address(tileset_offset)] with EbCompressibleBlock(size=arrangement.block_size()) as compressed_block: arrangement.to_block(block=compressed_block, offset=0) compressed_block.compress() arrangement_offset = rom.allocate(data=compressed_block) self.arrangement_pointer_table[i] = [to_snes_address(arrangement_offset)] graphics_pointer_table_offset = rom.allocate(size=self.graphics_pointer_table.size) self.graphics_pointer_table.to_block(block=rom, offset=graphics_pointer_table_offset) for asm_pointer_offset in GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(graphics_pointer_table_offset)) arrangement_pointer_table_offset = rom.allocate(size=self.arrangement_pointer_table.size) self.arrangement_pointer_table.to_block(block=rom, offset=arrangement_pointer_table_offset) for asm_pointer_offset in ARRANGEMENT_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(arrangement_pointer_table_offset)) # Write pals self.palette_pointer_table.recreate(num_rows=len(self.palettes)) for i, palette in enumerate(self.palettes): with Block(32) as block: palette.to_block(block=block, offset=0) palette_offset = rom.allocate(data=block) self.palette_pointer_table[i] = [to_snes_address(palette_offset)] palette_pointer_table_offset = rom.allocate(size=self.palette_pointer_table.size) self.palette_pointer_table.to_block(block=rom, offset=palette_pointer_table_offset) for asm_pointer_offset in PALETTE_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer(block=rom, offset=asm_pointer_offset, pointer=to_snes_address(palette_pointer_table_offset))
def write_to_rom(self, rom): pointer_table_offset = rom.allocate(size=self.table.size) self.table.to_block(rom, pointer_table_offset) write_asm_pointer(rom, self.POINTER_TABLE_ASM_POINTER_OFFSET, to_snes_address(pointer_table_offset))
def write(self, rom, address): log.info("Writing pointer at " + hex(self.offset)) write_asm_pointer(rom, self.offset, address)
def write(self, block, address): write_asm_pointer(block=block, offset=self.asm_pointer_loc, pointer=address)
def test_write_asm_pointer(): block = Block() block.from_list([0xee] * 9) write_asm_pointer(block, 1, 0xabcdef12) assert_list_equal(block.to_list(), [0xee, 0xee, 0x12, 0xef, 0xee, 0xee, 0xee, 0xcd, 0xab])
def write_to_rom(self, rom): # Write the data table self.bg_table.to_block( block=rom, offset=from_snes_address(BACKGROUND_TABLE_OFFSET)) self.scroll_table.to_block( block=rom, offset=from_snes_address(SCROLL_TABLE_OFFSET)) self.distortion_table.to_block( block=rom, offset=from_snes_address(DISTORTION_TABLE_OFFSET)) # Write graphics and arrangements self.graphics_pointer_table.recreate(num_rows=len(self.backgrounds)) self.arrangement_pointer_table.recreate(num_rows=len(self.backgrounds)) for i, (tileset, color_depth, arrangement) in enumerate(self.backgrounds): with EbCompressibleBlock(size=tileset.block_size( bpp=color_depth)) as compressed_block: tileset.to_block(block=compressed_block, offset=0, bpp=color_depth) compressed_block.compress() tileset_offset = rom.allocate(data=compressed_block) self.graphics_pointer_table[i] = [ to_snes_address(tileset_offset) ] with EbCompressibleBlock( size=arrangement.block_size()) as compressed_block: arrangement.to_block(block=compressed_block, offset=0) compressed_block.compress() arrangement_offset = rom.allocate(data=compressed_block) self.arrangement_pointer_table[i] = [ to_snes_address(arrangement_offset) ] graphics_pointer_table_offset = rom.allocate( size=self.graphics_pointer_table.size) self.graphics_pointer_table.to_block( block=rom, offset=graphics_pointer_table_offset) for asm_pointer_offset in GRAPHICS_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer( block=rom, offset=asm_pointer_offset, pointer=to_snes_address(graphics_pointer_table_offset)) arrangement_pointer_table_offset = rom.allocate( size=self.arrangement_pointer_table.size) self.arrangement_pointer_table.to_block( block=rom, offset=arrangement_pointer_table_offset) for asm_pointer_offset in ARRANGEMENT_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer( block=rom, offset=asm_pointer_offset, pointer=to_snes_address(arrangement_pointer_table_offset)) # Write pals self.palette_pointer_table.recreate(num_rows=len(self.palettes)) for i, palette in enumerate(self.palettes): with Block(32) as block: palette.to_block(block=block, offset=0) palette_offset = rom.allocate(data=block) self.palette_pointer_table[i] = [ to_snes_address(palette_offset) ] palette_pointer_table_offset = rom.allocate( size=self.palette_pointer_table.size) self.palette_pointer_table.to_block( block=rom, offset=palette_pointer_table_offset) for asm_pointer_offset in PALETTE_POINTER_TABLE_ASM_POINTER_OFFSETS: write_asm_pointer( block=rom, offset=asm_pointer_offset, pointer=to_snes_address(palette_pointer_table_offset))