mirror of
https://github.com/zeldaret/oot.git
synced 2024-12-27 07:07:09 +00:00
Create macros for and decompile elf_message scripts (#999)
* elf_message * Review suggestions
This commit is contained in:
parent
a3b4dcf388
commit
9ca6bfdac3
6 changed files with 464 additions and 25 deletions
129
include/z64elf_message.h
Normal file
129
include/z64elf_message.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
#ifndef Z64ELF_MESSAGE_H
|
||||
#define Z64ELF_MESSAGE_H
|
||||
|
||||
#include "ultra64.h"
|
||||
|
||||
// Checks the condition and exits the script if the check passes
|
||||
#define ELF_MSG_TYPE_CHECK 0
|
||||
// ? (unused)
|
||||
#define ELF_MSG_TYPE_UNK_1 1
|
||||
// ? (unused)
|
||||
#define ELF_MSG_TYPE_UNK_2 2
|
||||
// Checks the condition and skips forward by some number of commands if the check passes
|
||||
#define ELF_MSG_TYPE_SKIP 3
|
||||
// Always ends the script, returning the text id for this command
|
||||
#define ELF_MSG_TYPE_END 7
|
||||
|
||||
// Check an eventChkInf flag
|
||||
#define ELF_MSG_CONDITION_FLAG 0
|
||||
// Check a dungeon item (map, compass, boss key)
|
||||
#define ELF_MSG_CONDITION_DUNGEON_ITEM 1
|
||||
// Check if an item is in an item slot
|
||||
#define ELF_MSG_CONDITION_ITEM 2
|
||||
// "Other" conditions described below
|
||||
#define ELF_MSG_CONDITION_OTHER 3
|
||||
|
||||
// Check what strength upgrade has been obtained so far
|
||||
#define ELF_MSG_CONDITION_STRENGTH_UPG 0
|
||||
// Check if specific boots have been obtained so far
|
||||
#define ELF_MSG_CONDITION_BOOTS 1
|
||||
// Check if a particular song has been obtained
|
||||
#define ELF_MSG_CONDITION_SONG 2
|
||||
// Check if a particular medallion has been obtained
|
||||
#define ELF_MSG_CONDITION_MEDALLION 3
|
||||
// Check if the magic meter has been obtained
|
||||
#define ELF_MSG_CONDITION_MAGIC 4
|
||||
|
||||
/*
|
||||
* Bitpack byte 0
|
||||
*/
|
||||
#define ELF_MSG_B0(type, cond_type, tf) \
|
||||
_SHIFTL(ELF_MSG_TYPE_##type, 5, 3) | \
|
||||
_SHIFTL(ELF_MSG_CONDITION_##cond_type, 1, 4) | \
|
||||
_SHIFTL(tf, 0, 1)
|
||||
|
||||
/*
|
||||
* Bitpack byte 1
|
||||
*/
|
||||
#define ELF_MSG_B1(cond_type, data) \
|
||||
_SHIFTL(ELF_MSG_CONDITION_##cond_type, 4, 4) | \
|
||||
_SHIFTL(data, 0, 4)
|
||||
|
||||
/*
|
||||
* Other bytes
|
||||
*/
|
||||
#define ELF_MSG_B(data) \
|
||||
_SHIFTL(data, 0, 8)
|
||||
|
||||
/*
|
||||
* Command macros
|
||||
*/
|
||||
|
||||
#define ELF_MSG_FLAG(type, textId, tf, flag) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, FLAG, tf), \
|
||||
ELF_MSG_B(flag), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(0), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_END(textId) \
|
||||
ELF_MSG_FLAG(END, textId, false, 0)
|
||||
|
||||
#define ELF_MSG_DUNGEON_ITEM(type, textId, tf, itemId) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, DUNGEON_ITEM, tf), \
|
||||
ELF_MSG_B(itemId), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(0), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_ITEM(type, textId, tf, slotItemId, itemId) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, ITEM, tf), \
|
||||
ELF_MSG_B(slotItemId), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(itemId), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_STRENGTH_UPG(type, textId, tf, strUpg) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, OTHER, tf), \
|
||||
ELF_MSG_B1(STRENGTH_UPG, strUpg), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(0), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_BOOTS(type, textId, tf, itemId) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, OTHER, tf), \
|
||||
ELF_MSG_B1(BOOTS, 0), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(itemId), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_SONG(type, textId, tf, itemId) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, OTHER, tf), \
|
||||
ELF_MSG_B1(SONG, 0), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(itemId), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_MEDALLION(type, textId, tf, itemId) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, OTHER, tf), \
|
||||
ELF_MSG_B1(MEDALLION, 0), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(itemId), \
|
||||
}
|
||||
|
||||
#define ELF_MSG_MAGIC(type, textId, tf) \
|
||||
{ \
|
||||
ELF_MSG_B0(type, OTHER, tf), \
|
||||
ELF_MSG_B1(MAGIC, 0), \
|
||||
ELF_MSG_B(textId), \
|
||||
ELF_MSG_B(0), \
|
||||
}
|
||||
|
||||
#endif
|
6
spec
6
spec
|
@ -6796,13 +6796,15 @@ endseg
|
|||
beginseg
|
||||
name "elf_message_field"
|
||||
romalign 0x1000
|
||||
include "build/baserom/elf_message_field.o"
|
||||
include "build/src/elf_message/elf_message_field.o"
|
||||
number 0
|
||||
endseg
|
||||
|
||||
beginseg
|
||||
name "elf_message_ydan"
|
||||
romalign 0x1000
|
||||
include "build/baserom/elf_message_ydan.o"
|
||||
include "build/src/elf_message/elf_message_ydan.o"
|
||||
number 0
|
||||
endseg
|
||||
|
||||
beginseg
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
#include "global.h"
|
||||
#include "z64elf_message.h"
|
||||
|
||||
// TODO: use macros to define elf messages once the format is fully documented
|
||||
ElfMessage sChildSariaMsgs[] = {
|
||||
{ 0x66, 0x00, 0x03, 0x00 }, { 0x00, 0x37, 0x61, 0x00 }, { 0xE0, 0x00, 0x64, 0x00 }, { 0x00, 0x25, 0x62, 0x00 },
|
||||
{ 0x00, 0x37, 0x63, 0x00 }, { 0x00, 0x43, 0x65, 0x00 }, { 0x06, 0x30, 0x66, 0x66 }, { 0x06, 0x30, 0x66, 0x67 },
|
||||
{ 0x06, 0x30, 0x66, 0x68 }, { 0x06, 0x20, 0x67, 0x65 }, { 0x06, 0x30, 0x68, 0x69 }, { 0x06, 0x30, 0x68, 0x6A },
|
||||
{ 0xE0, 0x00, 0x69, 0x00 },
|
||||
ELF_MSG_STRENGTH_UPG(SKIP, 3, false, 0),
|
||||
ELF_MSG_FLAG(CHECK, 0x61, false, 0x37), /* eventChkInf[3] & 0x80 */
|
||||
ELF_MSG_END(0x64),
|
||||
ELF_MSG_FLAG(CHECK, 0x62, false, 0x25), /* eventChkInf[2] & 0x20 */
|
||||
ELF_MSG_FLAG(CHECK, 0x63, false, 0x37), /* eventChkInf[3] & 0x80 */
|
||||
ELF_MSG_FLAG(CHECK, 0x65, false, 0x43), /* eventChkInf[4] & 0x8 */
|
||||
ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_FOREST),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_FIRE),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_WATER),
|
||||
ELF_MSG_SONG(CHECK, 0x67, false, ITEM_SONG_STORMS),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x68, false, ITEM_MEDALLION_SPIRIT),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x68, false, ITEM_MEDALLION_SHADOW),
|
||||
ELF_MSG_END(0x69),
|
||||
};
|
||||
|
||||
ElfMessage sAdultSariaMsgs[] = {
|
||||
{ 0x06, 0x30, 0x6A, 0x66 }, { 0x06, 0x30, 0x6B, 0x67 }, { 0x06, 0x30, 0x6B, 0x68 },
|
||||
{ 0x06, 0x30, 0x6C, 0x69 }, { 0x06, 0x30, 0x6C, 0x6A }, { 0xE0, 0x00, 0x6D, 0x00 },
|
||||
ELF_MSG_MEDALLION(CHECK, 0x6A, false, ITEM_MEDALLION_FOREST),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x6B, false, ITEM_MEDALLION_FIRE),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x6B, false, ITEM_MEDALLION_WATER),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x6C, false, ITEM_MEDALLION_SPIRIT),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x6C, false, ITEM_MEDALLION_SHADOW),
|
||||
ELF_MSG_END(0x6D),
|
||||
};
|
||||
|
||||
u32 ElfMessage_CheckCondition(ElfMessage* msg) {
|
||||
|
@ -18,29 +31,29 @@ u32 ElfMessage_CheckCondition(ElfMessage* msg) {
|
|||
u16 flag;
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
case (ELF_MSG_CONDITION_FLAG << 1):
|
||||
flag = 1 << (msg->byte1 & 0x0F);
|
||||
return ((msg->byte0 & 1) == 1) == ((flag & gSaveContext.eventChkInf[(msg->byte1 & 0xF0) >> 4]) != 0);
|
||||
case 2:
|
||||
case (ELF_MSG_CONDITION_DUNGEON_ITEM << 1):
|
||||
return ((msg->byte0 & 1) == 1) ==
|
||||
(CHECK_DUNGEON_ITEM(msg->byte1 - ITEM_KEY_BOSS, gSaveContext.mapIndex) != 0);
|
||||
case 4:
|
||||
case (ELF_MSG_CONDITION_ITEM << 1):
|
||||
return ((msg->byte0 & 1) == 1) == (msg->byte3 == INV_CONTENT(msg->byte1));
|
||||
case 6:
|
||||
case (ELF_MSG_CONDITION_OTHER << 1):
|
||||
switch (msg->byte1 & 0xF0) {
|
||||
case 0x00:
|
||||
case (ELF_MSG_CONDITION_STRENGTH_UPG << 4):
|
||||
return ((msg->byte0 & 1) == 1) == ((msg->byte1 & 0x0F) == CUR_UPG_VALUE(UPG_STRENGTH));
|
||||
case 0x10:
|
||||
case (ELF_MSG_CONDITION_BOOTS << 4):
|
||||
return ((msg->byte0 & 1) == 1) ==
|
||||
(((gBitFlags[msg->byte3 - ITEM_BOOTS_KOKIRI] << gEquipShifts[EQUIP_BOOTS]) &
|
||||
gSaveContext.inventory.equipment) != 0);
|
||||
case 0x20:
|
||||
case (ELF_MSG_CONDITION_SONG << 4):
|
||||
return ((msg->byte0 & 1) == 1) ==
|
||||
(CHECK_QUEST_ITEM(msg->byte3 - ITEM_SONG_MINUET + QUEST_SONG_MINUET) != 0);
|
||||
case 0x30:
|
||||
case (ELF_MSG_CONDITION_MEDALLION << 4):
|
||||
return ((msg->byte0 & 1) == 1) ==
|
||||
(CHECK_QUEST_ITEM(msg->byte3 - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST) != 0);
|
||||
case 0x40:
|
||||
case (ELF_MSG_CONDITION_MAGIC << 4):
|
||||
return ((msg->byte0 & 1) == 1) == (((void)0, gSaveContext.magicAcquired) != 0);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +67,7 @@ u32 ElfMessage_CheckCondition(ElfMessage* msg) {
|
|||
u32 func_8006BE88(ElfMessage** msgp) {
|
||||
u32 temp = true;
|
||||
|
||||
while (((*msgp)->byte0 & 0xE0) == 0x20) {
|
||||
while (((*msgp)->byte0 & 0xE0) == (ELF_MSG_TYPE_UNK_1 << 5)) {
|
||||
if (!ElfMessage_CheckCondition(*msgp)) {
|
||||
temp = false;
|
||||
}
|
||||
|
@ -80,7 +93,7 @@ u32 func_8006BF1C(ElfMessage** msgp) {
|
|||
temp1 += sp44[temp2];
|
||||
temp2++;
|
||||
msg++;
|
||||
} while ((msg->byte0 & 0xE0) == 0x40);
|
||||
} while ((msg->byte0 & 0xE0) == (ELF_MSG_TYPE_UNK_2 << 5));
|
||||
|
||||
if (temp1 == 0) {
|
||||
return false;
|
||||
|
@ -104,28 +117,28 @@ u32 func_8006BF1C(ElfMessage** msgp) {
|
|||
u16 ElfMessage_GetTextFromMsgs(ElfMessage* msg) {
|
||||
while (true) {
|
||||
switch (msg->byte0 & 0xE0) {
|
||||
case 0x00:
|
||||
case (ELF_MSG_TYPE_CHECK << 5):
|
||||
if (ElfMessage_CheckCondition(msg)) {
|
||||
return msg->byte2 | 0x100;
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
case (ELF_MSG_TYPE_UNK_1 << 5):
|
||||
if (func_8006BE88(&msg)) {
|
||||
return msg->byte2 | 0x100;
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
case (ELF_MSG_TYPE_UNK_2 << 5):
|
||||
if (func_8006BF1C(&msg)) {
|
||||
return msg->byte2 | 0x100;
|
||||
}
|
||||
break;
|
||||
case 0x60:
|
||||
case (ELF_MSG_TYPE_SKIP << 5):
|
||||
if (ElfMessage_CheckCondition(msg)) {
|
||||
msg += msg->byte2;
|
||||
msg--;
|
||||
}
|
||||
break;
|
||||
case 0xE0:
|
||||
case (ELF_MSG_TYPE_END << 5):
|
||||
return msg->byte2 | 0x100;
|
||||
default:
|
||||
LOG_STRING("企画外 条件", "../z_elf_message.c", 281); // "Unplanned conditions"
|
||||
|
|
33
src/elf_message/elf_message_field.c
Normal file
33
src/elf_message/elf_message_field.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "global.h"
|
||||
#include "z64elf_message.h"
|
||||
|
||||
ElfMessage gOverworldNaviMsgs[] = {
|
||||
ELF_MSG_FLAG(CHECK, 0x40, false, 0x05), /* eventChkInf[0] & 0x20 */
|
||||
ELF_MSG_FLAG(CHECK, 0x41, false, 0x09), /* eventChkInf[0] & 0x200 */
|
||||
ELF_MSG_FLAG(CHECK, 0x42, false, 0x12), /* eventChkInf[1] & 0x4 */
|
||||
ELF_MSG_FLAG(CHECK, 0x43, false, 0x14), /* eventChkInf[1] & 0x10 */
|
||||
ELF_MSG_FLAG(CHECK, 0x44, false, 0x40), /* eventChkInf[4] & 0x1 */
|
||||
ELF_MSG_SONG(CHECK, 0x45, false, ITEM_SONG_SARIA),
|
||||
ELF_MSG_STRENGTH_UPG(CHECK, 0x46, true, 0),
|
||||
ELF_MSG_FLAG(CHECK, 0x47, false, 0x25), /* eventChkInf[2] & 0x20 */
|
||||
ELF_MSG_MAGIC(CHECK, 0x48, false),
|
||||
ELF_MSG_FLAG(CHECK, 0x49, false, 0x33), /* eventChkInf[3] & 0x8 */
|
||||
ELF_MSG_FLAG(CHECK, 0x4A, false, 0x37), /* eventChkInf[3] & 0x80 */
|
||||
ELF_MSG_FLAG(CHECK, 0x4B, false, 0x80), /* eventChkInf[8] & 0x1 */
|
||||
ELF_MSG_FLAG(CHECK, 0x4C, false, 0x43), /* eventChkInf[4] & 0x8 */
|
||||
ELF_MSG_FLAG(CHECK, 0x4D, false, 0x45), /* eventChkInf[4] & 0x20 */
|
||||
ELF_MSG_ITEM(CHECK, 0x4E, true, ITEM_HOOKSHOT, ITEM_NONE),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x50, false, ITEM_MEDALLION_FOREST),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x51, false, ITEM_MEDALLION_FIRE),
|
||||
ELF_MSG_BOOTS(CHECK, 0x52, false, ITEM_BOOTS_IRON),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x53, false, ITEM_MEDALLION_WATER),
|
||||
ELF_MSG_FLAG(CHECK, 0x54, false, 0xAA), /* eventChkInf[10] & 0x400 */
|
||||
ELF_MSG_ITEM(CHECK, 0x55, true, ITEM_LENS, ITEM_NONE),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x57, false, ITEM_MEDALLION_SHADOW),
|
||||
ELF_MSG_SONG(CHECK, 0x58, false, ITEM_SONG_REQUIEM),
|
||||
ELF_MSG_STRENGTH_UPG(CHECK, 0x56, true, 1),
|
||||
ELF_MSG_MEDALLION(CHECK, 0x5A, false, ITEM_MEDALLION_SPIRIT),
|
||||
ELF_MSG_ITEM(CHECK, 0x5B, true, ITEM_ARROW_LIGHT, ITEM_NONE),
|
||||
ELF_MSG_FLAG(CHECK, 0x5C, false, 0xC3), /* eventChkInf[12] & 0x8 */
|
||||
ELF_MSG_END(0x5F),
|
||||
};
|
6
src/elf_message/elf_message_ydan.c
Normal file
6
src/elf_message/elf_message_ydan.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "global.h"
|
||||
#include "z64elf_message.h"
|
||||
|
||||
ElfMessage gDungeonNaviMsgs[] = {
|
||||
ELF_MSG_END(0x5F),
|
||||
};
|
256
tools/disasm_elf_msg.py
Normal file
256
tools/disasm_elf_msg.py
Normal file
|
@ -0,0 +1,256 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import struct, sys
|
||||
|
||||
item_ids = {
|
||||
0x00 : "ITEM_STICK",
|
||||
0x01 : "ITEM_NUT",
|
||||
0x02 : "ITEM_BOMB",
|
||||
0x03 : "ITEM_BOW",
|
||||
0x04 : "ITEM_ARROW_FIRE",
|
||||
0x05 : "ITEM_DINS_FIRE",
|
||||
0x06 : "ITEM_SLINGSHOT",
|
||||
0x07 : "ITEM_OCARINA_FAIRY",
|
||||
0x08 : "ITEM_OCARINA_TIME",
|
||||
0x09 : "ITEM_BOMBCHU",
|
||||
0x0A : "ITEM_HOOKSHOT",
|
||||
0x0B : "ITEM_LONGSHOT",
|
||||
0x0C : "ITEM_ARROW_ICE",
|
||||
0x0D : "ITEM_FARORES_WIND",
|
||||
0x0E : "ITEM_BOOMERANG",
|
||||
0x0F : "ITEM_LENS",
|
||||
0x10 : "ITEM_BEAN",
|
||||
0x11 : "ITEM_HAMMER",
|
||||
0x12 : "ITEM_ARROW_LIGHT",
|
||||
0x13 : "ITEM_NAYRUS_LOVE",
|
||||
0x14 : "ITEM_BOTTLE",
|
||||
0x15 : "ITEM_POTION_RED",
|
||||
0x16 : "ITEM_POTION_GREEN",
|
||||
0x17 : "ITEM_POTION_BLUE",
|
||||
0x18 : "ITEM_FAIRY",
|
||||
0x19 : "ITEM_FISH",
|
||||
0x1A : "ITEM_MILK_BOTTLE",
|
||||
0x1B : "ITEM_LETTER_RUTO",
|
||||
0x1C : "ITEM_BLUE_FIRE",
|
||||
0x1D : "ITEM_BUG",
|
||||
0x1E : "ITEM_BIG_POE",
|
||||
0x1F : "ITEM_MILK_HALF",
|
||||
0x20 : "ITEM_POE",
|
||||
0x21 : "ITEM_WEIRD_EGG",
|
||||
0x22 : "ITEM_CHICKEN",
|
||||
0x23 : "ITEM_LETTER_ZELDA",
|
||||
0x24 : "ITEM_MASK_KEATON",
|
||||
0x25 : "ITEM_MASK_SKULL",
|
||||
0x26 : "ITEM_MASK_SPOOKY",
|
||||
0x27 : "ITEM_MASK_BUNNY",
|
||||
0x28 : "ITEM_MASK_GORON",
|
||||
0x29 : "ITEM_MASK_ZORA",
|
||||
0x2A : "ITEM_MASK_GERUDO",
|
||||
0x2B : "ITEM_MASK_TRUTH",
|
||||
0x2C : "ITEM_SOLD_OUT",
|
||||
0x2D : "ITEM_POCKET_EGG",
|
||||
0x2E : "ITEM_POCKET_CUCCO",
|
||||
0x2F : "ITEM_COJIRO",
|
||||
0x30 : "ITEM_ODD_MUSHROOM",
|
||||
0x31 : "ITEM_ODD_POTION",
|
||||
0x32 : "ITEM_SAW",
|
||||
0x33 : "ITEM_SWORD_BROKEN",
|
||||
0x34 : "ITEM_PRESCRIPTION",
|
||||
0x35 : "ITEM_FROG",
|
||||
0x36 : "ITEM_EYEDROPS",
|
||||
0x37 : "ITEM_CLAIM_CHECK",
|
||||
0x38 : "ITEM_BOW_ARROW_FIRE",
|
||||
0x39 : "ITEM_BOW_ARROW_ICE",
|
||||
0x3A : "ITEM_BOW_ARROW_LIGHT",
|
||||
0x3B : "ITEM_SWORD_KOKIRI",
|
||||
0x3C : "ITEM_SWORD_MASTER",
|
||||
0x3D : "ITEM_SWORD_BGS",
|
||||
0x3E : "ITEM_SHIELD_DEKU",
|
||||
0x3F : "ITEM_SHIELD_HYLIAN",
|
||||
0x40 : "ITEM_SHIELD_MIRROR",
|
||||
0x41 : "ITEM_TUNIC_KOKIRI",
|
||||
0x42 : "ITEM_TUNIC_GORON",
|
||||
0x43 : "ITEM_TUNIC_ZORA",
|
||||
0x44 : "ITEM_BOOTS_KOKIRI",
|
||||
0x45 : "ITEM_BOOTS_IRON",
|
||||
0x46 : "ITEM_BOOTS_HOVER",
|
||||
0x47 : "ITEM_BULLET_BAG_30",
|
||||
0x48 : "ITEM_BULLET_BAG_40",
|
||||
0x49 : "ITEM_BULLET_BAG_50",
|
||||
0x4A : "ITEM_QUIVER_30",
|
||||
0x4B : "ITEM_QUIVER_40",
|
||||
0x4C : "ITEM_QUIVER_50",
|
||||
0x4D : "ITEM_BOMB_BAG_20",
|
||||
0x4E : "ITEM_BOMB_BAG_30",
|
||||
0x4F : "ITEM_BOMB_BAG_40",
|
||||
0x50 : "ITEM_BRACELET",
|
||||
0x51 : "ITEM_GAUNTLETS_SILVER",
|
||||
0x52 : "ITEM_GAUNTLETS_GOLD",
|
||||
0x53 : "ITEM_SCALE_SILVER",
|
||||
0x54 : "ITEM_SCALE_GOLDEN",
|
||||
0x55 : "ITEM_SWORD_KNIFE",
|
||||
0x56 : "ITEM_WALLET_ADULT",
|
||||
0x57 : "ITEM_WALLET_GIANT",
|
||||
0x58 : "ITEM_SEEDS",
|
||||
0x59 : "ITEM_FISHING_POLE",
|
||||
0x5A : "ITEM_SONG_MINUET",
|
||||
0x5B : "ITEM_SONG_BOLERO",
|
||||
0x5C : "ITEM_SONG_SERENADE",
|
||||
0x5D : "ITEM_SONG_REQUIEM",
|
||||
0x5E : "ITEM_SONG_NOCTURNE",
|
||||
0x5F : "ITEM_SONG_PRELUDE",
|
||||
0x60 : "ITEM_SONG_LULLABY",
|
||||
0x61 : "ITEM_SONG_EPONA",
|
||||
0x62 : "ITEM_SONG_SARIA",
|
||||
0x63 : "ITEM_SONG_SUN",
|
||||
0x64 : "ITEM_SONG_TIME",
|
||||
0x65 : "ITEM_SONG_STORMS",
|
||||
0x66 : "ITEM_MEDALLION_FOREST",
|
||||
0x67 : "ITEM_MEDALLION_FIRE",
|
||||
0x68 : "ITEM_MEDALLION_WATER",
|
||||
0x69 : "ITEM_MEDALLION_SPIRIT",
|
||||
0x6A : "ITEM_MEDALLION_SHADOW",
|
||||
0x6B : "ITEM_MEDALLION_LIGHT",
|
||||
0x6C : "ITEM_KOKIRI_EMERALD",
|
||||
0x6D : "ITEM_GORON_RUBY",
|
||||
0x6E : "ITEM_ZORA_SAPPHIRE",
|
||||
0x6F : "ITEM_STONE_OF_AGONY",
|
||||
0x70 : "ITEM_GERUDO_CARD",
|
||||
0x71 : "ITEM_SKULL_TOKEN",
|
||||
0x72 : "ITEM_HEART_CONTAINER",
|
||||
0x73 : "ITEM_HEART_PIECE",
|
||||
0x74 : "ITEM_KEY_BOSS",
|
||||
0x75 : "ITEM_COMPASS",
|
||||
0x76 : "ITEM_DUNGEON_MAP",
|
||||
0x77 : "ITEM_KEY_SMALL",
|
||||
0x78 : "ITEM_MAGIC_SMALL",
|
||||
0x79 : "ITEM_MAGIC_LARGE",
|
||||
0x7A : "ITEM_HEART_PIECE_2",
|
||||
0x7B : "ITEM_INVALID_1",
|
||||
0x7C : "ITEM_INVALID_2",
|
||||
0x7D : "ITEM_INVALID_3",
|
||||
0x7E : "ITEM_INVALID_4",
|
||||
0x7F : "ITEM_INVALID_5",
|
||||
0x80 : "ITEM_INVALID_6",
|
||||
0x81 : "ITEM_INVALID_7",
|
||||
0x82 : "ITEM_MILK",
|
||||
0x83 : "ITEM_HEART",
|
||||
0x84 : "ITEM_RUPEE_GREEN",
|
||||
0x85 : "ITEM_RUPEE_BLUE",
|
||||
0x86 : "ITEM_RUPEE_RED",
|
||||
0x87 : "ITEM_RUPEE_PURPLE",
|
||||
0x88 : "ITEM_RUPEE_GOLD",
|
||||
0x89 : "ITEM_INVALID_8",
|
||||
0x8A : "ITEM_STICKS_5",
|
||||
0x8B : "ITEM_STICKS_10",
|
||||
0x8C : "ITEM_NUTS_5",
|
||||
0x8D : "ITEM_NUTS_10",
|
||||
0x8E : "ITEM_BOMBS_5",
|
||||
0x8F : "ITEM_BOMBS_10",
|
||||
0x90 : "ITEM_BOMBS_20",
|
||||
0x91 : "ITEM_BOMBS_30",
|
||||
0x92 : "ITEM_ARROWS_SMALL",
|
||||
0x93 : "ITEM_ARROWS_MEDIUM",
|
||||
0x94 : "ITEM_ARROWS_LARGE",
|
||||
0x95 : "ITEM_SEEDS_30",
|
||||
0x96 : "ITEM_BOMBCHUS_5",
|
||||
0x97 : "ITEM_BOMBCHUS_20",
|
||||
0x98 : "ITEM_STICK_UPGRADE_20",
|
||||
0x99 : "ITEM_STICK_UPGRADE_30",
|
||||
0x9A : "ITEM_NUT_UPGRADE_30",
|
||||
0x9B : "ITEM_NUT_UPGRADE_40",
|
||||
0xFC : "ITEM_LAST_USED",
|
||||
0xFE : "ITEM_NONE_FE",
|
||||
0xFF : "ITEM_NONE",
|
||||
}
|
||||
|
||||
def disas_elfmsgs(start):
|
||||
baserom = None
|
||||
with open("baserom.z64", "rb") as infile:
|
||||
baserom = bytearray(infile.read())
|
||||
|
||||
branches = []
|
||||
pos = start
|
||||
|
||||
while (True):
|
||||
print(f"/* {pos - start:04X} {((pos - start) // 4):3} */ ", end="")
|
||||
|
||||
b0, b1, b2, b3 = struct.unpack(">BBBB", baserom[pos:pos+4])
|
||||
|
||||
elf_message_types = {
|
||||
0x00: "CHECK",
|
||||
0x20: "UNK_1",
|
||||
0x40: "UNK_2",
|
||||
0x60: "SKIP",
|
||||
0xE0: "END",
|
||||
}
|
||||
|
||||
cont = True
|
||||
branch_to = None
|
||||
|
||||
# Get Type
|
||||
|
||||
elf_message_type = b0 & 0xE0
|
||||
ARG_0 = elf_message_types[elf_message_type]
|
||||
|
||||
if elf_message_type in [0, 0x20, 0x40, 0xE0]:
|
||||
if elf_message_type == 0xE0:
|
||||
cont = False
|
||||
ARG_1 = f"0x{(b2 & 0xFF):04X}"
|
||||
elif elf_message_type == 0x60:
|
||||
branch_to = 4 * (b2 & 0xFF)
|
||||
ARG_1 = (b2 & 0xFF)
|
||||
else:
|
||||
assert False , "Encountered unknown type"
|
||||
|
||||
ARG_2 = f"{bool(b0 & 1)}".lower()
|
||||
|
||||
# Get condition
|
||||
condition_type = b0 & 0x1E
|
||||
|
||||
if condition_type == 0:
|
||||
if elf_message_type == 0xE0 and b1 == 0 and not (b0 & 1):
|
||||
print(f"ELF_MSG_END({ARG_1}),")
|
||||
else:
|
||||
print(f"ELF_MSG_FLAG({ARG_0}, {ARG_1}, {ARG_2}, 0x{b1:02X}), /* eventChkInf[{(b1 >> 4) & 0xF}] & 0x{1 << (b1 & 0xF):X} */")
|
||||
assert b3 == 0
|
||||
elif condition_type == 2:
|
||||
print(f"ELF_MSG_DUNGEON_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}),")
|
||||
assert b3 == 0
|
||||
elif condition_type == 4:
|
||||
print(f"ELF_MSG_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}, {item_ids[b3]}),")
|
||||
elif condition_type == 6:
|
||||
condition_other_type = b1 & 0xF0
|
||||
|
||||
if condition_other_type == 0:
|
||||
print(f"ELF_MSG_STRENGTH_UPG({ARG_0}, {ARG_1}, {ARG_2}, {b1 & 0xF}),")
|
||||
assert b3 == 0
|
||||
elif condition_other_type == 0x10:
|
||||
print(f"ELF_MSG_BOOTS({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),")
|
||||
assert (b1 & 0xF) == 0
|
||||
elif condition_other_type == 0x20:
|
||||
print(f"ELF_MSG_SONG({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),")
|
||||
assert (b1 & 0xF) == 0
|
||||
elif condition_other_type == 0x30:
|
||||
print(f"ELF_MSG_MEDALLION({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),")
|
||||
assert (b1 & 0xF) == 0
|
||||
elif condition_other_type == 0x40:
|
||||
print(f"ELF_MSG_MAGIC({ARG_0}, {ARG_1}, {ARG_2}),")
|
||||
assert (b1 & 0xF) == 0
|
||||
assert b3 == 0
|
||||
else:
|
||||
assert False , "Encountered unknown condition (other) type"
|
||||
else:
|
||||
assert False , "Encountered unknown condition type"
|
||||
|
||||
# Control flow
|
||||
|
||||
if branch_to is not None:
|
||||
branches.append(branch_to)
|
||||
pos += 4
|
||||
if not cont:
|
||||
print("")
|
||||
if not cont and all([dst < pos - start for dst in branches]):
|
||||
break
|
||||
|
||||
disas_elfmsgs(int(sys.argv[1],16))
|
Loading…
Reference in a new issue