fix IOP getting stuck on music load (#1437)

* fix IOP getting stuck on music load

* fix regression? and clang

* fix a decomp

* fix another regression

* another

* fix "all actors"

* another regression!
This commit is contained in:
ManDude 2022-06-11 00:04:16 +01:00 committed by GitHub
parent 3ce301ad0d
commit 8ba89dd95e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 98 additions and 56 deletions

View file

@ -27748,7 +27748,7 @@
;; - Functions
(define-extern blocking-plane-spawn (function curve-control none))
(define-extern blocking-plane-spawn (function curve-control none :behavior process))
(define-extern racer-effect (function none :behavior racer))
(define-extern blocking-plane-destroy (function none))

View file

@ -412,11 +412,14 @@ u32 ISOThread() {
ReturnMessage(msg_from_mbx);
} break;
case LOAD_MUSIC: {
// NOTE: this check has been removed. there doesn't seem to be any issues with this, and
// it fixes some other issues. there doesn't appear to be any extra safety from it either
// if there's an in progress vag command, try again.
if (in_progress_vag_command && !in_progress_vag_command->paused) {
SendMbx(iso_mbx, msg_from_mbx);
break;
}
// if (in_progress_vag_command && !in_progress_vag_command->paused) {
// SendMbx(iso_mbx, msg_from_mbx);
// break;
// }
auto buff = TryAllocateBuffer(BUFFER_PAGE_SIZE);
if (!buff) {
@ -641,6 +644,11 @@ u32 ISOThread() {
ProcessMessageData();
if (!read_buffer) {
// HACK!! sometimes when we want to exit, some other threads will wait for stuff to be loaded
// in such cases, we continue running until we're the last thread alive when it's safe to die
if (ThreadWantsExit(GetThreadId()) && OnlyThreadAlive(GetThreadId())) {
return 0;
}
// didn't actually start a read, just delay for a bit I guess.
DelayThread(100);
} else {

View file

@ -49,6 +49,7 @@
#include "game/overlord/srpc.h"
#include "game/overlord/stream.h"
#include "game/overlord/sbank.h"
#include "game/overlord/ssound.h"
#include "game/graphics/gfx.h"
@ -330,6 +331,9 @@ RuntimeExitStatus exec_runtime(int argc, char** argv) {
Gfx::Exit();
}
// hack to make the IOP die quicker if it's loading/unloading music
gMusicFade = 0;
deci_thread.join();
// DECI has been killed, shutdown!

View file

@ -217,4 +217,12 @@ s32 WakeupThread(s32 thid) {
iop->kernel.WakeupThread(thid);
return 0;
}
bool ThreadWantsExit(s32 thid) {
return iop->kernel.GetWantExit(thid);
}
bool OnlyThreadAlive(s32 thid) {
return iop->kernel.OnlyThreadAlive(thid);
}
} // namespace iop

View file

@ -1,8 +1,5 @@
#pragma once
#ifndef JAK1_IOP_H
#define JAK1_IOP_H
#include "common/common_types.h"
#define SMEM_Low (0)
@ -101,6 +98,9 @@ void DelayThread(u32 usec);
s32 CreateThread(ThreadParam* param);
s32 StartThread(s32 thid, u32 arg);
s32 WakeupThread(s32 thid);
// kind of a hack
bool ThreadWantsExit(s32 thid);
bool OnlyThreadAlive(s32 thid);
void sceSifInitRpc(int mode);
void sceSifInitRpc(unsigned int mode);
@ -143,5 +143,3 @@ void LIBRARY_INIT();
void LIBRARY_register(::IOP* i);
void LIBRARY_kill();
} // namespace iop
#endif // JAK1_IOP_H

View file

@ -105,6 +105,21 @@ void IOP_Kernel::WakeupThread(s32 id) {
// todo, should we ever switch directly to that thread?
}
bool IOP_Kernel::OnlyThreadAlive(s32 thid) {
bool yes = false;
for (u64 i = 0; i < threads.size(); i++) {
if (threads[i].started && !threads[i].done) {
if (i != thid) {
return false;
}
if (i == thid) {
yes = true;
}
}
}
return yes;
}
/*!
* Dispatch all IOP threads.
*/

View file

@ -123,11 +123,6 @@ class IOP_Kernel {
* Returns if it got something.
*/
s32 PollMbx(void** msg, s32 mbx) {
if (_currentThread != -1 && threads.at(_currentThread).wantExit) {
// total hack - returning this value causes the ISO thread to error out and quit.
return KE_WAIT_DELETE;
}
ASSERT(mbx < (s32)mbxs.size());
s32 gotSomething = mbxs[mbx].empty() ? 0 : 1;
if (gotSomething) {
@ -165,6 +160,9 @@ class IOP_Kernel {
void* recvBuff,
s32 recvSize);
bool GetWantExit(s32 thid) const { return threads.at(thid).wantExit; }
bool OnlyThreadAlive(s32 thid);
private:
void setupThread(s32 id);
void runThread(s32 id);

View file

@ -1720,9 +1720,7 @@
)
)
)
((#if PC_PORT
(or (= (-> s4-2 display?) 'actor) (with-pc (-> *pc-settings* force-actors?)))
(= (-> s4-2 display?) 'actor))
((= (-> s4-2 display?) 'actor)
(let* ((s4-4 (-> s4-2 entity))
(s3-3 (-> s4-4 length))
)
@ -1785,7 +1783,10 @@
(dotimes (s1-2 s2-4)
(set! sv-32 (-> s3-5 data s1-2))
(cond
((and (is-object-visible? s4-2 (-> sv-32 vis-id))
((and (#if PC_PORT
(or (with-pc (-> *pc-settings* force-actors?)) (is-object-visible? s4-2 (-> sv-32 vis-id)))
(is-object-visible? s4-2 (-> sv-32 vis-id))
)
(zero? (logand (-> sv-32 perm status) (entity-perm-status bit-9 bit-10)))
)
(when (not (or (-> sv-32 process) (logtest? (-> sv-32 perm status) (entity-perm-status bit-0 dead)) s0-1))

View file

@ -1687,7 +1687,7 @@
(let ((s5-0 (new-stack-matrix0))
(gp-0 (vector-reset! (new 'stack-no-clear 'vector)))
)
(let* ((f0-0 (analog-input (the-as int (+ (-> *cpad-list* cpads 0 rightx) -128)) 0.0 48.0 110.0 -1.0))
(let* ((f0-0 (analog-input-horizontal-third (the-as int (+ (-> *cpad-list* cpads 0 rightx) -128)) 0.0 48.0 110.0 -1.0)) ;; changed for pc port
(f1-1 (* -546.13336 f0-0))
(f0-2 (fmin 546.13336 (fmax -546.13336 f1-1)))
)

View file

@ -498,8 +498,16 @@
(set! (-> s4-0 param 2) (the-as uint (target-pos 0)))
(send-event-function *target* s4-0)
)
;; NOTE : added case for "training" here. in the original game, the training level does NOT come
;; with its own code for warp gates and buttons, and uses the villagep-obs imported from village1
;; instead. opengoal loads files different enough that warp from training to anywhere except village1
;; crashes the game due to running unlinked code. the original game also crashes, but it is not consistent.
;; the citadel/lavatube case makes it so we wait until it's safe to unload both levels in the heaps,
;; since the citadel warp gate is located in both levels at once (visually lavatube, technically citadel)
;; we add "training" to the list here so that the training warp gate waits until it's safe to
;; dispose the old code from memory.
(case (-> self level)
(('citadel 'lavatube)
(('citadel 'lavatube 'training)
(while (and *target* (zero? (logand (-> *target* draw status) (draw-status hidden))))
(suspend)
)

View file

@ -85,25 +85,23 @@
(none)
)
(defun blocking-plane-spawn ((arg0 curve-control))
(with-pp
(cond
((or (not arg0) (logtest? (-> arg0 flags) (path-control-flag not-found)))
)
(else
(let ((s5-0 (the int (the float (+ (-> arg0 curve num-cverts) -1))))
(s4-0 0)
)
(while (< s4-0 s5-0)
(process-spawn blocking-plane arg0 s4-0 :to pp)
(+! s4-0 2)
(defbehavior blocking-plane-spawn process ((arg0 curve-control))
(cond
((or (not arg0) (logtest? (-> arg0 flags) (path-control-flag not-found)))
)
(else
(let ((s5-0 (the int (the float (+ (-> arg0 curve num-cverts) -1))))
(s4-0 0)
)
(while (< s4-0 s5-0)
(process-spawn blocking-plane arg0 s4-0 :to self)
(+! s4-0 2)
)
)
)
0
(none)
)
0
(none)
)
(defun blocking-plane-destroy ()

View file

@ -215,9 +215,8 @@
)
)
)
(when (and arg0 *debug-segment* (cpad-pressed? 1 x))
(logclear! (-> *cpad-list* cpads 1 button0-abs 0) (pad-buttons x))
(logclear! (-> *cpad-list* cpads 1 button0-rel 0) (pad-buttons x))
(when (and arg0 *debug-segment* (cpad-pressed? 0 l3)) ;; NOTE : changed from (cpad-pressed? 1 x)
(cpad-clear! 0 l3)
(go arg0)
)
(none)

View file

@ -6,7 +6,7 @@
;; dgos: L1, FIC, LAV, MIS, OGR, RACERP, ROL
(define-extern blocking-plane-destroy (function none))
(define-extern blocking-plane-spawn (function curve-control none))
(define-extern blocking-plane-spawn (function curve-control none :behavior process))
;; DECOMP BEGINS

View file

@ -619,8 +619,14 @@
)
)
)
;; note: they appear to be calling this on the wrong object.
;; this doesn't actually cause any problems but corrupts the type of `float` in the symbol
;; table because they they write to some field of arg0, which is actually #t and not a
;; basebutton. The corruption is completely harmless but is annoying because it looks like
;; a more severe memory corruption problem. So we fix it.
(the-as int ((the-as (function basebutton symbol none) (find-parent-method warp-gate-switch 31))
(the-as basebutton arg0)
;;(the-as basebutton arg0)
obj
arg0
)
)

View file

@ -42,7 +42,8 @@ files_with_modifications = [
"citadel-sages",
"racer-part",
"collectables-part",
"collectables"
"collectables",
"basebutton"
]
for file in files:

View file

@ -13,7 +13,7 @@
(random-mult int32 :offset 12)
(sym symbol :offset 4)
(func symbol :offset 4)
(tex uint32 :offset 4)
(tex texture-id :offset 4)
(pntr pointer :offset 4)
(sound sound-spec :offset 4)
)

View file

@ -94,25 +94,23 @@
;; definition for function blocking-plane-spawn
;; INFO: Return type mismatch int vs none.
(defun blocking-plane-spawn ((arg0 curve-control))
(with-pp
(cond
((or (not arg0) (logtest? (-> arg0 flags) (path-control-flag not-found)))
)
(else
(let ((s5-0 (the int (the float (+ (-> arg0 curve num-cverts) -1))))
(s4-0 0)
)
(while (< s4-0 s5-0)
(process-spawn blocking-plane arg0 s4-0 :to pp)
(+! s4-0 2)
(defbehavior blocking-plane-spawn process ((arg0 curve-control))
(cond
((or (not arg0) (logtest? (-> arg0 flags) (path-control-flag not-found)))
)
(else
(let ((s5-0 (the int (the float (+ (-> arg0 curve num-cverts) -1))))
(s4-0 0)
)
(while (< s4-0 s5-0)
(process-spawn blocking-plane arg0 s4-0 :to self)
(+! s4-0 2)
)
)
)
0
(none)
)
0
(none)
)
;; definition for function blocking-plane-destroy