Update to release v000r07.

byuu says:

Changelog:
- fixed sprite Vflip check
- fixed up window rendering (well, mostly, works great in Megaman II but
  not so great in Makaitoushi SaGa)
- added MBC2, MBC5 (already had MBC0, MBC1)
- removed reset, hooked up power cycle and Vsync toggle
- some other stuff

Makaitoushi SaGa locks on the main menu after some graphical glitches on
the title screen, damn.
Shin Megami Tensei - Devichil Black Book locks up immediately, hitting
HALT opcodes all the time, damn again.

Megaman II should be fully playable now.
Contra 3 is really close, but goes crazy on the turtle boss fight.
This commit is contained in:
Tim Allen
2011-01-03 15:28:36 +11:00
parent ebd6a52811
commit afdb3c4d20
24 changed files with 239 additions and 142 deletions

View File

@@ -5,7 +5,7 @@ ui := ui
# compiler # compiler
c := $(compiler) -std=gnu99 c := $(compiler) -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
flags := -O3 -fomit-frame-pointer -I. -I$(gameboy) flags := -O3 -fomit-frame-pointer -I.
link := link :=
objects := objects :=

View File

@@ -1,10 +1,12 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define CARTRIDGE_CPP #define CARTRIDGE_CPP
namespace GameBoy { namespace GameBoy {
#include "mbc0/mbc0.cpp" #include "mbc0/mbc0.cpp"
#include "mbc1/mbc1.cpp" #include "mbc1/mbc1.cpp"
#include "mbc2/mbc2.cpp"
#include "mbc5/mbc5.cpp"
Cartridge cartridge; Cartridge cartridge;
void Cartridge::load(uint8_t *data, unsigned size) { void Cartridge::load(uint8_t *data, unsigned size) {
@@ -25,11 +27,20 @@ void Cartridge::load(uint8_t *data, unsigned size) {
info.battery = false; info.battery = false;
info.rtc = false; info.rtc = false;
switch(romdata[0x0147]) { default: switch(romdata[0x0147]) {
case 0x00: info.mapper = Mapper::MBC0; break; case 0x00: info.mapper = Mapper::MBC0; break;
case 0x01: info.mapper = Mapper::MBC1; break; case 0x01: info.mapper = Mapper::MBC1; break;
case 0x02: info.mapper = Mapper::MBC1; info.ram = true; break; case 0x02: info.mapper = Mapper::MBC1; info.ram = true; break;
case 0x03: info.mapper = Mapper::MBC1; info.ram = true; info.battery = true; break; case 0x03: info.mapper = Mapper::MBC1; info.ram = true; info.battery = true; break;
case 0x05: info.mapper = Mapper::MBC2; info.ram = true; break;
case 0x06: info.mapper = Mapper::MBC2; info.ram = true; info.battery = true; break;
case 0x19: info.mapper = Mapper::MBC5; break;
case 0x1a: info.mapper = Mapper::MBC5; info.ram = true; break;
case 0x1b: info.mapper = Mapper::MBC5; info.ram = true; info.battery = true; break;
case 0x1c: info.mapper = Mapper::MBC5; info.rumble = true; break;
case 0x1d: info.mapper = Mapper::MBC5; info.rumble = true; info.ram = true; break;
case 0x1e: info.mapper = Mapper::MBC5; info.rumble = true; info.ram = true; info.battery = true; break;
default: print("Unknown mapper: ", hex<2>(romdata[0x0147]), "\n"); break;
} }
switch(romdata[0x0148]) { default: switch(romdata[0x0148]) { default:
@@ -46,7 +57,6 @@ void Cartridge::load(uint8_t *data, unsigned size) {
case 0x54: info.romsize = 96 * 16 * 1024; break; case 0x54: info.romsize = 96 * 16 * 1024; break;
} }
//TODO: MBC2 always stores 0x00 here; yet it has 512x4-bits RAM
switch(romdata[0x0149]) { default: switch(romdata[0x0149]) { default:
case 0x00: info.ramsize = 0 * 1024; break; case 0x00: info.ramsize = 0 * 1024; break;
case 0x01: info.ramsize = 2 * 1024; break; case 0x01: info.ramsize = 2 * 1024; break;
@@ -54,6 +64,8 @@ void Cartridge::load(uint8_t *data, unsigned size) {
case 0x03: info.ramsize = 32 * 1024; break; case 0x03: info.ramsize = 32 * 1024; break;
} }
if(info.mapper == Mapper::MBC2) info.ramsize = 256; //512 x 4-bit
ramdata = new uint8_t[ramsize = info.ramsize](); ramdata = new uint8_t[ramsize = info.ramsize]();
loaded = true; loaded = true;
@@ -92,23 +104,21 @@ void Cartridge::ram_write(unsigned addr, uint8 data) {
void Cartridge::power() { void Cartridge::power() {
mbc0.power(); mbc0.power();
mbc1.power(); mbc1.power();
mbc2.power();
mbc5.power();
MMIO *mapper = 0; MMIO *mapper = 0;
switch(info.mapper) { switch(info.mapper) { default:
case Mapper::MBC0: mapper = &mbc0; break; case Mapper::MBC0: mapper = &mbc0; break;
case Mapper::MBC1: mapper = &mbc1; break; case Mapper::MBC1: mapper = &mbc1; break;
case Mapper::MBC2: mapper = &mbc2; break;
case Mapper::MBC5: mapper = &mbc5; break;
} }
if(mapper) { if(mapper) {
for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = mapper; for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = mapper;
for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = mapper; for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = mapper;
} }
reset();
}
void Cartridge::reset() {
mbc1.reset();
mbc1.reset();
} }
Cartridge::Cartridge() { Cartridge::Cartridge() {

View File

@@ -1,22 +1,27 @@
struct Cartridge : property<Cartridge> { struct Cartridge : property<Cartridge> {
#include "mbc0/mbc0.hpp" #include "mbc0/mbc0.hpp"
#include "mbc1/mbc1.hpp" #include "mbc1/mbc1.hpp"
#include "mbc2/mbc2.hpp"
#include "mbc5/mbc5.hpp"
enum Mapper : unsigned { enum Mapper : unsigned {
MBC0, MBC0,
MBC1, MBC1,
MBC2,
MBC5,
Unknown, Unknown,
}; };
struct Information { struct Information {
string name; string name;
uint8 cgbflag; uint8 cgbflag;
uint8 sgbflag; uint8 sgbflag;
Mapper mapper; Mapper mapper;
bool ram; bool ram;
bool battery; bool battery;
bool rtc; bool rtc;
bool rumble;
unsigned romsize; unsigned romsize;
unsigned ramsize; unsigned ramsize;
@@ -39,7 +44,6 @@ struct Cartridge : property<Cartridge> {
void ram_write(unsigned addr, uint8 data); void ram_write(unsigned addr, uint8 data);
void power(); void power();
void reset();
Cartridge(); Cartridge();
~Cartridge(); ~Cartridge();

View File

@@ -11,7 +11,4 @@ void Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) {
void Cartridge::MBC0::power() { void Cartridge::MBC0::power() {
} }
void Cartridge::MBC0::reset() {
}
#endif #endif

View File

@@ -2,5 +2,4 @@ struct MBC0 : MMIO {
uint8 mmio_read(uint16 addr); uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data); void mmio_write(uint16 addr, uint8 data);
void power(); void power();
void reset();
} mbc0; } mbc0;

View File

@@ -47,9 +47,6 @@ void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) {
} }
void Cartridge::MBC1::power() { void Cartridge::MBC1::power() {
}
void Cartridge::MBC1::reset() {
ram_enable = false; ram_enable = false;
rom_select = 0x01; rom_select = 0x01;
ram_select = 0x00; ram_select = 0x00;

View File

@@ -10,5 +10,4 @@ struct MBC1 : MMIO {
uint8 mmio_read(uint16 addr); uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data); void mmio_write(uint16 addr, uint8 data);
void power(); void power();
void reset();
} mbc1; } mbc1;

55
gameboy/cartridge/mbc2/mbc2.cpp Executable file
View File

@@ -0,0 +1,55 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC2::mmio_read(uint16 addr) {
if(addr >= 0x0000 && addr <= 0x3fff) {
return cartridge.rom_read(addr);
}
if(addr >= 0x4000 && addr <= 0x7fff) {
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
}
if(addr >= 0xa000 && addr <= 0xa1ff) {
if(ram_enable) {
uint8 data = cartridge.ram_read(addr & 0x1ff);
return (addr & 1) == 0 ? ((data >> 4) & 0x0f) : ((data >> 0) & 0x0f);
}
return 0x00;
}
return 0x00;
}
void Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) {
if(addr >= 0x0000 && addr <= 0x1fff) {
if((addr & 0x100) == 0) {
ram_enable = (data & 0x0f) == 0x0a;
}
}
if(addr >= 0x2000 && addr <= 0x3fff) {
if(addr & 0x100) {
rom_select = data & 0x0f;
if(rom_select == 0) rom_select = 1;
}
}
if(addr >= 0xa000 && addr <= 0xa1ff) {
if(ram_enable) {
addr &= 511;
if((addr & 1) == 0) {
cartridge.ram_write(addr, (cartridge.ram_read(addr) & 0x0f) | (data << 4));
} else {
cartridge.ram_write(addr, (cartridge.ram_read(addr) & 0xf0) | (data << 0));
}
return;
}
}
}
void Cartridge::MBC2::power() {
ram_enable = false;
rom_select = 0x01;
}
#endif

View File

@@ -0,0 +1,8 @@
struct MBC2 : MMIO {
bool ram_enable; //0000-1fff
uint8 rom_select; //2000-3fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mbc2;

52
gameboy/cartridge/mbc5/mbc5.cpp Executable file
View File

@@ -0,0 +1,52 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC5::mmio_read(uint16 addr) {
if(addr >= 0x0000 && addr <= 0x3fff) {
return cartridge.rom_read(addr);
}
if(addr >= 0x4000 && addr <= 0x7fff) {
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
}
if(addr >= 0xa000 && addr <= 0xbfff) {
if(ram_enable) {
return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
}
return 0x00;
}
return 0x00;
}
void Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) {
if(addr >= 0x0000 && addr <= 0x1fff) {
ram_enable = (data & 0x0f) == 0x0a;
}
if(addr >= 0x2000 && addr <= 0x2fff) {
rom_select = (rom_select & 0x0100) | data;
}
if(addr >= 0x3000 && addr <= 0x3fff) {
rom_select = ((data & 1) << 8) | (rom_select & 0x00ff);
}
if(addr >= 0x4000 && addr <= 0x5fff) {
ram_select = data & 0x0f;
}
if(addr >= 0xa000 && addr <= 0xbfff) {
if(ram_enable) {
cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
}
}
}
void Cartridge::MBC5::power() {
ram_enable = false;
rom_select = 0x001;
ram_select = 0x00;
}
#endif

View File

@@ -0,0 +1,9 @@
struct MBC5 : MMIO {
bool ram_enable; //0000-1fff
uint16 rom_select; //2000-2fff + 3000-3fff
uint8 ram_select; //4000-5fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mbc5;

View File

@@ -1,4 +1,4 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define CPU_CPP #define CPU_CPP
namespace GameBoy { namespace GameBoy {
@@ -67,9 +67,13 @@ void CPU::interrupt_exec(uint16 pc) {
op_write(--r[SP], r[PC] >> 0); op_write(--r[SP], r[PC] >> 0);
r[PC] = pc; r[PC] = pc;
op_io(); op_io();
op_io();
op_io();
} }
void CPU::power() { void CPU::power() {
create(Main, 4 * 1024 * 1024);
for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM 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 = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
for(unsigned n = 0xff00; n <= 0xff0f; n++) bus.mmio[n] = this; //MMIO for(unsigned n = 0xff00; n <= 0xff0f; n++) bus.mmio[n] = this; //MMIO
@@ -78,15 +82,9 @@ void CPU::power() {
for(unsigned n = 0; n < 8192; n++) wram[n] = 0x00; for(unsigned n = 0; n < 8192; n++) wram[n] = 0x00;
for(unsigned n = 0; n < 128; n++) hram[n] = 0x00; for(unsigned n = 0; n < 128; n++) hram[n] = 0x00;
reset();
}
void CPU::reset() {
create(Main, 4 * 1024 * 1024);
r[PC] = 0x0100; r[PC] = 0x0100;
r[SP] = 0xfffe; r[SP] = 0xfffe;
r[AF] = 0x0000; r[AF] = 0x0100;
r[BC] = 0x0000; r[BC] = 0x0000;
r[DE] = 0x0000; r[DE] = 0x0000;
r[HL] = 0x0000; r[HL] = 0x0000;

View File

@@ -63,7 +63,6 @@ struct CPU : Processor, MMIO {
void interrupt_test(); void interrupt_test();
void interrupt_exec(uint16 pc); void interrupt_exec(uint16 pc);
void power(); void power();
void reset();
CPU(); CPU();
}; };

View File

@@ -5,7 +5,7 @@
namespace GameBoy { namespace GameBoy {
namespace Info { namespace Info {
static const char Name[] = "bgameboy"; static const char Name[] = "bgameboy";
static const char Version[] = "000.06"; static const char Version[] = "000.07";
} }
} }
@@ -43,10 +43,10 @@ namespace GameBoy {
inline Processor() : thread(0) {} inline Processor() : thread(0) {}
}; };
#include <system/system.hpp> #include <gameboy/system/system.hpp>
#include <scheduler/scheduler.hpp> #include <gameboy/scheduler/scheduler.hpp>
#include <memory/memory.hpp> #include <gameboy/memory/memory.hpp>
#include <cartridge/cartridge.hpp> #include <gameboy/cartridge/cartridge.hpp>
#include <cpu/cpu.hpp> #include <gameboy/cpu/cpu.hpp>
#include <lcd/lcd.hpp> #include <gameboy/lcd/lcd.hpp>
}; };

View File

@@ -1,4 +1,4 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define LCD_CPP #define LCD_CPP
namespace GameBoy { namespace GameBoy {
@@ -55,93 +55,66 @@ void LCD::frame() {
} }
void LCD::render() { void LCD::render() {
for(unsigned n = 0; n < 160; n++) { for(unsigned n = 0; n < 160; n++) line[n] = 0x00;
line[n].source = Line::Source::None;
line[n].output = 0;
}
if(status.display_enable == true) { if(status.display_enable == true) {
if(status.bg_enable == true) render_bg(); if(status.bg_enable == true) render_bg();
if(status.obj_enable == true) render_obj();
if(status.window_display_enable == true) render_window(); if(status.window_display_enable == true) render_window();
if(status.obj_enable == true) render_obj();
} }
uint8_t *output = screen + status.ly * 160; uint8_t *output = screen + status.ly * 160;
for(unsigned n = 0; n < 160; n++) { for(unsigned n = 0; n < 160; n++) output[n] = (3 - line[n]) * 0x55;
output[n] = (3 - line[n].output) * 0x55; }
uint16 LCD::read_tile(bool select, unsigned x, unsigned y) {
unsigned tmaddr = 0x1800 + (select << 10), tdaddr;
tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff;
if(status.bg_tiledata_select == 0) {
tdaddr = 0x1000 + ((int8)vram[tmaddr] << 4);
} else {
tdaddr = 0x0000 + (vram[tmaddr] << 4);
} }
tdaddr += (y & 7) << 1;
return (vram[tdaddr + 0] << 0) | (vram[tdaddr + 1] << 8);
} }
void LCD::render_bg() { void LCD::render_bg() {
unsigned iy = (status.ly + status.scy) & 255; unsigned iy = (status.ly + status.scy) & 255;
unsigned ix = status.scx; unsigned ix = status.scx, tx = ix & 7;
uint8 mask = 0x80 >> tx;
unsigned data = read_tile(status.bg_tilemap_select, ix, iy), palette;
unsigned tmaddr = (status.bg_tilemap_select == 0 ? 0x1800 : 0x1c00); for(unsigned ox = 0; ox < 160; ox++) {
palette = ((data & (mask << 0)) ? 1 : 0);
unsigned tx = (ix - 7) & 7; palette |= ((data & (mask << 8)) ? 2 : 0);
uint8 d0 = 0, d1 = 0; mask = (mask >> 1) | (mask << 7);
for(signed ox = -7; ox < 160; ox++) { line[ox] = status.bgp[palette];
if(tx == 0) {
unsigned tile = (((iy >> 3) * 32) + (ix >> 3)) & 0x3fff;
unsigned tdaddr;
if(status.bg_tiledata_select == 0) {
tdaddr = 0x1000 + (int8)vram[tmaddr + tile] * 16;
} else {
tdaddr = 0x0000 + vram[tmaddr + tile] * 16;
}
tdaddr += (iy & 7) * 2;
d0 = vram[tdaddr + 0];
d1 = vram[tdaddr + 1];
}
uint8 palette = ((d0 & 0x80) >> 7) + ((d1 & 0x80) >> 6);
d0 <<= 1, d1 <<= 1;
if(ox >= 0) {
line[ox].source = Line::Source::BG;
line[ox].output = status.bgp[palette];
}
ix = (ix + 1) & 255; ix = (ix + 1) & 255;
tx = (tx + 1) & 7; tx = (tx + 1) & 7;
if(tx == 0) data = read_tile(status.bg_tilemap_select, ix, iy);
} }
} }
void LCD::render_window() { void LCD::render_window() {
if(status.wy > status.ly) return; if(status.ly - status.wy >= 144U) return;
unsigned iy = (status.ly + status.wy) & 255; unsigned iy = status.ly - status.wy;
unsigned ix = (status.wx - 7) & 255; unsigned ix = (status.wx - 7) & 255, tx = ix & 7;
uint8 mask = 0x80 >> tx;
unsigned data = read_tile(status.window_tilemap_select, ix, iy), palette;
unsigned tmaddr = (status.window_tilemap_select == 0 ? 0x1800 : 0x1c00); for(unsigned ox = 0; ox < 160; ox++) {
palette = ((data & (mask << 0)) ? 1 : 0);
unsigned tx = (ix - 7) & 7; palette |= ((data & (mask << 8)) ? 2 : 0);
uint8 d0 = 0, d1 = 0; mask = (mask >> 1) | (mask << 7);
for(signed ox = -7; ox < 160; ox++) { if(ox - (status.wx - 7) < 160U) line[ox] = status.bgp[palette];
if(tx == 0) {
unsigned tile = (((iy >> 3) * 32) + (ix >> 3)) & 0x3fff;
unsigned tdaddr;
if(status.bg_tiledata_select == 0) {
tdaddr = 0x1000 + (int8)vram[tmaddr + tile] * 16;
} else {
tdaddr = 0x0000 + vram[tmaddr + tile] * 16;
}
tdaddr += (iy & 7) * 2;
d0 = vram[tdaddr + 0];
d1 = vram[tdaddr + 1];
}
uint8 palette = ((d0 & 0x80) >> 7) + ((d1 & 0x80) >> 6);
d0 <<= 1, d1 <<= 1;
if(ox >= 7) {
line[ox].source = Line::Source::Window;
line[ox].output = status.bgp[palette];
}
ix = (ix + 1) & 255; ix = (ix + 1) & 255;
tx = (tx + 1) & 7; tx = (tx + 1) & 7;
if(tx == 0) data = read_tile(status.window_tilemap_select, ix, iy);
} }
} }
@@ -173,17 +146,18 @@ void LCD::render_obj() {
unsigned ox = sx + (tx ^ xflip); unsigned ox = sx + (tx ^ xflip);
if(ox <= 159) { if(ox <= 159) {
if((attribute & 0x80) == 1) { if(attribute & 0x80) {
if(line[ox].source == Line::Source::BG && line[ox].output > 0) continue; if(line[ox] > 0) continue;
} }
line[ox].source = Line::Source::OBJ; line[ox] = palette;
line[ox].output = palette;
} }
} }
} }
} }
void LCD::power() { void LCD::power() {
create(Main, 4 * 1024 * 1024);
for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM 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 = 0xff40; n <= 0xff4b; n++) bus.mmio[n] = this; //MMIO
for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM
@@ -191,11 +165,6 @@ void LCD::power() {
for(unsigned n = 0; n < 8192; n++) vram[n] = 0x00; for(unsigned n = 0; n < 8192; n++) vram[n] = 0x00;
for(unsigned n = 0; n < 160; n++) oam [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; for(unsigned n = 0; n < 160 * 144; n++) screen[n] = 0x00;
status.lx = 0; status.lx = 0;

View File

@@ -49,11 +49,7 @@ struct LCD : Processor, MMIO {
uint8 screen[160 * 144]; uint8 screen[160 * 144];
uint8 vram[8192]; uint8 vram[8192];
uint8 oam[160]; uint8 oam[160];
uint8 line[160];
struct Line {
enum class Source : unsigned { None, BG, OBJ, Window } source;
uint8 output;
} line[160];
static void Main(); static void Main();
void main(); void main();
@@ -61,12 +57,12 @@ struct LCD : Processor, MMIO {
void scanline(); void scanline();
void frame(); void frame();
void render(); void render();
uint16 read_tile(bool select, unsigned x, unsigned y);
void render_bg(); void render_bg();
void render_window(); void render_window();
void render_obj(); void render_obj();
void power(); void power();
void reset();
}; };
extern LCD lcd; extern LCD lcd;

View File

@@ -1,4 +1,4 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define MEMORY_CPP #define MEMORY_CPP
namespace GameBoy { namespace GameBoy {

View File

@@ -1,4 +1,4 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define SCHEDULER_CPP #define SCHEDULER_CPP
namespace GameBoy { namespace GameBoy {

View File

@@ -1,4 +1,4 @@
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#define SYSTEM_CPP #define SYSTEM_CPP
namespace GameBoy { namespace GameBoy {
@@ -17,14 +17,6 @@ void System::power() {
scheduler.init(); scheduler.init();
} }
void System::reset() {
bus.reset();
cartridge.power();
cpu.reset();
lcd.reset();
scheduler.init();
}
void System::run() { void System::run() {
scheduler.enter(); scheduler.enter();
} }

View File

@@ -8,13 +8,12 @@ class System {
public: public:
void init(Interface*); void init(Interface*);
void power(); void power();
void reset();
void run(); void run();
//private: //private:
Interface *interface; Interface *interface;
}; };
#include <interface/interface.hpp> #include <gameboy/interface/interface.hpp>
extern System system; extern System system;

View File

@@ -10,7 +10,7 @@ using namespace ruby;
#include <phoenix/phoenix.hpp> #include <phoenix/phoenix.hpp>
using namespace phoenix; using namespace phoenix;
#include <gameboy.hpp> #include <gameboy/gameboy.hpp>
#include "interface.hpp" #include "interface.hpp"

View File

@@ -9,12 +9,10 @@ void MainWindow::create() {
systemLoadCartridge.create(system, "Load Cartridge ..."); systemLoadCartridge.create(system, "Load Cartridge ...");
systemSeparator1.create(system); systemSeparator1.create(system);
systemPower.create(system, "Power Cycle"); systemPower.create(system, "Power Cycle");
systemPower.setEnabled(false);
systemReset.create(system, "Reset");
systemReset.setEnabled(false);
settings.create(*this, "Settings"); settings.create(*this, "Settings");
//settings.setEnabled(false); settingsVideoSync.create(settings, "Synchronize Video");
settingsVideoSync.setChecked(true);
tools.create(*this, "Tools"); tools.create(*this, "Tools");
//tools.setEnabled(false); //tools.setEnabled(false);
@@ -37,6 +35,14 @@ void MainWindow::create() {
if(filename != "") utility.loadCartridge(filename); if(filename != "") utility.loadCartridge(filename);
}; };
systemPower.onTick = []() {
if(GameBoy::cartridge.loaded()) GameBoy::system.power();
};
settingsVideoSync.onTick = []() {
video.set(Video::Synchronize, mainWindow.settingsVideoSync.checked());
};
helpAbout.onTick = []() { helpAbout.onTick = []() {
MessageWindow::information(mainWindow, { MessageWindow::information(mainWindow, {
"bgameboy\n\n", "bgameboy\n\n",

View File

@@ -3,9 +3,9 @@ struct MainWindow : Window {
MenuItem systemLoadCartridge; MenuItem systemLoadCartridge;
MenuSeparator systemSeparator1; MenuSeparator systemSeparator1;
MenuItem systemPower; MenuItem systemPower;
MenuItem systemReset;
Menu settings; Menu settings;
MenuCheckItem settingsVideoSync;
Menu tools; Menu tools;

View File

@@ -22,13 +22,21 @@ void Application::main(int argc, char **argv) {
mainWindow.setVisible(); mainWindow.setVisible();
OS::run(); OS::run();
#if defined(PHOENIX_WINDOWS)
video.driver("Direct3D");
#else
video.driver("OpenGL"); video.driver("OpenGL");
#endif
video.set(Video::Handle, (uintptr_t)mainWindow.viewport.handle()); video.set(Video::Handle, (uintptr_t)mainWindow.viewport.handle());
video.set(Video::Synchronize, true); video.set(Video::Synchronize, true);
video.set(Video::Filter, (unsigned)0); video.set(Video::Filter, (unsigned)0);
video.init(); video.init();
#if defined(PHOENIX_WINDOWS)
input.driver("RawInput");
#else
input.driver("SDL"); input.driver("SDL");
#endif
input.set(Input::Handle, (uintptr_t)mainWindow.viewport.handle()); input.set(Input::Handle, (uintptr_t)mainWindow.viewport.handle());
input.init(); input.init();