subrepo:
  subdir:   "soh"
  merged:   "ba904bbd0"
upstream:
  origin:   "https://github.com/HarbourMasters/soh.git"
  branch:   "master"
  commit:   "ba904bbd0"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
This commit is contained in:
M4xw
2022-03-22 02:51:23 +01:00
parent 0bb0e7b53b
commit 39cc86c260
2466 changed files with 451557 additions and 0 deletions

9
soh/src/boot/assert.c Normal file
View File

@@ -0,0 +1,9 @@
#include "global.h"
void __assert(const char* exp, const char* file, s32 line) {
char msg[256];
osSyncPrintf("Assertion failed: %s, file %s, line %d, thread %d\n", exp, file, line, osGetThreadId(NULL));
sprintf(msg, "ASSERT: %s:%d(%d)", file, line, osGetThreadId(NULL));
Fault_AddHungupAndCrashImpl(msg, exp);
}

30
soh/src/boot/boot_main.c Normal file
View File

@@ -0,0 +1,30 @@
#include "global.h"
StackEntry sBootThreadInfo;
OSThread sIdleThread;
u8 sIdleThreadStack[0x400];
StackEntry sIdleThreadInfo;
u8 sBootThreadStack[0x400];
void cleararena(void) {
//bzero(_dmadataSegmentStart, osMemSize - OS_K0_TO_PHYSICAL(_dmadataSegmentStart));
}
void bootproc(void) {
StackCheck_Init(&sBootThreadInfo, sBootThreadStack, sBootThreadStack + sizeof(sBootThreadStack), 0, -1, "boot");
osMemSize = osGetMemSize();
cleararena();
__osInitialize_common();
__osInitialize_autodetect();
gCartHandle = osCartRomInit();
osDriveRomInit();
isPrintfInit();
Locale_Init();
StackCheck_Init(&sIdleThreadInfo, sIdleThreadStack, sIdleThreadStack + sizeof(sIdleThreadStack), 0, 256, "idle");
osCreateThread(&sIdleThread, 1, Idle_ThreadEntry, NULL, sIdleThreadStack + sizeof(sIdleThreadStack),
Z_PRIORITY_MAIN);
osStartThread(&sIdleThread);
}

8
soh/src/boot/build.c Normal file
View File

@@ -0,0 +1,8 @@
const char gBuildVersion[] = "DECKARD ALFA (1.0.0)";
const char gBuildTeam[] = "github.com/harbourmasters";
#ifdef __TIMESTAMP__
const char gBuildDate[] = __TIMESTAMP__;
#else
const char gBuildDate[] = __DATE__ " " __TIME__;
#endif
const char gBuildMakeOption[] = "";

90
soh/src/boot/idle.c Normal file
View File

@@ -0,0 +1,90 @@
#include "global.h"
#include "vt.h"
OSThread gMainThread;
u8 sMainStack[0x900];
StackEntry sMainStackInfo;
OSMesg sPiMgrCmdBuff[50];
OSMesgQueue gPiMgrCmdQ;
OSViMode gViConfigMode;
u8 D_80013960;
s8 D_80009430 = 1;
vu8 gViConfigUseDefault = 1;
u8 gViConfigAdditionalScanLines = 0;
u32 gViConfigFeatures = OS_VI_DITHER_FILTER_ON | OS_VI_GAMMA_OFF;
f32 gViConfigXScale = 1.0;
f32 gViConfigYScale = 1.0;
void Main_ThreadEntry(void* arg) {
OSTime time;
osSyncPrintf("mainx 実行開始\n");
DmaMgr_Init();
osSyncPrintf("codeセグメントロード中...");
time = osGetTime();
//DmaMgr_SendRequest1(_codeSegmentStart, (uintptr_t)_codeSegmentRomStart, _codeSegmentRomEnd - _codeSegmentRomStart,
//"../idle.c", 238);
time -= osGetTime();
osSyncPrintf("\rcodeセグメントロード中...完了\n");
osSyncPrintf("転送時間 %6.3f\n");
//bzero(_codeSegmentBssStart, _codeSegmentBssEnd - _codeSegmentBssStart);
osSyncPrintf("codeセグメントBSSクリア完了\n");
Main(arg);
osSyncPrintf("mainx 実行終了\n");
}
void Idle_ThreadEntry(void* arg) {
osSyncPrintf("アイドルスレッド(idleproc)実行開始\n");
osSyncPrintf("作製者 : %s\n", gBuildTeam);
osSyncPrintf("作成日時 : %s\n", gBuildDate);
osSyncPrintf("MAKEOPTION: %s\n", gBuildMakeOption);
osSyncPrintf(VT_FGCOL(GREEN));
osSyncPrintf("RAMサイズは %d キロバイトです(osMemSize/osGetMemSize)\n", (s32)osMemSize / 1024);
//osSyncPrintf("_bootSegmentEnd(%08x) 以降のRAM領域はクリアされました(boot)\n", _bootSegmentEnd);
osSyncPrintf("Zバッファのサイズは %d キロバイトです\n", 0x96);
osSyncPrintf("ダイナミックバッファのサイズは %d キロバイトです\n", 0x92);
osSyncPrintf("FIFOバッファのサイズは %d キロバイトです\n", 0x60);
osSyncPrintf("YIELDバッファのサイズは %d キロバイトです\n", 3);
osSyncPrintf("オーディオヒープのサイズは %d キロバイトです\n", ((s32)gSystemHeap - (s32)gAudioHeap) / 1024);
osSyncPrintf(VT_RST);
osCreateViManager(OS_PRIORITY_VIMGR);
gViConfigFeatures = OS_VI_GAMMA_OFF | OS_VI_DITHER_FILTER_ON;
gViConfigXScale = 1.0f;
gViConfigYScale = 1.0f;
switch (osTvType) {
case OS_TV_NTSC:
D_80013960 = 2;
gViConfigMode = osViModeNtscLan1;
break;
case OS_TV_MPAL:
D_80013960 = 0x1E;
gViConfigMode = osViModeMpalLan1;
break;
case OS_TV_PAL:
D_80013960 = 0x2C;
gViConfigMode = osViModeFpalLan1;
gViConfigYScale = 0.833f;
break;
}
D_80009430 = 1;
osViSetMode(&gViConfigMode);
ViConfig_UpdateVi(1);
osViBlack(1);
osViSwapBuffer(0x803DA80); //! @bug Invalid vram address (probably intended to be 0x803DA800)
osCreatePiManager(OS_PRIORITY_PIMGR, &gPiMgrCmdQ, sPiMgrCmdBuff, 50);
StackCheck_Init(&sMainStackInfo, sMainStack, sMainStack + sizeof(sMainStack), 0, 0x400, "main");
osCreateThread(&gMainThread, 3, Main_ThreadEntry, arg, sMainStack + sizeof(sMainStack), Z_PRIORITY_MAIN);
osStartThread(&gMainThread);
osSetThreadPri(NULL, OS_PRIORITY_IDLE);
while (1) {
;
}
}

