mirror of https://github.com/bsnes-emu/bsnes.git
Update to v078r06 release.
byuu says: This adds ikari_01's emulation of the ICD2 (Super Game Boy) $6001 register. It basically removes a really ugly hack where I was intercepting the DMA transfer destination address to determine while Game Boy tile row to transfer. This should make implementing SGB emulation in other emulators easier, as said hooks were very emulator-specific.
This commit is contained in:
parent
52443936e6
commit
bc0b86891a
|
@ -1,5 +1,6 @@
|
||||||
class Interface {
|
class Interface {
|
||||||
public:
|
public:
|
||||||
|
virtual void lcd_scanline() {}
|
||||||
virtual void joyp_write(bool p15, bool p14) {}
|
virtual void joyp_write(bool p15, bool p14) {}
|
||||||
|
|
||||||
virtual void video_refresh(const uint8_t *data) {}
|
virtual void video_refresh(const uint8_t *data) {}
|
||||||
|
|
|
@ -75,6 +75,7 @@ void LCD::render() {
|
||||||
|
|
||||||
uint8_t *output = screen + status.ly * 160;
|
uint8_t *output = screen + status.ly * 160;
|
||||||
for(unsigned n = 0; n < 160; n++) output[n] = (3 - line[n]) * 0x55;
|
for(unsigned n = 0; n < 160; n++) output[n] = (3 - line[n]) * 0x55;
|
||||||
|
system.interface->lcd_scanline();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 LCD::read_tile(bool select, unsigned x, unsigned y) {
|
uint16 LCD::read_tile(bool select, unsigned x, unsigned y) {
|
||||||
|
|
|
@ -33,10 +33,6 @@ void ICD2::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::load() {
|
void ICD2::load() {
|
||||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
|
||||||
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
|
||||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2181, 0x2182, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
|
||||||
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x420b, 0x420b, { &ICD2::mmio_read, &icd2 }, { &ICD2::mmio_write, &icd2 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICD2::unload() {
|
void ICD2::unload() {
|
||||||
|
@ -52,10 +48,8 @@ void ICD2::power() {
|
||||||
void ICD2::reset() {
|
void ICD2::reset() {
|
||||||
create(ICD2::Enter, cpu.frequency / 5);
|
create(ICD2::Enter, cpu.frequency / 5);
|
||||||
|
|
||||||
r2181 = 0x00;
|
r6000_ly = 0x00;
|
||||||
r2182 = 0x00;
|
r6000_row = 0x00;
|
||||||
|
|
||||||
r6000 = 0x00;
|
|
||||||
r6003 = 0x00;
|
r6003 = 0x00;
|
||||||
r6004 = 0xff;
|
r6004 = 0xff;
|
||||||
r6005 = 0xff;
|
r6005 = 0xff;
|
||||||
|
@ -65,7 +59,9 @@ void ICD2::reset() {
|
||||||
r7800 = 0x0000;
|
r7800 = 0x0000;
|
||||||
mlt_req = 0;
|
mlt_req = 0;
|
||||||
|
|
||||||
for(unsigned n = 0; n < 320; n++) vram[n] = 0xff;
|
foreach(byte, lcd.buffer) byte = 0xff;
|
||||||
|
foreach(byte, lcd.output) byte = 0xff;
|
||||||
|
lcd.row = 0;
|
||||||
|
|
||||||
packetsize = 0;
|
packetsize = 0;
|
||||||
joyp_id = 3;
|
joyp_id = 3;
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
#ifdef ICD2_CPP
|
#ifdef ICD2_CPP
|
||||||
|
|
||||||
|
//called on rendered lines 0-143 (not on Vblank lines 144-153)
|
||||||
|
void ICD2::lcd_scanline() {
|
||||||
|
if((GameBoy::lcd.status.ly & 7) == 0) {
|
||||||
|
lcd.row = (lcd.row + 1) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned offset = (lcd.row * 160 * 8) + ((GameBoy::lcd.status.ly & 7) * 160);
|
||||||
|
memcpy(lcd.buffer + offset, GameBoy::lcd.screen + GameBoy::lcd.status.ly * 160, 160);
|
||||||
|
}
|
||||||
|
|
||||||
void ICD2::joyp_write(bool p15, bool p14) {
|
void ICD2::joyp_write(bool p15, bool p14) {
|
||||||
//joypad handling
|
//joypad handling
|
||||||
if(p15 == 1 && p14 == 1) {
|
if(p15 == 1 && p14 == 1) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
void lcd_scanline();
|
||||||
void joyp_write(bool p15, bool p14);
|
void joyp_write(bool p15, bool p14);
|
||||||
void video_refresh(const uint8_t *data);
|
void video_refresh(const uint8_t *data);
|
||||||
void audio_sample(int16_t center, int16_t left, int16_t right);
|
void audio_sample(int16_t center, int16_t left, int16_t right);
|
||||||
|
|
|
@ -1,38 +1,19 @@
|
||||||
#ifdef ICD2_CPP
|
#ifdef ICD2_CPP
|
||||||
|
|
||||||
uint8 ICD2::mmio_read(unsigned addr) {
|
//convert linear pixel data { 0x00, 0x55, 0xaa, 0xff } to 2bpp planar tiledata
|
||||||
if((uint16)addr == 0x2181) return cpu.mmio_read(addr);
|
void ICD2::render(const uint8 *source) {
|
||||||
if((uint16)addr == 0x2182) return cpu.mmio_read(addr);
|
memset(lcd.output, 0x00, 320);
|
||||||
if((uint16)addr == 0x420b) return cpu.mmio_read(addr);
|
|
||||||
return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICD2::mmio_write(unsigned addr, uint8 data) {
|
for(unsigned y = 0; y < 8; y++) {
|
||||||
if((uint16)addr == 0x420b && data == 0x10) {
|
for(unsigned x = 0; x < 160; x++) {
|
||||||
unsigned offset = (r2182 << 8) | (r2181 << 0);
|
unsigned pixel = *source++ / 0x55;
|
||||||
r7800 = 0;
|
pixel ^= 3;
|
||||||
unsigned row = 0;
|
|
||||||
if(offset >= 0x5000 && offset <= 0x6540) row = (offset - 0x5000) / 320;
|
|
||||||
if(offset >= 0x6800 && offset <= 0x7d40) row = (offset - 0x6800) / 320;
|
|
||||||
|
|
||||||
uint8 *source = GameBoy::lcd.screen + row * 160 * 8;
|
unsigned addr = y * 2 + (x / 8 * 16);
|
||||||
memset(vram, 0x00, 320);
|
lcd.output[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7));
|
||||||
|
lcd.output[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7));
|
||||||
for(unsigned y = row * 8; y < row * 8 + 8; y++) {
|
|
||||||
for(unsigned x = 0; x < 160; x++) {
|
|
||||||
unsigned pixel = *source++ / 0x55;
|
|
||||||
pixel ^= 3;
|
|
||||||
|
|
||||||
unsigned addr = (x / 8 * 16) + ((y & 7) * 2);
|
|
||||||
vram[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7));
|
|
||||||
vram[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((uint16)addr == 0x2181) return cpu.mmio_write(addr, r2181 = data);
|
|
||||||
if((uint16)addr == 0x2182) return cpu.mmio_write(addr, r2182 = data);
|
|
||||||
if((uint16)addr == 0x420b) return cpu.mmio_write(addr, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 ICD2::read(unsigned addr) {
|
uint8 ICD2::read(unsigned addr) {
|
||||||
|
@ -40,7 +21,9 @@ uint8 ICD2::read(unsigned addr) {
|
||||||
|
|
||||||
//LY counter
|
//LY counter
|
||||||
if(addr == 0x6000) {
|
if(addr == 0x6000) {
|
||||||
return GameBoy::lcd.status.ly;
|
r6000_ly = GameBoy::lcd.status.ly;
|
||||||
|
r6000_row = lcd.row;
|
||||||
|
return r6000_ly;
|
||||||
}
|
}
|
||||||
|
|
||||||
//command ready port
|
//command ready port
|
||||||
|
@ -66,7 +49,7 @@ uint8 ICD2::read(unsigned addr) {
|
||||||
|
|
||||||
//VRAM port
|
//VRAM port
|
||||||
if(addr == 0x7800) {
|
if(addr == 0x7800) {
|
||||||
uint8 data = vram[r7800];
|
uint8 data = lcd.output[r7800];
|
||||||
r7800 = (r7800 + 1) % 320;
|
r7800 = (r7800 + 1) % 320;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -77,6 +60,17 @@ uint8 ICD2::read(unsigned addr) {
|
||||||
void ICD2::write(unsigned addr, uint8 data) {
|
void ICD2::write(unsigned addr, uint8 data) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
//VRAM port
|
||||||
|
if(addr == 0x6001) {
|
||||||
|
r6001 = data;
|
||||||
|
r7800 = 0;
|
||||||
|
|
||||||
|
unsigned offset = (r6000_row - (4 - (r6001 - (r6000_ly & 3)))) & 3;
|
||||||
|
render(lcd.buffer + offset * 160 * 8);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//control port
|
//control port
|
||||||
//d7: 0 = halt, 1 = reset
|
//d7: 0 = halt, 1 = reset
|
||||||
//d5,d4: 0 = 1-player, 1 = 2-player, 2 = 4-player, 3 = ???
|
//d5,d4: 0 = 1-player, 1 = 2-player, 2 = 4-player, 3 = ???
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
uint8 r2181;
|
void render(const uint8 *source);
|
||||||
uint8 r2182;
|
|
||||||
uint8 mmio_read(unsigned addr);
|
|
||||||
void mmio_write(unsigned addr, uint8 data);
|
|
||||||
|
|
||||||
uint8 r6000;
|
uint8 r6000_ly; //SGB BIOS' cache of LY
|
||||||
uint8 r6003;
|
uint8 r6000_row; //SGB BIOS' cache of ROW
|
||||||
uint8 r6004;
|
uint8 r6001; //VRAM conversion
|
||||||
uint8 r6005;
|
uint8 r6003; //control port
|
||||||
uint8 r6006;
|
uint8 r6004; //joypad 1
|
||||||
uint8 r6007;
|
uint8 r6005; //joypad 2
|
||||||
uint8 r7000[16];
|
uint8 r6006; //joypad 3
|
||||||
unsigned r7800;
|
uint8 r6007; //joypad 4
|
||||||
uint8 mlt_req;
|
uint8 r7000[16]; //JOYP packet data
|
||||||
|
unsigned r7800; //VRAM offset
|
||||||
|
uint8 mlt_req; //number of active joypads
|
||||||
|
|
||||||
uint8 vram[320];
|
struct LCD {
|
||||||
|
uint8 buffer[4 * 160 * 8]; //four tile rows of linear video data
|
||||||
|
uint8 output[320]; //one tile row of 2bpp video data
|
||||||
|
unsigned row; //active ICD2 rendering tile row
|
||||||
|
} lcd;
|
||||||
|
|
|
@ -18,10 +18,9 @@ void ICD2::serialize(serializer &s) {
|
||||||
s.integer(bitdata);
|
s.integer(bitdata);
|
||||||
s.integer(bitoffset);
|
s.integer(bitoffset);
|
||||||
|
|
||||||
s.integer(r2181);
|
s.integer(r6000_ly);
|
||||||
s.integer(r2182);
|
s.integer(r6000_row);
|
||||||
|
s.integer(r6001);
|
||||||
s.integer(r6000);
|
|
||||||
s.integer(r6003);
|
s.integer(r6003);
|
||||||
s.integer(r6004);
|
s.integer(r6004);
|
||||||
s.integer(r6005);
|
s.integer(r6005);
|
||||||
|
@ -31,7 +30,9 @@ void ICD2::serialize(serializer &s) {
|
||||||
s.integer(r7800);
|
s.integer(r7800);
|
||||||
s.integer(mlt_req);
|
s.integer(mlt_req);
|
||||||
|
|
||||||
s.array(vram);
|
s.array(lcd.buffer);
|
||||||
|
s.array(lcd.output);
|
||||||
|
s.integer(lcd.row);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "078.05";
|
static const char Version[] = "078.06";
|
||||||
static const unsigned SerializerVersion = 20;
|
static const unsigned SerializerVersion = 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue