Update to v098r11 release.

byuu says:

Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
  file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
  - this should stop all the bug reports where two nall users were
    generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
  - merged emulation/native-mode opcodes
  - use camel-case naming on memory.hpp functions
  - simplify address masking code for memory.hpp functions
  - simplify a few opcodes themselves (avoid redundant copies, etc)
  - rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
  - cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
  - example: emulator.ports[p].devices[d].inputs[i]
  - example: vector<Medium> media
- probably more surprises

Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
  IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
  Justifier)
- after the above, we need to fix the turbo button for the Super Scope

I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
This commit is contained in:
Tim Allen 2016-05-25 21:13:02 +10:00
parent 3ebc77c148
commit ae5d380d06
76 changed files with 1672 additions and 1948 deletions

View File

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

View File

@ -17,13 +17,13 @@ struct Interface {
} capability;
} information;
struct Media {
struct Medium {
uint id;
string name;
string type;
bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges)
};
vector<Media> media;
vector<Medium> media;
struct Device {
uint id;
@ -35,16 +35,15 @@ struct Interface {
string name;
uintptr guid; //user data field
};
vector<Input> input;
vector<uint> order;
vector<Input> inputs;
};
struct Port {
uint id;
string name;
vector<Device> device;
vector<Device> devices;
};
vector<Port> port;
vector<Port> ports;
struct Bind {
virtual auto loadRequest(uint, string, string, bool) -> void {}

View File

@ -15,12 +15,15 @@ auto Input::latch(bool data) -> void {
}
auto Input::data(bool port) -> bool {
//table to convert native button ordering to Emulator::Interface ordering
static const uint lookup[] = {5, 4, 6, 7, 0, 1, 2, 3};
bool result = 0;
if(port == 0) {
if(port1 == Device::Joypad) {
if(counter1 >= 8) return 1;
result = interface->inputPoll(0, 0u, counter1);
result = interface->inputPoll(0, 0u, lookup[counter1]);
if(latchdata == 0) counter1++;
}
}
@ -28,7 +31,7 @@ auto Input::data(bool port) -> bool {
if(port == 1) {
if(port2 == Device::Joypad) {
if(counter2 >= 8) return 1;
result = interface->inputPoll(1, 0u, counter2);
result = interface->inputPoll(1, 0u, lookup[counter2]);
if(latchdata == 0) counter2++;
}
}

View File

@ -22,25 +22,24 @@ Interface::Interface() {
media.append({ID::Famicom, "Famicom", "fc", true});
{ Device device{0, ID::Port1 | ID::Port2, "Controller"};
device.input.append({0, 0, "A" });
device.input.append({1, 0, "B" });
device.input.append({2, 0, "Select"});
device.input.append({3, 0, "Start" });
device.input.append({4, 0, "Up" });
device.input.append({5, 0, "Down" });
device.input.append({6, 0, "Left" });
device.input.append({7, 0, "Right" });
device.order = {4, 5, 6, 7, 1, 0, 2, 3};
this->device.append(device);
device.inputs.append({0, 0, "Up" });
device.inputs.append({1, 0, "Down" });
device.inputs.append({2, 0, "Left" });
device.inputs.append({3, 0, "Right" });
device.inputs.append({4, 0, "B" });
device.inputs.append({5, 0, "A" });
device.inputs.append({6, 0, "Select"});
device.inputs.append({7, 0, "Start" });
devices.append(device);
}
port.append({0, "Port 1"});
port.append({1, "Port 2"});
ports.append({0, "Port 1"});
ports.append({1, "Port 2"});
for(auto& device : this->device) {
for(auto& port : this->port) {
for(auto& device : devices) {
for(auto& port : ports) {
if(device.portmask & (1 << port.id)) {
port.device.append(device);
port.devices.append(device);
}
}
}
@ -98,14 +97,14 @@ auto Interface::videoColor(uint32 n) -> uint64 {
v *= brightness / 12.0;
y += v;
i += v * std::cos((3.141592653 / 6.0) * (p + hue));
q += v * std::sin((3.141592653 / 6.0) * (p + hue));
i += v * cos((3.141592653 / 6.0) * (p + hue));
q += v * sin((3.141592653 / 6.0) * (p + hue));
}
i *= saturation;
q *= saturation;
auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); };
auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : pow(f, 2.2 / gamma); };
uint64 r = uclamp<16>(65535.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q));
uint64 g = uclamp<16>(65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q));
uint64 b = uclamp<16>(65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q));

View File