90
soh/src/boot/is_debug.c Normal file
View File

@@ -0,0 +1,90 @@
#include "global.h"
OSPiHandle* sISVHandle; // official name : is_Handle
#define gISVDbgPrnAdrs ((ISVDbg*)0xB3FF0000)
#define ASCII_TO_U32(a, b, c, d) ((u32)((a << 24) | (b << 16) | (c << 8) | (d << 0)))
void isPrintfInit(void) {
sISVHandle = osCartRomInit();
osEPiWriteIo(sISVHandle, (u32)&gISVDbgPrnAdrs->put, 0);
osEPiWriteIo(sISVHandle, (u32)&gISVDbgPrnAdrs->get, 0);
osEPiWriteIo(sISVHandle, (u32)&gISVDbgPrnAdrs->magic, ASCII_TO_U32('I', 'S', '6', '4'));
}
void osSyncPrintfUnused(const char* fmt, ...) {
}
/*void osSyncPrintf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
_Printf(is_proutSyncPrintf, NULL, fmt, args);
va_end(args);
}*/
// assumption
void rmonPrintf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
_Printf(is_proutSyncPrintf, NULL, fmt, args);
va_end(args);
}
void* is_proutSyncPrintf(void* arg, const char* str, u32 count) {
u32 data;
s32 pos;
s32 start;
s32 end;
//OTRLogString(str);
osEPiReadIo(sISVHandle, (u32)&gISVDbgPrnAdrs->magic, &data);
if (data != ASCII_TO_U32('I', 'S', '6', '4')) {
return 1;
}
osEPiReadIo(sISVHandle, (u32)&gISVDbgPrnAdrs->get, &data);
pos = data;
osEPiReadIo(sISVHandle, (u32)&gISVDbgPrnAdrs->put, &data);
start = data;
end = start + count;
if (end >= 0xFFE0) {
end -= 0xFFE0;
if (pos < end || start < pos) {
return 1;
}
} else {
if (start < pos && pos < end) {
return 1;
}
}
while (count) {
u32 addr = (u32)&gISVDbgPrnAdrs->data + (start & 0xFFFFFFC);
s32 shift = ((3 - (start & 3)) * 8);
if (*str) {
osEPiReadIo(sISVHandle, addr, &data);
osEPiWriteIo(sISVHandle, addr, (*str << shift) | (data & ~(0xFF << shift)));
start++;
if (start >= 0xFFE0) {
start -= 0xFFE0;
}
}
count--;
str++;
}
osEPiWriteIo(sISVHandle, (u32)&gISVDbgPrnAdrs->put, start);
return 1;
}
void func_80002384(const char* exp, const char* file, u32 line) {
osSyncPrintf("File:%s Line:%d %s \n", file, line, exp);
while (true) {
;
}
}

112
soh/src/boot/logutils.c Normal file
View File

