mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2024-11-07 15:15:05 +01:00
Fixed some libultra thread implementation issues, fixed flash implementation not getting detected by the game
This commit is contained in:
parent
ba37150ed1
commit
d994bd381d
@ -167,7 +167,12 @@ XCOPY "$(ProjectDir)lib\SDL2-2.24.0\lib\$(Platform)\SDL2.dll" "$(TargetDir)" /S
|
|||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<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\events.cpp" />
|
||||||
<ClCompile Include="portultra\mesgqueue.cpp" />
|
<ClCompile Include="portultra\mesgqueue.cpp" />
|
||||||
<ClCompile Include="portultra\misc_ultra.cpp" />
|
<ClCompile Include="portultra\misc_ultra.cpp" />
|
||||||
|
@ -97,6 +97,7 @@
|
|||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@ -118,6 +119,7 @@
|
|||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<PrecompiledHeaderFile />
|
<PrecompiledHeaderFile />
|
||||||
|
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@ -136,6 +138,7 @@
|
|||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@ -157,6 +160,7 @@
|
|||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||||
<PrecompiledHeaderFile />
|
<PrecompiledHeaderFile />
|
||||||
|
<ExceptionHandling>SyncCThrow</ExceptionHandling>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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};
|
std::lock_guard lock{scheduler_context.mutex};
|
||||||
|
|
||||||
while (!scheduler_context.to_cleanup.empty()) {
|
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);
|
debug_printf("[Scheduler] Destroying thread %d\n", to_cleanup->id);
|
||||||
running_thread_queue.remove(to_cleanup);
|
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();
|
to_cleanup->context->host_thread.join();
|
||||||
delete to_cleanup->context;
|
delete to_cleanup->context;
|
||||||
|
to_cleanup->context = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +165,7 @@ void scheduler_func() {
|
|||||||
handle_thread_stopping(running_thread_queue);
|
handle_thread_stopping(running_thread_queue);
|
||||||
|
|
||||||
// Handle cleaning up threads
|
// 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 queueing threads to run
|
||||||
handle_thread_queueing(running_thread_queue);
|
handle_thread_queueing(running_thread_queue);
|
||||||
|
@ -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)
|
#define run_thread_function(func, sp, arg) func(arg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct thread_terminated : std::exception {};
|
||||||
|
|
||||||
static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entrypoint, PTR(void) arg) {
|
static void _thread_func(RDRAM_ARG PTR(OSThread) self_, PTR(thread_func_t) entrypoint, PTR(void) arg) {
|
||||||
OSThread *self = TO_PTR(OSThread, self_);
|
OSThread *self = TO_PTR(OSThread, self_);
|
||||||
debug_printf("[Thread] Thread created: %d\n", self->id);
|
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);
|
debug_printf("[Thread] Thread started: %d\n", self->id);
|
||||||
|
|
||||||
|
try {
|
||||||
// Run the thread's function with the provided argument.
|
// Run the thread's function with the provided argument.
|
||||||
run_thread_function(PASS_RDRAM entrypoint, self->sp, arg);
|
run_thread_function(PASS_RDRAM entrypoint, self->sp, arg);
|
||||||
|
} catch (thread_terminated& terminated) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Dispose of this thread after it completes.
|
// Dispose of this thread after it completes.
|
||||||
Multilibultra::cleanup_thread(self);
|
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->id = id;
|
||||||
t->state = OSThreadState::PAUSED;
|
t->state = OSThreadState::PAUSED;
|
||||||
t->sp = sp - 0x10; // Set up the first stack frame
|
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.
|
// Spawn a new thread, which will immediately pause itself and wait until it's been started.
|
||||||
t->context = new UltraThreadContext{};
|
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_) {
|
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) {
|
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();
|
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) {
|
void Multilibultra::wait_for_resumed(RDRAM_ARG1) {
|
||||||
|
check_destroyed(TO_PTR(OSThread, thread_self));
|
||||||
TO_PTR(OSThread, thread_self)->context->running.wait(false);
|
TO_PTR(OSThread, thread_self)->context->running.wait(false);
|
||||||
|
check_destroyed(TO_PTR(OSThread, thread_self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multilibultra::pause_thread_impl(OSThread* t) {
|
void Multilibultra::pause_thread_impl(OSThread* t) {
|
||||||
|
@ -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) {
|
extern "C" int osSetTimer(RDRAM_ARG PTR(OSTimer) t_, OSTime countdown, OSTime interval, PTR(OSMesgQueue) mq, OSMesg msg) {
|
||||||
OSTimer* t = TO_PTR(OSTimer, t_);
|
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
|
// Determine the time when this timer will trigger off
|
||||||
if (countdown == 0) {
|
if (countdown == 0) {
|
||||||
// Set the timestamp based on the interval
|
// Set the timestamp based on the interval
|
||||||
|
@ -93,6 +93,7 @@ typedef struct OSThread_t {
|
|||||||
int32_t pad3;
|
int32_t pad3;
|
||||||
UltraThreadContext* context; // An actual pointer regardless of platform
|
UltraThreadContext* context; // An actual pointer regardless of platform
|
||||||
int32_t sp;
|
int32_t sp;
|
||||||
|
bool destroyed;
|
||||||
} OSThread;
|
} OSThread;
|
||||||
|
|
||||||
typedef u32 OSEvent;
|
typedef u32 OSEvent;
|
||||||
|
@ -31,8 +31,9 @@ extern "C" void osFlashReadId_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||||||
PTR(u32) flash_type = ctx->r4;
|
PTR(u32) flash_type = ctx->r4;
|
||||||
PTR(u32) flash_maker = ctx->r5;
|
PTR(u32) flash_maker = ctx->r5;
|
||||||
|
|
||||||
MEM_B(0, flash_type) = 0;
|
// Mimic a real flash chip's type and maker, as some games actually check if one is present.
|
||||||
MEM_B(0, flash_maker) = 0;
|
MEM_W(0, flash_type) = 0x11118001;
|
||||||
|
MEM_W(0, flash_maker) = 0x00C2001E;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void osFlashClearStatus_recomp(uint8_t * rdram, recomp_context * ctx) {
|
extern "C" void osFlashClearStatus_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||||
|
Loading…
Reference in New Issue
Block a user