1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-25 09:45:02 +00:00

[ntsc-1.2] Import n64dd code from Decompollaborate/n64dd (#2136)

* Import n64dd code from Decompollaborate/n64dd

Co-authored-by: Anghelo Carvajal <angheloalf95@gmail.com>
Co-authored-by: Elliptic Ellipsis <elliptic.ellipsis@gmail.com>

* 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 <angheloalf95@gmail.com>
Co-authored-by: Elliptic Ellipsis <elliptic.ellipsis@gmail.com>
This commit is contained in:
cadmic 2024-09-07 11:37:15 -07:00 committed by GitHub
parent c27b83ac29
commit e52d135e15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 2199 additions and 30 deletions

View file

@ -0,0 +1,8 @@
<Root>
<File Name="n64dd" OutName="n64dd_error_textures">
<Texture Name="gN64DDError41JPNTex" OutName="n64dd_error_41_jpn" Format="i4" Width="192" Height="16" Offset="0x0"/>
<Texture Name="gN64DDError41ENGTex" OutName="n64dd_error_41_eng" Format="i4" Width="192" Height="16" Offset="0x600"/>
<Texture Name="gN64DDPleaseReadManualJPNTex" OutName="n64dd_please_read_manual_jpn" Format="i4" Width="320" Height="64" Offset="0xC00"/>
<Texture Name="gN64DDPleaseReadManualENGTex" OutName="n64dd_please_read_manual_eng" Format="i4" Width="320" Height="64" Offset="0x3400"/>
</File>
</Root>

View file

@ -75,6 +75,10 @@ assets:
xml_path: assets/xml/code/fbdemo_wipe1.xml xml_path: assets/xml/code/fbdemo_wipe1.xml
start_offset: 0xEB610 start_offset: 0xEB610
end_offset: 0xEBFA0 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 - name: misc/link_animetion
xml_path: assets/xml/misc/link_animetion.xml xml_path: assets/xml/misc/link_animetion.xml
- name: misc/z_select_static - name: misc/z_select_static

View file

@ -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}" 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.start_offset is not None
assert assetConfig.end_offset is not None assert assetConfig.end_offset is not None

View file

@ -1395,6 +1395,8 @@ void Audio_SetCutsceneFlag(s8 flag);
void Audio_PlaySfxIfNotInCutscene(u16 sfxId); void Audio_PlaySfxIfNotInCutscene(u16 sfxId);
void func_800F6964(u16); void func_800F6964(u16);
void Audio_StopBgmAndFanfare(u16 fadeOutDuration); void Audio_StopBgmAndFanfare(u16 fadeOutDuration);
void func_800F6B3C(void);
void func_800F6BDC(void);
void Audio_PreNMI(void); void Audio_PreNMI(void);
void Audio_SetNatureAmbienceChannelIO(u8 channelIdxRange, u8 ioPort, u8 ioData); void Audio_SetNatureAmbienceChannelIO(u8 channelIdxRange, u8 ioPort, u8 ioData);
void Audio_PlayNatureAmbienceSequence(u8 natureAmbienceId); void Audio_PlayNatureAmbienceSequence(u8 natureAmbienceId);

View file

@ -2,6 +2,7 @@
#define N64DD_H #define N64DD_H
#include "ultra64.h" #include "ultra64.h"
#include "ultra64/leo.h"
#include "z64pause.h" #include "z64pause.h"
#include "z64scene.h" #include "z64scene.h"
#include "z64map_mark.h" #include "z64map_mark.h"
@ -59,6 +60,35 @@ typedef struct n64ddStruct_80121220 {
s32 (*unk_78)(struct PlayState*, void*, void*); s32 (*unk_78)(struct PlayState*, void*, void*);
} n64ddStruct_80121220; // size = ? } 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_800AD410(void);
void func_800AD488(void); void func_800AD488(void);
n64ddStruct_80121220* func_800AD4C0(n64ddStruct_80121220* arg0); 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 func_801C7E78(void);
void n64dd_SetDiskVersion(s32 arg0); 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_800FEE70_pointers D_800FEE70;
extern n64ddStruct_80121220* B_80121220; extern n64ddStruct_80121220* B_80121220;
@ -86,4 +145,25 @@ extern u8 D_80121212;
extern vu8 D_80121213; extern vu8 D_80121213;
extern vu8 D_80121214; 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 #endif

View file

@ -203,6 +203,7 @@ extern PreNmiBuff* gAppNmiBufferPtr;
extern uintptr_t gSegments[NUM_SEGMENTS]; extern uintptr_t gSegments[NUM_SEGMENTS];
extern Scheduler gScheduler; extern Scheduler gScheduler;
extern PadMgr gPadMgr; extern PadMgr gPadMgr;
extern IrqMgr gIrqMgr;
extern volatile OSTime gAudioThreadUpdateTimeTotalPerGfxTask; extern volatile OSTime gAudioThreadUpdateTimeTotalPerGfxTask;
extern volatile OSTime gGfxTaskSentToNextReadyMinusAudioThreadUpdateTime; extern volatile OSTime gGfxTaskSentToNextReadyMinusAudioThreadUpdateTime;
extern volatile OSTime gRSPAudioTimeTotal; extern volatile OSTime gRSPAudioTimeTotal;

