Update to v102r10 release.

byuu says:

Changelog:

  - removed Emulator::Interface::Capabilities¹
  - MS: improved the PSG emulation a bit
  - MS: added cheat code support
  - MS: added save state support²
  - MD: emulated the PSG³

¹: there's really no point to it anymore. I intend to add cheat codes
to the GBA core, as well as both cheat codes and save states to the Mega
Drive core. I no longer intend to emulate any new systems, so these
values will always be true. Further, the GUI doesn't respond to these
values to disable those features anymore ever since the hiro rewrite, so
they're double useless.

²: right now, the Z80 core is using a pointer for HL-\>(IX,IY)
overrides. But I can't reliably serialize pointers, so I need to convert
the Z80 core to use an integer here. The save states still appear to
work fine, but there's the potential for an instruction to execute
incorrectly if you're incredibly unlucky, so this needs to be fixed as
soon as possible. Further, I still need a way to serialize
array<T, Size> objects, and I should also add nall::Boolean
serialization support.

³: I don't have a system in place to share identical sound chips. But
this chip is so incredibly simple that it's not really much trouble to
duplicate it. Further, I can strip out the stereo sound support code
from the Game Gear portion, so it's even tinier.

Note that the Mega Drive only just barely uses the PSG. Not at all in
Altered Beast, and only for a tiny part of the BGM music on Sonic 1,
plus his jump sound effect.
This commit is contained in:
Tim Allen 2017-02-23 08:25:01 +11:00
parent 8071da4c6a
commit 68f04c3bb8
41 changed files with 465 additions and 70 deletions

View File

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

View File