@@ -0,0 +1,112 @@
#include "global.h"
#include "vt.h"
f32 LogUtils_CheckFloatRange(const char* exp, s32 line, const char* valueName, f32 value, const char* minName, f32 min,
const char* maxName, f32 max) {
if (value < min || max < value) {
osSyncPrintf("%s %d: range error %s(%f) < %s(%f) < %s(%f)\n", exp, line, minName, min, valueName, value,
maxName, max);
}
return value;
}
s32 LogUtils_CheckIntRange(const char* exp, s32 line, const char* valueName, s32 value, const char* minName, s32 min,
const char* maxName, s32 max) {
if (value < min || max < value) {
osSyncPrintf("%s %d: range error %s(%d) < %s(%d) < %s(%d)\n", exp, line, minName, min, valueName, value,
maxName, max);
}
return value;
}
void LogUtils_LogHexDump(void* ptr, ptrdiff_t size0) {
u8* addr = (u8*)ptr;
ptrdiff_t size = size0;
s32 rest;
s32 i;
u32 off;
osSyncPrintf("dump(%08x, %u)\n", addr, size);
osSyncPrintf("address off +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f 0123456789abcdef\n");
off = 0;
while (size > 0) {
osSyncPrintf("%08x %04x", addr, off);
rest = (size < 0x10) ? size : 0x10;
i = 0;
while (true) {
if (i < rest) {
osSyncPrintf(" %02x", *((u8*)addr + i));
} else {
osSyncPrintf(" ");
}
i++;
if (i > 0xF) {
break;
}
}
osSyncPrintf(" ");
i = 0;
while (true) {
if (i < rest) {
u8 a = *(addr + i);
osSyncPrintf("%c", (a >= 0x20 && a < 0x7F) ? a : '.');
} else {
osSyncPrintf(" ");
}
i++;
if (i > 0xF) {
break;
}
}
osSyncPrintf("\n");
size -= rest;
addr += rest;
off += rest;
}
}
void LogUtils_LogPointer(s32 value, u32 max, void* ptr, const char* name, const char* file, s32 line) {
osSyncPrintf(VT_COL(RED, WHITE) "%s %d %s[%d] max=%u ptr=%08x\n" VT_RST, file, line, name, value, max, ptr);
}
void LogUtils_CheckBoundary(const char* name, s32 value, s32 unk, const char* file, s32 line) {
u32 mask = (unk - 1);
if (value & mask) {
osSyncPrintf(VT_COL(RED, WHITE) "%s %d:%s(%08x) は バウンダリ(%d)違反です\n" VT_RST, file, line, name, value,
unk);
}
}
void LogUtils_CheckNullPointer(const char* exp, void* ptr, const char* file, s32 line) {
if (ptr == NULL) {
osSyncPrintf(VT_COL(RED, WHITE) "%s %d:%s は はヌルポインタです\n" VT_RST, file, line, exp);
}
}
void LogUtils_CheckValidPointer(const char* exp, void* ptr, const char* file, s32 line) {
if (ptr == NULL || (uintptr_t)ptr < 0x80000000 || (0x80000000 + osMemSize) <= (uintptr_t)ptr) {
osSyncPrintf(VT_COL(RED, WHITE) "%s %d:ポインタ %s(%08x) が異常です\n" VT_RST, file, line, exp, ptr);
}
}
void LogUtils_LogThreadId(const char* name, s32 line) {
osSyncPrintf("<%d %s %d>", osGetThreadId(NULL), name, line);
}
void LogUtils_HungupThread(const char* name, s32 line) {
osSyncPrintf("*** HungUp in thread %d, [%s:%d] ***\n", osGetThreadId(NULL), name, line);
Fault_AddHungupAndCrash(name, line);
}
void LogUtils_ResetHungup(void) {
osSyncPrintf("*** Reset ***\n");
Fault_AddHungupAndCrash("Reset", 0);
}

View File

@@ -0,0 +1,13 @@
#include "global.h"
// Define functions needed for the GCC build here.
f32 __floatundisf(u32 c) {
return (f32)c;
}
f64 __floatundidf(u32 c) {
return (f64)c;
}

134
soh/src/boot/stackcheck.c Normal file
View File

