From dc0667ade4f0b7b1a28b4170eab34cac72eebca6 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 17 Jul 2020 01:36:51 -0500 Subject: [PATCH] [nostalgia/core/gba] Fix event cycle and add to setter for event handler --- src/nostalgia/core/config.hpp | 12 +++++-- src/nostalgia/core/core.hpp | 6 ++++ src/nostalgia/core/gba/CMakeLists.txt | 3 +- src/nostalgia/core/gba/bios.hpp | 9 ++++-- src/nostalgia/core/gba/bios.s | 14 ++++----- src/nostalgia/core/gba/core.arm.cpp | 45 +++++++++++++++++++++++++++ src/nostalgia/core/gba/core.cpp | 15 +++++---- src/nostalgia/core/gba/gfx.cpp | 15 ++++++--- src/nostalgia/core/gba/irq.arm.cpp | 6 +++- src/nostalgia/core/gba/irq.hpp | 6 ---- src/nostalgia/core/gba/panic.cpp | 9 +++--- src/nostalgia/core/sdl/core.cpp | 7 +++++ 12 files changed, 111 insertions(+), 36 deletions(-) create mode 100644 src/nostalgia/core/gba/core.arm.cpp diff --git a/src/nostalgia/core/config.hpp b/src/nostalgia/core/config.hpp index 17d65406..4bd59354 100644 --- a/src/nostalgia/core/config.hpp +++ b/src/nostalgia/core/config.hpp @@ -8,9 +8,17 @@ #pragma once -namespace nostalgia::core::config { +#include + +namespace nostalgia::core { + +namespace config { constexpr auto GbaSpriteBufferLen = 128; -constexpr auto GbaTimerBits = 64; +constexpr auto GbaEventLoopTimerBased = false; + +} + +using gba_timer_t = uint32_t; } diff --git a/src/nostalgia/core/core.hpp b/src/nostalgia/core/core.hpp index 5d3f8143..621f34f0 100644 --- a/src/nostalgia/core/core.hpp +++ b/src/nostalgia/core/core.hpp @@ -16,10 +16,16 @@ namespace nostalgia::core { +using event_handler = int(*)(void); + [[nodiscard]] ox::Error init(Context *ctx); [[nodiscard]] ox::Error run(Context *ctx); +// Sets event handler that sleeps for the time given in the return value. The +// sleep time is a minimum of ~16 milliseconds. +void setEventHandler(event_handler); + // Returns the number of milliseconds that have passed since the start of the // program. [[nodiscard]] uint64_t ticksMs(); diff --git a/src/nostalgia/core/gba/CMakeLists.txt b/src/nostalgia/core/gba/CMakeLists.txt index a85cee31..30329095 100644 --- a/src/nostalgia/core/gba/CMakeLists.txt +++ b/src/nostalgia/core/gba/CMakeLists.txt @@ -4,6 +4,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA") add_library( NostalgiaCore-GBA bios.s + core.arm.cpp core.cpp gfx.cpp irq.arm.cpp @@ -12,7 +13,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA") panic.cpp ) - set_source_files_properties(irq.arm.cpp PROPERTIES COMPILE_FLAGS -marm) + set_source_files_properties(core.arm.cpp irq.arm.cpp PROPERTIES COMPILE_FLAGS -marm) target_link_libraries( NostalgiaCore-GBA PUBLIC diff --git a/src/nostalgia/core/gba/bios.hpp b/src/nostalgia/core/gba/bios.hpp index b2be8a1a..bfe85906 100644 --- a/src/nostalgia/core/gba/bios.hpp +++ b/src/nostalgia/core/gba/bios.hpp @@ -8,14 +8,19 @@ #pragma once +// Functions for accessing BIOS calls + extern "C" { +// waits for any interrupt void nostalgia_core_halt(); void nostalgia_core_stop(); -void nostalgia_core_wfi(); +// waits for interrupts specified in interSubs +void nostalgia_core_intrwait(unsigned discardExistingIntrs, unsigned intrSubs); -void nostalgia_core_vblankwfi(); +// waits for vblank interrupt +void nostalgia_core_vblankintrwait(); } diff --git a/src/nostalgia/core/gba/bios.s b/src/nostalgia/core/gba/bios.s index 933dd445..2380bcd2 100644 --- a/src/nostalgia/core/gba/bios.s +++ b/src/nostalgia/core/gba/bios.s @@ -1,5 +1,5 @@ // -// Copyright 2016 - 2020 gtalent2@gmail.com +// Copyright 2016 - 2020 gary@drinkingtea.net // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -22,15 +22,15 @@ nostalgia_core_stop: swi 3 bx lr -.global nostalgia_core_wfi -.type nostalgia_core_wfi, %function -nostalgia_core_wfi: +.global nostalgia_core_intrwait +.type nostalgia_core_intrwait, %function +nostalgia_core_intrwait: swi 4 bx lr -.global nostalgia_core_vblankwfi -.type nostalgia_core_vblankwfi, %function -nostalgia_core_vblankwfi: +.global nostalgia_core_vblankintrwait +.type nostalgia_core_vblankintrwait, %function +nostalgia_core_vblankintrwait: swi 5 bx lr diff --git a/src/nostalgia/core/gba/core.arm.cpp b/src/nostalgia/core/gba/core.arm.cpp new file mode 100644 index 00000000..421055ef --- /dev/null +++ b/src/nostalgia/core/gba/core.arm.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2016 - 2020 gary@drinkingtea.net + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include "addresses.hpp" +#include "bios.hpp" +#include "irq.hpp" + +extern "C" void isr(); + +namespace nostalgia::core { + +extern volatile gba_timer_t g_timerMs; +gba_timer_t g_wakeupTime; +event_handler g_eventHandler = nullptr; + +ox::Error run(Context*) { + g_wakeupTime = 0; + while (1) { + if (g_wakeupTime <= g_timerMs && g_eventHandler) { + auto sleepTime = g_eventHandler(); + if (sleepTime >= 0) { + g_wakeupTime = g_timerMs + static_cast(sleepTime); + } else { + g_wakeupTime = ~gba_timer_t(0); + } + } + if constexpr(config::GbaEventLoopTimerBased) { + // wait for timer interrupt + nostalgia_core_intrwait(0, Int_timer0 | Int_timer1 | Int_timer2 | Int_timer3); + } else { + nostalgia_core_vblankintrwait(); + } + } + return OxError(0); +} + +} diff --git a/src/nostalgia/core/gba/core.cpp b/src/nostalgia/core/gba/core.cpp index ded1523b..e3eca6b2 100644 --- a/src/nostalgia/core/gba/core.cpp +++ b/src/nostalgia/core/gba/core.cpp @@ -18,11 +18,13 @@ extern "C" void isr(); namespace nostalgia::core { // Timer Consts -constexpr auto NanoSecond = 1000000000; -constexpr auto MilliSecond = 1000; +constexpr int NanoSecond = 1000000000; +constexpr int MilliSecond = 1000; constexpr int TicksMs59ns = 65535 - (NanoSecond / MilliSecond) / 59.59; -extern volatile ox::Uint g_timerMs; +extern event_handler g_eventHandler; + +extern volatile gba_timer_t g_timerMs; static void initIrq() { REG_ISR = isr; @@ -44,11 +46,8 @@ ox::Error init(Context *ctx) { return OxError(0); } -ox::Error run(Context*) { - while (1) { - nostalgia_core_vblankwfi(); - } - return OxError(0); +void setEventHandler(event_handler h) { + g_eventHandler = h; } uint64_t ticksMs() { diff --git a/src/nostalgia/core/gba/gfx.cpp b/src/nostalgia/core/gba/gfx.cpp index 64baa06a..c13b0877 100644 --- a/src/nostalgia/core/gba/gfx.cpp +++ b/src/nostalgia/core/gba/gfx.cpp @@ -225,11 +225,18 @@ void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx) { oa.idx = idx; // block until g_spriteUpdates is less than buffer len if (g_spriteUpdates >= config::GbaSpriteBufferLen) { - nostalgia_core_vblankwfi(); + nostalgia_core_vblankintrwait(); + } + if constexpr(config::GbaEventLoopTimerBased) { + REG_IE &= ~Int_vblank; // disable vblank interrupt handler + g_spriteBuffer[g_spriteUpdates++] = oa; + REG_IE |= Int_vblank; // enable vblank interrupt handler + } else { + auto ie = REG_IE; // disable vblank interrupt handler + REG_IE &= ~Int_vblank; // disable vblank interrupt handler + g_spriteBuffer[g_spriteUpdates++] = oa; + REG_IE = ie; // enable vblank interrupt handler } - REG_IE &= ~Int_vblank; // disable vblank interrupt handler - g_spriteBuffer[g_spriteUpdates++] = oa; - REG_IE |= Int_vblank; // enable vblank interrupt handler } } diff --git a/src/nostalgia/core/gba/irq.arm.cpp b/src/nostalgia/core/gba/irq.arm.cpp index 4582315b..4d229700 100644 --- a/src/nostalgia/core/gba/irq.arm.cpp +++ b/src/nostalgia/core/gba/irq.arm.cpp @@ -18,7 +18,7 @@ namespace nostalgia::core { volatile uint16_t g_spriteUpdates = 0; GbaSpriteAttrUpdate g_spriteBuffer[config::GbaSpriteBufferLen]; -volatile uint32_t g_timerMs = 0; +volatile gba_timer_t g_timerMs = 0; } @@ -36,6 +36,10 @@ void nostalgia_core_isr_vblank() { MEM_OAM[oa.idx] = *reinterpret_cast(&oa); } g_spriteUpdates = 0; + if constexpr(config::GbaEventLoopTimerBased) { + // disable vblank interrupt until it is needed again + REG_IE &= ~Int_vblank; + } } void nostalgia_core_isr_timer0() { diff --git a/src/nostalgia/core/gba/irq.hpp b/src/nostalgia/core/gba/irq.hpp index cb72effa..e753e8db 100644 --- a/src/nostalgia/core/gba/irq.hpp +++ b/src/nostalgia/core/gba/irq.hpp @@ -26,9 +26,3 @@ constexpr uint16_t Int_input = 1 << 14; // gamepad constexpr uint16_t Int_cart = 1 << 15; // cartridge removed } - -extern "C" { - -void nostalgia_core_wfi(); - -} diff --git a/src/nostalgia/core/gba/panic.cpp b/src/nostalgia/core/gba/panic.cpp index 1cdf1985..1cdbe07c 100644 --- a/src/nostalgia/core/gba/panic.cpp +++ b/src/nostalgia/core/gba/panic.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016 - 2019 gtalent2@gmail.com + * Copyright 2016 - 2020 gary@drinkingtea.net * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -31,10 +31,9 @@ void panic(const char*, int, const char *msg, ox::Error err) { puts(nullptr, 32 + 2, 6, msg); puts(nullptr, 32 + 2, 8, serr.c_str()); puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM"); - // disable interrupts and wait for interrupt, halt and stop seem to have - // issues in mGBA - REG_IME = 0; - nostalgia_core_wfi(); + // disable all interrupt handling and IntrWait on no interrupts + REG_IE = 0; + nostalgia_core_intrwait(0, 0); } } diff --git a/src/nostalgia/core/sdl/core.cpp b/src/nostalgia/core/sdl/core.cpp index daa470ad..33698453 100644 --- a/src/nostalgia/core/sdl/core.cpp +++ b/src/nostalgia/core/sdl/core.cpp @@ -9,9 +9,12 @@ #include #include +#include namespace nostalgia::core { +static event_handler g_eventHandler = nullptr; + void draw(Context *ctx); ox::Error init(Context *ctx) { @@ -41,6 +44,10 @@ ox::Error run(Context *ctx) { return OxError(0); } +void setEventHandler(event_handler h) { + g_eventHandler = h; +} + uint64_t ticksMs() { return SDL_GetTicks();; }