[nostalgia/core/gba] Add wfi functions
This commit is contained in:
parent
834ca2893b
commit
f10d318e54
@ -3,6 +3,7 @@ if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
|||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
NostalgiaCore-GBA
|
NostalgiaCore-GBA
|
||||||
|
bios.s
|
||||||
core.cpp
|
core.cpp
|
||||||
gfx.cpp
|
gfx.cpp
|
||||||
irq.arm.cpp
|
irq.arm.cpp
|
||||||
|
21
src/nostalgia/core/gba/bios.hpp
Normal file
21
src/nostalgia/core/gba/bios.hpp
Normal 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();
|
||||||
|
|
||||||
|
}
|
37
src/nostalgia/core/gba/bios.s
Normal file
37
src/nostalgia/core/gba/bios.s
Normal 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
|
@ -10,6 +10,7 @@
|
|||||||
#include <nostalgia/core/core.hpp>
|
#include <nostalgia/core/core.hpp>
|
||||||
|
|
||||||
#include "addresses.hpp"
|
#include "addresses.hpp"
|
||||||
|
#include "bios.hpp"
|
||||||
#include "irq.hpp"
|
#include "irq.hpp"
|
||||||
|
|
||||||
extern "C" void isr();
|
extern "C" void isr();
|
||||||
@ -19,7 +20,7 @@ namespace nostalgia::core {
|
|||||||
// Timer Consts
|
// Timer Consts
|
||||||
constexpr auto NanoSecond = 1000000000;
|
constexpr auto NanoSecond = 1000000000;
|
||||||
constexpr auto MilliSecond = 1000;
|
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;
|
extern volatile ox::Uint<config::GbaTimerBits> g_timerMs;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ ox::Error init(Context *ctx) {
|
|||||||
|
|
||||||
ox::Error run(Context*) {
|
ox::Error run(Context*) {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
nostalgia_core_vblankwfi();
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,14 @@
|
|||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
|
||||||
#include "addresses.hpp"
|
#include "addresses.hpp"
|
||||||
|
#include "bios.hpp"
|
||||||
#include "irq.hpp"
|
#include "irq.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
constexpr auto GbaTileColumns = 32;
|
constexpr auto GbaTileColumns = 32;
|
||||||
|
constexpr auto GbaTileRows = 32;
|
||||||
|
|
||||||
constexpr uint16_t DispStat_irq_vblank = 1 << 3;
|
constexpr uint16_t DispStat_irq_vblank = 1 << 3;
|
||||||
constexpr uint16_t DispStat_irq_hblank = 1 << 4;
|
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;
|
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) {
|
void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx) {
|
||||||
GbaSpriteAttrUpdate oa;
|
GbaSpriteAttrUpdate oa;
|
||||||
oa.attr0 = static_cast<uint16_t>(y & ox::onMask<uint8_t>(7))
|
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.attr2 = static_cast<uint16_t>(tileIdx & ox::onMask<uint16_t>(8));
|
||||||
oa.idx = idx;
|
oa.idx = idx;
|
||||||
// block until g_spriteUpdates is less than buffer len
|
// 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
|
REG_IE &= ~Int_vblank; // disable vblank interrupt handler
|
||||||
g_spriteBuffer[g_spriteUpdates++] = oa;
|
g_spriteBuffer[g_spriteUpdates++] = oa;
|
||||||
REG_IE |= Int_vblank; // enable vblank interrupt handler
|
REG_IE |= Int_vblank; // enable vblank interrupt handler
|
||||||
|
@ -26,3 +26,9 @@ 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 - 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
|
||||||
@ -16,7 +16,7 @@
|
|||||||
.extern nostalgia_core_isr_timer2
|
.extern nostalgia_core_isr_timer2
|
||||||
.extern nostalgia_core_isr_timer3
|
.extern nostalgia_core_isr_timer3
|
||||||
|
|
||||||
.equ REG_IFBIOS, 0x03fffff8
|
.equ REG_IFBIOS, 0x03007ff8
|
||||||
|
|
||||||
.equ REG_IE, 0x04000200
|
.equ REG_IE, 0x04000200
|
||||||
.equ REG_IF, 0x04000202
|
.equ REG_IF, 0x04000202
|
||||||
@ -54,51 +54,59 @@ isr:
|
|||||||
strh r1, [r0, #2]
|
strh r1, [r0, #2]
|
||||||
ldr r0, =#REG_IFBIOS
|
ldr r0, =#REG_IFBIOS
|
||||||
// Acknowledge IRQ in 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
|
orr r2, r2, r1
|
||||||
strh r2, [r0]
|
str r2, [r0]
|
||||||
// done with r2 as IFBIOS value
|
// done with r2 as IFBIOS value
|
||||||
// done with r0 as REG_IE
|
// done with r0 as REG_IFBIOS
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// Interrupt Table Begin //
|
// Interrupt Table Begin //
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
cmp r1, #Int_vblank
|
cmp r1, #Int_vblank
|
||||||
beq nostalgia_core_isr_vblank
|
ldreq r0, =nostalgia_core_isr_vblank
|
||||||
|
beq isr_call_handler
|
||||||
|
|
||||||
cmp r1, #Int_timer0
|
cmp r1, #Int_timer0
|
||||||
beq nostalgia_core_isr_timer0
|
ldreq r0, =nostalgia_core_isr_timer0
|
||||||
|
beq isr_call_handler
|
||||||
|
|
||||||
cmp r1, #Int_timer1
|
cmp r1, #Int_timer1
|
||||||
beq nostalgia_core_isr_timer1
|
ldreq r0, =nostalgia_core_isr_timer1
|
||||||
|
beq isr_call_handler
|
||||||
|
|
||||||
cmp r1, #Int_timer2
|
cmp r1, #Int_timer2
|
||||||
beq nostalgia_core_isr_timer2
|
ldreq r0, =nostalgia_core_isr_timer2
|
||||||
|
beq isr_call_handler
|
||||||
|
|
||||||
cmp r1, #Int_timer3
|
cmp r1, #Int_timer3
|
||||||
beq nostalgia_core_isr_timer3
|
ldreq r0, =nostalgia_core_isr_timer3
|
||||||
|
beq isr_call_handler
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// Interrupt Table End //
|
// Interrupt Table End //
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
isr_end:
|
b isr_end
|
||||||
// restore lr from before the Interrupt Table
|
|
||||||
|
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}
|
pop {lr}
|
||||||
|
|
||||||
// re-enter irq mode
|
// re-enter irq mode
|
||||||
@ -112,6 +120,8 @@ isr_end:
|
|||||||
mov r0, #1
|
mov r0, #1
|
||||||
str r0, [r2]
|
str r0, [r2]
|
||||||
|
|
||||||
|
isr_end:
|
||||||
|
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
// vim: ft=armv4
|
// vim: ft=armv4
|
||||||
|
@ -6,8 +6,13 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../core.hpp"
|
#include <ox/std/memops.hpp>
|
||||||
#include "../gfx.hpp"
|
|
||||||
|
#include <nostalgia/core/core.hpp>
|
||||||
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
|
||||||
|
#include "addresses.hpp"
|
||||||
|
#include "bios.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
@ -16,15 +21,20 @@ using namespace nostalgia::core;
|
|||||||
void panic(const char*, int, const char *msg, ox::Error err) {
|
void panic(const char*, int, const char *msg, ox::Error err) {
|
||||||
oxIgnoreError(initGfx(nullptr));
|
oxIgnoreError(initGfx(nullptr));
|
||||||
oxIgnoreError(initConsole(nullptr));
|
oxIgnoreError(initConsole(nullptr));
|
||||||
|
// enable only BG 0
|
||||||
|
REG_DISPCTL = 0x0100;
|
||||||
|
clearTileLayer(nullptr, 0);
|
||||||
ox::BString<23> serr = "Error code: ";
|
ox::BString<23> serr = "Error code: ";
|
||||||
serr += err;
|
serr += err;
|
||||||
puts(nullptr, 32 + 0, 1, "SADNESS...");
|
puts(nullptr, 32 + 1, 1, "SADNESS...");
|
||||||
puts(nullptr, 32 + 0, 4, "UNEXPECTED STATE:");
|
puts(nullptr, 32 + 1, 4, "UNEXPECTED STATE:");
|
||||||
puts(nullptr, 32 + 2, 6, msg);
|
puts(nullptr, 32 + 2, 6, msg);
|
||||||
puts(nullptr, 32 + 2, 7, serr.c_str());
|
puts(nullptr, 32 + 2, 8, serr.c_str());
|
||||||
puts(nullptr, 32 + 0, 10, "PLEASE RESTART THE SYSTEM");
|
puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
|
||||||
// TODO: properly end program execution, this wastes power
|
// disable interrupts and wait for interrupt, halt and stop seem to have
|
||||||
while (1);
|
// issues in mGBA
|
||||||
|
REG_IME = 0;
|
||||||
|
nostalgia_core_wfi();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 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);
|
void setSprite(unsigned idx, unsigned x, unsigned y, unsigned tileIdx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user