@@ -0,0 +1,134 @@
#include "global.h"
#include "vt.h"
StackEntry* sStackInfoListStart = NULL;
StackEntry* sStackInfoListEnd = NULL;
void StackCheck_Init(StackEntry* entry, void* stackTop, void* stackBottom, u32 initValue, s32 minSpace,
const char* name) {
StackEntry* iter;
u32* addr;
if (entry == NULL) {
sStackInfoListStart = NULL;
} else {
entry->head = (uintptr_t)stackTop;
entry->tail = (uintptr_t)stackBottom;
entry->initValue = initValue;
entry->minSpace = minSpace;
entry->name = name;
iter = sStackInfoListStart;
while (iter) {
if (iter == entry) {
osSyncPrintf(VT_COL(RED, WHITE) "stackcheck_init: %08x は既にリスト中にある\n" VT_RST, entry);
return;
}
iter = iter->next;
}
entry->prev = sStackInfoListEnd;
entry->next = NULL;
if (sStackInfoListEnd) {
sStackInfoListEnd->next = entry;
}
sStackInfoListEnd = entry;
if (!sStackInfoListStart) {
sStackInfoListStart = entry;
}
if (entry->minSpace != -1) {
addr = (u32*)entry->head;
while ((uintptr_t)addr < entry->tail) {
*addr++ = entry->initValue;
}
}
}
}
void StackCheck_Cleanup(StackEntry* entry) {
u32 inconsistency = false;
if (!entry->prev) {
if (entry == sStackInfoListStart) {
sStackInfoListStart = entry->next;
} else {
inconsistency = true;
}
} else {
entry->prev->next = entry->next;
}
if (!entry->next) {
if (entry == sStackInfoListEnd) {
sStackInfoListEnd = entry->prev;
} else {
inconsistency = true;
}
}
if (inconsistency) {
osSyncPrintf(VT_COL(RED, WHITE) "stackcheck_cleanup: %08x リスト不整合です\n" VT_RST, entry);
}
}
StackStatus StackCheck_GetState(StackEntry* entry) {
u32* last;
size_t used;
size_t free;
s32 ret;
for (last = (uintptr_t*)entry->head; (uintptr_t)last < entry->tail; last++) {
if (entry->initValue != *last) {
break;
}
}
used = entry->tail - (uintptr_t)last;
free = (uintptr_t)last - entry->head;
if (free == 0) {
ret = STACK_STATUS_OVERFLOW;
osSyncPrintf(VT_FGCOL(RED));
} else if (free < (u32)entry->minSpace && entry->minSpace != -1) {
ret = STACK_STATUS_WARNING;
osSyncPrintf(VT_FGCOL(YELLOW));
} else {
osSyncPrintf(VT_FGCOL(GREEN));
ret = STACK_STATUS_OK;
}
osSyncPrintf("head=%08x tail=%08x last=%08x used=%08x free=%08x [%s]\n", entry->head, entry->tail, last, used, free,
entry->name != NULL ? entry->name : "(null)");
osSyncPrintf(VT_RST);
if (ret != STACK_STATUS_OK) {
LogUtils_LogHexDump(entry->head, entry->tail - entry->head);
}
return ret;
}
u32 StackCheck_CheckAll(void) {
u32 ret = 0;
StackEntry* iter = sStackInfoListStart;
while (iter) {
u32 state = StackCheck_GetState(iter);
if (state != STACK_STATUS_OK) {
ret = 1;
}
iter = iter->next;
}
return ret;
}
u32 StackCheck_Check(StackEntry* entry) {
if (entry == NULL) {
return StackCheck_CheckAll();
} else {
return StackCheck_GetState(entry);
}
}

46
soh/src/boot/viconfig.c Normal file
View File

@@ -0,0 +1,46 @@
#include "global.h"
#include "vt.h"
// this should probably go elsewhere but right now viconfig.o is the only object between idle and z_std_dma
OSPiHandle* gCartHandle = 0;
void ViConfig_UpdateVi(u32 mode) {
if (mode != 0) {
osSyncPrintf(VT_COL(YELLOW, BLACK) "osViSetYScale1(%f);\n" VT_RST, 1.0f);
if (osTvType == OS_TV_PAL) {
osViSetMode(&osViModePalLan1);
}
osViSetYScale(1.0f);
} else {
osViSetMode(&gViConfigMode);
if (gViConfigAdditionalScanLines != 0) {
osViExtendVStart(gViConfigAdditionalScanLines);
}
if (gViConfigFeatures != 0) {
osViSetSpecialFeatures(gViConfigFeatures);
}
if (gViConfigXScale != 1.0f) {
osViSetXScale(gViConfigXScale);
}
if (gViConfigYScale != 1.0f) {
osSyncPrintf(VT_COL(YELLOW, BLACK) "osViSetYScale3(%f);\n" VT_RST, gViConfigYScale);
osViSetYScale(gViConfigYScale);
}
}
gViConfigUseDefault = mode;
}
void ViConfig_UpdateBlack(void) {
if (gViConfigUseDefault != 0) {
osViBlack(1);
} else {
osViBlack(0);
}
}

102
soh/src/boot/yaz0.c Normal file
View File