@ -7,10 +7,6 @@ struct Interface {
string manufacturer;
string name;
bool overscan;
struct Capability {
bool states;
bool cheats;
} capability;
} information;
struct Region {

View File

@ -9,9 +9,6 @@ Interface::Interface() {
information.name = "Famicom";
information.overscan = true;
information.capability.states = true;
information.capability.cheats = true;
media.append({ID::Famicom, "Famicom", "fc"});
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};

View File

@ -8,9 +8,6 @@ Settings settings;
#include "game-boy-color.cpp"
Interface::Interface() {
information.capability.states = true;
information.capability.cheats = true;
Port hardwarePort{ID::Port::Hardware, "Hardware"};
{ Device device{ID::Device::Controls, "Controls"};

View File

@ -9,9 +9,6 @@ Interface::Interface() {
information.name = "Game Boy Advance";
information.overscan = false;
information.capability.states = true;
information.capability.cheats = false;
media.append({ID::GameBoyAdvance, "Game Boy Advance", "gba"});
Port hardwarePort{ID::Port::Hardware, "Hardware"};

View File

@ -9,9 +9,6 @@ Interface::Interface() {
information.name = "Mega Drive";
information.overscan = true;
information.capability.states = false;
information.capability.cheats = false;
regions.append({"Autodetect"});
regions.append({"NTSC-J"});
regions.append({"NTSC-U"});

View File

@ -1,2 +1,53 @@
auto PSG::write(uint8 data) -> void {
bool l = data.bit(7);
if(l) select = data.bits(4,6);
switch(select) {
case 0: {
if(l) tone0.pitch.bits(0,3) = data.bits(0,3);
else tone0.pitch.bits(4,9) = data.bits(0,5);
break;
}
case 1: {
tone0.volume = data.bits(0,3);
break;
}
case 2: {
if(l) tone1.pitch.bits(0,3) = data.bits(0,3);
else tone1.pitch.bits(4,9) = data.bits(0,5);
break;
}
case 3: {
tone1.volume = data.bits(0,3);
break;
}
case 4: {
if(l) tone2.pitch.bits(0,3) = data.bits(0,3);
else tone2.pitch.bits(4,9) = data.bits(0,5);
break;
}
case 5: {
tone2.volume = data.bits(0,3);
break;
}
case 6: {
noise.rate = data.bits(0,1);
noise.enable = data.bit(2);
noise.lfsr = 0x8000;
break;
}
case 7: {
noise.volume = data.bits(0,3);
break;
}
}
}

26
higan/md/psg/noise.cpp Normal file
View File

@ -0,0 +1,26 @@
auto PSG::Noise::run() -> void {
auto latch = clock;
counter++;
if(rate == 0) output ^= !counter.bits(0,3);
if(rate == 1) output ^= !counter.bits(0,4);
if(rate == 2) output ^= !counter.bits(0,5);
if(rate == 3) output ^= psg.tone2.clock;
if(!latch && clock) {
auto eor = enable ? ~lfsr >> 3 : 0;
lfsr = (lfsr ^ eor) << 15 | lfsr >> 1;
}
output = lfsr.bit(0);
}
auto PSG::Noise::power() -> void {
volume = ~0;
counter = 0;
enable = 0;
rate = 0;
lfsr = 0x8000;
clock = 0;
output = 0;
}

View File

@ -4,13 +4,30 @@ namespace MegaDrive {
PSG psg;
#include "io.cpp"
#include "tone.cpp"
#include "noise.cpp"
auto PSG::Enter() -> void {
while(true) scheduler.synchronize(), psg.main();
}
auto PSG::main() -> void {
stream->sample(0.0);
tone0.run();
tone1.run();
tone2.run();
noise.run();
int output = 0;
if(tone0.output) output += levels[tone0.volume];
if(tone1.output) output += levels[tone1.volume];
if(tone2.output) output += levels[tone2.volume];
if(noise.output) output += levels[noise.volume];
lowpass += (output - lowpass) * 20.0 / 256.0;
output = output * 2.0 / 6.0 + lowpass * 3.0 / 4.0;
output = sclamp<16>(output - 32768);
stream->sample(output / 32768.0);
step(1);
}
@ -21,7 +38,19 @@ auto PSG::step(uint clocks) -> void {
auto PSG::power() -> void {
create(PSG::Enter, system.colorburst() / 16.0);
stream = Emulator::audio.createStream(1, system.colorburst() / 16.0);
stream = Emulator::audio.createStream(1, frequency());
select = 0;
lowpass = 0;
for(auto n : range(15)) {
levels[n] = 0x3fff * pow(2, n * -2.0 / 6.0) + 0.5;
}
levels[15] = 0;
tone0.power();
tone1.power();
tone2.power();
noise.power();
}
}

View File

@ -11,6 +11,37 @@ struct PSG : Thread {
//io.cpp
auto write(uint8 data) -> void;
private:
struct Tone {
//tone.cpp
auto run() -> void;
auto power() -> void;
uint4 volume;
uint10 counter;
uint10 pitch;
uint1 clock;
uint1 output;
} tone0, tone1, tone2;
struct Noise {
//noise.cpp
auto run() -> void;
auto power() -> void;
uint4 volume;
uint6 counter;
uint1 enable;
uint2 rate;
uint16 lfsr;
uint1 clock;
uint1 output;
} noise;
uint3 select;
int lowpass;
uint16 levels[16];
};
extern PSG psg;

16
higan/md/psg/tone.cpp Normal file
View File

@ -0,0 +1,16 @@
auto PSG::Tone::run() -> void {
clock = 0;
if(--counter) return;
clock = 1;
counter = pitch;
output ^= 1;
}
auto PSG::Tone::power() -> void {
volume = ~0;
counter = 0;
pitch = 0;
clock = 0;
output = 0;
}

View File

@ -11,7 +11,7 @@ auto YM2612::Enter() -> void {
auto YM2612::main() -> void {
stream->sample(0.0, 0.0);
step(144);
step(1);
}
auto YM2612::step(uint clocks) -> void {
@ -20,8 +20,8 @@ auto YM2612::step(uint clocks) -> void {
}
auto YM2612::power() -> void {
create(YM2612::Enter, system.colorburst() * 15.0 / 7.0);
stream = Emulator::audio.createStream(2, system.colorburst() * 15.0 / 7.0 / 144.0);
create(YM2612::Enter, system.colorburst() * 15.0 / 7.0 / 144.0);
stream = Emulator::audio.createStream(2, frequency());
}
}

View File

@ -3,8 +3,15 @@
namespace MasterSystem {
Bus bus;
#include "serialization.cpp"
auto Bus::read(uint16 addr) -> uint8 {
auto data = read_(addr);
if(auto result = cheat.find(addr, data)) data = result();
return data;
}
auto Bus::read_(uint16 addr) -> uint8 {
if(auto data = cartridge.read(addr)) return data();
if(addr >= 0xc000) return ram[addr & 0x1fff];
return 0x00;

View File

@ -1,10 +1,14 @@
struct Bus : Processor::Z80::Bus {
auto read(uint16 addr) -> uint8 override;
auto read_(uint16 addr) -> uint8;
auto write(uint16 addr, uint8 data) -> void override;
auto in(uint8 addr) -> uint8 override;
auto out(uint8 addr, uint8 data) -> void override;
//serialization.cpp
auto serialize(serializer&) -> void;
private:
uint8 ram[0x2000];
};

View File

@ -0,0 +1,5 @@
auto Bus::serialize(serializer& s) -> void {
Processor::Z80::Bus::serialize(s);
s.array(ram);
}

View File

@ -4,6 +4,7 @@ namespace MasterSystem {
Cartridge cartridge;
#include "mapper.cpp"
#include "serialization.cpp"
auto Cartridge::load() -> bool {
information = {};

View File

@ -14,6 +14,9 @@ struct Cartridge {
auto read(uint16 addr) -> maybe<uint8>;
auto write(uint16 addr, uint8 data) -> bool;
//serialization.cpp
auto serialize(serializer&) -> void;
private:
struct Information {
uint pathID = 0;

View File

@ -0,0 +1,3 @@
auto Cartridge::serialize(serializer& s) -> void {
if(ram.size) s.array(ram.data, ram.size);
}

View File

@ -3,6 +3,7 @@
namespace MasterSystem {
CPU cpu;
#include "serialization.cpp"
auto CPU::Enter() -> void {
while(true) scheduler.synchronize(), cpu.main();
@ -48,7 +49,6 @@ auto CPU::setINT(bool value) -> void {
}
auto CPU::power() -> void {
Z80::bus = &MasterSystem::bus;
Z80::power();
create(CPU::Enter, system.colorburst());
@ -57,4 +57,8 @@ auto CPU::power() -> void {
memory::fill(&state, sizeof(State));
}
CPU::CPU() {
Z80::bus = &MasterSystem::bus;
}
}

View File

@ -11,12 +11,17 @@ struct CPU : Processor::Z80, Thread {
auto power() -> void;
CPU();
//serialization.cpp
auto serialize(serializer&) -> void;
vector<Thread*> peripherals;
private:
struct State {
boolean nmiLine;
boolean intLine;
bool nmiLine;
bool intLine;
} state;
};

View File

@ -0,0 +1,7 @@
auto CPU::serialize(serializer& s) -> void {
Z80::serialize(s);
Thread::serialize(s);
s.integer(state.nmiLine);
s.integer(state.intLine);
}

View File

@ -7,8 +7,6 @@ Settings settings;
#include "game-gear.cpp"
Interface::Interface() {
information.capability.states = false;
information.capability.cheats = false;
}
auto Interface::manifest() -> string {
@ -49,11 +47,16 @@ auto Interface::run() -> void {
}
auto Interface::serialize() -> serializer {
return {};
system.runToSave();
return system.serialize();
}
auto Interface::unserialize(serializer& s) -> bool {
return false;
return system.unserialize(s);
}
auto Interface::cheatSet(const string_vector& list) -> void {
cheat.assign(list);
}
auto Interface::cap(const string& name) -> bool {

View File

@ -40,6 +40,8 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override;
auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override;
auto set(const string& name, const any& value) -> bool override;

View File

@ -6,6 +6,7 @@
#include <emulator/emulator.hpp>
#include <emulator/thread.hpp>
#include <emulator/scheduler.hpp>
#include <emulator/cheat.hpp>
#include <processor/z80/z80.hpp>
@ -13,8 +14,9 @@ namespace MasterSystem {
#define platform Emulator::platform
namespace File = Emulator::File;
using Scheduler = Emulator::Scheduler;
using Cheat = Emulator::Cheat;
extern Scheduler scheduler;
struct Interface;
extern Cheat cheat;
struct Thread : Emulator::Thread {
auto create(auto (*entrypoint)() -> void, double frequency) -> void {

View File

@ -1,7 +1,3 @@
//note: tone is supposed to reload counters on volume writes
//however, if this is always done, the output is very grainy
//as such, this behavior is suppressed when pitch >= 2 (which is a hack)
auto PSG::write(uint8 data) -> void {
bool l = data.bit(7);
if(l) select = data.bits(4,6);
@ -16,10 +12,6 @@ auto PSG::write(uint8 data) -> void {
case 1: {
tone0.volume = data.bits(0,3);
if(tone0.pitch < 2) {
tone0.output = 1;
tone0.counter = tone0.pitch;
}
break;
}
@ -31,10 +23,6 @@ auto PSG::write(uint8 data) -> void {
case 3: {
tone1.volume = data.bits(0,3);
if(tone1.pitch < 2) {
tone1.output = 1;
tone1.counter = tone1.pitch;
}
break;
}
@ -46,10 +34,6 @@ auto PSG::write(uint8 data) -> void {
case 5: {
tone2.volume = data.bits(0,3);
if(tone2.pitch < 2) {
tone2.output = 1;
tone2.counter = tone2.pitch;
}
break;
}
@ -62,7 +46,6 @@ auto PSG::write(uint8 data) -> void {
case 7: {
noise.volume = data.bits(0,3);
noise.output = 1;
break;
}

View File

@ -2,11 +2,10 @@ auto PSG::Noise::run() -> void {
auto latch = clock;
counter++;
if(rate < 3) {
clock ^= counter & ((16 << rate) - 1) == 0;
} else {
clock ^= psg.tone2.clock;
}
if(rate == 0) output ^= !counter.bits(0,3);
if(rate == 1) output ^= !counter.bits(0,4);
if(rate == 2) output ^= !counter.bits(0,5);
if(rate == 3) output ^= psg.tone2.clock;
if(!latch && clock) {
auto eor = enable ? ~lfsr >> 3 : 0;

View File

@ -6,6 +6,7 @@ PSG psg;
#include "io.cpp"
#include "tone.cpp"
#include "noise.cpp"
#include "serialization.cpp"
auto PSG::Enter() -> void {
while(true) scheduler.synchronize(), psg.main();
@ -25,7 +26,7 @@ auto PSG::main() -> void {
lowpassLeft += (left - lowpassLeft) * 20.0 / 256.0;
left = left * 2.0 / 6.0 + lowpassLeft * 3.0 / 4.0;
left = sclamp<16>(left);
left = sclamp<16>(left - 32768);
int right = 0;
if(tone0.output && tone0.right) right += levels[tone0.volume];
@ -35,10 +36,10 @@ auto PSG::main() -> void {
lowpassRight += (right - lowpassRight) * 20.0 / 256.0;
right = right * 2.0 / 6.0 + lowpassRight * 3.0 / 4.0;
right = sclamp<16>(right);
right = sclamp<16>(right - 32768);
step(1);
stream->sample(left / 32768.0, right / 32768.0);
step(1);
}
auto PSG::step(uint clocks) -> void {

View File

@ -13,12 +13,18 @@ struct PSG : Thread {
auto write(uint8 data) -> void;
auto balance(uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
private:
struct Tone {
//tone.cpp
auto run() -> void;
auto power() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint4 volume;
uint10 counter;
uint10 pitch;
@ -34,6 +40,9 @@ private:
auto run() -> void;
auto power() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
uint4 volume;
uint6 counter;
uint1 enable;

View File

@ -0,0 +1,37 @@
auto PSG::serialize(serializer& s) -> void {
Thread::serialize(s);
tone0.serialize(s);
tone1.serialize(s);
tone2.serialize(s);
noise.serialize(s);
s.integer(select);
s.integer(lowpassLeft);
s.integer(lowpassRight);
s.array(levels);
}
auto PSG::Tone::serialize(serializer& s) -> void {
s.integer(volume);
s.integer(counter);
s.integer(pitch);
s.integer(clock);
s.integer(output);
s.integer(left);
s.integer(right);
}
auto PSG::Noise::serialize(serializer& s) -> void {
s.integer(volume);
s.integer(counter);
s.integer(enable);
s.integer(rate);
s.integer(lfsr);
s.integer(clock);
s.integer(output);
s.integer(left);
s.integer(right);
}

View File

@ -0,0 +1,66 @@
auto System::serializeInit() -> void {
serializer s;
uint signature = 0;
char version[16] = {0};
char hash[64] = {0};
char description[512] = {0};
s.integer(signature);
s.array(version);
s.array(hash);
s.array(description);
serializeAll(s);
information.serializeSize = s.size();
}
auto System::serialize() -> serializer {
serializer s{information.serializeSize};
uint signature = 0x31545342;
char version[16] = {0};
char hash[64] = {0};
char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature);
s.array(version);
s.array(hash);
s.array(description);
serializeAll(s);
return s;
}
auto System::unserialize(serializer& s) -> bool {
uint signature = 0;
char version[16] = {0};
char hash[64] = {0};
char description[512] = {0};
s.integer(signature);
s.array(version);
s.array(hash);
s.array(description);
if(signature != 0x31545342) return false;
if(string{version} != Emulator::SerializerVersion) return false;
power();
serializeAll(s);
return true;
}
auto System::serializeAll(serializer& s) -> void {
system.serialize(s);
bus.serialize(s);
cartridge.serialize(s);
cpu.serialize(s);
vdp.serialize(s);
psg.serialize(s);
}
auto System::serialize(serializer& s) -> void {
}

View File

@ -2,9 +2,11 @@
namespace MasterSystem {
#include "peripherals.cpp"
System system;
Scheduler scheduler;
Cheat cheat;
#include "peripherals.cpp"
#include "serialization.cpp"
auto System::run() -> void {
if(scheduler.enter() == Scheduler::Event::Frame) {
@ -13,6 +15,12 @@ auto System::run() -> void {
}
}
auto System::runToSave() -> void {
scheduler.synchronize(cpu);
scheduler.synchronize(vdp);
scheduler.synchronize(psg);
}
auto System::load(Emulator::Interface* interface, Model model) -> bool {
information = {};
information.model = model;
@ -24,6 +32,7 @@ auto System::load(Emulator::Interface* interface, Model model) -> bool {
auto document = BML::unserialize(information.manifest);
if(!cartridge.load()) return false;
serializeInit();
this->interface = interface;
information.colorburst = Emulator::Constants::Colorburst::NTSC;
return information.loaded = true;

View File

@ -6,6 +6,7 @@ struct System {
auto colorburst() const -> double { return information.colorburst; }
auto run() -> void;
auto runToSave() -> void;
auto load(Emulator::Interface* interface, Model model) -> bool;
auto save() -> void;
@ -13,6 +14,13 @@ struct System {
auto power() -> void;
//serialization.cpp
auto serializeInit() -> void;
auto serialize() -> serializer;
auto unserialize(serializer&) -> bool;
auto serializeAll(serializer&) -> void;
auto serialize(serializer&) -> void;
private:
Emulator::Interface* interface = nullptr;
@ -21,6 +29,7 @@ private:
Model model = Model::MasterSystem;
string manifest;
double colorburst = 0.0;
uint serializeSize = 0;
} information;
};

View File

@ -0,0 +1,64 @@
auto VDP::serialize(serializer& s) -> void {
Thread::serialize(s);
background.serialize(s);
sprite.serialize(s);
s.array(vram);
s.array(cram);
s.integer(io.vcounter);
s.integer(io.hcounter);
s.integer(io.lcounter);
s.integer(io.intLine);
s.integer(io.intFrame);
s.integer(io.spriteOverflow);
s.integer(io.spriteCollision);
s.integer(io.fifthSprite);
s.integer(io.controlLatch);
s.integer(io.controlData);
s.integer(io.code);
s.integer(io.address);
s.integer(io.vramLatch);
s.integer(io.externalSync);
s.integer(io.extendedHeight);
s.integer(io.mode4);
s.integer(io.spriteShift);
s.integer(io.lineInterrupts);
s.integer(io.leftClip);
s.integer(io.horizontalScrollLock);
s.integer(io.verticalScrollLock);
s.integer(io.spriteDouble);
s.integer(io.spriteTile);
s.integer(io.lines240);
s.integer(io.lines224);
s.integer(io.frameInterrupts);
s.integer(io.displayEnable);
s.integer(io.nameTableMask);
s.integer(io.nameTableAddress);
s.integer(io.colorTableAddress);
s.integer(io.patternTableAddress);
s.integer(io.spriteAttributeTableMask);
s.integer(io.spriteAttributeTableAddress);
s.integer(io.spritePatternTableMask);
s.integer(io.spritePatternTableAddress);
s.integer(io.backdropColor);
s.integer(io.hscroll);
s.integer(io.vscroll);
s.integer(io.lineCounter);
}
auto VDP::Background::serialize(serializer& s) -> void {
s.integer(state.x);
s.integer(state.y);
s.integer(output.color);
s.integer(output.palette);
s.integer(output.priority);
}
auto VDP::Sprite::serialize(serializer& s) -> void {
s.integer(state.x);
s.integer(state.y);
s.integer(output.color);
//todo: array<Object, 8> is not serializable
}

View File

@ -6,6 +6,7 @@ VDP vdp;
#include "io.cpp"
#include "background.cpp"
#include "sprite.cpp"
#include "serialization.cpp"
auto VDP::Enter() -> void {
while(true) scheduler.synchronize(), vdp.main();

View File

@ -28,6 +28,9 @@ struct VDP : Thread {
auto power() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
struct State {
uint x;
uint y;
@ -47,6 +50,9 @@ struct VDP : Thread {
auto power() -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
struct Object {
uint8 x;
uint8 y;
@ -65,6 +71,9 @@ struct VDP : Thread {
array<Object, 8> objects;
} sprite;
//serialization.cpp
auto serialize(serializer&) -> void;
private:
auto palette(uint5 index) -> uint12;

View File

@ -10,9 +10,6 @@ Settings settings;
Interface::Interface() {
information.overscan = true;
information.capability.states = true;
information.capability.cheats = true;
Port controllerPort{ID::Port::Controller, "Controller Port"};
{ Device device{ID::Device::None, "None"};

View File

@ -0,0 +1,27 @@
auto Z80::serialize(serializer& s) -> void {
s.integer(r.af.word);
s.integer(r.bc.word);
s.integer(r.de.word);
s.integer(r.hl.word);
s.integer(r.ix.word);
s.integer(r.iy.word);
s.integer(r.ir.word);
s.integer(r.sp);
s.integer(r.pc);
s.integer(r.af_.word);
s.integer(r.bc_.word);
s.integer(r.de_.word);
s.integer(r.hl_.word);
s.integer(r.ei);
s.integer(r.halt);
s.integer(r.iff1);
s.integer(r.iff2);
s.integer(r.im);
//todo: r.hlp is not serializable
}
auto Z80::Bus::serialize(serializer& s) -> void {
s.integer(_requested);
s.integer(_granted);
}

View File

@ -8,6 +8,7 @@ namespace Processor {
#include "memory.cpp"
#include "instruction.cpp"
#include "instructions.cpp"
#include "serialization.cpp"
auto Z80::power() -> void {
memory::fill(&r, sizeof(Registers));

View File

@ -18,6 +18,9 @@ struct Z80 {
virtual auto in(uint8 addr) -> uint8 = 0;
virtual auto out(uint8 addr, uint8 data) -> void = 0;
//serialization.cpp
virtual auto serialize(serializer&) -> void;
private:
bool _requested;
bool _granted;
@ -205,6 +208,9 @@ struct Z80 {
auto instructionXOR_a_n() -> void;
auto instructionXOR_a_r(uint8&) -> void;
//serialization.cpp
auto serialize(serializer&) -> void;
//disassembler.cpp
auto disassemble(uint16 pc) -> string;
auto disassemble(uint16 pc, uint8 prefix, uint8 code) -> string;
@ -229,10 +235,10 @@ struct Z80 {
uint16 sp;
uint16 pc;
boolean ei; //EI instruction executed
boolean halt; //HALT instruction executed
boolean iff1; //interrupt flip-flop 1
boolean iff2; //interrupt flip-flop 2
bool ei; //EI instruction executed
bool halt; //HALT instruction executed
bool iff1; //interrupt flip-flop 1
bool iff2; //interrupt flip-flop 2
uint2 im; //interrupt mode (0-2)
Pair* hlp = nullptr;

View File

@ -11,9 +11,6 @@ Interface::Interface() {
information.name = "Super Famicom";
information.overscan = true;
information.capability.states = true;
information.capability.cheats = true;
media.append({ID::SuperFamicom, "Super Famicom", "sfc"});
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};

View File

@ -7,9 +7,6 @@ Settings settings;
#include "wonderswan-color.cpp"
Interface::Interface() {
information.capability.states = true;
information.capability.cheats = true;
Port hardwareHorizontalPort{ID::Port::HardwareHorizontal, "Hardware - Horizontal"};
Port hardwareVerticalPort{ID::Port::HardwareVertical, "Hardware - Vertical"};