@ -55,7 +55,7 @@ struct Interface : Emulator::Interface {
auto set(const string& name, const any& value) -> bool override;
private:
vector<Device> device;
vector<Device> devices;
};
struct Settings {

View File

@ -25,19 +25,18 @@ Interface::Interface() {
{
Device device{0, ID::Device, "Controller"};
device.input.append({0, 0, "Up" });
device.input.append({1, 0, "Down" });
device.input.append({2, 0, "Left" });
device.input.append({3, 0, "Right" });
device.input.append({4, 0, "B" });
device.input.append({5, 0, "A" });
device.input.append({6, 0, "Select"});
device.input.append({7, 0, "Start" });
device.order = {0, 1, 2, 3, 4, 5, 6, 7};
this->device.append(device);
device.inputs.append({0, 0, "Up" });
device.inputs.append({1, 0, "Down" });
device.inputs.append({2, 0, "Left" });
device.inputs.append({3, 0, "Right" });
device.inputs.append({4, 0, "B" });
device.inputs.append({5, 0, "A" });
device.inputs.append({6, 0, "Select"});
device.inputs.append({7, 0, "Start" });
devices.append(device);
}
port.append({0, "Device", {device[0]}});
ports.append({0, "Device", {devices[0]}});
}
auto Interface::manifest() -> string {

View File

@ -69,7 +69,7 @@ struct Interface : Emulator::Interface {
auto joypWrite(bool p15, bool p14) -> void;
private:
vector<Device> device;
vector<Device> devices;
};
struct Settings {

View File

@ -91,12 +91,15 @@ auto CPU::sync_step(uint clocks) -> void {
}
auto CPU::keypad_run() -> void {
if(regs.keypad.control.enable == false) return;
//lookup table to convert button indexes to Emulator::Interface indexes
static const uint lookup[] = {5, 4, 8, 9, 3, 2, 0, 1, 7, 6};
if(!regs.keypad.control.enable) return;
bool test = regs.keypad.control.condition; //0 = OR, 1 = AND
for(auto n : range(10)) {
if(regs.keypad.control.flag[n] == false) continue;
bool input = interface->inputPoll(0, 0, n);
if(!regs.keypad.control.flag[n]) continue;
bool input = interface->inputPoll(0, 0, lookup[n]);
if(regs.keypad.control.condition == 0) test |= input;
if(regs.keypad.control.condition == 1) test &= input;
}

View File

@ -61,9 +61,10 @@ auto CPU::read(uint32 addr) -> uint8 {
//KEYINPUT
case 0x04000130: {
static const uint lookup[] = {5, 4, 8, 9, 3, 2, 0, 1};
if(auto result = player.keyinput()) return result() >> 0;
uint8 result = 0;
for(uint n = 0; n < 8; n++) result |= interface->inputPoll(0, 0, n) << n;
for(uint n = 0; n < 8; n++) result |= interface->inputPoll(0, 0, lookup[n]) << n;
if((result & 0xc0) == 0xc0) result &= (uint8)~0xc0; //up+down cannot be pressed simultaneously
if((result & 0x30) == 0x30) result &= (uint8)~0x30; //left+right cannot be pressed simultaneously
return result ^ 0xff;
@ -71,8 +72,8 @@ auto CPU::read(uint32 addr) -> uint8 {
case 0x04000131: {
if(auto result = player.keyinput()) return result() >> 8;
uint8 result = 0;
result |= interface->inputPoll(0, 0, 8) << 0;
result |= interface->inputPoll(0, 0, 9) << 1;
result |= interface->inputPoll(0, 0, 7) << 0;
result |= interface->inputPoll(0, 0, 6) << 1;
return result ^ 0x03;
}

View File

@ -22,22 +22,21 @@ Interface::Interface() {
media.append({ID::GameBoyAdvance, "Game Boy Advance", "gba", true});
{ Device device{0, ID::Device, "Controller"};
device.input.append({ 0, 0, "A" });
device.input.append({ 1, 0, "B" });
device.input.append({ 2, 0, "Select"});
device.input.append({ 3, 0, "Start" });
device.input.append({ 4, 0, "Right" });
device.input.append({ 5, 0, "Left" });
device.input.append({ 6, 0, "Up" });
device.input.append({ 7, 0, "Down" });
device.input.append({ 8, 0, "R" });
device.input.append({ 9, 0, "L" });
device.input.append({10, 2, "Rumble"});
device.order = {6, 7, 5, 4, 1, 0, 9, 8, 2, 3, 10};
this->device.append(device);
device.inputs.append({ 0, 0, "Up" });
device.inputs.append({ 1, 0, "Down" });
device.inputs.append({ 2, 0, "Left" });
device.inputs.append({ 3, 0, "Right" });
device.inputs.append({ 4, 0, "B" });
device.inputs.append({ 5, 0, "A" });
device.inputs.append({ 6, 0, "L" });
device.inputs.append({ 7, 0, "R" });
device.inputs.append({ 8, 0, "Select"});
device.inputs.append({ 9, 0, "Start" });
device.inputs.append({10, 2, "Rumble"});
devices.append(device);
}
port.append({0, "Device", {device[0]}});
ports.append({0, "Device", {devices[0]}});
}
auto Interface::manifest() -> string {

View File

@ -52,7 +52,7 @@ struct Interface : Emulator::Interface {
auto set(const string& name, const any& value) -> bool override;
private:
vector<Device> device;
vector<Device> devices;
};
struct Settings {

View File

@ -1,327 +1,327 @@
auto R65816::op_adc_b() {
int result;
if(!regs.p.d) {
result = regs.a.l + rd.l + regs.p.c;
if(!r.p.d) {
result = r.a.l + rd.l + r.p.c;
} else {
result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0);
result = (r.a.l & 0x0f) + (rd.l & 0x0f) + (r.p.c << 0);
if(result > 0x09) result += 0x06;
regs.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f);
r.p.c = result > 0x0f;
result = (r.a.l & 0xf0) + (rd.l & 0xf0) + (r.p.c << 4) + (result & 0x0f);
}
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80;
if(regs.p.d && result > 0x9f) result += 0x60;
regs.p.c = result > 0xff;
regs.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0;
r.p.v = ~(r.a.l ^ rd.l) & (r.a.l ^ result) & 0x80;
if(r.p.d && result > 0x9f) result += 0x60;
r.p.c = result > 0xff;
r.p.n = result & 0x80;
r.p.z = (uint8)result == 0;
regs.a.l = result;
r.a.l = result;
}
auto R65816::op_adc_w() {
int result;
if(!regs.p.d) {
result = regs.a.w + rd.w + regs.p.c;
if(!r.p.d) {
result = r.a.w + rd.w + r.p.c;
} else {
result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0);
result = (r.a.w & 0x000f) + (rd.w & 0x000f) + (r.p.c << 0);
if(result > 0x0009) result += 0x0006;
regs.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f);
r.p.c = result > 0x000f;
result = (r.a.w & 0x00f0) + (rd.w & 0x00f0) + (r.p.c << 4) + (result & 0x000f);
if(result > 0x009f) result += 0x0060;
regs.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff);
r.p.c = result > 0x00ff;
result = (r.a.w & 0x0f00) + (rd.w & 0x0f00) + (r.p.c << 8) + (result & 0x00ff);
if(result > 0x09ff) result += 0x0600;
regs.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff);
r.p.c = result > 0x0fff;
result = (r.a.w & 0xf000) + (rd.w & 0xf000) + (r.p.c << 12) + (result & 0x0fff);
}
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000;
if(regs.p.d && result > 0x9fff) result += 0x6000;
regs.p.c = result > 0xffff;
regs.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0;
r.p.v = ~(r.a.w ^ rd.w) & (r.a.w ^ result) & 0x8000;
if(r.p.d && result > 0x9fff) result += 0x6000;
r.p.c = result > 0xffff;
r.p.n = result & 0x8000;
r.p.z = (uint16)result == 0;
regs.a.w = result;
r.a.w = result;
}
auto R65816::op_and_b() {
regs.a.l &= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
r.a.l &= rd.l;
r.p.n = r.a.l & 0x80;
r.p.z = r.a.l == 0;
}
auto R65816::op_and_w() {
regs.a.w &= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
r.a.w &= rd.w;
r.p.n = r.a.w & 0x8000;
r.p.z = r.a.w == 0;
}
auto R65816::op_bit_b() {
regs.p.n = rd.l & 0x80;
regs.p.v = rd.l & 0x40;
regs.p.z = (rd.l & regs.a.l) == 0;
r.p.n = rd.l & 0x80;
r.p.v = rd.l & 0x40;
r.p.z = (rd.l & r.a.l) == 0;
}
auto R65816::op_bit_w() {
regs.p.n = rd.w & 0x8000;
regs.p.v = rd.w & 0x4000;
regs.p.z = (rd.w & regs.a.w) == 0;
r.p.n = rd.w & 0x8000;
r.p.v = rd.w & 0x4000;
r.p.z = (rd.w & r.a.w) == 0;
}
auto R65816::op_cmp_b() {
int r = regs.a.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
int result = r.a.l - rd.l;
r.p.n = result & 0x80;
r.p.z = (uint8)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_cmp_w() {
int r = regs.a.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
int result = r.a.w - rd.w;
r.p.n = result & 0x8000;
r.p.z = (uint16)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_cpx_b() {
int r = regs.x.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
int result = r.x.l - rd.l;
r.p.n = result & 0x80;
r.p.z = (uint8)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_cpx_w() {
int r = regs.x.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
int result = r.x.w - rd.w;
r.p.n = result & 0x8000;
r.p.z = (uint16)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_cpy_b() {
int r = regs.y.l - rd.l;
regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0;
int result = r.y.l - rd.l;
r.p.n = result & 0x80;
r.p.z = (uint8)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_cpy_w() {
int r = regs.y.w - rd.w;
regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0;
int result = r.y.w - rd.w;
r.p.n = result & 0x8000;
r.p.z = (uint16)result == 0;
r.p.c = result >= 0;
}
auto R65816::op_eor_b() {
regs.a.l ^= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
r.a.l ^= rd.l;
r.p.n = r.a.l & 0x80;
r.p.z = r.a.l == 0;
}
auto R65816::op_eor_w() {
regs.a.w ^= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
r.a.w ^= rd.w;
r.p.n = r.a.w & 0x8000;
r.p.z = r.a.w == 0;
}
auto R65816::op_lda_b() {
regs.a.l = rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
r.a.l = rd.l;
r.p.n = r.a.l & 0x80;
r.p.z = r.a.l == 0;
}
auto R65816::op_lda_w() {
regs.a.w = rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
r.a.w = rd.w;
r.p.n = r.a.w & 0x8000;
r.p.z = r.a.w == 0;
}
auto R65816::op_ldx_b() {
regs.x.l = rd.l;
regs.p.n = regs.x.l & 0x80;
regs.p.z = regs.x.l == 0;
r.x.l = rd.l;
r.p.n = r.x.l & 0x80;
r.p.z = r.x.l == 0;
}
auto R65816::op_ldx_w() {
regs.x.w = rd.w;
regs.p.n = regs.x.w & 0x8000;
regs.p.z = regs.x.w == 0;
r.x.w = rd.w;
r.p.n = r.x.w & 0x8000;
r.p.z = r.x.w == 0;
}
auto R65816::op_ldy_b() {
regs.y.l = rd.l;
regs.p.n = regs.y.l & 0x80;
regs.p.z = regs.y.l == 0;
r.y.l = rd.l;
r.p.n = r.y.l & 0x80;
r.p.z = r.y.l == 0;
}
auto R65816::op_ldy_w() {
regs.y.w = rd.w;
regs.p.n = regs.y.w & 0x8000;
regs.p.z = regs.y.w == 0;
r.y.w = rd.w;
r.p.n = r.y.w & 0x8000;
r.p.z = r.y.w == 0;
}
auto R65816::op_ora_b() {
regs.a.l |= rd.l;
regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0;
r.a.l |= rd.l;
r.p.n = r.a.l & 0x80;
r.p.z = r.a.l == 0;
}
auto R65816::op_ora_w() {
regs.a.w |= rd.w;
regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0;
r.a.w |= rd.w;
r.p.n = r.a.w & 0x8000;
r.p.z = r.a.w == 0;
}
auto R65816::op_sbc_b() {
int result;
rd.l ^= 0xff;
if(!regs.p.d) {
result = regs.a.l + rd.l + regs.p.c;
if(!r.p.d) {
result = r.a.l + rd.l + r.p.c;
} else {
result = (regs.a.l & 0x0f) + (rd.l & 0x0f) + (regs.p.c << 0);
result = (r.a.l & 0x0f) + (rd.l & 0x0f) + (r.p.c << 0);
if(result <= 0x0f) result -= 0x06;
regs.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (result & 0x0f);
r.p.c = result > 0x0f;
result = (r.a.l & 0xf0) + (rd.l & 0xf0) + (r.p.c << 4) + (result & 0x0f);
}
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ result) & 0x80;
if(regs.p.d && result <= 0xff) result -= 0x60;
regs.p.c = result > 0xff;
regs.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0;
r.p.v = ~(r.a.l ^ rd.l) & (r.a.l ^ result) & 0x80;
if(r.p.d && result <= 0xff) result -= 0x60;
r.p.c = result > 0xff;
r.p.n = result & 0x80;
r.p.z = (uint8_t)result == 0;
regs.a.l = result;
r.a.l = result;
}
auto R65816::op_sbc_w() {
int result;
rd.w ^= 0xffff;
if(!regs.p.d) {
result = regs.a.w + rd.w + regs.p.c;
if(!r.p.d) {
result = r.a.w + rd.w + r.p.c;
} else {
result = (regs.a.w & 0x000f) + (rd.w & 0x000f) + (regs.p.c << 0);
result = (r.a.w & 0x000f) + (rd.w & 0x000f) + (r.p.c << 0);
if(result <= 0x000f) result -= 0x0006;
regs.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f);
r.p.c = result > 0x000f;
result = (r.a.w & 0x00f0) + (rd.w & 0x00f0) + (r.p.c << 4) + (result & 0x000f);
if(result <= 0x00ff) result -= 0x0060;
regs.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff);
r.p.c = result > 0x00ff;
result = (r.a.w & 0x0f00) + (rd.w & 0x0f00) + (r.p.c << 8) + (result & 0x00ff);
if(result <= 0x0fff) result -= 0x0600;
regs.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (result & 0x0fff);
r.p.c = result > 0x0fff;
result = (r.a.w & 0xf000) + (rd.w & 0xf000) + (r.p.c << 12) + (result & 0x0fff);
}
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ result) & 0x8000;
if(regs.p.d && result <= 0xffff) result -= 0x6000;
regs.p.c = result > 0xffff;
regs.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0;
r.p.v = ~(r.a.w ^ rd.w) & (r.a.w ^ result) & 0x8000;
if(r.p.d && result <= 0xffff) result -= 0x6000;
r.p.c = result > 0xffff;
r.p.n = result & 0x8000;
r.p.z = (uint16_t)result == 0;
regs.a.w = result;
r.a.w = result;
}
auto R65816::op_inc_b() {
rd.l++;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_inc_w() {
rd.w++;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_dec_b() {
rd.l--;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_dec_w() {
rd.w--;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_asl_b() {
regs.p.c = rd.l & 0x80;
r.p.c = rd.l & 0x80;
rd.l <<= 1;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_asl_w() {
regs.p.c = rd.w & 0x8000;
r.p.c = rd.w & 0x8000;
rd.w <<= 1;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_lsr_b() {
regs.p.c = rd.l & 1;
r.p.c = rd.l & 1;
rd.l >>= 1;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_lsr_w() {
regs.p.c = rd.w & 1;
r.p.c = rd.w & 1;
rd.w >>= 1;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_rol_b() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.l & 0x80;
auto carry = (uint)r.p.c;
r.p.c = rd.l & 0x80;
rd.l = (rd.l << 1) | carry;
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_rol_w() {
unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.w & 0x8000;
auto carry = (uint)r.p.c;
r.p.c = rd.w & 0x8000;
rd.w = (rd.w << 1) | carry;
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_ror_b() {
unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = rd.l & 1;
auto carry = (uint)r.p.c << 7;
r.p.c = rd.l & 1;
rd.l = carry | (rd.l >> 1);
regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0;
r.p.n = rd.l & 0x80;
r.p.z = rd.l == 0;
}
auto R65816::op_ror_w() {
unsigned carry = (unsigned)regs.p.c << 15;
regs.p.c = rd.w & 1;
auto carry = (uint)r.p.c << 15;
r.p.c = rd.w & 1;
rd.w = carry | (rd.w >> 1);
regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0;
r.p.n = rd.w & 0x8000;
r.p.z = rd.w == 0;
}
auto R65816::op_trb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l &= ~regs.a.l;
r.p.z = (rd.l & r.a.l) == 0;
rd.l &= ~r.a.l;
}
auto R65816::op_trb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w &= ~regs.a.w;
r.p.z = (rd.w & r.a.w) == 0;
rd.w &= ~r.a.w;
}
auto R65816::op_tsb_b() {
regs.p.z = (rd.l & regs.a.l) == 0;
rd.l |= regs.a.l;
r.p.z = (rd.l & r.a.l) == 0;
rd.l |= r.a.l;
}
auto R65816::op_tsb_w() {
regs.p.z = (rd.w & regs.a.w) == 0;
rd.w |= regs.a.w;
r.p.z = (rd.w & r.a.w) == 0;
rd.w |= r.a.w;
}

View File

@ -23,93 +23,93 @@ auto R65816::dreadl(uint24 addr) -> uint24 {
}
auto R65816::decode(uint8 mode, uint24 addr) -> uint24 {
uint24 r = 0;
uint24 a = 0;
switch(mode) {
case OPTYPE_DP:
r = (regs.d + (addr & 0xffff)) & 0xffff;
a = (r.d + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPX:
r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
a = (r.d + r.x + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_DPY:
r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff;
a = (r.d + r.y + (addr & 0xffff)) & 0xffff;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
addr = (r.d + (addr & 0xffff)) & 0xffff;
a = (r.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
addr = (r.d + r.x + (addr & 0xffff)) & 0xffff;
a = (r.db << 16) + dreadw(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
addr = (r.d + (addr & 0xffff)) & 0xffff;
a = (r.db << 16) + dreadw(addr) + r.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr);
addr = (r.d + (addr & 0xffff)) & 0xffff;
a = dreadl(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr) + regs.y;
addr = (r.d + (addr & 0xffff)) & 0xffff;
a = dreadl(addr) + r.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
a = (r.db << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
a = (r.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_ADDRX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x;
a = (r.db << 16) + (addr & 0xffff) + r.x;
break;
case OPTYPE_ADDRY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y;
a = (r.db << 16) + (addr & 0xffff) + r.y;
break;
case OPTYPE_IADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff);
a = (r.pc.b << 16) + (addr & 0xffff);
break;
case OPTYPE_IADDRX:
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff);
a = (r.pc.b << 16) + ((addr + r.x) & 0xffff);
break;
case OPTYPE_ILADDR:
r = addr;
a = addr;
break;
case OPTYPE_LONG:
r = addr;
a = addr;
break;
case OPTYPE_LONGX:
r = (addr + regs.x);
a = (addr + r.x);
break;
case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff;
a = (r.s + (addr & 0xff)) & 0xffff;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
addr = (r.s + (addr & 0xff)) & 0xffff;
a = (r.db << 16) + dreadw(addr) + r.y;
break;
case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff);
r += int8(addr);
a = (r.pc.b << 16) + ((r.pc.w + 2) & 0xffff);
a += int8(addr);
break;
case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff);
r += (int16)addr;
a = (r.pc.b << 16) + ((r.pc.w + 3) & 0xffff);
a += (int16)addr;
break;
}
return r;
return a;
}
auto R65816::disassemble() -> string {
return disassemble(regs.pc.d, regs.e, regs.p.m, regs.p.x);
return disassemble(r.pc.d, r.e, r.p.m, r.p.x);
}
auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
string s;
reg24_t pc;
reg24 pc;
pc.d = addr;
s = {hex(pc, 6), " "};
@ -403,23 +403,23 @@ auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
#undef x8
s.append(t, " A:{0} X:{1} Y:{2} S:{3} D:{4} B:{5} ", format{
hex(regs.a.w, 4), hex(regs.x.w, 4), hex(regs.y.w, 4),
hex(regs.s.w, 4), hex(regs.d.w, 4), hex(regs.db, 2)
hex(r.a.w, 4), hex(r.x.w, 4), hex(r.y.w, 4),
hex(r.s.w, 4), hex(r.d.w, 4), hex(r.db, 2)
});
if(regs.e) {
if(r.e) {
s.append(
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'
r.p.n ? 'N' : 'n', r.p.v ? 'V' : 'v',
r.p.m ? '1' : '0', r.p.x ? 'B' : 'b',
r.p.d ? 'D' : 'd', r.p.i ? 'I' : 'i',
r.p.z ? 'Z' : 'z', r.p.c ? 'C' : 'c'
);
} else {
s.append(
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v',
regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c'
r.p.n ? 'N' : 'n', r.p.v ? 'V' : 'v',
r.p.m ? 'M' : 'm', r.p.x ? 'X' : 'x',
r.p.d ? 'D' : 'd', r.p.i ? 'I' : 'i',
r.p.z ? 'Z' : 'z', r.p.c ? 'C' : 'c'
);
}

View File

@ -1,77 +1,81 @@
alwaysinline auto readpc() -> uint8 {
return read((regs.pc.b << 16) + regs.pc.w++);
alwaysinline auto readPC() -> uint8 {
return read(r.pc.b << 16 | uint16(r.pc.w++));
}
alwaysinline auto readstack() -> uint8 {
regs.e ? regs.s.l++ : regs.s.w++;
return read(regs.s.w);
alwaysinline auto readSP() -> uint8 {
r.e ? r.s.l++ : r.s.w++;
return read(r.s.w);
}
alwaysinline auto readstackn() -> uint8 {
return read(++regs.s.w);
alwaysinline auto readSPn() -> uint8 {
return read(++r.s.w);
}
alwaysinline auto readaddr(uint32 addr) -> uint8 {
return read(addr & 0xffff);
alwaysinline auto readAddr(uint addr) -> uint8 {
return read(uint16(addr));
}
alwaysinline auto readlong(uint32 addr) -> uint8 {
return read(addr & 0xffffff);
alwaysinline auto readLong(uint addr) -> uint8 {
return read(uint24(addr));
}
alwaysinline auto readdbr(uint32 addr) -> uint8 {
return read(((regs.db << 16) + addr) & 0xffffff);
alwaysinline auto readDB(uint addr) -> uint8 {
return read(r.db << 16 | uint16(addr));
}
alwaysinline auto readpbr(uint32 addr) -> uint8 {
return read((regs.pc.b << 16) + (addr & 0xffff));
alwaysinline auto readPB(uint addr) -> uint8 {
return read(r.pc.b << 16 | uint16(addr));
}
alwaysinline auto readdp(uint32 addr) -> uint8 {
if(regs.e && regs.d.l == 0x00) {
return read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
alwaysinline auto readDP(uint addr) -> uint8 {
if(r.e && r.d.l == 0x00) {
return read(r.d | uint8(addr));
} else {
return read((regs.d + (addr & 0xffff)) & 0xffff);
return read(uint16(r.d + addr));
}
}
alwaysinline auto readsp(uint32 addr) -> uint8 {
return read((regs.s + (addr & 0xffff)) & 0xffff);
alwaysinline auto readDPn(uint addr) -> uint8 {
return read(uint16(r.d + addr));
}
alwaysinline auto writestack(uint8 data) -> void {
write(regs.s.w, data);
regs.e ? regs.s.l-- : regs.s.w--;
alwaysinline auto readSP(uint addr) -> uint8 {
return read(uint16(r.s + addr));
}
alwaysinline auto writestackn(uint8 data) -> void {
write(regs.s.w--, data);
alwaysinline auto writeSP(uint8 data) -> void {
write(r.s.w, data);
r.e ? r.s.l-- : r.s.w--;
}
alwaysinline auto writeaddr(uint32 addr, uint8 data) -> void {
write(addr & 0xffff, data);
alwaysinline auto writeSPn(uint8 data) -> void {
write(r.s.w--, data);
}
alwaysinline auto writelong(uint32 addr, uint8 data) -> void {
write(addr & 0xffffff, data);
alwaysinline auto writeAddr(uint addr, uint8 data) -> void {
write(uint16(addr), data);
}
alwaysinline auto writedbr(uint32 addr, uint8 data) -> void {
write(((regs.db << 16) + addr) & 0xffffff, data);
alwaysinline auto writeLong(uint addr, uint8 data) -> void {
write(uint24(addr), data);
}
alwaysinline auto writepbr(uint32 addr, uint8 data) -> void {
write((regs.pc.b << 16) + (addr & 0xffff), data);
alwaysinline auto writeDB(uint addr, uint8 data) -> void {
write(r.db << 16 | uint16(addr), data);
}
alwaysinline auto writedp(uint32 addr, uint8 data) -> void {
if(regs.e && regs.d.l == 0x00) {
write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
alwaysinline auto writePB(uint addr, uint8 data) -> void {
write(r.pc.b << 16 | uint16(addr), data);
}
alwaysinline auto writeDP(uint addr, uint8 data) -> void {
if(r.e && r.d.l == 0x00) {
write(r.d | uint8(addr), data);
} else {
write((regs.d + (addr & 0xffff)) & 0xffff, data);
write(uint16(r.d + addr), data);
}
}
alwaysinline auto writesp(uint32 addr, uint8 data) -> void {
write((regs.s + (addr & 0xffff)) & 0xffff, data);
alwaysinline auto writeSP(uint addr, uint8 data) -> void {
write(uint16(r.s + addr), data);
}

View File

@ -3,81 +3,65 @@ L ioIRQ();
}
auto R65816::op_wdm() {
L readpc();
L readPC();
}
auto R65816::op_xba() {
io();
L io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
swap(r.a.l, r.a.h);
r.p.n = (r.a.l & 0x80);
r.p.z = (r.a.l == 0);
}
auto R65816::op_move_b(signed adjust) {
dp = readpc();
sp = readpc();
regs.db = dp;
rd.l = readlong((sp << 16) | regs.x.w);
writelong((dp << 16) | regs.y.w, rd.l);
auto R65816::op_move_b(int adjust) {
dp = readPC();
sp = readPC();
r.db = dp;
rd.l = readLong(sp << 16 | r.x.w);
writeLong(dp << 16 | r.y.w, rd.l);
io();
regs.x.l += adjust;
regs.y.l += adjust;
r.x.l += adjust;
r.y.l += adjust;
L io();
if(regs.a.w--) regs.pc.w -= 3;
if(r.a.w--) r.pc.w -= 3;
}
auto R65816::op_move_w(signed adjust) {
dp = readpc();
sp = readpc();
regs.db = dp;
rd.l = readlong((sp << 16) | regs.x.w);
writelong((dp << 16) | regs.y.w, rd.l);
auto R65816::op_move_w(int adjust) {
dp = readPC();
sp = readPC();
r.db = dp;
rd.l = readLong(sp << 16 | r.x.w);
writeLong(dp << 16 | r.y.w, rd.l);
io();
regs.x.w += adjust;
regs.y.w += adjust;
r.x.w += adjust;
r.y.w += adjust;
L io();
if(regs.a.w--) regs.pc.w -= 3;
if(r.a.w--) r.pc.w -= 3;
}
auto R65816::op_interrupt_e(uint16 vector) {
readpc();
writestack(regs.pc.h);
writestack(regs.pc.l);
writestack(regs.p);
rd.l = readlong(vector + 0);
regs.pc.b = 0;
regs.p.i = 1;
regs.p.d = 0;
L rd.h = readlong(vector + 1);
regs.pc.w = rd.w;
}
auto R65816::op_interrupt_n(uint16 vector) {
readpc();
writestack(regs.pc.b);
writestack(regs.pc.h);
writestack(regs.pc.l);
writestack(regs.p);
rd.l = readlong(vector + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
L rd.h = readlong(vector + 1);
regs.pc.w = rd.w;
auto R65816::op_interrupt(uint16 vector) {
readPC();
N writeSP(r.pc.b);
writeSP(r.pc.h);
writeSP(r.pc.l);
writeSP(r.p);
r.pc.l = readLong(vector + 0);
r.p.i = 1;
r.p.d = 0;
L r.pc.h = readLong(vector + 1);
r.pc.b = 0x00;
}
auto R65816::op_stp() {
while(regs.wai = true) {
while(r.wai = true) {
L io();
}
}
auto R65816::op_wai() {
regs.wai = true;
while(regs.wai) {
r.wai = true;
while(r.wai) {
L io();
}
io();
@ -85,15 +69,15 @@ L io();
auto R65816::op_xce() {
L ioIRQ();
bool carry = regs.p.c;
regs.p.c = regs.e;
regs.e = carry;
if(regs.e) {
regs.p.m = 1;
regs.p.x = 1;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
bool carry = r.p.c;
r.p.c = r.e;
r.e = carry;
if(r.e) {
r.p.m = 1;
r.p.x = 1;
r.x.h = 0x00;
r.y.h = 0x00;
r.s.h = 0x01;
}
}
@ -102,226 +86,160 @@ L ioIRQ();
flag = value;
}
auto R65816::op_pflag_e(bool mode) {
rd.l = readpc();
auto R65816::op_pflag(bool mode) {
rd.l = readPC();
L io();
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
regs.p.m = 1;
regs.p.x = 1;
regs.x.h = 0x00;
regs.y.h = 0x00;
}
auto R65816::op_pflag_n(bool mode) {
rd.l = readpc();
L io();
regs.p = (mode ? regs.p | rd.l : regs.p & ~rd.l);
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
r.p = (mode ? r.p | rd.l : r.p & ~rd.l);
E r.p.m = 1, r.p.x = 1;
if(r.p.x) {
r.x.h = 0x00;
r.y.h = 0x00;
}
}
auto R65816::op_transfer_b(reg16_t& from, reg16_t& to) {
auto R65816::op_transfer_b(reg16& from, reg16& to) {
L ioIRQ();
to.l = from.l;
regs.p.n = (to.l & 0x80);
regs.p.z = (to.l == 0);
r.p.n = (to.l & 0x80);
r.p.z = (to.l == 0);
}
auto R65816::op_transfer_w(reg16_t& from, reg16_t& to) {
auto R65816::op_transfer_w(reg16& from, reg16& to) {
L ioIRQ();
to.w = from.w;
regs.p.n = (to.w & 0x8000);
regs.p.z = (to.w == 0);
r.p.n = (to.w & 0x8000);
r.p.z = (to.w == 0);
}
auto R65816::op_tcs_e() {
auto R65816::op_tcs() {
L ioIRQ();
regs.s.l = regs.a.l;
}
auto R65816::op_tcs_n() {
L ioIRQ();
regs.s.w = regs.a.w;
r.s.w = r.a.w;
E r.s.h = 0x01;
}
auto R65816::op_tsx_b() {
L ioIRQ();
regs.x.l = regs.s.l;
regs.p.n = (regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
r.x.l = r.s.l;
r.p.n = (r.x.l & 0x80);
r.p.z = (r.x.l == 0);
}
auto R65816::op_tsx_w() {
L ioIRQ();
regs.x.w = regs.s.w;
regs.p.n = (regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
r.x.w = r.s.w;
r.p.n = (r.x.w & 0x8000);
r.p.z = (r.x.w == 0);
}
auto R65816::op_txs_e() {
auto R65816::op_txs() {
L ioIRQ();
regs.s.l = regs.x.l;
E r.s.l = r.x.l;
N r.s.w = r.x.w;
}
auto R65816::op_txs_n() {
L ioIRQ();
regs.s.w = regs.x.w;
}
auto R65816::op_push_b(reg16_t& reg) {
auto R65816::op_push_b(reg16& reg) {
io();
L writestack(reg.l);
L writeSP(reg.l);
}
auto R65816::op_push_w(reg16_t& reg) {
auto R65816::op_push_w(reg16& reg) {
io();
writestack(reg.h);
L writestack(reg.l);
writeSP(reg.h);
L writeSP(reg.l);
}
auto R65816::op_phd_e() {
auto R65816::op_phd() {
io();
writestackn(regs.d.h);
L writestackn(regs.d.l);
regs.s.h = 0x01;
}
auto R65816::op_phd_n() {
io();
writestackn(regs.d.h);
L writestackn(regs.d.l);
writeSPn(r.d.h);
L writeSPn(r.d.l);
E r.s.h = 0x01;
}
auto R65816::op_phb() {
io();
L writestack(regs.db);
L writeSP(r.db);
}
auto R65816::op_phk() {
io();
L writestack(regs.pc.b);
L writeSP(r.pc.b);
}
auto R65816::op_php() {
io();
L writestack(regs.p);
L writeSP(r.p);
}
auto R65816::op_pull_b(reg16_t& reg) {
auto R65816::op_pull_b(reg16& reg) {
io();
io();
L reg.l = readstack();
regs.p.n = (reg.l & 0x80);
regs.p.z = (reg.l == 0);
L reg.l = readSP();
r.p.n = (reg.l & 0x80);
r.p.z = (reg.l == 0);
}
auto R65816::op_pull_w(reg16_t& reg) {
auto R65816::op_pull_w(reg16& reg) {
io();
io();
reg.l = readstack();
L reg.h = readstack();
regs.p.n = (reg.w & 0x8000);
regs.p.z = (reg.w == 0);
reg.l = readSP();
L reg.h = readSP();
r.p.n = (reg.w & 0x8000);
r.p.z = (reg.w == 0);
}
auto R65816::op_pld_e() {
auto R65816::op_pld() {
io();
io();
regs.d.l = readstackn();
L regs.d.h = readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
regs.s.h = 0x01;
}
auto R65816::op_pld_n() {
io();
io();
regs.d.l = readstackn();
L regs.d.h = readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
r.d.l = readSPn();
L r.d.h = readSPn();
r.p.n = (r.d.w & 0x8000);
r.p.z = (r.d.w == 0);
E r.s.h = 0x01;
}
auto R65816::op_plb() {
io();
io();
L regs.db = readstack();
regs.p.n = (regs.db & 0x80);
regs.p.z = (regs.db == 0);
L r.db = readSP();
r.p.n = (r.db & 0x80);
r.p.z = (r.db == 0);
}
auto R65816::op_plp_e() {
auto R65816::op_plp() {
io();
io();
L regs.p = readstack() | 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
L r.p = readSP();
E r.p.m = 1, r.p.x = 1;
if(r.p.x) {
r.x.h = 0x00;
r.y.h = 0x00;
}
}
auto R65816::op_plp_n() {
io();
io();
L regs.p = readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
auto R65816::op_pea() {
aa.l = readPC();
aa.h = readPC();
writeSPn(aa.h);
L writeSPn(aa.l);
E r.s.h = 0x01;
}
auto R65816::op_pea_e() {
aa.l = readpc();
aa.h = readpc();
writestackn(aa.h);
L writestackn(aa.l);
regs.s.h = 0x01;
}
auto R65816::op_pea_n() {
aa.l = readpc();
aa.h = readpc();
writestackn(aa.h);
L writestackn(aa.l);
}
auto R65816::op_pei_e() {
dp = readpc();
auto R65816::op_pei() {
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
writestackn(aa.h);
L writestackn(aa.l);
regs.s.h = 0x01;
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
writeSPn(aa.h);
L writeSPn(aa.l);
E r.s.h = 0x01;
}
auto R65816::op_pei_n() {
dp = readpc();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
writestackn(aa.h);
L writestackn(aa.l);
}
auto R65816::op_per_e() {
aa.l = readpc();
aa.h = readpc();
auto R65816::op_per() {
aa.l = readPC();
aa.h = readPC();
io();
rd.w = regs.pc.d + (int16)aa.w;
writestackn(rd.h);
L writestackn(rd.l);
regs.s.h = 0x01;
}
auto R65816::op_per_n() {
aa.l = readpc();
aa.h = readpc();
io();
rd.w = regs.pc.d + (int16)aa.w;
writestackn(rd.h);
L writestackn(rd.l);
rd.w = r.pc.d + (int16)aa.w;
writeSPn(rd.h);
L writeSPn(rd.l);
E r.s.h = 0x01;
}

View File

@ -1,176 +1,138 @@
auto R65816::op_branch(bool flag, bool value) {
if(flag != value) {
L rd.l = readpc();
L rd.l = readPC();
} else {
rd.l = readpc();
aa.w = regs.pc.d + (int8)rd.l;
rd.l = readPC();
aa.w = r.pc.d + (int8)rd.l;
io6(aa.w);
L io();
regs.pc.w = aa.w;
r.pc.w = aa.w;
}
}
auto R65816::op_bra() {
rd.l = readpc();
aa.w = regs.pc.d + (int8)rd.l;
rd.l = readPC();
aa.w = r.pc.d + (int8)rd.l;
io6(aa.w);
L io();
regs.pc.w = aa.w;
r.pc.w = aa.w;
}
auto R65816::op_brl() {
rd.l = readpc();
rd.h = readpc();
rd.l = readPC();
rd.h = readPC();
L io();
regs.pc.w = regs.pc.d + (int16)rd.w;
r.pc.w = r.pc.d + (int16)rd.w;
}
auto R65816::op_jmp_addr() {
rd.l = readpc();
L rd.h = readpc();
regs.pc.w = rd.w;
rd.l = readPC();
L rd.h = readPC();
r.pc.w = rd.w;
}
auto R65816::op_jmp_long() {
rd.l = readpc();
rd.h = readpc();
L rd.b = readpc();
regs.pc.d = rd.d & 0xffffff;
rd.l = readPC();
rd.h = readPC();
L rd.b = readPC();
r.pc.d = rd.d;
}
auto R65816::op_jmp_iaddr() {
aa.l = readpc();
aa.h = readpc();
rd.l = readaddr(aa.w + 0);
L rd.h = readaddr(aa.w + 1);
regs.pc.w = rd.w;
aa.l = readPC();
aa.h = readPC();
rd.l = readAddr(aa.w + 0);
L rd.h = readAddr(aa.w + 1);
r.pc.w = rd.w;
}
auto R65816::op_jmp_iaddrx() {
aa.l = readpc();
aa.h = readpc();
aa.l = readPC();
aa.h = readPC();
io();
rd.l = readpbr(aa.w + regs.x.w + 0);
L rd.h = readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
rd.l = readPB(aa.w + r.x.w + 0);
L rd.h = readPB(aa.w + r.x.w + 1);
r.pc.w = rd.w;
}
auto R65816::op_jmp_iladdr() {
aa.l = readpc();
aa.h = readpc();
rd.l = readaddr(aa.w + 0);
rd.h = readaddr(aa.w + 1);
L rd.b = readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
aa.l = readPC();
aa.h = readPC();
rd.l = readAddr(aa.w + 0);
rd.h = readAddr(aa.w + 1);
L rd.b = readAddr(aa.w + 2);
r.pc.d = rd.d;
}
auto R65816::op_jsr_addr() {
aa.l = readpc();
aa.h = readpc();
aa.l = readPC();
aa.h = readPC();
io();
regs.pc.w--;
writestack(regs.pc.h);
L writestack(regs.pc.l);
regs.pc.w = aa.w;
r.pc.w--;
writeSP(r.pc.h);
L writeSP(r.pc.l);
r.pc.w = aa.w;
}
auto R65816::op_jsr_long_e() {
aa.l = readpc();
aa.h = readpc();
writestackn(regs.pc.b);
auto R65816::op_jsr_long() {
aa.l = readPC();
aa.h = readPC();
writeSPn(r.pc.b);
io();
aa.b = readpc();
regs.pc.w--;
writestackn(regs.pc.h);
L writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
regs.s.h = 0x01;
aa.b = readPC();
r.pc.w--;
writeSPn(r.pc.h);
L writeSPn(r.pc.l);
r.pc.d = aa.d;
E r.s.h = 0x01;
}
auto R65816::op_jsr_long_n() {
aa.l = readpc();
aa.h = readpc();
writestackn(regs.pc.b);
auto R65816::op_jsr_iaddrx() {
aa.l = readPC();
writeSPn(r.pc.h);
writeSPn(r.pc.l);
aa.h = readPC();
io();
aa.b = readpc();
regs.pc.w--;
writestackn(regs.pc.h);
L writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
rd.l = readPB(aa.w + r.x.w + 0);
L rd.h = readPB(aa.w + r.x.w + 1);
r.pc.w = rd.w;
E r.s.h = 0x01;
}
auto R65816::op_jsr_iaddrx_e() {
aa.l = readpc();
writestackn(regs.pc.h);
writestackn(regs.pc.l);
aa.h = readpc();
io();
rd.l = readpbr(aa.w + regs.x.w + 0);
L rd.h = readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
regs.s.h = 0x01;
}
auto R65816::op_jsr_iaddrx_n() {
aa.l = readpc();
writestackn(regs.pc.h);
writestackn(regs.pc.l);
aa.h = readpc();
io();
rd.l = readpbr(aa.w + regs.x.w + 0);
L rd.h = readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
auto R65816::op_rti_e() {
auto R65816::op_rti() {
io();
io();
regs.p = readstack() | 0x30;
rd.l = readstack();
L rd.h = readstack();
regs.pc.w = rd.w;
}
auto R65816::op_rti_n() {
io();
io();
regs.p = readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
r.p = readSP();
E r.p.m = 1, r.p.x = 1;
if(r.p.x) {
r.x.h = 0x00;
r.y.h = 0x00;
}
r.pc.l = readSP();
if(r.e) {
L r.pc.h = readSP();
} else {
r.pc.h = readSP();
L r.pc.b = readSP();
}
rd.l = readstack();
rd.h = readstack();
L rd.b = readstack();
regs.pc.d = rd.d & 0xffffff;
}
auto R65816::op_rts() {
io();
io();
rd.l = readstack();
rd.h = readstack();
rd.l = readSP();
rd.h = readSP();
L io();
regs.pc.w = ++rd.w;
r.pc.w = ++rd.w;
}
auto R65816::op_rtl_e() {
auto R65816::op_rtl() {
io();
io();
rd.l = readstackn();
rd.h = readstackn();
L rd.b = readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
regs.s.h = 0x01;
}
auto R65816::op_rtl_n() {
io();
io();
rd.l = readstackn();
rd.h = readstackn();
L rd.b = readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
rd.l = readSPn();
rd.h = readSPn();
L rd.b = readSPn();
r.pc.b = rd.b;
r.pc.w = ++rd.w;
E r.s.h = 0x01;
}

View File

@ -1,275 +1,275 @@
auto R65816::op_read_const_b(fp op) {
L rd.l = readpc();
L rd.l = readPC();
call(op);
}
auto R65816::op_read_const_w(fp op) {
rd.l = readpc();
L rd.h = readpc();
rd.l = readPC();
L rd.h = readPC();
call(op);
}
auto R65816::op_read_bit_const_b() {
L rd.l = readpc();
regs.p.z = ((rd.l & regs.a.l) == 0);
L rd.l = readPC();
r.p.z = ((rd.l & r.a.l) == 0);
}
auto R65816::op_read_bit_const_w() {
rd.l = readpc();
L rd.h = readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
rd.l = readPC();
L rd.h = readPC();
r.p.z = ((rd.w & r.a.w) == 0);
}
auto R65816::op_read_addr_b(fp op) {
aa.l = readpc();
aa.h = readpc();
L rd.l = readdbr(aa.w);
aa.l = readPC();
aa.h = readPC();
L rd.l = readDB(aa.w);
call(op);
}
auto R65816::op_read_addr_w(fp op) {
aa.l = readpc();
aa.h = readpc();
rd.l = readdbr(aa.w + 0);
L rd.h = readdbr(aa.w + 1);
aa.l = readPC();
aa.h = readPC();
rd.l = readDB(aa.w + 0);
L rd.h = readDB(aa.w + 1);
call(op);
}
auto R65816::op_read_addrx_b(fp op) {
aa.l = readpc();
aa.h = readpc();
io4(aa.w, aa.w + regs.x.w);
L rd.l = readdbr(aa.w + regs.x.w);
aa.l = readPC();
aa.h = readPC();
io4(aa.w, aa.w + r.x.w);
L rd.l = readDB(aa.w + r.x.w);
call(op);
}
auto R65816::op_read_addrx_w(fp op) {
aa.l = readpc();
aa.h = readpc();
io4(aa.w, aa.w + regs.x.w);
rd.l = readdbr(aa.w + regs.x.w + 0);
L rd.h = readdbr(aa.w + regs.x.w + 1);
aa.l = readPC();
aa.h = readPC();
io4(aa.w, aa.w + r.x.w);
rd.l = readDB(aa.w + r.x.w + 0);
L rd.h = readDB(aa.w + r.x.w + 1);
call(op);
}
auto R65816::op_read_addry_b(fp op) {
aa.l = readpc();
aa.h = readpc();
io4(aa.w, aa.w + regs.y.w);
L rd.l = readdbr(aa.w + regs.y.w);
aa.l = readPC();
aa.h = readPC();
io4(aa.w, aa.w + r.y.w);
L rd.l = readDB(aa.w + r.y.w);
call(op);
}
auto R65816::op_read_addry_w(fp op) {
aa.l = readpc();
aa.h = readpc();
io4(aa.w, aa.w + regs.y.w);
rd.l = readdbr(aa.w + regs.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1);
aa.l = readPC();
aa.h = readPC();
io4(aa.w, aa.w + r.y.w);
rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readDB(aa.w + r.y.w + 1);
call(op);
}
auto R65816::op_read_long_b(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
L rd.l = readlong(aa.d);
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
L rd.l = readLong(aa.d);
call(op);
}
auto R65816::op_read_long_w(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
rd.l = readlong(aa.d + 0);
L rd.h = readlong(aa.d + 1);
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
rd.l = readLong(aa.d + 0);
L rd.h = readLong(aa.d + 1);
call(op);
}
auto R65816::op_read_longx_b(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
L rd.l = readlong(aa.d + regs.x.w);
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
L rd.l = readLong(aa.d + r.x.w);
call(op);
}
auto R65816::op_read_longx_w(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
rd.l = readlong(aa.d + regs.x.w + 0);
L rd.h = readlong(aa.d + regs.x.w + 1);
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
rd.l = readLong(aa.d + r.x.w + 0);
L rd.h = readLong(aa.d + r.x.w + 1);
call(op);
}
auto R65816::op_read_dp_b(fp op) {
dp = readpc();
dp = readPC();
io2();
L rd.l = readdp(dp);
L rd.l = readDP(dp);
call(op);
}
auto R65816::op_read_dp_w(fp op) {
dp = readpc();
dp = readPC();
io2();
rd.l = readdp(dp + 0);
L rd.h = readdp(dp + 1);
rd.l = readDP(dp + 0);
L rd.h = readDP(dp + 1);
call(op);
}
auto R65816::op_read_dpr_b(fp op, reg16_t& reg) {
dp = readpc();
auto R65816::op_read_dpr_b(fp op, reg16& reg) {
dp = readPC();
io2();
io();
L rd.l = readdp(dp + reg.w);
L rd.l = readDP(dp + reg.w);
call(op);
}
auto R65816::op_read_dpr_w(fp op, reg16_t& reg) {
dp = readpc();
auto R65816::op_read_dpr_w(fp op, reg16& reg) {
dp = readPC();
io2();
io();
rd.l = readdp(dp + reg.w + 0);
L rd.h = readdp(dp + reg.w + 1);
rd.l = readDP(dp + reg.w + 0);
L rd.h = readDP(dp + reg.w + 1);
call(op);
}
auto R65816::op_read_idp_b(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
L rd.l = readdbr(aa.w);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
L rd.l = readDB(aa.w);
call(op);
}
auto R65816::op_read_idp_w(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
rd.l = readdbr(aa.w + 0);
L rd.h = readdbr(aa.w + 1);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
rd.l = readDB(aa.w + 0);
L rd.h = readDB(aa.w + 1);
call(op);
}
auto R65816::op_read_idpx_b(fp op) {
dp = readpc();
dp = readPC();
io2();
io();
aa.l = readdp(dp + regs.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1);
L rd.l = readdbr(aa.w);
aa.l = readDP(dp + r.x.w + 0);
aa.h = readDP(dp + r.x.w + 1);
L rd.l = readDB(aa.w);
call(op);
}
auto R65816::op_read_idpx_w(fp op) {
dp = readpc();
dp = readPC();
io2();
io();
aa.l = readdp(dp + regs.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1);
rd.l = readdbr(aa.w + 0);
L rd.h = readdbr(aa.w + 1);
aa.l = readDP(dp + r.x.w + 0);
aa.h = readDP(dp + r.x.w + 1);
rd.l = readDB(aa.w + 0);
L rd.h = readDB(aa.w + 1);
call(op);
}
auto R65816::op_read_idpy_b(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
io4(aa.w, aa.w + regs.y.w);
L rd.l = readdbr(aa.w + regs.y.w);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
io4(aa.w, aa.w + r.y.w);
L rd.l = readDB(aa.w + r.y.w);
call(op);
}
auto R65816::op_read_idpy_w(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
io4(aa.w, aa.w + regs.y.w);
rd.l = readdbr(aa.w + regs.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
io4(aa.w, aa.w + r.y.w);
rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readDB(aa.w + r.y.w + 1);
call(op);
}
auto R65816::op_read_ildp_b(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
L rd.l = readlong(aa.d);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
L rd.l = readLong(aa.d);
call(op);
}
auto R65816::op_read_ildp_w(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
rd.l = readlong(aa.d + 0);
L rd.h = readlong(aa.d + 1);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
rd.l = readLong(aa.d + 0);
L rd.h = readLong(aa.d + 1);
call(op);
}
auto R65816::op_read_ildpy_b(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
L rd.l = readlong(aa.d + regs.y.w);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
L rd.l = readLong(aa.d + r.y.w);
call(op);
}
auto R65816::op_read_ildpy_w(fp op) {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
rd.l = readlong(aa.d + regs.y.w + 0);
L rd.h = readlong(aa.d + regs.y.w + 1);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
rd.l = readLong(aa.d + r.y.w + 0);
L rd.h = readLong(aa.d + r.y.w + 1);
call(op);
}
auto R65816::op_read_sr_b(fp op) {
sp = readpc();
sp = readPC();
io();
L rd.l = readsp(sp);
L rd.l = readSP(sp);
call(op);
}
auto R65816::op_read_sr_w(fp op) {
sp = readpc();
sp = readPC();
io();
rd.l = readsp(sp + 0);
L rd.h = readsp(sp + 1);
rd.l = readSP(sp + 0);
L rd.h = readSP(sp + 1);
call(op);
}
auto R65816::op_read_isry_b(fp op) {
sp = readpc();
sp = readPC();
io();
aa.l = readsp(sp + 0);
aa.h = readsp(sp + 1);
aa.l = readSP(sp + 0);
aa.h = readSP(sp + 1);
io();
L rd.l = readdbr(aa.w + regs.y.w);
L rd.l = readDB(aa.w + r.y.w);
call(op);
}
auto R65816::op_read_isry_w(fp op) {
sp = readpc();
sp = readPC();
io();
aa.l = readsp(sp + 0);
aa.h = readsp(sp + 1);
aa.l = readSP(sp + 0);
aa.h = readSP(sp + 1);
io();
rd.l = readdbr(aa.w + regs.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1);
rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readDB(aa.w + r.y.w + 1);
call(op);
}

View File

@ -1,165 +1,165 @@
auto R65816::op_adjust_imm_b(reg16_t& reg, signed adjust) {
auto R65816::op_adjust_imm_b(reg16& reg, int adjust) {
L ioIRQ();
reg.l += adjust;
regs.p.n = (reg.l & 0x80);
regs.p.z = (reg.l == 0);
r.p.n = (reg.l & 0x80);
r.p.z = (reg.l == 0);
}
auto R65816::op_adjust_imm_w(reg16_t& reg, signed adjust) {
auto R65816::op_adjust_imm_w(reg16& reg, int adjust) {
L ioIRQ();
reg.w += adjust;
regs.p.n = (reg.w & 0x8000);
regs.p.z = (reg.w == 0);
r.p.n = (reg.w & 0x8000);
r.p.z = (reg.w == 0);
}
auto R65816::op_asl_imm_b() {
L ioIRQ();
regs.p.c = (regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
r.p.c = (r.a.l & 0x80);
r.a.l <<= 1;
r.p.n = (r.a.l & 0x80);
r.p.z = (r.a.l == 0);
}
auto R65816::op_asl_imm_w() {
L ioIRQ();
regs.p.c = (regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
r.p.c = (r.a.w & 0x8000);
r.a.w <<= 1;
r.p.n = (r.a.w & 0x8000);
r.p.z = (r.a.w == 0);
}
auto R65816::op_lsr_imm_b() {
L ioIRQ();
regs.p.c = (regs.a.l & 0x01);
regs.a.l >>= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
r.p.c = (r.a.l & 0x01);
r.a.l >>= 1;
r.p.n = (r.a.l & 0x80);
r.p.z = (r.a.l == 0);
}
auto R65816::op_lsr_imm_w() {
L ioIRQ();
regs.p.c = (regs.a.w & 0x0001);
regs.a.w >>= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
r.p.c = (r.a.w & 0x0001);
r.a.w >>= 1;
r.p.n = (r.a.w & 0x8000);
r.p.z = (r.a.w == 0);
}
auto R65816::op_rol_imm_b() {
L ioIRQ();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x80);
regs.a.l = (regs.a.l << 1) | carry;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
bool carry = r.p.c;
r.p.c = (r.a.l & 0x80);
r.a.l = (r.a.l << 1) | carry;
r.p.n = (r.a.l & 0x80);
r.p.z = (r.a.l == 0);
}
auto R65816::op_rol_imm_w() {
L ioIRQ();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x8000);
regs.a.w = (regs.a.w << 1) | carry;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
bool carry = r.p.c;
r.p.c = (r.a.w & 0x8000);
r.a.w = (r.a.w << 1) | carry;
r.p.n = (r.a.w & 0x8000);
r.p.z = (r.a.w == 0);
}
auto R65816::op_ror_imm_b() {
L ioIRQ();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x01);
regs.a.l = (carry << 7) | (regs.a.l >> 1);
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
bool carry = r.p.c;
r.p.c = (r.a.l & 0x01);
r.a.l = (carry << 7) | (r.a.l >> 1);
r.p.n = (r.a.l & 0x80);
r.p.z = (r.a.l == 0);
}
auto R65816::op_ror_imm_w() {
L ioIRQ();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x0001);
regs.a.w = (carry << 15) | (regs.a.w >> 1);
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
bool carry = r.p.c;
r.p.c = (r.a.w & 0x0001);
r.a.w = (carry << 15) | (r.a.w >> 1);
r.p.n = (r.a.w & 0x8000);
r.p.z = (r.a.w == 0);
}
auto R65816::op_adjust_addr_b(fp op) {
aa.l = readpc();
aa.h = readpc();
rd.l = readdbr(aa.w);
aa.l = readPC();
aa.h = readPC();
rd.l = readDB(aa.w);
io();
call(op);
L writedbr(aa.w, rd.l);
L writeDB(aa.w, rd.l);
}
auto R65816::op_adjust_addr_w(fp op) {
aa.l = readpc();
aa.h = readpc();
rd.l = readdbr(aa.w + 0);
rd.h = readdbr(aa.w + 1);
aa.l = readPC();
aa.h = readPC();
rd.l = readDB(aa.w + 0);
rd.h = readDB(aa.w + 1);
io();
call(op);
writedbr(aa.w + 1, rd.h);
L writedbr(aa.w + 0, rd.l);
writeDB(aa.w + 1, rd.h);
L writeDB(aa.w + 0, rd.l);
}
auto R65816::op_adjust_addrx_b(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.l = readPC();
aa.h = readPC();
io();
rd.l = readdbr(aa.w + regs.x.w);
rd.l = readDB(aa.w + r.x.w);
io();
call(op);
L writedbr(aa.w + regs.x.w, rd.l);
L writeDB(aa.w + r.x.w, rd.l);
}
auto R65816::op_adjust_addrx_w(fp op) {
aa.l = readpc();
aa.h = readpc();
aa.l = readPC();
aa.h = readPC();
io();
rd.l = readdbr(aa.w + regs.x.w + 0);
rd.h = readdbr(aa.w + regs.x.w + 1);
rd.l = readDB(aa.w + r.x.w + 0);
rd.h = readDB(aa.w + r.x.w + 1);
io();
call(op);
writedbr(aa.w + regs.x.w + 1, rd.h);
L writedbr(aa.w + regs.x.w + 0, rd.l);
writeDB(aa.w + r.x.w + 1, rd.h);
L writeDB(aa.w + r.x.w + 0, rd.l);
}
auto R65816::op_adjust_dp_b(fp op) {
dp = readpc();
dp = readPC();
io2();
rd.l = readdp(dp);
rd.l = readDP(dp);
io();
call(op);
L writedp(dp, rd.l);
L writeDP(dp, rd.l);
}
auto R65816::op_adjust_dp_w(fp op) {
dp = readpc();
dp = readPC();
io2();
rd.l = readdp(dp + 0);
rd.h = readdp(dp + 1);
rd.l = readDP(dp + 0);
rd.h = readDP(dp + 1);
io();
call(op);
writedp(dp + 1, rd.h);
L writedp(dp + 0, rd.l);
writeDP(dp + 1, rd.h);
L writeDP(dp + 0, rd.l);
}
auto R65816::op_adjust_dpx_b(fp op) {
dp = readpc();
dp = readPC();
io2();
io();
rd.l = readdp(dp + regs.x.w);
rd.l = readDP(dp + r.x.w);
io();
call(op);
L writedp(dp + regs.x.w, rd.l);
L writeDP(dp + r.x.w, rd.l);
}
auto R65816::op_adjust_dpx_w(fp op) {
dp = readpc();
dp = readPC();
io2();
io();
rd.l = readdp(dp + regs.x.w + 0);
rd.h = readdp(dp + regs.x.w + 1);
rd.l = readDP(dp + r.x.w + 0);
rd.h = readDP(dp + r.x.w + 1);
io();
call(op);
writedp(dp + regs.x.w + 1, rd.h);
L writedp(dp + regs.x.w + 0, rd.l);
writeDP(dp + r.x.w + 1, rd.h);
L writeDP(dp + r.x.w + 0, rd.l);
}

View File

@ -1,195 +1,195 @@
auto R65816::op_write_addr_b(reg16_t& reg) {
aa.l = readpc();
aa.h = readpc();
L writedbr(aa.w, reg);
auto R65816::op_write_addr_b(reg16& reg) {
aa.l = readPC();
aa.h = readPC();
L writeDB(aa.w, reg);
}
auto R65816::op_write_addr_w(reg16_t& reg) {
aa.l = readpc();
aa.h = readpc();
writedbr(aa.w + 0, reg >> 0);
L writedbr(aa.w + 1, reg >> 8);
auto R65816::op_write_addr_w(reg16& reg) {
aa.l = readPC();
aa.h = readPC();
writeDB(aa.w + 0, reg >> 0);
L writeDB(aa.w + 1, reg >> 8);
}
auto R65816::op_write_addrr_b(reg16_t& reg, reg16_t& idx) {
aa.l = readpc();
aa.h = readpc();
auto R65816::op_write_addrr_b(reg16& reg, reg16& idx) {
aa.l = readPC();
aa.h = readPC();
io();
L writedbr(aa.w + idx, reg);
L writeDB(aa.w + idx, reg);
}
auto R65816::op_write_addrr_w(reg16_t& reg, reg16_t& idx) {
aa.l = readpc();
aa.h = readpc();
auto R65816::op_write_addrr_w(reg16& reg, reg16& idx) {
aa.l = readPC();
aa.h = readPC();
io();
writedbr(aa.w + idx + 0, reg >> 0);
L writedbr(aa.w + idx + 1, reg >> 8);
writeDB(aa.w + idx + 0, reg >> 0);
L writeDB(aa.w + idx + 1, reg >> 8);
}
auto R65816::op_write_longr_b(reg16_t& idx) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
L writelong(aa.d + idx, regs.a.l);
auto R65816::op_write_longr_b(reg16& idx) {
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
L writeLong(aa.d + idx, r.a.l);
}
auto R65816::op_write_longr_w(reg16_t& idx) {
aa.l = readpc();
aa.h = readpc();
aa.b = readpc();
writelong(aa.d + idx + 0, regs.a.l);
L writelong(aa.d + idx + 1, regs.a.h);
auto R65816::op_write_longr_w(reg16& idx) {
aa.l = readPC();
aa.h = readPC();
aa.b = readPC();
writeLong(aa.d + idx + 0, r.a.l);
L writeLong(aa.d + idx + 1, r.a.h);
}
auto R65816::op_write_dp_b(reg16_t& reg) {
dp = readpc();
auto R65816::op_write_dp_b(reg16& reg) {
dp = readPC();
io2();
L writedp(dp, reg);
L writeDP(dp, reg);
}
auto R65816::op_write_dp_w(reg16_t& reg) {
dp = readpc();
auto R65816::op_write_dp_w(reg16& reg) {
dp = readPC();
io2();
writedp(dp + 0, reg >> 0);
L writedp(dp + 1, reg >> 8);
writeDP(dp + 0, reg >> 0);
L writeDP(dp + 1, reg >> 8);
}
auto R65816::op_write_dpr_b(reg16_t& reg, reg16_t& idx) {
dp = readpc();
auto R65816::op_write_dpr_b(reg16& reg, reg16& idx) {
dp = readPC();
io2();
io();
L writedp(dp + idx, reg);
L writeDP(dp + idx, reg);
}
auto R65816::op_write_dpr_w(reg16_t& reg, reg16_t& idx) {
dp = readpc();
auto R65816::op_write_dpr_w(reg16& reg, reg16& idx) {
dp = readPC();
io2();
io();
writedp(dp + idx + 0, reg >> 0);
L writedp(dp + idx + 1, reg >> 8);
writeDP(dp + idx + 0, reg >> 0);
L writeDP(dp + idx + 1, reg >> 8);
}
auto R65816::op_sta_idp_b() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
L writedbr(aa.w, regs.a.l);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
L writeDB(aa.w, r.a.l);
}
auto R65816::op_sta_idp_w() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
writedbr(aa.w + 0, regs.a.l);
L writedbr(aa.w + 1, regs.a.h);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
writeDB(aa.w + 0, r.a.l);
L writeDB(aa.w + 1, r.a.h);
}
auto R65816::op_sta_ildp_b() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
L writelong(aa.d, regs.a.l);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
L writeLong(aa.d, r.a.l);
}
auto R65816::op_sta_ildp_w() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
writelong(aa.d + 0, regs.a.l);
L writelong(aa.d + 1, regs.a.h);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
writeLong(aa.d + 0, r.a.l);
L writeLong(aa.d + 1, r.a.h);
}
auto R65816::op_sta_idpx_b() {
dp = readpc();
dp = readPC();
io2();
io();
aa.l = readdp(dp + regs.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1);
L writedbr(aa.w, regs.a.l);
aa.l = readDP(dp + r.x.w + 0);
aa.h = readDP(dp + r.x.w + 1);
L writeDB(aa.w, r.a.l);
}
auto R65816::op_sta_idpx_w() {
dp = readpc();
dp = readPC();
io2();
io();
aa.l = readdp(dp + regs.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1);
writedbr(aa.w + 0, regs.a.l);
L writedbr(aa.w + 1, regs.a.h);
aa.l = readDP(dp + r.x.w + 0);
aa.h = readDP(dp + r.x.w + 1);
writeDB(aa.w + 0, r.a.l);
L writeDB(aa.w + 1, r.a.h);
}
auto R65816::op_sta_idpy_b() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
io();
L writedbr(aa.w + regs.y.w, regs.a.l);
L writeDB(aa.w + r.y.w, r.a.l);
}
auto R65816::op_sta_idpy_w() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.l = readDP(dp + 0);
aa.h = readDP(dp + 1);
io();
writedbr(aa.w + regs.y.w + 0, regs.a.l);
L writedbr(aa.w + regs.y.w + 1, regs.a.h);
writeDB(aa.w + r.y.w + 0, r.a.l);
L writeDB(aa.w + r.y.w + 1, r.a.h);
}
auto R65816::op_sta_ildpy_b() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
L writelong(aa.d + regs.y.w, regs.a.l);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
L writeLong(aa.d + r.y.w, r.a.l);
}
auto R65816::op_sta_ildpy_w() {
dp = readpc();
dp = readPC();
io2();
aa.l = readdp(dp + 0);
aa.h = readdp(dp + 1);
aa.b = readdp(dp + 2);
writelong(aa.d + regs.y.w + 0, regs.a.l);
L writelong(aa.d + regs.y.w + 1, regs.a.h);
aa.l = readDPn(dp + 0);
aa.h = readDPn(dp + 1);
aa.b = readDPn(dp + 2);
writeLong(aa.d + r.y.w + 0, r.a.l);
L writeLong(aa.d + r.y.w + 1, r.a.h);
}
auto R65816::op_sta_sr_b() {
sp = readpc();
sp = readPC();
io();
L writesp(sp, regs.a.l);
L writeSP(sp, r.a.l);
}
auto R65816::op_sta_sr_w() {
sp = readpc();
sp = readPC();
io();
writesp(sp + 0, regs.a.l);
L writesp(sp + 1, regs.a.h);
writeSP(sp + 0, r.a.l);
L writeSP(sp + 1, r.a.h);
}
auto R65816::op_sta_isry_b() {
sp = readpc();
sp = readPC();
io();
aa.l = readsp(sp + 0);
aa.h = readsp(sp + 1);
aa.l = readSP(sp + 0);
aa.h = readSP(sp + 1);
io();
L writedbr(aa.w + regs.y.w, regs.a.l);
L writeDB(aa.w + r.y.w, r.a.l);
}
auto R65816::op_sta_isry_w() {
sp = readpc();
sp = readPC();
io();
aa.l = readsp(sp + 0);
aa.h = readsp(sp + 1);
aa.l = readSP(sp + 0);
aa.h = readSP(sp + 1);
io();
writedbr(aa.w + regs.y.w + 0, regs.a.l);
L writedbr(aa.w + regs.y.w + 1, regs.a.h);
writeDB(aa.w + r.y.w + 0, r.a.l);
L writeDB(aa.w + r.y.w + 1, r.a.h);
}

View File

@ -7,6 +7,8 @@ namespace Processor {
#include "disassembler.cpp"
#include "serialization.cpp"
#define E if(r.e)
#define N if(!r.e)
#define L lastCycle();
#define call(op) (this->*op)()
@ -17,9 +19,6 @@ namespace Processor {
#include "opcode_misc.cpp"
#include "switch.cpp"
#undef L
#undef call
//immediate, 2-cycle opcodes with I/O cycle will become bus read
//when an IRQ is to be triggered immediately after opcode completion.
//this affects the following opcodes:
@ -31,43 +30,47 @@ namespace Processor {
auto R65816::ioIRQ() -> void {
if(interruptPending()) {
//modify I/O cycle to bus read cycle, do not increment PC
read(regs.pc.d);
read(r.pc.d);
} else {
io();
}
}
auto R65816::io2() -> void {
if(regs.d.l != 0x00) {
if(r.d.l != 0x00) {
io();
}
}
auto R65816::io4(uint16 x, uint16 y) -> void {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
if(!r.p.x || (x & 0xff00) != (y & 0xff00)) {
io();
}
}
auto R65816::io6(uint16 addr) -> void {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
if(r.e && (r.pc.w & 0xff00) != (addr & 0xff00)) {
io();
}
}
auto R65816::interrupt() -> void {
read(regs.pc.d);
read(r.pc.d);
io();
if(!regs.e) writestack(regs.pc.b);
writestack(regs.pc.h);
writestack(regs.pc.l);
writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = read(regs.vector + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = read(regs.vector + 1);
regs.pc.w = rd.w;
N writeSP(r.pc.b);
writeSP(r.pc.h);
writeSP(r.pc.l);
writeSP(r.e ? (r.p & ~0x10) : r.p);
r.pc.l = read(r.vector + 0);
r.p.i = 1;
r.p.d = 0;
r.pc.h = read(r.vector + 1);
r.pc.b = 0x00;
}
#undef E
#undef N
#undef L
#undef call
}

View File

@ -20,7 +20,7 @@ struct R65816 {
virtual auto interruptPending() const -> bool = 0;
virtual auto interrupt() -> void;
virtual auto disassemblerRead(uint24 addr) -> uint8 { return 0u; }
virtual auto disassemblerRead(uint24 addr) -> uint8 { return 0; }
//r65816.cpp
alwaysinline auto ioIRQ() -> void;
@ -88,8 +88,8 @@ struct R65816 {
auto op_read_longx_w(fp);
auto op_read_dp_b(fp);
auto op_read_dp_w(fp);
auto op_read_dpr_b(fp, reg16_t&);
auto op_read_dpr_w(fp, reg16_t&);
auto op_read_dpr_b(fp, reg16&);
auto op_read_dpr_w(fp, reg16&);
auto op_read_idp_b(fp);
auto op_read_idp_w(fp);
auto op_read_idpx_b(fp);
@ -106,16 +106,16 @@ struct R65816 {
auto op_read_isry_w(fp);
//opcode_write.cpp
auto op_write_addr_b(reg16_t&);
auto op_write_addr_w(reg16_t&);
auto op_write_addrr_b(reg16_t&, reg16_t&);
auto op_write_addrr_w(reg16_t&, reg16_t&);
auto op_write_longr_b(reg16_t&);
auto op_write_longr_w(reg16_t&);
auto op_write_dp_b(reg16_t&);
auto op_write_dp_w(reg16_t&);
auto op_write_dpr_b(reg16_t&, reg16_t&);
auto op_write_dpr_w(reg16_t&, reg16_t&);
auto op_write_addr_b(reg16&);
auto op_write_addr_w(reg16&);
auto op_write_addrr_b(reg16&, reg16&);
auto op_write_addrr_w(reg16&, reg16&);
auto op_write_longr_b(reg16&);
auto op_write_longr_w(reg16&);
auto op_write_dp_b(reg16&);
auto op_write_dp_w(reg16&);
auto op_write_dpr_b(reg16&, reg16&);
auto op_write_dpr_w(reg16&, reg16&);
auto op_sta_idp_b();
auto op_sta_idp_w();
auto op_sta_ildp_b();
@ -132,8 +132,8 @@ struct R65816 {
auto op_sta_isry_w();
//opcode_rmw.cpp
auto op_adjust_imm_b(reg16_t&, signed);
auto op_adjust_imm_w(reg16_t&, signed);
auto op_adjust_imm_b(reg16&, int);
auto op_adjust_imm_w(reg16&, int);
auto op_asl_imm_b();
auto op_asl_imm_w();
auto op_lsr_imm_b();
@ -161,58 +161,44 @@ struct R65816 {
auto op_jmp_iaddrx();
auto op_jmp_iladdr();
auto op_jsr_addr();
auto op_jsr_long_e();
auto op_jsr_long_n();
auto op_jsr_iaddrx_e();
auto op_jsr_iaddrx_n();
auto op_rti_e();
auto op_rti_n();
auto op_jsr_long();
auto op_jsr_iaddrx();
auto op_rti();
auto op_rts();
auto op_rtl_e();
auto op_rtl_n();
auto op_rtl();
//opcode_misc.cpp
auto op_nop();
auto op_wdm();
auto op_xba();
auto op_move_b(signed adjust);
auto op_move_w(signed adjust);
auto op_interrupt_e(uint16);
auto op_interrupt_n(uint16);
auto op_move_b(int adjust);
auto op_move_w(int adjust);
auto op_interrupt(uint16);
auto op_stp();
auto op_wai();
auto op_xce();
auto op_flag(bool& flag, bool value);
auto op_pflag_e(bool);
auto op_pflag_n(bool);
auto op_transfer_b(reg16_t&, reg16_t&);
auto op_transfer_w(reg16_t&, reg16_t&);
auto op_tcs_e();
auto op_tcs_n();
auto op_pflag(bool);
auto op_transfer_b(reg16&, reg16&);
auto op_transfer_w(reg16&, reg16&);
auto op_tcs();
auto op_tsx_b();
auto op_tsx_w();
auto op_txs_e();
auto op_txs_n();
auto op_push_b(reg16_t&);
auto op_push_w(reg16_t&);
auto op_phd_e();
auto op_phd_n();
auto op_txs();
auto op_push_b(reg16&);
auto op_push_w(reg16&);
auto op_phd();
auto op_phb();
auto op_phk();
auto op_php();
auto op_pull_b(reg16_t&);
auto op_pull_w(reg16_t&);
auto op_pld_e();
auto op_pld_n();
auto op_pull_b(reg16&);
auto op_pull_w(reg16&);
auto op_pld();
auto op_plb();
auto op_plp_e();
auto op_plp_n();
auto op_pea_e();
auto op_pea_n();
auto op_pei_e();
auto op_pei_n();
auto op_per_e();
auto op_per_n();
auto op_plp();
auto op_pea();
auto op_pei();
auto op_per();
//switch.cpp
auto instruction() -> void;
@ -220,8 +206,8 @@ struct R65816 {
//serialization.cpp
auto serialize(serializer&) -> void;
regs_t regs;
reg24_t aa, rd;
Registers r;
reg24 aa, rd;
uint8 sp, dp;
};

View File

@ -1,4 +1,4 @@
struct flag_t {
struct Flags {
bool n{0};
bool v{0};
bool m{0};
@ -8,68 +8,68 @@ struct flag_t {
bool z{0};
bool c{0};
inline operator unsigned() const {
inline operator uint() const {
return (n << 7) + (v << 6) + (m << 5) + (x << 4)
+ (d << 3) + (i << 2) + (z << 1) + (c << 0);
}
inline auto operator=(uint8 data) -> unsigned {
inline auto operator=(uint8 data) -> uint {
n = data & 0x80; v = data & 0x40; m = data & 0x20; x = data & 0x10;
d = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01;
return data;
}
};
struct reg16_t {
struct reg16 {
union {
uint16_t w = 0;
struct { uint8_t order_lsb2(l, h); };
};
inline operator unsigned() const { return w; }
inline auto operator = (unsigned i) -> unsigned { return w = i; }
inline auto operator |= (unsigned i) -> unsigned { return w |= i; }
inline auto operator ^= (unsigned i) -> unsigned { return w ^= i; }
inline auto operator &= (unsigned i) -> unsigned { return w &= i; }
inline auto operator <<= (unsigned i) -> unsigned { return w <<= i; }
inline auto operator >>= (unsigned i) -> unsigned { return w >>= i; }
inline auto operator += (unsigned i) -> unsigned { return w += i; }
inline auto operator -= (unsigned i) -> unsigned { return w -= i; }
inline auto operator *= (unsigned i) -> unsigned { return w *= i; }
inline auto operator /= (unsigned i) -> unsigned { return w /= i; }
inline auto operator %= (unsigned i) -> unsigned { return w %= i; }
inline operator uint() const { return w; }
inline auto operator =(uint i) -> uint { return w = i; }
inline auto operator |=(uint i) -> uint { return w |= i; }
inline auto operator ^=(uint i) -> uint { return w ^= i; }
inline auto operator &=(uint i) -> uint { return w &= i; }
inline auto operator<<=(uint i) -> uint { return w <<= i; }
inline auto operator>>=(uint i) -> uint { return w >>= i; }
inline auto operator +=(uint i) -> uint { return w += i; }
inline auto operator -=(uint i) -> uint { return w -= i; }
inline auto operator *=(uint i) -> uint { return w *= i; }
inline auto operator /=(uint i) -> uint { return w /= i; }
inline auto operator %=(uint i) -> uint { return w %= i; }
};
struct reg24_t {
struct reg24 {
union {
uint32_t d = 0;
struct { uint16_t order_lsb2(w, wh); };
struct { uint8_t order_lsb4(l, h, b, bh); };
};
inline operator unsigned() const { return d; }
inline auto operator = (unsigned i) -> unsigned { return d = uclip<24>(i); }
inline auto operator |= (unsigned i) -> unsigned { return d = uclip<24>(d | i); }
inline auto operator ^= (unsigned i) -> unsigned { return d = uclip<24>(d ^ i); }
inline auto operator &= (unsigned i) -> unsigned { return d = uclip<24>(d & i); }
inline auto operator <<= (unsigned i) -> unsigned { return d = uclip<24>(d << i); }
inline auto operator >>= (unsigned i) -> unsigned { return d = uclip<24>(d >> i); }
inline auto operator += (unsigned i) -> unsigned { return d = uclip<24>(d + i); }
inline auto operator -= (unsigned i) -> unsigned { return d = uclip<24>(d - i); }
inline auto operator *= (unsigned i) -> unsigned { return d = uclip<24>(d * i); }
inline auto operator /= (unsigned i) -> unsigned { return d = uclip<24>(d / i); }
inline auto operator %= (unsigned i) -> unsigned { return d = uclip<24>(d % i); }
inline operator uint() const { return d; }
inline auto operator =(uint i) -> uint { return d = uclip<24>(i); }
inline auto operator |=(uint i) -> uint { return d = uclip<24>(d | i); }
inline auto operator ^=(uint i) -> uint { return d = uclip<24>(d ^ i); }
inline auto operator &=(uint i) -> uint { return d = uclip<24>(d & i); }
inline auto operator<<=(uint i) -> uint { return d = uclip<24>(d << i); }
inline auto operator>>=(uint i) -> uint { return d = uclip<24>(d >> i); }
inline auto operator +=(uint i) -> uint { return d = uclip<24>(d + i); }
inline auto operator -=(uint i) -> uint { return d = uclip<24>(d - i); }
inline auto operator *=(uint i) -> uint { return d = uclip<24>(d * i); }
inline auto operator /=(uint i) -> uint { return d = uclip<24>(d / i); }
inline auto operator %=(uint i) -> uint { return d = uclip<24>(d % i); }
};
struct regs_t {
reg24_t pc;
reg16_t a;
reg16_t x;
reg16_t y;
reg16_t z; //pseudo-register (zero register)
reg16_t s;
reg16_t d;
flag_t p;
struct Registers {
reg24 pc;
reg16 a;
reg16 x;
reg16 y;
reg16 z; //pseudo-register (zero register)
reg16 s;
reg16 d;
Flags p;
uint8 db{0};
bool e{0};

View File

@ -1,28 +1,28 @@
auto R65816::serialize(serializer& s) -> void {
s.integer(regs.pc.d);
s.integer(r.pc.d);
s.integer(regs.a.w);
s.integer(regs.x.w);
s.integer(regs.y.w);
s.integer(regs.z.w);
s.integer(regs.s.w);
s.integer(regs.d.w);
s.integer(r.a.w);
s.integer(r.x.w);
s.integer(r.y.w);
s.integer(r.z.w);
s.integer(r.s.w);
s.integer(r.d.w);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.m);
s.integer(regs.p.x);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(r.p.n);
s.integer(r.p.v);
s.integer(r.p.m);
s.integer(r.p.x);
s.integer(r.p.d);
s.integer(r.p.i);
s.integer(r.p.z);
s.integer(r.p.c);
s.integer(regs.db);
s.integer(regs.e);
s.integer(regs.irq);
s.integer(regs.wai);
s.integer(regs.mdr);
s.integer(regs.vector);
s.integer(r.db);
s.integer(r.e);
s.integer(r.irq);
s.integer(r.wai);
s.integer(r.mdr);
s.integer(r.vector);
s.integer(aa.d);
s.integer(rd.d);

View File

@ -1,24 +1,22 @@
auto R65816::instruction() -> void {
#define opA( n, o ) case n: return op_##o();
#define opAI( n, o, i ) case n: return op_##o(i);
#define opAII(n, o, i, j) case n: return op_##o(i, j);
#define opE( n, o ) case n: return regs.e ? op_##o##_e() : op_##o##_n();
#define opEI( n, o, i ) case n: return regs.e ? op_##o##_e(i) : op_##o##_n(i);
#define opEII(n, o, i, j) case n: return regs.e ? op_##o##_e(i) : op_##o##_n(j);
#define opM( n, o ) case n: return regs.p.m ? op_##o##_b() : op_##o##_w();
#define opMF( n, o, f ) case n: return regs.p.m ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
#define opMFI(n, o, f, i) case n: return regs.p.m ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
#define opMI( n, o, i ) case n: return regs.p.m ? op_##o##_b(i) : op_##o##_w(i);
#define opMII(n, o, i, j) case n: return regs.p.m ? op_##o##_b(i, j) : op_##o##_w(i, j);
#define opX( n, o) case n: return regs.p.x ? op_##o##_b() : op_##o##_w();
#define opXF( n, o, f ) case n: return regs.p.x ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
#define opXFI(n, o, f, i) case n: return regs.p.x ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
#define opXI( n, o, i ) case n: return regs.p.x ? op_##o##_b(i) : op_##o##_w(i);
#define opXII(n, o, i, j) case n: return regs.p.x ? op_##o##_b(i, j) : op_##o##_w(i, j);
#define opM( n, o ) case n: return r.p.m ? op_##o##_b() : op_##o##_w();
#define opMF( n, o, f ) case n: return r.p.m ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
#define opMFI(n, o, f, i) case n: return r.p.m ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
#define opMI( n, o, i ) case n: return r.p.m ? op_##o##_b(i) : op_##o##_w(i);
#define opMII(n, o, i, j) case n: return r.p.m ? op_##o##_b(i, j) : op_##o##_w(i, j);
#define opX( n, o) case n: return r.p.x ? op_##o##_b() : op_##o##_w();
#define opXF( n, o, f ) case n: return r.p.x ? op_##o##_b(&R65816::op_##f##_b) : op_##o##_w(&R65816::op_##f##_w);
#define opXFI(n, o, f, i) case n: return r.p.x ? op_##o##_b(&R65816::op_##f##_b, i) : op_##o##_w(&R65816::op_##f##_w, i);
#define opXI( n, o, i ) case n: return r.p.x ? op_##o##_b(i) : op_##o##_w(i);
#define opXII(n, o, i, j) case n: return r.p.x ? op_##o##_b(i, j) : op_##o##_w(i, j);
switch(readpc()) {
opEII(0x00, interrupt, 0xfffe, 0xffe6)
switch(readPC()) {
opAI (0x00, interrupt, r.e ? 0xffe6 : 0xfffe)
opMF (0x01, read_idpx, ora)
opEII(0x02, interrupt, 0xfff4, 0xffe4)
opAI (0x02, interrupt, r.e ? 0xffe4 : 0xfff4)
opMF (0x03, read_sr, ora)
opMF (0x04, adjust_dp, tsb)
opMF (0x05, read_dp, ora)
@ -27,60 +25,60 @@ auto R65816::instruction() -> void {
opA (0x08, php)
opMF (0x09, read_const, ora)
opM (0x0a, asl_imm)
opE (0x0b, phd)
opA (0x0b, phd)
opMF (0x0c, adjust_addr, tsb)
opMF (0x0d, read_addr, ora)
opMF (0x0e, adjust_addr, asl)
opMF (0x0f, read_long, ora)
opAII(0x10, branch, regs.p.n, 0)
opAII(0x10, branch, r.p.n, 0)
opMF (0x11, read_idpy, ora)
opMF (0x12, read_idp, ora)
opMF (0x13, read_isry, ora)
opMF (0x14, adjust_dp, trb)
opMFI(0x15, read_dpr, ora, regs.x)
opMFI(0x15, read_dpr, ora, r.x)
opMF (0x16, adjust_dpx, asl)
opMF (0x17, read_ildpy, ora)
opAII(0x18, flag, regs.p.c, 0)
opAII(0x18, flag, r.p.c, 0)
opMF (0x19, read_addry, ora)
opMII(0x1a, adjust_imm, regs.a, +1)
opE (0x1b, tcs)
opMII(0x1a, adjust_imm, r.a, +1)
opA (0x1b, tcs)
opMF (0x1c, adjust_addr, trb)
opMF (0x1d, read_addrx, ora)
opMF (0x1e, adjust_addrx, asl)
opMF (0x1f, read_longx, ora)
opA (0x20, jsr_addr)
opMF (0x21, read_idpx, and)
opE (0x22, jsr_long)
opA (0x22, jsr_long)
opMF (0x23, read_sr, and)
opMF (0x24, read_dp, bit)
opMF (0x25, read_dp, and)
opMF (0x26, adjust_dp, rol)
opMF (0x27, read_ildp, and)
opE (0x28, plp)
opA (0x28, plp)
opMF (0x29, read_const, and)
opM (0x2a, rol_imm)
opE (0x2b, pld)
opA (0x2b, pld)
opMF (0x2c, read_addr, bit)
opMF (0x2d, read_addr, and)
opMF (0x2e, adjust_addr, rol)
opMF (0x2f, read_long, and)
opAII(0x30, branch, regs.p.n, 1)
opAII(0x30, branch, r.p.n, 1)
opMF (0x31, read_idpy, and)
opMF (0x32, read_idp, and)
opMF (0x33, read_isry, and)
opMFI(0x34, read_dpr, bit, regs.x)
opMFI(0x35, read_dpr, and, regs.x)
opMFI(0x34, read_dpr, bit, r.x)
opMFI(0x35, read_dpr, and, r.x)
opMF (0x36, adjust_dpx, rol)
opMF (0x37, read_ildpy, and)
opAII(0x38, flag, regs.p.c, 1)
opAII(0x38, flag, r.p.c, 1)
opMF (0x39, read_addry, and)
opMII(0x3a, adjust_imm, regs.a, -1)
opAII(0x3b, transfer_w, regs.s, regs.a)
opMII(0x3a, adjust_imm, r.a, -1)
opAII(0x3b, transfer_w, r.s, r.a)
opMF (0x3c, read_addrx, bit)
opMF (0x3d, read_addrx, and)
opMF (0x3e, adjust_addrx, rol)
opMF (0x3f, read_longx, and)
opE (0x40, rti)
opA (0x40, rti)
opMF (0x41, read_idpx, eor)
opA (0x42, wdm)
opMF (0x43, read_sr, eor)
@ -88,7 +86,7 @@ auto R65816::instruction() -> void {
opMF (0x45, read_dp, eor)
opMF (0x46, adjust_dp, lsr)
opMF (0x47, read_ildp, eor)
opMI (0x48, push, regs.a)
opMI (0x48, push, r.a)
opMF (0x49, read_const, eor)
opM (0x4a, lsr_imm)
opA (0x4b, phk)
@ -96,50 +94,50 @@ auto R65816::instruction() -> void {
opMF (0x4d, read_addr, eor)
opMF (0x4e, adjust_addr, lsr)
opMF (0x4f, read_long, eor)
opAII(0x50, branch, regs.p.v, 0)
opAII(0x50, branch, r.p.v, 0)
opMF (0x51, read_idpy, eor)
opMF (0x52, read_idp, eor)
opMF (0x53, read_isry, eor)
opXI (0x54, move, +1)
opMFI(0x55, read_dpr, eor, regs.x)
opMFI(0x55, read_dpr, eor, r.x)
opMF (0x56, adjust_dpx, lsr)
opMF (0x57, read_ildpy, eor)
opAII(0x58, flag, regs.p.i, 0)
opAII(0x58, flag, r.p.i, 0)
opMF (0x59, read_addry, eor)
opXI (0x5a, push, regs.y)
opAII(0x5b, transfer_w, regs.a, regs.d)
opXI (0x5a, push, r.y)
opAII(0x5b, transfer_w, r.a, r.d)
opA (0x5c, jmp_long)
opMF (0x5d, read_addrx, eor)
opMF (0x5e, adjust_addrx, lsr)
opMF (0x5f, read_longx, eor)
opA (0x60, rts)
opMF (0x61, read_idpx, adc)
opE (0x62, per)
opA (0x62, per)
opMF (0x63, read_sr, adc)
opMI (0x64, write_dp, regs.z)
opMI (0x64, write_dp, r.z)
opMF (0x65, read_dp, adc)
opMF (0x66, adjust_dp, ror)
opMF (0x67, read_ildp, adc)
opMI (0x68, pull, regs.a)
opMI (0x68, pull, r.a)
opMF (0x69, read_const, adc)
opM (0x6a, ror_imm)
opE (0x6b, rtl)
opA (0x6b, rtl)
opA (0x6c, jmp_iaddr)
opMF (0x6d, read_addr, adc)
opMF (0x6e, adjust_addr, ror)
opMF (0x6f, read_long, adc)
opAII(0x70, branch, regs.p.v, 1)
opAII(0x70, branch, r.p.v, 1)
opMF (0x71, read_idpy, adc)
opMF (0x72, read_idp, adc)
opMF (0x73, read_isry, adc)
opMII(0x74, write_dpr, regs.z, regs.x)
opMFI(0x75, read_dpr, adc, regs.x)
opMII(0x74, write_dpr, r.z, r.x)
opMFI(0x75, read_dpr, adc, r.x)
opMF (0x76, adjust_dpx, ror)
opMF (0x77, read_ildpy, adc)
opAII(0x78, flag, regs.p.i, 1)
opAII(0x78, flag, r.p.i, 1)
opMF (0x79, read_addry, adc)
opXI (0x7a, pull, regs.y)
opAII(0x7b, transfer_w, regs.d, regs.a)
opXI (0x7a, pull, r.y)
opAII(0x7b, transfer_w, r.d, r.a)
opA (0x7c, jmp_iaddrx)
opMF (0x7d, read_addrx, adc)
opMF (0x7e, adjust_addrx, ror)
@ -148,34 +146,34 @@ auto R65816::instruction() -> void {
opM (0x81, sta_idpx)
opA (0x82, brl)
opM (0x83, sta_sr)
opXI (0x84, write_dp, regs.y)
opMI (0x85, write_dp, regs.a)
opXI (0x86, write_dp, regs.x)
opXI (0x84, write_dp, r.y)
opMI (0x85, write_dp, r.a)
opXI (0x86, write_dp, r.x)
opM (0x87, sta_ildp)
opXII(0x88, adjust_imm, regs.y, -1)
opXII(0x88, adjust_imm, r.y, -1)
opM (0x89, read_bit_const)
opMII(0x8a, transfer, regs.x, regs.a)
opMII(0x8a, transfer, r.x, r.a)
opA (0x8b, phb)
opXI (0x8c, write_addr, regs.y)
opMI (0x8d, write_addr, regs.a)
opXI (0x8e, write_addr, regs.x)
opMI (0x8f, write_longr, regs.z)
opAII(0x90, branch, regs.p.c, 0)
opXI (0x8c, write_addr, r.y)
opMI (0x8d, write_addr, r.a)
opXI (0x8e, write_addr, r.x)
opMI (0x8f, write_longr, r.z)
opAII(0x90, branch, r.p.c, 0)
opM (0x91, sta_idpy)
opM (0x92, sta_idp)
opM (0x93, sta_isry)
opXII(0x94, write_dpr, regs.y, regs.x)
opMII(0x95, write_dpr, regs.a, regs.x)
opXII(0x96, write_dpr, regs.x, regs.y)
opXII(0x94, write_dpr, r.y, r.x)
opMII(0x95, write_dpr, r.a, r.x)
opXII(0x96, write_dpr, r.x, r.y)
opM (0x97, sta_ildpy)
opMII(0x98, transfer, regs.y, regs.a)
opMII(0x99, write_addrr, regs.a, regs.y)
opE (0x9a, txs)
opXII(0x9b, transfer, regs.x, regs.y)
opMI (0x9c, write_addr, regs.z)
opMII(0x9d, write_addrr, regs.a, regs.x)
opMII(0x9e, write_addrr, regs.z, regs.x)
opMI (0x9f, write_longr, regs.x)
opMII(0x98, transfer, r.y, r.a)
opMII(0x99, write_addrr, r.a, r.y)
opA (0x9a, txs)
opXII(0x9b, transfer, r.x, r.y)
opMI (0x9c, write_addr, r.z)
opMII(0x9d, write_addrr, r.a, r.x)
opMII(0x9e, write_addrr, r.z, r.x)
opMI (0x9f, write_longr, r.x)
opXF (0xa0, read_const, ldy)
opMF (0xa1, read_idpx, lda)
opXF (0xa2, read_const, ldx)
@ -184,57 +182,57 @@ auto R65816::instruction() -> void {
opMF (0xa5, read_dp, lda)
opXF (0xa6, read_dp, ldx)
opMF (0xa7, read_ildp, lda)
opXII(0xa8, transfer, regs.a, regs.y)
opXII(0xa8, transfer, r.a, r.y)
opMF (0xa9, read_const, lda)
opXII(0xaa, transfer, regs.a, regs.x)
opXII(0xaa, transfer, r.a, r.x)
opA (0xab, plb)
opXF (0xac, read_addr, ldy)
opMF (0xad, read_addr, lda)
opXF (0xae, read_addr, ldx)
opMF (0xaf, read_long, lda)
opAII(0xb0, branch, regs.p.c, 1)
opAII(0xb0, branch, r.p.c, 1)
opMF (0xb1, read_idpy, lda)
opMF (0xb2, read_idp, lda)
opMF (0xb3, read_isry, lda)
opXFI(0xb4, read_dpr, ldy, regs.x)
opMFI(0xb5, read_dpr, lda, regs.x)
opXFI(0xb6, read_dpr, ldx, regs.y)
opXFI(0xb4, read_dpr, ldy, r.x)
opMFI(0xb5, read_dpr, lda, r.x)
opXFI(0xb6, read_dpr, ldx, r.y)
opMF (0xb7, read_ildpy, lda)
opAII(0xb8, flag, regs.p.v, 0)
opAII(0xb8, flag, r.p.v, 0)
opMF (0xb9, read_addry, lda)
opX (0xba, tsx)
opXII(0xbb, transfer, regs.y, regs.x)
opXII(0xbb, transfer, r.y, r.x)
opXF (0xbc, read_addrx, ldy)
opMF (0xbd, read_addrx, lda)
opXF (0xbe, read_addry, ldx)
opMF (0xbf, read_longx, lda)
opXF (0xc0, read_const, cpy)
opMF (0xc1, read_idpx, cmp)
opEI (0xc2, pflag, 0)
opAI (0xc2, pflag, 0)
opMF (0xc3, read_sr, cmp)
opXF (0xc4, read_dp, cpy)
opMF (0xc5, read_dp, cmp)
opMF (0xc6, adjust_dp, dec)
opMF (0xc7, read_ildp, cmp)
opXII(0xc8, adjust_imm, regs.y, +1)
opXII(0xc8, adjust_imm, r.y, +1)
opMF (0xc9, read_const, cmp)
opXII(0xca, adjust_imm, regs.x, -1)
opXII(0xca, adjust_imm, r.x, -1)
opA (0xcb, wai)
opXF (0xcc, read_addr, cpy)
opMF (0xcd, read_addr, cmp)
opMF (0xce, adjust_addr, dec)
opMF (0xcf, read_long, cmp)
opAII(0xd0, branch, regs.p.z, 0)
opAII(0xd0, branch, r.p.z, 0)
opMF (0xd1, read_idpy, cmp)
opMF (0xd2, read_idp, cmp)
opMF (0xd3, read_isry, cmp)
opE (0xd4, pei)
opMFI(0xd5, read_dpr, cmp, regs.x)
opA (0xd4, pei)
opMFI(0xd5, read_dpr, cmp, r.x)
opMF (0xd6, adjust_dpx, dec)
opMF (0xd7, read_ildpy, cmp)
opAII(0xd8, flag, regs.p.d, 0)
opAII(0xd8, flag, r.p.d, 0)
opMF (0xd9, read_addry, cmp)
opXI (0xda, push, regs.x)
opXI (0xda, push, r.x)
opA (0xdb, stp)
opA (0xdc, jmp_iladdr)
opMF (0xdd, read_addrx, cmp)
@ -242,13 +240,13 @@ auto R65816::instruction() -> void {
opMF (0xdf, read_longx, cmp)
opXF (0xe0, read_const, cpx)
opMF (0xe1, read_idpx, sbc)
opEI (0xe2, pflag, 1)
opAI (0xe2, pflag, 1)
opMF (0xe3, read_sr, sbc)
opXF (0xe4, read_dp, cpx)
opMF (0xe5, read_dp, sbc)
opMF (0xe6, adjust_dp, inc)
opMF (0xe7, read_ildp, sbc)
opXII(0xe8, adjust_imm, regs.x, +1)
opXII(0xe8, adjust_imm, r.x, +1)
opMF (0xe9, read_const, sbc)
opA (0xea, nop)
opA (0xeb, xba)
@ -256,29 +254,27 @@ auto R65816::instruction() -> void {
opMF (0xed, read_addr, sbc)
opMF (0xee, adjust_addr, inc)
opMF (0xef, read_long, sbc)
opAII(0xf0, branch, regs.p.z, 1)
opAII(0xf0, branch, r.p.z, 1)
opMF (0xf1, read_idpy, sbc)
opMF (0xf2, read_idp, sbc)
opMF (0xf3, read_isry, sbc)
opE (0xf4, pea)
opMFI(0xf5, read_dpr, sbc, regs.x)
opA (0xf4, pea)
opMFI(0xf5, read_dpr, sbc, r.x)
opMF (0xf6, adjust_dpx, inc)
opMF (0xf7, read_ildpy, sbc)
opAII(0xf8, flag, regs.p.d, 1)
opAII(0xf8, flag, r.p.d, 1)
opMF (0xf9, read_addry, sbc)
opXI (0xfa, pull, regs.x)
opXI (0xfa, pull, r.x)
opA (0xfb, xce)
opE (0xfc, jsr_iaddrx)
opA (0xfc, jsr_iaddrx)
opMF (0xfd, read_addrx, sbc)
opMF (0xfe, adjust_addrx, inc)
opMF (0xff, read_longx, sbc)
}
#undef opA
#undef opAI
#undef opAII
#undef opE
#undef opEI
#undef opEII
#undef opM
#undef opMF
#undef opMFI

View File

@ -1,6 +1,6 @@
struct Gamepad : Controller {
enum : uint {
B, Y, Select, Start, Up, Down, Left, Right, A, X, L, R,
Up, Down, Left, Right, B, A, Y, X, L, R, Select, Start,
};
Gamepad(bool port);

View File

@ -25,7 +25,7 @@ auto ICD2::main() -> void {
GameBoy::system._clocksExecuted = 0;
} else { //DMG halted
stream->sample(0, 0);
step(1);
step(2); //two clocks per audio sample
}
synchronizeCPU();
}
@ -54,7 +54,7 @@ auto ICD2::power() -> void {
auto ICD2::reset(bool soft) -> void {
create(ICD2::Enter, cpu.frequency / 5);
if(!soft) stream = Emulator::audio.createStream(2, 4194304.0 / 2.0);
if(!soft) stream = Emulator::audio.createStream(2, cpu.frequency / 10);
r6003 = 0x00;
r6004 = 0xff;

View File

@ -4,7 +4,7 @@
auto SA1::dma_normal() -> void {
while(mmio.dtc--) {
uint8 data = regs.mdr;
uint8 data = r.mdr;
uint32 dsa = mmio.dsa++;
uint32 dda = mmio.dda++;
@ -61,7 +61,7 @@ auto SA1::dma_cc1() -> void {
mmio.chdma_irqfl = true;
if(mmio.chdma_irqen) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
cpu.r.irq = 1;
}
}

View File

@ -115,13 +115,13 @@ auto SA1::io() -> void {
auto SA1::read(uint24 addr) -> uint8 {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr, regs.mdr);
return bus_read(addr, r.mdr);
}
auto SA1::write(uint24 addr, uint8 data) -> void {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
bus_write(addr, regs.mdr = data);
bus_write(addr, r.mdr = data);
}
//note: addresses are translated prior to invoking this function:

View File

@ -2,8 +2,8 @@
auto SA1::mmio_w2200(uint8 data) -> void {
if(mmio.sa1_resb && !(data & 0x80)) {
//reset SA-1 CPU
regs.pc.w = mmio.crv;
regs.pc.b = 0x00;
r.pc.w = mmio.crv;
r.pc.b = 0x00;
}
mmio.sa1_irq = (data & 0x80);
@ -28,14 +28,14 @@ auto SA1::mmio_w2201(uint8 data) -> void {
if(!mmio.cpu_irqen && (data & 0x80)) {
if(mmio.cpu_irqfl) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
cpu.r.irq = 1;
}
}
if(!mmio.chdma_irqen && (data & 0x20)) {
if(mmio.chdma_irqfl) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
cpu.r.irq = 1;
}
}
@ -51,7 +51,7 @@ auto SA1::mmio_w2202(uint8 data) -> void {
if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false;
if(mmio.chdma_irqcl) mmio.chdma_irqfl = false;
if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0;
if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.r.irq = 0;
}
//(CRV) SA-1 reset vector
@ -77,7 +77,7 @@ auto SA1::mmio_w2209(uint8 data) -> void {
mmio.cpu_irqfl = true;
if(mmio.cpu_irqen) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
cpu.r.irq = 1;
}
}
}

View File

@ -32,41 +32,41 @@ auto SA1::main() -> void {
}
auto SA1::interrupt() -> void {
read(regs.pc.d);
read(r.pc.d);
io();
if(!regs.e) writestack(regs.pc.b);
writestack(regs.pc.h);
writestack(regs.pc.l);
writestack(regs.e ? (regs.p & ~0x10) : regs.p);
regs.pc.w = regs.vector;
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
if(!r.e) writeSP(r.pc.b);
writeSP(r.pc.h);
writeSP(r.pc.l);
writeSP(r.e ? (r.p & ~0x10) : r.p);
r.pc.w = r.vector;
r.pc.b = 0x00;
r.p.i = 1;
r.p.d = 0;
}
auto SA1::lastCycle() -> void {
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
status.interrupt_pending = true;
regs.vector = mmio.cnv;
r.vector = mmio.cnv;
mmio.sa1_nmifl = true;
mmio.sa1_nmicl = 1;
regs.wai = false;
} else if(!regs.p.i) {
r.wai = false;
} else if(!r.p.i) {
if(mmio.timer_irqen && !mmio.timer_irqcl) {
status.interrupt_pending = true;
regs.vector = mmio.civ;
r.vector = mmio.civ;
mmio.timer_irqfl = true;
regs.wai = false;
r.wai = false;
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
status.interrupt_pending = true;
regs.vector = mmio.civ;
r.vector = mmio.civ;
mmio.dma_irqfl = true;
regs.wai = false;
r.wai = false;
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
status.interrupt_pending = true;
regs.vector = mmio.civ;
r.vector = mmio.civ;
mmio.sa1_irqfl = true;
regs.wai = false;
r.wai = false;
}
}
}
@ -124,8 +124,10 @@ auto SA1::unload() -> void {
}
auto SA1::power() -> void {
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
r.a = 0x0000;
r.x = 0x0000;
r.y = 0x0000;
r.s = 0x01ff;
}
auto SA1::reset() -> void {
@ -136,17 +138,17 @@ auto SA1::reset() -> void {
iram.write(addr, 0x00);
}
regs.pc.d = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
regs.vector = 0x0000;
r.pc.d = 0x000000;
r.x.h = 0x00;
r.y.h = 0x00;
r.s.h = 0x01;
r.d = 0x0000;
r.db = 0x00;
r.p = 0x34;
r.e = 1;
r.mdr = 0x00;
r.wai = false;
r.vector = 0x0000;
status.tick_counter = 0;

View File

@ -1,5 +1,5 @@
auto SuperFX::stop() -> void {
cpu.regs.irq = 1;
cpu.r.irq = 1;
}
auto SuperFX::color(uint8 source) -> uint8 {

View File

@ -18,7 +18,7 @@ auto SuperFX::mmio_read(uint24 addr, uint8) -> uint8 {
case 0x3031: {
uint8 r = regs.sfr >> 8;
regs.sfr.irq = 0;
cpu.regs.irq = 0;
cpu.r.irq = 0;
return r;
}

View File

@ -60,28 +60,28 @@ auto CPU::main() -> void {
status.interrupt_pending = false;
if(status.nmi_pending) {
status.nmi_pending = false;
regs.vector = !regs.e ? 0xffea : 0xfffa;
r.vector = r.e ? 0xfffa : 0xffea;
interrupt();
debugger.op_nmi();
} else if(status.irq_pending) {
status.irq_pending = false;
regs.vector = !regs.e ? 0xffee : 0xfffe;
r.vector = r.e ? 0xfffe : 0xffee;
interrupt();
debugger.op_irq();
} else if(status.reset_pending) {
status.reset_pending = false;
addClocks(132);
regs.vector = 0xfffc;
r.vector = 0xfffc;
interrupt();
} else if(status.power_pending) {
status.power_pending = false;
addClocks(186);
regs.pc.l = bus.read(0xfffc, regs.mdr);
regs.pc.h = bus.read(0xfffd, regs.mdr);
r.pc.l = bus.read(0xfffc, r.mdr);
r.pc.h = bus.read(0xfffd, r.mdr);
}
}
debugger.op_exec(regs.pc.d);
debugger.op_exec(r.pc.d);
instruction();
}
@ -89,8 +89,10 @@ auto CPU::power() -> void {
for(auto& byte : wram) byte = random(0x55);
//CPU
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
r.a = 0x0000;
r.x = 0x0000;
r.y = 0x0000;
r.s = 0x01ff;
//DMA
for(auto& channel : this->channel) {
@ -144,17 +146,17 @@ auto CPU::reset() -> void {
bus.map(reader, writer, "7e-7f:0000-ffff", 0x20000);
//CPU
regs.pc = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
regs.vector = 0xfffc; //reset vector address
r.pc = 0x000000;
r.x.h = 0x00;
r.y.h = 0x00;
r.s.h = 0x01;
r.d = 0x0000;
r.db = 0x00;
r.p = 0x34;
r.e = 1;
r.mdr = 0x00;
r.wai = false;
r.vector = 0xfffc; //reset vector address
//$2140-217f
for(auto& port : status.port) port = 0x00;

View File

@ -24,7 +24,7 @@ auto CPU::dmaAddressValid(uint24 abus) -> bool {
auto CPU::dmaRead(uint24 abus) -> uint8 {
if(!dmaAddressValid(abus)) return 0x00;
return bus.read(abus, regs.mdr);
return bus.read(abus, r.mdr);
}
//simulate two-stage pipeline for DMA transfers; example:
@ -42,14 +42,14 @@ auto CPU::dmaWrite(bool valid, uint addr, uint8 data) -> void {
auto CPU::dmaTransfer(bool direction, uint8 bbus, uint24 abus) -> void {
if(direction == 0) {
dmaAddClocks(4);
regs.mdr = dmaRead(abus);
r.mdr = dmaRead(abus);
dmaAddClocks(4);
dmaWrite(dmaTransferValid(bbus, abus), 0x2100 | bbus, regs.mdr);
dmaWrite(dmaTransferValid(bbus, abus), 0x2100 | bbus, r.mdr);
} else {
dmaAddClocks(4);
regs.mdr = dmaTransferValid(bbus, abus) ? bus.read(0x2100 | bbus, regs.mdr) : (uint8)0x00;
r.mdr = dmaTransferValid(bbus, abus) ? bus.read(0x2100 | bbus, r.mdr) : (uint8)0x00;
dmaAddClocks(4);
dmaWrite(dmaAddressValid(abus), abus, regs.mdr);
dmaWrite(dmaAddressValid(abus), abus, r.mdr);
}
}
@ -155,12 +155,12 @@ auto CPU::dmaRun() -> void {
auto CPU::hdmaUpdate(uint n) -> void {
dmaAddClocks(4);
regs.mdr = dmaRead(channel[n].source_bank << 16 | channel[n].hdma_addr);
r.mdr = dmaRead(channel[n].source_bank << 16 | channel[n].hdma_addr);
dmaAddClocks(4);
dmaWrite(false);
if((channel[n].line_counter & 0x7f) == 0) {
channel[n].line_counter = regs.mdr;
channel[n].line_counter = r.mdr;
channel[n].hdma_addr++;
channel[n].hdma_completed = channel[n].line_counter == 0;
@ -168,16 +168,16 @@ auto CPU::hdmaUpdate(uint n) -> void {
if(channel[n].indirect) {
dmaAddClocks(4);
regs.mdr = dmaRead(hdmaAddress(n));
channel[n].indirect_addr = regs.mdr << 8;
r.mdr = dmaRead(hdmaAddress(n));
channel[n].indirect_addr = r.mdr << 8;
dmaAddClocks(4);
dmaWrite(false);
if(!channel[n].hdma_completed || hdmaActiveAfter(n)) {
dmaAddClocks(4);
regs.mdr = dmaRead(hdmaAddress(n));
r.mdr = dmaRead(hdmaAddress(n));
channel[n].indirect_addr >>= 8;
channel[n].indirect_addr |= regs.mdr << 8;
channel[n].indirect_addr |= r.mdr << 8;
dmaAddClocks(4);
dmaWrite(false);
}

View File

@ -90,13 +90,13 @@ auto CPU::timeup() -> bool {
auto CPU::nmiTest() -> bool {
if(!status.nmi_transition) return false;
status.nmi_transition = false;
regs.wai = false;
r.wai = false;
return true;
}
auto CPU::irqTest() -> bool {
if(!status.irq_transition && !regs.irq) return false;
if(!status.irq_transition && !r.irq) return false;
status.irq_transition = false;
regs.wai = false;
return !regs.p.i;
r.wai = false;
return !r.p.i;
}

View File

@ -17,11 +17,11 @@ auto CPU::read(uint24 addr) -> uint8 {
status.clock_count = speed(addr);
dmaEdge();
addClocks(status.clock_count - 4);
regs.mdr = bus.read(addr, regs.mdr);
r.mdr = bus.read(addr, r.mdr);
addClocks(4);
aluEdge();
debugger.op_read(addr, regs.mdr);
return regs.mdr;
debugger.op_read(addr, r.mdr);
return r.mdr;
}
auto CPU::write(uint24 addr, uint8 data) -> void {
@ -29,8 +29,8 @@ auto CPU::write(uint24 addr, uint8 data) -> void {
status.clock_count = speed(addr);
dmaEdge();
addClocks(status.clock_count);
bus.write(addr, regs.mdr = data);
debugger.op_write(addr, regs.mdr);
bus.write(addr, r.mdr = data);
debugger.op_write(addr, r.mdr);
}
auto CPU::speed(uint24 addr) const -> uint {
@ -44,5 +44,5 @@ auto CPU::speed(uint24 addr) const -> uint {
}
auto CPU::disassemblerRead(uint24 addr) -> uint8 {
return bus.read(addr, regs.mdr);
return bus.read(addr, r.mdr);
}

View File

@ -8,16 +8,16 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 {
//WMDATA
if(addr == 0x2180) {
return bus.read(0x7e0000 | status.wram_addr++, regs.mdr);
return bus.read(0x7e0000 | status.wram_addr++, r.mdr);
}
//JOYSER0
//7-2 = MDR
//1-0 = Joypad serial data
if(addr == 0x4016) {
uint8 r = regs.mdr & 0xfc;
r |= SuperFamicom::peripherals.controllerPort1->data();
return r;
uint8 v = r.mdr & 0xfc;
v |= SuperFamicom::peripherals.controllerPort1->data();
return v;
}
//JOYSER1
@ -25,9 +25,9 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 {
//7-5 = MDR
//4-2 = Always 1 (pins are connected to GND)
//1-0 = Joypad serial data
uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= SuperFamicom::peripherals.controllerPort2->data();
return r;
uint8 v = (r.mdr & 0xe0) | 0x1c;
v |= SuperFamicom::peripherals.controllerPort2->data();
return v;
}
//RDNMI
@ -35,19 +35,19 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 {
//7 = NMI acknowledge
//6-4 = MDR
//3-0 = CPU (5a22) version
uint8 r = (regs.mdr & 0x70);
r |= (uint8)(rdnmi()) << 7;
r |= (cpu_version & 0x0f);
return r;
uint8 v = (r.mdr & 0x70);
v |= (uint8)(rdnmi()) << 7;
v |= (cpu_version & 0x0f);
return v;
}
//TIMEUP
if(addr == 0x4211) {
//7 = IRQ acknowledge
//6-0 = MDR
uint8 r = (regs.mdr & 0x7f);
r |= (uint8)(timeup()) << 7;
return r;
uint8 v = (r.mdr & 0x7f);
v |= (uint8)(timeup()) << 7;
return v;
}
//HVBJOY
@ -56,11 +56,11 @@ auto CPU::cpuPortRead(uint24 addr, uint8 data) -> uint8 {
//6 = HBLANK acknowledge
//5-1 = MDR
//0 = JOYPAD acknowledge
uint8 r = (regs.mdr & 0x3e);
if(status.auto_joypad_active) r |= 0x01;
if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank
if(vcounter() >= ppu.vdisp()) r |= 0x80; //vblank
return r;
uint8 v = (r.mdr & 0x3e);
if(status.auto_joypad_active) v |= 0x01;
if(hcounter() <= 2 || hcounter() >= 1096) v |= 0x40; //hblank
if(vcounter() >= ppu.vdisp()) v |= 0x80; //vblank
return v;
}
//RDIO

View File

@ -28,15 +28,15 @@ auto SuperDisc::Enter() -> void {
}
auto SuperDisc::main() -> void {
cpu.regs.irq = 0;
cpu.r.irq = 0;
if(r.irqEnable.bit(3)) {
cpu.regs.irq = 1;
cpu.r.irq = 1;
nec.data = necPollIRQ();
}
if(r.irqEnable.bit(2)) {
cpu.regs.irq = 1;
cpu.r.irq = 1;
sony.data = sonyPollIRQ();
}
@ -52,7 +52,7 @@ auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 {
}
if(addr == 0x21e1) {
cpu.regs.irq = 0;
cpu.r.irq = 0;
data = necReadData();
}
@ -61,7 +61,7 @@ auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 {
}
if(addr == 0x21e3) {
cpu.regs.irq = 0;
cpu.r.irq = 0;
data = sonyReadData();
}

View File

@ -26,113 +26,105 @@ Interface::Interface() {
media.append({ID::SuperFamicom, "Sufami Turbo", "st", false});
{ Device device{0, ID::ControllerPort1 | ID::ControllerPort2 | ID::ExpansionPort, "None"};
this->device.append(device);
devices.append(device);
}
{ Device device{1, ID::ControllerPort1 | ID::ControllerPort2, "Gamepad"};
device.input.append({ 0, 0, "B" });
device.input.append({ 1, 0, "Y" });
device.input.append({ 2, 0, "Select"});
device.input.append({ 3, 0, "Start" });
device.input.append({ 4, 0, "Up" });
device.input.append({ 5, 0, "Down" });
device.input.append({ 6, 0, "Left" });
device.input.append({ 7, 0, "Right" });
device.input.append({ 8, 0, "A" });
device.input.append({ 9, 0, "X" });
device.input.append({10, 0, "L" });
device.input.append({11, 0, "R" });
device.order = {4, 5, 6, 7, 0, 8, 1, 9, 10, 11, 2, 3};
this->device.append(device);
device.inputs.append({ 0, 0, "Up" });
device.inputs.append({ 1, 0, "Down" });
device.inputs.append({ 2, 0, "Left" });
device.inputs.append({ 3, 0, "Right" });
device.inputs.append({ 4, 0, "B" });
device.inputs.append({ 5, 0, "A" });
device.inputs.append({ 6, 0, "Y" });
device.inputs.append({ 7, 0, "X" });
device.inputs.append({ 8, 0, "L" });
device.inputs.append({ 9, 0, "R" });
device.inputs.append({10, 0, "Select"});
device.inputs.append({11, 0, "Start" });
devices.append(device);
}
{ Device device{2, ID::ControllerPort1 | ID::ControllerPort2, "Multitap"};
for(uint p = 1, n = 0; p <= 4; p++, n += 12) {
device.input.append({n + 0, 0, {"Port ", p, " - ", "B" }});
device.input.append({n + 1, 0, {"Port ", p, " - ", "Y" }});
device.input.append({n + 2, 0, {"Port ", p, " - ", "Select"}});
device.input.append({n + 3, 0, {"Port ", p, " - ", "Start" }});
device.input.append({n + 4, 0, {"Port ", p, " - ", "Up" }});
device.input.append({n + 5, 0, {"Port ", p, " - ", "Down" }});
device.input.append({n + 6, 0, {"Port ", p, " - ", "Left" }});
device.input.append({n + 7, 0, {"Port ", p, " - ", "Right" }});
device.input.append({n + 8, 0, {"Port ", p, " - ", "A" }});
device.input.append({n + 9, 0, {"Port ", p, " - ", "X" }});
device.input.append({n + 10, 0, {"Port ", p, " - ", "L" }});
device.input.append({n + 11, 0, {"Port ", p, " - ", "R" }});
device.order.append({n + 4, n + 5, n + 6, n + 7, n + 0, n + 8});
device.order.append({n + 1, n + 9, n + 10, n + 11, n + 2, n + 3});
device.inputs.append({n + 0, 0, {"Port ", p, " - ", "Up" }});
device.inputs.append({n + 1, 0, {"Port ", p, " - ", "Down" }});
device.inputs.append({n + 2, 0, {"Port ", p, " - ", "Left" }});
device.inputs.append({n + 3, 0, {"Port ", p, " - ", "Right" }});
device.inputs.append({n + 4, 0, {"Port ", p, " - ", "B" }});
device.inputs.append({n + 5, 0, {"Port ", p, " - ", "A" }});
device.inputs.append({n + 6, 0, {"Port ", p, " - ", "Y" }});
device.inputs.append({n + 7, 0, {"Port ", p, " - ", "X" }});
device.inputs.append({n + 8, 0, {"Port ", p, " - ", "L" }});
device.inputs.append({n + 9, 0, {"Port ", p, " - ", "R" }});
device.inputs.append({n + 10, 0, {"Port ", p, " - ", "Select"}});
device.inputs.append({n + 11, 0, {"Port ", p, " - ", "Start" }});
}
this->device.append(device);
devices.append(device);
}
{ Device device{3, ID::ControllerPort1 | ID::ControllerPort2, "Mouse"};
device.input.append({0, 1, "X-axis"});
device.input.append({1, 1, "Y-axis"});
device.input.append({2, 0, "Left" });
device.input.append({3, 0, "Right" });
device.order = {0, 1, 2, 3};
this->device.append(device);
device.inputs.append({0, 1, "X-axis"});
device.inputs.append({1, 1, "Y-axis"});
device.inputs.append({2, 0, "Left" });
device.inputs.append({3, 0, "Right" });
devices.append(device);
}
{ Device device{4, ID::ControllerPort2, "Super Scope"};
device.input.append({0, 1, "X-axis" });
device.input.append({1, 1, "Y-axis" });
device.input.append({2, 0, "Trigger"});
device.input.append({3, 0, "Cursor" });
device.input.append({4, 0, "Turbo" });
device.input.append({5, 0, "Pause" });
device.order = {0, 1, 2, 3, 4, 5};
this->device.append(device);
device.inputs.append({0, 1, "X-axis" });
device.inputs.append({1, 1, "Y-axis" });
device.inputs.append({2, 0, "Trigger"});
device.inputs.append({3, 0, "Cursor" });
device.inputs.append({4, 0, "Turbo" });
device.inputs.append({5, 0, "Pause" });
devices.append(device);
}
{ Device device{5, ID::ControllerPort2, "Justifier"};
device.input.append({0, 1, "X-axis" });
device.input.append({1, 1, "Y-axis" });
device.input.append({2, 0, "Trigger"});
device.input.append({3, 0, "Start" });
device.order = {0, 1, 2, 3};
this->device.append(device);
device.inputs.append({0, 1, "X-axis" });
device.inputs.append({1, 1, "Y-axis" });
device.inputs.append({2, 0, "Trigger"});
device.inputs.append({3, 0, "Start" });
devices.append(device);
}
{ Device device{6, ID::ControllerPort2, "Justifiers"};
device.input.append({0, 1, "Port 1 - X-axis" });
device.input.append({1, 1, "Port 1 - Y-axis" });
device.input.append({2, 0, "Port 1 - Trigger"});
device.input.append({3, 0, "Port 1 - Start" });
device.order.append({0, 1, 2, 3});
device.input.append({4, 1, "Port 2 - X-axis" });
device.input.append({5, 1, "Port 2 - Y-axis" });
device.input.append({6, 0, "Port 2 - Trigger"});
device.input.append({7, 0, "Port 2 - Start" });
device.order.append({4, 5, 6, 7});
this->device.append(device);
device.inputs.append({0, 1, "Port 1 - X-axis" });
device.inputs.append({1, 1, "Port 1 - Y-axis" });
device.inputs.append({2, 0, "Port 1 - Trigger"});
device.inputs.append({3, 0, "Port 1 - Start" });
device.inputs.append({4, 1, "Port 2 - X-axis" });
device.inputs.append({5, 1, "Port 2 - Y-axis" });
device.inputs.append({6, 0, "Port 2 - Trigger"});
device.inputs.append({7, 0, "Port 2 - Start" });
devices.append(device);
}
{ Device device{7, ID::ControllerPort1, "Serial USART"};
this->device.append(device);
devices.append(device);
}
{ Device device{8, ID::ExpansionPort, "Satellaview"};
this->device.append(device);
devices.append(device);
}
{ Device device{9, ID::ExpansionPort, "Super Disc"};
this->device.append(device);
devices.append(device);
}
{ Device device{10, ID::ExpansionPort, "21fx"};
this->device.append(device);
devices.append(device);
}
port.append({0, "Controller Port 1"});
port.append({1, "Controller Port 2"});
port.append({2, "Expansion Port"});
ports.append({0, "Controller Port 1"});
ports.append({1, "Controller Port 2"});
ports.append({2, "Expansion Port"});
for(auto& device : this->device) {
for(auto& port : this->port) {
for(auto& device : devices) {
for(auto& port : ports) {
if(device.portmask & (1 << port.id)) {
port.device.append(device);
port.devices.append(device);
}
}
}

View File

@ -124,7 +124,7 @@ struct Interface : Emulator::Interface {
auto get(const string& name) -> any override;
auto set(const string& name, const any& value) -> bool override;
vector<Device> device;
vector<Device> devices;
};
struct Settings {

View File

@ -13,21 +13,21 @@ auto PPU::read(uint24 addr, uint8 data) -> uint8 {
//MPYL
case 0x2134: {
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
uint result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
regs.ppu1_mdr = (result >> 0);
return regs.ppu1_mdr;
}
//MPYM
case 0x2135: {
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
uint result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
regs.ppu1_mdr = (result >> 8);
return regs.ppu1_mdr;
}
//MPYH
case 0x2136: {
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
uint result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
regs.ppu1_mdr = (result >> 16);
return regs.ppu1_mdr;
}
@ -35,7 +35,7 @@ auto PPU::read(uint24 addr, uint8 data) -> uint8 {
//SLHV
case 0x2137: {
if(cpu.pio() & 0x80) latchCounters();
return cpu.regs.mdr;
return cpu.r.mdr;
}
//OAMDATAREAD

View File

@ -6,13 +6,13 @@ auto Program::loadRequest(uint id, string name, string type, bool required) -> v
.openFolder();
if(!directory::exists(location)) return;
mediaPaths(id) = location;
mediumPaths(id) = location;
folderPaths.append(location);
emulator->load(id);
}
auto Program::loadRequest(uint id, string filename, bool required) -> void {
string pathname = mediaPaths(emulator->group(id));
string pathname = mediumPaths(emulator->group(id));
string location = {pathname, filename};
if(filename == "manifest.bml" && pathname && !pathname.endsWith("sys/")) {
@ -36,7 +36,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
}
auto Program::saveRequest(uint id, string filename) -> void {
string pathname = mediaPaths(emulator->group(id));
string pathname = mediumPaths(emulator->group(id));
string location = {pathname, filename};
//filestream stream{location, file::mode::write};
@ -113,7 +113,7 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
}
auto Program::path(uint group) -> string {
return mediaPaths(group);
return mediumPaths(group);
}
auto Program::notify(string text) -> void {

View File

@ -1,21 +1,21 @@
auto Program::loadMedia(string location) -> void {
auto Program::loadMedium(string location) -> void {
location.transform("\\", "/");
if(!location.endsWith("/")) location.append("/");
if(!directory::exists(location)) return;
string type = suffixname(location).trimLeft(".", 1L);
for(auto& media : emulator->media) {
if(!media.bootable) continue;
if(media.type != type) continue;
return loadMedia(media, location);
for(auto& medium : emulator->media) {
if(!medium.bootable) continue;
if(medium.type != type) continue;
return loadMedium(medium, location);
}
}
auto Program::loadMedia(Emulator::Interface::Media& media, string location) -> void {
unloadMedia();
auto Program::loadMedium(Emulator::Interface::Medium& medium, string location) -> void {
unloadMedium();
mediaPaths(0) = locate({media.name, ".sys/"});
mediaPaths(media.id) = location;
mediumPaths(0) = locate({medium.name, ".sys/"});
mediumPaths(medium.id) = location;
folderPaths.append(location);
emulator->set("Blur Emulation", false);
@ -28,17 +28,17 @@ auto Program::loadMedia(Emulator::Interface::Media& media, string location) -> v
emulator->connect((uint)SFC::Port::Controller2, (uint)SFC::Device::None);
emulator->connect((uint)SFC::Port::Expansion, (uint)SFC::Device::None);
emulator->load(media.id);
emulator->load(medium.id);
emulator->power();
presentation->setTitle(emulator->title());
}
auto Program::unloadMedia() -> void {
auto Program::unloadMedium() -> void {
if(!emulator->loaded()) return;
emulator->unload();
mediaPaths.reset();
mediumPaths.reset();
folderPaths.reset();
presentation->setTitle("");

View File

@ -1,6 +1,6 @@
#include "../loki.hpp"
#include "interface.cpp"
#include "media.cpp"
#include "medium.cpp"
unique_pointer<Program> program;
Program::Program(lstring args) {
@ -38,7 +38,7 @@ Program::Program(lstring args) {
"Legend of Zelda - A Link to the Past, The (USA) (1.0).sfc/"
};
if(directory::exists(location)) loadMedia(location);
if(directory::exists(location)) loadMedium(location);
}
auto Program::main() -> void {
@ -52,7 +52,7 @@ auto Program::main() -> void {
}
auto Program::quit() -> void {
unloadMedia();
unloadMedium();
video.reset();
audio.reset();
input.reset();

View File

@ -5,9 +5,9 @@ struct Program : Emulator::Interface::Bind {
auto quit() -> void;
//media.cpp
auto loadMedia(string location) -> void;
auto loadMedia(Emulator::Interface::Media& media, string location) -> void;
auto unloadMedia() -> void;
auto loadMedium(string location) -> void;
auto loadMedium(Emulator::Interface::Medium& medium, string location) -> void;
auto unloadMedium() -> void;
//interface.cpp
auto loadRequest(uint id, string name, string type, bool required) -> void override;
@ -22,7 +22,7 @@ struct Program : Emulator::Interface::Bind {
auto notify(string text) -> void override;
vector<shared_pointer<HID::Device>> devices;
vector<string> mediaPaths;
vector<string> mediumPaths;
vector<string> folderPaths;
};

View File

@ -150,16 +150,15 @@ InputManager::InputManager() {
auto& inputEmulator = emulators.right();
inputEmulator.name = emulator->information.name;
for(auto& port : emulator->port) {
for(auto& port : emulator->ports) {
inputEmulator.ports.append(InputPort());
auto& inputPort = inputEmulator.ports.right();
inputPort.name = port.name;
for(auto& device : port.device) {
for(auto& device : port.devices) {
inputPort.devices.append(InputDevice());
auto& inputDevice = inputPort.devices.right();
inputDevice.name = device.name;
for(auto number : device.order) {
auto& input = device.input[number];
for(auto& input : device.inputs) {
inputDevice.mappings.append(new InputMapping());
auto& inputMapping = inputDevice.mappings.right();
inputMapping->name = input.name;

View File

@ -17,7 +17,7 @@ Presentation::Presentation() {
.setFilters(string{media.name, "|*.", media.type})
.openFolder();
if(directory::exists(location)) {
program->loadMedia(location);
program->loadMedium(location);
}
});
loadBootableMedia.append(item);
@ -29,7 +29,7 @@ Presentation::Presentation() {
libraryMenu.append(MenuItem().setText("Load ROM File ...").onActivate([&] {
audio->clear();
if(auto location = execute("icarus", "--import")) {
program->loadMedia(location.output.strip());
program->loadMedium(location.output.strip());
}
}));
libraryMenu.append(MenuItem().setText("Import ROM Files ...").onActivate([&] {
@ -40,7 +40,7 @@ Presentation::Presentation() {
systemMenu.setText("System").setVisible(false);
powerSystem.setText("Power").onActivate([&] { program->powerCycle(); });
resetSystem.setText("Reset").onActivate([&] { program->softReset(); });
unloadSystem.setText("Unload").onActivate([&] { program->unloadMedia(); drawSplashScreen(); });
unloadSystem.setText("Unload").onActivate([&] { program->unloadMedium(); drawSplashScreen(); });
settingsMenu.setText("Settings");
videoScaleMenu.setText("Video Scale");
@ -173,14 +173,14 @@ auto Presentation::updateEmulator() -> void {
inputPort2.setVisible(false).reset();
inputPort3.setVisible(false).reset();
for(auto n : range(emulator->port)) {
for(auto n : range(emulator->ports)) {
if(n >= 3) break;
auto& port = emulator->port[n];
auto& port = emulator->ports[n];
auto& menu = (n == 0 ? inputPort1 : n == 1 ? inputPort2 : inputPort3);
menu.setText(port.name);
Group devices;
for(auto& device : port.device) {
for(auto& device : port.devices) {
MenuRadioItem item{&menu};
item.setText(device.name).onActivate([=] {
auto path = string{emulator->information.name, "/", port.name}.replace(" ", "");

View File

@ -7,14 +7,14 @@ auto Program::loadRequest(uint id, string name, string type, bool required) -> v
.openFolder();
if(!directory::exists(location)) return;
mediaPaths(id) = location;
mediumPaths(id) = location;
folderPaths.append(location);
emulator->load(id);
}
//request from emulation core to load non-volatile media file
auto Program::loadRequest(uint id, string filename, bool required) -> void {
string pathname = mediaPaths(emulator->group(id));
string pathname = mediumPaths(emulator->group(id));
string location = {pathname, filename};
if(filename == "manifest.bml" && pathname && !pathname.endsWith(".sys/")) {
@ -39,7 +39,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
//request from emulation core to save non-volatile media file
auto Program::saveRequest(uint id, string filename) -> void {
string pathname = mediaPaths(emulator->group(id));
string pathname = mediumPaths(emulator->group(id));
string location = {pathname, filename};
if(!pathname) return; //should never occur
@ -89,19 +89,13 @@ auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint heig
}
}
auto Program::audioSample(int16 lsample, int16 rsample) -> void {
audio->sample(lsample, rsample);
//int samples[] = {lsample, rsample};
//dsp.sample(samples);
//while(dsp.pending()) {
// dsp.read(samples);
// audio->sample(samples[0], samples[1]);
//}
auto Program::audioSample(int16 left, int16 right) -> void {
audio->sample(left, right);
}
auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean()) {
auto guid = emulator->port[port].device[device].input[input].guid;
auto guid = emulator->ports[port].devices[device].inputs[input].guid;
auto mapping = (InputMapping*)guid;
if(mapping) return mapping->poll();
}
@ -110,7 +104,7 @@ auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void {
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) {
auto guid = emulator->port[port].device[device].input[input].guid;
auto guid = emulator->ports[port].devices[device].inputs[input].guid;
auto mapping = (InputMapping*)guid;
if(mapping) return mapping->rumble(enable);
}
@ -121,7 +115,7 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
}
auto Program::path(uint group) -> string {
return mediaPaths(group);
return mediumPaths(group);
}
auto Program::notify(string text) -> void {

View File

@ -1,23 +1,23 @@
auto Program::loadMedia(string location) -> void {
auto Program::loadMedium(string location) -> void {
location.transform("\\", "/");
if(!location.endsWith("/")) location.append("/");
if(!directory::exists(location)) return;
string type = suffixname(location).trimLeft(".", 1L);
for(auto& emulator : emulators) {
for(auto& media : emulator->media) {
if(!media.bootable) continue;
if(media.type != type) continue;
return loadMedia(*emulator, media, location);
for(auto& medium : emulator->media) {
if(!medium.bootable) continue;
if(medium.type != type) continue;
return loadMedium(*emulator, medium, location);
}
}
}
auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, string location) -> void {
unloadMedia();
auto Program::loadMedium(Emulator::Interface& interface, Emulator::Interface::Medium& medium, string location) -> void {
unloadMedium();
mediaPaths(0) = locate({media.name, ".sys/"});
mediaPaths(media.id) = location;
mediumPaths(0) = locate({medium.name, ".sys/"});
mediumPaths(medium.id) = location;
folderPaths.append(location);
//note: the order of operations in this block of code is critical
@ -25,14 +25,14 @@ auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Med
Emulator::audio.setFrequency(audio->get(Audio::Frequency).get<uint>());
emulator = &interface;
connectDevices();
emulator->load(media.id);
emulator->load(medium.id);
updateAudioDriver();
updateAudioEffects();
emulator->power();
presentation->resizeViewport();
presentation->setTitle(emulator->title());
presentation->systemMenu.setText(media.name).setVisible(true);
presentation->systemMenu.setText(medium.name).setVisible(true);
presentation->toolsMenu.setVisible(true);
presentation->updateEmulator();
toolsManager->cheatEditor.loadCheats();
@ -40,14 +40,14 @@ auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Med
toolsManager->manifestViewer.doRefresh();
}
auto Program::unloadMedia() -> void {
auto Program::unloadMedium() -> void {
if(!emulator) return;
toolsManager->cheatEditor.saveCheats();
emulator->unload();
emulator = nullptr;
mediaPaths.reset();
mediumPaths.reset();
folderPaths.reset();
presentation->setTitle({"higan v", Emulator::Version});

View File

@ -5,7 +5,7 @@
#include <gba/interface/interface.hpp>
#include <ws/interface/interface.hpp>
#include "interface.cpp"
#include "media.cpp"
#include "medium.cpp"
#include "state.cpp"
#include "utility.cpp"
unique_pointer<Program> program;
@ -64,7 +64,7 @@ Program::Program(lstring args) {
auto Program::load(string location) -> void {
if(directory::exists(location)) {
loadMedia(location);
loadMedium(location);
} else if(file::exists(location)) {
//special handling to allow importing the Game Boy Advance BIOS
if(file::size(location) == 16384 && file::sha256(location).beginsWith("fd2547724b505f48")) {
@ -77,7 +77,7 @@ auto Program::load(string location) -> void {
//ask icarus to import the game; and play it upon success
if(auto result = execute("icarus", "--import", location)) {
loadMedia(result.output.strip());
loadMedium(result.output.strip());
}
}
}
@ -96,7 +96,7 @@ auto Program::main() -> void {
}
auto Program::quit() -> void {
unloadMedia();
unloadMedium();
settings.quit();
inputManager->quit();
Application::quit();

View File

@ -17,10 +17,10 @@ struct Program : Emulator::Interface::Bind {
auto path(uint group) -> string override;
auto notify(string text) -> void override;
//media.cpp
auto loadMedia(string location) -> void;
auto loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, string location) -> void;
auto unloadMedia() -> void;
//medium.cpp
auto loadMedium(string location) -> void;
auto loadMedium(Emulator::Interface& interface, Emulator::Interface::Medium& medium, string location) -> void;
auto unloadMedium() -> void;
//state.cpp
auto stateName(uint slot, bool manager = false) -> string;
@ -42,7 +42,7 @@ struct Program : Emulator::Interface::Bind {
vector<Emulator::Interface*> emulators;
vector<string> mediaPaths;
vector<string> mediumPaths;
vector<string> folderPaths;
string statusText;

View File

@ -13,10 +13,10 @@ auto Program::softReset() -> void {
auto Program::connectDevices() -> void {
if(!emulator) return;
for(auto& port : emulator->port) {
for(auto& port : emulator->ports) {
auto path = string{emulator->information.name, "/", port.name}.replace(" ", "");
auto name = settings(path).text();
for(auto& device : port.device) {
for(auto& device : port.devices) {
if(device.name == name) {
emulator->connect(port.id, device.id);
break;

View File

@ -23,41 +23,39 @@ Interface::Interface() {
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc", true});
{ Device device{0, ID::DeviceHorizontal, "Controller"};
device.input.append({ 0, 0, "Y1"});
device.input.append({ 1, 0, "Y2"});
device.input.append({ 2, 0, "Y3"});
device.input.append({ 3, 0, "Y4"});
device.input.append({ 4, 0, "X1"});
device.input.append({ 5, 0, "X2"});
device.input.append({ 6, 0, "X3"});
device.input.append({ 7, 0, "X4"});
device.input.append({ 8, 0, "B"});
device.input.append({ 9, 0, "A"});
device.input.append({10, 0, "Start"});
device.input.append({11, 0, "Rotate"});
device.order = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
this->device.append(device);
device.inputs.append({ 0, 0, "Y1"});
device.inputs.append({ 1, 0, "Y2"});
device.inputs.append({ 2, 0, "Y3"});
device.inputs.append({ 3, 0, "Y4"});
device.inputs.append({ 4, 0, "X1"});
device.inputs.append({ 5, 0, "X2"});
device.inputs.append({ 6, 0, "X3"});
device.inputs.append({ 7, 0, "X4"});
device.inputs.append({ 8, 0, "B"});
device.inputs.append({ 9, 0, "A"});
device.inputs.append({10, 0, "Start"});
device.inputs.append({11, 0, "Rotate"});
devices.append(device);
}
{ Device device{1, ID::DeviceVertical, "Controller"};
device.input.append({ 0, 0, "Y1"});
device.input.append({ 1, 0, "Y2"});
device.input.append({ 2, 0, "Y3"});
device.input.append({ 3, 0, "Y4"});
device.input.append({ 4, 0, "X1"});
device.input.append({ 5, 0, "X2"});
device.input.append({ 6, 0, "X3"});
device.input.append({ 7, 0, "X4"});
device.input.append({ 8, 0, "B"});
device.input.append({ 9, 0, "A"});
device.input.append({10, 0, "Start"});
device.input.append({11, 0, "Rotate"});
device.order = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
this->device.append(device);
device.inputs.append({ 0, 0, "Y1"});
device.inputs.append({ 1, 0, "Y2"});
device.inputs.append({ 2, 0, "Y3"});
device.inputs.append({ 3, 0, "Y4"});
device.inputs.append({ 4, 0, "X1"});
device.inputs.append({ 5, 0, "X2"});
device.inputs.append({ 6, 0, "X3"});
device.inputs.append({ 7, 0, "X4"});
device.inputs.append({ 8, 0, "B"});
device.inputs.append({ 9, 0, "A"});
device.inputs.append({10, 0, "Start"});
device.inputs.append({11, 0, "Rotate"});
devices.append(device);
}
port.append({0, "Horizontal Orientation", {device[0]}});
port.append({1, "Vertical Orientation", {device[1]}});
ports.append({0, "Horizontal Orientation", {devices[0]}});
ports.append({1, "Vertical Orientation", {devices[1]}});
}
auto Interface::manifest() -> string {

View File

@ -57,7 +57,7 @@ struct Interface : Emulator::Interface {
auto set(const string& name, const any& value) -> bool override;
private:
vector<Device> device;
vector<Device> devices;
};
struct Settings {

View File

@ -1,4 +1,8 @@
#define decimal decimal_cocoa
#define int8 int8_cocoa
#define int16 int16_cocoa
#define int32 int32_cocoa
#define int64 int64_cocoa
#define uint8 uint8_cocoa
#define uint16 uint16_cocoa
#define uint32 uint32_cocoa
@ -6,6 +10,10 @@
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#undef decimal
#undef int8
#undef int16
#undef int32
#undef int64
#undef uint8
#undef uint16
#undef uint32

View File

@ -4,28 +4,28 @@
namespace nall {
template<unsigned bits> inline auto uclamp(const uintmax_t x) -> uintmax_t {
enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
template<uint bits> inline auto uclamp(const uintmax x) -> uintmax {
enum : uintmax { b = 1ull << (bits - 1), y = b * 2 - 1 };
return y + ((x - y) & -(x < y)); //min(x, y);
}
template<unsigned bits> inline auto uclip(const uintmax_t x) -> uintmax_t {
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
template<uint bits> inline auto uclip(const uintmax x) -> uintmax {
enum : uintmax { b = 1ull << (bits - 1), m = b * 2 - 1 };
return (x & m);
}
template<unsigned bits> inline auto sclamp(const intmax_t x) -> intmax_t {
enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 };
template<uint bits> inline auto sclamp(const intmax x) -> intmax {
enum : intmax { b = 1ull << (bits - 1), m = b - 1 };
return (x > m) ? m : (x < -b) ? -b : x;
}
template<unsigned bits> inline auto sclip(const intmax_t x) -> intmax_t {
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
template<uint bits> inline auto sclip(const intmax x) -> intmax {
enum : uintmax { b = 1ull << (bits - 1), m = b * 2 - 1 };
return ((x & m) ^ b) - b;
}
namespace bit {
constexpr inline auto mask(const char* s, uintmax_t sum = 0) -> uintmax_t {
constexpr inline auto mask(const char* s, uintmax sum = 0) -> uintmax {
return (
*s == '0' || *s == '1' ? mask(s + 1, (sum << 1) | 1) :
*s == ' ' || *s == '_' ? mask(s + 1, sum) :
@ -34,7 +34,7 @@ namespace bit {
);
}
constexpr inline auto test(const char* s, uintmax_t sum = 0) -> uintmax_t {
constexpr inline auto test(const char* s, uintmax sum = 0) -> uintmax {
return (
*s == '0' || *s == '1' ? test(s + 1, (sum << 1) | (*s - '0')) :
*s == ' ' || *s == '_' ? test(s + 1, sum) :
@ -44,38 +44,38 @@ namespace bit {
}
//lowest(0b1110) == 0b0010
constexpr inline auto lowest(const uintmax_t x) -> uintmax_t {
constexpr inline auto lowest(const uintmax x) -> uintmax {
return x & -x;
}
//clear_lowest(0b1110) == 0b1100
constexpr inline auto clear_lowest(const uintmax_t x) -> uintmax_t {
constexpr inline auto clear_lowest(const uintmax x) -> uintmax {
return x & (x - 1);
}
//set_lowest(0b0101) == 0b0111
constexpr inline auto set_lowest(const uintmax_t x) -> uintmax_t {
constexpr inline auto set_lowest(const uintmax x) -> uintmax {
return x | (x + 1);
}
//count number of bits set in a byte
inline auto count(uintmax_t x) -> unsigned {
unsigned count = 0;
inline auto count(uintmax x) -> uint {
uint count = 0;
do count += x & 1; while(x >>= 1);
return count;
}
//return index of the first bit set (or zero of no bits are set)
//first(0b1000) == 3
inline auto first(uintmax_t x) -> unsigned {
unsigned first = 0;
inline auto first(uintmax x) -> uint {
uint first = 0;
while(x) { if(x & 1) break; x >>= 1; first++; }
return first;
}
//round up to next highest single bit:
//round(15) == 16, round(16) == 16, round(17) == 32
inline auto round(uintmax_t x) -> uintmax_t {
inline auto round(uintmax x) -> uintmax {
if((x & (x - 1)) == 0) return x;
while(x & (x - 1)) x &= x - 1;
return x << 1;

View File

@ -10,7 +10,7 @@ namespace Configuration {
struct Node {
string name;
string desc;
enum class Type : unsigned { Null, Boolean, Integer, Natural, Double, String } type = Type::Null;
enum class Type : uint { Null, Boolean, Integer, Natural, Double, String } type = Type::Null;
void* data = nullptr;
vector<Node> children;
@ -74,7 +74,7 @@ struct Node {
}
}
auto save(file& fp, unsigned depth = 0) -> void {
auto save(file& fp, uint depth = 0) -> void {
for(auto& child : children) {
if(child.desc) {
for(auto n : range(depth)) fp.print(" ");

View File

@ -65,7 +65,7 @@ inline auto library::close() -> void {
inline auto library::open(const string& name, const string& path) -> bool {
if(handle) close();
if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string(Path::user(), ".local/lib/lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".dylib"), RTLD_LAZY);
return handle;

View File

@ -7,7 +7,7 @@
//remove: O(1) average; O(n) worst
//
//requirements:
// auto T::hash() const -> unsigned;
// auto T::hash() const -> uint;
// auto T::operator==(const T&) const -> bool;
namespace nall {
@ -15,7 +15,7 @@ namespace nall {
template<typename T>
struct hashset {
hashset() = default;
hashset(unsigned length) : length(bit::round(length)) {}
hashset(uint length) : length(bit::round(length)) {}
hashset(const hashset& source) { operator=(source); }
hashset(hashset&& source) { operator=(move(source)); }
~hashset() { reset(); }
@ -23,7 +23,7 @@ struct hashset {
auto operator=(const hashset& source) -> hashset& {
reset();
if(source.pool) {
for(unsigned n = 0; n < source.count; n++) {
for(uint n : range(source.count)) {
insert(*source.pool[n]);
}
}
@ -42,12 +42,12 @@ struct hashset {
}
explicit operator bool() const { return count; }
auto capacity() const -> unsigned { return length; }
auto size() const -> unsigned { return count; }
auto capacity() const -> uint { return length; }
auto size() const -> uint { return count; }
auto reset() -> void {
if(pool) {
for(unsigned n = 0; n < length; n++) {
for(uint n : range(length)) {
if(pool[n]) {
delete pool[n];
pool[n] = nullptr;
@ -60,15 +60,15 @@ struct hashset {
count = 0;
}
auto reserve(unsigned size) -> void {
auto reserve(uint size) -> void {
//ensure all items will fit into pool (with <= 50% load) and amortize growth
size = bit::round(max(size, count << 1));
T** copy = new T*[size]();
if(pool) {
for(unsigned n = 0; n < length; n++) {
for(uint n : range(length)) {
if(pool[n]) {
unsigned hash = (*pool[n]).hash() & (size - 1);
uint hash = (*pool[n]).hash() & (size - 1);
while(copy[hash]) if(++hash >= size) hash = 0;
copy[hash] = pool[n];
pool[n] = nullptr;
@ -84,7 +84,7 @@ struct hashset {
auto find(const T& value) -> maybe<T&> {
if(!pool) return nothing;
unsigned hash = value.hash() & (length - 1);
uint hash = value.hash() & (length - 1);
while(pool[hash]) {
if(value == *pool[hash]) return *pool[hash];
if(++hash >= length) hash = 0;
@ -100,7 +100,7 @@ struct hashset {
if(count >= (length >> 1)) reserve(length << 1);
count++;
unsigned hash = value.hash() & (length - 1);
uint hash = value.hash() & (length - 1);
while(pool[hash]) if(++hash >= length) hash = 0;
pool[hash] = new T(value);
@ -110,7 +110,7 @@ struct hashset {
auto remove(const T& value) -> bool {
if(!pool) return false;
unsigned hash = value.hash() & (length - 1);
uint hash = value.hash() & (length - 1);
while(pool[hash]) {
if(value == *pool[hash]) {
delete pool[hash];
@ -126,8 +126,8 @@ struct hashset {
protected:
T** pool = nullptr;
unsigned length = 8; //length of pool
unsigned count = 0; //number of objects inside of the pool
uint length = 8; //length of pool
uint count = 0; //number of objects inside of the pool
};
}

View File

@ -19,10 +19,10 @@ struct Group : vector<Input> {
Group(const string& name) : _name(name) {}
auto name() const -> string { return _name; }
auto input(unsigned id) -> Input& { return operator[](id); }
auto input(uint id) -> Input& { return operator[](id); }
auto append(const string& name) -> void { vector::append(Input{name}); }
auto find(const string& name) const -> maybe<unsigned> {
auto find(const string& name) const -> maybe<uint> {
for(auto id : range(size())) {
if(operator[](id)._name == name) return id;
}
@ -50,10 +50,10 @@ struct Device : vector<Group> {
auto name() const -> string { return _name; }
auto id() const -> uint64_t { return _id; }
auto setID(uint64_t id) -> void { _id = id; }
auto group(unsigned id) -> Group& { return operator[](id); }
auto group(uint id) -> Group& { return operator[](id); }
auto append(const string& name) -> void { vector::append(Group{name}); }
auto find(const string& name) const -> maybe<unsigned> {
auto find(const string& name) const -> maybe<uint> {
for(auto id : range(size())) {
if(operator[](id)._name == name) return id;
}
@ -71,7 +71,7 @@ struct Null : Device {
};
struct Keyboard : Device {
enum GroupID : unsigned { Button };
enum GroupID : uint { Button };
Keyboard() : Device("Keyboard") { append("Button"); }
auto isKeyboard() const -> bool { return true; }
@ -79,7 +79,7 @@ struct Keyboard : Device {
};
struct Mouse : Device {
enum GroupID : unsigned { Axis, Button };
enum GroupID : uint { Axis, Button };
Mouse() : Device("Mouse") { append("Axis"), append("Button"); }
auto isMouse() const -> bool { return true; }
@ -88,7 +88,7 @@ struct Mouse : Device {
};
struct Joypad : Device {
enum GroupID : unsigned { Axis, Hat, Trigger, Button };
enum GroupID : uint { Axis, Hat, Trigger, Button };
Joypad() : Device("Joypad") { append("Axis"), append("Hat"), append("Trigger"), append("Button"); }
auto isJoypad() const -> bool { return true; }

View File

@ -9,7 +9,7 @@
namespace nall {
struct inode {
enum class time : unsigned { access, modify };
enum class time : uint { access, modify };
static auto exists(const string& name) -> bool {
return access(name, F_OK) == 0;
@ -27,19 +27,19 @@ struct inode {
return access(name, X_OK) == 0;
}
static auto uid(const string& name) -> unsigned {
static auto uid(const string& name) -> uint {
struct stat data{0};
stat(name, &data);
return data.st_uid;
}
static auto gid(const string& name) -> unsigned {
static auto gid(const string& name) -> uint {
struct stat data{0};
stat(name, &data);
return data.st_gid;
}
static auto mode(const string& name) -> unsigned {
static auto mode(const string& name) -> uint {
struct stat data{0};
stat(name, &data);
return data.st_mode;
@ -55,7 +55,7 @@ struct inode {
}
//returns true if 'name' already exists
static auto create(const string& name, unsigned permissions = 0755) -> bool {
static auto create(const string& name, uint permissions = 0755) -> bool {
if(exists(name)) return true;
if(name.endsWith("/")) return mkdir(name, permissions) == 0;
int fd = open(name, O_CREAT | O_EXCL, permissions);

View File

@ -1,13 +1,15 @@
#pragma once
namespace nall {
using uint = unsigned;
struct Intrinsics {
enum class Compiler : unsigned { Clang, GCC, VisualCPP, Unknown };
enum class Platform : unsigned { Windows, MacOSX, Linux, BSD, Unknown };
enum class API : unsigned { Windows, Posix, Unknown };
enum class Display : unsigned { Windows, Quartz, Xorg, Unknown };
enum class Processor : unsigned { x86, amd64, ARM, PPC32, PPC64, Unknown };
enum class Endian : unsigned { LSB, MSB, Unknown };
enum class Compiler : uint { Clang, GCC, VisualCPP, Unknown };
enum class Platform : uint { Windows, MacOSX, Linux, BSD, Unknown };
enum class API : uint { Windows, Posix, Unknown };
enum class Display : uint { Windows, Quartz, Xorg, Unknown };
enum class Processor : uint { x86, amd64, ARM, PPC32, PPC64, Unknown };
enum class Endian : uint { LSB, MSB, Unknown };
static inline auto compiler() -> Compiler;
static inline auto platform() -> Platform;

View File

@ -4,13 +4,13 @@ namespace nall {
namespace Matrix {
template<typename T> inline auto Multiply(T* output, const T* xdata, unsigned xrows, unsigned xcols, const T* ydata, unsigned yrows, unsigned ycols) -> void {
template<typename T> inline auto Multiply(T* output, const T* xdata, uint xrows, uint xcols, const T* ydata, uint yrows, uint ycols) -> void {
if(xcols != yrows) return;
for(unsigned y = 0; y < xrows; y++) {
for(unsigned x = 0; x < ycols; x++) {
for(uint y : range(xrows)) {
for(uint x : range(ycols)) {
T sum = 0;
for(unsigned z = 0; z < xcols; z++) {
for(uint z : range(xcols)) {
sum += xdata[y * xcols + z] * ydata[z * ycols + x];
}
*output++ = sum;
@ -18,7 +18,7 @@ template<typename T> inline auto Multiply(T* output, const T* xdata, unsigned xr
}
}
template<typename T> inline auto Multiply(const T* xdata, unsigned xrows, unsigned xcols, const T* ydata, unsigned yrows, unsigned ycols) -> vector<T> {
template<typename T> inline auto Multiply(const T* xdata, uint xrows, uint xcols, const T* ydata, uint yrows, uint ycols) -> vector<T> {
vector<T> output;
output.resize(xrows * ycols);
Multiply(output.data(), xdata, xrows, xcols, ydata, yrows, ycols);

View File

@ -30,11 +30,11 @@ inline auto program() -> string {
GetModuleFileName(nullptr, path, PATH_MAX);
string result = (const char*)utf8_t(path);
result.transform("\\", "/");
return real(result);
return Path::real(result);
#else
Dl_info info;
dladdr((void*)&program, &info);
return real(info.dli_fname);
return Path::real(info.dli_fname);
#endif
}
@ -78,9 +78,9 @@ inline auto config() -> string {
string result = (const char*)utf8_t(path);
result.transform("\\", "/");
#elif defined(PLATFORM_MACOSX)
string result = {user(), "Library/Application Support/"};
string result = {Path::user(), "Library/Application Support/"};
#else
string result = {user(), ".config/"};
string result = {Path::user(), ".config/"};
#endif
if(!result) result = ".";
if(!result.endsWith("/")) result.append("/");
@ -96,9 +96,9 @@ inline auto local() -> string {
string result = (const char*)utf8_t(path);
result.transform("\\", "/");
#elif defined(PLATFORM_MACOSX)
string result = {user(), "Library/Application Support/"};
string result = {Path::user(), "Library/Application Support/"};
#else
string result = {user(), ".local/share/"};
string result = {Path::user(), ".local/share/"};
#endif
if(!result) result = ".";
if(!result.endsWith("/")) result.append("/");

View File

@ -1,106 +0,0 @@
#pragma once
#include <limits>
#include <nall/function.hpp>
#include <nall/serializer.hpp>
#include <nall/utility.hpp>
namespace nall {
template<typename type_t> auto priority_queue_nocallback(type_t) -> void {}
//priority queue implementation using binary min-heap array;
//does not require normalize() function.
//O(1) find (tick)
//O(log n) append (enqueue)
//O(log n) remove (dequeue)
template<typename type_t> struct priority_queue {
priority_queue(unsigned size, function<void (type_t)> callback = &priority_queue_nocallback<type_t>) : callback(callback) {
heap = new heap_t[size];
heapcapacity = size;
reset();
}
~priority_queue() {
delete[] heap;
}
priority_queue(const priority_queue&) = delete;
auto operator=(const priority_queue&) -> priority_queue& = delete;
inline auto tick(unsigned ticks) -> void {
basecounter += ticks;
while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue());
}
//counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks);
//counter cannot exceed std::numeric_limits<unsigned>::max() >> 1.
auto enqueue(unsigned counter, type_t event) -> void {
unsigned child = heapsize++;
counter += basecounter;
while(child) {
unsigned parent = (child - 1) >> 1;
if(gte(counter, heap[parent].counter)) break;
heap[child].counter = heap[parent].counter;
heap[child].event = heap[parent].event;
child = parent;
}
heap[child].counter = counter;
heap[child].event = event;
}
auto dequeue() -> type_t {
type_t event(heap[0].event);
unsigned parent = 0;
unsigned counter = heap[--heapsize].counter;
while(true) {
unsigned child = (parent << 1) + 1;
if(child >= heapsize) break;
if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++;
if(gte(heap[child].counter, counter)) break;
heap[parent].counter = heap[child].counter;
heap[parent].event = heap[child].event;
parent = child;
}
heap[parent].counter = counter;
heap[parent].event = heap[heapsize].event;
return event;
}
auto reset() -> void {
basecounter = 0;
heapsize = 0;
}
auto serialize(serializer& s) -> void {
s.integer(basecounter);
s.integer(heapsize);
for(unsigned n = 0; n < heapcapacity; n++) {
s.integer(heap[n].counter);
s.integer(heap[n].event);
}
}
private:
function<void (type_t)> callback;
unsigned basecounter;
unsigned heapsize;
unsigned heapcapacity;
struct heap_t {
unsigned counter;
type_t event;
} *heap;
//return true if x is greater than or equal to y
inline auto gte(unsigned x, unsigned y) -> bool {
return x - y < (std::numeric_limits<unsigned>::max() >> 1);
}
};
}

View File

@ -15,11 +15,11 @@ struct RandomNumberGenerator {
struct LinearFeedbackShiftRegisterGenerator : RandomNumberGenerator {
auto seed(uint64_t seed) -> void {
lfsr = seed;
for(unsigned n = 0; n < 8; n++) operator()();
for(uint n = 0; n < 8; n++) operator()();
}
auto operator()() -> uint64_t {
return lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & crc64jones);
return lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & crc64);
}
auto serialize(serializer& s) -> void {
@ -27,9 +27,8 @@ struct LinearFeedbackShiftRegisterGenerator : RandomNumberGenerator {
}
private:
static const uint64_t crc64ecma = 0x42f0e1eba9ea3693;
static const uint64_t crc64jones = 0xad93d23594c935a9;
uint64_t lfsr = crc64ecma;
static const uint64_t crc64 = 0xc96c'5795'd787'0f42;
uint64_t lfsr = crc64;
};
inline auto random() -> uint64_t {

View File

@ -26,7 +26,7 @@ template<typename T> struct set {
};
node_t* root = nullptr;
unsigned nodes = 0;
uint nodes = 0;
set() = default;
set(const set& source) { operator=(source); }
@ -50,7 +50,7 @@ template<typename T> struct set {
}
explicit operator bool() const { return nodes; }
auto size() const -> unsigned { return nodes; }
auto size() const -> uint { return nodes; }
auto reset() -> void {
reset(root);
@ -68,7 +68,7 @@ template<typename T> struct set {
}
auto insert(const T& value) -> maybe<T&> {
unsigned count = size();
uint count = size();
node_t* v = insert(root, value);
root->red = 0;
if(size() == count) return nothing;
@ -82,7 +82,7 @@ template<typename T> struct set {
}
auto remove(const T& value) -> bool {
unsigned count = size();
uint count = size();
bool done = 0;
remove(root, &value, done);
if(root) root->red = 0;
@ -112,7 +112,7 @@ template<typename T> struct set {
return *this;
}
base_iterator(const set& source, unsigned position) : source(source), position(position) {
base_iterator(const set& source, uint position) : source(source), position(position) {
node_t* node = source.root;
while(node) {
stack.append(node);
@ -122,12 +122,12 @@ template<typename T> struct set {
protected:
const set& source;
unsigned position;
uint position;
vector<node_t*> stack;
};
struct iterator : base_iterator {
iterator(const set& source, unsigned position) : base_iterator(source, position) {}
iterator(const set& source, uint position) : base_iterator(source, position) {}
auto operator*() const -> T& { return base_iterator::stack.right()->value; }
};
@ -135,7 +135,7 @@ template<typename T> struct set {
auto end() -> iterator { return iterator(*this, size()); }
struct const_iterator : base_iterator {
const_iterator(const set& source, unsigned position) : base_iterator(source, position) {}
const_iterator(const set& source, uint position) : base_iterator(source, position) {}
auto operator*() const -> const T& { return base_iterator::stack.right()->value; }
};

View File

@ -18,14 +18,14 @@
namespace nall {
struct SMTP {
enum class Format : unsigned { Plain, HTML };
enum class Format : uint { Plain, HTML };
inline auto server(string server, uint16_t port = 25) -> void;
inline auto from(string mail, string name = "") -> void;
inline auto to(string mail, string name = "") -> void;
inline auto cc(string mail, string name = "") -> void;
inline auto bcc(string mail, string name = "") -> void;
inline auto attachment(const uint8_t* data, unsigned size, string name) -> void;
inline auto attachment(const uint8_t* data, uint size, string name) -> void;
inline auto attachment(string filename, string name = "") -> bool;
inline auto subject(string subject) -> void;
inline auto body(string body, Format format = Format::Plain) -> void;
@ -94,7 +94,7 @@ auto SMTP::bcc(string mail, string name) -> void {
info.bcc.append({mail, name});
}
auto SMTP::attachment(const uint8_t* data, unsigned size, string name) -> void {
auto SMTP::attachment(const uint8_t* data, uint size, string name) -> void {
vector<uint8_t> buffer;
buffer.resize(size);
memcpy(buffer.data(), data, size);
@ -223,7 +223,7 @@ auto SMTP::response() -> string {
auto SMTP::send(int sock, const string& text) -> bool {
const char* data = text.data();
unsigned size = text.size();
uint size = text.size();
while(size) {
int length = ::send(sock, (const char*)data, size, 0);
if(length == -1) return false;
@ -249,7 +249,7 @@ auto SMTP::boundary() -> string {
random_lfsr random;
random.seed(time(0));
string boundary;
for(unsigned n = 0; n < 16; n++) boundary.append(hex<2>(random()));
for(uint n = 0; n < 16; n++) boundary.append(hex<2>(random()));
return boundary;
}
@ -279,9 +279,9 @@ auto SMTP::contacts(const vector<Information::Contact>& contacts) -> string {
auto SMTP::split(const string& text) -> string {
string result;
unsigned offset = 0;
uint offset = 0;
while(offset < text.size()) {
unsigned length = min(76, text.size() - offset);
uint length = min(76, text.size() - offset);
if(length < 76) {
result.append(text.slice(offset));
} else {

View File

@ -19,13 +19,13 @@
namespace nall {
template<typename T, typename Comparator> auto sort(T list[], unsigned size, const Comparator& lessthan) -> void {
template<typename T, typename Comparator> auto sort(T list[], uint size, const Comparator& lessthan) -> void {
if(size <= 1) return; //nothing to sort
//use insertion sort to quickly sort smaller blocks
if(size < 64) {
#if defined(NALL_SORT_INSERTION)
for(signed i = 1, j; i < size; i++) {
for(int i = 1, j; i < size; i++) {
T copy = std::move(list[i]);
for(j = i - 1; j >= 0; j--) {
if(!lessthan(copy, list[j])) break;
@ -34,9 +34,9 @@ template<typename T, typename Comparator> auto sort(T list[], unsigned size, con
list[j + 1] = std::move(copy);
}
#elif defined(NALL_SORT_SELECTION)
for(unsigned i = 0; i < size; i++) {
unsigned min = i;
for(unsigned j = i + 1; j < size; j++) {
for(uint i = 0; i < size; i++) {
uint min = i;
for(uint j = i + 1; j < size; j++) {
if(lessthan(list[j], list[min])) min = j;
}
if(min != i) std::swap(list[i], list[min]);
@ -46,13 +46,13 @@ template<typename T, typename Comparator> auto sort(T list[], unsigned size, con
}
//split list in half and recursively sort both
unsigned middle = size / 2;
uint middle = size / 2;
sort(list, middle, lessthan);
sort(list + middle, size - middle, lessthan);
//left and right are sorted here; perform merge sort
T* buffer = new T[size];
unsigned offset = 0, left = 0, right = middle;
uint offset = 0, left = 0, right = middle;
while(left < middle && right < size) {
if(!lessthan(list[right], list[left])) {
buffer[offset++] = std::move(list[left++]);
@ -63,11 +63,11 @@ template<typename T, typename Comparator> auto sort(T list[], unsigned size, con
while(left < middle) buffer[offset++] = std::move(list[left++]);
while(right < size) buffer[offset++] = std::move(list[right++]);
for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]);
for(uint i = 0; i < size; i++) list[i] = std::move(buffer[i]);
delete[] buffer;
}
template<typename T> auto sort(T list[], unsigned size) -> void {
template<typename T> auto sort(T list[], uint size) -> void {
return sort(list, size, [](const T& l, const T& r) { return l < r; });
}

View File

@ -19,13 +19,13 @@ namespace nall {
struct thread {
inline auto join() -> void;
static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, unsigned stacksize = 0) -> thread;
static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
static inline auto detach() -> void;
static inline auto exit() -> void;
struct context {
function<void (uintptr_t)> callback;
uintptr_t parameter = 0;
function<auto (uintptr) -> void> callback;
uintptr parameter = 0;
};
private:
@ -43,7 +43,7 @@ auto thread::join() -> void {
pthread_join(handle, nullptr);
}
auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, unsigned stacksize) -> thread {
auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
thread instance;
auto context = new thread::context;
@ -76,13 +76,13 @@ struct thread {
inline ~thread();
inline auto join() -> void;
static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, unsigned stacksize = 0) -> thread;
static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
static inline auto detach() -> void;
static inline auto exit() -> void;
struct context {
function<void (uintptr_t)> callback;
uintptr_t parameter = 0;
function<auto (uintptr) -> void> callback;
uintptr parameter = 0;
};
private:
@ -111,7 +111,7 @@ auto thread::join() -> void {
}
}
auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, unsigned stacksize) -> thread {
auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
thread instance;
auto context = new thread::context;

View File

@ -9,9 +9,9 @@ template<typename T> struct base_from_member {
T value;
};
template<typename T> inline auto allocate(unsigned size, const T& value) -> T* {
template<typename T> inline auto allocate(uint size, const T& value) -> T* {
T* array = new T[size];
for(unsigned i = 0; i < size; i++) array[i] = value;
for(uint i = 0; i < size; i++) array[i] = value;
return array;
}

View File

@ -10,8 +10,8 @@ struct varint {
virtual auto read() -> uint8_t = 0;
virtual auto write(uint8_t) -> void = 0;
auto readvu() -> uintmax_t {
uintmax_t data = 0, shift = 1;
auto readvu() -> uintmax {
uintmax data = 0, shift = 1;
while(true) {
uint8_t x = read();
data += (x & 0x7f) * shift;
@ -22,15 +22,15 @@ struct varint {
return data;
}
auto readvs() -> intmax_t {
uintmax_t data = readvu();
auto readvs() -> intmax {
uintmax data = readvu();
bool negate = data & 1;
data >>= 1;
if(negate) data = ~data;
return data;
}
auto writevu(uintmax_t data) -> void {
auto writevu(uintmax data) -> void {
while(true) {
uint8_t x = data & 0x7f;
data >>= 7;
@ -40,7 +40,7 @@ struct varint {
}
}
auto writevs(intmax_t data) -> void {
auto writevs(intmax data) -> void {
bool negate = data < 0;
if(negate) data = ~data;
data = (data << 1) | negate;

View File

@ -1,27 +1,17 @@
#pragma once
#include <nall/random.hpp>
#include <nall/string.hpp>
namespace nall {
//generate unique GUID
inline auto guid() -> string {
LinearFeedbackShiftRegisterGenerator lfsr;
lfsr.seed(time(nullptr));
for(uint n = 0; n < 256; n++) lfsr();
GUID guidInstance;
CoCreateGuid(&guidInstance);
string output;
for(uint n = 0; n < 4; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(uint n = 0; n < 2; n++) output.append(hex(lfsr(), 2L));
output.append("-");
for(uint n = 0; n < 6; n++) output.append(hex(lfsr(), 2L));
return {"{", output, "}"};
wchar_t guidString[39];
StringFromGUID2(guidInstance, guidString, 39);
return (char*)utf8_t(guidString);
}
}

View File

@ -77,7 +77,7 @@ namespace nall {
inline auto utf8_args(int& argc, char**& argv) -> void {
wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
argv = new char*[argc];
argv = new char*[argc + 1]();
for(uint i = 0; i < argc; i++) {
argv[i] = new char[PATH_MAX];
strcpy(argv[i], nall::utf8_t(wargv[i]));

View File

@ -1,6 +1,5 @@
#include "xaudio2.hpp"
#include <windows.h>
#include <audioclient.h>
struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback {
~AudioXAudio2() { term(); }

View File

@ -6,14 +6,15 @@
#define GUID_EXT EXTERN_C
#define GUID_SECT
#include <BaseTyps.h>
#include <audioclient.h>
#include <basetyps.h>
#define DEFINE_GUID_X(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) GUID_EXT const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#define DEFINE_GUID_X(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) GUID_EXT const GUID n GUID_SECT = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
#define DEFINE_CLSID_X(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID_X(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define DEFINE_IID_X(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID_X(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define X2DEFAULT(x) =x
#define X2DEFAULT(x) = x
DEFINE_CLSID_X(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08);
DEFINE_CLSID_X(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd);
@ -28,34 +29,30 @@ DECLARE_INTERFACE(IXAudio2Voice);
#define XAUDIO2_DEBUG_ENGINE 0x0001
#define XAUDIO2_VOICE_NOSRC 0x0004
typedef enum XAUDIO2_DEVICE_ROLE
{
typedef enum XAUDIO2_DEVICE_ROLE {
NotDefaultDevice = 0x0,
DefaultConsoleDevice = 0x1,
DefaultMultimediaDevice = 0x2,
DefaultCommunicationsDevice = 0x4,
DefaultGameDevice = 0x8,
GlobalDefaultDevice = 0xf,
InvalidDeviceRole = ~GlobalDefaultDevice
InvalidDeviceRole = ~GlobalDefaultDevice,
} XAUDIO2_DEVICE_ROLE;
typedef struct XAUDIO2_DEVICE_DETAILS
{
typedef struct XAUDIO2_DEVICE_DETAILS {
WCHAR DeviceID[256];
WCHAR DisplayName[256];
XAUDIO2_DEVICE_ROLE Role;
WAVEFORMATEXTENSIBLE OutputFormat;
} XAUDIO2_DEVICE_DETAILS;
typedef struct XAUDIO2_VOICE_DETAILS
{
typedef struct XAUDIO2_VOICE_DETAILS {
UINT32 CreationFlags;
UINT32 InputChannels;
UINT32 InputSampleRate;
} XAUDIO2_VOICE_DETAILS;
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER
{
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER {
Processor1 = 0x00000001,
Processor2 = 0x00000002,
Processor3 = 0x00000004,
@ -89,45 +86,38 @@ typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER
Processor31 = 0x40000000,
Processor32 = 0x80000000,
XAUDIO2_ANY_PROCESSOR = 0xffffffff,
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR,
} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR;
typedef struct XAUDIO2_VOICE_SENDS
{
typedef struct XAUDIO2_VOICE_SENDS {
UINT32 OutputCount;
IXAudio2Voice** pOutputVoices;
} XAUDIO2_VOICE_SENDS;
typedef struct XAUDIO2_EFFECT_DESCRIPTOR
{
typedef struct XAUDIO2_EFFECT_DESCRIPTOR {
IUnknown* pEffect;
BOOL InitialState;
UINT32 OutputChannels;
} XAUDIO2_EFFECT_DESCRIPTOR;
typedef struct XAUDIO2_EFFECT_CHAIN
{
typedef struct XAUDIO2_EFFECT_CHAIN {
UINT32 EffectCount;
const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors;
} XAUDIO2_EFFECT_CHAIN;
typedef enum XAUDIO2_FILTER_TYPE
{
typedef enum XAUDIO2_FILTER_TYPE {
LowPassFilter,
BandPassFilter,
HighPassFilter
HighPassFilter,
} XAUDIO2_FILTER_TYPE;
typedef struct XAUDIO2_FILTER_PARAMETERS
{
typedef struct XAUDIO2_FILTER_PARAMETERS {
XAUDIO2_FILTER_TYPE Type;
float Frequency;
float OneOverQ;
} XAUDIO2_FILTER_PARAMETERS;
typedef struct XAUDIO2_BUFFER
{
typedef struct XAUDIO2_BUFFER {
UINT32 Flags;
UINT32 AudioBytes;
const BYTE* pAudioData;
@ -139,21 +129,18 @@ typedef struct XAUDIO2_BUFFER
void* pContext;
} XAUDIO2_BUFFER;
typedef struct XAUDIO2_BUFFER_WMA
{
typedef struct XAUDIO2_BUFFER_WMA {
const UINT32* pDecodedPacketCumulativeBytes;
UINT32 PacketCount;
} XAUDIO2_BUFFER_WMA;
typedef struct XAUDIO2_VOICE_STATE
{
typedef struct XAUDIO2_VOICE_STATE {
void* pCurrentBufferContext;
UINT32 BuffersQueued;
UINT64 SamplesPlayed;
} XAUDIO2_VOICE_STATE;
typedef struct XAUDIO2_PERFORMANCE_DATA
{
typedef struct XAUDIO2_PERFORMANCE_DATA {
UINT64 AudioCyclesSinceLastQuery;
UINT64 TotalCyclesSinceLastQuery;
UINT32 MinimumCyclesPerQuantum;
@ -169,8 +156,7 @@ typedef struct XAUDIO2_PERFORMANCE_DATA
UINT32 ActiveXmaStreams;
} XAUDIO2_PERFORMANCE_DATA;
typedef struct XAUDIO2_DEBUG_CONFIGURATION
{
typedef struct XAUDIO2_DEBUG_CONFIGURATION {
UINT32 TraceMask;
UINT32 BreakMask;
BOOL LogThreadID;
@ -179,15 +165,13 @@ typedef struct XAUDIO2_DEBUG_CONFIGURATION
BOOL LogTiming;
} XAUDIO2_DEBUG_CONFIGURATION;
DECLARE_INTERFACE(IXAudio2EngineCallback)
{
DECLARE_INTERFACE(IXAudio2EngineCallback) {
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
};
DECLARE_INTERFACE(IXAudio2VoiceCallback)
{
DECLARE_INTERFACE(IXAudio2VoiceCallback) {
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE;
STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnStreamEnd) (THIS) PURE;
@ -197,8 +181,7 @@ DECLARE_INTERFACE(IXAudio2VoiceCallback)
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE;
};
DECLARE_INTERFACE(IXAudio2Voice)
{
DECLARE_INTERFACE(IXAudio2Voice) {
#define Declare_IXAudio2Voice_Methods() \
STDMETHOD_(void, GetVoiceDetails) (THIS_ XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \
STDMETHOD(SetOutputVoices) (THIS_ const XAUDIO2_VOICE_SENDS* pSendList) PURE; \
@ -235,19 +218,15 @@ DECLARE_INTERFACE(IXAudio2Voice)
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice)
{
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) {
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice)
{
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) {
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice)
{
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) {
Declare_IXAudio2Voice_Methods();
STDMETHOD(Start) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(Stop) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
@ -261,8 +240,7 @@ DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice)
STDMETHOD_(void, GetFrequencyRatio) (THIS_ float* pRatio) PURE;
};
DECLARE_INTERFACE_(IXAudio2, IUnknown)
{
DECLARE_INTERFACE_(IXAudio2, IUnknown) {
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void** ppvInterface) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
@ -298,20 +276,15 @@ DECLARE_INTERFACE_(IXAudio2, IUnknown)
};
__inline HRESULT XAudio2Create(IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0),
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR))
{
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) {
IXAudio2* pXAudio2;
HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2,
NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2);
if (SUCCEEDED(hr))
{
if(SUCCEEDED(hr)) {
hr = pXAudio2->Initialize(Flags, XAudio2Processor);
if (SUCCEEDED(hr))
{
if(SUCCEEDED(hr)) {
*ppXAudio2 = pXAudio2;
}
else
{
} else {
pXAudio2->Release();
}
}