@@ -0,0 +1,102 @@
#include "global.h"
#include <string.h>
u8 sYaz0DataBuffer[0x400];
uintptr_t sYaz0CurDataEnd;
uintptr_t sYaz0CurRomStart;
u32 sYaz0CurSize;
uintptr_t sYaz0MaxPtr;
void* Yaz0_FirstDMA(void) {
u32 pad0;
u32 pad1;
u32 dmaSize;
u32 curSize;
sYaz0MaxPtr = sYaz0CurDataEnd - 0x19;
curSize = sYaz0CurDataEnd - (uintptr_t)sYaz0DataBuffer;
dmaSize = (curSize > sYaz0CurSize) ? sYaz0CurSize : curSize;
DmaMgr_DmaRomToRam(sYaz0CurRomStart, sYaz0DataBuffer, dmaSize);
sYaz0CurRomStart += dmaSize;
sYaz0CurSize -= dmaSize;
return sYaz0DataBuffer;
}
void* Yaz0_NextDMA(void* curSrcPos) {
u8* dst;
u32 restSize;
u32 dmaSize;
restSize = sYaz0CurDataEnd - (uintptr_t)curSrcPos;
dst = (restSize & 7) ? (sYaz0DataBuffer - (restSize & 7)) + 8 : sYaz0DataBuffer;
memcpy(dst, curSrcPos, restSize);
dmaSize = (sYaz0CurDataEnd - (uintptr_t)dst) - restSize;
if (sYaz0CurSize < dmaSize) {
dmaSize = sYaz0CurSize;
}
if (dmaSize != 0) {
DmaMgr_DmaRomToRam(sYaz0CurRomStart, (uintptr_t)dst + restSize, dmaSize);
sYaz0CurRomStart += dmaSize;
sYaz0CurSize -= dmaSize;
if (!sYaz0CurSize) {
sYaz0MaxPtr = (uintptr_t)dst + restSize + dmaSize;
}
}
return dst;
}
void Yaz0_DecompressImpl(Yaz0Header* hdr, u8* dst) {
u32 bitIdx = 0;
u8* src = (u8*)hdr->data;
u8* dstEnd = dst + hdr->decSize;
u32 chunkHeader;
u32 nibble;
u8* backPtr;
u32 chunkSize;
u32 off;
do {
if (bitIdx == 0) {
if ((sYaz0MaxPtr < (uintptr_t)src) && (sYaz0CurSize != 0)) {
src = Yaz0_NextDMA(src);
}
chunkHeader = *src++;
bitIdx = 8;
}
if (chunkHeader & (1 << 7)) { // uncompressed
*dst = *src;
dst++;
src++;
} else { // compressed
off = ((*src & 0xF) << 8 | *(src + 1));
nibble = *src >> 4;
backPtr = dst - off;
src += 2;
chunkSize = (nibble == 0) // N = chunkSize; B = back offset
? (u32)(*src++ + 0x12) // 3 bytes 0B BB NN
: nibble + 2; // 2 bytes NB BB
do {
*dst++ = *(backPtr++ - 1);
chunkSize--;
} while (chunkSize != 0);
}
chunkHeader <<= 1;
bitIdx--;
} while (dst != dstEnd);
}
void Yaz0_Decompress(uintptr_t romStart, void* dst, size_t size) {
sYaz0CurRomStart = romStart;
sYaz0CurSize = size;
sYaz0CurDataEnd = sYaz0DataBuffer + sizeof(sYaz0DataBuffer);
Yaz0_DecompressImpl(Yaz0_FirstDMA(), dst);
}

63
soh/src/boot/z_locale.c Normal file
View File

@@ -0,0 +1,63 @@
#include "global.h"
#include "vt.h"
u32 gCurrentRegion = 0;
LocaleCartInfo sCartInfo;
void Locale_Init(void) {
osEPiReadIo(gCartHandle, 0x38, &sCartInfo.mediaFormat);
osEPiReadIo(gCartHandle, 0x3C, &sCartInfo.regionInfo);
switch (sCartInfo.countryCode) {
case 'J': // "NTSC-U (North America)"
gCurrentRegion = REGION_US;
break;
case 'E': // "NTSC-J (Japan)"
gCurrentRegion = REGION_JP;
break;
case 'P': // "PAL (Europe)"
gCurrentRegion = REGION_EU;
break;
default:
osSyncPrintf(VT_COL(RED, WHITE));
osSyncPrintf("z_locale_init: 日本用かアメリカ用か判別できません\n");
LogUtils_HungupThread("../z_locale.c", 118);
osSyncPrintf(VT_RST);
break;
}
osSyncPrintf("z_locale_init:日本用かアメリカ用か3コンで判断させる\n");
}
void Locale_ResetRegion(void) {
gCurrentRegion = REGION_NULL;
}
u32 func_80001F48(void) {
if (gCurrentRegion == REGION_NATIVE) {
return 0;
}
if (gPadMgr.validCtrlrsMask & 4) {
return 0;
}
return 1;
}
u32 func_80001F8C(void) {
if (gCurrentRegion == REGION_NATIVE) {
return 0;
}
if (gPadMgr.validCtrlrsMask & 4) {
return 1;
}
return 0;
}
// This function appears to be unused?
u32 Locale_IsRegionNative(void) {
return gCurrentRegion == REGION_NATIVE;
}

461
soh/src/boot/z_std_dma.c Normal file
View File

