mirror of
https://github.com/open-goal/jak-project
synced 2026-09-02 10:11:44 -04:00
+71
-32
@@ -70,10 +70,14 @@ s32 iso_thread;
|
||||
s32 dgo_thread;
|
||||
s32 str_thread;
|
||||
s32 play_thread;
|
||||
VagDir gVagDir;
|
||||
VagDirJak2 gVagDir;
|
||||
u32 gPlayPos;
|
||||
static RPC_Dgo_Cmd sRPCBuff[1]; // todo move...
|
||||
DgoCommand scmd;
|
||||
// todo move...
|
||||
static RPC_Dgo_Cmd sRPCBuff[1];
|
||||
DgoCommand scmd; // renamed to sLoadDGO in Jak 2
|
||||
// :-)
|
||||
#define sLoadDGO scmd
|
||||
|
||||
static VagCommand vag_cmd;
|
||||
VagCommand* gVAGCMD = nullptr;
|
||||
s32 gDialogVolume = 0;
|
||||
@@ -108,9 +112,8 @@ void iso_init_globals() {
|
||||
* Initialize the ISO Driver.
|
||||
* Requires a buffer large enough to hold 3 sector (or 4 if you have DUP files)
|
||||
*/
|
||||
static MsgPacket not_on_stack_sync;
|
||||
void InitDriver(u8* buffer) {
|
||||
MsgPacket msg_packet;
|
||||
|
||||
if (!isofs->init(buffer)) {
|
||||
// succesful init!
|
||||
iso_init_flag = 0;
|
||||
@@ -118,7 +121,10 @@ void InitDriver(u8* buffer) {
|
||||
|
||||
// you idiots, you're giving the kernel a pointer to a stack variable!
|
||||
// (this is fixed in Jak 1 Japan and NTSC Greatest Hits)
|
||||
SendMbx(sync_mbx, &msg_packet);
|
||||
// SendMbx(sync_mbx, &msg_packet);
|
||||
|
||||
// whoever fixed that bug felt similarly about it
|
||||
SendMbx(sync_mbx, ¬_on_stack_sync);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -161,8 +167,10 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
// mark us as NOT initialized.
|
||||
iso_init_flag = 1;
|
||||
|
||||
while (!DMA_SendToSPUAndSync(&VAG_SilentLoop, 0x30, gTrapSRAM)) {
|
||||
DelayThread(1000);
|
||||
if (g_game_version == GameVersion::Jak1) {
|
||||
while (!DMA_SendToSPUAndSync(&VAG_SilentLoop, 0x30, gTrapSRAM)) {
|
||||
DelayThread(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// INITIALIZE MESSAGE BOXES
|
||||
@@ -171,6 +179,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
mbx_param.option = 0;
|
||||
iso_mbx = CreateMbx(&mbx_param);
|
||||
if (iso_mbx <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create ISO mbx\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -178,6 +189,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
mbx_param.option = 0;
|
||||
dgo_mbx = CreateMbx(&mbx_param);
|
||||
if (dgo_mbx <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create DGO mbx\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -185,6 +199,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
mbx_param.option = 0;
|
||||
sync_mbx = CreateMbx(&mbx_param);
|
||||
if (sync_mbx <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create sync mbx\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -198,6 +215,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
strcpy(thread_param.name, "ISOThread");
|
||||
iso_thread = CreateThread(&thread_param);
|
||||
if (iso_thread <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create ISO thread\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -209,6 +229,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
strcpy(thread_param.name, "DGOThread");
|
||||
dgo_thread = CreateThread(&thread_param);
|
||||
if (dgo_thread <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create DGO thread\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -220,6 +243,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
strcpy(thread_param.name, "STRThread");
|
||||
str_thread = CreateThread(&thread_param);
|
||||
if (str_thread <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create STR thread\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -231,6 +257,9 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
strcpy(thread_param.name, "PLAYThread");
|
||||
play_thread = CreateThread(&thread_param);
|
||||
if (play_thread <= 0) {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : Cannot create PLAY thread\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -246,7 +275,12 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
// LOAD VAGDIR file
|
||||
FileRecord* vagdir_file = FindISOFile("VAGDIR.AYB");
|
||||
if (vagdir_file) {
|
||||
LoadISOFileToIOP(vagdir_file, &gVagDir, sizeof(gVagDir));
|
||||
LoadISOFileToIOP(vagdir_file, &gVagDir,
|
||||
g_game_version == GameVersion::Jak1 ? sizeof(VagDir) : sizeof(VagDirJak2));
|
||||
} else {
|
||||
printf("IOP: ======================================================================\n");
|
||||
printf("IOP : iso InitISOFS : cannot load VAG directory\n");
|
||||
printf("IOP: ======================================================================\n");
|
||||
}
|
||||
FileRecord* loading_screen_file = FindISOFile(loading_screen);
|
||||
if (loading_screen_file) {
|
||||
@@ -381,18 +415,22 @@ u32 ISOThread() {
|
||||
}
|
||||
// Got a DGO command. There is one LoadDGO command for the entire DGO.
|
||||
// queued successfully, open the file.
|
||||
auto* load_single_cmd = (IsoCommandLoadSingle*)msg_from_mbx;
|
||||
load_single_cmd->fd = isofs->open(load_single_cmd->file_record, -1);
|
||||
if (!load_single_cmd->fd) {
|
||||
auto* load_dgo_cmd = (DgoCommand*)msg_from_mbx;
|
||||
load_dgo_cmd->fd = isofs->open(load_dgo_cmd->fr, -1);
|
||||
if (!load_dgo_cmd->fd) {
|
||||
// failed to open, return error
|
||||
load_single_cmd->status = CMD_STATUS_FAILED_TO_OPEN;
|
||||
UnqueueMessage(load_single_cmd);
|
||||
ReturnMessage(load_single_cmd);
|
||||
load_dgo_cmd->status = CMD_STATUS_FAILED_TO_OPEN;
|
||||
UnqueueMessage(load_dgo_cmd);
|
||||
if (g_game_version == GameVersion::Jak1) {
|
||||
ReturnMessage(load_dgo_cmd);
|
||||
} else {
|
||||
SendMbx(iso_mbx, &sLoadDGO);
|
||||
}
|
||||
} else {
|
||||
// init DGO state machine and register as the callback.
|
||||
load_single_cmd->status = CMD_STATUS_IN_PROGRESS;
|
||||
((DgoCommand*)load_single_cmd)->dgo_state = DgoState::Init;
|
||||
load_single_cmd->callback_function = RunDGOStateMachine;
|
||||
load_dgo_cmd->status = CMD_STATUS_IN_PROGRESS;
|
||||
load_dgo_cmd->dgo_state = DgoState::Init;
|
||||
load_dgo_cmd->callback_function = RunDGOStateMachine;
|
||||
}
|
||||
|
||||
} break;
|
||||
@@ -598,17 +636,19 @@ u32 ISOThread() {
|
||||
// Handle Sound
|
||||
////////////////////////////
|
||||
|
||||
if (in_progress_vag_command && !CheckVAGStreamProgress(in_progress_vag_command)) {
|
||||
gVAGCMD = nullptr;
|
||||
StopVAG(in_progress_vag_command);
|
||||
ReleaseMessage(in_progress_vag_command);
|
||||
in_progress_vag_command = nullptr;
|
||||
// added. this variable seems to determine whether a vag stream is actually playing, and it is
|
||||
// possible to get into a scenario where (for example) you want to unpause a vag stream but a
|
||||
// different sound command hasn't run yet to correct this value, which makes the game either
|
||||
// play the wrong sound or crash right away if no actual sound is to be played with the vag
|
||||
// stream
|
||||
unk = 0;
|
||||
if (g_game_version == GameVersion::Jak1) {
|
||||
if (in_progress_vag_command && !CheckVAGStreamProgress(in_progress_vag_command)) {
|
||||
gVAGCMD = nullptr;
|
||||
StopVAG(in_progress_vag_command);
|
||||
ReleaseMessage(in_progress_vag_command);
|
||||
in_progress_vag_command = nullptr;
|
||||
// added. this variable seems to determine whether a vag stream is actually playing, and it
|
||||
// is possible to get into a scenario where (for example) you want to unpause a vag stream
|
||||
// but a different sound command hasn't run yet to correct this value, which makes the game
|
||||
// either play the wrong sound or crash right away if no actual sound is to be played with
|
||||
// the vag stream
|
||||
unk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
@@ -1456,11 +1496,10 @@ void CancelDGO(RPC_Dgo_Cmd* cmd) {
|
||||
// this will cause a crash if we cancel because we try to load 2 dgos at the same time.
|
||||
// this should succeed if it's an actual cancel because we changed which level we're trying to
|
||||
// load.
|
||||
// I don't understand how this works in the real game.
|
||||
// maybe the IOP doesn't crash on writing to 0x0?
|
||||
// This is weird in the original game, the IOP doesn't crash on writing to 0
|
||||
// or, we have some other bug.
|
||||
// NOTE : actually got fixed in Jak 2 so who cares
|
||||
if (cmd) {
|
||||
printf("null pointer case in CancelDGO hit!\n");
|
||||
cmd->result = DGO_RPC_RESULT_ABORTED;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ struct VagDir {
|
||||
VagDirEntry vag[VAG_COUNT];
|
||||
};
|
||||
|
||||
static constexpr int VAG_COUNT_JAK2 = 2728;
|
||||
struct VagDirJak2 {
|
||||
u32 count;
|
||||
VagDirEntry vag[VAG_COUNT_JAK2];
|
||||
};
|
||||
|
||||
void iso_init_globals();
|
||||
FileRecord* FindISOFile(const char* name);
|
||||
u32 GetISOFileLength(FileRecord* f);
|
||||
|
||||
@@ -163,7 +163,8 @@ void FreeBuffer(IsoBufferHeader* buffer) {
|
||||
void DisplayQueue() {
|
||||
for (int pri = 0; pri < N_PRIORITIES; pri++) {
|
||||
for (int cmd = 0; cmd < (int)gPriStack[pri].n; cmd++) {
|
||||
lg::debug(" PRI {} elt {} {}", pri, cmd, gPriStack[pri].names[cmd]);
|
||||
lg::debug(" PRI {} elt {} {} @ #x{:X}", pri, cmd, gPriStack[pri].names[cmd],
|
||||
(u64)gPriStack[pri].cmds[cmd]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +181,7 @@ u32 QueueMessage(IsoMessage* cmd, int32_t priority, const char* name) {
|
||||
gPriStack[priority].names[gPriStack[priority].n] = name;
|
||||
gPriStack[priority].n++;
|
||||
lg::debug("[OVERLORD] Queue {} ({}/{}), {}", priority, gPriStack[priority].n, PRI_STACK_LENGTH,
|
||||
gPriStack[priority].names[gPriStack[priority].n - 1].c_str());
|
||||
name);
|
||||
DisplayQueue();
|
||||
} else {
|
||||
lg::warn("[OVERLORD ISO QUEUE] Failed to queue!");
|
||||
@@ -200,24 +201,25 @@ void UnqueueMessage(IsoMessage* cmd) {
|
||||
|
||||
// loop over priorities
|
||||
for (pri = 0; pri < N_PRIORITIES; pri++) {
|
||||
pse = gPriStack + pri;
|
||||
pse = &gPriStack[pri];
|
||||
|
||||
// loop over entries
|
||||
for (idx = 0; idx < gPriStack[pri].n; idx++) {
|
||||
for (idx = 0; idx < pse->n; idx++) {
|
||||
if (pse->cmds[idx] == cmd) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
lg::warn("[OVERLORD ISO QUEUE] Failed to unqueue!");
|
||||
return;
|
||||
|
||||
found:
|
||||
ASSERT(gPriStack[pri].cmds[idx] == cmd);
|
||||
ASSERT(pse->cmds[idx] == cmd);
|
||||
|
||||
// pop
|
||||
gPriStack[pri].n--;
|
||||
pse->n--;
|
||||
// and move other entries up.
|
||||
while (idx < gPriStack[pri].n) {
|
||||
while (idx < pse->n) {
|
||||
pse->cmds[idx] = pse->cmds[idx + 1];
|
||||
idx++;
|
||||
}
|
||||
@@ -233,8 +235,8 @@ found:
|
||||
IsoMessage* GetMessage() {
|
||||
// loop over all priorities
|
||||
for (int pri = (N_PRIORITIES - 1); pri >= 0; pri--) {
|
||||
auto pse = gPriStack + pri;
|
||||
int idx = gPriStack[pri].n;
|
||||
auto pse = &gPriStack[pri];
|
||||
int idx = pse->n;
|
||||
for (idx = idx - 1; idx >= 0; idx--) {
|
||||
if (pse->cmds[idx]->fd && pse->cmds[idx]->status == CMD_STATUS_IN_PROGRESS &&
|
||||
pse->cmds[idx]->ready_for_data) {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
(define-extern *level-load-list* pair)
|
||||
|
||||
(defmacro start-debug (str &rest args)
|
||||
`(format 0 ,(string-append "[START] " str) ,@args)
|
||||
)
|
||||
;`(format 0 ,(string-append "[START] " str) ,@args)
|
||||
0)
|
||||
|
||||
|
||||
(defenum load-buffer-mode
|
||||
|
||||
@@ -414,7 +414,7 @@ into 7 sections, which might explain the weird sizes in the center.
|
||||
the level object.
|
||||
This function is the way to transition from loaded to alive/active."
|
||||
|
||||
(start-debug "level-status-update trying to do ~A to ~A~%" (-> obj status) arg0)
|
||||
(start-debug "level-status-update trying to do ~A to ~A for ~A~%" (-> obj status) arg0 (-> obj name))
|
||||
(case arg0
|
||||
(('inactive)
|
||||
;; any request to go inactive should unload.
|
||||
@@ -634,7 +634,6 @@ into 7 sections, which might explain the weird sizes in the center.
|
||||
(set! sv-16 (the-as symbol #f))
|
||||
(let ((s5-0 (dgo-load-get-next (& sv-16))))
|
||||
(when s5-0
|
||||
(start-debug "dgo-load-get-next: #x~X~%" s5-0)
|
||||
;; we got something! remember where and update stats
|
||||
(set! (-> obj load-buffer-last) (the-as uint s5-0))
|
||||
(+! (-> *level* load-size) (-> (the-as (pointer uint32) s5-0)))
|
||||
@@ -1039,6 +1038,7 @@ into 7 sections, which might explain the weird sizes in the center.
|
||||
;; - we can't allocate during login. Or if we allocate more than our link data, then bad things happen.
|
||||
(set! (-> obj load-buffer-mode) (load-buffer-mode borrow))
|
||||
(let ((a3-19 (logand -64 (&+ (-> obj heap current) 63))))
|
||||
(start-debug "DGO-LOAD-BEGIN FOR BORROW: #x~x~%" a3-19)
|
||||
;; start dgo loader!
|
||||
(dgo-load-begin *temp-string* a3-19 a3-19 a3-19)
|
||||
)
|
||||
@@ -2457,7 +2457,12 @@ into 7 sections, which might explain the weird sizes in the center.
|
||||
)
|
||||
)
|
||||
|
||||
(when (>= unload-idx 0) ;; did we find one to unload?
|
||||
;; did we find one to unload?
|
||||
;; PC NOTE : added an extra check for DGO time. If you start a load and discard it on the next frame,
|
||||
;; you may attempt to start a new load right away before the ISO thread can properly stop the previous load
|
||||
;; which will just crash the game. Sadly this means loads may sometimes be delayed by one frame. The horror.
|
||||
(when ;(>= unload-idx 0)
|
||||
(and (>= unload-idx 0) (< 1 (- (-> *display* real-clock integral-frame-counter) *dgo-time*)))
|
||||
(let ((lev-to-unload (-> *level* level unload-idx)))
|
||||
(format 0 "Discarding level ~A~%" (-> lev-to-unload name))
|
||||
(level-status-update! lev-to-unload 'inactive) ;; kill it.
|
||||
|
||||
@@ -61,6 +61,15 @@
|
||||
|
||||
(cgo-file "kernel.gd" ())
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;; misc files
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; the VAGDIR file
|
||||
(defstep :in "$ISO/VAG/VAGDIR.AYB"
|
||||
:tool 'copy
|
||||
:out '("$OUT/iso/VAGDIR.AYB"))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;; DGOs
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -324,6 +333,8 @@
|
||||
|
||||
(group-list "iso"
|
||||
`("$OUT/iso/0COMMON.TXT"
|
||||
"$OUT/iso/TWEAKVAL.MUS"
|
||||
"$OUT/iso/VAGDIR.AYB"
|
||||
,@(reverse *all-vis*)
|
||||
,@(reverse *all-str*)
|
||||
,@(reverse *all-sbk*)
|
||||
|
||||
Reference in New Issue
Block a user