mirror of https://github.com/bsnes-emu/bsnes.git
143 lines
3.9 KiB
C++
143 lines
3.9 KiB
C++
|
#include <snes.hpp>
|
||
|
|
||
|
#define SUPERGAMEBOY_CPP
|
||
|
namespace SNES {
|
||
|
|
||
|
SuperGameBoy supergameboy;
|
||
|
|
||
|
#include "serialization.cpp"
|
||
|
|
||
|
void SuperGameBoy::Enter() { supergameboy.enter(); }
|
||
|
|
||
|
void SuperGameBoy::enter() {
|
||
|
if(!sgb_run) while(true) {
|
||
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||
|
}
|
||
|
|
||
|
audio.coprocessor_sample(0, 0);
|
||
|
step(1);
|
||
|
synchronize_cpu();
|
||
|
}
|
||
|
|
||
|
while(true) {
|
||
|
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||
|
}
|
||
|
|
||
|
unsigned samples = sgb_run(samplebuffer, 16);
|
||
|
for(unsigned i = 0; i < samples; i++) {
|
||
|
int16 left = samplebuffer[i] >> 0;
|
||
|
int16 right = samplebuffer[i] >> 16;
|
||
|
|
||
|
//SNES audio is notoriously quiet; lower Game Boy samples to match SGB sound effects
|
||
|
audio.coprocessor_sample(left / 3, right / 3);
|
||
|
}
|
||
|
|
||
|
step(samples);
|
||
|
synchronize_cpu();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::save() {
|
||
|
if(sgb_save) sgb_save();
|
||
|
}
|
||
|
|
||
|
uint8 SuperGameBoy::mmio_read(unsigned addr) {
|
||
|
addr &= 0xffff;
|
||
|
|
||
|
if(addr == 0x2181) return mmio[0]->mmio_read(addr);
|
||
|
if(addr == 0x2182) return mmio[1]->mmio_read(addr);
|
||
|
if(addr == 0x420b) return mmio[2]->mmio_read(addr);
|
||
|
|
||
|
return 0x00;
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::mmio_write(unsigned addr, uint8 data) {
|
||
|
addr &= 0xffff;
|
||
|
|
||
|
if(addr == 0x2181) {
|
||
|
row = (row & 0xff00) | (data << 0);
|
||
|
mmio[0]->mmio_write(addr, data);
|
||
|
}
|
||
|
|
||
|
if(addr == 0x2182) {
|
||
|
row = (row & 0x00ff) | (data << 8);
|
||
|
mmio[1]->mmio_write(addr, data);
|
||
|
}
|
||
|
|
||
|
if(addr == 0x420b) {
|
||
|
if(data == 0x10 && sgb_row) {
|
||
|
if(row >= 0x5000 && row <= 0x6540) sgb_row((row - 0x5000) / 320);
|
||
|
if(row >= 0x6800 && row <= 0x7d40) sgb_row((row - 0x6800) / 320);
|
||
|
}
|
||
|
mmio[2]->mmio_write(addr, data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint8 SuperGameBoy::read(unsigned addr) {
|
||
|
if(sgb_read) return sgb_read(addr);
|
||
|
return 0x00;
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::write(unsigned addr, uint8 data) {
|
||
|
if(sgb_write) sgb_write(addr, data);
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::init() {
|
||
|
if(open("supergameboy")) {
|
||
|
sgb_rom = sym("sgb_rom");
|
||
|
sgb_ram = sym("sgb_ram");
|
||
|
sgb_rtc = sym("sgb_rtc");
|
||
|
sgb_init = sym("sgb_init");
|
||
|
sgb_term = sym("sgb_term");
|
||
|
sgb_power = sym("sgb_power");
|
||
|
sgb_reset = sym("sgb_reset");
|
||
|
sgb_row = sym("sgb_row");
|
||
|
sgb_read = sym("sgb_read");
|
||
|
sgb_write = sym("sgb_write");
|
||
|
sgb_run = sym("sgb_run");
|
||
|
sgb_save = sym("sgb_save");
|
||
|
sgb_serialize = sym("sgb_serialize");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::enable() {
|
||
|
mmio[0] = memory::mmio.mmio[0x2181 - 0x2000];
|
||
|
mmio[1] = memory::mmio.mmio[0x2182 - 0x2000];
|
||
|
mmio[2] = memory::mmio.mmio[0x420b - 0x2000];
|
||
|
|
||
|
memory::mmio.map(0x2181, *this);
|
||
|
memory::mmio.map(0x2182, *this);
|
||
|
memory::mmio.map(0x420b, *this);
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::power() {
|
||
|
unsigned frequency = (cartridge.supergameboy_version() == Cartridge::SuperGameBoyVersion::Version1 ? system.cpu_frequency() / 10 : 2097152);
|
||
|
create(SuperGameBoy::Enter, frequency);
|
||
|
|
||
|
audio.coprocessor_enable(true);
|
||
|
audio.coprocessor_frequency(cartridge.supergameboy_version() == Cartridge::SuperGameBoyVersion::Version1 ? 2147727.0 : 2097152.0);
|
||
|
|
||
|
sgb_rom(memory::gbrom.data(), memory::gbrom.size() == -1U ? 0 : memory::gbrom.size());
|
||
|
sgb_ram(memory::gbram.data(), memory::gbram.size() == -1U ? 0 : memory::gbram.size());
|
||
|
sgb_rtc(memory::gbrtc.data(), memory::gbrtc.size() == -1U ? 0 : memory::gbrtc.size());
|
||
|
|
||
|
bool version = (cartridge.supergameboy_version() == Cartridge::SuperGameBoyVersion::Version1) ? 0 : 1;
|
||
|
if(sgb_init) sgb_init(version);
|
||
|
if(sgb_power) sgb_power();
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::reset() {
|
||
|
unsigned frequency = (cartridge.supergameboy_version() == Cartridge::SuperGameBoyVersion::Version1 ? system.cpu_frequency() / 10 : 2097152);
|
||
|
create(SuperGameBoy::Enter, frequency);
|
||
|
|
||
|
if(sgb_reset) sgb_reset();
|
||
|
}
|
||
|
|
||
|
void SuperGameBoy::unload() {
|
||
|
if(sgb_term) sgb_term();
|
||
|
}
|
||
|
|
||
|
}
|