From e52d135e15be227326b58d75d6779fbb1db6f232 Mon Sep 17 00:00:00 2001 From: cadmic Date: Sat, 7 Sep 2024 11:37:15 -0700 Subject: [PATCH] [ntsc-1.2] Import n64dd code from Decompollaborate/n64dd (#2136) * Import n64dd code from Decompollaborate/n64dd Co-authored-by: Anghelo Carvajal Co-authored-by: Elliptic Ellipsis * Don't stub out missing textures * Remove @brief * Add low-effort file comments * Match OoT if style * Fix n64dd matching due to int vs long * Fix English n64dd error textures * Compress n64dd segment * Align n64dd to 0x40 --------- Co-authored-by: Anghelo Carvajal Co-authored-by: Elliptic Ellipsis --- assets/xml/n64dd/error_textures.xml | 8 + baseroms/ntsc-1.2/config.yml | 4 + extract_assets.py | 2 +- include/functions.h | 2 + include/n64dd.h | 80 +++ include/variables.h | 1 + include/z64.h | 4 + spec | 13 +- src/n64dd/n64dd_801C8000.c | 345 ++++++++++++ src/n64dd/n64dd_801C8940.c | 398 +++++++++++++ src/n64dd/n64dd_801C9440.c | 263 +++++++++ src/n64dd/n64dd_801C9B70.c | 172 ++++++ src/n64dd/n64dd_801CA0B0.c | 243 ++++++++ src/n64dd/n64dd_data_buffer.c | 5 + src/n64dd/n64dd_error_bodies.c | 47 ++ src/n64dd/n64dd_error_headers.c | 5 + src/n64dd/n64dd_error_textures.c | 23 + src/n64dd/z_n64dd.c | 584 ++++++++++++++++++++ src/overlays/actors/ovl_Fishing/z_fishing.c | 2 +- tools/disasm/ntsc-1.2/variables.txt | 2 - tools/fix_bss.py | 1 + undefined_syms.txt | 25 - 22 files changed, 2199 insertions(+), 30 deletions(-) create mode 100644 assets/xml/n64dd/error_textures.xml create mode 100644 src/n64dd/n64dd_801C8000.c create mode 100644 src/n64dd/n64dd_801C8940.c create mode 100644 src/n64dd/n64dd_801C9440.c create mode 100644 src/n64dd/n64dd_801C9B70.c create mode 100644 src/n64dd/n64dd_801CA0B0.c create mode 100644 src/n64dd/n64dd_data_buffer.c create mode 100644 src/n64dd/n64dd_error_bodies.c create mode 100644 src/n64dd/n64dd_error_headers.c create mode 100644 src/n64dd/n64dd_error_textures.c create mode 100644 src/n64dd/z_n64dd.c diff --git a/assets/xml/n64dd/error_textures.xml b/assets/xml/n64dd/error_textures.xml new file mode 100644 index 0000000000..6db2ab37d5 --- /dev/null +++ b/assets/xml/n64dd/error_textures.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/baseroms/ntsc-1.2/config.yml b/baseroms/ntsc-1.2/config.yml index a64d9547ec..306b953484 100644 --- a/baseroms/ntsc-1.2/config.yml +++ b/baseroms/ntsc-1.2/config.yml @@ -75,6 +75,10 @@ assets: xml_path: assets/xml/code/fbdemo_wipe1.xml start_offset: 0xEB610 end_offset: 0xEBFA0 +- name: n64dd/error_textures + xml_path: assets/xml/n64dd/error_textures.xml + start_offset: 0xC120 + end_offset: 0x11D20 - name: misc/link_animetion xml_path: assets/xml/misc/link_animetion.xml - name: misc/z_select_static diff --git a/extract_assets.py b/extract_assets.py index 905004cfd1..da9715a5ac 100755 --- a/extract_assets.py +++ b/extract_assets.py @@ -32,7 +32,7 @@ def ExtractFile(assetConfig: version_config.AssetConfig, outputPath: Path, outpu execStr = f"{zapdPath} e -eh -i {xmlPath} -b {globalBaseromSegmentsDir} -o {outputPath} -osf {outputSourcePath} -gsf 1 -rconf {configPath} --cs-float both {ZAPDArgs}" - if name.startswith("code/") or name.startswith("overlays/"): + if name.startswith("code/") or name.startswith("n64dd/") or name.startswith("overlays/"): assert assetConfig.start_offset is not None assert assetConfig.end_offset is not None diff --git a/include/functions.h b/include/functions.h index 403cd89b26..ee7a203a62 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1395,6 +1395,8 @@ void Audio_SetCutsceneFlag(s8 flag); void Audio_PlaySfxIfNotInCutscene(u16 sfxId); void func_800F6964(u16); void Audio_StopBgmAndFanfare(u16 fadeOutDuration); +void func_800F6B3C(void); +void func_800F6BDC(void); void Audio_PreNMI(void); void Audio_SetNatureAmbienceChannelIO(u8 channelIdxRange, u8 ioPort, u8 ioData); void Audio_PlayNatureAmbienceSequence(u8 natureAmbienceId); diff --git a/include/n64dd.h b/include/n64dd.h index 4f117f682d..6931eac26c 100644 --- a/include/n64dd.h +++ b/include/n64dd.h @@ -2,6 +2,7 @@ #define N64DD_H #include "ultra64.h" +#include "ultra64/leo.h" #include "z64pause.h" #include "z64scene.h" #include "z64map_mark.h" @@ -59,6 +60,35 @@ typedef struct n64ddStruct_80121220 { s32 (*unk_78)(struct PlayState*, void*, void*); } n64ddStruct_80121220; // size = ? +typedef struct struct_801E0D18 { + /* 0x00 */ LEOCmd unk_00; + /* 0x1C */ OSMesgQueue unk_1C; + /* 0x38 */ LEODiskID diskId; + /* 0x58 */ UNK_TYPE unk_58; + /* 0x5C */ UNK_TYPE unk_5C; + /* 0x60 */ u32 unk_60; + /* 0x64 */ u8 unk_64; + /* 0x65 */ u8 unk_65; + /* 0x66 */ u8 unk_66; + /* 0x68 */ s32 unk_68; + /* 0x6C */ s32 unk_6C; +} struct_801E0D18; // size = 0x70 + +typedef struct struct_801D9D50 { + /* 0x00 */ u8 unk_00; // command enum + /* 0x04 */ s32 unk_04; + /* 0x08 */ u8 unk_08; + /* 0x0C */ void (*unk_0C)(void*, void*, void*); + /* 0x10 */ s32 unk_10; + /* 0x14 */ void (*unk_14)(void*, uintptr_t, size_t); + /* 0x18 */ void* unk_18; + /* 0x1C */ void* unk_1C; // either OSMesgQueue* (command 0) or integer LBA (commands 2 and 3) + /* 0x20 */ void* unk_20; // either OSMesgQueue* (command 0) or integer byte size (commands 3 and 4) + /* 0x24 */ OSId unk_24; + /* 0x28 */ void* unk_28; + /* 0x2C */ OSPri unk_2C; +} struct_801D9D50; // size = 0x30 + void func_800AD410(void); void func_800AD488(void); n64ddStruct_80121220* func_800AD4C0(n64ddStruct_80121220* arg0); @@ -77,6 +107,35 @@ void func_801C7C1C(void* dest, s32 offset, s32 size); void func_801C7E78(void); void n64dd_SetDiskVersion(s32 arg0); +s32 func_801C8000(struct_801D9D50* arg0); +s32 func_801C81C4(void); +void func_801C81EC(struct_801E0D18* arg0); +void func_801C8298(struct_801E0D18* arg0); +void func_801C82E0(struct_801E0D18* arg0); +void func_801C832C(struct_801E0D18* arg0); +void func_801C83A0(struct_801E0D18* arg0); +void func_801C8414(struct_801E0D18* arg0); +s32 func_801C873C(struct_801E0D18* arg0); + +void func_801C8AA8(void); +s32 func_801C91E0(struct_801E0D18*); +s32 func_801C9260(struct_801E0D18*); +s32 func_801C9334(struct_801E0D18*); +s32 func_801C93C4(struct_801E0D18*); + +void func_801C94F8(u8* arg0, u16 arg1); +void func_801C9A10(u8* arg0, s32 arg1, u8* str); +void func_801C9B50(s32 arg0, void (*arg1)(void*, uintptr_t, size_t)); + +u8* func_801C9E28(s32 errorNum); +u8* func_801C9EC0(void); +u8* func_801C9F90(s32 errorNum); +u8* func_801C9FFC(void); +u8* func_801CA030(s32 errorNum); +u8* func_801CA070(void); + +void func_801CA1F0(void* charTexBuf, s32 posX, s32 posY, s32 dx, s32 dy, s32 cy, void* frameBuf, s32 screenWidth); + extern n64ddStruct_800FEE70_pointers D_800FEE70; extern n64ddStruct_80121220* B_80121220; @@ -86,4 +145,25 @@ extern u8 D_80121212; extern vu8 D_80121213; extern vu8 D_80121214; +extern s32 (*D_801D2E54)(struct_801E0D18*); + +extern u8 B_801DC000[]; + +extern s32 D_801D2E90; +extern OSMesgQueue* B_801E0D10[2]; + +extern s32 D_801D2EA0; +extern s32 D_801D2EA8; +extern s32 B_801E0F60; +extern s32 B_801E0F64; +extern void (*D_801D2EB4)(void*, void*, void*); + +// Error messages +extern const char* D_801D2ED0[]; // "Error Number " array +extern const char* D_801D2EE0[2][8][4]; // Array of error message strings + +// Error textures +extern u64 gN64DDError41Texs[2][0x600 / sizeof(u64)]; +extern u64 gN64DDPleaseReadManualTexs[2][0x2800 / sizeof(u64)]; + #endif diff --git a/include/variables.h b/include/variables.h index bf4fb15c52..dc01f712da 100644 --- a/include/variables.h +++ b/include/variables.h @@ -203,6 +203,7 @@ extern PreNmiBuff* gAppNmiBufferPtr; extern uintptr_t gSegments[NUM_SEGMENTS]; extern Scheduler gScheduler; extern PadMgr gPadMgr; +extern IrqMgr gIrqMgr; extern volatile OSTime gAudioThreadUpdateTimeTotalPerGfxTask; extern volatile OSTime gGfxTaskSentToNextReadyMinusAudioThreadUpdateTime; extern volatile OSTime gRSPAudioTimeTotal; diff --git a/include/z64.h b/include/z64.h index 7a6187a485..377a760ce5 100644 --- a/include/z64.h +++ b/include/z64.h @@ -76,6 +76,8 @@ #define THREAD_PRI_DMAMGR_LOW 10 // Used when decompressing files #define THREAD_PRI_GRAPH 11 #define THREAD_PRI_AUDIOMGR 12 +#define THREAD_PRI_N64DD 13 +#define THREAD_PRI_DDMSG 13 #define THREAD_PRI_PADMGR 14 #define THREAD_PRI_MAIN 15 #define THREAD_PRI_SCHED 15 @@ -90,6 +92,8 @@ #define THREAD_ID_GRAPH 4 #define THREAD_ID_SCHED 5 #define THREAD_ID_PADMGR 7 +#define THREAD_ID_N64DD 8 +#define THREAD_ID_DDMSG 9 #define THREAD_ID_AUDIOMGR 10 #define THREAD_ID_DMAMGR 18 #define THREAD_ID_IRQMGR 19 diff --git a/spec b/spec index 378485e84b..0f9befd969 100644 --- a/spec +++ b/spec @@ -788,7 +788,18 @@ endseg #if PLATFORM_N64 beginseg name "n64dd" - // TODO: remaining n64dd files + compress + align 0x40 + include "$(BUILD_DIR)/src/n64dd/z_n64dd.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_data_buffer.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_801C8000.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_801C8940.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_801C9440.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_801C9B70.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_error_headers.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_error_bodies.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_error_textures.o" + include "$(BUILD_DIR)/src/n64dd/n64dd_801CA0B0.o" include "$(BUILD_DIR)/src/libleo/api/readwrite.o" include "$(BUILD_DIR)/src/libleo/leo/leofunc.o" include "$(BUILD_DIR)/src/libleo/leo/leoram.o" diff --git a/src/n64dd/n64dd_801C8000.c b/src/n64dd/n64dd_801C8000.c new file mode 100644 index 0000000000..3bf7159aab --- /dev/null +++ b/src/n64dd/n64dd_801C8000.c @@ -0,0 +1,345 @@ +// Does some command processing +#include "global.h" +#include "n64dd.h" +#include "versions.h" + +void func_801C8554(void); +void func_801C8578(void* arg0, void* arg1, OSId id, void* sp, OSPri pri); +void func_801C8638(void (*arg0)(void*, void*, void*), s32 arg1, void (*arg2)(void*, uintptr_t, size_t)); +void func_801C868C(void* arg0, void* arg1, void* arg2, u8 arg3); +s8 func_801C8770(void); +s32 func_801C87C0(void); +s32 func_801C87FC(void); +s32 func_801C8844(void); +s32 func_801C885C(void); +s32 func_801C88AC(void); +s32 func_801C88FC(void); + +s32 D_801D2E60 = 0; +s32 D_801D2E64 = 0; + +typedef struct struct_801D2E68 { + /* 0x0 */ void (*unk_0)(struct_801E0D18*); + /* 0x4 */ s32 (*unk_4)(struct_801E0D18*); +} struct_801D2E68; // size = 0x8 + +struct_801D2E68 D_801D2E68[5] = { + { func_801C81EC, func_801C91E0 }, { func_801C832C, func_801C9260 }, { func_801C83A0, func_801C9260 }, + { func_801C8414, func_801C9334 }, { func_801C8414, func_801C93C4 }, +}; + +s32 D_801D2E90 = 0; + +OSMesgQueue* B_801E0D10[2]; +struct_801E0D18 B_801E0D18; +OSMesg B_801E0D88[1]; +OSMesg B_801E0D90[8]; +OSThread B_801E0DB0; + +s32 func_801C8000(struct_801D9D50* arg0) { + switch (arg0->unk_00) { + case 0: + if (func_801C8844() != 0) { + return 1; + } + func_801C8554(); + break; + case 1: + func_801C8578(arg0->unk_1C, arg0->unk_20, arg0->unk_24, arg0->unk_28, arg0->unk_2C); + break; + case 2: + func_801C8638(arg0->unk_0C, arg0->unk_10, arg0->unk_14); + break; + case 3: + if (func_801C8844() != 0) { + return 1; + } + func_801C868C(arg0->unk_18, arg0->unk_1C, arg0->unk_20, 1); + break; + case 4: + if (func_801C8844() != 0) { + return 1; + } + func_801C868C(arg0->unk_18, arg0->unk_1C, arg0->unk_20, 2); + break; + case 5: + arg0->unk_08 = func_801C8770(); + return arg0->unk_08; + case 7: + return func_801C87FC(); + case 6: + return func_801C8844(); + case 8: + arg0->unk_04 = func_801C87C0(); + return arg0->unk_04; + case 9: + return func_801C885C(); + case 10: + return func_801C88AC(); + case 11: + return func_801C88FC(); + case 12: + D_801D2EA0 = 0; + break; + case 13: + D_801D2EA0 = 1; + break; + } + return 0; +} + +void func_801C819C(UNK_TYPE arg0) { + if (arg0 != 0) { + D_801D2E60 = 1; + } else { + D_801D2E60 = 2; + } +} + +s32 func_801C81C4(void) { + return D_801D2E60; +} + +s32 func_801C81D4(void) { + return D_801D2E64 == 1; +} + +void func_801C81EC(struct_801E0D18* arg0) { + osCreateMesgQueue(&arg0->unk_1C, B_801E0D88, ARRAY_COUNT(B_801E0D88)); + + if (gCurrentRegion == 1) { + arg0->unk_68 = LeoCJCreateLeoManager(LEO_PRIORITY_WRK, LEO_PRIORITY_INT, B_801E0D90, ARRAY_COUNT(B_801E0D90)); + } else { + arg0->unk_68 = LeoCACreateLeoManager(LEO_PRIORITY_WRK, LEO_PRIORITY_INT, B_801E0D90, ARRAY_COUNT(B_801E0D90)); + } + + if ((arg0->unk_68 == LEO_ERROR_DEVICE_COMMUNICATION_FAILURE) || (arg0->unk_68 == LEO_ERROR_GOOD)) { + D_801D2E64 = 1; + } +} + +void func_801C8298(struct_801E0D18* arg0) { + LEOCmd sp1C; + + // TODO: passing a pointer as a logical block address? + LeoSeek(&sp1C, (u32)&arg0->diskId, &arg0->unk_1C); + osRecvMesg(&arg0->unk_1C, (OSMesg*)&arg0->unk_68, OS_MESG_BLOCK); +} + +void func_801C82E0(struct_801E0D18* arg0) { + LEOCmd sp1C; + + LeoSpdlMotor(&sp1C, 4, &arg0->unk_1C); + osRecvMesg(&arg0->unk_1C, (OSMesg*)&arg0->unk_68, OS_MESG_BLOCK); +} + +void func_801C832C(struct_801E0D18* arg0) { + s32 sp34; + s32 startLBA = arg0->unk_5C; + + if (LeoByteToLBA(startLBA, arg0->unk_60, &sp34) == LEO_ERROR_GOOD) { + OSMesgQueue* sp28 = &arg0->unk_1C; + + LeoReadWrite(&arg0->unk_00, OS_READ, startLBA, (void*)arg0->unk_58, sp34, sp28); + osRecvMesg(sp28, (OSMesg*)&arg0->unk_68, OS_MESG_BLOCK); + } +} + +void func_801C83A0(struct_801E0D18* arg0) { + s32 sp34; + s32 startLBA = arg0->unk_58; + + if (LeoByteToLBA(startLBA, arg0->unk_60, &sp34) == LEO_ERROR_GOOD) { + OSMesgQueue* sp28 = &arg0->unk_1C; + + LeoReadWrite(&arg0->unk_00, OS_WRITE, startLBA, (void*)arg0->unk_5C, sp34, sp28); + osRecvMesg(sp28, (OSMesg*)&arg0->unk_68, OS_MESG_BLOCK); + } +} + +void func_801C8414(struct_801E0D18* arg0) { + arg0->unk_68 = 9; +} + +void func_801C8424(struct_801E0D18* arg0) { + struct_801D2E68* temp_v0; + s32 (*temp_s2)(struct_801E0D18*); + void (*aux)(struct_801E0D18*); + s32 temp_v0_2; + + arg0->unk_68 = -1; + if ((func_801C81D4() != 0) || (arg0->unk_64 == 0)) { + arg0->unk_66 = 1; + temp_v0 = &D_801D2E68[arg0->unk_64]; + aux = temp_v0->unk_0; + temp_s2 = temp_v0->unk_4; + do { + aux(arg0); + temp_v0_2 = temp_s2(arg0); + } while (temp_v0_2 == 2); + arg0->unk_6C = temp_v0_2; + if (arg0->unk_64 == 0) { + func_801C819C(temp_v0_2); + } + arg0->unk_66 = 0; + } +} + +void func_801C84D4(void* arg) { + while (true) { + struct_801E0D18* sp24; + + osRecvMesg(B_801E0D10[0], (OSMesg*)&sp24, OS_MESG_BLOCK); + func_801C8424(sp24); + osSendMesg(B_801E0D10[1], NULL, OS_MESG_BLOCK); + } +} + +void func_801C8554(void) { + osDestroyThread(&B_801E0DB0); +} + +void func_801C8578(void* arg0, void* arg1, OSId id, void* sp, OSPri pri) { + B_801E0D10[0] = (OSMesgQueue*)arg0; + B_801E0D10[1] = (OSMesgQueue*)arg1; + osCreateThread(&B_801E0DB0, id, &func_801C84D4, NULL, sp, pri); + osStartThread(&B_801E0DB0); +} + +void func_801C85F0(struct_801E0D18* arg0, s32 arg1) { + if (arg1 == 1) { + func_801C8424(arg0); + } else { + osSendMesg(B_801E0D10[0], arg0, OS_MESG_BLOCK); + } +} + +void func_801C8638(void (*arg0)(void*, void*, void*), s32 arg1, void (*arg2)(void*, uintptr_t, size_t)) { + s32 var0 = 0; + + func_801C9B50(arg1, arg2); + D_801D2EB4 = arg0; + B_801E0D18.unk_64 = var0; + B_801E0D18.unk_65 = var0; + func_801C85F0(&B_801E0D18, 0); +} + +void func_801C868C(void* arg0, void* arg1, void* arg2, u8 arg3) { + s32 var0 = (s32)arg0; + s32 var1 = (s32)arg1; + s32 var2 = (s32)arg2; + s32 var3 = arg3; + s32 var4 = 4; + + if (D_801D2E90 == 1) { + D_801D2E90 = 0; + B_801E0D18.unk_64 = var4; + func_801C85F0(&B_801E0D18, 1); + if (B_801E0D18.unk_6C == 3 || B_801E0D18.unk_6C == 4) { + return; + } + } + + B_801E0D18.unk_58 = var0; + B_801E0D18.unk_5C = var1; + B_801E0D18.unk_60 = var2; + B_801E0D18.unk_64 = var3; + func_801C85F0(&B_801E0D18, 0); +} + +s32 func_801C873C(struct_801E0D18* arg0) { + u8 sp1F; + + arg0->unk_68 = LeoTestUnitReady(&sp1F); + return !(sp1F & LEO_TEST_UNIT_MR); +} + +s8 func_801C8770(void) { + s32 temp = func_801C873C(&B_801E0D18); + + if (B_801E0D18.unk_68 == LEO_ERROR_BUSY) { + return 0; + } + + if (!temp) { + return 2; + } + + return 1; +} + +s32 func_801C87C0(void) { + if (func_801C8844() == 0) { + if (B_801E0D18.unk_68 != 0) { + return B_801E0D18.unk_68; + } + } + + return -1; +} + +s32 func_801C87FC(void) { + s32* new_var = &B_801E0D18.unk_68; + s32 temp_v0; + + if (func_801C8844() == 0) { + temp_v0 = B_801E0D18.unk_6C; + + if ((temp_v0 == 3) || (temp_v0 == 4)) { + return *new_var; + } + } + + return 0; +} + +s32 func_801C8844(void) { + return B_801E0D18.unk_66 == 1; +} + +s32 func_801C885C(void) { + B_801E0D18.unk_64 = 3; + func_801C85F0(&B_801E0D18, 1); + +#if OOT_VERSION > NTSC_1_0 + D_801D2E90 = 0; +#endif + + if ((B_801E0D18.unk_6C == 3) || (B_801E0D18.unk_6C == 4)) { + return -1; + } + return B_801E0D18.unk_6C == 0; +} + +s32 func_801C88AC(void) { + s32 phi_v0; + + B_801E0D18.unk_64 = 4; + func_801C85F0(&B_801E0D18, 1); + +#if OOT_VERSION > NTSC_1_0 + D_801D2E90 = 0; +#endif + + if ((B_801E0D18.unk_6C == 3) || (B_801E0D18.unk_6C == 4)) { + return -1; + } + return B_801E0D18.unk_6C == 0; +} + +s32 func_801C88FC(void) { + s32 temp = 0; + s32 phi_v1; + + if (LeoDriveExist()) { + phi_v1 = 8; + } else { + phi_v1 = 0; + } + + temp = phi_v1 == temp; + + B_801E0D18.unk_68 = phi_v1; + + return temp; +} diff --git a/src/n64dd/n64dd_801C8940.c b/src/n64dd/n64dd_801C8940.c new file mode 100644 index 0000000000..437a23dcf2 --- /dev/null +++ b/src/n64dd/n64dd_801C8940.c @@ -0,0 +1,398 @@ +// Lower-level command processing in a background thread +#include "global.h" +#include "n64dd.h" + +s32 D_801D2EA0 = 0; +u8* D_801D2EA4 = NULL; +s32 D_801D2EA8 = 0; +u8* D_801D2EAC = NULL; +u8* D_801D2EB0 = NULL; +void (*D_801D2EB4)(void*, void*, void*) = NULL; + +s32 B_801E0F60; +s32 B_801E0F64; + +// Set error message title texture? +void func_801C8940(s32 errorNum) { + D_801D2EA4 = func_801C9E28(errorNum); + D_801D2EA8 = 1; +} + +// Clear error message title texture? +void func_801C8974(void) { + if (D_801D2EA8 == 1) { + D_801D2EA4 = func_801C9EC0(); + D_801D2EA8 = 0; + } +} + +// Set error message something +void func_801C89B8(s32 errorNum) { + D_801D2EAC = func_801C9F90(errorNum); + B_801E0F60 = 1; +} + +// Clear error message something +void func_801C89EC(void) { + if (B_801E0F60 == 1) { + D_801D2EAC = func_801C9FFC(); + B_801E0F60 = 0; + } +} + +// Set error message something +void func_801C8A30(s32 errorNum) { + D_801D2EB0 = func_801CA030(errorNum); + B_801E0F64 = 1; +} + +// Clear error message something +void func_801C8A64(void) { + if (B_801E0F64 == 1) { + D_801D2EB0 = func_801CA070(); + B_801E0F64 = 0; + } +} + +void func_801C8AA8(void) { + osRecvMesg(B_801E0D10[1], NULL, OS_MESG_NOBLOCK); + + if ((D_801D2EB4 != NULL) && (D_801D2EA0 == 0)) { + u32 temp_v0 = osSetIntMask(OS_IM_NONE); + void* sp20 = D_801D2EA4; + void* sp1C = D_801D2EAC; + void* sp18 = D_801D2EB0; + + D_801D2EA4 = NULL; + D_801D2EAC = NULL; + D_801D2EB0 = NULL; + osSetIntMask(temp_v0); + D_801D2EB4(sp20, sp1C, sp18); + } +} + +void func_801C8B58(s32 arg0, s32 arg1, s32 arg2) { + func_801C8940(arg0); + func_801C89B8(arg1); + func_801C8A30(arg2); +} + +void func_801C8B90(void) { + func_801C8974(); + func_801C89EC(); + func_801C8A64(); +} + +s32 func_801C8BC0(struct_801E0D18* arg0) { + if ((arg0->unk_68 < 0x25) || (arg0->unk_68 >= 0x29)) { + if ((arg0->unk_68 != 0x1F) && (arg0->unk_68 != 0x20)) { + func_801C8940(arg0->unk_68); + func_801C89B8(3); + } + } + LeoClearQueue(); + return 4; +} + +s32 func_801C8C1C(struct_801E0D18* arg0) { + s32 var_s0; + + do { + var_s0 = 0; + Sleep_Msec(60); + func_801C82E0(arg0); + + switch (arg0->unk_68) { + case 0x2A: + func_801C8A64(); + return 0; + case 0x22: + func_801C8A64(); + LeoClearQueue(); + return 3; + case 0: + func_801C8A30(6); + FALLTHROUGH; + case 0x23: + var_s0 = 1; + break; + } + } while (var_s0 != 0); + + func_801C8A64(); + return func_801C8BC0(arg0); +} + +s32 func_801C8CEC(struct_801E0D18* arg0) { + switch (arg0->unk_68) { + case 0x22: + func_801C8B90(); + LeoClearQueue(); + return 3; + case 0x2: + func_801C8940(arg0->unk_68); + func_801C8A30(5); + return 9; + case 0x0: + func_801C8B90(); + return 0; + case 0x2B: + if (arg0->unk_65 == 0) { + func_801C8B90(); + arg0->unk_65 = 2; + return 1; + } + FALLTHROUGH; + default: + func_801C8B90(); + return func_801C8BC0(arg0); + case 0x23: + return 9; + } +} + +s32 func_801C8DC0(struct_801E0D18* arg0) { + s32 temp_v0; + + while (true) { + func_801C8298(arg0); + switch (arg0->unk_68) { + case 0x31: + func_801C8940(arg0->unk_68); + func_801C89B8(2); + return 5; + case 0x2A: + func_801C8B90(); + return 5; + } + temp_v0 = func_801C8CEC(arg0); + if (temp_v0 != 9) { + return temp_v0; + } + Sleep_Msec(60); + } +} + +s32 func_801C8E70(struct_801E0D18* arg0) { + s32 temp_a0; + s32 temp_v0; + + while (true) { + Sleep_Msec(60); + func_801C8298(arg0); + + switch (arg0->unk_68) { + case 0x23: + continue; + case 0x31: + func_801C8940(arg0->unk_68); + func_801C89B8(2); + FALLTHROUGH; + case 0x2A: + func_801C8A30(4); + continue; + } + + temp_v0 = func_801C8CEC(arg0); + if (temp_v0 != 9) { + return temp_v0; + } + } +} + +s32 func_801C8F1C(struct_801E0D18* arg0) { + if (D_801D2E54 != NULL) { + return D_801D2E54(arg0); + } + return 1; +} + +s32 func_801C8F58(struct_801E0D18* arg0) { + s32 temp_v0; + + while (true) { + temp_v0 = func_801C8E70(arg0); + if (temp_v0 == 3 || temp_v0 == 4) { + return temp_v0; + } + + // Fake match? + if ((temp_v0 & 0xFFFFFFFF) == 0) { + if (func_801C8F1C(arg0) != 0) { + return 2; + } + func_801C89B8(1); + temp_v0 = func_801C8C1C(arg0); + if (temp_v0 != 0) { + return temp_v0; + } + func_801C89EC(); + } + } +} + +s32 func_801C9000(struct_801E0D18* arg0) { + s32 phi_s0; + s32 temp_s4; + + while (true) { + phi_s0 = func_801C8E70(arg0); + if (phi_s0 == 3 || phi_s0 == 4) { + return phi_s0; + } + + // Fake match? + if ((phi_s0 & 0xFFFFFFFF) == 0) { + func_801C8B90(); + + temp_s4 = func_801C8F1C(arg0); + if (temp_s4 == 3 || temp_s4 == 4) {} + if (temp_s4 != 0) { + return 2; + } + + func_801C89B8(1); + + phi_s0 = func_801C8C1C(arg0); + if (phi_s0 == 3 || phi_s0 == 4) {} + if (phi_s0 != 0) { + return phi_s0; + } + + func_801C89EC(); + if (temp_s4 != 0) { + return phi_s0; + } + } + } +} + +s32 func_801C90C4(struct_801E0D18* arg0) { + func_801C8940(arg0->unk_68); + func_801C89B8(2); + return func_801C9000(arg0); +} + +s32 func_801C90FC(struct_801E0D18* arg0) { + func_801C8940(arg0->unk_68); + return func_801C9000(arg0); +} + +s32 func_801C912C(struct_801E0D18* arg0) { + s32 i = 0; + s32 temp_v0; + + do { + LeoResetClear(); + + temp_v0 = func_801C8DC0(arg0); + if (temp_v0 == 3 || temp_v0 == 4) { + return temp_v0; + } + if (temp_v0 != 1) { + if (temp_v0 == 0) { + return temp_v0; + } else { + return temp_v0; + } + } + + Sleep_Msec(250); + } while (i++ < 30); + + return func_801C8BC0(arg0); +} + +s32 func_801C91E0(struct_801E0D18* arg0) { + if (arg0->unk_68 == 0x29) { + return func_801C8BC0(arg0); + } + + if (osMemSize < 0x800000) { + // LEO_ERROR_RAMPACK_NOT_CONNECTED? + func_801C8B58(0x2C, 0, 3); + return 4; + } + + if (func_801C912C(arg0) == 0) { + D_801D2E90 = 1; + } + return 0; +} + +s32 func_801C9260(struct_801E0D18* arg0) { + s32 temp_v0; + + switch (arg0->unk_68) { + case 0x17: + func_801C873C(arg0); + temp_v0 = func_801C8C1C(arg0); + if (temp_v0 != 0) { + return temp_v0; + } + func_801C8B90(); + return 2; + + case 0x2: + return func_801C8F58(arg0); + + case 0x22: + LeoClearQueue(); + return 3; + + case 0x31: + return func_801C90C4(arg0); + + case 0x2F: + return func_801C9000(arg0); + + case 0x2A: + return func_801C90FC(arg0); + + case 0x0: + return 0; + + case 0x23: + return 2; + } + + return func_801C8BC0(arg0); +} + +s32 func_801C9334(struct_801E0D18* arg0) { + while (true) { + u32 temp_v0 = func_801C8DC0(arg0); + + if (temp_v0 == 3 || temp_v0 == 4 || temp_v0 == 5) { + return temp_v0; + } + + // Fake match? + if ((temp_v0 & 0xFFFFFFFF) == 0) { + if (func_801C8F1C(arg0) != 0) { + return 0; + } + return 7; + } + + if (1) {} + } +} + +s32 func_801C93C4(struct_801E0D18* arg0) { + s32 temp_v0; + s32 temp_v0_2; + + while (true) { + temp_v0_2 = func_801C9334(arg0); + if (temp_v0_2 != 7) { + return temp_v0_2; + } + func_801C89B8(1); + temp_v0 = func_801C8C1C(arg0); + if (temp_v0 != 0) { + return temp_v0; + } + func_801C89EC(); + } +} diff --git a/src/n64dd/n64dd_801C9440.c b/src/n64dd/n64dd_801C9440.c new file mode 100644 index 0000000000..28ab8b5625 --- /dev/null +++ b/src/n64dd/n64dd_801C9440.c @@ -0,0 +1,263 @@ +// Some text-handling functions +#include "global.h" +#include "n64dd.h" + +void (*D_801D2EC0)(void*, uintptr_t, size_t) = NULL; + +s32 B_801E0F70; + +/** + * Seems to work out if a pair of bytes is a valid EUC-JP character, although there may be additions to the font that + * make the strange first check make more sense. + * + * @param bytes Array 2 bytes to test + * @return boolean + */ +int func_801C9440(u8* bytes) { + // This is every possible first byte. May make more sense what was intended with the font files? + if (((*bytes >= 0x8E) && (*bytes <= 0xFE)) || ((*bytes != 0x8F) && (*bytes != 0xA0))) { + bytes++; + return (*bytes >= 0xA0) && (*bytes <= 0xFE); + } + return false; +} + +/** + * A crude check for a valid 2-byte Shift-JIS character + * + * @param bytes Array containing a pair of bytes to test + * @return boolean + */ +int func_801C9494(u8* bytes) { + // Allowable first bytes. + if (((*bytes >= 0x81) && (*bytes <= 0x9F)) || ((*bytes >= 0xE0) && (*bytes <= 0xFC))) { + bytes++; + // Allowable second bytes. + return (*bytes >= 0x40) && (*bytes <= 0xFC) && *bytes != 0x7F; + } + return false; +} + +// Extracts 2 bytes from a bytepacked big-endian short. +void func_801C94F8(u8* arg0, u16 arg1) { + arg0[0] = arg1 >> 8; + arg0[1] = arg1 & 0xFF; +} + +// Convert EUC-JP to JIS X 0208 +u16 func_801C9514(u16 eucjpCh) { + return eucjpCh - 0x8080; +} + +/** + * Converts a JIS X 0208 codepoint to a Shift-JIS one. + * + * @param jisCodepoint Two bytes, each between 0x21 and 0x7E, packed big-endian into a short. + * @return u16 Shift-JIS character representation (expected to be big-endian) + */ +u16 func_801C9534(u16 jisCodepoint) { + u8 hiByte = (jisCodepoint >> 8) & 0xFF; + u8 loByte = jisCodepoint & 0xFF; + + if (hiByte & 1) { + loByte += 0x1F; + if (loByte >= 0x7F) { + loByte++; + } + } else { + loByte += 0x7E; + } + + hiByte = (hiByte - 0x21) / 2 + 0x81; + if (hiByte >= 0xA0) { + hiByte += 0x40; + } + + return (hiByte << 8) + loByte; +} + +void func_801C95C0(void* arg0, uintptr_t arg1, size_t arg2) { + if (D_801D2EC0 != NULL) { + D_801D2EC0(arg0, arg1, arg2); + } +} + +s32 func_801C95F0(u8* arg0) { + return LeoGetKAdr(func_801C9534(func_801C9514((arg0[0] << 8) | arg0[1]))) + DDROM_FONT_START; +} + +s32 func_801C963C(s32* arg0, int* dx, int* dy, int* cy, u8 arg4) { + s32 temp_v0; + s32 temp_v1; + + u16 temp = arg4 - 0x20; + temp += 0xC0 * B_801E0F70; + + temp_v0 = LeoGetAAdr(temp, dx, dy, cy); + temp_v1 = temp_v0 & 0xF; + *arg0 = (temp_v0 - temp_v1) + DDROM_FONT_START; + return temp_v1; +} + +s32 func_801C969C(void* arg0, int* dx, int* dy, int* cy, u8* arg4) { + s32 sp24; + s32 phi_v1; + + if (func_801C9440(arg4)) { + sp24 = func_801C95F0(arg4); + *dx = 16; + *dy = 16; + *cy = 11; + phi_v1 = 0; + } else { + phi_v1 = func_801C963C(&sp24, dx, dy, cy, *arg4); + } + + func_801C95C0(arg0, sp24, 0x80); + return phi_v1; +} + +// return boolean +s32 func_801C9740(u8* arg0, s32 arg1, u8 arg2) { + if (arg1 == 1) { + *arg0 = arg2 << 4; + return false; + } else { + *arg0 |= arg2; + return true; + } +} + +u8* func_801C9778(u8* arg0, s32* arg1, s32 arg2) { + arg0 += (arg2 >> 1); + + if (((*arg1 == 1) && !(arg2 & 1)) || ((*arg1 == 0) && (arg2 & 1))) { + arg0 += arg2 & 1; + *arg1 = 1; + } else { + *arg1 = 0; + } + return arg0; +} + +s32 func_801C97C4(u8** arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, u8* arg5, s32 dx, s32 dy, s32 cy) { + u8* var_fp; + u8* var_s0; + s32 var_s1; + s32 x; + s32 sp4C; + s32 var_s4; + s32 sp44; + + sp4C = arg2; + sp44 = dx + arg3 + arg4; + var_s4 = 1; + var_fp = func_801C9778(*arg0, &sp4C, arg3); + arg1 >>= 1; + var_fp += ((11 - cy) * arg1); + if (dx & 1) { + dx++; + } + while (dy--) { + var_s0 = var_fp; + var_s1 = sp4C; + for (x = 0; x < dx; x++) { + if (var_s4 == 1) { + if (func_801C9740(var_s0, var_s1, *arg5 >> 4)) { + var_s0++; + } + } else { + if (func_801C9740(var_s0, var_s1, *arg5 & 0xF)) { + var_s0++; + } + arg5++; + } + var_s4 ^= 1; + var_s1 ^= 1; + } + var_fp += arg1; + } + *arg0 = func_801C9778(*arg0, &arg2, sp44); + return arg2; +} + +void func_801C9954(u8* bytes, s32* arg1, s32* arg2) { + u8 prevCh; + u8 nextCh; + + if (func_801C9440(bytes)) { + *arg1 = *arg2 = 0; + return; + } + + *arg1 = *arg2 = 0; + + prevCh = bytes[-1]; + nextCh = bytes[1]; + + switch (bytes[0]) { + case ' ': + *arg1 = *arg2 = 0; + return; + + case 'I': + case 'i': +#if OOT_NTSC + *arg2 = 2; + if (1) {} +#endif + + *arg1 = 2; + *arg2 = 2; + + if (prevCh == ' ') { + *arg1 = 0; + } + if (nextCh == ' ') { + *arg2 = 0; + } + return; + } + +#if OOT_NTSC + *arg2 = 1; + if (1) {} +#endif + + *arg1 = 1; + *arg2 = 1; +} + +void func_801C9A10(u8* arg0, s32 arg1, u8* str) { + u8 sp80[0xA0]; + u8* temp_s1; + int dx; + int dy; + int cy; + s32 var_s2; + s32 sp68; + s32 sp64; + s32 temp_v1; + + temp_s1 = (u8*)((((uintptr_t)&sp80 + 0xF) / 0x10) * 0x10); + var_s2 = 1; + if (str != NULL) { + while (*str != '\0') { + func_801C9954(str, &sp68, &sp64); + temp_v1 = func_801C969C(temp_s1, &dx, &dy, &cy, str); + if (dx & 1) { + dx++; + } + var_s2 = func_801C97C4(&arg0, arg1, var_s2, sp68, sp64, &temp_s1[temp_v1], dx, dy, cy); + if (func_801C9440(str)) { + str++; + } + str++; + } + } +} + +void func_801C9B50(s32 arg0, void (*arg1)(void*, uintptr_t, size_t)) { + B_801E0F70 = arg0; + D_801D2EC0 = arg1; +} diff --git a/src/n64dd/n64dd_801C9B70.c b/src/n64dd/n64dd_801C9B70.c new file mode 100644 index 0000000000..d7d2f63849 --- /dev/null +++ b/src/n64dd/n64dd_801C9B70.c @@ -0,0 +1,172 @@ +// User-facing error handling +#include "global.h" +#include "n64dd.h" + +u8 B_801E0F80[0x600]; +u8 B_801E1580[0x2800]; +u8 B_801E3D80[0x1400]; + +/** + * Converts a number in decimal to a hexadecimal number with the same digits, e.g. 1234 -> 0x1234. + * + * Will only work on nonnegative numbers. + * + * @param decNumber Number in decimal to convert, e.g. 1234 + * @return s32 Hexadecimal number with the same digits as decNumber, e.g. 0x1234 + */ +s32 func_801C9B70(s32 decNumber) { + s32 currPlaceValue; + s32 currExponent = 0; + s32 accumulatedHexDigits = 0; + s32 remainingDecDigits; + + // Nothing to do if only one digit. + if (decNumber < 10) { + return decNumber; + } + + // Find the place value / exponent of the most significant digit in decNumber. + for (currPlaceValue = 1; 10 * currPlaceValue <= decNumber; currPlaceValue *= 10) { + currExponent++; + } + + remainingDecDigits = decNumber; + + // Transfer the digits to hex one at a time. + while (currExponent--) { + // Place the most significant remaining digit at the end of the hex output. + accumulatedHexDigits |= remainingDecDigits / currPlaceValue; + accumulatedHexDigits *= 0x10; // Shift left one hex digit. + + remainingDecDigits %= currPlaceValue; // Remove most significant of the remaining digits. + + currPlaceValue /= 10; + } + + accumulatedHexDigits += remainingDecDigits; // Only one digit left in the remainingDecDigits. + return accumulatedHexDigits; +} + +// n64ddError_GetLanguage +s32 func_801C9C48(void) { + return (gCurrentRegion == 1) ? 0 : 1; +} + +// n64ddError_Memset +void func_801C9C74(u8* dest, u8 value, u32 count) { + while (count--) { + *dest++ = value; + } +} + +// n64ddError_GetErrorHeader +const char* func_801C9CA4(void) { + return D_801D2ED0[func_801C9C48()]; +} + +// n64ddError_WriteNumberJP +// Writes a 2-digit number to the char buffer provided +// Character indices for numbers in the error code (EUC-JP) +void func_801C9CD4(u8* buf, s32 number) { + s32 temp_v0 = func_801C9B70(number); + u16 character; + + if (number >= 10) { + character = ((temp_v0 >> 4) + 0xA3B0); // '0' + } else { + character = 0xA1A1; // ' ' + } + + func_801C94F8(buf, character); + buf += 2; + func_801C94F8(buf, ((temp_v0 & 0xF) + 0xA3B0)); // '0' +} + +// n64ddError_WriteNumberEN +// Writes a 2-digit number to the char buffer provided +// Character indices for numbers in the error code (ASCII) +void func_801C9D54(u8* buf, s32 number) { + s32 temp_v0 = func_801C9B70(number); + + if (number >= 10) { + *buf = (temp_v0 >> 4) + '0'; + } else { + *buf = ' '; + } + buf++; + *buf = (temp_v0 & 0xF) + '0'; +} + +void func_801C9DB8(u8* arg0, s32 errorNum) { + u8* errorHeader = (u8*)func_801C9CA4(); + + //! @bug: both of these functions will write to the pointer target, but errorHeader points to a string literal, + //! which is meant to be const. + if (gCurrentRegion == 1) { + func_801C9CD4(&errorHeader[12], errorNum); + } else { + func_801C9D54(&errorHeader[13], errorNum); + } + func_801C9A10(arg0, 192, errorHeader); +} + +u8* func_801C9E28(s32 errorNum) { + func_801C9EC0(); + + if (errorNum == 41) { + return (u8*)gN64DDError41Texs[func_801C9C48()]; + } + + // 31,32, 37,38,39,40 + if (((errorNum >= 37) && (errorNum < 41)) || (errorNum == 31) || (errorNum == 32)) { + return B_801E0F80; + } else { + func_801C9DB8(B_801E0F80, errorNum); + return B_801E0F80; + } +} + +// Clear something +u8* func_801C9EC0(void) { + func_801C9C74(B_801E0F80, 0, 0x600); + return B_801E0F80; +} + +// Prints the error message body (?) +void func_801C9EF4(u8* arg0, s32 errorNum, s32 lineCount) { + s32 i; + + for (i = 0; i < lineCount; i++, arg0 += 0xA00) { + u8* line = (u8*)D_801D2EE0[func_801C9C48()][errorNum][i]; + + if (1) {} + func_801C9A10(arg0, 320, line); + } +} + +u8* func_801C9F90(s32 errorNum) { + func_801C9FFC(); + if (errorNum == 3) { + return (u8*)gN64DDPleaseReadManualTexs[func_801C9C48()]; + } + func_801C9EF4(B_801E1580, errorNum, 4); + return B_801E1580; +} + +// Clear something +u8* func_801C9FFC(void) { + func_801C9C74(B_801E1580, 0, 0x2800); + return B_801E1580; +} + +u8* func_801CA030(s32 errorNum) { + func_801CA070(); + func_801C9EF4(B_801E3D80, errorNum, 2); + return B_801E3D80; +} + +// Clear something +u8* func_801CA070(void) { + func_801C9C74(B_801E3D80, 0, 0x1400); + return B_801E3D80; +} diff --git a/src/n64dd/n64dd_801CA0B0.c b/src/n64dd/n64dd_801CA0B0.c new file mode 100644 index 0000000000..8758e0fd62 --- /dev/null +++ b/src/n64dd/n64dd_801CA0B0.c @@ -0,0 +1,243 @@ +#include "global.h" +#include "n64dd.h" + +// Draws text to framebuffer +typedef struct struct_801CA704 { + /* 0x00 */ PrintCallback callback; + /* 0x04 */ void* charTexBuf; + /* 0x08 */ u16 unk_08; + /* 0x0A */ u16 posX; + /* 0x0C */ u16 posY; + /* 0x10 */ Color_RGBA8_u32 color; + /* 0x14 */ u16 baseX; + /* 0x16 */ u16 baseY; + /* 0x18 */ u16 endX; + /* 0x1A */ u16 endY; + /* 0x1C */ u8 sjisPrevByte; + /* 0x20 */ void* frameBuf; + /* 0x24 */ u16 screenWidth; + /* 0x26 */ u16 screenHeight; +} struct_801CA704; + +// clang-format off +u32 D_801D8BE0[0x5F] = { + 0x00009D14, 0x00232A14, 0x00296314, 0x002F8A14, 0x00457E18, 0x0063CA14, 0x0084AA14, 0x00A03314, + 0x00A45E14, 0x00BB4E14, 0x00CA6514, 0x00D3770E, 0x00E33302, 0x00E78108, 0x00EB2102, 0x00EC6C14, + 0x01008A14, 0x01163A14, 0x01217A14, 0x01377A14, 0x014D8A14, 0x01638A14, 0x01798A14, 0x018F7A14, + 0x01A58A14, 0x01BB8A14, 0x01D1170E, 0x01D5490E, 0x01DF770E, 0x01EF740A, 0x01F9770E, 0x02097A14, + 0x021FDC16, 0x024DBA14, 0x026E7A14, 0x0284BA14, 0x02A59A14, 0x02C16A14, 0x02D26A14, 0x02E3BA14, + 0x03048A14, 0x031A1A14, 0x03206A14, 0x03318A14, 0x03476A14, 0x0358CA14, 0x03799A14, 0x0395CA14, + 0x03B67A14, 0x03CCCA14, 0x03ED8A14, 0x04037A14, 0x04196A14, 0x042A8A14, 0x0440AA14, 0x045CDA14, + 0x04839A14, 0x049F9A14, 0x04BB7A14, 0x04D14D14, 0x04DF5C14, 0x04F33D14, 0x05015216, 0x050681FA, + 0x050A9D14, 0x052D9810, 0x05449A14, 0x05609810, 0x05779A14, 0x05939810, 0x05AA5A14, 0x05BB9C10, + 0x05DC7A14, 0x05F22A14, 0x05F83D14, 0x06067A14, 0x061C2A14, 0x0622D810, 0x06427810, 0x06549810, + 0x066B9B10, 0x06899B10, 0x06A74810, 0x06B06810, 0x06BE5A14, 0x06CF770E, 0x06DF870E, 0x06EFB70E, + 0x0707670E, 0x07138A0E, 0x0729670E, 0x07356D14, 0x074A1F16, 0x07526D14, 0x07675216, +}; +// clang-format on + +// Loads character texture to buffer +s32 func_801CA0B0(s32 charCode, void* charTexBuf, int* dx, int* dy, int* cy) { + s32 offset; + OSPiHandle* handle; + OSMesgQueue queue; + OSMesg msgBuf[1]; + OSIoMesg mesg; + + handle = osDriveRomInit(); + if (charCode >= 0x20 && charCode < 0x7F) { // ASCII + offset = LeoGetAAdr2(D_801D8BE0[charCode - 0x20], dx, dy, cy); + } else if (charCode >= 0x8140) { // Shift-JIS + offset = LeoGetKAdr(charCode); + *dx = 16; + *dy = 16; + *cy = 11; + } else { + return -1; + } + + osCreateMesgQueue(&queue, msgBuf, ARRAY_COUNT(msgBuf)); + + // clang-format off + mesg.hdr.retQueue = &queue; \ + mesg.devAddr = offset + DDROM_FONT_START; \ + mesg.dramAddr = charTexBuf; \ + mesg.size = 0x80; \ + mesg.hdr.pri = 0; + // clang-format on + + handle->transferInfo.cmdType = 2; + osEPiStartDma(handle, &mesg, 0); + osRecvMesg(&queue, NULL, OS_MESG_BLOCK); + + return 0; +} + +const u16 D_801D9390[16] = { + 0x0001, 0x1085, 0x2109, 0x318D, 0x4211, 0x5295, 0x6319, 0x739D, + 0x8C63, 0x9CE7, 0xAD6B, 0xBDEF, 0xCE73, 0xDEF7, 0xEF7B, 0xFFFF, +}; + +// Maps 4-bit intensity to a 16-bit color +u16 func_801CA1D4(u32 arg0) { + return D_801D9390[arg0 % ARRAY_COUNT(D_801D9390)]; +} + +void func_801CA1F0(void* charTexBuf, s32 posX, s32 posY, s32 dx, s32 dy, s32 cy, void* frameBuf, s32 screenWidth) { + s32 intensity; + s32 x; + s32 y; + u8* src = charTexBuf; + u16* dst = frameBuf; + + for (y = 0; y < dy; y++) { + for (x = 0; x < dx; x++) { + if (!(x & 1)) { + intensity = *src >> 4; + } else { + intensity = *src & 0xF; + src++; + } + dst[posX + x + ((posY + (11 - cy) + y) * screenWidth)] = func_801CA1D4(intensity); + } + if (dx & 1) { + src++; + } + } +} + +void func_801CA2F8(struct_801CA704* arg0, u32 r, u32 g, u32 b, u32 a) { + arg0->color.r = r; + arg0->color.g = g; + arg0->color.b = b; + arg0->color.a = a; +} + +void func_801CA314(struct_801CA704* arg0, s32 arg1, s32 arg2) { + arg0->posX = arg0->baseX + arg1; + arg0->posY = arg0->baseY + arg2; +} + +void func_801CA334(struct_801CA704* arg0, s32 baseX, s32 baseY, s32 endX, s32 endY) { + arg0->baseX = baseX; + arg0->baseY = baseY; + arg0->endX = endX; + arg0->endY = endY; +} + +void func_801CA350(struct_801CA704* arg0, void* frameBuf, s32 screenWidth, s32 screenHeight) { + arg0->frameBuf = (u8*)frameBuf + 0x20000000; + arg0->screenWidth = screenWidth; + arg0->screenHeight = screenHeight; + func_801CA334(arg0, 0, 0, screenWidth - 1, screenHeight - 1); +} + +void func_801CA3B4(struct_801CA704* arg0, void* charTexBuf, s32 arg2) { + arg0->charTexBuf = (u8*)charTexBuf + 0x20000000; + arg0->unk_08 = arg2; +} + +void func_801CA3CC(struct_801CA704* arg0, char c) { + s32 charCode; + int dx; + int dy; + int cy; + + if (arg0->sjisPrevByte != 0) { + charCode = (arg0->sjisPrevByte << 8) | c; + } else { + if (c >= 0x80 && c < 0x99) { + arg0->sjisPrevByte = c; + return; + } + charCode = c; + } + + arg0->sjisPrevByte = 0; + if (func_801CA0B0(charCode, arg0->charTexBuf, &dx, &dy, &cy) == 0) { + if (arg0->posX + dx > arg0->endX) { + arg0->posX = arg0->baseX; + if (arg0->posY + 16 > arg0->endY) { + arg0->posY = arg0->baseY; + } else { + arg0->posY += 16; + } + } + func_801CA1F0(arg0->charTexBuf, arg0->posX, arg0->posY, dx, dy, cy, arg0->frameBuf, arg0->screenWidth); + arg0->posX += (dx == 16 ? dx : dx + 2); + } +} + +void func_801CA4F4(struct_801CA704* arg0, char c) { + if (c >= ' ' && c <= 0xFF) { + func_801CA3CC(arg0, c); + } else { + switch (c) { + case '\n': + arg0->posY += 32; + FALLTHROUGH; + case '\r': + arg0->posX = arg0->baseX; + break; + case '\t': + do { + func_801CA3CC(arg0, ' '); + } while ((arg0->posX - arg0->baseX) % 256); + break; + case '\0': + break; + } + } +} + +void func_801CA5BC(struct_801CA704* arg0, const char* str, s32 arg2, size_t count) { + const char* s = str; + s32 n = arg2 * count; + + while (n != 0) { + func_801CA4F4(arg0, *s++); + n--; + } +} + +void func_801CA618(struct_801CA704* arg0, const char* str) { + while (*str != 0) { + func_801CA4F4(arg0, *str++); + } +} + +void* func_801CA670(void* arg, const char* str, size_t count) { + func_801CA5BC(arg, str, 1, count); + return arg; +} + +void func_801CA6A0(struct_801CA704* arg0) { + arg0->callback = &func_801CA670; + arg0->posX = 0; + arg0->posY = 0; + arg0->baseX = 0; + arg0->baseY = 0; + arg0->endX = 0; + arg0->endY = 0; + arg0->color.rgba = 0; + arg0->sjisPrevByte = 0; + arg0->charTexBuf = NULL; +} + +void func_801CA6D8(struct_801CA704* arg0) { +} + +s32 func_801CA6E4(struct_801CA704* arg0, const char* fmt, va_list args) { + return PrintUtils_VPrintf(&arg0->callback, fmt, args); +} + +s32 func_801CA704(struct_801CA704* arg0, const char* fmt, ...) { + s32 ret; + va_list args; + + va_start(args, fmt); + ret = func_801CA6E4(arg0, fmt, args); + va_end(args); + + return ret; +} diff --git a/src/n64dd/n64dd_data_buffer.c b/src/n64dd/n64dd_data_buffer.c new file mode 100644 index 0000000000..6aacae2d57 --- /dev/null +++ b/src/n64dd/n64dd_data_buffer.c @@ -0,0 +1,5 @@ +#include "global.h" +#include "n64dd.h" + +// Buffer used for reading from the disk? +u8 B_801DC000[0x4D10]; diff --git a/src/n64dd/n64dd_error_bodies.c b/src/n64dd/n64dd_error_bodies.c new file mode 100644 index 0000000000..757e1afb6b --- /dev/null +++ b/src/n64dd/n64dd_error_bodies.c @@ -0,0 +1,47 @@ +#include "global.h" +#include "n64dd.h" + +const char* D_801D2EE0[2][8][4] = { + { + { "  メモリー拡張パックが正しく差し込", "  んでありますか?        ", NULL, NULL }, + { "  間違ったディスクが差し込まれてい", "  る可能性があります。正しいディス", + "  クに交換してください。     ", NULL }, + { "  注意:アクセスランプ点滅中にディ", "  スクを抜かないでください。詳しく", + "  は、取扱説明書をお読みください。", NULL }, + { "  詳しくは、取扱説明書をお読みくだ", "  さい。             ", NULL, NULL }, + { "   ディスクを差し込んでください。", NULL, NULL, NULL }, + { "  ディスクを差し込み直してください。", NULL, NULL, NULL }, + { "   ディスクを取り出してください。", NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL }, + }, + { + { + " Are you sure the Expansion", + " Pak is inserted correctly?", + NULL, + NULL, + }, + { + " Check to see if the proper", + " disk is inserted.", + " Please insert the disk the", + " correct disk.", + }, + { + " Do not remove the disk when", + " the access light is flashing.", + " Please read the instruction", + " manual for details.", + }, + { + " Please read the instruction", + " manual for details.", + NULL, + NULL, + }, + { " Please insert a disk.", NULL, NULL, NULL }, + { " Please insert the disk again.", NULL, NULL, NULL }, + { " Please remove the disk.", NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL }, + }, +}; diff --git a/src/n64dd/n64dd_error_headers.c b/src/n64dd/n64dd_error_headers.c new file mode 100644 index 0000000000..b14d80fba5 --- /dev/null +++ b/src/n64dd/n64dd_error_headers.c @@ -0,0 +1,5 @@ +#include "global.h" +#include "n64dd.h" + +// Padding in .rodata suggests that these are in a separate file +const char* D_801D2ED0[4] = { "エラー番号   ", "Error Number ", NULL, NULL }; diff --git a/src/n64dd/n64dd_error_textures.c b/src/n64dd/n64dd_error_textures.c new file mode 100644 index 0000000000..037ed7835b --- /dev/null +++ b/src/n64dd/n64dd_error_textures.c @@ -0,0 +1,23 @@ +#include "ultra64.h" + +#if PLATFORM_N64 + +u64 gN64DDError41Texs[2][0x600 / sizeof(u64)] = { + { +#include "assets/n64dd/error_textures/n64dd_error_41_jpn.i4.inc.c" + }, + { +#include "assets/n64dd/error_textures/n64dd_error_41_eng.i4.inc.c" + }, +}; + +u64 gN64DDPleaseReadManualTexs[2][0x2800 / sizeof(u64)] = { + { +#include "assets/n64dd/error_textures/n64dd_please_read_manual_jpn.i4.inc.c" + }, + { +#include "assets/n64dd/error_textures/n64dd_please_read_manual_eng.i4.inc.c" + }, +}; + +#endif diff --git a/src/n64dd/z_n64dd.c b/src/n64dd/z_n64dd.c new file mode 100644 index 0000000000..4e90806e9a --- /dev/null +++ b/src/n64dd/z_n64dd.c @@ -0,0 +1,584 @@ +// Main interface for the 64DD from the rest of the game. Starts background +// threads and provides functions to submit commands to them. +#include "global.h" +#include "fault.h" +#include "n64dd.h" +#include "stack.h" +#include "versions.h" + +typedef struct struct_801D9C30 { + /* 0x000 */ s32 unk_000; // disk start + /* 0x004 */ s32 unk_004; // disk end + /* 0x008 */ uintptr_t unk_008; // ram start + /* 0x00C */ uintptr_t unk_00C; // ram end + /* 0x010 */ UNK_PTR unk_010; + /* 0x014 */ char unk_014[0x104]; +} struct_801D9C30; // size = 0x118 + +typedef struct struct_801D9B90 { + /* 0x00 */ OSMesg unk_00[30]; + /* 0x78 */ OSMesgQueue unk_78; + /* 0x90 */ IrqMgrClient unk_90; + /* 0x98 */ IrqMgr* unk_98; +} struct_801D9B90; // size = 0x9C + +s32 func_801C7A1C(struct_801E0D18* arg0); + +void* D_801D2E50 = &B_801DC000; +s32 (*D_801D2E54)(struct_801E0D18*) = func_801C7A1C; + +struct_801D9B90 B_801D9B90; +struct_801D9C30 B_801D9C30; +struct_801D9C30* B_801D9D48; +struct_801D9D50 B_801D9D50; +OSMesgQueue B_801D9D80; +OSMesgQueue B_801D9D98; +OSMesg B_801D9DB0[1]; +OSMesg B_801D9DB4[1]; +volatile u8 B_801D9DB8; +volatile OSTime B_801D9DC0; +s32 B_801D9DC8; // 1 if disk gameName is correct, 2 otherwise +void* B_801D9DCC; +void* B_801D9DD0; +void* B_801D9DD4; +OSThread B_801D9DD8; +STACK(B_801D9F88, 0x1000); +StackEntry B_801DAF88; +STACK(B_801DAFA8, 0x1000); +StackEntry B_801DBFA8; +UNK_TYPE B_801DBFC4; // unused? + +u32 func_801C6E80(void) { +#if OOT_NTSC + return LeoDriveExist(); +#else + return 0; +#endif +} + +void func_801C6EA0(Gfx** gfxP) { +} + +void func_801C6EAC(void) { + if (D_80121214 == 0) { + func_800F6BDC(); + D_80121214 = 1; + } +} + +s32 func_801C6EF0(void) { + return D_80121214 != 0; +} + +s32 func_801C6F08(void) { + if (D_80121214 != 0) { + return 1; + } + return 1; +} + +void func_801C6F30(void) { + func_801C6EAC(); + while (func_801C6F08() == 0) { + Sleep_Usec(16666); // 100000 / 6 + } +} + +void func_801C6F78(void) { + if (D_80121214 != 0) { + D_80121214 = 0; + func_800F6B3C(); + } +} + +// boolean +s32 func_801C6FAC(void) { + if (D_80121213 == 0) { + return false; + } else { + D_80121213 = 0; + return true; + } +} + +void func_801C6FD8(void) { + while (!func_801C6FAC()) { + Sleep_Usec(16666); // 100000 / 6 + } +} + +// Adds a HungupAndCrash +void func_801C7018(void) { + if (D_80121213 != 0) { +#if OOT_VERSION == NTSC_1_0 + Fault_AddHungupAndCrash("../z_n64dd.c", 503); +#elif OOT_VERSION == NTSC_1_1 + Fault_AddHungupAndCrash("../z_n64dd.c", 551); +#else + Fault_AddHungupAndCrash("../z_n64dd.c", 573); +#endif + } + D_80121213 = 1; +} + +s32 func_801C7064(void) { + B_801D9D50.unk_00 = 5; + return (&func_801C8000)(&B_801D9D50); +} + +s32 func_801C7098(void) { + s32 phi_v1; + +#if OOT_VERSION <= NTSC_1_1 + if (0) {} +#endif + + B_801D9D50.unk_00 = 10; + phi_v1 = (&func_801C8000)(&B_801D9D50); + if (phi_v1 < 0) { + func_800D31A0(); + } + return phi_v1; +} + +s32 func_801C70E4(void) { + return B_801D9DC8 == 1; +} + +// Used by EnMag and FileChoose +s32 func_801C70FC(void) { + return func_801C70E4(); +} + +void func_801C711C(void* arg) { + static void* B_801DBFC8; + struct_801D9B90* arg0 = (struct_801D9B90*)arg; + s16* sp58; + s32 var_s0; + void* temp_v0; + + sp58 = NULL; + arg0->unk_98 = &gIrqMgr; + osCreateMesgQueue(&arg0->unk_78, arg0->unk_00, ARRAY_COUNT(arg0->unk_00)); + IrqMgr_AddClient(arg0->unk_98, &arg0->unk_90, &arg0->unk_78); + var_s0 = 0; + do { + osRecvMesg(&arg0->unk_78, (OSMesg*)&sp58, OS_MESG_BLOCK); + switch (*sp58) { + case 1: + temp_v0 = osViGetNextFramebuffer(); + if (B_801DBFC8 != temp_v0) { + B_801DBFC8 = temp_v0; + B_801D9DB8 = 1; + } + func_801C8AA8(); + break; + case 4: + LeoReset(); + break; + case 3: + var_s0 = 1; + break; + } + } while (var_s0 == 0); + IrqMgr_RemoveClient(arg0->unk_98, &arg0->unk_90); +} + +#if OOT_VERSION > NTSC_1_0 +void func_801C7B28_ne2(void) { + s32 temp; + + if (B_801D9DC0 != 0) { + temp = (osGetTime() - B_801D9DC0) * 64 / 3000; + if (1000000 - temp > 0) { + Sleep_Usec(1000000 - temp); + } + } +} +#endif + +void func_801C7268(void) { + s32 pad; + s32 sp20; + s32 sp1C; + + sp20 = func_801C6EF0(); + if (sp20 == 0) { + func_801C6F30(); + } + B_801D9DB8 = 1; + B_801D9DC0 = 0; + if (func_801C7064() == 1) { + func_801C7098(); + } else if (B_801D9DC8 != 0) { + B_801D9DC8 = 0; + } +#if OOT_VERSION == NTSC_1_0 + if (B_801D9DC0 != 0) { + sp1C = (osGetTime() - B_801D9DC0) * 64 / 3000; + + // Remnants from debug statements? + (void)(osGetTime() - B_801D9DC0); + (void)((osGetTime() - B_801D9DC0) * 64 / 3000); + (void)((osGetTime() - B_801D9DC0) * 64 / 3000); + + if (1000000 - sp1C > 0) { + Sleep_Usec(1000000 - sp1C); + } + } +#else + if (D_801D2EA8 == 1 || B_801E0F60 == 1 || B_801E0F64 == 1) { + B_801D9DC0 = osGetTime(); + } + func_801C7B28_ne2(); +#endif + if (sp20 == 0) { + func_801C6F78(); + } +} + +// Clears framebuffer +void func_801C7438(void* arg0) { + u16* var_v0; + + for (var_v0 = (u16*)arg0; var_v0 < (u16*)arg0 + SCREEN_WIDTH * SCREEN_HEIGHT; var_v0++) { + *var_v0 = 1; + } +} + +void func_801C746C(void* arg0, void* arg1, void* arg2) { + void* sp2C; + + if (arg0 != NULL || arg1 != NULL || arg2 != NULL) { + sp2C = (u8*)osViGetNextFramebuffer() + 0x20000000; + if ((u32)sp2C & 0xFFFFFF) { + if (B_801D9DB8 != 0) { + B_801D9DB8 = 0; + func_801C7438(sp2C); + B_801D9DC0 = osGetTime(); + } + if (arg0 != NULL) { + func_801CA1F0(arg0, 96, 32, 192, 16, 11, sp2C, SCREEN_WIDTH); + } + if (arg1 != NULL) { + func_801CA1F0(arg1, 0, 80, 320, 64, 11, sp2C, SCREEN_WIDTH); + } + if (arg2 != NULL) { + func_801CA1F0(arg2, 0, 176, 320, 32, 11, sp2C, SCREEN_WIDTH); + } +#if OOT_VERSION <= NTSC_1_1 + osViBlack(0); +#endif + } + } +} + +void func_801C75BC(void* arg0, void* arg1, void* arg2) { + s32 temp; + + if (arg0 == NULL && arg1 == NULL && arg2 == NULL) { + return; + } + + if (B_801D9DB8) {} + + if (arg0 != 0) { + B_801D9DCC = arg0; + } + if (arg1 != 0) { + B_801D9DD0 = arg1; + } + if (arg2 != 0) { + B_801D9DD4 = arg2; + } + func_801C746C(arg0, arg1, arg2); +} + +void func_801C761C(void) { + Sleep_Msec(100); + func_801C746C(B_801D9DCC, B_801D9DD0, B_801D9DD4); +} + +s32 func_801C7658(void) { + if (D_80121212 != 0) { + return 0; + } + +#if OOT_VERSION <= NTSC_1_1 + StackCheck_Init(&B_801DAF88, B_801D9F88, STACK_TOP(B_801D9F88), 0, 0x100, "ddmsg"); + osCreateThread(&B_801D9DD8, THREAD_ID_DDMSG, &func_801C711C, &B_801D9B90, STACK_TOP(B_801D9F88), THREAD_PRI_DDMSG); + osStartThread(&B_801D9DD8); +#endif + + osCreateMesgQueue(&B_801D9D80, B_801D9DB0, ARRAY_COUNT(B_801D9DB0)); + osCreateMesgQueue(&B_801D9D98, B_801D9DB4, ARRAY_COUNT(B_801D9DB4)); + + StackCheck_Init(&B_801DBFA8, B_801DAFA8, STACK_TOP(B_801DAFA8), 0, 0x100, "n64dd"); + + B_801D9D50.unk_1C = &B_801D9D80; + B_801D9D50.unk_20 = &B_801D9D98; + B_801D9D50.unk_24 = THREAD_ID_N64DD; + B_801D9D50.unk_28 = STACK_TOP(B_801DAFA8); + B_801D9D50.unk_2C = THREAD_PRI_N64DD; + B_801D9D50.unk_00 = 1; + + (&func_801C8000)(&B_801D9D50); + + D_80121213 = 1; + func_801C6FD8(); + + B_801D9D50.unk_00 = 2; + B_801D9D50.unk_10 = 6; + B_801D9D50.unk_14 = &DmaMgr_DmaFromDriveRom; + B_801D9D50.unk_0C = &func_801C75BC; + (&func_801C8000)(&B_801D9D50); + + B_801D9D50.unk_00 = 13; + (&func_801C8000)(&B_801D9D50); + +#if OOT_VERSION > NTSC_1_1 + StackCheck_Init(&B_801DAF88, B_801D9F88, STACK_TOP(B_801D9F88), 0, 0x100, "ddmsg"); + osCreateThread(&B_801D9DD8, THREAD_ID_DDMSG, &func_801C711C, &B_801D9B90, STACK_TOP(B_801D9F88), THREAD_PRI_DDMSG); + osStartThread(&B_801D9DD8); +#endif + + return 0; +} + +s32 func_801C7818(void) { +#if OOT_VERSION > NTSC_1_0 + B_801D9DB8 = 1; + B_801D9DC0 = 0; +#endif + + B_801D9D50.unk_00 = 12; + (&func_801C8000)(&B_801D9D50); + + while (func_801C81C4() == 0) { + // the number 16666 sounds like it could be 1 frame (at 60 frames per second) + Sleep_Usec(1000000 * 1 / 60); + } + +#if OOT_VERSION > NTSC_1_0 + if (D_801D2EA8 == 1 || B_801E0F60 == 1 || B_801E0F64 == 1) { + B_801D9DC0 = osGetTime(); + } + func_801C7B28_ne2(); +#endif + + if (func_801C81C4() != 2) { + func_801C761C(); + func_800D31A0(); + return -3; + } + + func_801C7018(); + D_80121212 = 1; + return 0; +} + +s32 func_801C78B8(void) { + s32 phi_v1 = func_801C7658(); + + if (phi_v1 == 0) { + phi_v1 = func_801C7818(); + } + return phi_v1; +} + +s32 func_801C78F0(void) { + B_801D9D50.unk_00 = 0; + return (&func_801C8000)(&B_801D9D50); +} + +void func_801C7920(s32 arg0, void* arg1, s32 arg2) { + B_801D9D50.unk_18 = arg1; + B_801D9D50.unk_1C = (void*)arg0; + B_801D9D50.unk_20 = (void*)arg2; + B_801D9D50.unk_00 = 3; + (&func_801C8000)(&B_801D9D50); + osGetTime(); + B_801D9D50.unk_00 = 6; + while ((&func_801C8000)(&B_801D9D50) != 0) { + Sleep_Usec(16666); // 100000 / 6 + } + B_801D9D50.unk_00 = 7; + if ((&func_801C8000)(&B_801D9D50) != 0) { + func_800D31A0(); + } +} + +void func_801C79CC(void* arg0, s32 arg1, s32 arg2) { + B_801D9D50.unk_18 = arg0; + B_801D9D50.unk_1C = (void*)arg1; + B_801D9D50.unk_20 = (void*)arg2; + B_801D9D50.unk_00 = 4; + (&func_801C8000)(&B_801D9D50); +} + +void func_801C7A10(LEODiskID* arg0) { +} + +// Checks diskId, sets B_801D9DC8 and returns true if diskId is correct +s32 func_801C7A1C(struct_801E0D18* arg0) { + static LEODiskID B_801DBFD0; + static s32 B_801DBFF0; // bool + + func_801C7A10(&arg0->diskId); + if (!B_801DBFF0) { +#if OOT_NTSC + if (bcmp(arg0->diskId.gameName, "EZLJ", 4) == 0 || bcmp(arg0->diskId.gameName, "EZLE", 4) == 0) +#else + if (bcmp(arg0->diskId.gameName, "EZLP", 4) == 0) +#endif + { + B_801DBFD0 = arg0->diskId; + B_801DBFF0 = true; + B_801D9DC8 = 1; + } else { + B_801D9DC8 = 2; + } + } else if (bcmp(&B_801DBFD0, &arg0->diskId, sizeof(LEODiskID)) == 0) { + B_801D9DC8 = 1; + } else { + B_801D9DC8 = 2; + } + return B_801D9DC8 == 1; +} + +// Translates byte position to LBA and byte offset +s32 func_801C7B48(s32 arg0, s32* arg1, s32* arg2) { + s32 sp2C; + s32 temp_v0_2; + s32 sp24; + s32 sp20; + s32 temp_v0; + + temp_v0_2 = LeoByteToLBA(1, arg0 + 1, &sp2C); + if (temp_v0_2 != LEO_ERROR_GOOD) { + return temp_v0_2; + } + sp24 = sp2C - 1; + if (sp2C == 1) { + sp20 = 0; + } else { + temp_v0 = LeoLBAToByte(1, sp24, &sp20); + if (temp_v0 != LEO_ERROR_GOOD) { + return temp_v0; + } + } + *arg1 = sp24 + 1; + *arg2 = arg0 - sp20; + return LEO_ERROR_GOOD; +} + +s32 func_801C7BEC(s32 startLBA) { + s32 bytes; + + if (LeoLBAToByte(startLBA, 1, &bytes) == LEO_ERROR_GOOD) { + return bytes; + } + return 0; +} + +// Copies bytes from disk to arg0 +void func_801C7C1C(void* dest, s32 offset, s32 size) { + s32 sp5C; + s32 sp58; + s32 sp54; + s32 sp50; + void* sp4C; + s32 var_s0; + s32 var_s1; + s32 temp_v1_2; + + func_801C6FD8(); + func_801C6F30(); + B_801D9DB8 = 1; + B_801D9DC0 = 0; + func_801C7B48(offset, &sp5C, &sp54); + func_801C7B48(offset + size, &sp58, &sp50); + sp4C = D_801D2E50; + if (sp5C == sp58) { + func_801C7920(sp5C, sp4C, func_801C7BEC(sp5C)); + bcopy((u8*)sp4C + sp54, dest, size); + } else { + var_s1 = 0; + func_801C7920(sp5C, sp4C, func_801C7BEC(sp5C)); + bcopy((u8*)sp4C + sp54, dest, func_801C7BEC(sp5C) - sp54); + if (sp5C + 1 < sp58) { + for (var_s0 = sp5C + 1; var_s0 < sp58; var_s0++) { + var_s1 += func_801C7BEC(var_s0); + } + func_801C7920(sp5C + 1, (u8*)dest + func_801C7BEC(sp5C) - sp54, var_s1); + } + if (sp50 > 0) { + func_801C7920(sp58, sp4C, func_801C7BEC(sp58)); + bcopy((u8*)sp4C, (u8*)dest + func_801C7BEC(sp5C) - sp54 + var_s1, sp50); + } + } +#if OOT_VERSION == NTSC_1_0 + if (B_801D9DC0 != 0) { + temp_v1_2 = (osGetTime() - B_801D9DC0) * 64 / 3000; + if (1000000 - temp_v1_2 > 0) { + Sleep_Usec(1000000 - temp_v1_2); + } + } +#else + func_801C7B28_ne2(); +#endif + func_801C7018(); + func_801C6F78(); +} + +void func_801C7E78(void) { +} + +s32 func_801C7E80(void) { + s32 sp24; + s32 sp20; + s32 sp1C; + uintptr_t sp18; + + if (B_801D9D48 != NULL) { + return -1; + } + B_801D9D48 = &B_801D9C30; + func_801C7C1C(B_801D9D48, 0x1060, 0x118); + sp24 = B_801D9D48->unk_004 - B_801D9D48->unk_000; + sp20 = B_801D9D48->unk_00C - B_801D9D48->unk_008; + sp18 = B_801D9D48->unk_008 + sp24; + func_801C7C1C((void*)B_801D9D48->unk_008, B_801D9D48->unk_000, sp24); + bzero((void*)sp18, sp20 - sp24); + func_800AD4C0(B_801D9D48->unk_010); + return 0; +} + +s32 func_801C7F24(void) { + uintptr_t temp_a0; + struct_801D9C30* temp_v0; + + if (B_801D9D48 == 0) { + return -1; + } + + // Function from code + func_800AD51C(); + + temp_v0 = B_801D9D48; + temp_a0 = temp_v0->unk_008; + bzero((void*)temp_a0, temp_v0->unk_00C - temp_a0); + bzero(B_801D9D48, sizeof(struct_801D9C30)); + B_801D9D48 = 0; + return 0; +} + +void n64dd_SetDiskVersion(s32 arg0) { + if (arg0 != 0) { + if (B_801D9D48 == 0) { + func_801C7E80(); + } + } else if (B_801D9D48 != 0) { + func_801C7F24(); + } +} diff --git a/src/overlays/actors/ovl_Fishing/z_fishing.c b/src/overlays/actors/ovl_Fishing/z_fishing.c index d7d65652e4..d59c379b4d 100644 --- a/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -14,7 +14,7 @@ #include "cic6105.h" #endif -#pragma increment_block_number "gc-eu:149 gc-eu-mq:149 gc-jp:151 gc-jp-ce:151 gc-jp-mq:151 gc-us:151 gc-us-mq:151" +#pragma increment_block_number "gc-eu:148 gc-eu-mq:148 gc-jp:150 gc-jp-ce:150 gc-jp-mq:150 gc-us:150 gc-us-mq:150" #define FLAGS ACTOR_FLAG_4 diff --git a/tools/disasm/ntsc-1.2/variables.txt b/tools/disasm/ntsc-1.2/variables.txt index ce115492fd..d657081ebd 100644 --- a/tools/disasm/ntsc-1.2/variables.txt +++ b/tools/disasm/ntsc-1.2/variables.txt @@ -19,8 +19,6 @@ D_80121212 = 0x80121AE2; // size:0x1 type:u8 _n64ddSegmentStart = 0x801C7740; _n64ddSegmentRomStart = 0x00B8ADA0; _n64ddSegmentRomEnd = 0x00B9DA70; -D_801DA410 = 0x801DA410; -D_801E8090 = 0x801E8090; D_800FEE70 = 0x800FF4B0; // size:0xB0 type:n64ddStruct_800FEE70_pointers gPadMgr = 0x8011DBD0; // size:0x468 type:PadMgr gFaultMgr = 0x80121B60; // size:0x5D8 type:FaultMgr_v1 diff --git a/tools/fix_bss.py b/tools/fix_bss.py index 8f5f16436c..6217e822fc 100755 --- a/tools/fix_bss.py +++ b/tools/fix_bss.py @@ -189,6 +189,7 @@ def compare_pointers(version: str) -> dict[Path, BssSection]: if not ( mapfile_segment.name.startswith("..boot") or mapfile_segment.name.startswith("..code") + or mapfile_segment.name.startswith("..n64dd") or mapfile_segment.name.startswith("..ovl_") ): continue diff --git a/undefined_syms.txt b/undefined_syms.txt index b5b1b772f7..deba8affd0 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -9,28 +9,3 @@ D_0F000000 = 0x0F000000; // z_bg_mjin D_06000000 = 0x06000000; - -#if PLATFORM_N64 - -// code_n64dd_800AD410.c -func_801C6E80 = 0x801C7740; -func_801C7C1C = 0x801C8510; -D_801DA410 = 0x801DA410; -D_801E8090 = 0x801E8090; - -// game.c -func_801C7E78 = 0x801C86F0; -func_801C6EA0 = 0x801C7760; - -// z_en_mag.c -func_801C70FC = 0x801C79BC; - -// z_setup.c -n64dd_SetDiskVersion = 0x801C8808; - -// z_title.c -func_801C7818 = 0x801C8090; -func_801C7268 = 0x801C7BC4; -func_801C7658 = 0x801C7ED0; - -#endif