Update to v095r08 release.

byuu says:

Changelog:
- added preliminary WASAPI driver (it's really terrible, though. Patches
  most welcome.)
- all of processor/ updated to auto fn() -> ret syntax
- all of gb/ updated to auto fn() -> ret syntax

If you want to test the WASAPI driver, then edit ui-tomoko/GNUmakefile,
and replace audio.xaudio2 with audio.wasapi Note that the two drivers
are incompatible and cannot co-exist (yet. We can probably make it work
in the future.)

All that's left for the auto fn() -> ret syntax is the NES core and the
balanced/performance SNES components. This is kind of a big deal because
this syntax change causes diffs between WIPs to go crazy. So the sooner
we get this done and out of the way, the better. It's also nice from
a consistency standpoint, of course.
This commit is contained in:
Tim Allen 2015-11-21 18:36:48 +11:00
parent 6adfe71836
commit a219f9c121
109 changed files with 2048 additions and 1951 deletions

View File

@ -7,7 +7,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "095.07";
static const string Version = "095.08";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -1,6 +1,5 @@
#include <gb/gb.hpp>
#define APU_CPP
namespace GameBoy {
#include "square1/square1.cpp"
@ -11,11 +10,11 @@ namespace GameBoy {
#include "serialization.cpp"
APU apu;
void APU::Main() {
auto APU::Main() -> void {
apu.main();
}
void APU::main() {
auto APU::main() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
@ -57,14 +56,14 @@ void APU::main() {
}
}
void APU::hipass(int16& sample, int64& bias) {
auto APU::hipass(int16& sample, int64& bias) -> void {
bias += ((((int64)sample << 16) - (bias >> 16)) * 57593) >> 16;
sample = sclamp<16>(sample - (bias >> 32));
}
void APU::power() {
auto APU::power() -> void {
create(Main, 2 * 1024 * 1024);
for(unsigned n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this;
for(uint n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this;
for(auto& n : mmio_data) n = 0x00;
sequencer_base = 0;
@ -77,7 +76,7 @@ void APU::power() {
master.power();
}
uint8 APU::mmio_read(uint16 addr) {
auto APU::mmio_read(uint16 addr) -> uint8 {
static const uint8 table[48] = {
0x80, 0x3f, 0x00, 0xff, 0xbf, //square1
0xff, 0x3f, 0x00, 0xff, 0xbf, //square2
@ -102,7 +101,7 @@ uint8 APU::mmio_read(uint16 addr) {
return 0xff;
}
void APU::mmio_write(uint16 addr, uint8 data) {
auto APU::mmio_write(uint16 addr, uint8 data) -> void {
if(addr >= 0xff10 && addr <= 0xff3f) mmio_data[addr - 0xff10] = data;
if(addr >= 0xff10 && addr <= 0xff14) return square1.write (addr - 0xff10, data);

View File

@ -1,4 +1,14 @@
struct APU : Thread, MMIO {
static auto Main() -> void;
auto main() -> void;
auto hipass(int16& sample, int64& bias) -> void;
auto power() -> void;
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto serialize(serializer&) -> void;
#include "square1/square1.hpp"
#include "square2/square2.hpp"
#include "wave/wave.hpp"
@ -14,16 +24,6 @@ struct APU : Thread, MMIO {
Wave wave;
Noise noise;
Master master;
static void Main();
void main();
void hipass(int16& sample, int64& bias);
void power();
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void serialize(serializer&);
};
extern APU apu;

View File

@ -1,16 +1,14 @@
#ifdef APU_CPP
void APU::Master::run() {
auto APU::Master::run() -> void {
if(enable == false) {
center = 0;
left = 0;
right = 0;
center_bias = left_bias = right_bias = 0;
center_bias = left_bias = right_bias = 0;
return;
}
signed sample = 0;
int sample = 0;
sample += apu.square1.output;
sample += apu.square2.output;
sample += apu.wave.output;
@ -41,7 +39,7 @@ center_bias = left_bias = right_bias = 0;
right >>= 1;
}
void APU::Master::write(unsigned r, uint8 data) {
auto APU::Master::write(uint r, uint8 data) -> void {
if(r == 0) { //$ff24 NR50
left_in_enable = data & 0x80;
left_volume = (data >> 4) & 7;
@ -65,7 +63,7 @@ void APU::Master::write(unsigned r, uint8 data) {
}
}
void APU::Master::power() {
auto APU::Master::power() -> void {
left_in_enable = 0;
left_volume = 0;
right_in_enable = 0;
@ -89,7 +87,7 @@ void APU::Master::power() {
right_bias = 0;
}
void APU::Master::serialize(serializer& s) {
auto APU::Master::serialize(serializer& s) -> void {
s.integer(left_in_enable);
s.integer(left_volume);
s.integer(right_in_enable);
@ -112,5 +110,3 @@ void APU::Master::serialize(serializer& s) {
s.integer(left_bias);
s.integer(right_bias);
}
#endif

View File

@ -1,4 +1,10 @@
struct Master {
auto run() -> void;
auto write(uint r, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
bool left_in_enable;
uint3 left_volume;
bool right_in_enable;
@ -20,9 +26,4 @@ struct Master {
int64 center_bias;
int64 left_bias;
int64 right_bias;
void run();
void write(unsigned r, uint8 data);
void power();
void serialize(serializer&);
};

View File

@ -1,10 +1,8 @@
#ifdef APU_CPP
bool APU::Noise::dac_enable() {
auto APU::Noise::dac_enable() const -> bool {
return (envelope_volume || envelope_direction);
}
void APU::Noise::run() {
auto APU::Noise::run() -> void {
if(period && --period == 0) {
period = divisor << frequency;
if(frequency < 14) {
@ -19,13 +17,13 @@ void APU::Noise::run() {
output = sample;
}
void APU::Noise::clock_length() {
auto APU::Noise::clock_length() -> void {
if(enable && counter) {
if(++length == 0) enable = false;
}
}
void APU::Noise::clock_envelope() {
auto APU::Noise::clock_envelope() -> void {
if(enable && envelope_frequency && --envelope_period == 0) {
envelope_period = envelope_frequency;
if(envelope_direction == 0 && volume > 0) volume--;
@ -33,7 +31,7 @@ void APU::Noise::clock_envelope() {
}
}
void APU::Noise::write(unsigned r, uint8 data) {
auto APU::Noise::write(uint r, uint8 data) -> void {
if(r == 1) { //$ff20 NR41
length = data & 0x3f;
}
@ -66,7 +64,7 @@ void APU::Noise::write(unsigned r, uint8 data) {
}
}
void APU::Noise::power() {
auto APU::Noise::power() -> void {
enable = 0;
envelope_volume = 0;
@ -85,7 +83,7 @@ void APU::Noise::power() {
lfsr = 0;
}
void APU::Noise::serialize(serializer& s) {
auto APU::Noise::serialize(serializer& s) -> void {
s.integer(enable);
s.integer(envelope_volume);
@ -103,5 +101,3 @@ void APU::Noise::serialize(serializer& s) {
s.integer(period);
s.integer(lfsr);
}
#endif

View File

@ -1,4 +1,14 @@
struct Noise {
auto dac_enable() const -> bool;
auto run() -> void;
auto clock_length() -> void;
auto clock_envelope() -> void;
auto write(uint r, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
bool enable;
uint4 envelope_volume;
@ -6,22 +16,13 @@ struct Noise {
uint3 envelope_frequency;
uint4 frequency;
bool narrow_lfsr;
unsigned divisor;
uint divisor;
bool counter;
int16 output;
uint6 length;
uint3 envelope_period;
uint4 volume;
unsigned period;
uint period;
uint15 lfsr;
bool dac_enable();
void run();
void clock_length();
void clock_envelope();
void write(unsigned r, uint8 data);
void power();
void serialize(serializer&);
};

View File

@ -1,6 +1,4 @@
#ifdef APU_CPP
void APU::serialize(serializer& s) {
auto APU::serialize(serializer& s) -> void {
Thread::serialize(s);
s.array(mmio_data);
@ -13,5 +11,3 @@ void APU::serialize(serializer& s) {
noise.serialize(s);
master.serialize(s);
}
#endif

View File

@ -1,10 +1,8 @@
#ifdef APU_CPP
bool APU::Square1::dac_enable() {
auto APU::Square1::dac_enable() const -> bool {
return (envelope_volume || envelope_direction);
}
void APU::Square1::run() {
auto APU::Square1::run() -> void {
if(period && --period == 0) {
period = 2 * (2048 - frequency);
phase++;
@ -22,12 +20,12 @@ void APU::Square1::run() {
output = sample;
}
void APU::Square1::sweep(bool update) {
auto APU::Square1::sweep(bool update) -> void {
if(sweep_enable == false) return;
sweep_negate = sweep_direction;
unsigned delta = frequency_shadow >> sweep_shift;
signed freq = frequency_shadow + (sweep_negate ? -delta : delta);
uint delta = frequency_shadow >> sweep_shift;
int freq = frequency_shadow + (sweep_negate ? -delta : delta);
if(freq > 2047) {
enable = false;
@ -38,13 +36,13 @@ void APU::Square1::sweep(bool update) {
}
}
void APU::Square1::clock_length() {
auto APU::Square1::clock_length() -> void {
if(counter && enable) {
if(++length == 0) enable = false;
}
}
void APU::Square1::clock_sweep() {
auto APU::Square1::clock_sweep() -> void {
if(enable && sweep_frequency && --sweep_period == 0) {
sweep_period = sweep_frequency;
sweep(1);
@ -52,7 +50,7 @@ void APU::Square1::clock_sweep() {
}
}
void APU::Square1::clock_envelope() {
auto APU::Square1::clock_envelope() -> void {
if(enable && envelope_frequency && --envelope_period == 0) {
envelope_period = envelope_frequency;
if(envelope_direction == 0 && volume > 0) volume--;
@ -60,7 +58,7 @@ void APU::Square1::clock_envelope() {
}
}
void APU::Square1::write(unsigned r, uint8 data) {
auto APU::Square1::write(uint r, uint8 data) -> void {
if(r == 0) { //$ff10 NR10
if(sweep_negate && sweep_direction && !(data & 0x08)) enable = false;
sweep_frequency = (data >> 4) & 7;
@ -103,7 +101,7 @@ void APU::Square1::write(unsigned r, uint8 data) {
}
}
void APU::Square1::power() {
auto APU::Square1::power() -> void {
enable = 0;
sweep_frequency = 0;
@ -129,7 +127,7 @@ void APU::Square1::power() {
volume = 0;
}
void APU::Square1::serialize(serializer& s) {
auto APU::Square1::serialize(serializer& s) -> void {
s.integer(enable);
s.integer(sweep_frequency);
@ -154,5 +152,3 @@ void APU::Square1::serialize(serializer& s) {
s.integer(sweep_enable);
s.integer(volume);
}
#endif

View File

@ -1,4 +1,16 @@
struct Square1 {
auto dac_enable() const -> bool;
auto run() -> void;
auto sweep(bool update) -> void;
auto clock_length() -> void;
auto clock_sweep() -> void;
auto clock_envelope() -> void;
auto write(uint r, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
bool enable;
uint3 sweep_frequency;
@ -16,21 +28,10 @@ struct Square1 {
int16 output;
bool duty_output;
uint3 phase;
unsigned period;
uint period;
uint3 envelope_period;
uint3 sweep_period;
signed frequency_shadow;
int frequency_shadow;
bool sweep_enable;
uint4 volume;
bool dac_enable();
void run();
void sweep(bool update);
void clock_length();
void clock_sweep();
void clock_envelope();
void write(unsigned r, uint8 data);
void power();
void serialize(serializer&);
};

View File

@ -1,10 +1,8 @@
#ifdef APU_CPP
bool APU::Square2::dac_enable() {
auto APU::Square2::dac_enable() const -> bool {
return (envelope_volume || envelope_direction);
}
void APU::Square2::run() {
auto APU::Square2::run() -> void {
if(period && --period == 0) {
period = 2 * (2048 - frequency);
phase++;
@ -22,13 +20,13 @@ void APU::Square2::run() {
output = sample;
}
void APU::Square2::clock_length() {
auto APU::Square2::clock_length() -> void {
if(counter && enable) {
if(++length == 0) enable = false;
}
}
void APU::Square2::clock_envelope() {
auto APU::Square2::clock_envelope() -> void {
if(enable && envelope_frequency && --envelope_period == 0) {
envelope_period = envelope_frequency;
if(envelope_direction == 0 && volume > 0) volume--;
@ -36,7 +34,7 @@ void APU::Square2::clock_envelope() {
}
}
void APU::Square2::write(unsigned r, uint8 data) {
auto APU::Square2::write(uint r, uint8 data) -> void {
if(r == 1) { //$ff16 NR21
duty = data >> 6;
length = (data & 0x3f);
@ -67,7 +65,7 @@ void APU::Square2::write(unsigned r, uint8 data) {
}
}
void APU::Square2::power() {
auto APU::Square2::power() -> void {
enable = 0;
duty = 0;
@ -86,7 +84,7 @@ void APU::Square2::power() {
volume = 0;
}
void APU::Square2::serialize(serializer& s) {
auto APU::Square2::serialize(serializer& s) -> void {
s.integer(enable);
s.integer(duty);
@ -104,5 +102,3 @@ void APU::Square2::serialize(serializer& s) {
s.integer(envelope_period);
s.integer(volume);
}
#endif

View File

@ -1,4 +1,14 @@
struct Square2 {
auto dac_enable() const -> bool;
auto run() -> void;
auto clock_length() -> void;
auto clock_envelope() -> void;
auto write(uint r, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
bool enable;
uint2 duty;
@ -12,16 +22,7 @@ struct Square2 {
int16 output;
bool duty_output;
uint3 phase;
unsigned period;
uint period;
uint3 envelope_period;
uint4 volume;
bool dac_enable();
void run();
void clock_length();
void clock_envelope();
void write(unsigned r, uint8 data);
void power();
void serialize(serializer&);
};

View File

@ -1,6 +1,4 @@
#ifdef APU_CPP
void APU::Wave::run() {
auto APU::Wave::run() -> void {
if(period && --period == 0) {
period = 1 * (2048 - frequency);
pattern_sample = pattern[++pattern_offset];
@ -12,13 +10,13 @@ void APU::Wave::run() {
output = sample;
}
void APU::Wave::clock_length() {
auto APU::Wave::clock_length() -> void {
if(enable && counter) {
if(++length == 0) enable = false;
}
}
void APU::Wave::write(unsigned r, uint8 data) {
auto APU::Wave::write(uint r, uint8 data) -> void {
if(r == 0) { //$ff1a NR30
dac_enable = data & 0x80;
if(dac_enable == false) enable = false;
@ -54,13 +52,13 @@ void APU::Wave::write(unsigned r, uint8 data) {
}
}
void APU::Wave::write_pattern(unsigned p, uint8 data) {
auto APU::Wave::write_pattern(uint p, uint8 data) -> void {
p <<= 1;
pattern[p + 0] = (data >> 4) & 15;
pattern[p + 1] = (data >> 0) & 15;
}
void APU::Wave::power() {
auto APU::Wave::power() -> void {
enable = 0;
dac_enable = 0;
@ -78,7 +76,7 @@ void APU::Wave::power() {
pattern_sample = 0;
}
void APU::Wave::serialize(serializer& s) {
auto APU::Wave::serialize(serializer& s) -> void {
s.integer(enable);
s.integer(dac_enable);
@ -93,5 +91,3 @@ void APU::Wave::serialize(serializer& s) {
s.integer(pattern_offset);
s.integer(pattern_sample);
}
#endif

View File

@ -1,22 +1,23 @@
struct Wave {
auto run() -> void;
auto clock_length() -> void;
auto write(uint r, uint8 data) -> void;
auto write_pattern(uint p, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
bool enable;
bool dac_enable;
unsigned volume_shift;
uint volume_shift;
uint11 frequency;
bool counter;
uint8 pattern[32];
int16 output;
uint8 length;
unsigned period;
uint period;
uint5 pattern_offset;
uint4 pattern_sample;
void run();
void clock_length();
void write(unsigned r, uint8 data);
void write_pattern(unsigned p, uint8 data);
void power();
void serialize(serializer&);
};

View File

@ -1,6 +1,5 @@
#include <gb/gb.hpp>
#define CARTRIDGE_CPP
namespace GameBoy {
#include "mbc0/mbc0.cpp"
@ -14,12 +13,21 @@ namespace GameBoy {
#include "serialization.cpp"
Cartridge cartridge;
string Cartridge::title() {
Cartridge::Cartridge() {
loaded = false;
sha256 = "";
}
Cartridge::~Cartridge() {
unload();
}
auto Cartridge::title() -> string {
return information.title;
}
//intended for use with Super Game Boy for when no Game Boy cartridge is inserted
void Cartridge::load_empty(System::Revision revision) {
auto Cartridge::load_empty(System::Revision revision) -> void {
unload();
romsize = 32768;
romdata = allocate<uint8>(romsize, 0xff);
@ -30,7 +38,7 @@ void Cartridge::load_empty(System::Revision revision) {
system.load(revision);
}
void Cartridge::load(System::Revision revision) {
auto Cartridge::load(System::Revision revision) -> void {
unload();
system.revision = revision; //needed for ID::Manifest to return correct group ID
@ -99,35 +107,35 @@ void Cartridge::load(System::Revision revision) {
system.load(revision);
}
void Cartridge::unload() {
auto Cartridge::unload() -> void {
if(romdata) { delete[] romdata; romdata = nullptr; romsize = 0; }
if(ramdata) { delete[] ramdata; ramdata = nullptr; ramsize = 0; }
loaded = false;
}
uint8 Cartridge::rom_read(unsigned addr) {
auto Cartridge::rom_read(uint addr) -> uint8 {
if(addr >= romsize) addr %= romsize;
return romdata[addr];
}
void Cartridge::rom_write(unsigned addr, uint8 data) {
auto Cartridge::rom_write(uint addr, uint8 data) -> void {
if(addr >= romsize) addr %= romsize;
romdata[addr] = data;
}
uint8 Cartridge::ram_read(unsigned addr) {
auto Cartridge::ram_read(uint addr) -> uint8 {
if(ramsize == 0) return 0x00;
if(addr >= ramsize) addr %= ramsize;
return ramdata[addr];
}
void Cartridge::ram_write(unsigned addr, uint8 data) {
auto Cartridge::ram_write(uint addr, uint8 data) -> void {
if(ramsize == 0) return;
if(addr >= ramsize) addr %= ramsize;
ramdata[addr] = data;
}
uint8 Cartridge::mmio_read(uint16 addr) {
auto Cartridge::mmio_read(uint16 addr) -> uint8 {
if(addr == 0xff50) return 0x00;
if(bootrom_enable) {
@ -144,7 +152,7 @@ uint8 Cartridge::mmio_read(uint16 addr) {
return mapper->mmio_read(addr);
}
void Cartridge::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::mmio_write(uint16 addr, uint8 data) -> void {
if(bootrom_enable && addr == 0xff50) {
bootrom_enable = false;
return;
@ -153,7 +161,7 @@ void Cartridge::mmio_write(uint16 addr, uint8 data) {
mapper->mmio_write(addr, data);
}
void Cartridge::power() {
auto Cartridge::power() -> void {
bootrom_enable = true;
mbc0.power();
@ -165,18 +173,9 @@ void Cartridge::power() {
huc1.power();
huc3.power();
for(unsigned n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = this;
for(unsigned n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = this;
for(uint n = 0x0000; n <= 0x7fff; n++) bus.mmio[n] = this;
for(uint n = 0xa000; n <= 0xbfff; n++) bus.mmio[n] = this;
bus.mmio[0xff50] = this;
}
Cartridge::Cartridge() {
loaded = false;
sha256 = "";
}
Cartridge::~Cartridge() {
unload();
}
}

View File

@ -1,4 +1,23 @@
struct Cartridge : MMIO, property<Cartridge> {
Cartridge();
~Cartridge();
auto load_empty(System::Revision revision) -> void;
auto load(System::Revision revision) -> void;
auto unload() -> void;
auto rom_read(uint addr) -> uint8;
auto rom_write(uint addr, uint8 data) -> void;
auto ram_read(uint addr) -> uint8;
auto ram_write(uint addr, uint8 data) -> void;
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
#include "mbc0/mbc0.hpp"
#include "mbc1/mbc1.hpp"
#include "mbc2/mbc2.hpp"
@ -8,7 +27,7 @@ struct Cartridge : MMIO, property<Cartridge> {
#include "huc1/huc1.hpp"
#include "huc3/huc3.hpp"
enum Mapper : unsigned {
enum Mapper : uint {
MBC0,
MBC1,
MBC2,
@ -30,14 +49,14 @@ struct Cartridge : MMIO, property<Cartridge> {
bool rtc;
bool rumble;
unsigned romsize;
unsigned ramsize;
uint romsize;
uint ramsize;
} information;
string title();
struct Memory {
unsigned id;
uint id;
string name;
};
vector<Memory> memory;
@ -45,32 +64,14 @@ struct Cartridge : MMIO, property<Cartridge> {
readonly<bool> loaded;
readonly<string> sha256;
uint8_t* romdata = nullptr;
unsigned romsize = 0;
uint8* romdata = nullptr;
uint romsize = 0;
uint8_t* ramdata = nullptr;
unsigned ramsize = 0;
uint8* ramdata = nullptr;
uint ramsize = 0;
MMIO* mapper = nullptr;
bool bootrom_enable = true;
void load_empty(System::Revision revision);
void load(System::Revision revision);
void unload();
uint8 rom_read(unsigned addr);
void rom_write(unsigned addr, uint8 data);
uint8 ram_read(unsigned addr);
void ram_write(unsigned addr, uint8 data);
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
void serialize(serializer&);
Cartridge();
~Cartridge();
};
extern Cartridge cartridge;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::HuC1::mmio_read(uint16 addr) {
auto Cartridge::HuC1::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -16,7 +14,7 @@ uint8 Cartridge::HuC1::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
ram_writable = (data & 0x0f) == 0x0a;
return;
@ -44,11 +42,9 @@ void Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::HuC1::power() {
auto Cartridge::HuC1::power() -> void {
ram_writable = false;
rom_select = 0x01;
ram_select = 0x00;
model = 0;
}
#endif

View File

@ -1,10 +1,10 @@
struct HuC1 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_writable; //$0000-1fff
uint8 rom_select; //$2000-3fff
uint8 ram_select; //$4000-5fff
bool model; //$6000-7fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} huc1;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::HuC3::mmio_read(uint16 addr) {
auto Cartridge::HuC3::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -17,7 +15,7 @@ uint8 Cartridge::HuC3::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
@ -44,10 +42,8 @@ void Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::HuC3::power() {
auto Cartridge::HuC3::power() -> void {
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
}
#endif

View File

@ -1,9 +1,9 @@
struct HuC3 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_enable; //$0000-1fff
uint8 rom_select; //$2000-3fff
uint8 ram_select; //$4000-5fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} huc3;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC0::mmio_read(uint16 addr) {
auto Cartridge::MBC0::mmio_read(uint16 addr) -> uint8 {
if((addr & 0x8000) == 0x0000) { //$0000-7fff
return cartridge.rom_read(addr);
}
@ -12,14 +10,12 @@ uint8 Cartridge::MBC0::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0xa000) { //$a000-bfff
cartridge.ram_write(addr & 0x1fff, data);
return;
}
}
void Cartridge::MBC0::power() {
auto Cartridge::MBC0::power() -> void {
}
#endif

View File

@ -1,5 +1,5 @@
struct MBC0 : MMIO {
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
} mbc0;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC1::mmio_read(uint16 addr) {
auto Cartridge::MBC1::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -27,7 +25,7 @@ uint8 Cartridge::MBC1::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
@ -60,11 +58,9 @@ void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::MBC1::power() {
auto Cartridge::MBC1::power() -> void {
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
mode_select = 0;
}
#endif

View File

@ -1,10 +1,10 @@
struct MBC1 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_enable; //$0000-1fff
uint8 rom_select; //$2000-3fff
uint8 ram_select; //$4000-5fff
bool mode_select; //$6000-7fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mbc1;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC2::mmio_read(uint16 addr) {
auto Cartridge::MBC2::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -17,7 +15,7 @@ uint8 Cartridge::MBC2::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
if(!(addr & 0x0100)) ram_enable = (data & 0x0f) == 0x0a;
return;
@ -34,9 +32,7 @@ void Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::MBC2::power() {
auto Cartridge::MBC2::power() -> void {
ram_enable = false;
rom_select = 0x01;
}
#endif

View File

@ -1,8 +1,8 @@
struct MBC2 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_enable; //$0000-1fff
uint8 rom_select; //$2000-3fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mbc2;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
void Cartridge::MBC3::second() {
auto Cartridge::MBC3::second() -> void {
if(rtc_halt == false) {
if(++rtc_second >= 60) {
rtc_second = 0;
@ -18,7 +16,7 @@ void Cartridge::MBC3::second() {
}
}
uint8 Cartridge::MBC3::mmio_read(uint16 addr) {
auto Cartridge::MBC3::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -44,7 +42,7 @@ uint8 Cartridge::MBC3::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
@ -97,7 +95,7 @@ void Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::MBC3::power() {
auto Cartridge::MBC3::power() -> void {
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
@ -116,5 +114,3 @@ void Cartridge::MBC3::power() {
rtc_latch_day = 0;
rtc_latch_day_carry = false;
}
#endif

View File

@ -1,24 +1,24 @@
struct MBC3 : MMIO {
auto second() -> void;
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_enable; //$0000-1fff
uint8 rom_select; //$2000-3fff
uint8 ram_select; //$4000-5fff
bool rtc_latch; //$6000-7fff
bool rtc_halt;
unsigned rtc_second;
unsigned rtc_minute;
unsigned rtc_hour;
unsigned rtc_day;
uint rtc_second;
uint rtc_minute;
uint rtc_hour;
uint rtc_day;
bool rtc_day_carry;
unsigned rtc_latch_second;
unsigned rtc_latch_minute;
unsigned rtc_latch_hour;
unsigned rtc_latch_day;
unsigned rtc_latch_day_carry;
void second();
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
uint rtc_latch_second;
uint rtc_latch_minute;
uint rtc_latch_hour;
uint rtc_latch_day;
uint rtc_latch_day_carry;
} mbc3;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MBC5::mmio_read(uint16 addr) {
auto Cartridge::MBC5::mmio_read(uint16 addr) -> uint8 {
if((addr & 0xc000) == 0x0000) { //$0000-3fff
return cartridge.rom_read(addr);
}
@ -17,7 +15,7 @@ uint8 Cartridge::MBC5::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
@ -44,10 +42,8 @@ void Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::MBC5::power() {
auto Cartridge::MBC5::power() -> void {
ram_enable = false;
rom_select = 0x001;
ram_select = 0x00;
}
#endif

View File

@ -1,9 +1,9 @@
struct MBC5 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool ram_enable; //$0000-1fff
uint16 rom_select; //$2000-2fff + $3000-3fff
uint8 ram_select; //$4000-5fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mbc5;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MMM01::mmio_read(uint16 addr) {
auto Cartridge::MMM01::mmio_read(uint16 addr) -> uint8 {
if((addr & 0x8000) == 0x0000) { //$0000-7fff
if(rom_mode == 0) return cartridge.rom_read(addr);
}
@ -21,7 +19,7 @@ uint8 Cartridge::MMM01::mmio_read(uint16 addr) {
return 0x00;
}
void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
auto Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) -> void {
if((addr & 0xe000) == 0x0000) { //$0000-1fff
if(rom_mode == 0) {
rom_mode = 1;
@ -53,7 +51,7 @@ void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
}
}
void Cartridge::MMM01::power() {
auto Cartridge::MMM01::power() -> void {
rom_mode = 0;
rom_base = 0;
@ -61,5 +59,3 @@ void Cartridge::MMM01::power() {
rom_select = 0x01;
ram_select = 0x00;
}
#endif

View File

@ -1,12 +1,12 @@
struct MMM01 : MMIO {
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
auto power() -> void;
bool rom_mode;
uint8 rom_base;
bool ram_enable;
uint8 rom_select;
uint8 ram_select;
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mmm01;

View File

@ -1,6 +1,4 @@
#ifdef CARTRIDGE_CPP
void Cartridge::serialize(serializer& s) {
auto Cartridge::serialize(serializer& s) -> void {
if(information.battery) s.array(ramdata, ramsize);
s.integer(bootrom_enable);
@ -50,5 +48,3 @@ void Cartridge::serialize(serializer& s) {
s.integer(huc3.rom_select);
s.integer(huc3.ram_select);
}
#endif

View File

@ -4,19 +4,19 @@ namespace GameBoy {
Cheat cheat;
void Cheat::reset() {
auto Cheat::reset() -> void {
codes.reset();
}
void Cheat::append(unsigned addr, unsigned data) {
auto Cheat::append(uint addr, uint data) -> void {
codes.append({addr, Unused, data});
}
void Cheat::append(unsigned addr, unsigned comp, unsigned data) {
auto Cheat::append(uint addr, uint comp, uint data) -> void {
codes.append({addr, comp, data});
}
maybe<unsigned> Cheat::find(unsigned addr, unsigned comp) {
auto Cheat::find(uint addr, uint comp) -> maybe<uint> {
for(auto& code : codes) {
if(code.addr == addr && (code.comp == Unused || code.comp == comp)) {
return code.data;

View File

@ -1,17 +1,18 @@
struct Cheat {
struct Code {
unsigned addr;
unsigned comp;
unsigned data;
uint addr;
uint comp;
uint data;
};
vector<Code> codes;
enum : unsigned { Unused = ~0u };
enum : uint { Unused = ~0u };
alwaysinline bool enable() const { return codes.size() > 0; }
void reset();
void append(unsigned addr, unsigned data);
void append(unsigned addr, unsigned comp, unsigned data);
maybe<unsigned> find(unsigned addr, unsigned comp);
alwaysinline auto enable() const -> bool { return codes.size() > 0; }
auto reset() -> void;
auto append(uint addr, uint data) -> void;
auto append(uint addr, uint comp, uint data) -> void;
auto find(uint addr, uint comp) -> maybe<uint>;
};
extern Cheat cheat;

View File

@ -1,6 +1,5 @@
#include <gb/gb.hpp>
#define CPU_CPP
namespace GameBoy {
#include "mmio.cpp"
@ -9,11 +8,11 @@ namespace GameBoy {
#include "serialization.cpp"
CPU cpu;
void CPU::Main() {
auto CPU::Main() -> void {
cpu.main();
}
void CPU::main() {
auto CPU::main() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
scheduler.sync = Scheduler::SynchronizeMode::All;
@ -25,7 +24,7 @@ void CPU::main() {
}
}
void CPU::interrupt_raise(CPU::Interrupt id) {
auto CPU::interrupt_raise(CPU::Interrupt id) -> void {
if(id == Interrupt::Vblank) {
status.interrupt_request_vblank = 1;
if(status.interrupt_enable_vblank) r.halt = false;
@ -52,7 +51,7 @@ void CPU::interrupt_raise(CPU::Interrupt id) {
}
}
void CPU::interrupt_test() {
auto CPU::interrupt_test() -> void {
if(r.ime) {
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
status.interrupt_request_vblank = 0;
@ -81,7 +80,7 @@ void CPU::interrupt_test() {
}
}
void CPU::interrupt_exec(uint16 pc) {
auto CPU::interrupt_exec(uint16 pc) -> void {
r.ime = 0;
op_write(--r[SP], r[PC] >> 8);
op_write(--r[SP], r[PC] >> 0);
@ -91,7 +90,7 @@ void CPU::interrupt_exec(uint16 pc) {
op_io();
}
bool CPU::stop() {
auto CPU::stop() -> bool {
if(status.speed_switch) {
status.speed_switch = 0;
status.speed_double ^= 1;
@ -102,13 +101,13 @@ bool CPU::stop() {
return false;
}
void CPU::power() {
auto CPU::power() -> void {
create(Main, 4 * 1024 * 1024);
LR35902::power();
for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM
for(unsigned n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
for(unsigned n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM
for(uint n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM
for(uint n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
for(uint n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM
bus.mmio[0xff00] = this; //JOYP
bus.mmio[0xff01] = this; //SB

View File

@ -1,14 +1,42 @@
struct CPU : Processor::LR35902, Thread, MMIO {
enum class Interrupt : unsigned {
Vblank,
Stat,
Timer,
Serial,
Joypad,
};
enum class Interrupt : uint { Vblank, Stat, Timer, Serial, Joypad };
static auto Main() -> void;
auto main() -> void;
auto interrupt_raise(Interrupt id) -> void;
auto interrupt_test() -> void;
auto interrupt_exec(uint16 pc) -> void;
auto stop() -> bool;
auto power() -> void;
auto serialize(serializer&) -> void;
//mmio.cpp
auto wram_addr(uint16 addr) const -> uint;
auto mmio_joyp_poll() -> void;
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
//memory.cpp
auto op_io() -> void;
auto op_read(uint16 addr) -> uint8;
auto op_write(uint16 addr, uint8 data) -> void;
auto cycle_edge() -> void;
auto dma_read(uint16 addr) -> uint8;
auto dma_write(uint16 addr, uint8 data) -> void;
auto debugger_read(uint16 addr) -> uint8;
//timing.cpp
auto add_clocks(uint clocks) -> void;
auto timer_262144hz() -> void;
auto timer_65536hz() -> void;
auto timer_16384hz() -> void;
auto timer_8192hz() -> void;
auto timer_4096hz() -> void;
auto hblank() -> void;
struct Status {
unsigned clock;
uint clock;
//$ff00 JOYP
bool p15;
@ -18,7 +46,7 @@ struct CPU : Processor::LR35902, Thread, MMIO {
//$ff01 SB
uint8 serial_data;
unsigned serial_bits;
uint serial_bits;
//$ff02 SC
bool serial_transfer;
@ -35,7 +63,7 @@ struct CPU : Processor::LR35902, Thread, MMIO {
//$ff07 TAC
bool timer_enable;
unsigned timer_clock;
uint timer_clock;
//$ff0f IF
bool interrupt_request_joypad;
@ -87,40 +115,6 @@ struct CPU : Processor::LR35902, Thread, MMIO {
uint8 wram[32768]; //GB=8192, GBC=32768
uint8 hram[128];
static void Main();
void main();
void interrupt_raise(Interrupt id);
void interrupt_test();
void interrupt_exec(uint16 pc);
bool stop();
void power();
void serialize(serializer&);
//mmio.cpp
unsigned wram_addr(uint16 addr) const;
void mmio_joyp_poll();
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
//memory.cpp
void op_io();
uint8 op_read(uint16 addr);
void op_write(uint16 addr, uint8 data);
void cycle_edge();
uint8 dma_read(uint16 addr);
void dma_write(uint16 addr, uint8 data);
uint8 debugger_read(uint16 addr);
//timing.cpp
void add_clocks(unsigned clocks);
void timer_262144hz();
void timer_65536hz();
void timer_16384hz();
void timer_8192hz();
void timer_4096hz();
void hblank();
};
extern CPU cpu;

View File

@ -1,25 +1,23 @@
#ifdef CPU_CPP
void CPU::op_io() {
auto CPU::op_io() -> void {
cycle_edge();
add_clocks(4);
}
uint8 CPU::op_read(uint16 addr) {
auto CPU::op_read(uint16 addr) -> uint8 {
cycle_edge();
add_clocks(4);
if(oamdma.active && (addr < 0xff80 || addr == 0xffff)) return 0x00;
return bus.read(addr);
}
void CPU::op_write(uint16 addr, uint8 data) {
auto CPU::op_write(uint16 addr, uint8 data) -> void {
cycle_edge();
add_clocks(4);
if(oamdma.active && (addr < 0xff80 || addr == 0xffff)) return;
bus.write(addr, data);
}
void CPU::cycle_edge() {
auto CPU::cycle_edge() -> void {
if(r.ei) {
r.ei = false;
r.ime = 1;
@ -27,7 +25,7 @@ void CPU::cycle_edge() {
}
//VRAM DMA source can only be ROM or RAM
uint8 CPU::dma_read(uint16 addr) {
auto CPU::dma_read(uint16 addr) -> uint8 {
if(addr < 0x8000) return bus.read(addr); //0000-7fff
if(addr < 0xa000) return 0x00; //8000-9fff
if(addr < 0xe000) return bus.read(addr); //a000-dfff
@ -35,13 +33,11 @@ uint8 CPU::dma_read(uint16 addr) {
}
//VRAM DMA target is always VRAM
void CPU::dma_write(uint16 addr, uint8 data) {
auto CPU::dma_write(uint16 addr, uint8 data) -> void {
addr = 0x8000 | (addr & 0x1fff); //8000-9fff
return bus.write(addr, data);
}
uint8 CPU::debugger_read(uint16 addr) {
auto CPU::debugger_read(uint16 addr) -> uint8 {
return bus.read(addr);
}
#endif

View File

@ -1,24 +1,22 @@
#ifdef CPU_CPP
unsigned CPU::wram_addr(uint16 addr) const {
auto CPU::wram_addr(uint16 addr) const -> uint {
addr &= 0x1fff;
if(addr < 0x1000) return addr;
auto bank = status.wram_bank + (status.wram_bank == 0);
return (bank * 0x1000) + (addr & 0x0fff);
}
void CPU::mmio_joyp_poll() {
unsigned button = 0, dpad = 0;
auto CPU::mmio_joyp_poll() -> void {
uint button = 0, dpad = 0;
button |= interface->inputPoll(0, 0, (unsigned)Input::Start) << 3;
button |= interface->inputPoll(0, 0, (unsigned)Input::Select) << 2;
button |= interface->inputPoll(0, 0, (unsigned)Input::B) << 1;
button |= interface->inputPoll(0, 0, (unsigned)Input::A) << 0;
button |= interface->inputPoll(0, 0, (uint)Input::Start) << 3;
button |= interface->inputPoll(0, 0, (uint)Input::Select) << 2;
button |= interface->inputPoll(0, 0, (uint)Input::B) << 1;
button |= interface->inputPoll(0, 0, (uint)Input::A) << 0;
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Down) << 3;
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Up) << 2;
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Left) << 1;
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Right) << 0;
dpad |= interface->inputPoll(0, 0, (uint)Input::Down) << 3;
dpad |= interface->inputPoll(0, 0, (uint)Input::Up) << 2;
dpad |= interface->inputPoll(0, 0, (uint)Input::Left) << 1;
dpad |= interface->inputPoll(0, 0, (uint)Input::Right) << 0;
if(system.revision != System::Revision::SuperGameBoy) {
//D-pad pivot makes it impossible to press opposing directions at the same time
@ -34,7 +32,7 @@ void CPU::mmio_joyp_poll() {
if(status.joyp != 0x0f) interrupt_raise(Interrupt::Joypad);
}
uint8 CPU::mmio_read(uint16 addr) {
auto CPU::mmio_read(uint16 addr) -> uint8 {
if(addr >= 0xc000 && addr <= 0xfdff) return wram[wram_addr(addr)];
if(addr >= 0xff80 && addr <= 0xfffe) return hram[addr & 0x7f];
@ -135,7 +133,7 @@ uint8 CPU::mmio_read(uint16 addr) {
return 0x00;
}
void CPU::mmio_write(uint16 addr, uint8 data) {
auto CPU::mmio_write(uint16 addr, uint8 data) -> void {
if(addr >= 0xc000 && addr <= 0xfdff) { wram[wram_addr(addr)] = data; return; }
if(addr >= 0xff80 && addr <= 0xfffe) { hram[addr & 0x7f] = data; return; }
@ -280,5 +278,3 @@ void CPU::mmio_write(uint16 addr, uint8 data) {
return;
}
}
#endif

View File

@ -1,6 +1,4 @@
#ifdef CPU_CPP
void CPU::serialize(serializer& s) {
auto CPU::serialize(serializer& s) -> void {
LR35902::serialize(s);
Thread::serialize(s);
@ -60,5 +58,3 @@ void CPU::serialize(serializer& s) {
s.integer(oamdma.bank);
s.integer(oamdma.offset);
}
#endif

View File

@ -2,11 +2,9 @@
// 456 clocks/scanline
// 154 scanlines/frame
#ifdef CPU_CPP
void CPU::add_clocks(unsigned clocks) {
auto CPU::add_clocks(uint clocks) -> void {
if(oamdma.active) {
for(unsigned n = 0; n < 4 * clocks; n++) {
for(uint n = 0; n < 4 * clocks; n++) {
bus.write(0xfe00 + oamdma.offset, bus.read((oamdma.bank << 8) + oamdma.offset));
if(++oamdma.offset == 160) {
oamdma.active = false;
@ -38,7 +36,7 @@ void CPU::add_clocks(unsigned clocks) {
if(apu.clock < 0) co_switch(scheduler.active_thread = apu.thread);
}
void CPU::timer_262144hz() {
auto CPU::timer_262144hz() -> void {
if(status.timer_enable && status.timer_clock == 1) {
if(++status.tima == 0) {
status.tima = status.tma;
@ -47,7 +45,7 @@ void CPU::timer_262144hz() {
}
}
void CPU::timer_65536hz() {
auto CPU::timer_65536hz() -> void {
if(status.timer_enable && status.timer_clock == 2) {
if(++status.tima == 0) {
status.tima = status.tma;
@ -56,7 +54,7 @@ void CPU::timer_65536hz() {
}
}
void CPU::timer_16384hz() {
auto CPU::timer_16384hz() -> void {
if(status.timer_enable && status.timer_clock == 3) {
if(++status.tima == 0) {
status.tima = status.tma;
@ -67,7 +65,7 @@ void CPU::timer_16384hz() {
status.div++;
}
void CPU::timer_8192hz() {
auto CPU::timer_8192hz() -> void {
if(status.serial_transfer && status.serial_clock) {
if(--status.serial_bits == 0) {
status.serial_transfer = 0;
@ -76,7 +74,7 @@ void CPU::timer_8192hz() {
}
}
void CPU::timer_4096hz() {
auto CPU::timer_4096hz() -> void {
if(status.timer_enable && status.timer_clock == 0) {
if(++status.tima == 0) {
status.tima = status.tma;
@ -85,14 +83,12 @@ void CPU::timer_4096hz() {
}
}
void CPU::hblank() {
auto CPU::hblank() -> void {
if(status.dma_mode == 1 && status.dma_length && ppu.status.ly < 144) {
for(unsigned n = 0; n < 16; n++) {
for(auto n : range(16)) {
dma_write(status.dma_target++, dma_read(status.dma_source++));
}
add_clocks(8 << status.speed_double);
status.dma_length -= 16;
}
}
#endif

View File

@ -4,148 +4,6 @@ namespace GameBoy {
Interface* interface = nullptr;
void Interface::lcdScanline() {
if(hook) hook->lcdScanline();
}
void Interface::lcdOutput(uint2 color) {
if(hook) hook->lcdOutput(color);
}
void Interface::joypWrite(bool p15, bool p14) {
if(hook) hook->joypWrite(p15, p14);
}
string Interface::title() {
return cartridge.title();
}
double Interface::videoFrequency() {
return 4194304.0 / (154.0 * 456.0);
}
double Interface::audioFrequency() {
return 4194304.0 / 2.0;
}
bool Interface::loaded() {
return cartridge.loaded();
}
string Interface::sha256() {
return cartridge.sha256();
}
unsigned Interface::group(unsigned id) {
switch(id) {
case ID::SystemManifest:
case ID::GameBoyBootROM:
case ID::SuperGameBoyBootROM:
case ID::GameBoyColorBootROM:
return 0;
case ID::Manifest:
case ID::ROM:
case ID::RAM:
switch(system.revision) {
case System::Revision::GameBoy: return ID::GameBoy;
case System::Revision::SuperGameBoy: return ID::SuperGameBoy;
case System::Revision::GameBoyColor: return ID::GameBoyColor;
}
throw;
}
throw;
}
void Interface::load(unsigned id) {
if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy);
if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy);
if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor);
}
void Interface::save() {
for(auto& memory : cartridge.memory) {
interface->saveRequest(memory.id, memory.name);
}
}
void Interface::load(unsigned id, const stream& stream) {
if(id == ID::SystemManifest) {
system.information.manifest = stream.text();
}
if(id == ID::GameBoyBootROM) {
stream.read(system.bootROM.dmg, min( 256u, stream.size()));
}
if(id == ID::SuperGameBoyBootROM) {
stream.read(system.bootROM.sgb, min( 256u, stream.size()));
}
if(id == ID::GameBoyColorBootROM) {
stream.read(system.bootROM.cgb, min(2048u, stream.size()));
}
if(id == ID::Manifest) {
cartridge.information.markup = stream.text();
}
if(id == ID::ROM) {
stream.read(cartridge.romdata, min(cartridge.romsize, stream.size()));
}
if(id == ID::RAM) {
stream.read(cartridge.ramdata, min(stream.size(), cartridge.ramsize));
}
}
void Interface::save(unsigned id, const stream& stream) {
if(id == ID::RAM) {
stream.write(cartridge.ramdata, cartridge.ramsize);
}
}
void Interface::unload() {
save();
cartridge.unload();
}
void Interface::power() {
system.power();
}
void Interface::reset() {
system.power();
}
void Interface::run() {
system.run();
}
serializer Interface::serialize() {
system.runtosave();
return system.serialize();
}
bool Interface::unserialize(serializer& s) {
return system.unserialize(s);
}
void Interface::cheatSet(const lstring& list) {
cheat.reset();
for(auto& codeset : list) {
lstring codes = codeset.split("+");
for(auto& code : codes) {
lstring part = code.split("/");
if(part.size() == 2) cheat.append(hex(part[0]), hex(part[1]));
if(part.size() == 3) cheat.append(hex(part[0]), hex(part[1]), hex(part[2]));
}
}
}
void Interface::paletteUpdate(PaletteMode mode) {
video.generate_palette(mode);
}
Interface::Interface() {
interface = this;
hook = nullptr;
@ -179,4 +37,146 @@ Interface::Interface() {
port.append({0, "Device", {device[0]}});
}
auto Interface::title() -> string {
return cartridge.title();
}
auto Interface::videoFrequency() -> double {
return 4194304.0 / (154.0 * 456.0);
}
auto Interface::audioFrequency() -> double {
return 4194304.0 / 2.0;
}
auto Interface::loaded() -> bool {
return cartridge.loaded();
}
auto Interface::sha256() -> string {
return cartridge.sha256();
}
auto Interface::group(uint id) -> uint {
switch(id) {
case ID::SystemManifest:
case ID::GameBoyBootROM:
case ID::SuperGameBoyBootROM:
case ID::GameBoyColorBootROM:
return 0;
case ID::Manifest:
case ID::ROM:
case ID::RAM:
switch(system.revision) {
case System::Revision::GameBoy: return ID::GameBoy;
case System::Revision::SuperGameBoy: return ID::SuperGameBoy;
case System::Revision::GameBoyColor: return ID::GameBoyColor;
}
throw;
}
throw;
}
auto Interface::load(uint id) -> void {
if(id == ID::GameBoy) cartridge.load(System::Revision::GameBoy);
if(id == ID::SuperGameBoy) cartridge.load(System::Revision::SuperGameBoy);
if(id == ID::GameBoyColor) cartridge.load(System::Revision::GameBoyColor);
}
auto Interface::save() -> void {
for(auto& memory : cartridge.memory) {
interface->saveRequest(memory.id, memory.name);
}
}
auto Interface::load(uint id, const stream& stream) -> void {
if(id == ID::SystemManifest) {
system.information.manifest = stream.text();
}
if(id == ID::GameBoyBootROM) {
stream.read(system.bootROM.dmg, min( 256u, stream.size()));
}
if(id == ID::SuperGameBoyBootROM) {
stream.read(system.bootROM.sgb, min( 256u, stream.size()));
}
if(id == ID::GameBoyColorBootROM) {
stream.read(system.bootROM.cgb, min(2048u, stream.size()));
}
if(id == ID::Manifest) {
cartridge.information.markup = stream.text();
}
if(id == ID::ROM) {
stream.read(cartridge.romdata, min(cartridge.romsize, stream.size()));
}
if(id == ID::RAM) {
stream.read(cartridge.ramdata, min(stream.size(), cartridge.ramsize));
}
}
auto Interface::save(uint id, const stream& stream) -> void {
if(id == ID::RAM) {
stream.write(cartridge.ramdata, cartridge.ramsize);
}
}
auto Interface::unload() -> void {
save();
cartridge.unload();
}
auto Interface::power() -> void {
system.power();
}
auto Interface::reset() -> void {
system.power();
}
auto Interface::run() -> void {
system.run();
}
auto Interface::serialize() -> serializer {
system.runtosave();
return system.serialize();
}
auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s);
}
auto Interface::cheatSet(const lstring& list) -> void {
cheat.reset();
for(auto& codeset : list) {
lstring codes = codeset.split("+");
for(auto& code : codes) {
lstring part = code.split("/");
if(part.size() == 2) cheat.append(hex(part[0]), hex(part[1]));
if(part.size() == 3) cheat.append(hex(part[0]), hex(part[1]), hex(part[2]));
}
}
}
auto Interface::paletteUpdate(PaletteMode mode) -> void {
video.generate_palette(mode);
}
auto Interface::lcdScanline() -> void {
if(hook) hook->lcdScanline();
}
auto Interface::lcdOutput(uint2 color) -> void {
if(hook) hook->lcdOutput(color);
}
auto Interface::joypWrite(bool p15, bool p14) -> void {
if(hook) hook->joypWrite(p15, p14);
}
}

View File

@ -3,14 +3,14 @@ namespace GameBoy {
#endif
struct ID {
enum : unsigned {
enum : uint {
System,
GameBoy,
SuperGameBoy,
GameBoyColor,
};
enum : unsigned {
enum : uint {
SystemManifest,
GameBoyBootROM,
SuperGameBoyBootROM,
@ -21,49 +21,49 @@ struct ID {
RAM,
};
enum : unsigned {
enum : uint {
Device = 1,
};
};
struct Interface : Emulator::Interface {
Interface();
auto title() -> string;
auto videoFrequency() -> double;
auto audioFrequency() -> double;
auto loaded() -> bool;
auto sha256() -> string;
auto group(uint id) -> uint;
auto load(uint id) -> void;
auto save() -> void;
auto load(uint id, const stream& stream) -> void;
auto save(uint id, const stream& stream) -> void;
auto unload() -> void;
auto power() -> void;
auto reset() -> void;
auto run() -> void;
auto serialize() -> serializer;
auto unserialize(serializer&) -> bool;
auto cheatSet(const lstring&) -> void;
auto paletteUpdate(PaletteMode mode) -> void;
//Super Game Boy bindings
struct Hook {
virtual void lcdScanline() {}
virtual void lcdOutput(uint2 color) {}
virtual void joypWrite(bool p15, bool p14) {}
virtual auto lcdScanline() -> void {}
virtual auto lcdOutput(uint2 color) -> void {}
virtual auto joypWrite(bool p15, bool p14) -> void {}
};
Hook* hook = nullptr;
void lcdScanline();
void lcdOutput(uint2 color);
void joypWrite(bool p15, bool p14);
string title();
double videoFrequency();
double audioFrequency();
bool loaded();
string sha256();
unsigned group(unsigned id);
void load(unsigned id);
void save();
void load(unsigned id, const stream& stream);
void save(unsigned id, const stream& stream);
void unload();
void power();
void reset();
void run();
serializer serialize();
bool unserialize(serializer&);
void cheatSet(const lstring&);
void paletteUpdate(PaletteMode mode);
Interface();
auto lcdScanline() -> void;
auto lcdOutput(uint2 color) -> void;
auto joypWrite(bool p15, bool p14) -> void;
private:
vector<Device> device;

View File

@ -1,47 +1,41 @@
#include <gb/gb.hpp>
#define MEMORY_CPP
namespace GameBoy {
Unmapped unmapped;
Bus bus;
uint8_t& Memory::operator[](unsigned addr) {
Memory::~Memory() {
free();
}
auto Memory::operator[](uint addr) -> uint8& {
return data[addr];
}
void Memory::allocate(unsigned size_) {
auto Memory::allocate(uint size_) -> void {
free();
size = size_;
data = new uint8_t[size]();
}
void Memory::copy(const uint8_t* data_, unsigned size_) {
auto Memory::copy(const uint8_t* data_, unsigned size_) -> void {
free();
size = size_;
data = new uint8_t[size];
memcpy(data, data_, size);
}
void Memory::free() {
auto Memory::free() -> void {
if(data) {
delete[] data;
data = 0;
data = nullptr;
}
}
Memory::Memory() {
data = 0;
size = 0;
}
Memory::~Memory() {
free();
}
//
uint8 Bus::read(uint16 addr) {
auto Bus::read(uint16 addr) -> uint8 {
uint8 data = mmio[addr]->mmio_read(addr);
if(cheat.enable()) {
@ -51,12 +45,12 @@ uint8 Bus::read(uint16 addr) {
return data;
}
void Bus::write(uint16 addr, uint8 data) {
auto Bus::write(uint16 addr, uint8 data) -> void {
mmio[addr]->mmio_write(addr, data);
}
void Bus::power() {
for(unsigned n = 0x0000; n <= 0xffff; n++) mmio[n] = &unmapped;
auto Bus::power() -> void {
for(auto n : range(65536)) mmio[n] = &unmapped;
}
}

View File

@ -1,31 +1,31 @@
struct Memory {
uint8_t* data;
unsigned size;
uint8_t& operator[](unsigned addr);
void allocate(unsigned size);
void copy(const uint8_t* data, unsigned size);
void free();
Memory();
~Memory();
auto operator[](uint addr) -> uint8&;
auto allocate(uint size) -> void;
auto copy(const uint8* data, uint size) -> void;
auto free() -> void;
uint8* data = nullptr;
uint size = 0;
};
struct MMIO {
virtual uint8 mmio_read(uint16 addr) = 0;
virtual void mmio_write(uint16 addr, uint8 data) = 0;
virtual auto mmio_read(uint16 addr) -> uint8 = 0;
virtual auto mmio_write(uint16 addr, uint8 data) -> void = 0;
};
struct Unmapped : MMIO {
uint8 mmio_read(uint16) { return 0x00; }
void mmio_write(uint16, uint8) {}
auto mmio_read(uint16) -> uint8 { return 0x00; }
auto mmio_write(uint16, uint8) -> void {}
};
struct Bus {
MMIO* mmio[65536];
uint8 read(uint16 addr);
void write(uint16 addr, uint8 data);
auto read(uint16 addr) -> uint8;
auto write(uint16 addr, uint8 data) -> void;
auto power() -> void;
void power();
MMIO* mmio[65536];
};
extern Unmapped unmapped;

View File

@ -1,5 +1,3 @@
#ifdef PPU_CPP
//BG attributes:
//0x80: 0 = OAM priority, 1 = BG priority
//0x40: vertical flip
@ -14,14 +12,14 @@
//0x08: VRAM bank#
//0x07: palette#
void PPU::cgb_read_tile(bool select, unsigned x, unsigned y, unsigned& attr, unsigned& data) {
unsigned tmaddr = 0x1800 + (select << 10);
auto PPU::cgb_read_tile(bool select, uint x, uint y, uint& attr, uint& data) -> void {
uint tmaddr = 0x1800 + (select << 10);
tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff;
unsigned tile = vram[0x0000 + tmaddr];
uint tile = vram[0x0000 + tmaddr];
attr = vram[0x2000 + tmaddr];
unsigned tdaddr = attr & 0x08 ? 0x2000 : 0x0000;
uint tdaddr = attr & 0x08 ? 0x2000 : 0x0000;
if(status.bg_tiledata_select == 0) {
tdaddr += 0x1000 + ((int8)tile << 4);
} else {
@ -37,14 +35,14 @@ void PPU::cgb_read_tile(bool select, unsigned x, unsigned y, unsigned& attr, uns
if(attr & 0x20) data = hflip(data);
}
void PPU::cgb_scanline() {
auto PPU::cgb_scanline() -> void {
px = 0;
const unsigned Height = (status.ob_size == 0 ? 8 : 16);
const uint Height = (status.ob_size == 0 ? 8 : 16);
sprites = 0;
//find first ten sprites on this scanline
for(unsigned n = 0; n < 40 * 4; n += 4) {
for(uint n = 0; n < 40 * 4; n += 4) {
Sprite& s = sprite[sprites];
s.y = oam[n + 0] - 16;
s.x = oam[n + 1] - 8;
@ -55,7 +53,7 @@ void PPU::cgb_scanline() {
if(s.y >= Height) continue;
if(s.attr & 0x40) s.y ^= (Height - 1);
unsigned tdaddr = (s.attr & 0x08 ? 0x2000 : 0x0000) + (s.tile << 4) + (s.y << 1);
uint tdaddr = (s.attr & 0x08 ? 0x2000 : 0x0000) + (s.tile << 4) + (s.y << 1);
s.data = vram[tdaddr + 0] << 0;
s.data |= vram[tdaddr + 1] << 8;
if(s.attr & 0x20) s.data = hflip(s.data);
@ -64,12 +62,12 @@ void PPU::cgb_scanline() {
}
}
void PPU::cgb_run() {
auto PPU::cgb_run() -> void {
ob.color = 0;
ob.palette = 0;
ob.priority = 0;
unsigned color = 0x7fff;
uint color = 0x7fff;
if(status.display_enable) {
cgb_run_bg();
if(status.window_display_enable) cgb_run_window();
@ -94,17 +92,17 @@ void PPU::cgb_run() {
*output = color;
}
void PPU::cgb_run_bg() {
unsigned scrolly = (status.ly + status.scy) & 255;
unsigned scrollx = (px + status.scx) & 255;
unsigned tx = scrollx & 7;
auto PPU::cgb_run_bg() -> void {
uint scrolly = (status.ly + status.scy) & 255;
uint scrollx = (px + status.scx) & 255;
uint tx = scrollx & 7;
if(tx == 0 || px == 0) cgb_read_tile(status.bg_tilemap_select, scrollx, scrolly, background.attr, background.data);
unsigned index = 0;
uint index = 0;
index |= (background.data & (0x0080 >> tx)) ? 1 : 0;
index |= (background.data & (0x8000 >> tx)) ? 2 : 0;
unsigned palette = ((background.attr & 0x07) << 2) + index;
unsigned color = 0;
uint palette = ((background.attr & 0x07) << 2) + index;
uint color = 0;
color |= bgpd[(palette << 1) + 0] << 0;
color |= bgpd[(palette << 1) + 1] << 8;
color &= 0x7fff;
@ -114,19 +112,19 @@ void PPU::cgb_run_bg() {
bg.priority = background.attr & 0x80;
}
void PPU::cgb_run_window() {
unsigned scrolly = status.ly - status.wy;
unsigned scrollx = px + 7 - status.wx;
auto PPU::cgb_run_window() -> void {
uint scrolly = status.ly - status.wy;
uint scrollx = px + 7 - status.wx;
if(scrolly >= 144u) return; //also matches underflow (scrolly < 0)
if(scrollx >= 160u) return; //also matches underflow (scrollx < 0)
unsigned tx = scrollx & 7;
uint tx = scrollx & 7;
if(tx == 0 || px == 0) cgb_read_tile(status.window_tilemap_select, scrollx, scrolly, window.attr, window.data);
unsigned index = 0;
uint index = 0;
index |= (window.data & (0x0080 >> tx)) ? 1 : 0;
index |= (window.data & (0x8000 >> tx)) ? 2 : 0;
unsigned palette = ((window.attr & 0x07) << 2) + index;
unsigned color = 0;
uint palette = ((window.attr & 0x07) << 2) + index;
uint color = 0;
color |= bgpd[(palette << 1) + 0] << 0;
color |= bgpd[(palette << 1) + 1] << 8;
color &= 0x7fff;
@ -136,21 +134,21 @@ void PPU::cgb_run_window() {
bg.priority = window.attr & 0x80;
}
void PPU::cgb_run_ob() {
auto PPU::cgb_run_ob() -> void {
//render backwards, so that first sprite has priority
for(signed n = sprites - 1; n >= 0; n--) {
for(int n = sprites - 1; n >= 0; n--) {
Sprite& s = sprite[n];
signed tx = px - s.x;
int tx = px - s.x;
if(tx < 0 || tx > 7) continue;
unsigned index = 0;
uint index = 0;
index |= (s.data & (0x0080 >> tx)) ? 1 : 0;
index |= (s.data & (0x8000 >> tx)) ? 2 : 0;
if(index == 0) continue;
unsigned palette = ((s.attr & 0x07) << 2) + index;
unsigned color = 0;
uint palette = ((s.attr & 0x07) << 2) + index;
uint color = 0;
color |= obpd[(palette << 1) + 0] << 0;
color |= obpd[(palette << 1) + 1] << 8;
color &= 0x7fff;
@ -160,5 +158,3 @@ void PPU::cgb_run_ob() {
ob.priority = !(s.attr & 0x80);
}
}
#endif

View File

@ -1,13 +1,11 @@
#ifdef PPU_CPP
//OB attributes:
//0x80: 0 = OBJ above BG, 1 = BG above OBJ
//0x40: vertical flip
//0x20: horizontal flip
//0x10: palette#
void PPU::dmg_read_tile(bool select, unsigned x, unsigned y, unsigned& data) {
unsigned tmaddr = 0x1800 + (select << 10), tdaddr;
auto PPU::dmg_read_tile(bool select, uint x, uint y, uint& data) -> void {
uint tmaddr = 0x1800 + (select << 10), tdaddr;
tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff;
if(status.bg_tiledata_select == 0) {
tdaddr = 0x1000 + ((int8)vram[tmaddr] << 4);
@ -19,14 +17,14 @@ void PPU::dmg_read_tile(bool select, unsigned x, unsigned y, unsigned& data) {
data |= vram[tdaddr + 1] << 8;
}
void PPU::dmg_scanline() {
auto PPU::dmg_scanline() -> void {
px = 0;
const unsigned Height = (status.ob_size == 0 ? 8 : 16);
const uint Height = (status.ob_size == 0 ? 8 : 16);
sprites = 0;
//find first ten sprites on this scanline
for(unsigned n = 0; n < 40 * 4; n += 4) {
for(uint n = 0; n < 40 * 4; n += 4) {
Sprite& s = sprite[sprites];
s.y = oam[n + 0] - 16;
s.x = oam[n + 1] - 8;
@ -37,7 +35,7 @@ void PPU::dmg_scanline() {
if(s.y >= Height) continue;
if(s.attr & 0x40) s.y ^= (Height - 1);
unsigned tdaddr = (s.tile << 4) + (s.y << 1);
uint tdaddr = (s.tile << 4) + (s.y << 1);
s.data = vram[tdaddr + 0] << 0;
s.data |= vram[tdaddr + 1] << 8;
if(s.attr & 0x20) s.data = hflip(s.data);
@ -46,21 +44,21 @@ void PPU::dmg_scanline() {
}
//sort by X-coordinate
for(unsigned lo = 0; lo < sprites; lo++) {
for(unsigned hi = lo + 1; hi < sprites; hi++) {
if(sprite[hi].x < sprite[lo].x) std::swap(sprite[lo], sprite[hi]);
for(uint lo = 0; lo < sprites; lo++) {
for(uint hi = lo + 1; hi < sprites; hi++) {
if(sprite[hi].x < sprite[lo].x) swap(sprite[lo], sprite[hi]);
}
}
}
void PPU::dmg_run() {
auto PPU::dmg_run() -> void {
bg.color = 0;
bg.palette = 0;
ob.color = 0;
ob.palette = 0;
unsigned color = 0;
uint color = 0;
if(status.display_enable) {
if(status.bg_enable) dmg_run_bg();
if(status.window_display_enable) dmg_run_window();
@ -82,13 +80,13 @@ void PPU::dmg_run() {
interface->lcdOutput(color); //Super Game Boy notification
}
void PPU::dmg_run_bg() {
unsigned scrolly = (status.ly + status.scy) & 255;
unsigned scrollx = (px + status.scx) & 255;
unsigned tx = scrollx & 7;
auto PPU::dmg_run_bg() -> void {
uint scrolly = (status.ly + status.scy) & 255;
uint scrollx = (px + status.scx) & 255;
uint tx = scrollx & 7;
if(tx == 0 || px == 0) dmg_read_tile(status.bg_tilemap_select, scrollx, scrolly, background.data);
unsigned index = 0;
uint index = 0;
index |= (background.data & (0x0080 >> tx)) ? 1 : 0;
index |= (background.data & (0x8000 >> tx)) ? 2 : 0;
@ -96,15 +94,15 @@ void PPU::dmg_run_bg() {
bg.palette = index;
}
void PPU::dmg_run_window() {
unsigned scrolly = status.ly - status.wy;
unsigned scrollx = px + 7 - status.wx;
auto PPU::dmg_run_window() -> void {
uint scrolly = status.ly - status.wy;
uint scrollx = px + 7 - status.wx;
if(scrolly >= 144u) return; //also matches underflow (scrolly < 0)
if(scrollx >= 160u) return; //also matches underflow (scrollx < 0)
unsigned tx = scrollx & 7;
uint tx = scrollx & 7;
if(tx == 0 || px == 0) dmg_read_tile(status.window_tilemap_select, scrollx, scrolly, window.data);
unsigned index = 0;
uint index = 0;
index |= (window.data & (0x0080 >> tx)) ? 1 : 0;
index |= (window.data & (0x8000 >> tx)) ? 2 : 0;
@ -112,15 +110,15 @@ void PPU::dmg_run_window() {
bg.palette = index;
}
void PPU::dmg_run_ob() {
auto PPU::dmg_run_ob() -> void {
//render backwards, so that first sprite has priority
for(signed n = sprites - 1; n >= 0; n--) {
for(int n = sprites - 1; n >= 0; n--) {
Sprite& s = sprite[n];
signed tx = px - s.x;
int tx = px - s.x;
if(tx < 0 || tx > 7) continue;
unsigned index = 0;
uint index = 0;
index |= (s.data & (0x0080 >> tx)) ? 1 : 0;
index |= (s.data & (0x8000 >> tx)) ? 2 : 0;
if(index == 0) continue;
@ -130,5 +128,3 @@ void PPU::dmg_run_ob() {
ob.priority = !(s.attr & 0x80);
}
}
#endif

View File

@ -1,10 +1,8 @@
#ifdef PPU_CPP
unsigned PPU::vram_addr(uint16 addr) const {
auto PPU::vram_addr(uint16 addr) const -> uint {
return (status.vram_bank * 0x2000) + (addr & 0x1fff);
}
uint8 PPU::mmio_read(uint16 addr) {
auto PPU::mmio_read(uint16 addr) -> uint8 {
if(addr >= 0x8000 && addr <= 0x9fff) return vram[vram_addr(addr)];
if(addr >= 0xfe00 && addr <= 0xfe9f) return oam[addr & 0xff];
@ -20,7 +18,7 @@ uint8 PPU::mmio_read(uint16 addr) {
}
if(addr == 0xff41) { //STAT
unsigned mode;
uint mode;
if(status.ly >= 144) mode = 1; //Vblank
else if(status.lx < 80) mode = 2; //OAM
else if(status.lx < 252) mode = 3; //LCD
@ -90,7 +88,7 @@ uint8 PPU::mmio_read(uint16 addr) {
return 0x00;
}
void PPU::mmio_write(uint16 addr, uint8 data) {
auto PPU::mmio_write(uint16 addr, uint8 data) -> void {
if(addr >= 0x8000 && addr <= 0x9fff) { vram[vram_addr(addr)] = data; return; }
if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; }
@ -199,5 +197,3 @@ void PPU::mmio_write(uint16 addr, uint8 data) {
if(status.obpi_increment) status.obpi++;
}
}
#endif

View File

@ -6,7 +6,6 @@
//LX = 0-455
#define PPU_CPP
namespace GameBoy {
#include "mmio.cpp"
@ -15,11 +14,11 @@ namespace GameBoy {
#include "serialization.cpp"
PPU ppu;
void PPU::Main() {
auto PPU::Main() -> void {
ppu.main();
}
void PPU::main() {
auto PPU::main() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
@ -30,7 +29,7 @@ void PPU::main() {
if(status.display_enable && status.ly < 144) {
if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
add_clocks(92);
for(unsigned n = 0; n < 160; n++) {
for(auto n : range(160)) {
system.cgb() ? cgb_run() : dmg_run();
add_clocks(1);
}
@ -45,7 +44,7 @@ void PPU::main() {
}
}
void PPU::add_clocks(unsigned clocks) {
auto PPU::add_clocks(uint clocks) -> void {
status.lx += clocks;
clock += clocks * cpu.frequency;
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) {
@ -53,7 +52,7 @@ void PPU::add_clocks(unsigned clocks) {
}
}
void PPU::scanline() {
auto PPU::scanline() -> void {
status.lx = 0;
if(++status.ly == 154) frame();
@ -71,23 +70,23 @@ void PPU::scanline() {
}
}
void PPU::frame() {
auto PPU::frame() -> void {
status.ly = 0;
scheduler.exit(Scheduler::ExitReason::FrameEvent);
}
unsigned PPU::hflip(unsigned data) const {
auto PPU::hflip(uint data) const -> uint {
return ((data & 0x8080) >> 7) | ((data & 0x4040) >> 5)
| ((data & 0x2020) >> 3) | ((data & 0x1010) >> 1)
| ((data & 0x0808) << 1) | ((data & 0x0404) << 3)
| ((data & 0x0202) << 5) | ((data & 0x0101) << 7);
}
void PPU::power() {
auto PPU::power() -> void {
create(Main, 4 * 1024 * 1024);
for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM
for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM
for(uint n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM
for(uint n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM
bus.mmio[0xff40] = this; //LCDC
bus.mmio[0xff41] = this; //STAT
@ -174,7 +173,4 @@ void PPU::power() {
window.data = 0;
}
PPU::PPU() {
}
}

View File

@ -1,4 +1,37 @@
struct PPU : Thread, MMIO {
static auto Main() -> void;
auto main() -> void;
auto add_clocks(uint clocks) -> void;
auto scanline() -> void;
auto frame() -> void;
auto hflip(uint data) const -> uint;
//mmio.cpp
auto vram_addr(uint16 addr) const -> uint;
auto mmio_read(uint16 addr) -> uint8;
auto mmio_write(uint16 addr, uint8 data) -> void;
//dmg.cpp
auto dmg_read_tile(bool select, uint x, uint y, uint& data) -> void;
auto dmg_scanline() -> void;
auto dmg_run() -> void;
auto dmg_run_bg() -> void;
auto dmg_run_window() -> void;
auto dmg_run_ob() -> void;
//cgb.cpp
auto cgb_read_tile(bool select, uint x, uint y, uint& attr, uint& data) -> void;
auto cgb_scanline() -> void;
auto cgb_run() -> void;
auto cgb_run_bg() -> void;
auto cgb_run_window() -> void;
auto cgb_run_ob() -> void;
auto power() -> void;
auto serialize(serializer&) -> void;
uint8 vram[16384]; //GB = 8192, GBC = 16384
uint8 oam[160];
uint8 bgp[4];
@ -7,7 +40,7 @@ struct PPU : Thread, MMIO {
uint8 obpd[64];
struct Status {
unsigned lx;
uint lx;
//$ff40 LCDC
bool display_enable;
@ -66,57 +99,23 @@ struct PPU : Thread, MMIO {
Pixel ob;
struct Sprite {
unsigned x;
unsigned y;
unsigned tile;
unsigned attr;
unsigned data;
uint x;
uint y;
uint tile;
uint attr;
uint data;
};
Sprite sprite[10];
unsigned sprites;
uint sprites;
unsigned px;
uint px;
struct Background {
unsigned attr;
unsigned data;
uint attr;
uint data;
};
Background background;
Background window;
static void Main();
void main();
void add_clocks(unsigned clocks);
void scanline();
void frame();
unsigned hflip(unsigned data) const;
//mmio.cpp
unsigned vram_addr(uint16 addr) const;
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
//dmg.cpp
void dmg_read_tile(bool select, unsigned x, unsigned y, unsigned& data);
void dmg_scanline();
void dmg_run();
void dmg_run_bg();
void dmg_run_window();
void dmg_run_ob();
//cgb.cpp
void cgb_read_tile(bool select, unsigned x, unsigned y, unsigned& attr, unsigned& data);
void cgb_scanline();
void cgb_run();
void cgb_run_bg();
void cgb_run_window();
void cgb_run_ob();
void power();
void serialize(serializer&);
PPU();
};
extern PPU ppu;

View File

@ -1,6 +1,4 @@
#ifdef PPU_CPP
void PPU::serialize(serializer& s) {
auto PPU::serialize(serializer& s) -> void {
Thread::serialize(s);
s.array(vram);
@ -68,5 +66,3 @@ void PPU::serialize(serializer& s) {
s.integer(window.attr);
s.integer(window.data);
}
#endif

View File

@ -1,30 +1,23 @@
#include <gb/gb.hpp>
#define SCHEDULER_CPP
namespace GameBoy {
Scheduler scheduler;
void Scheduler::enter() {
auto Scheduler::init() -> void {
host_thread = co_active();
active_thread = cpu.thread;
}
auto Scheduler::enter() -> void {
host_thread = co_active();
co_switch(active_thread);
}
void Scheduler::exit(ExitReason reason) {
auto Scheduler::exit(ExitReason reason) -> void {
exit_reason = reason;
active_thread = co_active();
co_switch(host_thread);
}
void Scheduler::init() {
host_thread = co_active();
active_thread = cpu.thread;
}
Scheduler::Scheduler() {
exit_reason = ExitReason::UnknownEvent;
host_thread = nullptr;
active_thread = nullptr;
}
}

View File

@ -1,16 +1,14 @@
struct Scheduler : property<Scheduler> {
enum class SynchronizeMode : unsigned { None, CPU, All } sync;
enum class ExitReason : unsigned { UnknownEvent, StepEvent, FrameEvent, SynchronizeEvent };
readonly<ExitReason> exit_reason;
struct Scheduler {
enum class SynchronizeMode : uint { None, CPU, All } sync;
enum class ExitReason : uint { UnknownEvent, StepEvent, FrameEvent, SynchronizeEvent };
cothread_t host_thread;
cothread_t active_thread;
auto init() -> void;
auto enter() -> void;
auto exit(ExitReason) -> void;
void enter();
void exit(ExitReason);
void init();
Scheduler();
cothread_t host_thread = nullptr;
cothread_t active_thread = nullptr;
ExitReason exit_reason = ExitReason::UnknownEvent;
};
extern Scheduler scheduler;

View File

@ -1,9 +1,7 @@
#ifdef SYSTEM_CPP
serializer System::serialize() {
auto System::serialize() -> serializer {
serializer s(serialize_size);
unsigned signature = 0x31545342, version = Info::SerializerVersion;
uint signature = 0x31545342, version = Info::SerializerVersion;
char hash[64], description[512];
memcpy(&hash, (const char*)cartridge.sha256(), 64);
memset(&description, 0, sizeof description);
@ -17,8 +15,8 @@ serializer System::serialize() {
return s;
}
bool System::unserialize(serializer& s) {
unsigned signature, version;
auto System::unserialize(serializer& s) -> bool {
uint signature, version;
char hash[64], description[512];
s.integer(signature);
@ -34,11 +32,11 @@ bool System::unserialize(serializer& s) {
return true;
}
void System::serialize(serializer& s) {
auto System::serialize(serializer& s) -> void {
s.integer(clocks_executed);
}
void System::serialize_all(serializer& s) {
auto System::serialize_all(serializer& s) -> void {
cartridge.serialize(s);
system.serialize(s);
cpu.serialize(s);
@ -46,10 +44,10 @@ void System::serialize_all(serializer& s) {
apu.serialize(s);
}
void System::serialize_init() {
auto System::serialize_init() -> void {
serializer s;
unsigned signature = 0, version = 0, crc32 = 0;
uint signature = 0, version = 0, crc32 = 0;
char hash[64], description[512];
s.integer(signature);
@ -60,5 +58,3 @@ void System::serialize_init() {
serialize_all(s);
serialize_size = s.size();
}
#endif

View File

@ -1,21 +1,26 @@
#include <gb/gb.hpp>
#define SYSTEM_CPP
namespace GameBoy {
#include "serialization.cpp"
System system;
void System::run() {
System::System() {
for(auto& byte : bootROM.dmg) byte = 0;
for(auto& byte : bootROM.sgb) byte = 0;
for(auto& byte : bootROM.cgb) byte = 0;
}
auto System::run() -> void {
scheduler.sync = Scheduler::SynchronizeMode::None;
scheduler.enter();
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
if(scheduler.exit_reason == Scheduler::ExitReason::FrameEvent) {
interface->videoRefresh(video.palette, ppu.screen, 4 * 160, 160, 144);
}
}
void System::runtosave() {
auto System::runtosave() -> void {
scheduler.sync = Scheduler::SynchronizeMode::CPU;
runthreadtosave();
@ -30,21 +35,21 @@ void System::runtosave() {
scheduler.sync = Scheduler::SynchronizeMode::None;
}
void System::runthreadtosave() {
auto System::runthreadtosave() -> void {
while(true) {
scheduler.enter();
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
if(scheduler.exit_reason == Scheduler::ExitReason::SynchronizeEvent) break;
if(scheduler.exit_reason == Scheduler::ExitReason::FrameEvent) {
interface->videoRefresh(video.palette, ppu.screen, 4 * 160, 160, 144);
}
}
}
void System::init() {
auto System::init() -> void {
assert(interface != nullptr);
}
void System::load(Revision revision) {
auto System::load(Revision revision) -> void {
this->revision = revision;
serialize_init();
if(revision == Revision::SuperGameBoy) return; //Super Famicom core loads boot ROM for SGB
@ -60,7 +65,7 @@ void System::load(Revision revision) {
}
}
void System::power() {
auto System::power() -> void {
bus.power();
cartridge.power();
cpu.power();
@ -71,10 +76,4 @@ void System::power() {
clocks_executed = 0;
}
System::System() {
for(auto& byte : bootROM.dmg) byte = 0;
for(auto& byte : bootROM.sgb) byte = 0;
for(auto& byte : bootROM.cgb) byte = 0;
}
}

View File

@ -1,19 +1,37 @@
class Interface;
enum class Input : unsigned {
enum class Input : uint {
Up, Down, Left, Right, B, A, Select, Start,
};
struct System {
enum class Revision : unsigned {
enum class Revision : uint {
GameBoy,
SuperGameBoy,
GameBoyColor,
} revision;
inline bool dmg() const { return revision == Revision::GameBoy; }
inline bool sgb() const { return revision == Revision::SuperGameBoy; }
inline bool cgb() const { return revision == Revision::GameBoyColor; }
System();
inline auto dmg() const { return revision == Revision::GameBoy; }
inline auto sgb() const { return revision == Revision::SuperGameBoy; }
inline auto cgb() const { return revision == Revision::GameBoyColor; }
auto run() -> void;
auto runtosave() -> void;
auto runthreadtosave() -> void;
auto init() -> void;
auto load(Revision) -> void;
auto power() -> void;
//serialization.cpp
auto serialize() -> serializer;
auto unserialize(serializer&) -> bool;
auto serialize(serializer&) -> void;
auto serialize_all(serializer&) -> void;
auto serialize_init() -> void;
struct BootROM {
uint8 dmg[ 256];
@ -21,31 +39,12 @@ struct System {
uint8 cgb[2048];
} bootROM;
void run();
void runtosave();
void runthreadtosave();
void init();
void load(Revision);
void power();
unsigned clocks_executed;
//serialization.cpp
unsigned serialize_size;
serializer serialize();
bool unserialize(serializer&);
void serialize(serializer&);
void serialize_all(serializer&);
void serialize_init();
System();
struct Information {
string manifest;
} information;
uint clocks_executed = 0;
uint serialize_size = 0;
};
#include <gb/interface/interface.hpp>

View File

@ -1,17 +1,9 @@
#include <gb/gb.hpp>
#define VIDEO_CPP
namespace GameBoy {
Video video;
void Video::generate_palette(Emulator::Interface::PaletteMode mode) {
this->mode = mode;
if(system.dmg()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_dmg(n);
if(system.sgb()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_sgb(n);
if(system.cgb()) for(unsigned n = 0; n < (1 << 15); n++) palette[n] = palette_cgb(n);
}
Video::Video() {
palette = new uint32_t[1 << 15]();
}
@ -20,43 +12,50 @@ Video::~Video() {
delete[] palette;
}
unsigned Video::palette_dmg(unsigned color) const {
auto Video::generate_palette(Emulator::Interface::PaletteMode mode) -> void {
this->mode = mode;
if(system.dmg()) for(auto n : range(4)) palette[n] = paletteDMG(n);
if(system.sgb()) for(auto n : range(4)) palette[n] = paletteSGB(n);
if(system.cgb()) for(auto n : range(1 << 15)) palette[n] = paletteCGB(n);
}
auto Video::paletteDMG(uint color) const -> uint {
if(mode == Emulator::Interface::PaletteMode::Literal) {
return color;
}
if(mode == Emulator::Interface::PaletteMode::Channel) {
unsigned L = image::normalize(color, 2, 16);
uint L = image::normalize(color, 2, 16);
return interface->videoColor(color, 0, 0, 0, L);
}
if(mode == Emulator::Interface::PaletteMode::Standard) {
unsigned L = image::normalize(3 - color, 2, 16);
uint L = image::normalize(3 - color, 2, 16);
return interface->videoColor(color, 0, L, L, L);
}
if(mode == Emulator::Interface::PaletteMode::Emulation) {
unsigned R = monochrome[color][0];
unsigned G = monochrome[color][1];
unsigned B = monochrome[color][2];
uint R = monochrome[color][0];
uint G = monochrome[color][1];
uint B = monochrome[color][2];
return interface->videoColor(color, 0, R, G, B);
}
return 0;
}
unsigned Video::palette_sgb(unsigned color) const {
auto Video::paletteSGB(uint color) const -> uint {
return color;
}
unsigned Video::palette_cgb(unsigned color) const {
auto Video::paletteCGB(uint color) const -> uint {
if(mode == Emulator::Interface::PaletteMode::Literal) {
return color;
}
unsigned r = (color >> 0) & 31;
unsigned g = (color >> 5) & 31;
unsigned b = (color >> 10) & 31;
uint r = (color >> 0) & 31;
uint g = (color >> 5) & 31;
uint b = (color >> 10) & 31;
if(mode == Emulator::Interface::PaletteMode::Channel) {
r = image::normalize(r, 5, 16);
@ -73,9 +72,9 @@ unsigned Video::palette_cgb(unsigned color) const {
}
if(mode == Emulator::Interface::PaletteMode::Emulation) {
unsigned R = (r * 26 + g * 4 + b * 2);
unsigned G = ( g * 24 + b * 8);
unsigned B = (r * 6 + g * 4 + b * 22);
uint R = (r * 26 + g * 4 + b * 2);
uint G = ( g * 24 + b * 8);
uint B = (r * 6 + g * 4 + b * 22);
R = min(960, R);
G = min(960, G);

View File

@ -1,16 +1,17 @@
struct Video {
uint32_t* palette = nullptr;
void generate_palette(Emulator::Interface::PaletteMode mode);
Video();
~Video();
auto generate_palette(Emulator::Interface::PaletteMode mode) -> void;
uint32* palette = nullptr;
private:
Emulator::Interface::PaletteMode mode;
static const uint16 monochrome[4][3];
uint32_t palette_dmg(unsigned color) const;
uint32_t palette_sgb(unsigned color) const;
uint32_t palette_cgb(unsigned color) const;
auto paletteDMG(uint color) const -> uint;
auto paletteSGB(uint color) const -> uint;
auto paletteCGB(uint color) const -> uint;
};
extern Video video;

View File

@ -1,14 +1,16 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct Buffer {
double** sample = nullptr;
uint16_t rdoffset = 0;
uint16_t wroffset = 0;
unsigned channels = 0;
Buffer() {
}
void setChannels(unsigned channels) {
~Buffer() {
setChannels(0);
}
auto setChannels(uint channels) -> void {
if(sample) {
for(unsigned c = 0; c < this->channels; c++) {
for(auto c : range(this->channels)) {
if(sample[c]) delete[] sample[c];
}
delete[] sample;
@ -18,22 +20,22 @@ struct Buffer {
if(channels == 0) return;
sample = new double*[channels];
for(unsigned c = 0; c < channels; c++) {
for(auto c : range(channels)) {
sample[c] = new double[65536]();
}
}
inline double& read(unsigned channel, signed offset = 0) {
return sample[channel][(uint16_t)(rdoffset + offset)];
inline auto read(uint channel, int offset = 0) -> double& {
return sample[channel][(uint16)(rdoffset + offset)];
}
inline double& write(unsigned channel, signed offset = 0) {
return sample[channel][(uint16_t)(wroffset + offset)];
inline auto write(uint channel, int offset = 0) -> double& {
return sample[channel][(uint16)(wroffset + offset)];
}
inline void clear() {
for(unsigned c = 0; c < channels; c++) {
for(unsigned n = 0; n < 65536; n++) {
inline auto clear() -> void {
for(auto c : range(channels)) {
for(auto n : range(65536)) {
sample[c][n] = 0;
}
}
@ -41,12 +43,10 @@ struct Buffer {
wroffset = 0;
}
Buffer() {
}
~Buffer() {
setChannels(0);
}
double** sample = nullptr;
uint16 rdoffset = 0;
uint16 wroffset = 0;
uint channels = 0;
};
#endif

View File

@ -6,24 +6,22 @@
namespace nall {
//precision: can be float, double or long double
#define real float
struct DSP;
struct Resampler {
DSP& dsp;
real frequency;
virtual void setFrequency() = 0;
virtual void clear() = 0;
virtual void sample() = 0;
Resampler(DSP& dsp) : dsp(dsp) {}
virtual ~Resampler() {}
virtual auto setFrequency() -> void = 0;
virtual auto clear() -> void = 0;
virtual auto sample() -> void = 0;
DSP& dsp;
double frequency = 44100.0;
};
struct DSP {
enum class ResampleEngine : unsigned {
enum class ResampleEngine : uint {
Nearest,
Linear,
Cosine,
@ -33,24 +31,48 @@ struct DSP {
Sinc,
};
inline void setChannels(unsigned channels);
inline void setPrecision(unsigned precision);
inline void setFrequency(real frequency); //inputFrequency
inline void setVolume(real volume);
inline void setBalance(real balance);
inline void setResampler(ResampleEngine resamplingEngine);
inline void setResamplerFrequency(real frequency); //outputFrequency
inline void sample(signed channel[]);
inline bool pending();
inline void read(signed channel[]);
inline void clear();
inline DSP();
inline ~DSP();
inline auto setChannels(uint channels) -> void;
inline auto setPrecision(uint precision) -> void;
inline auto setFrequency(double frequency) -> void; //inputFrequency
inline auto setVolume(double volume) -> void;
inline auto setBalance(double balance) -> void;
inline auto setResampler(ResampleEngine resamplingEngine) -> void;
inline auto setResamplerFrequency(double frequency) -> void; //outputFrequency
inline auto sample(int channel[]) -> void;
inline auto pending() const -> bool;
inline auto read(int channel[]) -> void;
inline auto clear() -> void;
protected:
inline auto write(double channel[]) -> void;
inline auto adjustVolume() -> void;
inline auto adjustBalance() -> void;
inline auto clamp(const uint bits, const int input) -> int;
struct Settings {
uint channels;
uint precision;
double frequency;
double volume;
double balance;
//internal
double intensity;
double intensityInverse;
} settings;
Resampler* resampler = nullptr;
#include "buffer.hpp"
Buffer buffer;
Buffer output;
friend class ResampleNearest;
friend class ResampleLinear;
friend class ResampleCosine;
@ -58,29 +80,6 @@ protected:
friend class ResampleAverage;
friend class ResampleHermite;
friend class ResampleSinc;
struct Settings {
unsigned channels;
unsigned precision;
real frequency;
real volume;
real balance;
//internal
real intensity;
real intensityInverse;
} settings;
Resampler* resampler = nullptr;
inline void write(real channel[]);
#include "buffer.hpp"
Buffer buffer;
Buffer output;
inline void adjustVolume();
inline void adjustBalance();
inline signed clamp(const unsigned bits, const signed x);
};
#include "resample/nearest.hpp"
@ -92,59 +91,6 @@ protected:
#include "resample/sinc.hpp"
#include "settings.hpp"
void DSP::sample(signed channel[]) {
for(unsigned c = 0; c < settings.channels; c++) {
buffer.write(c) = (real)channel[c] * settings.intensityInverse;
}
buffer.wroffset++;
resampler->sample();
}
bool DSP::pending() {
return output.rdoffset != output.wroffset;
}
void DSP::read(signed channel[]) {
adjustVolume();
adjustBalance();
for(unsigned c = 0; c < settings.channels; c++) {
channel[c] = clamp(settings.precision, output.read(c) * settings.intensity);
}
output.rdoffset++;
}
void DSP::write(real channel[]) {
for(unsigned c = 0; c < settings.channels; c++) {
output.write(c) = channel[c];
}
output.wroffset++;
}
void DSP::adjustVolume() {
for(unsigned c = 0; c < settings.channels; c++) {
output.read(c) *= settings.volume;
}
}
void DSP::adjustBalance() {
if(settings.channels != 2) return; //TODO: support > 2 channels
if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
}
signed DSP::clamp(const unsigned bits, const signed x) {
const signed b = 1U << (bits - 1);
const signed m = (1U << (bits - 1)) - 1;
return (x > m) ? m : (x < -b) ? -b : x;
}
void DSP::clear() {
buffer.clear();
output.clear();
resampler->clear();
}
DSP::DSP() {
setResampler(ResampleEngine::Hermite);
setResamplerFrequency(44100.0);
@ -162,7 +108,58 @@ DSP::~DSP() {
if(resampler) delete resampler;
}
#undef real
auto DSP::sample(int channel[]) -> void {
for(auto c : range(settings.channels)) {
buffer.write(c) = (double)channel[c] * settings.intensityInverse;
}
buffer.wroffset++;
resampler->sample();
}
auto DSP::pending() const -> bool {
return output.rdoffset != output.wroffset;
}
auto DSP::read(int channel[]) -> void {
adjustVolume();
adjustBalance();
for(auto c : range(settings.channels)) {
channel[c] = clamp(settings.precision, output.read(c) * settings.intensity);
}
output.rdoffset++;
}
auto DSP::write(double channel[]) -> void {
for(auto c : range(settings.channels)) {
output.write(c) = channel[c];
}
output.wroffset++;
}
auto DSP::adjustVolume() -> void {
for(auto c : range(settings.channels)) {
output.read(c) *= settings.volume;
}
}
auto DSP::adjustBalance() -> void {
if(settings.channels != 2) return; //TODO: support > 2 channels
if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
}
auto DSP::clamp(const uint bits, const int x) -> int {
const int b = 1U << (bits - 1);
const int m = (1U << (bits - 1)) - 1;
return (x > m) ? m : (x < -b) ? -b : x;
}
auto DSP::clear() -> void {
buffer.clear();
output.clear();
resampler->clear();
}
}

View File

@ -1,46 +1,48 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleAverage : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
inline void sampleLinear();
ResampleAverage(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
inline auto sampleLinear() -> void;
private:
double fraction;
double step;
};
void ResampleAverage::setFrequency() {
auto ResampleAverage::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleAverage::clear() {
auto ResampleAverage::clear() -> void {
fraction = 0.0;
}
void ResampleAverage::sample() {
auto ResampleAverage::sample() -> void {
//can only average if input frequency >= output frequency
if(step < 1.0) return sampleLinear();
fraction += 1.0;
real scalar = 1.0;
double scalar = 1.0;
if(fraction > step) scalar = 1.0 - (fraction - step);
for(unsigned c = 0; c < dsp.settings.channels; c++) {
for(auto c : range(dsp.settings.channels)) {
dsp.output.write(c) += dsp.buffer.read(c) * scalar;
}
if(fraction >= step) {
for(unsigned c = 0; c < dsp.settings.channels; c++) {
for(auto c : range(dsp.settings.channels)) {
dsp.output.write(c) /= step;
}
dsp.output.wroffset++;
fraction -= step;
for(unsigned c = 0; c < dsp.settings.channels; c++) {
for(auto c : range(dsp.settings.channels)) {
dsp.output.write(c) = dsp.buffer.read(c) * fraction;
}
}
@ -48,15 +50,15 @@ void ResampleAverage::sample() {
dsp.buffer.rdoffset++;
}
void ResampleAverage::sampleLinear() {
auto ResampleAverage::sampleLinear() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -1);
real b = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -1);
double b = dsp.buffer.read(n, -0);
real mu = fraction;
double mu = fraction;
channel[n] = a * (1.0 - mu) + b * mu;
}

View File

@ -1,33 +1,35 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleCosine : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
ResampleCosine(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
double fraction;
double step;
};
void ResampleCosine::setFrequency() {
auto ResampleCosine::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleCosine::clear() {
auto ResampleCosine::clear() -> void {
fraction = 0.0;
}
void ResampleCosine::sample() {
auto ResampleCosine::sample() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -1);
real b = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -1);
double b = dsp.buffer.read(n, -0);
real mu = fraction;
double mu = fraction;
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
channel[n] = a * (1.0 - mu) + b * mu;

View File

@ -1,40 +1,42 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleCubic : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
ResampleCubic(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
double fraction;
double step;
};
void ResampleCubic::setFrequency() {
auto ResampleCubic::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleCubic::clear() {
auto ResampleCubic::clear() -> void {
fraction = 0.0;
}
void ResampleCubic::sample() {
auto ResampleCubic::sample() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -3);
real b = dsp.buffer.read(n, -2);
real c = dsp.buffer.read(n, -1);
real d = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -3);
double b = dsp.buffer.read(n, -2);
double c = dsp.buffer.read(n, -1);
double d = dsp.buffer.read(n, -0);
real mu = fraction;
double mu = fraction;
real A = d - c - a + b;
real B = a - b - A;
real C = c - a;
real D = b;
double A = d - c - a + b;
double B = a - b - A;
double C = c - a;
double D = b;
channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D;
}

View File

@ -1,38 +1,40 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleHermite : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
ResampleHermite(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
double fraction;
double step;
};
void ResampleHermite::setFrequency() {
auto ResampleHermite::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleHermite::clear() {
auto ResampleHermite::clear() -> void {
fraction = 0.0;
}
void ResampleHermite::sample() {
auto ResampleHermite::sample() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -3);
real b = dsp.buffer.read(n, -2);
real c = dsp.buffer.read(n, -1);
real d = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -3);
double b = dsp.buffer.read(n, -2);
double c = dsp.buffer.read(n, -1);
double d = dsp.buffer.read(n, -0);
const real tension = 0.0; //-1 = low, 0 = normal, +1 = high
const real bias = 0.0; //-1 = left, 0 = even, +1 = right
const double tension = 0.0; //-1 = low, 0 = normal, +1 = high
const double bias = 0.0; //-1 = left, 0 = even, +1 = right
real mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
mu1 = fraction;
mu2 = mu1 * mu1;

View File

@ -1,33 +1,35 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleLinear : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
ResampleLinear(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
double fraction;
double step;
};
void ResampleLinear::setFrequency() {
auto ResampleLinear::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleLinear::clear() {
auto ResampleLinear::clear() -> void {
fraction = 0.0;
}
void ResampleLinear::sample() {
auto ResampleLinear::sample() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -1);
real b = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -1);
double b = dsp.buffer.read(n, -0);
real mu = fraction;
double mu = fraction;
channel[n] = a * (1.0 - mu) + b * mu;
}

View File

@ -1,33 +1,35 @@
#ifdef NALL_DSP_INTERNAL_HPP
struct ResampleNearest : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
ResampleNearest(DSP& dsp) : Resampler(dsp) {}
real fraction;
real step;
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
double fraction;
double step;
};
void ResampleNearest::setFrequency() {
auto ResampleNearest::setFrequency() -> void {
fraction = 0.0;
step = dsp.settings.frequency / frequency;
}
void ResampleNearest::clear() {
auto ResampleNearest::clear() -> void {
fraction = 0.0;
}
void ResampleNearest::sample() {
auto ResampleNearest::sample() -> void {
while(fraction <= 1.0) {
real channel[dsp.settings.channels];
double channel[dsp.settings.channels];
for(unsigned n = 0; n < dsp.settings.channels; n++) {
real a = dsp.buffer.read(n, -1);
real b = dsp.buffer.read(n, -0);
for(auto n : range(dsp.settings.channels)) {
double a = dsp.buffer.read(n, -1);
double b = dsp.buffer.read(n, -0);
real mu = fraction;
double mu = fraction;
channel[n] = mu < 0.5 ? a : b;
}

View File

@ -3,51 +3,61 @@
#include "lib/sinc.hpp"
struct ResampleSinc : Resampler {
inline void setFrequency();
inline void clear();
inline void sample();
inline ResampleSinc(DSP& dsp);
inline ~ResampleSinc();
inline auto setFrequency() -> void;
inline auto clear() -> void;
inline auto sample() -> void;
private:
inline void remakeSinc();
SincResample* sinc_resampler[8];
SincResample* sincResampler[8] = {0};
};
void ResampleSinc::setFrequency() {
ResampleSinc::ResampleSinc(DSP& dsp) : Resampler(dsp) {
for(auto n : range(8)) {
sincResampler[n] = nullptr;
}
}
ResampleSinc::~ResampleSinc() {
for(auto n : range(8)) {
if(sincResampler[n]) delete sincResampler[n];
}
}
auto ResampleSinc::setFrequency() -> void {
remakeSinc();
}
void ResampleSinc::clear() {
auto ResampleSinc::clear() -> void {
remakeSinc();
}
void ResampleSinc::sample() {
for(unsigned c = 0; c < dsp.settings.channels; c++) {
sinc_resampler[c]->write(dsp.buffer.read(c));
auto ResampleSinc::sample() -> void {
for(auto c : range(dsp.settings.channels)) {
sincResampler[c]->write(dsp.buffer.read(c));
}
if(sinc_resampler[0]->output_avail()) {
if(sincResampler[0]->output_avail()) {
do {
for(unsigned c = 0; c < dsp.settings.channels; c++) {
dsp.output.write(c) = sinc_resampler[c]->read();
for(auto c : range(dsp.settings.channels)) {
dsp.output.write(c) = sincResampler[c]->read();
}
dsp.output.wroffset++;
} while(sinc_resampler[0]->output_avail());
} while(sincResampler[0]->output_avail());
}
dsp.buffer.rdoffset++;
}
ResampleSinc::ResampleSinc(DSP& dsp) : Resampler(dsp) {
for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = nullptr;
}
void ResampleSinc::remakeSinc() {
auto ResampleSinc::remakeSinc() -> void {
assert(dsp.settings.channels < 8);
for(unsigned c = 0; c < dsp.settings.channels; c++) {
if(sinc_resampler[c]) delete sinc_resampler[c];
sinc_resampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH);
for(auto c : range(dsp.settings.channels)) {
if(sincResampler[c]) delete sincResampler[c];
sincResampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH);
}
}

View File

@ -1,35 +1,35 @@
#ifdef NALL_DSP_INTERNAL_HPP
void DSP::setChannels(unsigned channels) {
assert(channels > 0);
auto DSP::setChannels(uint channels) -> void {
channels = max(1u, channels);
buffer.setChannels(channels);
output.setChannels(channels);
settings.channels = channels;
}
void DSP::setPrecision(unsigned precision) {
auto DSP::setPrecision(uint precision) -> void {
settings.precision = precision;
settings.intensity = 1 << (settings.precision - 1);
settings.intensityInverse = 1.0 / settings.intensity;
}
void DSP::setFrequency(real frequency) {
auto DSP::setFrequency(double frequency) -> void {
settings.frequency = frequency;
resampler->setFrequency();
}
void DSP::setVolume(real volume) {
auto DSP::setVolume(double volume) -> void {
settings.volume = volume;
}
void DSP::setBalance(real balance) {
auto DSP::setBalance(double balance) -> void {
settings.balance = balance;
}
void DSP::setResampler(ResampleEngine engine) {
auto DSP::setResampler(ResampleEngine engine) -> void {
if(resampler) delete resampler;
switch(engine) {
switch(engine) { default:
case ResampleEngine::Nearest: resampler = new ResampleNearest(*this); return;
case ResampleEngine::Linear: resampler = new ResampleLinear (*this); return;
case ResampleEngine::Cosine: resampler = new ResampleCosine (*this); return;
@ -38,11 +38,9 @@ void DSP::setResampler(ResampleEngine engine) {
case ResampleEngine::Average: resampler = new ResampleAverage(*this); return;
case ResampleEngine::Sinc: resampler = new ResampleSinc (*this); return;
}
throw;
}
void DSP::setResamplerFrequency(real frequency) {
auto DSP::setResamplerFrequency(double frequency) -> void {
resampler->frequency = frequency;
resampler->setFrequency();
}

View File

@ -7,7 +7,7 @@ namespace Processor {
#include "instructions.cpp"
#include "serialization.cpp"
void HG51B::exec(uint24 addr) {
auto HG51B::exec(uint24 addr) -> void {
if(regs.halt) return;
addr = addr + regs.pc * 2;
opcode = bus_read(addr++) << 0;
@ -16,7 +16,7 @@ void HG51B::exec(uint24 addr) {
instruction();
}
void HG51B::power() {
auto HG51B::power() -> void {
regs.halt = true;
regs.n = 0;

View File

@ -1,29 +1,56 @@
//Hitachi HG51B169 (HG51BS family/derivative?)
#ifndef PROCESSOR_HG51B_HPP
#define PROCESSOR_HG51B_HPP
namespace Processor {
//Hitachi HG51B169 (HG51BS family/derivative?)
struct HG51B {
auto exec(uint24 addr) -> void;
virtual auto bus_read(uint24 addr) -> uint8 = 0;
virtual auto bus_write(uint24 addr, uint8 data) -> void = 0;
auto power() -> void;
auto serialize(serializer&) -> void;
//uint16 programROM[2][256];
uint24 dataROM[1024];
uint8 dataRAM[3072];
#include "registers.hpp"
void exec(uint24 addr);
virtual uint8 bus_read(uint24 addr) = 0;
virtual void bus_write(uint24 addr, uint8 data) = 0;
void power();
void serialize(serializer&);
protected:
void push();
void pull();
unsigned sa();
unsigned ri();
unsigned np();
void instruction();
auto push() -> void;
auto pull() -> void;
auto sa() -> uint;
auto ri() -> uint;
auto np() -> uint;
auto instruction() -> void;
//registers.cpp
auto reg_read(uint8 addr) const -> uint24;
auto reg_write(uint8 addr, uint24 data) -> void;
struct Registers {
bool halt;
uint24 pc;
uint16 p;
bool n;
bool z;
bool c;
uint24 a;
uint24 acch;
uint24 accl;
uint24 busdata;
uint24 romdata;
uint24 ramdata;
uint24 busaddr;
uint24 ramaddr;
uint24 gpr[16];
} regs;
uint24 stack[8];
uint16 opcode;
};
}

View File

@ -1,6 +1,6 @@
#ifdef PROCESSOR_HG51B_HPP
void HG51B::push() {
auto HG51B::push() -> void {
stack[7] = stack[6];
stack[6] = stack[5];
stack[5] = stack[4];
@ -11,7 +11,7 @@ void HG51B::push() {
stack[0] = regs.pc;
}
void HG51B::pull() {
auto HG51B::pull() -> void {
regs.pc = stack[0];
stack[0] = stack[1];
stack[1] = stack[2];
@ -24,7 +24,7 @@ void HG51B::pull() {
}
//Shift-A: math opcodes can shift A register prior to ALU operation
unsigned HG51B::sa() {
auto HG51B::sa() -> uint {
switch(opcode & 0x0300) { default:
case 0x0000: return regs.a << 0;
case 0x0100: return regs.a << 1;
@ -34,18 +34,18 @@ unsigned HG51B::sa() {
}
//Register-or-Immediate: most opcodes can load from a register or immediate
unsigned HG51B::ri() {
auto HG51B::ri() -> uint {
if(opcode & 0x0400) return opcode & 0xff;
return reg_read(opcode & 0xff);
}
//New-PC: determine jump target address; opcode.d9 = long jump flag (1 = yes)
unsigned HG51B::np() {
auto HG51B::np() -> uint {
if(opcode & 0x0200) return (regs.p << 8) | (opcode & 0xff);
return (regs.pc & 0xffff00) | (opcode & 0xff);
}
void HG51B::instruction() {
auto HG51B::instruction() -> void {
if((opcode & 0xffff) == 0x0000) {
//0000 0000 0000 0000
//nop

View File

@ -1,6 +1,6 @@
#ifdef PROCESSOR_HG51B_HPP
uint24 HG51B::reg_read(uint8 addr) const {
auto HG51B::reg_read(uint8 addr) const -> uint24 {
switch(addr) {
case 0x00: return regs.a;
case 0x01: return regs.acch;
@ -46,7 +46,7 @@ uint24 HG51B::reg_read(uint8 addr) const {
return 0x000000;
}
void HG51B::reg_write(uint8 addr, uint24 data) {
auto HG51B::reg_write(uint8 addr, uint24 data) -> void {
switch(addr) {
case 0x00: regs.a = data; return;
case 0x01: regs.acch = data; return;

View File

@ -1,25 +0,0 @@
struct Registers {
bool halt;
uint24 pc;
uint16 p;
bool n;
bool z;
bool c;
uint24 a;
uint24 acch;
uint24 accl;
uint24 busdata;
uint24 romdata;
uint24 ramdata;
uint24 busaddr;
uint24 ramaddr;
uint24 gpr[16];
} regs;
uint24 stack[8];
uint16 opcode;
uint24 reg_read(uint8 addr) const;
void reg_write(uint8 addr, uint24 data);

View File

@ -1,6 +1,6 @@
#ifdef PROCESSOR_HG51B_HPP
void HG51B::serialize(serializer& s) {
auto HG51B::serialize(serializer& s) -> void {
s.array(dataRAM);
for(auto& n : stack) s.integer(n);
s.integer(opcode);

View File

@ -1,9 +1,9 @@
string LR35902::disassemble(uint16 pc) {
auto LR35902::disassemble(uint16 pc) -> string {
char output[80];
memset(output, ' ', sizeof output);
output[79] = 0;
string opcode = disassemble_opcode(pc);
string opcode = disassembleOpcode(pc);
string registers = {
" AF:", hex(r[AF], 4L),
" BC:", hex(r[BC], 4L),
@ -19,7 +19,7 @@ string LR35902::disassemble(uint16 pc) {
return output;
}
string LR35902::disassemble_opcode(uint16 pc) {
auto LR35902::disassembleOpcode(uint16 pc) -> string {
uint8 opcode = debugger_read(pc);
uint8 p0 = debugger_read(pc + 1);
uint8 p1 = debugger_read(pc + 2);
@ -229,7 +229,7 @@ string LR35902::disassemble_opcode(uint16 pc) {
case 0xc8: return { "ret z" };
case 0xc9: return { "ret" };
case 0xca: return { "jp z,$", hex(p1, 2L), hex(p0, 2L) };
case 0xcb: return disassemble_opcode_cb(pc + 1);
case 0xcb: return disassembleOpcodeCB(pc + 1);
case 0xcc: return { "call z,$", hex(p1, 2L), hex(p0, 2L) };
case 0xcd: return { "call $", hex(p1, 2L), hex(p0, 2L) };
case 0xce: return { "adc a,$", hex(p0, 2L) };
@ -287,7 +287,7 @@ string LR35902::disassemble_opcode(uint16 pc) {
return "";
}
string LR35902::disassemble_opcode_cb(uint16 pc) {
auto LR35902::disassembleOpcodeCB(uint16 pc) -> string {
uint8 opcode = debugger_read(pc);
uint8 p0 = debugger_read(pc + 1);
uint8 p1 = debugger_read(pc + 2);

View File

@ -1,121 +1,121 @@
void LR35902::op_xx() {
auto LR35902::op_xx() {
}
void LR35902::op_cb() {
exec_cb();
auto LR35902::op_cb() {
execCB();
}
//8-bit load commands
template<unsigned x, unsigned y> void LR35902::op_ld_r_r() {
template<uint x, uint y> auto LR35902::op_ld_r_r() {
r[x] = r[y];
}
template<unsigned x> void LR35902::op_ld_r_n() {
template<uint x> auto LR35902::op_ld_r_n() {
r[x] = op_read(r[PC]++);
}
template<unsigned x> void LR35902::op_ld_r_hl() {
template<uint x> auto LR35902::op_ld_r_hl() {
r[x] = op_read(r[HL]);
}
template<unsigned x> void LR35902::op_ld_hl_r() {
template<uint x> auto LR35902::op_ld_hl_r() {
op_write(r[HL], r[x]);
}
void LR35902::op_ld_hl_n() {
auto LR35902::op_ld_hl_n() {
op_write(r[HL], op_read(r[PC]++));
}
template<unsigned x> void LR35902::op_ld_a_rr() {
template<uint x> auto LR35902::op_ld_a_rr() {
r[A] = op_read(r[x]);
}
void LR35902::op_ld_a_nn() {
auto LR35902::op_ld_a_nn() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
r[A] = op_read((hi << 8) | (lo << 0));
}
template<unsigned x> void LR35902::op_ld_rr_a() {
template<uint x> auto LR35902::op_ld_rr_a() {
op_write(r[x], r[A]);
}
void LR35902::op_ld_nn_a() {
auto LR35902::op_ld_nn_a() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
op_write((hi << 8) | (lo << 0), r[A]);
}
void LR35902::op_ld_a_ffn() {
auto LR35902::op_ld_a_ffn() {
r[A] = op_read(0xff00 + op_read(r[PC]++));
}
void LR35902::op_ld_ffn_a() {
auto LR35902::op_ld_ffn_a() {
op_write(0xff00 + op_read(r[PC]++), r[A]);
}
void LR35902::op_ld_a_ffc() {
auto LR35902::op_ld_a_ffc() {
r[A] = op_read(0xff00 + r[C]);
}
void LR35902::op_ld_ffc_a() {
auto LR35902::op_ld_ffc_a() {
op_write(0xff00 + r[C], r[A]);
}
void LR35902::op_ldi_hl_a() {
auto LR35902::op_ldi_hl_a() {
op_write(r[HL], r[A]);
r[HL]++;
}
void LR35902::op_ldi_a_hl() {
auto LR35902::op_ldi_a_hl() {
r[A] = op_read(r[HL]);
r[HL]++;
}
void LR35902::op_ldd_hl_a() {
auto LR35902::op_ldd_hl_a() {
op_write(r[HL], r[A]);
r[HL]--;
}
void LR35902::op_ldd_a_hl() {
auto LR35902::op_ldd_a_hl() {
r[A] = op_read(r[HL]);
r[HL]--;
}
//16-bit load commands
template<unsigned x> void LR35902::op_ld_rr_nn() {
template<uint x> auto LR35902::op_ld_rr_nn() {
r[x] = op_read(r[PC]++) << 0;
r[x] |= op_read(r[PC]++) << 8;
}
void LR35902::op_ld_nn_sp() {
auto LR35902::op_ld_nn_sp() {
uint16 addr = op_read(r[PC]++) << 0;
addr |= op_read(r[PC]++) << 8;
op_write(addr + 0, r[SP] >> 0);
op_write(addr + 1, r[SP] >> 8);
}
void LR35902::op_ld_sp_hl() {
auto LR35902::op_ld_sp_hl() {
r[SP] = r[HL];
op_io();
}
template<unsigned x> void LR35902::op_push_rr() {
template<uint x> auto LR35902::op_push_rr() {
op_write(--r[SP], r[x] >> 8);
op_write(--r[SP], r[x] >> 0);
op_io();
}
template<unsigned x> void LR35902::op_pop_rr() {
template<uint x> auto LR35902::op_pop_rr() {
r[x] = op_read(r[SP]++) << 0;
r[x] |= op_read(r[SP]++) << 8;
}
//8-bit arithmetic commands
void LR35902::opi_add_a(uint8 x) {
auto LR35902::opi_add_a(uint8 x) {
uint16 rh = r[A] + x;
uint16 rl = (r[A] & 0x0f) + (x & 0x0f);
r[A] = rh;
@ -125,11 +125,11 @@ void LR35902::opi_add_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<unsigned x> void LR35902::op_add_a_r() { opi_add_a(r[x]); }
void LR35902::op_add_a_n() { opi_add_a(op_read(r[PC]++)); }
void LR35902::op_add_a_hl() { opi_add_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_add_a_r() { opi_add_a(r[x]); }
auto LR35902::op_add_a_n() { opi_add_a(op_read(r[PC]++)); }
auto LR35902::op_add_a_hl() { opi_add_a(op_read(r[HL])); }
void LR35902::opi_adc_a(uint8 x) {
auto LR35902::opi_adc_a(uint8 x) {
uint16 rh = r[A] + x + r.f.c;
uint16 rl = (r[A] & 0x0f) + (x & 0x0f) + r.f.c;
r[A] = rh;
@ -139,11 +139,11 @@ void LR35902::opi_adc_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<unsigned x> void LR35902::op_adc_a_r() { opi_adc_a(r[x]); }
void LR35902::op_adc_a_n() { opi_adc_a(op_read(r[PC]++)); }
void LR35902::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_adc_a_r() { opi_adc_a(r[x]); }
auto LR35902::op_adc_a_n() { opi_adc_a(op_read(r[PC]++)); }
auto LR35902::op_adc_a_hl() { opi_adc_a(op_read(r[HL])); }
void LR35902::opi_sub_a(uint8 x) {
auto LR35902::opi_sub_a(uint8 x) {
uint16 rh = r[A] - x;
uint16 rl = (r[A] & 0x0f) - (x & 0x0f);
r[A] = rh;
@ -153,11 +153,11 @@ void LR35902::opi_sub_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<unsigned x> void LR35902::op_sub_a_r() { opi_sub_a(r[x]); }
void LR35902::op_sub_a_n() { opi_sub_a(op_read(r[PC]++)); }
void LR35902::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_sub_a_r() { opi_sub_a(r[x]); }
auto LR35902::op_sub_a_n() { opi_sub_a(op_read(r[PC]++)); }
auto LR35902::op_sub_a_hl() { opi_sub_a(op_read(r[HL])); }
void LR35902::opi_sbc_a(uint8 x) {
auto LR35902::opi_sbc_a(uint8 x) {
uint16 rh = r[A] - x - r.f.c;
uint16 rl = (r[A] & 0x0f) - (x & 0x0f) - r.f.c;
r[A] = rh;
@ -167,11 +167,11 @@ void LR35902::opi_sbc_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<unsigned x> void LR35902::op_sbc_a_r() { opi_sbc_a(r[x]); }
void LR35902::op_sbc_a_n() { opi_sbc_a(op_read(r[PC]++)); }
void LR35902::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_sbc_a_r() { opi_sbc_a(r[x]); }
auto LR35902::op_sbc_a_n() { opi_sbc_a(op_read(r[PC]++)); }
auto LR35902::op_sbc_a_hl() { opi_sbc_a(op_read(r[HL])); }
void LR35902::opi_and_a(uint8 x) {
auto LR35902::opi_and_a(uint8 x) {
r[A] &= x;
r.f.z = r[A] == 0;
r.f.n = 0;
@ -179,11 +179,11 @@ void LR35902::opi_and_a(uint8 x) {
r.f.c = 0;
}
template<unsigned x> void LR35902::op_and_a_r() { opi_and_a(r[x]); }
void LR35902::op_and_a_n() { opi_and_a(op_read(r[PC]++)); }
void LR35902::op_and_a_hl() { opi_and_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_and_a_r() { opi_and_a(r[x]); }
auto LR35902::op_and_a_n() { opi_and_a(op_read(r[PC]++)); }
auto LR35902::op_and_a_hl() { opi_and_a(op_read(r[HL])); }
void LR35902::opi_xor_a(uint8 x) {
auto LR35902::opi_xor_a(uint8 x) {
r[A] ^= x;
r.f.z = r[A] == 0;
r.f.n = 0;
@ -191,11 +191,11 @@ void LR35902::opi_xor_a(uint8 x) {
r.f.c = 0;
}
template<unsigned x> void LR35902::op_xor_a_r() { opi_xor_a(r[x]); }
void LR35902::op_xor_a_n() { opi_xor_a(op_read(r[PC]++)); }
void LR35902::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_xor_a_r() { opi_xor_a(r[x]); }
auto LR35902::op_xor_a_n() { opi_xor_a(op_read(r[PC]++)); }
auto LR35902::op_xor_a_hl() { opi_xor_a(op_read(r[HL])); }
void LR35902::opi_or_a(uint8 x) {
auto LR35902::opi_or_a(uint8 x) {
r[A] |= x;
r.f.z = r[A] == 0;
r.f.n = 0;
@ -203,11 +203,11 @@ void LR35902::opi_or_a(uint8 x) {
r.f.c = 0;
}
template<unsigned x> void LR35902::op_or_a_r() { opi_or_a(r[x]); }
void LR35902::op_or_a_n() { opi_or_a(op_read(r[PC]++)); }
void LR35902::op_or_a_hl() { opi_or_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_or_a_r() { opi_or_a(r[x]); }
auto LR35902::op_or_a_n() { opi_or_a(op_read(r[PC]++)); }
auto LR35902::op_or_a_hl() { opi_or_a(op_read(r[HL])); }
void LR35902::opi_cp_a(uint8 x) {
auto LR35902::opi_cp_a(uint8 x) {
uint16 rh = r[A] - x;
uint16 rl = (r[A] & 0x0f) - (x & 0x0f);
r.f.z = (uint8)rh == 0;
@ -216,18 +216,18 @@ void LR35902::opi_cp_a(uint8 x) {
r.f.c = rh > 0xff;
}
template<unsigned x> void LR35902::op_cp_a_r() { opi_cp_a(r[x]); }
void LR35902::op_cp_a_n() { opi_cp_a(op_read(r[PC]++)); }
void LR35902::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); }
template<uint x> auto LR35902::op_cp_a_r() { opi_cp_a(r[x]); }
auto LR35902::op_cp_a_n() { opi_cp_a(op_read(r[PC]++)); }
auto LR35902::op_cp_a_hl() { opi_cp_a(op_read(r[HL])); }
template<unsigned x> void LR35902::op_inc_r() {
template<uint x> auto LR35902::op_inc_r() {
r[x]++;
r.f.z = r[x] == 0;
r.f.n = 0;
r.f.h = (r[x] & 0x0f) == 0x00;
}
void LR35902::op_inc_hl() {
auto LR35902::op_inc_hl() {
uint8 n = op_read(r[HL]);
op_write(r[HL], ++n);
r.f.z = n == 0;
@ -235,14 +235,14 @@ void LR35902::op_inc_hl() {
r.f.h = (n & 0x0f) == 0x00;
}
template<unsigned x> void LR35902::op_dec_r() {
template<uint x> auto LR35902::op_dec_r() {
r[x]--;
r.f.z = r[x] == 0;
r.f.n = 1;
r.f.h = (r[x] & 0x0f) == 0x0f;
}
void LR35902::op_dec_hl() {
auto LR35902::op_dec_hl() {
uint8 n = op_read(r[HL]);
op_write(r[HL], --n);
r.f.z = n == 0;
@ -250,7 +250,7 @@ void LR35902::op_dec_hl() {
r.f.h = (n & 0x0f) == 0x0f;
}
void LR35902::op_daa() {
auto LR35902::op_daa() {
uint16 a = r[A];
if(r.f.n == 0) {
if(r.f.h || (a & 0x0f) > 0x09) a += 0x06;
@ -268,7 +268,7 @@ void LR35902::op_daa() {
r.f.c |= a & 0x100;
}
void LR35902::op_cpl() {
auto LR35902::op_cpl() {
r[A] ^= 0xff;
r.f.n = 1;
r.f.h = 1;
@ -276,7 +276,7 @@ void LR35902::op_cpl() {
//16-bit arithmetic commands
template<unsigned x> void LR35902::op_add_hl_rr() {
template<uint x> auto LR35902::op_add_hl_rr() {
op_io();
uint32 rb = (r[HL] + r[x]);
uint32 rn = (r[HL] & 0xfff) + (r[x] & 0xfff);
@ -286,20 +286,20 @@ template<unsigned x> void LR35902::op_add_hl_rr() {
r.f.c = rb > 0xffff;
}
template<unsigned x> void LR35902::op_inc_rr() {
template<uint x> auto LR35902::op_inc_rr() {
op_io();
r[x]++;
}
template<unsigned x> void LR35902::op_dec_rr() {
template<uint x> auto LR35902::op_dec_rr() {
op_io();
r[x]--;
}
void LR35902::op_add_sp_n() {
auto LR35902::op_add_sp_n() {
op_io();
op_io();
signed n = (int8)op_read(r[PC]++);
int n = (int8)op_read(r[PC]++);
r.f.z = 0;
r.f.n = 0;
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
@ -307,9 +307,9 @@ void LR35902::op_add_sp_n() {
r[SP] += n;
}
void LR35902::op_ld_hl_sp_n() {
auto LR35902::op_ld_hl_sp_n() {
op_io();
signed n = (int8)op_read(r[PC]++);
int n = (int8)op_read(r[PC]++);
r.f.z = 0;
r.f.n = 0;
r.f.h = ((r[SP] & 0x0f) + (n & 0x0f)) > 0x0f;
@ -319,7 +319,7 @@ void LR35902::op_ld_hl_sp_n() {
//rotate/shift commands
void LR35902::op_rlca() {
auto LR35902::op_rlca() {
r[A] = (r[A] << 1) | (r[A] >> 7);
r.f.z = 0;
r.f.n = 0;
@ -327,7 +327,7 @@ void LR35902::op_rlca() {
r.f.c = r[A] & 0x01;
}
void LR35902::op_rla() {
auto LR35902::op_rla() {
bool c = r[A] & 0x80;
r[A] = (r[A] << 1) | (r.f.c << 0);
r.f.z = 0;
@ -336,7 +336,7 @@ void LR35902::op_rla() {
r.f.c = c;
}
void LR35902::op_rrca() {
auto LR35902::op_rrca() {
r[A] = (r[A] >> 1) | (r[A] << 7);
r.f.z = 0;
r.f.n = 0;
@ -344,7 +344,7 @@ void LR35902::op_rrca() {
r.f.c = r[A] & 0x80;
}
void LR35902::op_rra() {
auto LR35902::op_rra() {
bool c = r[A] & 0x01;
r[A] = (r[A] >> 1) | (r.f.c << 7);
r.f.z = 0;
@ -353,7 +353,7 @@ void LR35902::op_rra() {
r.f.c = c;
}
template<unsigned x> void LR35902::op_rlc_r() {
template<uint x> auto LR35902::op_rlc_r() {
r[x] = (r[x] << 1) | (r[x] >> 7);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -361,7 +361,7 @@ template<unsigned x> void LR35902::op_rlc_r() {
r.f.c = r[x] & 0x01;
}
void LR35902::op_rlc_hl() {
auto LR35902::op_rlc_hl() {
uint8 n = op_read(r[HL]);
n = (n << 1) | (n >> 7);
op_write(r[HL], n);
@ -371,7 +371,7 @@ void LR35902::op_rlc_hl() {
r.f.c = n & 0x01;
}
template<unsigned x> void LR35902::op_rl_r() {
template<uint x> auto LR35902::op_rl_r() {
bool c = r[x] & 0x80;
r[x] = (r[x] << 1) | (r.f.c << 0);
r.f.z = r[x] == 0;
@ -380,7 +380,7 @@ template<unsigned x> void LR35902::op_rl_r() {
r.f.c = c;
}
void LR35902::op_rl_hl() {
auto LR35902::op_rl_hl() {
uint8 n = op_read(r[HL]);
bool c = n & 0x80;
n = (n << 1) | (r.f.c << 0);
@ -391,7 +391,7 @@ void LR35902::op_rl_hl() {
r.f.c = c;
}
template<unsigned x> void LR35902::op_rrc_r() {
template<uint x> auto LR35902::op_rrc_r() {
r[x] = (r[x] >> 1) | (r[x] << 7);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -399,7 +399,7 @@ template<unsigned x> void LR35902::op_rrc_r() {
r.f.c = r[x] & 0x80;
}
void LR35902::op_rrc_hl() {
auto LR35902::op_rrc_hl() {
uint8 n = op_read(r[HL]);
n = (n >> 1) | (n << 7);
op_write(r[HL], n);
@ -409,7 +409,7 @@ void LR35902::op_rrc_hl() {
r.f.c = n & 0x80;
}
template<unsigned x> void LR35902::op_rr_r() {
template<uint x> auto LR35902::op_rr_r() {
bool c = r[x] & 0x01;
r[x] = (r[x] >> 1) | (r.f.c << 7);
r.f.z = r[x] == 0;
@ -418,7 +418,7 @@ template<unsigned x> void LR35902::op_rr_r() {
r.f.c = c;
}
void LR35902::op_rr_hl() {
auto LR35902::op_rr_hl() {
uint8 n = op_read(r[HL]);
bool c = n & 0x01;
n = (n >> 1) | (r.f.c << 7);
@ -429,7 +429,7 @@ void LR35902::op_rr_hl() {
r.f.c = c;
}
template<unsigned x> void LR35902::op_sla_r() {
template<uint x> auto LR35902::op_sla_r() {
bool c = r[x] & 0x80;
r[x] <<= 1;
r.f.z = r[x] == 0;
@ -438,7 +438,7 @@ template<unsigned x> void LR35902::op_sla_r() {
r.f.c = c;
}
void LR35902::op_sla_hl() {
auto LR35902::op_sla_hl() {
uint8 n = op_read(r[HL]);
bool c = n & 0x80;
n <<= 1;
@ -449,7 +449,7 @@ void LR35902::op_sla_hl() {
r.f.c = c;
}
template<unsigned x> void LR35902::op_swap_r() {
template<uint x> auto LR35902::op_swap_r() {
r[x] = (r[x] << 4) | (r[x] >> 4);
r.f.z = r[x] == 0;
r.f.n = 0;
@ -457,7 +457,7 @@ template<unsigned x> void LR35902::op_swap_r() {
r.f.c = 0;
}
void LR35902::op_swap_hl() {
auto LR35902::op_swap_hl() {
uint8 n = op_read(r[HL]);
n = (n << 4) | (n >> 4);
op_write(r[HL], n);
@ -467,7 +467,7 @@ void LR35902::op_swap_hl() {
r.f.c = 0;
}
template<unsigned x> void LR35902::op_sra_r() {
template<uint x> auto LR35902::op_sra_r() {
bool c = r[x] & 0x01;
r[x] = (int8)r[x] >> 1;
r.f.z = r[x] == 0;
@ -476,7 +476,7 @@ template<unsigned x> void LR35902::op_sra_r() {
r.f.c = c;
}
void LR35902::op_sra_hl() {
auto LR35902::op_sra_hl() {
uint8 n = op_read(r[HL]);
bool c = n & 0x01;
n = (int8)n >> 1;
@ -487,7 +487,7 @@ void LR35902::op_sra_hl() {
r.f.c = c;
}
template<unsigned x> void LR35902::op_srl_r() {
template<uint x> auto LR35902::op_srl_r() {
bool c = r[x] & 0x01;
r[x] >>= 1;
r.f.z = r[x] == 0;
@ -496,7 +496,7 @@ template<unsigned x> void LR35902::op_srl_r() {
r.f.c = c;
}
void LR35902::op_srl_hl() {
auto LR35902::op_srl_hl() {
uint8 n = op_read(r[HL]);
bool c = n & 0x01;
n >>= 1;
@ -509,34 +509,34 @@ void LR35902::op_srl_hl() {
//single-bit commands
template<unsigned b, unsigned x> void LR35902::op_bit_n_r() {
template<uint b, uint x> auto LR35902::op_bit_n_r() {
r.f.z = (r[x] & (1 << b)) == 0;
r.f.n = 0;
r.f.h = 1;
}
template<unsigned b> void LR35902::op_bit_n_hl() {
template<uint b> auto LR35902::op_bit_n_hl() {
uint8 n = op_read(r[HL]);
r.f.z = (n & (1 << b)) == 0;
r.f.n = 0;
r.f.h = 1;
}
template<unsigned b, unsigned x> void LR35902::op_set_n_r() {
template<uint b, uint x> auto LR35902::op_set_n_r() {
r[x] |= 1 << b;
}
template<unsigned b> void LR35902::op_set_n_hl() {
template<uint b> auto LR35902::op_set_n_hl() {
uint8 n = op_read(r[HL]);
n |= 1 << b;
op_write(r[HL], n);
}
template<unsigned b, unsigned x> void LR35902::op_res_n_r() {
template<uint b, uint x> auto LR35902::op_res_n_r() {
r[x] &= ~(1 << b);
}
template<unsigned b> void LR35902::op_res_n_hl() {
template<uint b> auto LR35902::op_res_n_hl() {
uint8 n = op_read(r[HL]);
n &= ~(1 << b);
op_write(r[HL], n);
@ -544,55 +544,55 @@ template<unsigned b> void LR35902::op_res_n_hl() {
//control commands
void LR35902::op_ccf() {
auto LR35902::op_ccf() {
r.f.n = 0;
r.f.h = 0;
r.f.c = !r.f.c;
}
void LR35902::op_scf() {
auto LR35902::op_scf() {
r.f.n = 0;
r.f.h = 0;
r.f.c = 1;
}
void LR35902::op_nop() {
auto LR35902::op_nop() {
}
void LR35902::op_halt() {
auto LR35902::op_halt() {
r.halt = true;
while(r.halt == true) op_io();
}
void LR35902::op_stop() {
auto LR35902::op_stop() {
if(stop()) return;
r.stop = true;
while(r.stop == true) op_io();
}
void LR35902::op_di() {
auto LR35902::op_di() {
r.ime = 0;
}
void LR35902::op_ei() {
auto LR35902::op_ei() {
r.ei = true;
//r.ime = 1;
}
//jump commands
void LR35902::op_jp_nn() {
auto LR35902::op_jp_nn() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
r[PC] = (hi << 8) | (lo << 0);
op_io();
}
void LR35902::op_jp_hl() {
auto LR35902::op_jp_hl() {
r[PC] = r[HL];
}
template<unsigned x, bool y> void LR35902::op_jp_f_nn() {
template<uint x, bool y> auto LR35902::op_jp_f_nn() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
if(r.f[x] == y) {
@ -601,13 +601,13 @@ template<unsigned x, bool y> void LR35902::op_jp_f_nn() {
}
}
void LR35902::op_jr_n() {
auto LR35902::op_jr_n() {
int8 n = op_read(r[PC]++);
r[PC] += n;
op_io();
}
template<unsigned x, bool y> void LR35902::op_jr_f_n() {
template<uint x, bool y> auto LR35902::op_jr_f_n() {
int8 n = op_read(r[PC]++);
if(r.f[x] == y) {
r[PC] += n;
@ -615,7 +615,7 @@ template<unsigned x, bool y> void LR35902::op_jr_f_n() {
}
}
void LR35902::op_call_nn() {
auto LR35902::op_call_nn() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
op_write(--r[SP], r[PC] >> 8);
@ -624,7 +624,7 @@ void LR35902::op_call_nn() {
op_io();
}
template<unsigned x, bool y> void LR35902::op_call_f_nn() {
template<uint x, bool y> auto LR35902::op_call_f_nn() {
uint8 lo = op_read(r[PC]++);
uint8 hi = op_read(r[PC]++);
if(r.f[x] == y) {
@ -635,14 +635,14 @@ template<unsigned x, bool y> void LR35902::op_call_f_nn() {
}
}
void LR35902::op_ret() {
auto LR35902::op_ret() {
uint8 lo = op_read(r[SP]++);
uint8 hi = op_read(r[SP]++);
r[PC] = (hi << 8) | (lo << 0);
op_io();
}
template<unsigned x, bool y> void LR35902::op_ret_f() {
template<uint x, bool y> auto LR35902::op_ret_f() {
op_io();
if(r.f[x] == y) {
uint8 lo = op_read(r[SP]++);
@ -652,7 +652,7 @@ template<unsigned x, bool y> void LR35902::op_ret_f() {
}
}
void LR35902::op_reti() {
auto LR35902::op_reti() {
uint8 lo = op_read(r[SP]++);
uint8 hi = op_read(r[SP]++);
r[PC] = (hi << 8) | (lo << 0);
@ -660,7 +660,7 @@ void LR35902::op_reti() {
r.ime = 1;
}
template<unsigned n> void LR35902::op_rst_n() {
template<uint n> auto LR35902::op_rst_n() {
op_write(--r[SP], r[PC] >> 8);
op_write(--r[SP], r[PC] >> 0);
r[PC] = n;

View File

@ -7,14 +7,14 @@ namespace Processor {
#include "disassembler.cpp"
#include "serialization.cpp"
void LR35902::power() {
auto LR35902::power() -> void {
r.halt = false;
r.stop = false;
r.ei = false;
r.ime = false;
}
void LR35902::exec() {
auto LR35902::exec() -> void {
uint8 opcode = op_read(r[PC]++);
switch(opcode) {
case 0x00: return op_nop();
@ -276,7 +276,7 @@ void LR35902::exec() {
}
}
void LR35902::exec_cb() {
auto LR35902::execCB() -> void {
uint8 opcode = op_read(r[PC]++);
switch(opcode) {
case 0x00: return op_rlc_r<B>();

View File

@ -1,165 +1,166 @@
//Sharp LR35902 (Game Boy Z80-derivative)
#ifndef PROCESSOR_LR35902_HPP
#define PROCESSOR_LR35902_HPP
namespace Processor {
//Sharp LR35902 (Game Boy Z80-derivative)
struct LR35902 {
virtual auto op_io() -> void = 0;
virtual auto op_read(uint16 addr) -> uint8 = 0;
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
virtual auto stop() -> bool = 0;
virtual auto debugger_read(uint16 addr) -> uint8 { return 0u; }
auto power() -> void;
auto exec() -> void;
auto execCB() -> void;
auto serialize(serializer&) -> void;
#include "registers.hpp"
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
virtual bool stop() = 0;
virtual uint8 debugger_read(uint16 addr) { return 0u; }
void power();
void exec();
void exec_cb();
void serialize(serializer&);
privileged:
void op_xx();
void op_cb();
auto op_xx();
auto op_cb();
//8-bit load commands
template<unsigned x, unsigned y> void op_ld_r_r();
template<unsigned x> void op_ld_r_n();
template<unsigned x> void op_ld_r_hl();
template<unsigned x> void op_ld_hl_r();
void op_ld_hl_n();
template<unsigned x> void op_ld_a_rr();
void op_ld_a_nn();
template<unsigned x> void op_ld_rr_a();
void op_ld_nn_a();
void op_ld_a_ffn();
void op_ld_ffn_a();
void op_ld_a_ffc();
void op_ld_ffc_a();
void op_ldi_hl_a();
void op_ldi_a_hl();
void op_ldd_hl_a();
void op_ldd_a_hl();
template<uint x, uint y> auto op_ld_r_r();
template<uint x> auto op_ld_r_n();
template<uint x> auto op_ld_r_hl();
template<uint x> auto op_ld_hl_r();
auto op_ld_hl_n();
template<uint x> auto op_ld_a_rr();
auto op_ld_a_nn();
template<uint x> auto op_ld_rr_a();
auto op_ld_nn_a();
auto op_ld_a_ffn();
auto op_ld_ffn_a();
auto op_ld_a_ffc();
auto op_ld_ffc_a();
auto op_ldi_hl_a();
auto op_ldi_a_hl();
auto op_ldd_hl_a();
auto op_ldd_a_hl();
//16-bit load commands
template<unsigned x> void op_ld_rr_nn();
void op_ld_nn_sp();
void op_ld_sp_hl();
template<unsigned x> void op_push_rr();
template<unsigned x> void op_pop_rr();
template<uint x> auto op_ld_rr_nn();
auto op_ld_nn_sp();
auto op_ld_sp_hl();
template<uint x> auto op_push_rr();
template<uint x> auto op_pop_rr();
//8-bit arithmetic commands
void opi_add_a(uint8 x);
template<unsigned x> void op_add_a_r();
void op_add_a_n();
void op_add_a_hl();
auto opi_add_a(uint8 x);
template<uint x> auto op_add_a_r();
auto op_add_a_n();
auto op_add_a_hl();
void opi_adc_a(uint8 x);
template<unsigned x> void op_adc_a_r();
void op_adc_a_n();
void op_adc_a_hl();
auto opi_adc_a(uint8 x);
template<uint x> auto op_adc_a_r();
auto op_adc_a_n();
auto op_adc_a_hl();
void opi_sub_a(uint8 x);
template<unsigned x> void op_sub_a_r();
void op_sub_a_n();
void op_sub_a_hl();
auto opi_sub_a(uint8 x);
template<uint x> auto op_sub_a_r();
auto op_sub_a_n();
auto op_sub_a_hl();
void opi_sbc_a(uint8 x);
template<unsigned x> void op_sbc_a_r();
void op_sbc_a_n();
void op_sbc_a_hl();
auto opi_sbc_a(uint8 x);
template<uint x> auto op_sbc_a_r();
auto op_sbc_a_n();
auto op_sbc_a_hl();
void opi_and_a(uint8 x);
template<unsigned x> void op_and_a_r();
void op_and_a_n();
void op_and_a_hl();
auto opi_and_a(uint8 x);
template<uint x> auto op_and_a_r();
auto op_and_a_n();
auto op_and_a_hl();
void opi_xor_a(uint8 x);
template<unsigned x> void op_xor_a_r();
void op_xor_a_n();
void op_xor_a_hl();
auto opi_xor_a(uint8 x);
template<uint x> auto op_xor_a_r();
auto op_xor_a_n();
auto op_xor_a_hl();
void opi_or_a(uint8 x);
template<unsigned x> void op_or_a_r();
void op_or_a_n();
void op_or_a_hl();
auto opi_or_a(uint8 x);
template<uint x> auto op_or_a_r();
auto op_or_a_n();
auto op_or_a_hl();
void opi_cp_a(uint8 x);
template<unsigned x> void op_cp_a_r();
void op_cp_a_n();
void op_cp_a_hl();
auto opi_cp_a(uint8 x);
template<uint x> auto op_cp_a_r();
auto op_cp_a_n();
auto op_cp_a_hl();
template<unsigned x> void op_inc_r();
void op_inc_hl();
template<unsigned x> void op_dec_r();
void op_dec_hl();
void op_daa();
void op_cpl();
template<uint x> auto op_inc_r();
auto op_inc_hl();
template<uint x> auto op_dec_r();
auto op_dec_hl();
auto op_daa();
auto op_cpl();
//16-bit arithmetic commands
template<unsigned x> void op_add_hl_rr();
template<unsigned x> void op_inc_rr();
template<unsigned x> void op_dec_rr();
void op_add_sp_n();
void op_ld_hl_sp_n();
template<uint x> auto op_add_hl_rr();
template<uint x> auto op_inc_rr();
template<uint x> auto op_dec_rr();
auto op_add_sp_n();
auto op_ld_hl_sp_n();
//rotate/shift commands
void op_rlca();
void op_rla();
void op_rrca();
void op_rra();
template<unsigned x> void op_rlc_r();
void op_rlc_hl();
template<unsigned x> void op_rl_r();
void op_rl_hl();
template<unsigned x> void op_rrc_r();
void op_rrc_hl();
template<unsigned x> void op_rr_r();
void op_rr_hl();
template<unsigned x> void op_sla_r();
void op_sla_hl();
template<unsigned x> void op_swap_r();
void op_swap_hl();
template<unsigned x> void op_sra_r();
void op_sra_hl();
template<unsigned x> void op_srl_r();
void op_srl_hl();
auto op_rlca();
auto op_rla();
auto op_rrca();
auto op_rra();
template<uint x> auto op_rlc_r();
auto op_rlc_hl();
template<uint x> auto op_rl_r();
auto op_rl_hl();
template<uint x> auto op_rrc_r();
auto op_rrc_hl();
template<uint x> auto op_rr_r();
auto op_rr_hl();
template<uint x> auto op_sla_r();
auto op_sla_hl();
template<uint x> auto op_swap_r();
auto op_swap_hl();
template<uint x> auto op_sra_r();
auto op_sra_hl();
template<uint x> auto op_srl_r();
auto op_srl_hl();
//single-bit commands
template<unsigned b, unsigned x> void op_bit_n_r();
template<unsigned b> void op_bit_n_hl();
template<unsigned b, unsigned x> void op_set_n_r();
template<unsigned b> void op_set_n_hl();
template<unsigned b, unsigned x> void op_res_n_r();
template<unsigned b> void op_res_n_hl();
template<uint b, uint x> auto op_bit_n_r();
template<uint b> auto op_bit_n_hl();
template<uint b, uint x> auto op_set_n_r();
template<uint b> auto op_set_n_hl();
template<uint b, uint x> auto op_res_n_r();
template<uint b> auto op_res_n_hl();
//control commands
void op_ccf();
void op_scf();
void op_nop();
void op_halt();
void op_stop();
void op_di();
void op_ei();
auto op_ccf();
auto op_scf();
auto op_nop();
auto op_halt();
auto op_stop();
auto op_di();
auto op_ei();
//jump commands
void op_jp_nn();
void op_jp_hl();
template<unsigned x, bool y> void op_jp_f_nn();
void op_jr_n();
template<unsigned x, bool y> void op_jr_f_n();
void op_call_nn();
template<unsigned x, bool y> void op_call_f_nn();
void op_ret();
template<unsigned x, bool y> void op_ret_f();
void op_reti();
template<unsigned n> void op_rst_n();
auto op_jp_nn();
auto op_jp_hl();
template<uint x, bool y> auto op_jp_f_nn();
auto op_jr_n();
template<uint x, bool y> auto op_jr_f_n();
auto op_call_nn();
template<uint x, bool y> auto op_call_f_nn();
auto op_ret();
template<uint x, bool y> auto op_ret_f();
auto op_reti();
template<uint n> auto op_rst_n();
//disassembler.cpp
string disassemble(uint16 pc);
string disassemble_opcode(uint16 pc);
string disassemble_opcode_cb(uint16 pc);
auto disassemble(uint16 pc) -> string;
auto disassembleOpcode(uint16 pc) -> string;
auto disassembleOpcodeCB(uint16 pc) -> string;
};
}

View File

@ -1,4 +1,4 @@
void LR35902::serialize(serializer& s) {
auto LR35902::serialize(serializer& s) -> void {
s.integer(r.a.data);
s.integer(r.f.z);
s.integer(r.f.n);

View File

@ -1,18 +1,18 @@
string R6502::disassemble() {
string output = { hex(regs.pc, 4L), " " };
auto R6502::disassemble() -> string {
string output = {hex(regs.pc, 4L), " "};
auto abs = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L) }; };
auto abx = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ",x" }; };
auto aby = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ",y" }; };
auto iab = [&]() -> string { return { "($", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ")" }; };
auto imm = [&]() -> string { return { "#$", hex(debugger_read(regs.pc + 1), 2L) }; };
auto imp = [&]() -> string { return ""; };
auto izx = [&]() -> string { return { "($", hex(debugger_read(regs.pc + 1), 2L), ",x)" }; };
auto izy = [&]() -> string { return { "($", hex(debugger_read(regs.pc + 1), 2L), "),y" }; };
auto rel = [&]() -> string { return { "$", hex((regs.pc + 2) + (int8)debugger_read(regs.pc + 1), 4L) }; };
auto zpg = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 1), 2L) }; };
auto zpx = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 1), 2L), ",x" }; };
auto zpy = [&]() -> string { return { "$", hex(debugger_read(regs.pc + 1), 2L), ",y" }; };
auto abs = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L)}; };
auto abx = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ",x"}; };
auto aby = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ",y"}; };
auto iab = [&]() -> string { return {"($", hex(debugger_read(regs.pc + 2), 2L), hex(debugger_read(regs.pc + 1), 2L), ")"}; };
auto imm = [&]() -> string { return {"#$", hex(debugger_read(regs.pc + 1), 2L)}; };
auto imp = [&]() -> string { return {""}; };
auto izx = [&]() -> string { return {"($", hex(debugger_read(regs.pc + 1), 2L), ",x)"}; };
auto izy = [&]() -> string { return {"($", hex(debugger_read(regs.pc + 1), 2L), "),y"}; };
auto rel = [&]() -> string { return {"$", hex((regs.pc + 2) + (int8)debugger_read(regs.pc + 1), 4L)}; };
auto zpg = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 1), 2L)}; };
auto zpx = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 1), 2L), ",x"}; };
auto zpy = [&]() -> string { return {"$", hex(debugger_read(regs.pc + 1), 2L), ",y"}; };
#define op(byte, prefix, mode) \
case byte: output.append(#prefix, " ", mode()); \

View File

@ -1,8 +1,8 @@
//opcode functions
//================
void R6502::opf_adc() {
signed result = regs.a + rd + regs.p.c;
auto R6502::opf_adc() {
int result = regs.a + rd + regs.p.c;
regs.p.v = ~(regs.a ^ rd) & (regs.a ^ result) & 0x80;
regs.p.c = (result > 0xff);
regs.p.n = (result & 0x80);
@ -10,140 +10,140 @@ void R6502::opf_adc() {
regs.a = result;
}
void R6502::opf_and() {
auto R6502::opf_and() {
regs.a &= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_asl() {
auto R6502::opf_asl() {
regs.p.c = rd & 0x80;
rd <<= 1;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_bit() {
auto R6502::opf_bit() {
regs.p.n = (rd & 0x80);
regs.p.v = (rd & 0x40);
regs.p.z = ((rd & regs.a) == 0);
}
void R6502::opf_cmp() {
signed r = regs.a - rd;
auto R6502::opf_cmp() {
int r = regs.a - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void R6502::opf_cpx() {
signed r = regs.x - rd;
auto R6502::opf_cpx() {
int r = regs.x - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void R6502::opf_cpy() {
signed r = regs.y - rd;
auto R6502::opf_cpy() {
int r = regs.y - rd;
regs.p.n = (r & 0x80);
regs.p.z = (uint8)(r == 0);
regs.p.c = (r >= 0);
}
void R6502::opf_dec() {
auto R6502::opf_dec() {
rd--;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_eor() {
auto R6502::opf_eor() {
regs.a ^= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_inc() {
auto R6502::opf_inc() {
rd++;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_lda() {
auto R6502::opf_lda() {
regs.a = rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_ldx() {
auto R6502::opf_ldx() {
regs.x = rd;
regs.p.n = (regs.x & 0x80);
regs.p.z = (regs.x == 0);
}
void R6502::opf_ldy() {
auto R6502::opf_ldy() {
regs.y = rd;
regs.p.n = (regs.y & 0x80);
regs.p.z = (regs.y == 0);
}
void R6502::opf_lsr() {
auto R6502::opf_lsr() {
regs.p.c = rd & 0x01;
rd >>= 1;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_ora() {
auto R6502::opf_ora() {
regs.a |= rd;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_rla() {
unsigned carry = (unsigned)regs.p.c;
auto R6502::opf_rla() {
uint carry = (uint)regs.p.c;
regs.p.c = regs.a & 0x80;
regs.a = (regs.a << 1) | carry;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_rol() {
unsigned carry = (unsigned)regs.p.c;
auto R6502::opf_rol() {
uint carry = (uint)regs.p.c;
regs.p.c = rd & 0x80;
rd = (rd << 1) | carry;
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_ror() {
unsigned carry = (unsigned)regs.p.c << 7;
auto R6502::opf_ror() {
uint carry = (uint)regs.p.c << 7;
regs.p.c = rd & 0x01;
rd = carry | (rd >> 1);
regs.p.n = (rd & 0x80);
regs.p.z = (rd == 0);
}
void R6502::opf_rra() {
unsigned carry = (unsigned)regs.p.c << 7;
auto R6502::opf_rra() {
uint carry = (uint)regs.p.c << 7;
regs.p.c = regs.a & 0x01;
regs.a = carry | (regs.a >> 1);
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_sbc() {
auto R6502::opf_sbc() {
rd ^= 0xff;
return opf_adc();
}
void R6502::opf_sla() {
auto R6502::opf_sla() {
regs.p.c = regs.a & 0x80;
regs.a <<= 1;
regs.p.n = (regs.a & 0x80);
regs.p.z = (regs.a == 0);
}
void R6502::opf_sra() {
auto R6502::opf_sra() {
regs.p.c = regs.a & 0x01;
regs.a >>= 1;
regs.p.n = (regs.a & 0x80);
@ -153,7 +153,7 @@ void R6502::opf_sra() {
//opcode implementations
//======================
void R6502::opi_branch(bool condition) {
auto R6502::opi_branch(bool condition) {
if(condition == false) {
L rd = op_readpci();
} else {
@ -165,26 +165,26 @@ L op_readpc();
}
}
void R6502::opi_clear_flag(bool& flag) {
auto R6502::opi_clear_flag(bool& flag) {
L op_readpc();
flag = 0;
}
void R6502::opi_decrement(uint8& r) {
auto R6502::opi_decrement(uint8& r) {
L op_readpc();
r--;
regs.p.n = (r & 0x80);
regs.p.z = (r == 0);
}
void R6502::opi_increment(uint8& r) {
auto R6502::opi_increment(uint8& r) {
L op_readpc();
r++;
regs.p.n = (r & 0x80);
regs.p.z = (r == 0);
}
void R6502::opi_pull(uint8& r) {
auto R6502::opi_pull(uint8& r) {
op_readpc();
op_readpc();
L r = op_readsp();
@ -192,21 +192,21 @@ L r = op_readsp();
regs.p.z = (r == 0);
}
void R6502::opi_push(uint8& r) {
auto R6502::opi_push(uint8& r) {
op_readpc();
L op_writesp(r);
}
template<void (R6502::*op)()>
void R6502::opi_read_absolute() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
L rd = op_read(abs.w);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_absolute_x() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.x);
@ -214,8 +214,8 @@ L rd = op_read(abs.w + regs.x);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_absolute_y() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_absolute_y() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.y);
@ -223,14 +223,14 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_immediate() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_immediate() {
L rd = op_readpci();
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_indirect_zero_page_x() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_indirect_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
abs.l = op_readzp(zp++ + regs.x);
@ -239,8 +239,8 @@ L rd = op_read(abs.w);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_indirect_zero_page_y() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_indirect_zero_page_y() {
rd = op_readpci();
abs.l = op_readzp(rd++);
abs.h = op_readzp(rd++);
@ -249,31 +249,31 @@ L rd = op_read(abs.w + regs.y);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_zero_page() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page() {
zp = op_readpci();
L rd = op_readzp(zp);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_zero_page_x() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.x);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_read_zero_page_y() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_read_zero_page_y() {
zp = op_readpci();
op_readzp(zp);
L rd = op_readzp(zp + regs.y);
call(op);
}
template<void (R6502::*op)()>
void R6502::opi_rmw_absolute() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
rd = op_read(abs.w);
@ -282,8 +282,8 @@ void R6502::opi_rmw_absolute() {
L op_write(abs.w, rd);
}
template<void (R6502::*op)()>
void R6502::opi_rmw_absolute_x() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.x);
@ -293,8 +293,8 @@ void R6502::opi_rmw_absolute_x() {
L op_write(abs.w + regs.x, rd);
}
template<void (R6502::*op)()>
void R6502::opi_rmw_zero_page() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_zero_page() {
zp = op_readpci();
rd = op_readzp(zp);
op_writezp(zp, rd);
@ -302,8 +302,8 @@ void R6502::opi_rmw_zero_page() {
L op_writezp(zp, rd);
}
template<void (R6502::*op)()>
void R6502::opi_rmw_zero_page_x() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_rmw_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
rd = op_readzp(zp + regs.x);
@ -312,38 +312,38 @@ void R6502::opi_rmw_zero_page_x() {
L op_writezp(zp + regs.x, rd);
}
void R6502::opi_set_flag(bool& flag) {
auto R6502::opi_set_flag(bool& flag) {
L op_readpc();
flag = 1;
}
template<void (R6502::*op)()>
void R6502::opi_shift() {
template<auto (R6502::*op)() -> void>
auto R6502::opi_shift() {
L op_readpc();
call(op);
}
void R6502::opi_store_absolute(uint8& r) {
auto R6502::opi_store_absolute(uint8& r) {
abs.l = op_readpci();
abs.h = op_readpci();
L op_write(abs.w, r);
}
void R6502::opi_store_absolute_x(uint8& r) {
auto R6502::opi_store_absolute_x(uint8& r) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.x);
L op_write(abs.w + regs.x, r);
}
void R6502::opi_store_absolute_y(uint8& r) {
auto R6502::opi_store_absolute_y(uint8& r) {
abs.l = op_readpci();
abs.h = op_readpci();
op_page_always(abs.w, abs.w + regs.y);
L op_write(abs.w + regs.y, r);
}
void R6502::opi_store_indirect_zero_page_x(uint8& r) {
auto R6502::opi_store_indirect_zero_page_x(uint8& r) {
zp = op_readpci();
op_readzp(zp);
abs.l = op_readzp(zp++ + regs.x);
@ -351,7 +351,7 @@ void R6502::opi_store_indirect_zero_page_x(uint8& r) {
L op_write(abs.w, r);
}
void R6502::opi_store_indirect_zero_page_y(uint8& r) {
auto R6502::opi_store_indirect_zero_page_y(uint8& r) {
rd = op_readpci();
abs.l = op_readzp(rd++);
abs.h = op_readzp(rd++);
@ -359,24 +359,24 @@ void R6502::opi_store_indirect_zero_page_y(uint8& r) {
L op_write(abs.w + regs.y, r);
}
void R6502::opi_store_zero_page(uint8& r) {
auto R6502::opi_store_zero_page(uint8& r) {
zp = op_readpci();
L op_writezp(zp, r);
}
void R6502::opi_store_zero_page_x(uint8& r) {
auto R6502::opi_store_zero_page_x(uint8& r) {
zp = op_readpci();
op_readzp(zp);
L op_writezp(zp + regs.x, r);
}
void R6502::opi_store_zero_page_y(uint8& r) {
auto R6502::opi_store_zero_page_y(uint8& r) {
zp = op_readpci();
op_readzp(zp);
L op_writezp(zp + regs.y, r);
}
void R6502::opi_transfer(uint8& s, uint8& d, bool flag) {
auto R6502::opi_transfer(uint8& s, uint8& d, bool flag) {
L op_readpc();
d = s;
if(flag == false) return;
@ -387,7 +387,7 @@ L op_readpc();
//opcodes
//=======
void R6502::op_brk() {
auto R6502::op_brk() {
op_readpci();
op_writesp(regs.pc >> 8);
op_writesp(regs.pc >> 0);
@ -399,13 +399,13 @@ L abs.h = op_read(0xffff);
regs.pc = abs.w;
}
void R6502::op_jmp_absolute() {
auto R6502::op_jmp_absolute() {
abs.l = op_readpci();
L abs.h = op_readpci();
regs.pc = abs.w;
}
void R6502::op_jmp_indirect_absolute() {
auto R6502::op_jmp_indirect_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
iabs.l = op_read(abs.w); abs.l++;
@ -413,7 +413,7 @@ L iabs.h = op_read(abs.w); abs.l++;
regs.pc = iabs.w;
}
void R6502::op_jsr_absolute() {
auto R6502::op_jsr_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
op_readpc();
@ -423,22 +423,22 @@ L op_writesp(regs.pc >> 0);
regs.pc = abs.w;
}
void R6502::op_nop() {
auto R6502::op_nop() {
L op_readpc();
}
void R6502::op_php() {
auto R6502::op_php() {
op_readpc();
L op_writesp(regs.p | 0x30);
}
void R6502::op_plp() {
auto R6502::op_plp() {
op_readpc();
op_readpc();
L regs.p = op_readsp();
}
void R6502::op_rti() {
auto R6502::op_rti() {
op_readpc();
op_readpc();
regs.p = op_readsp();
@ -447,7 +447,7 @@ L abs.h = op_readsp();
regs.pc = abs.w;
}
void R6502::op_rts() {
auto R6502::op_rts() {
op_readpc();
op_readpc();
abs.l = op_readsp();
@ -459,7 +459,7 @@ L op_readpc();
//illegal opcodes
//===============
void R6502::opill_arr_immediate() {
auto R6502::opill_arr_immediate() {
L rd = op_readpci();
regs.a &= rd;
regs.a = (regs.p.c << 7) | (regs.a >> 1);
@ -469,33 +469,33 @@ L rd = op_readpci();
regs.p.v = regs.p.c ^ ((regs.a >> 5) & 1);
}
void R6502::opill_nop_absolute() {
auto R6502::opill_nop_absolute() {
abs.l = op_readpci();
abs.h = op_readpci();
L op_readpc();
}
void R6502::opill_nop_absolute_x() {
auto R6502::opill_nop_absolute_x() {
abs.l = op_readpci();
abs.h = op_readpci();
op_page(abs.w, abs.w + regs.x);
L op_readpc();
}
void R6502::opill_nop_immediate() {
auto R6502::opill_nop_immediate() {
L rd = op_readpc();
}
void R6502::opill_nop_implied() {
auto R6502::opill_nop_implied() {
L op_readpc();
}
void R6502::opill_nop_zero_page() {
auto R6502::opill_nop_zero_page() {
zp = op_readpci();
L op_readzp(zp);
}
void R6502::opill_nop_zero_page_x() {
auto R6502::opill_nop_zero_page_x() {
zp = op_readpci();
op_readzp(zp);
L op_readzp(zp + regs.x);

View File

@ -1,35 +1,35 @@
uint8 R6502::op_readpc() {
auto R6502::op_readpc() -> uint8 {
return op_read(regs.pc);
}
uint8 R6502::op_readpci() {
auto R6502::op_readpci() -> uint8 {
return op_read(regs.pc++);
}
uint8 R6502::op_readsp() {
auto R6502::op_readsp() -> uint8 {
return op_read(0x0100 | ++regs.s);
}
uint8 R6502::op_readzp(uint8 addr) {
auto R6502::op_readzp(uint8 addr) -> uint8 {
return op_read(addr);
}
//
void R6502::op_writesp(uint8 data) {
auto R6502::op_writesp(uint8 data) -> void {
op_write(0x0100 | regs.s--, data);
}
void R6502::op_writezp(uint8 addr, uint8 data) {
auto R6502::op_writezp(uint8 addr, uint8 data) -> void {
op_write(addr, data);
}
//
void R6502::op_page(uint16 x, uint16 y) {
auto R6502::op_page(uint16 x, uint16 y) -> void {
if((x & 0xff00) != (y & 0xff00)) op_read((x & 0xff00) | (y & 0x00ff));
}
void R6502::op_page_always(uint16 x, uint16 y) {
auto R6502::op_page_always(uint16 x, uint16 y) -> void {
op_read((x & 0xff00) | (y & 0x00ff));
}

View File

@ -12,11 +12,11 @@ namespace Processor {
#include "disassembler.cpp"
#include "serialization.cpp"
uint8 R6502::mdr() const {
auto R6502::mdr() const -> uint8 {
return regs.mdr;
}
void R6502::power() {
auto R6502::power() -> void {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
@ -24,13 +24,13 @@ void R6502::power() {
regs.p = 0x04;
}
void R6502::reset() {
auto R6502::reset() -> void {
regs.mdr = 0x00;
regs.s -= 3;
regs.p.i = 1;
}
void R6502::interrupt() {
auto R6502::interrupt() -> void {
op_readpc();
op_readpc();
op_writesp(regs.pc >> 8);
@ -45,7 +45,7 @@ L abs.h = op_read(vector++);
regs.pc = abs.w;
}
void R6502::exec() {
auto R6502::exec() -> void {
uint8 opcode = op_readpci();
switch(opcode) {
case 0x00: return op_brk();

View File

@ -1,116 +1,116 @@
//Ricoh 6502
//* Ricoh 2A03
//* Ricoh 2A07
#ifndef PROCESSOR_R6502_HPP
#define PROCESSOR_R6502_HPP
namespace Processor {
//Ricoh 6502
//* Ricoh 2A03
//* Ricoh 2A07
struct R6502 {
#include "registers.hpp"
virtual auto op_read(uint16 addr) -> uint8 = 0;
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
virtual auto last_cycle() -> void = 0;
virtual auto nmi(uint16& vector) -> void = 0;
virtual auto debugger_read(uint16 addr) -> uint8 { return 0u; }
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
virtual void last_cycle() = 0;
virtual void nmi(uint16& vector) = 0;
virtual uint8 debugger_read(uint16 addr) { return 0u; }
auto mdr() const -> uint8;
auto power() -> void;
auto reset() -> void;
auto interrupt() -> void;
auto exec() -> void;
uint8 mdr() const;
void power();
void reset();
void interrupt();
void exec();
void serialize(serializer&);
auto serialize(serializer&) -> void;
//memory.cpp
uint8 op_readpc();
uint8 op_readpci();
uint8 op_readsp();
uint8 op_readzp(uint8 addr);
auto op_readpc() -> uint8;
auto op_readpci() -> uint8;
auto op_readsp() -> uint8;
auto op_readzp(uint8 addr) -> uint8;
void op_writesp(uint8 data);
void op_writezp(uint8 addr, uint8 data);
auto op_writesp(uint8 data) -> void;
auto op_writezp(uint8 addr, uint8 data) -> void;
void op_page(uint16 x, uint16 y);
void op_page_always(uint16 x, uint16 y);
auto op_page(uint16 x, uint16 y) -> void;
auto op_page_always(uint16 x, uint16 y) -> void;
//instructions.cpp
void opf_asl();
void opf_adc();
void opf_and();
void opf_bit();
void opf_cmp();
void opf_cpx();
void opf_cpy();
void opf_dec();
void opf_eor();
void opf_inc();
void opf_lda();
void opf_ldx();
void opf_ldy();
void opf_lsr();
void opf_ora();
void opf_rla();
void opf_rol();
void opf_ror();
void opf_rra();
void opf_sbc();
void opf_sla();
void opf_sra();
auto opf_asl();
auto opf_adc();
auto opf_and();
auto opf_bit();
auto opf_cmp();
auto opf_cpx();
auto opf_cpy();
auto opf_dec();
auto opf_eor();
auto opf_inc();
auto opf_lda();
auto opf_ldx();
auto opf_ldy();
auto opf_lsr();
auto opf_ora();
auto opf_rla();
auto opf_rol();
auto opf_ror();
auto opf_rra();
auto opf_sbc();
auto opf_sla();
auto opf_sra();
void opi_branch(bool condition);
void opi_clear_flag(bool& flag);
void opi_decrement(uint8& r);
void opi_increment(uint8& r);
void opi_pull(uint8& r);
void opi_push(uint8& r);
template<void (R6502::*op)()> void opi_read_absolute();
template<void (R6502::*op)()> void opi_read_absolute_x();
template<void (R6502::*op)()> void opi_read_absolute_y();
template<void (R6502::*op)()> void opi_read_immediate();
template<void (R6502::*op)()> void opi_read_indirect_zero_page_x();
template<void (R6502::*op)()> void opi_read_indirect_zero_page_y();
template<void (R6502::*op)()> void opi_read_zero_page();
template<void (R6502::*op)()> void opi_read_zero_page_x();
template<void (R6502::*op)()> void opi_read_zero_page_y();
template<void (R6502::*op)()> void opi_rmw_absolute();
template<void (R6502::*op)()> void opi_rmw_absolute_x();
template<void (R6502::*op)()> void opi_rmw_zero_page();
template<void (R6502::*op)()> void opi_rmw_zero_page_x();
void opi_set_flag(bool& flag);
template<void (R6502::*op)()> void opi_shift();
void opi_store_absolute(uint8& r);
void opi_store_absolute_x(uint8& r);
void opi_store_absolute_y(uint8& r);
void opi_store_indirect_zero_page_x(uint8& r);
void opi_store_indirect_zero_page_y(uint8& r);
void opi_store_zero_page(uint8& r);
void opi_store_zero_page_x(uint8& r);
void opi_store_zero_page_y(uint8& r);
void opi_transfer(uint8& s, uint8& d, bool flag);
auto opi_branch(bool condition);
auto opi_clear_flag(bool& flag);
auto opi_decrement(uint8& r);
auto opi_increment(uint8& r);
auto opi_pull(uint8& r);
auto opi_push(uint8& r);
template<auto (R6502::*op)() -> void> auto opi_read_absolute();
template<auto (R6502::*op)() -> void> auto opi_read_absolute_x();
template<auto (R6502::*op)() -> void> auto opi_read_absolute_y();
template<auto (R6502::*op)() -> void> auto opi_read_immediate();
template<auto (R6502::*op)() -> void> auto opi_read_indirect_zero_page_x();
template<auto (R6502::*op)() -> void> auto opi_read_indirect_zero_page_y();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page_x();
template<auto (R6502::*op)() -> void> auto opi_read_zero_page_y();
template<auto (R6502::*op)() -> void> auto opi_rmw_absolute();
template<auto (R6502::*op)() -> void> auto opi_rmw_absolute_x();
template<auto (R6502::*op)() -> void> auto opi_rmw_zero_page();
template<auto (R6502::*op)() -> void> auto opi_rmw_zero_page_x();
auto opi_set_flag(bool& flag);
template<auto (R6502::*op)() -> void> auto opi_shift();
auto opi_store_absolute(uint8& r);
auto opi_store_absolute_x(uint8& r);
auto opi_store_absolute_y(uint8& r);
auto opi_store_indirect_zero_page_x(uint8& r);
auto opi_store_indirect_zero_page_y(uint8& r);
auto opi_store_zero_page(uint8& r);
auto opi_store_zero_page_x(uint8& r);
auto opi_store_zero_page_y(uint8& r);
auto opi_transfer(uint8& s, uint8& d, bool flag);
void op_brk();
void op_jmp_absolute();
void op_jmp_indirect_absolute();
void op_jsr_absolute();
void op_nop();
void op_php();
void op_plp();
void op_rti();
void op_rts();
auto op_brk();
auto op_jmp_absolute();
auto op_jmp_indirect_absolute();
auto op_jsr_absolute();
auto op_nop();
auto op_php();
auto op_plp();
auto op_rti();
auto op_rts();
void opill_arr_immediate();
void opill_nop_absolute();
void opill_nop_absolute_x();
void opill_nop_immediate();
void opill_nop_implied();
void opill_nop_zero_page();
void opill_nop_zero_page_x();
auto opill_arr_immediate();
auto opill_nop_absolute();
auto opill_nop_absolute_x();
auto opill_nop_immediate();
auto opill_nop_implied();
auto opill_nop_zero_page();
auto opill_nop_zero_page_x();
//disassembler.cpp
string disassemble();
auto disassemble() -> string;
#include "registers.hpp"
};
}

View File

@ -1,15 +1,15 @@
struct Flags {
bool n, v, d, i, z, c;
inline operator unsigned() {
inline operator uint() {
return (n << 7) | (v << 6) | (d << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline Flags& operator=(uint8 data) {
inline auto operator=(uint8 data) -> Flags& {
n = data & 0x80; v = data & 0x40;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return *this;
}
bool n, v, d, i, z, c;
};
struct Registers {

View File

@ -1,4 +1,4 @@
void R6502::serialize(serializer& s) {
auto R6502::serialize(serializer& s) -> void {
s.integer(regs.mdr);
s.integer(regs.pc);
s.integer(regs.a);

View File

@ -1,4 +1,4 @@
uint8 SPC700::op_adc(uint8 x, uint8 y) {
auto SPC700::op_adc(uint8 x, uint8 y) -> uint8 {
int r = x + y + regs.p.c;
regs.p.n = r & 0x80;
regs.p.v = ~(x ^ y) & (x ^ r) & 0x80;
@ -8,14 +8,14 @@ uint8 SPC700::op_adc(uint8 x, uint8 y) {
return r;
}
uint8 SPC700::op_and(uint8 x, uint8 y) {
auto SPC700::op_and(uint8 x, uint8 y) -> uint8 {
x &= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SPC700::op_asl(uint8 x) {
auto SPC700::op_asl(uint8 x) -> uint8 {
regs.p.c = x & 0x80;
x <<= 1;
regs.p.n = x & 0x80;
@ -23,7 +23,7 @@ uint8 SPC700::op_asl(uint8 x) {
return x;
}
uint8 SPC700::op_cmp(uint8 x, uint8 y) {
auto SPC700::op_cmp(uint8 x, uint8 y) -> uint8 {
int r = x - y;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
@ -31,34 +31,34 @@ uint8 SPC700::op_cmp(uint8 x, uint8 y) {
return x;
}
uint8 SPC700::op_dec(uint8 x) {
auto SPC700::op_dec(uint8 x) -> uint8 {
x--;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SPC700::op_eor(uint8 x, uint8 y) {
auto SPC700::op_eor(uint8 x, uint8 y) -> uint8 {
x ^= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SPC700::op_inc(uint8 x) {
auto SPC700::op_inc(uint8 x) -> uint8 {
x++;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SPC700::op_ld(uint8 x, uint8 y) {
auto SPC700::op_ld(uint8 x, uint8 y) -> uint8 {
regs.p.n = y & 0x80;
regs.p.z = y == 0;
return y;
}
uint8 SPC700::op_lsr(uint8 x) {
auto SPC700::op_lsr(uint8 x) -> uint8 {
regs.p.c = x & 0x01;
x >>= 1;
regs.p.n = x & 0x80;
@ -66,15 +66,15 @@ uint8 SPC700::op_lsr(uint8 x) {
return x;
}
uint8 SPC700::op_or(uint8 x, uint8 y) {
auto SPC700::op_or(uint8 x, uint8 y) -> uint8 {
x |= y;
regs.p.n = x & 0x80;
regs.p.z = x == 0;
return x;
}
uint8 SPC700::op_rol(uint8 x) {
unsigned carry = regs.p.c << 0;
auto SPC700::op_rol(uint8 x) -> uint8 {
uint carry = regs.p.c << 0;
regs.p.c = x & 0x80;
x = (x << 1) | carry;
regs.p.n = x & 0x80;
@ -82,8 +82,8 @@ uint8 SPC700::op_rol(uint8 x) {
return x;
}
uint8 SPC700::op_ror(uint8 x) {
unsigned carry = regs.p.c << 7;
auto SPC700::op_ror(uint8 x) -> uint8 {
uint carry = regs.p.c << 7;
regs.p.c = x & 0x01;
x = carry | (x >> 1);
regs.p.n = x & 0x80;
@ -91,17 +91,17 @@ uint8 SPC700::op_ror(uint8 x) {
return x;
}
uint8 SPC700::op_sbc(uint8 x, uint8 y) {
auto SPC700::op_sbc(uint8 x, uint8 y) -> uint8 {
return op_adc(x, ~y);
}
uint8 SPC700::op_st(uint8 x, uint8 y) {
auto SPC700::op_st(uint8 x, uint8 y) -> uint8 {
return y;
}
//
uint16 SPC700::op_adw(uint16 x, uint16 y) {
auto SPC700::op_adw(uint16 x, uint16 y) -> uint16 {
uint16 r;
regs.p.c = 0;
r = op_adc(x, y);
@ -110,7 +110,7 @@ uint16 SPC700::op_adw(uint16 x, uint16 y) {
return r;
}
uint16 SPC700::op_cpw(uint16 x, uint16 y) {
auto SPC700::op_cpw(uint16 x, uint16 y) -> uint16 {
int r = x - y;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
@ -118,13 +118,13 @@ uint16 SPC700::op_cpw(uint16 x, uint16 y) {
return x;
}
uint16 SPC700::op_ldw(uint16 x, uint16 y) {
auto SPC700::op_ldw(uint16 x, uint16 y) -> uint16 {
regs.p.n = y & 0x8000;
regs.p.z = y == 0;
return y;
}
uint16 SPC700::op_sbw(uint16 x, uint16 y) {
auto SPC700::op_sbw(uint16 x, uint16 y) -> uint16 {
uint16 r;
regs.p.c = 1;
r = op_sbc(x, y);

View File

@ -1,20 +1,20 @@
string SPC700::disassemble_opcode(uint16 addr, bool p) {
auto SPC700::disassemble(uint16 addr, bool p) -> string {
auto read = [&](uint16 addr) -> uint8 {
return disassembler_read(addr);
};
auto relative = [&](unsigned length, int8 offset) -> uint16 {
auto relative = [&](uint length, int8 offset) -> uint16 {
uint16 pc = addr + length;
return pc + offset;
};
auto a = [&] { return hex((read(addr + 1) << 0) + (read(addr + 2) << 8), 4L); };
auto b = [&](unsigned n) { return hex(read(addr + 1 + n), 2L); };
auto r = [&](unsigned r, unsigned n = 0) { return hex(addr + r + (int8)read(addr + 1 + n), 4L); };
auto dp = [&](unsigned n) { return hex((p << 8) + read(addr + 1 + n), 3L); };
auto b = [&](uint n) { return hex(read(addr + 1 + n), 2L); };
auto r = [&](uint r, uint n = 0) { return hex(addr + r + (int8)read(addr + 1 + n), 4L); };
auto dp = [&](uint n) { return hex((p << 8) + read(addr + 1 + n), 3L); };
auto ab = [&] {
unsigned n = (read(addr + 1) << 0) + (read(addr + 2) << 8);
return string{ hex(n & 0x1fff, 4L), ":", hex(n >> 13, 1L) };
uint n = (read(addr + 1) << 0) + (read(addr + 2) << 8);
return string{hex(n & 0x1fff, 4L), ":", hex(n >> 13, 1L)};
};
auto mnemonic = [&]() -> string {
@ -279,9 +279,9 @@ string SPC700::disassemble_opcode(uint16 addr, bool p) {
throw;
};
string output = { "..", hex(addr, 4L), " ", mnemonic() };
string output = {"..", hex(addr, 4L), " ", mnemonic()};
unsigned length = output.length();
uint length = output.length();
while(length++ < 30) output.append(" ");
output.append(

View File

@ -1,13 +1,13 @@
#define call (this->*op)
template<uint8 (SPC700::*op)(uint8)>
void SPC700::op_adjust(uint8& r) {
template<auto (SPC700::*op)(uint8) -> uint8>
auto SPC700::op_adjust(uint8& r) -> void {
op_io();
r = call(r);
}
template<uint8 (SPC700::*op)(uint8)>
void SPC700::op_adjust_addr() {
template<auto (SPC700::*op)(uint8) -> uint8>
auto SPC700::op_adjust_addr() -> void {
dp.l = op_readpc();
dp.h = op_readpc();
rd = op_read(dp);
@ -15,15 +15,15 @@ void SPC700::op_adjust_addr() {
op_write(dp, rd);
}
template<uint8 (SPC700::*op)(uint8)>
void SPC700::op_adjust_dp() {
template<auto (SPC700::*op)(uint8) -> uint8>
auto SPC700::op_adjust_dp() -> void {
dp = op_readpc();
rd = op_readdp(dp);
rd = call(rd);
op_writedp(dp, rd);
}
void SPC700::op_adjust_dpw(signed n) {
auto SPC700::op_adjust_dpw(int n) -> void {
dp = op_readpc();
rd.w = op_readdp(dp) + n;
op_writedp(dp++, rd.l);
@ -33,8 +33,8 @@ void SPC700::op_adjust_dpw(signed n) {
regs.p.z = rd == 0;
}
template<uint8 (SPC700::*op)(uint8)>
void SPC700::op_adjust_dpx() {
template<auto (SPC700::*op)(uint8) -> uint8>
auto SPC700::op_adjust_dpx() -> void {
dp = op_readpc();
op_io();
rd = op_readdp(dp + regs.x);
@ -42,7 +42,7 @@ void SPC700::op_adjust_dpx() {
op_writedp(dp + regs.x, rd);
}
void SPC700::op_branch(bool condition) {
auto SPC700::op_branch(bool condition) -> void {
rd = op_readpc();
if(condition == false) return;
op_io();
@ -50,7 +50,7 @@ void SPC700::op_branch(bool condition) {
regs.pc += (int8)rd;
}
void SPC700::op_branch_bit() {
auto SPC700::op_branch_bit() -> void {
dp = op_readpc();
sp = op_readdp(dp);
rd = op_readpc();
@ -61,28 +61,28 @@ void SPC700::op_branch_bit() {
regs.pc += (int8)rd;
}
void SPC700::op_pull(uint8& r) {
auto SPC700::op_pull(uint8& r) -> void {
op_io();
op_io();
r = op_readsp();
}
void SPC700::op_push(uint8 r) {
auto SPC700::op_push(uint8 r) -> void {
op_io();
op_io();
op_writesp(r);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_addr(uint8& r) {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_addr(uint8& r) -> void {
dp.l = op_readpc();
dp.h = op_readpc();
rd = op_read(dp);
r = call(r, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_addri(uint8& r) {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_addri(uint8& r) -> void {
dp.l = op_readpc();
dp.h = op_readpc();
op_io();
@ -90,29 +90,29 @@ void SPC700::op_read_addri(uint8& r) {
regs.a = call(regs.a, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_const(uint8& r) {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_const(uint8& r) -> void {
rd = op_readpc();
r = call(r, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_dp(uint8& r) {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_dp(uint8& r) -> void {
dp = op_readpc();
rd = op_readdp(dp);
r = call(r, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_dpi(uint8& r, uint8& i) {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_dpi(uint8& r, uint8& i) -> void {
dp = op_readpc();
op_io();
rd = op_readdp(dp + i);
r = call(r, rd);
}
template<uint16 (SPC700::*op)(uint16, uint16)>
void SPC700::op_read_dpw() {
template<auto (SPC700::*op)(uint16, uint16) -> uint16>
auto SPC700::op_read_dpw() -> void {
dp = op_readpc();
rd.l = op_readdp(dp++);
if(op != &SPC700::op_cpw) op_io();
@ -120,8 +120,8 @@ void SPC700::op_read_dpw() {
regs.ya = call(regs.ya, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_idpx() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_idpx() -> void {
dp = op_readpc() + regs.x;
op_io();
sp.l = op_readdp(dp++);
@ -130,8 +130,8 @@ void SPC700::op_read_idpx() {
regs.a = call(regs.a, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_idpy() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_idpy() -> void {
dp = op_readpc();
op_io();
sp.l = op_readdp(dp++);
@ -140,14 +140,14 @@ void SPC700::op_read_idpy() {
regs.a = call(regs.a, rd);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_read_ix() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_read_ix() -> void {
op_io();
rd = op_readdp(regs.x);
regs.a = call(regs.a, rd);
}
void SPC700::op_set_addr_bit() {
auto SPC700::op_set_addr_bit() -> void {
dp.l = op_readpc();
dp.h = op_readpc();
bit = dp >> 13;
@ -182,19 +182,19 @@ void SPC700::op_set_addr_bit() {
}
}
void SPC700::op_set_bit() {
auto SPC700::op_set_bit() -> void {
dp = op_readpc();
rd = op_readdp(dp) & ~(1 << (opcode >> 5));
op_writedp(dp, rd | (!(opcode & 0x10) << (opcode >> 5)));
}
void SPC700::op_set_flag(bool& flag, bool data) {
auto SPC700::op_set_flag(bool& flag, bool data) -> void {
op_io();
if(&flag == &regs.p.i) op_io();
flag = data;
}
void SPC700::op_test_addr(bool set) {
auto SPC700::op_test_addr(bool set) -> void {
dp.l = op_readpc();
dp.h = op_readpc();
rd = op_read(dp);
@ -204,7 +204,7 @@ void SPC700::op_test_addr(bool set) {
op_write(dp, set ? rd | regs.a : rd & ~regs.a);
}
void SPC700::op_transfer(uint8& from, uint8& to) {
auto SPC700::op_transfer(uint8& from, uint8& to) -> void {
op_io();
to = from;
if(&to == &regs.s) return;
@ -212,14 +212,14 @@ void SPC700::op_transfer(uint8& from, uint8& to) {
regs.p.z = (to == 0);
}
void SPC700::op_write_addr(uint8& r) {
auto SPC700::op_write_addr(uint8& r) -> void {
dp.l = op_readpc();
dp.h = op_readpc();
op_read(dp);
op_write(dp, r);
}
void SPC700::op_write_addri(uint8& i) {
auto SPC700::op_write_addri(uint8& i) -> void {
dp.l = op_readpc();
dp.h = op_readpc();
op_io();
@ -228,21 +228,21 @@ void SPC700::op_write_addri(uint8& i) {
op_write(dp, regs.a);
}
void SPC700::op_write_dp(uint8& r) {
auto SPC700::op_write_dp(uint8& r) -> void {
dp = op_readpc();
op_readdp(dp);
op_writedp(dp, r);
}
void SPC700::op_write_dpi(uint8& r, uint8& i) {
auto SPC700::op_write_dpi(uint8& r, uint8& i) -> void {
dp = op_readpc() + i;
op_io();
op_readdp(dp);
op_writedp(dp, r);
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_write_dp_const() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_write_dp_const() -> void {
rd = op_readpc();
dp = op_readpc();
wr = op_readdp(dp);
@ -250,8 +250,8 @@ void SPC700::op_write_dp_const() {
op != &SPC700::op_cmp ? op_writedp(dp, wr) : op_io();
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_write_dp_dp() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_write_dp_dp() -> void {
sp = op_readpc();
rd = op_readdp(sp);
dp = op_readpc();
@ -260,8 +260,8 @@ void SPC700::op_write_dp_dp() {
op != &SPC700::op_cmp ? op_writedp(dp, wr) : op_io();
}
template<uint8 (SPC700::*op)(uint8, uint8)>
void SPC700::op_write_ix_iy() {
template<auto (SPC700::*op)(uint8, uint8) -> uint8>
auto SPC700::op_write_ix_iy() -> void {
op_io();
rd = op_readdp(regs.y);
wr = op_readdp(regs.x);
@ -271,7 +271,7 @@ void SPC700::op_write_ix_iy() {
//
void SPC700::op_bne_dp() {
auto SPC700::op_bne_dp() -> void {
dp = op_readpc();
sp = op_readdp(dp);
rd = op_readpc();
@ -282,7 +282,7 @@ void SPC700::op_bne_dp() {
regs.pc += (int8)rd;
}
void SPC700::op_bne_dpdec() {
auto SPC700::op_bne_dpdec() -> void {
dp = op_readpc();
wr = op_readdp(dp);
op_writedp(dp, --wr);
@ -293,7 +293,7 @@ void SPC700::op_bne_dpdec() {
regs.pc += (int8)rd;
}
void SPC700::op_bne_dpx() {
auto SPC700::op_bne_dpx() -> void {
dp = op_readpc();
op_io();
sp = op_readdp(dp + regs.x);
@ -305,7 +305,7 @@ void SPC700::op_bne_dpx() {
regs.pc += (int8)rd;
}
void SPC700::op_bne_ydec() {
auto SPC700::op_bne_ydec() -> void {
rd = op_readpc();
op_io();
op_io();
@ -315,7 +315,7 @@ void SPC700::op_bne_ydec() {
regs.pc += (int8)rd;
}
void SPC700::op_brk() {
auto SPC700::op_brk() -> void {
rd.l = op_read(0xffde);
rd.h = op_read(0xffdf);
op_io();
@ -328,19 +328,19 @@ void SPC700::op_brk() {
regs.p.i = 0;
}
void SPC700::op_clv() {
auto SPC700::op_clv() -> void {
op_io();
regs.p.v = 0;
regs.p.h = 0;
}
void SPC700::op_cmc() {
auto SPC700::op_cmc() -> void {
op_io();
op_io();
regs.p.c = !regs.p.c;
}
void SPC700::op_daa() {
auto SPC700::op_daa() -> void {
op_io();
op_io();
if(regs.p.c || (regs.a) > 0x99) {
@ -354,7 +354,7 @@ void SPC700::op_daa() {
regs.p.z = (regs.a == 0);
}
void SPC700::op_das() {
auto SPC700::op_das() -> void {
op_io();
op_io();
if(!regs.p.c || (regs.a) > 0x99) {
@ -368,7 +368,7 @@ void SPC700::op_das() {
regs.p.z = (regs.a == 0);
}
void SPC700::op_div_ya_x() {
auto SPC700::op_div_ya_x() -> void {
op_io();
op_io();
op_io();
@ -399,13 +399,13 @@ void SPC700::op_div_ya_x() {
regs.p.z = (regs.a == 0);
}
void SPC700::op_jmp_addr() {
auto SPC700::op_jmp_addr() -> void {
rd.l = op_readpc();
rd.h = op_readpc();
regs.pc = rd;
}
void SPC700::op_jmp_iaddrx() {
auto SPC700::op_jmp_iaddrx() -> void {
dp.l = op_readpc();
dp.h = op_readpc();
op_io();
@ -415,7 +415,7 @@ void SPC700::op_jmp_iaddrx() {
regs.pc = rd;
}
void SPC700::op_jsp_dp() {
auto SPC700::op_jsp_dp() -> void {
rd = op_readpc();
op_io();
op_io();
@ -424,7 +424,7 @@ void SPC700::op_jsp_dp() {
regs.pc = 0xff00 | rd;
}
void SPC700::op_jsr_addr() {
auto SPC700::op_jsr_addr() -> void {
rd.l = op_readpc();
rd.h = op_readpc();
op_io();
@ -435,7 +435,7 @@ void SPC700::op_jsr_addr() {
regs.pc = rd;
}
void SPC700::op_jst() {
auto SPC700::op_jst() -> void {
dp = 0xffde - ((opcode >> 4) << 1);
rd.l = op_read(dp++);
rd.h = op_read(dp++);
@ -447,7 +447,7 @@ void SPC700::op_jst() {
regs.pc = rd;
}
void SPC700::op_lda_ixinc() {
auto SPC700::op_lda_ixinc() -> void {
op_io();
regs.a = op_readdp(regs.x++);
op_io();
@ -455,7 +455,7 @@ void SPC700::op_lda_ixinc() {
regs.p.z = regs.a == 0;
}
void SPC700::op_mul_ya() {
auto SPC700::op_mul_ya() -> void {
op_io();
op_io();
op_io();
@ -472,17 +472,17 @@ void SPC700::op_mul_ya() {
regs.p.z = (regs.y == 0);
}
void SPC700::op_nop() {
auto SPC700::op_nop() -> void {
op_io();
}
void SPC700::op_plp() {
auto SPC700::op_plp() -> void {
op_io();
op_io();
regs.p = op_readsp();
}
void SPC700::op_rti() {
auto SPC700::op_rti() -> void {
regs.p = op_readsp();
rd.l = op_readsp();
rd.h = op_readsp();
@ -491,7 +491,7 @@ void SPC700::op_rti() {
regs.pc = rd;
}
void SPC700::op_rts() {
auto SPC700::op_rts() -> void {
rd.l = op_readsp();
rd.h = op_readsp();
op_io();
@ -499,7 +499,7 @@ void SPC700::op_rts() {
regs.pc = rd;
}
void SPC700::op_sta_idpx() {
auto SPC700::op_sta_idpx() -> void {
sp = op_readpc() + regs.x;
op_io();
dp.l = op_readdp(sp++);
@ -508,7 +508,7 @@ void SPC700::op_sta_idpx() {
op_write(dp, regs.a);
}
void SPC700::op_sta_idpy() {
auto SPC700::op_sta_idpy() -> void {
sp = op_readpc();
dp.l = op_readdp(sp++);
dp.h = op_readdp(sp++);
@ -518,33 +518,33 @@ void SPC700::op_sta_idpy() {
op_write(dp, regs.a);
}
void SPC700::op_sta_ix() {
auto SPC700::op_sta_ix() -> void {
op_io();
op_readdp(regs.x);
op_writedp(regs.x, regs.a);
}
void SPC700::op_sta_ixinc() {
auto SPC700::op_sta_ixinc() -> void {
op_io();
op_io();
op_writedp(regs.x++, regs.a);
}
void SPC700::op_stw_dp() {
auto SPC700::op_stw_dp() -> void {
dp = op_readpc();
op_readdp(dp);
op_writedp(dp++, regs.a);
op_writedp(dp++, regs.y);
}
void SPC700::op_wait() {
auto SPC700::op_wait() -> void {
while(true) {
op_io();
op_io();
}
}
void SPC700::op_xcn() {
auto SPC700::op_xcn() -> void {
op_io();
op_io();
op_io();

View File

@ -1,19 +1,19 @@
alwaysinline uint8 op_readpc() {
alwaysinline auto op_readpc() -> uint8 {
return op_read(regs.pc++);
}
alwaysinline uint8 op_readsp() {
alwaysinline auto op_readsp() -> uint8 {
return op_read(0x0100 | ++regs.s);
}
alwaysinline void op_writesp(uint8 data) {
alwaysinline auto op_writesp(uint8 data) -> void {
return op_write(0x0100 | regs.s--, data);
}
alwaysinline uint8 op_readdp(uint8 addr) {
alwaysinline auto op_readdp(uint8 addr) -> uint8 {
return op_read((regs.p.p << 8) + addr);
}
alwaysinline void op_writedp(uint8 addr, uint8 data) {
alwaysinline auto op_writedp(uint8 addr, uint8 data) -> void {
return op_write((regs.p.p << 8) + addr, data);
}

View File

@ -1,51 +1,51 @@
struct flag_t {
bool n, v, p, b, h, i, z, c;
inline operator unsigned() const {
struct Flag {
inline operator uint() const {
return (n << 7) | (v << 6) | (p << 5) | (b << 4)
| (h << 3) | (i << 2) | (z << 1) | (c << 0);
}
inline unsigned operator=(uint8 data) {
inline auto operator=(uint8 data) -> uint {
n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10;
h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
inline unsigned operator|=(uint8 data) { return operator=(operator unsigned() | data); }
inline unsigned operator^=(uint8 data) { return operator=(operator unsigned() ^ data); }
inline unsigned operator&=(uint8 data) { return operator=(operator unsigned() & data); }
inline auto operator|=(uint8 data) -> uint { return operator=(operator uint() | data); }
inline auto operator^=(uint8 data) -> uint { return operator=(operator uint() ^ data); }
inline auto operator&=(uint8 data) -> uint { return operator=(operator uint() & data); }
bool n, v, p, b, h, i, z, c;
};
struct word_t {
struct Word {
inline operator uint() const { return w; }
inline auto operator=(uint data) -> uint { return w = data; }
inline auto operator++() -> uint { return ++w; }
inline auto operator--() -> uint { return --w; }
inline auto operator++(int) -> uint { unsigned data = w++; return data; }
inline auto operator--(int) -> uint { unsigned data = w--; return data; }
inline auto operator+=(uint data) -> uint { return w += data;; }
inline auto operator-=(uint data) -> uint { return w -= data;; }
inline auto operator|=(uint data) -> uint { return w |= data; }
inline auto operator^=(uint data) -> uint { return w ^= data; }
inline auto operator&=(uint data) -> uint { return w &= data; }
union {
uint16 w;
struct { uint8 order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline unsigned operator=(unsigned data) { return w = data; }
inline unsigned operator++() { return ++w; }
inline unsigned operator--() { return --w; }
inline unsigned operator++(int) { unsigned data = w++; return data; }
inline unsigned operator--(int) { unsigned data = w--; return data; }
inline unsigned operator+=(unsigned data) { return w += data;; }
inline unsigned operator-=(unsigned data) { return w -= data;; }
inline unsigned operator|=(unsigned data) { return w |= data; }
inline unsigned operator^=(unsigned data) { return w ^= data; }
inline unsigned operator&=(unsigned data) { return w &= data; }
};
struct regs_t {
word_t pc;
struct Regs {
Word pc;
union {
uint16 ya;
struct { uint8 order_lsb2(a, y); };
};
uint8 x, s;
flag_t p;
Flag p;
};

View File

@ -1,4 +1,4 @@
void SPC700::serialize(serializer& s) {
auto SPC700::serialize(serializer& s) -> void {
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);

View File

@ -8,7 +8,7 @@ namespace Processor {
#include "disassembler.cpp"
#include "serialization.cpp"
void SPC700::op_step() {
auto SPC700::op_step() -> void {
switch(opcode = op_readpc()) {
case 0x00: return op_nop();
case 0x01: return op_jst();

View File

@ -4,102 +4,103 @@
namespace Processor {
struct SPC700 {
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
void op_step();
virtual auto op_io() -> void = 0;
virtual auto op_read(uint16 addr) -> uint8 = 0;
virtual auto op_write(uint16 addr, uint8 data) -> void = 0;
virtual auto disassembler_read(uint16 addr) -> uint8 = 0;
virtual uint8 disassembler_read(uint16 addr) = 0;
auto op_step() -> void;
auto serialize(serializer&) -> void;
auto disassemble(uint16 addr, bool p) -> string;
#include "registers.hpp"
#include "memory.hpp"
regs_t regs;
word_t dp, sp, rd, wr, bit, ya;
Regs regs;
Word dp, sp, rd, wr, bit, ya;
uint8 opcode;
void serialize(serializer&);
string disassemble_opcode(uint16 addr, bool p);
protected:
uint8 op_adc(uint8, uint8);
uint8 op_and(uint8, uint8);
uint8 op_asl(uint8);
uint8 op_cmp(uint8, uint8);
uint8 op_dec(uint8);
uint8 op_eor(uint8, uint8);
uint8 op_inc(uint8);
uint8 op_ld (uint8, uint8);
uint8 op_lsr(uint8);
uint8 op_or (uint8, uint8);
uint8 op_rol(uint8);
uint8 op_ror(uint8);
uint8 op_sbc(uint8, uint8);
uint8 op_st (uint8, uint8);
uint16 op_adw(uint16, uint16);
uint16 op_cpw(uint16, uint16);
uint16 op_ldw(uint16, uint16);
uint16 op_sbw(uint16, uint16);
auto op_adc(uint8, uint8) -> uint8;
auto op_and(uint8, uint8) -> uint8;
auto op_asl(uint8) -> uint8;
auto op_cmp(uint8, uint8) -> uint8;
auto op_dec(uint8) -> uint8;
auto op_eor(uint8, uint8) -> uint8;
auto op_inc(uint8) -> uint8;
auto op_ld (uint8, uint8) -> uint8;
auto op_lsr(uint8) -> uint8;
auto op_or (uint8, uint8) -> uint8;
auto op_rol(uint8) -> uint8;
auto op_ror(uint8) -> uint8;
auto op_sbc(uint8, uint8) -> uint8;
auto op_st (uint8, uint8) -> uint8;
auto op_adw(uint16, uint16) -> uint16;
auto op_cpw(uint16, uint16) -> uint16;
auto op_ldw(uint16, uint16) -> uint16;
auto op_sbw(uint16, uint16) -> uint16;
template<uint8 (SPC700::*op)(uint8)> void op_adjust(uint8&);
template<uint8 (SPC700::*op)(uint8)> void op_adjust_addr();
template<uint8 (SPC700::*op)(uint8)> void op_adjust_dp();
void op_adjust_dpw(signed);
template<uint8 (SPC700::*op)(uint8)> void op_adjust_dpx();
void op_branch(bool);
void op_branch_bit();
void op_pull(uint8&);
void op_push(uint8);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_addr(uint8&);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_addri(uint8&);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_const(uint8&);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_dp(uint8&);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_dpi(uint8&, uint8&);
template<uint16 (SPC700::*op)(uint16, uint16)> void op_read_dpw();
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_idpx();
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_idpy();
template<uint8 (SPC700::*op)(uint8, uint8)> void op_read_ix();
void op_set_addr_bit();
void op_set_bit();
void op_set_flag(bool&, bool);
void op_test_addr(bool);
void op_transfer(uint8&, uint8&);
void op_write_addr(uint8&);
void op_write_addri(uint8&);
void op_write_dp(uint8&);
void op_write_dpi(uint8&, uint8&);
template<uint8 (SPC700::*op)(uint8, uint8)> void op_write_dp_const();
template<uint8 (SPC700::*op)(uint8, uint8)> void op_write_dp_dp();
template<uint8 (SPC700::*op)(uint8, uint8)> void op_write_ix_iy();
template<auto (SPC700::*op)(uint8) -> uint8> auto op_adjust(uint8&) -> void;
template<auto (SPC700::*op)(uint8) -> uint8> auto op_adjust_addr() -> void;
template<auto (SPC700::*op)(uint8) -> uint8> auto op_adjust_dp() -> void;
auto op_adjust_dpw(int) -> void;
template<auto (SPC700::*op)(uint8) -> uint8> auto op_adjust_dpx() -> void;
auto op_branch(bool) -> void;
auto op_branch_bit() -> void;
auto op_pull(uint8&) -> void;
auto op_push(uint8) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_addr(uint8&) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_addri(uint8&) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_const(uint8&) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_dp(uint8&) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_dpi(uint8&, uint8&) -> void;
template<auto (SPC700::*op)(uint16, uint16) -> uint16> auto op_read_dpw() -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_idpx() -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_idpy() -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_read_ix() -> void;
auto op_set_addr_bit() -> void;
auto op_set_bit() -> void;
auto op_set_flag(bool&, bool) -> void;
auto op_test_addr(bool) -> void;
auto op_transfer(uint8&, uint8&) -> void;
auto op_write_addr(uint8&) -> void;
auto op_write_addri(uint8&) -> void;
auto op_write_dp(uint8&) -> void;
auto op_write_dpi(uint8&, uint8&) -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_write_dp_const() -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_write_dp_dp() -> void;
template<auto (SPC700::*op)(uint8, uint8) -> uint8> auto op_write_ix_iy() -> void;
void op_bne_dp();
void op_bne_dpdec();
void op_bne_dpx();
void op_bne_ydec();
void op_brk();
void op_clv();
void op_cmc();
void op_daa();
void op_das();
void op_div_ya_x();
void op_jmp_addr();
void op_jmp_iaddrx();
void op_jsp_dp();
void op_jsr_addr();
void op_jst();
void op_lda_ixinc();
void op_mul_ya();
void op_nop();
void op_plp();
void op_rti();
void op_rts();
void op_sta_idpx();
void op_sta_idpy();
void op_sta_ix();
void op_sta_ixinc();
void op_stw_dp();
void op_wait();
void op_xcn();
auto op_bne_dp() -> void;
auto op_bne_dpdec() -> void;
auto op_bne_dpx() -> void;
auto op_bne_ydec() -> void;
auto op_brk() -> void;
auto op_clv() -> void;
auto op_cmc() -> void;
auto op_daa() -> void;
auto op_das() -> void;
auto op_div_ya_x() -> void;
auto op_jmp_addr() -> void;
auto op_jmp_iaddrx() -> void;
auto op_jsp_dp() -> void;
auto op_jsr_addr() -> void;
auto op_jst() -> void;
auto op_lda_ixinc() -> void;
auto op_mul_ya() -> void;
auto op_nop() -> void;
auto op_plp() -> void;
auto op_rti() -> void;
auto op_rts() -> void;
auto op_sta_idpx() -> void;
auto op_sta_idpy() -> void;
auto op_sta_ix() -> void;
auto op_sta_ixinc() -> void;
auto op_stw_dp() -> void;
auto op_wait() -> void;
auto op_xcn() -> void;
};
}

View File

@ -1,7 +1,5 @@
#ifdef NECDSP_CPP
string NECDSP::disassemble(uint14 ip) {
string output = { hex<4>(ip), " " };
auto uPD96050::disassemble(uint14 ip) -> string {
string output = {hex(ip, 4L), " "};
uint24 opcode = programROM[ip];
uint2 type = opcode >> 22;
@ -98,7 +96,7 @@ string NECDSP::disassemble(uint14 ip) {
}
if(dphm) {
output.append("\n m", hex<1>(dphm));
output.append("\n m", hex(dphm, 1L));
}
if(rpdcr == 1) {
@ -160,7 +158,7 @@ string NECDSP::disassemble(uint14 ip) {
default: output.append("?????? "); break;
}
output.append("$", hex<4>(jp));
output.append("$", hex(jp, 4L));
}
if(type == 3) { //LD
@ -168,7 +166,7 @@ string NECDSP::disassemble(uint14 ip) {
uint16 id = opcode >> 6;
uint4 dst = opcode >> 0;
output.append("$", hex<4>(id), ",");
output.append("$", hex(id, 4L), ",");
switch(dst) {
case 0: output.append("non"); break;
@ -192,5 +190,3 @@ string NECDSP::disassemble(uint14 ip) {
return output;
}
#endif

View File

@ -1,10 +1,10 @@
void uPD96050::exec() {
auto uPD96050::exec() -> void {
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
case 0: execOP(opcode); break;
case 1: execRT(opcode); break;
case 2: execJP(opcode); break;
case 3: execLD(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
@ -12,7 +12,7 @@ void uPD96050::exec() {
regs.n = result << 1; //store low 15-bits + zero
}
void uPD96050::exec_op(uint24 opcode) {
auto uPD96050::execOP(uint24 opcode) -> void {
uint2 pselect = opcode >> 20; //P select
uint4 alu = opcode >> 16; //ALU operation mode
uint1 asl = opcode >> 15; //accumulator select
@ -123,7 +123,7 @@ void uPD96050::exec_op(uint24 opcode) {
}
}
exec_ld((idb << 6) + dst);
execLD((idb << 6) + dst);
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
@ -136,12 +136,12 @@ void uPD96050::exec_op(uint24 opcode) {
if(rpdcr) regs.rp--;
}
void uPD96050::exec_rt(uint24 opcode) {
exec_op(opcode);
auto uPD96050::execRT(uint24 opcode) -> void {
execOP(opcode);
regs.pc = regs.stack[--regs.sp];
}
void uPD96050::exec_jp(uint24 opcode) {
auto uPD96050::execJP(uint24 opcode) -> void {
uint9 brch = opcode >> 13; //branch
uint11 na = opcode >> 2; //next address
uint2 bank = opcode >> 0; //bank address
@ -197,7 +197,7 @@ void uPD96050::exec_jp(uint24 opcode) {
}
}
void uPD96050::exec_ld(uint24 opcode) {
auto uPD96050::execLD(uint24 opcode) -> void {
uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination

View File

@ -1,11 +1,11 @@
uint8 uPD96050::sr_read() {
auto uPD96050::readSR() -> uint8 {
return regs.sr >> 8;
}
void uPD96050::sr_write(uint8 data) {
auto uPD96050::writeSR(uint8 data) -> void {
}
uint8 uPD96050::dr_read() {
auto uPD96050::readDR() -> uint8 {
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
@ -23,7 +23,7 @@ uint8 uPD96050::dr_read() {
}
}
void uPD96050::dr_write(uint8 data) {
auto uPD96050::writeDR(uint8 data) -> void {
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
@ -41,7 +41,7 @@ void uPD96050::dr_write(uint8 data) {
}
}
uint8 uPD96050::dp_read(uint12 addr) {
auto uPD96050::readDP(uint12 addr) -> uint8 {
bool hi = addr & 1;
addr = (addr >> 1) & 2047;
@ -52,7 +52,7 @@ uint8 uPD96050::dp_read(uint12 addr) {
}
}
void uPD96050::dp_write(uint12 addr, uint8 data) {
auto uPD96050::writeDP(uint12 addr, uint8 data) -> void {
bool hi = addr & 1;
addr = (addr >> 1) & 2047;

View File

@ -0,0 +1,21 @@
uPD96050::Flag::operator uint() const {
return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0);
}
auto uPD96050::Flag::operator=(uint d) -> uint {
s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01;
return d;
}
uPD96050::Status::operator uint() const {
return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ (ei << 7) + (p1 << 1) + (p0 << 0);
}
auto uPD96050::Status::operator=(uint d) -> uint {
rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
return d;
}

View File

@ -1,51 +0,0 @@
struct Flag {
bool s1, s0, c, z, ov1, ov0;
inline operator unsigned() const {
return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0);
}
inline unsigned operator=(unsigned d) {
s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01;
return d;
}
};
struct Status {
bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0;
inline operator unsigned() const {
return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ (ei << 7) + (p1 << 1) + (p0 << 0);
}
inline unsigned operator=(unsigned d) {
rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
return d;
}
};
struct Regs {
uint16 stack[16]; //LIFO
varuint pc; //program counter
varuint rp; //ROM pointer
varuint dp; //data pointer
uint4 sp; //stack pointer
int16 k;
int16 l;
int16 m;
int16 n;
int16 a; //accumulator
int16 b; //accumulator
Flag flaga;
Flag flagb;
uint16 tr; //temporary register
uint16 trb; //temporary register
Status sr; //status register
uint16 dr; //data register
uint16 si;
uint16 so;
} regs;

View File

@ -1,4 +1,4 @@
void uPD96050::serialize(serializer& s) {
auto uPD96050::serialize(serializer& s) -> void {
s.array(dataRAM);
s.array(regs.stack);

Some files were not shown because too many files have changed in this diff Show More