summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/boot_variables.h15
-rw-r--r--include/irqmgr.h2
-rw-r--r--include/loadfragment.h2
-rw-r--r--include/m_thread.h11
-rw-r--r--include/yaz0.h3
-rw-r--r--include/z_std_dma.h57
-rw-r--r--linker_scripts/jp/symbol_addrs_boot.txt72
-rw-r--r--src/boot/O2/loadfragment2.c8
-rw-r--r--src/boot/boot_main.c2
-rw-r--r--src/boot/idle.c7
-rw-r--r--src/boot/ovlmgr.c6
-rw-r--r--src/boot/z_std_dma.c470
-rw-r--r--src/code/irqmgr.c2
-rw-r--r--src/dmadata/dmadata.c2
-rw-r--r--src/overlays/gamestates/ovl_play/m_play.c2
-rw-r--r--yamls/jp/boot.yaml10
16 files changed, 577 insertions, 94 deletions
diff --git a/include/boot_variables.h b/include/boot_variables.h
index 4f6f51a..8345c2c 100644
--- a/include/boot_variables.h
+++ b/include/boot_variables.h
@@ -12,8 +12,8 @@
// extern UNK_TYPE D_8003BBC4_jp;
// extern UNK_TYPE D_FLT_8003BBC8_jp;
// extern UNK_TYPE D_FLT_8003BBCC_jp;
-extern OSPiHandle* gCartHandle; // TODO: Determine where this goes
-// extern UNK_TYPE D_8003BBE0_jp;
+extern OSPiHandle* carthandle; // TODO: Determine where this goes
+
// extern UNK_TYPE D_8003BBF0_jp;
// extern UNK_TYPE D_8003BC38_jp;
// extern UNK_TYPE D_8003BC50_jp;
@@ -238,16 +238,7 @@ extern OSPiHandle* gCartHandle; // TODO: Determine where this goes
// extern UNK_TYPE B_8003FEE0_jp;
// extern UNK_TYPE gViConfigBlackNext;
// extern UNK_TYPE gViConfigBlack;
-// extern UNK_TYPE B_8003FF40_jp;
-// extern UNK_TYPE B_8003FF5C_jp;
-// extern UNK_TYPE B_8003FF60_jp;
-// extern UNK_TYPE B_8003FF78_jp;
-// extern UNK_TYPE B_8003FFF8_jp;
-// extern UNK_TYPE B_800401A8_jp;
-// extern UNK_TYPE B_800406A8_jp;
-// extern UNK_TYPE B_800406AC_jp;
-// extern UNK_TYPE B_800406B0_jp;
-// extern UNK_TYPE B_800406B4_jp;
+
// extern UNK_TYPE B_800406C0_jp;
// extern UNK_TYPE B_80040AC0_jp;
// extern UNK_TYPE B_80040AC4_jp;
diff --git a/include/irqmgr.h b/include/irqmgr.h
index 2acff16..ea04422 100644
--- a/include/irqmgr.h
+++ b/include/irqmgr.h
@@ -47,7 +47,7 @@ void IrqMgr_HandleRetrace(void);
void irqmgr_Main(void* arg);
void CreateIRQManager(void* stack, OSPri priority, u8 retracecount);
-extern vu32 ResetStatus;
+extern vs32 ResetStatus;
extern volatile OSTime ResetTime;
extern volatile OSTime RetraceTime;
extern u32 RetraceCount;
diff --git a/include/loadfragment.h b/include/loadfragment.h
index 487f042..6630759 100644
--- a/include/loadfragment.h
+++ b/include/loadfragment.h
@@ -34,6 +34,6 @@ typedef struct OverlayRelocationSection {
/* 0x14 */ u32 relocations[1]; // size is nRelocations
} OverlayRelocationSection; // size >= 0x18
-s32 Overlay_Load(RomOffset vromStart, RomOffset vromEnd, void *ovlStart, void *ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs);
+s32 Overlay_Load(RomOffset vromStart, RomOffset vromEnd, RomOffset ovlStart, RomOffset ovlEnd, void *vramStart, void *vramEnd, void *allocatedRamAddr, OverlayRelocationSection *ovlRelocs);
#endif
diff --git a/include/m_thread.h b/include/m_thread.h
index db6ed1b..45cb851 100644
--- a/include/m_thread.h
+++ b/include/m_thread.h
@@ -1,12 +1,15 @@
#ifndef M_THREAD_H
#define M_THREAD_H
-#define M_THREAD_ID_IDLE 1
-#define M_THREAD_ID_MAIN 3
+#define M_THREAD_ID_IDLE 1
+#define M_THREAD_ID_MAIN 3
+#define M_THREAD_ID_DMAMGR 8
#define M_THREAD_ID_IRQMGR 9
-#define M_PRIORITY_IDLE 12
-#define M_PRIORITY_MAIN 12
+#define M_PRIORITY_DMAMGR_LOW 10 // Used when decompressing files
+#define M_PRIORITY_IDLE 12
+#define M_PRIORITY_MAIN 12
+#define M_PRIORITY_DMAMGR 17
#endif
diff --git a/include/yaz0.h b/include/yaz0.h
index d20c698..dadf6e6 100644
--- a/include/yaz0.h
+++ b/include/yaz0.h
@@ -2,10 +2,11 @@
#define YAZ0_H
#include "ultra64.h"
+#include "other_types.h"
// void Yaz0_FirstDMA();
// void Yaz0_NextDMA();
// void Yaz0_DecompressImpl();
-// void Yaz0_Decompress();
+void Yaz0_Decompress(RomOffset vrom, void* dst, size_t size);
#endif
diff --git a/include/z_std_dma.h b/include/z_std_dma.h
index bd337e5..a047ddd 100644
--- a/include/z_std_dma.h
+++ b/include/z_std_dma.h
@@ -1,9 +1,22 @@
#ifndef Z_STD_DMA_H
#define Z_STD_DMA_H
-#include "libc/stdint.h"
#include "ultra64.h"
+#include "libc/stdint.h"
+#include "alignment.h"
#include "other_types.h"
+#include "unk.h"
+
+typedef struct DmaRequest {
+ /* 0x00 */ RomOffset vrom;
+ /* 0x04 */ void* vram;
+ /* 0x08 */ size_t size;
+ /* 0x0C */ const char* filename;
+ /* 0x10 */ s32 line;
+ /* 0x14 */ UNK_TYPE unk_14;
+ /* 0x18 */ OSMesgQueue* mq;
+ /* 0x1C */ OSMesg msg;
+} DmaRequest; // size = 0x20
typedef struct DmaEntry {
/* 0x0 */ RomOffset vromStart;
@@ -12,26 +25,26 @@ typedef struct DmaEntry {
/* 0xC */ RomOffset romEnd;
} DmaEntry; // size = 0x10
-extern DmaEntry gDmaDataTable[];
-
-// void func_800263F0_jp();
-// void DmaMgr_DmaRomToRam();
-// void func_800266C4_jp();
-// void func_80026714_jp();
-// void func_80026770_jp();
-// void func_800267DC_jp();
-// void func_80026814_jp();
-// void func_80026828_jp();
-// void func_800269E4_jp();
-// void func_80026A64_jp();
-void DmaMgr_RequestSync(void* ram, void* vrom, size_t size);
-// void func_80026BC0_jp();
-// void func_80026C00_jp();
-// void func_80026C28_jp();
-s32 func_80026C4C_jp(RomOffset vromStart, RomOffset* vromEnd, void* ovlStart, void* ovlEnd);
-void func_80026CAC_jp(void);
-void func_80026DA0_jp(void);
-// void func_80026DCC_jp();
-void func_80026E10_jp(void* arg0, RomOffset arg1, size_t arg2, const char* arg3, s32 arg4);
+extern DmaEntry dma_rom_ad[];
+
+s32 DmaMgr_DmaRomToRam(RomOffset vrom, void* vram, size_t size);
+s32 DmaMgr_AudioDmaHandler(OSPiHandle* pihandle, OSIoMesg* mb, s32 direction);
+s32 DmaMgr_RequestSync(void* vram, RomOffset vrom, size_t size);
+s32 DmaMgr_RequestSyncNoSize(void* vram, RomOffset vrom);
+size_t DmaMgr_GetSegmentSize(RomOffset vrom);
+RomOffset DmaMgr_GetOvlStart(RomOffset vrom);
+s32 DmaMgr_GetOvlOffsets(RomOffset vromStart, RomOffset* vromEnd, RomOffset* ovlStart, RomOffset* ovlEnd);
+void DmaMgr_Init(void);
+void DmaMgr_Stop(void);
+void DmaMgr_RequestAsync(DmaRequest* req, void* vram, RomOffset vrom, size_t size, s32 arg4, OSMesgQueue* mq, OSMesg msg, const char* filename, s32 line);
+s32 DmaMgr_RequestSyncDebug(void* vram, RomOffset vrom, size_t size, const char* filename, s32 line);
+
+
+#define DMAMGR_DEFAULT_BUFSIZE ALIGN16(0x2000)
+
+extern size_t gDmaMgrDmaBuffSize;
+
+extern size_t B_800406B0_jp;
+extern size_t B_800406B4_jp;
#endif
diff --git a/linker_scripts/jp/symbol_addrs_boot.txt b/linker_scripts/jp/symbol_addrs_boot.txt
index e94cfe2..38ae7bc 100644
--- a/linker_scripts/jp/symbol_addrs_boot.txt
+++ b/linker_scripts/jp/symbol_addrs_boot.txt
@@ -17,25 +17,25 @@ ovlmgr_Free = 0x8002628C; // type:func
ovlmgr_LoadImpl = 0x800262D0; // type:func
ovlmgr_Load = 0x800263C0; // type:func
-func_800263F0_jp = 0x800263F0; // type:func
+DmaMgr_Error = 0x800263F0; // type:func
DmaMgr_DmaRomToRam = 0x80026500; // type:func
-func_800266C4_jp = 0x800266C4; // type:func
-func_80026714_jp = 0x80026714; // type:func
-func_80026770_jp = 0x80026770; // type:func
-func_800267DC_jp = 0x800267DC; // type:func
+DmaMgr_AudioDmaHandler = 0x800266C4; // type:func
+DmaMgr_FindDmaEntry = 0x80026714; // type:func
+DmaMgr_TranslateVromToRom = 0x80026770; // type:func
+DmaMgr_FindDmaIndex = 0x800267DC; // type:func
func_80026814_jp = 0x80026814; // type:func
-func_80026828_jp = 0x80026828; // type:func
-func_800269E4_jp = 0x800269E4; // type:func
-func_80026A64_jp = 0x80026A64; // type:func
+DmaMgr_ProcessRequest = 0x80026828; // type:func
+DmaMgr_ThreadEntry = 0x800269E4; // type:func
+DmaMgr_SendRequest = 0x80026A64; // type:func
DmaMgr_RequestSync = 0x80026B44; // type:func
-func_80026BC0_jp = 0x80026BC0; // type:func
-func_80026C00_jp = 0x80026C00; // type:func
-func_80026C28_jp = 0x80026C28; // type:func
-func_80026C4C_jp = 0x80026C4C; // type:func
-func_80026CAC_jp = 0x80026CAC; // type:func
-func_80026DA0_jp = 0x80026DA0; // type:func
-func_80026DCC_jp = 0x80026DCC; // type:func
-func_80026E10_jp = 0x80026E10; // type:func
+DmaMgr_RequestSyncNoSize = 0x80026BC0; // type:func
+DmaMgr_GetSegmentSize = 0x80026C00; // type:func
+DmaMgr_GetOvlStart = 0x80026C28; // type:func
+DmaMgr_GetOvlOffsets = 0x80026C4C; // type:func
+DmaMgr_Init = 0x80026CAC; // type:func
+DmaMgr_Stop = 0x80026DA0; // type:func
+DmaMgr_RequestAsync = 0x80026DCC; // type:func
+DmaMgr_RequestSyncDebug = 0x80026E10; // type:func
Yaz0_FirstDMA = 0x80026EA0; // type:func
Yaz0_NextDMA = 0x80026F40; // type:func
@@ -270,8 +270,8 @@ D_8003BBC0_jp = 0x8003BBC0; // type:s8
gViConfigFeatures = 0x8003BBC4; //
gViConfigXScale = 0x8003BBC8; // type:f32
gViConfigYScale = 0x8003BBCC; // type:f32
-gCartHandle = 0x8003BBD0; //
-D_8003BBE0_jp = 0x8003BBE0; //
+carthandle = 0x8003BBD0; //
+gDmaMgrDmaBuffSize = 0x8003BBE0; //
D_8003BBF0_jp = 0x8003BBF0; //
D_8003BC38_jp = 0x8003BC38; //
D_8003BC50_jp = 0x8003BC50; //
@@ -312,23 +312,23 @@ RO_STR_8003D1B4_jp = 0x8003D1B4; // type:asciz
RO_STR_8003D1D0_jp = 0x8003D1D0; // type:asciz
RO_STR_8003D1D4_jp = 0x8003D1D4; // type:asciz
-RO_STR_8003D1D8_jp = 0x8003D1D8; // type:asciz
-RO_STR_8003D1EC_jp = 0x8003D1EC; // type:asciz
-RO_STR_8003D200_jp = 0x8003D200; // type:asciz
-RO_STR_8003D214_jp = 0x8003D214; // type:asciz
-RO_STR_8003D218_jp = 0x8003D218; // type:asciz
-RO_STR_8003D22C_jp = 0x8003D22C; // type:asciz
+RO_STR_8003D1D8_jp = 0x8003D1D8; // type:asciz force_not_migration:True
+RO_STR_8003D1EC_jp = 0x8003D1EC; // type:asciz force_not_migration:True
+RO_STR_8003D200_jp = 0x8003D200; // type:asciz force_not_migration:True
+RO_STR_8003D214_jp = 0x8003D214; // type:asciz force_not_migration:True
+RO_STR_8003D218_jp = 0x8003D218; // type:asciz force_not_migration:True
+RO_STR_8003D22C_jp = 0x8003D22C; // type:asciz force_not_migration:True
RO_STR_8003D230_jp = 0x8003D230; // type:asciz
RO_STR_8003D23C_jp = 0x8003D23C; // type:asciz
RO_STR_8003D250_jp = 0x8003D250; // type:asciz
RO_STR_8003D264_jp = 0x8003D264; // type:asciz
-RO_8003D268_jp = 0x8003D268; //
+RO_STR_8003D268_jp = 0x8003D268; // type:asciz
RO_STR_8003D26C_jp = 0x8003D26C; // type:asciz
RO_STR_8003D284_jp = 0x8003D284; // type:asciz
-RO_8003D2C0_jp = 0x8003D2C0; //
+RO_STR_8003D2C0_jp = 0x8003D2C0; // type:asciz
RO_STR_8003D2C4_jp = 0x8003D2C4; // type:asciz
RO_STR_8003D2DC_jp = 0x8003D2DC; // type:asciz
-RO_8003D31C_jp = 0x8003D31C; //
+RO_STR_8003D31C_jp = 0x8003D31C; // type:asciz
RO_STR_8003D320_jp = 0x8003D320; // type:asciz
RO_STR_8003D338_jp = 0x8003D338; // type:asciz
RO_STR_8003D378_jp = 0x8003D378; // type:asciz
@@ -529,14 +529,14 @@ sPiMgrCmdQueue = 0x8003FEC8; //
gViConfigMode = 0x8003FEE0; //
gViConfigBlackNext = 0x8003FF30; // type:u8
gViConfigBlack = 0x8003FF31; // type:u8
-B_8003FF40_jp = 0x8003FF40; //
-B_8003FF5C_jp = 0x8003FF5C; // type:u16
-B_8003FF60_jp = 0x8003FF60; //
-B_8003FF78_jp = 0x8003FF78; //
-B_8003FFF8_jp = 0x8003FFF8; //
-B_800401A8_jp = 0x800401A8; //
-B_800406A8_jp = 0x800406A8; //
-B_800406AC_jp = 0x800406AC; //
+sDmaMgrStackInfo = 0x8003FF40; //
+sNumDmaEntries = 0x8003FF5C; // type:u16
+sDmaMgrMsgQueue = 0x8003FF60; //
+dmaEntryMsgBufs = 0x8003FF78; //
+sDmaMgrThread = 0x8003FFF8; //
+sDmaMgrStack = 0x800401A8; //
+sDmaMgrCurFileName = 0x800406A8; //
+sDmaMgrCurFileLine = 0x800406AC; //
B_800406B0_jp = 0x800406B0; //
B_800406B4_jp = 0x800406B4; //
B_800406C0_jp = 0x800406C0; //
@@ -573,4 +573,4 @@ sArenaLockMsg = 0x80041A00; // size:0x4
B_80044684_jp = 0x80044684; //
-gDmaDataTable = 0x80044690; //
+dma_rom_ad = 0x80044690; //
diff --git a/src/boot/O2/loadfragment2.c b/src/boot/O2/loadfragment2.c
index fdb6938..3b4a888 100644
--- a/src/boot/O2/loadfragment2.c
+++ b/src/boot/O2/loadfragment2.c
@@ -13,15 +13,15 @@
void DoRelocation(void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs, void* vramStart);
// original name unknown
-s32 Overlay_Load(RomOffset vromStart, RomOffset vromEnd, void* ovlStart, void* ovlEnd, void* vramStart, void* vramEnd,
- void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs) {
+s32 Overlay_Load(RomOffset vromStart, RomOffset vromEnd, RomOffset ovlStart, RomOffset ovlEnd, void* vramStart,
+ void* vramEnd, void* allocatedRamAddr, OverlayRelocationSection* ovlRelocs) {
OverlayRelocationSection* ovl = ovlRelocs;
s32 vromSize = vromEnd - vromStart;
- s32 ovlSize = (uintptr_t)ovlEnd - (uintptr_t)ovlStart;
+ s32 ovlSize = ovlEnd - ovlStart;
s32 vramSize = (uintptr_t)vramEnd - (uintptr_t)vramStart;
void* end = (void*)((uintptr_t)allocatedRamAddr + vromSize);
- DmaMgr_RequestSync(allocatedRamAddr, (void*)vromStart, vromSize);
+ DmaMgr_RequestSync(allocatedRamAddr, vromStart, vromSize);
DmaMgr_RequestSync(ovl, ovlStart, ovlSize);
DoRelocation(allocatedRamAddr, ovl, vramStart);
diff --git a/src/boot/boot_main.c b/src/boot/boot_main.c
index 9269248..c3a70e6 100644
--- a/src/boot/boot_main.c
+++ b/src/boot/boot_main.c
@@ -43,7 +43,7 @@ void bootproc(void) {
osUnmapTLBAll();
bootclear();
- gCartHandle = osCartRomInit();
+ carthandle = osCartRomInit();
StackCheck_Init(&sIdleStackInfo, sIdleStack, STACK_TOP(sIdleStack), 0, 0x100, "idle");
osCreateThread(&sIdleThread, M_THREAD_ID_IDLE, Idle_ThreadEntry, NULL, STACK_TOP(sIdleStack), M_PRIORITY_IDLE);
diff --git a/src/boot/idle.c b/src/boot/idle.c
index a958fd6..6a2d627 100644
--- a/src/boot/idle.c
+++ b/src/boot/idle.c
@@ -22,11 +22,12 @@ f32 gViConfigXScale = 1.0f;
f32 gViConfigYScale = 1.0f;
void Main_ThreadEntry(void* arg) {
- func_80026CAC_jp();
- func_80026E10_jp(SEGMENT_VRAM_START(code), SEGMENT_ROM_START(code), SEGMENT_ROM_SIZE_ALT(code), "../idle.c", 53);
+ DmaMgr_Init();
+ DmaMgr_RequestSyncDebug(SEGMENT_VRAM_START(code), SEGMENT_ROM_START(code), SEGMENT_ROM_SIZE_ALT(code), "../idle.c",
+ 53);
bzero(SEGMENT_BSS_START(code), SEGMENT_BSS_SIZE(code));
func_800D66D0_jp(arg);
- func_80026DA0_jp();
+ DmaMgr_Stop();
}
void Idle_InitVideo(void) {
diff --git a/src/boot/ovlmgr.c b/src/boot/ovlmgr.c
index c63e40a..9e20d96 100644
--- a/src/boot/ovlmgr.c
+++ b/src/boot/ovlmgr.c
@@ -31,13 +31,13 @@ void ovlmgr_Free(void* ptr) {
void ovlmgr_LoadImpl(RomOffset vromStart, UNUSED RomOffset vromEndUnused, void* vramStart, void* vramEnd,
void* allocatedRamAddr, struct OverlayRelocationSection* ovl, size_t size) {
RomOffset vromEnd;
- void* ovlStart;
- void* ovlEnd;
+ RomOffset ovlStart;
+ RomOffset ovlEnd;
size_t ovlSize;
OverlayRelocationSection* ovlRelocs;
char ovlSizeStr[80];
- func_80026C4C_jp(vromStart, &vromEnd, &ovlStart, &ovlEnd);
+ DmaMgr_GetOvlOffsets(vromStart, &vromEnd, &ovlStart, &ovlEnd);
ovlSize = (uintptr_t)ovlEnd - (uintptr_t)ovlStart;
diff --git a/src/boot/z_std_dma.c b/src/boot/z_std_dma.c
new file mode 100644
index 0000000..04184d9
--- /dev/null
+++ b/src/boot/z_std_dma.c
@@ -0,0 +1,470 @@
+#include "stack.h"
+#include "libu64/stackcheck.h"
+#include "unk.h"
+
+StackEntry sDmaMgrStackInfo;
+u16 sNumDmaEntries;
+OSMesgQueue sDmaMgrMsgQueue;
+OSMesg dmaEntryMsgBufs[0x20];
+OSThread sDmaMgrThread;
+STACK(sDmaMgrStack, 0x500);
+const char* sDmaMgrCurFileName;
+UNK_TYPE sDmaMgrCurFileLine;
+size_t B_800406B0_jp;
+size_t B_800406B4_jp;
+
+#include "z_std_dma.h"
+#include "fault.h"
+#include "irqmgr.h"
+#include "yaz0.h"
+#include "libc/stdbool.h"
+#include "m_thread.h"
+#include "macros.h"
+#include "attributes.h"
+#include "segment_symbols.h"
+#include "boot_variables.h"
+
+size_t gDmaMgrDmaBuffSize = DMAMGR_DEFAULT_BUFSIZE;
+
+/**
+ * DMA error encountered, print error messages and bring up the crash screen.
+ *
+ * @param req DMA Request causing the error.
+ * @param file DMA data filename associated with the operation that errored.
+ * @param errorName Error name string.
+ * @param errorDesc Error description string.
+ *
+ * This function does not return.
+ */
+NORETURN void DmaMgr_Error(DmaRequest* req, const char* file, const char* errorName, const char* errorDesc) {
+ RomOffset vrom = req->vrom;
+ void* vram = req->vram;
+ size_t size = req->size;
+ char buff1[80];
+ char buff2[80];
+
+ (void)(errorDesc != NULL ? errorDesc : (errorName != NULL ? errorName : "???"));
+ (void)(file != NULL ? file : "???");
+
+ if (req->filename != NULL) {
+ } else if (sDmaMgrCurFileName != NULL) {
+ }
+
+ if (req->filename != NULL) {
+ sprintf(buff1, "DMA ERROR: %.50s %d", req->filename, req->line);
+ } else if (sDmaMgrCurFileName != NULL) {
+ sprintf(buff1, "DMA ERROR: %.50s %d", sDmaMgrCurFileName, sDmaMgrCurFileLine);
+ } else {
+ sprintf(buff1, "DMA ERROR: %.50s", (errorName != NULL) ? errorName : "???");
+ }
+
+ sprintf(buff2, "%07X %08X %X %.50s", vrom, vram, size, (file != NULL) ? file : "???");
+ Fault_AddHungupAndCrashImpl(buff1, buff2);
+}
+
+/**
+ * Transfer `size` bytes from physical ROM address `vrom` to `vram`.
+ *
+ * This function is intended for internal use only, however it is possible to use this function externally in which
+ * case it behaves as a synchronous transfer, data is available as soon as this function returns.
+ *
+ * Transfers are divided into chunks based on the current value of `gDmaMgrDmaBuffSize` to avoid congestion of the PI
+ * so that higher priority transfers can still be carried out in a timely manner. The transfers are sent in a queue to
+ * the OS PI Manager which performs the transfer.
+ *
+ * The `vrom` address and the `size` are expected to be at least 0x2 aligned, while the destination `vram` should be 0x8
+ * aligned, otherwise a fatal error will be triggered.
+ *
+ * @return 0 if successful, -1 if the DMA could not be queued with the PI Manager.
+ */
+s32 DmaMgr_DmaRomToRam(RomOffset vrom, void* vram, size_t size) {
+ OSIoMesg ioMsg;
+ OSMesgQueue queue;
+ OSMesg msg[1];
+ s32 ret;
+ size_t buffSize = gDmaMgrDmaBuffSize;
+ DmaRequest req;
+
+ if (((vrom << 31) != 0) || (((u32)vram << 29) != 0) || ((size << 31) != 0)) {
+ req.vrom = vrom;
+ req.vram = vram;
+ req.size = size;
+ req.filename = "percial_DMA";
+ req.line = 0;
+ // "alignment error"
+ DmaMgr_Error(&req, NULL, "ILLIGAL ALIGNMENT", "アライメント異常");
+ }
+
+ osInvalDCache(vram, size);
+ osCreateMesgQueue(&queue, msg, ARRAY_COUNT(msg));
+
+ if (buffSize > 0) {
+ while (size > buffSize) {
+ // The system avoids large DMAs as these would stall the PI for too long, potentially causing issues with
+ // audio. To allow audio to continue to DMA whenever it needs to, other DMAs are split into manageable
+ // chunks.
+
+ ioMsg.hdr.pri = 0;
+ ioMsg.hdr.retQueue = &queue;
+ ioMsg.devAddr = vrom;
+ ioMsg.dramAddr = vram;
+ ioMsg.size = buffSize;
+ B_800406B0_jp += buffSize;
+
+ //! FAKE
+ if (1) {}
+ if (1) {}
+
+ ret = osEPiStartDma(carthandle, &ioMsg, 0);
+ if (ret != 0) {
+ goto end;
+ }
+
+ osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
+ size -= buffSize;
+ vrom += buffSize;
+ vram = (void*)((uintptr_t)vram + buffSize);
+ }
+ }
+
+ ioMsg.hdr.pri = 0;
+ ioMsg.hdr.retQueue = &queue;
+ ioMsg.devAddr = vrom;
+ ioMsg.dramAddr = vram;
+ ioMsg.size = size;
+ B_800406B0_jp += size;
+
+ ret = osEPiStartDma(carthandle, &ioMsg, 0);
+ if (ret != 0) {
+ goto end;
+ }
+
+ osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
+ osInvalDCache(vram, size);
+
+end:
+ return ret;
+}
+
+/**
+ * Callback function to facilitate audio DMA. Audio DMA does not use the request queue as audio data is often needed
+ * very soon after the request is sent, requiring a higher priority method for enqueueing a DMA on the OS PI command
+ * queue.
+ *
+ * @param pihandle Cartridge ROM PI Handle.
+ * @param mb IO Message describing the transfer.
+ * @param direction Read or write. (Only read is allowed)
+ * @return 0 if the IO Message was successfully put on the OS PI command queue, < 0 otherwise
+ */
+s32 DmaMgr_AudioDmaHandler(OSPiHandle* pihandle, OSIoMesg* mb, s32 direction) {
+ s32 ret = osEPiStartDma(pihandle, mb, direction);
+
+ B_800406B0_jp += mb->size;
+ B_800406B4_jp += mb->size;
+
+ return ret;
+}
+
+DmaEntry* DmaMgr_FindDmaEntry(RomOffset vrom) {
+ DmaEntry* entry;
+
+ for (entry = dma_rom_ad; entry->vromEnd != 0; entry++) {
+ if ((vrom >= entry->vromStart) && (vrom < entry->vromEnd)) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+RomOffset DmaMgr_TranslateVromToRom(RomOffset vrom) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vrom);
+
+ if (entry != NULL) {
+ if (entry->romEnd == 0) {
+ return (entry->romStart + vrom) - entry->vromStart;
+ }
+
+ if (vrom == entry->vromStart) {
+ return entry->romStart;
+ }
+
+ return -1;
+ }
+
+ return -1;
+}
+
+s32 DmaMgr_FindDmaIndex(RomOffset vrom) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vrom);
+
+ if (entry != NULL) {
+ return entry - dma_rom_ad;
+ }
+ return -1;
+}
+
+const char* func_80026814_jp(UNUSED s32 arg0) {
+ return "??";
+}
+
+void DmaMgr_ProcessRequest(DmaRequest* req) {
+ RomOffset vrom = req->vrom;
+ void* vram = req->vram;
+ size_t size = req->size;
+ RomOffset romStart;
+ size_t romSize;
+ DmaEntry* entry;
+ s32 index = DmaMgr_FindDmaIndex(vrom);
+
+ if ((index >= 0) && (index < sNumDmaEntries)) {
+ entry = &dma_rom_ad[index];
+
+ if (entry->romEnd == 0) {
+ // romEnd of 0 indicates that the file is uncompressed. Files that are stored uncompressed can have only
+ // part of their content loaded into RAM, so DMA only the requested region.
+
+ if (entry->vromEnd < (vrom + size)) {
+ // Error, vrom + size ends up in a different file than it started in
+
+ // "DMA transfers cannot cross segment boundaries"
+ DmaMgr_Error(req, "", "Segment Alignment Error",
+ "セグメント境界をまたがってDMA転送することはできません");
+ }
+ DmaMgr_DmaRomToRam((entry->romStart + vrom) - entry->vromStart, vram, size);
+ } else {
+ // File is compressed. Files that are stored compressed must be loaded into RAM all at once.
+
+ romSize = entry->romEnd - entry->romStart;
+ romStart = entry->romStart;
+ if (vrom != entry->vromStart) {
+ // "DMA transfer cannot be performed from the middle of a compressed segment"
+ DmaMgr_Error(req, "", "Can't Transfer Segment",
+ "圧縮されたセグメントの途中からはDMA転送することはできません");
+ }
+
+ if (size != (entry->vromEnd - entry->vromStart)) {
+ // Error, only part of the file was requested
+
+ // "It is not possible to DMA only part of a compressed segment"
+ DmaMgr_Error(req, "", "Can't Transfer Segment",
+ "圧縮されたセグメントの一部だけをDMA転送することはできません");
+ }
+
+ // Reduce the thread priority and decompress the file, the decompression routine handles the DMA in chunks.
+ // Restores the thread priority when done.
+ osSetThreadPri(NULL, M_PRIORITY_DMAMGR_LOW);
+ Yaz0_Decompress(romStart, vram, romSize);
+ osSetThreadPri(NULL, M_PRIORITY_DMAMGR);
+ }
+ } else {
+ // "Corresponding data does not exist"
+ DmaMgr_Error(req, NULL, "DATA DON'T EXIST", "該当するデータが存在しません");
+ }
+}
+
+void DmaMgr_ThreadEntry(UNUSED void* arg) {
+ OSMesg msg;
+ DmaRequest* req;
+
+ while (true) {
+ // Wait for DMA Requests to arrive from other threads
+ osRecvMesg(&sDmaMgrMsgQueue, &msg, OS_MESG_BLOCK);
+
+ if (msg == NULL) {
+ break;
+ }
+ req = msg;
+
+ // Process the DMA request
+ DmaMgr_ProcessRequest(req);
+
+ // Notify the sender that the request has been processed
+ if (req->mq != NULL) {
+ osSendMesg(req->mq, req->msg, OS_MESG_NOBLOCK);
+ }
+ }
+}
+
+/**
+ * Submits a DMA request to the DMA manager. For internal use only.
+ *
+ * @param req DMA request, filled out internally.
+ * @param vram Location in DRAM for data to be written.
+ * @param vrom Virtual ROM location for data to be read.
+ * @param size Transfer size.
+ * @param mq Message queue to notify with `msg` once the transfer is complete.
+ * @param msg Message to send to `mq` once the transfer is complete.
+ */
+s32 DmaMgr_SendRequest(DmaRequest* req, void* vram, RomOffset vrom, size_t size, UNUSED s32 arg4, OSMesgQueue* mq,
+ OSMesg arg6) {
+ if (ResetStatus >= 2) {
+ return -2;
+ }
+
+ req->vrom = vrom;
+ req->vram = vram;
+ req->size = size;
+ req->unk_14 = 0;
+ req->mq = mq;
+ req->msg = arg6;
+
+ if ((vram == NULL) || (osMemSize < (OS_K0_TO_PHYSICAL(vram) + size)) || (vrom % 2 != 0) || (vrom > 0x04000000) ||
+ (size == 0) || (size % 2 != 0)) {
+ DmaMgr_Error(req, NULL, "ILLIGAL DMA-FUNCTION CALL", "パラメータ異常です");
+ }
+
+ osSendMesg(&sDmaMgrMsgQueue, req, OS_MESG_BLOCK);
+ return 0;
+}
+
+/**
+ * Submit a synchronous DMA request. This will block the current thread until the requested transfer is complete. Data
+ * is immediately available as soon as this function returns.
+ *
+ * @param vram Location in RAM for data to be written.
+ * @param vrom Virtual ROM location for data to be read.
+ * @param size Transfer size.
+ */
+s32 DmaMgr_RequestSync(void* vram, RomOffset vrom, size_t size) {
+ DmaRequest req;
+ OSMesgQueue mq;
+ OSMesg msg[1];
+ s32 ret;
+
+ osCreateMesgQueue(&mq, msg, ARRAY_COUNT(msg));
+ ret = DmaMgr_SendRequest(&req, vram, vrom, size, 0, &mq, NULL);
+ if (ret == -1) {
+ return ret;
+ }
+
+ osRecvMesg(&mq, NULL, OS_MESG_BLOCK);
+
+ return 0;
+}
+
+/**
+ * Synchronous DMA Request that calculates the size of the segment automatically.
+ *
+ * @see DmaMgr_RequestSync
+ */
+s32 DmaMgr_RequestSyncNoSize(void* vram, RomOffset vrom) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vrom);
+
+ return DmaMgr_RequestSync(vram, vrom, entry->vromEnd - entry->vromStart);
+}
+
+/**
+ * Returns the uncompressed size for a given segment.
+ */
+size_t DmaMgr_GetSegmentSize(RomOffset vrom) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vrom);
+
+ return entry->vromEnd - entry->vromStart;
+}
+
+/**
+ * Returns the ovl reloc vrom start for a given segment.
+ */
+RomOffset DmaMgr_GetOvlStart(RomOffset vrom) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vrom);
+
+ return entry[1].vromStart;
+}
+
+/**
+ * Searches for the rom offsets of the ovl reloc segment for a given segment.
+ *
+ * The values will be stored in the pointers passed as parameters. If no segment matches the given vrom then the
+ * parameters will be left untouched.
+ *
+ * @param vromStart The vrom start of the segment.
+ * @param[out] vromEnd The vrom end for the given segment.
+ * @param[out] ovlStart The vrom start for the ovl reloc segment.
+ * @param[out] ovlEnd The vrom end for the ovl reloc segment.
+ * @return s32 0 if the given segment is found, -1 otherwise.
+ */
+s32 DmaMgr_GetOvlOffsets(RomOffset vromStart, RomOffset* vromEnd, RomOffset* ovlStart, RomOffset* ovlEnd) {
+ DmaEntry* entry = DmaMgr_FindDmaEntry(vromStart);
+
+ if (entry != NULL) {
+ *vromEnd = entry[0].vromEnd;
+ *ovlStart = entry[1].vromStart;
+ *ovlEnd = entry[1].vromEnd;
+ return 0;
+ }
+ return -1;
+}
+
+void DmaMgr_Init(void) {
+ // DMA the dma data table to RAM
+ DmaMgr_DmaRomToRam(SEGMENT_ROM_START(dmadata), SEGMENT_VRAM_START(dmadata), SEGMENT_ROM_SIZE(dmadata));
+
+ {
+ DmaEntry* entry = dma_rom_ad;
+ s32 count = 0;
+
+ for (; entry->vromEnd != 0; entry++) {
+ count++;
+ }
+
+ sNumDmaEntries = count;
+ }
+
+ osCreateMesgQueue(&sDmaMgrMsgQueue, dmaEntryMsgBufs, ARRAY_COUNT(dmaEntryMsgBufs));
+ StackCheck_Init(&sDmaMgrStackInfo, sDmaMgrStack, STACK_TOP(sDmaMgrStack), 0, 0x100, "dmamgr");
+ osCreateThread(&sDmaMgrThread, M_THREAD_ID_DMAMGR, DmaMgr_ThreadEntry, NULL, STACK_TOP(sDmaMgrStack),
+ M_PRIORITY_DMAMGR);
+ osStartThread(&sDmaMgrThread);
+}
+
+void DmaMgr_Stop(void) {
+ osSendMesg(&sDmaMgrMsgQueue, NULL, OS_MESG_BLOCK);
+}
+
+/**
+ * Submit an asynchronous DMA request. Unlike other DMA requests, this will not block the current thread. Data arrival
+ * is not immediate however, ensure that the request has completed by awaiting a message sent to `mq` when the DMA
+ * operation has completed.
+ *
+ * @param req DMA request structure, filled out internally.
+ * @param vram Location in DRAM for data to be written.
+ * @param vrom Virtual ROM location for data to be read.
+ * @param size Transfer size.
+ * @param mq Message queue to notify with `msg` once the transfer is complete.
+ * @param msg Message to send to `queue` once the transfer is complete.
+ * @param file Debug filename of caller.
+ * @param line Debug line number of caller.
+ * @return 0
+ */
+void DmaMgr_RequestAsync(DmaRequest* req, void* vram, RomOffset vrom, size_t size, s32 arg4, OSMesgQueue* mq,
+ OSMesg msg, const char* filename, s32 line) {
+ req->filename = filename;
+ req->line = line;
+ DmaMgr_SendRequest(req, vram, vrom, size, arg4, mq, msg);
+}
+
+/**
+ * Synchronous DMA Request with source file and line info for debugging.
+ *
+ * @see DmaMgr_RequestSync
+ */
+s32 DmaMgr_RequestSyncDebug(void* vram, RomOffset vrom, size_t size, const char* filename, s32 line) {
+ DmaRequest req;
+ s32 ret;
+ OSMesgQueue mq;
+ OSMesg msg[1];
+ UNUSED s32 pad;
+
+ req.filename = filename;
+ req.line = line;
+
+ osCreateMesgQueue(&mq, msg, ARRAY_COUNT(msg));
+
+ ret = DmaMgr_SendRequest(&req, vram, vrom, size, 0, &mq, NULL);
+ if (ret == -1) {
+ return ret;
+ }
+
+ osRecvMesg(&mq, NULL, OS_MESG_BLOCK);
+ return 0;
+}
diff --git a/src/code/irqmgr.c b/src/code/irqmgr.c
index a2faa5d..ea66416 100644
--- a/src/code/irqmgr.c
+++ b/src/code/irqmgr.c
@@ -8,7 +8,7 @@
Irqmgr irqmgr_class;
Irqmgr* this;
-vu32 ResetStatus = 0;
+vs32 ResetStatus = 0;
volatile OSTime ResetTime = 0;
volatile OSTime RetraceTime = 0;
u32 RetraceCount = 0;
diff --git a/src/dmadata/dmadata.c b/src/dmadata/dmadata.c
index 45d5030..a535a7c 100644
--- a/src/dmadata/dmadata.c
+++ b/src/dmadata/dmadata.c
@@ -11,7 +11,7 @@
// dmadata Table definition
#define DEFINE_DMA_ENTRY(name, _1) { SEGMENT_ROM_START(name), SEGMENT_ROM_END(name), SEGMENT_ROM_START(name), 0 },
-DmaEntry gDmaDataTable[] = {
+DmaEntry dma_rom_ad[] = {
#include "tables/dmadata_table.h"
{ 0 },
};
diff --git a/src/overlays/gamestates/ovl_play/m_play.c b/src/overlays/gamestates/ovl_play/m_play.c
index d66269f..1da970c 100644
--- a/src/overlays/gamestates/ovl_play/m_play.c
+++ b/src/overlays/gamestates/ovl_play/m_play.c
@@ -811,7 +811,7 @@ void* func_80804138_jp(Game_Play* game_play, Struct_8010EAA0* arg1) {
u32 sp24 = arg1->unk_04 - arg1->unk_00;
void* sp20 = THA_alloc16(&game_play->state.heap, sp24);
- func_80026E10_jp(sp20, arg1->unk_00, sp24, "../m_play.c", 2302);
+ DmaMgr_RequestSyncDebug(sp20, arg1->unk_00, sp24, "../m_play.c", 2302);
return sp20;
}
diff --git a/yamls/jp/boot.yaml b/yamls/jp/boot.yaml
index fd11480..de6c6ae 100644
--- a/yamls/jp/boot.yaml
+++ b/yamls/jp/boot.yaml
@@ -10,7 +10,7 @@
- [0x0011F0, c, boot/idle]
- [0x0014A0, c, boot/viconfig]
- [0x001640, c, boot/ovlmgr]
- - [0x0017F0, asm, boot/z_std_dma]
+ - [0x0017F0, c, boot/z_std_dma]
- [0x0022A0, asm, boot/yaz0]
- [0x0026C0, c, boot/syncprintf]
- [0x002720, asm, boot/fault]
@@ -213,7 +213,10 @@
- [0x016EF0, data, boot/rsp/rspboot]
- [0x016FC0, .data, boot/idle]
+
- [0x016FD0, data, boot/016FD0]
+ - [0x016FE0, .data, boot/z_std_dma]
+ - [0x016FF0, data, boot/016FF0]
- [0x017090, data, boot/libu64/stackcheck]
@@ -258,7 +261,7 @@
- [0x018580, .rodata, boot/boot_main]
- [0x018590, .rodata, boot/idle]
- [0x0185B0, .rodata, boot/ovlmgr]
- - [0x0185D0, rodata, boot/0185D0]
+ - [0x0185D0, .rodata, boot/z_std_dma]
- [0x0187F0, rodata, boot/0187F0]
- [0x018840, rodata, boot/018840]
- [0x019250, rodata, boot/019250]
@@ -289,7 +292,8 @@
- { start: 0x019D40, type: .bss, vram: 0x8003E940, name: boot/boot_main }
- { start: 0x019D40, type: .bss, vram: 0x8003F330, name: boot/idle }
- { start: 0x019D40, type: .bss, vram: 0x8003FF30, name: boot/viconfig }
- - { start: 0x019D40, type: bss, vram: 0x8003FF40, name: boot/8003FF40 }
+ - { start: 0x019D40, type: .bss, vram: 0x8003FF40, name: boot/z_std_dma }
+ - { start: 0x019D40, type: bss, vram: 0x800406C0, name: boot/800406C0 }
# libu64
- { start: 0x019D40, type: bss, vram: 0x800419A0, name: boot/libu64/gfxprint }