Make it run (no actual randomizing yet).

This commit is contained in:
Lyle Mantooth 2022-06-04 09:39:52 -04:00
parent 87b0476b7e
commit 1113adca98
Signed by: IslandUsurper
GPG key ID: 6DB52EAE123A5789
5 changed files with 196 additions and 27 deletions

View file

@ -10,3 +10,105 @@ pub const NEW_BOSS_GRAPHICS: usize = 0x1B0000;
pub const RANDOM_SPRITE_GRAPHICS: usize = 0x300000; pub const RANDOM_SPRITE_GRAPHICS: usize = 0x300000;
pub const ENEMIZER_FILE_LENGTH: usize = 0x200000; pub const ENEMIZER_FILE_LENGTH: usize = 0x200000;
pub const HIDDEN_ENEMY_CHANCE_POOL: usize = 0xD7BBB; 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 ];

View file

@ -11,6 +11,7 @@ pub mod asar;
pub mod bosses; pub mod bosses;
pub mod constants; pub mod constants;
pub mod option_flags; pub mod option_flags;
pub mod randomize;
pub mod rom; pub mod rom;
#[derive(Debug, Error)] #[derive(Debug, Error)]

View file

@ -3,11 +3,14 @@ use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Instant; use std::time::Instant;
use anyhow::ensure; use anyhow::{bail, ensure};
use clap::Parser; use clap::Parser;
use enemize::{asar, rom::RomData}; 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 /// Randomizes enemy placements in The Legend of Zelda: A Link to the Past for the Super Nintendo
/// Entertainment System /// Entertainment System
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@ -17,7 +20,7 @@ struct Args {
rom: PathBuf, rom: PathBuf,
/// seed number /// seed number
#[clap(short, long)] #[clap(short, long)]
seed: Option<u32>, seed: Option<i32>,
/// path to the enemizerOptions.json /// path to the enemizerOptions.json
#[clap(short, long)] #[clap(short, long)]
enemizer: PathBuf, enemizer: PathBuf,
@ -34,7 +37,7 @@ fn main() -> anyhow::Result<()> {
let stopwatch = Instant::now(); let stopwatch = Instant::now();
let options = serde_json::from_reader(File::open(args.enemizer)?)?; 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 raw_data = vec![];
let mut rom_file = File::open(args.rom)?; let mut rom_file = File::open(args.rom)?;
@ -42,17 +45,24 @@ fn main() -> anyhow::Result<()> {
raw_data.resize(2 * 1024 * 1024, 0); raw_data.resize(2 * 1024 * 1024, 0);
let mut rom_data = RomData::new(symbols, raw_data); let mut rom = 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."); 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 { if args.binary {
out_file.write_all(rom.get_rom_bytes())?;
out_file.flush()?;
println!("Generated SFC file {}", args.output.to_string_lossy());
} else { } else {
let patches = rom.generate_patch();
serde_json::to_writer(out_file, &patches)?;
} }
println!("Seed generated in: {}ms", stopwatch.elapsed().as_millis()); println!("Seed generated in: {}ms", stopwatch.elapsed().as_millis());
@ -60,21 +70,10 @@ fn main() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
fn load_symbols(rom: &Path) -> anyhow::Result<asar::Symbols> { fn load_symbols() -> anyhow::Result<asar::Symbols> {
let sym_path = rom.with_extension("sym"); if let Err(_) = std::fs::metadata(ASAR_SYMBOLS) {
bail!("Could not find symbols at {}. Did you run prepare.sh?", ASAR_SYMBOLS);
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");
} }
asar::load_symbols(sym_path.as_path()) asar::load_symbols(Path::new(ASAR_SYMBOLS))
} }

29
enemize/src/randomize.rs Normal file
View file

@ -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(())
}
}

View file

@ -31,9 +31,9 @@ pub const RANDOMIZER_MODE_FLAG: usize = 0x180032;
pub struct RomData { pub struct RomData {
asar_symbols: Symbols, asar_symbols: Symbols,
spoiler: String, spoiler: String,
rom_data: Vec<u8>, pub(crate) rom_data: Vec<u8>,
patch_data: BTreeMap<usize, u8>, patch_data: BTreeMap<usize, u8>,
seed: i32, pub(crate) seed: i32,
} }
impl RomData { impl RomData {
@ -41,6 +41,25 @@ impl RomData {
self.spoiler.as_str() 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<Patch> { pub fn generate_patch(&self) -> Vec<Patch> {
let mut patches = vec![]; let mut patches = vec![];
@ -54,6 +73,10 @@ impl RomData {
patches patches
} }
pub fn get_rom_bytes(&self) -> &[u8] {
&self.rom_data
}
fn set_rom_bytes(&mut self, bytes: &[u8], range: Range<usize>) { fn set_rom_bytes(&mut self, bytes: &[u8], range: Range<usize>) {
self.rom_data.splice(range, bytes.into_iter().map(|&b| b)); self.rom_data.splice(range, bytes.into_iter().map(|&b| b));
} }
@ -92,6 +115,12 @@ impl RomData {
&self.rom_data[0x7FC0..0x7FCE] == b"ZELDANODENSETSU") &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) { 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.");
} }
@ -127,6 +156,15 @@ impl RomData {
self.set_patch_bytes(seed_start..seed_end); 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> { pub fn get_enemizer_version(&self) -> anyhow::Result<&str> {
if self.is_enemizer() { 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;
@ -208,7 +246,7 @@ impl RomData {
pub fn move_room_headers(&mut self) { pub fn move_room_headers(&mut self) {
let table_base = DUNGEON_HEADER_POINTER_TABLE; 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. // 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"]];