@@ -0,0 +1,461 @@
#include "global.h"
#include "vt.h"
StackEntry sDmaMgrStackInfo;
OSMesgQueue sDmaMgrMsgQueue;
OSMesg sDmaMgrMsgs[0x20];
OSThread sDmaMgrThread;
u8 sDmaMgrStack[0x500];
const char* sDmaMgrCurFileName;
s32 sDmaMgrCurFileLine;
u32 D_80009460 = 0;
u32 gDmaMgrDmaBuffSize = 0x2000;
u32 sDmaMgrDataExistError = 0;
// dmadata filenames
#define DEFINE_DMA_ENTRY(name) #name,
const char* sDmaMgrFileNames[] = {
#include "tables/dmadata_table.h"
};
#undef DEFINE_DMA_ENTRY
s32 DmaMgr_CompareName(const char* name1, const char* name2) {
while (*name1 != 0u) {
if (*name1 > *name2) {
return 1;
}
if (*name1 < *name2) {
return -1;
}
name1++;
name2++;
}
if (*name2 > 0) {
return -1;
}
return 0;
}
s32 DmaMgr_DmaRomToRam(uintptr_t rom, uintptr_t ram, size_t size) {
OSIoMesg ioMsg;
OSMesgQueue queue;
OSMesg msg;
s32 ret;
u32 buffSize = gDmaMgrDmaBuffSize;
s32 pad[2];
if (buffSize == 0) {
buffSize = 0x2000;
}
osInvalICache((void*)ram, size);
osInvalDCache((void*)ram, size);
osCreateMesgQueue(&queue, &msg, 1);
while (size > buffSize) {
if (1) {} // Necessary to match
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
ioMsg.hdr.retQueue = &queue;
ioMsg.devAddr = rom;
ioMsg.dramAddr = (void*)ram;
ioMsg.size = buffSize;
if (D_80009460 == 10) {
osSyncPrintf("%10lld ノーマルDMA %08x %08x %08x (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), ioMsg.dramAddr,
ioMsg.devAddr, ioMsg.size, gPiMgrCmdQ.validCount);
}
ret = osEPiStartDma(gCartHandle, &ioMsg, OS_READ);
if (ret) {
goto end;
}
if (D_80009460 == 10) {
osSyncPrintf("%10lld ノーマルDMA START (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), gPiMgrCmdQ.validCount);
}
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
if (D_80009460 == 10) {
osSyncPrintf("%10lld ノーマルDMA END (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), gPiMgrCmdQ.validCount);
}
size -= buffSize;
rom += buffSize;
ram += buffSize;
}
if (1) {} // Also necessary to match
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
ioMsg.hdr.retQueue = &queue;
ioMsg.devAddr = rom;
ioMsg.dramAddr = (void*)ram;
ioMsg.size = size;
if (D_80009460 == 10) {
osSyncPrintf("%10lld ノーマルDMA %08x %08x %08x (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), ioMsg.dramAddr,
ioMsg.devAddr, ioMsg.size, gPiMgrCmdQ.validCount);
}
ret = osEPiStartDma(gCartHandle, &ioMsg, OS_READ);
if (ret) {
goto end;
}
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
if (D_80009460 == 10) {
osSyncPrintf("%10lld ノーマルDMA END (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), gPiMgrCmdQ.validCount);
}
end:
osInvalICache((void*)ram, size);
osInvalDCache((void*)ram, size);
return ret;
}
s32 DmaMgr_DmaHandler(OSPiHandle* pihandle, OSIoMesg* mb, s32 direction) {
s32 ret;
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);
if (D_80009460 == 10) {
osSyncPrintf("%10lld サウンドDMA %08x %08x %08x (%d)\n", OS_CYCLES_TO_USEC(osGetTime()), mb->dramAddr,
mb->devAddr, mb->size, gPiMgrCmdQ.validCount);
}
ret = osEPiStartDma(pihandle, mb, direction);
if (ret) {
osSyncPrintf("OOPS!!\n");
}
return ret;
}
void DmaMgr_DmaFromDriveRom(uintptr_t ram, uintptr_t rom, size_t size) {
OSPiHandle* handle = osDriveRomInit();
OSMesgQueue queue;
OSMesg msg;
OSIoMesg ioMsg;
osInvalICache((void*)ram, size);
osInvalDCache((void*)ram, size);
osCreateMesgQueue(&queue, &msg, 1);
ioMsg.hdr.retQueue = &queue;
ioMsg.hdr.pri = OS_MESG_PRI_NORMAL;
ioMsg.devAddr = rom;
ioMsg.dramAddr = (void*)ram;
ioMsg.size = size;
handle->transferInfo.cmdType = 2;
osEPiStartDma(handle, &ioMsg, OS_READ);
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
return;
}
void DmaMgr_Error(DmaRequest* req, const char* file, const char* errorName, const char* errorDesc) {
uintptr_t vrom = req->vromAddr;
uintptr_t ram = (uintptr_t)req->dramAddr;
size_t size = req->size;
char buff1[80];
char buff2[80];
osSyncPrintf("%c", 7);
osSyncPrintf(VT_FGCOL(RED));
osSyncPrintf("DMA致命的エラー(%s)\nROM:%X RAM:%X SIZE:%X %s\n",
errorDesc != NULL ? errorDesc : (errorName != NULL ? errorName : "???"), vrom, ram, size,
file != NULL ? file : "???");
if (req->filename) {
osSyncPrintf("DMA ERROR: %s %d", req->filename, req->line);
} else if (sDmaMgrCurFileName) {
osSyncPrintf("DMA ERROR: %s %d", sDmaMgrCurFileName, sDmaMgrCurFileLine);
}
osSyncPrintf(VT_RST);
if (req->filename) {
sprintf(buff1, "DMA ERROR: %s %d", req->filename, req->line);
} else if (sDmaMgrCurFileName) {
sprintf(buff1, "DMA ERROR: %s %d", sDmaMgrCurFileName, sDmaMgrCurFileLine);
} else {
sprintf(buff1, "DMA ERROR: %s", errorName != NULL ? errorName : "???");
}
sprintf(buff2, "%07X %08X %X %s", vrom, ram, size, file != NULL ? file : "???");
Fault_AddHungupAndCrashImpl(buff1, buff2);
}
const char* DmaMgr_GetFileNameImpl(uintptr_t vrom) {
DmaEntry* iter = gDmaDataTable;
const char** name = sDmaMgrFileNames;
while (iter->vromEnd) {
if (vrom >= iter->vromStart && vrom < iter->vromEnd) {
return *name;
}
iter++;
name++;
}
//! @bug Since there is no return, in case the file isn't found, the return value will be a pointer to the end
// of gDmaDataTable
}
const char* DmaMgr_GetFileName(uintptr_t vrom) {
const char* ret = DmaMgr_GetFileNameImpl(vrom);
if (ret == NULL) {
return "(unknown)";
}
if (DmaMgr_CompareName(ret, "kanji") == 0 || DmaMgr_CompareName(ret, "link_animetion") == 0) {
return NULL;
}
return ret;
}
void DmaMgr_ProcessMsg(DmaRequest* req) {
uintptr_t vrom = req->vromAddr;
void* ram = req->dramAddr;
size_t size = req->size;
uintptr_t romStart;
uintptr_t romSize;
u8 found = false;
DmaEntry* iter;
const char* filename;
if (0) {
// the string is defined in .rodata but not used, suggesting
// a debug print is here but optimized out in some way
osSyncPrintf("DMA ROM:%08X RAM:%08X SIZE:%08X %s\n");
// the last arg of this print looks like it may be filename, but
// filename above this block does not match
}
filename = DmaMgr_GetFileName(vrom);
iter = gDmaDataTable;
while (iter->vromEnd) {
if (vrom >= iter->vromStart && vrom < iter->vromEnd) {
if (1) {} // Necessary to match
if (iter->romEnd == 0) {
if (iter->vromEnd < vrom + size) {
DmaMgr_Error(req, filename, "Segment Alignment Error",
"セグメント境界をまたがってDMA転送することはできません");
}
DmaMgr_DmaRomToRam(iter->romStart + (vrom - iter->vromStart), ram, size);
found = true;
if (0) {
osSyncPrintf("No Press ROM:%08X RAM:%08X SIZE:%08X\n", vrom, ram, size);
}
} else {
romStart = iter->romStart;
romSize = iter->romEnd - iter->romStart;
if (vrom != iter->vromStart) {
DmaMgr_Error(req, filename, "Can't Transfer Segment",
"圧縮されたセグメントの途中からはDMA転送することはできません");
}
if (size != iter->vromEnd - iter->vromStart) {
DmaMgr_Error(req, filename, "Can't Transfer Segment",
"圧縮されたセグメントの一部だけをDMA転送することはできません");
}
osSetThreadPri(NULL, Z_PRIORITY_MAIN);
Yaz0_Decompress(romStart, ram, romSize);
osSetThreadPri(NULL, Z_PRIORITY_DMAMGR);
found = true;
if (0) {
osSyncPrintf(" Press ROM:%X RAM:%X SIZE:%X\n", vrom, ram, size);
}
}
break;
}
iter++;
}
if (!found) {
if (sDmaMgrDataExistError) {
DmaMgr_Error(req, NULL, "DATA DON'T EXIST", "該当するデータが存在しません");
return;
}
DmaMgr_DmaRomToRam(vrom, (uintptr_t)ram, size);
if (0) {
osSyncPrintf("No Press ROM:%08X RAM:%08X SIZE:%08X (非公式)\n", vrom, ram, size);
}
}
}
void DmaMgr_ThreadEntry(void* arg0) {
OSMesg msg;
DmaRequest* req;
osSyncPrintf("DMAマネージャスレッド実行開始\n");
while (true) {
osRecvMesg(&sDmaMgrMsgQueue, &msg, OS_MESG_BLOCK);
req = (DmaRequest*)msg;
if (req == NULL) {
break;
}
if (0) {
osSyncPrintf("DMA登録受付 dmap=%08x\n", req);
}
DmaMgr_ProcessMsg(req);
if (req->notifyQueue) {
osSendMesg(req->notifyQueue, req->notifyMsg, OS_MESG_NOBLOCK);
if (0) {
osSyncPrintf("osSendMesg: dmap=%08x, mq=%08x, m=%08x \n", req, req->notifyQueue, req->notifyMsg);
}
}
}
osSyncPrintf("DMAマネージャスレッド実行終了\n");
}
s32 DmaMgr_SendRequestImpl(DmaRequest* req, uintptr_t ram, uintptr_t vrom, size_t size, u32 unk, OSMesgQueue* queue, OSMesg msg) {
static s32 sDmaMgrQueueFullLogged = 0;
if ((1 && (ram == 0)) || (osMemSize < ram + size + 0x80000000) || (vrom & 1) || (vrom > 0x4000000) || (size == 0) ||
(size & 1)) {
//! @bug `req` is passed to `DmaMgr_Error` without rom, ram and size being set
DmaMgr_Error(req, NULL, "ILLIGAL DMA-FUNCTION CALL", "パラメータ異常です");
}
req->vromAddr = vrom;
req->dramAddr = (void*)ram;
req->size = size;
req->unk_14 = 0;
req->notifyQueue = queue;
req->notifyMsg = msg;
if (1) {
if ((sDmaMgrQueueFullLogged == 0) && (sDmaMgrMsgQueue.validCount >= sDmaMgrMsgQueue.msgCount)) {
sDmaMgrQueueFullLogged++;
osSyncPrintf("%c", 7);
osSyncPrintf(VT_FGCOL(RED));
osSyncPrintf("dmaEntryMsgQが一杯です。キューサイズの再検討をおすすめします。");
LOG_NUM("(sizeof(dmaEntryMsgBufs) / sizeof(dmaEntryMsgBufs[0]))", ARRAY_COUNT(sDmaMgrMsgs),
"../z_std_dma.c", 952);
osSyncPrintf(VT_RST);
}
}
osSendMesg(&sDmaMgrMsgQueue, req, OS_MESG_BLOCK);
return 0;
}
s32 DmaMgr_SendRequest0(uintptr_t ram, uintptr_t vrom, size_t size) {
DmaRequest req;
OSMesgQueue queue;
OSMesg msg;
s32 ret;
osCreateMesgQueue(&queue, &msg, 1);
ret = DmaMgr_SendRequestImpl(&req, ram, vrom, size, 0, &queue, NULL);
if (ret == -1) {
return ret;
}
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
return 0;
}
void DmaMgr_Init(void) {
const char** name;
s32 idx;
DmaEntry* iter;
//DmaMgr_DmaRomToRam((uintptr_t)_dmadataSegmentRomStart, (uintptr_t)_dmadataSegmentStart,
//(uintptr_t)(_dmadataSegmentRomEnd - _dmadataSegmentRomStart));
osSyncPrintf("dma_rom_ad[]\n");
sDmaMgrDataExistError = 0;
name = sDmaMgrFileNames;
iter = gDmaDataTable;
idx = 0;
while (iter->vromEnd != 0) {
if (iter->romEnd != 0) {
sDmaMgrDataExistError = 1;
}
osSyncPrintf(
"%3d %08x %08x %08x %08x %08x %c %s\n", idx, iter->vromStart, iter->vromEnd, iter->romStart, iter->romEnd,
(iter->romEnd != 0) ? iter->romEnd - iter->romStart : iter->vromEnd - iter->vromStart,
(((iter->romEnd != 0) ? iter->romEnd - iter->romStart : 0) > 0x10000) ? '*' : ' ', name ? *name : "");
idx++;
iter++;
if (name) {
name++;
}
}
#if 0
if ((uintptr_t)_bootSegmentRomStart != gDmaDataTable[0].vromEnd)
{
osSyncPrintf("_bootSegmentRomStart(%08x) != dma_rom_ad[0].rom_b(%08x)\n", _bootSegmentRomStart,
gDmaDataTable[0].vromEnd);
Fault_AddHungupAndCrash("../z_std_dma.c", 1055);
}
#endif
osCreateMesgQueue(&sDmaMgrMsgQueue, sDmaMgrMsgs, ARRAY_COUNT(sDmaMgrMsgs));
StackCheck_Init(&sDmaMgrStackInfo, sDmaMgrStack, sDmaMgrStack + sizeof(sDmaMgrStack), 0, 0x100, "dmamgr");
osCreateThread(&sDmaMgrThread, 0x12, DmaMgr_ThreadEntry, 0, sDmaMgrStack + sizeof(sDmaMgrStack), Z_PRIORITY_DMAMGR);
osStartThread(&sDmaMgrThread);
}
s32 DmaMgr_SendRequest2(DmaRequest* req, uintptr_t ram, uintptr_t vrom, size_t size, u32 unk5, OSMesgQueue* queue, OSMesg msg,
const char* file, s32 line) {
#if 0
req->filename = file;
req->line = line;
DmaMgr_SendRequestImpl(req, ram, vrom, size, unk5, queue, msg);
#endif
}
s32 DmaMgr_SendRequest1(void* ram0, uintptr_t vrom, size_t size, const char* file, s32 line) {
//printf("DmaMgr_SendRequest1 called...\n");
return 0;
#if 0
DmaRequest req;
s32 ret;
OSMesgQueue queue;
OSMesg msg;
uintptr_t ram = (uintptr_t)ram0;
req.filename = file;
req.line = line;
osCreateMesgQueue(&queue, &msg, 1);
ret = DmaMgr_SendRequestImpl(&req, ram, vrom, size, 0, &queue, 0);
if (ret == -1) {
return ret;
}
osRecvMesg(&queue, NULL, OS_MESG_BLOCK);
return 0;
#endif
}