diff --git a/higan/emulator/audio/audio.cpp b/higan/emulator/audio/audio.cpp index c6fb080a..c743b58d 100644 --- a/higan/emulator/audio/audio.cpp +++ b/higan/emulator/audio/audio.cpp @@ -64,7 +64,7 @@ auto Audio::process() -> void { if(balance > 0.0) samples[0] *= 1.0 - balance; } - platform->audioSample(samples, channels); + platform->audioFrame(samples, channels); } } diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 0467f50e..aa085241 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -30,7 +30,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.69"; + static const string Version = "106.70"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index 4017b6c3..759ba7ee 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -54,7 +54,7 @@ struct Interface { //information virtual auto information() -> Information { return {}; } - virtual auto displays() -> vector { return {}; } + virtual auto display() -> Display { return {}; } virtual auto color(uint32 color) -> uint64 { return 0; } //game interface diff --git a/higan/emulator/platform.hpp b/higan/emulator/platform.hpp index 111cc07f..09288cb5 100644 --- a/higan/emulator/platform.hpp +++ b/higan/emulator/platform.hpp @@ -16,8 +16,8 @@ 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, vector options = {}) -> Load { return {}; } - 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 videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void {} + virtual auto audioFrame(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; } diff --git a/higan/emulator/video/video.cpp b/higan/emulator/video/video.cpp index d06d0be9..816f7657 100644 --- a/higan/emulator/video/video.cpp +++ b/higan/emulator/video/video.cpp @@ -28,7 +28,7 @@ auto Video::setPalette() -> void { if(!interface) return; delete palette; - colors = interface->displays()[0].colors; + colors = interface->display().colors; palette = new uint32[colors]; for(auto index : range(colors)) { uint64 color = interface->color(index); @@ -185,7 +185,7 @@ auto Video::refresh(uint32* input, uint pitch, uint width, uint height) -> void } } - platform->videoRefresh(0, output, width * sizeof(uint32), width, height); + platform->videoFrame(output, width * sizeof(uint32), width, height); } } diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 255a80f4..b60d9a18 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -13,7 +13,7 @@ auto Interface::information() -> Information { return information; } -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 9; @@ -23,7 +23,7 @@ auto Interface::displays() -> vector { display.internalHeight = 240; display.aspectCorrection = 8.0 / 7.0; display.refreshRate = system.frequency() / (ppu.vlines() * ppu.rate() * 341.0); - return {display}; + return display; } auto Interface::color(uint32 n) -> uint64 { diff --git a/higan/fc/interface/interface.hpp b/higan/fc/interface/interface.hpp index 88dca3d7..d37a7d6e 100644 --- a/higan/fc/interface/interface.hpp +++ b/higan/fc/interface/interface.hpp @@ -23,7 +23,7 @@ struct ID { struct Interface : Emulator::Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 0663925c..f7dc4ec8 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -7,7 +7,7 @@ Settings settings; #include "game-boy.cpp" #include "game-boy-color.cpp" -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::LCD; display.colors = Model::GameBoyColor() ? 1 << 15 : 1 << 2; @@ -17,7 +17,7 @@ auto Interface::displays() -> vector { display.internalHeight = 144; display.aspectCorrection = 1.0; display.refreshRate = (4.0 * 1024.0 * 1024.0) / (154.0 * 456.0); - return {display}; + return display; } auto Interface::loaded() -> bool { diff --git a/higan/gb/interface/interface.hpp b/higan/gb/interface/interface.hpp index 58d26bae..42f07097 100644 --- a/higan/gb/interface/interface.hpp +++ b/higan/gb/interface/interface.hpp @@ -23,7 +23,7 @@ struct ID { }; struct Interface : Emulator::Interface { - auto displays() -> vector override; + auto display() -> Display override; auto loaded() -> bool override; auto hashes() -> vector override; diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index 1365d62f..a7e54330 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -12,7 +12,7 @@ auto Interface::information() -> Information { return information; } -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::LCD; display.colors = 1 << 15; @@ -26,7 +26,7 @@ auto Interface::displays() -> vector { swap(display.width, display.height); swap(display.internalWidth, display.internalHeight); } - return {display}; + return display; } auto Interface::color(uint32 color) -> uint64 { diff --git a/higan/gba/interface/interface.hpp b/higan/gba/interface/interface.hpp index 6fe128de..6819a887 100644 --- a/higan/gba/interface/interface.hpp +++ b/higan/gba/interface/interface.hpp @@ -20,7 +20,7 @@ struct ID { struct Interface : Emulator::Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index c27b24a3..1c235378 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -13,7 +13,7 @@ auto Interface::information() -> Information { return information; } -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 3 * (1 << 9); @@ -23,7 +23,7 @@ auto Interface::displays() -> vector { display.internalHeight = 480; display.aspectCorrection = 1.0; display.refreshRate = (system.frequency() / 2.0) / (vdp.frameHeight() * 1710.0); - return {display}; + return display; } auto Interface::color(uint32 color) -> uint64 { diff --git a/higan/md/interface/interface.hpp b/higan/md/interface/interface.hpp index 85f8be88..eaf60b1e 100644 --- a/higan/md/interface/interface.hpp +++ b/higan/md/interface/interface.hpp @@ -24,7 +24,7 @@ struct ID { struct Interface : Emulator::Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/ms/interface/colecovision.cpp b/higan/ms/interface/colecovision.cpp index 110c4d1b..b0ff5fc7 100644 --- a/higan/ms/interface/colecovision.cpp +++ b/higan/ms/interface/colecovision.cpp @@ -6,7 +6,7 @@ auto ColecoVisionInterface::information() -> Information { return information; } -auto ColecoVisionInterface::displays() -> vector { +auto ColecoVisionInterface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 4; @@ -17,7 +17,7 @@ auto ColecoVisionInterface::displays() -> vector { display.aspectCorrection = 1.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}; + return display; } auto ColecoVisionInterface::color(uint32 color) -> uint64 { diff --git a/higan/ms/interface/game-gear.cpp b/higan/ms/interface/game-gear.cpp index b8c4c9aa..b3844bec 100644 --- a/higan/ms/interface/game-gear.cpp +++ b/higan/ms/interface/game-gear.cpp @@ -6,7 +6,7 @@ auto GameGearInterface::information() -> Information { return information; } -auto GameGearInterface::displays() -> vector { +auto GameGearInterface::display() -> Display { Display display; display.type = Display::Type::LCD; display.colors = 1 << 12; @@ -16,7 +16,7 @@ auto GameGearInterface::displays() -> vector { display.internalHeight = 144; display.aspectCorrection = 1.0; display.refreshRate = (system.colorburst() * 15.0 / 5.0) / (262.0 * 684.0); - return {display}; + return display; } auto GameGearInterface::color(uint32 color) -> uint64 { diff --git a/higan/ms/interface/interface.hpp b/higan/ms/interface/interface.hpp index 1b2484cb..9044d752 100644 --- a/higan/ms/interface/interface.hpp +++ b/higan/ms/interface/interface.hpp @@ -53,7 +53,7 @@ struct Interface : Emulator::Interface { struct ColecoVisionInterface : Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; @@ -69,7 +69,7 @@ struct ColecoVisionInterface : Interface { struct SG1000Interface : Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; @@ -85,7 +85,7 @@ struct SG1000Interface : Interface { struct SC3000Interface : Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; @@ -101,7 +101,7 @@ struct SC3000Interface : Interface { struct MasterSystemInterface : Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; @@ -117,7 +117,7 @@ struct MasterSystemInterface : Interface { struct GameGearInterface : Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 0bd23f4f..5380f608 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -6,7 +6,7 @@ auto MasterSystemInterface::information() -> Information { return information; } -auto MasterSystemInterface::displays() -> vector { +auto MasterSystemInterface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 6; @@ -17,7 +17,7 @@ auto MasterSystemInterface::displays() -> vector { 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}; + return display; } auto MasterSystemInterface::color(uint32 color) -> uint64 { diff --git a/higan/ms/interface/sc-3000.cpp b/higan/ms/interface/sc-3000.cpp index 429ecc16..5f400814 100644 --- a/higan/ms/interface/sc-3000.cpp +++ b/higan/ms/interface/sc-3000.cpp @@ -6,7 +6,7 @@ auto SC3000Interface::information() -> Information { return information; } -auto SC3000Interface::displays() -> vector { +auto SC3000Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 4; @@ -17,7 +17,7 @@ auto SC3000Interface::displays() -> vector { display.aspectCorrection = 1.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}; + return display; } auto SC3000Interface::color(uint32 color) -> uint64 { diff --git a/higan/ms/interface/sg-1000.cpp b/higan/ms/interface/sg-1000.cpp index 97c338cf..28410927 100644 --- a/higan/ms/interface/sg-1000.cpp +++ b/higan/ms/interface/sg-1000.cpp @@ -6,7 +6,7 @@ auto SG1000Interface::information() -> Information { return information; } -auto SG1000Interface::displays() -> vector { +auto SG1000Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 4; @@ -17,7 +17,7 @@ auto SG1000Interface::displays() -> vector { display.aspectCorrection = 1.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}; + return display; } auto SG1000Interface::color(uint32 color) -> uint64 { diff --git a/higan/ms/vdp/background.cpp b/higan/ms/vdp/background.cpp index b8800b5d..6c74669e 100644 --- a/higan/ms/vdp/background.cpp +++ b/higan/ms/vdp/background.cpp @@ -57,13 +57,8 @@ auto VDP::Background::graphics2(uint8 hoffset, uint9 voffset) -> void { patternAddress.bits(3,10) = pattern; if(voffset >= 64 && voffset <= 127) patternAddress.bit(11) = vdp.io.patternTableAddress.bit(0); if(voffset >= 128 && voffset <= 191) patternAddress.bit(12) = vdp.io.patternTableAddress.bit(1); + uint14 colorAddress = patternAddress; patternAddress.bit(13) = vdp.io.patternTableAddress.bit(2); - - uint14 colorAddress; - colorAddress.bits(0, 2) = voffset.bits(0,2); - colorAddress.bits(3,10) = pattern; - if(voffset >= 64 && voffset <= 127) colorAddress.bit(11) = vdp.io.patternTableAddress.bit(0); - if(voffset >= 128 && voffset <= 191) colorAddress.bit(12) = vdp.io.patternTableAddress.bit(1); colorAddress.bit(13) = vdp.io.colorTableAddress.bit(7); uint8 colorMask = vdp.io.colorTableAddress.bits(0,6) << 1 | 1; diff --git a/higan/msx/cartridge/cartridge.cpp b/higan/msx/cartridge/cartridge.cpp index 9a538f5e..63d71f78 100644 --- a/higan/msx/cartridge/cartridge.cpp +++ b/higan/msx/cartridge/cartridge.cpp @@ -58,4 +58,11 @@ auto Cartridge::unload() -> void { auto Cartridge::power() -> void { } +auto Cartridge::read(uint16 address) -> uint8 { + return rom.read(address); +} + +auto Cartridge::write(uint16 address, uint8 data) -> void { +} + } diff --git a/higan/msx/cartridge/cartridge.hpp b/higan/msx/cartridge/cartridge.hpp index ee9716e9..1d2c0c5c 100644 --- a/higan/msx/cartridge/cartridge.hpp +++ b/higan/msx/cartridge/cartridge.hpp @@ -12,6 +12,9 @@ struct Cartridge { auto power() -> void; + auto read(uint16 address) -> uint8; + auto write(uint16 address, uint8 data) -> void; + //serialization.cpp auto serialize(serializer&) -> void; diff --git a/higan/msx/cpu/cpu.cpp b/higan/msx/cpu/cpu.cpp index 34b24202..3c16295c 100644 --- a/higan/msx/cpu/cpu.cpp +++ b/higan/msx/cpu/cpu.cpp @@ -11,11 +11,14 @@ auto CPU::Enter() -> void { } auto CPU::main() -> void { + if(io.irqLine) irq(1, 0x0038, 0xff); instruction(); } auto CPU::step(uint clocks) -> void { Thread::step(clocks); + synchronize(vdp); + synchronize(psg); } auto CPU::synchronizing() const -> bool { @@ -23,6 +26,19 @@ auto CPU::synchronizing() const -> bool { } auto CPU::power() -> void { + Z80::bus = this; + Z80::power(); + create(CPU::Enter, system.colorburst()); + + r.pc = 0x0000; //reset vector address + + ram.allocate(0x10000); + + io = {}; +} + +auto CPU::setIRQ(bool line) -> void { + io.irqLine = line; } } diff --git a/higan/msx/cpu/cpu.hpp b/higan/msx/cpu/cpu.hpp index ddb8f637..92ced7f0 100644 --- a/higan/msx/cpu/cpu.hpp +++ b/higan/msx/cpu/cpu.hpp @@ -6,6 +6,7 @@ struct CPU : Processor::Z80, Processor::Z80::Bus, Thread { auto synchronizing() const -> bool override; auto power() -> void; + auto setIRQ(bool) -> void; //memory.cpp auto read(uint16 address) -> uint8 override; @@ -16,6 +17,14 @@ struct CPU : Processor::Z80, Processor::Z80::Bus, Thread { //serialization.cpp auto serialize(serializer&) -> void; + +private: + Emulator::Memory::Writable ram; + + struct IO { + uint1 irqLine; + uint2 slot[4]; + } io; }; extern CPU cpu; diff --git a/higan/msx/cpu/memory.cpp b/higan/msx/cpu/memory.cpp index de026692..054fcc40 100644 --- a/higan/msx/cpu/memory.cpp +++ b/higan/msx/cpu/memory.cpp @@ -1,13 +1,65 @@ auto CPU::read(uint16 address) -> uint8 { + uint2 slot = io.slot[address.bits(14,15)]; + + if(slot == 0) { + if(!address.bit(15)) return system.bios.read(address); + return 0xff; + } + + if(slot == 1) { + return cartridge.read(address); + } + + if(slot == 2) { + return ram.read(address); + } + + if(slot == 3) { + } + return 0xff; } auto CPU::write(uint16 address, uint8 data) -> void { + uint2 slot = io.slot[address.bits(14,15)]; + + if(slot == 0) { + return; + } + + if(slot == 1) { + return cartridge.write(address, data); + } + + if(slot == 2) { + return ram.write(address, data); + } + + if(slot == 3) { + return; + } } auto CPU::in(uint8 address) -> uint8 { + switch(address) { + case 0x98: return vdp.data(); + case 0x99: return vdp.status(); + case 0xa8: return io.slot[0] << 0 + | io.slot[1] << 2 + | io.slot[2] << 4 + | io.slot[3] << 6; + } return 0xff; } auto CPU::out(uint8 address, uint8 data) -> void { + switch(address) { + case 0x98: return vdp.data(data); + case 0x99: return vdp.control(data); + case 0xa8: io.slot[0] = data.bits(0,1); + io.slot[1] = data.bits(2,3); + io.slot[2] = data.bits(4,5); + io.slot[3] = data.bits(6,7); + break; + } } diff --git a/higan/msx/interface/interface.cpp b/higan/msx/interface/interface.cpp index c8d54fd6..65122783 100644 --- a/higan/msx/interface/interface.cpp +++ b/higan/msx/interface/interface.cpp @@ -6,11 +6,11 @@ auto Interface::information() -> Information { Information information; information.manufacturer = ""; information.name = "MSX"; - information.extension = ".msx"; + information.extension = "msx"; return information; } -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 4; @@ -20,40 +20,58 @@ auto Interface::displays() -> vector { display.internalHeight = 192; display.aspectCorrection = 1.0; display.refreshRate = 60.0; //todo: PAL - return {display}; + return display; } auto Interface::color(uint32 color) -> uint64 { switch(color.bits(0,3)) { + case 0: return 0x0000'0000'0000ull; //transparent + case 1: return 0x0000'0000'0000ull; //black + case 2: return 0x2121'c8c8'4242ull; //medium green + case 3: return 0x5e5e'dcdc'7878ull; //light green + case 4: return 0x5454'5555'ededull; //dark blue + case 5: return 0x7d7d'7676'fcfcull; //light blue + case 6: return 0xd4d4'5252'4d4dull; //dark red + case 7: return 0x4242'ebeb'f5f5ull; //cyan + case 8: return 0xfcfc'5555'5454ull; //medium red + case 9: return 0xffff'7979'7878ull; //light red + case 10: return 0xd4d4'c1c1'5454ull; //dark yellow + case 11: return 0xe6e6'cece'8080ull; //light yellow + case 12: return 0x2121'b0b0'3b3bull; //dark green + case 13: return 0xc9c9'5b5b'babaull; //magenta + case 14: return 0xcccc'cccc'ccccull; //gray + case 15: return 0xffff'ffff'ffffull; //white } return 0; } auto Interface::loaded() -> bool { - return false; + return system.loaded(); } auto Interface::hashes() -> vector { - return {}; + return {cartridge.hash()}; } auto Interface::manifests() -> vector { - return {}; + return {cartridge.manifest()}; } auto Interface::titles() -> vector { - return {}; + return {cartridge.title()}; } auto Interface::load() -> bool { - return false; + return system.load(this, System::Model::MSX); } auto Interface::save() -> void { + system.save(); } auto Interface::unload() -> void { save(); + system.unload(); } auto Interface::ports() -> vector { return { @@ -91,17 +109,20 @@ auto Interface::inputs(uint device) -> vector { } auto Interface::power() -> void { + system.power(); } auto Interface::run() -> void { + system.run(); } auto Interface::serialize() -> serializer { - return {}; + system.runToSave(); + return system.serialize(); } auto Interface::unserialize(serializer& s) -> bool { - return false; + return system.unserialize(s); } } diff --git a/higan/msx/interface/interface.hpp b/higan/msx/interface/interface.hpp index ce8af658..9ac06c99 100644 --- a/higan/msx/interface/interface.hpp +++ b/higan/msx/interface/interface.hpp @@ -25,7 +25,7 @@ struct ID { struct Interface : Emulator::Interface { auto information() -> Information override; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/msx/system/system.cpp b/higan/msx/system/system.cpp index a23cfff5..5a5d3a81 100644 --- a/higan/msx/system/system.cpp +++ b/higan/msx/system/system.cpp @@ -29,6 +29,13 @@ auto System::load(Emulator::Interface* interface, Model model) -> bool { auto document = BML::unserialize(information.manifest); + if(auto memory = document["system/memory(type=ROM,content=BIOS)"]) { + bios.allocate(memory["size"].natural()); + if(auto fp = platform->open(ID::System, "bios.rom", File::Read, File::Required)) { + bios.load(fp); + } else return false; + } else return false; + if(!cartridge.load()) return false; if(cartridge.region() == "NTSC") { diff --git a/higan/msx/system/system.hpp b/higan/msx/system/system.hpp index 75b07c38..ee4e4db6 100644 --- a/higan/msx/system/system.hpp +++ b/higan/msx/system/system.hpp @@ -24,6 +24,8 @@ struct System { auto serializeAll(serializer&) -> void; auto serialize(serializer&) -> void; + Emulator::Memory::Readable bios; + private: Emulator::Interface* interface = nullptr; diff --git a/higan/msx/vdp/background.cpp b/higan/msx/vdp/background.cpp new file mode 100644 index 00000000..771cc649 --- /dev/null +++ b/higan/msx/vdp/background.cpp @@ -0,0 +1,73 @@ +auto VDP::background(uint8 hoffset, uint8 voffset) -> void { + if(!io.displayEnable) { + output.color = io.colorBackground; + return; + } + + switch(io.videoMode) { + case 0: return graphics1(hoffset, voffset); +//case 1: return text1(hoffset, voffset); + case 2: return graphics2(hoffset, voffset); + case 3: return multicolor(hoffset, voffset); + default: output.color = 8; return; //medium red color to identify unimplemented modes + } +} + +auto VDP::text1(uint8 hoffset, uint8 voffset) -> void { +} + +auto VDP::graphics1(uint8 hoffset, uint8 voffset) -> void { + uint14 nameAddress; + nameAddress.bits( 0, 4) = hoffset.bits(3,7); + nameAddress.bits( 5, 9) = voffset.bits(3,7); + nameAddress.bits(10,13) = io.nameTableAddress; + + uint8 pattern = vram.read(nameAddress); + + uint14 patternAddress; + patternAddress.bits( 0, 2) = voffset.bits(0,2); + patternAddress.bits( 3,10) = pattern; + patternAddress.bits(11,13) = io.patternTableAddress; + + uint14 colorAddress; //d5 = 0 + colorAddress.bits(0, 4) = pattern.bits(3,7); + colorAddress.bits(6,13) = io.colorTableAddress; + + uint8 color = vram.read(colorAddress); + uint3 index = hoffset ^ 7; + if(!vram.read(patternAddress).bit(index)) { + output.color = color.bits(0,3); + } else { + output.color = color.bits(4,7); + } +} + +auto VDP::graphics2(uint8 hoffset, uint8 voffset) -> void { + uint14 nameAddress; + nameAddress.bits( 0, 4) = hoffset.bits(3,7); + nameAddress.bits( 5, 9) = voffset.bits(3,7); + nameAddress.bits(10,13) = io.nameTableAddress; + + uint8 pattern = vram.read(nameAddress); + + uint14 patternAddress; + patternAddress.bits(0, 2) = voffset.bits(0,2); + patternAddress.bits(3,10) = pattern; + if(voffset >= 64 && voffset <= 127) patternAddress.bit(11) = io.patternTableAddress.bit(0); + if(voffset >= 128 && voffset <= 191) patternAddress.bit(12) = io.patternTableAddress.bit(1); + uint14 colorAddress = patternAddress; + patternAddress.bit(13) = io.patternTableAddress.bit(2); + colorAddress.bit(13) = io.colorTableAddress.bit(7); + + uint8 colorMask = io.colorTableAddress.bits(0,6) << 1 | 1; + uint8 color = vram.read(colorAddress); + uint3 index = hoffset ^ 7; + if(!vram.read(patternAddress).bit(index)) { + output.color = color.bits(0,3); + } else { + output.color = color.bits(4,7); + } +} + +auto VDP::multicolor(uint8 hoffset, uint8 voffset) -> void { +} diff --git a/higan/msx/vdp/io.cpp b/higan/msx/vdp/io.cpp new file mode 100644 index 00000000..51b3d187 --- /dev/null +++ b/higan/msx/vdp/io.cpp @@ -0,0 +1,79 @@ +auto VDP::status() -> uint8 { + io.controlLatch = 0; + uint8 data = 0x00; + data.bits(0,4) = io.spriteOverflowIndex; + data.bit(5) = io.spriteCollision; + data.bit(6) = io.spriteOverflow; + data.bit(7) = io.irqLine; + io.irqLine = 0; + return data; +} + +auto VDP::data() -> uint8 { + io.controlLatch = 0; + uint8 data = io.vramLatch; + uint14 address = io.controlValue.bits(0,13)++; + io.vramLatch = vram.read(address); + return data; +} + +auto VDP::data(uint8 data) -> void { + io.controlLatch = 0; + uint14 address = io.controlValue.bits(0,13)++; + vram.write(address, data); +} + +auto VDP::control(uint8 data) -> void { + if(io.controlLatch == 0) { + io.controlLatch = 1; + io.controlValue.byte(0) = data; + return; + } else { + io.controlLatch = 0; + io.controlValue.byte(1) = data; + } + + if(!io.controlValue.bit(15)) { + if(!io.controlValue.bit(14)) { + uint14 address = io.controlValue.bits(0,13)++; + io.vramLatch = vram.read(address); + } + return; + } + + data = io.controlValue.bits(0,7); + switch(io.controlValue.bits(8,10)) { + case 0: + io.externalInput = data.bit(0); + io.videoMode.bit(1) = data.bit(1); + break; + case 1: + io.spriteZoom = data.bit(0); + io.spriteSize = data.bit(1); + io.videoMode.bit(2) = data.bit(3); + io.videoMode.bit(0) = data.bit(4); + io.irqEnable = data.bit(5); + io.displayEnable = data.bit(6); + io.ramMode = data.bit(7); + break; + case 2: + io.nameTableAddress = data.bits(0,3); + break; + case 3: + io.colorTableAddress = data.bits(0,7); + break; + case 4: + io.patternTableAddress = data.bits(0,2); + break; + case 5: + io.spriteAttributeTableAddress = data.bits(0,6); + break; + case 6: + io.spritePatternTableAddress = data.bits(0,2); + break; + case 7: + io.colorBackground = data.bits(0,3); + io.colorForeground = data.bits(4,7); + break; + } +} diff --git a/higan/msx/vdp/sprites.cpp b/higan/msx/vdp/sprites.cpp new file mode 100644 index 00000000..0767a8a1 --- /dev/null +++ b/higan/msx/vdp/sprites.cpp @@ -0,0 +1,58 @@ +auto VDP::sprite(uint8 voffset) -> void { + uint valid = 0; + uint limit = io.spriteSize ? 15 : 7; + for(uint index : range(4)) sprites[index].y = 0xd0; + + uint14 attributeAddress; + attributeAddress.bits(7,13) = io.spriteAttributeTableAddress; + for(uint index : range(32)) { + uint8 y = vram.read(attributeAddress++); + if(y == 0xd0) break; + + uint8 x = vram.read(attributeAddress++); + uint8 pattern = vram.read(attributeAddress++); + uint8 extra = vram.read(attributeAddress++); + + if(extra.bit(7)) x -= 32; + y += 1; + if(voffset < y) continue; + if(voffset > y + limit) continue; + + if(limit == 15) pattern.bits(0,1) = 0; + + if(valid == 4) { + io.spriteOverflow = true; + io.spriteOverflowIndex = index; + break; + } + + sprites[valid++] = {x, y, pattern, extra.bits(0,3)}; + } +} + +auto VDP::sprite(uint8 hoffset, uint8 voffset) -> void { + uint4 color; + uint limit = io.spriteSize ? 15 : 7; + + for(uint n : range(4)) { + auto& o = sprites[n]; + if(o.y == 0xd0) continue; + if(hoffset < o.x) continue; + if(hoffset > o.x + limit) continue; + + uint x = hoffset - o.x; + uint y = voffset - o.y; + + uint14 address; + address.bits( 0,10) = (o.pattern << 3) + (x >> 3 << 4) + (y & limit); + address.bits(11,13) = io.spritePatternTableAddress; + + uint3 index = x ^ 7; + if(vram.read(address).bit(index)) { + if(color) { io.spriteCollision = true; break; } + color = o.color; + } + } + + if(color) output.color = color; +} diff --git a/higan/msx/vdp/vdp.cpp b/higan/msx/vdp/vdp.cpp index 12c61476..61977f7b 100644 --- a/higan/msx/vdp/vdp.cpp +++ b/higan/msx/vdp/vdp.cpp @@ -1,10 +1,13 @@ #include -//228 clocks/scanline +//456 clocks/scanline namespace MSX { VDP vdp; +#include "io.cpp" +#include "background.cpp" +#include "sprites.cpp" #include "serialization.cpp" auto VDP::Enter() -> void { @@ -12,11 +15,30 @@ auto VDP::Enter() -> void { } auto VDP::main() -> void { - step(1); + if(io.vcounter < 192) { + uint8 y = io.vcounter; + sprite(y); + auto line = buffer + y * 256; + for(uint8 x : range(256)) { + background(x, y); + sprite(x, y); + line[x] = output.color; + step(1); + } + step(200); + } else { + step(456); + } + + io.vcounter++; + if(io.vcounter == 262) io.vcounter = 0; + if(io.vcounter == 0) io.irqLine = 0; + if(io.vcounter == 192) io.irqLine = 1, scheduler.exit(Scheduler::Event::Frame); } auto VDP::step(uint clocks) -> void { Thread::step(clocks); + synchronize(cpu); } auto VDP::refresh() -> void { @@ -24,7 +46,10 @@ auto VDP::refresh() -> void { } auto VDP::power() -> void { - create(VDP::Enter, system.colorburst()); + create(VDP::Enter, system.colorburst() * 2); + vram.allocate(0x4000); + + io = {}; } } diff --git a/higan/msx/vdp/vdp.hpp b/higan/msx/vdp/vdp.hpp index d8761de9..42fa2fe8 100644 --- a/higan/msx/vdp/vdp.hpp +++ b/higan/msx/vdp/vdp.hpp @@ -9,11 +9,70 @@ struct VDP : Thread { auto power() -> void; + //io.cpp + auto status() -> uint8; + auto data() -> uint8; + + auto data(uint8) -> void; + auto control(uint8) -> void; + + //background.cpp + auto background(uint8 hoffset, uint8 voffset) -> void; + auto text1(uint8 hoffset, uint8 voffset) -> void; + auto graphics1(uint8 hoffset, uint8 voffset) -> void; + auto graphics2(uint8 hoffset, uint8 voffset) -> void; + auto multicolor(uint8 hoffset, uint8 voffset) -> void; + + //sprites.cpp + auto sprite(uint8 voffset) -> void; + auto sprite(uint8 hoffset, uint8 voffset) -> void; + //serialization.cpp auto serialize(serializer&) -> void; private: uint32 buffer[256 * 192]; + Emulator::Memory::Writable vram; + + struct IO { + uint vcounter = 0; + uint hcounter = 0; + + uint1 controlLatch; + uint16 controlValue; + uint8 vramLatch; + + uint5 spriteOverflowIndex; + uint1 spriteCollision; + uint1 spriteOverflow; + uint1 irqLine; + + uint1 externalInput; + uint3 videoMode; + uint1 spriteZoom; + uint1 spriteSize; + uint1 irqEnable; + uint1 displayEnable; + uint1 ramMode = 1; //0 = 4KB; 1 = 16KB + uint4 nameTableAddress; + uint8 colorTableAddress; + uint3 patternTableAddress; + uint7 spriteAttributeTableAddress; + uint3 spritePatternTableAddress; + uint4 colorBackground; + uint4 colorForeground; + } io; + + struct Sprite { + uint8 x; + uint8 y; + uint8 pattern; + uint4 color; + } sprites[4]; + + struct Output { + uint4 color; + } output; }; extern VDP vdp; diff --git a/higan/ngp/interface/interface.cpp b/higan/ngp/interface/interface.cpp index 9947836c..b1150c56 100644 --- a/higan/ngp/interface/interface.cpp +++ b/higan/ngp/interface/interface.cpp @@ -6,7 +6,7 @@ namespace NeoGeoPocket { #include "neo-geo-pocket-color.cpp" //todo: add correct values -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::LCD; display.colors = 1; @@ -16,7 +16,7 @@ auto Interface::displays() -> vector { display.internalHeight = 240; display.aspectCorrection = 1.0; display.refreshRate = 60.0; - return {display}; + return display; } auto Interface::color(uint32 color) -> uint64 { diff --git a/higan/ngp/interface/interface.hpp b/higan/ngp/interface/interface.hpp index 506283cc..72acadbe 100644 --- a/higan/ngp/interface/interface.hpp +++ b/higan/ngp/interface/interface.hpp @@ -19,7 +19,7 @@ struct ID { }; struct Interface : Emulator::Interface { - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index 383b8e0d..021e44fe 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -7,7 +7,7 @@ Settings settings; #include "pc-engine.cpp" #include "supergrafx.cpp" -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 9; @@ -17,7 +17,7 @@ auto Interface::displays() -> vector { display.internalHeight = 240; display.aspectCorrection = 8.0 / 7.0; display.refreshRate = (system.colorburst() * 6.0) / (262.0 * 1365.0); - return {display}; + return display; } auto Interface::color(uint32 color) -> uint64 { diff --git a/higan/pce/interface/interface.hpp b/higan/pce/interface/interface.hpp index ff01287f..5d476c18 100644 --- a/higan/pce/interface/interface.hpp +++ b/higan/pce/interface/interface.hpp @@ -20,7 +20,7 @@ struct ID { }; struct Interface : Emulator::Interface { - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index d9cb8b1f..ee17c0e6 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -14,7 +14,7 @@ auto Interface::information() -> Information { return information; } -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::CRT; display.colors = 1 << 19; @@ -25,7 +25,7 @@ auto Interface::displays() -> vector { 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}; + return display; } auto Interface::color(uint32 color) -> uint64 { diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index 4cd5c067..ba5d531b 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -35,7 +35,7 @@ struct ID { struct Interface : Emulator::Interface { auto information() -> Information; - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto loaded() -> bool override; diff --git a/higan/systems/MSX.sys/bios.rom b/higan/systems/MSX.sys/bios.rom new file mode 100644 index 00000000..041fcf0f Binary files /dev/null and b/higan/systems/MSX.sys/bios.rom differ diff --git a/higan/systems/MSX.sys/manifest.bml b/higan/systems/MSX.sys/manifest.bml index e14b5a67..22522b76 100644 --- a/higan/systems/MSX.sys/manifest.bml +++ b/higan/systems/MSX.sys/manifest.bml @@ -1 +1,5 @@ system name:MSX + memory + type: ROM + size: 0x8000 + content: BIOS diff --git a/higan/target-bsnes/presentation/about.cpp b/higan/target-bsnes/presentation/about.cpp deleted file mode 100644 index ce64f5d2..00000000 --- a/higan/target-bsnes/presentation/about.cpp +++ /dev/null @@ -1,26 +0,0 @@ -auto AboutWindow::create() -> void { - setTitle({tr("About {0}", "bsnes"), " ..."}); - setBackgroundColor({255, 255, 240}); - layout.setPadding(10); - auto logo = image{Resource::Logo}; - logo.alphaBlend(0xfffff0); - canvas.setIcon(logo); - tableLayout.setFont(Font().setBold()); - tableLayout.setSize({2, 4}); - tableLayout.column(0).setSpacing(4); - tableLayout.row(0).setSpacing(2); - tableLayout.row(1).setSpacing(2); - tableLayout.row(2).setSpacing(2); - versionLabel.setText({tr("Version"), ":"}).setAlignment(1.0); - versionValue.setText(Emulator::Version); - authorLabel.setText({tr("Author"), ":"}).setAlignment(1.0); - authorValue.setText(Emulator::Author).setToolTip("ビュウ"); - licenseLabel.setText({tr("License"), ":"}).setAlignment(1.0); - licenseValue.setText(Emulator::License); - websiteLabel.setText({tr("Website"), ":"}).setAlignment(1.0); - websiteValue.setText(Emulator::Website); - - setResizable(false); - setSize(layout.minimumSize()); - setDismissable(); -} diff --git a/higan/target-bsnes/presentation/presentation.cpp b/higan/target-bsnes/presentation/presentation.cpp index 2d932d58..c50a6eaa 100644 --- a/higan/target-bsnes/presentation/presentation.cpp +++ b/higan/target-bsnes/presentation/presentation.cpp @@ -1,6 +1,4 @@ #include "../bsnes.hpp" -#include "about.cpp" -AboutWindow aboutWindow; Presentation presentation; auto Presentation::create() -> void { @@ -137,7 +135,14 @@ auto Presentation::create() -> void { invoke("https://doc.byuu.org/bsnes/"); }); about.setIcon(Icon::Prompt::Question).setText({tr("About"), " ..."}).onActivate([&] { - aboutWindow.setCentered(*this).setVisible().setFocused(); + AboutDialog() + .setLogo(Resource::Logo) + .setVersion(Emulator::Version) + .setAuthor("byuu") + .setLicense("GPLv3") + .setWebsite("https://byuu.org/") + .setParent(*this) + .show(); }); viewport.setDroppable().onDrop([&](vector locations) { diff --git a/higan/target-bsnes/presentation/presentation.hpp b/higan/target-bsnes/presentation/presentation.hpp index ba398c2a..e8fbba5d 100644 --- a/higan/target-bsnes/presentation/presentation.hpp +++ b/higan/target-bsnes/presentation/presentation.hpp @@ -1,23 +1,3 @@ -struct AboutWindow : Window { - Application::Namespace tr{"AboutWindow"}; - auto create() -> void; - - VerticalLayout layout{this}; - Canvas canvas{&layout, Size{400, 85}, 0}; - TableLayout tableLayout{&layout, Size{~0, 0}}; - Label versionLabel{&tableLayout, Size{~0, 0}}; - Label versionValue{&tableLayout, Size{~0, 0}}; - // - Label authorLabel{&tableLayout, Size{~0, 0}}; - Label authorValue{&tableLayout, Size{~0, 0}}; - // - Label licenseLabel{&tableLayout, Size{~0, 0}}; - Label licenseValue{&tableLayout, Size{~0, 0}}; - // - Label websiteLabel{&tableLayout, Size{~0, 0}}; - Label websiteValue{&tableLayout, Size{~0, 0}}; -}; - struct Presentation : Window { Application::Namespace tr{"Presentation"}; auto create() -> void; @@ -117,5 +97,4 @@ struct Presentation : Window { Label spacerRight{&statusLayout, Size{8, ~0}, 0}; }; -extern AboutWindow aboutWindow; extern Presentation presentation; diff --git a/higan/target-bsnes/program/platform.cpp b/higan/target-bsnes/program/platform.cpp index e7fbc5e1..090fb299 100644 --- a/higan/target-bsnes/program/platform.cpp +++ b/higan/target-bsnes/program/platform.cpp @@ -207,7 +207,7 @@ auto Program::load(uint id, string name, string type, vector options) -> return {}; } -auto Program::videoRefresh(uint display, const uint32* data, uint pitch, uint width, uint height) -> void { +auto Program::videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void { uint32_t* output; uint length; @@ -255,7 +255,7 @@ auto Program::videoRefresh(uint display, const uint32* data, uint pitch, uint wi } } -auto Program::audioSample(const double* samples, uint channels) -> void { +auto Program::audioFrame(const double* samples, uint channels) -> void { audio.output(samples); } diff --git a/higan/target-bsnes/program/program.cpp b/higan/target-bsnes/program/program.cpp index 2f696ae7..fedb52fd 100644 --- a/higan/target-bsnes/program/program.cpp +++ b/higan/target-bsnes/program/program.cpp @@ -18,7 +18,6 @@ auto Program::create() -> void { presentation.create(); presentation.setVisible(); - aboutWindow.create(); settingsWindow.create(); videoSettings.create(); diff --git a/higan/target-bsnes/program/program.hpp b/higan/target-bsnes/program/program.hpp index 98281d54..ad45f7cf 100644 --- a/higan/target-bsnes/program/program.hpp +++ b/higan/target-bsnes/program/program.hpp @@ -9,8 +9,8 @@ struct Program : Lock, Emulator::Platform { //platform.cpp auto open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file override; auto load(uint id, string name, string type, vector options = {}) -> Emulator::Platform::Load 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 videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void override; + auto audioFrame(const double* samples, uint channels) -> void override; auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; diff --git a/higan/target-higan/presentation/about.cpp b/higan/target-higan/presentation/about.cpp deleted file mode 100644 index 1bc59429..00000000 --- a/higan/target-higan/presentation/about.cpp +++ /dev/null @@ -1,27 +0,0 @@ -AboutWindow::AboutWindow() { - aboutWindow = this; - - setTitle("About higan ..."); - setBackgroundColor({255, 255, 240}); - layout.setPadding(10); - auto logo = image{Resource::Logo}; - logo.alphaBlend(0xfffff0); - canvas.setIcon(logo); - informationLeft.setFont(Font().setBold()).setAlignment(1.0).setText({ - "Version:\n", - "Author:\n", - "License:\n", - "Website:" - }); - informationRight.setFont(Font().setBold()).setAlignment(0.0).setText({ - Emulator::Version, "\n", - Emulator::Author, "\n", - Emulator::License, "\n", - Emulator::Website - }); - - setResizable(false); - setSize(layout.minimumSize()); - setCentered(); - setDismissable(); -} diff --git a/higan/target-higan/presentation/presentation.cpp b/higan/target-higan/presentation/presentation.cpp index 26355f51..45a83bee 100644 --- a/higan/target-higan/presentation/presentation.cpp +++ b/higan/target-higan/presentation/presentation.cpp @@ -1,6 +1,4 @@ #include "../higan.hpp" -#include "about.cpp" -unique_pointer aboutWindow; unique_pointer presentation; Presentation::Presentation() { @@ -131,7 +129,14 @@ Presentation::Presentation() { invoke("https://doc.byuu.org/higan/credits/"); }); about.setIcon(Icon::Prompt::Question).setText("About ...").onActivate([&] { - aboutWindow->setCentered(*this).setVisible().setFocused(); + AboutDialog() + .setLogo(Resource::Logo) + .setVersion(Emulator::Version) + .setAuthor("byuu") + .setLicense("GPLv3") + .setWebsite("https://byuu.org/") + .setParent(*this) + .show(); }); viewport.setDroppable().onDrop([&](vector locations) { @@ -345,7 +350,7 @@ auto Presentation::resizeViewport() -> void { uint height = 240; if(emulator) { - auto display = emulator->displays().first(); + auto display = emulator->display(); width = display.width; height = display.height; if(settings["View/AspectCorrection"].boolean()) width *= display.aspectCorrection; @@ -412,7 +417,7 @@ auto Presentation::resizeWindow() -> void { uint statusHeight = settings["View/StatusBar"].boolean() ? StatusHeight : 0; if(emulator) { - auto display = emulator->displays().first(); + auto display = emulator->display(); width = display.width; height = display.height; if(settings["View/AspectCorrection"].boolean()) width *= display.aspectCorrection; diff --git a/higan/target-higan/presentation/presentation.hpp b/higan/target-higan/presentation/presentation.hpp index c4392c11..b190e60d 100644 --- a/higan/target-higan/presentation/presentation.hpp +++ b/higan/target-higan/presentation/presentation.hpp @@ -1,13 +1,3 @@ -struct AboutWindow : Window { - AboutWindow(); - - VerticalLayout layout{this}; - Canvas canvas{&layout, Size{399, 95}, 15}; - HorizontalLayout informationLayout{&layout, Size{~0, 0}}; - Label informationLeft{&informationLayout, Size{~0, 0}, 3}; - Label informationRight{&informationLayout, Size{~0, 0}}; -}; - struct Presentation : Window { enum : uint { StatusHeight = 24 }; @@ -104,5 +94,4 @@ struct Presentation : Window { Label spacerRight{&statusLayout, Size{8, ~0}, 0}; }; -extern unique_pointer aboutWindow; extern unique_pointer presentation; diff --git a/higan/target-higan/program/platform.cpp b/higan/target-higan/program/platform.cpp index dd58a24a..9119bad0 100644 --- a/higan/target-higan/program/platform.cpp +++ b/higan/target-higan/program/platform.cpp @@ -50,14 +50,14 @@ auto Program::load(uint id, string name, string type, vector options) -> return {pathID, option}; } -auto Program::videoRefresh(uint displayID, const uint32* data, uint pitch, uint width, uint height) -> void { +auto Program::videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void { uint32_t* output; uint length; pitch >>= 2; if(!settings["View/Overscan"].boolean()) { - auto display = emulator->displays()[displayID]; + auto display = emulator->display(); if(display.type == Emulator::Interface::Display::Type::CRT) { uint overscanHorizontal = settings["View/Overscan/Horizontal"].natural(); uint overscanVertical = settings["View/Overscan/Vertical"].natural(); @@ -92,7 +92,7 @@ auto Program::videoRefresh(uint displayID, const uint32* data, uint pitch, uint } } -auto Program::audioSample(const double* samples, uint channels) -> void { +auto Program::audioFrame(const double* samples, uint channels) -> void { if(channels == 1) { double stereo[] = {samples[0], samples[0]}; audio->output(stereo); diff --git a/higan/target-higan/program/program.cpp b/higan/target-higan/program/program.cpp index 5635b4cf..ddaeca4e 100644 --- a/higan/target-higan/program/program.cpp +++ b/higan/target-higan/program/program.cpp @@ -103,7 +103,6 @@ Program::Program(Arguments arguments) { new SettingsManager; new CheatDatabase; new ToolsManager; - new AboutWindow; updateVideoShader(); updateAudioDriver(); diff --git a/higan/target-higan/program/program.hpp b/higan/target-higan/program/program.hpp index 67ff8d39..998146aa 100644 --- a/higan/target-higan/program/program.hpp +++ b/higan/target-higan/program/program.hpp @@ -8,8 +8,8 @@ struct Program : Emulator::Platform { auto path(uint id) -> string 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, vector options = {}) -> Emulator::Platform::Load 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 videoFrame(const uint32* data, uint pitch, uint width, uint height) -> void override; + auto audioFrame(const double* samples, uint channels) -> void override; auto inputPoll(uint port, uint device, uint input) -> int16 override; auto inputRumble(uint port, uint device, uint input, bool enable) -> void override; auto dipSettings(Markup::Node node) -> uint override; diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index abb35834..abaeb33c 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -7,7 +7,7 @@ Settings settings; #include "wonderswan-color.cpp" #include "pocket-challenge-v2.cpp" -auto Interface::displays() -> vector { +auto Interface::display() -> Display { Display display; display.type = Display::Type::LCD; display.colors = 1 << 12; @@ -21,7 +21,7 @@ auto Interface::displays() -> vector { swap(display.width, display.height); swap(display.internalWidth, display.internalHeight); } - return {display}; + return display; } //todo: the WonderSwan and PocketChallengeV2 interfaces should be generating grayscale shades diff --git a/higan/ws/interface/interface.hpp b/higan/ws/interface/interface.hpp index aa467858..a16820ce 100644 --- a/higan/ws/interface/interface.hpp +++ b/higan/ws/interface/interface.hpp @@ -20,7 +20,7 @@ struct ID { }; struct Interface : Emulator::Interface { - auto displays() -> vector override; + auto display() -> Display override; auto color(uint32 color) -> uint64 override; auto ports() -> vector override; diff --git a/hiro/extension/message-dialog.cpp b/hiro/extension/message-dialog.cpp index fe0caa01..ebfcd7a0 100644 --- a/hiro/extension/message-dialog.cpp +++ b/hiro/extension/message-dialog.cpp @@ -49,7 +49,9 @@ auto MessageDialog::_run() -> string { Window window; VerticalLayout layout{&window}; HorizontalLayout messageLayout{&layout, Size{~0, 0}, 5}; - Canvas messageIcon{&messageLayout, Size{16, 16}, 5}; + VerticalLayout messageIconLayout{&messageLayout, Size{16, ~0}, 5}; + Canvas messageIcon{&messageIconLayout, Size{16, 16}, 0}; + Widget messageIconSpacer{&messageIconLayout, Size{16, ~0}}; Label messageText{&messageLayout, Size{~0, 0}}; HorizontalLayout controlLayout{&layout, Size{~0, 0}}; Widget controlSpacer{&controlLayout, Size{~0, 0}}; diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp index 9a300b8a..ec28937d 100644 --- a/icarus/icarus.cpp +++ b/icarus/icarus.cpp @@ -131,22 +131,22 @@ auto nall::main(Arguments arguments) -> void { new ImportDialog; new ErrorDialog; - if constexpr(platform() == Platform::MacOS) { - Application::Cocoa::onAbout([&] { - MessageDialog().setTitle("About icarus").setText({ - "icarus\n\n" - "Author: byuu\n" - "License: GPLv3\n" - "Website: https://byuu.org/\n" - }).information(); - }); - Application::Cocoa::onPreferences([&] { - scanDialog->settingsButton.doActivate(); - }); - Application::Cocoa::onQuit([&] { - Application::quit(); - }); - } + #if defined(PLATFORM_MACOS) + Application::Cocoa::onAbout([&] { + MessageDialog().setTitle("About icarus").setText({ + "icarus\n\n" + "Author: byuu\n" + "License: GPLv3\n" + "Website: https://byuu.org/\n" + }).information(); + }); + Application::Cocoa::onPreferences([&] { + scanDialog->settingsButton.doActivate(); + }); + Application::Cocoa::onQuit([&] { + Application::quit(); + }); + #endif scanDialog->show(); Application::run();