diff --git a/game/overlord/jak3/iso.cpp b/game/overlord/jak3/iso.cpp index e7ec44cd2..265ef9aeb 100644 --- a/game/overlord/jak3/iso.cpp +++ b/game/overlord/jak3/iso.cpp @@ -3,9 +3,9 @@ #include #include "common/log/log.h" +#include "common/util/Assert.h" #include "game/common/dgo_rpc_types.h" -#include "game/overlord/common/isocommon.h" #include "game/overlord/jak3/basefilesystem.h" #include "game/overlord/jak3/iso_api.h" #include "game/overlord/jak3/iso_fake.h" @@ -34,7 +34,11 @@ static int s_nDGOMbx; static u32 DGOThread(); u32 ISOThread(); -int NullCallback(ISO_Msg* msg); +int NullCallback(ISO_Hdr* msg); +int CopyDataToEE(ISO_Hdr*); +int CopyDataToIOP(ISO_Hdr*); +int CopyDataTo989snd(ISO_Hdr*); +int CopyData(ISO_LoadSingle*, int); /* COMPLETE */ void InitDriver() { @@ -158,14 +162,78 @@ u32 ISOThread() { msg->file = nullptr; msg->callback = NullCallback; - switch (msg->msg_kind) { - case LOAD_TO_EE_CMD_ID: - case LOAD_TO_IOP_CMD_ID: - case LOAD_TO_EE_OFFSET_CMD_ID: + /* LoadSingle messages */ + if (msg->msg_kind >= LOAD_TO_EE_CMD_ID && msg->msg_kind <= LOAD_TO_989SND) { + auto* ls = static_cast(msg); + int pri = 0; + if (ls->unk40 == 2) { + pri = 2; + } + if (ls->unk40 == 10) { + pri = 4; + } + if (!QueueMessage(msg, pri)) { break; - default: - lg::error("unhandled iso msg type {:x}", msg->msg_kind); + } + + msg->file = nullptr; + if (msg->msg_kind == LOAD_TO_EE_OFFSET_CMD_ID) { + msg->file = g_pFileSystem->Open(ls->fd, ls->offset, EFileComp::MODE1); + } else if (msg->msg_kind == LOAD_TO_989SND) { + char name[16] = {0}; + if (ls->filename) { + strncpy(name, ls->filename, 12); + name[8] = 0; + strcat(name, ".sbk"); + auto fd = g_pFileSystem->Find(name); + if (fd) { + msg->file = g_pFileSystem->Open(ls->fd, -1, EFileComp::MODE1); + } + } + } else { + msg->file = g_pFileSystem->Open(ls->fd, -1, EFileComp::MODE1); + } + + if (!msg->file) { + msg->m_nStatus = 8; + UnqueueMessage(msg); + ReturnMessage(msg); break; + } + + ls->unk44 = ls->address; + ls->unk48 = 0; + ls->length_to_copy = g_pFileSystem->GetLength(ls->fd); + if (msg->msg_kind == LOAD_TO_989SND) { + ls->length = ls->length_to_copy; + } else { + if (!ls->length_to_copy || ls->length < ls->length_to_copy) { + ls->length_to_copy = ls->length; + } + } + + switch (msg->msg_kind) { + case LOAD_TO_EE_CMD_ID: + msg->callback = CopyDataToEE; + break; + case LOAD_TO_IOP_CMD_ID: + msg->callback = CopyDataToIOP; + break; + case LOAD_TO_EE_OFFSET_CMD_ID: + msg->callback = CopyDataToEE; + break; + case LOAD_TO_989SND: + msg->callback = CopyDataTo989snd; + break; + default: + ASSERT_NOT_REACHED(); + } + + msg->m_nStatus = 2; + msg->SetActive(true); + } else if (msg->msg_kind == 0xADEADBEE) { + ReturnMessage(msg); + ExitThread(); } } @@ -221,13 +289,19 @@ static void ISO_LoadDGO(RPC_Dgo_Cmd* msg) { return; } + ASSERT_NOT_REACHED(); + msg->buffer1 = msg->buffer_heap_top; msg->result = 0; } -static void ISO_LoadNextDGO(RPC_Dgo_Cmd* msg) {} +static void ISO_LoadNextDGO(RPC_Dgo_Cmd* msg) { + ASSERT_NOT_REACHED(); +} -static void ISO_CancelDGO(RPC_Dgo_Cmd* msg) {} +static void ISO_CancelDGO(RPC_Dgo_Cmd* msg) { + ASSERT_NOT_REACHED(); +} /* COMPLETE */ const ISOFileDef* FindISOFile(char* name) { @@ -239,7 +313,24 @@ s32 GetISOFileLength(const ISOFileDef* fd) { return g_pFileSystem->GetLength(fd); } -int NullCallback(ISO_Msg* msg) { +int CopyDataToEE(ISO_Hdr* msg) { + return CopyData((ISO_LoadSingle*)msg, 0); +} + +int CopyDataToIOP(ISO_Hdr* msg) { + return CopyData((ISO_LoadSingle*)msg, 1); +} + +int CopyDataTo989snd(ISO_Hdr* msg) { + return CopyData((ISO_LoadSingle*)msg, 2); +} + +int CopyData(ISO_LoadSingle*, int) { + ASSERT_NOT_REACHED(); + return 0; +} + +int NullCallback(ISO_Hdr* msg) { return 7; } diff --git a/game/overlord/jak3/iso.h b/game/overlord/jak3/iso.h index 2ddf613f7..9d7f5b69a 100644 --- a/game/overlord/jak3/iso.h +++ b/game/overlord/jak3/iso.h @@ -4,6 +4,15 @@ #include "game/sce/iop.h" namespace jak3 { + +constexpr int LOAD_TO_EE_CMD_ID = 0x100; // command to load file to ee +constexpr int LOAD_TO_IOP_CMD_ID = 0x101; // command to load to iop +constexpr int LOAD_TO_EE_OFFSET_CMD_ID = 0x102; // command to load file to ee with offset. +constexpr int LOAD_TO_989SND = 0x103; +constexpr int PAUSE_VAG_STREAM = 0x403; // Command to pause a vag stream +constexpr int CONTINUE_VAG_STREAM = 0x404; // Command to continue a vag stream +constexpr int SET_DIALOG_VOLUME = 0x406; // Command to set the volume of vag playback + extern int g_nISOMbx; struct ISO_Hdr { @@ -22,8 +31,9 @@ struct ISO_Msg : ISO_Hdr { u32 msg_kind; int mbx_to_reply; int thread_id; - int (*callback)(ISO_Msg*); + int (*callback)(ISO_Hdr*); CBaseFile* file; + u32 priority; }; struct ISO_LoadDGO : ISO_Msg { @@ -36,6 +46,11 @@ struct ISO_LoadSingle : ISO_Msg { u32 length; u32 length_to_copy; u32 offset; + char* filename; + u32 unk40; + void* unk44; + u32 unk48; + u32 unk4c; }; int InitISOFS(const char* fs_mode, const char* loading_sceeen); diff --git a/game/overlord/jak3/iso_queue.cpp b/game/overlord/jak3/iso_queue.cpp index dc457a021..92561d525 100644 --- a/game/overlord/jak3/iso_queue.cpp +++ b/game/overlord/jak3/iso_queue.cpp @@ -1,6 +1,10 @@ #include "iso_queue.h" +#include "common/log/log.h" +#include "common/util/Assert.h" + #include "game/overlord/jak3/pagemanager.h" +#include "game/overlord/jak3/util.h" #include "game/sce/iop.h" namespace jak3 { @@ -13,6 +17,8 @@ u32 g_auTrapSRAM[N_VAG_CMDS]; int g_nPriQueueSema; int g_nISOSema; +PriStackEntry gPriStack[N_PRIORITIES]; + CPageManager g_PageManager; void InitBuffers() { @@ -32,4 +38,41 @@ void InitBuffers() { semap.option = 0; g_nISOSema = CreateSema(&semap); } + +bool QueueMessage(ISO_Msg* msg, int priority) { + msg->m_nStatus = 2; + msg->priority = priority; + + int level = priority == 5; + + { + ScopedLock l(g_nPriQueueSema); + + if (gPriStack[level].count != 8) { + gPriStack[level].entries[gPriStack[level].count] = msg; + gPriStack[level].count++; + + return true; + } + } + + msg->m_nStatus = 4; + ReturnMessage(msg); + + return false; +} + +void UnqueueMessage(ISO_Msg* msg) {} + +void ReturnMessage(ISO_Msg* msg) { + if (msg->mbx_to_reply) { + SendMbx(msg->mbx_to_reply, msg); + } else if (msg->thread_id) { + WakeupThread(msg->thread_id); + } else { + // FreeVAGCommand(msg); + ASSERT_NOT_REACHED_MSG("unimplemented"); + } +} + } // namespace jak3 diff --git a/game/overlord/jak3/iso_queue.h b/game/overlord/jak3/iso_queue.h index 2433d56a3..156d26571 100644 --- a/game/overlord/jak3/iso_queue.h +++ b/game/overlord/jak3/iso_queue.h @@ -1,8 +1,21 @@ #ifndef ISO_QUEUE_H_ #define ISO_QUEUE_H_ +#include "game/overlord/jak3/iso.h" + namespace jak3 { +constexpr int N_PRIORITIES = 2; +constexpr int PRI_STACK_LENGTH = 8; + +struct PriStackEntry { + ISO_Msg* entries[PRI_STACK_LENGTH]; + int count; +}; + void InitBuffers(); -} +bool QueueMessage(ISO_Msg* msg, int priority); +void ReturnMessage(ISO_Msg* msg); +void UnqueueMessage(ISO_Msg* msg); +} // namespace jak3 #endif // ISO_QUEUE_H_ diff --git a/game/overlord/jak3/pagemanager.cpp b/game/overlord/jak3/pagemanager.cpp index 6e3384028..f4a82e9d6 100644 --- a/game/overlord/jak3/pagemanager.cpp +++ b/game/overlord/jak3/pagemanager.cpp @@ -155,4 +155,37 @@ int CPageManager::TryFreePages(int nPages) { return 0; } +CPageManager::CPageList* CPageManager::AllocPageList(int nPages, char unk) { + CPageList* pList = nullptr; + CPage* apCollectedPages[29]; + int nPageCount; + + if (nPages <= 0) { + return nullptr; + } + + if (m_Cache.m_nNumFree < nPages) { + if (nPages >= 29) { + return nullptr; + } + + int nFreed = TryFreePages(nPages); + if (nFreed < nPages) { + return nullptr; + } + } + + int nPageListID = std::countr_one(m_Cache.m_uAllocatedListMap); + if (nPages >= 29) { + return nullptr; + } + + m_Cache.m_uAllocatedListMap |= 1u << nPageListID; + + nPageCount = 0; + while (nPageCount < nPages) { + int nPageID = std::countr_one(m_Cache.m_uAllocatedPageMap); + } +} + } // namespace jak3