From 1fdd0582fcc7df850f3ff341c913e28e269c27c7 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 17 Jan 2016 19:59:25 +1100 Subject: [PATCH] Update to v097 release. byuu says: This release features improvements to all emulation cores, but most substantially for the Game Boy core. All of blargg's test ROMs that pass in gambatte now either pass in higan, or are off by 1-2 clocks (the actual behaviors are fully emulated.) I consider the Game Boy core to now be fairly accurate, but there's still more improvements to be had. Also, what's sure to be a major feature for some: higan now has full support for loading and playing ordinary ROM files, whether they have copier headers, weird extensions, or are inside compressed archives. You can load these games from the command-line, from the main Library menu (via Load ROM Image), or via drag-and-drop on the main higan window. Of course, fans of game folders and the library need not worry: that's still there as well. Also new, you can drop the (uncompressed) Game Boy Advance BIOS onto the higan main window to install it into the correct location with the correct file name. Lastly, this release technically restores Mac OS X support. However, it's still not very stable, so I have decided against releasing binaries at this time. I'd rather not rush this and leave a bad first impression for OS X users. Changelog (since v096): - higan: project source code hierarchy restructured; icarus directly integrated - higan: added software emulation of color-bleed, LCD-refresh, scanlines, interlacing - icarus: you can now load and import ROM files/archives from the main higan menu - NES: fixed manifest parsing for board mirroring and VRC pinouts - SNES: fixed manifest for Star Ocean - SNES: fixed manifest for Rockman X2,X3 - GB: enabling LCD restarts frame - GB: emulated extra OAM STAT IRQ quirk required for GBVideoPlayer (Shonumi) - GB: VBK, BGPI, OBPI are readable - GB: OAM DMA happens inside PPU core instead of CPU core - GB: fixed APU length and sweep operations - GB: emulated wave RAM quirks when accessing while channel is enabled - GB: improved timings of several CPU opcodes (gekkio) - GB: improved timings of OAM DMA refresh (gekkio) - GB: CPU uses open collector logic; return 0xFF for unmapped memory (gekkio) - GBA: fixed sequencer enable flags; fixes audio in Zelda - Minish Cap (Jonas Quinn) - GBA: fixed disassembler masking error (Lioncash) - hiro: Cocoa support added; higan can now be compiled on Mac OS X 10.7+ - nall: improved program path detection on Windows - higan/Windows: moved configuration data from %appdata% to %localappdata% - higan/Linux,BSD: moved configuration data from ~/.config/higan to ~/.local/higan --- higan/emulator/emulator.hpp | 2 +- higan/gb/apu/apu.cpp | 50 ++++++++++--------- higan/gb/apu/apu.hpp | 10 ++-- .../master.cpp => sequencer/sequencer.cpp} | 10 ++-- .../master.hpp => sequencer/sequencer.hpp} | 2 +- higan/gb/apu/serialization.cpp | 8 +-- higan/gb/apu/wave/wave.cpp | 35 ++++++++++++- higan/gb/apu/wave/wave.hpp | 1 + higan/gb/cpu/cpu.cpp | 5 -- higan/gb/cpu/cpu.hpp | 6 --- higan/gb/cpu/memory.cpp | 4 -- higan/gb/cpu/mmio.cpp | 7 --- higan/gb/cpu/serialization.cpp | 4 -- higan/gb/cpu/timing.cpp | 15 ------ higan/gb/ppu/mmio.cpp | 29 +++++++++-- higan/gb/ppu/ppu.cpp | 22 ++++++++ higan/gb/ppu/ppu.hpp | 5 ++ higan/gb/ppu/serialization.cpp | 4 ++ .../configuration/configuration.cpp | 5 +- .../presentation/presentation.cpp | 28 +++++------ hiro/cocoa/widget/text-edit.cpp | 2 +- icarus/icarus.cpp | 2 +- 22 files changed, 150 insertions(+), 106 deletions(-) rename higan/gb/apu/{master/master.cpp => sequencer/sequencer.cpp} (93%) rename higan/gb/apu/{master/master.hpp => sequencer/sequencer.hpp} (96%) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 7d799cc4..3664b3d9 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "096.08"; + static const string Version = "097"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gb/apu/apu.cpp b/higan/gb/apu/apu.cpp index a983205e..da32a507 100644 --- a/higan/gb/apu/apu.cpp +++ b/higan/gb/apu/apu.cpp @@ -2,11 +2,11 @@ namespace GameBoy { +#include "sequencer/sequencer.cpp" #include "square1/square1.cpp" #include "square2/square2.cpp" #include "wave/wave.cpp" #include "noise/noise.cpp" -#include "master/master.cpp" #include "serialization.cpp" APU apu; @@ -20,7 +20,19 @@ auto APU::main() -> void { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } - if(stage == 0) { //512hz + square1.run(); + square2.run(); + wave.run(); + noise.run(); + sequencer.run(); + + hipass(sequencer.center, sequencer.centerBias); + hipass(sequencer.left, sequencer.leftBias); + hipass(sequencer.right, sequencer.rightBias); + + interface->audioSample(sequencer.left, sequencer.right); + + if(cycle == 0) { //512hz if(phase == 0 || phase == 2 || phase == 4 || phase == 6) { //256hz square1.clockLength(); square2.clockLength(); @@ -37,25 +49,16 @@ auto APU::main() -> void { } phase++; } - stage++; - - square1.run(); - square2.run(); - wave.run(); - noise.run(); - master.run(); - - hipass(master.center, master.centerBias); - hipass(master.left, master.leftBias); - hipass(master.right, master.rightBias); - - interface->audioSample(master.left, master.right); + cycle++; clock += cpu.frequency; - if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(scheduler.active_thread = cpu.thread); + if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) { + co_switch(scheduler.active_thread = cpu.thread); + } } } +//filter to remove DC bias auto APU::hipass(int16& sample, int64& bias) -> void { bias += ((((int64)sample << 16) - (bias >> 16)) * 57593) >> 16; sample = sclamp<16>(sample - (bias >> 32)); @@ -65,14 +68,13 @@ auto APU::power() -> void { create(Main, 2 * 1024 * 1024); for(uint n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this; - stage = 0; - phase = 0; - square1.power(); square2.power(); wave.power(); noise.power(); - master.power(); + sequencer.power(); + phase = 0; + cycle = 0; LinearFeedbackShiftRegisterGenerator r; for(auto& n : wave.pattern) n = r(); @@ -83,16 +85,16 @@ auto APU::mmio_read(uint16 addr) -> uint8 { if(addr >= 0xff15 && addr <= 0xff19) return square2.read(addr); if(addr >= 0xff1a && addr <= 0xff1e) return wave.read(addr); if(addr >= 0xff1f && addr <= 0xff23) return noise.read(addr); - if(addr >= 0xff24 && addr <= 0xff26) return master.read(addr); + if(addr >= 0xff24 && addr <= 0xff26) return sequencer.read(addr); if(addr >= 0xff30 && addr <= 0xff3f) return wave.read(addr); return 0xff; } auto APU::mmio_write(uint16 addr, uint8 data) -> void { - if(!master.enable) { + if(!sequencer.enable) { bool valid = addr == 0xff26; //NR52 if(!system.cgb()) { - //NRx1 length is writable only on DMG/SGB; not on CGB + //NRx1 length is writable only on DMG,SGB; not on CGB if(addr == 0xff11) valid = true, data &= 0x3f; //NR11; duty is not writable (remains 0) if(addr == 0xff16) valid = true, data &= 0x3f; //NR21; duty is not writable (remains 0) if(addr == 0xff1b) valid = true; //NR31 @@ -105,7 +107,7 @@ auto APU::mmio_write(uint16 addr, uint8 data) -> void { if(addr >= 0xff15 && addr <= 0xff19) return square2.write(addr, data); if(addr >= 0xff1a && addr <= 0xff1e) return wave.write(addr, data); if(addr >= 0xff1f && addr <= 0xff23) return noise.write(addr, data); - if(addr >= 0xff24 && addr <= 0xff26) return master.write(addr, data); + if(addr >= 0xff24 && addr <= 0xff26) return sequencer.write(addr, data); if(addr >= 0xff30 && addr <= 0xff3f) return wave.write(addr, data); } diff --git a/higan/gb/apu/apu.hpp b/higan/gb/apu/apu.hpp index f30a6d15..8a20d2f4 100644 --- a/higan/gb/apu/apu.hpp +++ b/higan/gb/apu/apu.hpp @@ -13,16 +13,16 @@ struct APU : Thread, MMIO { #include "square2/square2.hpp" #include "wave/wave.hpp" #include "noise/noise.hpp" - #include "master/master.hpp" - - uint12 stage; - uint3 phase; + #include "sequencer/sequencer.hpp" Square1 square1; Square2 square2; Wave wave; Noise noise; - Master master; + Sequencer sequencer; + + uint3 phase; //high 3-bits of clock counter + uint12 cycle; //low 12-bits of clock counter }; extern APU apu; diff --git a/higan/gb/apu/master/master.cpp b/higan/gb/apu/sequencer/sequencer.cpp similarity index 93% rename from higan/gb/apu/master/master.cpp rename to higan/gb/apu/sequencer/sequencer.cpp index 3feb4ec6..907b3087 100644 --- a/higan/gb/apu/master/master.cpp +++ b/higan/gb/apu/sequencer/sequencer.cpp @@ -1,4 +1,4 @@ -auto APU::Master::run() -> void { +auto APU::Sequencer::run() -> void { if(enable == false) { center = 0; left = 0; @@ -39,7 +39,7 @@ auto APU::Master::run() -> void { right >>= 1; } -auto APU::Master::read(uint16 addr) -> uint8 { +auto APU::Sequencer::read(uint16 addr) -> uint8 { if(addr == 0xff24) { //NR50 return leftEnable << 7 | leftVolume << 4 | rightEnable << 3 | rightVolume; } @@ -66,7 +66,7 @@ auto APU::Master::read(uint16 addr) -> uint8 { return 0xff; } -auto APU::Master::write(uint16 addr, uint8 data) -> void { +auto APU::Sequencer::write(uint16 addr, uint8 data) -> void { if(addr == 0xff24) { //NR50 leftEnable = (uint1)(data >> 7); leftVolume = (uint3)(data >> 4); @@ -103,7 +103,7 @@ auto APU::Master::write(uint16 addr, uint8 data) -> void { } } -auto APU::Master::power() -> void { +auto APU::Sequencer::power() -> void { leftEnable = 0; leftVolume = 0; rightEnable = 0; @@ -127,7 +127,7 @@ auto APU::Master::power() -> void { rightBias = 0; } -auto APU::Master::serialize(serializer& s) -> void { +auto APU::Sequencer::serialize(serializer& s) -> void { s.integer(leftEnable); s.integer(leftVolume); s.integer(rightEnable); diff --git a/higan/gb/apu/master/master.hpp b/higan/gb/apu/sequencer/sequencer.hpp similarity index 96% rename from higan/gb/apu/master/master.hpp rename to higan/gb/apu/sequencer/sequencer.hpp index 0c861610..2dd64c9b 100644 --- a/higan/gb/apu/master/master.hpp +++ b/higan/gb/apu/sequencer/sequencer.hpp @@ -1,4 +1,4 @@ -struct Master { +struct Sequencer { auto run() -> void; auto read(uint16 addr) -> uint8; auto write(uint16 addr, uint8 data) -> void; diff --git a/higan/gb/apu/serialization.cpp b/higan/gb/apu/serialization.cpp index cfb2327d..1ae311aa 100644 --- a/higan/gb/apu/serialization.cpp +++ b/higan/gb/apu/serialization.cpp @@ -1,12 +1,12 @@ auto APU::serialize(serializer& s) -> void { Thread::serialize(s); - s.integer(stage); - s.integer(phase); - square1.serialize(s); square2.serialize(s); wave.serialize(s); noise.serialize(s); - master.serialize(s); + sequencer.serialize(s); + + s.integer(phase); + s.integer(cycle); } diff --git a/higan/gb/apu/wave/wave.cpp b/higan/gb/apu/wave/wave.cpp index 20f623f4..edb4e9f7 100644 --- a/higan/gb/apu/wave/wave.cpp +++ b/higan/gb/apu/wave/wave.cpp @@ -3,9 +3,12 @@ auto APU::Wave::getPattern(uint5 offset) const -> uint4 { } auto APU::Wave::run() -> void { + if(patternHold) patternHold--; + if(period && --period == 0) { period = 1 * (2048 - frequency); patternSample = getPattern(++patternOffset); + patternHold = 1; } static const uint shift[] = {4, 0, 1, 2}; //0%, 100%, 50%, 25% @@ -43,7 +46,12 @@ auto APU::Wave::read(uint16 addr) -> uint8 { } if(addr >= 0xff30 && addr <= 0xff3f) { - return pattern[addr & 15]; + if(enable) { + if(!system.cgb() && !patternHold) return 0xff; + return pattern[patternOffset >> 1]; + } else { + return pattern[addr & 15]; + } } return 0xff; @@ -77,9 +85,25 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void { frequency = ((data & 7) << 8) | (frequency & 0x00ff); if(initialize) { + if(!system.cgb() && patternHold) { + //DMG,SGB trigger while channel is being read corrupts wave RAM + if((patternOffset >> 1) <= 3) { + //if current pattern is with 0-3; only byte 0 is corrupted + pattern[0] = pattern[patternOffset >> 1]; + } else { + //if current pattern is within 4-15; pattern&~3 is copied to pattern[0-3] + pattern[0] = pattern[((patternOffset >> 1) & ~3) + 0]; + pattern[1] = pattern[((patternOffset >> 1) & ~3) + 1]; + pattern[2] = pattern[((patternOffset >> 1) & ~3) + 2]; + pattern[3] = pattern[((patternOffset >> 1) & ~3) + 3]; + } + } + enable = dacEnable; period = 1 * (2048 - frequency); patternOffset = 0; + patternSample = 0; + patternHold = 0; if(!length) { length = 256; @@ -89,7 +113,12 @@ auto APU::Wave::write(uint16 addr, uint8 data) -> void { } if(addr >= 0xff30 && addr <= 0xff3f) { - pattern[addr & 15] = data; + if(enable) { + if(!system.cgb() && !patternHold) return; + pattern[patternOffset >> 1] = data; + } else { + pattern[addr & 15] = data; + } } } @@ -105,6 +134,7 @@ auto APU::Wave::power(bool initializeLength) -> void { period = 0; patternOffset = 0; patternSample = 0; + patternHold = 0; if(initializeLength) length = 256; } @@ -123,4 +153,5 @@ auto APU::Wave::serialize(serializer& s) -> void { s.integer(period); s.integer(patternOffset); s.integer(patternSample); + s.integer(patternHold); } diff --git a/higan/gb/apu/wave/wave.hpp b/higan/gb/apu/wave/wave.hpp index 732c6cc6..5b4cd7e1 100644 --- a/higan/gb/apu/wave/wave.hpp +++ b/higan/gb/apu/wave/wave.hpp @@ -22,4 +22,5 @@ struct Wave { uint period; uint5 patternOffset; uint4 patternSample; + uint patternHold; }; diff --git a/higan/gb/cpu/cpu.cpp b/higan/gb/cpu/cpu.cpp index 3c2289d4..4cfab005 100644 --- a/higan/gb/cpu/cpu.cpp +++ b/higan/gb/cpu/cpu.cpp @@ -117,7 +117,6 @@ auto CPU::power() -> void { bus.mmio[0xff06] = this; //TMA bus.mmio[0xff07] = this; //TAC bus.mmio[0xff0f] = this; //IF - bus.mmio[0xff46] = this; //DMA bus.mmio[0xffff] = this; //IE if(system.cgb()) { @@ -199,10 +198,6 @@ auto CPU::power() -> void { status.interrupt_enable_timer = 0; status.interrupt_enable_stat = 0; status.interrupt_enable_vblank = 0; - - oamdma.active = false; - oamdma.clock = 0; - oamdma.bank = 0; } } diff --git a/higan/gb/cpu/cpu.hpp b/higan/gb/cpu/cpu.hpp index 02fdd800..50ed05c1 100644 --- a/higan/gb/cpu/cpu.hpp +++ b/higan/gb/cpu/cpu.hpp @@ -107,12 +107,6 @@ struct CPU : Processor::LR35902, Thread, MMIO { bool interrupt_enable_vblank; } status; - struct OAMDMA { - bool active; - uint clock; - uint8 bank; - } oamdma; - uint8 wram[32768]; //GB=8192, GBC=32768 uint8 hram[128]; }; diff --git a/higan/gb/cpu/memory.cpp b/higan/gb/cpu/memory.cpp index 6b743415..642876a0 100644 --- a/higan/gb/cpu/memory.cpp +++ b/higan/gb/cpu/memory.cpp @@ -6,16 +6,12 @@ auto CPU::op_io() -> void { auto CPU::op_read(uint16 addr) -> uint8 { cycle_edge(); add_clocks(4); - //OAM is inaccessible during OAMDMA transfer - if(oamdma.active && oamdma.clock >= 8 && addr >= 0xfe00 && addr <= 0xfe9f) return 0xff; return bus.read(addr); } auto CPU::op_write(uint16 addr, uint8 data) -> void { cycle_edge(); add_clocks(4); - //OAM is inaccessible during OAMDMA transfer - if(oamdma.active && oamdma.clock >= 8 && addr >= 0xfe00 && addr <= 0xfe9f) return; bus.write(addr, data); } diff --git a/higan/gb/cpu/mmio.cpp b/higan/gb/cpu/mmio.cpp index 104e169e..f5cdb6d9 100644 --- a/higan/gb/cpu/mmio.cpp +++ b/higan/gb/cpu/mmio.cpp @@ -186,13 +186,6 @@ auto CPU::mmio_write(uint16 addr, uint8 data) -> void { return; } - if(addr == 0xff46) { //DMA - oamdma.active = true; - oamdma.clock = 0; - oamdma.bank = data; - return; - } - if(addr == 0xff4d) { //KEY1 status.speed_switch = data & 0x01; return; diff --git a/higan/gb/cpu/serialization.cpp b/higan/gb/cpu/serialization.cpp index bc13028d..33ecf448 100644 --- a/higan/gb/cpu/serialization.cpp +++ b/higan/gb/cpu/serialization.cpp @@ -53,8 +53,4 @@ auto CPU::serialize(serializer& s) -> void { s.integer(status.interrupt_enable_timer); s.integer(status.interrupt_enable_stat); s.integer(status.interrupt_enable_vblank); - - s.integer(oamdma.active); - s.integer(oamdma.clock); - s.integer(oamdma.bank); } diff --git a/higan/gb/cpu/timing.cpp b/higan/gb/cpu/timing.cpp index 6af540d4..2f71ba26 100644 --- a/higan/gb/cpu/timing.cpp +++ b/higan/gb/cpu/timing.cpp @@ -6,21 +6,6 @@ auto CPU::add_clocks(uint clocks) -> void { if(system.sgb()) system.clocks_executed += clocks; while(clocks--) { - if(oamdma.active) { - uint offset = oamdma.clock++; - if((offset & 3) == 0) { - offset >>= 2; - if(offset == 0) { - //warm-up - } else if(offset == 161) { - //cool-down; disable - oamdma.active = false; - } else { - bus.write(0xfe00 + offset - 1, bus.read((oamdma.bank << 8) + offset - 1)); - } - } - } - if(++status.clock == 0) { cartridge.mbc3.second(); } diff --git a/higan/gb/ppu/mmio.cpp b/higan/gb/ppu/mmio.cpp index e6af4bf9..67567513 100644 --- a/higan/gb/ppu/mmio.cpp +++ b/higan/gb/ppu/mmio.cpp @@ -3,8 +3,14 @@ auto PPU::vram_addr(uint16 addr) const -> uint { } auto PPU::mmio_read(uint16 addr) -> uint8 { - if(addr >= 0x8000 && addr <= 0x9fff) return vram[vram_addr(addr)]; - if(addr >= 0xfe00 && addr <= 0xfe9f) return oam[addr & 0xff]; + if(addr >= 0x8000 && addr <= 0x9fff) { + return vram[vram_addr(addr)]; + } + + if(addr >= 0xfe00 && addr <= 0xfe9f) { + if(status.dma_active && status.dma_clock >= 8) return 0xff; + return oam[addr & 0xff]; + } if(addr == 0xff40) { //LCDC return (status.display_enable << 7) @@ -101,8 +107,16 @@ auto PPU::mmio_read(uint16 addr) -> uint8 { } auto PPU::mmio_write(uint16 addr, uint8 data) -> void { - if(addr >= 0x8000 && addr <= 0x9fff) { vram[vram_addr(addr)] = data; return; } - if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; } + if(addr >= 0x8000 && addr <= 0x9fff) { + vram[vram_addr(addr)] = data; + return; + } + + if(addr >= 0xfe00 && addr <= 0xfe9f) { + if(status.dma_active && status.dma_clock >= 8) return; + oam[addr & 0xff] = data; + return; + } if(addr == 0xff40) { //LCDC if(status.display_enable == false && (data & 0x80)) { @@ -154,6 +168,13 @@ auto PPU::mmio_write(uint16 addr, uint8 data) -> void { return; } + if(addr == 0xff46) { //DMA + status.dma_active = true; + status.dma_clock = 0; + status.dma_bank = data; + return; + } + if(addr == 0xff47) { //BGP bgp[3] = (data >> 6) & 3; bgp[2] = (data >> 4) & 3; diff --git a/higan/gb/ppu/ppu.cpp b/higan/gb/ppu/ppu.cpp index a097c754..34d3d95e 100644 --- a/higan/gb/ppu/ppu.cpp +++ b/higan/gb/ppu/ppu.cpp @@ -72,6 +72,22 @@ auto PPU::main() -> void { auto PPU::add_clocks(uint clocks) -> void { while(clocks--) { + if(status.dma_active) { + uint hi = status.dma_clock++; + uint lo = hi & (cpu.status.speed_double ? 1 : 3); + hi >>= cpu.status.speed_double ? 1 : 2; + if(lo == 0) { + if(hi == 0) { + //warm-up + } else if(hi == 161) { + //cool-down; disable + status.dma_active = false; + } else { + oam[hi - 1] = bus.read(status.dma_bank << 8 | hi - 1); + } + } + } + status.lx++; clock += cpu.frequency; if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) { @@ -107,6 +123,7 @@ auto PPU::power() -> void { bus.mmio[0xff43] = this; //SCX bus.mmio[0xff44] = this; //LY bus.mmio[0xff45] = this; //LYC + bus.mmio[0xff46] = this; //DMA bus.mmio[0xff47] = this; //BGP bus.mmio[0xff48] = this; //OBP0 bus.mmio[0xff49] = this; //OBP1 @@ -149,6 +166,11 @@ auto PPU::power() -> void { status.scx = 0; status.ly = 0; status.lyc = 0; + + status.dma_active = false; + status.dma_clock = 0; + status.dma_bank = 0; + status.wy = 0; status.wx = 0; diff --git a/higan/gb/ppu/ppu.hpp b/higan/gb/ppu/ppu.hpp index 7ffa8326..2736f319 100644 --- a/higan/gb/ppu/ppu.hpp +++ b/higan/gb/ppu/ppu.hpp @@ -71,6 +71,11 @@ struct PPU : Thread, MMIO { //$ff45 LYC uint8 lyc; + //$ff46 DMA + bool dma_active; + uint dma_clock; + uint8 dma_bank; + //$ff4a WY uint8 wy; diff --git a/higan/gb/ppu/serialization.cpp b/higan/gb/ppu/serialization.cpp index 8ce748fc..6c97ba77 100644 --- a/higan/gb/ppu/serialization.cpp +++ b/higan/gb/ppu/serialization.cpp @@ -31,6 +31,10 @@ auto PPU::serialize(serializer& s) -> void { s.integer(status.ly); s.integer(status.lyc); + s.integer(status.dma_active); + s.integer(status.dma_clock); + s.integer(status.dma_bank); + s.integer(status.wy); s.integer(status.wx); diff --git a/higan/target-tomoko/configuration/configuration.cpp b/higan/target-tomoko/configuration/configuration.cpp index 13c1466d..ce95d1b4 100644 --- a/higan/target-tomoko/configuration/configuration.cpp +++ b/higan/target-tomoko/configuration/configuration.cpp @@ -18,11 +18,10 @@ Settings::Settings() { set("Video/Synchronize", false); set("Video/Scale", "Small"); set("Video/AspectCorrection", true); - set("Video/Filter", "Blur"); - set("Video/Shader", "None"); + set("Video/Shader", "Blur"); set("Video/BlurEmulation", true); set("Video/ColorEmulation", true); - set("Video/ScanlineEmulation", true); + set("Video/ScanlineEmulation", false); set("Video/Saturation", 100); set("Video/Gamma", 100); set("Video/Luminance", 100); diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index e7a51123..3d86da90 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -80,8 +80,6 @@ Presentation::Presentation() { settings["Video/Overscan/Mask"].setValue(maskOverscan.checked()); }); videoShaderMenu.setText("Video Shader"); - if(settings["Video/Shader"].text() == "None") videoShaderNone.setChecked(); - if(settings["Video/Shader"].text() == "Blur") videoShaderBlur.setChecked(); videoShaderNone.setText("None").onActivate([&] { settings["Video/Shader"].setValue("None"); program->updateVideoShader(); @@ -277,20 +275,22 @@ auto Presentation::drawSplashScreen() -> void { } auto Presentation::loadShaders() -> void { - if(settings["Video/Driver"].text() != "OpenGL") { - return; + auto pathname = locate({localpath(), "higan/"}, "Video Shaders/"); + + if(settings["Video/Driver"].text() == "OpenGL") { + for(auto shader : directory::folders(pathname, "*.shader")) { + if(videoShaders.objectCount() == 2) videoShaderMenu.append(MenuSeparator()); + MenuRadioItem item{&videoShaderMenu}; + item.setText(string{shader}.rtrim(".shader/", 1L)).onActivate([=] { + settings["Video/Shader"].setValue({pathname, shader}); + program->updateVideoShader(); + }); + videoShaders.append(item); + } } - auto pathname = locate({localpath(), "higan/"}, "Video Shaders/"); - for(auto shader : directory::folders(pathname, "*.shader")) { - if(videoShaders.objectCount() == 2) videoShaderMenu.append(MenuSeparator()); - MenuRadioItem item{&videoShaderMenu}; - item.setText(string{shader}.rtrim(".shader/", 1L)).onActivate([=] { - settings["Video/Shader"].setValue({pathname, shader}); - program->updateVideoShader(); - }); - videoShaders.append(item); - } + if(settings["Video/Shader"].text() == "None") videoShaderNone.setChecked(); + if(settings["Video/Shader"].text() == "Blur") videoShaderBlur.setChecked(); for(auto radioItem : videoShaders.objects()) { if(settings["Video/Shader"].text() == string{pathname, radioItem.text(), ".shader/"}) { diff --git a/hiro/cocoa/widget/text-edit.cpp b/hiro/cocoa/widget/text-edit.cpp index 8be57b00..3b18ed56 100644 --- a/hiro/cocoa/widget/text-edit.cpp +++ b/hiro/cocoa/widget/text-edit.cpp @@ -84,7 +84,7 @@ auto pTextEdit::setEditable(bool editable) -> void { auto pTextEdit::setEnabled(bool enabled) -> void { pWidget::setEnabled(enabled); - setEditable(self().editable); //Cocoa lacks NSTextView::setEnabled; simulate via setEnabled() + setEditable(state().editable); //Cocoa lacks NSTextView::setEnabled; simulate via setEnabled() } auto pTextEdit::setFont(const Font& font) -> void { diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp index 2da0855f..ffd9abe9 100644 --- a/icarus/icarus.cpp +++ b/icarus/icarus.cpp @@ -86,7 +86,7 @@ auto nall::main(lstring args) -> void { Application::Cocoa::onPreferences([&] { scanDialog->settingsButton.doActivate(); }); - Application::Cocoa::onQuit({ + Application::Cocoa::onQuit([&] { Application::quit(); }); #endif