mirror of
https://github.com/libretro/bsnes-libretro.git
synced 2024-11-23 08:59:40 +00:00
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:
parent
ef65bb862a
commit
4b29f4bad7
@ -66,16 +66,16 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
|
||||
}
|
||||
|
||||
if(addr == 0xff21) { //NR42
|
||||
envelopeVolume = data >> 4;
|
||||
envelopeDirection = data & 0x08;
|
||||
envelopeFrequency = data & 0x07;
|
||||
envelopeVolume = data.bits(7,4);
|
||||
envelopeDirection = data.bit (3);
|
||||
envelopeFrequency = data.bits(2,0);
|
||||
if(!dacEnable()) enable = false;
|
||||
}
|
||||
|
||||
if(addr == 0xff22) { //NR43
|
||||
frequency = data >> 4;
|
||||
narrow = data & 0x08;
|
||||
divisor = data & 0x07;
|
||||
frequency = data.bits(7,4);
|
||||
narrow = data.bit (3);
|
||||
divisor = data.bits(2,0);
|
||||
period = getPeriod();
|
||||
}
|
||||
|
||||
@ -84,10 +84,9 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
|
||||
if(length && --length == 0) enable = false;
|
||||
}
|
||||
|
||||
bool initialize = data & 0x80;
|
||||
counter = data & 0x40;
|
||||
counter = data.bit(6);
|
||||
|
||||
if(initialize) {
|
||||
if(data.bit(7)) {
|
||||
enable = dacEnable();
|
||||
lfsr = -1;
|
||||
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
|
||||
@ -95,7 +94,7 @@ auto APU::Noise::write(uint16 addr, uint8 data) -> void {
|
||||
|
||||
if(!length) {
|
||||
length = 64;
|
||||
if((apu.phase & 1) && counter) length--;
|
||||
if(apu.phase.bit(0) && counter) length--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,26 +68,26 @@ auto APU::Sequencer::read(uint16 addr) -> uint8 {
|
||||
|
||||
auto APU::Sequencer::write(uint16 addr, uint8 data) -> void {
|
||||
if(addr == 0xff24) { //NR50
|
||||
leftEnable = (uint1)(data >> 7);
|
||||
leftVolume = (uint3)(data >> 4);
|
||||
rightEnable = (uint1)(data >> 3);
|
||||
rightVolume = (uint3)(data >> 0);
|
||||
leftEnable = data.bit (7);
|
||||
leftVolume = data.bits(6,4);
|
||||
rightEnable = data.bit (3);
|
||||
rightVolume = data.bits(2,0);
|
||||
}
|
||||
|
||||
if(addr == 0xff25) { //NR51
|
||||
noise.leftEnable = data & 0x80;
|
||||
wave.leftEnable = data & 0x40;
|
||||
square2.leftEnable = data & 0x20;
|
||||
square1.leftEnable = data & 0x10;
|
||||
noise.rightEnable = data & 0x08;
|
||||
wave.rightEnable = data & 0x04;
|
||||
square2.rightEnable = data & 0x02;
|
||||
square1.rightEnable = data & 0x01;
|
||||
noise.leftEnable = data.bit(7);
|
||||
wave.leftEnable = data.bit(6);
|
||||
square2.leftEnable = data.bit(5);
|
||||
square1.leftEnable = data.bit(4);
|
||||
noise.rightEnable = data.bit(3);
|
||||
wave.rightEnable = data.bit(2);
|
||||
square2.rightEnable = data.bit(1);
|
||||
square1.rightEnable = data.bit(0);
|
||||
}
|
||||
|
||||
if(addr == 0xff26) { //NR52
|
||||
if(enable != (bool)(data & 0x80)) {
|
||||
enable = data & 0x80;
|
||||
if(enable != data.bit(7)) {
|
||||
enable = data.bit(7);
|
||||
|
||||
if(!enable) {
|
||||
//power(bool) resets length counters when true (eg for CGB only)
|
||||
|
@ -86,38 +86,37 @@ auto APU::Square1::read(uint16 addr) -> uint8 {
|
||||
|
||||
auto APU::Square1::write(uint16 addr, uint8 data) -> void {
|
||||
if(addr == 0xff10) { //NR10
|
||||
if(sweepEnable && sweepNegate && !(data & 0x08)) enable = false;
|
||||
sweepFrequency = (data >> 4) & 7;
|
||||
sweepDirection = data & 0x08;
|
||||
sweepShift = data & 0x07;
|
||||
if(sweepEnable && sweepNegate && !data.bit(3)) enable = false;
|
||||
sweepFrequency = data.bits(6,4);
|
||||
sweepDirection = data.bit (3);
|
||||
sweepShift = data.bits(2,0);
|
||||
}
|
||||
|
||||
if(addr == 0xff11) { //NR11
|
||||
duty = data >> 6;
|
||||
length = 64 - (data & 0x3f);
|
||||
duty = data.bits(7,6);
|
||||
length = 64 - data.bits(5,0);
|
||||
}
|
||||
|
||||
if(addr == 0xff12) { //NR12
|
||||
envelopeVolume = data >> 4;
|
||||
envelopeDirection = data & 0x08;
|
||||
envelopeFrequency = data & 0x07;
|
||||
envelopeVolume = data.bits(7,4);
|
||||
envelopeDirection = data.bit (3);
|
||||
envelopeFrequency = data.bits(2,0);
|
||||
if(!dacEnable()) enable = false;
|
||||
}
|
||||
|
||||
if(addr == 0xff13) { //NR13
|
||||
frequency = (frequency & 0x0700) | data;
|
||||
frequency.bits(7,0) = data;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool initialize = data & 0x80;
|
||||
counter = data & 0x40;
|
||||
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
|
||||
counter = data.bit(6);
|
||||
frequency.bits(10,8) = data.bits(2,0);
|
||||
|
||||
if(initialize) {
|
||||
if(data.bit(7)) {
|
||||
enable = dacEnable();
|
||||
period = 2 * (2048 - frequency);
|
||||
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
|
||||
@ -125,7 +124,7 @@ auto APU::Square1::write(uint16 addr, uint8 data) -> void {
|
||||
|
||||
if(!length) {
|
||||
length = 64;
|
||||
if((apu.phase & 1) && counter) length--;
|
||||
if(apu.phase.bit(0) && counter) length--;
|
||||
}
|
||||
|
||||
frequencyShadow = frequency;
|
||||
|
@ -60,31 +60,30 @@ auto APU::Square2::read(uint16 addr) -> uint8 {
|
||||
|
||||
auto APU::Square2::write(uint16 addr, uint8 data) -> void {
|
||||
if(addr == 0xff16) { //NR21
|
||||
duty = data >> 6;
|
||||
length = 64 - (data & 0x3f);
|
||||
duty = data.bits(7,6);
|
||||
length = 64 - data.bits(5,0);
|
||||
}
|
||||
|
||||
if(addr == 0xff17) { //NR22
|
||||
envelopeVolume = data >> 4;
|
||||
envelopeDirection = data & 0x08;
|
||||
envelopeFrequency = data & 0x07;
|
||||
envelopeVolume = data.bits(7,4);
|
||||
envelopeDirection = data.bit (3);
|
||||
envelopeFrequency = data.bits(2,0);
|
||||
if(!dacEnable()) enable = false;
|
||||
}
|
||||
|
||||
if(addr == 0xff18) { //NR23
|
||||
frequency = (frequency & 0x0700) | data;
|
||||
frequency.bits(7,0) = data;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool initialize = data & 0x80;
|
||||
counter = data & 0x40;
|
||||
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
|
||||
counter = data.bit(6);
|
||||
frequency.bits(10,8) = data.bits(2,0);
|
||||
|
||||
if(initialize) {
|
||||
if(data.bit(7)) {
|
||||
enable = dacEnable();
|
||||
period = 2 * (2048 - frequency);
|
||||
envelopePeriod = envelopeFrequency ? (uint)envelopeFrequency : 8;
|
||||
@ -92,7 +91,7 @@ auto APU::Square2::write(uint16 addr, uint8 data) -> void {
|
||||
|
||||
if(!length) {
|
||||
length = 64;
|
||||
if((apu.phase & 1) && counter) length--;
|
||||
if(apu.phase.bit(0) && counter) length--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ auto APU::Wave::read(uint16 addr) -> uint8 {
|
||||
|
||||
auto APU::Wave::write(uint16 addr, uint8 data) -> void {
|
||||
if(addr == 0xff1a) { //NR30
|
||||
dacEnable = data & 0x80;
|
||||
dacEnable = data.bit(7);
|
||||
if(!dacEnable) enable = false;
|
||||
}
|
||||
|
||||
@ -68,23 +68,22 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
|
||||
}
|
||||
|
||||
if(addr == 0xff1c) { //NR32
|
||||
volume = data >> 5;
|
||||
volume = data.bits(6,5);
|
||||
}
|
||||
|
||||
if(addr == 0xff1d) { //NR33
|
||||
frequency = (frequency & 0x0700) | data;
|
||||
frequency.bits(7,0) = data;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool initialize = data & 0x80;
|
||||
counter = data & 0x40;
|
||||
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
|
||||
counter = data.bit(6);
|
||||
frequency.bits(10,8) = data.bits(2,0);
|
||||
|
||||
if(initialize) {
|
||||
if(data.bit(7)) {
|
||||
if(!system.cgb() && patternHold) {
|
||||
//DMG,SGB trigger while channel is being read corrupts wave RAM
|
||||
if((patternOffset >> 1) <= 3) {
|
||||
@ -107,7 +106,7 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void {
|
||||
|
||||
if(!length) {
|
||||
length = 256;
|
||||
if((apu.phase & 1) && counter) length--;
|
||||
if(apu.phase.bit(0) && counter) length--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ auto CPU::read(uint32 addr) -> uint8 {
|
||||
case 0x04000130:
|
||||
if(auto result = player.keyinput()) return result() >> 0;
|
||||
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 & 0x30) == 0x30) result &= ~0x30; //left+right cannot be pressed simultaneously
|
||||
if((result & 0xc0) == 0xc0) result &= (uint8)~0xc0; //up+down cannot be pressed simultaneously
|
||||
if((result & 0x30) == 0x30) result &= (uint8)~0x30; //left+right cannot be pressed simultaneously
|
||||
return result ^ 0xff;
|
||||
case 0x04000131:
|
||||
if(auto result = player.keyinput()) return result() >> 8;
|
||||
|
@ -537,7 +537,7 @@ template<uint b, uint x> auto LR35902::op_res_n_r() {
|
||||
}
|
||||
|
||||
template<uint b> auto LR35902::op_res_n_hl() {
|
||||
uint8 n = op_read(r[HL]);
|
||||
uint n = op_read(r[HL]);
|
||||
n &= ~(1 << b);
|
||||
op_write(r[HL], n);
|
||||
}
|
||||
|
@ -14,13 +14,13 @@ struct R65816 {
|
||||
using fp = auto (R65816::*)() -> void;
|
||||
|
||||
virtual auto op_io() -> void = 0;
|
||||
virtual auto op_read(uint32 addr) -> uint8 = 0;
|
||||
virtual auto op_write(uint32 addr, uint8 data) -> void = 0;
|
||||
virtual auto op_read(uint24 addr) -> uint8 = 0;
|
||||
virtual auto op_write(uint24 addr, uint8 data) -> void = 0;
|
||||
virtual auto last_cycle() -> void = 0;
|
||||
virtual auto interrupt_pending() -> bool = 0;
|
||||
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
|
||||
alwaysinline auto op_io_irq() -> void;
|
||||
|
@ -36,15 +36,15 @@ struct Cartridge : property<Cartridge> {
|
||||
MappedRAM ram;
|
||||
|
||||
struct Mapping {
|
||||
function<auto (uint, uint8) -> uint8> reader;
|
||||
function<auto (uint, uint8) -> void> writer;
|
||||
function<auto (uint24, uint8) -> uint8> reader;
|
||||
function<auto (uint24, uint8) -> void> writer;
|
||||
string addr;
|
||||
uint size = 0;
|
||||
uint base = 0;
|
||||
uint mask = 0;
|
||||
|
||||
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&);
|
||||
};
|
||||
vector<Mapping> mapping;
|
||||
@ -84,7 +84,7 @@ private:
|
||||
//markup.cpp
|
||||
auto parseMarkup(const string&) -> 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 parseMarkupROM(Markup::Node) -> void;
|
||||
|
@ -3,7 +3,7 @@ Cartridge::Mapping::Mapping(SuperFamicom::Memory& 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->writer = writer;
|
||||
}
|
||||
@ -51,8 +51,8 @@ auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -
|
||||
|
||||
auto Cartridge::parseMarkupMap(
|
||||
Markup::Node map,
|
||||
const function<uint8 (uint, uint8)>& reader,
|
||||
const function<void (uint, uint8)>& writer
|
||||
const function<uint8 (uint24, uint8)>& reader,
|
||||
const function<void (uint24, uint8)>& writer
|
||||
) -> void {
|
||||
Mapping m{reader, writer};
|
||||
m.addr = map["address"].text();
|
||||
|
@ -58,7 +58,7 @@ auto ArmDSP::step(uint clocks) -> void {
|
||||
//3800-3807 mirrored throughout
|
||||
//a0 ignored
|
||||
|
||||
auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
|
||||
auto ArmDSP::mmio_read(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
|
||||
uint8 data = 0x00;
|
||||
@ -82,7 +82,7 @@ auto ArmDSP::mmio_read(uint addr, uint8) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto ArmDSP::mmio_write(uint addr, uint8 data) -> void {
|
||||
auto ArmDSP::mmio_write(uint24 addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
|
||||
addr &= 0xff06;
|
||||
|
@ -15,8 +15,8 @@ struct ArmDSP : Processor::ARM, Coprocessor {
|
||||
auto bus_read(uint mode, uint32 addr) -> uint32 override;
|
||||
auto bus_write(uint mode, uint32 addr, uint32 word) -> void override;
|
||||
|
||||
auto mmio_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint addr, uint8 data) -> void;
|
||||
auto mmio_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto init() -> void;
|
||||
auto load() -> void;
|
||||
|
@ -135,7 +135,7 @@ auto EpsonRTC::sync() -> void {
|
||||
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();
|
||||
addr &= 3;
|
||||
|
||||
@ -160,7 +160,7 @@ auto EpsonRTC::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto EpsonRTC::write(uint addr, uint8 data) -> void {
|
||||
auto EpsonRTC::write(uint24 addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr &= 3, data &= 15;
|
||||
|
||||
|
@ -11,8 +11,8 @@ struct EpsonRTC : Coprocessor {
|
||||
auto reset() -> void;
|
||||
auto sync() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -56,7 +56,7 @@ auto Event::reset() -> void {
|
||||
scoreSecondsRemaining = 0;
|
||||
}
|
||||
|
||||
auto Event::mcuRead(uint addr, uint8 data) -> uint8 {
|
||||
auto Event::mcuRead(uint24 addr, uint8 data) -> uint8 {
|
||||
if(board == Board::CampusChallenge92) {
|
||||
uint id = 0;
|
||||
if(select == 0x09) id = 1;
|
||||
@ -92,17 +92,17 @@ auto Event::mcuRead(uint addr, uint8 data) -> uint8 {
|
||||
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) {
|
||||
return status;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
auto Event::write(uint addr, uint8 data) -> void {
|
||||
auto Event::write(uint24 addr, uint8 data) -> void {
|
||||
if(addr == 0x206000 || addr == 0xe00000) {
|
||||
select = data;
|
||||
if(timer && data == 0x09) {
|
||||
|
@ -11,11 +11,11 @@ struct Event : Coprocessor {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto mcuRead(uint addr, uint8) -> uint8;
|
||||
auto mcuWrite(uint addr, uint8) -> void;
|
||||
auto mcuRead(uint24 addr, uint8) -> uint8;
|
||||
auto mcuWrite(uint24 addr, uint8) -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -18,20 +18,20 @@ struct HitachiDSP : Processor::HG51B, Coprocessor {
|
||||
auto bus_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
//CPU ROM read/write
|
||||
auto rom_read(uint addr, uint8 data) -> uint8;
|
||||
auto rom_write(uint addr, uint8 data) -> void;
|
||||
auto rom_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto rom_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
//CPU RAM read/write
|
||||
auto ram_read(uint addr, uint8 data) -> uint8;
|
||||
auto ram_write(uint addr, uint8 data) -> void;
|
||||
auto ram_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto ram_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
//HG51B data RAM read/write
|
||||
auto dram_read(uint addr, uint8 data) -> uint8;
|
||||
auto dram_write(uint addr, uint8 data) -> void;
|
||||
auto dram_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto dram_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
//CPU MMIO read/write
|
||||
auto dsp_read(uint addr, uint8 data) -> uint8;
|
||||
auto dsp_write(uint addr, uint8 data) -> void;
|
||||
auto dsp_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto dsp_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto firmware() const -> vector<uint8>;
|
||||
auto serialize(serializer&) -> void;
|
||||
|
@ -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) {
|
||||
addr = Bus::mirror(addr, rom.size());
|
||||
//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;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
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;
|
||||
if(addr >= 0xc00) return data;
|
||||
return dataRAM[addr];
|
||||
}
|
||||
|
||||
auto HitachiDSP::dram_write(uint addr, uint8 data) -> void {
|
||||
auto HitachiDSP::dram_write(uint24 addr, uint8 data) -> void {
|
||||
addr &= 0xfff;
|
||||
if(addr >= 0xc00) return;
|
||||
dataRAM[addr] = data;
|
||||
}
|
||||
|
||||
auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
|
||||
auto HitachiDSP::dsp_read(uint24 addr, uint8) -> uint8 {
|
||||
addr = 0x7c00 | (addr & 0x03ff);
|
||||
|
||||
//MMIO
|
||||
@ -115,7 +115,7 @@ auto HitachiDSP::dsp_read(uint addr, uint8) -> uint8 {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto HitachiDSP::dsp_write(uint addr, uint8 data) -> void {
|
||||
auto HitachiDSP::dsp_write(uint24 addr, uint8 data) -> void {
|
||||
addr = 0x7c00 | (addr & 0x03ff);
|
||||
|
||||
//MMIO
|
||||
|
@ -8,8 +8,8 @@ struct ICD2 : Emulator::Interface::Bind, GameBoy::Interface::Hook, Coprocessor {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
auto ICD2::read(uint addr, uint8 data) -> uint8 {
|
||||
auto ICD2::read(uint24 addr, uint8 data) -> uint8 {
|
||||
addr &= 0x40ffff;
|
||||
|
||||
//LY counter
|
||||
@ -38,7 +38,7 @@ auto ICD2::read(uint addr, uint8 data) -> uint8 {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto ICD2::write(uint addr, uint8 data) -> void {
|
||||
auto ICD2::write(uint24 addr, uint8 data) -> void {
|
||||
addr &= 0xffff;
|
||||
|
||||
//VRAM port
|
||||
|
@ -26,7 +26,7 @@ auto MCC::reset() -> void {
|
||||
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());
|
||||
if(!write) {
|
||||
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=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) {
|
||||
//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
|
||||
@ -88,15 +88,15 @@ auto MCC::mcu_access(bool write, uint addr, uint8 data) -> uint8 {
|
||||
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);
|
||||
}
|
||||
|
||||
auto MCC::mcu_write(uint addr, uint8 data) -> void {
|
||||
auto MCC::mcu_write(uint24 addr, uint8 data) -> void {
|
||||
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
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
return r[n];
|
||||
@ -105,7 +105,7 @@ auto MCC::read(uint addr, uint8 data) -> uint8 {
|
||||
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
|
||||
uint8 n = (addr >> 16) & 15;
|
||||
r[n] = data;
|
||||
|
@ -10,14 +10,14 @@ struct MCC {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto memory_access(bool write, Memory& memory, uint addr, uint8 data) -> uint8;
|
||||
auto mcu_access(bool write, uint addr, uint8 data) -> uint8;
|
||||
auto memory_access(bool write, Memory& memory, uint24 addr, uint8 data) -> uint8;
|
||||
auto mcu_access(bool write, uint24 addr, uint8 data) -> uint8;
|
||||
|
||||
auto mcu_read(uint addr, uint8 data) -> uint8;
|
||||
auto mcu_write(uint addr, uint8 data) -> void;
|
||||
auto mcu_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mcu_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto commit() -> void;
|
||||
|
||||
|
@ -119,18 +119,20 @@ auto MSU1::audioOpen() -> void {
|
||||
mmio.audioError = true;
|
||||
}
|
||||
|
||||
auto MSU1::mmioRead(uint addr, uint8) -> uint8 {
|
||||
auto MSU1::mmioRead(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr = 0x2000 | (addr & 7);
|
||||
|
||||
switch(addr) {
|
||||
case 0x2000:
|
||||
return (mmio.dataBusy << 7)
|
||||
| (mmio.audioBusy << 6)
|
||||
| (mmio.audioRepeat << 5)
|
||||
| (mmio.audioPlay << 4)
|
||||
| (mmio.audioError << 3)
|
||||
| (Revision << 0);
|
||||
return (
|
||||
mmio.dataBusy << 7
|
||||
| mmio.audioBusy << 6
|
||||
| mmio.audioRepeat << 5
|
||||
| mmio.audioPlay << 4
|
||||
| mmio.audioError << 3
|
||||
| Revision << 0
|
||||
);
|
||||
case 0x2001:
|
||||
if(mmio.dataBusy) 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();
|
||||
addr = 0x2000 | (addr & 7);
|
||||
|
||||
switch(addr) {
|
||||
case 0x2000: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffffff00) | (data << 0); break;
|
||||
case 0x2001: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xffff00ff) | (data << 8); break;
|
||||
case 0x2002: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0xff00ffff) | (data << 16); break;
|
||||
case 0x2003: mmio.dataSeekOffset = (mmio.dataSeekOffset & 0x00ffffff) | (data << 24);
|
||||
case 0x2000: mmio.dataSeekOffset.byte(0) = data; break;
|
||||
case 0x2001: mmio.dataSeekOffset.byte(1) = data; break;
|
||||
case 0x2002: mmio.dataSeekOffset.byte(2) = data; break;
|
||||
case 0x2003: mmio.dataSeekOffset.byte(3) = data;
|
||||
mmio.dataReadOffset = mmio.dataSeekOffset;
|
||||
dataOpen();
|
||||
break;
|
||||
case 0x2004: mmio.audioTrack = (mmio.audioTrack & 0xff00) | (data << 0); break;
|
||||
case 0x2005: mmio.audioTrack = (mmio.audioTrack & 0x00ff) | (data << 8);
|
||||
case 0x2004: mmio.audioTrack.byte(0) = data; break;
|
||||
case 0x2005: mmio.audioTrack.byte(1) = data;
|
||||
mmio.audioPlayOffset = 8;
|
||||
if(mmio.audioTrack == mmio.audioResumeTrack) {
|
||||
mmio.audioPlayOffset = mmio.audioResumeOffset;
|
||||
@ -173,9 +175,9 @@ auto MSU1::mmioWrite(uint addr, uint8 data) -> void {
|
||||
case 0x2007:
|
||||
if(mmio.audioBusy) break;
|
||||
if(mmio.audioError) break;
|
||||
bool audioResume = data & 4;
|
||||
mmio.audioRepeat = data & 2;
|
||||
mmio.audioPlay = data & 1;
|
||||
bool audioResume = data.bit(2);
|
||||
mmio.audioRepeat = data.bit(1);
|
||||
mmio.audioPlay = data.bit(0);
|
||||
if(!mmio.audioPlay && audioResume) {
|
||||
mmio.audioResumeTrack = mmio.audioTrack;
|
||||
mmio.audioResumeOffset = mmio.audioPlayOffset;
|
||||
|
@ -10,8 +10,8 @@ struct MSU1 : Coprocessor {
|
||||
auto dataOpen() -> void;
|
||||
auto audioOpen() -> void;
|
||||
|
||||
auto mmioRead(uint addr, uint8 data) -> uint8;
|
||||
auto mmioWrite(uint addr, uint8 data) -> void;
|
||||
auto mmioRead(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmioWrite(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -15,7 +15,7 @@ auto NECDSP::main() -> void {
|
||||
synchronizeCPU();
|
||||
}
|
||||
|
||||
auto NECDSP::read(uint addr, uint8) -> uint8 {
|
||||
auto NECDSP::read(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if(addr & 1) {
|
||||
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();
|
||||
if(addr & 1) {
|
||||
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();
|
||||
return uPD96050::readDP(addr);
|
||||
}
|
||||
|
||||
auto NECDSP::writeRAM(uint addr, uint8 data) -> void {
|
||||
auto NECDSP::writeRAM(uint24 addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
return uPD96050::writeDP(addr, data);
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ struct NECDSP : Processor::uPD96050, Coprocessor {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto readRAM(uint addr, uint8 data) -> uint8;
|
||||
auto writeRAM(uint addr, uint8 data) -> void;
|
||||
auto readRAM(uint24 addr, uint8 data) -> uint8;
|
||||
auto writeRAM(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto init() -> void;
|
||||
auto load() -> void;
|
||||
|
@ -23,11 +23,11 @@ auto NSS::set_dip(uint16 dip) -> void {
|
||||
this->dip = dip;
|
||||
}
|
||||
|
||||
auto NSS::read(uint, uint8) -> uint8 {
|
||||
auto NSS::read(uint24, uint8) -> uint8 {
|
||||
return dip;
|
||||
}
|
||||
|
||||
auto NSS::write(uint, uint8) -> void {
|
||||
auto NSS::write(uint24, uint8) -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ struct NSS {
|
||||
auto reset() -> void;
|
||||
|
||||
auto set_dip(uint16 dip) -> void;
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
uint8 dip = 0x00;
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ auto OBC1::reset() -> void {
|
||||
status.shift = (ramRead(0x1ff6) & 3) << 1;
|
||||
}
|
||||
|
||||
auto OBC1::read(uint addr, uint8) -> uint8 {
|
||||
auto OBC1::read(uint24 addr, uint8) -> uint8 {
|
||||
addr &= 0x1fff;
|
||||
|
||||
switch(addr) {
|
||||
@ -38,7 +38,7 @@ auto OBC1::read(uint addr, uint8) -> uint8 {
|
||||
return ramRead(addr);
|
||||
}
|
||||
|
||||
auto OBC1::write(uint addr, uint8 data) -> void {
|
||||
auto OBC1::write(uint24 addr, uint8 data) -> void {
|
||||
addr &= 0x1fff;
|
||||
|
||||
switch(addr) {
|
||||
|
@ -5,8 +5,8 @@ struct OBC1 {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -4,12 +4,12 @@ auto SA1::CPUIRAM::size() const -> uint {
|
||||
return sa1.iram.size();
|
||||
}
|
||||
|
||||
auto SA1::CPUIRAM::read(uint addr, uint8) -> uint8 {
|
||||
auto SA1::CPUIRAM::read(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
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();
|
||||
sa1.iram.write(addr & 0x07ff, data);
|
||||
}
|
||||
@ -18,13 +18,13 @@ auto SA1::CPUBWRAM::size() const -> uint {
|
||||
return sa1.bwram.size();
|
||||
}
|
||||
|
||||
auto SA1::CPUBWRAM::read(uint addr, uint8) -> uint8 {
|
||||
auto SA1::CPUBWRAM::read(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if(dma) return sa1.dma_cc1_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();
|
||||
sa1.bwram.write(addr, data);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
struct CPUIRAM : Memory {
|
||||
auto size() const -> uint;
|
||||
alwaysinline auto read(uint, uint8 = 0) -> uint8;
|
||||
alwaysinline auto write(uint, uint8) -> void;
|
||||
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
|
||||
alwaysinline auto write(uint24, uint8) -> void;
|
||||
} cpuiram;
|
||||
|
||||
struct CPUBWRAM : Memory {
|
||||
auto size() const -> uint;
|
||||
alwaysinline auto read(uint, uint8 = 0) -> uint8;
|
||||
alwaysinline auto write(uint, uint8) -> void;
|
||||
alwaysinline auto read(uint24, uint8 = 0) -> uint8;
|
||||
alwaysinline auto write(uint24, uint8) -> void;
|
||||
bool dma;
|
||||
} cpubwram;
|
||||
|
@ -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
|
||||
return mmio_read(addr, data);
|
||||
}
|
||||
@ -40,7 +40,7 @@ auto SA1::bus_read(uint addr, uint8 data) -> uint8 {
|
||||
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
|
||||
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
|
||||
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
|
||||
//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
|
||||
addr = ((addr & 0x800000) >> 2) | ((addr & 0x3f0000) >> 1) | (addr & 0x7fff);
|
||||
return mmcrom_read(addr, data);
|
||||
@ -112,13 +112,13 @@ auto SA1::op_io() -> void {
|
||||
tick();
|
||||
}
|
||||
|
||||
auto SA1::op_read(uint32 addr) -> uint8 {
|
||||
auto SA1::op_read(uint24 addr) -> uint8 {
|
||||
tick();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
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();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
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:
|
||||
//$00-3f,80-bf:8000-ffff mask=0x408000 => $00-3f:0000-ffff
|
||||
//$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
|
||||
if((addr & 0xffffe0) == 0x007fe0) { //$00:ffe0-ffef
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
cpu.synchronizeCoprocessors();
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr = bus.mirror(mmio.sbm * 0x2000 + (addr & 0x1fff), cpubwram.size());
|
||||
|
@ -1,16 +1,16 @@
|
||||
auto bus_read(uint addr, uint8 data) -> uint8;
|
||||
auto bus_write(uint addr, uint8 data) -> void;
|
||||
auto vbr_read(uint addr, uint8 data = 0) -> uint8;
|
||||
auto bus_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto bus_write(uint24 addr, uint8 data) -> void;
|
||||
auto vbr_read(uint24 addr, uint8 data = 0) -> uint8;
|
||||
|
||||
alwaysinline auto op_io() -> void;
|
||||
alwaysinline auto op_read(uint32 addr) -> uint8;
|
||||
alwaysinline auto op_write(uint32 addr, uint8 data) -> void;
|
||||
alwaysinline auto op_io() -> void override;
|
||||
alwaysinline auto op_read(uint24 addr) -> uint8 override;
|
||||
alwaysinline auto op_write(uint24 addr, uint8 data) -> void override;
|
||||
|
||||
auto mmcrom_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmcrom_write(uint addr, uint8 data) -> void;
|
||||
auto mmcrom_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmcrom_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto mmcbwram_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmcbwram_write(uint addr, uint8 data) -> void;
|
||||
auto mmcbwram_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmcbwram_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto mmc_sa1_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmc_sa1_write(uint addr, uint8 data) -> void;
|
||||
|
@ -445,7 +445,7 @@ auto SA1::mmio_r230e() -> uint8 {
|
||||
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());
|
||||
addr &= 0xffff;
|
||||
|
||||
@ -470,7 +470,7 @@ auto SA1::mmio_read(uint addr, uint8) -> uint8 {
|
||||
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());
|
||||
addr &= 0xffff;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
auto mmio_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint addr, uint8 data) -> void;
|
||||
auto mmio_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
struct MMIO {
|
||||
//$2200 CCNT
|
||||
|
@ -17,11 +17,11 @@ struct SA1 : Processor::R65816, public Coprocessor {
|
||||
static auto Enter() -> void;
|
||||
auto main() -> void;
|
||||
auto tick() -> void;
|
||||
auto op_irq() -> void;
|
||||
auto op_irq() -> void override;
|
||||
|
||||
alwaysinline auto trigger_irq() -> void;
|
||||
alwaysinline auto last_cycle() -> void;
|
||||
alwaysinline auto interrupt_pending() -> bool;
|
||||
alwaysinline auto last_cycle() -> void override;
|
||||
alwaysinline auto interrupt_pending() -> bool override;
|
||||
|
||||
auto init() -> void;
|
||||
auto load() -> void;
|
||||
|
@ -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);
|
||||
|
||||
switch(addr) {
|
||||
@ -54,7 +54,7 @@ auto SDD1::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto SDD1::write(uint addr, uint8 data) -> void {
|
||||
auto SDD1::write(uint24 addr, uint8 data) -> void {
|
||||
addr = 0x4800 | (addr & 7);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
auto SDD1::dma_write(uint addr, uint8 data) -> void {
|
||||
auto SDD1::dma_write(uint24 addr, uint8 data) -> void {
|
||||
uint channel = (addr >> 4) & 7;
|
||||
switch(addr & 15) {
|
||||
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);
|
||||
}
|
||||
|
||||
auto SDD1::mmc_read(uint addr) -> uint8 {
|
||||
auto SDD1::mmc_read(uint24 addr) -> uint8 {
|
||||
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
|
||||
//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
|
||||
if(addr < 0x200000) {
|
||||
return rom.read(addr);
|
||||
@ -143,16 +143,16 @@ auto SDD1::mcurom_read(uint addr, uint8) -> uint8 {
|
||||
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=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);
|
||||
}
|
||||
|
||||
auto SDD1::mcuram_write(uint addr, uint8 data) -> void {
|
||||
auto SDD1::mcuram_write(uint24 addr, uint8 data) -> void {
|
||||
return ram.write(addr & 0x1fff, data);
|
||||
}
|
||||
|
||||
|
@ -5,19 +5,19 @@ struct SDD1 {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto dma_read(uint addr, uint8 data) -> uint8;
|
||||
auto dma_write(uint addr, uint8 data) -> void;
|
||||
auto dma_read(uint24 addr, uint8 data) -> uint8;
|
||||
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_write(uint addr, uint8 data) -> void;
|
||||
auto mcurom_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mcurom_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto mcuram_read(uint addr, uint8 data) -> uint8;
|
||||
auto mcuram_write(uint addr, uint8 data) -> void;
|
||||
auto mcuram_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mcuram_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -59,7 +59,7 @@ auto SharpRTC::sync() -> void {
|
||||
weekday = timeinfo->tm_wday;
|
||||
}
|
||||
|
||||
auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
|
||||
auto SharpRTC::read(uint24 addr, uint8 data) -> uint8 {
|
||||
addr &= 1;
|
||||
|
||||
if(addr == 0) {
|
||||
@ -79,7 +79,7 @@ auto SharpRTC::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto SharpRTC::write(uint addr, uint8 data) -> void {
|
||||
auto SharpRTC::write(uint24 addr, uint8 data) -> void {
|
||||
addr &= 1, data &= 15;
|
||||
|
||||
if(addr == 1) {
|
||||
|
@ -9,8 +9,8 @@ struct SharpRTC : Coprocessor {
|
||||
auto reset() -> void;
|
||||
auto sync() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -104,7 +104,7 @@ auto SPC7110::reset() -> void {
|
||||
r4834 = 0x00;
|
||||
}
|
||||
|
||||
auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
||||
auto SPC7110::read(uint24 addr, uint8 data) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
|
||||
if((addr & 0xff0000) == 0x580000) addr = 0x4808; //$58:0000-ffff == $4808
|
||||
@ -188,7 +188,7 @@ auto SPC7110::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto SPC7110::write(uint addr, uint8 data) -> void {
|
||||
auto SPC7110::write(uint24 addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
if((addr & 0xff0000) == 0x500000) addr = 0x4800; //$50:0000-ffff == $4800
|
||||
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=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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
|
||||
auto SPC7110::mcuram_read(uint24 addr, uint8) -> uint8 {
|
||||
if(r4830 & 0x80) {
|
||||
addr = bus.mirror(addr, ram.size());
|
||||
return ram.read(addr);
|
||||
@ -304,7 +304,7 @@ auto SPC7110::mcuram_read(uint addr, uint8) -> uint8 {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto SPC7110::mcuram_write(uint addr, uint8 data) -> void {
|
||||
auto SPC7110::mcuram_write(uint24 addr, uint8 data) -> void {
|
||||
if(r4830 & 0x80) {
|
||||
addr = bus.mirror(addr, ram.size());
|
||||
ram.write(addr, data);
|
||||
|
@ -14,14 +14,14 @@ struct SPC7110 : Coprocessor {
|
||||
|
||||
auto add_clocks(uint clocks) -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto mcurom_read(uint addr, uint8 data) -> uint8;
|
||||
auto mcurom_write(uint addr, uint8 data) -> void;
|
||||
auto mcurom_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mcurom_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto mcuram_read(uint addr, uint8 data) -> uint8;
|
||||
auto mcuram_write(uint addr, uint8 data) -> void;
|
||||
auto mcuram_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mcuram_write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
|
@ -4,7 +4,7 @@ auto SuperFX::CPUROM::size() const -> uint {
|
||||
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) {
|
||||
static const uint8 vector[16] = {
|
||||
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);
|
||||
}
|
||||
|
||||
auto SuperFX::CPUROM::write(uint addr, uint8 data) -> void {
|
||||
auto SuperFX::CPUROM::write(uint24 addr, uint8 data) -> void {
|
||||
superfx.rom.write(addr, data);
|
||||
}
|
||||
|
||||
@ -23,11 +23,11 @@ auto SuperFX::CPURAM::size() const -> uint {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
struct CPUROM : Memory {
|
||||
auto size() const -> uint;
|
||||
auto read(uint, uint8) -> uint8;
|
||||
auto write(uint, uint8) -> void;
|
||||
auto read(uint24, uint8) -> uint8;
|
||||
auto write(uint24, uint8) -> void;
|
||||
} cpurom;
|
||||
|
||||
struct CPURAM : Memory {
|
||||
auto size() const -> uint;
|
||||
auto read(uint, uint8) -> uint8;
|
||||
auto write(uint, uint8) -> void;
|
||||
auto read(uint24, uint8) -> uint8;
|
||||
auto write(uint24, uint8) -> void;
|
||||
} cpuram;
|
||||
|
@ -1,4 +1,4 @@
|
||||
auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
|
||||
auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr &= 0xffff;
|
||||
|
||||
@ -50,7 +50,7 @@ auto SuperFX::mmio_read(uint addr, uint8) -> uint8 {
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
auto SuperFX::mmio_write(uint addr, uint8 data) -> void {
|
||||
auto SuperFX::mmio_write(uint24 addr, uint8 data) -> void {
|
||||
cpu.synchronizeCoprocessors();
|
||||
addr &= 0xffff;
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
auto mmio_read(uint addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint addr, uint8 data) -> void;
|
||||
auto mmio_read(uint24 addr, uint8 data) -> uint8;
|
||||
auto mmio_write(uint24 addr, uint8 data) -> void;
|
||||
|
@ -13,7 +13,7 @@ auto CPU::op_io() -> void {
|
||||
alu_edge();
|
||||
}
|
||||
|
||||
auto CPU::op_read(uint32 addr) -> uint8 {
|
||||
auto CPU::op_read(uint24 addr) -> uint8 {
|
||||
status.clock_count = speed(addr);
|
||||
dma_edge();
|
||||
add_clocks(status.clock_count - 4);
|
||||
@ -24,7 +24,7 @@ auto CPU::op_read(uint32 addr) -> uint8 {
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
auto CPU::op_write(uint32 addr, uint8 data) -> void {
|
||||
auto CPU::op_write(uint24 addr, uint8 data) -> void {
|
||||
alu_edge();
|
||||
status.clock_count = speed(addr);
|
||||
dma_edge();
|
||||
@ -33,7 +33,7 @@ auto CPU::op_write(uint32 addr, uint8 data) -> void {
|
||||
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 & 0x800000) return status.rom_speed;
|
||||
return 8;
|
||||
@ -43,6 +43,6 @@ auto CPU::speed(uint addr) const -> uint {
|
||||
return 12;
|
||||
}
|
||||
|
||||
auto CPU::disassembler_read(uint32 addr) -> uint8 {
|
||||
auto CPU::disassembler_read(uint24 addr) -> uint8 {
|
||||
return bus.read(addr, regs.mdr);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
auto op_io() -> void;
|
||||
auto op_read(uint32 addr) -> uint8;
|
||||
auto op_write(uint32 addr, uint8 data) -> void;
|
||||
alwaysinline auto speed(uint addr) const -> uint;
|
||||
auto op_io() -> void override;
|
||||
auto op_read(uint24 addr) -> uint8 override;
|
||||
auto op_write(uint24 addr, uint8 data) -> void override;
|
||||
alwaysinline auto speed(uint24 addr) const -> uint;
|
||||
|
||||
auto disassembler_read(uint32 addr) -> uint8;
|
||||
auto disassembler_read(uint24 addr) -> uint8 override;
|
||||
|
@ -8,8 +8,8 @@ auto eBoot::init() -> void {
|
||||
}
|
||||
|
||||
auto eBoot::load() -> void {
|
||||
resetVector = bus.read(0xfffc, 0x00) << 0;
|
||||
resetVector |= bus.read(0xfffd, 0x00) << 8;
|
||||
resetVector.byte(0) = bus.read(0xfffc, 0x00);
|
||||
resetVector.byte(1) = bus.read(0xfffd, 0x00);
|
||||
|
||||
for(auto& byte : ram) byte = 0xdb; //stp
|
||||
ram[0] = 0x6c; //jmp ($fffc)
|
||||
@ -35,15 +35,15 @@ auto eBoot::reset() -> void {
|
||||
booted = false;
|
||||
}
|
||||
|
||||
auto eBoot::read(uint addr, uint8 data) -> uint8 {
|
||||
auto eBoot::read(uint24 addr, uint8 data) -> uint8 {
|
||||
addr &= 0x40ffff;
|
||||
if(addr == 0xfffc) return booted ? resetVector >> 0 : 0x84;
|
||||
if(addr == 0xfffd) return booted ? resetVector >> 8 : (booted = true, 0x21);
|
||||
if(addr == 0xfffc) return booted ? resetVector.byte(0) : (uint8)0x84;
|
||||
if(addr == 0xfffd) return booted ? resetVector.byte(1) : (booted = true, (uint8)0x21);
|
||||
if(addr >= 0x2184 && addr <= 0x21ff) return ram[addr - 0x2184];
|
||||
return data;
|
||||
}
|
||||
|
||||
auto eBoot::write(uint addr, uint8 data) -> void {
|
||||
auto eBoot::write(uint24 addr, uint8 data) -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ struct eBoot : Memory {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
private:
|
||||
bool booted = false;
|
||||
uint16 resetVector = 0;
|
||||
uint8 ram[124] = {0};
|
||||
uint16 resetVector;
|
||||
uint8 ram[124];
|
||||
};
|
||||
|
||||
extern eBoot eboot;
|
||||
|
@ -22,7 +22,7 @@ auto Satellaview::reset() -> void {
|
||||
memory::fill(®s, sizeof regs);
|
||||
}
|
||||
|
||||
auto Satellaview::read(uint addr, uint8 data) -> uint8 {
|
||||
auto Satellaview::read(uint24 addr, uint8 data) -> uint8 {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
@ -80,7 +80,7 @@ auto Satellaview::read(uint addr, uint8 data) -> uint8 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto Satellaview::write(uint addr, uint8 data) -> void {
|
||||
auto Satellaview::write(uint24 addr, uint8 data) -> void {
|
||||
addr &= 0xffff;
|
||||
|
||||
switch(addr) {
|
||||
|
@ -5,8 +5,8 @@ struct Satellaview : Memory {
|
||||
auto power() -> void;
|
||||
auto reset() -> void;
|
||||
|
||||
auto read(uint addr, uint8 data) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8 data) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
private:
|
||||
struct {
|
||||
|
@ -10,10 +10,10 @@ StaticRAM::~StaticRAM() { delete[] data_; }
|
||||
auto StaticRAM::data() -> uint8* { return data_; }
|
||||
auto StaticRAM::size() const -> uint { return size_; }
|
||||
|
||||
auto StaticRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
|
||||
auto StaticRAM::write(uint addr, uint8 data) -> void { data_[addr] = data; }
|
||||
auto StaticRAM::operator[](uint addr) -> uint8& { return data_[addr]; }
|
||||
auto StaticRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
|
||||
auto StaticRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
|
||||
auto StaticRAM::write(uint24 addr, uint8 data) -> void { data_[addr] = data; }
|
||||
auto StaticRAM::operator[](uint24 addr) -> uint8& { return data_[addr]; }
|
||||
auto StaticRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
|
||||
|
||||
//MappedRAM
|
||||
|
||||
@ -48,9 +48,9 @@ auto MappedRAM::write_protect(bool status) -> void { write_protect_ = status; }
|
||||
auto MappedRAM::data() -> uint8* { return data_; }
|
||||
auto MappedRAM::size() const -> uint { return size_; }
|
||||
|
||||
auto MappedRAM::read(uint addr, uint8) -> uint8 { return data_[addr]; }
|
||||
auto MappedRAM::write(uint addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
|
||||
auto MappedRAM::operator[](uint addr) const -> const uint8& { return data_[addr]; }
|
||||
auto MappedRAM::read(uint24 addr, uint8) -> uint8 { return data_[addr]; }
|
||||
auto MappedRAM::write(uint24 addr, uint8 data) -> void { if(!write_protect_) data_[addr] = data; }
|
||||
auto MappedRAM::operator[](uint24 addr) const -> const uint8& { return data_[addr]; }
|
||||
|
||||
//Bus
|
||||
|
||||
@ -79,16 +79,14 @@ auto Bus::reduce(uint addr, uint mask) -> uint {
|
||||
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);
|
||||
|
||||
if(cheat.enable()) {
|
||||
if(auto result = cheat.find(addr, data)) return result();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ Bus::~Bus() {
|
||||
}
|
||||
|
||||
auto Bus::reset() -> void {
|
||||
function<auto (uint, uint8) -> uint8> reader = [](uint, uint8 data) { return data; };
|
||||
function<auto (uint, uint8) -> void> writer = [](uint, uint8) {};
|
||||
function<auto (uint24, uint8) -> uint8> reader = [](uint24, uint8 data) { return data; };
|
||||
function<auto (uint24, uint8) -> void> writer = [](uint24, uint8) {};
|
||||
|
||||
idcount = 0;
|
||||
map(reader, writer, 0x00, 0xff, 0x0000, 0xffff);
|
||||
@ -42,13 +42,13 @@ auto Bus::map() -> void {
|
||||
}
|
||||
|
||||
auto Bus::map(
|
||||
const function<uint8 (uint, uint8)>& reader,
|
||||
const function<void (uint, uint8)>& writer,
|
||||
uint banklo, uint bankhi, uint addrlo, uint addrhi,
|
||||
const function<uint8 (uint24, uint8)>& reader,
|
||||
const function<void (uint24, uint8)>& writer,
|
||||
uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
|
||||
uint size, uint base, uint mask
|
||||
) -> void {
|
||||
assert(banklo <= bankhi && bankhi <= 0xff);
|
||||
assert(addrlo <= addrhi && addrhi <= 0xffff);
|
||||
assert(banklo <= bankhi);
|
||||
assert(addrlo <= addrhi);
|
||||
assert(idcount < 255);
|
||||
|
||||
uint id = idcount++;
|
||||
|
@ -1,7 +1,7 @@
|
||||
struct Memory {
|
||||
virtual inline auto size() const -> uint;
|
||||
virtual auto read(uint addr, uint8 data = 0) -> uint8 = 0;
|
||||
virtual auto write(uint addr, uint8 data) -> void = 0;
|
||||
virtual auto read(uint24 addr, uint8 data = 0) -> uint8 = 0;
|
||||
virtual auto write(uint24 addr, uint8 data) -> void = 0;
|
||||
};
|
||||
|
||||
struct StaticRAM : Memory {
|
||||
@ -11,10 +11,10 @@ struct StaticRAM : Memory {
|
||||
inline auto data() -> uint8*;
|
||||
inline auto size() const -> uint;
|
||||
|
||||
inline auto read(uint addr, uint8 data = 0) -> uint8;
|
||||
inline auto write(uint addr, uint8 data) -> void;
|
||||
inline auto operator[](uint addr) -> uint8&;
|
||||
inline auto operator[](uint addr) const -> const uint8&;
|
||||
inline auto read(uint24 addr, uint8 data = 0) -> uint8;
|
||||
inline auto write(uint24 addr, uint8 data) -> void;
|
||||
inline auto operator[](uint24 addr) -> uint8&;
|
||||
inline auto operator[](uint24 addr) const -> const uint8&;
|
||||
|
||||
private:
|
||||
uint8* data_ = nullptr;
|
||||
@ -31,9 +31,9 @@ struct MappedRAM : Memory {
|
||||
inline auto data() -> uint8*;
|
||||
inline auto size() const -> uint;
|
||||
|
||||
inline auto read(uint addr, uint8 data = 0) -> uint8;
|
||||
inline auto write(uint addr, uint8 data) -> void;
|
||||
inline auto operator[](uint addr) const -> const uint8&;
|
||||
inline auto read(uint24 addr, uint8 data = 0) -> uint8;
|
||||
inline auto write(uint24 addr, uint8 data) -> void;
|
||||
inline auto operator[](uint24 addr) const -> const uint8&;
|
||||
|
||||
private:
|
||||
uint8* data_ = nullptr;
|
||||
@ -48,15 +48,15 @@ struct Bus {
|
||||
Bus();
|
||||
~Bus();
|
||||
|
||||
alwaysinline auto read(uint addr, uint8 data) -> uint8;
|
||||
alwaysinline auto write(uint addr, uint8 data) -> void;
|
||||
alwaysinline auto read(uint24 addr, uint8 data) -> uint8;
|
||||
alwaysinline auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
auto reset() -> void;
|
||||
auto map() -> void;
|
||||
auto map(
|
||||
const function<uint8 (uint, uint8)>& reader,
|
||||
const function<void (uint, uint8)>& writer,
|
||||
uint banklo, uint bankhi, uint addrlo, uint addrhi,
|
||||
const function<uint8 (uint24, uint8)>& reader,
|
||||
const function<void (uint24, uint8)>& writer,
|
||||
uint8 banklo, uint8 bankhi, uint16 addrlo, uint16 addrhi,
|
||||
uint size = 0, uint base = 0, uint mask = 0
|
||||
) -> void;
|
||||
|
||||
@ -64,8 +64,8 @@ struct Bus {
|
||||
uint32* target = nullptr;
|
||||
|
||||
uint idcount = 0;
|
||||
function<auto (uint, uint8) -> uint8> reader[256];
|
||||
function<auto (uint, uint8) -> void> writer[256];
|
||||
function<auto (uint24, uint8) -> uint8> reader[256];
|
||||
function<auto (uint24, uint8) -> void> writer[256];
|
||||
};
|
||||
|
||||
extern Bus bus;
|
||||
|
@ -35,7 +35,7 @@ auto BSMemory::size() const -> uint {
|
||||
return memory.size();
|
||||
}
|
||||
|
||||
auto BSMemory::read(uint addr, uint8 data) -> uint8 {
|
||||
auto BSMemory::read(uint24 addr, uint8 data) -> uint8 {
|
||||
if(readonly) {
|
||||
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);
|
||||
}
|
||||
|
||||
auto BSMemory::write(uint addr, uint8 data) -> void {
|
||||
auto BSMemory::write(uint24 addr, uint8 data) -> void {
|
||||
if(readonly) {
|
||||
return;
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ struct BSMemory : Memory {
|
||||
auto reset() -> void;
|
||||
|
||||
auto size() const -> uint;
|
||||
auto read(uint addr, uint8) -> uint8;
|
||||
auto write(uint addr, uint8 data) -> void;
|
||||
auto read(uint24 addr, uint8) -> uint8;
|
||||
auto write(uint24 addr, uint8 data) -> void;
|
||||
|
||||
MappedRAM memory;
|
||||
bool readonly;
|
||||
|
@ -1,6 +1,6 @@
|
||||
auto CPU::dmaTransfer() -> void {
|
||||
//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;
|
||||
return;
|
||||
}
|
||||
@ -10,7 +10,7 @@ auto CPU::dmaTransfer() -> void {
|
||||
wait(2);
|
||||
uint16 data = 0;
|
||||
//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 + 1) << 8;
|
||||
write(r.dmaTarget + 0, data >> 0);
|
||||
|
@ -14,6 +14,7 @@ struct Boolean {
|
||||
|
||||
inline auto serialize(serializer& s) { s(data); }
|
||||
|
||||
private:
|
||||
bool data;
|
||||
};
|
||||
|
||||
@ -28,32 +29,32 @@ template<uint Bits> struct Natural {
|
||||
enum : type { Mask = ~0ull >> (64 - Bits) };
|
||||
|
||||
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; }
|
||||
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; 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; assign(data - 1); return value; }
|
||||
|
||||
inline auto& operator++() { data = clip(data + 1); return *this; }
|
||||
inline auto& operator--() { data = clip(data - 1); return *this; }
|
||||
inline auto& operator++() { assign(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) { data = clip(data | value); return *this; }
|
||||
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; }
|
||||
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; }
|
||||
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; }
|
||||
inline auto& operator +=(const type value) { data = clip(data + value); return *this; }
|
||||
inline auto& operator -=(const type value) { data = clip(data - value); return *this; }
|
||||
inline auto& operator *=(const type value) { data = clip(data * value); return *this; }
|
||||
inline auto& operator /=(const type value) { data = clip(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) { assign(data | value); return *this; }
|
||||
inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
|
||||
inline auto& operator<<=(const type value) { assign(data << value); return *this; }
|
||||
inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
|
||||
inline auto& operator +=(const type value) { assign(data + value); return *this; }
|
||||
inline auto& operator -=(const type value) { assign(data - value); return *this; }
|
||||
inline auto& operator *=(const type value) { assign(data * value); return *this; }
|
||||
inline auto& operator /=(const type value) { assign(data / value); return *this; }
|
||||
inline auto& operator %=(const type value) { assign(data % value); return *this; }
|
||||
|
||||
inline auto serialize(serializer& s) { s(data); }
|
||||
|
||||
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 {
|
||||
const type RangeBits = Hi - Lo + 1;
|
||||
@ -70,55 +71,32 @@ template<uint Bits> struct Natural {
|
||||
|
||||
private:
|
||||
Natural& source;
|
||||
const uint Lo;
|
||||
const uint Hi;
|
||||
const type Lo;
|
||||
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 byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
|
||||
|
||||
template<uint Lo, uint Hi> struct Range {
|
||||
enum : type { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask };
|
||||
inline auto clamp(uint bits) -> uintmax {
|
||||
const uintmax b = 1ull << (bits - 1);
|
||||
const uintmax m = b * 2 - 1;
|
||||
return data < m ? data : m;
|
||||
}
|
||||
|
||||
inline operator type() const {
|
||||
return (self() & RangeMask) >> Lo;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
inline auto clip(uint bits) -> uintmax {
|
||||
const uintmax b = 1ull << (bits - 1);
|
||||
const uintmax m = b * 2 - 1;
|
||||
return data & m;
|
||||
}
|
||||
|
||||
private:
|
||||
auto clip(type value) const -> type {
|
||||
return value & Mask;
|
||||
auto assign(type value) -> void {
|
||||
data = value & Mask;
|
||||
}
|
||||
|
||||
type data;
|
||||
};
|
||||
|
||||
template<uint Bits> struct Integer {
|
||||
@ -133,32 +111,32 @@ template<uint Bits> struct Integer {
|
||||
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
|
||||
|
||||
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; }
|
||||
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; 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; assign(data - 1); return value; }
|
||||
|
||||
inline auto& operator++() { data = clip(data + 1); return *this; }
|
||||
inline auto& operator--() { data = clip(data - 1); return *this; }
|
||||
inline auto& operator++() { assign(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) { data = clip(data | value); return *this; }
|
||||
inline auto& operator ^=(const type value) { data = clip(data ^ value); return *this; }
|
||||
inline auto& operator<<=(const type value) { data = clip(data << value); return *this; }
|
||||
inline auto& operator>>=(const type value) { data = clip(data >> value); return *this; }
|
||||
inline auto& operator +=(const type value) { data = clip(data + value); return *this; }
|
||||
inline auto& operator -=(const type value) { data = clip(data - value); return *this; }
|
||||
inline auto& operator *=(const type value) { data = clip(data * value); return *this; }
|
||||
inline auto& operator /=(const type value) { data = clip(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) { assign(data | value); return *this; }
|
||||
inline auto& operator ^=(const type value) { assign(data ^ value); return *this; }
|
||||
inline auto& operator<<=(const type value) { assign(data << value); return *this; }
|
||||
inline auto& operator>>=(const type value) { assign(data >> value); return *this; }
|
||||
inline auto& operator +=(const type value) { assign(data + value); return *this; }
|
||||
inline auto& operator -=(const type value) { assign(data - value); return *this; }
|
||||
inline auto& operator *=(const type value) { assign(data * value); return *this; }
|
||||
inline auto& operator /=(const type value) { assign(data / value); return *this; }
|
||||
inline auto& operator %=(const type value) { assign(data % value); return *this; }
|
||||
|
||||
inline auto serialize(serializer& s) { s(data); }
|
||||
|
||||
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 {
|
||||
const type RangeBits = Hi - Lo + 1;
|
||||
@ -175,55 +153,32 @@ template<uint Bits> struct Integer {
|
||||
|
||||
private:
|
||||
Integer& source;
|
||||
uint Lo;
|
||||
uint Hi;
|
||||
const uint Lo;
|
||||
const uint 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 byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
|
||||
|
||||
template<uint Lo, uint Hi> struct Range {
|
||||
enum : utype { RangeBits = Hi - Lo + 1, RangeMask = (((1ull << RangeBits) - 1) << Lo) & Mask };
|
||||
inline auto clamp(uint bits) -> intmax {
|
||||
const intmax b = 1ull << (bits - 1);
|
||||
const intmax m = b - 1;
|
||||
return data > m ? m : data < -b ? -b : data;
|
||||
}
|
||||
|
||||
inline operator utype() const {
|
||||
return ((utype)self() & RangeMask) >> Lo;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
inline auto clip(uint bits) -> intmax {
|
||||
const uintmax b = 1ull << (bits - 1);
|
||||
const uintmax m = b * 2 - 1;
|
||||
return ((data & m) ^ b) - b;
|
||||
}
|
||||
|
||||
private:
|
||||
auto clip(type value) const -> type {
|
||||
return ((value & Mask) ^ Sign) - Sign;
|
||||
auto assign(type value) -> void {
|
||||
data = ((value & Mask) ^ Sign) - Sign;
|
||||
}
|
||||
|
||||
type data;
|
||||
};
|
||||
|
||||
template<uint Bits> struct Real {
|
||||
|
@ -79,6 +79,8 @@ private:
|
||||
|
||||
}
|
||||
|
||||
using boolean = nall::Boolean;
|
||||
|
||||
using int1 = nall::Integer< 1>;
|
||||
using int2 = nall::Integer< 2>;
|
||||
using int3 = nall::Integer< 3>;
|
||||
|
Loading…
Reference in New Issue
Block a user