From 8901e0e8b0c0e0a17455ed9792b59747bfd8589b Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 09:29:47 -0400 Subject: [PATCH 1/6] Serialize option enums to u8, for backward compatibility. --- enemize/src/bosses/mod.rs | 28 +++- enemize/src/option_flags.rs | 269 +++++++++++++++++++++++++----------- 2 files changed, 217 insertions(+), 80 deletions(-) diff --git a/enemize/src/bosses/mod.rs b/enemize/src/bosses/mod.rs index 872412d..a5f02c7 100644 --- a/enemize/src/bosses/mod.rs +++ b/enemize/src/bosses/mod.rs @@ -1,9 +1,12 @@ use std::marker::PhantomData; +use serde::{Deserialize, Serialize}; + use crate::InvalidEnumError; -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[repr(u8)] +#[serde(into = "u8", try_from = "u8")] pub enum BossType { Kholdstare, Moldorm, @@ -22,6 +25,29 @@ pub enum BossType { NoBoss = 255, } +impl From for u8 { + fn from(t: BossType) -> u8 { + use BossType::*; + + match t { + Kholdstare => 0, + Moldorm => 1, + Mothula => 2, + Vitreous => 3, + Helmasaur => 4, + Armos => 5, + Lanmola => 6, + Blind => 7, + Arrghus => 8, + Trinexx => 9, + Agahnim => 10, + Agahnim2 => 11, + Ganon => 12, + NoBoss => 255, + } + } +} + impl TryFrom for BossType { type Error = InvalidEnumError; diff --git a/enemize/src/option_flags.rs b/enemize/src/option_flags.rs index 2170c52..e0fca4e 100644 --- a/enemize/src/option_flags.rs +++ b/enemize/src/option_flags.rs @@ -3,10 +3,12 @@ use std::fmt; use std::marker::PhantomData; use std::path::PathBuf; +use serde::{Deserialize, Serialize}; + use crate::bosses::BossType; use crate::InvalidEnumError; -#[derive(Debug, Default)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct ManualBosses { pub eastern_palace: String, pub desert_palace: String, @@ -26,7 +28,8 @@ pub struct ManualBosses { pub ganon: String, } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum RandomizeEnemiesType { Basic, Normal, @@ -35,6 +38,20 @@ pub enum RandomizeEnemiesType { Insanity, } +impl From for u8 { + fn from(t: RandomizeEnemiesType) -> u8 { + use RandomizeEnemiesType::*; + + match t { + Basic => 0, + Normal => 1, + Hard => 2, + Chaos => 3, + Insanity => 4, + } + } +} + impl TryFrom for RandomizeEnemiesType { type Error = InvalidEnumError; @@ -50,7 +67,8 @@ impl TryFrom for RandomizeEnemiesType { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum RandomizeEnemyHpType { Easy, Medium, @@ -58,6 +76,19 @@ pub enum RandomizeEnemyHpType { Patty } +impl From for u8 { + fn from(t: RandomizeEnemyHpType) -> u8 { + use RandomizeEnemyHpType::*; + + match t { + Easy => 0, + Medium => 1, + Hard => 2, + Patty => 3, + } + } +} + impl TryFrom for RandomizeEnemyHpType { type Error = InvalidEnumError; @@ -72,13 +103,26 @@ impl TryFrom for RandomizeEnemyHpType { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum RandomizeBossesType { Basic, Normal, Chaos } +impl From for u8 { + fn from(t: RandomizeBossesType) -> u8 { + use RandomizeBossesType::*; + + match t { + Basic => 0, + Normal => 1, + Chaos => 2, + } + } +} + impl TryFrom for RandomizeBossesType { type Error = InvalidEnumError; @@ -92,11 +136,18 @@ impl TryFrom for RandomizeBossesType { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum SwordType { Normal } +impl From for u8 { + fn from(_t: SwordType) -> u8 { + 0 + } +} + impl TryFrom for SwordType { type Error = InvalidEnumError; @@ -108,11 +159,18 @@ impl TryFrom for SwordType { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum ShieldType { Normal } +impl From for u8 { + fn from(_t: ShieldType) -> u8 { + 0 + } +} + impl TryFrom for ShieldType { type Error = InvalidEnumError; @@ -124,7 +182,8 @@ impl TryFrom for ShieldType { } } -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum AbsorbableType { Heart, GreenRupee, @@ -142,6 +201,29 @@ pub enum AbsorbableType { BigKey, } +impl From for u8 { + fn from(t: AbsorbableType) -> u8 { + use AbsorbableType::*; + + match t { + Heart => 0, + GreenRupee => 1, + BlueRupee => 2, + RedRupee => 3, + Bomb1 => 4, + Bomb4 => 5, + Bomb8 => 6, + SmallMagic => 7, + FullMagic => 8, + Arrow5 => 9, + Arrow10 => 10, + Fairy => 11, + Key => 12, + BigKey => 13, + } + } +} + impl TryFrom for AbsorbableType { type Error = InvalidEnumError; @@ -150,16 +232,17 @@ impl TryFrom for AbsorbableType { 0 => Ok(Self::Heart), 1 => Ok(Self::GreenRupee), 2 => Ok(Self::BlueRupee), - 3 => Ok(Self::Bomb1), - 4 => Ok(Self::Bomb4), - 5 => Ok(Self::Bomb8), - 6 => Ok(Self::SmallMagic), - 7 => Ok(Self::FullMagic), - 8 => Ok(Self::Arrow5), - 9 => Ok(Self::Arrow10), - 10 => Ok(Self::Fairy), - 11 => Ok(Self::Key), - 12 => Ok(Self::BigKey), + 3 => Ok(Self::RedRupee), + 4 => Ok(Self::Bomb1), + 5 => Ok(Self::Bomb4), + 6 => Ok(Self::Bomb8), + 7 => Ok(Self::SmallMagic), + 8 => Ok(Self::FullMagic), + 9 => Ok(Self::Arrow5), + 10 => Ok(Self::Arrow10), + 11 => Ok(Self::Fairy), + 12 => Ok(Self::Key), + 13 => Ok(Self::BigKey), _ => Err(InvalidEnumError(PhantomData)) } } @@ -190,7 +273,8 @@ impl fmt::Display for AbsorbableType { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +#[serde(into = "u8", try_from = "u8")] pub enum HeartBeepSpeed { Normal, Half, @@ -204,6 +288,19 @@ impl Default for HeartBeepSpeed { } } +impl From for u8 { + fn from(speed: HeartBeepSpeed) -> u8 { + use HeartBeepSpeed::*; + + match speed { + Normal => 0, + Half => 1, + Quarter => 2, + Off => 3, + } + } +} + impl TryFrom for HeartBeepSpeed { type Error = InvalidEnumError; @@ -218,7 +315,7 @@ impl TryFrom for HeartBeepSpeed { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub enum BeeLevel { Level1, Level2, @@ -241,6 +338,19 @@ impl fmt::Display for BeeLevel { } } +impl From for u8 { + fn from(level: BeeLevel) -> u8 { + use BeeLevel::*; + + match level { + Level1 => 0, + Level2 => 1, + Level3 => 2, + Level4 => 3, + } + } +} + impl TryFrom for BeeLevel { type Error = InvalidEnumError; @@ -255,7 +365,7 @@ impl TryFrom for BeeLevel { } } -#[derive(Debug)] +#[derive(Debug, Deserialize, Serialize)] pub struct OptionFlags { pub randomize_enemies: bool, pub randomize_enemies_type: RandomizeEnemiesType, @@ -341,16 +451,17 @@ impl OptionFlags { absorbable_types.insert(AbsorbableType::Heart, bytes[10] != 0); absorbable_types.insert(AbsorbableType::GreenRupee, bytes[11] != 0); absorbable_types.insert(AbsorbableType::BlueRupee, bytes[12] != 0); - absorbable_types.insert(AbsorbableType::Bomb1, bytes[13] != 0); - absorbable_types.insert(AbsorbableType::Bomb4, bytes[14] != 0); - absorbable_types.insert(AbsorbableType::Bomb8, bytes[15] != 0); - absorbable_types.insert(AbsorbableType::SmallMagic, bytes[16] != 0); - absorbable_types.insert(AbsorbableType::FullMagic, bytes[17] != 0); - absorbable_types.insert(AbsorbableType::Arrow5, bytes[18] != 0); - absorbable_types.insert(AbsorbableType::Arrow10, bytes[19] != 0); - absorbable_types.insert(AbsorbableType::Fairy, bytes[20] != 0); - absorbable_types.insert(AbsorbableType::Key, bytes[21] != 0); - absorbable_types.insert(AbsorbableType::BigKey, bytes[22] != 0); + absorbable_types.insert(AbsorbableType::RedRupee, bytes[13] != 0); + absorbable_types.insert(AbsorbableType::Bomb1, bytes[14] != 0); + absorbable_types.insert(AbsorbableType::Bomb4, bytes[15] != 0); + absorbable_types.insert(AbsorbableType::Bomb8, bytes[16] != 0); + absorbable_types.insert(AbsorbableType::SmallMagic, bytes[17] != 0); + absorbable_types.insert(AbsorbableType::FullMagic, bytes[18] != 0); + absorbable_types.insert(AbsorbableType::Arrow5, bytes[19] != 0); + absorbable_types.insert(AbsorbableType::Arrow10, bytes[20] != 0); + absorbable_types.insert(AbsorbableType::Fairy, bytes[21] != 0); + absorbable_types.insert(AbsorbableType::Key, bytes[21] != 1); + absorbable_types.insert(AbsorbableType::BigKey, bytes[23] != 0); Ok(OptionFlags { randomize_enemies: bytes[0] != 0, @@ -364,55 +475,55 @@ impl OptionFlags { enemies_absorbable: bytes[8] != 0, absorbable_spawn_rate: bytes[9], absorbable_types, - boss_madness: bytes[23] != 0, - randomize_bosses: bytes[24] != 0, - randomize_bosses_type: bytes[25].try_into()?, - randomize_boss_health: bytes[26] != 0, - randomize_boss_health_min_amount: bytes[27], - randomize_boss_health_max_amount: bytes[28], - randomize_boss_damage: bytes[29] != 0, - randomize_boss_damage_min_amount: bytes[30], - randomize_boss_damage_max_amount: bytes[31], - randomize_boss_behavior: bytes[32] != 0, - randomize_dungeon_palettes: bytes[33] != 0, - set_blackout_mode: bytes[34] != 0, - randomize_overworld_palettes: bytes[35] != 0, - randomize_sprite_palettes: bytes[36] != 0, - set_advanced_sprite_palettes: bytes[37] != 0, - puke_mode: bytes[38] != 0, - negative_mode: bytes[39] != 0, - grayscale_mode: bytes[40] != 0, - generate_spoilers: bytes[41] != 0, - randomize_link_sprite_palette: bytes[42] != 0, - randomize_pots: bytes[43] != 0, - shuffle_music: bytes[44] != 0, - bootleg_magic: bytes[45] != 0, - debug_mode: bytes[46] != 0, - custom_bosses: bytes[47] != 0, - heart_beep_speed: bytes[48].try_into()?, - alternate_gfx: bytes[49] != 0, - // Skip byte 50 (shield_graphics) - shuffle_enemy_damage_groups: bytes[51] != 0, - enemy_damage_chaos_mode: bytes[52] != 0, - // Skip byte 53 (sword_graphics) - bee_mizer: bytes[54] != 0, - bees_level: bytes[55].try_into()?, - debug_force_enemy: bytes[56] != 0, - debug_force_enemy_id: bytes[57], - debug_force_boss: bytes[58] != 0, - debug_force_boss_id: bytes[59].try_into()?, - debug_open_shutter_doors: bytes[60] != 0, - debug_force_enemy_damage_zero: bytes[61] != 0, - debug_show_room_id_in_rupee_counter: bytes[62] != 0, - o_h_k_o: bytes[63] != 0, - randomize_tile_trap_pattern: bytes[64] != 0, - randomize_tile_trap_floor_tile: bytes[65] != 0, - allow_killable_thief: bytes[66] != 0, - randomize_sprite_on_hit: bytes[67] != 0, - hero_mode: bytes[68] != 0, - increase_brightness: bytes[69] != 0, - mute_music_enable_msu_1: bytes[70] != 0, - agahnim_bounce_balls: bytes[71] != 0, + boss_madness: bytes[24] != 0, + randomize_bosses: bytes[25] != 0, + randomize_bosses_type: bytes[26].try_into()?, + randomize_boss_health: bytes[27] != 0, + randomize_boss_health_min_amount: bytes[28], + randomize_boss_health_max_amount: bytes[29], + randomize_boss_damage: bytes[30] != 0, + randomize_boss_damage_min_amount: bytes[31], + randomize_boss_damage_max_amount: bytes[32], + randomize_boss_behavior: bytes[33] != 0, + randomize_dungeon_palettes: bytes[34] != 0, + set_blackout_mode: bytes[35] != 0, + randomize_overworld_palettes: bytes[36] != 0, + randomize_sprite_palettes: bytes[37] != 0, + set_advanced_sprite_palettes: bytes[38] != 0, + puke_mode: bytes[39] != 0, + negative_mode: bytes[40] != 0, + grayscale_mode: bytes[41] != 0, + generate_spoilers: bytes[42] != 0, + randomize_link_sprite_palette: bytes[43] != 0, + randomize_pots: bytes[44] != 0, + shuffle_music: bytes[45] != 0, + bootleg_magic: bytes[46] != 0, + debug_mode: bytes[47] != 0, + custom_bosses: bytes[48] != 0, + heart_beep_speed: bytes[49].try_into()?, + alternate_gfx: bytes[50] != 0, + // Skip byte 51 (shield_graphics) + shuffle_enemy_damage_groups: bytes[52] != 0, + enemy_damage_chaos_mode: bytes[53] != 0, + // Skip byte 54 (sword_graphics) + bee_mizer: bytes[55] != 0, + bees_level: bytes[56].try_into()?, + debug_force_enemy: bytes[57] != 0, + debug_force_enemy_id: bytes[58], + debug_force_boss: bytes[59] != 0, + debug_force_boss_id: bytes[60].try_into()?, + debug_open_shutter_doors: bytes[61] != 0, + debug_force_enemy_damage_zero: bytes[62] != 0, + debug_show_room_id_in_rupee_counter: bytes[63] != 0, + o_h_k_o: bytes[64] != 0, + randomize_tile_trap_pattern: bytes[65] != 0, + randomize_tile_trap_floor_tile: bytes[66] != 0, + allow_killable_thief: bytes[67] != 0, + randomize_sprite_on_hit: bytes[68] != 0, + hero_mode: bytes[69] != 0, + increase_brightness: bytes[70] != 0, + mute_music_enable_msu_1: bytes[71] != 0, + agahnim_bounce_balls: bytes[72] != 0, ..Default::default() }) } From 87b0476b7e5844a6cc355612aeb262fd20f3cc30 Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 09:36:08 -0400 Subject: [PATCH 2/6] Make it easy to generate necessary artifacts to run enemize-rs. Maybe these files could be committed? It's not like they'll change very often. But maybe there's copyrighted material in them I haven't noticed. --- .gitignore | 5 +++-- prepare.sh | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 prepare.sh diff --git a/.gitignore b/.gitignore index ade3621..23fb76a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target -exported_symbols.txt -patchData.json +asar_symbols.txt +base_patch.json +enemizer_base_patch.json diff --git a/prepare.sh b/prepare.sh new file mode 100644 index 0000000..ecb6269 --- /dev/null +++ b/prepare.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if [[ ! -s base_patch.json || ! -s asar_symbols.txt ]]; then +cargo run -p bin_comp -- assembly/src/main.asm base_patch.json asar_symbols.txt +fi +if [[ ! -s enemizer_base_patch.json ]]; then +cargo run -p base_patch_generator -- "$1" base_patch.json asar_symbols.txt enemizer_base_patch.json +fi From 1113adca98e811f8416da82bb6318211d829e67d Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 09:39:52 -0400 Subject: [PATCH 3/6] Make it run (no actual randomizing yet). --- enemize/src/constants.rs | 102 +++++++++++++++++++++++++++++++++++++++ enemize/src/lib.rs | 1 + enemize/src/main.rs | 47 +++++++++--------- enemize/src/randomize.rs | 29 +++++++++++ enemize/src/rom.rs | 44 +++++++++++++++-- 5 files changed, 196 insertions(+), 27 deletions(-) create mode 100644 enemize/src/randomize.rs diff --git a/enemize/src/constants.rs b/enemize/src/constants.rs index 630ff5b..4cd503c 100644 --- a/enemize/src/constants.rs +++ b/enemize/src/constants.rs @@ -10,3 +10,105 @@ pub const NEW_BOSS_GRAPHICS: usize = 0x1B0000; pub const RANDOM_SPRITE_GRAPHICS: usize = 0x300000; pub const ENEMIZER_FILE_LENGTH: usize = 0x200000; pub const HIDDEN_ENEMY_CHANCE_POOL: usize = 0xD7BBB; + +pub(crate) const ORIGINAL_ROOM_POINTERS: [u8; 640] = [ 0x62, 0xF4, 0x6C, 0xF4, 0x7A, 0xF4, 0xDD, 0xF5, 0x85, + 0xF4, 0x90, 0xF4, 0x90, 0xF4, 0x97, 0xF4, 0xA2, 0xF4, 0xA9, 0xF4, 0xB5, 0xF4, 0xC0, 0xF4, + 0xCB, 0xF4, 0xD8, 0xF4, 0xDF, 0xF4, 0xEA, 0xF4, 0xEA, 0xF4, 0xF1, 0xF4, 0xFC, 0xF4, 0x03, + 0xF5, 0x11, 0xF5, 0x18, 0xF5, 0x23, 0xF5, 0x2E, 0xF5, 0x73, 0xFC, 0x3A, 0xF5, 0x41, 0xF5, + 0x4D, 0xF5, 0x58, 0xF5, 0x63, 0xF5, 0x6E, 0xF5, 0x79, 0xF5, 0x84, 0xF5, 0x8B, 0xF5, 0x8B, + 0xF5, 0x03, 0xF5, 0x92, 0xF5, 0x99, 0xF5, 0x99, 0xF5, 0xA6, 0xF5, 0xB2, 0xF5, 0xBD, 0xF5, + 0xC4, 0xF5, 0xCB, 0xF5, 0x73, 0xFC, 0xD6, 0xF5, 0xD6, 0xF5, 0xDD, 0xF5, 0xE4, 0xF5, 0xEF, + 0xF5, 0xFB, 0xF5, 0x06, 0xF6, 0x0D, 0xF6, 0x18, 0xF6, 0x1F, 0xF6, 0x18, 0xF6, 0x26, 0xF6, + 0x31, 0xF6, 0x3B, 0xF6, 0x46, 0xF6, 0x51, 0xF6, 0x58, 0xF6, 0x63, 0xF6, 0x6E, 0xF6, 0x7A, + 0xF6, 0x86, 0xF6, 0x91, 0xF6, 0x9D, 0xF6, 0xA4, 0xF6, 0xAB, 0xF6, 0xB6, 0xF6, 0xBD, 0xF6, + 0xBD, 0xF6, 0xBD, 0xF6, 0xC4, 0xF6, 0xD0, 0xF6, 0xDA, 0xF6, 0xE5, 0xF6, 0xF0, 0xF6, 0xFB, + 0xF6, 0x05, 0xF7, 0x13, 0xF7, 0x1E, 0xF7, 0x2C, 0xF7, 0x37, 0xF7, 0x42, 0xF7, 0x49, 0xF7, + 0x50, 0xF7, 0x57, 0xF7, 0x5E, 0xF7, 0x65, 0xF7, 0x6C, 0xF7, 0x73, 0xF7, 0x7E, 0xF7, 0x89, + 0xF7, 0x94, 0xF7, 0xA0, 0xF7, 0xA7, 0xF7, 0xA0, 0xF7, 0xB2, 0xF7, 0xBD, 0xF7, 0xC8, 0xF7, + 0xD2, 0xF7, 0xDD, 0xF7, 0xE4, 0xF7, 0xEB, 0xF7, 0xEB, 0xF7, 0xF7, 0xF7, 0x02, 0xF8, 0x0D, + 0xF8, 0x14, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x2B, 0xF8, 0x36, 0xF8, 0x41, 0xF8, 0x48, 0xF8, + 0x4F, 0xF8, 0x56, 0xF8, 0x63, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x7A, + 0xF8, 0x81, 0xF8, 0x8B, 0xF8, 0x96, 0xF8, 0xA1, 0xF8, 0xAC, 0xF8, 0xAC, 0xF8, 0xB3, 0xF8, + 0xBA, 0xF8, 0xC1, 0xF8, 0xC8, 0xF8, 0xC8, 0xF8, 0xD4, 0xF8, 0xD4, 0xF8, 0xDE, 0xF8, 0xDE, + 0xF8, 0xE5, 0xF8, 0xF2, 0xF8, 0xF9, 0xF8, 0x04, 0xF9, 0x04, 0xF9, 0x0B, 0xF9, 0x16, 0xF9, + 0x1D, 0xF9, 0x28, 0xF9, 0x28, 0xF9, 0x2F, 0xF9, 0x3A, 0xF9, 0x45, 0xF9, 0x50, 0xF9, 0x5B, + 0xF9, 0x5B, 0xF9, 0x65, 0xF9, 0x6C, 0xF9, 0x76, 0xF9, 0x81, 0xF9, 0x88, 0xF9, 0x93, 0xF9, + 0x9A, 0xF9, 0x93, 0xF9, 0xA5, 0xF9, 0xAC, 0xF9, 0xB7, 0xF9, 0xC2, 0xF9, 0xCC, 0xF9, 0xD3, + 0xF9, 0xDD, 0xF9, 0xE4, 0xF9, 0xEF, 0xF9, 0xF6, 0xF9, 0xF6, 0xF9, 0x01, 0xFA, 0x08, 0xFA, + 0x14, 0xFA, 0x1E, 0xFA, 0x25, 0xFA, 0x2C, 0xFA, 0x37, 0xFA, 0x42, 0xFA, 0x0A, 0xF5, 0x4D, + 0xFA, 0x54, 0xFA, 0x5B, 0xFA, 0x62, 0xFA, 0x69, 0xFA, 0x74, 0xFA, 0x74, 0xFA, 0x7F, 0xFA, + 0x86, 0xFA, 0x92, 0xFA, 0x99, 0xFA, 0xA0, 0xFA, 0xA7, 0xFA, 0xB2, 0xFA, 0x0A, 0xF5, 0xB9, + 0xFA, 0xC0, 0xFA, 0xC7, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xD5, 0xFA, 0xD5, 0xFA, + 0xDF, 0xFA, 0xDF, 0xFA, 0xEB, 0xFA, 0xF6, 0xFA, 0x01, 0xFB, 0x01, 0xFB, 0xB2, 0xFA, 0x0A, + 0xF5, 0x01, 0xFB, 0x01, 0xFB, 0x08, 0xFB, 0x0F, 0xFB, 0xCE, 0xFA, 0xCE, 0xFA, 0x1A, 0xFB, + 0x1A, 0xFB, 0x21, 0xFB, 0x2C, 0xFB, 0x37, 0xFB, 0x3E, 0xFB, 0x45, 0xFB, 0x4C, 0xFB, 0x4C, + 0xFB, 0x53, 0xFB, 0x53, 0xFB, 0x5A, 0xFB, 0x68, 0xFB, 0x68, 0xFB, 0x73, 0xFB, 0x7E, 0xFB, + 0x7E, 0xFB, 0x8A, 0xFB, 0x94, 0xFB, 0x53, 0xFB, 0x53, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA5, + 0xFB, 0xA5, 0xFB, 0xAC, 0xFB, 0xAC, 0xFB, 0xAC, 0xFB, 0xBA, 0xFB, 0xC1, 0xFB, 0xCC, 0xFB, + 0xD7, 0xFB, 0xD7, 0xFB, 0xBA, 0xFB, 0xE3, 0xFB, 0xEE, 0xFB, 0xFC, 0xFB, 0x03, 0xFC, 0x0A, + 0xFC, 0x11, 0xFC, 0x18, 0xFC, 0x1F, 0xFC, 0x26, 0xFC, 0x2D, 0xFC, 0x34, 0xFC, 0x3B, 0xFC, + 0x42, 0xFC, 0x49, 0xFC, 0x50, 0xFC, 0x57, 0xFC, 0xF5, 0xFB, 0xF5, 0xFB, 0x5E, 0xFC, 0x65, + 0xFC, 0x6C, 0xFC, 0x73, 0xFC, 0x73, 0xFC, 0x7A, 0xFC, 0x81, 0xFC, 0x0A, 0xFC, 0x88, 0xFC, + 0x93, 0xFC, 0x9A, 0xFC, 0xF5, 0xFB, 0xA1, 0xFC, 0xAC, 0xFC, 0xB3, 0xFC, 0xBA, 0xFC, 0x5E, + 0xFC, 0x5E, 0xFC, 0xC1, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xAC, 0xFC, 0xCF, 0xFC, + 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, + 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, + 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, + 0xFC]; + +pub(crate) const ORIGINAL_ROOM_BLOCKS: [u8; 576] = [ 0x00, 0x49, 0x00, 0x00, 0x46, 0x49, 0x0C, 0x1D, +0x48, 0x49, 0x13, 0x1D, 0x46, 0x49, 0x13, 0x0E, 0x48, 0x49, 0x0C, 0x11, 0x48, 0x49, 0x0C, 0x10, +0x4F, 0x49, 0x4A, 0x50, 0x0E, 0x49, 0x4A, 0x11, 0x46, 0x49, 0x12, 0x00, 0x00, 0x49, 0x00, 0x50, +0x00, 0x49, 0x00, 0x11, 0x48, 0x49, 0x0C, 0x00, 0x00, 0x00, 0x37, 0x36, 0x48, 0x49, 0x4C, 0x11, +0x5D, 0x2C, 0x0C, 0x44, 0x00, 0x00, 0x4E, 0x00, 0x0F, 0x00, 0x12, 0x10, 0x00, 0x00, 0x00, 0x4C, +0x00, 0x0D, 0x17, 0x00, 0x16, 0x0D, 0x17, 0x1B, 0x16, 0x0D, 0x17, 0x14, 0x15, 0x0D, 0x17, 0x15, +0x16, 0x0D, 0x18, 0x19, 0x16, 0x0D, 0x17, 0x19, 0x16, 0x0D, 0x00, 0x00, 0x16, 0x0D, 0x18, 0x1B, +0x0F, 0x49, 0x4A, 0x11, 0x4B, 0x2A, 0x5C, 0x15, 0x16, 0x49, 0x17, 0x1D, 0x00, 0x00, 0x00, 0x15, +0x16, 0x0D, 0x17, 0x10, 0x16, 0x49, 0x12, 0x00, 0x16, 0x49, 0x0C, 0x11, 0x00, 0x00, 0x12, 0x10, +0x16, 0x0D, 0x00, 0x11, 0x16, 0x49, 0x0C, 0x00, 0x16, 0x0D, 0x4C, 0x11, 0x0E, 0x0D, 0x4A, 0x11, +0x16, 0x1A, 0x17, 0x1B, 0x4F, 0x34, 0x4A, 0x50, 0x35, 0x4D, 0x65, 0x36, 0x4A, 0x34, 0x4E, 0x00, +0x0E, 0x34, 0x4A, 0x11, 0x51, 0x34, 0x5D, 0x59, 0x4B, 0x49, 0x4C, 0x11, 0x2D, 0x00, 0x00, 0x00, +0x5D, 0x00, 0x12, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x49, 0x2B, 0x2D, 0x46, 0x49, 0x1C, 0x52, +0x00, 0x49, 0x1C, 0x52, 0x5D, 0x49, 0x00, 0x52, 0x46, 0x49, 0x13, 0x52, 0x4B, 0x4D, 0x4A, 0x5A, +0x47, 0x49, 0x1C, 0x52, 0x4B, 0x4D, 0x39, 0x36, 0x1F, 0x2C, 0x2E, 0x52, 0x1F, 0x2C, 0x2E, 0x1D, +0x2F, 0x2C, 0x2E, 0x52, 0x2F, 0x2C, 0x2E, 0x31, 0x1F, 0x1E, 0x30, 0x52, 0x51, 0x49, 0x13, 0x00, +0x4F, 0x49, 0x13, 0x50, 0x4F, 0x4D, 0x4A, 0x50, 0x4B, 0x49, 0x4C, 0x2B, 0x1F, 0x20, 0x22, 0x53, +0x55, 0x3D, 0x42, 0x43, 0x1F, 0x1E, 0x23, 0x52, 0x1F, 0x1E, 0x39, 0x3A, 0x1F, 0x1E, 0x3A, 0x3E, +0x1F, 0x1E, 0x3C, 0x3D, 0x40, 0x1E, 0x27, 0x3F, 0x55, 0x1A, 0x42, 0x43, 0x1F, 0x1E, 0x2A, 0x52, +0x1F, 0x1E, 0x38, 0x52, 0x1F, 0x20, 0x28, 0x52, 0x1F, 0x20, 0x26, 0x52, 0x1F, 0x2C, 0x25, 0x52, +0x1F, 0x20, 0x27, 0x52, 0x1F, 0x1E, 0x29, 0x52, 0x1F, 0x2C, 0x3B, 0x52, 0x46, 0x49, 0x24, 0x52, +0x21, 0x41, 0x45, 0x33, 0x1F, 0x2C, 0x28, 0x31, 0x1F, 0x0D, 0x29, 0x52, 0x1F, 0x1E, 0x27, 0x52, +0x1F, 0x20, 0x27, 0x53, 0x48, 0x49, 0x13, 0x52, 0x0E, 0x1E, 0x4A, 0x50, 0x1F, 0x20, 0x26, 0x53, +0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x2A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, +0x5D, 0x49, 0x00, 0x52, 0x55, 0x49, 0x42, 0x43, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, +0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, +0x61, 0x56, 0x57, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, +0x61, 0x56, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, 0x61, 0x56, 0x33, 0x50, 0x61, 0x56, 0x57, 0x50, +0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50 ]; + +pub(crate) const ORIGINAL_OVERWORLD_BLOCKS: [u8; 272] = [ 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, +0x10, 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, 0x04, 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, +0x0A, 0x06, 0x06, 0x01, 0x01, 0x01, 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x01, 0x01, 0x04, 0x05, +0x05, 0x06, 0x09, 0x0F, 0x00, 0x00, 0x0B, 0x0B, 0x05, 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, +0x04, 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, +0x10, 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, 0x04, 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, +0x0A, 0x06, 0x06, 0x1C, 0x1C, 0x1C, 0x02, 0x05, 0x05, 0x06, 0x06, 0x06, 0x1C, 0x1C, 0x00, 0x05, +0x05, 0x06, 0x00, 0x0F, 0x00, 0x00, 0x23, 0x23, 0x05, 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, +0x20, 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, +0x14, 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, 0x16, 0x15, 0x15, 0x12, 0x13, 0x13, 0x18, 0x16, +0x16, 0x15, 0x15, 0x13, 0x26, 0x26, 0x13, 0x17, 0x17, 0x15, 0x15, 0x15, 0x26, 0x26, 0x13, 0x17, +0x17, 0x1B, 0x1D, 0x11, 0x13, 0x13, 0x18, 0x18, 0x17, 0x16, 0x16, 0x13, 0x13, 0x13, 0x19, 0x19, +0x19, 0x16, 0x16, 0x18, 0x13, 0x18, 0x19, 0x19, 0x19, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, +0x09, 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, 0x03 ]; diff --git a/enemize/src/lib.rs b/enemize/src/lib.rs index e5c016e..aae5429 100644 --- a/enemize/src/lib.rs +++ b/enemize/src/lib.rs @@ -11,6 +11,7 @@ pub mod asar; pub mod bosses; pub mod constants; pub mod option_flags; +pub mod randomize; pub mod rom; #[derive(Debug, Error)] diff --git a/enemize/src/main.rs b/enemize/src/main.rs index ea0f310..e74877b 100644 --- a/enemize/src/main.rs +++ b/enemize/src/main.rs @@ -3,11 +3,14 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::time::Instant; -use anyhow::ensure; +use anyhow::{bail, ensure}; use clap::Parser; use enemize::{asar, rom::RomData}; +const ASAR_SYMBOLS: &'static str = "asar_symbols.txt"; +const ENEMIZER_BASE_PATCH: &'static str = "enemizer_base_patch.json"; + /// Randomizes enemy placements in The Legend of Zelda: A Link to the Past for the Super Nintendo /// Entertainment System #[derive(Debug, Parser)] @@ -17,7 +20,7 @@ struct Args { rom: PathBuf, /// seed number #[clap(short, long)] - seed: Option, + seed: Option, /// path to the enemizerOptions.json #[clap(short, long)] enemizer: PathBuf, @@ -34,7 +37,7 @@ fn main() -> anyhow::Result<()> { let stopwatch = Instant::now(); let options = serde_json::from_reader(File::open(args.enemizer)?)?; - let symbols = load_symbols(&args.rom)?; + let symbols = load_symbols()?; let mut raw_data = vec![]; let mut rom_file = File::open(args.rom)?; @@ -42,17 +45,24 @@ fn main() -> anyhow::Result<()> { raw_data.resize(2 * 1024 * 1024, 0); - let mut rom_data = RomData::new(symbols, raw_data); - ensure!(!rom_data.is_enemizer(), "It appears that the provided base ROM is already enemized. Please ensure you are using an original game ROM."); + let mut rom = RomData::new(symbols, raw_data); + ensure!(!rom.is_enemizer(), "It appears that the provided base ROM is already enemized. Please ensure you are using an original game ROM."); - let seed = args.seed.unwrap_or_else(|| rand::random()); + // Oh noes! The max seed number is twice as likely to show up as any other! + // (That is, 2 out of 2 billion instead of 1.) + let seed = args.seed.unwrap_or_else(|| rand::random()).saturating_abs(); - //let randomized_rom = randomize_rom(seed, raw_data, options); + rom.randomize(Path::new(ENEMIZER_BASE_PATCH), options, seed)?; + + let mut out_file = File::create(&args.output)?; if args.binary { - + out_file.write_all(rom.get_rom_bytes())?; + out_file.flush()?; + println!("Generated SFC file {}", args.output.to_string_lossy()); } else { - + let patches = rom.generate_patch(); + serde_json::to_writer(out_file, &patches)?; } println!("Seed generated in: {}ms", stopwatch.elapsed().as_millis()); @@ -60,21 +70,10 @@ fn main() -> anyhow::Result<()> { Ok(()) } -fn load_symbols(rom: &Path) -> anyhow::Result { - let sym_path = rom.with_extension("sym"); - - if let Err(_) = std::fs::metadata(&sym_path) { - let status = std::process::Command::new("asar") - .arg("--no-title-check") - .arg("--fix-checksum=off") - .arg("--symbols=wla") - .arg("-Iassembly/src") - .arg("assembly/src/main.asm") - .arg(rom) - .status()?; - - ensure!(status.success(), "could not generate symbols"); +fn load_symbols() -> anyhow::Result { + if let Err(_) = std::fs::metadata(ASAR_SYMBOLS) { + bail!("Could not find symbols at {}. Did you run prepare.sh?", ASAR_SYMBOLS); } - asar::load_symbols(sym_path.as_path()) + asar::load_symbols(Path::new(ASAR_SYMBOLS)) } diff --git a/enemize/src/randomize.rs b/enemize/src/randomize.rs new file mode 100644 index 0000000..a1abdb9 --- /dev/null +++ b/enemize/src/randomize.rs @@ -0,0 +1,29 @@ +use std::path::Path; + +use anyhow::ensure; + +use crate::PatchSet; +use crate::option_flags::OptionFlags; +use crate::rom::RomData; + +impl RomData { + pub fn randomize(&mut self, base_patch: &Path, option_flags: OptionFlags, seed: i32) -> anyhow::Result<()> { + ensure!(self.is_randomizer(), "Enemizer only supports randomizer ROMs for input."); + ensure!(!self.is_race(), "Enemizer does not support race roms."); + + if self.is_enemizer() { + // Reuse seed in ROM, not the one given. + self.reset_enemizer(); + } else { + self.set_enemizer_seed(seed); + } + + self.expand_rom(); + self.set_info_flags(option_flags)?; + + let patches = PatchSet::load(base_patch)?; + patches.patch_rom(self); + + Ok(()) + } +} diff --git a/enemize/src/rom.rs b/enemize/src/rom.rs index 95b1fb6..6b264ed 100644 --- a/enemize/src/rom.rs +++ b/enemize/src/rom.rs @@ -31,9 +31,9 @@ pub const RANDOMIZER_MODE_FLAG: usize = 0x180032; pub struct RomData { asar_symbols: Symbols, spoiler: String, - rom_data: Vec, + pub(crate) rom_data: Vec, patch_data: BTreeMap, - seed: i32, + pub(crate) seed: i32, } impl RomData { @@ -41,6 +41,25 @@ impl RomData { self.spoiler.as_str() } + pub fn reset_enemizer(&mut self) -> i32 { + use crate::constants::*; + + let seed = self.get_enemizer_seed(); + + self.rom_data[ROOM_HEADER_BANK_LOCATION] = 0x04; + + let dungeon_header_range = DUNGEON_HEADER_POINTER_TABLE..(DUNGEON_HEADER_POINTER_TABLE + 640); + self.rom_data[dungeon_header_range].copy_from_slice(&ORIGINAL_ROOM_POINTERS); + + let room_range = 0x5B97..(0x5B97 + 576); + self.rom_data[room_range].copy_from_slice(&ORIGINAL_ROOM_BLOCKS); + + let ow_gfx_range = OVERWORLD_AREA_GRAPHICS_BLOCK..(OVERWORLD_AREA_GRAPHICS_BLOCK + 272); + self.rom_data[ow_gfx_range].copy_from_slice(&ORIGINAL_OVERWORLD_BLOCKS); + + seed + } + pub fn generate_patch(&self) -> Vec { let mut patches = vec![]; @@ -54,6 +73,10 @@ impl RomData { patches } + pub fn get_rom_bytes(&self) -> &[u8] { + &self.rom_data + } + fn set_rom_bytes(&mut self, bytes: &[u8], range: Range) { self.rom_data.splice(range, bytes.into_iter().map(|&b| b)); } @@ -92,6 +115,12 @@ impl RomData { &self.rom_data[0x7FC0..0x7FCE] == b"ZELDANODENSETSU") } + pub fn is_race(&self) -> bool { + self.is_randomizer() && + (&self.rom_data[0x180213..0x180214] == &[1, 0] || + &self.rom_data[0x7FC0..0x7FC9] == b"VT TOURNEY") + } + fn assert_rom_length(&self) { assert!(self.rom_data.len() >= ENEMIZER_FILE_LENGTH, "You need to expand the rom before you can use Enemizer features."); } @@ -127,6 +156,15 @@ impl RomData { self.set_patch_bytes(seed_start..seed_end); } + pub fn expand_rom(&mut self) { + self.rom_data.resize(0x40_0000, 0); + // Update header length. + self.rom_data[0x7FD7] = 0x0C; + self.set_patch_bytes(0x7FD7..0x7FD8); + + self.set_enemizer_version("6.0.32".to_owned()); + } + pub fn get_enemizer_version(&self) -> anyhow::Result<&str> { if self.is_enemizer() { let version_start = self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_VERSION_OFFSET; @@ -208,7 +246,7 @@ impl RomData { pub fn move_room_headers(&mut self) { let table_base = DUNGEON_HEADER_POINTER_TABLE; - let header_base = self.asar_symbols["rom_header_table"]; + let header_base = self.asar_symbols["room_header_table"]; // Change room header bank (at 0xB5E7) to 0x04. let new_room_bank = self.rom_data[self.asar_symbols["moved_room_header_bank_value_address"]]; From 27d5a4d6c00b68b6c0ccd736d84b82da8f6e58fb Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 09:41:29 -0400 Subject: [PATCH 4/6] Format! --- base_patch_generator/src/main.rs | 2 +- enemize/src/asar.rs | 45 ++++--- enemize/src/bosses/mod.rs | 3 +- enemize/src/constants.rs | 198 +++++++++++++++---------------- enemize/src/main.rs | 5 +- enemize/src/option_flags.rs | 122 +++++++++++++++---- enemize/src/randomize.rs | 14 ++- enemize/src/rom.rs | 90 ++++++++------ 8 files changed, 291 insertions(+), 188 deletions(-) diff --git a/base_patch_generator/src/main.rs b/base_patch_generator/src/main.rs index 4abf411..e089a9a 100644 --- a/base_patch_generator/src/main.rs +++ b/base_patch_generator/src/main.rs @@ -3,9 +3,9 @@ use std::fs::File; use std::io::Read; use std::path::Path; -use enemize::PatchSet; use enemize::asar; use enemize::rom::RomData; +use enemize::PatchSet; fn main() -> Result<(), anyhow::Error> { let mut args = env::args(); diff --git a/enemize/src/asar.rs b/enemize/src/asar.rs index f405e9d..b4afba8 100644 --- a/enemize/src/asar.rs +++ b/enemize/src/asar.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use std::fs::File; -use std::io::{BufReader, BufRead}; +use std::io::{BufRead, BufReader}; use std::path::Path; pub type Symbols = HashMap; @@ -9,28 +9,35 @@ pub fn load_symbols(filename: &Path) -> anyhow::Result { let file = File::open(filename)?; let reader = BufReader::new(file); - let symbols = reader.lines().filter_map(|l| l.ok().and_then(|line| { - let mut words = line.split_ascii_whitespace(); - match (words.next(), words.next(), words.next()) { - // Get only two-word lines. - (Some(address), Some(symbol), None) => - Some((symbol.to_owned(), address.to_owned())), + let symbols = reader + .lines() + .filter_map(|l| { + l.ok() + .and_then(|line| { + let mut words = line.split_ascii_whitespace(); + match (words.next(), words.next(), words.next()) { + // Get only two-word lines. + (Some(address), Some(symbol), None) => { + Some((symbol.to_owned(), address.to_owned())) + } - _ => None - } - }) - .and_then(|(symbol, mut address)| { - if let Some(colon_at) = address.find(':') { - address.remove(colon_at); - } + _ => None, + } + }) + .and_then(|(symbol, mut address)| { + if let Some(colon_at) = address.find(':') { + address.remove(colon_at); + } - // Filter out the ones that don't have a hexadecimal number as the first word. - let snes_address = u32::from_str_radix(&address, 16).ok()?; + // Filter out the ones that don't have a hexadecimal number as the first word. + let snes_address = u32::from_str_radix(&address, 16).ok()?; - let pc_address = snes_to_pc_address(snes_address); + let pc_address = snes_to_pc_address(snes_address); - Some((symbol, pc_address)) - })).collect(); + Some((symbol, pc_address)) + }) + }) + .collect(); Ok(symbols) } diff --git a/enemize/src/bosses/mod.rs b/enemize/src/bosses/mod.rs index a5f02c7..ea7692b 100644 --- a/enemize/src/bosses/mod.rs +++ b/enemize/src/bosses/mod.rs @@ -67,8 +67,7 @@ impl TryFrom for BossType { 11 => Ok(Self::Agahnim2), 12 => Ok(Self::Ganon), 255 => Ok(Self::NoBoss), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } - diff --git a/enemize/src/constants.rs b/enemize/src/constants.rs index 4cd503c..3becd7a 100644 --- a/enemize/src/constants.rs +++ b/enemize/src/constants.rs @@ -11,104 +11,104 @@ pub const RANDOM_SPRITE_GRAPHICS: usize = 0x300000; pub const ENEMIZER_FILE_LENGTH: usize = 0x200000; pub const HIDDEN_ENEMY_CHANCE_POOL: usize = 0xD7BBB; -pub(crate) const ORIGINAL_ROOM_POINTERS: [u8; 640] = [ 0x62, 0xF4, 0x6C, 0xF4, 0x7A, 0xF4, 0xDD, 0xF5, 0x85, - 0xF4, 0x90, 0xF4, 0x90, 0xF4, 0x97, 0xF4, 0xA2, 0xF4, 0xA9, 0xF4, 0xB5, 0xF4, 0xC0, 0xF4, - 0xCB, 0xF4, 0xD8, 0xF4, 0xDF, 0xF4, 0xEA, 0xF4, 0xEA, 0xF4, 0xF1, 0xF4, 0xFC, 0xF4, 0x03, - 0xF5, 0x11, 0xF5, 0x18, 0xF5, 0x23, 0xF5, 0x2E, 0xF5, 0x73, 0xFC, 0x3A, 0xF5, 0x41, 0xF5, - 0x4D, 0xF5, 0x58, 0xF5, 0x63, 0xF5, 0x6E, 0xF5, 0x79, 0xF5, 0x84, 0xF5, 0x8B, 0xF5, 0x8B, - 0xF5, 0x03, 0xF5, 0x92, 0xF5, 0x99, 0xF5, 0x99, 0xF5, 0xA6, 0xF5, 0xB2, 0xF5, 0xBD, 0xF5, - 0xC4, 0xF5, 0xCB, 0xF5, 0x73, 0xFC, 0xD6, 0xF5, 0xD6, 0xF5, 0xDD, 0xF5, 0xE4, 0xF5, 0xEF, - 0xF5, 0xFB, 0xF5, 0x06, 0xF6, 0x0D, 0xF6, 0x18, 0xF6, 0x1F, 0xF6, 0x18, 0xF6, 0x26, 0xF6, - 0x31, 0xF6, 0x3B, 0xF6, 0x46, 0xF6, 0x51, 0xF6, 0x58, 0xF6, 0x63, 0xF6, 0x6E, 0xF6, 0x7A, - 0xF6, 0x86, 0xF6, 0x91, 0xF6, 0x9D, 0xF6, 0xA4, 0xF6, 0xAB, 0xF6, 0xB6, 0xF6, 0xBD, 0xF6, - 0xBD, 0xF6, 0xBD, 0xF6, 0xC4, 0xF6, 0xD0, 0xF6, 0xDA, 0xF6, 0xE5, 0xF6, 0xF0, 0xF6, 0xFB, - 0xF6, 0x05, 0xF7, 0x13, 0xF7, 0x1E, 0xF7, 0x2C, 0xF7, 0x37, 0xF7, 0x42, 0xF7, 0x49, 0xF7, - 0x50, 0xF7, 0x57, 0xF7, 0x5E, 0xF7, 0x65, 0xF7, 0x6C, 0xF7, 0x73, 0xF7, 0x7E, 0xF7, 0x89, - 0xF7, 0x94, 0xF7, 0xA0, 0xF7, 0xA7, 0xF7, 0xA0, 0xF7, 0xB2, 0xF7, 0xBD, 0xF7, 0xC8, 0xF7, - 0xD2, 0xF7, 0xDD, 0xF7, 0xE4, 0xF7, 0xEB, 0xF7, 0xEB, 0xF7, 0xF7, 0xF7, 0x02, 0xF8, 0x0D, - 0xF8, 0x14, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x2B, 0xF8, 0x36, 0xF8, 0x41, 0xF8, 0x48, 0xF8, - 0x4F, 0xF8, 0x56, 0xF8, 0x63, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x7A, - 0xF8, 0x81, 0xF8, 0x8B, 0xF8, 0x96, 0xF8, 0xA1, 0xF8, 0xAC, 0xF8, 0xAC, 0xF8, 0xB3, 0xF8, - 0xBA, 0xF8, 0xC1, 0xF8, 0xC8, 0xF8, 0xC8, 0xF8, 0xD4, 0xF8, 0xD4, 0xF8, 0xDE, 0xF8, 0xDE, - 0xF8, 0xE5, 0xF8, 0xF2, 0xF8, 0xF9, 0xF8, 0x04, 0xF9, 0x04, 0xF9, 0x0B, 0xF9, 0x16, 0xF9, - 0x1D, 0xF9, 0x28, 0xF9, 0x28, 0xF9, 0x2F, 0xF9, 0x3A, 0xF9, 0x45, 0xF9, 0x50, 0xF9, 0x5B, - 0xF9, 0x5B, 0xF9, 0x65, 0xF9, 0x6C, 0xF9, 0x76, 0xF9, 0x81, 0xF9, 0x88, 0xF9, 0x93, 0xF9, - 0x9A, 0xF9, 0x93, 0xF9, 0xA5, 0xF9, 0xAC, 0xF9, 0xB7, 0xF9, 0xC2, 0xF9, 0xCC, 0xF9, 0xD3, - 0xF9, 0xDD, 0xF9, 0xE4, 0xF9, 0xEF, 0xF9, 0xF6, 0xF9, 0xF6, 0xF9, 0x01, 0xFA, 0x08, 0xFA, - 0x14, 0xFA, 0x1E, 0xFA, 0x25, 0xFA, 0x2C, 0xFA, 0x37, 0xFA, 0x42, 0xFA, 0x0A, 0xF5, 0x4D, - 0xFA, 0x54, 0xFA, 0x5B, 0xFA, 0x62, 0xFA, 0x69, 0xFA, 0x74, 0xFA, 0x74, 0xFA, 0x7F, 0xFA, - 0x86, 0xFA, 0x92, 0xFA, 0x99, 0xFA, 0xA0, 0xFA, 0xA7, 0xFA, 0xB2, 0xFA, 0x0A, 0xF5, 0xB9, - 0xFA, 0xC0, 0xFA, 0xC7, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xD5, 0xFA, 0xD5, 0xFA, - 0xDF, 0xFA, 0xDF, 0xFA, 0xEB, 0xFA, 0xF6, 0xFA, 0x01, 0xFB, 0x01, 0xFB, 0xB2, 0xFA, 0x0A, - 0xF5, 0x01, 0xFB, 0x01, 0xFB, 0x08, 0xFB, 0x0F, 0xFB, 0xCE, 0xFA, 0xCE, 0xFA, 0x1A, 0xFB, - 0x1A, 0xFB, 0x21, 0xFB, 0x2C, 0xFB, 0x37, 0xFB, 0x3E, 0xFB, 0x45, 0xFB, 0x4C, 0xFB, 0x4C, - 0xFB, 0x53, 0xFB, 0x53, 0xFB, 0x5A, 0xFB, 0x68, 0xFB, 0x68, 0xFB, 0x73, 0xFB, 0x7E, 0xFB, - 0x7E, 0xFB, 0x8A, 0xFB, 0x94, 0xFB, 0x53, 0xFB, 0x53, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA5, - 0xFB, 0xA5, 0xFB, 0xAC, 0xFB, 0xAC, 0xFB, 0xAC, 0xFB, 0xBA, 0xFB, 0xC1, 0xFB, 0xCC, 0xFB, - 0xD7, 0xFB, 0xD7, 0xFB, 0xBA, 0xFB, 0xE3, 0xFB, 0xEE, 0xFB, 0xFC, 0xFB, 0x03, 0xFC, 0x0A, - 0xFC, 0x11, 0xFC, 0x18, 0xFC, 0x1F, 0xFC, 0x26, 0xFC, 0x2D, 0xFC, 0x34, 0xFC, 0x3B, 0xFC, - 0x42, 0xFC, 0x49, 0xFC, 0x50, 0xFC, 0x57, 0xFC, 0xF5, 0xFB, 0xF5, 0xFB, 0x5E, 0xFC, 0x65, - 0xFC, 0x6C, 0xFC, 0x73, 0xFC, 0x73, 0xFC, 0x7A, 0xFC, 0x81, 0xFC, 0x0A, 0xFC, 0x88, 0xFC, - 0x93, 0xFC, 0x9A, 0xFC, 0xF5, 0xFB, 0xA1, 0xFC, 0xAC, 0xFC, 0xB3, 0xFC, 0xBA, 0xFC, 0x5E, - 0xFC, 0x5E, 0xFC, 0xC1, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xAC, 0xFC, 0xCF, 0xFC, - 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, - 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, - 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, - 0xFC]; +pub(crate) const ORIGINAL_ROOM_POINTERS: [u8; 640] = [ + 0x62, 0xF4, 0x6C, 0xF4, 0x7A, 0xF4, 0xDD, 0xF5, 0x85, 0xF4, 0x90, 0xF4, 0x90, 0xF4, 0x97, 0xF4, + 0xA2, 0xF4, 0xA9, 0xF4, 0xB5, 0xF4, 0xC0, 0xF4, 0xCB, 0xF4, 0xD8, 0xF4, 0xDF, 0xF4, 0xEA, 0xF4, + 0xEA, 0xF4, 0xF1, 0xF4, 0xFC, 0xF4, 0x03, 0xF5, 0x11, 0xF5, 0x18, 0xF5, 0x23, 0xF5, 0x2E, 0xF5, + 0x73, 0xFC, 0x3A, 0xF5, 0x41, 0xF5, 0x4D, 0xF5, 0x58, 0xF5, 0x63, 0xF5, 0x6E, 0xF5, 0x79, 0xF5, + 0x84, 0xF5, 0x8B, 0xF5, 0x8B, 0xF5, 0x03, 0xF5, 0x92, 0xF5, 0x99, 0xF5, 0x99, 0xF5, 0xA6, 0xF5, + 0xB2, 0xF5, 0xBD, 0xF5, 0xC4, 0xF5, 0xCB, 0xF5, 0x73, 0xFC, 0xD6, 0xF5, 0xD6, 0xF5, 0xDD, 0xF5, + 0xE4, 0xF5, 0xEF, 0xF5, 0xFB, 0xF5, 0x06, 0xF6, 0x0D, 0xF6, 0x18, 0xF6, 0x1F, 0xF6, 0x18, 0xF6, + 0x26, 0xF6, 0x31, 0xF6, 0x3B, 0xF6, 0x46, 0xF6, 0x51, 0xF6, 0x58, 0xF6, 0x63, 0xF6, 0x6E, 0xF6, + 0x7A, 0xF6, 0x86, 0xF6, 0x91, 0xF6, 0x9D, 0xF6, 0xA4, 0xF6, 0xAB, 0xF6, 0xB6, 0xF6, 0xBD, 0xF6, + 0xBD, 0xF6, 0xBD, 0xF6, 0xC4, 0xF6, 0xD0, 0xF6, 0xDA, 0xF6, 0xE5, 0xF6, 0xF0, 0xF6, 0xFB, 0xF6, + 0x05, 0xF7, 0x13, 0xF7, 0x1E, 0xF7, 0x2C, 0xF7, 0x37, 0xF7, 0x42, 0xF7, 0x49, 0xF7, 0x50, 0xF7, + 0x57, 0xF7, 0x5E, 0xF7, 0x65, 0xF7, 0x6C, 0xF7, 0x73, 0xF7, 0x7E, 0xF7, 0x89, 0xF7, 0x94, 0xF7, + 0xA0, 0xF7, 0xA7, 0xF7, 0xA0, 0xF7, 0xB2, 0xF7, 0xBD, 0xF7, 0xC8, 0xF7, 0xD2, 0xF7, 0xDD, 0xF7, + 0xE4, 0xF7, 0xEB, 0xF7, 0xEB, 0xF7, 0xF7, 0xF7, 0x02, 0xF8, 0x0D, 0xF8, 0x14, 0xF8, 0x1F, 0xF8, + 0x1F, 0xF8, 0x2B, 0xF8, 0x36, 0xF8, 0x41, 0xF8, 0x48, 0xF8, 0x4F, 0xF8, 0x56, 0xF8, 0x63, 0xF8, + 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x70, 0xF8, 0x7A, 0xF8, 0x81, 0xF8, 0x8B, 0xF8, 0x96, 0xF8, + 0xA1, 0xF8, 0xAC, 0xF8, 0xAC, 0xF8, 0xB3, 0xF8, 0xBA, 0xF8, 0xC1, 0xF8, 0xC8, 0xF8, 0xC8, 0xF8, + 0xD4, 0xF8, 0xD4, 0xF8, 0xDE, 0xF8, 0xDE, 0xF8, 0xE5, 0xF8, 0xF2, 0xF8, 0xF9, 0xF8, 0x04, 0xF9, + 0x04, 0xF9, 0x0B, 0xF9, 0x16, 0xF9, 0x1D, 0xF9, 0x28, 0xF9, 0x28, 0xF9, 0x2F, 0xF9, 0x3A, 0xF9, + 0x45, 0xF9, 0x50, 0xF9, 0x5B, 0xF9, 0x5B, 0xF9, 0x65, 0xF9, 0x6C, 0xF9, 0x76, 0xF9, 0x81, 0xF9, + 0x88, 0xF9, 0x93, 0xF9, 0x9A, 0xF9, 0x93, 0xF9, 0xA5, 0xF9, 0xAC, 0xF9, 0xB7, 0xF9, 0xC2, 0xF9, + 0xCC, 0xF9, 0xD3, 0xF9, 0xDD, 0xF9, 0xE4, 0xF9, 0xEF, 0xF9, 0xF6, 0xF9, 0xF6, 0xF9, 0x01, 0xFA, + 0x08, 0xFA, 0x14, 0xFA, 0x1E, 0xFA, 0x25, 0xFA, 0x2C, 0xFA, 0x37, 0xFA, 0x42, 0xFA, 0x0A, 0xF5, + 0x4D, 0xFA, 0x54, 0xFA, 0x5B, 0xFA, 0x62, 0xFA, 0x69, 0xFA, 0x74, 0xFA, 0x74, 0xFA, 0x7F, 0xFA, + 0x86, 0xFA, 0x92, 0xFA, 0x99, 0xFA, 0xA0, 0xFA, 0xA7, 0xFA, 0xB2, 0xFA, 0x0A, 0xF5, 0xB9, 0xFA, + 0xC0, 0xFA, 0xC7, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xD5, 0xFA, 0xD5, 0xFA, 0xDF, 0xFA, + 0xDF, 0xFA, 0xEB, 0xFA, 0xF6, 0xFA, 0x01, 0xFB, 0x01, 0xFB, 0xB2, 0xFA, 0x0A, 0xF5, 0x01, 0xFB, + 0x01, 0xFB, 0x08, 0xFB, 0x0F, 0xFB, 0xCE, 0xFA, 0xCE, 0xFA, 0x1A, 0xFB, 0x1A, 0xFB, 0x21, 0xFB, + 0x2C, 0xFB, 0x37, 0xFB, 0x3E, 0xFB, 0x45, 0xFB, 0x4C, 0xFB, 0x4C, 0xFB, 0x53, 0xFB, 0x53, 0xFB, + 0x5A, 0xFB, 0x68, 0xFB, 0x68, 0xFB, 0x73, 0xFB, 0x7E, 0xFB, 0x7E, 0xFB, 0x8A, 0xFB, 0x94, 0xFB, + 0x53, 0xFB, 0x53, 0xFB, 0xA0, 0xFB, 0xA0, 0xFB, 0xA5, 0xFB, 0xA5, 0xFB, 0xAC, 0xFB, 0xAC, 0xFB, + 0xAC, 0xFB, 0xBA, 0xFB, 0xC1, 0xFB, 0xCC, 0xFB, 0xD7, 0xFB, 0xD7, 0xFB, 0xBA, 0xFB, 0xE3, 0xFB, + 0xEE, 0xFB, 0xFC, 0xFB, 0x03, 0xFC, 0x0A, 0xFC, 0x11, 0xFC, 0x18, 0xFC, 0x1F, 0xFC, 0x26, 0xFC, + 0x2D, 0xFC, 0x34, 0xFC, 0x3B, 0xFC, 0x42, 0xFC, 0x49, 0xFC, 0x50, 0xFC, 0x57, 0xFC, 0xF5, 0xFB, + 0xF5, 0xFB, 0x5E, 0xFC, 0x65, 0xFC, 0x6C, 0xFC, 0x73, 0xFC, 0x73, 0xFC, 0x7A, 0xFC, 0x81, 0xFC, + 0x0A, 0xFC, 0x88, 0xFC, 0x93, 0xFC, 0x9A, 0xFC, 0xF5, 0xFB, 0xA1, 0xFC, 0xAC, 0xFC, 0xB3, 0xFC, + 0xBA, 0xFC, 0x5E, 0xFC, 0x5E, 0xFC, 0xC1, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xC8, 0xFC, 0xAC, 0xFC, + 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, + 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, + 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, 0xCF, 0xFC, +]; -pub(crate) const ORIGINAL_ROOM_BLOCKS: [u8; 576] = [ 0x00, 0x49, 0x00, 0x00, 0x46, 0x49, 0x0C, 0x1D, -0x48, 0x49, 0x13, 0x1D, 0x46, 0x49, 0x13, 0x0E, 0x48, 0x49, 0x0C, 0x11, 0x48, 0x49, 0x0C, 0x10, -0x4F, 0x49, 0x4A, 0x50, 0x0E, 0x49, 0x4A, 0x11, 0x46, 0x49, 0x12, 0x00, 0x00, 0x49, 0x00, 0x50, -0x00, 0x49, 0x00, 0x11, 0x48, 0x49, 0x0C, 0x00, 0x00, 0x00, 0x37, 0x36, 0x48, 0x49, 0x4C, 0x11, -0x5D, 0x2C, 0x0C, 0x44, 0x00, 0x00, 0x4E, 0x00, 0x0F, 0x00, 0x12, 0x10, 0x00, 0x00, 0x00, 0x4C, -0x00, 0x0D, 0x17, 0x00, 0x16, 0x0D, 0x17, 0x1B, 0x16, 0x0D, 0x17, 0x14, 0x15, 0x0D, 0x17, 0x15, -0x16, 0x0D, 0x18, 0x19, 0x16, 0x0D, 0x17, 0x19, 0x16, 0x0D, 0x00, 0x00, 0x16, 0x0D, 0x18, 0x1B, -0x0F, 0x49, 0x4A, 0x11, 0x4B, 0x2A, 0x5C, 0x15, 0x16, 0x49, 0x17, 0x1D, 0x00, 0x00, 0x00, 0x15, -0x16, 0x0D, 0x17, 0x10, 0x16, 0x49, 0x12, 0x00, 0x16, 0x49, 0x0C, 0x11, 0x00, 0x00, 0x12, 0x10, -0x16, 0x0D, 0x00, 0x11, 0x16, 0x49, 0x0C, 0x00, 0x16, 0x0D, 0x4C, 0x11, 0x0E, 0x0D, 0x4A, 0x11, -0x16, 0x1A, 0x17, 0x1B, 0x4F, 0x34, 0x4A, 0x50, 0x35, 0x4D, 0x65, 0x36, 0x4A, 0x34, 0x4E, 0x00, -0x0E, 0x34, 0x4A, 0x11, 0x51, 0x34, 0x5D, 0x59, 0x4B, 0x49, 0x4C, 0x11, 0x2D, 0x00, 0x00, 0x00, -0x5D, 0x00, 0x12, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x49, 0x2B, 0x2D, 0x46, 0x49, 0x1C, 0x52, -0x00, 0x49, 0x1C, 0x52, 0x5D, 0x49, 0x00, 0x52, 0x46, 0x49, 0x13, 0x52, 0x4B, 0x4D, 0x4A, 0x5A, -0x47, 0x49, 0x1C, 0x52, 0x4B, 0x4D, 0x39, 0x36, 0x1F, 0x2C, 0x2E, 0x52, 0x1F, 0x2C, 0x2E, 0x1D, -0x2F, 0x2C, 0x2E, 0x52, 0x2F, 0x2C, 0x2E, 0x31, 0x1F, 0x1E, 0x30, 0x52, 0x51, 0x49, 0x13, 0x00, -0x4F, 0x49, 0x13, 0x50, 0x4F, 0x4D, 0x4A, 0x50, 0x4B, 0x49, 0x4C, 0x2B, 0x1F, 0x20, 0x22, 0x53, -0x55, 0x3D, 0x42, 0x43, 0x1F, 0x1E, 0x23, 0x52, 0x1F, 0x1E, 0x39, 0x3A, 0x1F, 0x1E, 0x3A, 0x3E, -0x1F, 0x1E, 0x3C, 0x3D, 0x40, 0x1E, 0x27, 0x3F, 0x55, 0x1A, 0x42, 0x43, 0x1F, 0x1E, 0x2A, 0x52, -0x1F, 0x1E, 0x38, 0x52, 0x1F, 0x20, 0x28, 0x52, 0x1F, 0x20, 0x26, 0x52, 0x1F, 0x2C, 0x25, 0x52, -0x1F, 0x20, 0x27, 0x52, 0x1F, 0x1E, 0x29, 0x52, 0x1F, 0x2C, 0x3B, 0x52, 0x46, 0x49, 0x24, 0x52, -0x21, 0x41, 0x45, 0x33, 0x1F, 0x2C, 0x28, 0x31, 0x1F, 0x0D, 0x29, 0x52, 0x1F, 0x1E, 0x27, 0x52, -0x1F, 0x20, 0x27, 0x53, 0x48, 0x49, 0x13, 0x52, 0x0E, 0x1E, 0x4A, 0x50, 0x1F, 0x20, 0x26, 0x53, -0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x2A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, -0x5D, 0x49, 0x00, 0x52, 0x55, 0x49, 0x42, 0x43, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, -0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, -0x61, 0x56, 0x57, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, -0x61, 0x56, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, 0x61, 0x56, 0x33, 0x50, 0x61, 0x56, 0x57, 0x50, -0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50 ]; +pub(crate) const ORIGINAL_ROOM_BLOCKS: [u8; 576] = [ + 0x00, 0x49, 0x00, 0x00, 0x46, 0x49, 0x0C, 0x1D, 0x48, 0x49, 0x13, 0x1D, 0x46, 0x49, 0x13, 0x0E, + 0x48, 0x49, 0x0C, 0x11, 0x48, 0x49, 0x0C, 0x10, 0x4F, 0x49, 0x4A, 0x50, 0x0E, 0x49, 0x4A, 0x11, + 0x46, 0x49, 0x12, 0x00, 0x00, 0x49, 0x00, 0x50, 0x00, 0x49, 0x00, 0x11, 0x48, 0x49, 0x0C, 0x00, + 0x00, 0x00, 0x37, 0x36, 0x48, 0x49, 0x4C, 0x11, 0x5D, 0x2C, 0x0C, 0x44, 0x00, 0x00, 0x4E, 0x00, + 0x0F, 0x00, 0x12, 0x10, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x0D, 0x17, 0x00, 0x16, 0x0D, 0x17, 0x1B, + 0x16, 0x0D, 0x17, 0x14, 0x15, 0x0D, 0x17, 0x15, 0x16, 0x0D, 0x18, 0x19, 0x16, 0x0D, 0x17, 0x19, + 0x16, 0x0D, 0x00, 0x00, 0x16, 0x0D, 0x18, 0x1B, 0x0F, 0x49, 0x4A, 0x11, 0x4B, 0x2A, 0x5C, 0x15, + 0x16, 0x49, 0x17, 0x1D, 0x00, 0x00, 0x00, 0x15, 0x16, 0x0D, 0x17, 0x10, 0x16, 0x49, 0x12, 0x00, + 0x16, 0x49, 0x0C, 0x11, 0x00, 0x00, 0x12, 0x10, 0x16, 0x0D, 0x00, 0x11, 0x16, 0x49, 0x0C, 0x00, + 0x16, 0x0D, 0x4C, 0x11, 0x0E, 0x0D, 0x4A, 0x11, 0x16, 0x1A, 0x17, 0x1B, 0x4F, 0x34, 0x4A, 0x50, + 0x35, 0x4D, 0x65, 0x36, 0x4A, 0x34, 0x4E, 0x00, 0x0E, 0x34, 0x4A, 0x11, 0x51, 0x34, 0x5D, 0x59, + 0x4B, 0x49, 0x4C, 0x11, 0x2D, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x12, 0x59, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x49, 0x2B, 0x2D, 0x46, 0x49, 0x1C, 0x52, 0x00, 0x49, 0x1C, 0x52, 0x5D, 0x49, 0x00, 0x52, + 0x46, 0x49, 0x13, 0x52, 0x4B, 0x4D, 0x4A, 0x5A, 0x47, 0x49, 0x1C, 0x52, 0x4B, 0x4D, 0x39, 0x36, + 0x1F, 0x2C, 0x2E, 0x52, 0x1F, 0x2C, 0x2E, 0x1D, 0x2F, 0x2C, 0x2E, 0x52, 0x2F, 0x2C, 0x2E, 0x31, + 0x1F, 0x1E, 0x30, 0x52, 0x51, 0x49, 0x13, 0x00, 0x4F, 0x49, 0x13, 0x50, 0x4F, 0x4D, 0x4A, 0x50, + 0x4B, 0x49, 0x4C, 0x2B, 0x1F, 0x20, 0x22, 0x53, 0x55, 0x3D, 0x42, 0x43, 0x1F, 0x1E, 0x23, 0x52, + 0x1F, 0x1E, 0x39, 0x3A, 0x1F, 0x1E, 0x3A, 0x3E, 0x1F, 0x1E, 0x3C, 0x3D, 0x40, 0x1E, 0x27, 0x3F, + 0x55, 0x1A, 0x42, 0x43, 0x1F, 0x1E, 0x2A, 0x52, 0x1F, 0x1E, 0x38, 0x52, 0x1F, 0x20, 0x28, 0x52, + 0x1F, 0x20, 0x26, 0x52, 0x1F, 0x2C, 0x25, 0x52, 0x1F, 0x20, 0x27, 0x52, 0x1F, 0x1E, 0x29, 0x52, + 0x1F, 0x2C, 0x3B, 0x52, 0x46, 0x49, 0x24, 0x52, 0x21, 0x41, 0x45, 0x33, 0x1F, 0x2C, 0x28, 0x31, + 0x1F, 0x0D, 0x29, 0x52, 0x1F, 0x1E, 0x27, 0x52, 0x1F, 0x20, 0x27, 0x53, 0x48, 0x49, 0x13, 0x52, + 0x0E, 0x1E, 0x4A, 0x50, 0x1F, 0x20, 0x26, 0x53, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x2A, 0x52, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x5D, 0x49, 0x00, 0x52, 0x55, 0x49, 0x42, 0x43, + 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, + 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, 0x61, 0x62, 0x63, 0x50, + 0x61, 0x62, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, 0x61, 0x56, 0x63, 0x50, 0x61, 0x56, 0x57, 0x50, + 0x61, 0x56, 0x33, 0x50, 0x61, 0x56, 0x57, 0x50, 0x61, 0x62, 0x63, 0x50, 0x61, 0x62, 0x63, 0x50, +]; -pub(crate) const ORIGINAL_OVERWORLD_BLOCKS: [u8; 272] = [ 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, -0x10, 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, 0x04, 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, -0x0A, 0x06, 0x06, 0x01, 0x01, 0x01, 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x01, 0x01, 0x04, 0x05, -0x05, 0x06, 0x09, 0x0F, 0x00, 0x00, 0x0B, 0x0B, 0x05, 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, -0x04, 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, -0x10, 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, 0x04, 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, -0x0A, 0x06, 0x06, 0x1C, 0x1C, 0x1C, 0x02, 0x05, 0x05, 0x06, 0x06, 0x06, 0x1C, 0x1C, 0x00, 0x05, -0x05, 0x06, 0x00, 0x0F, 0x00, 0x00, 0x23, 0x23, 0x05, 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, -0x20, 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, -0x14, 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, 0x16, 0x15, 0x15, 0x12, 0x13, 0x13, 0x18, 0x16, -0x16, 0x15, 0x15, 0x13, 0x26, 0x26, 0x13, 0x17, 0x17, 0x15, 0x15, 0x15, 0x26, 0x26, 0x13, 0x17, -0x17, 0x1B, 0x1D, 0x11, 0x13, 0x13, 0x18, 0x18, 0x17, 0x16, 0x16, 0x13, 0x13, 0x13, 0x19, 0x19, -0x19, 0x16, 0x16, 0x18, 0x13, 0x18, 0x19, 0x19, 0x19, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, -0x09, 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, 0x03 ]; +pub(crate) const ORIGINAL_OVERWORLD_BLOCKS: [u8; 272] = [ + 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x07, 0x07, 0x07, 0x10, 0x10, 0x10, 0x10, 0x04, + 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, 0x0A, 0x06, 0x06, 0x01, 0x01, 0x01, 0x04, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x01, 0x01, 0x04, 0x05, 0x05, 0x06, 0x09, 0x0F, 0x00, 0x00, 0x0B, 0x0B, 0x05, + 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, 0x10, 0x07, 0x07, 0x1A, 0x10, 0x10, 0x10, 0x10, 0x04, + 0x06, 0x06, 0x00, 0x03, 0x03, 0x00, 0x0D, 0x0A, 0x06, 0x06, 0x1C, 0x1C, 0x1C, 0x02, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x1C, 0x1C, 0x00, 0x05, 0x05, 0x06, 0x00, 0x0F, 0x00, 0x00, 0x23, 0x23, 0x05, + 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x1F, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x17, 0x14, 0x14, 0x14, 0x14, 0x16, + 0x15, 0x15, 0x12, 0x13, 0x13, 0x18, 0x16, 0x16, 0x15, 0x15, 0x13, 0x26, 0x26, 0x13, 0x17, 0x17, + 0x15, 0x15, 0x15, 0x26, 0x26, 0x13, 0x17, 0x17, 0x1B, 0x1D, 0x11, 0x13, 0x13, 0x18, 0x18, 0x17, + 0x16, 0x16, 0x13, 0x13, 0x13, 0x19, 0x19, 0x19, 0x16, 0x16, 0x18, 0x13, 0x18, 0x19, 0x19, 0x19, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x05, 0x06, 0x09, 0x09, 0x09, 0x09, 0x03, +]; diff --git a/enemize/src/main.rs b/enemize/src/main.rs index e74877b..0e3cc09 100644 --- a/enemize/src/main.rs +++ b/enemize/src/main.rs @@ -72,7 +72,10 @@ fn main() -> anyhow::Result<()> { fn load_symbols() -> anyhow::Result { if let Err(_) = std::fs::metadata(ASAR_SYMBOLS) { - bail!("Could not find symbols at {}. Did you run prepare.sh?", ASAR_SYMBOLS); + bail!( + "Could not find symbols at {}. Did you run prepare.sh?", + ASAR_SYMBOLS + ); } asar::load_symbols(Path::new(ASAR_SYMBOLS)) diff --git a/enemize/src/option_flags.rs b/enemize/src/option_flags.rs index e0fca4e..4ff62cd 100644 --- a/enemize/src/option_flags.rs +++ b/enemize/src/option_flags.rs @@ -62,7 +62,7 @@ impl TryFrom for RandomizeEnemiesType { 2 => Ok(Self::Hard), 3 => Ok(Self::Chaos), 4 => Ok(Self::Insanity), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -73,7 +73,7 @@ pub enum RandomizeEnemyHpType { Easy, Medium, Hard, - Patty + Patty, } impl From for u8 { @@ -98,7 +98,7 @@ impl TryFrom for RandomizeEnemyHpType { 1 => Ok(Self::Medium), 2 => Ok(Self::Hard), 3 => Ok(Self::Patty), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -108,7 +108,7 @@ impl TryFrom for RandomizeEnemyHpType { pub enum RandomizeBossesType { Basic, Normal, - Chaos + Chaos, } impl From for u8 { @@ -131,7 +131,7 @@ impl TryFrom for RandomizeBossesType { 0 => Ok(Self::Basic), 1 => Ok(Self::Normal), 2 => Ok(Self::Chaos), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -139,7 +139,7 @@ impl TryFrom for RandomizeBossesType { #[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[serde(into = "u8", try_from = "u8")] pub enum SwordType { - Normal + Normal, } impl From for u8 { @@ -154,7 +154,7 @@ impl TryFrom for SwordType { fn try_from(byte: u8) -> Result { match byte { 0 => Ok(Self::Normal), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -162,7 +162,7 @@ impl TryFrom for SwordType { #[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[serde(into = "u8", try_from = "u8")] pub enum ShieldType { - Normal + Normal, } impl From for u8 { @@ -177,7 +177,7 @@ impl TryFrom for ShieldType { fn try_from(byte: u8) -> Result { match byte { 0 => Ok(Self::Normal), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -243,7 +243,7 @@ impl TryFrom for AbsorbableType { 11 => Ok(Self::Fairy), 12 => Ok(Self::Key), 13 => Ok(Self::BigKey), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -310,7 +310,7 @@ impl TryFrom for HeartBeepSpeed { 1 => Ok(Self::Half), 2 => Ok(Self::Quarter), 3 => Ok(Self::Off), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -360,7 +360,7 @@ impl TryFrom for BeeLevel { 1 => Ok(Self::Level2), 2 => Ok(Self::Level3), 3 => Ok(Self::Level4), - _ => Err(InvalidEnumError(PhantomData)) + _ => Err(InvalidEnumError(PhantomData)), } } } @@ -542,20 +542,90 @@ impl OptionFlags { bytes.push(self.enemies_absorbable as u8); bytes.push(self.absorbable_spawn_rate); - bytes.push(self.absorbable_types.get(&AbsorbableType::Heart).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::GreenRupee).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::BlueRupee).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::RedRupee).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Bomb1).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Bomb4).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Bomb8).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::SmallMagic).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::FullMagic).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Arrow5).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Arrow10).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Fairy).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::Key).copied().unwrap_or(false) as u8); - bytes.push(self.absorbable_types.get(&AbsorbableType::BigKey).copied().unwrap_or(false) as u8); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Heart) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::GreenRupee) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::BlueRupee) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::RedRupee) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Bomb1) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Bomb4) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Bomb8) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::SmallMagic) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::FullMagic) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Arrow5) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Arrow10) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Fairy) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::Key) + .copied() + .unwrap_or(false) as u8, + ); + bytes.push( + self.absorbable_types + .get(&AbsorbableType::BigKey) + .copied() + .unwrap_or(false) as u8, + ); bytes.push(self.boss_madness as u8); bytes.push(self.randomize_bosses as u8); diff --git a/enemize/src/randomize.rs b/enemize/src/randomize.rs index a1abdb9..4fe78ae 100644 --- a/enemize/src/randomize.rs +++ b/enemize/src/randomize.rs @@ -2,13 +2,21 @@ use std::path::Path; use anyhow::ensure; -use crate::PatchSet; use crate::option_flags::OptionFlags; use crate::rom::RomData; +use crate::PatchSet; impl RomData { - pub fn randomize(&mut self, base_patch: &Path, option_flags: OptionFlags, seed: i32) -> anyhow::Result<()> { - ensure!(self.is_randomizer(), "Enemizer only supports randomizer ROMs for input."); + pub fn randomize( + &mut self, + base_patch: &Path, + option_flags: OptionFlags, + seed: i32, + ) -> anyhow::Result<()> { + ensure!( + self.is_randomizer(), + "Enemizer only supports randomizer ROMs for input." + ); ensure!(!self.is_race(), "Enemizer does not support race roms."); if self.is_enemizer() { diff --git a/enemize/src/rom.rs b/enemize/src/rom.rs index 6b264ed..2ae8d66 100644 --- a/enemize/src/rom.rs +++ b/enemize/src/rom.rs @@ -4,14 +4,15 @@ use std::ops::Range; use anyhow::bail; -use crate::asar::{Symbols, snes_to_pc_address, pc_to_snes_address}; +use crate::asar::{pc_to_snes_address, snes_to_pc_address, Symbols}; use crate::constants::*; use crate::option_flags::OptionFlags; use crate::Patch; pub const ENEMIZER_INFO_SEED_OFFSET: usize = 0; pub const ENEMIZER_INFO_SEED_LENGTH: usize = 12; -pub const ENEMIZER_INFO_VERSION_OFFSET: usize = ENEMIZER_INFO_SEED_OFFSET + ENEMIZER_INFO_SEED_LENGTH; +pub const ENEMIZER_INFO_VERSION_OFFSET: usize = + ENEMIZER_INFO_SEED_OFFSET + ENEMIZER_INFO_SEED_LENGTH; pub const ENEMIZER_INFO_VERSION_LENGTH: usize = 8; pub const ENEMIZER_INFO_FLAGS_OFFSET: usize = ENEMIZER_INFO_VERSION_OFFSET + ENEMIZER_INFO_VERSION_LENGTH; @@ -48,7 +49,8 @@ impl RomData { self.rom_data[ROOM_HEADER_BANK_LOCATION] = 0x04; - let dungeon_header_range = DUNGEON_HEADER_POINTER_TABLE..(DUNGEON_HEADER_POINTER_TABLE + 640); + let dungeon_header_range = + DUNGEON_HEADER_POINTER_TABLE..(DUNGEON_HEADER_POINTER_TABLE + 640); self.rom_data[dungeon_header_range].copy_from_slice(&ORIGINAL_ROOM_POINTERS); let room_range = 0x5B97..(0x5B97 + 576); @@ -64,9 +66,15 @@ impl RomData { let mut patches = vec![]; for (&addr, &byte) in self.patch_data.iter() { - match patches.last_mut().filter(|p: &&mut Patch| p.address + 1 == addr) { - None => patches.push(Patch { address: addr, patch_data: vec![byte] }), - Some(patch) => patch.patch_data.push(byte) + match patches + .last_mut() + .filter(|p: &&mut Patch| p.address + 1 == addr) + { + None => patches.push(Patch { + address: addr, + patch_data: vec![byte], + }), + Some(patch) => patch.patch_data.push(byte), } } @@ -83,46 +91,48 @@ impl RomData { fn set_patch_bytes(&mut self, range: Range) { let slice = &self.rom_data[range.clone()]; - self.patch_data.extend(iter::zip(range, slice.into_iter().map(|&b| b))); + self.patch_data + .extend(iter::zip(range, slice.into_iter().map(|&b| b))); } pub fn is_enemizer(&self) -> bool { self.rom_data.len() == ENEMIZER_FILE_LENGTH - && self.rom_data[self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_SEED_OFFSET] == b'E' - && self.rom_data[self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_SEED_OFFSET + 1] == b'N' + && self.rom_data[self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_SEED_OFFSET] + == b'E' + && self.rom_data + [self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_SEED_OFFSET + 1] + == b'N' } pub fn is_randomizer(&self) -> bool { let acceptable = [ - // item rando - b"VT", - // entrance rando - b"ER", - // door rando - b"DR", - // Berserker's multiworld - b"BM", - // Berserker's multiworld doors - b"BD", - // Archipelago - b"AP", - // Archipelago with door rando - b"AD", + b"VT", // item rando + b"ER", // entrance rando + b"DR", // door rando + b"BM", // Berserker's multiworld + b"BD", // Berserker's multiworld doors + b"AP", // Archipelago + b"AD", // Archipelago with door rando ]; - acceptable.iter().any(|abbr| &abbr[..] == &self.rom_data[0x7FC0..0x7Fc1]) || - (self.rom_data.len() >= 0x20_0000 && - &self.rom_data[0x7FC0..0x7FCE] == b"ZELDANODENSETSU") + acceptable + .iter() + .any(|abbr| &abbr[..] == &self.rom_data[0x7FC0..0x7Fc1]) + || (self.rom_data.len() >= 0x20_0000 + && &self.rom_data[0x7FC0..0x7FCE] == b"ZELDANODENSETSU") } pub fn is_race(&self) -> bool { - self.is_randomizer() && - (&self.rom_data[0x180213..0x180214] == &[1, 0] || - &self.rom_data[0x7FC0..0x7FC9] == b"VT TOURNEY") + self.is_randomizer() + && (&self.rom_data[0x180213..0x180214] == &[1, 0] + || &self.rom_data[0x7FC0..0x7FC9] == b"VT TOURNEY") } fn assert_rom_length(&self) { - assert!(self.rom_data.len() >= ENEMIZER_FILE_LENGTH, "You need to expand the rom before you can use Enemizer features."); + assert!( + self.rom_data.len() >= ENEMIZER_FILE_LENGTH, + "You need to expand the rom before you can use Enemizer features." + ); } pub fn get_enemizer_seed(&self) -> i32 { @@ -167,9 +177,12 @@ impl RomData { pub fn get_enemizer_version(&self) -> anyhow::Result<&str> { if self.is_enemizer() { - let version_start = self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_VERSION_OFFSET; + let version_start = + self.asar_symbols["enemizer_info_table"] + ENEMIZER_INFO_VERSION_OFFSET; let version_end = version_start + ENEMIZER_INFO_VERSION_LENGTH; - Ok(std::str::from_utf8(&self.rom_data[version_start..version_end])?) + Ok(std::str::from_utf8( + &self.rom_data[version_start..version_end], + )?) } else { bail!("Not Enemizer Rom") } @@ -187,7 +200,7 @@ impl RomData { self.set_patch_bytes(version_start..version_end) } - pub fn set_info_flags(&mut self, flags: OptionFlags) -> anyhow::Result<()>{ + pub fn set_info_flags(&mut self, flags: OptionFlags) -> anyhow::Result<()> { let bytes = flags.into_bytes(); if bytes.len() > 0x100 - ENEMIZER_INFO_FLAGS_OFFSET { bail!("Option flags is too long to fit in the space allocated. Need to move data/code in asm file."); @@ -249,7 +262,8 @@ impl RomData { let header_base = self.asar_symbols["room_header_table"]; // Change room header bank (at 0xB5E7) to 0x04. - let new_room_bank = self.rom_data[self.asar_symbols["moved_room_header_bank_value_address"]]; + let new_room_bank = + self.rom_data[self.asar_symbols["moved_room_header_bank_value_address"]]; self.rom_data[ROOM_HEADER_BANK_LOCATION] = new_room_bank; // Copy header table. @@ -260,14 +274,15 @@ impl RomData { self.rom_data[table_base + (i * 2)], self.rom_data[table_base + (i * 2) + 1], 4, - 0 + 0, ]; let snes_address = u32::from_le_bytes(room_pointer); let pc_address = snes_to_pc_address(snes_address); // Copy i'th room's headers to new room_header_table. let header_start = header_base + (i * 14); - self.rom_data.copy_within(pc_address..(pc_address + 14), header_start); + self.rom_data + .copy_within(pc_address..(pc_address + 14), header_start); } // Repoint the pointer table to the new header table. @@ -276,7 +291,8 @@ impl RomData { assert_eq!(snes[2], new_room_bank, "We changed banks in the middle of moving the room headers! This should have been caught by dev team, unless you were playing with files you shouldn't touch."); - self.rom_data[(table_base + (i * 2))..(table_base + (i * 2) + 1)].copy_from_slice(&snes[0..1]); + self.rom_data[(table_base + (i * 2))..(table_base + (i * 2) + 1)] + .copy_from_slice(&snes[0..1]); } } } From 034af7fa92c9e99441ca6c67b777f23f3af193a1 Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 09:58:10 -0400 Subject: [PATCH 5/6] More backwards compatibility. --- enemize/src/option_flags.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/enemize/src/option_flags.rs b/enemize/src/option_flags.rs index 4ff62cd..259f160 100644 --- a/enemize/src/option_flags.rs +++ b/enemize/src/option_flags.rs @@ -366,6 +366,7 @@ impl TryFrom for BeeLevel { } #[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] pub struct OptionFlags { pub randomize_enemies: bool, pub randomize_enemies_type: RandomizeEnemiesType, From 4cbc70eeca3e2f3702a6d63cd33e25bc0a443260 Mon Sep 17 00:00:00 2001 From: Lyle Mantooth Date: Sat, 4 Jun 2022 10:00:06 -0400 Subject: [PATCH 6/6] Make it easy to write options file. --- enemize/src/option_flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enemize/src/option_flags.rs b/enemize/src/option_flags.rs index 259f160..a8d2fd9 100644 --- a/enemize/src/option_flags.rs +++ b/enemize/src/option_flags.rs @@ -366,7 +366,7 @@ impl TryFrom for BeeLevel { } #[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "PascalCase")] +#[serde(default, rename_all = "PascalCase")] pub struct OptionFlags { pub randomize_enemies: bool, pub randomize_enemies_type: RandomizeEnemiesType,