Update to v106r52 release.

byuu says:

I stand corrected, I managed to create and even larger diff than ever.
This one weighs in at 309KiB `>__>`

I'll have to create a changelog later, I'm too tired right now to go
through all of that.
This commit is contained in:
Tim Allen 2018-07-25 22:24:03 +10:00
parent f1a4576ac4
commit 22bd4b9277
171 changed files with 1725 additions and 1403 deletions

View File

@ -1,4 +1,4 @@
target := higan target := bsnes
binary := application binary := application
build := performance build := performance
openmp := true openmp := true
@ -42,6 +42,49 @@ obj/audio.o: audio/audio.cpp
obj/video.o: video/video.cpp obj/video.o: video/video.cpp
obj/resource.o: resource/resource.cpp obj/resource.o: resource/resource.cpp
ifeq ($(target),higan)
cores := fc sfc ms md pce gb gba ws
endif
ifeq ($(target),bsnes)
cores := sfc gb
endif
ifneq ($(filter $(cores),fc),)
include fc/GNUmakefile
endif
ifneq ($(filter $(cores),sfc),)
include sfc/GNUmakefile
endif
ifneq ($(filter $(cores),ms),)
include ms/GNUmakefile
endif
ifneq ($(filter $(cores),md),)
include md/GNUmakefile
endif
ifneq ($(filter $(cores),pce),)
include pce/GNUmakefile
endif
ifneq ($(filter $(cores),gb),)
include gb/GNUmakefile
endif
ifneq ($(filter $(cores),gba),)
include gba/GNUmakefile
endif
ifneq ($(filter $(cores),ws),)
include ws/GNUmakefile
endif
include processor/GNUmakefile
flags += $(foreach c,$(call strupper,$(cores)),-DCORE_$c)
ui := target-$(target) ui := target-$(target)
include $(ui)/GNUmakefile include $(ui)/GNUmakefile
-include obj/*.d -include obj/*.d

View File

@ -17,11 +17,11 @@ struct Cheat {
codes.reset(); codes.reset();
} }
auto append(uint addr, uint data, maybe<uint> comp = nothing) -> void { auto append(uint addr, uint data, maybe<uint> comp = {}) -> void {
codes.append({addr, data, comp}); codes.append({addr, data, comp});
} }
auto assign(const string_vector& list) -> void { auto assign(const vector<string>& list) -> void {
reset(); reset();
for(auto& entry : list) { for(auto& entry : list) {
for(auto code : entry.split("+")) { for(auto code : entry.split("+")) {

View File

@ -6,7 +6,7 @@ struct Game {
struct Memory; struct Memory;
struct Oscillator; struct Oscillator;
inline auto load(string_view) -> void; inline auto load(view<string>) -> void;
inline auto memory(Markup::Node) -> maybe<Memory>; inline auto memory(Markup::Node) -> maybe<Memory>;
inline auto oscillator(natural = 0) -> maybe<Oscillator>; inline auto oscillator(natural = 0) -> maybe<Oscillator>;
@ -44,7 +44,7 @@ struct Game {
vector<Oscillator> oscillatorList; vector<Oscillator> oscillatorList;
}; };
auto Game::load(string_view text) -> void { auto Game::load(view<string> text) -> void {
document = BML::unserialize(text); document = BML::unserialize(text);
sha256 = document["game/sha256"].text(); sha256 = document["game/sha256"].text();

View File

@ -3,22 +3,20 @@
namespace Emulator { namespace Emulator {
struct Interface { struct Interface {
//information
struct Information { struct Information {
string manufacturer; string manufacturer;
string name; string name;
string extension; string extension;
bool resettable = false; bool resettable = false;
}; };
virtual auto information() -> Information = 0;
virtual auto manifest() -> string = 0;
virtual auto title() -> string = 0;
struct Display { struct Display {
struct Type { enum : uint { struct Type { enum : uint {
CRT, CRT,
LCD, LCD,
};}; };};
uint id = 0;
string name;
uint type = 0; uint type = 0;
uint colors = 0; uint colors = 0;
uint width = 0; uint width = 0;
@ -28,28 +26,16 @@ struct Interface {
double aspectCorrection = 0; double aspectCorrection = 0;
double refreshRate = 0; double refreshRate = 0;
}; };
virtual auto display() -> Display = 0;
virtual auto color(uint32 color) -> uint64 = 0;
//game interface
virtual auto loaded() -> bool = 0;
virtual auto sha256() -> string { return ""; }
virtual auto load() -> bool = 0;
virtual auto save() -> void = 0;
virtual auto unload() -> void = 0;
//system interface
struct Port { struct Port {
uint id; uint id;
string name; string name;
}; };
virtual auto ports() -> vector<Port> = 0;
struct Device { struct Device {
uint id; uint id;
string name; string name;
}; };
virtual auto devices(uint port) -> vector<Device> = 0;
struct Input { struct Input {
struct Type { enum : uint { struct Type { enum : uint {
@ -60,35 +46,51 @@ struct Interface {
Axis, Axis,
Rumble, Rumble,
};}; };};
uint type; uint type;
string name; string name;
}; };
virtual auto inputs(uint device) -> vector<Input> = 0;
//information
virtual auto information() -> Information { return {}; }
virtual auto displays() -> vector<Display> { return {}; }
virtual auto color(uint32 color) -> uint64 { return 0; }
//game interface
virtual auto loaded() -> bool { return false; }
virtual auto hashes() -> vector<string> { return {}; }
virtual auto manifests() -> vector<string> { return {}; }
virtual auto titles() -> vector<string> { return {}; }
virtual auto load() -> bool { return false; }
virtual auto save() -> void {}
virtual auto unload() -> void {}
//system interface
virtual auto ports() -> vector<Port> { return {}; }
virtual auto devices(uint port) -> vector<Device> { return {}; }
virtual auto inputs(uint device) -> vector<Input> { return {}; }
virtual auto connected(uint port) -> uint { return 0; } virtual auto connected(uint port) -> uint { return 0; }
virtual auto connect(uint port, uint device) -> void {} virtual auto connect(uint port, uint device) -> void {}
virtual auto power() -> void = 0; virtual auto power() -> void {}
virtual auto reset() -> void {} virtual auto reset() -> void {}
virtual auto run() -> void = 0; virtual auto run() -> void {}
//time functions //time functions
virtual auto rtc() -> bool { return false; } virtual auto rtc() -> bool { return false; }
virtual auto rtcSynchronize() -> void {} virtual auto synchronize(uint64 timestamp = 0) -> void {}
//state functions //state functions
virtual auto serialize() -> serializer = 0; virtual auto serialize() -> serializer { return {}; }
virtual auto unserialize(serializer&) -> bool = 0; virtual auto unserialize(serializer&) -> bool { return false; }
//cheat functions //cheat functions
virtual auto cheatSet(const string_vector& = {}) -> void {} virtual auto cheats(const vector<string>& = {}) -> void {}
//settings //settings
virtual auto cap(const string& name) -> bool { return false; } virtual auto cap(const string& name) -> bool { return false; }
virtual auto get(const string& name) -> any { return {}; } virtual auto get(const string& name) -> any { return {}; }
virtual auto set(const string& name, const any& value) -> bool { return false; } virtual auto set(const string& name, const any& value) -> bool { return false; }
//shared functions
auto videoColor(uint16 r, uint16 g, uint16 b) -> uint32;
}; };
} }

View File

@ -4,27 +4,24 @@ namespace Emulator {
struct Platform { struct Platform {
struct Load { struct Load {
Load() : _pathID(nothing) {} Load() = default;
Load(uint pathID, string option = "") : _pathID(pathID), _option(option) {} Load(uint pathID, string option = "") : valid(true), pathID(pathID), option(option) {}
explicit operator bool() const { return valid; }
explicit operator bool() const { return (bool)_pathID; } bool valid = false;
auto pathID() const -> uint { return _pathID(); } uint pathID = 0;
auto option() const -> string { return _option; } string option;
private:
maybe<uint> _pathID;
string _option;
}; };
virtual auto path(uint id) -> string { return ""; } virtual auto path(uint id) -> string { return ""; }
virtual auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return {}; } virtual auto open(uint id, string name, vfs::file::mode mode, bool required = false) -> vfs::shared::file { return {}; }
virtual auto load(uint id, string name, string type, string_vector options = {}) -> Load { return {}; } virtual auto load(uint id, string name, string type, vector<string> options = {}) -> Load { return {}; }
virtual auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {} virtual auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void {}
virtual auto audioSample(const double* samples, uint channels) -> void {} virtual auto audioSample(const double* samples, uint channels) -> void {}
virtual auto inputPoll(uint port, uint device, uint input) -> int16 { return 0; } virtual auto inputPoll(uint port, uint device, uint input) -> int16 { return 0; }
virtual auto inputRumble(uint port, uint device, uint input, bool enable) -> void {} virtual auto inputRumble(uint port, uint device, uint input, bool enable) -> void {}
virtual auto dipSettings(Markup::Node node) -> uint { return 0; } virtual auto dipSettings(Markup::Node node) -> uint { return 0; }
virtual auto notify(string text) -> void { print(text, "\n"); } virtual auto notify(string text) -> void {}
}; };
extern Platform* platform; extern Platform* platform;

View File

@ -22,6 +22,7 @@ struct BandaiFCG : Board {
case 2: return 0x0000 | (addr & 0x03ff); case 2: return 0x0000 | (addr & 0x03ff);
case 3: return 0x0400 | (addr & 0x03ff); case 3: return 0x0400 | (addr & 0x03ff);
} }
unreachable;
} }
auto readPRG(uint addr) -> uint8 { auto readPRG(uint addr) -> uint8 {

View File

@ -151,6 +151,7 @@ struct Sunsoft5B : Board {
case 2: return 0x0000 | (addr & 0x03ff); //first case 2: return 0x0000 | (addr & 0x03ff); //first
case 3: return 0x0400 | (addr & 0x03ff); //second case 3: return 0x0400 | (addr & 0x03ff); //second
} }
unreachable;
} }
auto readCHR(uint addr) -> uint8 { auto readCHR(uint addr) -> uint8 {

View File

@ -17,8 +17,8 @@ auto Cartridge::main() -> void {
auto Cartridge::load() -> bool { auto Cartridge::load() -> bool {
if(auto loaded = platform->load(ID::Famicom, "Famicom", "fc", {"NTSC-J", "NTSC-U", "PAL"})) { if(auto loaded = platform->load(ID::Famicom, "Famicom", "fc", {"NTSC-J", "NTSC-U", "PAL"})) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
information.region = loaded.option(); information.region = loaded.option;
} else return false; } else return false;
if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) {

View File

@ -10,7 +10,7 @@ struct Cartridge : Thread {
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto region() const -> string { return information.region; } auto region() const -> string { return information.region; }
auto sha256() const -> string { return information.sha256; } auto hash() const -> string { return information.sha256; }
auto manifest() const -> string { return information.manifest; } auto manifest() const -> string { return information.manifest; }
auto title() const -> string { return information.title; } auto title() const -> string { return information.title; }

View File

@ -34,6 +34,7 @@ struct MMC1 : Chip {
case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); case 2: return ((addr & 0x0400) >> 0) | (addr & 0x03ff);
case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); case 3: return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
} }
unreachable;
} }
auto writeIO(uint addr, uint8 data) -> void { auto writeIO(uint addr, uint8 data) -> void {

View File

@ -35,6 +35,7 @@ struct MMC3 : Chip {
case 3: case 3:
return (0x3f << 13) | (addr & 0x1fff); return (0x3f << 13) | (addr & 0x1fff);
} }
unreachable;
} }
auto addrCHR(uint addr) const -> uint { auto addrCHR(uint addr) const -> uint {
@ -53,11 +54,13 @@ struct MMC3 : Chip {
if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff); if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff);
if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff); if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff);
} }
return 0;
} }
auto addrCIRAM(uint addr) const -> uint { auto addrCIRAM(uint addr) const -> uint {
if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff);
if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
unreachable;
} }
auto readRAM(uint addr) -> uint8 { auto readRAM(uint addr) -> uint8 {

View File

@ -83,6 +83,8 @@ struct MMC5 : Chip {
case 0x5205: return (multiplier * multiplicand) >> 0; case 0x5205: return (multiplier * multiplicand) >> 0;
case 0x5206: return (multiplier * multiplicand) >> 8; case 0x5206: return (multiplier * multiplicand) >> 8;
} }
return 0x00;
} }
auto writePRG(uint addr, uint8 data) -> void { auto writePRG(uint addr, uint8 data) -> void {
@ -215,6 +217,8 @@ struct MMC5 : Chip {
auto bank = chrSpriteBank[(addr / 0x0400)]; auto bank = chrSpriteBank[(addr / 0x0400)];
return (bank * 0x0400) + (addr & 0x03ff); return (bank * 0x0400) + (addr & 0x03ff);
} }
unreachable;
} }
auto chrBGAddr(uint addr) -> uint { auto chrBGAddr(uint addr) -> uint {
@ -239,6 +243,8 @@ struct MMC5 : Chip {
auto bank = chrBGBank[(addr / 0x0400)]; auto bank = chrBGBank[(addr / 0x0400)];
return (bank * 0x0400) + (addr & 0x03ff); return (bank * 0x0400) + (addr & 0x03ff);
} }
unreachable;
} }
auto chrVSAddr(uint addr) -> uint { auto chrVSAddr(uint addr) -> uint {
@ -274,6 +280,7 @@ struct MMC5 : Chip {
case 2: return exramMode < 2 ? exram[addr & 0x03ff] : (uint8)0x00; case 2: return exramMode < 2 ? exram[addr & 0x03ff] : (uint8)0x00;
case 3: return (hcounter & 2) == 0 ? fillmodeTile : fillmodeColor; case 3: return (hcounter & 2) == 0 ? fillmodeTile : fillmodeColor;
} }
unreachable;
} }
auto readCHR(uint addr) -> uint8 { auto readCHR(uint addr) -> uint8 {

View File

@ -35,6 +35,7 @@ struct MMC6 : Chip {
case 3: case 3:
return (0x3f << 13) | (addr & 0x1fff); return (0x3f << 13) | (addr & 0x1fff);
} }
unreachable;
} }
auto addrCHR(uint addr) const -> uint { auto addrCHR(uint addr) const -> uint {
@ -53,11 +54,13 @@ struct MMC6 : Chip {
if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff); if(addr <= 0x17ff) return (chrBank[0] << 10) | (addr & 0x07ff);
if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff); if(addr <= 0x1fff) return (chrBank[1] << 10) | (addr & 0x07ff);
} }
return 0;
} }
auto addrCIRAM(uint addr) const -> uint { auto addrCIRAM(uint addr) const -> uint {
if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff);
if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
unreachable;
} }
auto readRAM(uint addr) -> uint8 { auto readRAM(uint addr) -> uint8 {

View File

@ -115,6 +115,7 @@ struct VRC6 : Chip {
if((addr & 0xc000) == 0x8000) return (prgBank[0] << 14) | (addr & 0x3fff); if((addr & 0xc000) == 0x8000) return (prgBank[0] << 14) | (addr & 0x3fff);
if((addr & 0xe000) == 0xc000) return (prgBank[1] << 13) | (addr & 0x1fff); if((addr & 0xe000) == 0xc000) return (prgBank[1] << 13) | (addr & 0x1fff);
if((addr & 0xe000) == 0xe000) return ( 0xff << 13) | (addr & 0x1fff); if((addr & 0xe000) == 0xe000) return ( 0xff << 13) | (addr & 0x1fff);
return 0x00;
} }
auto addrCHR(uint addr) const -> uint { auto addrCHR(uint addr) const -> uint {
@ -129,6 +130,7 @@ struct VRC6 : Chip {
case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first)
case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second)
} }
unreachable;
} }
auto readRAM(uint addr) -> uint8 { auto readRAM(uint addr) -> uint8 {

View File

@ -96,6 +96,7 @@ struct VRC7 : Chip {
case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first)
case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second)
} }
unreachable;
} }
auto power() -> void { auto power() -> void {

View File

@ -2,36 +2,30 @@
namespace Famicom { namespace Famicom {
#define returns(T) T { return ([&] { struct With : T { With() {
#define $ }}; return With(); })(); }
Settings settings; Settings settings;
auto Interface::information() -> returns(Information) { auto Interface::information() -> Information {
manufacturer = "Nintendo"; Information information;
name = "Famicom"; information.manufacturer = "Nintendo";
resettable = true; information.name = "Famicom";
}$ information.extension = "fc";
information.resettable = true;
auto Interface::manifest() -> string { return information;
return cartridge.manifest();
} }
auto Interface::title() -> string { auto Interface::displays() -> vector<Display> {
return cartridge.title(); Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 9;
display.width = 256;
display.height = 240;
display.internalWidth = 256;
display.internalHeight = 240;
display.aspectCorrection = 8.0 / 7.0;
display.refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0);
return {display};
} }
auto Interface::display() -> returns(Display) {
type = Display::Type::CRT;
colors = 1 << 9;
width = 256;
height = 240;
internalWidth = 256;
internalHeight = 240;
aspectCorrection = 8.0 / 7.0;
refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0);
}$
auto Interface::color(uint32 n) -> uint64 { auto Interface::color(uint32 n) -> uint64 {
double saturation = 2.0; double saturation = 2.0;
double hue = 0.0; double hue = 0.0;
@ -87,8 +81,16 @@ auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::sha256() -> string { auto Interface::hashes() -> vector<string> {
return cartridge.sha256(); return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {cartridge.title()};
} }
auto Interface::load() -> bool { auto Interface::load() -> bool {
@ -181,7 +183,7 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.assign(list); cheat.assign(list);
} }
@ -207,7 +209,4 @@ auto Interface::set(const string& name, const any& value) -> bool {
return false; return false;
} }
#undef returns
#undef $
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_FC)
namespace Famicom { namespace Famicom {
struct ID { struct ID {
@ -19,18 +21,15 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
using Emulator::Interface::load;
auto information() -> Information override; auto information() -> Information override;
auto manifest() -> string override; auto displays() -> vector<Display> override;
auto title() -> string override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto sha256() -> string override; auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto load() -> bool override; auto load() -> bool override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -48,7 +47,7 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override; auto cheats(const vector<string>&) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -67,3 +66,5 @@ struct Settings {
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -3,14 +3,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,12 +17,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature; uint signature;
char version[16]; char version[16];
char hash[64];
char description[512]; char description[512];
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;
@ -54,12 +49,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16]; char version[16];
char hash[64];
char description[512]; char description[512];
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);

View File

@ -28,19 +28,19 @@ auto Cartridge::load() -> bool {
if(Model::GameBoy()) { if(Model::GameBoy()) {
if(auto loaded = platform->load(ID::GameBoy, "Game Boy", "gb")) { if(auto loaded = platform->load(ID::GameBoy, "Game Boy", "gb")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }
if(Model::GameBoyColor()) { if(Model::GameBoyColor()) {
if(auto loaded = platform->load(ID::GameBoyColor, "Game Boy Color", "gbc")) { if(auto loaded = platform->load(ID::GameBoyColor, "Game Boy Color", "gbc")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }
if(Model::SuperGameBoy()) { if(Model::SuperGameBoy()) {
if(auto loaded = platform->load(ID::SuperGameBoy, "Game Boy", "gb")) { if(auto loaded = platform->load(ID::SuperGameBoy, "Game Boy", "gb")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }

View File

@ -1,6 +1,6 @@
struct Cartridge : MMIO { struct Cartridge : MMIO {
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto sha256() const -> string { return information.sha256; } auto hash() const -> string { return information.sha256; }
auto manifest() const -> string { return information.manifest; } auto manifest() const -> string { return information.manifest; }
auto title() const -> string { return information.title; } auto title() const -> string { return information.title; }

View File

@ -1,8 +1,10 @@
auto GameBoyColorInterface::information() -> returns(Information) { auto GameBoyColorInterface::information() -> Information {
manufacturer = "Nintendo"; Information information;
name = "Game Boy Color"; information.manufacturer = "Nintendo";
extension = "gbc"; information.name = "Game Boy Color";
}$ information.extension = "gbc";
return information;
}
auto GameBoyColorInterface::color(uint32 color) -> uint64 { auto GameBoyColorInterface::color(uint32 color) -> uint64 {
uint r = color.bits( 0, 4); uint r = color.bits( 0, 4);

View File

@ -1,8 +1,10 @@
auto GameBoyInterface::information() -> returns(Information) { auto GameBoyInterface::information() -> Information {
manufacturer = "Nintendo"; Information information;
name = "Game Boy"; information.manufacturer = "Nintendo";
extension = "gb"; information.name = "Game Boy";
}$ information.extension = "gb";
return information;
}
auto GameBoyInterface::color(uint32 color) -> uint64 { auto GameBoyInterface::color(uint32 color) -> uint64 {
if(!settings.colorEmulation) { if(!settings.colorEmulation) {

View File

@ -2,39 +2,38 @@
namespace GameBoy { namespace GameBoy {
#define returns(T) T { return ([&] { struct With : T { With() {
#define $ }}; return With(); })(); }
SuperGameBoyInterface* superGameBoy = nullptr; SuperGameBoyInterface* superGameBoy = nullptr;
Settings settings; Settings settings;
#include "game-boy.cpp" #include "game-boy.cpp"
#include "game-boy-color.cpp" #include "game-boy-color.cpp"
auto Interface::manifest() -> string { auto Interface::displays() -> vector<Display> {
return cartridge.manifest(); Display display;
display.type = Display::Type::LCD;
display.colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2;
display.width = 160;
display.height = 144;
display.internalWidth = 160;
display.internalHeight = 144;
display.aspectCorrection = 1.0;
display.refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0);
return {display};
} }
auto Interface::title() -> string {
return cartridge.title();
}
auto Interface::display() -> returns(Display) {
type = Display::Type::LCD;
colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2;
width = 160;
height = 144;
internalWidth = 160;
internalHeight = 144;
aspectCorrection = 1.0;
refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0);
}$
auto Interface::loaded() -> bool { auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::sha256() -> string { auto Interface::hashes() -> vector<string> {
return cartridge.sha256(); return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {cartridge.title()};
} }
auto Interface::save() -> void { auto Interface::save() -> void {
@ -95,7 +94,7 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.assign(list); cheat.assign(list);
} }
@ -129,7 +128,4 @@ auto Interface::set(const string& name, const any& value) -> bool {
return false; return false;
} }
#undef returns
#undef $
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_GB)
namespace GameBoy { namespace GameBoy {
struct ID { struct ID {
@ -18,13 +20,12 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
auto manifest() -> string override; auto displays() -> vector<Display> override;
auto title() -> string override;
auto display() -> Display override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto sha256() -> string override; auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -39,7 +40,7 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override; auto cheats(const vector<string>&) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -47,8 +48,6 @@ struct Interface : Emulator::Interface {
}; };
struct GameBoyInterface : Interface { struct GameBoyInterface : Interface {
using Emulator::Interface::load;
auto information() -> Information override; auto information() -> Information override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
@ -57,8 +56,6 @@ struct GameBoyInterface : Interface {
}; };
struct GameBoyColorInterface : Interface { struct GameBoyColorInterface : Interface {
using Emulator::Interface::load;
auto information() -> Information override; auto information() -> Information override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
@ -85,3 +82,5 @@ extern SuperGameBoyInterface* superGameBoy;
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -3,14 +3,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,12 +17,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature; uint signature;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512]; char description[512];
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;
@ -53,12 +48,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);

View File

@ -37,6 +37,7 @@ auto APU::Noise::read(uint addr) const -> uint8 {
case 3: return (divisor << 0) | (narrowlfsr << 3) | (frequency << 4); case 3: return (divisor << 0) | (narrowlfsr << 3) | (frequency << 4);
case 4: return (counter << 6); case 4: return (counter << 6);
} }
return 0;
} }
auto APU::Noise::write(uint addr, uint8 byte) -> void { auto APU::Noise::write(uint addr, uint8 byte) -> void {

View File

@ -69,6 +69,7 @@ auto APU::Sequencer::read(uint addr) const -> uint8 {
| (masterenable << 7) | (masterenable << 7)
); );
} }
return 0;
} }
auto APU::Sequencer::write(uint addr, uint8 byte) -> void { auto APU::Sequencer::write(uint addr, uint8 byte) -> void {

View File

@ -30,6 +30,7 @@ auto APU::Square1::read(uint addr) const -> uint8 {
case 3: return 0; case 3: return 0;
case 4: return (counter << 6); case 4: return (counter << 6);
} }
return 0;
} }
auto APU::Square1::write(uint addr, uint8 byte) -> void { auto APU::Square1::write(uint addr, uint8 byte) -> void {

View File

@ -5,6 +5,7 @@ auto APU::Square2::read(uint addr) const -> uint8 {
case 3: return 0; case 3: return 0;
case 4: return (counter << 6); case 4: return (counter << 6);
} }
return 0;
} }
auto APU::Square2::write(uint addr, uint8 byte) -> void { auto APU::Square2::write(uint addr, uint8 byte) -> void {

View File

@ -25,6 +25,7 @@ auto APU::Wave::read(uint addr) const -> uint8 {
case 3: return 0; case 3: return 0;
case 4: return (counter << 6); case 4: return (counter << 6);
} }
return 0;
} }
auto APU::Wave::write(uint addr, uint8 byte) -> void { auto APU::Wave::write(uint addr, uint8 byte) -> void {

View File

@ -27,7 +27,7 @@ auto Cartridge::load() -> bool {
information = Information(); information = Information();
if(auto loaded = platform->load(ID::GameBoyAdvance, "Game Boy Advance", "gba")) { if(auto loaded = platform->load(ID::GameBoyAdvance, "Game Boy Advance", "gba")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) {

View File

@ -2,7 +2,7 @@ struct Cartridge {
#include "memory.hpp" #include "memory.hpp"
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto sha256() const -> string { return information.sha256; } auto hash() const -> string { return information.sha256; }
auto manifest() const -> string { return information.manifest; } auto manifest() const -> string { return information.manifest; }
auto title() const -> string { return information.title; } auto title() const -> string { return information.title; }

View File

@ -2,38 +2,32 @@
namespace GameBoyAdvance { namespace GameBoyAdvance {
#define returns(T) T { return ([&] { struct With : T { With() {
#define $ }}; return With(); })(); }
Settings settings; Settings settings;
auto Interface::information() -> returns(Information) { auto Interface::information() -> Information {
manufacturer = "Nintendo"; Information information;
name = "Game Boy Advance"; information.manufacturer = "Nintendo";
}$ information.name = "Game Boy Advance";
information.extension = "gba";
auto Interface::manifest() -> string { return information;
return cartridge.manifest();
} }
auto Interface::title() -> string { auto Interface::displays() -> vector<Display> {
return cartridge.title(); Display display;
} display.type = Display::Type::LCD;
display.colors = 1 << 15;
auto Interface::display() -> returns(Display) { display.width = 240;
type = Display::Type::LCD; display.height = 160;
colors = 1 << 15; display.internalWidth = 240;
width = 240; display.internalHeight = 160;
height = 160; display.aspectCorrection = 1.0;
internalWidth = 240; display.refreshRate = system.frequency() / (228.0 * 1232.0);
internalHeight = 160;
aspectCorrection = 1.0;
refreshRate = system.frequency() / (228.0 * 1232.0);
if(settings.rotateLeft) { if(settings.rotateLeft) {
swap(width, height); swap(display.width, display.height);
swap(internalWidth, internalHeight); swap(display.internalWidth, display.internalHeight);
}
return {display};
} }
}$
auto Interface::color(uint32 color) -> uint64 { auto Interface::color(uint32 color) -> uint64 {
uint R = color.bits( 0, 4); uint R = color.bits( 0, 4);
@ -61,6 +55,18 @@ auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::hashes() -> vector<string> {
return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {cartridge.title()};
}
auto Interface::load() -> bool { auto Interface::load() -> bool {
return system.load(this); return system.load(this);
} }
@ -159,7 +165,4 @@ auto Interface::set(const string& name, const any& value) -> bool {
return false; return false;
} }
#undef returns
#undef $
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_GBA)
namespace GameBoyAdvance { namespace GameBoyAdvance {
struct ID { struct ID {
@ -16,17 +18,15 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
using Emulator::Interface::load;
auto information() -> Information override; auto information() -> Information override;
auto manifest() -> string override; auto displays() -> vector<Display> override;
auto title() -> string override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto load() -> bool override; auto load() -> bool override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -55,3 +55,5 @@ struct Settings {
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -101,6 +101,8 @@ auto PPU::readOAM(uint mode, uint32 addr) -> uint32 {
} }
} }
unreachable;
} }
auto PPU::writeOAM(uint mode, uint32 addr, uint32 word) -> void { auto PPU::writeOAM(uint mode, uint32 addr, uint32 word) -> void {

View File

@ -3,14 +3,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,12 +17,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;
@ -55,12 +50,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);

View File

@ -11,6 +11,8 @@ auto APU::read(uint16 addr) -> uint8 {
if((addr & 0x8000) == 0x8000) { if((addr & 0x8000) == 0x8000) {
return cartridge.read(io.bank << 15 | (addr & 0x7ffe)).byte(!addr.bit(0)); return cartridge.read(io.bank << 15 | (addr & 0x7ffe)).byte(!addr.bit(0));
} }
return 0x00;
} }
auto APU::write(uint16 addr, uint8 data) -> void { auto APU::write(uint16 addr, uint8 data) -> void {

View File

@ -5,40 +5,147 @@ namespace MegaDrive {
Cartridge cartridge; Cartridge cartridge;
#include "serialization.cpp" #include "serialization.cpp"
auto Cartridge::region() const -> string {
return game.region;
}
auto Cartridge::hashes() const -> vector<string> {
vector<string> hashes;
hashes.append(game.hash);
if(lockOn.hash) hashes.append(lockOn.hash);
return hashes;
}
auto Cartridge::manifests() const -> vector<string> {
vector<string> manifests;
manifests.append(game.manifest);
if(lockOn.manifest) manifests.append(lockOn.manifest);
return manifests;
}
auto Cartridge::titles() const -> vector<string> {
vector<string> titles;
titles.append(game.title);
if(lockOn.title) titles.append(lockOn.title);
return titles;
}
auto Cartridge::load() -> bool { auto Cartridge::load() -> bool {
information = {}; game = {};
lockOn = {};
read.reset();
write.reset();
if(!loadGame()) {
game = {};
return false;
}
read = {&Cartridge::readGame, this};
write = {&Cartridge::writeGame, this};
if(game.patch.size) {
read = {&Cartridge::readLockOn, this};
write = {&Cartridge::writeLockOn, this};
if(!loadLockOn()) lockOn = {};
}
return true;
}
auto Cartridge::loadGame() -> bool {
if(auto loaded = platform->load(ID::MegaDrive, "Mega Drive", "md", {"Auto", "NTSC-J", "NTSC-U", "PAL"})) { if(auto loaded = platform->load(ID::MegaDrive, "Mega Drive", "md", {"Auto", "NTSC-J", "NTSC-U", "PAL"})) {
information.pathID = loaded.pathID(); game.pathID = loaded.pathID;
information.region = loaded.option(); game.region = loaded.option;
} else return false; } else return false;
if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { if(auto fp = platform->open(game.pathID, "manifest.bml", File::Read, File::Required)) {
information.manifest = fp->reads(); game.manifest = fp->reads();
} else return false; } else return false;
auto document = BML::unserialize(information.manifest); game.document = BML::unserialize(game.manifest);
information.title = document["game/label"].text(); game.hash = game.document["game/sha256"].text();
game.title = game.document["game/label"].text();
if(information.region == "Auto") { if(!loadROM(game.rom, game.pathID, game.document["game/board/memory(type=ROM,content=Program)"])) {
if(auto region = document["game/region"].text()) { game.rom.reset();
information.region = region.upcase(); return false;
}
if(!loadROM(game.patch, game.pathID, game.document["game/board/memory(type=ROM,content=Patch)"])) {
game.patch.reset();
}
if(!loadRAM(game.ram, game.pathID, game.document["game/board/memory(type=RAM,content=Save)"])) {
game.ram.reset();
}
if(game.region == "Auto") {
if(auto region = game.document["game/region"].text()) {
game.region = region.upcase();
} else { } else {
information.region = "NTSC-J"; game.region = "NTSC-J";
} }
} }
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) { return true;
rom.size = memory.size >> 1; }
auto Cartridge::loadLockOn() -> bool {
if(auto loaded = platform->load(ID::MegaDrive, "Mega Drive", "md")) {
lockOn.pathID = loaded.pathID;
} else return false;
if(auto fp = platform->open(lockOn.pathID, "manifest.bml", File::Read, File::Required)) {
lockOn.manifest = fp->reads();
} else return false;
lockOn.document = BML::unserialize(lockOn.manifest);
lockOn.hash = lockOn.document["game/sha256"].text();
lockOn.title = lockOn.document["game/label"].text();
if(!loadROM(lockOn.rom, lockOn.pathID, lockOn.document["game/board/memory(type=ROM,content=Program)"])) {
lockOn.rom.reset();
return false;
}
if(!loadRAM(lockOn.ram, lockOn.pathID, lockOn.document["game/board/memory(type=RAM,content=Save)"])) {
lockOn.ram.reset();
}
if(lockOn.rom.size >= 0x200) {
string name;
name.resize(48);
for(uint n : range(24)) {
name.get()[n * 2 + 0] = lockOn.rom.data[0x120 / 2 + n].byte(1);
name.get()[n * 2 + 1] = lockOn.rom.data[0x120 / 2 + n].byte(0);
}
name.strip();
while(name.find(" ")) name.replace(" ", " ");
lockOn.patch = name == "SONIC THE HEDGEHOG 2";
}
return true;
}
auto Cartridge::loadROM(Memory& rom, uint pathID, Markup::Node memory) -> bool {
if(!memory) return false;
auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase();
rom.size = memory["size"].natural() >> 1;
rom.mask = bit::round(rom.size) - 1; rom.mask = bit::round(rom.size) - 1;
rom.data = new uint16[rom.mask + 1](); rom.data = new uint16[rom.mask + 1]();
if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) { if(auto fp = platform->open(pathID, name, File::Read, File::Required)) {
for(uint n : range(rom.size)) rom.data[n] = fp->readm(2); for(uint n : range(rom.size)) rom.data[n] = fp->readm(2);
} } else return false;
return true;
} }
//todo: handle mode, offset in Emulator::Game::Memory auto Cartridge::loadRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool {
if(auto memory = document["game/board/memory(type=RAM,content=Save)"]) { if(!memory) return false;
auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase();
if(auto mode = memory["mode"].text()) { if(auto mode = memory["mode"].text()) {
if(mode == "lo" ) ram.bits = 0x00ff; if(mode == "lo" ) ram.bits = 0x00ff;
if(mode == "hi" ) ram.bits = 0xff00; if(mode == "hi" ) ram.bits = 0xff00;
@ -48,38 +155,46 @@ auto Cartridge::load() -> bool {
ram.mask = bit::round(ram.size) - 1; ram.mask = bit::round(ram.size) - 1;
ram.data = new uint16[ram.mask + 1](); ram.data = new uint16[ram.mask + 1]();
if(!(bool)memory["volatile"]) { if(!(bool)memory["volatile"]) {
if(auto fp = platform->open(pathID(), "save.ram", File::Read)) { if(auto fp = platform->open(pathID, name, File::Read)) {
for(uint n : range(ram.size)) { for(uint n : range(ram.size)) {
if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101; if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101;
if(ram.bits == 0xffff) ram.data[n] = fp->readm(2); if(ram.bits == 0xffff) ram.data[n] = fp->readm(2);
} }
} }
} }
}
return true; return true;
} }
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest); saveRAM(game.ram, game.pathID, game.document["game/board/memory(type=RAM,content=Save)"]);
saveRAM(lockOn.ram, lockOn.pathID, lockOn.document["game/board/memory(type=RAM,content=Save)"]);
}
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) { auto Cartridge::saveRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool {
if(memory.nonVolatile) { if(!memory) return false;
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) { if((bool)memory["volatile"]) return true;
auto name = string{memory["content"].text(), ".", memory["type"].text()}.downcase();
if(auto fp = platform->open(pathID, name, File::Write)) {
for(uint n : range(ram.size)) { for(uint n : range(ram.size)) {
if(ram.bits != 0xffff) fp->writem(ram.data[n], 1); if(ram.bits != 0xffff) fp->writem(ram.data[n], 1);
if(ram.bits == 0xffff) fp->writem(ram.data[n], 2); if(ram.bits == 0xffff) fp->writem(ram.data[n], 2);
} }
} } else return false;
}
} return true;
} }
auto Cartridge::unload() -> void { auto Cartridge::unload() -> void {
delete[] rom.data; game.rom.reset();
delete[] ram.data; game.patch.reset();
rom = {}; game.ram.reset();
ram = {}; game = {};
lockOn.rom.reset();
lockOn.ram.reset();
lockOn = {};
} }
auto Cartridge::power() -> void { auto Cartridge::power() -> void {
@ -88,37 +203,81 @@ auto Cartridge::power() -> void {
for(auto n : range(8)) bank[n] = n; for(auto n : range(8)) bank[n] = n;
} }
auto Cartridge::read(uint24 address) -> uint16 { //
if(address.bit(21) && ram.size && ramEnable) {
return ram.data[address >> 1 & ram.mask];
} else {
address = bank[address.bits(19,21)] << 19 | address.bits(0,18);
return rom.data[address >> 1 & rom.mask];
}
}
auto Cartridge::write(uint24 address, uint16 data) -> void { auto Cartridge::readIO(uint24 address) -> uint16 {
//emulating RAM write protect bit breaks some commercial software
if(address.bit(21) && ram.size && ramEnable /* && ramWritable */) {
if(ram.bits == 0x00ff) data = data.byte(0) * 0x0101;
if(ram.bits == 0xff00) data = data.byte(1) * 0x0101;
ram.data[address >> 1 & ram.mask] = data;
}
}
auto Cartridge::readIO(uint24 addr) -> uint16 {
return 0x0000; return 0x0000;
} }
auto Cartridge::writeIO(uint24 addr, uint16 data) -> void { auto Cartridge::writeIO(uint24 address, uint16 data) -> void {
if(addr == 0xa130f1) ramEnable = data.bit(0), ramWritable = data.bit(1); if(address == 0xa130f1) ramEnable = data.bit(0), ramWritable = data.bit(1);
if(addr == 0xa130f3) bank[1] = data; if(address == 0xa130f3) bank[1] = data;
if(addr == 0xa130f5) bank[2] = data; if(address == 0xa130f5) bank[2] = data;
if(addr == 0xa130f7) bank[3] = data; if(address == 0xa130f7) bank[3] = data;
if(addr == 0xa130f9) bank[4] = data; if(address == 0xa130f9) bank[4] = data;
if(addr == 0xa130fb) bank[5] = data; if(address == 0xa130fb) bank[5] = data;
if(addr == 0xa130fd) bank[6] = data; if(address == 0xa130fd) bank[6] = data;
if(addr == 0xa130ff) bank[7] = data; if(address == 0xa130ff) bank[7] = data;
}
//
auto Cartridge::readGame(uint24 address) -> uint16 {
if(address >= 0x200000 && game.ram.size && ramEnable) {
return game.ram.data[address >> 1 & game.ram.mask];
} else {
address = bank[address.bits(19,21)] << 19 | address.bits(0,18);
return game.rom.data[address >> 1 & game.rom.mask];
}
}
auto Cartridge::writeGame(uint24 address, uint16 data) -> void {
//emulating RAM write protect bit breaks some commercial software
if(address >= 0x200000 && game.ram.size && ramEnable /* && ramWritable */) {
if(game.ram.bits == 0x00ff) data = data.byte(0) * 0x0101;
if(game.ram.bits == 0xff00) data = data.byte(1) * 0x0101;
game.ram.data[address >> 1 & game.ram.mask] = data;
}
}
//
auto Cartridge::readLockOn(uint24 address) -> uint16 {
if(address >= 0x200000 && lockOn.ram.size && ramEnable) {
return lockOn.ram.data[address >> 1 & lockOn.ram.mask];
}
if(address >= 0x300000 && lockOn.patch) {
return game.patch.data[address >> 1 & game.patch.mask];
}
if(address >= 0x200000 && lockOn.rom.data) {
return lockOn.rom.data[address >> 1 & lockOn.rom.mask];
}
if(address >= 0x200000) {
return 0x00;
}
return game.rom.data[address >> 1 & game.rom.mask];
}
auto Cartridge::writeLockOn(uint24 address, uint16 data) -> void {
if(address >= 0x200000 && lockOn.ram.size && ramEnable) {
if(lockOn.ram.bits == 0x00ff) data = data.byte(0) * 0x0101;
if(lockOn.ram.bits == 0xff00) data = data.byte(1) * 0x0101;
lockOn.ram.data[address >> 1 & lockOn.ram.mask] = data;
}
}
//
auto Cartridge::Memory::reset() -> void {
delete[] data;
data = nullptr;
size = 0;
mask = 0;
bits = 0;
} }
} }

