From 79be6f2355de6ae41390a98a5ee11548a4f31c5a Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 3 Jan 2019 21:05:20 +1100 Subject: [PATCH] Update to v106r70 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: Changelog: - Interface::displays() -> vector → Interface::display() -> Display - , ...) → (...) - (...) → (...) - higan, icarus: use AboutDialog class instead of ad-hoc implementations - about dialog is now modal, but now has a clickable website URL - icarus: reverted if constexpr for now - MSX: implemented basic CPU, VDP support I took out the multiple displays support thing because it was never really implemented fully (Emulator::Video and the GUIs both ignored it) or used anyway. If it ends up necessary in the future, I'll worry about it then. There's enough MSX emulation now to run Mr. Do! without sound or input. I'm shipping higan with C-BIOS 0.29a, although it likely won't be good enough in the future (eg it can't do BASIC, floppy disk, or cassette loading.) I have keyboard and (not working) AY-3-8910 support in a different branch, so that won't take too long to implement. Main problem is naming all the darned keyboard keys. I think I need to change settings.bml's input mapping lines so that the key names are values instead of node names, so that any characters can appear inside of them. It turns out my MSX set uses .rom for the file extensions ... gods. So, icarus can't really import them like this. I may have to re-design icarus' importer to stop caring about the file extension and instead ask you what kind of games you are importing. There's no way icarus can heuristically guess what systems the images belong to, because many systems don't have any standardized magic bytes. I'm struggling with where to put SG-1000, SC-3000, ColecoVision, Coleco Adam stuff. I think they need to be split to two separate higan subfolders (sg and cv, most likely ...) The MS/GG share a very customized and extended VDP that the other systems don't have. The Sega and Coleco older hardware share the same TMS9918 as the MSX, yet have very different memory maps and peripherals that I don't want to mix together. Especially if we start getting into the computer-variants more. --- higan/emulator/audio/audio.cpp | 2 +- higan/emulator/emulator.hpp | 2 +- higan/emulator/interface.hpp | 2 +- higan/emulator/platform.hpp | 4 +- higan/emulator/video/video.cpp | 4 +- higan/fc/interface/interface.cpp | 4 +- higan/fc/interface/interface.hpp | 2 +- higan/gb/interface/interface.cpp | 4 +- higan/gb/interface/interface.hpp | 2 +- higan/gba/interface/interface.cpp | 4 +- higan/gba/interface/interface.hpp | 2 +- higan/md/interface/interface.cpp | 4 +- higan/md/interface/interface.hpp | 2 +- higan/ms/interface/colecovision.cpp | 4 +- higan/ms/interface/game-gear.cpp | 4 +- higan/ms/interface/interface.hpp | 10 +-- higan/ms/interface/master-system.cpp | 4 +- higan/ms/interface/sc-3000.cpp | 4 +- higan/ms/interface/sg-1000.cpp | 4 +- higan/ms/vdp/background.cpp | 7 +- higan/msx/cartridge/cartridge.cpp | 7 ++ higan/msx/cartridge/cartridge.hpp | 3 + higan/msx/cpu/cpu.cpp | 16 ++++ higan/msx/cpu/cpu.hpp | 9 ++ higan/msx/cpu/memory.cpp | 52 ++++++++++++ higan/msx/interface/interface.cpp | 41 ++++++--- higan/msx/interface/interface.hpp | 2 +- higan/msx/system/system.cpp | 7 ++ higan/msx/system/system.hpp | 2 + higan/msx/vdp/background.cpp | 73 ++++++++++++++++ higan/msx/vdp/io.cpp | 79 ++++++++++++++++++ higan/msx/vdp/sprites.cpp | 58 +++++++++++++ higan/msx/vdp/vdp.cpp | 31 ++++++- higan/msx/vdp/vdp.hpp | 59 +++++++++++++ higan/ngp/interface/interface.cpp | 4 +- higan/ngp/interface/interface.hpp | 2 +- higan/pce/interface/interface.cpp | 4 +- higan/pce/interface/interface.hpp | 2 +- higan/sfc/interface/interface.cpp | 4 +- higan/sfc/interface/interface.hpp | 2 +- higan/systems/MSX.sys/bios.rom | Bin 0 -> 32768 bytes higan/systems/MSX.sys/manifest.bml | 4 + higan/target-bsnes/presentation/about.cpp | 26 ------ .../presentation/presentation.cpp | 11 ++- .../presentation/presentation.hpp | 21 ----- higan/target-bsnes/program/platform.cpp | 4 +- higan/target-bsnes/program/program.cpp | 1 - higan/target-bsnes/program/program.hpp | 4 +- higan/target-higan/presentation/about.cpp | 27 ------ .../presentation/presentation.cpp | 15 ++-- .../presentation/presentation.hpp | 11 --- higan/target-higan/program/platform.cpp | 6 +- higan/target-higan/program/program.cpp | 1 - higan/target-higan/program/program.hpp | 4 +- higan/ws/interface/interface.cpp | 4 +- higan/ws/interface/interface.hpp | 2 +- hiro/extension/message-dialog.cpp | 4 +- icarus/icarus.cpp | 32 +++---- 58 files changed, 522 insertions(+), 187 deletions(-) create mode 100644 higan/msx/vdp/background.cpp create mode 100644 higan/msx/vdp/io.cpp create mode 100644 higan/msx/vdp/sprites.cpp create mode 100644 higan/systems/MSX.sys/bios.rom delete mode 100644 higan/target-bsnes/presentation/about.cpp delete mode 100644 higan/target-higan/presentation/about.cpp 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 0000000000000000000000000000000000000000..041fcf0fe093f4f5829256e6ba778a37d2d92b3e GIT binary patch literal 32768 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 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();