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 { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -17,13 +17,13 @@ struct Interface {
} capability; } capability;
} information; } information;
struct Media { struct Medium {
uint id; uint id;
string name; string name;
string type; string type;
bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges) bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges)
}; };
vector<Media> media; vector<Medium> media;
struct Device { struct Device {
uint id; uint id;
@ -35,16 +35,15 @@ struct Interface {
string name; string name;
uintptr guid; //user data field uintptr guid; //user data field
}; };
vector<Input> input; vector<Input> inputs;
vector<uint> order;
}; };
struct Port { struct Port {
uint id; uint id;
string name; string name;
vector<Device> device; vector<Device> devices;
}; };
vector<Port> port; vector<Port> ports;
struct Bind { struct Bind {
virtual auto loadRequest(uint, string, string, bool) -> void {} 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 { 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; bool result = 0;
if(port == 0) { if(port == 0) {
if(port1 == Device::Joypad) { if(port1 == Device::Joypad) {
if(counter1 >= 8) return 1; if(counter1 >= 8) return 1;
result = interface->inputPoll(0, 0u, counter1); result = interface->inputPoll(0, 0u, lookup[counter1]);
if(latchdata == 0) counter1++; if(latchdata == 0) counter1++;
} }
} }
@ -28,7 +31,7 @@ auto Input::data(bool port) -> bool {
if(port == 1) { if(port == 1) {
if(port2 == Device::Joypad) { if(port2 == Device::Joypad) {
if(counter2 >= 8) return 1; if(counter2 >= 8) return 1;
result = interface->inputPoll(1, 0u, counter2); result = interface->inputPoll(1, 0u, lookup[counter2]);
if(latchdata == 0) counter2++; if(latchdata == 0) counter2++;
} }
} }

View File

@ -22,25 +22,24 @@ Interface::Interface() {
media.append({ID::Famicom, "Famicom", "fc", true}); media.append({ID::Famicom, "Famicom", "fc", true});
{ Device device{0, ID::Port1 | ID::Port2, "Controller"}; { Device device{0, ID::Port1 | ID::Port2, "Controller"};
device.input.append({0, 0, "A" }); device.inputs.append({0, 0, "Up" });
device.input.append({1, 0, "B" }); device.inputs.append({1, 0, "Down" });
device.input.append({2, 0, "Select"}); device.inputs.append({2, 0, "Left" });
device.input.append({3, 0, "Start" }); device.inputs.append({3, 0, "Right" });
device.input.append({4, 0, "Up" }); device.inputs.append({4, 0, "B" });
device.input.append({5, 0, "Down" }); device.inputs.append({5, 0, "A" });
device.input.append({6, 0, "Left" }); device.inputs.append({6, 0, "Select"});
device.input.append({7, 0, "Right" }); device.inputs.append({7, 0, "Start" });
device.order = {4, 5, 6, 7, 1, 0, 2, 3}; devices.append(device);
this->device.append(device);
} }
port.append({0, "Port 1"}); ports.append({0, "Port 1"});
port.append({1, "Port 2"}); ports.append({1, "Port 2"});
for(auto& device : this->device) { for(auto& device : devices) {
for(auto& port : this->port) { for(auto& port : ports) {
if(device.portmask & (1 << port.id)) { 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; v *= brightness / 12.0;
y += v; y += v;
i += v * std::cos((3.141592653 / 6.0) * (p + hue)); i += v * cos((3.141592653 / 6.0) * (p + hue));
q += v * std::sin((3.141592653 / 6.0) * (p + hue)); q += v * sin((3.141592653 / 6.0) * (p + hue));
} }
i *= saturation; i *= saturation;
q *= 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 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 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)); 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; auto set(const string& name, const any& value) -> bool override;
private: private:
vector<Device> device; vector<Device> devices;
}; };
struct Settings { struct Settings {

View File

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

View File

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

View File

@ -91,12 +91,15 @@ auto CPU::sync_step(uint clocks) -> void {
} }
auto CPU::keypad_run() -> 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 bool test = regs.keypad.control.condition; //0 = OR, 1 = AND
for(auto n : range(10)) { for(auto n : range(10)) {
if(regs.keypad.control.flag[n] == false) continue; if(!regs.keypad.control.flag[n]) continue;
bool input = interface->inputPoll(0, 0, n); bool input = interface->inputPoll(0, 0, lookup[n]);
if(regs.keypad.control.condition == 0) test |= input; if(regs.keypad.control.condition == 0) test |= input;
if(regs.keypad.control.condition == 1) test &= input; if(regs.keypad.control.condition == 1) test &= input;
} }

View File

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

View File

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

View File

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

View File

@ -1,327 +1,327 @@
auto R65816::op_adc_b() { auto R65816::op_adc_b() {
int result; int result;
if(!regs.p.d) { if(!r.p.d) {
result = regs.a.l + rd.l + regs.p.c; result = r.a.l + rd.l + r.p.c;
} else { } 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; if(result > 0x09) result += 0x06;
regs.p.c = result > 0x0f; r.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (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; r.p.v = ~(r.a.l ^ rd.l) & (r.a.l ^ result) & 0x80;
if(regs.p.d && result > 0x9f) result += 0x60; if(r.p.d && result > 0x9f) result += 0x60;
regs.p.c = result > 0xff; r.p.c = result > 0xff;
regs.p.n = result & 0x80; r.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0; r.p.z = (uint8)result == 0;
regs.a.l = result; r.a.l = result;
} }
auto R65816::op_adc_w() { auto R65816::op_adc_w() {
int result; int result;
if(!regs.p.d) { if(!r.p.d) {
result = regs.a.w + rd.w + regs.p.c; result = r.a.w + rd.w + r.p.c;
} else { } 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; if(result > 0x0009) result += 0x0006;
regs.p.c = result > 0x000f; r.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f); result = (r.a.w & 0x00f0) + (rd.w & 0x00f0) + (r.p.c << 4) + (result & 0x000f);
if(result > 0x009f) result += 0x0060; if(result > 0x009f) result += 0x0060;
regs.p.c = result > 0x00ff; r.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff); result = (r.a.w & 0x0f00) + (rd.w & 0x0f00) + (r.p.c << 8) + (result & 0x00ff);
if(result > 0x09ff) result += 0x0600; if(result > 0x09ff) result += 0x0600;
regs.p.c = result > 0x0fff; r.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (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; r.p.v = ~(r.a.w ^ rd.w) & (r.a.w ^ result) & 0x8000;
if(regs.p.d && result > 0x9fff) result += 0x6000; if(r.p.d && result > 0x9fff) result += 0x6000;
regs.p.c = result > 0xffff; r.p.c = result > 0xffff;
regs.p.n = result & 0x8000; r.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0; r.p.z = (uint16)result == 0;
regs.a.w = result; r.a.w = result;
} }
auto R65816::op_and_b() { auto R65816::op_and_b() {
regs.a.l &= rd.l; r.a.l &= rd.l;
regs.p.n = regs.a.l & 0x80; r.p.n = r.a.l & 0x80;
regs.p.z = regs.a.l == 0; r.p.z = r.a.l == 0;
} }
auto R65816::op_and_w() { auto R65816::op_and_w() {
regs.a.w &= rd.w; r.a.w &= rd.w;
regs.p.n = regs.a.w & 0x8000; r.p.n = r.a.w & 0x8000;
regs.p.z = regs.a.w == 0; r.p.z = r.a.w == 0;
} }
auto R65816::op_bit_b() { auto R65816::op_bit_b() {
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.v = rd.l & 0x40; r.p.v = rd.l & 0x40;
regs.p.z = (rd.l & regs.a.l) == 0; r.p.z = (rd.l & r.a.l) == 0;
} }
auto R65816::op_bit_w() { auto R65816::op_bit_w() {
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.v = rd.w & 0x4000; r.p.v = rd.w & 0x4000;
regs.p.z = (rd.w & regs.a.w) == 0; r.p.z = (rd.w & r.a.w) == 0;
} }
auto R65816::op_cmp_b() { auto R65816::op_cmp_b() {
int r = regs.a.l - rd.l; int result = r.a.l - rd.l;
regs.p.n = r & 0x80; r.p.n = result & 0x80;
regs.p.z = (uint8)r == 0; r.p.z = (uint8)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_cmp_w() { auto R65816::op_cmp_w() {
int r = regs.a.w - rd.w; int result = r.a.w - rd.w;
regs.p.n = r & 0x8000; r.p.n = result & 0x8000;
regs.p.z = (uint16)r == 0; r.p.z = (uint16)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_cpx_b() { auto R65816::op_cpx_b() {
int r = regs.x.l - rd.l; int result = r.x.l - rd.l;
regs.p.n = r & 0x80; r.p.n = result & 0x80;
regs.p.z = (uint8)r == 0; r.p.z = (uint8)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_cpx_w() { auto R65816::op_cpx_w() {
int r = regs.x.w - rd.w; int result = r.x.w - rd.w;
regs.p.n = r & 0x8000; r.p.n = result & 0x8000;
regs.p.z = (uint16)r == 0; r.p.z = (uint16)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_cpy_b() { auto R65816::op_cpy_b() {
int r = regs.y.l - rd.l; int result = r.y.l - rd.l;
regs.p.n = r & 0x80; r.p.n = result & 0x80;
regs.p.z = (uint8)r == 0; r.p.z = (uint8)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_cpy_w() { auto R65816::op_cpy_w() {
int r = regs.y.w - rd.w; int result = r.y.w - rd.w;
regs.p.n = r & 0x8000; r.p.n = result & 0x8000;
regs.p.z = (uint16)r == 0; r.p.z = (uint16)result == 0;
regs.p.c = r >= 0; r.p.c = result >= 0;
} }
auto R65816::op_eor_b() { auto R65816::op_eor_b() {
regs.a.l ^= rd.l; r.a.l ^= rd.l;
regs.p.n = regs.a.l & 0x80; r.p.n = r.a.l & 0x80;
regs.p.z = regs.a.l == 0; r.p.z = r.a.l == 0;
} }
auto R65816::op_eor_w() { auto R65816::op_eor_w() {
regs.a.w ^= rd.w; r.a.w ^= rd.w;
regs.p.n = regs.a.w & 0x8000; r.p.n = r.a.w & 0x8000;
regs.p.z = regs.a.w == 0; r.p.z = r.a.w == 0;
} }
auto R65816::op_lda_b() { auto R65816::op_lda_b() {
regs.a.l = rd.l; r.a.l = rd.l;
regs.p.n = regs.a.l & 0x80; r.p.n = r.a.l & 0x80;
regs.p.z = regs.a.l == 0; r.p.z = r.a.l == 0;
} }
auto R65816::op_lda_w() { auto R65816::op_lda_w() {
regs.a.w = rd.w; r.a.w = rd.w;
regs.p.n = regs.a.w & 0x8000; r.p.n = r.a.w & 0x8000;
regs.p.z = regs.a.w == 0; r.p.z = r.a.w == 0;
} }
auto R65816::op_ldx_b() { auto R65816::op_ldx_b() {
regs.x.l = rd.l; r.x.l = rd.l;
regs.p.n = regs.x.l & 0x80; r.p.n = r.x.l & 0x80;
regs.p.z = regs.x.l == 0; r.p.z = r.x.l == 0;
} }
auto R65816::op_ldx_w() { auto R65816::op_ldx_w() {
regs.x.w = rd.w; r.x.w = rd.w;
regs.p.n = regs.x.w & 0x8000; r.p.n = r.x.w & 0x8000;
regs.p.z = regs.x.w == 0; r.p.z = r.x.w == 0;
} }
auto R65816::op_ldy_b() { auto R65816::op_ldy_b() {
regs.y.l = rd.l; r.y.l = rd.l;
regs.p.n = regs.y.l & 0x80; r.p.n = r.y.l & 0x80;
regs.p.z = regs.y.l == 0; r.p.z = r.y.l == 0;
} }
auto R65816::op_ldy_w() { auto R65816::op_ldy_w() {
regs.y.w = rd.w; r.y.w = rd.w;
regs.p.n = regs.y.w & 0x8000; r.p.n = r.y.w & 0x8000;
regs.p.z = regs.y.w == 0; r.p.z = r.y.w == 0;
} }
auto R65816::op_ora_b() { auto R65816::op_ora_b() {
regs.a.l |= rd.l; r.a.l |= rd.l;
regs.p.n = regs.a.l & 0x80; r.p.n = r.a.l & 0x80;
regs.p.z = regs.a.l == 0; r.p.z = r.a.l == 0;
} }
auto R65816::op_ora_w() { auto R65816::op_ora_w() {
regs.a.w |= rd.w; r.a.w |= rd.w;
regs.p.n = regs.a.w & 0x8000; r.p.n = r.a.w & 0x8000;
regs.p.z = regs.a.w == 0; r.p.z = r.a.w == 0;
} }
auto R65816::op_sbc_b() { auto R65816::op_sbc_b() {
int result; int result;
rd.l ^= 0xff; rd.l ^= 0xff;
if(!regs.p.d) { if(!r.p.d) {
result = regs.a.l + rd.l + regs.p.c; result = r.a.l + rd.l + r.p.c;
} else { } 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; if(result <= 0x0f) result -= 0x06;
regs.p.c = result > 0x0f; r.p.c = result > 0x0f;
result = (regs.a.l & 0xf0) + (rd.l & 0xf0) + (regs.p.c << 4) + (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; r.p.v = ~(r.a.l ^ rd.l) & (r.a.l ^ result) & 0x80;
if(regs.p.d && result <= 0xff) result -= 0x60; if(r.p.d && result <= 0xff) result -= 0x60;
regs.p.c = result > 0xff; r.p.c = result > 0xff;
regs.p.n = result & 0x80; r.p.n = result & 0x80;
regs.p.z = (uint8_t)result == 0; r.p.z = (uint8_t)result == 0;
regs.a.l = result; r.a.l = result;
} }
auto R65816::op_sbc_w() { auto R65816::op_sbc_w() {
int result; int result;
rd.w ^= 0xffff; rd.w ^= 0xffff;
if(!regs.p.d) { if(!r.p.d) {
result = regs.a.w + rd.w + regs.p.c; result = r.a.w + rd.w + r.p.c;
} else { } 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; if(result <= 0x000f) result -= 0x0006;
regs.p.c = result > 0x000f; r.p.c = result > 0x000f;
result = (regs.a.w & 0x00f0) + (rd.w & 0x00f0) + (regs.p.c << 4) + (result & 0x000f); result = (r.a.w & 0x00f0) + (rd.w & 0x00f0) + (r.p.c << 4) + (result & 0x000f);
if(result <= 0x00ff) result -= 0x0060; if(result <= 0x00ff) result -= 0x0060;
regs.p.c = result > 0x00ff; r.p.c = result > 0x00ff;
result = (regs.a.w & 0x0f00) + (rd.w & 0x0f00) + (regs.p.c << 8) + (result & 0x00ff); result = (r.a.w & 0x0f00) + (rd.w & 0x0f00) + (r.p.c << 8) + (result & 0x00ff);
if(result <= 0x0fff) result -= 0x0600; if(result <= 0x0fff) result -= 0x0600;
regs.p.c = result > 0x0fff; r.p.c = result > 0x0fff;
result = (regs.a.w & 0xf000) + (rd.w & 0xf000) + (regs.p.c << 12) + (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; r.p.v = ~(r.a.w ^ rd.w) & (r.a.w ^ result) & 0x8000;
if(regs.p.d && result <= 0xffff) result -= 0x6000; if(r.p.d && result <= 0xffff) result -= 0x6000;
regs.p.c = result > 0xffff; r.p.c = result > 0xffff;
regs.p.n = result & 0x8000; r.p.n = result & 0x8000;
regs.p.z = (uint16_t)result == 0; r.p.z = (uint16_t)result == 0;
regs.a.w = result; r.a.w = result;
} }
auto R65816::op_inc_b() { auto R65816::op_inc_b() {
rd.l++; rd.l++;
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_inc_w() { auto R65816::op_inc_w() {
rd.w++; rd.w++;
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_dec_b() { auto R65816::op_dec_b() {
rd.l--; rd.l--;
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_dec_w() { auto R65816::op_dec_w() {
rd.w--; rd.w--;
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_asl_b() { auto R65816::op_asl_b() {
regs.p.c = rd.l & 0x80; r.p.c = rd.l & 0x80;
rd.l <<= 1; rd.l <<= 1;
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_asl_w() { auto R65816::op_asl_w() {
regs.p.c = rd.w & 0x8000; r.p.c = rd.w & 0x8000;
rd.w <<= 1; rd.w <<= 1;
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_lsr_b() { auto R65816::op_lsr_b() {
regs.p.c = rd.l & 1; r.p.c = rd.l & 1;
rd.l >>= 1; rd.l >>= 1;
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_lsr_w() { auto R65816::op_lsr_w() {
regs.p.c = rd.w & 1; r.p.c = rd.w & 1;
rd.w >>= 1; rd.w >>= 1;
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_rol_b() { auto R65816::op_rol_b() {
unsigned carry = (unsigned)regs.p.c; auto carry = (uint)r.p.c;
regs.p.c = rd.l & 0x80; r.p.c = rd.l & 0x80;
rd.l = (rd.l << 1) | carry; rd.l = (rd.l << 1) | carry;
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_rol_w() { auto R65816::op_rol_w() {
unsigned carry = (unsigned)regs.p.c; auto carry = (uint)r.p.c;
regs.p.c = rd.w & 0x8000; r.p.c = rd.w & 0x8000;
rd.w = (rd.w << 1) | carry; rd.w = (rd.w << 1) | carry;
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_ror_b() { auto R65816::op_ror_b() {
unsigned carry = (unsigned)regs.p.c << 7; auto carry = (uint)r.p.c << 7;
regs.p.c = rd.l & 1; r.p.c = rd.l & 1;
rd.l = carry | (rd.l >> 1); rd.l = carry | (rd.l >> 1);
regs.p.n = rd.l & 0x80; r.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; r.p.z = rd.l == 0;
} }
auto R65816::op_ror_w() { auto R65816::op_ror_w() {
unsigned carry = (unsigned)regs.p.c << 15; auto carry = (uint)r.p.c << 15;
regs.p.c = rd.w & 1; r.p.c = rd.w & 1;
rd.w = carry | (rd.w >> 1); rd.w = carry | (rd.w >> 1);
regs.p.n = rd.w & 0x8000; r.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; r.p.z = rd.w == 0;
} }
auto R65816::op_trb_b() { auto R65816::op_trb_b() {
regs.p.z = (rd.l & regs.a.l) == 0; r.p.z = (rd.l & r.a.l) == 0;
rd.l &= ~regs.a.l; rd.l &= ~r.a.l;
} }
auto R65816::op_trb_w() { auto R65816::op_trb_w() {
regs.p.z = (rd.w & regs.a.w) == 0; r.p.z = (rd.w & r.a.w) == 0;
rd.w &= ~regs.a.w; rd.w &= ~r.a.w;
} }
auto R65816::op_tsb_b() { auto R65816::op_tsb_b() {
regs.p.z = (rd.l & regs.a.l) == 0; r.p.z = (rd.l & r.a.l) == 0;
rd.l |= regs.a.l; rd.l |= r.a.l;
} }
auto R65816::op_tsb_w() { auto R65816::op_tsb_w() {
regs.p.z = (rd.w & regs.a.w) == 0; r.p.z = (rd.w & r.a.w) == 0;
rd.w |= regs.a.w; 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 { auto R65816::decode(uint8 mode, uint24 addr) -> uint24 {
uint24 r = 0; uint24 a = 0;
switch(mode) { switch(mode) {
case OPTYPE_DP: case OPTYPE_DP:
r = (regs.d + (addr & 0xffff)) & 0xffff; a = (r.d + (addr & 0xffff)) & 0xffff;
break; break;
case OPTYPE_DPX: case OPTYPE_DPX:
r = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; a = (r.d + r.x + (addr & 0xffff)) & 0xffff;
break; break;
case OPTYPE_DPY: case OPTYPE_DPY:
r = (regs.d + regs.y + (addr & 0xffff)) & 0xffff; a = (r.d + r.y + (addr & 0xffff)) & 0xffff;
break; break;
case OPTYPE_IDP: case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = (r.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr); a = (r.db << 16) + dreadw(addr);
break; break;
case OPTYPE_IDPX: case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff; addr = (r.d + r.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr); a = (r.db << 16) + dreadw(addr);
break; break;
case OPTYPE_IDPY: case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = (r.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y; a = (r.db << 16) + dreadw(addr) + r.y;
break; break;
case OPTYPE_ILDP: case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = (r.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr); a = dreadl(addr);
break; break;
case OPTYPE_ILDPY: case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff; addr = (r.d + (addr & 0xffff)) & 0xffff;
r = dreadl(addr) + regs.y; a = dreadl(addr) + r.y;
break; break;
case OPTYPE_ADDR: case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff); a = (r.db << 16) + (addr & 0xffff);
break; break;
case OPTYPE_ADDR_PC: case OPTYPE_ADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff); a = (r.pc.b << 16) + (addr & 0xffff);
break; break;
case OPTYPE_ADDRX: case OPTYPE_ADDRX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x; a = (r.db << 16) + (addr & 0xffff) + r.x;
break; break;
case OPTYPE_ADDRY: case OPTYPE_ADDRY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y; a = (r.db << 16) + (addr & 0xffff) + r.y;
break; break;
case OPTYPE_IADDR_PC: case OPTYPE_IADDR_PC:
r = (regs.pc.b << 16) + (addr & 0xffff); a = (r.pc.b << 16) + (addr & 0xffff);
break; break;
case OPTYPE_IADDRX: case OPTYPE_IADDRX:
r = (regs.pc.b << 16) + ((addr + regs.x) & 0xffff); a = (r.pc.b << 16) + ((addr + r.x) & 0xffff);
break; break;
case OPTYPE_ILADDR: case OPTYPE_ILADDR:
r = addr; a = addr;
break; break;
case OPTYPE_LONG: case OPTYPE_LONG:
r = addr; a = addr;
break; break;
case OPTYPE_LONGX: case OPTYPE_LONGX:
r = (addr + regs.x); a = (addr + r.x);
break; break;
case OPTYPE_SR: case OPTYPE_SR:
r = (regs.s + (addr & 0xff)) & 0xffff; a = (r.s + (addr & 0xff)) & 0xffff;
break; break;
case OPTYPE_ISRY: case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff; addr = (r.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y; a = (r.db << 16) + dreadw(addr) + r.y;
break; break;
case OPTYPE_RELB: case OPTYPE_RELB:
r = (regs.pc.b << 16) + ((regs.pc.w + 2) & 0xffff); a = (r.pc.b << 16) + ((r.pc.w + 2) & 0xffff);
r += int8(addr); a += int8(addr);
break; break;
case OPTYPE_RELW: case OPTYPE_RELW:
r = (regs.pc.b << 16) + ((regs.pc.w + 3) & 0xffff); a = (r.pc.b << 16) + ((r.pc.w + 3) & 0xffff);
r += (int16)addr; a += (int16)addr;
break; break;
} }
return r; return a;
} }
auto R65816::disassemble() -> string { 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 { auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
string s; string s;
reg24_t pc; reg24 pc;
pc.d = addr; pc.d = addr;
s = {hex(pc, 6), " "}; s = {hex(pc, 6), " "};
@ -403,23 +403,23 @@ auto R65816::disassemble(uint24 addr, bool e, bool m, bool x) -> string {
#undef x8 #undef x8
s.append(t, " A:{0} X:{1} Y:{2} S:{3} D:{4} B:{5} ", format{ 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(r.a.w, 4), hex(r.x.w, 4), hex(r.y.w, 4),
hex(regs.s.w, 4), hex(regs.d.w, 4), hex(regs.db, 2) hex(r.s.w, 4), hex(r.d.w, 4), hex(r.db, 2)
}); });
if(regs.e) { if(r.e) {
s.append( s.append(
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', r.p.n ? 'N' : 'n', r.p.v ? 'V' : 'v',
regs.p.m ? '1' : '0', regs.p.x ? 'B' : 'b', r.p.m ? '1' : '0', r.p.x ? 'B' : 'b',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', r.p.d ? 'D' : 'd', r.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c' r.p.z ? 'Z' : 'z', r.p.c ? 'C' : 'c'
); );
} else { } else {
s.append( s.append(
regs.p.n ? 'N' : 'n', regs.p.v ? 'V' : 'v', r.p.n ? 'N' : 'n', r.p.v ? 'V' : 'v',
regs.p.m ? 'M' : 'm', regs.p.x ? 'X' : 'x', r.p.m ? 'M' : 'm', r.p.x ? 'X' : 'x',
regs.p.d ? 'D' : 'd', regs.p.i ? 'I' : 'i', r.p.d ? 'D' : 'd', r.p.i ? 'I' : 'i',
regs.p.z ? 'Z' : 'z', regs.p.c ? 'C' : 'c' r.p.z ? 'Z' : 'z', r.p.c ? 'C' : 'c'
); );
} }

View File

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

View File

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

View File

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

View File

@ -1,275 +1,275 @@
auto R65816::op_read_const_b(fp op) { auto R65816::op_read_const_b(fp op) {
L rd.l = readpc(); L rd.l = readPC();
call(op); call(op);
} }
auto R65816::op_read_const_w(fp op) { auto R65816::op_read_const_w(fp op) {
rd.l = readpc(); rd.l = readPC();
L rd.h = readpc(); L rd.h = readPC();
call(op); call(op);
} }
auto R65816::op_read_bit_const_b() { auto R65816::op_read_bit_const_b() {
L rd.l = readpc(); L rd.l = readPC();
regs.p.z = ((rd.l & regs.a.l) == 0); r.p.z = ((rd.l & r.a.l) == 0);
} }
auto R65816::op_read_bit_const_w() { auto R65816::op_read_bit_const_w() {
rd.l = readpc(); rd.l = readPC();
L rd.h = readpc(); L rd.h = readPC();
regs.p.z = ((rd.w & regs.a.w) == 0); r.p.z = ((rd.w & r.a.w) == 0);
} }
auto R65816::op_read_addr_b(fp op) { auto R65816::op_read_addr_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
L rd.l = readdbr(aa.w); L rd.l = readDB(aa.w);
call(op); call(op);
} }
auto R65816::op_read_addr_w(fp op) { auto R65816::op_read_addr_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
rd.l = readdbr(aa.w + 0); rd.l = readDB(aa.w + 0);
L rd.h = readdbr(aa.w + 1); L rd.h = readDB(aa.w + 1);
call(op); call(op);
} }
auto R65816::op_read_addrx_b(fp op) { auto R65816::op_read_addrx_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io4(aa.w, aa.w + regs.x.w); io4(aa.w, aa.w + r.x.w);
L rd.l = readdbr(aa.w + regs.x.w); L rd.l = readDB(aa.w + r.x.w);
call(op); call(op);
} }
auto R65816::op_read_addrx_w(fp op) { auto R65816::op_read_addrx_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io4(aa.w, aa.w + regs.x.w); io4(aa.w, aa.w + r.x.w);
rd.l = readdbr(aa.w + regs.x.w + 0); rd.l = readDB(aa.w + r.x.w + 0);
L rd.h = readdbr(aa.w + regs.x.w + 1); L rd.h = readDB(aa.w + r.x.w + 1);
call(op); call(op);
} }
auto R65816::op_read_addry_b(fp op) { auto R65816::op_read_addry_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io4(aa.w, aa.w + regs.y.w); io4(aa.w, aa.w + r.y.w);
L rd.l = readdbr(aa.w + regs.y.w); L rd.l = readDB(aa.w + r.y.w);
call(op); call(op);
} }
auto R65816::op_read_addry_w(fp op) { auto R65816::op_read_addry_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io4(aa.w, aa.w + regs.y.w); io4(aa.w, aa.w + r.y.w);
rd.l = readdbr(aa.w + regs.y.w + 0); rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1); L rd.h = readDB(aa.w + r.y.w + 1);
call(op); call(op);
} }
auto R65816::op_read_long_b(fp op) { auto R65816::op_read_long_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
aa.b = readpc(); aa.b = readPC();
L rd.l = readlong(aa.d); L rd.l = readLong(aa.d);
call(op); call(op);
} }
auto R65816::op_read_long_w(fp op) { auto R65816::op_read_long_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
aa.b = readpc(); aa.b = readPC();
rd.l = readlong(aa.d + 0); rd.l = readLong(aa.d + 0);
L rd.h = readlong(aa.d + 1); L rd.h = readLong(aa.d + 1);
call(op); call(op);
} }
auto R65816::op_read_longx_b(fp op) { auto R65816::op_read_longx_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
aa.b = readpc(); aa.b = readPC();
L rd.l = readlong(aa.d + regs.x.w); L rd.l = readLong(aa.d + r.x.w);
call(op); call(op);
} }
auto R65816::op_read_longx_w(fp op) { auto R65816::op_read_longx_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
aa.b = readpc(); aa.b = readPC();
rd.l = readlong(aa.d + regs.x.w + 0); rd.l = readLong(aa.d + r.x.w + 0);
L rd.h = readlong(aa.d + regs.x.w + 1); L rd.h = readLong(aa.d + r.x.w + 1);
call(op); call(op);
} }
auto R65816::op_read_dp_b(fp op) { auto R65816::op_read_dp_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
L rd.l = readdp(dp); L rd.l = readDP(dp);
call(op); call(op);
} }
auto R65816::op_read_dp_w(fp op) { auto R65816::op_read_dp_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
rd.l = readdp(dp + 0); rd.l = readDP(dp + 0);
L rd.h = readdp(dp + 1); L rd.h = readDP(dp + 1);
call(op); call(op);
} }
auto R65816::op_read_dpr_b(fp op, reg16_t& reg) { auto R65816::op_read_dpr_b(fp op, reg16& reg) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
L rd.l = readdp(dp + reg.w); L rd.l = readDP(dp + reg.w);
call(op); call(op);
} }
auto R65816::op_read_dpr_w(fp op, reg16_t& reg) { auto R65816::op_read_dpr_w(fp op, reg16& reg) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
rd.l = readdp(dp + reg.w + 0); rd.l = readDP(dp + reg.w + 0);
L rd.h = readdp(dp + reg.w + 1); L rd.h = readDP(dp + reg.w + 1);
call(op); call(op);
} }
auto R65816::op_read_idp_b(fp op) { auto R65816::op_read_idp_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDP(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDP(dp + 1);
L rd.l = readdbr(aa.w); L rd.l = readDB(aa.w);
call(op); call(op);
} }
auto R65816::op_read_idp_w(fp op) { auto R65816::op_read_idp_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDP(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDP(dp + 1);
rd.l = readdbr(aa.w + 0); rd.l = readDB(aa.w + 0);
L rd.h = readdbr(aa.w + 1); L rd.h = readDB(aa.w + 1);
call(op); call(op);
} }
auto R65816::op_read_idpx_b(fp op) { auto R65816::op_read_idpx_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
aa.l = readdp(dp + regs.x.w + 0); aa.l = readDP(dp + r.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1); aa.h = readDP(dp + r.x.w + 1);
L rd.l = readdbr(aa.w); L rd.l = readDB(aa.w);
call(op); call(op);
} }
auto R65816::op_read_idpx_w(fp op) { auto R65816::op_read_idpx_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
aa.l = readdp(dp + regs.x.w + 0); aa.l = readDP(dp + r.x.w + 0);
aa.h = readdp(dp + regs.x.w + 1); aa.h = readDP(dp + r.x.w + 1);
rd.l = readdbr(aa.w + 0); rd.l = readDB(aa.w + 0);
L rd.h = readdbr(aa.w + 1); L rd.h = readDB(aa.w + 1);
call(op); call(op);
} }
auto R65816::op_read_idpy_b(fp op) { auto R65816::op_read_idpy_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDP(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDP(dp + 1);
io4(aa.w, aa.w + regs.y.w); io4(aa.w, aa.w + r.y.w);
L rd.l = readdbr(aa.w + regs.y.w); L rd.l = readDB(aa.w + r.y.w);
call(op); call(op);
} }
auto R65816::op_read_idpy_w(fp op) { auto R65816::op_read_idpy_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDP(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDP(dp + 1);
io4(aa.w, aa.w + regs.y.w); io4(aa.w, aa.w + r.y.w);
rd.l = readdbr(aa.w + regs.y.w + 0); rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1); L rd.h = readDB(aa.w + r.y.w + 1);
call(op); call(op);
} }
auto R65816::op_read_ildp_b(fp op) { auto R65816::op_read_ildp_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDPn(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDPn(dp + 1);
aa.b = readdp(dp + 2); aa.b = readDPn(dp + 2);
L rd.l = readlong(aa.d); L rd.l = readLong(aa.d);
call(op); call(op);
} }
auto R65816::op_read_ildp_w(fp op) { auto R65816::op_read_ildp_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDPn(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDPn(dp + 1);
aa.b = readdp(dp + 2); aa.b = readDPn(dp + 2);
rd.l = readlong(aa.d + 0); rd.l = readLong(aa.d + 0);
L rd.h = readlong(aa.d + 1); L rd.h = readLong(aa.d + 1);
call(op); call(op);
} }
auto R65816::op_read_ildpy_b(fp op) { auto R65816::op_read_ildpy_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDPn(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDPn(dp + 1);
aa.b = readdp(dp + 2); aa.b = readDPn(dp + 2);
L rd.l = readlong(aa.d + regs.y.w); L rd.l = readLong(aa.d + r.y.w);
call(op); call(op);
} }
auto R65816::op_read_ildpy_w(fp op) { auto R65816::op_read_ildpy_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
aa.l = readdp(dp + 0); aa.l = readDPn(dp + 0);
aa.h = readdp(dp + 1); aa.h = readDPn(dp + 1);
aa.b = readdp(dp + 2); aa.b = readDPn(dp + 2);
rd.l = readlong(aa.d + regs.y.w + 0); rd.l = readLong(aa.d + r.y.w + 0);
L rd.h = readlong(aa.d + regs.y.w + 1); L rd.h = readLong(aa.d + r.y.w + 1);
call(op); call(op);
} }
auto R65816::op_read_sr_b(fp op) { auto R65816::op_read_sr_b(fp op) {
sp = readpc(); sp = readPC();
io(); io();
L rd.l = readsp(sp); L rd.l = readSP(sp);
call(op); call(op);
} }
auto R65816::op_read_sr_w(fp op) { auto R65816::op_read_sr_w(fp op) {
sp = readpc(); sp = readPC();
io(); io();
rd.l = readsp(sp + 0); rd.l = readSP(sp + 0);
L rd.h = readsp(sp + 1); L rd.h = readSP(sp + 1);
call(op); call(op);
} }
auto R65816::op_read_isry_b(fp op) { auto R65816::op_read_isry_b(fp op) {
sp = readpc(); sp = readPC();
io(); io();
aa.l = readsp(sp + 0); aa.l = readSP(sp + 0);
aa.h = readsp(sp + 1); aa.h = readSP(sp + 1);
io(); io();
L rd.l = readdbr(aa.w + regs.y.w); L rd.l = readDB(aa.w + r.y.w);
call(op); call(op);
} }
auto R65816::op_read_isry_w(fp op) { auto R65816::op_read_isry_w(fp op) {
sp = readpc(); sp = readPC();
io(); io();
aa.l = readsp(sp + 0); aa.l = readSP(sp + 0);
aa.h = readsp(sp + 1); aa.h = readSP(sp + 1);
io(); io();
rd.l = readdbr(aa.w + regs.y.w + 0); rd.l = readDB(aa.w + r.y.w + 0);
L rd.h = readdbr(aa.w + regs.y.w + 1); L rd.h = readDB(aa.w + r.y.w + 1);
call(op); 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(); L ioIRQ();
reg.l += adjust; reg.l += adjust;
regs.p.n = (reg.l & 0x80); r.p.n = (reg.l & 0x80);
regs.p.z = (reg.l == 0); 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(); L ioIRQ();
reg.w += adjust; reg.w += adjust;
regs.p.n = (reg.w & 0x8000); r.p.n = (reg.w & 0x8000);
regs.p.z = (reg.w == 0); r.p.z = (reg.w == 0);
} }
auto R65816::op_asl_imm_b() { auto R65816::op_asl_imm_b() {
L ioIRQ(); L ioIRQ();
regs.p.c = (regs.a.l & 0x80); r.p.c = (r.a.l & 0x80);
regs.a.l <<= 1; r.a.l <<= 1;
regs.p.n = (regs.a.l & 0x80); r.p.n = (r.a.l & 0x80);
regs.p.z = (regs.a.l == 0); r.p.z = (r.a.l == 0);
} }
auto R65816::op_asl_imm_w() { auto R65816::op_asl_imm_w() {
L ioIRQ(); L ioIRQ();
regs.p.c = (regs.a.w & 0x8000); r.p.c = (r.a.w & 0x8000);
regs.a.w <<= 1; r.a.w <<= 1;
regs.p.n = (regs.a.w & 0x8000); r.p.n = (r.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); r.p.z = (r.a.w == 0);
} }
auto R65816::op_lsr_imm_b() { auto R65816::op_lsr_imm_b() {
L ioIRQ(); L ioIRQ();
regs.p.c = (regs.a.l & 0x01); r.p.c = (r.a.l & 0x01);
regs.a.l >>= 1; r.a.l >>= 1;
regs.p.n = (regs.a.l & 0x80); r.p.n = (r.a.l & 0x80);
regs.p.z = (regs.a.l == 0); r.p.z = (r.a.l == 0);
} }
auto R65816::op_lsr_imm_w() { auto R65816::op_lsr_imm_w() {
L ioIRQ(); L ioIRQ();
regs.p.c = (regs.a.w & 0x0001); r.p.c = (r.a.w & 0x0001);
regs.a.w >>= 1; r.a.w >>= 1;
regs.p.n = (regs.a.w & 0x8000); r.p.n = (r.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); r.p.z = (r.a.w == 0);
} }
auto R65816::op_rol_imm_b() { auto R65816::op_rol_imm_b() {
L ioIRQ(); L ioIRQ();
bool carry = regs.p.c; bool carry = r.p.c;
regs.p.c = (regs.a.l & 0x80); r.p.c = (r.a.l & 0x80);
regs.a.l = (regs.a.l << 1) | carry; r.a.l = (r.a.l << 1) | carry;
regs.p.n = (regs.a.l & 0x80); r.p.n = (r.a.l & 0x80);
regs.p.z = (regs.a.l == 0); r.p.z = (r.a.l == 0);
} }
auto R65816::op_rol_imm_w() { auto R65816::op_rol_imm_w() {
L ioIRQ(); L ioIRQ();
bool carry = regs.p.c; bool carry = r.p.c;
regs.p.c = (regs.a.w & 0x8000); r.p.c = (r.a.w & 0x8000);
regs.a.w = (regs.a.w << 1) | carry; r.a.w = (r.a.w << 1) | carry;
regs.p.n = (regs.a.w & 0x8000); r.p.n = (r.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); r.p.z = (r.a.w == 0);
} }
auto R65816::op_ror_imm_b() { auto R65816::op_ror_imm_b() {
L ioIRQ(); L ioIRQ();
bool carry = regs.p.c; bool carry = r.p.c;
regs.p.c = (regs.a.l & 0x01); r.p.c = (r.a.l & 0x01);
regs.a.l = (carry << 7) | (regs.a.l >> 1); r.a.l = (carry << 7) | (r.a.l >> 1);
regs.p.n = (regs.a.l & 0x80); r.p.n = (r.a.l & 0x80);
regs.p.z = (regs.a.l == 0); r.p.z = (r.a.l == 0);
} }
auto R65816::op_ror_imm_w() { auto R65816::op_ror_imm_w() {
L ioIRQ(); L ioIRQ();
bool carry = regs.p.c; bool carry = r.p.c;
regs.p.c = (regs.a.w & 0x0001); r.p.c = (r.a.w & 0x0001);
regs.a.w = (carry << 15) | (regs.a.w >> 1); r.a.w = (carry << 15) | (r.a.w >> 1);
regs.p.n = (regs.a.w & 0x8000); r.p.n = (r.a.w & 0x8000);
regs.p.z = (regs.a.w == 0); r.p.z = (r.a.w == 0);
} }
auto R65816::op_adjust_addr_b(fp op) { auto R65816::op_adjust_addr_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
rd.l = readdbr(aa.w); rd.l = readDB(aa.w);
io(); io();
call(op); call(op);
L writedbr(aa.w, rd.l); L writeDB(aa.w, rd.l);
} }
auto R65816::op_adjust_addr_w(fp op) { auto R65816::op_adjust_addr_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
rd.l = readdbr(aa.w + 0); rd.l = readDB(aa.w + 0);
rd.h = readdbr(aa.w + 1); rd.h = readDB(aa.w + 1);
io(); io();
call(op); call(op);
writedbr(aa.w + 1, rd.h); writeDB(aa.w + 1, rd.h);
L writedbr(aa.w + 0, rd.l); L writeDB(aa.w + 0, rd.l);
} }
auto R65816::op_adjust_addrx_b(fp op) { auto R65816::op_adjust_addrx_b(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io(); io();
rd.l = readdbr(aa.w + regs.x.w); rd.l = readDB(aa.w + r.x.w);
io(); io();
call(op); 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) { auto R65816::op_adjust_addrx_w(fp op) {
aa.l = readpc(); aa.l = readPC();
aa.h = readpc(); aa.h = readPC();
io(); io();
rd.l = readdbr(aa.w + regs.x.w + 0); rd.l = readDB(aa.w + r.x.w + 0);
rd.h = readdbr(aa.w + regs.x.w + 1); rd.h = readDB(aa.w + r.x.w + 1);
io(); io();
call(op); call(op);
writedbr(aa.w + regs.x.w + 1, rd.h); writeDB(aa.w + r.x.w + 1, rd.h);
L writedbr(aa.w + regs.x.w + 0, rd.l); L writeDB(aa.w + r.x.w + 0, rd.l);
} }
auto R65816::op_adjust_dp_b(fp op) { auto R65816::op_adjust_dp_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
rd.l = readdp(dp); rd.l = readDP(dp);
io(); io();
call(op); call(op);
L writedp(dp, rd.l); L writeDP(dp, rd.l);
} }
auto R65816::op_adjust_dp_w(fp op) { auto R65816::op_adjust_dp_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
rd.l = readdp(dp + 0); rd.l = readDP(dp + 0);
rd.h = readdp(dp + 1); rd.h = readDP(dp + 1);
io(); io();
call(op); call(op);
writedp(dp + 1, rd.h); writeDP(dp + 1, rd.h);
L writedp(dp + 0, rd.l); L writeDP(dp + 0, rd.l);
} }
auto R65816::op_adjust_dpx_b(fp op) { auto R65816::op_adjust_dpx_b(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
rd.l = readdp(dp + regs.x.w); rd.l = readDP(dp + r.x.w);
io(); io();
call(op); 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) { auto R65816::op_adjust_dpx_w(fp op) {
dp = readpc(); dp = readPC();
io2(); io2();
io(); io();
rd.l = readdp(dp + regs.x.w + 0); rd.l = readDP(dp + r.x.w + 0);
rd.h = readdp(dp + regs.x.w + 1); rd.h = readDP(dp + r.x.w + 1);
io(); io();
call(op); call(op);
writedp(dp + regs.x.w + 1, rd.h); writeDP(dp + r.x.w + 1, rd.h);
L writedp(dp + regs.x.w + 0, rd.l); L writeDP(dp + r.x.w + 0, rd.l);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
struct Gamepad : Controller { struct Gamepad : Controller {
enum : uint { 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); Gamepad(bool port);

View File

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

View File

@ -4,7 +4,7 @@
auto SA1::dma_normal() -> void { auto SA1::dma_normal() -> void {
while(mmio.dtc--) { while(mmio.dtc--) {
uint8 data = regs.mdr; uint8 data = r.mdr;
uint32 dsa = mmio.dsa++; uint32 dsa = mmio.dsa++;
uint32 dda = mmio.dda++; uint32 dda = mmio.dda++;
@ -61,7 +61,7 @@ auto SA1::dma_cc1() -> void {
mmio.chdma_irqfl = true; mmio.chdma_irqfl = true;
if(mmio.chdma_irqen) { if(mmio.chdma_irqen) {
mmio.chdma_irqcl = 0; 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 { auto SA1::read(uint24 addr) -> uint8 {
tick(); tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr, regs.mdr); return bus_read(addr, r.mdr);
} }
auto SA1::write(uint24 addr, uint8 data) -> void { auto SA1::write(uint24 addr, uint8 data) -> void {
tick(); tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
bus_write(addr, regs.mdr = data); bus_write(addr, r.mdr = data);
} }
//note: addresses are translated prior to invoking this function: //note: addresses are translated prior to invoking this function:

View File

@ -2,8 +2,8 @@
auto SA1::mmio_w2200(uint8 data) -> void { auto SA1::mmio_w2200(uint8 data) -> void {
if(mmio.sa1_resb && !(data & 0x80)) { if(mmio.sa1_resb && !(data & 0x80)) {
//reset SA-1 CPU //reset SA-1 CPU
regs.pc.w = mmio.crv; r.pc.w = mmio.crv;
regs.pc.b = 0x00; r.pc.b = 0x00;
} }
mmio.sa1_irq = (data & 0x80); 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_irqen && (data & 0x80)) {
if(mmio.cpu_irqfl) { if(mmio.cpu_irqfl) {
mmio.cpu_irqcl = 0; mmio.cpu_irqcl = 0;
cpu.regs.irq = 1; cpu.r.irq = 1;
} }
} }
if(!mmio.chdma_irqen && (data & 0x20)) { if(!mmio.chdma_irqen && (data & 0x20)) {
if(mmio.chdma_irqfl) { if(mmio.chdma_irqfl) {
mmio.chdma_irqcl = 0; 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.cpu_irqcl ) mmio.cpu_irqfl = false;
if(mmio.chdma_irqcl) mmio.chdma_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 //(CRV) SA-1 reset vector
@ -77,7 +77,7 @@ auto SA1::mmio_w2209(uint8 data) -> void {
mmio.cpu_irqfl = true; mmio.cpu_irqfl = true;
if(mmio.cpu_irqen) { if(mmio.cpu_irqen) {
mmio.cpu_irqcl = 0; 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 { auto SA1::interrupt() -> void {
read(regs.pc.d); read(r.pc.d);
io(); io();
if(!regs.e) writestack(regs.pc.b); if(!r.e) writeSP(r.pc.b);
writestack(regs.pc.h); writeSP(r.pc.h);
writestack(regs.pc.l); writeSP(r.pc.l);
writestack(regs.e ? (regs.p & ~0x10) : regs.p); writeSP(r.e ? (r.p & ~0x10) : r.p);
regs.pc.w = regs.vector; r.pc.w = r.vector;
regs.pc.b = 0x00; r.pc.b = 0x00;
regs.p.i = 1; r.p.i = 1;
regs.p.d = 0; r.p.d = 0;
} }
auto SA1::lastCycle() -> void { auto SA1::lastCycle() -> void {
if(mmio.sa1_nmi && !mmio.sa1_nmicl) { if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
status.interrupt_pending = true; status.interrupt_pending = true;
regs.vector = mmio.cnv; r.vector = mmio.cnv;
mmio.sa1_nmifl = true; mmio.sa1_nmifl = true;
mmio.sa1_nmicl = 1; mmio.sa1_nmicl = 1;
regs.wai = false; r.wai = false;
} else if(!regs.p.i) { } else if(!r.p.i) {
if(mmio.timer_irqen && !mmio.timer_irqcl) { if(mmio.timer_irqen && !mmio.timer_irqcl) {
status.interrupt_pending = true; status.interrupt_pending = true;
regs.vector = mmio.civ; r.vector = mmio.civ;
mmio.timer_irqfl = true; mmio.timer_irqfl = true;
regs.wai = false; r.wai = false;
} else if(mmio.dma_irqen && !mmio.dma_irqcl) { } else if(mmio.dma_irqen && !mmio.dma_irqcl) {
status.interrupt_pending = true; status.interrupt_pending = true;
regs.vector = mmio.civ; r.vector = mmio.civ;
mmio.dma_irqfl = true; mmio.dma_irqfl = true;
regs.wai = false; r.wai = false;
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) { } else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
status.interrupt_pending = true; status.interrupt_pending = true;
regs.vector = mmio.civ; r.vector = mmio.civ;
mmio.sa1_irqfl = true; mmio.sa1_irqfl = true;
regs.wai = false; r.wai = false;
} }
} }
} }
@ -124,8 +124,10 @@ auto SA1::unload() -> void {
} }
auto SA1::power() -> void { auto SA1::power() -> void {
regs.a = regs.x = regs.y = 0x0000; r.a = 0x0000;
regs.s = 0x01ff; r.x = 0x0000;
r.y = 0x0000;
r.s = 0x01ff;
} }
auto SA1::reset() -> void { auto SA1::reset() -> void {
@ -136,17 +138,17 @@ auto SA1::reset() -> void {
iram.write(addr, 0x00); iram.write(addr, 0x00);
} }
regs.pc.d = 0x000000; r.pc.d = 0x000000;
regs.x.h = 0x00; r.x.h = 0x00;
regs.y.h = 0x00; r.y.h = 0x00;
regs.s.h = 0x01; r.s.h = 0x01;
regs.d = 0x0000; r.d = 0x0000;
regs.db = 0x00; r.db = 0x00;
regs.p = 0x34; r.p = 0x34;
regs.e = 1; r.e = 1;
regs.mdr = 0x00; r.mdr = 0x00;
regs.wai = false; r.wai = false;
regs.vector = 0x0000; r.vector = 0x0000;
status.tick_counter = 0; status.tick_counter = 0;

View File

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

View File

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

View File

@ -60,28 +60,28 @@ auto CPU::main() -> void {
status.interrupt_pending = false; status.interrupt_pending = false;
if(status.nmi_pending) { if(status.nmi_pending) {
status.nmi_pending = false; status.nmi_pending = false;
regs.vector = !regs.e ? 0xffea : 0xfffa; r.vector = r.e ? 0xfffa : 0xffea;
interrupt(); interrupt();
debugger.op_nmi(); debugger.op_nmi();
} else if(status.irq_pending) { } else if(status.irq_pending) {
status.irq_pending = false; status.irq_pending = false;
regs.vector = !regs.e ? 0xffee : 0xfffe; r.vector = r.e ? 0xfffe : 0xffee;
interrupt(); interrupt();
debugger.op_irq(); debugger.op_irq();
} else if(status.reset_pending) { } else if(status.reset_pending) {
status.reset_pending = false; status.reset_pending = false;
addClocks(132); addClocks(132);
regs.vector = 0xfffc; r.vector = 0xfffc;
interrupt(); interrupt();
} else if(status.power_pending) { } else if(status.power_pending) {
status.power_pending = false; status.power_pending = false;
addClocks(186); addClocks(186);
regs.pc.l = bus.read(0xfffc, regs.mdr); r.pc.l = bus.read(0xfffc, r.mdr);
regs.pc.h = bus.read(0xfffd, regs.mdr); r.pc.h = bus.read(0xfffd, r.mdr);
} }
} }
debugger.op_exec(regs.pc.d); debugger.op_exec(r.pc.d);
instruction(); instruction();
} }
@ -89,8 +89,10 @@ auto CPU::power() -> void {
for(auto& byte : wram) byte = random(0x55); for(auto& byte : wram) byte = random(0x55);
//CPU //CPU
regs.a = regs.x = regs.y = 0x0000; r.a = 0x0000;
regs.s = 0x01ff; r.x = 0x0000;
r.y = 0x0000;
r.s = 0x01ff;
//DMA //DMA
for(auto& channel : this->channel) { for(auto& channel : this->channel) {
@ -144,17 +146,17 @@ auto CPU::reset() -> void {
bus.map(reader, writer, "7e-7f:0000-ffff", 0x20000); bus.map(reader, writer, "7e-7f:0000-ffff", 0x20000);
//CPU //CPU
regs.pc = 0x000000; r.pc = 0x000000;
regs.x.h = 0x00; r.x.h = 0x00;
regs.y.h = 0x00; r.y.h = 0x00;
regs.s.h = 0x01; r.s.h = 0x01;
regs.d = 0x0000; r.d = 0x0000;
regs.db = 0x00; r.db = 0x00;
regs.p = 0x34; r.p = 0x34;
regs.e = 1; r.e = 1;
regs.mdr = 0x00; r.mdr = 0x00;
regs.wai = false; r.wai = false;
regs.vector = 0xfffc; //reset vector address r.vector = 0xfffc; //reset vector address
//$2140-217f //$2140-217f
for(auto& port : status.port) port = 0x00; 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 { auto CPU::dmaRead(uint24 abus) -> uint8 {
if(!dmaAddressValid(abus)) return 0x00; 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: //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 { auto CPU::dmaTransfer(bool direction, uint8 bbus, uint24 abus) -> void {
if(direction == 0) { if(direction == 0) {
dmaAddClocks(4); dmaAddClocks(4);
regs.mdr = dmaRead(abus); r.mdr = dmaRead(abus);
dmaAddClocks(4); dmaAddClocks(4);
dmaWrite(dmaTransferValid(bbus, abus), 0x2100 | bbus, regs.mdr); dmaWrite(dmaTransferValid(bbus, abus), 0x2100 | bbus, r.mdr);
} else { } else {
dmaAddClocks(4); 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); 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 { auto CPU::hdmaUpdate(uint n) -> void {
dmaAddClocks(4); 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); dmaAddClocks(4);
dmaWrite(false); dmaWrite(false);
if((channel[n].line_counter & 0x7f) == 0) { 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_addr++;
channel[n].hdma_completed = channel[n].line_counter == 0; channel[n].hdma_completed = channel[n].line_counter == 0;
@ -168,16 +168,16 @@ auto CPU::hdmaUpdate(uint n) -> void {
if(channel[n].indirect) { if(channel[n].indirect) {
dmaAddClocks(4); dmaAddClocks(4);
regs.mdr = dmaRead(hdmaAddress(n)); r.mdr = dmaRead(hdmaAddress(n));
channel[n].indirect_addr = regs.mdr << 8; channel[n].indirect_addr = r.mdr << 8;
dmaAddClocks(4); dmaAddClocks(4);
dmaWrite(false); dmaWrite(false);
if(!channel[n].hdma_completed || hdmaActiveAfter(n)) { if(!channel[n].hdma_completed || hdmaActiveAfter(n)) {
dmaAddClocks(4); dmaAddClocks(4);
regs.mdr = dmaRead(hdmaAddress(n)); r.mdr = dmaRead(hdmaAddress(n));
channel[n].indirect_addr >>= 8; channel[n].indirect_addr >>= 8;
channel[n].indirect_addr |= regs.mdr << 8; channel[n].indirect_addr |= r.mdr << 8;
dmaAddClocks(4); dmaAddClocks(4);
dmaWrite(false); dmaWrite(false);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,13 +6,13 @@ auto Program::loadRequest(uint id, string name, string type, bool required) -> v
.openFolder(); .openFolder();
if(!directory::exists(location)) return; if(!directory::exists(location)) return;
mediaPaths(id) = location; mediumPaths(id) = location;
folderPaths.append(location); folderPaths.append(location);
emulator->load(id); emulator->load(id);
} }
auto Program::loadRequest(uint id, string filename, bool required) -> void { 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}; string location = {pathname, filename};
if(filename == "manifest.bml" && pathname && !pathname.endsWith("sys/")) { 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 { auto Program::saveRequest(uint id, string filename) -> void {
string pathname = mediaPaths(emulator->group(id)); string pathname = mediumPaths(emulator->group(id));
string location = {pathname, filename}; string location = {pathname, filename};
//filestream stream{location, file::mode::write}; //filestream stream{location, file::mode::write};
@ -113,7 +113,7 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
} }
auto Program::path(uint group) -> string { auto Program::path(uint group) -> string {
return mediaPaths(group); return mediumPaths(group);
} }
auto Program::notify(string text) -> void { 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("\\", "/"); location.transform("\\", "/");
if(!location.endsWith("/")) location.append("/"); if(!location.endsWith("/")) location.append("/");
if(!directory::exists(location)) return; if(!directory::exists(location)) return;
string type = suffixname(location).trimLeft(".", 1L); string type = suffixname(location).trimLeft(".", 1L);
for(auto& media : emulator->media) { for(auto& medium : emulator->media) {
if(!media.bootable) continue; if(!medium.bootable) continue;
if(media.type != type) continue; if(medium.type != type) continue;
return loadMedia(media, location); return loadMedium(medium, location);
} }
} }
auto Program::loadMedia(Emulator::Interface::Media& media, string location) -> void { auto Program::loadMedium(Emulator::Interface::Medium& medium, string location) -> void {
unloadMedia(); unloadMedium();
mediaPaths(0) = locate({media.name, ".sys/"}); mediumPaths(0) = locate({medium.name, ".sys/"});
mediaPaths(media.id) = location; mediumPaths(medium.id) = location;
folderPaths.append(location); folderPaths.append(location);
emulator->set("Blur Emulation", false); 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::Controller2, (uint)SFC::Device::None);
emulator->connect((uint)SFC::Port::Expansion, (uint)SFC::Device::None); emulator->connect((uint)SFC::Port::Expansion, (uint)SFC::Device::None);
emulator->load(media.id); emulator->load(medium.id);
emulator->power(); emulator->power();
presentation->setTitle(emulator->title()); presentation->setTitle(emulator->title());
} }
auto Program::unloadMedia() -> void { auto Program::unloadMedium() -> void {
if(!emulator->loaded()) return; if(!emulator->loaded()) return;
emulator->unload(); emulator->unload();
mediaPaths.reset(); mediumPaths.reset();
folderPaths.reset(); folderPaths.reset();
presentation->setTitle(""); presentation->setTitle("");

View File

@ -1,6 +1,6 @@
#include "../loki.hpp" #include "../loki.hpp"
#include "interface.cpp" #include "interface.cpp"
#include "media.cpp" #include "medium.cpp"
unique_pointer<Program> program; unique_pointer<Program> program;
Program::Program(lstring args) { 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/" "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 { auto Program::main() -> void {
@ -52,7 +52,7 @@ auto Program::main() -> void {
} }
auto Program::quit() -> void { auto Program::quit() -> void {
unloadMedia(); unloadMedium();
video.reset(); video.reset();
audio.reset(); audio.reset();
input.reset(); input.reset();

View File

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

View File

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

View File

@ -17,7 +17,7 @@ Presentation::Presentation() {
.setFilters(string{media.name, "|*.", media.type}) .setFilters(string{media.name, "|*.", media.type})
.openFolder(); .openFolder();
if(directory::exists(location)) { if(directory::exists(location)) {
program->loadMedia(location); program->loadMedium(location);
} }
}); });
loadBootableMedia.append(item); loadBootableMedia.append(item);
@ -29,7 +29,7 @@ Presentation::Presentation() {
libraryMenu.append(MenuItem().setText("Load ROM File ...").onActivate([&] { libraryMenu.append(MenuItem().setText("Load ROM File ...").onActivate([&] {
audio->clear(); audio->clear();
if(auto location = execute("icarus", "--import")) { if(auto location = execute("icarus", "--import")) {
program->loadMedia(location.output.strip()); program->loadMedium(location.output.strip());
} }
})); }));
libraryMenu.append(MenuItem().setText("Import ROM Files ...").onActivate([&] { libraryMenu.append(MenuItem().setText("Import ROM Files ...").onActivate([&] {
@ -40,7 +40,7 @@ Presentation::Presentation() {
systemMenu.setText("System").setVisible(false); systemMenu.setText("System").setVisible(false);
powerSystem.setText("Power").onActivate([&] { program->powerCycle(); }); powerSystem.setText("Power").onActivate([&] { program->powerCycle(); });
resetSystem.setText("Reset").onActivate([&] { program->softReset(); }); resetSystem.setText("Reset").onActivate([&] { program->softReset(); });
unloadSystem.setText("Unload").onActivate([&] { program->unloadMedia(); drawSplashScreen(); }); unloadSystem.setText("Unload").onActivate([&] { program->unloadMedium(); drawSplashScreen(); });
settingsMenu.setText("Settings"); settingsMenu.setText("Settings");
videoScaleMenu.setText("Video Scale"); videoScaleMenu.setText("Video Scale");
@ -173,14 +173,14 @@ auto Presentation::updateEmulator() -> void {
inputPort2.setVisible(false).reset(); inputPort2.setVisible(false).reset();
inputPort3.setVisible(false).reset(); inputPort3.setVisible(false).reset();
for(auto n : range(emulator->port)) { for(auto n : range(emulator->ports)) {
if(n >= 3) break; if(n >= 3) break;
auto& port = emulator->port[n]; auto& port = emulator->ports[n];
auto& menu = (n == 0 ? inputPort1 : n == 1 ? inputPort2 : inputPort3); auto& menu = (n == 0 ? inputPort1 : n == 1 ? inputPort2 : inputPort3);
menu.setText(port.name); menu.setText(port.name);
Group devices; Group devices;
for(auto& device : port.device) { for(auto& device : port.devices) {
MenuRadioItem item{&menu}; MenuRadioItem item{&menu};
item.setText(device.name).onActivate([=] { item.setText(device.name).onActivate([=] {
auto path = string{emulator->information.name, "/", port.name}.replace(" ", ""); 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(); .openFolder();
if(!directory::exists(location)) return; if(!directory::exists(location)) return;
mediaPaths(id) = location; mediumPaths(id) = location;
folderPaths.append(location); folderPaths.append(location);
emulator->load(id); emulator->load(id);
} }
//request from emulation core to load non-volatile media file //request from emulation core to load non-volatile media file
auto Program::loadRequest(uint id, string filename, bool required) -> void { 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}; string location = {pathname, filename};
if(filename == "manifest.bml" && pathname && !pathname.endsWith(".sys/")) { 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 //request from emulation core to save non-volatile media file
auto Program::saveRequest(uint id, string filename) -> 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}; string location = {pathname, filename};
if(!pathname) return; //should never occur 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 { auto Program::audioSample(int16 left, int16 right) -> void {
audio->sample(lsample, rsample); audio->sample(left, right);
//int samples[] = {lsample, rsample};
//dsp.sample(samples);
//while(dsp.pending()) {
// dsp.read(samples);
// audio->sample(samples[0], samples[1]);
//}
} }
auto Program::inputPoll(uint port, uint device, uint input) -> int16 { auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean()) { 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; auto mapping = (InputMapping*)guid;
if(mapping) return mapping->poll(); 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 { auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void {
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) { 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; auto mapping = (InputMapping*)guid;
if(mapping) return mapping->rumble(enable); if(mapping) return mapping->rumble(enable);
} }
@ -121,7 +115,7 @@ auto Program::dipSettings(const Markup::Node& node) -> uint {
} }
auto Program::path(uint group) -> string { auto Program::path(uint group) -> string {
return mediaPaths(group); return mediumPaths(group);
} }
auto Program::notify(string text) -> void { 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("\\", "/"); location.transform("\\", "/");
if(!location.endsWith("/")) location.append("/"); if(!location.endsWith("/")) location.append("/");
if(!directory::exists(location)) return; if(!directory::exists(location)) return;
string type = suffixname(location).trimLeft(".", 1L); string type = suffixname(location).trimLeft(".", 1L);
for(auto& emulator : emulators) { for(auto& emulator : emulators) {
for(auto& media : emulator->media) { for(auto& medium : emulator->media) {
if(!media.bootable) continue; if(!medium.bootable) continue;
if(media.type != type) continue; if(medium.type != type) continue;
return loadMedia(*emulator, media, location); return loadMedium(*emulator, medium, location);
} }
} }
} }
auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, string location) -> void { auto Program::loadMedium(Emulator::Interface& interface, Emulator::Interface::Medium& medium, string location) -> void {
unloadMedia(); unloadMedium();
mediaPaths(0) = locate({media.name, ".sys/"}); mediumPaths(0) = locate({medium.name, ".sys/"});
mediaPaths(media.id) = location; mediumPaths(medium.id) = location;
folderPaths.append(location); folderPaths.append(location);
//note: the order of operations in this block of code is critical //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::audio.setFrequency(audio->get(Audio::Frequency).get<uint>());
emulator = &interface; emulator = &interface;
connectDevices(); connectDevices();
emulator->load(media.id); emulator->load(medium.id);
updateAudioDriver(); updateAudioDriver();
updateAudioEffects(); updateAudioEffects();
emulator->power(); emulator->power();
presentation->resizeViewport(); presentation->resizeViewport();
presentation->setTitle(emulator->title()); presentation->setTitle(emulator->title());
presentation->systemMenu.setText(media.name).setVisible(true); presentation->systemMenu.setText(medium.name).setVisible(true);
presentation->toolsMenu.setVisible(true); presentation->toolsMenu.setVisible(true);
presentation->updateEmulator(); presentation->updateEmulator();
toolsManager->cheatEditor.loadCheats(); toolsManager->cheatEditor.loadCheats();
@ -40,14 +40,14 @@ auto Program::loadMedia(Emulator::Interface& interface, Emulator::Interface::Med
toolsManager->manifestViewer.doRefresh(); toolsManager->manifestViewer.doRefresh();
} }
auto Program::unloadMedia() -> void { auto Program::unloadMedium() -> void {
if(!emulator) return; if(!emulator) return;
toolsManager->cheatEditor.saveCheats(); toolsManager->cheatEditor.saveCheats();
emulator->unload(); emulator->unload();
emulator = nullptr; emulator = nullptr;
mediaPaths.reset(); mediumPaths.reset();
folderPaths.reset(); folderPaths.reset();
presentation->setTitle({"higan v", Emulator::Version}); presentation->setTitle({"higan v", Emulator::Version});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,8 @@
#define decimal decimal_cocoa #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 uint8 uint8_cocoa
#define uint16 uint16_cocoa #define uint16 uint16_cocoa
#define uint32 uint32_cocoa #define uint32 uint32_cocoa
@ -6,6 +10,10 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h> #import <Carbon/Carbon.h>
#undef decimal #undef decimal
#undef int8
#undef int16
#undef int32
#undef int64
#undef uint8 #undef uint8
#undef uint16 #undef uint16
#undef uint32 #undef uint32

View File

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

View File

@ -10,7 +10,7 @@ namespace Configuration {
struct Node { struct Node {
string name; string name;
string desc; 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; void* data = nullptr;
vector<Node> children; 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) { for(auto& child : children) {
if(child.desc) { if(child.desc) {
for(auto n : range(depth)) fp.print(" "); 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 { inline auto library::open(const string& name, const string& path) -> bool {
if(handle) close(); if(handle) close();
if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".dylib"), RTLD_LAZY); 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("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".dylib"), RTLD_LAZY); if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".dylib"), RTLD_LAZY);
return handle; return handle;

View File

@ -7,7 +7,7 @@
//remove: O(1) average; O(n) worst //remove: O(1) average; O(n) worst
// //
//requirements: //requirements:
// auto T::hash() const -> unsigned; // auto T::hash() const -> uint;
// auto T::operator==(const T&) const -> bool; // auto T::operator==(const T&) const -> bool;
namespace nall { namespace nall {
@ -15,7 +15,7 @@ namespace nall {
template<typename T> template<typename T>
struct hashset { struct hashset {
hashset() = default; hashset() = default;
hashset(unsigned length) : length(bit::round(length)) {} hashset(uint length) : length(bit::round(length)) {}
hashset(const hashset& source) { operator=(source); } hashset(const hashset& source) { operator=(source); }
hashset(hashset&& source) { operator=(move(source)); } hashset(hashset&& source) { operator=(move(source)); }
~hashset() { reset(); } ~hashset() { reset(); }
@ -23,7 +23,7 @@ struct hashset {
auto operator=(const hashset& source) -> hashset& { auto operator=(const hashset& source) -> hashset& {
reset(); reset();
if(source.pool) { if(source.pool) {
for(unsigned n = 0; n < source.count; n++) { for(uint n : range(source.count)) {
insert(*source.pool[n]); insert(*source.pool[n]);
} }
} }
@ -42,12 +42,12 @@ struct hashset {
} }
explicit operator bool() const { return count; } explicit operator bool() const { return count; }
auto capacity() const -> unsigned { return length; } auto capacity() const -> uint { return length; }
auto size() const -> unsigned { return count; } auto size() const -> uint { return count; }
auto reset() -> void { auto reset() -> void {
if(pool) { if(pool) {
for(unsigned n = 0; n < length; n++) { for(uint n : range(length)) {
if(pool[n]) { if(pool[n]) {
delete pool[n]; delete pool[n];
pool[n] = nullptr; pool[n] = nullptr;
@ -60,15 +60,15 @@ struct hashset {
count = 0; 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 //ensure all items will fit into pool (with <= 50% load) and amortize growth
size = bit::round(max(size, count << 1)); size = bit::round(max(size, count << 1));
T** copy = new T*[size](); T** copy = new T*[size]();
if(pool) { if(pool) {
for(unsigned n = 0; n < length; n++) { for(uint n : range(length)) {
if(pool[n]) { 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; while(copy[hash]) if(++hash >= size) hash = 0;
copy[hash] = pool[n]; copy[hash] = pool[n];
pool[n] = nullptr; pool[n] = nullptr;
@ -84,7 +84,7 @@ struct hashset {
auto find(const T& value) -> maybe<T&> { auto find(const T& value) -> maybe<T&> {
if(!pool) return nothing; if(!pool) return nothing;
unsigned hash = value.hash() & (length - 1); uint hash = value.hash() & (length - 1);
while(pool[hash]) { while(pool[hash]) {
if(value == *pool[hash]) return *pool[hash]; if(value == *pool[hash]) return *pool[hash];
if(++hash >= length) hash = 0; if(++hash >= length) hash = 0;
@ -100,7 +100,7 @@ struct hashset {
if(count >= (length >> 1)) reserve(length << 1); if(count >= (length >> 1)) reserve(length << 1);
count++; count++;
unsigned hash = value.hash() & (length - 1); uint hash = value.hash() & (length - 1);
while(pool[hash]) if(++hash >= length) hash = 0; while(pool[hash]) if(++hash >= length) hash = 0;
pool[hash] = new T(value); pool[hash] = new T(value);
@ -110,7 +110,7 @@ struct hashset {
auto remove(const T& value) -> bool { auto remove(const T& value) -> bool {
if(!pool) return false; if(!pool) return false;
unsigned hash = value.hash() & (length - 1); uint hash = value.hash() & (length - 1);
while(pool[hash]) { while(pool[hash]) {
if(value == *pool[hash]) { if(value == *pool[hash]) {
delete pool[hash]; delete pool[hash];
@ -126,8 +126,8 @@ struct hashset {
protected: protected:
T** pool = nullptr; T** pool = nullptr;
unsigned length = 8; //length of pool uint length = 8; //length of pool
unsigned count = 0; //number of objects inside of the 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) {} Group(const string& name) : _name(name) {}
auto name() const -> string { return _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 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())) { for(auto id : range(size())) {
if(operator[](id)._name == name) return id; if(operator[](id)._name == name) return id;
} }
@ -50,10 +50,10 @@ struct Device : vector<Group> {
auto name() const -> string { return _name; } auto name() const -> string { return _name; }
auto id() const -> uint64_t { return _id; } auto id() const -> uint64_t { return _id; }
auto setID(uint64_t id) -> void { _id = 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 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())) { for(auto id : range(size())) {
if(operator[](id)._name == name) return id; if(operator[](id)._name == name) return id;
} }
@ -71,7 +71,7 @@ struct Null : Device {
}; };
struct Keyboard : Device { struct Keyboard : Device {
enum GroupID : unsigned { Button }; enum GroupID : uint { Button };
Keyboard() : Device("Keyboard") { append("Button"); } Keyboard() : Device("Keyboard") { append("Button"); }
auto isKeyboard() const -> bool { return true; } auto isKeyboard() const -> bool { return true; }
@ -79,7 +79,7 @@ struct Keyboard : Device {
}; };
struct Mouse : Device { struct Mouse : Device {
enum GroupID : unsigned { Axis, Button }; enum GroupID : uint { Axis, Button };
Mouse() : Device("Mouse") { append("Axis"), append("Button"); } Mouse() : Device("Mouse") { append("Axis"), append("Button"); }
auto isMouse() const -> bool { return true; } auto isMouse() const -> bool { return true; }
@ -88,7 +88,7 @@ struct Mouse : Device {
}; };
struct Joypad : 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"); } Joypad() : Device("Joypad") { append("Axis"), append("Hat"), append("Trigger"), append("Button"); }
auto isJoypad() const -> bool { return true; } auto isJoypad() const -> bool { return true; }

View File

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

View File

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

View File

@ -4,13 +4,13 @@ namespace nall {
namespace Matrix { 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; if(xcols != yrows) return;
for(unsigned y = 0; y < xrows; y++) { for(uint y : range(xrows)) {
for(unsigned x = 0; x < ycols; x++) { for(uint x : range(ycols)) {
T sum = 0; T sum = 0;
for(unsigned z = 0; z < xcols; z++) { for(uint z : range(xcols)) {
sum += xdata[y * xcols + z] * ydata[z * ycols + x]; sum += xdata[y * xcols + z] * ydata[z * ycols + x];
} }
*output++ = sum; *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; vector<T> output;
output.resize(xrows * ycols); output.resize(xrows * ycols);
Multiply(output.data(), xdata, xrows, xcols, ydata, yrows, 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); GetModuleFileName(nullptr, path, PATH_MAX);
string result = (const char*)utf8_t(path); string result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
return real(result); return Path::real(result);
#else #else
Dl_info info; Dl_info info;
dladdr((void*)&program, &info); dladdr((void*)&program, &info);
return real(info.dli_fname); return Path::real(info.dli_fname);
#endif #endif
} }
@ -78,9 +78,9 @@ inline auto config() -> string {
string result = (const char*)utf8_t(path); string result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
#elif defined(PLATFORM_MACOSX) #elif defined(PLATFORM_MACOSX)
string result = {user(), "Library/Application Support/"}; string result = {Path::user(), "Library/Application Support/"};
#else #else
string result = {user(), ".config/"}; string result = {Path::user(), ".config/"};
#endif #endif
if(!result) result = "."; if(!result) result = ".";
if(!result.endsWith("/")) result.append("/"); if(!result.endsWith("/")) result.append("/");
@ -96,9 +96,9 @@ inline auto local() -> string {
string result = (const char*)utf8_t(path); string result = (const char*)utf8_t(path);
result.transform("\\", "/"); result.transform("\\", "/");
#elif defined(PLATFORM_MACOSX) #elif defined(PLATFORM_MACOSX)
string result = {user(), "Library/Application Support/"}; string result = {Path::user(), "Library/Application Support/"};
#else #else
string result = {user(), ".local/share/"}; string result = {Path::user(), ".local/share/"};
#endif #endif
if(!result) result = "."; if(!result) result = ".";
if(!result.endsWith("/")) result.append("/"); 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 { struct LinearFeedbackShiftRegisterGenerator : RandomNumberGenerator {
auto seed(uint64_t seed) -> void { auto seed(uint64_t seed) -> void {
lfsr = seed; lfsr = seed;
for(unsigned n = 0; n < 8; n++) operator()(); for(uint n = 0; n < 8; n++) operator()();
} }
auto operator()() -> uint64_t { auto operator()() -> uint64_t {
return lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & crc64jones); return lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & crc64);
} }
auto serialize(serializer& s) -> void { auto serialize(serializer& s) -> void {
@ -27,9 +27,8 @@ struct LinearFeedbackShiftRegisterGenerator : RandomNumberGenerator {
} }
private: private:
static const uint64_t crc64ecma = 0x42f0e1eba9ea3693; static const uint64_t crc64 = 0xc96c'5795'd787'0f42;
static const uint64_t crc64jones = 0xad93d23594c935a9; uint64_t lfsr = crc64;
uint64_t lfsr = crc64ecma;
}; };
inline auto random() -> uint64_t { inline auto random() -> uint64_t {

View File

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

View File

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

View File

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

View File

@ -19,13 +19,13 @@ namespace nall {
struct thread { struct thread {
inline auto join() -> void; 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 detach() -> void;
static inline auto exit() -> void; static inline auto exit() -> void;
struct context { struct context {
function<void (uintptr_t)> callback; function<auto (uintptr) -> void> callback;
uintptr_t parameter = 0; uintptr parameter = 0;
}; };
private: private:
@ -43,7 +43,7 @@ auto thread::join() -> void {
pthread_join(handle, nullptr); 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; thread instance;
auto context = new thread::context; auto context = new thread::context;
@ -76,13 +76,13 @@ struct thread {
inline ~thread(); inline ~thread();
inline auto join() -> void; 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 detach() -> void;
static inline auto exit() -> void; static inline auto exit() -> void;
struct context { struct context {
function<void (uintptr_t)> callback; function<auto (uintptr) -> void> callback;
uintptr_t parameter = 0; uintptr parameter = 0;
}; };
private: 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; thread instance;
auto context = new thread::context; auto context = new thread::context;

View File

@ -9,9 +9,9 @@ template<typename T> struct base_from_member {
T value; 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]; 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; return array;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -6,14 +6,15 @@
#define GUID_EXT EXTERN_C #define GUID_EXT EXTERN_C
#define GUID_SECT #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 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_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 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_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, 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); DEFINE_CLSID_X(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd);
@ -21,299 +22,271 @@ DEFINE_IID_X(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
DECLARE_INTERFACE(IXAudio2Voice); DECLARE_INTERFACE(IXAudio2Voice);
#define XAUDIO2_COMMIT_NOW 0 #define XAUDIO2_COMMIT_NOW 0
#define XAUDIO2_DEFAULT_CHANNELS 0 #define XAUDIO2_DEFAULT_CHANNELS 0
#define XAUDIO2_DEFAULT_SAMPLERATE 0 #define XAUDIO2_DEFAULT_SAMPLERATE 0
#define XAUDIO2_DEFAULT_FREQ_RATIO 4.0f #define XAUDIO2_DEFAULT_FREQ_RATIO 4.0f
#define XAUDIO2_DEBUG_ENGINE 0x0001 #define XAUDIO2_DEBUG_ENGINE 0x0001
#define XAUDIO2_VOICE_NOSRC 0x0004 #define XAUDIO2_VOICE_NOSRC 0x0004
typedef enum XAUDIO2_DEVICE_ROLE typedef enum XAUDIO2_DEVICE_ROLE {
{ NotDefaultDevice = 0x0,
NotDefaultDevice = 0x0, DefaultConsoleDevice = 0x1,
DefaultConsoleDevice = 0x1, DefaultMultimediaDevice = 0x2,
DefaultMultimediaDevice = 0x2, DefaultCommunicationsDevice = 0x4,
DefaultCommunicationsDevice = 0x4, DefaultGameDevice = 0x8,
DefaultGameDevice = 0x8, GlobalDefaultDevice = 0xf,
GlobalDefaultDevice = 0xf, InvalidDeviceRole = ~GlobalDefaultDevice,
InvalidDeviceRole = ~GlobalDefaultDevice
} XAUDIO2_DEVICE_ROLE; } XAUDIO2_DEVICE_ROLE;
typedef struct XAUDIO2_DEVICE_DETAILS typedef struct XAUDIO2_DEVICE_DETAILS {
{ WCHAR DeviceID[256];
WCHAR DeviceID[256]; WCHAR DisplayName[256];
WCHAR DisplayName[256]; XAUDIO2_DEVICE_ROLE Role;
XAUDIO2_DEVICE_ROLE Role; WAVEFORMATEXTENSIBLE OutputFormat;
WAVEFORMATEXTENSIBLE OutputFormat;
} XAUDIO2_DEVICE_DETAILS; } XAUDIO2_DEVICE_DETAILS;
typedef struct XAUDIO2_VOICE_DETAILS typedef struct XAUDIO2_VOICE_DETAILS {
{ UINT32 CreationFlags;
UINT32 CreationFlags; UINT32 InputChannels;
UINT32 InputChannels; UINT32 InputSampleRate;
UINT32 InputSampleRate;
} XAUDIO2_VOICE_DETAILS; } XAUDIO2_VOICE_DETAILS;
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER {
{ Processor1 = 0x00000001,
Processor1 = 0x00000001, Processor2 = 0x00000002,
Processor2 = 0x00000002, Processor3 = 0x00000004,
Processor3 = 0x00000004, Processor4 = 0x00000008,
Processor4 = 0x00000008, Processor5 = 0x00000010,
Processor5 = 0x00000010, Processor6 = 0x00000020,
Processor6 = 0x00000020, Processor7 = 0x00000040,
Processor7 = 0x00000040, Processor8 = 0x00000080,
Processor8 = 0x00000080, Processor9 = 0x00000100,
Processor9 = 0x00000100, Processor10 = 0x00000200,
Processor10 = 0x00000200, Processor11 = 0x00000400,
Processor11 = 0x00000400, Processor12 = 0x00000800,
Processor12 = 0x00000800, Processor13 = 0x00001000,
Processor13 = 0x00001000, Processor14 = 0x00002000,
Processor14 = 0x00002000, Processor15 = 0x00004000,
Processor15 = 0x00004000, Processor16 = 0x00008000,
Processor16 = 0x00008000, Processor17 = 0x00010000,
Processor17 = 0x00010000, Processor18 = 0x00020000,
Processor18 = 0x00020000, Processor19 = 0x00040000,
Processor19 = 0x00040000, Processor20 = 0x00080000,
Processor20 = 0x00080000, Processor21 = 0x00100000,
Processor21 = 0x00100000, Processor22 = 0x00200000,
Processor22 = 0x00200000, Processor23 = 0x00400000,
Processor23 = 0x00400000, Processor24 = 0x00800000,
Processor24 = 0x00800000, Processor25 = 0x01000000,
Processor25 = 0x01000000, Processor26 = 0x02000000,
Processor26 = 0x02000000, Processor27 = 0x04000000,
Processor27 = 0x04000000, Processor28 = 0x08000000,
Processor28 = 0x08000000, Processor29 = 0x10000000,
Processor29 = 0x10000000, Processor30 = 0x20000000,
Processor30 = 0x20000000, Processor31 = 0x40000000,
Processor31 = 0x40000000, Processor32 = 0x80000000,
Processor32 = 0x80000000, XAUDIO2_ANY_PROCESSOR = 0xffffffff,
XAUDIO2_ANY_PROCESSOR = 0xffffffff, XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR,
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR; } XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR;
typedef struct XAUDIO2_VOICE_SENDS typedef struct XAUDIO2_VOICE_SENDS {
{ UINT32 OutputCount;
UINT32 OutputCount; IXAudio2Voice** pOutputVoices;
IXAudio2Voice** pOutputVoices;
} XAUDIO2_VOICE_SENDS; } XAUDIO2_VOICE_SENDS;
typedef struct XAUDIO2_EFFECT_DESCRIPTOR typedef struct XAUDIO2_EFFECT_DESCRIPTOR {
{ IUnknown* pEffect;
IUnknown* pEffect; BOOL InitialState;
BOOL InitialState; UINT32 OutputChannels;
UINT32 OutputChannels;
} XAUDIO2_EFFECT_DESCRIPTOR; } XAUDIO2_EFFECT_DESCRIPTOR;
typedef struct XAUDIO2_EFFECT_CHAIN typedef struct XAUDIO2_EFFECT_CHAIN {
{ UINT32 EffectCount;
UINT32 EffectCount; const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors;
const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors;
} XAUDIO2_EFFECT_CHAIN; } XAUDIO2_EFFECT_CHAIN;
typedef enum XAUDIO2_FILTER_TYPE typedef enum XAUDIO2_FILTER_TYPE {
{ LowPassFilter,
LowPassFilter, BandPassFilter,
BandPassFilter, HighPassFilter,
HighPassFilter
} XAUDIO2_FILTER_TYPE; } XAUDIO2_FILTER_TYPE;
typedef struct XAUDIO2_FILTER_PARAMETERS typedef struct XAUDIO2_FILTER_PARAMETERS {
{ XAUDIO2_FILTER_TYPE Type;
XAUDIO2_FILTER_TYPE Type; float Frequency;
float Frequency; float OneOverQ;
float OneOverQ;
} XAUDIO2_FILTER_PARAMETERS; } XAUDIO2_FILTER_PARAMETERS;
typedef struct XAUDIO2_BUFFER typedef struct XAUDIO2_BUFFER {
{ UINT32 Flags;
UINT32 Flags; UINT32 AudioBytes;
UINT32 AudioBytes; const BYTE* pAudioData;
const BYTE* pAudioData; UINT32 PlayBegin;
UINT32 PlayBegin; UINT32 PlayLength;
UINT32 PlayLength; UINT32 LoopBegin;
UINT32 LoopBegin; UINT32 LoopLength;
UINT32 LoopLength; UINT32 LoopCount;
UINT32 LoopCount; void* pContext;
void* pContext;
} XAUDIO2_BUFFER; } XAUDIO2_BUFFER;
typedef struct XAUDIO2_BUFFER_WMA typedef struct XAUDIO2_BUFFER_WMA {
{ const UINT32* pDecodedPacketCumulativeBytes;
const UINT32* pDecodedPacketCumulativeBytes; UINT32 PacketCount;
UINT32 PacketCount;
} XAUDIO2_BUFFER_WMA; } XAUDIO2_BUFFER_WMA;
typedef struct XAUDIO2_VOICE_STATE typedef struct XAUDIO2_VOICE_STATE {
{ void* pCurrentBufferContext;
void* pCurrentBufferContext; UINT32 BuffersQueued;
UINT32 BuffersQueued; UINT64 SamplesPlayed;
UINT64 SamplesPlayed;
} XAUDIO2_VOICE_STATE; } XAUDIO2_VOICE_STATE;
typedef struct XAUDIO2_PERFORMANCE_DATA typedef struct XAUDIO2_PERFORMANCE_DATA {
{ UINT64 AudioCyclesSinceLastQuery;
UINT64 AudioCyclesSinceLastQuery; UINT64 TotalCyclesSinceLastQuery;
UINT64 TotalCyclesSinceLastQuery; UINT32 MinimumCyclesPerQuantum;
UINT32 MinimumCyclesPerQuantum; UINT32 MaximumCyclesPerQuantum;
UINT32 MaximumCyclesPerQuantum; UINT32 MemoryUsageInBytes;
UINT32 MemoryUsageInBytes; UINT32 CurrentLatencyInSamples;
UINT32 CurrentLatencyInSamples; UINT32 GlitchesSinceEngineStarted;
UINT32 GlitchesSinceEngineStarted; UINT32 ActiveSourceVoiceCount;
UINT32 ActiveSourceVoiceCount; UINT32 TotalSourceVoiceCount;
UINT32 TotalSourceVoiceCount; UINT32 ActiveSubmixVoiceCount;
UINT32 ActiveSubmixVoiceCount; UINT32 TotalSubmixVoiceCount;
UINT32 TotalSubmixVoiceCount; UINT32 ActiveXmaSourceVoices;
UINT32 ActiveXmaSourceVoices; UINT32 ActiveXmaStreams;
UINT32 ActiveXmaStreams;
} XAUDIO2_PERFORMANCE_DATA; } XAUDIO2_PERFORMANCE_DATA;
typedef struct XAUDIO2_DEBUG_CONFIGURATION typedef struct XAUDIO2_DEBUG_CONFIGURATION {
{ UINT32 TraceMask;
UINT32 TraceMask; UINT32 BreakMask;
UINT32 BreakMask; BOOL LogThreadID;
BOOL LogThreadID; BOOL LogFileline;
BOOL LogFileline; BOOL LogFunctionName;
BOOL LogFunctionName; BOOL LogTiming;
BOOL LogTiming;
} XAUDIO2_DEBUG_CONFIGURATION; } XAUDIO2_DEBUG_CONFIGURATION;
DECLARE_INTERFACE(IXAudio2EngineCallback) DECLARE_INTERFACE(IXAudio2EngineCallback) {
{ STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE; STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE; STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
}; };
DECLARE_INTERFACE(IXAudio2VoiceCallback) DECLARE_INTERFACE(IXAudio2VoiceCallback) {
{ STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE;
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE; STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE; STDMETHOD_(void, OnStreamEnd) (THIS) PURE;
STDMETHOD_(void, OnStreamEnd) (THIS) PURE; STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE; STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE; STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE; STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE;
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE;
}; };
DECLARE_INTERFACE(IXAudio2Voice) DECLARE_INTERFACE(IXAudio2Voice) {
{ #define Declare_IXAudio2Voice_Methods() \
#define Declare_IXAudio2Voice_Methods() \ STDMETHOD_(void, GetVoiceDetails) (THIS_ XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \
STDMETHOD_(void, GetVoiceDetails) (THIS_ XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \ STDMETHOD(SetOutputVoices) (THIS_ const XAUDIO2_VOICE_SENDS* pSendList) PURE; \
STDMETHOD(SetOutputVoices) (THIS_ const XAUDIO2_VOICE_SENDS* pSendList) PURE; \ STDMETHOD(SetEffectChain) (THIS_ const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \
STDMETHOD(SetEffectChain) (THIS_ const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \ STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \
STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \
STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, BOOL* pEnabled) PURE; \
STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, BOOL* pEnabled) PURE; \ STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \
STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \ const void* pParameters, \
const void* pParameters, \ UINT32 ParametersByteSize, \
UINT32 ParametersByteSize, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, void* pParameters, \
STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, void* pParameters, \ UINT32 ParametersByteSize) PURE; \
UINT32 ParametersByteSize) PURE; \ STDMETHOD(SetFilterParameters) (THIS_ const XAUDIO2_FILTER_PARAMETERS* pParameters, \
STDMETHOD(SetFilterParameters) (THIS_ const XAUDIO2_FILTER_PARAMETERS* pParameters, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD_(void, GetFilterParameters) (THIS_ XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \
STDMETHOD_(void, GetFilterParameters) (THIS_ XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ STDMETHOD(SetVolume) (THIS_ float Volume, \
STDMETHOD(SetVolume) (THIS_ float Volume, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD_(void, GetVolume) (THIS_ float* pVolume) PURE; \
STDMETHOD_(void, GetVolume) (THIS_ float* pVolume) PURE; \ STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, const float* pVolumes, \
STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, const float* pVolumes, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, float* pVolumes) PURE; \
STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, float* pVolumes) PURE; \ STDMETHOD(SetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \
STDMETHOD(SetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \ UINT32 SourceChannels, UINT32 DestinationChannels, \
UINT32 SourceChannels, UINT32 DestinationChannels, \ const float* pLevelMatrix, \
const float* pLevelMatrix, \ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ STDMETHOD_(void, GetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \
STDMETHOD_(void, GetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \ UINT32 SourceChannels, UINT32 DestinationChannels, \
UINT32 SourceChannels, UINT32 DestinationChannels, \ float* pLevelMatrix) PURE; \
float* pLevelMatrix) PURE; \ STDMETHOD_(void, DestroyVoice) (THIS) PURE
STDMETHOD_(void, DestroyVoice) (THIS) PURE
Declare_IXAudio2Voice_Methods(); Declare_IXAudio2Voice_Methods();
}; };
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) {
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) Declare_IXAudio2Voice_Methods();
{
Declare_IXAudio2Voice_Methods();
}; };
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) {
{ Declare_IXAudio2Voice_Methods();
Declare_IXAudio2Voice_Methods();
}; };
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) {
{ Declare_IXAudio2Voice_Methods();
Declare_IXAudio2Voice_Methods(); STDMETHOD(Start) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(Start) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; STDMETHOD(Stop) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(Stop) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; STDMETHOD(SubmitSourceBuffer) (THIS_ const XAUDIO2_BUFFER* pBuffer, const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE;
STDMETHOD(SubmitSourceBuffer) (THIS_ const XAUDIO2_BUFFER* pBuffer, const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE; STDMETHOD(FlushSourceBuffers) (THIS) PURE;
STDMETHOD(FlushSourceBuffers) (THIS) PURE; STDMETHOD(Discontinuity) (THIS) PURE;
STDMETHOD(Discontinuity) (THIS) PURE; STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; STDMETHOD_(void, GetState) (THIS_ XAUDIO2_VOICE_STATE* pVoiceState) PURE;
STDMETHOD_(void, GetState) (THIS_ XAUDIO2_VOICE_STATE* pVoiceState) PURE; STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio,
STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; STDMETHOD_(void, GetFrequencyRatio) (THIS_ float* pRatio) PURE;
STDMETHOD_(void, GetFrequencyRatio) (THIS_ float* pRatio) PURE;
}; };
DECLARE_INTERFACE_(IXAudio2, IUnknown) DECLARE_INTERFACE_(IXAudio2, IUnknown) {
{ STDMETHOD(QueryInterface) (THIS_ REFIID riid, void** ppvInterface) PURE;
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void** ppvInterface) PURE; STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE; STDMETHOD_(ULONG, Release) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE; STDMETHOD(GetDeviceCount) (THIS_ UINT32* pCount) PURE;
STDMETHOD(GetDeviceCount) (THIS_ UINT32* pCount) PURE; STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE;
STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE; STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0),
STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0), XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE;
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE; STDMETHOD(RegisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE;
STDMETHOD(RegisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE; STDMETHOD_(void, UnregisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE;
STDMETHOD_(void, UnregisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE; STDMETHOD(CreateSourceVoice) (THIS_ IXAudio2SourceVoice** ppSourceVoice,
STDMETHOD(CreateSourceVoice) (THIS_ IXAudio2SourceVoice** ppSourceVoice, const WAVEFORMATEX* pSourceFormat,
const WAVEFORMATEX* pSourceFormat, UINT32 Flags X2DEFAULT(0),
UINT32 Flags X2DEFAULT(0), float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO),
float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO), IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL),
IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL), const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL),
const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; STDMETHOD(CreateSubmixVoice) (THIS_ IXAudio2SubmixVoice** ppSubmixVoice,
STDMETHOD(CreateSubmixVoice) (THIS_ IXAudio2SubmixVoice** ppSubmixVoice, UINT32 InputChannels, UINT32 InputSampleRate,
UINT32 InputChannels, UINT32 InputSampleRate, UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0),
UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0), const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL),
const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; STDMETHOD(CreateMasteringVoice) (THIS_ IXAudio2MasteringVoice** ppMasteringVoice,
STDMETHOD(CreateMasteringVoice) (THIS_ IXAudio2MasteringVoice** ppMasteringVoice, UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS),
UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS), UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE),
UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE), UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0),
UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0), const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; STDMETHOD(StartEngine) (THIS) PURE;
STDMETHOD(StartEngine) (THIS) PURE; STDMETHOD_(void, StopEngine) (THIS) PURE;
STDMETHOD_(void, StopEngine) (THIS) PURE; STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE;
STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE; STDMETHOD_(void, GetPerformanceData) (THIS_ XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE;
STDMETHOD_(void, GetPerformanceData) (THIS_ XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE; STDMETHOD_(void, SetDebugConfiguration) (THIS_ const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration,
STDMETHOD_(void, SetDebugConfiguration) (THIS_ const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration, void* pReserved X2DEFAULT(NULL)) PURE;
void* pReserved X2DEFAULT(NULL)) PURE;
}; };
__inline HRESULT XAudio2Create(IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), __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;
IXAudio2* pXAudio2; HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2,
HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2);
NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2); if(SUCCEEDED(hr)) {
if (SUCCEEDED(hr)) hr = pXAudio2->Initialize(Flags, XAudio2Processor);
{ if(SUCCEEDED(hr)) {
hr = pXAudio2->Initialize(Flags, XAudio2Processor); *ppXAudio2 = pXAudio2;
if (SUCCEEDED(hr)) } else {
{ pXAudio2->Release();
*ppXAudio2 = pXAudio2; }
} }
else return hr;
{
pXAudio2->Release();
}
}
return hr;
} }