"Size", 1, SPRITE_SIZES) SpriteGroupCollisionNSWidthEntry = LittleEndianIntegerTableEntry.create( "North/South Collision Width", 1) SpriteGroupCollisionNSHeightEntry = LittleEndianIntegerTableEntry.create( "North/South Collision Height", 1) SpriteGroupCollisionEWWidthEntry = LittleEndianIntegerTableEntry.create( "East/West Collision Width", 1) SpriteGroupCollisionEWHeightEntry = LittleEndianIntegerTableEntry.create( "East/West Collision Height", 1) SpriteGroupHeaderTableEntry = RowTableEntry.from_schema( name="Sprite Group Header Table Entry", schema=[ LittleEndianIntegerTableEntry.create("Height", 1), LittleEndianIntegerTableEntry.create("Width", 1), SpriteGroupSizeTableEntry, LittleEndianIntegerTableEntry.create("Palette", 1), SpriteGroupCollisionNSWidthEntry, SpriteGroupCollisionNSHeightEntry, SpriteGroupCollisionEWWidthEntry, SpriteGroupCollisionEWHeightEntry, LittleEndianIntegerTableEntry.create("Bank", 1) ]) class SpriteGroup(object): # The order in which sprite directions are compiled to form a sprite group, based on examining the game data. # The order is: S, N, W, E, NW, SW, SE, NE SPRITE_COMPILATION_ORDER = [2, 4, 1, 3, 8, 7, 6, 5] def __init__(self, num_sprites): self.width = 0 self.height = 0
from coilsnake.exceptions.common.exceptions import TableSchemaError, \ TableEntryError from coilsnake.model.common.table import LittleEndianIntegerTableEntry, \ RowTableEntry, TableEntry from coilsnake.model.eb.table import EbEventFlagTableEntry EnemyGroupTableEntry = RowTableEntry.from_schema( name="Enemy Group Entry", schema=[LittleEndianIntegerTableEntry.create("Amount", 1), LittleEndianIntegerTableEntry.create("Enemy", 2)] ) MapEnemyGroupHeaderTableEntry = RowTableEntry.from_schema( name="Map Enemy Group Header Table Entry", schema=[EbEventFlagTableEntry, type("Rate1", (LittleEndianIntegerTableEntry,), {"name": "Sub-Group 1 Rate", "size": 1}), type("Rate2", (LittleEndianIntegerTableEntry,), {"name": "Sub-Group 2 Rate", "size": 1})] ) MapEnemySubGroupTableEntry = RowTableEntry.from_schema( name="Map Enemy Sub-Group Table Entry", schema=[type("Probability", (LittleEndianIntegerTableEntry,), {"name": "Probability", "size": 1}), type("EnemyGroup", (LittleEndianIntegerTableEntry,), {"name": "Enemy Group", "size": 2})] ) class MapEnemyGroupTableEntry(TableEntry): name = "Map Enemy Group Table Entry" @classmethod
from coilsnake.exceptions.common.exceptions import TableSchemaError, \ TableEntryError from coilsnake.model.common.table import LittleEndianIntegerTableEntry, \ RowTableEntry, TableEntry from coilsnake.model.eb.table import EbEventFlagTableEntry EnemyGroupTableEntry = RowTableEntry.from_schema( name="Enemy Group Entry", schema=[ LittleEndianIntegerTableEntry.create("Amount", 1), LittleEndianIntegerTableEntry.create("Enemy", 2) ]) MapEnemyGroupHeaderTableEntry = RowTableEntry.from_schema( name="Map Enemy Group Header Table Entry", schema=[ EbEventFlagTableEntry, type("Rate1", (LittleEndianIntegerTableEntry, ), { "name": "Sub-Group 1 Rate", "size": 1 }), type("Rate2", (LittleEndianIntegerTableEntry, ), { "name": "Sub-Group 2 Rate", "size": 1 }) ]) MapEnemySubGroupTableEntry = RowTableEntry.from_schema( name="Map Enemy Sub-Group Table Entry", schema=[ type("Probability", (LittleEndianIntegerTableEntry, ), {
TOWN_MAP_NAMES = ["Onett", "Twoson", "Threed", "Fourside", "Scaraba", "Summers"] TownMapEnum = enum_class_from_name_list(TOWN_MAP_NAMES) TOWN_MAP_ICON_NAMES = ["Nothing", "Hamburger Shop", "Bakery", "Hotel", "Restaurant", "Hospital", "Shop", "Dept Store", "Bus Stop", "South to Twoson", "North to Onett", "South to Threed", "West to Twoson", "East to Desert", "West to Desert", "East to Toto", "Hint", "Ness", "Small Ness", "North", "South", "West", "East"] TownMapIconEnum = enum_class_from_name_list(TOWN_MAP_ICON_NAMES) TownMapIconPlacementTableEntry = RowTableEntry.from_schema( name="Town Map Icon Placement Table Entry", schema=[type("TownMapIconX", (LittleEndianIntegerTableEntry,), {"name": "X", "size": 1}), type("TownMapIconY", (LittleEndianIntegerTableEntry,), {"name": "Y", "size": 1}), type("TownMapIconIcon", (EnumeratedLittleEndianIntegerTableEntry,), { "name": "Icon", "size": 1, "enumeration_class": TownMapIconEnum}), EbEventFlagTableEntry] ) class TownMapIconPlacementPointerTableEntry(EbPointerTableEntry): name = "Town Map Icon Pointer Placement Table Entry" size = 4 table_entry_class = TownMapIconPlacementTableEntry @classmethod def from_block(cls, block, offset): data_offset = from_snes_address(super(TownMapIconPlacementPointerTableEntry, cls).from_block(block, offset)) if not data_offset: return []
from functools import partial from coilsnake.model.common.table import LittleEndianIntegerTableEntry, RowTableEntry from coilsnake.model.eb.table import EbPointerTableEntry from coilsnake.util.eb.helper import is_in_bank SpritePlacementTableEntry = RowTableEntry.from_schema( name="SpritePlacementTableEntry", schema=[type("NpcId", (LittleEndianIntegerTableEntry,), {"name": "NPC ID", "size": 2}), type("Y", (LittleEndianIntegerTableEntry,), {"name": "Y", "size": 1}), type("X", (LittleEndianIntegerTableEntry,), {"name": "X", "size": 1})] ) class SpritePlacementPointerTableEntry(EbPointerTableEntry): name = "Sprite Placement Pointer Table Entry" size = 2 @classmethod def from_block(cls, block, offset): area_offset = super(SpritePlacementPointerTableEntry, cls).from_block(block, offset) if not area_offset: return [] area_offset |= 0x0F0000 # Format: AA AA [BB BB YY XX] # AA = # of entries. BB = TPT. YY = y pos. XX = x pos. sprite_placements = [] size = block.read_multi(area_offset, 2) for i in range(area_offset + 2, area_offset + 2 + (4 * size), 4):
"South to Threed", "West to Twoson", "East to Desert", "West to Desert", "East to Toto", "Hint", "Ness", "Small Ness", "North", "South", "West", "East" ] TownMapIconEnum = enum_class_from_name_list(TOWN_MAP_ICON_NAMES) TownMapIconPlacementTableEntry = RowTableEntry.from_schema( name="Town Map Icon Placement Table Entry", schema=[ type("TownMapIconX", (LittleEndianIntegerTableEntry, ), { "name": "X", "size": 1 }), type("TownMapIconY", (LittleEndianIntegerTableEntry, ), { "name": "Y", "size": 1 }), type("TownMapIconIcon", (EnumeratedLittleEndianIntegerTableEntry, ), { "name": "Icon", "size": 1, "enumeration_class": TownMapIconEnum }), EbEventFlagTableEntry ]) class TownMapIconPlacementPointerTableEntry(EbPointerTableEntry): name = "Town Map Icon Pointer Placement Table Entry" size = 4 table_entry_class = TownMapIconPlacementTableEntry
from coilsnake.model.common.table import TableEntry, LittleEndianIntegerTableEntry, RowTableEntry from coilsnake.model.eb.table import EbEventFlagTableEntry MapMusicSubTableEntry = RowTableEntry.from_schema( name="Map Music Sub Table Entry", schema=[EbEventFlagTableEntry, type("Music", (LittleEndianIntegerTableEntry,), {"name": "Music", "size": 2})] ) class MapMusicTableEntry(TableEntry): name = "Map Music Table Entry" @classmethod def from_block(cls, block, offset): subentries = [] while True: subentry = MapMusicSubTableEntry.from_block(block, offset) subentries.append(subentry) offset += MapMusicSubTableEntry.size if subentry[0] == 0: break return subentries @classmethod def to_block_size(cls, value): return MapMusicSubTableEntry.size * len(value) @classmethod def to_block(cls, block, offset, value):
from functools import partial from coilsnake.model.common.table import RowTableEntry, LittleEndianIntegerTableEntry from coilsnake.model.eb.table import EbPointerTableEntry, EbEventFlagTableEntry from coilsnake.util.eb.helper import is_in_bank MapEventSubTableEntry = RowTableEntry.from_schema( name="Map Event Sub Table Entry", schema=[type("Before", (LittleEndianIntegerTableEntry,), {"name": "Before", "size": 2}), type("After", (LittleEndianIntegerTableEntry,), {"name": "After", "size": 2})] ) class MapEventPointerTableEntry(EbPointerTableEntry): name = "Map Event Pointer Table Entry" size = 2 @classmethod def from_block(cls, block, offset): data_offset = super(MapEventPointerTableEntry, cls).from_block(block, offset) data_offset |= (cls.bank << 16) value = [] while block.read_multi(data_offset, 2) != 0: flag = EbEventFlagTableEntry.from_block(block, data_offset) data_offset += EbEventFlagTableEntry.size num_sub_entries = block.read_multi(data_offset, 2) data_offset += 2 sub_entries = [MapEventSubTableEntry.from_block(block, x)
["None", "Onett", "Twoson", "Threed", "Fourside", "Scaraba", "Summers"] ) TOWNMAP_ARROW_ENTRY = EnumeratedLittleEndianIntegerTableEntry.create( "Town Map Arrow", 1, ["None", "Up", "Down", "Right", "Left"] ) TOWNMAP_X = LittleEndianIntegerTableEntry.create("Town Map X", 1) TOWNMAP_Y = LittleEndianIntegerTableEntry.create("Town Map Y", 1) SectorYmlTable = RowTableEntry.from_schema( name="Aggregate Sector Properties Table Entry", schema=[LittleEndianIntegerTableEntry.create("Tileset", 1), LittleEndianIntegerTableEntry.create("Palette", 1), LittleEndianIntegerTableEntry.create("Music", 1), TELEPORT_ENTRY, TOWNMAP_ENTRY, SETTING_ENTRY, LittleEndianIntegerTableEntry.create("Item", 1), TOWNMAP_ARROW_ENTRY, TOWNMAP_IMAGE_ENTRY, TOWNMAP_X, TOWNMAP_Y] ) class MapModule(EbModule): NAME = "Map" def __init__(self): super(MapModule, self).__init__() self.tiles = [] self.sector_tilesets_palettes_table = eb_table_from_offset(offset=SECTOR_TILESETS_PALETTES_TABLE_OFFSET,
SPRITE_SIZES = ["16x16", "16x16 2", "24x16", "32x16", "48x16", "16x24", "24x24", "16x32", "32x32", "48x32", "24x40", "16x48", "32x48", "48x48", "64x48", "64x64", "64x80"] SpriteGroupSizeTableEntry = EnumeratedLittleEndianIntegerTableEntry.create("Size", 1, SPRITE_SIZES) SpriteGroupCollisionNSWidthEntry = LittleEndianIntegerTableEntry.create("North/South Collision Width", 1) SpriteGroupCollisionNSHeightEntry = LittleEndianIntegerTableEntry.create("North/South Collision Height", 1) SpriteGroupCollisionEWWidthEntry = LittleEndianIntegerTableEntry.create("East/West Collision Width", 1) SpriteGroupCollisionEWHeightEntry = LittleEndianIntegerTableEntry.create("East/West Collision Height", 1) SpriteGroupHeaderTableEntry = RowTableEntry.from_schema( name="Sprite Group Header Table Entry", schema=[LittleEndianIntegerTableEntry.create("Height", 1), LittleEndianIntegerTableEntry.create("Width", 1), SpriteGroupSizeTableEntry, LittleEndianIntegerTableEntry.create("Palette", 1), SpriteGroupCollisionNSWidthEntry, SpriteGroupCollisionNSHeightEntry, SpriteGroupCollisionEWWidthEntry, SpriteGroupCollisionEWHeightEntry, LittleEndianIntegerTableEntry.create("Bank", 1)]) class SpriteGroup(object): # The order in which sprite directions are compiled to form a sprite group, based on examining the game data. # The order is: S, N, W, E, NW, SW, SE, NE SPRITE_COMPILATION_ORDER = [2, 4, 1, 3, 8, 7, 6, 5] def __init__(self, num_sprites): self.width = 0 self.height = 0