mirror of https://github.com/bsnes-emu/bsnes.git
Update to v102r06 release.
byuu says: Changelog: - added higan/emulator/platform.hpp (moved out Emulator::Platform from emulator/interface.hpp) - moved gmake build paramter to nall/GNUmakefile; both higan and icarus use it now - added build=profile mode - MD: added the region select I/O register - MD: started to add region selection support internally (still no external select or PAL support) - PCE: added cycle stealing when reading/writing to the VDC or VCE; and when using ST# instructions - PCE: cleaned up PSG to match the behavior of Mednafen (doesn't improve sound at all ;_;) - note: need to remove loadWaveSample, loadWavePeriod - HuC6280: ADC/SBC decimal mode consumes an extra cycle; does not set V flag - HuC6280: block transfer instructions were taking one cycle too many - icarus: added code to strip out PC Engine ROM headers - hiro: added options support to BrowserDialog The last one sure ended in failure. The plan was to put a region dropdown directly onto hiro::BrowserDialog, and I had all the code for it working. But I forgot one important detail: the system loads cartridges AFTER powering on, so even though I could technically change the system region post-boot, I'd rather not do so. So that means we have to know what region we want before we even select a game. Shit.
This commit is contained in:
parent
bf70044edc
commit
fa6cbac251
|
@ -1,24 +1,12 @@
|
||||||
|
build := release
|
||||||
include ../nall/GNUmakefile
|
include ../nall/GNUmakefile
|
||||||
|
|
||||||
target := tomoko
|
target := tomoko
|
||||||
objects := libco emulator audio video resource
|
objects := libco emulator audio video resource
|
||||||
build := release
|
|
||||||
# console := true
|
# console := true
|
||||||
|
|
||||||
flags += -I. -I..
|
flags += -I. -I..
|
||||||
|
|
||||||
ifeq ($(build),release)
|
|
||||||
flags += -O3
|
|
||||||
link += -s
|
|
||||||
else ifeq ($(build),debug)
|
|
||||||
flags += -g
|
|
||||||
else ifeq ($(build),instrument)
|
|
||||||
flags += -O3 -fprofile-generate
|
|
||||||
link += -lgcov
|
|
||||||
else ifeq ($(build),optimize)
|
|
||||||
flags += -O3 -fprofile-use
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
ifeq ($(console),true)
|
ifeq ($(console),true)
|
||||||
link += -mconsole
|
link += -mconsole
|
||||||
|
|
|
@ -12,7 +12,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "102.05";
|
static const string Version = "102.06";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
@ -26,6 +26,15 @@ namespace Emulator {
|
||||||
static constexpr double PAL = 283.75 * 15'625.0 + 25.0;
|
static constexpr double PAL = 283.75 * 15'625.0 + 25.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nall/vfs shorthand constants for open(), load()
|
||||||
|
namespace File {
|
||||||
|
static const auto Read = vfs::file::mode::read;
|
||||||
|
static const auto Write = vfs::file::mode::write;
|
||||||
|
static const auto Optional = false;
|
||||||
|
static const auto Required = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "platform.hpp"
|
||||||
#include "interface.hpp"
|
#include "interface.hpp"
|
||||||
|
|
|
@ -2,18 +2,6 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
|
|
||||||
struct Platform {
|
|
||||||
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 load(uint id, string name, string type) -> maybe<uint> { return nothing; }
|
|
||||||
virtual auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {}
|
|
||||||
virtual auto audioSample(const double* samples, uint channels) -> void {}
|
|
||||||
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 dipSettings(Markup::Node node) -> uint { return 0; }
|
|
||||||
virtual auto notify(string text) -> void { print(text, "\n"); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Interface {
|
struct Interface {
|
||||||
struct Information {
|
struct Information {
|
||||||
string manufacturer;
|
string manufacturer;
|
||||||
|
@ -25,6 +13,11 @@ struct Interface {
|
||||||
} capability;
|
} capability;
|
||||||
} information;
|
} information;
|
||||||
|
|
||||||
|
struct Region {
|
||||||
|
string name;
|
||||||
|
};
|
||||||
|
vector<Region> regions;
|
||||||
|
|
||||||
struct Medium {
|
struct Medium {
|
||||||
uint id;
|
uint id;
|
||||||
string name;
|
string name;
|
||||||
|
@ -96,14 +89,4 @@ struct Interface {
|
||||||
auto videoColor(uint16 r, uint16 g, uint16 b) -> uint32;
|
auto videoColor(uint16 r, uint16 g, uint16 b) -> uint32;
|
||||||
};
|
};
|
||||||
|
|
||||||
//nall/vfs shorthand constants for open(), load()
|
|
||||||
struct File {
|
|
||||||
static const auto Read = vfs::file::mode::read;
|
|
||||||
static const auto Write = vfs::file::mode::write;
|
|
||||||
static const auto Optional = false;
|
|
||||||
static const auto Required = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Platform* platform;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Emulator {
|
||||||
|
|
||||||
|
struct Platform {
|
||||||
|
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 load(uint id, string name, string type) -> maybe<uint> { return nothing; }
|
||||||
|
virtual auto videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {}
|
||||||
|
virtual auto audioSample(const double* samples, uint channels) -> void {}
|
||||||
|
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 dipSettings(Markup::Node node) -> uint { return 0; }
|
||||||
|
virtual auto notify(string text) -> void { print(text, "\n"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Platform* platform;
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace Famicom {
|
namespace Famicom {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
using Cheat = Emulator::Cheat;
|
using Cheat = Emulator::Cheat;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace GameBoy {
|
namespace GameBoy {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
using Cheat = Emulator::Cheat;
|
using Cheat = Emulator::Cheat;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace GameBoyAdvance {
|
namespace GameBoyAdvance {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,13 @@ auto BusCPU::writeWord(uint24 addr, uint16 data) -> void {
|
||||||
|
|
||||||
auto BusCPU::readIO(uint24 addr) -> uint16 {
|
auto BusCPU::readIO(uint24 addr) -> uint16 {
|
||||||
switch(addr & ~1) {
|
switch(addr & ~1) {
|
||||||
|
case 0xa10000: return (
|
||||||
|
!Region::NTSCJ() << 7 //0 = domestic (Japan); 1 = export
|
||||||
|
| Region::PAL() << 6 //0 = NTSC; 1 = PAL
|
||||||
|
| 1 << 5 //0 = Mega CD connected; 1 = no expansion connected
|
||||||
|
| 0 << 0 //0 = Model 1; 1 = Model 2+
|
||||||
|
);
|
||||||
|
|
||||||
case 0xa10002: return peripherals.controllerPort1->readData();
|
case 0xa10002: return peripherals.controllerPort1->readData();
|
||||||
case 0xa10004: return peripherals.controllerPort2->readData();
|
case 0xa10004: return peripherals.controllerPort2->readData();
|
||||||
case 0xa10006: return peripherals.extensionPort->readData();
|
case 0xa10006: return peripherals.extensionPort->readData();
|
||||||
|
|
|
@ -12,6 +12,11 @@ Interface::Interface() {
|
||||||
information.capability.states = false;
|
information.capability.states = false;
|
||||||
information.capability.cheats = false;
|
information.capability.cheats = false;
|
||||||
|
|
||||||
|
regions.append({"Autodetect"});
|
||||||
|
regions.append({"NTSC-J"});
|
||||||
|
regions.append({"NTSC-U"});
|
||||||
|
regions.append({"PAL"});
|
||||||
|
|
||||||
media.append({ID::MegaDrive, "Mega Drive", "md"});
|
media.append({ID::MegaDrive, "Mega Drive", "md"});
|
||||||
|
|
||||||
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};
|
Port controllerPort1{ID::Port::Controller1, "Controller Port 1"};
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace MegaDrive {
|
namespace MegaDrive {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
||||||
|
@ -36,6 +36,12 @@ namespace MegaDrive {
|
||||||
uint wait = 0;
|
uint wait = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Region {
|
||||||
|
inline static auto NTSCJ() -> bool;
|
||||||
|
inline static auto NTSCU() -> bool;
|
||||||
|
inline static auto PAL() -> bool;
|
||||||
|
};
|
||||||
|
|
||||||
#include <md/controller/controller.hpp>
|
#include <md/controller/controller.hpp>
|
||||||
|
|
||||||
#include <md/cpu/cpu.hpp>
|
#include <md/cpu/cpu.hpp>
|
||||||
|
|
|
@ -10,7 +10,7 @@ auto System::run() -> void {
|
||||||
if(scheduler.enter() == Scheduler::Event::Frame) vdp.refresh();
|
if(scheduler.enter() == Scheduler::Event::Frame) vdp.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::load(Emulator::Interface* interface) -> bool {
|
auto System::load(Emulator::Interface* interface, maybe<Region> region) -> bool {
|
||||||
information = {};
|
information = {};
|
||||||
|
|
||||||
if(auto fp = platform->open(ID::System, "manifest.bml", File::Read, File::Required)) {
|
if(auto fp = platform->open(ID::System, "manifest.bml", File::Read, File::Required)) {
|
||||||
|
@ -20,6 +20,7 @@ auto System::load(Emulator::Interface* interface) -> bool {
|
||||||
auto document = BML::unserialize(information.manifest);
|
auto document = BML::unserialize(information.manifest);
|
||||||
if(!cartridge.load()) return false;
|
if(!cartridge.load()) return false;
|
||||||
|
|
||||||
|
information.region = Region::NTSCU;
|
||||||
information.colorburst = Emulator::Constants::Colorburst::NTSC;
|
information.colorburst = Emulator::Constants::Colorburst::NTSC;
|
||||||
this->interface = interface;
|
this->interface = interface;
|
||||||
return information.loaded = true;
|
return information.loaded = true;
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
struct System {
|
struct System {
|
||||||
|
enum class Region : uint {
|
||||||
|
NTSCJ,
|
||||||
|
NTSCU,
|
||||||
|
PAL,
|
||||||
|
};
|
||||||
|
|
||||||
auto loaded() const -> bool { return information.loaded; }
|
auto loaded() const -> bool { return information.loaded; }
|
||||||
|
auto region() const -> Region { return information.region; }
|
||||||
auto colorburst() const -> double { return information.colorburst; }
|
auto colorburst() const -> double { return information.colorburst; }
|
||||||
|
|
||||||
auto run() -> void;
|
auto run() -> void;
|
||||||
|
|
||||||
auto load(Emulator::Interface*) -> bool;
|
auto load(Emulator::Interface*, maybe<Region> = nothing) -> bool;
|
||||||
auto save() -> void;
|
auto save() -> void;
|
||||||
auto unload() -> void;
|
auto unload() -> void;
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
|
@ -14,6 +21,7 @@ private:
|
||||||
|
|
||||||
struct Information {
|
struct Information {
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
|
Region region = Region::NTSCJ;
|
||||||
string manifest;
|
string manifest;
|
||||||
double colorburst = 0.0;
|
double colorburst = 0.0;
|
||||||
} information;
|
} information;
|
||||||
|
@ -31,3 +39,7 @@ struct Peripherals {
|
||||||
|
|
||||||
extern System system;
|
extern System system;
|
||||||
extern Peripherals peripherals;
|
extern Peripherals peripherals;
|
||||||
|
|
||||||
|
auto Region::NTSCJ() -> bool { return system.region() == System::Region::NTSCJ; }
|
||||||
|
auto Region::NTSCU() -> bool { return system.region() == System::Region::NTSCU; }
|
||||||
|
auto Region::PAL() -> bool { return system.region() == System::Region::PAL; }
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace MasterSystem {
|
namespace MasterSystem {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
struct Interface;
|
struct Interface;
|
||||||
|
|
|
@ -19,12 +19,14 @@ auto CPU::read(uint8 bank, uint13 addr) -> uint8 {
|
||||||
if(bank == 0xff) {
|
if(bank == 0xff) {
|
||||||
//$0000-03ff VDC or VPC
|
//$0000-03ff VDC or VPC
|
||||||
if((addr & 0x1c00) == 0x0000) {
|
if((addr & 0x1c00) == 0x0000) {
|
||||||
|
HuC6280::io(); //penalty cycle
|
||||||
if(Model::PCEngine()) return vdc0.read(addr);
|
if(Model::PCEngine()) return vdc0.read(addr);
|
||||||
if(Model::SuperGrafx()) return vpc.read(addr);
|
if(Model::SuperGrafx()) return vpc.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//$0400-07ff VCE
|
//$0400-07ff VCE
|
||||||
if((addr & 0x1c00) == 0x0400) {
|
if((addr & 0x1c00) == 0x0400) {
|
||||||
|
HuC6280::io(); //penalty cycle
|
||||||
return vce.read(addr);
|
return vce.read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +125,14 @@ auto CPU::write(uint8 bank, uint13 addr, uint8 data) -> void {
|
||||||
if(bank == 0xff) {
|
if(bank == 0xff) {
|
||||||
//$0000-03ff VDC or VPC
|
//$0000-03ff VDC or VPC
|
||||||
if((addr & 0x1c00) == 0x0000) {
|
if((addr & 0x1c00) == 0x0000) {
|
||||||
|
HuC6280::io(); //penalty cycle
|
||||||
if(Model::PCEngine()) return vdc0.write(addr, data);
|
if(Model::PCEngine()) return vdc0.write(addr, data);
|
||||||
if(Model::SuperGrafx()) return vpc.write(addr, data);
|
if(Model::SuperGrafx()) return vpc.write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//$0400-07ff VCE
|
//$0400-07ff VCE
|
||||||
if((addr & 0x1c00) == 0x0400) {
|
if((addr & 0x1c00) == 0x0400) {
|
||||||
|
HuC6280::io(); //penalty cycle
|
||||||
return vce.write(addr, data);
|
return vce.write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +190,7 @@ auto CPU::write(uint8 bank, uint13 addr, uint8 data) -> void {
|
||||||
|
|
||||||
//ST0, ST1, ST2
|
//ST0, ST1, ST2
|
||||||
auto CPU::store(uint2 addr, uint8 data) -> void {
|
auto CPU::store(uint2 addr, uint8 data) -> void {
|
||||||
|
HuC6280::io(); //penalty cycle
|
||||||
if(addr) addr++; //0,1,2 => 0,2,3
|
if(addr) addr++; //0,1,2 => 0,2,3
|
||||||
if(Model::PCEngine()) vdc0.write(addr, data);
|
if(Model::PCEngine()) vdc0.write(addr, data);
|
||||||
if(Model::SuperGrafx()) vpc.store(addr, data);
|
if(Model::SuperGrafx()) vpc.store(addr, data);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace PCEngine {
|
namespace PCEngine {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
auto PSG::Channel::power() -> void {
|
auto PSG::Channel::power(uint id) -> void {
|
||||||
|
this->id = id;
|
||||||
memory::fill(&io, sizeof(IO));
|
memory::fill(&io, sizeof(IO));
|
||||||
memory::fill(&output, sizeof(Output));
|
memory::fill(&output, sizeof(Output));
|
||||||
}
|
}
|
||||||
|
@ -6,23 +7,31 @@ auto PSG::Channel::power() -> void {
|
||||||
auto PSG::Channel::run() -> void {
|
auto PSG::Channel::run() -> void {
|
||||||
if(!io.enable) return sample(0);
|
if(!io.enable) return sample(0);
|
||||||
|
|
||||||
if(io.noiseEnable) {
|
if(!io.direct && --io.wavePeriod == 0) {
|
||||||
if(--io.noisePeriod == 0) {
|
io.wavePeriod = io.waveFrequency;
|
||||||
io.noisePeriod = ~io.noiseFrequency << 7;
|
|
||||||
//todo: this should be a square wave; PRNG algorithm is also unknown
|
|
||||||
io.noiseSample = nall::random();
|
|
||||||
}
|
|
||||||
return sample(io.noiseSample);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(io.direct) return sample(io.waveDirect);
|
|
||||||
|
|
||||||
if(--io.period == 0) {
|
|
||||||
io.period = io.frequency;
|
|
||||||
io.waveOffset++;
|
io.waveOffset++;
|
||||||
|
io.waveSample = io.waveBuffer[io.waveOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
return sample(io.waveData[io.waveOffset]);
|
if(!io.noiseEnable) {
|
||||||
|
return sample(io.waveSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(--io.noisePeriod == 0) {
|
||||||
|
io.noisePeriod = ~io.noiseFrequency << 7;
|
||||||
|
//todo: this should be a square wave; PRNG algorithm is also unknown
|
||||||
|
io.noiseSample = nall::random();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample(io.noiseSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PSG::Channel::loadWavePeriod() -> void {
|
||||||
|
io.wavePeriod = io.waveFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PSG::Channel::loadWaveSample() -> void {
|
||||||
|
io.waveSample = io.waveBuffer[io.waveOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PSG::Channel::sample(uint5 sample) -> void {
|
auto PSG::Channel::sample(uint5 sample) -> void {
|
||||||
|
|
|
@ -1,81 +1,81 @@
|
||||||
auto PSG::write(uint4 addr, uint8 data) -> void {
|
auto PSG::write(uint4 addr, uint8 data) -> void {
|
||||||
if(addr == 0x00) {
|
if(addr == 0x00) {
|
||||||
io.channel = data.bits(0,2);
|
io.channel = data.bits(0,2);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr == 0x01) {
|
if(addr == 0x01) {
|
||||||
io.volumeRight = data.bits(0,3);
|
io.volumeRight = data.bits(0,3);
|
||||||
io.volumeLeft = data.bits(4,7);
|
io.volumeLeft = data.bits(4,7);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint3 C = io.channel;
|
if(addr >= 0x02 && addr <= 0x06 && io.channel <= 5) {
|
||||||
|
channel[io.channel].write(addr, data);
|
||||||
if(addr == 0x02) {
|
|
||||||
if(C == 6 || C == 7) return;
|
|
||||||
channel[C].io.frequency.bits(0,7) = data.bits(0,7);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr == 0x03) {
|
if(addr == 0x07 && io.channel >= 4 && io.channel <= 5) {
|
||||||
if(C == 6 || C == 7) return;
|
channel[io.channel].write(addr, data);
|
||||||
channel[C].io.frequency.bits(8,11) = data.bits(0,3);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x04) {
|
|
||||||
if(C == 6 || C == 7) return;
|
|
||||||
if(channel[C].io.direct && !data.bit(6)) {
|
|
||||||
channel[C].io.waveOffset = 0;
|
|
||||||
}
|
|
||||||
if(!channel[C].io.enable && data.bit(7)) {
|
|
||||||
channel[C].io.waveOffset = 0;
|
|
||||||
channel[C].io.period = channel[C].io.frequency;
|
|
||||||
}
|
|
||||||
channel[C].io.volume = data.bits(0,3);
|
|
||||||
channel[C].io.direct = data.bit(6);
|
|
||||||
channel[C].io.enable = data.bit(7);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x05) {
|
|
||||||
if(C == 6 || C == 7) return;
|
|
||||||
channel[C].io.volumeRight = data.bits(0,3);
|
|
||||||
channel[C].io.volumeLeft = data.bits(4,7);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x06) {
|
|
||||||
if(C == 6 || C == 7) return;
|
|
||||||
if(channel[C].io.direct) {
|
|
||||||
channel[C].io.waveDirect = data.bits(0,4);
|
|
||||||
} else if(!channel[C].io.enable) {
|
|
||||||
uint5 O = channel[C].io.waveOffset++;
|
|
||||||
channel[C].io.waveData[O] = data.bits(0,4);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(addr == 0x07) {
|
|
||||||
if(C != 4 && C != 5) return;
|
|
||||||
if(!channel[C].io.noiseEnable && data.bit(7)) {
|
|
||||||
channel[C].io.noisePeriod = ~data.bits(0,4) << 7;
|
|
||||||
channel[C].io.noiseSample = 0;
|
|
||||||
}
|
|
||||||
channel[C].io.noiseFrequency = data.bits(0,4);
|
|
||||||
channel[C].io.noiseEnable = data.bit(7);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr == 0x08) {
|
if(addr == 0x08) {
|
||||||
io.lfoFrequency = data;
|
io.lfoFrequency = data;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(addr == 0x09) {
|
if(addr == 0x09) {
|
||||||
io.lfoControl = data.bits(0,1);
|
io.lfoControl = data.bits(0,1);
|
||||||
io.lfoEnable = data.bit(7);
|
io.lfoEnable = data.bit(7);
|
||||||
return;
|
if(io.lfoEnable) {
|
||||||
|
channel[1].io.waveSample = channel[1].io.waveBuffer[channel[1].io.waveOffset = 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PSG::Channel::write(uint4 addr, uint8 data) -> void {
|
||||||
|
if(addr == 0x02) {
|
||||||
|
io.waveFrequency.bits(0,7) = data.bits(0,7);
|
||||||
|
io.wavePeriod = io.waveFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x03) {
|
||||||
|
io.waveFrequency.bits(8,11) = data.bits(0,3);
|
||||||
|
io.wavePeriod = io.waveFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x04) {
|
||||||
|
if(io.direct && !data.bit(6)) {
|
||||||
|
io.waveOffset = 0;
|
||||||
|
io.waveSample = io.waveBuffer[io.waveOffset];
|
||||||
|
}
|
||||||
|
if(!io.enable && data.bit(7) && !data.bit(6)) {
|
||||||
|
io.waveOffset++;
|
||||||
|
io.waveSample = io.waveBuffer[io.waveOffset];
|
||||||
|
}
|
||||||
|
io.volume = data.bits(0,3);
|
||||||
|
io.direct = data.bit(6);
|
||||||
|
io.enable = data.bit(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x05) {
|
||||||
|
io.volumeRight = data.bits(0,3);
|
||||||
|
io.volumeLeft = data.bits(4,7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addr == 0x06) {
|
||||||
|
if(!io.direct) {
|
||||||
|
io.waveBuffer[io.waveOffset] = data.bits(0,4);
|
||||||
|
if(!io.enable) io.waveOffset++;
|
||||||
|
}
|
||||||
|
if(io.enable) {
|
||||||
|
io.waveSample = data.bits(0,4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//channels 4 and 5 only
|
||||||
|
if(addr == 0x07) {
|
||||||
|
if(!io.noiseEnable && data.bit(7)) {
|
||||||
|
io.noisePeriod = ~data.bits(0,4) << 7;
|
||||||
|
io.noiseSample = 0;
|
||||||
|
}
|
||||||
|
io.noiseFrequency = data.bits(0,4);
|
||||||
|
io.noiseEnable = data.bit(7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ auto PSG::power() -> void {
|
||||||
stream = Emulator::audio.createStream(2, system.colorburst());
|
stream = Emulator::audio.createStream(2, system.colorburst());
|
||||||
|
|
||||||
memory::fill(&io, sizeof(IO));
|
memory::fill(&io, sizeof(IO));
|
||||||
for(auto C : range(6)) channel[C].power();
|
for(auto C : range(6)) channel[C].power(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,24 +24,29 @@ private:
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
//channel.cpp
|
//channel.cpp
|
||||||
auto power() -> void;
|
auto power(uint id) -> void;
|
||||||
auto run() -> void;
|
auto run() -> void;
|
||||||
|
auto loadWavePeriod() -> void;
|
||||||
|
auto loadWaveSample() -> void;
|
||||||
auto sample(uint5 sample) -> void;
|
auto sample(uint5 sample) -> void;
|
||||||
|
|
||||||
|
//io.cpp
|
||||||
|
auto write(uint4 addr, uint8 data) -> void;
|
||||||
|
|
||||||
struct IO {
|
struct IO {
|
||||||
uint12 frequency;
|
uint12 waveFrequency;
|
||||||
uint4 volume;
|
uint4 volume;
|
||||||
uint1 direct;
|
uint1 direct;
|
||||||
uint1 enable;
|
uint1 enable;
|
||||||
uint4 volumeLeft;
|
uint4 volumeLeft;
|
||||||
uint4 volumeRight;
|
uint4 volumeRight;
|
||||||
uint5 waveData[32];
|
uint5 waveBuffer[32];
|
||||||
uint5 waveOffset;
|
|
||||||
uint5 waveDirect;
|
|
||||||
uint5 noiseFrequency; //channels 4 and 5 only
|
uint5 noiseFrequency; //channels 4 and 5 only
|
||||||
uint1 noiseEnable; //channels 4 and 5 only
|
uint1 noiseEnable; //channels 4 and 5 only
|
||||||
|
|
||||||
uint12 period;
|
uint12 wavePeriod;
|
||||||
|
uint5 waveSample;
|
||||||
|
uint5 waveOffset;
|
||||||
uint12 noisePeriod;
|
uint12 noisePeriod;
|
||||||
uint5 noiseSample;
|
uint5 noiseSample;
|
||||||
} io;
|
} io;
|
||||||
|
@ -50,6 +55,8 @@ private:
|
||||||
uint left;
|
uint left;
|
||||||
uint right;
|
uint right;
|
||||||
} output;
|
} output;
|
||||||
|
|
||||||
|
uint id;
|
||||||
} channel[6];
|
} channel[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct HuC6280 {
|
||||||
inline auto store8(uint8, uint8) -> void;
|
inline auto store8(uint8, uint8) -> void;
|
||||||
inline auto store16(uint16, uint8) -> void;
|
inline auto store16(uint16, uint8) -> void;
|
||||||
|
|
||||||
auto io() -> uint8;
|
auto io() -> void;
|
||||||
auto opcode() -> uint8;
|
auto opcode() -> uint8;
|
||||||
auto operand() -> uint8;
|
auto operand() -> uint8;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ auto HuC6280::ADC(uint8 i) -> uint8 {
|
||||||
o = A + i + C;
|
o = A + i + C;
|
||||||
V = ~(A ^ i) & (A ^ o) & 0x80;
|
V = ~(A ^ i) & (A ^ o) & 0x80;
|
||||||
} else {
|
} else {
|
||||||
|
io();
|
||||||
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
|
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
|
||||||
if(o > 0x09) o += 0x06;
|
if(o > 0x09) o += 0x06;
|
||||||
C = o > 0x0f;
|
C = o > 0x0f;
|
||||||
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
|
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
|
||||||
V = ~(A ^ i) & (A ^ o) & 0x80;
|
|
||||||
if(o > 0x9f) o += 0x60;
|
if(o > 0x9f) o += 0x60;
|
||||||
}
|
}
|
||||||
C = o.bit(8);
|
C = o.bit(8);
|
||||||
|
@ -130,11 +130,11 @@ auto HuC6280::SBC(uint8 i) -> uint8 {
|
||||||
o = A + i + C;
|
o = A + i + C;
|
||||||
V = ~(A ^ i) & (A ^ o) & 0x80;
|
V = ~(A ^ i) & (A ^ o) & 0x80;
|
||||||
} else {
|
} else {
|
||||||
|
io();
|
||||||
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
|
o = (A & 0x0f) + (i & 0x0f) + (C << 0);
|
||||||
if(o <= 0x0f) o -= 0x06;
|
if(o <= 0x0f) o -= 0x06;
|
||||||
C = o > 0x0f;
|
C = o > 0x0f;
|
||||||
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
|
o = (A & 0xf0) + (i & 0xf0) + (C << 4) + (o & 0x0f);
|
||||||
V = ~(A ^ i) & (A ^ o) & 0x80;
|
|
||||||
if(o <= 0xff) o -= 0x60;
|
if(o <= 0xff) o -= 0x60;
|
||||||
}
|
}
|
||||||
C = o.bit(8);
|
C = o.bit(8);
|
||||||
|
@ -222,7 +222,6 @@ auto HuC6280::instruction_blockmove(bp alu) -> void {
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
io();
|
||||||
io();
|
|
||||||
bool alternate = 0;
|
bool alternate = 0;
|
||||||
do {
|
do {
|
||||||
auto data = load16(source);
|
auto data = load16(source);
|
||||||
|
@ -497,8 +496,8 @@ L store8(zeropage, data);
|
||||||
auto HuC6280::instruction_ST(uint2 index) -> void {
|
auto HuC6280::instruction_ST(uint2 index) -> void {
|
||||||
auto data = operand();
|
auto data = operand();
|
||||||
io();
|
io();
|
||||||
L io();
|
io();
|
||||||
store(index, data);
|
L store(index, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::instruction_TAM() -> void {
|
auto HuC6280::instruction_TAM() -> void {
|
||||||
|
|
|
@ -20,9 +20,8 @@ auto HuC6280::store16(uint16 addr, uint8 data) -> void {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto HuC6280::io() -> uint8 {
|
auto HuC6280::io() -> void {
|
||||||
step(r.cs);
|
step(r.cs);
|
||||||
return 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HuC6280::opcode() -> uint8 {
|
auto HuC6280::opcode() -> uint8 {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
namespace SuperFamicom {
|
namespace SuperFamicom {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
using Cheat = Emulator::Cheat;
|
using Cheat = Emulator::Cheat;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace WonderSwan {
|
namespace WonderSwan {
|
||||||
#define platform Emulator::platform
|
#define platform Emulator::platform
|
||||||
using File = Emulator::File;
|
namespace File = Emulator::File;
|
||||||
using Scheduler = Emulator::Scheduler;
|
using Scheduler = Emulator::Scheduler;
|
||||||
using Cheat = Emulator::Cheat;
|
using Cheat = Emulator::Cheat;
|
||||||
extern Scheduler scheduler;
|
extern Scheduler scheduler;
|
||||||
|
|
|
@ -7,7 +7,7 @@ struct BrowserDialogWindow {
|
||||||
auto change() -> void;
|
auto change() -> void;
|
||||||
auto isFolder(const string& name) -> bool;
|
auto isFolder(const string& name) -> bool;
|
||||||
auto isMatch(const string& name) -> bool;
|
auto isMatch(const string& name) -> bool;
|
||||||
auto run() -> string_vector;
|
auto run() -> BrowserDialog::Response;
|
||||||
auto setPath(string path) -> void;
|
auto setPath(string path) -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -20,12 +20,14 @@ private:
|
||||||
Button pathUp{&pathLayout, Size{0, 0}, 0};
|
Button pathUp{&pathLayout, Size{0, 0}, 0};
|
||||||
ListView view{&layout, Size{~0, ~0}, 5};
|
ListView view{&layout, Size{~0, ~0}, 5};
|
||||||
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
||||||
ComboButton filterList{&controlLayout, Size{120, 0}, 5};
|
ComboButton filterList{&controlLayout, Size{0, 0}, 5};
|
||||||
LineEdit fileName{&controlLayout, Size{~0, 0}, 5};
|
LineEdit fileName{&controlLayout, Size{~0, 0}, 5};
|
||||||
|
ComboButton optionList{&controlLayout, Size{0, 0}, 5};
|
||||||
Button acceptButton{&controlLayout, Size{80, 0}, 5};
|
Button acceptButton{&controlLayout, Size{80, 0}, 5};
|
||||||
Button cancelButton{&controlLayout, Size{80, 0}, 5};
|
Button cancelButton{&controlLayout, Size{80, 0}, 5};
|
||||||
|
|
||||||
BrowserDialog::State& state;
|
BrowserDialog::State& state;
|
||||||
|
BrowserDialog::Response response;
|
||||||
vector<string_vector> filters;
|
vector<string_vector> filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,20 +39,20 @@ auto BrowserDialogWindow::accept() -> void {
|
||||||
if(state.action == "openFile" && batched) {
|
if(state.action == "openFile" && batched) {
|
||||||
string name = batched.left()->cell(0)->text();
|
string name = batched.left()->cell(0)->text();
|
||||||
if(isFolder(name)) return setPath({state.path, name});
|
if(isFolder(name)) return setPath({state.path, name});
|
||||||
state.response.append(string{state.path, name});
|
response.selected.append(string{state.path, name});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.action == "openFiles") {
|
if(state.action == "openFiles") {
|
||||||
for(auto item : batched) {
|
for(auto item : batched) {
|
||||||
string name = item->cell(0)->text();
|
string name = item->cell(0)->text();
|
||||||
state.response.append(string{state.path, name, isFolder(name) ? "/" : ""});
|
response.selected.append(string{state.path, name, isFolder(name) ? "/" : ""});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.action == "openFolder" && batched) {
|
if(state.action == "openFolder" && batched) {
|
||||||
string name = batched.left()->cell(0)->text();
|
string name = batched.left()->cell(0)->text();
|
||||||
if(!isMatch(name)) return setPath({state.path, name});
|
if(!isMatch(name)) return setPath({state.path, name});
|
||||||
state.response.append(string{state.path, name, "/"});
|
response.selected.append(string{state.path, name, "/"});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.action == "saveFile") {
|
if(state.action == "saveFile") {
|
||||||
|
@ -60,15 +62,15 @@ auto BrowserDialogWindow::accept() -> void {
|
||||||
if(file::exists({state.path, name})) {
|
if(file::exists({state.path, name})) {
|
||||||
if(MessageDialog("File already exists; overwrite it?").question() != "Yes") return;
|
if(MessageDialog("File already exists; overwrite it?").question() != "Yes") return;
|
||||||
}
|
}
|
||||||
state.response.append(string{state.path, name});
|
response.selected.append(string{state.path, name});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.action == "selectFolder" && batched) {
|
if(state.action == "selectFolder" && batched) {
|
||||||
string name = batched.left()->cell(0)->text();
|
string name = batched.left()->cell(0)->text();
|
||||||
if(isFolder(name)) state.response.append(string{state.path, name, "/"});
|
if(isFolder(name)) response.selected.append(string{state.path, name, "/"});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.response) window.setModal(false);
|
if(response.selected) window.setModal(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//table view item double-clicked, or enter pressed on selected table view item
|
//table view item double-clicked, or enter pressed on selected table view item
|
||||||
|
@ -113,8 +115,8 @@ auto BrowserDialogWindow::isMatch(const string& name) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BrowserDialogWindow::run() -> string_vector {
|
auto BrowserDialogWindow::run() -> BrowserDialog::Response {
|
||||||
state.response.reset();
|
response = {};
|
||||||
|
|
||||||
layout.setMargin(5);
|
layout.setMargin(5);
|
||||||
pathName.onActivate([&] { setPath(pathName.text()); });
|
pathName.onActivate([&] { setPath(pathName.text()); });
|
||||||
|
@ -127,6 +129,11 @@ auto BrowserDialogWindow::run() -> string_vector {
|
||||||
auto part = filter.split("|", 1L);
|
auto part = filter.split("|", 1L);
|
||||||
filterList.append(ComboButtonItem().setText(part.left()));
|
filterList.append(ComboButtonItem().setText(part.left()));
|
||||||
}
|
}
|
||||||
|
optionList.setVisible((bool)state.options).onChange([&] { response.option = optionList.selected().text(); });
|
||||||
|
for(auto& option : state.options) {
|
||||||
|
optionList.append(ComboButtonItem().setText(option));
|
||||||
|
}
|
||||||
|
optionList.doChange(); //updates response.option to point to the default (first) option
|
||||||
fileName.setVisible(state.action == "saveFile").onActivate([&] { accept(); });
|
fileName.setVisible(state.action == "saveFile").onActivate([&] { accept(); });
|
||||||
acceptButton.onActivate([&] { accept(); });
|
acceptButton.onActivate([&] { accept(); });
|
||||||
if(state.action == "openFile" || state.action == "openFiles" || state.action == "openFolder") acceptButton.setText("Open");
|
if(state.action == "openFile" || state.action == "openFiles" || state.action == "openFolder") acceptButton.setText("Open");
|
||||||
|
@ -151,7 +158,7 @@ auto BrowserDialogWindow::run() -> string_vector {
|
||||||
window.setModal();
|
window.setModal();
|
||||||
window.setVisible(false);
|
window.setVisible(false);
|
||||||
|
|
||||||
return state.response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BrowserDialogWindow::setPath(string path) -> void {
|
auto BrowserDialogWindow::setPath(string path) -> void {
|
||||||
|
@ -211,6 +218,10 @@ auto BrowserDialog::openFolder() -> string {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto BrowserDialog::option() -> string {
|
||||||
|
return response.option;
|
||||||
|
}
|
||||||
|
|
||||||
auto BrowserDialog::saveFile() -> string {
|
auto BrowserDialog::saveFile() -> string {
|
||||||
state.action = "saveFile";
|
state.action = "saveFile";
|
||||||
if(!state.title) state.title = "Save File";
|
if(!state.title) state.title = "Save File";
|
||||||
|
@ -218,6 +229,10 @@ auto BrowserDialog::saveFile() -> string {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto BrowserDialog::selected() -> string_vector {
|
||||||
|
return response.selected;
|
||||||
|
}
|
||||||
|
|
||||||
auto BrowserDialog::selectFolder() -> string {
|
auto BrowserDialog::selectFolder() -> string {
|
||||||
state.action = "selectFolder";
|
state.action = "selectFolder";
|
||||||
if(!state.title) state.title = "Select Folder";
|
if(!state.title) state.title = "Select Folder";
|
||||||
|
@ -230,6 +245,11 @@ auto BrowserDialog::setFilters(const string_vector& filters) -> type& {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto BrowserDialog::setOptions(const string_vector& options) -> type& {
|
||||||
|
state.options = options;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
auto BrowserDialog::setParent(const sWindow& parent) -> type& {
|
auto BrowserDialog::setParent(const sWindow& parent) -> type& {
|
||||||
state.parent = parent;
|
state.parent = parent;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -247,7 +267,8 @@ auto BrowserDialog::setTitle(const string& title) -> type& {
|
||||||
|
|
||||||
auto BrowserDialog::_run() -> string_vector {
|
auto BrowserDialog::_run() -> string_vector {
|
||||||
if(!state.path) state.path = Path::user();
|
if(!state.path) state.path = Path::user();
|
||||||
return BrowserDialogWindow(state).run();
|
response = BrowserDialogWindow(state).run();
|
||||||
|
return response.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,9 +9,12 @@ struct BrowserDialog {
|
||||||
auto openFile() -> string; //one existing file
|
auto openFile() -> string; //one existing file
|
||||||
auto openFiles() -> string_vector; //any existing files or folders
|
auto openFiles() -> string_vector; //any existing files or folders
|
||||||
auto openFolder() -> string; //one existing folder
|
auto openFolder() -> string; //one existing folder
|
||||||
|
auto option() -> string;
|
||||||
auto saveFile() -> string; //one file
|
auto saveFile() -> string; //one file
|
||||||
|
auto selected() -> string_vector;
|
||||||
auto selectFolder() -> string; //one existing folder
|
auto selectFolder() -> string; //one existing folder
|
||||||
auto setFilters(const string_vector& filters = {}) -> type&;
|
auto setFilters(const string_vector& filters = {}) -> type&;
|
||||||
|
auto setOptions(const string_vector& options = {}) -> type&;
|
||||||
auto setParent(const sWindow& parent) -> type&;
|
auto setParent(const sWindow& parent) -> type&;
|
||||||
auto setPath(const string& path = "") -> type&;
|
auto setPath(const string& path = "") -> type&;
|
||||||
auto setTitle(const string& title = "") -> type&;
|
auto setTitle(const string& title = "") -> type&;
|
||||||
|
@ -20,12 +23,17 @@ private:
|
||||||
struct State {
|
struct State {
|
||||||
string action;
|
string action;
|
||||||
string_vector filters = {"*"};
|
string_vector filters = {"*"};
|
||||||
|
string_vector options;
|
||||||
sWindow parent;
|
sWindow parent;
|
||||||
string path;
|
string path;
|
||||||
string_vector response;
|
|
||||||
string title;
|
string title;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
|
struct Response {
|
||||||
|
string option;
|
||||||
|
string_vector selected;
|
||||||
|
} response;
|
||||||
|
|
||||||
auto _run() -> string_vector;
|
auto _run() -> string_vector;
|
||||||
|
|
||||||
friend class BrowserDialogWindow;
|
friend class BrowserDialogWindow;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
build := release
|
||||||
include ../nall/GNUmakefile
|
include ../nall/GNUmakefile
|
||||||
include ../hiro/GNUmakefile
|
include ../hiro/GNUmakefile
|
||||||
|
|
||||||
name := icarus
|
name := icarus
|
||||||
flags += -I.. -O3
|
flags += -I..
|
||||||
link +=
|
link +=
|
||||||
|
|
||||||
ifeq ($(platform),windows)
|
ifeq ($(platform),windows)
|
||||||
|
|
|
@ -9,6 +9,9 @@ struct PCEngineCartridge {
|
||||||
};
|
};
|
||||||
|
|
||||||
PCEngineCartridge::PCEngineCartridge(string location, uint8_t* data, uint size) {
|
PCEngineCartridge::PCEngineCartridge(string location, uint8_t* data, uint size) {
|
||||||
|
//skip header
|
||||||
|
if((size & 0x1fff) == 512) data += 512, size -= 512;
|
||||||
|
|
||||||
manifest.append("board\n");
|
manifest.append("board\n");
|
||||||
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
manifest.append(" rom name=program.rom size=0x", hex(size), "\n");
|
||||||
manifest.append("\n");
|
manifest.append("\n");
|
||||||
|
|
|
@ -59,6 +59,23 @@ ifeq ($(compiler),)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# build settings
|
||||||
|
ifeq ($(build),release)
|
||||||
|
flags += -O3
|
||||||
|
else ifeq ($(build),stable)
|
||||||
|
flags += -O1
|
||||||
|
else ifeq ($(build),debug)
|
||||||
|
flags += -g
|
||||||
|
else ifeq ($(build),profile)
|
||||||
|
flags += -pg
|
||||||
|
link += -pg
|
||||||
|
else ifeq ($(build),instrument)
|
||||||
|
flags += -O3 -fprofile-generate
|
||||||
|
link += -lgcov
|
||||||
|
else ifeq ($(build),optimize)
|
||||||
|
flags += -O3 -fprofile-use
|
||||||
|
endif
|
||||||
|
|
||||||
# clang settings
|
# clang settings
|
||||||
ifeq ($(findstring clang++,$(compiler)),clang++)
|
ifeq ($(findstring clang++,$(compiler)),clang++)
|
||||||
flags += -fno-strict-aliasing -fwrapv
|
flags += -fno-strict-aliasing -fwrapv
|
||||||
|
|
Loading…
Reference in New Issue