[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
|
#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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
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 {
|
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() {
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user