View File

@ -1,42 +1,70 @@
struct Cartridge { struct Cartridge {
auto pathID() const -> uint { return information.pathID; } auto region() const -> string;
auto region() const -> string { return information.region; } auto hashes() const -> vector<string>;
auto sha256() const -> string { return information.sha256; } auto manifests() const -> vector<string>;
auto manifest() const -> string { return information.manifest; } auto titles() const -> vector<string>;
auto title() const -> string { return information.title; }
struct Memory;
auto load() -> bool; auto load() -> bool;
auto loadGame() -> bool;
auto loadLockOn() -> bool;
auto loadROM(Memory& rom, uint pathID, Markup::Node memory) -> bool;
auto loadRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool;
auto save() -> void; auto save() -> void;
auto saveRAM(Memory& ram, uint pathID, Markup::Node memory) -> bool;
auto unload() -> void; auto unload() -> void;
auto power() -> void; auto power() -> void;
auto read(uint24 addr) -> uint16; function<uint16 (uint24 address)> read;
auto write(uint24 addr, uint16 data) -> void; function<void (uint24 address, uint16 data)> write;
auto readIO(uint24 addr) -> uint16; auto readIO(uint24 address) -> uint16;
auto writeIO(uint24 addr, uint16 data) -> void; auto writeIO(uint24 address, uint16 data) -> void;
auto readGame(uint24 address) -> uint16;
auto writeGame(uint24 address, uint16 data) -> void;
auto readLockOn(uint24 address) -> uint16;
auto writeLockOn(uint24 address, uint16 data) -> void;
//serialization.cpp //serialization.cpp
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
struct Information {
uint pathID = 0;
string region;
string sha256;
string manifest;
string title;
} information;
struct Memory { struct Memory {
auto reset() -> void;
uint16* data = nullptr; uint16* data = nullptr;
uint size = 0; uint size = 0;
uint mask = 0; uint mask = 0;
uint bits = 0; uint bits = 0;
}; };
struct Game {
uint pathID = 0;
string region;
string hash;
string manifest;
string title;
Markup::Node document;
Memory rom;
Memory patch;
Memory ram;
} game;
struct LockOn {
uint pathID = 0;
string hash;
string manifest;
string title;
Markup::Node document;
Memory rom; Memory rom;
Memory ram; Memory ram;
bool patch = false;
} lockOn;
uint1 ramEnable; uint1 ramEnable;
uint1 ramWritable; uint1 ramWritable;
uint6 bank[8]; uint6 bank[8];

View File

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

View File

@ -2,36 +2,30 @@
namespace MegaDrive { namespace MegaDrive {
#define returns(T) T { return ([&] { struct With : T { With() {
#define $ }}; return With(); })(); }
Settings settings; Settings settings;
auto Interface::information() -> returns(Information) { auto Interface::information() -> Information {
manufacturer = "Sega"; Information information;
name = "Mega Drive"; information.manufacturer = "Sega";
resettable = true; information.name = "Mega Drive";
}$ information.extension = "md";
information.resettable = true;
auto Interface::manifest() -> string { return information;
return cartridge.manifest();
} }
auto Interface::title() -> string { auto Interface::displays() -> vector<Display> {
return cartridge.title(); Display display;
display.type = Display::Type::CRT;
display.colors = 3 * (1 << 9);
display.width = 320;
display.height = 240;
display.internalWidth = 1280;
display.internalHeight = 480;
display.aspectCorrection = 1.0;
display.refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0);
return {display};
} }
auto Interface::display() -> returns(Display) {
type = Display::Type::CRT;
colors = 3 * (1 << 9);
width = 320;
height = 240;
internalWidth = 1280;
internalHeight = 480;
aspectCorrection = 1.0;
refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0);
}$
auto Interface::color(uint32 color) -> uint64 { auto Interface::color(uint32 color) -> uint64 {
uint R = color.bits(0, 2); uint R = color.bits(0, 2);
uint G = color.bits(3, 5); uint G = color.bits(3, 5);
@ -55,6 +49,18 @@ auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::hashes() -> vector<string> {
return cartridge.hashes();
}
auto Interface::manifests() -> vector<string> {
return cartridge.manifests();
}
auto Interface::titles() -> vector<string> {
return cartridge.titles();
}
auto Interface::load() -> bool { auto Interface::load() -> bool {
return system.load(this); return system.load(this);
} }
@ -163,7 +169,7 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.assign(list); cheat.assign(list);
} }
@ -179,7 +185,4 @@ auto Interface::set(const string& name, const any& value) -> bool {
return false; return false;
} }
#undef returns
#undef $
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_MD)
namespace MegaDrive { namespace MegaDrive {
struct ID { struct ID {
@ -20,17 +22,15 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
using Emulator::Interface::load;
auto information() -> Information override; auto information() -> Information override;
auto manifest() -> string override; auto displays() -> vector<Display> override;
auto title() -> string override;
auto display() -> Display override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto load() -> bool override; auto load() -> bool override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -48,7 +48,7 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector& list) -> void override; auto cheats(const vector<string>& list) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -64,3 +64,5 @@ struct Settings {
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -3,12 +3,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,14 +18,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -37,12 +32,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;

View File

@ -11,14 +11,14 @@ auto Cartridge::load() -> bool {
if(Model::MasterSystem()) { if(Model::MasterSystem()) {
if(auto loaded = platform->load(ID::MasterSystem, "Master System", "ms", {"NTSC", "PAL"})) { if(auto loaded = platform->load(ID::MasterSystem, "Master System", "ms", {"NTSC", "PAL"})) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
information.region = loaded.option(); information.region = loaded.option;
} else return false; } else return false;
} }
if(Model::GameGear()) { if(Model::GameGear()) {
if(auto loaded = platform->load(ID::GameGear, "Game Gear", "gg", {"NTSC"})) { if(auto loaded = platform->load(ID::GameGear, "Game Gear", "gg", {"NTSC"})) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }

View File

@ -1,7 +1,7 @@
struct Cartridge { struct Cartridge {
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto region() const -> string { return information.region; } auto region() const -> string { return information.region; }
auto sha256() const -> string { return information.sha256; } auto hash() const -> string { return information.sha256; }
auto manifest() const -> string { return information.manifest; } auto manifest() const -> string { return information.manifest; }
auto title() const -> string { return information.title; } auto title() const -> string { return information.title; }

View File

@ -1,42 +1,25 @@
GameGearInterface::GameGearInterface() { auto GameGearInterface::information() -> Information {
Information information;
information.manufacturer = "Sega"; information.manufacturer = "Sega";
information.name = "Game Gear"; information.name = "Game Gear";
information.overscan = false; information.extension = "gg";
return information;
media.append({ID::GameGear, "Game Gear", "gg"});
Port hardware{ID::Port::Hardware, "Hardware"};
{ Device device{ID::Device::GameGearControls, "Controls"};
device.inputs.append({0, "Up"});
device.inputs.append({0, "Down"});
device.inputs.append({0, "Left"});
device.inputs.append({0, "Right"});
device.inputs.append({0, "1"});
device.inputs.append({0, "2"});
device.inputs.append({0, "Start"});
hardware.devices.append(device);
} }
ports.append(move(hardware)); auto GameGearInterface::displays() -> vector<Display> {
Display display;
display.type = Display::Type::LCD;
display.colors = 1 << 12;
display.width = 160;
display.height = 144;
display.internalWidth = 160;
display.internalHeight = 144;
display.aspectCorrection = 1.0;
display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
return {display};
} }
auto GameGearInterface::videoInformation() -> VideoInformation { auto GameGearInterface::color(uint32 color) -> uint64 {
VideoInformation vi;
vi.width = 160;
vi.height = 144;
vi.internalWidth = 160;
vi.internalHeight = 144;
vi.aspectCorrection = 1.0;
vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
return vi;
}
auto GameGearInterface::videoColors() -> uint32 {
return 1 << 12;
}
auto GameGearInterface::videoColor(uint32 color) -> uint64 {
uint4 B = color >> 8; uint4 B = color >> 8;
uint4 G = color >> 4; uint4 G = color >> 4;
uint4 R = color >> 0; uint4 R = color >> 0;
@ -48,7 +31,34 @@ auto GameGearInterface::videoColor(uint32 color) -> uint64 {
return r << 32 | g << 16 | b << 0; return r << 32 | g << 16 | b << 0;
} }
auto GameGearInterface::load(uint id) -> bool { auto GameGearInterface::ports() -> vector<Port> { return {
if(id == ID::GameGear) return system.load(this, System::Model::GameGear); {ID::Port::Hardware, "Hardware"}};
return false; }
auto GameGearInterface::devices(uint port) -> vector<Device> {
if(port == ID::Port::Hardware) return {
{ID::Device::GameGearControls, "Controls"}
};
return {};
}
auto GameGearInterface::inputs(uint device) -> vector<Input> {
using Type = Input::Type;
if(device == ID::Device::GameGearControls) return {
{Type::Hat, "Up" },
{Type::Hat, "Down" },
{Type::Hat, "Left" },
{Type::Hat, "Right"},
{Type::Button, "1" },
{Type::Button, "2" },
{Type::Control, "Start"}
};
return {};
}
auto GameGearInterface::load() -> bool {
return system.load(this, System::Model::GameGear);
} }

View File

@ -6,21 +6,22 @@ Settings settings;
#include "master-system.cpp" #include "master-system.cpp"
#include "game-gear.cpp" #include "game-gear.cpp"
Interface::Interface() {
}
auto Interface::manifest() -> string {
return cartridge.manifest();
}
auto Interface::title() -> string {
return cartridge.title();
}
auto Interface::loaded() -> bool { auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::hashes() -> vector<string> {
return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {cartridge.title()};
}
auto Interface::save() -> void { auto Interface::save() -> void {
system.save(); system.save();
} }
@ -47,7 +48,7 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.assign(list); cheat.assign(list);
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_MS)
namespace MasterSystem { namespace MasterSystem {
struct ID { struct ID {
@ -22,12 +24,10 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
Interface();
auto manifest() -> string override;
auto title() -> string override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -37,7 +37,7 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override; auto cheats(const vector<string>& list) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -45,36 +45,41 @@ struct Interface : Emulator::Interface {
}; };
struct MasterSystemInterface : Interface { struct MasterSystemInterface : Interface {
using Emulator::Interface::load; auto information() -> Information override;
MasterSystemInterface(); auto displays() -> vector<Display> override;
auto color(uint32 color) -> uint64 override;
auto videoInformation() -> VideoInformation override; auto ports() -> vector<Port> override;
auto videoColors() -> uint32 override; auto devices(uint port) -> vector<Device> override;
auto videoColor(uint32 color) -> uint64 override; auto inputs(uint device) -> vector<Input> override;
auto load(uint id) -> bool override; auto load() -> bool override;
auto connected(uint port) -> uint override;
auto connect(uint port, uint device) -> void override; auto connect(uint port, uint device) -> void override;
}; };
struct GameGearInterface : Interface { struct GameGearInterface : Interface {
using Emulator::Interface::load; auto information() -> Information override;
GameGearInterface(); auto displays() -> vector<Display> override;
auto color(uint32 color) -> uint64 override;
auto videoInformation() -> VideoInformation override; auto ports() -> vector<Port> override;
auto videoColors() -> uint32 override; auto devices(uint port) -> vector<Device> override;
auto videoColor(uint32 color) -> uint64 override; auto inputs(uint device) -> vector<Input> override;
auto load(uint id) -> bool override; auto load() -> bool override;
}; };
struct Settings { struct Settings {
uint controllerPort1 = 0; uint controllerPort1 = ID::Device::Gamepad;
uint controllerPort2 = 0; uint controllerPort2 = ID::Device::Gamepad;
}; };
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -1,58 +1,26 @@
MasterSystemInterface::MasterSystemInterface() { auto MasterSystemInterface::information() -> Information {
Information information;
information.manufacturer = "Sega"; information.manufacturer = "Sega";
information.name = "Master System"; information.name = "Master System";
information.overscan = true; information.extension = "ms";
return information;
media.append({ID::MasterSystem, "Master System", "ms"});
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};
Port controllerPort2{ID::Port::Controller2, "Controller Port 2"};
Port hardware{ID::Port::Hardware, "Hardware"};
{ Device device{ID::Device::None, "None"};
controllerPort1.devices.append(device);
controllerPort2.devices.append(device);
} }
{ Device device{ID::Device::Gamepad, "Gamepad"}; auto MasterSystemInterface::displays() -> vector<Display> {
device.inputs.append({0, "Up"}); Display display;
device.inputs.append({0, "Down"}); display.type = Display::Type::CRT;
device.inputs.append({0, "Left"}); display.colors = 1 << 6;
device.inputs.append({0, "Right"}); display.width = 256;
device.inputs.append({0, "1"}); display.height = 240;
device.inputs.append({0, "2"}); display.internalWidth = 256;
controllerPort1.devices.append(device); display.internalHeight = 240;
controllerPort2.devices.append(device); display.aspectCorrection = 8.0 / 7.0;
if(Region::NTSC()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return {display};
} }
{ Device device{ID::Device::MasterSystemControls, "Controls"}; auto MasterSystemInterface::color(uint32 color) -> uint64 {
device.inputs.append({0, "Reset"});
device.inputs.append({0, "Pause"});
hardware.devices.append(device);
}
ports.append(move(controllerPort1));
ports.append(move(controllerPort2));
ports.append(move(hardware));
}
auto MasterSystemInterface::videoInformation() -> VideoInformation {
VideoInformation vi;
vi.width = 256;
vi.height = 240;
vi.internalWidth = 256;
vi.internalHeight = 240;
vi.aspectCorrection = 8.0 / 7.0;
if(Region::NTSC()) vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0);
if(Region::PAL()) vi.refreshRate = (system.colorburst() * 15.0 / 5.0) / (312.0 * 684.0);
return vi;
}
auto MasterSystemInterface::videoColors() -> uint32 {
return 1 << 6;
}
auto MasterSystemInterface::videoColor(uint32 color) -> uint64 {
uint2 B = color >> 4; uint2 B = color >> 4;
uint2 G = color >> 2; uint2 G = color >> 2;
uint2 R = color >> 0; uint2 R = color >> 0;
@ -64,9 +32,62 @@ auto MasterSystemInterface::videoColor(uint32 color) -> uint64 {
return r << 32 | g << 16 | b << 0; return r << 32 | g << 16 | b << 0;
} }
auto MasterSystemInterface::load(uint id) -> bool { auto MasterSystemInterface::ports() -> vector<Port> { return {
if(id == ID::MasterSystem) return system.load(this, System::Model::MasterSystem); {ID::Port::Controller1, "Controller Port 1"},
return false; {ID::Port::Controller2, "Controller Port 2"},
{ID::Port::Hardware, "Hardware" }};
}
auto MasterSystemInterface::devices(uint port) -> vector<Device> {
if(port == ID::Port::Controller1) return {
{ID::Device::None, "None" },
{ID::Device::Gamepad, "Gamepad"}
};
if(port == ID::Port::Controller2) return {
{ID::Device::None, "None" },
{ID::Device::Gamepad, "Gamepad"}
};
if(port == ID::Port::Hardware) return {
{ID::Device::MasterSystemControls, "Controls"}
};
return {};
}
auto MasterSystemInterface::inputs(uint device) -> vector<Input> {
using Type = Input::Type;
if(device == ID::Device::None) return {
};
if(device == ID::Device::Gamepad) return {
{Type::Hat, "Up" },
{Type::Hat, "Down" },
{Type::Hat, "Left" },
{Type::Hat, "Right"},
{Type::Button, "1" },
{Type::Button, "2" }
};
if(device == ID::Device::MasterSystemControls) return {
{Type::Control, "Reset"},
{Type::Control, "Power"}
};
return {};
}
auto MasterSystemInterface::load() -> bool {
return system.load(this, System::Model::MasterSystem);
}
auto MasterSystemInterface::connected(uint port) -> uint {
if(port == ID::Port::Controller1) return settings.controllerPort1;
if(port == ID::Port::Controller2) return settings.controllerPort2;
if(port == ID::Port::Hardware) return ID::Device::MasterSystemControls;
return 0;
} }
auto MasterSystemInterface::connect(uint port, uint device) -> void { auto MasterSystemInterface::connect(uint port, uint device) -> void {

View File

@ -3,12 +3,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,14 +18,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -37,12 +32,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;

View File

@ -9,13 +9,13 @@ auto Cartridge::load() -> bool {
if(Model::PCEngine()) { if(Model::PCEngine()) {
if(auto loaded = platform->load(ID::PCEngine, "PC Engine", "pce")) { if(auto loaded = platform->load(ID::PCEngine, "PC Engine", "pce")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }
if(Model::SuperGrafx()) { if(Model::SuperGrafx()) {
if(auto loaded = platform->load(ID::SuperGrafx, "SuperGrafx", "sg")) { if(auto loaded = platform->load(ID::SuperGrafx, "SuperGrafx", "sg")) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
} else return false; } else return false;
} }

View File

@ -1,6 +1,6 @@
struct Cartridge { struct Cartridge {
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto sha256() const -> string { return information.sha256; } auto hash() const -> string { return information.sha256; }
auto manifest() const -> string { return information.manifest; } auto manifest() const -> string { return information.manifest; }
auto title() const -> string { return information.title; } auto title() const -> string { return information.title; }

View File

@ -7,54 +7,20 @@ Settings settings;
#include "pc-engine.cpp" #include "pc-engine.cpp"
#include "supergrafx.cpp" #include "supergrafx.cpp"
Interface::Interface() { auto Interface::displays() -> vector<Display> {
information.overscan = true; Display display;
display.type = Display::Type::CRT;
Port controllerPort{ID::Port::Controller, "Controller Port"}; display.colors = 1 << 9;
display.width = 280;
{ Device device{ID::Device::None, "None"}; display.height = 240;
controllerPort.devices.append(device); display.internalWidth = 1120;
display.internalHeight = 240;
display.aspectCorrection = 8.0 / 7.0;
display.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0);
return {display};
} }
{ Device device{ID::Device::Gamepad, "Gamepad"}; auto Interface::color(uint32 color) -> uint64 {
device.inputs.append({0, "Up"});
device.inputs.append({0, "Down"});
device.inputs.append({0, "Left"});
device.inputs.append({0, "Right"});
device.inputs.append({0, "II"});
device.inputs.append({0, "I"});
device.inputs.append({0, "Select"});
device.inputs.append({0, "Run"});
controllerPort.devices.append(device);
}
ports.append(move(controllerPort));
}
auto Interface::manifest() -> string {
return cartridge.manifest();
}
auto Interface::title() -> string {
return cartridge.title();
}
auto Interface::videoInformation() -> VideoInformation {
VideoInformation vi;
vi.width = 280;
vi.height = 240;
vi.internalWidth = 1120;
vi.internalHeight = 240;
vi.aspectCorrection = 8.0 / 7.0;
vi.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0);
return vi;
}
auto Interface::videoColors() -> uint32 {
return 1 << 9;
}
auto Interface::videoColor(uint32 color) -> uint64 {
uint3 B = color.bits(0,2); uint3 B = color.bits(0,2);
uint3 R = color.bits(3,5); uint3 R = color.bits(3,5);
uint3 G = color.bits(6,8); uint3 G = color.bits(6,8);
@ -70,8 +36,16 @@ auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::sha256() -> string { auto Interface::hashes() -> vector<string> {
return cartridge.sha256(); return {cartridge.hash()};
}
auto Interface::manifests() -> vector<string> {
return {cartridge.manifest()};
}
auto Interface::titles() -> vector<string> {
return {cartridge.title()};
} }
auto Interface::save() -> void { auto Interface::save() -> void {
@ -83,6 +57,35 @@ auto Interface::unload() -> void {
system.unload(); system.unload();
} }
auto Interface::ports() -> vector<Port> { return {
{ID::Port::Controller, "Controller"}};
}
auto Interface::devices(uint port) -> vector<Device> {
if(port == ID::Port::Controller) return {
{ID::Device::Gamepad, "Gamepad"}
};
return {};
}
auto Interface::inputs(uint device) -> vector<Input> {
using Type = Input::Type;
if(device == ID::Device::Gamepad) return {
{Type::Hat, "Up" },
{Type::Hat, "Down" },
{Type::Hat, "Left" },
{Type::Hat, "Right" },
{Type::Button, "II" },
{Type::Button, "I" },
{Type::Control, "Select"},
{Type::Control, "Run" }
};
return {};
}
auto Interface::connected(uint port) -> uint { auto Interface::connected(uint port) -> uint {
if(port == ID::Port::Controller) return settings.controllerPort; if(port == ID::Port::Controller) return settings.controllerPort;
return 0; return 0;
@ -109,7 +112,7 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.assign(list); cheat.assign(list);
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_PCE)
namespace PCEngine { namespace PCEngine {
struct ID { struct ID {
@ -18,20 +20,20 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
Interface(); auto displays() -> vector<Display> override;
auto color(uint32 color) -> uint64 override;
auto manifest() -> string override;
auto title() -> string override;
auto videoInformation() -> VideoInformation override;
auto videoColors() -> uint32 override;
auto videoColor(uint32 color) -> uint64 override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto sha256() -> string override; auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
auto ports() -> vector<Port> override;
auto devices(uint port) -> vector<Device> override;
auto inputs(uint device) -> vector<Input> override;
auto connected(uint port) -> uint override; auto connected(uint port) -> uint override;
auto connect(uint port, uint device) -> void override; auto connect(uint port, uint device) -> void override;
auto power() -> void override; auto power() -> void override;
@ -40,7 +42,7 @@ struct Interface : Emulator::Interface {
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override; auto cheats(const vector<string>& list) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -48,15 +50,15 @@ struct Interface : Emulator::Interface {
}; };
struct PCEngineInterface : Interface { struct PCEngineInterface : Interface {
PCEngineInterface(); auto information() -> Information override;
auto load(uint id) -> bool override; auto load() -> bool override;
}; };
struct SuperGrafxInterface : Interface { struct SuperGrafxInterface : Interface {
SuperGrafxInterface(); auto information() -> Information override;
auto load(uint id) -> bool override; auto load() -> bool override;
}; };
struct Settings { struct Settings {
@ -66,3 +68,5 @@ struct Settings {
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -1,11 +1,11 @@
PCEngineInterface::PCEngineInterface() { auto PCEngineInterface::information() -> Information {
Information information;
information.manufacturer = "NEC"; information.manufacturer = "NEC";
information.name = "PC Engine"; information.name = "PC Engine";
information.extension = "pce";
media.append({ID::PCEngine, "PC Engine", "pce"}); return information;
} }
auto PCEngineInterface::load(uint id) -> bool { auto PCEngineInterface::load() -> bool {
if(id == ID::PCEngine) return system.load(this, System::Model::PCEngine); return system.load(this, System::Model::PCEngine);
return false;
} }

View File

@ -1,11 +1,11 @@
SuperGrafxInterface::SuperGrafxInterface() { auto SuperGrafxInterface::information() -> Information {
Information information;
information.manufacturer = "NEC"; information.manufacturer = "NEC";
information.name = "SuperGrafx"; information.name = "SuperGrafx";
information.extension = "sg";
media.append({ID::SuperGrafx, "SuperGrafx", "sg"}); return information;
} }
auto SuperGrafxInterface::load(uint id) -> bool { auto SuperGrafxInterface::load() -> bool {
if(id == ID::SuperGrafx) return system.load(this, System::Model::SuperGrafx); return system.load(this, System::Model::SuperGrafx);
return false;
} }

View File

@ -3,12 +3,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -20,14 +18,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
serializeAll(s); serializeAll(s);
@ -37,12 +32,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature = 0; uint signature = 0;
char version[16] = {0}; char version[16] = {0};
char hash[64] = {0};
char description[512] = {0}; char description[512] = {0};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;

View File

@ -25,6 +25,8 @@ auto VDC::read(uint2 addr) -> uint8 {
return data; return data;
} }
} }
return 0x00;
} }
auto VDC::write(uint2 addr, uint8 data) -> void { auto VDC::write(uint2 addr, uint8 data) -> void {

View File

@ -62,7 +62,7 @@ auto HuC6280::disassemble(uint16 pc) -> string {
uint8 opcode = readByte(); uint8 opcode = readByte();
#define op(id, name, ...) case id: o = {name, " ", string_vector{__VA_ARGS__}.merge(",")}; break; #define op(id, name, ...) case id: o = {name, " ", vector<string>{__VA_ARGS__}.merge(",")}; break;
string o; string o;
if(T == 1) switch(opcode) { if(T == 1) switch(opcode) {

View File

@ -48,7 +48,7 @@ auto Z80::disassemble(uint16 pc) -> string {
return s; return s;
} }
#define op(id, name, ...) case id: return {name, " ", string_vector{__VA_ARGS__}.merge(",")}; #define op(id, name, ...) case id: return {name, " ", vector<string>{__VA_ARGS__}.merge(",")};
#define N string{"$", hex(byte(), 2L)} #define N string{"$", hex(byte(), 2L)}
#define IN string{"(", N, ")"} #define IN string{"(", N, ")"}

View File

@ -7,23 +7,34 @@ namespace SuperFamicom {
#include "serialization.cpp" #include "serialization.cpp"
Cartridge cartridge; Cartridge cartridge;
auto Cartridge::manifest() const -> string { auto Cartridge::hashes() const -> vector<string> {
string manifest = BML::serialize(game.document); vector<string> hashes;
manifest.append("\n", BML::serialize(board)); hashes.append(game.sha256);
if(slotGameBoy.document) manifest.append("\n", BML::serialize(slotGameBoy.document)); if(slotGameBoy.sha256) hashes.append(slotGameBoy.sha256);
if(slotBSMemory.document) manifest.append("\n", BML::serialize(slotBSMemory.document)); if(slotBSMemory.sha256) hashes.append(slotBSMemory.sha256);
if(slotSufamiTurboA.document) manifest.append("\n", BML::serialize(slotSufamiTurboA.document)); if(slotSufamiTurboA.sha256) hashes.append(slotSufamiTurboA.sha256);
if(slotSufamiTurboB.document) manifest.append("\n", BML::serialize(slotSufamiTurboB.document)); if(slotSufamiTurboB.sha256) hashes.append(slotSufamiTurboB.sha256);
return manifest; return hashes;
} }
auto Cartridge::title() const -> string { auto Cartridge::manifests() const -> vector<string> {
auto label = game.label; vector<string> manifests;
if(slotGameBoy.label) label.append(" + ", slotGameBoy.label); manifests.append(string{BML::serialize(game.document), "\n", BML::serialize(board)});
if(slotBSMemory.label) label.append(" + ", slotBSMemory.label); if(slotGameBoy.document) manifests.append(BML::serialize(slotGameBoy.document));
if(slotSufamiTurboA.label) label.append(" + ", slotSufamiTurboA.label); if(slotBSMemory.document) manifests.append(BML::serialize(slotBSMemory.document));
if(slotSufamiTurboB.label) label.append(" + ", slotSufamiTurboB.label); if(slotSufamiTurboA.document) manifests.append(BML::serialize(slotSufamiTurboA.document));
return label; if(slotSufamiTurboB.document) manifests.append(BML::serialize(slotSufamiTurboB.document));
return manifests;
}
auto Cartridge::titles() const -> vector<string> {
vector<string> titles;
titles.append(game.label);
if(slotGameBoy.label) titles.append(slotGameBoy.label);
if(slotBSMemory.label) titles.append(slotBSMemory.label);
if(slotSufamiTurboA.label) titles.append(slotSufamiTurboA.label);
if(slotSufamiTurboB.label) titles.append(slotSufamiTurboB.label);
return titles;
} }
auto Cartridge::load() -> bool { auto Cartridge::load() -> bool {
@ -36,8 +47,8 @@ auto Cartridge::load() -> bool {
slotSufamiTurboB = {}; slotSufamiTurboB = {};
if(auto loaded = platform->load(ID::SuperFamicom, "Super Famicom", "sfc", {"Auto", "NTSC", "PAL"})) { if(auto loaded = platform->load(ID::SuperFamicom, "Super Famicom", "sfc", {"Auto", "NTSC", "PAL"})) {
information.pathID = loaded.pathID(); information.pathID = loaded.pathID;
information.region = loaded.option(); information.region = loaded.option;
} else return false; } else return false;
if(auto fp = platform->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) { if(auto fp = platform->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) {
@ -93,9 +104,9 @@ auto Cartridge::load() -> bool {
} }
auto Cartridge::loadGameBoy() -> bool { auto Cartridge::loadGameBoy() -> bool {
#if defined(SFC_SUPERGAMEBOY) #if defined(CORE_GB)
//invoked from ICD::load() //invoked from ICD::load()
information.sha256 = GameBoy::cartridge.sha256(); information.sha256 = GameBoy::cartridge.hash();
slotGameBoy.load(GameBoy::cartridge.manifest()); slotGameBoy.load(GameBoy::cartridge.manifest());
loadCartridgeGameBoy(slotGameBoy.document); loadCartridgeGameBoy(slotGameBoy.document);
return true; return true;

View File

@ -1,9 +1,10 @@
struct Cartridge { struct Cartridge {
auto pathID() const -> uint { return information.pathID; } auto pathID() const -> uint { return information.pathID; }
auto region() const -> string { return information.region; } auto region() const -> string { return information.region; }
auto sha256() const -> string { return information.sha256; }
auto manifest() const -> string; auto hashes() const -> vector<string>;
auto title() const -> string; auto manifests() const -> vector<string>;
auto titles() const -> vector<string>;
auto load() -> bool; auto load() -> bool;
auto save() -> void; auto save() -> void;

View File

@ -211,7 +211,7 @@ auto Cartridge::loadBSMemory(Markup::Node node) -> void {
has.BSMemorySlot = true; has.BSMemorySlot = true;
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) { if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
bsmemory.pathID = loaded.pathID(); bsmemory.pathID = loaded.pathID;
loadBSMemory(); loadBSMemory();
for(auto map : node.find("map")) { for(auto map : node.find("map")) {
@ -225,7 +225,7 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
has.SufamiTurboSlotA = true; has.SufamiTurboSlotA = true;
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
sufamiturboA.pathID = loaded.pathID(); sufamiturboA.pathID = loaded.pathID;
loadSufamiTurboA(); loadSufamiTurboA();
for(auto map : node.find("rom/map")) { for(auto map : node.find("rom/map")) {
@ -243,7 +243,7 @@ auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
has.SufamiTurboSlotB = true; has.SufamiTurboSlotB = true;
if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) { if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
sufamiturboB.pathID = loaded.pathID(); sufamiturboB.pathID = loaded.pathID;
loadSufamiTurboB(); loadSufamiTurboB();
for(auto map : node.find("rom/map")) { for(auto map : node.find("rom/map")) {

View File

@ -130,6 +130,8 @@ auto Justifier::data() -> uint2 {
case 30: return 0; case 30: return 0;
case 31: return 0; case 31: return 0;
} }
unreachable;
} }
auto Justifier::latch(bool data) -> void { auto Justifier::latch(bool data) -> void {

View File

@ -118,6 +118,8 @@ auto SuperScope::data() -> uint2 {
case 6: return offscreen; case 6: return offscreen;
case 7: return 0; //noise (1 = yes) case 7: return 0; //noise (1 = yes)
} }
unreachable;
} }
auto SuperScope::latch(bool data) -> void { auto SuperScope::latch(bool data) -> void {

View File

@ -85,8 +85,8 @@ auto EpsonRTC::power() -> void {
holdtick = 0; holdtick = 0;
} }
auto EpsonRTC::sync() -> void { auto EpsonRTC::synchronize(uint64 timestamp) -> void {
time_t systime = time(0); time_t systime = timestamp;
tm* timeinfo = localtime(&systime); tm* timeinfo = localtime(&systime);
uint second = min(59, timeinfo->tm_sec); uint second = min(59, timeinfo->tm_sec);

View File

@ -1,12 +1,14 @@
//Epson RTC-4513 Real-Time Clock //Epson RTC-4513 Real-Time Clock
struct EpsonRTC : Thread { struct EpsonRTC : Thread {
using Thread::synchronize;
static auto Enter() -> void; static auto Enter() -> void;
auto main() -> void; auto main() -> void;
auto initialize() -> void; auto initialize() -> void;
auto power() -> void; auto power() -> void;
auto sync() -> void; auto synchronize(uint64 timestamp) -> void;
auto read(uint24 addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;

View File

@ -4,7 +4,7 @@ namespace SuperFamicom {
ICD icd; ICD icd;
#if defined(SFC_SUPERGAMEBOY) #if defined(CORE_GB)
#include "platform.cpp" #include "platform.cpp"
#include "interface.cpp" #include "interface.cpp"

View File

@ -1,4 +1,4 @@
#if defined(SFC_SUPERGAMEBOY) #if defined(CORE_GB)
struct ICD : Emulator::Platform, GameBoy::SuperGameBoyInterface, Thread { struct ICD : Emulator::Platform, GameBoy::SuperGameBoyInterface, Thread {
shared_pointer<Emulator::Stream> stream; shared_pointer<Emulator::Stream> stream;

View File

@ -123,6 +123,8 @@ auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
case 0x2006: return 'U'; case 0x2006: return 'U';
case 0x2007: return '1'; case 0x2007: return '1';
} }
unreachable;
} }
auto MSU1::writeIO(uint24 addr, uint8 data) -> void { auto MSU1::writeIO(uint24 addr, uint8 data) -> void {

View File

@ -242,6 +242,7 @@ auto SA1::bitmapRead(uint addr, uint8 data) -> uint8 {
case 3: return (bwram.read(addr) >> 6) & 3; case 3: return (bwram.read(addr) >> 6) & 3;
} }
} }
unreachable;
} }
auto SA1::bitmapWrite(uint addr, uint8 data) -> void { auto SA1::bitmapWrite(uint addr, uint8 data) -> void {

View File

@ -253,6 +253,8 @@ auto SDD1::Decompressor::OL::decompress() -> uint8 {
} }
return r1; return r1;
} }
return 0; //unreachable?
} }
//core //core

View File

@ -35,8 +35,8 @@ auto SharpRTC::power() -> void {
index = -1; index = -1;
} }
auto SharpRTC::sync() -> void { auto SharpRTC::synchronize(uint64 timestamp) -> void {
time_t systime = time(0); time_t systime = timestamp;
tm* timeinfo = localtime(&systime); tm* timeinfo = localtime(&systime);
second = min(59, timeinfo->tm_sec); second = min(59, timeinfo->tm_sec);

View File

@ -1,10 +1,12 @@
struct SharpRTC : Thread { struct SharpRTC : Thread {
using Thread::synchronize;
static auto Enter() -> void; static auto Enter() -> void;
auto main() -> void; auto main() -> void;
auto initialize() -> void; auto initialize() -> void;
auto power() -> void; auto power() -> void;
auto sync() -> void; auto synchronize(uint64 timestamp) -> void;
auto read(uint24 addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;

View File

@ -30,7 +30,7 @@ private:
function<uint8 ()>, //read function<uint8 ()>, //read
function<void (uint8)> //write function<void (uint8)> //write
)> linkInit; )> linkInit;
function<void (string_vector)> linkMain; function<void (vector<string>)> linkMain;
vector<uint8> snesBuffer; //SNES -> Link vector<uint8> snesBuffer; //SNES -> Link
vector<uint8> linkBuffer; //Link -> SNES vector<uint8> linkBuffer; //Link -> SNES

View File

@ -2,38 +2,31 @@
namespace SuperFamicom { namespace SuperFamicom {
#define returns(T) T { return ([&] { struct With : T { With() {
#define $ }}; return With(); })(); }
Settings settings; Settings settings;
auto Interface::information() -> returns(Information) { auto Interface::information() -> Information {
manufacturer = "Nintendo"; Information information;
name = "Super Famicom"; information.manufacturer = "Nintendo";
extension = "sfc"; information.name = "Super Famicom";
resettable = true; information.extension = "sfc";
}$ information.resettable = true;
return information;
auto Interface::manifest() -> string {
return cartridge.manifest();
} }
auto Interface::title() -> string { auto Interface::displays() -> vector<Display> {
return cartridge.title(); Display display;
display.type = Display::Type::CRT;
display.colors = 1 << 19;
display.width = 256;
display.height = 240;
display.internalWidth = 512;
display.internalHeight = 480;
display.aspectCorrection = 8.0 / 7.0;
if(Region::NTSC()) display.refreshRate = system.cpuFrequency() / (262.0 * 1364.0);
if(Region::PAL()) display.refreshRate = system.cpuFrequency() / (312.0 * 1364.0);
return {display};
} }
auto Interface::display() -> returns(Display) {
type = Display::Type::CRT;
colors = 1 << 19;
width = 256;
height = 240;
internalWidth = 512;
internalHeight = 480;
aspectCorrection = 8.0 / 7.0;
if(Region::NTSC()) refreshRate = system.cpuFrequency() / (262.0 * 1364.0);
if(Region::PAL()) refreshRate = system.cpuFrequency() / (312.0 * 1364.0);
}$
auto Interface::color(uint32 color) -> uint64 { auto Interface::color(uint32 color) -> uint64 {
uint r = color.bits( 0, 4); uint r = color.bits( 0, 4);
uint g = color.bits( 5, 9); uint g = color.bits( 5, 9);
@ -66,8 +59,16 @@ auto Interface::loaded() -> bool {
return system.loaded(); return system.loaded();
} }
auto Interface::sha256() -> string { auto Interface::hashes() -> vector<string> {
return cartridge.sha256(); return cartridge.hashes();
}
auto Interface::manifests() -> vector<string> {
return cartridge.manifests();
}
auto Interface::titles() -> vector<string> {
return cartridge.titles();
} }
auto Interface::load() -> bool { auto Interface::load() -> bool {
@ -229,9 +230,10 @@ auto Interface::rtc() -> bool {
return false; return false;
} }
auto Interface::rtcSynchronize() -> void { auto Interface::synchronize(uint64 timestamp) -> void {
if(cartridge.has.EpsonRTC) epsonrtc.sync(); if(!timestamp) timestamp = chrono::timestamp();
if(cartridge.has.SharpRTC) sharprtc.sync(); if(cartridge.has.EpsonRTC) epsonrtc.synchronize(timestamp);
if(cartridge.has.SharpRTC) sharprtc.synchronize(timestamp);
} }
auto Interface::serialize() -> serializer { auto Interface::serialize() -> serializer {
@ -243,9 +245,9 @@ auto Interface::unserialize(serializer& s) -> bool {
return system.unserialize(s); return system.unserialize(s);
} }
auto Interface::cheatSet(const string_vector& list) -> void { auto Interface::cheats(const vector<string>& list) -> void {
cheat.reset(); cheat.reset();
#if defined(SFC_SUPERGAMEBOY) #if defined(CORE_GB)
if(cartridge.has.ICD) return GameBoy::cheat.assign(list); if(cartridge.has.ICD) return GameBoy::cheat.assign(list);
#endif #endif
cheat.assign(list); cheat.assign(list);
@ -307,7 +309,4 @@ auto Interface::set(const string& name, const any& value) -> bool {
return false; return false;
} }
#undef returns
#undef $
} }

View File

@ -1,3 +1,5 @@
#if defined(CORE_SFC)
namespace SuperFamicom { namespace SuperFamicom {
struct ID { struct ID {
@ -31,17 +33,15 @@ struct ID {
}; };
struct Interface : Emulator::Interface { struct Interface : Emulator::Interface {
using Emulator::Interface::load;
auto information() -> Information; auto information() -> Information;
auto manifest() -> string override;
auto title() -> string override;
auto display() -> Display override; auto displays() -> vector<Display> override;
auto color(uint32 color) -> uint64 override; auto color(uint32 color) -> uint64 override;
auto loaded() -> bool override; auto loaded() -> bool override;
auto sha256() -> string override; auto hashes() -> vector<string> override;
auto manifests() -> vector<string> override;
auto titles() -> vector<string> override;
auto load() -> bool override; auto load() -> bool override;
auto save() -> void override; auto save() -> void override;
auto unload() -> void override; auto unload() -> void override;
@ -57,12 +57,12 @@ struct Interface : Emulator::Interface {
auto run() -> void override; auto run() -> void override;
auto rtc() -> bool override; auto rtc() -> bool override;
auto rtcSynchronize() -> void override; auto synchronize(uint64 timestamp) -> void override;
auto serialize() -> serializer override; auto serialize() -> serializer override;
auto unserialize(serializer&) -> bool override; auto unserialize(serializer&) -> bool override;
auto cheatSet(const string_vector&) -> void override; auto cheats(const vector<string>&) -> void override;
auto cap(const string& name) -> bool override; auto cap(const string& name) -> bool override;
auto get(const string& name) -> any override; auto get(const string& name) -> any override;
@ -88,3 +88,5 @@ struct Settings {
extern Settings settings; extern Settings settings;
} }
#endif

View File

@ -16,7 +16,7 @@
#include <processor/upd96050/upd96050.hpp> #include <processor/upd96050/upd96050.hpp>
#include <processor/wdc65816/wdc65816.hpp> #include <processor/wdc65816/wdc65816.hpp>
#if defined(SFC_SUPERGAMEBOY) #if defined(CORE_GB)
#include <gb/gb.hpp> #include <gb/gb.hpp>
#endif #endif

View File

@ -3,14 +3,11 @@ auto System::serialize() -> serializer {
uint signature = 0x31545342; uint signature = 0x31545342;
char version[16] = {}; char version[16] = {};
char hash[64] = {};
char description[512] = {}; char description[512] = {};
memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size()); memory::copy(&version, (const char*)Emulator::SerializerVersion, Emulator::SerializerVersion.size());
memory::copy(&hash, (const char*)cartridge.sha256(), 64);
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
s.boolean(hacks.fastPPU); s.boolean(hacks.fastPPU);
@ -23,12 +20,10 @@ auto System::serialize() -> serializer {
auto System::unserialize(serializer& s) -> bool { auto System::unserialize(serializer& s) -> bool {
uint signature = 0; uint signature = 0;
char version[16] = {}; char version[16] = {};
char hash[64] = {};
char description[512] = {}; char description[512] = {};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
if(signature != 0x31545342) return false; if(signature != 0x31545342) return false;
@ -92,12 +87,10 @@ auto System::serializeInit() -> void {
uint signature = 0; uint signature = 0;
char version[16] = {}; char version[16] = {};
char hash[64] = {};
char description[512] = {}; char description[512] = {};
s.integer(signature); s.integer(signature);
s.array(version); s.array(version);
s.array(hash);
s.array(description); s.array(description);
s.boolean(hacks.fastPPU); s.boolean(hacks.fastPPU);

View File

@ -1,5 +1,5 @@
database database
revision: 2018-06-25 revision: 2018-07-25
//Boards (Production) //Boards (Production)
@ -565,7 +565,7 @@ board: SHVC-YJ0N-01
//Boards (Generic) //Boards (Generic)
database database
revision: 2018-06-25 revision: 2018-07-25
board: ARM-LOROM-RAM board: ARM-LOROM-RAM
memory type=ROM content=Program memory type=ROM content=Program
@ -768,18 +768,18 @@ board: LOROM
memory type=ROM content=Program memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
board: LOROM-RAM
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: LOROM-RAM#A board: LOROM-RAM#A
memory type=ROM content=Program memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
memory type=RAM content=Save memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff mask=0x8000 map address=70-7d,f0-ff:0000-ffff mask=0x8000
board: LOROM-RAM#B
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: NEC-HIROM board: NEC-HIROM
memory type=ROM content=Program memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
@ -814,6 +814,18 @@ board: NEC-LOROM
memory type=RAM content=Data architecture=uPD7725 memory type=RAM content=Data architecture=uPD7725
oscillator oscillator
board: NEC-LOROM-RAM
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000
processor architecture=uPD7725
map address=60-6f,e0-ef:0000-7fff mask=0x3fff
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: NEC-LOROM-RAM#A board: NEC-LOROM-RAM#A
memory type=ROM content=Program memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
@ -826,18 +838,6 @@ board: NEC-LOROM-RAM#A
memory type=RAM content=Data architecture=uPD7725 memory type=RAM content=Data architecture=uPD7725
oscillator oscillator
board: NEC-LOROM-RAM#B
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000
processor architecture=uPD7725
map address=60-6f,e0-ef:0000-7fff mask=0x3fff
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: OBC1-LOROM-RAM board: OBC1-LOROM-RAM
memory type=ROM content=Program memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000

View File

@ -1,9 +1,4 @@
name := bsnes name := bsnes
flags += -DSFC_SUPERGAMEBOY
include sfc/GNUmakefile
include gb/GNUmakefile
include processor/GNUmakefile
hiro.path := ../hiro hiro.path := ../hiro
hiro.resource := $(ui)/resource/bsnes.rc hiro.resource := $(ui)/resource/bsnes.rc

View File

@ -19,7 +19,7 @@ auto locate(string name) -> string {
} }
#include <nall/main.hpp> #include <nall/main.hpp>
auto nall::main(string_vector arguments) -> void { auto nall::main(vector<string> arguments) -> void {
string locale; // = "日本語"; string locale; // = "日本語";
for(auto argument : arguments) { for(auto argument : arguments) {
if(argument.beginsWith("--locale=")) { if(argument.beginsWith("--locale=")) {

View File

@ -132,7 +132,7 @@ Presentation::Presentation() {
aboutWindow->setCentered(*this).setVisible().setFocused(); aboutWindow->setCentered(*this).setVisible().setFocused();
}); });
viewport.setDroppable().onDrop([&](string_vector locations) { viewport.setDroppable().onDrop([&](vector<string> locations) {
program->gameQueue = locations; program->gameQueue = locations;
program->load(); program->load();
setFocused(); setFocused();

View File

@ -6,15 +6,18 @@ auto Program::load() -> void {
screenshot = {}; screenshot = {};
frameAdvance = false; frameAdvance = false;
if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) { if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) {
//todo: MessageDialog crashes with GTK+; unsure the reason why this happens auto response = MessageDialog(
//once MessageDialog functions, add an "Always" option "Warning: this game image is unverified.\n"
if(MessageWindow( "Running it *may* be a security risk.\n\n"
"Warning: this game image is unverified. Running it *may* be a security risk.\n\n"
"Do you wish to run the game anyway?" "Do you wish to run the game anyway?"
).setParent(*presentation).question() == MessageWindow::Response::No) { ).setParent(*presentation).question({"Always", "Yes", "No"});
if(response == "No") {
emulator->unload(); emulator->unload();
return showMessage("Game loading cancelled"); return showMessage("Game loading cancelled");
} }
if(response == "Always") {
settingsWindow->advanced.warnOnUnverifiedGames.setChecked(false).doToggle();
}
} }
hackCompatibility(); hackCompatibility();
emulator->power(); emulator->power();
@ -25,7 +28,7 @@ auto Program::load() -> void {
verified() ? "Verified game loaded" : "Game loaded", verified() ? "Verified game loaded" : "Game loaded",
appliedPatch() ? " and patch applied" : "" appliedPatch() ? " and patch applied" : ""
}); });
presentation->setTitle(emulator->title()); presentation->setTitle(emulator->titles().merge(" + "));
presentation->resetSystem.setEnabled(true); presentation->resetSystem.setEnabled(true);
presentation->unloadGame.setEnabled(true); presentation->unloadGame.setEnabled(true);
presentation->toolsMenu.setVisible(true); presentation->toolsMenu.setVisible(true);
@ -38,10 +41,10 @@ auto Program::load() -> void {
toolsWindow->manifestViewer.loadManifest(); toolsWindow->manifestViewer.loadManifest();
string locations = superFamicom.location; string locations = superFamicom.location;
if(auto location = gameBoy.location) locations.append("|", location); if(auto& location = gameBoy.location) locations.append("|", location);
if(auto location = bsMemory.location) locations.append("|", location); if(auto& location = bsMemory.location) locations.append("|", location);
if(auto location = sufamiTurboA.location) locations.append("|", location); if(auto& location = sufamiTurboA.location) locations.append("|", location);
if(auto location = sufamiTurboB.location) locations.append("|", location); if(auto& location = sufamiTurboB.location) locations.append("|", location);
presentation->addRecentGame(locations); presentation->addRecentGame(locations);
updateVideoPalette(); updateVideoPalette();
@ -75,9 +78,9 @@ auto Program::loadSuperFamicom(string location) -> bool {
rom.append(file::read({location, "program.rom"})); rom.append(file::read({location, "program.rom"}));
rom.append(file::read({location, "data.rom"})); rom.append(file::read({location, "data.rom"}));
rom.append(file::read({location, "expansion.rom"})); rom.append(file::read({location, "expansion.rom"}));
for(auto filename : directory::files(location, "*.boot.rom" )) rom.append(file::read({location, filename})); for(auto& filename : directory::files(location, "*.boot.rom" )) rom.append(file::read({location, filename}));
for(auto filename : directory::files(location, "*.program.rom")) rom.append(file::read({location, filename})); for(auto& filename : directory::files(location, "*.program.rom")) rom.append(file::read({location, filename}));
for(auto filename : directory::files(location, "*.data.rom" )) rom.append(file::read({location, filename})); for(auto& filename : directory::files(location, "*.data.rom" )) rom.append(file::read({location, filename}));
} else { } else {
manifest = file::read({Location::notsuffix(location), ".bml"}); manifest = file::read({Location::notsuffix(location), ".bml"});
rom = loadFile(location); rom = loadFile(location);

View File

@ -103,7 +103,7 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
return result; return result;
} }
auto Program::load(uint id, string name, string type, string_vector options) -> Emulator::Platform::Load { auto Program::load(uint id, string name, string type, vector<string> options) -> Emulator::Platform::Load {
BrowserDialog dialog; BrowserDialog dialog;
dialog.setParent(*presentation); dialog.setParent(*presentation);
dialog.setOptions(options); dialog.setOptions(options);
@ -196,7 +196,7 @@ auto Program::load(uint id, string name, string type, string_vector options) ->
return {}; return {};
} }
auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { auto Program::videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void {
uint32_t* output; uint32_t* output;
uint length; uint length;

View File

@ -13,7 +13,7 @@
#include "hacks.cpp" #include "hacks.cpp"
unique_pointer<Program> program; unique_pointer<Program> program;
Program::Program(string_vector arguments) { Program::Program(vector<string> arguments) {
program = this; program = this;
Emulator::platform = this; Emulator::platform = this;
@ -89,5 +89,5 @@ auto Program::quit() -> void {
video.reset(); video.reset();
audio.reset(); audio.reset();
input.reset(); input.reset();
Application::quit(); Application::kill();
} }

View File

@ -2,14 +2,14 @@ struct Program : Emulator::Platform {
Application::Namespace tr{"Program"}; Application::Namespace tr{"Program"};
//program.cpp //program.cpp
Program(string_vector arguments); Program(vector<string> arguments);
auto main() -> void; auto main() -> void;
auto quit() -> void; auto quit() -> void;
//platform.cpp //platform.cpp
auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override;
auto load(uint id, string name, string type, string_vector options = {}) -> Emulator::Platform::Load override; auto load(uint id, string name, string type, vector<string> options = {}) -> Emulator::Platform::Load override;
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void override;
auto audioSample(const double* samples, uint channels) -> void override; auto audioSample(const double* samples, uint channels) -> void override;
auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputPoll(uint port, uint device, uint input) -> int16 override;
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override;
@ -49,7 +49,7 @@ struct Program : Emulator::Platform {
auto screenshotPath() -> string; auto screenshotPath() -> string;
//states.cpp //states.cpp
auto managedStates() -> string_vector; auto managedStates() -> vector<string>;
auto loadState(string filename) -> bool; auto loadState(string filename) -> bool;
auto saveState(string filename) -> bool; auto saveState(string filename) -> bool;
auto saveUndoState() -> bool; auto saveUndoState() -> bool;
@ -124,7 +124,7 @@ public:
vector<uint8_t> program; vector<uint8_t> program;
} sufamiTurboA, sufamiTurboB; } sufamiTurboA, sufamiTurboB;
string_vector gameQueue; vector<string> gameQueue;
struct Screenshot { struct Screenshot {
const uint32* data = nullptr; const uint32* data = nullptr;

View File

@ -1,4 +1,4 @@
auto Program::managedStates() -> string_vector { auto Program::managedStates() -> vector<string> {
if(!emulator->loaded()) return {}; if(!emulator->loaded()) return {};
if(gamePath().endsWith("/")) { if(gamePath().endsWith("/")) {
@ -6,7 +6,7 @@ auto Program::managedStates() -> string_vector {
} else { } else {
Decode::ZIP input; Decode::ZIP input;
if(input.open(statePath())) { if(input.open(statePath())) {
string_vector filenames; vector<string> filenames;
for(auto& file : input.file) { for(auto& file : input.file) {
if(file.name.match("managed/*.bst")) filenames.append(file.name.trimLeft("managed/", 1L)); if(file.name.match("managed/*.bst")) filenames.append(file.name.trimLeft("managed/", 1L));
} }

View File

@ -863,8 +863,8 @@ const nall::vector<uint8_t> Manifest = { //size: 334
115,112,10,32,32,32,32,114,97,109,32,110,97,109,101,61,97,112,117,46,114,97,109,32,115,105,122,101,61,48,120,49, 115,112,10,32,32,32,32,114,97,109,32,110,97,109,101,61,97,112,117,46,114,97,109,32,115,105,122,101,61,48,120,49,
48,48,48,48,32,118,111,108,97,116,105,108,101,10, 48,48,48,48,32,118,111,108,97,116,105,108,101,10,
}; };
const nall::vector<uint8_t> Boards = { //size: 30186 const nall::vector<uint8_t> Boards = { //size: 30182
100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10, 100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,55,45,50,53,10,
10,47,47,66,111,97,114,100,115,32,40,80,114,111,100,117,99,116,105,111,110,41,10,10,100,97,116,97,98,97,115,101, 10,47,47,66,111,97,114,100,115,32,40,80,114,111,100,117,99,116,105,111,110,41,10,10,100,97,116,97,98,97,115,101,
10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,53,45,49,54,10,10,98,111,97,114,100,58,32, 10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,53,45,49,54,10,10,98,111,97,114,100,58,32,
66,65,78,68,65,73,45,80,84,45,57,50,51,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32, 66,65,78,68,65,73,45,80,84,45,57,50,51,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
@ -1437,7 +1437,7 @@ const nall::vector<uint8_t> Boards = { //size: 30186
32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32, 32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,
32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45, 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,
102,102,102,102,10,10,47,47,66,111,97,114,100,115,32,40,71,101,110,101,114,105,99,41,10,10,100,97,116,97,98,97, 102,102,102,102,10,10,47,47,66,111,97,114,100,115,32,40,71,101,110,101,114,105,99,41,10,10,100,97,116,97,98,97,
115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10,10,98,111,97,114,100, 115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,55,45,50,53,10,10,98,111,97,114,100,
58,32,65,82,77,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79, 58,32,65,82,77,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,
77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115, 77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56, 115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,
@ -1651,51 +1651,65 @@ const nall::vector<uint8_t> Boards = { //size: 30186
108,97,116,111,114,10,10,98,111,97,114,100,58,32,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112, 108,97,116,111,114,10,10,98,111,97,114,100,58,32,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100, 101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107, 100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,
61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101, 61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,
102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,
99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,
55,100,44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,
98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101,109,111,114,121,32,116,121,112,101,
61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,
114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,
48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,
61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,
102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,
78,69,67,45,72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,
101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,
102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,101,115,
115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,
97,115,107,61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,
110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,
50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,
97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,
101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,
111,97,114,100,58,32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,
102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,
10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,48,48,
48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,97,
114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,
120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,
32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,
114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,
101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,
32,78,69,67,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,
49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,
32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,
32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48,48,48,
45,102,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,
114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,
10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,
97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,
108,97,116,111,114,10,10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,
109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32, 109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102, 32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,
102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65, 102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,
77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55, 77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,
48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, 48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,32,116,121,
112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,
107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,
110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,
45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,
58,32,78,69,67,45,72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,
110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,
45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,
101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,
32,109,97,115,107,61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,
55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,
105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,
10,98,111,97,114,100,58,32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,
102,102,102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,
118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,
48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,
32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,
61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,
110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,
32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,
32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,
32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,
117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,
100,58,32,78,69,67,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50, 10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,
53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48, 53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,
48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116, 48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99, 121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,
116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77, 116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55, 32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,
@ -1715,99 +1729,85 @@ const nall::vector<uint8_t> Boards = { //size: 30186
61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109, 61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104, 101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,
105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10, 105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,
10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121, 10,98,111,97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,
32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97, 116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,
112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,
109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,
110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,
44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,
114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,55,
102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,
82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,
61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,
97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,
116,111,114,10,10,98,111,97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,
102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,
105,102,105,101,114,61,79,66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,
44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102,
102,102,44,101,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100,
58,32,83,65,49,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,
114,101,61,87,54,53,67,56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,
102,44,56,48,45,98,102,58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,
102,32,109,97,115,107,61,48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,
32,115,105,122,101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,
48,45,52,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
65,77,32,99,111,110,116,101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101,
61,48,120,56,48,48,10,10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32,
105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32,
32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,
45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,
48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,
110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32,
32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,
102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
55,48,45,55,51,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,
111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,
32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,
45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80,
67,55,49,49,48,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,
61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,
48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,
48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109, 32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,
97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99, 97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,
48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32, 114,61,79,66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114, 98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,
97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116, 32,97,100,100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102,102,102,44,101,
61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110, 48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109,111,114,121,32,
116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56, 116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100,58,32,83,65,
48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114, 49,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,87,
100,58,32,83,80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115, 54,53,67,56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,
115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97, 45,98,102,58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32, 97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,
32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32, 115,107,61,48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,
32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45, 45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,
98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32, 82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111,114,121,32,116,
32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,
107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,
112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97, 121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115, 100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,115,105,122,
107,61,48,120,101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111, 101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,52,102,
110,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56, 58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,
52,48,45,52,56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116, 111,110,116,101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
101,110,116,61,84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97, 115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101,61,48,120,56,
114,100,58,32,83,84,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99, 48,48,10,10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48, 116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,
48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48, 102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,
102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,
102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,
116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,
112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,
109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,
51,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,
115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,
117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,
56,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,
102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,
77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80,67,55,49,49,
48,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,
55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,
58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,
58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,
114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,
48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,
58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,
32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,
97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,
118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,
58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114,100,58,32,83,
80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115,115,111,114,32,
105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,
10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,
48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,
99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,
82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,
101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,52,48,45,52,
56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116,101,110,116,61,
84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97,114,100,58,32,
83,84,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,
110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,
44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,115,
108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,10,32,32,32,
32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,48,48,48,45,
102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,102,102,102,102,
10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109, 10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,
10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56, 10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45,100,102,58,48,
48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32, 48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,
32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45, 32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,
102,102,102,102,10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32, 102,102,102,102,10,10,
32,114,111,109,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45,
100,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,
10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,
48,48,48,45,102,102,102,102,10,10,
}; };
const nall::vector<uint8_t> IPLROM = { //size: 64 const nall::vector<uint8_t> IPLROM = { //size: 64
205,239,189,232,0,198,29,208,252,143,170,244,143,187,245,120,204,244,208,251,47,25,235,244,208,252,126,244,208,11,228,245, 205,239,189,232,0,198,29,208,252,143,170,244,143,187,245,120,204,244,208,251,47,25,235,244,208,252,126,244,208,11,228,245,

View File

@ -18,7 +18,7 @@ CheatDatabase::CheatDatabase() {
} }
auto CheatDatabase::findCheats() -> void { auto CheatDatabase::findCheats() -> void {
auto sha256 = emulator->sha256(); auto sha256 = emulator->hashes()[0];
auto document = BML::unserialize(string::read(locate("cheats.bml"))); auto document = BML::unserialize(string::read(locate("cheats.bml")));
for(auto game : document.find("cartridge")) { for(auto game : document.find("cartridge")) {
@ -232,11 +232,11 @@ auto CheatEditor::saveCheats() -> void {
} }
auto CheatEditor::synchronizeCodes() -> void { auto CheatEditor::synchronizeCodes() -> void {
string_vector codes; vector<string> codes;
if(enableCheats.checked()) { if(enableCheats.checked()) {
for(auto& cheat : cheats) { for(auto& cheat : cheats) {
if(cheat.enable) codes.append(cheat.code); if(cheat.enable) codes.append(cheat.code);
} }
} }
emulator->cheatSet(codes); emulator->cheats(codes);
} }

View File

@ -14,7 +14,7 @@ auto ManifestViewer::loadManifest() -> void {
return; return;
} }
manifestView.setText(emulator->manifest()); manifestView.setText(emulator->manifests().merge("\n"));
verifiedIcon.setIcon(program->verified() ? Icon::Emblem::Program : Icon::Emblem::Binary); verifiedIcon.setIcon(program->verified() ? Icon::Emblem::Program : Icon::Emblem::Binary);
verifiedLabel.setText(program->verified() ? "Verified" : "Unverified"); verifiedLabel.setText(program->verified() ? "Verified" : "Unverified");
} }

View File

@ -1,15 +1,4 @@
name := higan name := higan
flags += -DSFC_SUPERGAMEBOY
include fc/GNUmakefile
include sfc/GNUmakefile
#include ms/GNUmakefile
include md/GNUmakefile
#include pce/GNUmakefile
include gb/GNUmakefile
include gba/GNUmakefile
#include ws/GNUmakefile
include processor/GNUmakefile
hiro.path := ../hiro hiro.path := ../hiro
hiro.resource := $(ui)/resource/higan.rc hiro.resource := $(ui)/resource/higan.rc

View File

@ -13,9 +13,9 @@ auto locate(string name) -> string {
} }
#include <nall/main.hpp> #include <nall/main.hpp>
auto nall::main(string_vector args) -> void { auto nall::main(vector<string> arguments) -> void {
Application::setName("higan"); Application::setName("higan");
Application::setScreenSaver(false); Application::setScreenSaver(false);
new Program(args); new Program(arguments);
Application::run(); Application::run();
} }

View File

@ -286,7 +286,7 @@ auto Presentation::resizeViewport(bool resizeWindow) -> void {
double emulatorHeight = 240; double emulatorHeight = 240;
double aspectCorrection = 1.0; double aspectCorrection = 1.0;
if(emulator) { if(emulator) {
auto display = emulator->display(); auto display = emulator->displays()[0];
emulatorWidth = display.width; emulatorWidth = display.width;
emulatorHeight = display.height; emulatorHeight = display.height;
aspectCorrection = display.aspectCorrection; aspectCorrection = display.aspectCorrection;

View File

@ -33,7 +33,7 @@ auto Program::load(Emulator::Interface& interface) -> void {
updateAudioEffects(); updateAudioEffects();
presentation->resizeViewport(); presentation->resizeViewport();
presentation->setTitle(emulator->title()); presentation->setTitle(emulator->titles().merge(" + "));
presentation->systemMenu.setText(information.name).setVisible(true); presentation->systemMenu.setText(information.name).setVisible(true);
presentation->toolsMenu.setVisible(true); presentation->toolsMenu.setVisible(true);
toolsManager->cheatEditor.loadCheats(); toolsManager->cheatEditor.loadCheats();

View File

@ -23,7 +23,7 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
return {}; return {};
} }
auto Program::load(uint id, string name, string type, string_vector options) -> Emulator::Platform::Load { auto Program::load(uint id, string name, string type, vector<string> options) -> Emulator::Platform::Load {
string location, option; string location, option;
if(gameQueue) { if(gameQueue) {
auto entry = gameQueue.takeLeft().split("|", 1L); auto entry = gameQueue.takeLeft().split("|", 1L);
@ -50,13 +50,13 @@ auto Program::load(uint id, string name, string type, string_vector options) ->
return {pathID, option}; return {pathID, option};
} }
auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void { auto Program::videoRefresh(uint displayID, const uint32* data, uint pitch, uint width, uint height) -> void {
uint32_t* output; uint32_t* output;
uint length; uint length;
pitch >>= 2; pitch >>= 2;
auto display = emulator->display(); auto display = emulator->displays()[displayID];
if(display.type == Emulator::Interface::Display::Type::CRT) { if(display.type == Emulator::Interface::Display::Type::CRT) {
uint overscanHorizontal = settings["Video/Overscan/Horizontal"].natural(); uint overscanHorizontal = settings["Video/Overscan/Horizontal"].natural();
uint overscanVertical = settings["Video/Overscan/Vertical"].natural(); uint overscanVertical = settings["Video/Overscan/Vertical"].natural();

View File

@ -1,35 +1,62 @@
#include "../higan.hpp" #include "../higan.hpp"
#include <fc/interface/interface.hpp> #include <fc/interface/interface.hpp>
#include <sfc/interface/interface.hpp> #include <sfc/interface/interface.hpp>
//#include <ms/interface/interface.hpp> #include <ms/interface/interface.hpp>
#include <md/interface/interface.hpp> #include <md/interface/interface.hpp>
//#include <pce/interface/interface.hpp> #include <pce/interface/interface.hpp>
#include <gb/interface/interface.hpp> #include <gb/interface/interface.hpp>
#include <gba/interface/interface.hpp> #include <gba/interface/interface.hpp>
//#include <ws/interface/interface.hpp> #include <ws/interface/interface.hpp>
#include "platform.cpp" #include "platform.cpp"
#include "game.cpp" #include "game.cpp"
#include "state.cpp" #include "state.cpp"
#include "utility.cpp" #include "utility.cpp"
unique_pointer<Program> program; unique_pointer<Program> program;
Program::Program(string_vector args) { Program::Program(vector<string> arguments) {
program = this; program = this;
Emulator::platform = this; Emulator::platform = this;
#ifdef CORE_FC
emulators.append(new Famicom::Interface); emulators.append(new Famicom::Interface);
#endif
#ifdef CORE_SFC
emulators.append(new SuperFamicom::Interface); emulators.append(new SuperFamicom::Interface);
// emulators.append(new MasterSystem::MasterSystemInterface); #endif
#ifdef CORE_MS
emulators.append(new MasterSystem::MasterSystemInterface);
#endif
#ifdef CORE_MD
emulators.append(new MegaDrive::Interface); emulators.append(new MegaDrive::Interface);
// emulators.append(new PCEngine::PCEngineInterface); #endif
// emulators.append(new PCEngine::SuperGrafxInterface); #ifdef CORE_PCE
emulators.append(new PCEngine::PCEngineInterface);
#endif
#ifdef CORE_PCE
emulators.append(new PCEngine::SuperGrafxInterface);
#endif
#ifdef CORE_GB
emulators.append(new GameBoy::GameBoyInterface); emulators.append(new GameBoy::GameBoyInterface);
#endif
#ifdef CORE_GB
emulators.append(new GameBoy::GameBoyColorInterface); emulators.append(new GameBoy::GameBoyColorInterface);
#endif
#ifdef CORE_GBA
emulators.append(new GameBoyAdvance::Interface); emulators.append(new GameBoyAdvance::Interface);
// emulators.append(new MasterSystem::GameGearInterface); #endif
// emulators.append(new WonderSwan::WonderSwanInterface); #ifdef CORE_MS
// emulators.append(new WonderSwan::WonderSwanColorInterface); emulators.append(new MasterSystem::GameGearInterface);
// emulators.append(new WonderSwan::PocketChallengeV2Interface); #endif
#ifdef CORE_WS
emulators.append(new WonderSwan::WonderSwanInterface);
#endif
#ifdef CORE_WS
emulators.append(new WonderSwan::WonderSwanColorInterface);
#endif
#ifdef CORE_WS
emulators.append(new WonderSwan::PocketChallengeV2Interface);
#endif
new Presentation; new Presentation;
presentation->setVisible(); presentation->setVisible();
@ -62,8 +89,8 @@ Program::Program(string_vector args) {
updateAudioDriver(); updateAudioDriver();
updateAudioEffects(); updateAudioEffects();
args.takeLeft(); //ignore program location in argument parsing arguments.takeLeft(); //ignore program location in argument parsing
for(auto& argument : args) { for(auto& argument : arguments) {
if(argument == "--fullscreen") { if(argument == "--fullscreen") {
presentation->toggleFullScreen(); presentation->toggleFullScreen();
} else if(directory::exists(argument.split("|", 1L).right())) { } else if(directory::exists(argument.split("|", 1L).right())) {
@ -113,5 +140,5 @@ auto Program::quit() -> void {
video.reset(); video.reset();
audio.reset(); audio.reset();
input.reset(); input.reset();
Application::quit(); Application::kill();
} }

View File

@ -1,14 +1,14 @@
struct Program : Emulator::Platform { struct Program : Emulator::Platform {
//program.cpp //program.cpp
Program(string_vector args); Program(vector<string> arguments);
auto main() -> void; auto main() -> void;
auto quit() -> void; auto quit() -> void;
//platform.cpp //platform.cpp
auto path(uint id) -> string override; auto path(uint id) -> string override;
auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override;
auto load(uint id, string name, string type, string_vector options = {}) -> Emulator::Platform::Load override; auto load(uint id, string name, string type, vector<string> options = {}) -> Emulator::Platform::Load override;
auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void override; auto videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void override;
auto audioSample(const double* samples, uint channels) -> void override; auto audioSample(const double* samples, uint channels) -> void override;
auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputPoll(uint port, uint device, uint input) -> int16 override;
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override;

View File

@ -17,7 +17,7 @@ CheatDatabase::CheatDatabase() {
auto CheatDatabase::findCodes() -> void { auto CheatDatabase::findCodes() -> void {
if(!emulator) return; if(!emulator) return;
auto sha256 = emulator->sha256(); auto sha256 = emulator->hashes().left();
auto contents = string::read(locate("cheats.bml")); auto contents = string::read(locate("cheats.bml"));
auto document = BML::unserialize(contents); auto document = BML::unserialize(contents);

View File

@ -100,13 +100,13 @@ auto CheatEditor::doErase() -> void {
auto CheatEditor::synchronizeCodes() -> void { auto CheatEditor::synchronizeCodes() -> void {
if(!emulator) return; if(!emulator) return;
string_vector codes; vector<string> codes;
for(auto& cheat : cheats) { for(auto& cheat : cheats) {
if(!cheat.enabled || !cheat.code) continue; if(!cheat.enabled || !cheat.code) continue;
codes.append(cheat.code); codes.append(cheat.code);
} }
emulator->cheatSet(codes); emulator->cheats(codes);
} }
//returns true if code was added //returns true if code was added
@ -136,7 +136,7 @@ auto CheatEditor::loadCheats() -> void {
auto CheatEditor::saveCheats() -> void { auto CheatEditor::saveCheats() -> void {
if(!emulator) return; if(!emulator) return;
string document = {"cartridge sha256:", emulator->sha256(), "\n"}; string document = {"cartridge sha256:", emulator->hashes().left(), "\n"};
uint count = 0; uint count = 0;
for(auto& cheat : cheats) { for(auto& cheat : cheats) {
if(!cheat.code && !cheat.description) continue; if(!cheat.code && !cheat.description) continue;

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