diff --git a/examples/PoolBox/application/src/application.cpp b/examples/PoolBox/application/src/application.cpp index e2ff39e6..902ca15e 100644 --- a/examples/PoolBox/application/src/application.cpp +++ b/examples/PoolBox/application/src/application.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include using namespace JabyEngine; @@ -155,6 +156,10 @@ namespace LoadingScene { static void run() { if(old_state_changer != state_changer) { printf("Loading new state...\n"); + + Callback::VSyncCallback::install([]() { + printf("Still loading...\n"); + }); update(); GPU::swap_buffers_vsync(1); @@ -165,6 +170,7 @@ namespace LoadingScene { state_changer.asset_load(); old_state_changer = state_changer; CDDA::pop_play(); + Callback::VSyncCallback::uninstall(); } state_changer.main(); diff --git a/include/PSX/System/callbacks.hpp b/include/PSX/System/callbacks.hpp new file mode 100644 index 00000000..ae6e950c --- /dev/null +++ b/include/PSX/System/callbacks.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "syscalls.hpp" + +namespace JabyEngine { + namespace Callback { + struct VSyncCallback { + using Function = void (*)(); + + static Function callback; + + static void install(Function function) { + VSyncCallback::callback = function; + } + + static void uninstall() { + VSyncCallback::install(nullptr); + } + }; + } +} \ No newline at end of file diff --git a/include/PSX/System/syscalls.hpp b/include/PSX/System/syscalls.hpp index 6dd5d74e..92c64a29 100644 --- a/include/PSX/System/syscalls.hpp +++ b/include/PSX/System/syscalls.hpp @@ -118,6 +118,7 @@ namespace JabyEngine { typedef InterruptVerifierResult (*InterruptVerifier)(); typedef uint32_t (*InterruptHandler)(uint32_t); + using ThreadHandle = uint32_t; #pragma pack(push, 1) struct InterrupCallback { @@ -143,28 +144,13 @@ namespace JabyEngine { return __syscall_function_cast(Table_A, void*(*)(void*, const void*, size_t))(dst, src, len); } - static __always_inline uint32_t OpenTh(void (*thread_func)(), uint32_t* stack_ptr, uint32_t* gp) { + static __always_inline ThreadHandle OpenThread(void (*thread_func)(), uint32_t* stack_ptr, uint32_t* gp) { register uint32_t FuncID asm("t1") = 0x0E; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); - return __syscall_function_cast(Table_B, uint32_t(*)(void(*)(), uint32_t*, uint32_t*))(thread_func, stack_ptr, gp); + return __syscall_function_cast(Table_B, ThreadHandle(*)(void(*)(), uint32_t*, uint32_t*))(thread_func, stack_ptr, gp); } - static __always_inline uint32_t ChangeTh(uint32_t thread) { - register uint32_t FuncID asm("t1") = 0x10; - __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); - - return __syscall_function_cast(Table_B, uint32_t(*)(uint32_t))(thread); - } - - static __always_inline int changeThreadSubFunction(uint32_t address) { - register int n asm("a0") = 3; - register int tcb asm("a1") = address; - register int r asm("v0"); - __asm__ volatile("syscall\n" : "=r"(r) : "r"(n), "r"(tcb) : "memory"); - return r; -} - static __always_inline void InitPad(uint8_t *portA, uint32_t portASize, uint8_t *portB, uint32_t portBSize) { register uint32_t FuncID asm("t1") = 0x12; __asm__ volatile("" : "=r"(FuncID) : "r"(FuncID)); diff --git a/include/PSX/System/threads.hpp b/include/PSX/System/threads.hpp new file mode 100644 index 00000000..1ee97422 --- /dev/null +++ b/include/PSX/System/threads.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "syscalls.hpp" + +namespace JabyEngine { + struct Thread { + static constexpr uint32_t idx_from_handle(SysCall::ThreadHandle thread) { + return thread & 0xFFFF; + } + + static void prepare_next(SysCall::ThreadHandle thread) { + table_of_tables.processes->current_tcb = &table_of_tables.threads[idx_from_handle(thread)]; + } + + static void execute_next() { + SysCall::ReturnFromException(); + } + + static void set_kernel_mode_for(SysCall::ThreadHandle handle) { + table_of_tables.threads[idx_from_handle(handle)].sr = 0x0; + } + + static void set_user_mode_for(SysCall::ThreadHandle handle) { + table_of_tables.threads[idx_from_handle(handle)].sr = 0x40000404; + } + }; + + struct MainThread { + static void prepare_if_main(SysCall::ThreadHandle handle) { + if(table_of_tables.processes->current_tcb == &table_of_tables.threads[0]) { + Thread::prepare_next(handle); + } + } + + static void prepare_restore() { + Thread::prepare_next(0); + } + + static void restore() { + MainThread::prepare_restore(); + Thread::execute_next(); + } + }; +} \ No newline at end of file diff --git a/src/Library/internal-include/BootLoader/boot_loader.hpp b/src/Library/internal-include/BootLoader/boot_loader.hpp index 38b3ac0f..49b5a6ea 100644 --- a/src/Library/internal-include/BootLoader/boot_loader.hpp +++ b/src/Library/internal-include/BootLoader/boot_loader.hpp @@ -8,6 +8,10 @@ namespace JabyEngine { void identify(); } + namespace Callbacks { + void setup(); + } + namespace CD { void setup(); } diff --git a/src/Library/internal-include/System/callbacks_internal.hpp b/src/Library/internal-include/System/callbacks_internal.hpp new file mode 100644 index 00000000..6664e202 --- /dev/null +++ b/src/Library/internal-include/System/callbacks_internal.hpp @@ -0,0 +1,21 @@ +#pragma once +#include + +namespace JabyEngine { + namespace Callback { + namespace internal { + namespace VSync { + static constexpr size_t StackSize = 64; + + extern SysCall::ThreadHandle thread_handle; + extern uint32_t stack[StackSize]; + void routine(); + + static void execute() { + MainThread::prepare_if_main(VSync::thread_handle); + Thread::execute_next(); + } + } + } + } +} diff --git a/src/Library/src/BootLoader/callbacks_boot.cpp b/src/Library/src/BootLoader/callbacks_boot.cpp new file mode 100644 index 00000000..7c5fb44b --- /dev/null +++ b/src/Library/src/BootLoader/callbacks_boot.cpp @@ -0,0 +1,21 @@ +#include "../../internal-include/BootLoader/boot_loader.hpp" +#include "../../internal-include/System/callbacks_internal.hpp" + +namespace JabyEngine { + namespace boot { + namespace Callbacks { + namespace InternalCallback = JabyEngine::Callback::internal; + + void setup() { + SysCall::EnterCriticalSection(); + InternalCallback::VSync::thread_handle = SysCall::OpenThread( + InternalCallback::VSync::routine, + &InternalCallback::VSync::stack[InternalCallback::VSync::StackSize - 1], + SysCall::get_gp() + ); + Thread::set_user_mode_for(InternalCallback::VSync::thread_handle); + SysCall::ExitCriticalSection(); + } + } + } +} \ No newline at end of file diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index c97c659e..4c85bae2 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -47,6 +47,7 @@ namespace JabyEngine { static constexpr auto DebugScale = 1.0; BIOS::identify(); + Callbacks::setup(); __debug_boot_color_at(::JabyEngine::GPU::Color24::Grey(), DebugX, DebugY, DebugScale); DMA::setup(); @@ -69,7 +70,6 @@ namespace JabyEngine { test_bios_font(); test_gte_scale(); - //Pause?? SPU::setup(); } } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index e1674654..39d3f992 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -13,9 +13,6 @@ namespace JabyEngine { static SysCall::InterruptVerifierResult interrupt_verifier(); static uint32_t interrupt_handler(uint32_t); - static uint32_t stack[1024]; - static uint32_t thread = 0; - static SectorBufferAllocator sector_allocator; static uint32_t cur_lba; static uint32_t dst_lba; @@ -112,12 +109,15 @@ namespace JabyEngine { } break; case CD_IO::Interrupt::DataEnd: { - if(thread != 0 && table_of_tables.processes->current_tcb == &table_of_tables.threads[0]) { - //changeThread(thread); - printf("About to change...\n"); - table_of_tables.processes->current_tcb = &table_of_tables.threads[thread&0xFFFF]; - printf("Changed!\n"); - } + CD_IO::PortIndex0::change_to(); + Command::send(CD_IO::Command::SetLoc, static_cast(0x0), static_cast(0x09), static_cast(0x0)); + + CD_IO::PortIndex1::change_to(); + while(CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag) != CD_IO::Interrupt::Acknowledge); + CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); + + CD_IO::PortIndex0::change_to(); + Command::send(CD_IO::Command::Play); } break; case CD_IO::Interrupt::DiskError: { @@ -152,26 +152,6 @@ namespace JabyEngine { } void enable_CDDA() { - if(thread == 0) { - SysCall::EnterCriticalSection(); - thread = SysCall::OpenTh([]() { - printf("Hallo!\n"); - - CD_IO::PortIndex0::change_to(); - printf("Wait...\n"); - Command::send_wait(CD_IO::Command::SetLoc, static_cast(0x0), static_cast(0x09), static_cast(0x0)); - printf("Done!\n"); - Command::send(CD_IO::Command::Play); - - table_of_tables.processes->current_tcb = &table_of_tables.threads[0]; - SysCall::ReturnFromException(); - }, &stack[1023], SysCall::get_gp()); - SysCall::ExitCriticalSection(); - - table_of_tables.threads[thread&0xFFFF].sr = table_of_tables.threads[0].sr; - printf(">>> 0x%X\n", table_of_tables.threads[0].sr); - } - Command::wait_completed(); CD_IO::PortIndex0::change_to(); Command::send_wait(CD_IO::Command::SetMode, AudioSectorMode); diff --git a/src/Library/src/GPU/gpu.cpp b/src/Library/src/GPU/gpu.cpp index bd692544..e84edb7e 100644 --- a/src/Library/src/GPU/gpu.cpp +++ b/src/Library/src/GPU/gpu.cpp @@ -1,4 +1,5 @@ #include "../../internal-include/GPU/gpu_internal.hpp" +#include "../../internal-include/System/callbacks_internal.hpp" #include #include #include @@ -40,8 +41,7 @@ namespace JabyEngine { MasterTime::value++; Interrupt::ack_irq(Interrupt::VBlank); - SysCall::ReturnFromException(); - __builtin_unreachable(); + Callback::internal::VSync::execute(); } uint32_t Display :: exchange_buffer_and_display() { diff --git a/src/Library/src/System/callbacks.cpp b/src/Library/src/System/callbacks.cpp new file mode 100644 index 00000000..d71da9b5 --- /dev/null +++ b/src/Library/src/System/callbacks.cpp @@ -0,0 +1,26 @@ +#include "../../internal-include/System/callbacks_internal.hpp" +#include + +#include + +namespace JabyEngine { + namespace Callback { + VSyncCallback::Function VSyncCallback :: callback = nullptr; + + namespace internal { + namespace VSync { + SysCall::ThreadHandle thread_handle = 0; + uint32_t stack[StackSize] = {0}; + + void routine() { + while(true) { + if(VSyncCallback::callback) { + VSyncCallback::callback(); + } + MainThread::restore(); + } + } + } + } + } +} \ No newline at end of file