[nostalgia/core/gba] Fix event cycle and add to setter for event handler
This commit is contained in:
parent
a58467f327
commit
dc0667ade4
@ -8,9 +8,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nostalgia::core::config {
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
namespace config {
|
||||
|
||||
constexpr auto GbaSpriteBufferLen = 128;
|
||||
constexpr auto GbaTimerBits = 64;
|
||||
constexpr auto GbaEventLoopTimerBased = false;
|
||||
|
||||
}
|
||||
|
||||
using gba_timer_t = uint32_t;
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
45
src/nostalgia/core/gba/core.arm.cpp
Normal file
45
src/nostalgia/core/gba/core.arm.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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<config::GbaTimerBits> 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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<uint64_t*>(&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() {
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,9 +9,12 @@
|
||||
#include <SDL.h>
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/core/core.hpp>
|
||||
|
||||
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();;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user