Update to release v000r04.

byuu says:

[screenshot of the Tetris title screen]

Less than fourty-eight hours after starting on this. I guess you weren't
kidding, Exophase.
This commit is contained in:
Tim Allen 2010-12-30 18:18:47 +11:00
parent 71780949b0
commit 2330ed6e8c
16 changed files with 654 additions and 41 deletions

View File

@ -324,7 +324,7 @@ void CPU::op_rlca() {
void CPU::op_rla() {
bool c = r[A] & 0x80;
r[A] = (r[A] << 1) | (c << 0);
r[A] = (r[A] << 1) | (r.f.c << 0);
r.f.z = 0;
r.f.n = 0;
r.f.h = 0;
@ -341,7 +341,7 @@ void CPU::op_rrca() {
void CPU::op_rra() {
bool c = r[A] & 0x01;
r[A] = (r[A] >> 1) | (c << 7);
r[A] = (r[A] >> 1) | (r.f.c << 7);
r.f.z = 0;
r.f.n = 0;
r.f.h = 0;

View File

@ -15,15 +15,57 @@ void CPU::Main() {
void CPU::main() {
while(true) {
//print(disassemble(r[PC]), "\n");
interrupt_test();
uint8 opcode = op_read(r[PC]++);
(this->*opcode_table[opcode])();
}
}
void CPU::interrupt_test() {
if(status.ime) {
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
status.interrupt_request_vblank = 0;
return interrupt_exec(0x0040);
}
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
status.interrupt_request_stat = 0;
return interrupt_exec(0x0048);
}
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
status.interrupt_request_timer = 0;
return interrupt_exec(0x0050);
}
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
status.interrupt_request_serial = 0;
return interrupt_exec(0x0058);
}
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
status.interrupt_request_joypad = 0;
return interrupt_exec(0x0060);
}
}
}
void CPU::interrupt_exec(uint16 pc) {
status.ime = 0;
op_write(--r[SP], r[PC] >> 8);
op_write(--r[SP], r[PC] >> 0);
r[PC] = pc;
op_io();
}
void CPU::power() {
for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM
for(unsigned n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
for(unsigned n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM
for(unsigned n = 0xff00; n <= 0xff0f; n++) bus.mmio[n] = this; //MMIO
for(unsigned n = 0xff80; n <= 0xffff; n++) bus.mmio[n] = this; //HRAM+IE
for(unsigned n = 0; n < 8192; n++) wram[n] = 0x00;
for(unsigned n = 0; n < 128; n++) hram[n] = 0x00;
reset();
}
@ -39,6 +81,34 @@ void CPU::reset() {
r[HL] = 0x0000;
status.ime = 0;
status.timer0 = 0;
status.timer1 = 0;
status.timer2 = 0;
status.timer3 = 0;
status.p15 = 0;
status.p14 = 0;
status.div = 0;
status.tima = 0;
status.tma = 0;
status.timer_enable = 0;
status.timer_clock = 0;
status.interrupt_request_joypad = 0;
status.interrupt_request_serial = 0;
status.interrupt_request_timer = 0;
status.interrupt_request_stat = 0;
status.interrupt_request_vblank = 0;
status.interrupt_enable_joypad = 0;
status.interrupt_enable_serial = 0;
status.interrupt_enable_timer = 0;
status.interrupt_enable_stat = 0;
status.interrupt_enable_vblank = 0;
}
CPU::CPU() {

View File

@ -5,6 +5,41 @@ struct CPU : Processor, MMIO {
struct Status {
bool ime;
unsigned timer0;
unsigned timer1;
unsigned timer2;
unsigned timer3;
//$ff00 JOYP
bool p15;
bool p14;
//$ff04 DIV
uint8 div;
//$ff05 TIMA
uint8 tima;
//$ff06 TMA
uint8 tma;
//$ff07 TAC
bool timer_enable;
unsigned timer_clock;
//$ff0f IF
bool interrupt_request_joypad;
bool interrupt_request_serial;
bool interrupt_request_timer;
bool interrupt_request_stat;
bool interrupt_request_vblank;
//$ffff IE
bool interrupt_enable_joypad;
bool interrupt_enable_serial;
bool interrupt_enable_timer;
bool interrupt_enable_stat;
bool interrupt_enable_vblank;
} status;
uint8 wram[8192];
@ -12,6 +47,8 @@ struct CPU : Processor, MMIO {
static void Main();
void main();
void interrupt_test();
void interrupt_exec(uint16 pc);
void power();
void reset();
CPU();

View File

@ -4,12 +4,122 @@ uint8 CPU::mmio_read(uint16 addr) {
if(addr >= 0xc000 && addr <= 0xdfff) return wram[addr & 0x1fff];
if(addr >= 0xe000 && addr <= 0xfdff) return wram[addr & 0x1fff];
if(addr >= 0xff80 && addr <= 0xfffe) return hram[addr & 0x7f];
if(addr == 0xff00) { //JOYP
unsigned keys = 0x0f;
if(status.p15 == 0 && status.p14 == 1) {
keys = !system.interface->input_poll((unsigned)Input::Down) << 3;
keys |= !system.interface->input_poll((unsigned)Input::Up) << 2;
keys |= !system.interface->input_poll((unsigned)Input::Left) << 1;
keys |= !system.interface->input_poll((unsigned)Input::Right) << 0;
}
if(status.p15 == 1 && status.p14 == 0) {
keys = !system.interface->input_poll((unsigned)Input::Start) << 3;
keys |= !system.interface->input_poll((unsigned)Input::Select) << 2;
keys |= !system.interface->input_poll((unsigned)Input::B) << 1;
keys |= !system.interface->input_poll((unsigned)Input::A) << 0;
}
return (status.p15 << 5)
| (status.p14 << 4)
| (keys << 0);
}
if(addr == 0xff04) { //DIV
return status.div;
}
if(addr == 0xff05) { //TIMA
return status.tima;
}
if(addr == 0xff06) { //TMA
return status.tma;
}
if(addr == 0xff07) { //TAC
return (status.timer_enable << 2)
| (status.timer_clock << 0);
}
if(addr == 0xff0f) { //IF
return (status.interrupt_request_joypad << 4)
| (status.interrupt_request_serial << 3)
| (status.interrupt_request_timer << 2)
| (status.interrupt_request_stat << 1)
| (status.interrupt_request_vblank << 0);
}
if(addr == 0xffff) { //IE
return (status.interrupt_enable_joypad << 4)
| (status.interrupt_enable_serial << 3)
| (status.interrupt_enable_timer << 2)
| (status.interrupt_enable_stat << 1)
| (status.interrupt_enable_vblank << 0);
}
return 0x00;
}
void CPU::mmio_write(uint16 addr, uint8 data) {
if(addr >= 0xc000 && addr <= 0xdfff) { wram[addr & 0x1fff] = data; return; }
if(addr >= 0xe000 && addr <= 0xfdff) { wram[addr & 0x1fff] = data; return; }
if(addr >= 0xff80 && addr <= 0xfffe) { hram[addr & 0x7f] = data; return; }
if(addr == 0xff00) { //JOYP
status.p15 = data & 0x20;
status.p14 = data & 0x10;
return;
}
if(addr == 0xff01) { //SB
return;
}
if(addr == 0xff02) { //SC
return;
}
if(addr == 0xff04) { //DIV
status.div = 0;
return;
}
if(addr == 0xff05) { //TIMA
status.tima = data;
return;
}
if(addr == 0xff06) { //TMA
status.tma = data;
return;
}
if(addr == 0xff07) { //TAC
status.timer_enable = data & 0x04;
status.timer_clock = data & 0x03;
return;
}
if(addr == 0xff0f) { //IF
status.interrupt_request_joypad = data & 0x10;
status.interrupt_request_serial = data & 0x08;
status.interrupt_request_timer = data & 0x04;
status.interrupt_request_stat = data & 0x02;
status.interrupt_request_vblank = data & 0x01;
return;
}
if(addr == 0xffff) { //IE
status.interrupt_enable_joypad = data & 0x10;
status.interrupt_enable_serial = data & 0x08;
status.interrupt_enable_timer = data & 0x04;
status.interrupt_enable_stat = data & 0x02;
status.interrupt_enable_vblank = data & 0x01;
return;
}
}
#endif

View File

@ -3,26 +3,70 @@
// 456 clocks/scanline
// 154 scanlines/frame
//4194304 / 4096 = 1024
//4194304 / 262144 = 16
//4194304 / 65536 = 64
//4394304 / 16384 = 256
#ifdef CPU_CPP
#include "opcode.cpp"
void CPU::add_clocks(unsigned clocks) {
clock += clocks;
status.timer0 += clocks;
if(status.timer0 >= 16) timer_stage0();
if(clock >= 456) scanline();
cpu.clock += clocks;
if(cpu.clock >= 0) co_switch(scheduler.active_thread = lcd.thread);
}
void CPU::scanline() {
clock -= 456;
void CPU::timer_stage0() { //262144hz
if(status.timer_clock == 1) {
if(++status.tima == 0) {
status.tima = status.tma;
status.interrupt_request_timer = 1;
}
}
lcd.status.ly++;
if(lcd.status.ly >= 154) frame();
status.timer0 -= 16;
if(++status.timer1 >= 4) timer_stage1();
}
void CPU::frame() {
lcd.status.ly -= 154;
scheduler.exit();
void CPU::timer_stage1() { // 65536hz
if(status.timer_clock == 2) {
if(++status.tima == 0) {
status.tima = status.tma;
status.interrupt_request_timer = 1;
}
}
status.timer1 -= 4;
if(++status.timer2 >= 4) timer_stage2();
}
void CPU::timer_stage2() { // 16384hz
if(status.timer_clock == 3) {
if(++status.tima == 0) {
status.tima = status.tma;
status.interrupt_request_timer = 1;
}
}
status.div++;
status.timer2 -= 4;
if(++status.timer3 >= 4) timer_stage3();
}
void CPU::timer_stage3() { // 4096hz
if(status.timer_clock == 0) {
if(++status.tima == 0) {
status.tima = status.tma;
status.interrupt_request_timer = 1;
}
}
status.timer3 -= 4;
}
#endif

View File

@ -1,6 +1,8 @@
void add_clocks(unsigned clocks);
void scanline();
void frame();
void timer_stage0();
void timer_stage1();
void timer_stage2();
void timer_stage3();
//opcode.cpp
void op_io();

View File

@ -5,7 +5,7 @@
namespace GameBoy {
namespace Info {
static const char Name[] = "bgameboy";
static const char Version[] = "000.03";
static const char Version[] = "000.04";
}
}

View File

@ -6,16 +6,120 @@ namespace GameBoy {
#include "mmio/mmio.cpp"
LCD lcd;
void LCD::Main() {
lcd.main();
}
void LCD::main() {
while(true) {
add_clocks(4);
}
}
void LCD::add_clocks(unsigned clocks) {
status.lx += clocks;
if(status.lx >= 456) scanline();
cpu.clock -= clocks;
if(cpu.clock <= 0) co_switch(scheduler.active_thread = cpu.thread);
}
void LCD::scanline() {
status.lx -= 456;
status.ly++;
if(status.ly == 144) cpu.status.interrupt_request_vblank = 1;
//print("Vblank - ", cpu.status.ime, " - ", cpu.status.interrupt_enable_vblank, "\n"); }
if(status.ly == 154) frame();
if(status.ly < 144) render();
}
void LCD::frame() {
system.interface->video_refresh(screen);
system.interface->input_poll();
status.ly = 0;
scheduler.exit();
}
void LCD::render() {
uint8_t *output = screen + status.ly * 160;
uint8 y = status.ly + status.scy;
uint16 tmaddr = (status.bg_tilemap_select == 0 ? 0x1800 : 0x1c00);
tmaddr += (y >> 3) * 32;
tmaddr += (status.scx >> 3);
for(unsigned t = 0; t < 20; t++) {
unsigned tdaddr;
if(status.bg_tiledata_select == 0) {
tdaddr = 0x1000 + (int8)vram[tmaddr + t] * 16;
} else {
tdaddr = 0x0000 + vram[tmaddr + t] * 16;
}
tdaddr += (status.ly & 7) * 2;
uint8 d0 = vram[tdaddr + 0];
uint8 d1 = vram[tdaddr + 1];
for(unsigned x = 0; x < 8; x++) {
uint8 palette = ((d0 & 0x80) >> 7) + ((d1 & 0x80) >> 6);
d0 <<= 1, d1 <<= 1;
*output++ = (3 - status.bgp[palette]) * 0x55;
}
}
}
void LCD::power() {
for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = this; //VRAM
for(unsigned n = 0xff40; n <= 0xff4f; n++) bus.mmio[n] = this; //MMIO
for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM
for(unsigned n = 0xff40; n <= 0xff4b; n++) bus.mmio[n] = this; //MMIO
for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM
for(unsigned n = 0; n < 8192; n++) vram[n] = 0x00;
for(unsigned n = 0; n < 160; n++) oam [n] = 0x00;
reset();
}
void LCD::reset() {
create(Main, 4 * 1024 * 1024);
for(unsigned n = 0; n < 160 * 144; n++) screen[n] = 0x00;
status.lx = 0;
status.display_enable = 0;
status.window_tilemap_select = 0;
status.window_display_enable = 0;
status.bg_tiledata_select = 0;
status.bg_tilemap_select = 0;
status.obj_size = 0;
status.obj_enable = 0;
status.bg_display = 0;
status.interrupt_lyc = 0;
status.interrupt_oam = 0;
status.interrupt_vblank = 0;
status.interrupt_hblank = 0;
status.coincidence = 0;
status.mode = 0;
status.scy = 0;
status.scx = 0;
status.ly = 0;
status.lyc = 0;
for(unsigned n = 0; n < 4; n++) {
status.bgp[n] = n;
status.obp0[n] = n;
status.obp1[n] = n;
}
status.wy = 0;
status.wx = 0;
}
}

View File

@ -2,12 +2,65 @@ struct LCD : Processor, MMIO {
#include "mmio/mmio.hpp"
struct Status {
unsigned ly;
unsigned lx;
//$ff40 LCDC
bool display_enable;
bool window_tilemap_select;
bool window_display_enable;
bool bg_tiledata_select;
bool bg_tilemap_select;
bool obj_size;
bool obj_enable;
bool bg_display;
//$ff41 STAT
bool interrupt_lyc;
bool interrupt_oam;
bool interrupt_vblank;
bool interrupt_hblank;
bool coincidence;
unsigned mode;
//$ff42 SCY
uint8 scy;
//$ff43 SCX
uint8 scx;
//$ff44 LY
uint8 ly;
//$ff45 LYC
uint8 lyc;
//$ff47 BGP
uint8 bgp[4];
//$ff48 OBP0
uint8 obp0[4];
//$ff49 OBP1
uint8 obp1[4];
//$ff4a WY
uint8 wy;
//$ff4b WX
uint8 wx;
} status;
uint8 screen[160 * 144];
uint8 vram[8192];
uint8 oam[160];
static void Main();
void main();
void add_clocks(unsigned clocks);
void scanline();
void frame();
void render();
void power();
void reset();
};

View File

@ -1,26 +1,159 @@
#ifdef LCD_CPP
uint8 LCD::mmio_read(uint16 addr) {
if(addr >= 0xa000 && addr <= 0xbfff) return vram[addr & 0x1fff];
if(addr >= 0x8000 && addr <= 0x9fff) return vram[addr & 0x1fff];
if(addr >= 0xfe00 && addr <= 0xfe9f) return oam[addr & 0xff];
//LY
if(addr == 0xff44) {
if(addr == 0xff40) { //LCDC
return (status.display_enable << 7)
| (status.window_tilemap_select << 6)
| (status.window_display_enable << 5)
| (status.bg_tiledata_select << 4)
| (status.bg_tilemap_select << 3)
| (status.obj_size << 2)
| (status.obj_enable << 1)
| (status.bg_display << 0);
}
if(addr == 0xff41) { //STAT
return (status.interrupt_lyc << 6)
| (status.interrupt_oam << 5)
| (status.interrupt_vblank << 4)
| (status.interrupt_hblank << 3)
| (status.coincidence << 2)
| (status.mode << 0);
}
if(addr == 0xff42) { //SCY
return status.scy;
}
if(addr == 0xff43) { //SCX
return status.scx;
}
if(addr == 0xff44) { //LY
return status.ly;
}
if(addr == 0xff45) { //LYC
return status.lyc;
}
if(addr == 0xff47) { //BGP
return (status.bgp[3] << 6)
| (status.bgp[2] << 4)
| (status.bgp[1] << 2)
| (status.bgp[0] << 0);
}
if(addr == 0xff48) { //OBP0
return (status.obp0[3] << 6)
| (status.obp0[2] << 4)
| (status.obp0[1] << 2)
| (status.obp0[0] << 0);
}
if(addr == 0xff49) { //OBP1
return (status.obp1[3] << 6)
| (status.obp1[2] << 4)
| (status.obp1[1] << 2)
| (status.obp1[0] << 0);
}
if(addr == 0xff4a) { //WY
return status.wy;
}
if(addr == 0xff4b) { //WX
return status.wx;
}
return 0x00;
}
void LCD::mmio_write(uint16 addr, uint8 data) {
if(addr >= 0xa000 && addr <= 0xbfff) { vram[addr & 0x1fff] = data; return; }
if(addr >= 0x8000 && addr <= 0x9fff) { vram[addr & 0x1fff] = data; return; }
if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; }
//LY
if(addr == 0xff44) {
if(addr == 0xff40) { //LCDC
status.display_enable = data & 0x80;
status.window_tilemap_select = data & 0x40;
status.window_display_enable = data & 0x20;
status.bg_tiledata_select = data & 0x10;
status.bg_tilemap_select = data & 0x08;
status.obj_size = data & 0x04;
status.obj_enable = data & 0x02;
status.bg_display = data & 0x01;
return;
}
if(addr == 0xff41) { //STAT
status.interrupt_lyc = data & 0x40;
status.interrupt_oam = data & 0x20;
status.interrupt_vblank = data & 0x10;
status.interrupt_hblank = data & 0x08;
return;
}
if(addr == 0xff42) { //SCY
status.scy = data;
return;
}
if(addr == 0xff43) { //SCX
status.scx = data;
return;
}
if(addr == 0xff44) { //LY
status.ly = 0;
return;
}
if(addr == 0xff45) { //LYC
status.lyc = data;
return;
}
if(addr == 0xff46) { //DMA
//TODO
return;
}
if(addr == 0xff47) { //BGP
status.bgp[3] = (data >> 6) & 3;
status.bgp[2] = (data >> 4) & 3;
status.bgp[1] = (data >> 2) & 3;
status.bgp[0] = (data >> 0) & 3;
return;
}
if(addr == 0xff48) { //OBP0
status.obp0[3] = (data >> 6) & 3;
status.obp0[2] = (data >> 4) & 3;
status.obp0[1] = (data >> 2) & 3;
status.obp0[0] = (data >> 0) & 3;
return;
}
if(addr == 0xff49) { //OBP1
status.obp1[3] = (data >> 6) & 3;
status.obp1[2] = (data >> 4) & 3;
status.obp1[1] = (data >> 2) & 3;
status.obp1[0] = (data >> 0) & 3;
return;
}
if(addr == 0xff4a) { //WY
status.wy = data;
return;
}
if(addr == 0xff4b) { //WX
status.wx = data;
return;
}
}
#endif

View File

@ -1,5 +1,9 @@
class Interface;
enum class Input : unsigned {
Up, Down, Left, Right, B, A, Select, Start,
};
class System {
public:
void init(Interface*);

View File

@ -4,6 +4,9 @@
#include <nall/string.hpp>
using namespace nall;
#include <ruby/ruby.hpp>
using namespace ruby;
#include <phoenix/phoenix.hpp>
using namespace phoenix;
@ -18,6 +21,10 @@ using namespace phoenix;
struct Application {
bool quit;
Font proportionalFont;
Font proportionalFontBold;
Font monospaceFont;
void main(int argc, char **argv);
};

View File

@ -1,7 +1,9 @@
MainWindow mainWindow;
void MainWindow::create() {
Window::create(128, 128, 160 * 3, 144 * 3, { GameBoy::Info::Name, " v", GameBoy::Info::Version });
Window::create(128, 128, 160 * 2, 144 * 2, { GameBoy::Info::Name, " v", GameBoy::Info::Version });
setDefaultFont(application.proportionalFont);
setFont(application.proportionalFontBold);
system.create(*this, "System");
systemLoadCartridge.create(system, "Load Cartridge ...");
@ -12,15 +14,15 @@ void MainWindow::create() {
systemReset.setEnabled(false);
settings.create(*this, "Settings");
settings.setEnabled(false);
//settings.setEnabled(false);
tools.create(*this, "Tools");
tools.setEnabled(false);
//tools.setEnabled(false);
help.create(*this, "Help");
helpAbout.create(help, "About ...");
viewport.create(*this, 0, 0, 160 * 3, 144 * 3);
viewport.create(*this, 0, 0, 160 * 2, 144 * 2);
setMenuVisible(true);
setStatusVisible(true);

View File

@ -1,15 +1,52 @@
Interface interface;
void Interface::video_refresh(const uint8_t *data) {
uint32_t *buffer;
unsigned pitch;
if(video.lock(buffer, pitch, 160, 144)) {
for(unsigned y = 0; y < 144; y++) {
uint32_t *line = buffer + y * (pitch >> 2);
const uint8_t *source = data + y * 160;
for(unsigned x = 0; x < 160; x++) {
uint32_t color = *source++;
*line++ = (color << 16) | (color << 8) | (color << 0);
}
}
video.unlock();
video.refresh();
}
static unsigned frameCounter = 0;
static time_t timeCounter = time(0);
frameCounter++;
time_t currentTime = time(0);
if(currentTime != timeCounter) {
timeCounter = currentTime;
mainWindow.setStatusText({ "FPS: ", frameCounter });
frameCounter = 0;
}
}
void Interface::audio_sample(signed left, signed right) {
}
void Interface::input_poll() {
input.poll(inputState);
}
bool Interface::input_poll(unsigned id) {
switch(id) {
case GameBoy::Input::Up: return inputState[keyboard(0)[Keyboard::Up]];
case GameBoy::Input::Down: return inputState[keyboard(0)[Keyboard::Down]];
case GameBoy::Input::Left: return inputState[keyboard(0)[Keyboard::Left]];
case GameBoy::Input::Right: return inputState[keyboard(0)[Keyboard::Right]];
case GameBoy::Input::B: return inputState[keyboard(0)[Keyboard::Z]];
case GameBoy::Input::A: return inputState[keyboard(0)[Keyboard::X]];
case GameBoy::Input::Select: return inputState[keyboard(0)[Keyboard::Apostrophe]];
case GameBoy::Input::Start: return inputState[keyboard(0)[Keyboard::Return]];
}
return false;
}

View File

@ -1,4 +1,6 @@
struct Interface : public GameBoy::Interface {
int16_t inputState[Scancode::Limit];
void video_refresh(const uint8_t *data);
void audio_sample(signed left, signed right);
void input_poll();

View File

@ -8,34 +8,42 @@ Application application;
void Application::main(int argc, char **argv) {
quit = false;
mainWindow.create();
#if defined(PHOENIX_WINDOWS)
proportionalFont.create("Tahoma", 8);
proportionalFontBold.create("Tahoma", 8, Font::Style::Bold);
monospaceFont.create("Courier New", 8);
#else
proportionalFont.create("Sans", 8);
proportionalFontBold.create("Sans", 8, Font::Style::Bold);
monospaceFont.create("Liberation Mono", 8);
#endif
mainWindow.create();
mainWindow.setVisible();
OS::run();
video.driver("OpenGL");
video.set(Video::Handle, (uintptr_t)mainWindow.viewport.handle());
video.set(Video::Synchronize, false);
video.set(Video::Filter, (unsigned)0);
video.init();
input.driver("SDL");
input.set(Input::Handle, (uintptr_t)mainWindow.viewport.handle());
input.init();
GameBoy::system.init(&interface);
unsigned frameCounter = 0;
time_t timeCounter = time(0);
while(quit == false) {
OS::run();
if(GameBoy::cartridge.loaded()) {
GameBoy::system.run();
frameCounter++;
time_t currentTime = time(0);
if(currentTime != timeCounter) {
timeCounter = currentTime;
mainWindow.setStatusText({ "FPS: ", frameCounter });
frameCounter = 0;
}
}
}
}
int main(int argc, char **argv) {
application.main(argc, argv);
return 0;
}