Fixed some libultra thread implementation issues, fixed flash implementation not getting detected by the game

This commit is contained in:
Mr-Wiseguy 2023-02-21 01:26:05 -05:00
parent ba37150ed1
commit d994bd381d
8 changed files with 17001 additions and 13 deletions

View File

@ -167,7 +167,12 @@ XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="portultra\audio.cpp" />
<ClCompile Include="portultra\audio.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MaxSpeed</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</BasicRuntimeChecks>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Default</BasicRuntimeChecks>
</ClCompile>
<ClCompile Include="portultra\events.cpp" />
<ClCompile Include="portultra\mesgqueue.cpp" />
<ClCompile Include="portultra\misc_ultra.cpp" />

View File

@ -97,6 +97,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>SyncCThrow</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>
@ -118,6 +119,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PrecompiledHeaderFile />
<ExceptionHandling>SyncCThrow</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>
@ -136,6 +138,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>SyncCThrow</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>
@ -157,6 +160,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PrecompiledHeaderFile />
<ExceptionHandling>SyncCThrow</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@ void handle_thread_stopping(thread_queue_t& running_thread_queue) {
}
}
void handle_thread_cleanup(thread_queue_t& running_thread_queue) {
void handle_thread_cleanup(thread_queue_t& running_thread_queue, OSThread*& cur_running_thread) {
std::lock_guard lock{scheduler_context.mutex};
while (!scheduler_context.to_cleanup.empty()) {
@ -83,8 +83,20 @@ void handle_thread_cleanup(thread_queue_t& running_thread_queue) {
debug_printf("[Scheduler] Destroying thread %d\n", to_cleanup->id);
running_thread_queue.remove(to_cleanup);
// If the cleaned up thread was the running thread, schedule a new one to run.
if (to_cleanup == cur_running_thread) {
// If there's a thread queued to run, set it as the new running thread.
if (!running_thread_queue.empty()) {
cur_running_thread = running_thread_queue.top();
}
// Otherwise, set the running thread to null so the next thread that can be run gets started.
else {
cur_running_thread = nullptr;
}
}
to_cleanup->context->host_thread.join();
delete to_cleanup->context;
to_cleanup->context = nullptr;
}
}
@ -153,7 +165,7 @@ void scheduler_func() {
handle_thread_stopping(running_thread_queue);
// Handle cleaning up threads
handle_thread_cleanup(running_thread_queue);
handle_thread_cleanup(running_thread_queue, cur_running_thread);
// Handle queueing threads to run
handle_thread_queueing(running_thread_queue);

View File

@ -41,6 +41,8 @@ void run_thread_function(uint8_t* rdram, uint64_t addr, uint64_t sp, uint64_t ar
#define run_thread_function(func, sp, arg) func(arg)
#endif
struct thread_terminated : std::exception {};
static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entrypoint, PTR(void) arg) {
OSThread *self = TO_PTR(OSThread, self_);
debug_printf("[Thread] Thread created: %d\n", self->id);
@ -72,8 +74,12 @@ static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entry
debug_printf("[Thread] Thread started: %d\n", self->id);
// Run the thread's function with the provided argument.
run_thread_function(PASS_RDRAM entrypoint, self->sp, arg);
try {
// Run the thread's function with the provided argument.
run_thread_function(PASS_RDRAM entrypoint, self->sp, arg);
} catch (thread_terminated& terminated) {
}
// Dispose of this thread after it completes.
Multilibultra::cleanup_thread(self);
@ -110,6 +116,7 @@ extern "C" void osCreateThread(RDRAM_ARG PTR(OSThread) t_, OSId id, PTR(thread_f
t->id = id;
t->state = OSThreadState::PAUSED;
t->sp = sp - 0x10; // Set up the first stack frame
t->destroyed = false;
// Spawn a new thread, which will immediately pause itself and wait until it's been started.
t->context = new UltraThreadContext{};
@ -124,7 +131,16 @@ extern "C" void osStopThread(RDRAM_ARG PTR(OSThread) t_) {
}
extern "C" void osDestroyThread(RDRAM_ARG PTR(OSThread) t_) {
assert(false);
// Check if the thread is destroying itself (arg is null or thread_self)
if (t_ == NULLPTR || t_ == thread_self) {
throw thread_terminated{};
}
// Otherwise, mark the target thread as destroyed. Next time it reaches a stopping point,
// it'll check this and terminate itself instead of pausing.
else {
OSThread* t = TO_PTR(OSThread, t_);
t->destroyed = true;
}
}
extern "C" void osSetThreadPri(RDRAM_ARG PTR(OSThread) t, OSPri pri) {
@ -168,8 +184,16 @@ void Multilibultra::set_self_paused(RDRAM_ARG1) {
TO_PTR(OSThread, thread_self)->context->running.notify_all();
}
void check_destroyed(OSThread* t) {
if (t->destroyed) {
throw thread_terminated{};
}
}
void Multilibultra::wait_for_resumed(RDRAM_ARG1) {
check_destroyed(TO_PTR(OSThread, thread_self));
TO_PTR(OSThread, thread_self)->context->running.wait(false);
check_destroyed(TO_PTR(OSThread, thread_self));
}
void Multilibultra::pause_thread_impl(OSThread* t) {

View File

@ -163,11 +163,6 @@ extern "C" OSTime osGetTime() {
extern "C" int osSetTimer(RDRAM_ARG PTR(OSTimer) t_, OSTime countdown, OSTime interval, PTR(OSMesgQueue) mq, OSMesg msg) {
OSTimer* t = TO_PTR(OSTimer, t_);
// HACK: Skip the RCP timeout detection
if ((countdown == 140625000 || countdown == 1500000) && (uintptr_t)msg == 666) {
return 0;
}
// Determine the time when this timer will trigger off
if (countdown == 0) {
// Set the timestamp based on the interval

View File

@ -93,6 +93,7 @@ typedef struct OSThread_t {
int32_t pad3;
UltraThreadContext* context; // An actual pointer regardless of platform
int32_t sp;
bool destroyed;
} OSThread;
typedef u32 OSEvent;

View File

@ -31,8 +31,9 @@ extern "C" void osFlashReadId_recomp(uint8_t * rdram, recomp_context * ctx) {
PTR(u32) flash_type = ctx->r4;
PTR(u32) flash_maker = ctx->r5;
MEM_B(0, flash_type) = 0;
MEM_B(0, flash_maker) = 0;
// Mimic a real flash chip's type and maker, as some games actually check if one is present.
MEM_W(0, flash_type) = 0x11118001;
MEM_W(0, flash_maker) = 0x00C2001E;
}
extern "C" void osFlashClearStatus_recomp(uint8_t * rdram, recomp_context * ctx) {