[nostalgia/core/gba] Fix event cycle and add to setter for event handler

This commit is contained in:
Gary Talent 2020-07-17 01:36:51 -05:00
parent a58467f327
commit dc0667ade4
12 changed files with 111 additions and 36 deletions

View File

@ -8,9 +8,17 @@
#pragma once #pragma once
namespace nostalgia::core::config { #include <ox/std/types.hpp>
namespace nostalgia::core {
namespace config {
constexpr auto GbaSpriteBufferLen = 128; constexpr auto GbaSpriteBufferLen = 128;
constexpr auto GbaTimerBits = 64; constexpr auto GbaEventLoopTimerBased = false;
}
using gba_timer_t = uint32_t;
} }

View File

@ -16,10 +16,16 @@
namespace nostalgia::core { namespace nostalgia::core {
using event_handler = int(*)(void);
[[nodiscard]] ox::Error init(Context *ctx); [[nodiscard]] ox::Error init(Context *ctx);
[[nodiscard]] ox::Error run(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 // Returns the number of milliseconds that have passed since the start of the
// program. // program.
[[nodiscard]] uint64_t ticksMs(); [[nodiscard]] uint64_t ticksMs();

View File

@ -4,6 +4,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
add_library( add_library(
NostalgiaCore-GBA NostalgiaCore-GBA
bios.s bios.s
core.arm.cpp
core.cpp core.cpp
gfx.cpp gfx.cpp
irq.arm.cpp irq.arm.cpp
@ -12,7 +13,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
panic.cpp 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( target_link_libraries(
NostalgiaCore-GBA PUBLIC NostalgiaCore-GBA PUBLIC

View File

@ -8,14 +8,19 @@
#pragma once #pragma once
// Functions for accessing BIOS calls
extern "C" { extern "C" {
// waits for any interrupt
void nostalgia_core_halt(); void nostalgia_core_halt();
void nostalgia_core_stop(); 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();
} }

View File

@ -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 // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
@ -22,15 +22,15 @@ nostalgia_core_stop:
swi 3 swi 3
bx lr bx lr
.global nostalgia_core_wfi .global nostalgia_core_intrwait
.type nostalgia_core_wfi, %function .type nostalgia_core_intrwait, %function
nostalgia_core_wfi: nostalgia_core_intrwait:
swi 4 swi 4
bx lr bx lr
.global nostalgia_core_vblankwfi .global nostalgia_core_vblankintrwait
.type nostalgia_core_vblankwfi, %function .type nostalgia_core_vblankintrwait, %function
nostalgia_core_vblankwfi: nostalgia_core_vblankintrwait:
swi 5 swi 5
bx lr bx lr

View File

@ -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 <nostalgia/core/config.hpp>
#include <nostalgia/core/core.hpp>
#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<unsigned>(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);
}
}

View File

@ -18,11 +18,13 @@ extern "C" void isr();
namespace nostalgia::core { namespace nostalgia::core {
// Timer Consts // Timer Consts
constexpr auto NanoSecond = 1000000000; constexpr int NanoSecond = 1000000000;
constexpr auto MilliSecond = 1000; constexpr int MilliSecond = 1000;
constexpr int TicksMs59ns = 65535 - (NanoSecond / MilliSecond) / 59.59; constexpr int TicksMs59ns = 65535 - (NanoSecond / MilliSecond) / 59.59;
extern volatile ox::Uint<config::GbaTimerBits> g_timerMs; extern event_handler g_eventHandler;
extern volatile gba_timer_t g_timerMs;
static void initIrq() { static void initIrq() {
REG_ISR = isr; REG_ISR = isr;
@ -44,11 +46,8 @@ ox::Error init(Context *ctx) {
return OxError(0); return OxError(0);
} }
ox::Error run(Context*) { void setEventHandler(event_handler h) {
while (1) { g_eventHandler = h;
nostalgia_core_vblankwfi();
}
return OxError(0);
} }
uint64_t ticksMs() { uint64_t ticksMs() {

View File

@ -225,11 +225,18 @@ void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx) {
oa.idx = idx; oa.idx = idx;
// block until g_spriteUpdates is less than buffer len // block until g_spriteUpdates is less than buffer len
if (g_spriteUpdates >= config::GbaSpriteBufferLen) { 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
} }
} }

View File

@ -18,7 +18,7 @@ namespace nostalgia::core {
volatile uint16_t g_spriteUpdates = 0; volatile uint16_t g_spriteUpdates = 0;
GbaSpriteAttrUpdate g_spriteBuffer[config::GbaSpriteBufferLen]; 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<uint64_t*>(&oa); MEM_OAM[oa.idx] = *reinterpret_cast<uint64_t*>(&oa);
} }
g_spriteUpdates = 0; g_spriteUpdates = 0;
if constexpr(config::GbaEventLoopTimerBased) {
// disable vblank interrupt until it is needed again
REG_IE &= ~Int_vblank;
}
} }
void nostalgia_core_isr_timer0() { void nostalgia_core_isr_timer0() {

View File

@ -26,9 +26,3 @@ constexpr uint16_t Int_input = 1 << 14; // gamepad
constexpr uint16_t Int_cart = 1 << 15; // cartridge removed constexpr uint16_t Int_cart = 1 << 15; // cartridge removed
} }
extern "C" {
void nostalgia_core_wfi();
}

View File

@ -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 * 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 * 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, 6, msg);
puts(nullptr, 32 + 2, 8, serr.c_str()); puts(nullptr, 32 + 2, 8, serr.c_str());
puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM"); puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
// disable interrupts and wait for interrupt, halt and stop seem to have // disable all interrupt handling and IntrWait on no interrupts
// issues in mGBA REG_IE = 0;
REG_IME = 0; nostalgia_core_intrwait(0, 0);
nostalgia_core_wfi();
} }
} }

View File

@ -9,9 +9,12 @@
#include <SDL.h> #include <SDL.h>
#include <nostalgia/core/gfx.hpp> #include <nostalgia/core/gfx.hpp>
#include <nostalgia/core/core.hpp>
namespace nostalgia::core { namespace nostalgia::core {
static event_handler g_eventHandler = nullptr;
void draw(Context *ctx); void draw(Context *ctx);
ox::Error init(Context *ctx) { ox::Error init(Context *ctx) {
@ -41,6 +44,10 @@ ox::Error run(Context *ctx) {
return OxError(0); return OxError(0);
} }
void setEventHandler(event_handler h) {
g_eventHandler = h;
}
uint64_t ticksMs() { uint64_t ticksMs() {
return SDL_GetTicks();; return SDL_GetTicks();;
} }