Update to v097r15 release.

byuu says:

Changelog:
- higan now uses Natural<Size>/Integer<Size> for its internal types
- Super Famicom emulation now uses uint24 instead of uint for bus
  addresses (it's a 24-bit bus)
- cleaned up gb/apu MMIO writes
- cleaned up sfc/coprocessor/msu1 MMIO writes
- ~3% speed penalty

I've wanted to do that 24-bit bus thing for so long, but have always
been afraid of the speed impact. It's probably going to hurt
balanced/performance once they compile again, but it wasn't significant
enough to harm the accuracy core's frame rate, thankfully. Only lost one
frame per second.

The GBA core handlers are clearly going to take a lot more work. The
bit-ranges will make it substantially easier to handle, though. Lots of
32-bit registers where certain values span multiple bytes, but we have
to be able to read/write at byte-granularity.
This commit is contained in:
Tim Allen 2016-02-16 20:32:49 +11:00
parent ef65bb862a
commit 4b29f4bad7
61 changed files with 366 additions and 413 deletions

View File

@ -66,16 +66,16 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
} }
if(addr == 0xff21) { //NR42 if(addr == 0xff21) { //NR42
envelopeVolume = data >> 4; envelopeVolume = data.bits(7,4);
envelopeDirection = data & 0x08; envelopeDirection = data.bit (3);
envelopeFrequency = data & 0x07; envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false; if(!dacEnable()) enable = false;
} }
if(addr == 0xff22) { //NR43 if(addr == 0xff22) { //NR43
frequency = data >> 4; frequency = data.bits(7,4);
narrow = data & 0x08; narrow = data.bit (3);
divisor = data & 0x07; divisor = data.bits(2,0);
period = getPeriod(); period = getPeriod();
} }
@ -84,10 +84,9 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
if(length && --length == 0) enable = false; if(length && --length == 0) enable = false;
} }
bool initialize = data & 0x80; counter = data.bit(6);
counter = data & 0x40;
if(initialize) { if(data.bit(7)) {
enable = dacEnable(); enable = dacEnable();
lfsr = -1; lfsr = -1;
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8; envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -95,7 +94,7 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
if(!length) { if(!length) {
length = 64; length = 64;
if((apu.phase & 1) && counter) length--; if(apu.phase.bit(0) && counter) length--;
} }
} }
} }

View File

