[nostalgia/core/gba] Add wfi functions

This commit is contained in:
Gary Talent 2020-07-15 01:41:04 -05:00
parent 834ca2893b
commit f10d318e54
9 changed files with 134 additions and 36 deletions

View File

@ -3,6 +3,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
add_library(
NostalgiaCore-GBA
bios.s
core.cpp
gfx.cpp
irq.arm.cpp

View File

@ -0,0 +1,21 @@
/*
* 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/.
*/
#pragma once
extern "C" {
void nostalgia_core_halt();
void nostalgia_core_stop();
void nostalgia_core_wfi();
void nostalgia_core_vblankwfi();
}

View File

@ -0,0 +1,37 @@
//
// Copyright 2016 - 2020 gtalent2@gmail.com
//
// 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/.
//
.section .iwram, "ax", %progbits
.thumb
.align
.global nostalgia_core_halt
.type nostalgia_core_halt, %function
nostalgia_core_halt:
swi 2
bx lr
.global nostalgia_core_stop
.type nostalgia_core_stop, %function
nostalgia_core_stop:
swi 3
bx lr
.global nostalgia_core_wfi
.type nostalgia_core_wfi, %function
nostalgia_core_wfi:
swi 4
bx lr
.global nostalgia_core_vblankwfi
.type nostalgia_core_vblankwfi, %function
nostalgia_core_vblankwfi:
swi 5
bx lr
// vim: ft=armv4

View File

@ -10,6 +10,7 @@
#include <nostalgia/core/core.hpp>
#include "addresses.hpp"
#include "bios.hpp"
#include "irq.hpp"
extern "C" void isr();
@ -19,7 +20,7 @@ namespace nostalgia::core {
// Timer Consts
constexpr auto NanoSecond = 1000000000;
constexpr auto MilliSecond = 1000;
constexpr int TicksMs59ns = (NanoSecond / MilliSecond) / 59.59;
constexpr int TicksMs59ns = 65535 - (NanoSecond / MilliSecond) / 59.59;
extern volatile ox::Uint<config::GbaTimerBits> g_timerMs;
@ -45,6 +46,7 @@ ox::Error init(Context *ctx) {
ox::Error run(Context*) {
while (1) {
nostalgia_core_vblankwfi();
}
return OxError(0);
}

View File

@ -14,12 +14,14 @@
#include <nostalgia/core/gfx.hpp>
#include "addresses.hpp"
#include "bios.hpp"
#include "irq.hpp"
#include "gfx.hpp"
namespace nostalgia::core {
constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32;
constexpr uint16_t DispStat_irq_vblank = 1 << 3;
constexpr uint16_t DispStat_irq_hblank = 1 << 4;
@ -209,6 +211,11 @@ void setTile(Context*, int layer, int column, int row, uint8_t tile) {
MEM_BG_MAP[layer][row * GbaTileColumns + column] = tile;
}
// Do NOT use Context in the GBA version of this function.
void clearTileLayer(Context*, int layer) {
memset(&MEM_BG_MAP[layer], 0, GbaTileRows * GbaTileColumns);
}
void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx) {
GbaSpriteAttrUpdate oa;
oa.attr0 = static_cast<uint16_t>(y & ox::onMask<uint8_t>(7))
@ -217,7 +224,9 @@ void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx) {
oa.attr2 = static_cast<uint16_t>(tileIdx & ox::onMask<uint16_t>(8));
oa.idx = idx;
// block until g_spriteUpdates is less than buffer len
while (g_spriteUpdates >= config::GbaSpriteBufferLen);
if (g_spriteUpdates >= config::GbaSpriteBufferLen) {
nostalgia_core_vblankwfi();
}
REG_IE &= ~Int_vblank; // disable vblank interrupt handler
g_spriteBuffer[g_spriteUpdates++] = oa;
REG_IE |= Int_vblank; // enable vblank interrupt handler

View File

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

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
// License, v. 2.0. If a copy of the MPL was not distributed with this
@ -16,7 +16,7 @@
.extern nostalgia_core_isr_timer2
.extern nostalgia_core_isr_timer3
.equ REG_IFBIOS, 0x03fffff8
.equ REG_IFBIOS, 0x03007ff8
.equ REG_IE, 0x04000200
.equ REG_IF, 0x04000202
@ -54,51 +54,59 @@ isr:
strh r1, [r0, #2]
ldr r0, =#REG_IFBIOS
// Acknowledge IRQ in REG_IFBIOS
ldrh r2, [r0] // r2 becomes REG_IFBIOS value
ldr r2, [r0] // r2 becomes REG_IFBIOS value
orr r2, r2, r1
strh r2, [r0]
str r2, [r0]
// done with r2 as IFBIOS value
// done with r0 as REG_IE
// clear IME to disable interrupts
ldr r2, =#REG_IME
mov r0, #0
str r0, [r2]
// enter system mode
mrs r0, cpsr
bic r0, r0, #0xDF
orr r0, r0, #0x1F
msr cpsr, r0
push {lr}
ldr lr, =isr_end
// done with r0 as REG_IFBIOS
////////////////////////////////////////////////////
// Interrupt Table Begin //
////////////////////////////////////////////////////
cmp r1, #Int_vblank
beq nostalgia_core_isr_vblank
ldreq r0, =nostalgia_core_isr_vblank
beq isr_call_handler
cmp r1, #Int_timer0
beq nostalgia_core_isr_timer0
ldreq r0, =nostalgia_core_isr_timer0
beq isr_call_handler
cmp r1, #Int_timer1
beq nostalgia_core_isr_timer1
ldreq r0, =nostalgia_core_isr_timer1
beq isr_call_handler
cmp r1, #Int_timer2
beq nostalgia_core_isr_timer2
ldreq r0, =nostalgia_core_isr_timer2
beq isr_call_handler
cmp r1, #Int_timer3
beq nostalgia_core_isr_timer3
ldreq r0, =nostalgia_core_isr_timer3
beq isr_call_handler
////////////////////////////////////////////////////
// Interrupt Table End //
////////////////////////////////////////////////////
isr_end:
// restore lr from before the Interrupt Table
b isr_end
isr_call_handler:
// clear IME to disable interrupts
ldr r2, =#REG_IME
mov r1, #0
str r1, [r2]
// enter system mode
mrs r1, cpsr
bic r1, r1, #0xDF
orr r1, r1, #0x1F
msr cpsr, r1
push {lr}
ldr lr, =isr_restore
bx r0
isr_restore:
pop {lr}
// re-enter irq mode
@ -112,6 +120,8 @@ isr_end:
mov r0, #1
str r0, [r2]
isr_end:
bx lr
// vim: ft=armv4

View File

@ -6,8 +6,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "../core.hpp"
#include "../gfx.hpp"
#include <ox/std/memops.hpp>
#include <nostalgia/core/core.hpp>
#include <nostalgia/core/gfx.hpp>
#include "addresses.hpp"
#include "bios.hpp"
namespace ox {
@ -16,15 +21,20 @@ using namespace nostalgia::core;
void panic(const char*, int, const char *msg, ox::Error err) {
oxIgnoreError(initGfx(nullptr));
oxIgnoreError(initConsole(nullptr));
// enable only BG 0
REG_DISPCTL = 0x0100;
clearTileLayer(nullptr, 0);
ox::BString<23> serr = "Error code: ";
serr += err;
puts(nullptr, 32 + 0, 1, "SADNESS...");
puts(nullptr, 32 + 0, 4, "UNEXPECTED STATE:");
puts(nullptr, 32 + 1, 1, "SADNESS...");
puts(nullptr, 32 + 1, 4, "UNEXPECTED STATE:");
puts(nullptr, 32 + 2, 6, msg);
puts(nullptr, 32 + 2, 7, serr.c_str());
puts(nullptr, 32 + 0, 10, "PLEASE RESTART THE SYSTEM");
// TODO: properly end program execution, this wastes power
while (1);
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();
}
}

View File

@ -125,6 +125,8 @@ void puts(Context *ctx, int column, int row, const char *str);
void setTile(Context *ctx, int layer, int column, int row, uint8_t tile);
void clearTileLayer(Context*, int layer);
void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx);
}