mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
ebd6a52811
commit
afdb3c4d20
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ ui := ui
|
|||
# compiler
|
||||
c := $(compiler) -std=gnu99
|
||||
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
|
||||
flags := -O3 -fomit-frame-pointer -I. -I$(gameboy)
|
||||
flags := -O3 -fomit-frame-pointer -I.
|
||||
link :=
|
||||
objects :=
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define CARTRIDGE_CPP
|
||||
namespace GameBoy {
|
||||
|
||||
#include "mbc0/mbc0.cpp"
|
||||
#include "mbc1/mbc1.cpp"
|
||||
#include "mbc2/mbc2.cpp"
|
||||
#include "mbc5/mbc5.cpp"
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::load(uint8_t *data, unsigned size) {
|
||||
|
@ -25,11 +27,20 @@ void Cartridge::load(uint8_t *data, unsigned size) {
|
|||
info.battery = false;
|
||||
info.rtc = false;
|
||||
|
||||
switch(romdata[0x0147]) { default:
|
||||
switch(romdata[0x0147]) {
|
||||
case 0x00: info.mapper = Mapper::MBC0; break;
|
||||
case 0x01: info.mapper = Mapper::MBC1; 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 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:
|
||||
|
@ -46,7 +57,6 @@ void Cartridge::load(uint8_t *data, unsigned size) {
|
|||
case 0x54: info.romsize = 96 * 16 * 1024; break;
|
||||
}
|
||||
|
||||
//TODO: MBC2 always stores 0x00 here; yet it has 512x4-bits RAM
|
||||
switch(romdata[0x0149]) { default:
|
||||
case 0x00: info.ramsize = 0 * 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;
|
||||
}
|
||||
|
||||
if(info.mapper == Mapper::MBC2) info.ramsize = 256; //512 x 4-bit
|
||||
|
||||
ramdata = new uint8_t[ramsize = info.ramsize]();
|
||||
|
||||
loaded = true;
|
||||
|
@ -92,23 +104,21 @@ void Cartridge::ram_write(unsigned addr, uint8 data) {
|
|||
void Cartridge::power() {
|
||||
mbc0.power();
|
||||
mbc1.power();
|
||||
mbc2.power();
|
||||
mbc5.power();
|
||||
|
||||
MMIO *mapper = 0;
|
||||
switch(info.mapper) {
|
||||
switch(info.mapper) { default:
|
||||
case Mapper::MBC0: mapper = &mbc0; break;
|
||||
case Mapper::MBC1: mapper = &mbc1; break;
|
||||
case Mapper::MBC2: mapper = &mbc2; break;
|
||||
case Mapper::MBC5: mapper = &mbc5; break;
|
||||
}
|
||||
|
||||
if(mapper) {
|
||||
for(unsigned n = 0x0000; n <= 0x7fff; 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() {
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
struct Cartridge : property<Cartridge> {
|
||||
#include "mbc0/mbc0.hpp"
|
||||
#include "mbc1/mbc1.hpp"
|
||||
#include "mbc2/mbc2.hpp"
|
||||
#include "mbc5/mbc5.hpp"
|
||||
|
||||
enum Mapper : unsigned {
|
||||
MBC0,
|
||||
MBC1,
|
||||
MBC2,
|
||||
MBC5,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
struct Information {
|
||||
string name;
|
||||
uint8 cgbflag;
|
||||
uint8 sgbflag;
|
||||
string name;
|
||||
uint8 cgbflag;
|
||||
uint8 sgbflag;
|
||||
|
||||
Mapper mapper;
|
||||
bool ram;
|
||||
bool battery;
|
||||
bool rtc;
|
||||
Mapper mapper;
|
||||
bool ram;
|
||||
bool battery;
|
||||
bool rtc;
|
||||
bool rumble;
|
||||
|
||||
unsigned romsize;
|
||||
unsigned ramsize;
|
||||
|
@ -39,7 +44,6 @@ struct Cartridge : property<Cartridge> {
|
|||
void ram_write(unsigned addr, uint8 data);
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
Cartridge();
|
||||
~Cartridge();
|
||||
|
|
|
@ -11,7 +11,4 @@ void Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) {
|
|||
void Cartridge::MBC0::power() {
|
||||
}
|
||||
|
||||
void Cartridge::MBC0::reset() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,5 +2,4 @@ struct MBC0 : MMIO {
|
|||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
void power();
|
||||
void reset();
|
||||
} mbc0;
|
||||
|
|
|
@ -47,9 +47,6 @@ void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) {
|
|||
}
|
||||
|
||||
void Cartridge::MBC1::power() {
|
||||
}
|
||||
|
||||
void Cartridge::MBC1::reset() {
|
||||
ram_enable = false;
|
||||
rom_select = 0x01;
|
||||
ram_select = 0x00;
|
||||
|
|
|
@ -10,5 +10,4 @@ struct MBC1 : MMIO {
|
|||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
void power();
|
||||
void reset();
|
||||
} mbc1;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
|
@ -1,4 +1,4 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define CPU_CPP
|
||||
namespace GameBoy {
|
||||
|
@ -67,9 +67,13 @@ void CPU::interrupt_exec(uint16 pc) {
|
|||
op_write(--r[SP], r[PC] >> 0);
|
||||
r[PC] = pc;
|
||||
op_io();
|
||||
op_io();
|
||||
op_io();
|
||||
}
|
||||
|
||||
void CPU::power() {
|
||||
create(Main, 4 * 1024 * 1024);
|
||||
|
||||
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 = 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 < 128; n++) hram[n] = 0x00;
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void CPU::reset() {
|
||||
create(Main, 4 * 1024 * 1024);
|
||||
|
||||
r[PC] = 0x0100;
|
||||
r[SP] = 0xfffe;
|
||||
r[AF] = 0x0000;
|
||||
r[AF] = 0x0100;
|
||||
r[BC] = 0x0000;
|
||||
r[DE] = 0x0000;
|
||||
r[HL] = 0x0000;
|
||||
|
|
|
@ -63,7 +63,6 @@ struct CPU : Processor, MMIO {
|
|||
void interrupt_test();
|
||||
void interrupt_exec(uint16 pc);
|
||||
void power();
|
||||
void reset();
|
||||
CPU();
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace GameBoy {
|
||||
namespace Info {
|
||||
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) {}
|
||||
};
|
||||
|
||||
#include <system/system.hpp>
|
||||
#include <scheduler/scheduler.hpp>
|
||||
#include <memory/memory.hpp>
|
||||
#include <cartridge/cartridge.hpp>
|
||||
#include <cpu/cpu.hpp>
|
||||
#include <lcd/lcd.hpp>
|
||||
#include <gameboy/system/system.hpp>
|
||||
#include <gameboy/scheduler/scheduler.hpp>
|
||||
#include <gameboy/memory/memory.hpp>
|
||||
#include <gameboy/cartridge/cartridge.hpp>
|
||||
#include <gameboy/cpu/cpu.hpp>
|
||||
#include <gameboy/lcd/lcd.hpp>
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define LCD_CPP
|
||||
namespace GameBoy {
|
||||
|
@ -55,93 +55,66 @@ void LCD::frame() {
|
|||
}
|
||||
|
||||
void LCD::render() {
|
||||
for(unsigned n = 0; n < 160; n++) {
|
||||
line[n].source = Line::Source::None;
|
||||
line[n].output = 0;
|
||||
}
|
||||
for(unsigned n = 0; n < 160; n++) line[n] = 0x00;
|
||||
|
||||
if(status.display_enable == true) {
|
||||
if(status.bg_enable == true) render_bg();
|
||||
if(status.obj_enable == true) render_obj();
|
||||
if(status.window_display_enable == true) render_window();
|
||||
if(status.obj_enable == true) render_obj();
|
||||
}
|
||||
|
||||
uint8_t *output = screen + status.ly * 160;
|
||||
for(unsigned n = 0; n < 160; n++) {
|
||||
output[n] = (3 - line[n].output) * 0x55;
|
||||
for(unsigned n = 0; n < 160; n++) output[n] = (3 - line[n]) * 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() {
|
||||
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);
|
||||
|
||||
unsigned tx = (ix - 7) & 7;
|
||||
uint8 d0 = 0, d1 = 0;
|
||||
for(signed ox = -7; ox < 160; ox++) {
|
||||
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];
|
||||
}
|
||||
for(unsigned ox = 0; ox < 160; ox++) {
|
||||
palette = ((data & (mask << 0)) ? 1 : 0);
|
||||
palette |= ((data & (mask << 8)) ? 2 : 0);
|
||||
mask = (mask >> 1) | (mask << 7);
|
||||
line[ox] = status.bgp[palette];
|
||||
|
||||
ix = (ix + 1) & 255;
|
||||
tx = (tx + 1) & 7;
|
||||
|
||||
if(tx == 0) data = read_tile(status.bg_tilemap_select, ix, iy);
|
||||
}
|
||||
}
|
||||
|
||||
void LCD::render_window() {
|
||||
if(status.wy > status.ly) return;
|
||||
unsigned iy = (status.ly + status.wy) & 255;
|
||||
unsigned ix = (status.wx - 7) & 255;
|
||||
if(status.ly - status.wy >= 144U) return;
|
||||
unsigned iy = status.ly - status.wy;
|
||||
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);
|
||||
|
||||
unsigned tx = (ix - 7) & 7;
|
||||
uint8 d0 = 0, d1 = 0;
|
||||
for(signed ox = -7; ox < 160; ox++) {
|
||||
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];
|
||||
}
|
||||
for(unsigned ox = 0; ox < 160; ox++) {
|
||||
palette = ((data & (mask << 0)) ? 1 : 0);
|
||||
palette |= ((data & (mask << 8)) ? 2 : 0);
|
||||
mask = (mask >> 1) | (mask << 7);
|
||||
if(ox - (status.wx - 7) < 160U) line[ox] = status.bgp[palette];
|
||||
|
||||
ix = (ix + 1) & 255;
|
||||
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);
|
||||
|
||||
if(ox <= 159) {
|
||||
if((attribute & 0x80) == 1) {
|
||||
if(line[ox].source == Line::Source::BG && line[ox].output > 0) continue;
|
||||
if(attribute & 0x80) {
|
||||
if(line[ox] > 0) continue;
|
||||
}
|
||||
line[ox].source = Line::Source::OBJ;
|
||||
line[ox].output = palette;
|
||||
line[ox] = palette;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LCD::power() {
|
||||
create(Main, 4 * 1024 * 1024);
|
||||
|
||||
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
|
||||
|
@ -191,11 +165,6 @@ void LCD::power() {
|
|||
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;
|
||||
|
|
|
@ -49,11 +49,7 @@ struct LCD : Processor, MMIO {
|
|||
uint8 screen[160 * 144];
|
||||
uint8 vram[8192];
|
||||
uint8 oam[160];
|
||||
|
||||
struct Line {
|
||||
enum class Source : unsigned { None, BG, OBJ, Window } source;
|
||||
uint8 output;
|
||||
} line[160];
|
||||
uint8 line[160];
|
||||
|
||||
static void Main();
|
||||
void main();
|
||||
|
@ -61,12 +57,12 @@ struct LCD : Processor, MMIO {
|
|||
void scanline();
|
||||
void frame();
|
||||
void render();
|
||||
uint16 read_tile(bool select, unsigned x, unsigned y);
|
||||
void render_bg();
|
||||
void render_window();
|
||||
void render_obj();
|
||||
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
|
||||
extern LCD lcd;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define MEMORY_CPP
|
||||
namespace GameBoy {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define SCHEDULER_CPP
|
||||
namespace GameBoy {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#define SYSTEM_CPP
|
||||
namespace GameBoy {
|
||||
|
@ -17,14 +17,6 @@ void System::power() {
|
|||
scheduler.init();
|
||||
}
|
||||
|
||||
void System::reset() {
|
||||
bus.reset();
|
||||
cartridge.power();
|
||||
cpu.reset();
|
||||
lcd.reset();
|
||||
scheduler.init();
|
||||
}
|
||||
|
||||
void System::run() {
|
||||
scheduler.enter();
|
||||
}
|
||||
|
|
|
@ -8,13 +8,12 @@ class System {
|
|||
public:
|
||||
void init(Interface*);
|
||||
void power();
|
||||
void reset();
|
||||
void run();
|
||||
|
||||
//private:
|
||||
Interface *interface;
|
||||
};
|
||||
|
||||
#include <interface/interface.hpp>
|
||||
#include <gameboy/interface/interface.hpp>
|
||||
|
||||
extern System system;
|
||||
|
|
|
@ -10,7 +10,7 @@ using namespace ruby;
|
|||
#include <phoenix/phoenix.hpp>
|
||||
using namespace phoenix;
|
||||
|
||||
#include <gameboy.hpp>
|
||||
#include <gameboy/gameboy.hpp>
|
||||
|
||||
#include "interface.hpp"
|
||||
|
||||
|
|
|
@ -9,12 +9,10 @@ void MainWindow::create() {
|
|||
systemLoadCartridge.create(system, "Load Cartridge ...");
|
||||
systemSeparator1.create(system);
|
||||
systemPower.create(system, "Power Cycle");
|
||||
systemPower.setEnabled(false);
|
||||
systemReset.create(system, "Reset");
|
||||
systemReset.setEnabled(false);
|
||||
|
||||
settings.create(*this, "Settings");
|
||||
//settings.setEnabled(false);
|
||||
settingsVideoSync.create(settings, "Synchronize Video");
|
||||
settingsVideoSync.setChecked(true);
|
||||
|
||||
tools.create(*this, "Tools");
|
||||
//tools.setEnabled(false);
|
||||
|
@ -37,6 +35,14 @@ void MainWindow::create() {
|
|||
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 = []() {
|
||||
MessageWindow::information(mainWindow, {
|
||||
"bgameboy\n\n",
|
||||
|
|
|
@ -3,9 +3,9 @@ struct MainWindow : Window {
|
|||
MenuItem systemLoadCartridge;
|
||||
MenuSeparator systemSeparator1;
|
||||
MenuItem systemPower;
|
||||
MenuItem systemReset;
|
||||
|
||||
Menu settings;
|
||||
MenuCheckItem settingsVideoSync;
|
||||
|
||||
Menu tools;
|
||||
|
||||
|
|
|
@ -22,13 +22,21 @@ void Application::main(int argc, char **argv) {
|
|||
mainWindow.setVisible();
|
||||
OS::run();
|
||||
|
||||
#if defined(PHOENIX_WINDOWS)
|
||||
video.driver("Direct3D");
|
||||
#else
|
||||
video.driver("OpenGL");
|
||||
#endif
|
||||
video.set(Video::Handle, (uintptr_t)mainWindow.viewport.handle());
|
||||
video.set(Video::Synchronize, true);
|
||||
video.set(Video::Filter, (unsigned)0);
|
||||
video.init();
|
||||
|
||||
#if defined(PHOENIX_WINDOWS)
|
||||
input.driver("RawInput");
|
||||
#else
|
||||
input.driver("SDL");
|
||||
#endif
|
||||
input.set(Input::Handle, (uintptr_t)mainWindow.viewport.handle());
|
||||
input.init();
|
||||
|
||||
|
|
Loading…
Reference in New Issue