diff --git a/config/SALP4Q/splits.txt b/config/SALP4Q/splits.txt index cdaa4b2..b6afe92 100644 --- a/config/SALP4Q/splits.txt +++ b/config/SALP4Q/splits.txt @@ -85,6 +85,12 @@ Revolution/OS/__ppc_eabi_init.c: .init start:0x80004300 end:0x80004364 .text start:0x80376CF0 end:0x80376DAC +Revolution/DSP/dsp.c: + .text start:0x8038BB10 end:0x8038BDAC + .data start:0x8052BE10 end:0x8052BE90 + .sdata start:0x805F37A8 end:0x805F37AC + .sbss start:0x805F5D98 end:0x805F5D9C + Revolution/GX/GXBump.c: .text start:0x80392090 end:0x803924E4 .sdata2 start:0x805FA4B0 end:0x805FA4B4 diff --git a/config/SALP4Q/symbols.txt b/config/SALP4Q/symbols.txt index 98dc4f6..1d6dff7 100644 --- a/config/SALP4Q/symbols.txt +++ b/config/SALP4Q/symbols.txt @@ -37020,20 +37020,20 @@ fn_8038BAC0 = .text:0x8038BAC0; // type:function size:0xC fn_8038BAD0 = .text:0x8038BAD0; // type:function size:0xC fn_8038BAE0 = .text:0x8038BAE0; // type:function size:0xC fn_8038BAF0 = .text:0x8038BAF0; // type:function size:0x14 -fn_8038BB10 = .text:0x8038BB10; // type:function size:0x10 -fn_8038BB20 = .text:0x8038BB20; // type:function size:0x10 -fn_8038BB30 = .text:0x8038BB30; // type:function size:0x14 -fn_8038BB50 = .text:0x8038BB50; // type:function size:0x14 -fn_8038BB70 = .text:0x8038BB70; // type:function size:0xC0 -fn_8038BC30 = .text:0x8038BC30; // type:function size:0x8 -fn_8038BC40 = .text:0x8038BC40; // type:function size:0x70 -fn_8038BCB0 = .text:0x8038BCB0; // type:function size:0x40 -fn_8038BCF0 = .text:0x8038BCF0; // type:function size:0xBC -fn_8038BDB0 = .text:0x8038BDB0; // type:function size:0x50 -fn_8038BE00 = .text:0x8038BE00; // type:function size:0x42C +DSPCheckMailToDSP = .text:0x8038BB10; // type:function size:0x10 +DSPCheckMailFromDSP = .text:0x8038BB20; // type:function size:0x10 +DSPReadMailFromDSP = .text:0x8038BB30; // type:function size:0x14 +DSPSendMailToDSP = .text:0x8038BB50; // type:function size:0x14 +DSPInit = .text:0x8038BB70; // type:function size:0xC0 +DSPCheckInit = .text:0x8038BC30; // type:function size:0x8 +DSPAddTask = .text:0x8038BC40; // type:function size:0x70 +DSPCancelTask = .text:0x8038BCB0; // type:function size:0x40 +DSPAssertTask = .text:0x8038BCF0; // type:function size:0xBC +__DSP_debug_printf = .text:0x8038BDB0; // type:function size:0x50 +__DSPHandler = .text:0x8038BE00; // type:function size:0x42C fn_8038C230 = .text:0x8038C230; // type:function size:0x1A4 -fn_8038C3E0 = .text:0x8038C3E0; // type:function size:0x18C -fn_8038C570 = .text:0x8038C570; // type:function size:0xA0 +__DSP_boot_task = .text:0x8038C3E0; // type:function size:0x18C +__DSP_insert_task = .text:0x8038C570; // type:function size:0xA0 fn_8038C610 = .text:0x8038C610; // type:function size:0x88 fn_8038C6A0 = .text:0x8038C6A0; // type:function size:0xE4 fn_8038C790 = .text:0x8038C790; // type:function size:0x24 @@ -46246,7 +46246,10 @@ lbl_8052BBC0 = .data:0x8052BBC0; // type:object size:0xC0 lbl_8052BC80 = .data:0x8052BC80; // type:object size:0x100 lbl_8052BD80 = .data:0x8052BD80; // type:object size:0x20 lbl_8052BDA0 = .data:0x8052BDA0; // type:object size:0x70 -lbl_8052BE10 = .data:0x8052BE10; // type:object size:0x80 +@414 = .data:0x8052BE10; // type:object size:0x46 scope:local data:string +@449 = .data:0x8052BE58; // type:object size:0x1E scope:local data:string +@450 = .data:0x8052BE78; // type:object size:0xC scope:local data:string +@451 = .data:0x8052BE84; // type:object size:0x9 scope:local data:string lbl_8052BE90 = .data:0x8052BE90; // type:object size:0x150 lbl_8052BFE0 = .data:0x8052BFE0; // type:object size:0x170 GXTexRegionAddrTable = .data:0x8052C150; // type:object size:0xC0 scope:local data:4byte @@ -49732,7 +49735,7 @@ lbl_805F379A = .sdata:0x805F379A; // type:object size:0x2 data:2byte lbl_805F379C = .sdata:0x805F379C; // type:object size:0x2 data:2byte lbl_805F37A0 = .sdata:0x805F37A0; // type:object size:0x4 data:4byte lbl_805F37A4 = .sdata:0x805F37A4; // type:object size:0x4 data:4byte -lbl_805F37A8 = .sdata:0x805F37A8; // type:object size:0x8 data:4byte +__DSPVersion = .sdata:0x805F37A8; // type:object size:0x4 data:4byte __GXVersion = .sdata:0x805F37B0; // type:object size:0x4 scope:global data:4byte lbl_805F37B8 = .sdata:0x805F37B8; // type:object size:0x4 lbl_805F37BC = .sdata:0x805F37BC; // type:object size:0x4 @@ -51219,13 +51222,13 @@ lbl_805F5D88 = .sbss:0x805F5D88; // type:object size:0x4 data:4byte lbl_805F5D8C = .sbss:0x805F5D8C; // type:object size:0x4 data:4byte lbl_805F5D90 = .sbss:0x805F5D90; // type:object size:0x4 data:4byte lbl_805F5D94 = .sbss:0x805F5D94; // type:object size:0x4 data:4byte -lbl_805F5D98 = .sbss:0x805F5D98; // type:object size:0x8 data:4byte -lbl_805F5DA0 = .sbss:0x805F5DA0; // type:object size:0x4 data:4byte -lbl_805F5DA4 = .sbss:0x805F5DA4; // type:object size:0x4 data:4byte -lbl_805F5DA8 = .sbss:0x805F5DA8; // type:object size:0x4 data:4byte -lbl_805F5DAC = .sbss:0x805F5DAC; // type:object size:0x4 data:4byte -lbl_805F5DB0 = .sbss:0x805F5DB0; // type:object size:0x4 data:4byte -lbl_805F5DB4 = .sbss:0x805F5DB4; // type:object size:0x4 data:4byte +__DSP_init_flag = .sbss:0x805F5D98; // type:object size:0x4 scope:local data:4byte +__DSP_rude_task_pending = .sbss:0x805F5DA0; // type:object size:0x4 data:4byte +__DSP_rude_task = .sbss:0x805F5DA4; // type:object size:0x4 data:4byte +__DSP_tmp_task = .sbss:0x805F5DA8; // type:object size:0x4 data:4byte +__DSP_last_task = .sbss:0x805F5DAC; // type:object size:0x4 data:4byte +__DSP_first_task = .sbss:0x805F5DB0; // type:object size:0x4 data:4byte +__DSP_curr_task = .sbss:0x805F5DB4; // type:object size:0x4 data:4byte __piReg = .sbss:0x805F5DB8; // type:object size:0x4 scope:global data:4byte __cpReg = .sbss:0x805F5DBC; // type:object size:0x4 scope:global data:4byte __peReg = .sbss:0x805F5DC0; // type:object size:0x4 scope:global data:4byte diff --git a/configure.py b/configure.py index 4c587b6..1936829 100644 --- a/configure.py +++ b/configure.py @@ -291,6 +291,8 @@ def MatchingFor(*versions): "objects": [ # BASE Object(MatchingFor("SALP4Q"), "Revolution/BASE/PPCArch.c"), + # DSP + Object(MatchingFor("SALP4Q"), "Revolution/DSP/dsp.c"), # FS Object(MatchingFor("SALP4Q"), "Revolution/FS/fs.c"), # GX diff --git a/src/Revolution/DSP.h b/src/Revolution/DSP.h new file mode 100644 index 0000000..c946693 --- /dev/null +++ b/src/Revolution/DSP.h @@ -0,0 +1,15 @@ +#ifndef RVL_SDK_PUBLIC_DSP_H + #define RVL_SDK_PUBLIC_DSP_H + #ifdef __cplusplus + extern "C" { + #endif + + #include "Revolution/DSP/dsp.h" + #include "Revolution/DSP/dsp_debug.h" + #include "Revolution/DSP/dsp_hardware.h" + #include "Revolution/DSP/dsp_task.h" + + #ifdef __cplusplus + } + #endif +#endif diff --git a/src/Revolution/DSP/dsp.c b/src/Revolution/DSP/dsp.c new file mode 100644 index 0000000..e4019ae --- /dev/null +++ b/src/Revolution/DSP/dsp.c @@ -0,0 +1,147 @@ +#include "Revolution/DSP.h" // IWYU pragma: keep +#include "Revolution/OS.h" // IWYU pragma: keep + +const char* __DSPVersion = + "<< RVL_SDK - DSP release build: Feb 27 2009 10:01:57 (0x4302_145) >>"; + +static BOOL __DSP_init_flag = FALSE; + +BOOL DSPCheckMailToDSP(void) { + return (DSP_HW_REGS[DSP_DSPMBOX_H] & DSP_DSPMBOX_H_STATUS) != 0; +} + +BOOL DSPCheckMailFromDSP(void) { + return (DSP_HW_REGS[DSP_CPUMBOX_H] & DSP_CPUMBOX_H_STATUS) != 0; +} + +//unused +void DSPReadCPUToDSPMbox() {} + +DSPMail DSPReadMailFromDSP(void) { + return (DSPMail)(DSP_HW_REGS[DSP_CPUMBOX_H] << 16 | + DSP_HW_REGS[DSP_CPUMBOX_L]); +} + +void DSPSendMailToDSP(DSPMail mail) { + DSP_HW_REGS[DSP_DSPMBOX_H] = ((uintptr_t)mail) >> 16 & 0xFFFF; + DSP_HW_REGS[DSP_DSPMBOX_L] = ((uintptr_t)mail) & 0xFFFF; +} + +// unused +void DSPAssertInt(void) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + DSP_HW_REGS[DSP_CSR] = + (DSP_HW_REGS[DSP_CSR] & + ~(DSP_CSR_AIDINT | DSP_CSR_ARINT | DSP_CSR_DSPINT)) | + DSP_CSR_PIINT; + + OSRestoreInterrupts(enabled); +} + +void DSPInit(void) { + BOOL enabled; + + __DSP_debug_printf("DSPInit(): Build Date: %s %s\n", "Feb 27 2009", "10:01:57"); + + if (__DSP_init_flag == TRUE) { + return; + } + + OSRegisterVersion(__DSPVersion); + + enabled = OSDisableInterrupts(); + + __OSSetInterruptHandler(OS_INTR_DSP_DSP, __DSPHandler); + __OSUnmaskInterrupts(OS_INTR_MASK(OS_INTR_DSP_DSP)); + + DSP_HW_REGS[DSP_CSR] = + (DSP_HW_REGS[DSP_CSR] & + ~(DSP_CSR_AIDINT | DSP_CSR_ARINT | DSP_CSR_DSPINT)) | + DSP_CSR_RES; + + DSP_HW_REGS[DSP_CSR] = DSP_HW_REGS[DSP_CSR] & + ~(DSP_CSR_HALT | DSP_CSR_AIDINT | DSP_CSR_ARINT | DSP_CSR_DSPINT); + + __DSP_tmp_task = NULL; + __DSP_curr_task = NULL; + __DSP_last_task = NULL; + __DSP_first_task = NULL; + + __DSP_init_flag = TRUE; + + OSRestoreInterrupts(enabled); +} + +BOOL DSPCheckInit(void) { return __DSP_init_flag; } + +//unused +void DSPReset() {} + +//unused +void DSPHalt() {} + +//unused +void DSPUnhalt() {} + +//unused +void DSPGetDMAStatus() {} + +DSPTask* DSPAddTask(DSPTask* task) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + __DSP_insert_task(task); + task->state = DSP_TASK_STATE_0; + task->flags = DSP_TASK_ACTIVE; + + OSRestoreInterrupts(enabled); + + if (task == __DSP_first_task) { + __DSP_boot_task(task); + } + + return task; +} + +DSPTask* DSPCancelTask(DSPTask* task){ + BOOL enabled; + + enabled = OSDisableInterrupts(); + + task->flags |= DSP_TASK_CANCELED; + + OSRestoreInterrupts(enabled); + return task; +} + +DSPTask* DSPAssertTask(DSPTask* task) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (__DSP_curr_task == task) { + __DSP_rude_task = task; + __DSP_rude_task_pending = TRUE; + OSRestoreInterrupts(enabled); + return task; + } + + if (task->prio < __DSP_curr_task->prio) { + __DSP_rude_task = task; + __DSP_rude_task_pending = TRUE; + + if (__DSP_curr_task->state == DSP_TASK_STATE_1) { + DSPAssertInt(); + } + + OSRestoreInterrupts(enabled); + return task; + } + + OSRestoreInterrupts(enabled); + return NULL; +} diff --git a/src/Revolution/DSP/dsp.h b/src/Revolution/DSP/dsp.h new file mode 100644 index 0000000..556372f --- /dev/null +++ b/src/Revolution/DSP/dsp.h @@ -0,0 +1,26 @@ +#ifndef RVL_SDK_DSP_H + #define RVL_SDK_DSP_H + #include "Revolution/DSP/dsp_task.h" + #include "types.h" + #ifdef __cplusplus + extern "C" { + #endif + + // General-purpose typedef + typedef void* DSPMail; + + BOOL DSPCheckMailToDSP(void); + BOOL DSPCheckMailFromDSP(void); + DSPMail DSPReadMailFromDSP(void); + void DSPSendMailToDSP(DSPMail mail); + void DSPAssertInt(void); + void DSPInit(void); + BOOL DSPCheckInit(void); + DSPTask* DSPAddTask(DSPTask* task); + DSPTask* DSPCancelTask(DSPTask* task); + DSPTask* DSPAssertTask(DSPTask* task); + + #ifdef __cplusplus + } + #endif +#endif diff --git a/src/Revolution/DSP/dsp_debug.h b/src/Revolution/DSP/dsp_debug.h new file mode 100644 index 0000000..8dbb758 --- /dev/null +++ b/src/Revolution/DSP/dsp_debug.h @@ -0,0 +1,13 @@ +#ifndef RVL_SDK_DSP_DEBUG_H + #define RVL_SDK_DSP_DEBUG_H + #include "types.h" // IWYU pragma: keep + #ifdef __cplusplus + extern "C" { + #endif + + void __DSP_debug_printf(const char* fmt, ...); + + #ifdef __cplusplus + } + #endif +#endif diff --git a/src/Revolution/DSP/dsp_hardware.h b/src/Revolution/DSP/dsp_hardware.h new file mode 100644 index 0000000..9e09f76 --- /dev/null +++ b/src/Revolution/DSP/dsp_hardware.h @@ -0,0 +1,75 @@ +#ifndef RVL_SDK_DSP_HARDWARE_H + #define RVL_SDK_DSP_HARDWARE_H + #include "Revolution/os/OSUtils.h" + #include "types.h" + #ifdef __cplusplus + extern "C" { + #endif + + /** + * DSP Hardware Registers + * https://www.gc-forever.com/yagcd/chap5.html#sec5.6 + */ + volatile u16 DSP_HW_REGS[VARSIZE_ARRAY] AT_ADDRESS(0xCC005000); + + /** + * Hardware register indexes + */ + typedef enum { + DSP_DSPMBOX_H, //!< 0xCC005000 + DSP_DSPMBOX_L, //!< 0xCC005002 + DSP_CPUMBOX_H, //!< 0xCC005004 + DSP_CPUMBOX_L, //!< 0xCC005006 + DSP_REG_0x8, //!< 0xCC005008 + DSP_CSR, //!< 0xCC00500A + DSP_REG_0xC, //!< 0xCC00500C + DSP_REG_0xE, //!< 0xCC00500E + DSP_REG_0x10, //!< 0xCC005010 + DSP_AR_SIZE, //!< 0xCC005012 + DSP_REG_0x14, //!< 0xCC005014 + DSP_AR_MODE, //!< 0xCC005016 + DSP_REG_0x18, //!< 0xCC005018 + DSP_AR_REFRESH, //!< 0xCC00501A + DSP_REG_0x1C, //!< 0xCC00501C + DSP_REG_0x1E, //!< 0xCC00501E + DSP_AR_DMA_MMADDR_H, //!< 0xCC005020 + DSP_AR_DMA_MMADDR_L, //!< 0xCC005022 + DSP_AR_DMA_ARADDR_H, //!< 0xCC005024 + DSP_AR_DMA_ARADDR_L, //!< 0xCC005026 + DSP_AR_DMA_CNT_H, //!< 0xCC005028 + DSP_AR_DMA_CNT_L, //!< 0xCC00502A + DSP_REG_0x2C, //!< 0xCC00502C + DSP_REG_0x2E, //!< 0xCC00502E + DSP_AI_DMA_START_H, //!< 0xCC005030 + DSP_AI_DMA_START_L, //!< 0xCC005032 + DSP_REG_0x34, //!< 0xCC005034 + DSP_AI_DMA_CSR, //!< 0xCC005036 + DSP_REG_0x38, //!< 0xCC005038 + DSP_AI_DMA_BYTES_LEFT //!< 0xCC00503A + } DSPHwReg; + + // DSPMBOX_H - DSP Mailbox High (to DSP) + #define DSP_DSPMBOX_H_STATUS (1 << 15) + + // CPUMBOX_H - CPU Mailbox High (from DSP) + #define DSP_CPUMBOX_H_STATUS (1 << 15) + + // CSR - Control Status Register + #define DSP_CSR_RES (1 << 11) + #define DSP_CSR_DMAINT (1 << 9) + #define DSP_CSR_DSPINTMSK (1 << 8) + #define DSP_CSR_DSPINT (1 << 7) + #define DSP_CSR_ARINTMSK (1 << 6) + #define DSP_CSR_ARINT (1 << 5) + #define DSP_CSR_AIDINTMSK (1 << 4) + #define DSP_CSR_AIDINT (1 << 3) + #define DSP_CSR_HALT (1 << 2) + #define DSP_CSR_PIINT (1 << 1) + + // AI_DMA_CSR - AI DMA Control Status Register + #define DSP_AI_DMA_CSR_PLAY (1 << 15) + + #ifdef __cplusplus + } + #endif +#endif diff --git a/src/Revolution/DSP/dsp_task.h b/src/Revolution/DSP/dsp_task.h new file mode 100644 index 0000000..5a03862 --- /dev/null +++ b/src/Revolution/DSP/dsp_task.h @@ -0,0 +1,63 @@ +#ifndef RVL_SDK_DSP_TASK_H + #define RVL_SDK_DSP_TASK_H + #include "types.h" + #ifdef __cplusplus + extern "C" { + #endif + + // Forward declarations + typedef struct DSPTask; + typedef struct OSContext; + + typedef enum { + DSP_TASK_ACTIVE = (1 << 0), + DSP_TASK_CANCELED = (1 << 1), + } DSPTaskFlags; + + typedef enum { + DSP_TASK_STATE_0, + DSP_TASK_STATE_1, + DSP_TASK_STATE_2, + DSP_TASK_STATE_3, + } DSPTaskState; + + typedef void (*DSPTaskCallback)(struct DSPTask* task); + + typedef struct DSPTask { + volatile u32 state; // at 0x0 + u32 prio; // at 0x4 + volatile u32 flags; // at 0x8 + void* iramMmemAddr; // at 0xC + u32 iramMmemLen; // at 0x10 + void* iramDspAddr; // at 0x14 + u32 iramDspLen; // at 0x18 + u32 dramMmemLen; // at 0x1C + u32 WORD_0x20; + u16 startVector; // at 0x24 + u16 resumeVector; // at 0x26 + DSPTaskCallback initCallback; // at 0x28 + DSPTaskCallback resumeCallback; // at 0x2C + DSPTaskCallback doneCallback; // at 0x30 + DSPTaskCallback requestCallback; // at 0x34 + struct DSPTask* next; // at 0x38 + struct DSPTask* prev; // at 0x3C + } DSPTask; + + extern BOOL __DSP_rude_task_pending; + extern DSPTask* __DSP_rude_task; + extern DSPTask* __DSP_tmp_task; + extern DSPTask* __DSP_last_task; + extern DSPTask* __DSP_first_task; + extern DSPTask* __DSP_curr_task; + + void __DSPHandler(s32 intr, struct OSContext* ctx); + void __DSP_exec_task(DSPTask* task1, DSPTask* task2); + void __DSP_boot_task(DSPTask* task); + void __DSP_insert_task(DSPTask* task); + void __DSP_add_task(DSPTask* task); + void __DSP_remove_task(DSPTask* task); + + #ifdef __cplusplus + } + #endif +#endif