From df9506b585c5996e9c4f214c0f4cdc9fdf456543 Mon Sep 17 00:00:00 2001 From: Jaby Date: Wed, 26 Apr 2023 22:06:47 +0200 Subject: [PATCH] Create a frame rate --- examples/PoolBox/application/src/main.cpp | 8 ++- include/PSX/GPU/gpu.hpp | 2 + .../internal-include/GPU/gpu_internal.hpp | 2 + src/Library/src/BootLoader/cd_boot.cpp | 1 + src/Library/src/BootLoader/gpu_boot.cpp | 14 ++++- src/Library/src/BootLoader/start_boot.cpp | 8 ++- src/Library/src/GPU/gpu.cpp | 52 ++++++++++++++++++- 7 files changed, 79 insertions(+), 8 deletions(-) diff --git a/examples/PoolBox/application/src/main.cpp b/examples/PoolBox/application/src/main.cpp index 0ce2fba7..d5ddf32b 100644 --- a/examples/PoolBox/application/src/main.cpp +++ b/examples/PoolBox/application/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include extern "C" void busy_loop(int count); @@ -16,6 +17,11 @@ static void mesaure_busy_loop() { } void main() { - printf("Hello Planschbecken!\n"); + printf("Hello PoolBox!\n"); mesaure_busy_loop(); + + while(true) { + printf("Doing stuff...\n"); + JabyEngine::GPU::swap_buffers_vsync(2); + } } \ No newline at end of file diff --git a/include/PSX/GPU/gpu.hpp b/include/PSX/GPU/gpu.hpp index af26db57..c864052c 100644 --- a/include/PSX/GPU/gpu.hpp +++ b/include/PSX/GPU/gpu.hpp @@ -33,6 +33,8 @@ namespace JabyEngine { static void set_offset(uint16_t x, uint16_t y); }; + + uint8_t swap_buffers_vsync(uint8_t syncs); } } #endif //!__JABYENGINE_GPU_HPP__ \ No newline at end of file diff --git a/src/Library/internal-include/GPU/gpu_internal.hpp b/src/Library/internal-include/GPU/gpu_internal.hpp index 1b04be47..68c1d03d 100644 --- a/src/Library/internal-include/GPU/gpu_internal.hpp +++ b/src/Library/internal-include/GPU/gpu_internal.hpp @@ -24,6 +24,8 @@ namespace JabyEngine { static void exchange_buffer_and_display(); }; + void wait_vsync(uint8_t syncs); + static void set_draw_area(uint16_t x, uint16_t y) { GPU_IO::GP0 = GPU_IO::Command::DrawAreaTopLeft(x, y); GPU_IO::GP0 = GPU_IO::Command::DrawAreaBottomRight((x + Display::Width), (y + Display::Height)); diff --git a/src/Library/src/BootLoader/cd_boot.cpp b/src/Library/src/BootLoader/cd_boot.cpp index 24da5b48..b10ae087 100644 --- a/src/Library/src/BootLoader/cd_boot.cpp +++ b/src/Library/src/BootLoader/cd_boot.cpp @@ -10,6 +10,7 @@ namespace JabyEngine { extern InterrupCallback callback; } } + namespace boot { namespace CD { using JabyEngine::CD::internal::Command; diff --git a/src/Library/src/BootLoader/gpu_boot.cpp b/src/Library/src/BootLoader/gpu_boot.cpp index 4720d0f9..22390d12 100644 --- a/src/Library/src/BootLoader/gpu_boot.cpp +++ b/src/Library/src/BootLoader/gpu_boot.cpp @@ -1,6 +1,7 @@ #include "../../internal-include/GPU/gpu_internal.hpp" -#include +#include #include +#include #include #include @@ -13,6 +14,12 @@ extern "C" uint32_t __boot_loader_end; namespace JabyEngine { + namespace GPU { + namespace internal { + extern InterrupCallback callback; + } + } + namespace boot { namespace GPU { using namespace JabyEngine::GPU; @@ -61,6 +68,11 @@ namespace JabyEngine { GPU::internal::wait_ready_for_CMD(); GPU::internal::quick_fill_fast(Color24::Black(), PositionU16(32, 0), SizeU16(Display::Width, Display::Height)); + + __syscall_EnterCriticalSection(); + __syscall_SysEnqIntRP(VblankIrq, &::JabyEngine::GPU::internal::callback); + Interrupt::enable_irq(Interrupt::VBlank); + __syscall_ExitCriticalSection(); } } } diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index cc0e4629..11fb9a3a 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -1,14 +1,11 @@ #include "../../internal-include/BootLoader/boot_loader.hpp" -#include - -// 2x For setup timing -#include +#include "../../internal-include/GPU/gpu_internal.hpp" +#include #include namespace JabyEngine { namespace boot { namespace Start { - //This should become part of the bootloader later static void enable_DMA() { DMA_IO::DPCR = DMA_IO::DPCR_t(DMA_IO::DPCR).set(DMA_IO::DPCR_t::SPUEnable).set(DMA_IO::DPCR_t::GPUEnable).set(DMA_IO::DPCR_t::CDROMEnable); } @@ -35,6 +32,7 @@ namespace JabyEngine { boot::Start::setup(); printf("Running main...\n"); + GPU::internal::wait_vsync(0); run(); } } \ No newline at end of file diff --git a/src/Library/src/GPU/gpu.cpp b/src/Library/src/GPU/gpu.cpp index 8597cfeb..94ffa438 100644 --- a/src/Library/src/GPU/gpu.cpp +++ b/src/Library/src/GPU/gpu.cpp @@ -1,15 +1,58 @@ #include "../../internal-include/GPU/gpu_internal.hpp" +#include +#include namespace JabyEngine { namespace GPU { uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0 namespace internal { + static uint8_t vsync_count = 0; + + static InterruptVerifierResult interrupt_verifier(); + static void interrupt_handler(uint32_t); + + InterrupCallback callback = { + .next = nullptr, + .handler_function = reinterpret_cast(interrupt_handler), + .verifier_function = interrupt_verifier + }; + + static InterruptVerifierResult interrupt_verifier() { + if(Interrupt::is_irq(Interrupt::VBlank)) { + return InterruptVerifierResult::ExecuteHandler; + } + + else { + return InterruptVerifierResult::SkipHandler; + } + } + + static void interrupt_handler(uint32_t) { + if(vsync_count != 0xFF) { + vsync_count++; + } + + Interrupt::ack_irq(Interrupt::VBlank); + __syscall_ReturnFromException(); + } + void Display :: exchange_buffer_and_display() { GPU::internal::set_draw_area(0, (PublicDisplay::Height*PublicDisplay::current_id)); PublicDisplay::current_id ^= 1; GPU_IO::GP1 = GPU_IO::Command::DisplayArea(0, (PublicDisplay::Height*PublicDisplay::current_id)); } + + void wait_vsync(uint8_t syncs) { + volatile uint8_t& vsync_count = reinterpret_cast(internal::vsync_count); + + if(internal::vsync_count >= syncs) { + syncs = internal::vsync_count + 1; + } + + while(vsync_count < syncs); + vsync_count = 0; + } } #ifndef USE_NO$PSX @@ -21,10 +64,17 @@ namespace JabyEngine { GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height); } #else - void Screen :: set_offset(uint16_t x, uint16_t y) { + void Display :: set_offset(uint16_t x, uint16_t y) { GPU_IO::GP1 = GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)); GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)); } #endif //USE_NO$PSX + + uint8_t swap_buffers_vsync(uint8_t syncs) { + // Wait finish draw + internal::wait_vsync(syncs); + internal::Display::exchange_buffer_and_display(); + return Display::current_id; + } } } \ No newline at end of file