@ -68,26 +68,26 @@ auto APU::Sequencer::read(uint16 addr) -> uint8 {
auto APU::Sequencer::write(uint16 addr, uint8 data) -> void { auto APU::Sequencer::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff24) { //NR50 if(addr == 0xff24) { //NR50
leftEnable = (uint1)(data >> 7); leftEnable = data.bit (7);
leftVolume = (uint3)(data >> 4); leftVolume = data.bits(6,4);
rightEnable = (uint1)(data >> 3); rightEnable = data.bit (3);
rightVolume = (uint3)(data >> 0); rightVolume = data.bits(2,0);
} }
if(addr == 0xff25) { //NR51 if(addr == 0xff25) { //NR51
noise.leftEnable = data & 0x80; noise.leftEnable = data.bit(7);
wave.leftEnable = data & 0x40; wave.leftEnable = data.bit(6);
square2.leftEnable = data & 0x20; square2.leftEnable = data.bit(5);
square1.leftEnable = data & 0x10; square1.leftEnable = data.bit(4);
noise.rightEnable = data & 0x08; noise.rightEnable = data.bit(3);
wave.rightEnable = data & 0x04; wave.rightEnable = data.bit(2);
square2.rightEnable = data & 0x02; square2.rightEnable = data.bit(1);
square1.rightEnable = data & 0x01; square1.rightEnable = data.bit(0);
} }
if(addr == 0xff26) { //NR52 if(addr == 0xff26) { //NR52
if(enable != (bool)(data & 0x80)) { if(enable != data.bit(7)) {
enable = data & 0x80; enable = data.bit(7);
if(!enable) { if(!enable) {
//power(bool) resets length counters when true (eg for CGB only) //power(bool) resets length counters when true (eg for CGB only)

View File

@ -86,38 +86,37 @@ auto APU::Square1::read(uint16 addr) -> uint8 {
auto APU::Square1::write(uint16 addr, uint8 data) -> void { auto APU::Square1::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff10) { //NR10 if(addr == 0xff10) { //NR10
if(sweepEnable && sweepNegate && !(data & 0x08)) enable = false; if(sweepEnable && sweepNegate && !data.bit(3)) enable = false;
sweepFrequency = (data >> 4) & 7; sweepFrequency = data.bits(6,4);
sweepDirection = data & 0x08; sweepDirection = data.bit (3);
sweepShift = data & 0x07; sweepShift = data.bits(2,0);
} }
if(addr == 0xff11) { //NR11 if(addr == 0xff11) { //NR11
duty = data >> 6; duty = data.bits(7,6);
length = 64 - (data & 0x3f); length = 64 - data.bits(5,0);
} }
if(addr == 0xff12) { //NR12 if(addr == 0xff12) { //NR12
envelopeVolume = data >> 4; envelopeVolume = data.bits(7,4);
envelopeDirection = data & 0x08; envelopeDirection = data.bit (3);
envelopeFrequency = data & 0x07; envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false; if(!dacEnable()) enable = false;
} }
if(addr == 0xff13) { //NR13 if(addr == 0xff13) { //NR13
frequency = (frequency & 0x0700) | data; frequency.bits(7,0) = data;
} }
if(addr == 0xff14) { //NR14 if(addr == 0xff14) { //NR14
if((apu.phase & 1) && !counter && (data & 0x40)) { if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false; if(length && --length == 0) enable = false;
} }
bool initialize = data & 0x80; counter = data.bit(6);
counter = data & 0x40; frequency.bits(10,8) = data.bits(2,0);
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
if(initialize) { if(data.bit(7)) {
enable = dacEnable(); enable = dacEnable();
period = 2 * (2048 - frequency); period = 2 * (2048 - frequency);
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8; envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -125,7 +124,7 @@ auto APU::Square1::write(uint16 addr, uint8 data) -> void {
if(!length) { if(!length) {
length = 64; length = 64;
if((apu.phase & 1) && counter) length--; if(apu.phase.bit(0) && counter) length--;
} }
frequencyShadow = frequency; frequencyShadow = frequency;

View File

@ -60,31 +60,30 @@ auto APU::Square2::read(uint16 addr) -> uint8 {
auto APU::Square2::write(uint16 addr, uint8 data) -> void { auto APU::Square2::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff16) { //NR21 if(addr == 0xff16) { //NR21
duty = data >> 6; duty = data.bits(7,6);
length = 64 - (data & 0x3f); length = 64 - data.bits(5,0);
} }
if(addr == 0xff17) { //NR22 if(addr == 0xff17) { //NR22
envelopeVolume = data >> 4; envelopeVolume = data.bits(7,4);
envelopeDirection = data & 0x08; envelopeDirection = data.bit (3);
envelopeFrequency = data & 0x07; envelopeFrequency = data.bits(2,0);
if(!dacEnable()) enable = false; if(!dacEnable()) enable = false;
} }
if(addr == 0xff18) { //NR23 if(addr == 0xff18) { //NR23
frequency = (frequency & 0x0700) | data; frequency.bits(7,0) = data;
} }
if(addr == 0xff19) { //NR24 if(addr == 0xff19) { //NR24
if((apu.phase & 1) && !counter && (data & 0x40)) { if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false; if(length && --length == 0) enable = false;
} }
bool initialize = data & 0x80; counter = data.bit(6);
counter = data & 0x40; frequency.bits(10,8) = data.bits(2,0);
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
if(initialize) { if(data.bit(7)) {
enable = dacEnable(); enable = dacEnable();
period = 2 * (2048 - frequency); period = 2 * (2048 - frequency);
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8; envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
@ -92,7 +91,7 @@ auto APU::Square2::write(uint16 addr, uint8 data) -> void {
if(!length) { if(!length) {
length = 64; length = 64;
if((apu.phase & 1) && counter) length--; if(apu.phase.bit(0) && counter) length--;
} }
} }
} }

View File

@ -59,7 +59,7 @@ auto APU::Wave::read(uint16 addr) -> uint8 {
auto APU::Wave::write(uint16 addr, uint8 data) -> void { auto APU::Wave::write(uint16 addr, uint8 data) -> void {
if(addr == 0xff1a) { //NR30 if(addr == 0xff1a) { //NR30
dacEnable = data & 0x80; dacEnable = data.bit(7);
if(!dacEnable) enable = false; if(!dacEnable) enable = false;
} }
@ -68,23 +68,22 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
} }
if(addr == 0xff1c) { //NR32 if(addr == 0xff1c) { //NR32
volume = data >> 5; volume = data.bits(6,5);
} }
if(addr == 0xff1d) { //NR33 if(addr == 0xff1d) { //NR33
frequency = (frequency & 0x0700) | data; frequency.bits(7,0) = data;
} }
if(addr == 0xff1e) { //NR34 if(addr == 0xff1e) { //NR34
if((apu.phase & 1) && !counter && (data & 0x40)) { if(apu.phase.bit(0) && !counter && data.bit(6)) {
if(length && --length == 0) enable = false; if(length && --length == 0) enable = false;
} }
bool initialize = data & 0x80; counter = data.bit(6);
counter = data & 0x40; frequency.bits(10,8) = data.bits(2,0);
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
if(initialize) { if(data.bit(7)) {
if(!system.cgb() && patternHold) { if(!system.cgb() && patternHold) {
//DMG,SGB trigger while channel is being read corrupts wave RAM //DMG,SGB trigger while channel is being read corrupts wave RAM
if((patternOffset >> 1) <= 3) { if((patternOffset >> 1) <= 3) {
@ -107,7 +106,7 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
if(!length) { if(!length) {
length = 256; length = 256;
if((apu.phase & 1) && counter) length--; if(apu.phase.bit(0) && counter) length--;
} }
} }
} }

View File

@ -65,8 +65,8 @@ auto CPU::read(uint32 addr) -> uint8 {
case 0x04000130: case 0x04000130:
if(auto result = player.keyinput()) return result() >> 0; if(auto result = player.keyinput()) return result() >> 0;
for(unsigned n = 0; n < 8; n++) result |= interface->inputPoll(0, 0, n) << n; for(unsigned n = 0; n < 8; n++) result |= interface->inputPoll(0, 0, n) << n;
if((result & 0xc0) == 0xc0) result &= ~0xc0; //up+down cannot be pressed simultaneously if((result & 0xc0) == 0xc0) result &= (uint8)~0xc0; //up+down cannot be pressed simultaneously
if((result & 0x30) == 0x30) result &= ~0x30; //left+right cannot be pressed simultaneously if((result & 0x30) == 0x30) result &= (uint8)~0x30; //left+right cannot be pressed simultaneously
return result ^ 0xff; return result ^ 0xff;
case 0x04000131: case 0x04000131:
if(auto result = player.keyinput()) return result() >> 8; if(auto result = player.keyinput()) return result() >> 8;

View File

@ -537,7 +537,7 @@ template<uint b, uint x> auto LR35902::op_res_n_r() {
} }
template<uint b> auto LR35902::op_res_n_hl() { template<uint b> auto LR35902::op_res_n_hl() {
uint8 n = op_read(r[HL]); uint n = op_read(r[HL]);
n &= ~(1 << b); n &= ~(1 << b);
op_write(r[HL], n); op_write(r[HL], n);
} }

View File

@ -14,13 +14,13 @@ struct R65816 {
using fp = auto (R65816::*)() -> void; using fp = auto (R65816::*)() -> void;
virtual auto op_io() -> void = 0; virtual auto op_io() -> void = 0;
virtual auto op_read(uint32 addr) -> uint8 = 0; virtual auto op_read(uint24 addr) -> uint8 = 0;
virtual auto op_write(uint32 addr, uint8 data) -> void = 0; virtual auto op_write(uint24 addr, uint8 data) -> void = 0;
virtual auto last_cycle() -> void = 0; virtual auto last_cycle() -> void = 0;
virtual auto interrupt_pending() -> bool = 0; virtual auto interrupt_pending() -> bool = 0;
virtual auto op_irq() -> void; virtual auto op_irq() -> void;
virtual auto disassembler_read(uint32 addr) -> uint8 { return 0u; } virtual auto disassembler_read(uint24 addr) -> uint8 { return 0u; }
//r65816.cpp //r65816.cpp
alwaysinline auto op_io_irq() -> void; alwaysinline auto op_io_irq() -> void;

View File

@ -36,15 +36,15 @@ struct Cartridge : property<Cartridge> {
MappedRAM ram; MappedRAM ram;
struct Mapping { struct Mapping {
function<auto (uint, uint8) -> uint8> reader; function<auto (uint24, uint8) -> uint8> reader;
function<auto (uint, uint8) -> void> writer; function<auto (uint24, uint8) -> void> writer;
string addr; string addr;
uint size = 0; uint size = 0;
uint base = 0; uint base = 0;
uint mask = 0; uint mask = 0;
Mapping() = default; Mapping() = default;
Mapping(const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&); Mapping(const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&);
Mapping(SuperFamicom::Memory&); Mapping(SuperFamicom::Memory&);
}; };
vector<Mapping> mapping; vector<Mapping> mapping;
@ -84,7 +84,7 @@ private:
//markup.cpp //markup.cpp
auto parseMarkup(const string&) -> void; auto parseMarkup(const string&) -> void;
auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void; auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void;
auto parseMarkupMap(Markup::Node, const function<uint8 (uint, uint8)>&, const function<void (uint, uint8)>&) -> void; auto parseMarkupMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
auto parseMarkupMemory(MappedRAM&, Markup::Node, uint id, bool writable) -> void; auto parseMarkupMemory(MappedRAM&, Markup::Node, uint id, bool writable) -> void;
auto parseMarkupROM(Markup::Node) -> void; auto parseMarkupROM(Markup::Node) -> void;

View File

@ -3,7 +3,7 @@ Cartridge::Mapping::Mapping(SuperFamicom::Memory& memory) {
this->writer = {&SuperFamicom::Memory::write, &memory}; this->writer = {&SuperFamicom::Memory::write, &memory};
} }
Cartridge::Mapping::Mapping(const function<uint8 (uint, uint8)>& reader, const function<void (uint, uint8)>& writer) { Cartridge::Mapping::Mapping(const function<uint8 (uint24, uint8)>& reader, const function<void (uint24, uint8)>& writer) {
this->reader = reader; this->reader = reader;
this->writer = writer; this->writer = writer;
} }
@ -51,8 +51,8 @@ auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -
auto Cartridge::parseMarkupMap( auto Cartridge::parseMarkupMap(
Markup::Node map, Markup::Node map,
const function<uint8 (uint, uint8)>& reader, const function<uint8 (uint24, uint8)>& reader,
const function<void (uint, uint8)>& writer const function<void (uint24, uint8)>& writer
) -> void { ) -> void {
Mapping m{reader, writer}; Mapping m{reader, writer};
m.addr = map["address"].text(); m.addr = map["address"].text();

View File

@ -58,7 +58,7 @@ auto ArmDSP::step(uint clocks) -> void {
//3800-3807 mirrored throughout //3800-3807 mirrored throughout
//a0 ignored //a0 ignored
auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 { auto ArmDSP::mmio_read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
uint8 data = 0x00; uint8 data = 0x00;
@ -82,7 +82,7 @@ auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
return data; return data;
} }
auto ArmDSP::mmio_write(uint addr, uint8 data) -> void { auto ArmDSP::mmio_write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 0xff06; addr &= 0xff06;

View File

@ -15,8 +15,8 @@ struct ArmDSP : Processor::ARM, Coprocessor {
auto bus_read(uint mode, uint32 addr) -> uint32 override; auto bus_read(uint mode, uint32 addr) -> uint32 override;
auto bus_write(uint mode, uint32 addr, uint32 word) -> void override; auto bus_write(uint mode, uint32 addr, uint32 word) -> void override;
auto mmio_read(uint addr, uint8 data) -> uint8; auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void; auto mmio_write(uint24 addr, uint8 data) -> void;
auto init() -> void; auto init() -> void;
auto load() -> void; auto load() -> void;

View File

@ -135,7 +135,7 @@ auto EpsonRTC::sync() -> void {
resync = true; //alert program that time has changed resync = true; //alert program that time has changed
} }
auto EpsonRTC::read(uint addr, uint8 data) -> uint8 { auto EpsonRTC::read(uint24 addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 3; addr &= 3;
@ -160,7 +160,7 @@ auto EpsonRTC::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto EpsonRTC::write(uint addr, uint8 data) -> void { auto EpsonRTC::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 3, data &= 15; addr &= 3, data &= 15;

View File

@ -11,8 +11,8 @@ struct EpsonRTC : Coprocessor {
auto reset() -> void; auto reset() -> void;
auto sync() -> void; auto sync() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -56,7 +56,7 @@ auto Event::reset() -> void {
scoreSecondsRemaining = 0; scoreSecondsRemaining = 0;
} }
auto Event::mcuRead(uint addr, uint8 data) -> uint8 { auto Event::mcuRead(uint24 addr, uint8 data) -> uint8 {
if(board == Board::CampusChallenge92) { if(board == Board::CampusChallenge92) {
uint id = 0; uint id = 0;
if(select == 0x09) id = 1; if(select == 0x09) id = 1;
@ -92,17 +92,17 @@ auto Event::mcuRead(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto Event::mcuWrite(uint addr, uint8 data) -> void { auto Event::mcuWrite(uint24 addr, uint8 data) -> void {
} }
auto Event::read(uint addr, uint8 data) -> uint8 { auto Event::read(uint24 addr, uint8 data) -> uint8 {
if(addr == 0x106000 || addr == 0xc00000) { if(addr == 0x106000 || addr == 0xc00000) {
return status; return status;
} }
return data; return data;
} }
auto Event::write(uint addr, uint8 data) -> void { auto Event::write(uint24 addr, uint8 data) -> void {
if(addr == 0x206000 || addr == 0xe00000) { if(addr == 0x206000 || addr == 0xe00000) {
select = data; select = data;
if(timer && data == 0x09) { if(timer && data == 0x09) {

View File

@ -11,11 +11,11 @@ struct Event : Coprocessor {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto mcuRead(uint addr, uint8) -> uint8; auto mcuRead(uint24 addr, uint8) -> uint8;
auto mcuWrite(uint addr, uint8) -> void; auto mcuWrite(uint24 addr, uint8) -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -18,20 +18,20 @@ struct HitachiDSP : Processor::HG51B, Coprocessor {
auto bus_write(uint24 addr, uint8 data) -> void; auto bus_write(uint24 addr, uint8 data) -> void;
//CPU ROM read/write //CPU ROM read/write
auto rom_read(uint addr, uint8 data) -> uint8; auto rom_read(uint24 addr, uint8 data) -> uint8;
auto rom_write(uint addr, uint8 data) -> void; auto rom_write(uint24 addr, uint8 data) -> void;
//CPU RAM read/write //CPU RAM read/write
auto ram_read(uint addr, uint8 data) -> uint8; auto ram_read(uint24 addr, uint8 data) -> uint8;
auto ram_write(uint addr, uint8 data) -> void; auto ram_write(uint24 addr, uint8 data) -> void;
//HG51B data RAM read/write //HG51B data RAM read/write
auto dram_read(uint addr, uint8 data) -> uint8; auto dram_read(uint24 addr, uint8 data) -> uint8;
auto dram_write(uint addr, uint8 data) -> void; auto dram_write(uint24 addr, uint8 data) -> void;
//CPU MMIO read/write //CPU MMIO read/write
auto dsp_read(uint addr, uint8 data) -> uint8; auto dsp_read(uint24 addr, uint8 data) -> uint8;
auto dsp_write(uint addr, uint8 data) -> void; auto dsp_write(uint24 addr, uint8 data) -> void;
auto firmware() const -> vector<uint8>; auto firmware() const -> vector<uint8>;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -35,7 +35,7 @@ auto HitachiDSP::bus_write(uint24 addr, uint8 data) -> void {
} }
} }
auto HitachiDSP::rom_read(uint addr, uint8 data) -> uint8 { auto HitachiDSP::rom_read(uint24 addr, uint8 data) -> uint8 {
if(co_active() == hitachidsp.thread || regs.halt) { if(co_active() == hitachidsp.thread || regs.halt) {
addr = Bus::mirror(addr, rom.size()); addr = Bus::mirror(addr, rom.size());
//if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00; //if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
@ -45,32 +45,32 @@ auto HitachiDSP::rom_read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto HitachiDSP::rom_write(uint addr, uint8 data) -> void { auto HitachiDSP::rom_write(uint24 addr, uint8 data) -> void {
} }
auto HitachiDSP::ram_read(uint addr, uint8 data) -> uint8 { auto HitachiDSP::ram_read(uint24 addr, uint8 data) -> uint8 {
if(ram.size() == 0) return 0x00; //not open bus if(ram.size() == 0) return 0x00; //not open bus
return ram.read(Bus::mirror(addr, ram.size()), data); return ram.read(Bus::mirror(addr, ram.size()), data);
} }
auto HitachiDSP::ram_write(uint addr, uint8 data) -> void { auto HitachiDSP::ram_write(uint24 addr, uint8 data) -> void {
if(ram.size() == 0) return; if(ram.size() == 0) return;
return ram.write(Bus::mirror(addr, ram.size()), data); return ram.write(Bus::mirror(addr, ram.size()), data);
} }
auto HitachiDSP::dram_read(uint addr, uint8 data) -> uint8 { auto HitachiDSP::dram_read(uint24 addr, uint8 data) -> uint8 {
addr &= 0xfff; addr &= 0xfff;
if(addr >= 0xc00) return data; if(addr >= 0xc00) return data;
return dataRAM[addr]; return dataRAM[addr];
} }
auto HitachiDSP::dram_write(uint addr, uint8 data) -> void { auto HitachiDSP::dram_write(uint24 addr, uint8 data) -> void {
addr &= 0xfff; addr &= 0xfff;
if(addr >= 0xc00) return; if(addr >= 0xc00) return;
dataRAM[addr] = data; dataRAM[addr] = data;
} }
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 { auto HitachiDSP::dsp_read(uint24 addr, uint8) -> uint8 {
addr = 0x7c00 | (addr & 0x03ff); addr = 0x7c00 | (addr & 0x03ff);
//MMIO //MMIO
@ -115,7 +115,7 @@ auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
return 0x00; return 0x00;
} }
auto HitachiDSP::dsp_write(uint addr, uint8 data) -> void { auto HitachiDSP::dsp_write(uint24 addr, uint8 data) -> void {
addr = 0x7c00 | (addr & 0x03ff); addr = 0x7c00 | (addr & 0x03ff);
//MMIO //MMIO

View File

@ -8,8 +8,8 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -1,4 +1,4 @@
auto ICD2::read(uint addr, uint8 data) -> uint8 { auto ICD2::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0x40ffff; addr &= 0x40ffff;
//LY counter //LY counter
@ -38,7 +38,7 @@ auto ICD2::read(uint addr, uint8 data) -> uint8 {
return 0x00; return 0x00;
} }
auto ICD2::write(uint addr, uint8 data) -> void { auto ICD2::write(uint24 addr, uint8 data) -> void {
addr &= 0xffff; addr &= 0xffff;
//VRAM port //VRAM port

View File

@ -26,7 +26,7 @@ auto MCC::reset() -> void {
commit(); commit();
} }
auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8 { auto MCC::memory_access(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8 {
addr = bus.mirror(addr, memory.size()); addr = bus.mirror(addr, memory.size());
if(!write) { if(!write) {
return memory.read(addr, data); return memory.read(addr, data);
@ -37,7 +37,7 @@ auto MCC::memory_access(bool write, Memory& memory, uint addr, uint8 data) -> ui
//map address=00-3f,80-bf:8000-ffff mask=0x408000 //map address=00-3f,80-bf:8000-ffff mask=0x408000
//map address=40-7d,c0-ff:0000-ffff //map address=40-7d,c0-ff:0000-ffff
auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 { auto MCC::mcu_access(bool write, uint24 addr, uint8 data) -> uint8 {
if(addr < 0x400000) { if(addr < 0x400000) {
//note: manifest maps 00-3f,80-bf:8000-ffff mask=0x408000 => 00-3f:0000-ffff //note: manifest maps 00-3f,80-bf:8000-ffff mask=0x408000 => 00-3f:0000-ffff
//the intention is consistency in pre-decoding as much as possible //the intention is consistency in pre-decoding as much as possible
@ -88,15 +88,15 @@ auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
return 0x00; return 0x00;
} }
auto MCC::mcu_read(uint addr, uint8 data) -> uint8 { auto MCC::mcu_read(uint24 addr, uint8 data) -> uint8 {
return mcu_access(false, addr, data); return mcu_access(false, addr, data);
} }
auto MCC::mcu_write(uint addr, uint8 data) -> void { auto MCC::mcu_write(uint24 addr, uint8 data) -> void {
mcu_access(true, addr, data); mcu_access(true, addr, data);
} }
auto MCC::read(uint addr, uint8 data) -> uint8 { auto MCC::read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15; uint8 n = (addr >> 16) & 15;
return r[n]; return r[n];
@ -105,7 +105,7 @@ auto MCC::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto MCC::write(uint addr, uint8 data) -> void { auto MCC::write(uint24 addr, uint8 data) -> void {
if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000 if((addr & 0xf0ffff) == 0x005000) { //$00-0f:5000
uint8 n = (addr >> 16) & 15; uint8 n = (addr >> 16) & 15;
r[n] = data; r[n] = data;

View File

@ -10,14 +10,14 @@ struct MCC {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8; auto memory_access(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8;
auto mcu_access(bool write, uint addr, uint8 data) -> uint8; auto mcu_access(bool write, uint24 addr, uint8 data) -> uint8;
auto mcu_read(uint addr, uint8 data) -> uint8; auto mcu_read(uint24 addr, uint8 data) -> uint8;
auto mcu_write(uint addr, uint8 data) -> void; auto mcu_write(uint24 addr, uint8 data) -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto commit() -> void; auto commit() -> void;

View File

@ -119,18 +119,20 @@ auto MSU1::audioOpen() -> void {
mmio.audioError = true; mmio.audioError = true;
} }
auto MSU1::mmioRead(uint addr, uint8) -> uint8 { auto MSU1::mmioRead(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr = 0x2000 | (addr & 7); addr = 0x2000 | (addr & 7);
switch(addr) { switch(addr) {
case 0x2000: case 0x2000:
return (mmio.dataBusy << 7) return (
| (mmio.audioBusy << 6) mmio.dataBusy << 7
| (mmio.audioRepeat << 5) | mmio.audioBusy << 6
| (mmio.audioPlay << 4) | mmio.audioRepeat << 5
| (mmio.audioError << 3) | mmio.audioPlay << 4
| (Revision << 0); | mmio.audioError << 3
| Revision << 0
);
case 0x2001: case 0x2001:
if(mmio.dataBusy) return 0x00; if(mmio.dataBusy) return 0x00;
if(dataFile.end()) return 0x00; if(dataFile.end()) return 0x00;
@ -145,20 +147,20 @@ auto MSU1::mmioRead(uint addr, uint8) -> uint8 {
} }
} }
auto MSU1::mmioWrite(uint addr, uint8 data) -> void { auto MSU1::mmioWrite(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr = 0x2000 | (addr & 7); addr = 0x2000 | (addr & 7);
switch(addr) { switch(addr) {
case 0x2000: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffffff00) | (data << 0); break; case 0x2000: mmio.dataSeekOffset.byte(0) = data; break;
case 0x2001: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffff00ff) | (data << 8); break; case 0x2001: mmio.dataSeekOffset.byte(1) = data; break;
case 0x2002: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xff00ffff) | (data << 16); break; case 0x2002: mmio.dataSeekOffset.byte(2) = data; break;
case 0x2003: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0x00ffffff) | (data << 24); case 0x2003: mmio.dataSeekOffset.byte(3) = data;
mmio.dataReadOffset = mmio.dataSeekOffset; mmio.dataReadOffset = mmio.dataSeekOffset;
dataOpen(); dataOpen();
break; break;
case 0x2004: mmio.audioTrack = (mmio.audioTrack & 0xff00) | (data << 0); break; case 0x2004: mmio.audioTrack.byte(0) = data; break;
case 0x2005: mmio.audioTrack = (mmio.audioTrack & 0x00ff) | (data << 8); case 0x2005: mmio.audioTrack.byte(1) = data;
mmio.audioPlayOffset = 8; mmio.audioPlayOffset = 8;
if(mmio.audioTrack == mmio.audioResumeTrack) { if(mmio.audioTrack == mmio.audioResumeTrack) {
mmio.audioPlayOffset = mmio.audioResumeOffset; mmio.audioPlayOffset = mmio.audioResumeOffset;
@ -173,9 +175,9 @@ auto MSU1::mmioWrite(uint addr, uint8 data) -> void {
case 0x2007: case 0x2007:
if(mmio.audioBusy) break; if(mmio.audioBusy) break;
if(mmio.audioError) break; if(mmio.audioError) break;
bool audioResume = data & 4; bool audioResume = data.bit(2);
mmio.audioRepeat = data & 2; mmio.audioRepeat = data.bit(1);
mmio.audioPlay = data & 1; mmio.audioPlay = data.bit(0);
if(!mmio.audioPlay && audioResume) { if(!mmio.audioPlay && audioResume) {
mmio.audioResumeTrack = mmio.audioTrack; mmio.audioResumeTrack = mmio.audioTrack;
mmio.audioResumeOffset = mmio.audioPlayOffset; mmio.audioResumeOffset = mmio.audioPlayOffset;

View File

@ -10,8 +10,8 @@ struct MSU1 : Coprocessor {
auto dataOpen() -> void; auto dataOpen() -> void;
auto audioOpen() -> void; auto audioOpen() -> void;
auto mmioRead(uint addr, uint8 data) -> uint8; auto mmioRead(uint24 addr, uint8 data) -> uint8;
auto mmioWrite(uint addr, uint8 data) -> void; auto mmioWrite(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -15,7 +15,7 @@ auto NECDSP::main() -> void {
synchronizeCPU(); synchronizeCPU();
} }
auto NECDSP::read(uint addr, uint8) -> uint8 { auto NECDSP::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
if(addr & 1) { if(addr & 1) {
return uPD96050::readSR(); return uPD96050::readSR();
@ -24,7 +24,7 @@ auto NECDSP::read(uint addr, uint8) -> uint8 {
} }
} }
auto NECDSP::write(uint addr, uint8 data) -> void { auto NECDSP::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
if(addr & 1) { if(addr & 1) {
return uPD96050::writeSR(data); return uPD96050::writeSR(data);
@ -33,12 +33,12 @@ auto NECDSP::write(uint addr, uint8 data) -> void {
} }
} }
auto NECDSP::readRAM(uint addr, uint8) -> uint8 { auto NECDSP::readRAM(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
return uPD96050::readDP(addr); return uPD96050::readDP(addr);
} }
auto NECDSP::writeRAM(uint addr, uint8 data) -> void { auto NECDSP::writeRAM(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
return uPD96050::writeDP(addr, data); return uPD96050::writeDP(addr, data);
} }

View File

@ -2,11 +2,11 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
static auto Enter() -> void; static auto Enter() -> void;
auto main() -> void; auto main() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto readRAM(uint addr, uint8 data) -> uint8; auto readRAM(uint24 addr, uint8 data) -> uint8;
auto writeRAM(uint addr, uint8 data) -> void; auto writeRAM(uint24 addr, uint8 data) -> void;
auto init() -> void; auto init() -> void;
auto load() -> void; auto load() -> void;

View File

@ -23,11 +23,11 @@ auto NSS::set_dip(uint16 dip) -> void {
this->dip = dip; this->dip = dip;
} }
auto NSS::read(uint, uint8) -> uint8 { auto NSS::read(uint24, uint8) -> uint8 {
return dip; return dip;
} }
auto NSS::write(uint, uint8) -> void { auto NSS::write(uint24, uint8) -> void {
} }
} }

View File

@ -6,8 +6,8 @@ struct NSS {
auto reset() -> void; auto reset() -> void;
auto set_dip(uint16 dip) -> void; auto set_dip(uint16 dip) -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
uint8 dip = 0x00; uint8 dip = 0x00;
}; };

View File

@ -24,7 +24,7 @@ auto OBC1::reset() -> void {
status.shift = (ramRead(0x1ff6) & 3) << 1; status.shift = (ramRead(0x1ff6) & 3) << 1;
} }
auto OBC1::read(uint addr, uint8) -> uint8 { auto OBC1::read(uint24 addr, uint8) -> uint8 {
addr &= 0x1fff; addr &= 0x1fff;
switch(addr) { switch(addr) {
@ -38,7 +38,7 @@ auto OBC1::read(uint addr, uint8) -> uint8 {
return ramRead(addr); return ramRead(addr);
} }
auto OBC1::write(uint addr, uint8 data) -> void { auto OBC1::write(uint24 addr, uint8 data) -> void {
addr &= 0x1fff; addr &= 0x1fff;
switch(addr) { switch(addr) {

View File

@ -5,8 +5,8 @@ struct OBC1 {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -4,12 +4,12 @@ auto SA1::CPUIRAM::size() const -> uint {
return sa1.iram.size(); return sa1.iram.size();
} }
auto SA1::CPUIRAM::read(uint addr, uint8) -> uint8 { auto SA1::CPUIRAM::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
return sa1.iram.read(addr & 0x07ff); return sa1.iram.read(addr & 0x07ff);
} }
auto SA1::CPUIRAM::write(uint addr, uint8 data) -> void { auto SA1::CPUIRAM::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
sa1.iram.write(addr & 0x07ff, data); sa1.iram.write(addr & 0x07ff, data);
} }
@ -18,13 +18,13 @@ auto SA1::CPUBWRAM::size() const -> uint {
return sa1.bwram.size(); return sa1.bwram.size();
} }
auto SA1::CPUBWRAM::read(uint addr, uint8) -> uint8 { auto SA1::CPUBWRAM::read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
if(dma) return sa1.dma_cc1_read(addr); if(dma) return sa1.dma_cc1_read(addr);
return sa1.bwram.read(addr); return sa1.bwram.read(addr);
} }
auto SA1::CPUBWRAM::write(uint addr, uint8 data) -> void { auto SA1::CPUBWRAM::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
sa1.bwram.write(addr, data); sa1.bwram.write(addr, data);
} }

View File

@ -1,12 +1,12 @@
struct CPUIRAM : Memory { struct CPUIRAM : Memory {
auto size() const -> uint; auto size() const -> uint;
alwaysinline auto read(uint, uint8 = 0) -> uint8; alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void; alwaysinline auto write(uint24, uint8) -> void;
} cpuiram; } cpuiram;
struct CPUBWRAM : Memory { struct CPUBWRAM : Memory {
auto size() const -> uint; auto size() const -> uint;
alwaysinline auto read(uint, uint8 = 0) -> uint8; alwaysinline auto read(uint24, uint8 = 0) -> uint8;
alwaysinline auto write(uint, uint8) -> void; alwaysinline auto write(uint24, uint8) -> void;
bool dma; bool dma;
} cpubwram; } cpubwram;

View File

@ -1,4 +1,4 @@
auto SA1::bus_read(uint addr, uint8 data) -> uint8 { auto SA1::bus_read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_read(addr, data); return mmio_read(addr, data);
} }
@ -40,7 +40,7 @@ auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SA1::bus_write(uint addr, uint8 data) -> void { auto SA1::bus_write(uint24 addr, uint8 data) -> void {
if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff if((addr & 0x40fe00) == 0x002200) { //$00-3f,80-bf:2200-23ff
return mmio_write(addr, data); return mmio_write(addr, data);
} }
@ -74,7 +74,7 @@ auto SA1::bus_write(uint addr, uint8 data) -> void {
//this is used both to keep VBR-reads from accessing MMIO registers, and //this is used both to keep VBR-reads from accessing MMIO registers, and
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access //to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports. //these ports.
auto SA1::vbr_read(uint addr, uint8 data) -> uint8 { auto SA1::vbr_read(uint24 addr, uint8 data) -> uint8 {
if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff if((addr & 0x408000) == 0x008000) { //$00-3f,80-bf:8000-ffff
addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff); addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff);
return mmcrom_read(addr, data); return mmcrom_read(addr, data);
@ -112,13 +112,13 @@ auto SA1::op_io() -> void {
tick(); tick();
} }
auto SA1::op_read(uint32 addr) -> uint8 { auto SA1::op_read(uint24 addr) -> uint8 {
tick(); tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr, regs.mdr); return bus_read(addr, regs.mdr);
} }
auto SA1::op_write(uint32 addr, uint8 data) -> void { auto SA1::op_write(uint24 addr, uint8 data) -> void {
tick(); tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
bus_write(addr, regs.mdr = data); bus_write(addr, regs.mdr = data);
@ -127,7 +127,7 @@ auto SA1::op_write(uint32 addr, uint8 data) -> void {
//note: addresses are translated prior to invoking this function: //note: addresses are translated prior to invoking this function:
//$00-3f,80-bf:8000-ffff mask=0x408000 => $00-3f:0000-ffff //$00-3f,80-bf:8000-ffff mask=0x408000 => $00-3f:0000-ffff
//$c0-ff:0000-ffff mask=0 //$c0-ff:0000-ffff mask=0
auto SA1::mmcrom_read(uint addr, uint8) -> uint8 { auto SA1::mmcrom_read(uint24 addr, uint8) -> uint8 {
//reset vector overrides //reset vector overrides
if((addr & 0xffffe0) == 0x007fe0) { //$00:ffe0-ffef if((addr & 0xffffe0) == 0x007fe0) { //$00:ffe0-ffef
if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0; if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
@ -166,10 +166,10 @@ auto SA1::mmcrom_read(uint addr, uint8) -> uint8 {
return 0x00; return 0x00;
} }
auto SA1::mmcrom_write(uint addr, uint8 data) -> void { auto SA1::mmcrom_write(uint24 addr, uint8 data) -> void {
} }
auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 { auto SA1::mmcbwram_read(uint24 addr, uint8 data) -> uint8 {
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size()); addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
@ -183,7 +183,7 @@ auto SA1::mmcbwram_read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SA1::mmcbwram_write(uint addr, uint8 data) -> void { auto SA1::mmcbwram_write(uint24 addr, uint8 data) -> void {
if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff if(addr < 0x2000) { //$00-3f,80-bf:6000-7fff
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size()); addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());

View File

@ -1,16 +1,16 @@
auto bus_read(uint addr, uint8 data) -> uint8; auto bus_read(uint24 addr, uint8 data) -> uint8;
auto bus_write(uint addr, uint8 data) -> void; auto bus_write(uint24 addr, uint8 data) -> void;
auto vbr_read(uint addr, uint8 data = 0) -> uint8; auto vbr_read(uint24 addr, uint8 data = 0) -> uint8;
alwaysinline auto op_io() -> void; alwaysinline auto op_io() -> void override;
alwaysinline auto op_read(uint32 addr) -> uint8; alwaysinline auto op_read(uint24 addr) -> uint8 override;
alwaysinline auto op_write(uint32 addr, uint8 data) -> void; alwaysinline auto op_write(uint24 addr, uint8 data) -> void override;
auto mmcrom_read(uint addr, uint8 data) -> uint8; auto mmcrom_read(uint24 addr, uint8 data) -> uint8;
auto mmcrom_write(uint addr, uint8 data) -> void; auto mmcrom_write(uint24 addr, uint8 data) -> void;
auto mmcbwram_read(uint addr, uint8 data) -> uint8; auto mmcbwram_read(uint24 addr, uint8 data) -> uint8;
auto mmcbwram_write(uint addr, uint8 data) -> void; auto mmcbwram_write(uint24 addr, uint8 data) -> void;
auto mmc_sa1_read(uint addr, uint8 data) -> uint8; auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
auto mmc_sa1_write(uint addr, uint8 data) -> void; auto mmc_sa1_write(uint addr, uint8 data) -> void;

View File

@ -445,7 +445,7 @@ auto SA1::mmio_r230e() -> uint8 {
return 0x01; //true value unknown return 0x01; //true value unknown
} }
auto SA1::mmio_read(uint addr, uint8) -> uint8 { auto SA1::mmio_read(uint24 addr, uint8) -> uint8 {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU()); (co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff; addr &= 0xffff;
@ -470,7 +470,7 @@ auto SA1::mmio_read(uint addr, uint8) -> uint8 {
return 0x00; return 0x00;
} }
auto SA1::mmio_write(uint addr, uint8 data) -> void { auto SA1::mmio_write(uint24 addr, uint8 data) -> void {
(co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU()); (co_active() == cpu.thread ? cpu.synchronizeCoprocessors() : synchronizeCPU());
addr &= 0xffff; addr &= 0xffff;

View File

@ -1,5 +1,5 @@
auto mmio_read(uint addr, uint8 data) -> uint8; auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void; auto mmio_write(uint24 addr, uint8 data) -> void;
struct MMIO { struct MMIO {
//$2200 CCNT //$2200 CCNT

View File

@ -17,11 +17,11 @@ struct SA1 : Processor::R65816, public Coprocessor {
static auto Enter() -> void; static auto Enter() -> void;
auto main() -> void; auto main() -> void;
auto tick() -> void; auto tick() -> void;
auto op_irq() -> void; auto op_irq() -> void override;
alwaysinline auto trigger_irq() -> void; alwaysinline auto trigger_irq() -> void;
alwaysinline auto last_cycle() -> void; alwaysinline auto last_cycle() -> void override;
alwaysinline auto interrupt_pending() -> bool; alwaysinline auto interrupt_pending() -> bool override;
auto init() -> void; auto init() -> void;
auto load() -> void; auto load() -> void;

View File

@ -41,7 +41,7 @@ auto SDD1::reset() -> void {
} }
} }
auto SDD1::read(uint addr, uint8 data) -> uint8 { auto SDD1::read(uint24 addr, uint8 data) -> uint8 {
addr = 0x4800 | (addr & 7); addr = 0x4800 | (addr & 7);
switch(addr) { switch(addr) {
@ -54,7 +54,7 @@ auto SDD1::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SDD1::write(uint addr, uint8 data) -> void { auto SDD1::write(uint24 addr, uint8 data) -> void {
addr = 0x4800 | (addr & 7); addr = 0x4800 | (addr & 7);
switch(addr) { switch(addr) {
@ -68,11 +68,11 @@ auto SDD1::write(uint addr, uint8 data) -> void {
} }
} }
auto SDD1::dma_read(uint addr, uint8 data) -> uint8 { auto SDD1::dma_read(uint24 addr, uint8 data) -> uint8 {
return cpu.mmio_read(addr, data); return cpu.mmio_read(addr, data);
} }
auto SDD1::dma_write(uint addr, uint8 data) -> void { auto SDD1::dma_write(uint24 addr, uint8 data) -> void {
uint channel = (addr >> 4) & 7; uint channel = (addr >> 4) & 7;
switch(addr & 15) { switch(addr & 15) {
case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break; case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
@ -85,7 +85,7 @@ auto SDD1::dma_write(uint addr, uint8 data) -> void {
return cpu.mmio_write(addr, data); return cpu.mmio_write(addr, data);
} }
auto SDD1::mmc_read(uint addr) -> uint8 { auto SDD1::mmc_read(uint24 addr) -> uint8 {
return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff)); return rom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
} }
@ -107,7 +107,7 @@ auto SDD1::mmc_read(uint addr) -> uint8 {
// //
//the actual S-DD1 transfer can occur on any channel, but it is most likely limited to //the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
//one transfer per $420b write (for spooling purposes). however, this is not known for certain. //one transfer per $420b write (for spooling purposes). however, this is not known for certain.
auto SDD1::mcurom_read(uint addr, uint8) -> uint8 { auto SDD1::mcurom_read(uint24 addr, uint8) -> uint8 {
//map address=00-3f,80-bf:8000-ffff mask=0x808000 => 00-1f:0000-ffff //map address=00-3f,80-bf:8000-ffff mask=0x808000 => 00-1f:0000-ffff
if(addr < 0x200000) { if(addr < 0x200000) {
return rom.read(addr); return rom.read(addr);
@ -143,16 +143,16 @@ auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
return mmc_read(addr); return mmc_read(addr);
} }
auto SDD1::mcurom_write(uint addr, uint8 data) -> void { auto SDD1::mcurom_write(uint24 addr, uint8 data) -> void {
} }
//map address=00-3f,80-bf:6000-7fff mask=0xe000 //map address=00-3f,80-bf:6000-7fff mask=0xe000
//map address=70-7d:0000-7fff mask=0x8000 //map address=70-7d:0000-7fff mask=0x8000
auto SDD1::mcuram_read(uint addr, uint8 data) -> uint8 { auto SDD1::mcuram_read(uint24 addr, uint8 data) -> uint8 {
return ram.read(addr & 0x1fff, data); return ram.read(addr & 0x1fff, data);
} }
auto SDD1::mcuram_write(uint addr, uint8 data) -> void { auto SDD1::mcuram_write(uint24 addr, uint8 data) -> void {
return ram.write(addr & 0x1fff, data); return ram.write(addr & 0x1fff, data);
} }

View File

@ -5,19 +5,19 @@ struct SDD1 {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto dma_read(uint addr, uint8 data) -> uint8; auto dma_read(uint24 addr, uint8 data) -> uint8;
auto dma_write(uint addr, uint8 data) -> void; auto dma_write(uint24 addr, uint8 data) -> void;
auto mmc_read(uint addr) -> uint8; auto mmc_read(uint24 addr) -> uint8;
auto mcurom_read(uint addr, uint8 data) -> uint8; auto mcurom_read(uint24 addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void; auto mcurom_write(uint24 addr, uint8 data) -> void;
auto mcuram_read(uint addr, uint8 data) -> uint8; auto mcuram_read(uint24 addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void; auto mcuram_write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -59,7 +59,7 @@ auto SharpRTC::sync() -> void {
weekday = timeinfo->tm_wday; weekday = timeinfo->tm_wday;
} }
auto SharpRTC::read(uint addr, uint8 data) -> uint8 { auto SharpRTC::read(uint24 addr, uint8 data) -> uint8 {
addr &= 1; addr &= 1;
if(addr == 0) { if(addr == 0) {
@ -79,7 +79,7 @@ auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SharpRTC::write(uint addr, uint8 data) -> void { auto SharpRTC::write(uint24 addr, uint8 data) -> void {
addr &= 1, data &= 15; addr &= 1, data &= 15;
if(addr == 1) { if(addr == 1) {

View File

@ -9,8 +9,8 @@ struct SharpRTC : Coprocessor {
auto reset() -> void; auto reset() -> void;
auto sync() -> void; auto sync() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -104,7 +104,7 @@ auto SPC7110::reset() -> void {
r4834 = 0x00; r4834 = 0x00;
} }
auto SPC7110::read(uint addr, uint8 data) -> uint8 { auto SPC7110::read(uint24 addr, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800 if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808 if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
@ -188,7 +188,7 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SPC7110::write(uint addr, uint8 data) -> void { auto SPC7110::write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800 if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808 if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
@ -252,7 +252,7 @@ auto SPC7110::write(uint addr, uint8 data) -> void {
//map address=00-3f,80-bf:8000-ffff mask=0x800000 => 00-3f:8000-ffff //map address=00-3f,80-bf:8000-ffff mask=0x800000 => 00-3f:8000-ffff
//map address=c0-ff:0000-ffff mask=0xc00000 => c0-ff:0000-ffff //map address=c0-ff:0000-ffff mask=0xc00000 => c0-ff:0000-ffff
auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 { auto SPC7110::mcurom_read(uint24 addr, uint8 data) -> uint8 {
uint mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM uint mask = (1 << (r4834 & 3)) - 1; //8mbit, 16mbit, 32mbit, 64mbit DROM
if(addr < 0x100000) { //$00-0f,80-8f:8000-ffff; $c0-cf:0000-ffff if(addr < 0x100000) { //$00-0f,80-8f:8000-ffff; $c0-cf:0000-ffff
@ -288,7 +288,7 @@ auto SPC7110::mcurom_read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto SPC7110::mcurom_write(uint addr, uint8 data) -> void { auto SPC7110::mcurom_write(uint24 addr, uint8 data) -> void {
} }
//=============== //===============
@ -296,7 +296,7 @@ auto SPC7110::mcurom_write(uint addr, uint8 data) -> void {
//=============== //===============
//map address=00-3f,80-bf:6000-7fff mask=0x80e000 => 00-07:0000-ffff //map address=00-3f,80-bf:6000-7fff mask=0x80e000 => 00-07:0000-ffff
auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 { auto SPC7110::mcuram_read(uint24 addr, uint8) -> uint8 {
if(r4830 & 0x80) { if(r4830 & 0x80) {
addr = bus.mirror(addr, ram.size()); addr = bus.mirror(addr, ram.size());
return ram.read(addr); return ram.read(addr);
@ -304,7 +304,7 @@ auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
return 0x00; return 0x00;
} }
auto SPC7110::mcuram_write(uint addr, uint8 data) -> void { auto SPC7110::mcuram_write(uint24 addr, uint8 data) -> void {
if(r4830 & 0x80) { if(r4830 & 0x80) {
addr = bus.mirror(addr, ram.size()); addr = bus.mirror(addr, ram.size());
ram.write(addr, data); ram.write(addr, data);

View File

@ -14,14 +14,14 @@ struct SPC7110 : Coprocessor {
auto add_clocks(uint clocks) -> void; auto add_clocks(uint clocks) -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
auto mcurom_read(uint addr, uint8 data) -> uint8; auto mcurom_read(uint24 addr, uint8 data) -> uint8;
auto mcurom_write(uint addr, uint8 data) -> void; auto mcurom_write(uint24 addr, uint8 data) -> void;
auto mcuram_read(uint addr, uint8 data) -> uint8; auto mcuram_read(uint24 addr, uint8 data) -> uint8;
auto mcuram_write(uint addr, uint8 data) -> void; auto mcuram_write(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;

View File

@ -4,7 +4,7 @@ auto SuperFX::CPUROM::size() const -> uint {
return superfx.rom.size(); return superfx.rom.size();
} }
auto SuperFX::CPUROM::read(uint addr, uint8 data) -> uint8 { auto SuperFX::CPUROM::read(uint24 addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ron) { if(superfx.regs.sfr.g && superfx.regs.scmr.ron) {
static const uint8 vector[16] = { static const uint8 vector[16] = {
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
@ -15,7 +15,7 @@ auto SuperFX::CPUROM::read(uint addr, uint8 data) -> uint8 {
return superfx.rom.read(addr, data); return superfx.rom.read(addr, data);
} }
auto SuperFX::CPUROM::write(uint addr, uint8 data) -> void { auto SuperFX::CPUROM::write(uint24 addr, uint8 data) -> void {
superfx.rom.write(addr, data); superfx.rom.write(addr, data);
} }
@ -23,11 +23,11 @@ auto SuperFX::CPURAM::size() const -> uint {
return superfx.ram.size(); return superfx.ram.size();
} }
auto SuperFX::CPURAM::read(uint addr, uint8 data) -> uint8 { auto SuperFX::CPURAM::read(uint24 addr, uint8 data) -> uint8 {
if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return data; if(superfx.regs.sfr.g && superfx.regs.scmr.ran) return data;
return superfx.ram.read(addr, data); return superfx.ram.read(addr, data);
} }
auto SuperFX::CPURAM::write(uint addr, uint8 data) -> void { auto SuperFX::CPURAM::write(uint24 addr, uint8 data) -> void {
superfx.ram.write(addr, data); superfx.ram.write(addr, data);
} }

View File

@ -1,11 +1,11 @@
struct CPUROM : Memory { struct CPUROM : Memory {
auto size() const -> uint; auto size() const -> uint;
auto read(uint, uint8) -> uint8; auto read(uint24, uint8) -> uint8;
auto write(uint, uint8) -> void; auto write(uint24, uint8) -> void;
} cpurom; } cpurom;
struct CPURAM : Memory { struct CPURAM : Memory {
auto size() const -> uint; auto size() const -> uint;
auto read(uint, uint8) -> uint8; auto read(uint24, uint8) -> uint8;
auto write(uint, uint8) -> void; auto write(uint24, uint8) -> void;
} cpuram; } cpuram;

View File

@ -1,4 +1,4 @@
auto SuperFX::mmio_read(uint addr, uint8) -> uint8 { auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 0xffff; addr &= 0xffff;
@ -50,7 +50,7 @@ auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
return 0x00; return 0x00;
} }
auto SuperFX::mmio_write(uint addr, uint8 data) -> void { auto SuperFX::mmio_write(uint24 addr, uint8 data) -> void {
cpu.synchronizeCoprocessors(); cpu.synchronizeCoprocessors();
addr &= 0xffff; addr &= 0xffff;

View File

@ -1,2 +1,2 @@
auto mmio_read(uint addr, uint8 data) -> uint8; auto mmio_read(uint24 addr, uint8 data) -> uint8;
auto mmio_write(uint addr, uint8 data) -> void; auto mmio_write(uint24 addr, uint8 data) -> void;

View File

@ -13,7 +13,7 @@ auto CPU::op_io() -> void {
alu_edge(); alu_edge();
} }
auto CPU::op_read(uint32 addr) -> uint8 { auto CPU::op_read(uint24 addr) -> uint8 {
status.clock_count = speed(addr); status.clock_count = speed(addr);
dma_edge(); dma_edge();
add_clocks(status.clock_count - 4); add_clocks(status.clock_count - 4);
@ -24,7 +24,7 @@ auto CPU::op_read(uint32 addr) -> uint8 {
return regs.mdr; return regs.mdr;
} }
auto CPU::op_write(uint32 addr, uint8 data) -> void { auto CPU::op_write(uint24 addr, uint8 data) -> void {
alu_edge(); alu_edge();
status.clock_count = speed(addr); status.clock_count = speed(addr);
dma_edge(); dma_edge();
@ -33,7 +33,7 @@ auto CPU::op_write(uint32 addr, uint8 data) -> void {
debugger.op_write(addr, regs.mdr); debugger.op_write(addr, regs.mdr);
} }
auto CPU::speed(uint addr) const -> uint { auto CPU::speed(uint24 addr) const -> uint {
if(addr & 0x408000) { if(addr & 0x408000) {
if(addr & 0x800000) return status.rom_speed; if(addr & 0x800000) return status.rom_speed;
return 8; return 8;
@ -43,6 +43,6 @@ auto CPU::speed(uint addr) const -> uint {
return 12; return 12;
} }
auto CPU::disassembler_read(uint32 addr) -> uint8 { auto CPU::disassembler_read(uint24 addr) -> uint8 {
return bus.read(addr, regs.mdr); return bus.read(addr, regs.mdr);
} }

View File

@ -1,6 +1,6 @@
auto op_io() -> void; auto op_io() -> void override;
auto op_read(uint32 addr) -> uint8; auto op_read(uint24 addr) -> uint8 override;
auto op_write(uint32 addr, uint8 data) -> void; auto op_write(uint24 addr, uint8 data) -> void override;
alwaysinline auto speed(uint addr) const -> uint; alwaysinline auto speed(uint24 addr) const -> uint;
auto disassembler_read(uint32 addr) -> uint8; auto disassembler_read(uint24 addr) -> uint8 override;

View File

@ -8,8 +8,8 @@ auto eBoot::init() -> void {
} }
auto eBoot::load() -> void { auto eBoot::load() -> void {
resetVector = bus.read(0xfffc, 0x00) << 0; resetVector.byte(0) = bus.read(0xfffc, 0x00);
resetVector |= bus.read(0xfffd, 0x00) << 8; resetVector.byte(1) = bus.read(0xfffd, 0x00);
for(auto& byte : ram) byte = 0xdb; //stp for(auto& byte : ram) byte = 0xdb; //stp
ram[0] = 0x6c; //jmp ($fffc) ram[0] = 0x6c; //jmp ($fffc)
@ -35,15 +35,15 @@ auto eBoot::reset() -> void {
booted = false; booted = false;
} }
auto eBoot::read(uint addr, uint8 data) -> uint8 { auto eBoot::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0x40ffff; addr &= 0x40ffff;
if(addr == 0xfffc) return booted ? resetVector >> 0 : 0x84; if(addr == 0xfffc) return booted ? resetVector.byte(0) : (uint8)0x84;
if(addr == 0xfffd) return booted ? resetVector >> 8 : (booted = true, 0x21); if(addr == 0xfffd) return booted ? resetVector.byte(1) : (booted = true, (uint8)0x21);
if(addr >= 0x2184 && addr <= 0x21ff) return ram[addr - 0x2184]; if(addr >= 0x2184 && addr <= 0x21ff) return ram[addr - 0x2184];
return data; return data;
} }
auto eBoot::write(uint addr, uint8 data) -> void { auto eBoot::write(uint24 addr, uint8 data) -> void {
} }
} }

View File

@ -5,13 +5,13 @@ struct eBoot : Memory {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
private: private:
bool booted = false; bool booted = false;
uint16 resetVector = 0; uint16 resetVector;
uint8 ram[124] = {0}; uint8 ram[124];
}; };
extern eBoot eboot; extern eBoot eboot;

View File

@ -22,7 +22,7 @@ auto Satellaview::reset() -> void {
memory::fill(&regs, sizeof regs); memory::fill(&regs, sizeof regs);
} }
auto Satellaview::read(uint addr, uint8 data) -> uint8 { auto Satellaview::read(uint24 addr, uint8 data) -> uint8 {
addr &= 0xffff; addr &= 0xffff;
switch(addr) { switch(addr) {
@ -80,7 +80,7 @@ auto Satellaview::read(uint addr, uint8 data) -> uint8 {
return data; return data;
} }
auto Satellaview::write(uint addr, uint8 data) -> void { auto Satellaview::write(uint24 addr, uint8 data) -> void {
addr &= 0xffff; addr &= 0xffff;
switch(addr) { switch(addr) {

View File

@ -5,8 +5,8 @@ struct Satellaview : Memory {
auto power() -> void; auto power() -> void;
auto reset() -> void; auto reset() -> void;
auto read(uint addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
private: private:
struct { struct {

View File

@ -10,10 +10,10 @@ StaticRAM::~StaticRAM() { delete[] data_; }
auto StaticRAM::data() -> uint8* { return data_; } auto StaticRAM::data() -> uint8* { return data_; }
auto StaticRAM::size() const -> uint { return size_; } auto StaticRAM::size() const -> uint { return size_; }
auto StaticRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; } auto StaticRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
auto StaticRAM::write(uint addr, uint8 data) -> void { data_[addr] = data; } auto StaticRAM::write(uint24 addr, uint8 data) -> void { data_[addr] = data; }
auto StaticRAM::operator[](uint addr) -> uint8& { return data_[addr]; } auto StaticRAM::operator[](uint24 addr) -> uint8& { return data_[addr]; }
auto StaticRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; } auto StaticRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
//MappedRAM //MappedRAM
@ -48,9 +48,9 @@ auto MappedRAM::write_protect(bool status) -> void { write_protect_ = status; }
auto MappedRAM::data() -> uint8* { return data_; } auto MappedRAM::data() -> uint8* { return data_; }
auto MappedRAM::size() const -> uint { return size_; } auto MappedRAM::size() const -> uint { return size_; }
auto MappedRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; } auto MappedRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
auto MappedRAM::write(uint addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; } auto MappedRAM::write(uint24 addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
auto MappedRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; } auto MappedRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
//Bus //Bus
@ -79,16 +79,14 @@ auto Bus::reduce(uint addr, uint mask) -> uint {
return addr; return addr;
} }
auto Bus::read(uint addr, uint8 data) -> uint8 { auto Bus::read(uint24 addr, uint8 data) -> uint8 {
data = reader[lookup[addr]](target[addr], data); data = reader[lookup[addr]](target[addr], data);
if(cheat.enable()) { if(cheat.enable()) {
if(auto result = cheat.find(addr, data)) return result(); if(auto result = cheat.find(addr, data)) return result();
} }
return data; return data;
} }
auto Bus::write(uint addr, uint8 data) -> void { auto Bus::write(uint24 addr, uint8 data) -> void {
return writer[lookup[addr]](target[addr], data); return writer[lookup[addr]](target[addr], data);
} }

View File

@ -15,8 +15,8 @@ Bus::~Bus() {
} }
auto Bus::reset() -> void { auto Bus::reset() -> void {
function<auto (uint, uint8) -> uint8> reader = [](uint, uint8 data) { return data; }; function<auto (uint24, uint8) -> uint8> reader = [](uint24, uint8 data) { return data; };
function<auto (uint, uint8) -> void> writer = [](uint, uint8) {}; function<auto (uint24, uint8) -> void> writer = [](uint24, uint8) {};
idcount = 0; idcount = 0;
map(reader, writer, 0x00, 0xff, 0x0000, 0xffff); map(reader, writer, 0x00, 0xff, 0x0000, 0xffff);
@ -42,13 +42,13 @@ auto Bus::map() -> void {
} }
auto Bus::map( auto Bus::map(
const function<uint8 (uint, uint8)>& reader, const function<uint8 (uint24, uint8)>& reader,
const function<void (uint, uint8)>& writer, const function<void (uint24, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi, uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
uint size, uint base, uint mask uint size, uint base, uint mask
) -> void { ) -> void {
assert(banklo <= bankhi && bankhi <= 0xff); assert(banklo <= bankhi);
assert(addrlo <= addrhi && addrhi <= 0xffff); assert(addrlo <= addrhi);
assert(idcount < 255); assert(idcount < 255);
uint id = idcount++; uint id = idcount++;

View File

@ -1,7 +1,7 @@
struct Memory { struct Memory {
virtual inline auto size() const -> uint; virtual inline auto size() const -> uint;
virtual auto read(uint addr, uint8 data = 0) -> uint8 = 0; virtual auto read(uint24 addr, uint8 data = 0) -> uint8 = 0;
virtual auto write(uint addr, uint8 data) -> void = 0; virtual auto write(uint24 addr, uint8 data) -> void = 0;
}; };
struct StaticRAM : Memory { struct StaticRAM : Memory {
@ -11,10 +11,10 @@ struct StaticRAM : Memory {
inline auto data() -> uint8*; inline auto data() -> uint8*;
inline auto size() const -> uint; inline auto size() const -> uint;
inline auto read(uint addr, uint8 data = 0) -> uint8; inline auto read(uint24 addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void; inline auto write(uint24 addr, uint8 data) -> void;
inline auto operator[](uint addr) -> uint8&; inline auto operator[](uint24 addr) -> uint8&;
inline auto operator[](uint addr) const -> const uint8&; inline auto operator[](uint24 addr) const -> const uint8&;
private: private:
uint8* data_ = nullptr; uint8* data_ = nullptr;
@ -31,9 +31,9 @@ struct MappedRAM : Memory {
inline auto data() -> uint8*; inline auto data() -> uint8*;
inline auto size() const -> uint; inline auto size() const -> uint;
inline auto read(uint addr, uint8 data = 0) -> uint8; inline auto read(uint24 addr, uint8 data = 0) -> uint8;
inline auto write(uint addr, uint8 data) -> void; inline auto write(uint24 addr, uint8 data) -> void;
inline auto operator[](uint addr) const -> const uint8&; inline auto operator[](uint24 addr) const -> const uint8&;
private: private:
uint8* data_ = nullptr; uint8* data_ = nullptr;
@ -48,15 +48,15 @@ struct Bus {
Bus(); Bus();
~Bus(); ~Bus();
alwaysinline auto read(uint addr, uint8 data) -> uint8; alwaysinline auto read(uint24 addr, uint8 data) -> uint8;
alwaysinline auto write(uint addr, uint8 data) -> void; alwaysinline auto write(uint24 addr, uint8 data) -> void;
auto reset() -> void; auto reset() -> void;
auto map() -> void; auto map() -> void;
auto map( auto map(
const function<uint8 (uint, uint8)>& reader, const function<uint8 (uint24, uint8)>& reader,
const function<void (uint, uint8)>& writer, const function<void (uint24, uint8)>& writer,
uint banklo, uint bankhi, uint addrlo, uint addrhi, uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
uint size = 0, uint base = 0, uint mask = 0 uint size = 0, uint base = 0, uint mask = 0
) -> void; ) -> void;
@ -64,8 +64,8 @@ struct Bus {
uint32* target = nullptr; uint32* target = nullptr;
uint idcount = 0; uint idcount = 0;
function<auto (uint, uint8) -> uint8> reader[256]; function<auto (uint24, uint8) -> uint8> reader[256];
function<auto (uint, uint8) -> void> writer[256]; function<auto (uint24, uint8) -> void> writer[256];
}; };
extern Bus bus; extern Bus bus;

View File

@ -35,7 +35,7 @@ auto BSMemory::size() const -> uint {
return memory.size(); return memory.size();
} }
auto BSMemory::read(uint addr, uint8 data) -> uint8 { auto BSMemory::read(uint24 addr, uint8 data) -> uint8 {
if(readonly) { if(readonly) {
return memory.read(bus.mirror(addr, memory.size()), data); return memory.read(bus.mirror(addr, memory.size()), data);
} }
@ -66,7 +66,7 @@ auto BSMemory::read(uint addr, uint8 data) -> uint8 {
return memory.read(addr, data); return memory.read(addr, data);
} }
auto BSMemory::write(uint addr, uint8 data) -> void { auto BSMemory::write(uint24 addr, uint8 data) -> void {
if(readonly) { if(readonly) {
return; return;
} }

View File

@ -6,8 +6,8 @@ struct BSMemory : Memory {
auto reset() -> void; auto reset() -> void;
auto size() const -> uint; auto size() const -> uint;
auto read(uint addr, uint8) -> uint8; auto read(uint24 addr, uint8) -> uint8;
auto write(uint addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
MappedRAM memory; MappedRAM memory;
bool readonly; bool readonly;

View File

@ -1,6 +1,6 @@
auto CPU::dmaTransfer() -> void { auto CPU::dmaTransfer() -> void {
//length of 0 or SRAM source address cause immediate termination //length of 0 or SRAM source address cause immediate termination
if(r.dmaLength == 0 || r.dmaSource.b2 == 1) { if(r.dmaLength == 0 || r.dmaSource.byte(2) == 1) {
r.dmaEnable = false; r.dmaEnable = false;
return; return;
} }
@ -10,7 +10,7 @@ auto CPU::dmaTransfer() -> void {
wait(2); wait(2);
uint16 data = 0; uint16 data = 0;
//once DMA is started; SRAM reads still incur time penalty, but do not transfer //once DMA is started; SRAM reads still incur time penalty, but do not transfer
if(r.dmaSource.b2 != 1) { if(r.dmaSource.byte(2) != 1) {
data |= read(r.dmaSource + 0) << 0; data |= read(r.dmaSource + 0) << 0;
data |= read(r.dmaSource + 1) << 8; data |= read(r.dmaSource + 1) << 8;
write(r.dmaTarget + 0, data >> 0); write(r.dmaTarget + 0, data >> 0);

View File

@ -14,6 +14,7 @@ struct Boolean {
inline auto serialize(serializer& s) { s(data); } inline auto serialize(serializer& s) { s(data); }
private:
bool data; bool data;
}; };
@ -28,32 +29,32 @@ template<uint Bits> struct Natural {
enum : type { Mask = ~0ull >> (64 - Bits) }; enum : type { Mask = ~0ull >> (64 - Bits) };
inline Natural() : data(0) {} inline Natural() : data(0) {}
template<typename T> inline Natural(const T& value) : data(clip(value)) {} template<typename T> inline Natural(const T& value) { assign(value); }
inline operator type() const { return data; } inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = clip(value); return *this; } template<typename T> inline auto& operator=(const T& value) { assign(value); return *this; }
inline auto operator++(int) { type value = data; data = clip(data + 1); return value; } inline auto operator++(int) { type value = data; assign(data + 1); return value; }
inline auto operator--(int) { type value = data; data = clip(data - 1); return value; } inline auto operator--(int) { type value = data; assign(data - 1); return value; }
inline auto& operator++() { data = clip(data + 1); return *this; } inline auto& operator++() { assign(data + 1); return *this; }
inline auto& operator--() { data = clip(data - 1); return *this; } inline auto& operator--() { assign(data - 1); return *this; }
inline auto& operator &=(const type value) { data = clip(data & value); return *this; } inline auto& operator &=(const type value) { assign(data & value); return *this; }
inline auto& operator |=(const type value) { data = clip(data | value); return *this; } inline auto& operator |=(const type value) { assign(data | value); return *this; }
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; } inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; } inline auto& operator<<=(const type value) { assign(data << value); return *this; }
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; } inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
inline auto& operator +=(const type value) { data = clip(data + value); return *this; } inline auto& operator +=(const type value) { assign(data + value); return *this; }
inline auto& operator -=(const type value) { data = clip(data - value); return *this; } inline auto& operator -=(const type value) { assign(data - value); return *this; }
inline auto& operator *=(const type value) { data = clip(data * value); return *this; } inline auto& operator *=(const type value) { assign(data * value); return *this; }
inline auto& operator /=(const type value) { data = clip(data / value); return *this; } inline auto& operator /=(const type value) { assign(data / value); return *this; }
inline auto& operator %=(const type value) { data = clip(data % value); return *this; } inline auto& operator %=(const type value) { assign(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); } inline auto serialize(serializer& s) { s(data); }
struct Reference { struct Reference {
inline Reference(Natural& source, uint Lo, uint Hi) : source(source), Lo(Lo), Hi(Hi) {} inline Reference(Natural& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline operator type() const { inline operator type() const {
const type RangeBits = Hi - Lo + 1; const type RangeBits = Hi - Lo + 1;
@ -70,55 +71,32 @@ template<uint Bits> struct Natural {
private: private:
Natural& source; Natural& source;
const uint Lo; const type Lo;
const uint Hi; const type Hi;
}; };
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; } inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; } inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; } inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
template<uint Lo, uint Hi> struct Range { inline auto clamp(uint bits) -> uintmax {
enum : type { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask }; const uintmax b = 1ull << (bits - 1);
const uintmax m = b * 2 - 1;
return data < m ? data : m;
}
inline operator type() const { inline auto clip(uint bits) -> uintmax {
return (self() & RangeMask) >> Lo; const uintmax b = 1ull << (bits - 1);
} const uintmax m = b * 2 - 1;
return data & m;
inline auto& operator=(const type value) { }
self() = (self() & ~RangeMask) | ((value << Lo) & RangeMask);
return *this;
}
private:
inline auto self() const -> type& { return *(type*)this; }
};
union {
type data;
Range< 0, 7> b0;
Range< 8, 15> b1;
Range<16, 23> b2;
Range<24, 31> b3;
Range<32, 39> b4;
Range<40, 47> b5;
Range<48, 55> b6;
Range<56, 63> b7;
Range< 0, 15> h0;
Range<16, 31> h1;
Range<32, 47> h2;
Range<48, 63> h3;
Range< 0, 31> w0;
Range<32, 63> w1;
};
private: private:
auto clip(type value) const -> type { auto assign(type value) -> void {
return value & Mask; data = value & Mask;
} }
type data;
}; };
template<uint Bits> struct Integer { template<uint Bits> struct Integer {
@ -133,32 +111,32 @@ template<uint Bits> struct Integer {
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) }; enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
inline Integer() : data(0) {} inline Integer() : data(0) {}
template<typename T> inline Integer(const T& value) : data(clip(value)) {} template<typename T> inline Integer(const T& value) { assign(value); }
inline operator type() const { return data; } inline operator type() const { return data; }
template<typename T> inline auto& operator=(const T& value) { data = clip(value); return *this; } template<typename T> inline auto& operator=(const T& value) { assign(value); return *this; }
inline auto operator++(int) { type value = data; data = clip(data + 1); return value; } inline auto operator++(int) { type value = data; assign(data + 1); return value; }
inline auto operator--(int) { type value = data; data = clip(data - 1); return value; } inline auto operator--(int) { type value = data; assign(data - 1); return value; }
inline auto& operator++() { data = clip(data + 1); return *this; } inline auto& operator++() { assign(data + 1); return *this; }
inline auto& operator--() { data = clip(data - 1); return *this; } inline auto& operator--() { assign(data - 1); return *this; }
inline auto& operator &=(const type value) { data = clip(data & value); return *this; } inline auto& operator &=(const type value) { assign(data & value); return *this; }
inline auto& operator |=(const type value) { data = clip(data | value); return *this; } inline auto& operator |=(const type value) { assign(data | value); return *this; }
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; } inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; } inline auto& operator<<=(const type value) { assign(data << value); return *this; }
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; } inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
inline auto& operator +=(const type value) { data = clip(data + value); return *this; } inline auto& operator +=(const type value) { assign(data + value); return *this; }
inline auto& operator -=(const type value) { data = clip(data - value); return *this; } inline auto& operator -=(const type value) { assign(data - value); return *this; }
inline auto& operator *=(const type value) { data = clip(data * value); return *this; } inline auto& operator *=(const type value) { assign(data * value); return *this; }
inline auto& operator /=(const type value) { data = clip(data / value); return *this; } inline auto& operator /=(const type value) { assign(data / value); return *this; }
inline auto& operator %=(const type value) { data = clip(data % value); return *this; } inline auto& operator %=(const type value) { assign(data % value); return *this; }
inline auto serialize(serializer& s) { s(data); } inline auto serialize(serializer& s) { s(data); }
struct Reference { struct Reference {
inline Reference(Integer& source, uint Lo, uint Hi) : source(source), Lo(Lo), Hi(Hi) {} inline Reference(Integer& source, uint lo, uint hi) : source(source), Lo(lo), Hi(hi) {}
inline operator utype() const { inline operator utype() const {
const type RangeBits = Hi - Lo + 1; const type RangeBits = Hi - Lo + 1;
@ -175,55 +153,32 @@ template<uint Bits> struct Integer {
private: private:
Integer& source; Integer& source;
uint Lo; const uint Lo;
uint Hi; const uint Hi;
}; };
inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; } inline auto bits(uint lo, uint hi) -> Reference { return {*this, lo, hi}; }
inline auto bit(uint index) -> Reference { return {*this, index, index}; } inline auto bit(uint index) -> Reference { return {*this, index, index}; }
inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; } inline auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
template<uint Lo, uint Hi> struct Range { inline auto clamp(uint bits) -> intmax {
enum : utype { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask }; const intmax b = 1ull << (bits - 1);
const intmax m = b - 1;
return data > m ? m : data < -b ? -b : data;
}
inline operator utype() const { inline auto clip(uint bits) -> intmax {
return ((utype)self() & RangeMask) >> Lo; const uintmax b = 1ull << (bits - 1);
} const uintmax m = b * 2 - 1;
return ((data & m) ^ b) - b;
inline auto& operator=(const utype value) { }
self() = ((((utype)self() & ~RangeMask) | ((value << Lo) & RangeMask)) ^ Sign) - Sign;
return *this;
}
private:
inline auto self() const -> utype& { return *(utype*)this; }
};
union {
type data;
Range< 0, 7> b0;
Range< 8, 15> b1;
Range<16, 23> b2;
Range<24, 31> b3;
Range<32, 39> b4;
Range<40, 47> b5;
Range<48, 55> b6;
Range<56, 63> b7;
Range< 0, 15> h0;
Range<16, 31> h1;
Range<32, 47> h2;
Range<48, 63> h3;
Range< 0, 31> w0;
Range<32, 63> w1;
};
private: private:
auto clip(type value) const -> type { auto assign(type value) -> void {
return ((value & Mask) ^ Sign) - Sign; data = ((value & Mask) ^ Sign) - Sign;
} }
type data;
}; };
template<uint Bits> struct Real { template<uint Bits> struct Real {

View File

@ -79,6 +79,8 @@ private:
} }
using boolean = nall::Boolean;
using int1 = nall::Integer< 1>; using int1 = nall::Integer< 1>;
using int2 = nall::Integer< 2>; using int2 = nall::Integer< 2>;
using int3 = nall::Integer< 3>; using int3 = nall::Integer< 3>;