View file

@ -76,6 +76,8 @@
#define THREAD_PRI_DMAMGR_LOW 10 // Used when decompressing files #define THREAD_PRI_DMAMGR_LOW 10 // Used when decompressing files
#define THREAD_PRI_GRAPH 11 #define THREAD_PRI_GRAPH 11
#define THREAD_PRI_AUDIOMGR 12 #define THREAD_PRI_AUDIOMGR 12
#define THREAD_PRI_N64DD 13
#define THREAD_PRI_DDMSG 13
#define THREAD_PRI_PADMGR 14 #define THREAD_PRI_PADMGR 14
#define THREAD_PRI_MAIN 15 #define THREAD_PRI_MAIN 15
#define THREAD_PRI_SCHED 15 #define THREAD_PRI_SCHED 15
@ -90,6 +92,8 @@
#define THREAD_ID_GRAPH 4 #define THREAD_ID_GRAPH 4
#define THREAD_ID_SCHED 5 #define THREAD_ID_SCHED 5
#define THREAD_ID_PADMGR 7 #define THREAD_ID_PADMGR 7
#define THREAD_ID_N64DD 8
#define THREAD_ID_DDMSG 9
#define THREAD_ID_AUDIOMGR 10 #define THREAD_ID_AUDIOMGR 10
#define THREAD_ID_DMAMGR 18 #define THREAD_ID_DMAMGR 18
#define THREAD_ID_IRQMGR 19 #define THREAD_ID_IRQMGR 19

13
spec
View file

@ -788,7 +788,18 @@ endseg
#if PLATFORM_N64 #if PLATFORM_N64
beginseg beginseg
name "n64dd" 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/api/readwrite.o"
include "$(BUILD_DIR)/src/libleo/leo/leofunc.o" include "$(BUILD_DIR)/src/libleo/leo/leofunc.o"
include "$(BUILD_DIR)/src/libleo/leo/leoram.o" include "$(BUILD_DIR)/src/libleo/leo/leoram.o"

345
src/n64dd/n64dd_801C8000.c Normal file
View file

@ -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;
}

398
src/n64dd/n64dd_801C8940.c Normal file
View file

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

263
src/n64dd/n64dd_801C9440.c Normal file
View file

@ -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;
}

172
src/n64dd/n64dd_801C9B70.c Normal file
View file

@ -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); // ''
} else {
character = 0xA1A1; // ' '
}
func_801C94F8(buf, character);
buf += 2;
func_801C94F8(buf, ((temp_v0 & 0xF) + 0xA3B0)); // ''
}
// 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;
}

243
src/n64dd/n64dd_801CA0B0.c Normal file
View file

@ -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;
}

View file

@ -0,0 +1,5 @@
#include "global.h"
#include "n64dd.h"
// Buffer used for reading from the disk?
u8 B_801DC000[0x4D10];

View file

@ -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 },
},
};

View file

@ -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 };

View file

@ -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

584
src/n64dd/z_n64dd.c Normal file
View file

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

View file

@ -14,7 +14,7 @@
#include "cic6105.h" #include "cic6105.h"
#endif #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 #define FLAGS ACTOR_FLAG_4

View file

@ -19,8 +19,6 @@ D_80121212 = 0x80121AE2; // size:0x1 type:u8
_n64ddSegmentStart = 0x801C7740; _n64ddSegmentStart = 0x801C7740;
_n64ddSegmentRomStart = 0x00B8ADA0; _n64ddSegmentRomStart = 0x00B8ADA0;
_n64ddSegmentRomEnd = 0x00B9DA70; _n64ddSegmentRomEnd = 0x00B9DA70;
D_801DA410 = 0x801DA410;
D_801E8090 = 0x801E8090;
D_800FEE70 = 0x800FF4B0; // size:0xB0 type:n64ddStruct_800FEE70_pointers D_800FEE70 = 0x800FF4B0; // size:0xB0 type:n64ddStruct_800FEE70_pointers
gPadMgr = 0x8011DBD0; // size:0x468 type:PadMgr gPadMgr = 0x8011DBD0; // size:0x468 type:PadMgr
gFaultMgr = 0x80121B60; // size:0x5D8 type:FaultMgr_v1 gFaultMgr = 0x80121B60; // size:0x5D8 type:FaultMgr_v1

View file

@ -189,6 +189,7 @@ def compare_pointers(version: str) -> dict[Path, BssSection]:
if not ( if not (
mapfile_segment.name.startswith("..boot") mapfile_segment.name.startswith("..boot")
or mapfile_segment.name.startswith("..code") or mapfile_segment.name.startswith("..code")
or mapfile_segment.name.startswith("..n64dd")
or mapfile_segment.name.startswith("..ovl_") or mapfile_segment.name.startswith("..ovl_")
): ):
continue continue

View file

@ -9,28 +9,3 @@ D_0F000000 = 0x0F000000;
// z_bg_mjin // z_bg_mjin
D_06000000 = 0x06000000; 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