2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* @file z_std_dma.c
|
|
|
|
*
|
|
|
|
* This file implements a system for structuring the ROM image and retrieving data. It is designed to have the same
|
|
|
|
* external interface regardless of whether the ROM segments are compressed or not.
|
|
|
|
*
|
|
|
|
* The ROM image is partitioned into regions that are entered into the DMA data table `gDmaDataTable`. External code
|
|
|
|
* does not directly address locations on the ROM image directly, instead a "Virtual ROM" addressing is used. Virtual
|
|
|
|
* ROM is defined to be the ROM address of a segment in a totally uncompressed ROM. For uncompressed ROMs, "physical"
|
|
|
|
* ROM and VROM addresses coincide. The DMA data table converts VROM to ROM addresses so that code may exclusively use
|
|
|
|
* VROM addresses even if the ROM is compressed.
|
|
|
|
*
|
|
|
|
* External code typically submits requests to the DMA Manager asking for a transfer in terms of Virtual ROM; the DMA
|
|
|
|
* Manager translates this to the physical ROM address, performs the transfer to RAM and decompresses the data if
|
|
|
|
* required.
|
|
|
|
* Requests are processed in the order they are received and may be submitted both synchronously and asynchronously.
|
|
|
|
*
|
|
|
|
* There are some additional provisions to ensure that audio DMA is particularly high-speed, the audio data is assumed
|
|
|
|
* to be uncompressed and the request queue and address translation is skipped.
|
|
|
|
*/
|
2020-10-03 17:22:44 +02:00
|
|
|
#include "global.h"
|
2024-08-28 09:38:42 +02:00
|
|
|
#include "fault.h"
|
2024-09-03 12:30:14 -07:00
|
|
|
#include "stack.h"
|
2022-11-02 00:17:11 +01:00
|
|
|
#include "terminal.h"
|
2024-08-24 22:04:53 -07:00
|
|
|
#if PLATFORM_N64
|
|
|
|
#include "n64dd.h"
|
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-09-12 11:10:43 -07:00
|
|
|
#pragma increment_block_number "gc-eu:128 gc-eu-mq:128 gc-jp:128 gc-jp-ce:128 gc-jp-mq:128 gc-us:128 gc-us-mq:128" \
|
2024-09-27 20:51:00 +02:00
|
|
|
"ntsc-1.2:96"
|
2024-08-25 16:00:10 +02:00
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
StackEntry sDmaMgrStackInfo;
|
|
|
|
OSMesgQueue sDmaMgrMsgQueue;
|
2022-04-09 01:20:23 +01:00
|
|
|
OSMesg sDmaMgrMsgBuf[32];
|
2024-09-12 11:10:43 -07:00
|
|
|
|
|
|
|
u32 gDmaMgrVerbose = 0;
|
|
|
|
size_t gDmaMgrDmaBuffSize = DMAMGR_DEFAULT_BUFSIZE;
|
|
|
|
u32 sDmaMgrIsRomCompressed = false;
|
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
OSThread sDmaMgrThread;
|
2022-02-06 18:00:01 +00:00
|
|
|
STACK(sDmaMgrStack, 0x500);
|
2024-09-07 05:10:52 -07:00
|
|
|
|
|
|
|
#if OOT_DEBUG
|
2024-09-12 11:10:43 -07:00
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
const char* sDmaMgrCurFileName;
|
|
|
|
s32 sDmaMgrCurFileLine;
|
2021-02-14 00:49:40 +00:00
|
|
|
|
2021-11-30 23:29:09 +00:00
|
|
|
// dmadata filenames
|
2022-06-06 21:51:03 +02:00
|
|
|
#define DEFINE_DMA_ENTRY(_0, nameString) nameString,
|
2021-11-30 23:29:09 +00:00
|
|
|
|
|
|
|
const char* sDmaMgrFileNames[] = {
|
|
|
|
#include "tables/dmadata_table.h"
|
2020-03-17 00:31:30 -04:00
|
|
|
};
|
2024-09-12 11:10:43 -07:00
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2021-11-30 23:29:09 +00:00
|
|
|
#undef DEFINE_DMA_ENTRY
|
|
|
|
|
2024-08-24 22:04:53 -07:00
|
|
|
#if PLATFORM_N64 || OOT_DEBUG
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* Compares `str1` and `str2`.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* 0 if str1 and str2 are the same,
|
|
|
|
* -1 if the first character that does not match has a smaller value in str1 than str2,
|
|
|
|
* +1 if the first character that does not match has a greater value in str1 than str2
|
|
|
|
*/
|
|
|
|
s32 DmaMgr_StrCmp(const char* str1, const char* str2) {
|
|
|
|
while (*str1 != '\0') {
|
|
|
|
if (*str1 > *str2) {
|
2020-03-17 00:31:30 -04:00
|
|
|
return 1;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2022-11-17 02:57:02 +00:00
|
|
|
if (*str1 < *str2) {
|
2020-03-17 00:31:30 -04:00
|
|
|
return -1;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2022-11-17 02:57:02 +00:00
|
|
|
str1++;
|
|
|
|
str2++;
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
if (*str2 > '\0') {
|
2020-03-17 00:31:30 -04:00
|
|
|
return -1;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
return 0;
|
|
|
|
}
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* Transfer `size` bytes from physical ROM address `rom` to `ram`.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* @return 0 if successful, -1 if the DMA could not be queued with the PI Manager.
|
|
|
|
*/
|
|
|
|
s32 DmaMgr_DmaRomToRam(uintptr_t rom, void* ram, size_t size) {
|
2020-03-17 00:31:30 -04:00
|
|
|
OSIoMesg ioMsg;
|
|
|
|
OSMesgQueue queue;
|
|
|
|
OSMesg msg;
|
|
|
|
s32 ret;
|
2022-11-17 02:57:02 +00:00
|
|
|
size_t buffSize = gDmaMgrDmaBuffSize;
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2020-03-22 22:19:43 +01:00
|
|
|
if (buffSize == 0) {
|
2022-11-17 02:57:02 +00:00
|
|
|
buffSize = DMAMGR_DEFAULT_BUFSIZE;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-06-11 09:42:05 +02:00
|
|
|
osInvalICache(ram, size);
|
|
|
|
osInvalDCache(ram, size);
|
2020-03-17 00:31:30 -04:00
|
|
|
osCreateMesgQueue(&queue, &msg, 1);
|
|
|
|
|
2020-03-22 22:19:43 +01:00
|
|
|
while (size > buffSize) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// 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.
|
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
if (1) {} // Necessary to match
|
|
|
|
|
|
|
|
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
|
|
|
|
ioMsg.hdr.retQueue = &queue;
|
|
|
|
ioMsg.devAddr = rom;
|
2022-06-11 09:42:05 +02:00
|
|
|
ioMsg.dramAddr = ram;
|
2020-03-17 00:31:30 -04:00
|
|
|
ioMsg.size = buffSize;
|
|
|
|
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld ノーマルDMA %08x %08x %08x (%d)\n", "%10lld Normal DMA %08x %08x %08x (%d)\n"),
|
|
|
|
OS_CYCLES_TO_USEC(osGetTime()), ioMsg.dramAddr, ioMsg.devAddr, ioMsg.size,
|
|
|
|
MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
ret = osEPiStartDma(gCartHandle, &ioMsg, OS_READ);
|
2022-06-11 09:42:05 +02:00
|
|
|
if (ret != 0) {
|
2021-11-07 17:58:50 +01:00
|
|
|
goto end;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld ノーマルDMA START (%d)\n", "%10lld Normal DMA START (%d)\n"),
|
|
|
|
OS_CYCLES_TO_USEC(osGetTime()), MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2021-11-07 17:58:50 +01:00
|
|
|
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld ノーマルDMA END (%d)\n", "%10lld Normal DMA END (%d)\n"),
|
|
|
|
OS_CYCLES_TO_USEC(osGetTime()), MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
size -= buffSize;
|
2023-10-17 20:16:31 +01:00
|
|
|
rom += buffSize;
|
2022-06-11 09:42:05 +02:00
|
|
|
ram = (u8*)ram + buffSize;
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
if (1) { // Also necessary to match
|
|
|
|
s32 pad[2];
|
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
|
|
|
|
ioMsg.hdr.retQueue = &queue;
|
|
|
|
ioMsg.devAddr = rom;
|
2022-06-11 09:42:05 +02:00
|
|
|
ioMsg.dramAddr = ram;
|
2020-03-17 00:31:30 -04:00
|
|
|
ioMsg.size = size;
|
|
|
|
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld ノーマルDMA %08x %08x %08x (%d)\n", "%10lld Normal DMA %08x %08x %08x (%d)\n"),
|
|
|
|
OS_CYCLES_TO_USEC(osGetTime()), ioMsg.dramAddr, ioMsg.devAddr, ioMsg.size,
|
|
|
|
MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
ret = osEPiStartDma(gCartHandle, &ioMsg, OS_READ);
|
2022-06-11 09:42:05 +02:00
|
|
|
if (ret != 0) {
|
2021-11-07 17:58:50 +01:00
|
|
|
goto end;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2021-11-07 17:58:50 +01:00
|
|
|
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld ノーマルDMA END (%d)\n", "%10lld Normal DMA END (%d)\n"), OS_CYCLES_TO_USEC(osGetTime()),
|
2024-08-22 22:33:50 +02:00
|
|
|
MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2021-11-07 17:58:50 +01:00
|
|
|
end:
|
2022-06-11 09:42:05 +02:00
|
|
|
osInvalICache(ram, size);
|
|
|
|
osInvalDCache(ram, size);
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* 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) {
|
2020-03-17 00:31:30 -04:00
|
|
|
s32 ret;
|
|
|
|
|
2021-04-29 14:39:46 -04:00
|
|
|
ASSERT(pihandle == gCartHandle, "pihandle == carthandle", "../z_std_dma.c", 530);
|
|
|
|
ASSERT(direction == OS_READ, "direction == OS_READ", "../z_std_dma.c", 531);
|
|
|
|
ASSERT(mb != NULL, "mb != NULL", "../z_std_dma.c", 532);
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-08-24 22:04:53 -07:00
|
|
|
#if PLATFORM_N64
|
2024-09-04 11:56:24 -07:00
|
|
|
if (D_80121212) {
|
|
|
|
while (D_80121214) {
|
2024-08-24 22:04:53 -07:00
|
|
|
Sleep_Msec(1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-03-10 21:21:46 +01:00
|
|
|
if (gDmaMgrVerbose == 10) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("%10lld サウンドDMA %08x %08x %08x (%d)\n", "%10lld Sound DMA %08x %08x %08x (%d)\n"),
|
|
|
|
OS_CYCLES_TO_USEC(osGetTime()), mb->dramAddr, mb->devAddr, mb->size, MQ_GET_COUNT(&gPiMgrCmdQueue));
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
ret = osEPiStartDma(pihandle, mb, direction);
|
2022-06-11 09:42:05 +02:00
|
|
|
if (ret != 0) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("OOPS!!\n");
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* DMA read from disk drive. Blocks the current thread until DMA completes.
|
|
|
|
*
|
|
|
|
* @param ram RAM address to write data to.
|
|
|
|
* @param rom ROM address to read from.
|
|
|
|
* @param size Size of transfer.
|
|
|
|
*/
|
|
|
|
void DmaMgr_DmaFromDriveRom(void* ram, uintptr_t rom, size_t size) {
|
2024-08-24 22:04:53 -07:00
|
|
|
#if PLATFORM_N64
|
|
|
|
s32 pad;
|
|
|
|
#endif
|
2021-02-14 00:49:40 +00:00
|
|
|
OSPiHandle* handle = osDriveRomInit();
|
2020-03-17 00:31:30 -04:00
|
|
|
OSMesgQueue queue;
|
|
|
|
OSMesg msg;
|
|
|
|
OSIoMesg ioMsg;
|
|
|
|
|
2022-06-11 09:42:05 +02:00
|
|
|
osInvalICache(ram, size);
|
|
|
|
osInvalDCache(ram, size);
|
2020-03-17 00:31:30 -04:00
|
|
|
osCreateMesgQueue(&queue, &msg, 1);
|
|
|
|
|
|
|
|
ioMsg.hdr.retQueue = &queue;
|
|
|
|
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
|
|
|
|
ioMsg.devAddr = rom;
|
2022-06-11 09:42:05 +02:00
|
|
|
ioMsg.dramAddr = ram;
|
2020-03-17 00:31:30 -04:00
|
|
|
ioMsg.size = size;
|
|
|
|
handle->transferInfo.cmdType = 2;
|
|
|
|
|
2021-11-07 17:58:50 +01:00
|
|
|
osEPiStartDma(handle, &ioMsg, OS_READ);
|
2021-02-14 00:49:40 +00:00
|
|
|
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* DMA error encountered, print error messages and bring up the crash screen.
|
|
|
|
*
|
|
|
|
* @param req DMA Request causing the error.
|
2024-01-30 16:53:16 -08:00
|
|
|
* @param filename DMA data filename associated with the operation that errored.
|
2022-11-17 02:57:02 +00:00
|
|
|
* @param errorName Error name string.
|
|
|
|
* @param errorDesc Error description string.
|
|
|
|
*
|
|
|
|
* This function does not return.
|
|
|
|
*/
|
2024-01-30 16:53:16 -08:00
|
|
|
NORETURN void DmaMgr_Error(DmaRequest* req, const char* filename, const char* errorName, const char* errorDesc) {
|
2022-07-12 18:47:25 +02:00
|
|
|
uintptr_t vrom = req->vromAddr;
|
2022-06-11 09:42:05 +02:00
|
|
|
void* ram = req->dramAddr;
|
2022-11-17 02:57:02 +00:00
|
|
|
size_t size = req->size;
|
2020-03-22 22:19:43 +01:00
|
|
|
char buff1[80];
|
|
|
|
char buff2[80];
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("%c", BEL);
|
|
|
|
PRINTF(VT_FGCOL(RED));
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("DMA致命的エラー(%s)\nROM:%X RAM:%X SIZE:%X %s\n", "DMA Fatal Error (%s)\nROM:%X RAM:%X SIZE:%X %s\n"),
|
2024-01-12 07:38:13 -08:00
|
|
|
errorDesc != NULL ? errorDesc : (errorName != NULL ? errorName : "???"), vrom, ram, size,
|
2024-01-30 16:53:16 -08:00
|
|
|
filename != NULL ? filename : "???");
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
if (req->filename != NULL) { // Source file name that issued the DMA request
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("DMA ERROR: %s %d", req->filename, req->line);
|
2022-06-11 09:42:05 +02:00
|
|
|
} else if (sDmaMgrCurFileName != NULL) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("DMA ERROR: %s %d", sDmaMgrCurFileName, sDmaMgrCurFileLine);
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF(VT_RST);
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-06-11 09:42:05 +02:00
|
|
|
if (req->filename != NULL) {
|
2020-03-17 00:31:30 -04:00
|
|
|
sprintf(buff1, "DMA ERROR: %s %d", req->filename, req->line);
|
2022-06-11 09:42:05 +02:00
|
|
|
} else if (sDmaMgrCurFileName != NULL) {
|
2020-03-17 00:31:30 -04:00
|
|
|
sprintf(buff1, "DMA ERROR: %s %d", sDmaMgrCurFileName, sDmaMgrCurFileLine);
|
2020-03-22 22:19:43 +01:00
|
|
|
} else {
|
2021-10-03 05:17:09 +02:00
|
|
|
sprintf(buff1, "DMA ERROR: %s", errorName != NULL ? errorName : "???");
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
sprintf(buff2, "%07X %08X %X %s", vrom, ram, size, filename != NULL ? filename : "???");
|
2020-03-17 00:31:30 -04:00
|
|
|
Fault_AddHungupAndCrashImpl(buff1, buff2);
|
|
|
|
}
|
|
|
|
|
2024-08-24 22:04:53 -07:00
|
|
|
#define DMA_ERROR(req, filename, errorName, errorDesc, file, n64Line, gcLine) \
|
|
|
|
DmaMgr_Error(req, filename, errorName, errorDesc)
|
|
|
|
#elif PLATFORM_N64
|
|
|
|
#define DMA_ERROR(req, filename, errorName, errorDesc, file, n64Line, gcLine) Fault_AddHungupAndCrash(file, n64Line)
|
|
|
|
#elif PLATFORM_GC
|
|
|
|
#define DMA_ERROR(req, filename, errorName, errorDesc, file, n64Line, gcLine) Fault_AddHungupAndCrash(file, gcLine)
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
|
|
|
|
2024-08-24 22:04:53 -07:00
|
|
|
#if PLATFORM_GC
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* Searches the filesystem for the entry containing the address `vrom`. Retrieves the name of this entry from
|
|
|
|
* the array of file names.
|
|
|
|
*
|
|
|
|
* @param vrom Virtual ROM location
|
|
|
|
* @return Pointer to associated filename
|
|
|
|
*/
|
|
|
|
const char* DmaMgr_FindFileName(uintptr_t vrom) {
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2021-02-14 00:49:40 +00:00
|
|
|
DmaEntry* iter = gDmaDataTable;
|
|
|
|
const char** name = sDmaMgrFileNames;
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
while (iter->file.vromEnd != 0) {
|
|
|
|
if (vrom >= iter->file.vromStart && vrom < iter->file.vromEnd) {
|
2020-03-17 00:31:30 -04:00
|
|
|
return *name;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
iter++;
|
|
|
|
name++;
|
|
|
|
}
|
2021-10-03 05:17:09 +02:00
|
|
|
//! @bug Since there is no return, in case the file isn't found, the return value will be a pointer to the end
|
2020-03-22 22:19:43 +01:00
|
|
|
// of gDmaDataTable
|
2022-02-19 16:50:56 -05:00
|
|
|
#ifdef AVOID_UB
|
|
|
|
return "";
|
|
|
|
#endif
|
2024-01-30 16:53:16 -08:00
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
2024-08-24 22:04:53 -07:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-07-12 18:47:25 +02:00
|
|
|
const char* DmaMgr_GetFileName(uintptr_t vrom) {
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2022-11-17 02:57:02 +00:00
|
|
|
const char* ret = DmaMgr_FindFileName(vrom);
|
2021-02-14 00:49:40 +00:00
|
|
|
|
|
|
|
if (ret == NULL) {
|
2020-03-17 00:31:30 -04:00
|
|
|
return "(unknown)";
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
if (DmaMgr_StrCmp(ret, "kanji") == 0 || DmaMgr_StrCmp(ret, "link_animetion") == 0) {
|
|
|
|
// This check may be related to these files being too large to be loaded all at once, however a NULL filename
|
|
|
|
// does not prevent them from being loaded.
|
2020-03-17 00:31:30 -04:00
|
|
|
return NULL;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
return ret;
|
2024-08-24 22:04:53 -07:00
|
|
|
#elif PLATFORM_N64
|
|
|
|
return "??";
|
|
|
|
#elif PLATFORM_GC
|
2024-01-30 16:53:16 -08:00
|
|
|
return "";
|
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
void DmaMgr_ProcessRequest(DmaRequest* req) {
|
2022-07-12 18:47:25 +02:00
|
|
|
uintptr_t vrom = req->vromAddr;
|
2021-02-14 00:49:40 +00:00
|
|
|
void* ram = req->dramAddr;
|
2022-11-17 02:57:02 +00:00
|
|
|
size_t size = req->size;
|
2022-07-12 18:47:25 +02:00
|
|
|
uintptr_t romStart;
|
2022-11-17 02:57:02 +00:00
|
|
|
size_t romSize;
|
2021-02-14 00:49:40 +00:00
|
|
|
u8 found = false;
|
2020-03-17 00:31:30 -04:00
|
|
|
DmaEntry* iter;
|
|
|
|
const char* filename;
|
2024-08-24 22:04:53 -07:00
|
|
|
s32 i = 0;
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2022-11-17 02:57:02 +00:00
|
|
|
// Get the filename (for debugging)
|
2020-03-17 00:31:30 -04:00
|
|
|
filename = DmaMgr_GetFileName(vrom);
|
2024-09-03 23:54:22 -07:00
|
|
|
#elif PLATFORM_GC
|
|
|
|
// An unused empty string is defined in .rodata of GameCube retail builds, suggesting it was used near here.
|
|
|
|
filename = "";
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Iterate through the DMA data table until the region containing the vrom address for this request is found
|
|
|
|
iter = gDmaDataTable;
|
2024-02-29 05:15:04 -08:00
|
|
|
while (iter->file.vromEnd != 0) {
|
|
|
|
if (vrom >= iter->file.vromStart && vrom < iter->file.vromEnd) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Found the region this request falls into
|
|
|
|
|
2024-09-03 23:54:22 -07:00
|
|
|
#if PLATFORM_N64
|
|
|
|
// Based on the MM Debug ROM, these strings are part of the condition for the empty if statement below,
|
|
|
|
// as `... && DmaMgr_StrCmp("", "kanji") != 0 && DmaMgr_StrCmp("", "link_animetion") != 0`
|
|
|
|
(void)"";
|
|
|
|
(void)"kanji";
|
|
|
|
(void)"";
|
|
|
|
(void)"link_animetion";
|
|
|
|
#endif
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
if (0) {
|
|
|
|
// The string is defined in .rodata of debug builds but not used, suggesting a debug print is here
|
|
|
|
// but was optimized out in some way.
|
|
|
|
PRINTF("DMA ROM:%08X RAM:%08X SIZE:%08X %s\n", vrom, ram, size, filename);
|
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2020-03-22 22:19:43 +01:00
|
|
|
if (iter->romEnd == 0) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// 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.
|
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
if (iter->file.vromEnd < vrom + size) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Error, vrom + size ends up in a different file than it started in
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
DMA_ERROR(req, filename, "Segment Alignment Error",
|
2024-08-22 22:33:50 +02:00
|
|
|
T("セグメント境界をまたがってDMA転送することはできません",
|
|
|
|
"DMA transfers cannot cross segment boundaries"),
|
2024-08-24 22:04:53 -07:00
|
|
|
"../z_std_dma.c", 578, 726);
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
DmaMgr_DmaRomToRam(iter->romStart + (vrom - iter->file.vromStart), ram, size);
|
2020-03-17 00:31:30 -04:00
|
|
|
found = true;
|
|
|
|
|
2021-02-14 00:49:40 +00:00
|
|
|
if (0) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("No Press ROM:%08X RAM:%08X SIZE:%08X\n", vrom, ram, size);
|
2021-02-14 00:49:40 +00:00
|
|
|
}
|
2020-03-22 22:19:43 +01:00
|
|
|
} else {
|
2022-11-17 02:57:02 +00:00
|
|
|
// File is compressed. Files that are stored compressed must be loaded into RAM all at once.
|
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
romStart = iter->romStart;
|
|
|
|
romSize = iter->romEnd - iter->romStart;
|
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
if (vrom != iter->file.vromStart) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Error, requested vrom is not the start of a file
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
DMA_ERROR(req, filename, "Can't Transfer Segment",
|
2024-08-22 22:33:50 +02:00
|
|
|
T("圧縮されたセグメントの途中からはDMA転送することはできません",
|
|
|
|
"DMA transfer cannot be performed from the middle of a compressed segment"),
|
2024-08-24 22:04:53 -07:00
|
|
|
"../z_std_dma.c", 598, 746);
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
if (size != iter->file.vromEnd - iter->file.vromStart) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Error, only part of the file was requested
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
DMA_ERROR(req, filename, "Can't Transfer Segment",
|
2024-08-22 22:33:50 +02:00
|
|
|
T("圧縮されたセグメントの一部だけをDMA転送することはできません",
|
|
|
|
"It is not possible to DMA only part of a compressed segment"),
|
2024-08-24 22:04:53 -07:00
|
|
|
"../z_std_dma.c", 604, 752);
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Reduce the thread priority and decompress the file, the decompression routine handles the DMA
|
|
|
|
// in chunks. Restores the thread priority when done.
|
2022-04-09 01:20:23 +01:00
|
|
|
osSetThreadPri(NULL, THREAD_PRI_DMAMGR_LOW);
|
2020-03-17 00:31:30 -04:00
|
|
|
Yaz0_Decompress(romStart, ram, romSize);
|
2022-04-09 01:20:23 +01:00
|
|
|
osSetThreadPri(NULL, THREAD_PRI_DMAMGR);
|
2020-03-17 00:31:30 -04:00
|
|
|
found = true;
|
|
|
|
|
2021-02-14 00:49:40 +00:00
|
|
|
if (0) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF(" Press ROM:%X RAM:%X SIZE:%X\n", vrom, ram, size);
|
2021-02-14 00:49:40 +00:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2024-08-24 22:04:53 -07:00
|
|
|
|
|
|
|
#if PLATFORM_N64
|
|
|
|
if (i != 0) {
|
|
|
|
i += 4;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-03-17 00:31:30 -04:00
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
|
2020-03-22 22:19:43 +01:00
|
|
|
if (!found) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Requested region was not found in the filesystem
|
|
|
|
|
2022-01-17 21:30:30 +01:00
|
|
|
if (sDmaMgrIsRomCompressed) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Error, rom is compressed so DMA may only be requested within the filesystem bounds
|
|
|
|
|
2024-08-22 22:33:50 +02:00
|
|
|
DMA_ERROR(req, NULL, "DATA DON'T EXIST",
|
2024-08-24 22:04:53 -07:00
|
|
|
T("該当するデータが存在しません", "Corresponding data does not exist"), "../z_std_dma.c", 624,
|
|
|
|
771);
|
2020-03-17 00:31:30 -04:00
|
|
|
return;
|
2022-11-17 02:57:02 +00:00
|
|
|
} else {
|
|
|
|
// ROM is uncompressed, allow arbitrary DMA even if the region is not marked in the filesystem
|
|
|
|
DmaMgr_DmaRomToRam(vrom, ram, size);
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
if (0) {
|
2024-08-23 05:28:03 -04:00
|
|
|
PRINTF(T("No Press ROM:%08X RAM:%08X SIZE:%08X (非公式)\n",
|
|
|
|
"No Press ROM:%08X RAM:%08X SIZE:%08X (informal)\n"),
|
|
|
|
vrom, ram, size);
|
2022-11-17 02:57:02 +00:00
|
|
|
}
|
2021-02-14 00:49:40 +00:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-09 01:20:23 +01:00
|
|
|
void DmaMgr_ThreadEntry(void* arg) {
|
2020-03-17 00:31:30 -04:00
|
|
|
OSMesg msg;
|
|
|
|
DmaRequest* req;
|
2020-03-22 22:19:43 +01:00
|
|
|
|
2024-08-22 22:33:50 +02:00
|
|
|
PRINTF(T("DMAマネージャスレッド実行開始\n", "DMA manager thread execution start\n"));
|
2022-11-17 02:57:02 +00:00
|
|
|
|
2020-03-22 22:19:43 +01:00
|
|
|
while (true) {
|
2022-11-17 02:57:02 +00:00
|
|
|
// Wait for DMA Requests to arrive from other threads
|
2021-11-07 17:58:50 +01:00
|
|
|
osRecvMesg(&sDmaMgrMsgQueue, &msg, OS_MESG_BLOCK);
|
2020-03-17 00:31:30 -04:00
|
|
|
req = (DmaRequest*)msg;
|
2021-02-14 00:49:40 +00:00
|
|
|
if (req == NULL) {
|
2020-03-17 00:31:30 -04:00
|
|
|
break;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
|
|
|
|
2021-02-14 00:49:40 +00:00
|
|
|
if (0) {
|
2024-08-22 22:33:50 +02:00
|
|
|
PRINTF(T("DMA登録受付", "DMA registration acceptance") " dmap=%08x\n", req);
|
2021-02-14 00:49:40 +00:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Process the DMA request
|
|
|
|
DmaMgr_ProcessRequest(req);
|
|
|
|
|
|
|
|
// Notify the sender that the request has been processed
|
2022-06-11 09:42:05 +02:00
|
|
|
if (req->notifyQueue != NULL) {
|
2021-02-14 00:49:40 +00:00
|
|
|
osSendMesg(req->notifyQueue, req->notifyMsg, OS_MESG_NOBLOCK);
|
|
|
|
if (0) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("osSendMesg: dmap=%08x, mq=%08x, m=%08x \n", req, req->notifyQueue, req->notifyMsg);
|
2021-02-14 00:49:40 +00:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
}
|
2022-11-17 02:57:02 +00:00
|
|
|
|
2024-08-22 22:33:50 +02:00
|
|
|
PRINTF(T("DMAマネージャスレッド実行終了\n", "DMA manager thread execution end\n"));
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
2024-01-09 04:59:03 -08:00
|
|
|
* 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 `queue` when the DMA
|
|
|
|
* operation has completed.
|
2022-11-17 02:57:02 +00:00
|
|
|
*
|
2024-01-09 04:59:03 -08:00
|
|
|
* @param req DMA request structure, filled out internally.
|
2022-11-17 02:57:02 +00:00
|
|
|
* @param ram Location in DRAM for data to be written.
|
|
|
|
* @param vrom Virtual ROM location for data to be read.
|
|
|
|
* @param size Transfer size.
|
|
|
|
* @param queue Message queue to notify with `msg` once the transfer is complete.
|
|
|
|
* @param msg Message to send to `queue` once the transfer is complete.
|
|
|
|
* @return 0
|
|
|
|
*/
|
2024-01-09 04:59:03 -08:00
|
|
|
s32 DmaMgr_RequestAsync(DmaRequest* req, void* ram, uintptr_t vrom, size_t size, u32 unk, OSMesgQueue* queue,
|
|
|
|
OSMesg msg) {
|
2020-03-17 00:31:30 -04:00
|
|
|
static s32 sDmaMgrQueueFullLogged = 0;
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
|
|
|
if ((ram == NULL) || (osMemSize < OS_K0_TO_PHYSICAL(ram) + size) || (vrom & 1) || (vrom > 0x4000000) ||
|
2022-06-11 09:42:05 +02:00
|
|
|
(size == 0) || (size & 1)) {
|
2024-01-30 16:53:16 -08:00
|
|
|
// The line numbers for `DMA_ERROR` are only used in retail builds, but this usage was removed so
|
|
|
|
// its line number is unknown.
|
|
|
|
//! @bug `req` is passed to `DMA_ERROR` without rom, ram and size being set
|
2024-08-22 22:33:50 +02:00
|
|
|
DMA_ERROR(req, NULL, "ILLIGAL DMA-FUNCTION CALL", T("パラメータ異常です", "Parameter error"), "../z_std_dma.c",
|
2024-08-24 22:04:53 -07:00
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if PLATFORM_N64
|
2024-09-04 11:56:24 -07:00
|
|
|
if ((B_80121220 != NULL) && (B_80121220->unk_70 != NULL)) {
|
|
|
|
if (B_80121220->unk_70(req, ram, vrom, size, unk, queue, msg) != 0) {
|
2024-08-24 22:04:53 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
req->vromAddr = vrom;
|
2022-06-11 09:42:05 +02:00
|
|
|
req->dramAddr = ram;
|
2020-03-17 00:31:30 -04:00
|
|
|
req->size = size;
|
|
|
|
req->unk_14 = 0;
|
|
|
|
req->notifyQueue = queue;
|
|
|
|
req->notifyMsg = msg;
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2022-04-09 01:20:23 +01:00
|
|
|
if (1 && (sDmaMgrQueueFullLogged == 0) && MQ_IS_FULL(&sDmaMgrMsgQueue)) {
|
|
|
|
sDmaMgrQueueFullLogged++;
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("%c", BEL);
|
|
|
|
PRINTF(VT_FGCOL(RED));
|
2024-08-22 22:33:50 +02:00
|
|
|
PRINTF(T("dmaEntryMsgQが一杯です。キューサイズの再検討をおすすめします。",
|
|
|
|
"dmaEntryMsgQ is full. Reconsider your queue size."));
|
2022-04-09 01:20:23 +01:00
|
|
|
LOG_NUM("(sizeof(dmaEntryMsgBufs) / sizeof(dmaEntryMsgBufs[0]))", ARRAY_COUNT(sDmaMgrMsgBuf), "../z_std_dma.c",
|
|
|
|
952);
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF(VT_RST);
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-04-09 01:20:23 +01:00
|
|
|
osSendMesg(&sDmaMgrMsgQueue, (OSMesg)req, OS_MESG_BLOCK);
|
2020-03-17 00:31:30 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* 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 ram Location in DRAM for data to be written.
|
|
|
|
* @param vrom Virtual ROM location for data to be read.
|
|
|
|
* @param size Transfer size.
|
|
|
|
* @return 0
|
|
|
|
*/
|
|
|
|
s32 DmaMgr_RequestSync(void* ram, uintptr_t vrom, size_t size) {
|
2020-03-17 00:31:30 -04:00
|
|
|
DmaRequest req;
|
|
|
|
OSMesgQueue queue;
|
|
|
|
OSMesg msg;
|
|
|
|
s32 ret;
|
|
|
|
|
|
|
|
osCreateMesgQueue(&queue, &msg, 1);
|
2024-01-09 04:59:03 -08:00
|
|
|
ret = DmaMgr_RequestAsync(&req, ram, vrom, size, 0, &queue, NULL);
|
|
|
|
if (ret == -1) { // DmaMgr_RequestAsync only returns 0
|
2020-03-17 00:31:30 -04:00
|
|
|
return ret;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
|
|
|
|
2021-02-14 00:49:40 +00:00
|
|
|
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
|
2020-03-17 00:31:30 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-14 00:49:40 +00:00
|
|
|
void DmaMgr_Init(void) {
|
2020-03-17 00:31:30 -04:00
|
|
|
const char** name;
|
|
|
|
s32 idx;
|
|
|
|
DmaEntry* iter;
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// DMA the dma data table to RAM
|
2022-07-12 18:47:25 +02:00
|
|
|
DmaMgr_DmaRomToRam((uintptr_t)_dmadataSegmentRomStart, _dmadataSegmentStart,
|
2021-02-14 00:49:40 +00:00
|
|
|
(u32)(_dmadataSegmentRomEnd - _dmadataSegmentRomStart));
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("dma_rom_ad[]\n");
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2020-03-17 00:31:30 -04:00
|
|
|
name = sDmaMgrFileNames;
|
|
|
|
iter = gDmaDataTable;
|
|
|
|
idx = 0;
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Check if the ROM is compressed (romEnd not 0)
|
2024-01-30 16:53:16 -08:00
|
|
|
sDmaMgrIsRomCompressed = false;
|
2024-02-29 05:15:04 -08:00
|
|
|
while (iter->file.vromEnd != 0) {
|
2020-03-22 22:19:43 +01:00
|
|
|
if (iter->romEnd != 0) {
|
2022-01-17 21:30:30 +01:00
|
|
|
sDmaMgrIsRomCompressed = true;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2024-02-29 05:15:04 -08:00
|
|
|
PRINTF("%3d %08x %08x %08x %08x %08x %c %s\n", idx, iter->file.vromStart, iter->file.vromEnd, iter->romStart,
|
|
|
|
iter->romEnd,
|
|
|
|
(iter->romEnd != 0) ? iter->romEnd - iter->romStart : iter->file.vromEnd - iter->file.vromStart,
|
2024-01-12 07:38:13 -08:00
|
|
|
(((iter->romEnd != 0) ? iter->romEnd - iter->romStart : 0) > 0x10000) ? '*' : ' ', name ? *name : "");
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
idx++;
|
|
|
|
iter++;
|
|
|
|
|
2022-06-11 09:42:05 +02:00
|
|
|
if (name != NULL) {
|
2020-03-17 00:31:30 -04:00
|
|
|
name++;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Ensure that the boot segment always follows after the makerom segment.
|
2024-02-29 05:15:04 -08:00
|
|
|
if ((uintptr_t)_bootSegmentRomStart != gDmaDataTable[0].file.vromEnd) {
|
2024-01-12 07:38:13 -08:00
|
|
|
PRINTF("_bootSegmentRomStart(%08x) != dma_rom_ad[0].rom_b(%08x)\n", _bootSegmentRomStart,
|
2024-02-29 05:15:04 -08:00
|
|
|
gDmaDataTable[0].file.vromEnd);
|
2022-11-17 02:57:02 +00:00
|
|
|
//! @bug The main code file where fault.c resides is not yet loaded
|
2024-08-15 04:13:23 +02:00
|
|
|
#if PLATFORM_N64
|
|
|
|
Fault_AddHungupAndCrash("../z_std_dma.c", 840);
|
|
|
|
#else
|
2020-03-17 00:31:30 -04:00
|
|
|
Fault_AddHungupAndCrash("../z_std_dma.c", 1055);
|
2024-08-15 04:13:23 +02:00
|
|
|
#endif
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
// Start the DMA manager
|
2022-04-09 01:20:23 +01:00
|
|
|
osCreateMesgQueue(&sDmaMgrMsgQueue, sDmaMgrMsgBuf, ARRAY_COUNT(sDmaMgrMsgBuf));
|
2022-02-06 18:00:01 +00:00
|
|
|
StackCheck_Init(&sDmaMgrStackInfo, sDmaMgrStack, STACK_TOP(sDmaMgrStack), 0, 0x100, "dmamgr");
|
2022-04-09 01:20:23 +01:00
|
|
|
osCreateThread(&sDmaMgrThread, THREAD_ID_DMAMGR, DmaMgr_ThreadEntry, NULL, STACK_TOP(sDmaMgrStack),
|
|
|
|
THREAD_PRI_DMAMGR);
|
2020-03-17 00:31:30 -04:00
|
|
|
osStartThread(&sDmaMgrThread);
|
|
|
|
}
|
|
|
|
|
2024-01-30 16:53:16 -08:00
|
|
|
#if OOT_DEBUG
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
2024-01-09 04:59:03 -08:00
|
|
|
* Asynchronous DMA Request with source file and line info for debugging.
|
2022-11-17 02:57:02 +00:00
|
|
|
*
|
2024-01-09 04:59:03 -08:00
|
|
|
* @see DmaMgr_RequestAsync
|
2022-11-17 02:57:02 +00:00
|
|
|
*/
|
2024-01-09 04:59:03 -08:00
|
|
|
s32 DmaMgr_RequestAsyncDebug(DmaRequest* req, void* ram, uintptr_t vrom, size_t size, u32 unk5, OSMesgQueue* queue,
|
2024-02-27 07:37:33 +00:00
|
|
|
OSMesg msg, const char* file, int line) {
|
2020-03-17 00:31:30 -04:00
|
|
|
req->filename = file;
|
|
|
|
req->line = line;
|
2024-01-09 04:59:03 -08:00
|
|
|
return DmaMgr_RequestAsync(req, ram, vrom, size, unk5, queue, msg);
|
2020-03-17 00:31:30 -04:00
|
|
|
}
|
|
|
|
|
2022-11-17 02:57:02 +00:00
|
|
|
/**
|
|
|
|
* Synchronous DMA Request with source file and line info for debugging.
|
|
|
|
*
|
|
|
|
* @see DmaMgr_RequestSync
|
|
|
|
*/
|
2024-02-27 07:37:33 +00:00
|
|
|
s32 DmaMgr_RequestSyncDebug(void* ram, uintptr_t vrom, size_t size, const char* file, int line) {
|
2020-03-17 00:31:30 -04:00
|
|
|
DmaRequest req;
|
|
|
|
s32 ret;
|
|
|
|
OSMesgQueue queue;
|
|
|
|
OSMesg msg;
|
2022-06-11 09:42:05 +02:00
|
|
|
s32 pad;
|
2020-03-17 00:31:30 -04:00
|
|
|
|
|
|
|
req.filename = file;
|
|
|
|
req.line = line;
|
|
|
|
osCreateMesgQueue(&queue, &msg, 1);
|
2024-01-09 04:59:03 -08:00
|
|
|
ret = DmaMgr_RequestAsync(&req, ram, vrom, size, 0, &queue, NULL);
|
|
|
|
if (ret == -1) { // DmaMgr_RequestAsync only returns 0
|
2020-03-17 00:31:30 -04:00
|
|
|
return ret;
|
2020-03-22 22:19:43 +01:00
|
|
|
}
|
|
|
|
|
2021-11-07 17:58:50 +01:00
|
|
|
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
|
2020-03-17 00:31:30 -04:00
|
|
|
return 0;
|
|
|
|
}
|
2024-01-30 16:53:16 -08:00
|
|
|
#endif
|