466 lines
10 KiB
OCaml
466 lines
10 KiB
OCaml
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
|