open import "prelude.ml" open import "data/array.ml" open import "./pretty.ml" open import "./dolphin.ml" type item = | DekuStick | DekuNut | Bomb | FairyBow | FireArrow | DinsFire | FairySlingshot | FairyOcarina | OcarinaOfTime | Bombchu_10 | Hookshot | Longshot | IceArrow | FaroresWind | Boomerang | LensOfTruth | MagicBean | MegatonHammer | LightArrow | NayrusLove | EmptyBottle | RedPotionBottle | GreenPotionBottle | BluePotionBottle | FairyBottle | FishBottle | FullMilkBottle | RutosLetterBottle | BlueFireBottle | BugBottle | BigPoeBottle | HalfMilkBottle | PoeBottle | WeirdEgg | Chicken | ZeldasLetter | KeatonMask | SkullMask | SpookyMask | BunnyHood | GoronMask | ZoraMask | GerudoMask | MaskOfTruth | SoldOut | PocketEgg | PocketCucco | Cojiro | OddMushroom | OddPotion | PoachersSaw | BrokenGoronsSword | Prescription | EyeballFrog | EyeDrops | ClaimCheck | FairyBowAndFireArrow | FairyBowAndIceArrow | FairyBowAndLightArrow | KokiriSword | MasterSword | GiantsKnifeAndBiggoronsSword | DekuShield | HylianShield | MirrorShield | KokiriTunic | GoronTunic | ZoraTunic | KokiriBoots | IronBoots | HoverBoots | BulletBag_30 | BulletBag_40 | BulletBag_50 | Quiver_30 | BigQuiver_40 | BiggestQuiver_50 | BombBag_20 | BigBombBag_30 | BiggestBombBag_40 | GoronsBracelet | SilverGauntlets | GoldenGauntlets | SilverScale | GoldenScale | BrokenGiantsKnife | AdultsWallet | GiantsWallet | DekuSeeds_5 | FishingPole | MinuetOfForest | BoleroOfFire | SerenadeOfWater | RequiemOfSpirit | NocturneOfShadow | PreludeOfLight | ZeldasLullaby | EponasSong | SariasSong | SunsSong | SongOfTime | SongOfStorms | ForestMedallion | FireMedallion | WaterMedallion | SpiritMedallion | ShadowMedallion | LightMedallion | KokirisEmerald | GoronsRuby | ZorasSapphire | StoneOfAgony | GerudosCard | GoldSkulltulaToken | HeartContainer | PieceOfHeart_ | BossKey | Compass | DungeonMap | SmallKey | SmallMagicJar | LargeMagicJar | PieceOfHeart | LonLonMilk | RecoveryHeart | GreenRupee | BlueRupee | RedRupee | PurpleRupee | HugeRupee | DekuSticks_5 | DekuSticks_10 | DekuNuts_5 | DekuNuts_10 | Bombs_5 | Bombs_10 | Bombs_20 | Bombs_30 | Arrows_5_10 | Arrows_10_30 | Arrows_30_50 | DekuSeeds_30 | Bombchu_5 | Bombchu_20 | DekuStickCapacity_20 | DekuStickCapacity_30 | DekuNutCapacity_30 | DekuNutCapacity_40 | UnknownItem of u8 | NoItem instance decode item begin let decode addr x = let (U8 id) = decode addr x match id with | 0xFF -> NoItem end instance show item begin let show = function | NoItem -> "No Item" end type sword = | NoSword | KokiriSword | MasterSword | BiggoronsSword | UnknownSword of int instance show sword begin let show = function | NoSword -> "No Sword" | KokiriSword -> "Kokiri Sword" | MasterSword -> "Master Sword" | BiggoronsSword -> "Biggoron's Sword" | UnknownSword x -> "Unknown Sword " ^ (show x) end type shield = | NoShield | DekuShield | HylianShield | MirrorShield | UnknownShield of int instance show shield begin let show = function | NoShield -> "No Shield" | DekuShield -> "Deku Shield" | HylianShield -> "Hylian Shield" | MirrorShield -> "Mirror Shield" | UnknownShield x -> "Unknown Shield " ^ (show x) end type tunic = | KokiriTunic | GoronTunic | ZoraTunic | UnknownTunic of int instance show tunic begin let show = function | KokiriTunic -> "Kokiri Tunic" | GoronTunic -> "Goron Tunic" | ZoraTunic -> "Zora Tunic" | UnknownTunic x -> "Unknown Tunic " ^ (show x) end type boots = | KokiriBoots | IronBoots | HoverBoots | UnknownBoots of int instance show boots begin let show = function | KokiriBoots -> "Kokiri Boots" | IronBoots -> "Iron Boots" | HoverBoots -> "Hover Boots" | UnknownBoots x -> "Unknown Boots " ^ (show x) end type equipment = Equipment of { swordv: sword, shieldv: shield, tunicv: tunic, bootsv: boots } external private val ( %% ) : int -> int -> int = "function(a, b) return a % b end" instance decode equipment begin let decode addr x = let (U16 fields) = decode addr x let swords = fields %% (0x000F + 1) let shields = (fields // 8) %% (0x00F + 1) let tunics = (fields // 16) %% (0x0F + 1) let boots = (fields // 24) %% (0xF + 1) let fsword = match swords with | 0 -> NoSword | 1 -> KokiriSword | 2 -> MasterSword | 3 -> BiggoronsSword | x -> UnknownSword x let fshield = match shields with | 0 -> NoShield | 1 -> DekuShield | 2 -> HylianShield | 3 -> MirrorShield | x -> UnknownShield x let ftunic = match tunics with | 1 -> KokiriTunic | 2 -> GoronTunic | 3 -> ZoraTunic | x -> UnknownTunic x let fboot = match boots with | 1 -> KokiriBoots | 2 -> IronBoots | 3 -> HoverBoots | x -> UnknownBoots x Equipment { swordv = fsword, shieldv = fshield, tunicv = ftunic, bootsv = fboot } end instance prettyrecord equipment begin let name _ = "Equipment" let fields (Equipment x) = [] end type item_equips = ItemEquips of { button_item_b: u8, button_item_c_left: u8, button_item_c_down: u8, button_item_c_right: u8, button_slot_c_left: u8, button_slot_c_down: u8, button_slot_c_right: u8, equips: equipment } instance decode item_equips begin let decode addr x = ItemEquips { button_item_b = decode (addr + 0x00) x, button_item_c_left = decode (addr + 0x01) x, button_item_c_down = decode (addr + 0x02) x, button_item_c_right = decode (addr + 0x03) x, button_slot_c_left = decode (addr + 0x04) x, button_slot_c_down = decode (addr + 0x05) x, button_slot_c_right = decode (addr + 0x06) x, equips = decode (addr + 0x08) x } end instance prettyrecord item_equips begin let name _ = "ItemEquips" let fields (ItemEquips x) = [ ("button_item_b", S x.button_item_b), ("button_item_c_left", S x.button_item_c_left), ("button_item_c_down", S x.button_item_c_down), ("button_item_c_right", S x.button_item_c_right), ("button_slot_c_left", S x.button_slot_c_left), ("button_slot_c_down", S x.button_slot_c_down), ("button_slot_c_right", S x.button_slot_c_right), ("equips", P x.equips) ] end type inventory = Inventory of { items: array u8, ammo: array s8, equipment: u16, upgrades: u32, quest_items: u32, dungeon_items: array u8, dungeon_keys: array s8, defense_hearts: s8, gs_tokens: s16 } instance decode inventory begin let decode addr x = Inventory { items = init 24 (fun i -> decode (addr + 0x00 + i) x), ammo = init 16 (fun i -> decode (addr + 0x18 + i) x), equipment = decode (addr + 0x28) x, upgrades = decode (addr + 0x2C) x, quest_items = decode (addr + 0x30) x, dungeon_items = init 20 (fun i -> decode (addr + 0x34 + i) x), dungeon_keys = init 19 (fun i -> decode (addr + 0x48 + i) x), defense_hearts = decode (addr + 0x5B) x, gs_tokens = decode (addr + 0x5C) x } end instance prettyrecord inventory begin let name _ = "Inventory" let fields (Inventory x) = [ ("items", S x.items), ("ammo", S x.ammo), ("equipment", S x.equipment), ("upgrades", S x.upgrades), ("quest_items", S x.quest_items), ("dungeon_items", S x.dungeon_items), ("dungeon_keys", S x.dungeon_keys), ("defense_hearts", S x.defense_hearts), ("gs_tokens", S x.gs_tokens) ] end type save_context = SaveContext of { entrance_index: s32, link_age: s32, cutscene_index: s32, day_time: u16, night_flag: s32, num_days: s32, claim_days: s32, (* char newf[6], *) deaths: s16, (* char playerName[8], *) n64dd_flag: s16, health_capacity: s16, health: s16, magic_level: s8, magic: s8, rupees: s16, sword_health: u16, navi_timer: u16, magic_acquired: u8, (* char unk_3B[0x01], *) double_magic: u8, double_defense: u8, bgs_flag: u8, ocarina_game_reward: u8, child_equips: item_equips, adult_equips: item_equips, (* u32 unk_54, *) (* char unk_58[0x0E], *) saved_scene_num: s16, equips: item_equips, inventory: inventory } instance decode save_context begin let decode addr x = SaveContext { entrance_index = decode (addr + 0x0000) x, link_age = decode (addr + 0x0004) x, cutscene_index = decode (addr + 0x0008) x, day_time = decode (addr + 0x000C) x, night_flag = decode (addr + 0x0010) x, num_days = decode (addr + 0x0014) x, claim_days = decode (addr + 0x0018) x, (* newf, *) deaths = decode (addr + 0x0022) x, n64dd_flag = decode (addr + 0x002C) x, health_capacity = decode (addr + 0x002E) x, health = decode (addr + 0x0030) x, magic_level = decode (addr + 0x0032) x, magic = decode (addr + 0x0033) x, rupees = decode (addr + 0x0034) x, sword_health = decode (addr + 0x0036) x, navi_timer = decode (addr + 0x0038) x, magic_acquired = decode (addr + 0x003A) x, double_magic = decode (addr + 0x003C) x, double_defense = decode (addr + 0x003D) x, bgs_flag = decode (addr + 0x003E) x, ocarina_game_reward = decode (addr + 0x003F) x, child_equips = decode (addr + 0x0040) x, adult_equips = decode (addr + 0x004A) x, saved_scene_num = decode (addr + 0x0066) x, equips = decode (addr + 0x0068) x, inventory = decode (addr + 0x0074) x } end instance prettyrecord save_context begin let name _ = "SaveContext" let fields (SaveContext x) = [ ("entrance_index", S x.entrance_index), ("link_age", S x.link_age), ("cutscene_index", S x.cutscene_index), ("day_time", S x.day_time), ("night_flag", S x.night_flag), ("num_days", S x.num_days), ("claim_days", S x.claim_days), ("deaths", S x.deaths), ("n64dd_flag", S x.n64dd_flag), ("health_capacity", S x.health_capacity), ("health", S x.health), ("magic_level", S x.magic_level), ("magic", S x.magic), ("rupees", S x.rupees), ("sword_health", S x.sword_health), ("navi_timer", S x.navi_timer), ("magic_acquired", S x.magic_acquired), ("double_magic", S x.double_magic), ("double_defense", S x.double_defense), ("bgs_flag", S x.bgs_flag), ("ocarina_game_reward", S x.ocarina_game_reward), ("child_equips", P x.child_equips), ("adult_equips", P x.adult_equips), ("saved_scene_num", S x.saved_scene_num), ("equips", P x.equips), ("inventory", P x.inventory) ] end