From 0f78acffd72f113d0860afa6862aee8f96d6ff13 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 10 Dec 2013 23:12:54 +1100 Subject: [PATCH] Update to v093r07 release. byuu says: Changelog: - importing a game won't show message box on success - importing a game will select the game that was imported in the list - caveat: GTK+ port doesn't seem to be removing focus from item 0 even though the selection is on item 2 - Game Boy audio reduced in volume by 50% - Game Boy Advance audio reduced in volume by 50% - Game Boy internally mixes audio at 2MHz now - Game Boy Advance's Game Boy audio hardware internally mixes audio at 2MHz now - Game Boy Color doesn't sort sprites by X-coordinate - Game Boy Color allows transparency on BGpriority pixels - caveat: this seems to allow sprites to appear on top of windows - Game Boy Color VRAM DMA transfers 16 bytes in 8 clocks (or 16 clocks in double speed mode) - Game Boy Color VRAM DMA masks low 4-bits of source and destination address - Game Boy Color VRAM DMA only allows reads from ROM or RAM - Game Boy Color VRAM DMA only allows writes to VRAM - fixed a bug in dereferencing a nullptr from pObject::find(), should fix crash when pressing enter key on blank windows - fixed Windows RadioItem selection - Game Boy Advance color emulation code added --- emulator/emulator.hpp | 2 +- gb/apu/apu.cpp | 2 +- gb/apu/apu.hpp | 2 +- gb/apu/master/master.cpp | 9 ++- gb/apu/noise/noise.cpp | 4 +- gb/apu/square1/square1.cpp | 6 +- gb/apu/square2/square2.cpp | 4 +- gb/apu/wave/wave.cpp | 4 +- gb/cpu/cpu.cpp | 1 + gb/cpu/cpu.hpp | 3 + gb/cpu/memory.cpp | 14 +++++ gb/cpu/mmio.cpp | 21 ++++--- gb/cpu/serialization.cpp | 1 + gb/cpu/timing.cpp | 6 +- gb/interface/interface.cpp | 2 +- gb/ppu/cgb.cpp | 16 +----- gb/ppu/dmg.cpp | 8 +-- gba/apu/apu.cpp | 4 +- gba/apu/noise.cpp | 4 +- gba/apu/registers.hpp | 2 +- gba/apu/square.cpp | 2 +- gba/apu/square1.cpp | 4 +- gba/apu/square2.cpp | 2 +- gba/apu/wave.cpp | 4 +- gba/video/video.cpp | 57 +++++++++++++++++-- gba/video/video.hpp | 3 + nall/string/platform.hpp | 37 ++++++------ phoenix/windows/object.cpp | 6 +- phoenix/windows/platform.hpp | 2 +- phoenix/windows/utility.cpp | 3 +- .../disassembler.cpp} | 2 +- .../disassembler.hpp} | 0 sfc/chip/superfx/superfx.cpp | 2 +- sfc/chip/superfx/superfx.hpp | 2 +- target-ethos/configuration/configuration.cpp | 1 + target-ethos/configuration/configuration.hpp | 1 + target-ethos/general/library.cpp | 22 ++++++- 37 files changed, 177 insertions(+), 88 deletions(-) rename sfc/chip/superfx/{disasm/disasm.cpp => disassembler/disassembler.cpp} (99%) rename sfc/chip/superfx/{disasm/disasm.hpp => disassembler/disassembler.hpp} (100%) diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index e3e57a27..2149e102 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "093.06"; + static const char Version[] = "093.07"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/gb/apu/apu.cpp b/gb/apu/apu.cpp index 3701c536..4176a5f4 100644 --- a/gb/apu/apu.cpp +++ b/gb/apu/apu.cpp @@ -54,7 +54,7 @@ void APU::main() { } void APU::power() { - create(Main, 4 * 1024 * 1024); + create(Main, 2 * 1024 * 1024); for(unsigned n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this; for(auto& n : mmio_data) n = 0x00; diff --git a/gb/apu/apu.hpp b/gb/apu/apu.hpp index 59f3d50d..aefe2301 100644 --- a/gb/apu/apu.hpp +++ b/gb/apu/apu.hpp @@ -6,7 +6,7 @@ struct APU : Thread, MMIO { #include "master/master.hpp" uint8 mmio_data[48]; - uint13 sequencer_base; + uint12 sequencer_base; uint3 sequencer_step; Square1 square1; diff --git a/gb/apu/master/master.cpp b/gb/apu/master/master.cpp index 7e24161c..0505af41 100644 --- a/gb/apu/master/master.cpp +++ b/gb/apu/master/master.cpp @@ -21,8 +21,8 @@ void APU::Master::run() { if(channel3_left_enable) sample += apu.wave.output; if(channel4_left_enable) sample += apu.noise.output; sample = (sample * 512) - 16384; - sample = (sample * (left_volume + 1)) / 8; - left = sample; + sample = (sample * (left_volume + 1)) / 8; + left = sample; sample = 0; if(channel1_right_enable) sample += apu.square1.output; @@ -32,6 +32,11 @@ void APU::Master::run() { sample = (sample * 512) - 16384; sample = (sample * (right_volume + 1)) / 8; right = sample; + + //reduce audio volume + center >>= 1; + left >>= 1; + right >>= 1; } void APU::Master::write(unsigned r, uint8 data) { diff --git a/gb/apu/noise/noise.cpp b/gb/apu/noise/noise.cpp index 08b1c70c..c1566ba9 100644 --- a/gb/apu/noise/noise.cpp +++ b/gb/apu/noise/noise.cpp @@ -48,8 +48,8 @@ void APU::Noise::write(unsigned r, uint8 data) { if(r == 3) { //$ff22 NR43 frequency = data >> 4; narrow_lfsr = data & 0x08; - divisor = (data & 0x07) << 4; - if(divisor == 0) divisor = 8; + divisor = (data & 0x07) << 3; + if(divisor == 0) divisor = 4; period = divisor << frequency; } diff --git a/gb/apu/square1/square1.cpp b/gb/apu/square1/square1.cpp index c96287ec..88b7cf51 100644 --- a/gb/apu/square1/square1.cpp +++ b/gb/apu/square1/square1.cpp @@ -6,7 +6,7 @@ bool APU::Square1::dac_enable() { void APU::Square1::run() { if(period && --period == 0) { - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); phase++; switch(duty) { case 0: duty_output = (phase == 6); break; //______-_ @@ -34,7 +34,7 @@ void APU::Square1::sweep(bool update) { } else if(sweep_shift && update) { frequency_shadow = freq; frequency = freq & 2047; - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); } } @@ -91,7 +91,7 @@ void APU::Square1::write(unsigned r, uint8 data) { if(initialize) { enable = dac_enable(); - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); envelope_period = envelope_frequency; volume = envelope_volume; frequency_shadow = frequency; diff --git a/gb/apu/square2/square2.cpp b/gb/apu/square2/square2.cpp index f2e79a23..1c7282c9 100644 --- a/gb/apu/square2/square2.cpp +++ b/gb/apu/square2/square2.cpp @@ -6,7 +6,7 @@ bool APU::Square2::dac_enable() { void APU::Square2::run() { if(period && --period == 0) { - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); phase++; switch(duty) { case 0: duty_output = (phase == 6); break; //______-_ @@ -60,7 +60,7 @@ void APU::Square2::write(unsigned r, uint8 data) { if(initialize) { enable = dac_enable(); - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); envelope_period = envelope_frequency; volume = envelope_volume; } diff --git a/gb/apu/wave/wave.cpp b/gb/apu/wave/wave.cpp index afea5b05..892f9fd8 100644 --- a/gb/apu/wave/wave.cpp +++ b/gb/apu/wave/wave.cpp @@ -2,7 +2,7 @@ void APU::Wave::run() { if(period && --period == 0) { - period = 2 * (2048 - frequency); + period = 1 * (2048 - frequency); pattern_sample = pattern[++pattern_offset]; } @@ -48,7 +48,7 @@ void APU::Wave::write(unsigned r, uint8 data) { if(initialize) { enable = dac_enable; - period = 2 * (2048 - frequency); + period = 1 * (2048 - frequency); pattern_offset = 0; } } diff --git a/gb/cpu/cpu.cpp b/gb/cpu/cpu.cpp index c2251cbd..a7f5cbf4 100644 --- a/gb/cpu/cpu.cpp +++ b/gb/cpu/cpu.cpp @@ -185,6 +185,7 @@ void CPU::power() { status.dma_mode = 0; status.dma_length = 0; + status.dma_completed = true; status.ff6c = 0; status.ff72 = 0; diff --git a/gb/cpu/cpu.hpp b/gb/cpu/cpu.hpp index 9454514c..c9980337 100644 --- a/gb/cpu/cpu.hpp +++ b/gb/cpu/cpu.hpp @@ -57,6 +57,7 @@ struct CPU : Processor::LR35902, Thread, MMIO { //$ff55 HDMA5 bool dma_mode; uint16 dma_length; + bool dma_completed; //$ff6c ??? uint8 ff6c; @@ -102,6 +103,8 @@ struct CPU : Processor::LR35902, Thread, MMIO { uint8 op_read(uint16 addr); void op_write(uint16 addr, uint8 data); void cycle_edge(); + uint8 dma_read(uint16 addr); + void dma_write(uint16 addr, uint8 data); uint8 debugger_read(uint16 addr); //timing.cpp diff --git a/gb/cpu/memory.cpp b/gb/cpu/memory.cpp index 70a9920e..aec25eff 100644 --- a/gb/cpu/memory.cpp +++ b/gb/cpu/memory.cpp @@ -25,6 +25,20 @@ void CPU::cycle_edge() { } } +//VRAM DMA source can only be ROM or RAM +uint8 CPU::dma_read(uint16 addr) { + if(addr < 0x8000) return bus.read(addr); //0000-7fff + if(addr < 0xa000) return 0x00; //8000-9fff + if(addr < 0xe000) return bus.read(addr); //a000-dfff + return 0x00; //e000-ffff +} + +//VRAM DMA target is always VRAM +void CPU::dma_write(uint16 addr, uint8 data) { + addr = 0x8000 | (addr & 0x1fff); //8000-9fff + return bus.write(addr, data); +} + uint8 CPU::debugger_read(uint16 addr) { return bus.read(addr); } diff --git a/gb/cpu/mmio.cpp b/gb/cpu/mmio.cpp index 02f9bd32..1170420a 100644 --- a/gb/cpu/mmio.cpp +++ b/gb/cpu/mmio.cpp @@ -81,7 +81,8 @@ uint8 CPU::mmio_read(uint16 addr) { } if(addr == 0xff55) { //HDMA5 - return (status.dma_length / 16) - 1; + return (status.dma_completed << 7) + | (((status.dma_length / 16) - 1) & 0x7f); } if(addr == 0xff56) { //RP @@ -203,7 +204,7 @@ void CPU::mmio_write(uint16 addr, uint8 data) { } if(addr == 0xff52) { //HDMA2 - status.dma_source = (status.dma_source & 0xff00) | (data << 0); + status.dma_source = (status.dma_source & 0xff00) | (data & 0xf0); return; } @@ -213,18 +214,24 @@ void CPU::mmio_write(uint16 addr, uint8 data) { } if(addr == 0xff54) { //HDMA4 - status.dma_target = (status.dma_target & 0xff00) | (data << 0); + status.dma_target = (status.dma_target & 0xff00) | (data & 0xf0); return; } if(addr == 0xff55) { //HDMA5 status.dma_mode = data & 0x80; status.dma_length = ((data & 0x7f) + 1) * 16; + status.dma_completed = !status.dma_mode; - if(status.dma_mode == 0) do { - bus.write(status.dma_target++, bus.read(status.dma_source++)); - add_clocks(4 << status.speed_double); - } while(--status.dma_length); + if(status.dma_mode == 0) { + do { + for(unsigned n = 0; n < 16; n++) { + dma_write(status.dma_target++, dma_read(status.dma_source++)); + } + add_clocks(8 << status.speed_double); + status.dma_length -= 16; + } while(status.dma_length); + } return; } diff --git a/gb/cpu/serialization.cpp b/gb/cpu/serialization.cpp index 50edab10..6a912e13 100644 --- a/gb/cpu/serialization.cpp +++ b/gb/cpu/serialization.cpp @@ -39,6 +39,7 @@ void CPU::serialize(serializer& s) { s.integer(status.dma_target); s.integer(status.dma_mode); s.integer(status.dma_length); + s.integer(status.dma_completed); s.integer(status.ff6c); diff --git a/gb/cpu/timing.cpp b/gb/cpu/timing.cpp index 516f93aa..dfc0821c 100644 --- a/gb/cpu/timing.cpp +++ b/gb/cpu/timing.cpp @@ -76,11 +76,11 @@ void CPU::timer_4096hz() { } void CPU::hblank() { - if(status.dma_mode == 1 && status.dma_length) { + if(status.dma_mode == 1 && status.dma_length && ppu.status.ly < 144) { for(unsigned n = 0; n < 16; n++) { - bus.write(status.dma_target++, bus.read(status.dma_source++)); - add_clocks(4); + dma_write(status.dma_target++, dma_read(status.dma_source++)); } + add_clocks(8 << status.speed_double); status.dma_length -= 16; } } diff --git a/gb/interface/interface.cpp b/gb/interface/interface.cpp index 605b4dc3..de2ce616 100644 --- a/gb/interface/interface.cpp +++ b/gb/interface/interface.cpp @@ -21,7 +21,7 @@ double Interface::videoFrequency() { } double Interface::audioFrequency() { - return 4194304.0; + return 4194304.0 / 2.0; } bool Interface::loaded() { diff --git a/gb/ppu/cgb.cpp b/gb/ppu/cgb.cpp index 672ca341..a718107c 100644 --- a/gb/ppu/cgb.cpp +++ b/gb/ppu/cgb.cpp @@ -125,19 +125,6 @@ void PPU::cgb_render_ob() { if(sprites == 10) break; } - //sort by X-coordinate, when equal, lower address comes first - for(unsigned x = 0; x < sprites; x++) { - for(unsigned y = x + 1; y < sprites; y++) { - signed sx = oam[(sprite[x] << 2) + 1] - 8; - signed sy = oam[(sprite[y] << 2) + 1] - 8; - if(sy < sx) { - sprite[x] ^= sprite[y]; - sprite[y] ^= sprite[x]; - sprite[x] ^= sprite[y]; - } - } - } - //render backwards, so that first sprite has highest priority for(signed s = sprites - 1; s >= 0; s--) { unsigned n = sprite[s] << 2; @@ -170,9 +157,8 @@ void PPU::cgb_render_ob() { if(ox < 160) { //When LCDC.D0 (BG enable) is off, OB is always rendered above BG+Window if(status.bg_enable) { - if(pixels[ox].origin == Pixel::Origin::BGP) continue; if(attr & 0x80) { - if(pixels[ox].origin == Pixel::Origin::BG) { + if(pixels[ox].origin == Pixel::Origin::BG || pixels[ox].origin == Pixel::Origin::BGP) { if(pixels[ox].palette > 0) continue; } } diff --git a/gb/ppu/dmg.cpp b/gb/ppu/dmg.cpp index 9bb63ce4..107f29a4 100644 --- a/gb/ppu/dmg.cpp +++ b/gb/ppu/dmg.cpp @@ -95,16 +95,12 @@ void PPU::dmg_render_ob() { if(sprites == 10) break; } - //sort by X-coordinate, when equal, lower address comes first + //sort by X-coordinate; when equal, lower address comes first for(unsigned x = 0; x < sprites; x++) { for(unsigned y = x + 1; y < sprites; y++) { signed sx = oam[(sprite[x] << 2) + 1] - 8; signed sy = oam[(sprite[y] << 2) + 1] - 8; - if(sy < sx) { - sprite[x] ^= sprite[y]; - sprite[y] ^= sprite[x]; - sprite[x] ^= sprite[y]; - } + if(sy < sx) std::swap(sprite[x], sprite[y]); } } diff --git a/gba/apu/apu.cpp b/gba/apu/apu.cpp index 41750233..c5abddc2 100644 --- a/gba/apu/apu.cpp +++ b/gba/apu/apu.cpp @@ -25,7 +25,7 @@ void APU::Enter() { } void APU::main() { - for(unsigned n = 0; n < 128; n++) { + for(unsigned n = 0; n < 64; n++) { runsequencer(); } @@ -70,7 +70,7 @@ void APU::main() { if(regs.bias.amplitude == 3) lsample &= ~15, rsample &= ~15; if(cpu.regs.mode == CPU::Registers::Mode::Stop) lsample = 0, rsample = 0; - interface->audioSample(sclamp<16>(lsample << 7), sclamp<16>(rsample << 7)); //should be <<5, use <<7 for added volume + interface->audioSample(sclamp<16>(lsample << 6), sclamp<16>(rsample << 6)); //should be <<5, use <<6 for added volume step(512); } diff --git a/gba/apu/noise.cpp b/gba/apu/noise.cpp index 428542c1..1f96f1ab 100644 --- a/gba/apu/noise.cpp +++ b/gba/apu/noise.cpp @@ -1,6 +1,6 @@ unsigned APU::Noise::divider() const { - if(divisor == 0) return 8; - return divisor * 16; + if(divisor == 0) return 4; + return divisor * 8; } void APU::Noise::run() { diff --git a/gba/apu/registers.hpp b/gba/apu/registers.hpp index b2104be9..59c8eb84 100644 --- a/gba/apu/registers.hpp +++ b/gba/apu/registers.hpp @@ -128,7 +128,7 @@ struct Sequencer { uint1 enable[4]; uint1 masterenable; - uint13 base; + uint12 base; uint3 step; int16 lsample; int16 rsample; diff --git a/gba/apu/square.cpp b/gba/apu/square.cpp index 6152d7d3..e7e27d9b 100644 --- a/gba/apu/square.cpp +++ b/gba/apu/square.cpp @@ -1,6 +1,6 @@ void APU::Square::run() { if(period && --period == 0) { - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); phase++; switch(duty) { case 0: signal = (phase == 6); break; //_____-_ diff --git a/gba/apu/square1.cpp b/gba/apu/square1.cpp index 6ecf71a4..b020031d 100644 --- a/gba/apu/square1.cpp +++ b/gba/apu/square1.cpp @@ -10,7 +10,7 @@ void APU::Square1::runsweep(bool update) { } else if(sweep.shift && update) { shadowfrequency = updatefrequency; frequency = updatefrequency; - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); } } @@ -64,7 +64,7 @@ void APU::Square1::write(unsigned addr, uint8 byte) { if(initialize) { enable = envelope.dacenable(); - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); envelope.period = envelope.frequency; volume = envelope.volume; shadowfrequency = frequency; diff --git a/gba/apu/square2.cpp b/gba/apu/square2.cpp index facbb76f..4e784d1d 100644 --- a/gba/apu/square2.cpp +++ b/gba/apu/square2.cpp @@ -32,7 +32,7 @@ void APU::Square2::write(unsigned addr, uint8 byte) { if(initialize) { enable = envelope.dacenable(); - period = 4 * (2048 - frequency); + period = 2 * (2048 - frequency); envelope.period = envelope.frequency; volume = envelope.volume; } diff --git a/gba/apu/wave.cpp b/gba/apu/wave.cpp index e1b666cb..2677fde9 100644 --- a/gba/apu/wave.cpp +++ b/gba/apu/wave.cpp @@ -1,6 +1,6 @@ void APU::Wave::run() { if(period && --period == 0) { - period = 2 * (2048 - frequency); + period = 1 * (2048 - frequency); patternsample = pattern[patternbank * 16 + patternaddr++]; if(patternaddr == 0) patternbank ^= mode; } @@ -55,7 +55,7 @@ void APU::Wave::write(unsigned addr, uint8 byte) { if(initialize) { enable = dacenable; - period = 2 * (2048 - frequency); + period = 1 * (2048 - frequency); patternaddr = 0; patternbank = mode ? (uint1)0 : bank; } diff --git a/gba/video/video.cpp b/gba/video/video.cpp index f2fa094c..fda63117 100644 --- a/gba/video/video.cpp +++ b/gba/video/video.cpp @@ -7,13 +7,51 @@ Video video; void Video::generate_palette(bool color_emulation) { //todo: implement LCD color emulation for(unsigned color = 0; color < (1 << 15); color++) { - uint5 b = color >> 10; - uint5 g = color >> 5; - uint5 r = color >> 0; + unsigned B = (color >> 10) & 31; + unsigned G = (color >> 5) & 31; + unsigned R = (color >> 0) & 31; - uint16 R = r << 11 | r << 6 | r << 1 | r >> 4; - uint16 G = g << 11 | g << 6 | g << 1 | g >> 4; - uint16 B = b << 11 | b << 6 | b << 1 | b >> 4; + if(color_emulation) { + R = curve[R]; + G = curve[G]; + B = curve[B]; + + unsigned Rr = R * 16; + unsigned Gr = R * 4; + unsigned Br = R * 4; + + unsigned Rg = G * 8; + unsigned Gg = G * 16; + unsigned Bg = G * 8; + + unsigned Rb = B * 0; //intentionally always zero + unsigned Gb = B * 8; + unsigned Bb = B * 16; + + if(Rr < Rg) std::swap(Rr, Rg); + if(Rr < Rb) std::swap(Rr, Rb); + if(Rg < Rb) std::swap(Rg, Rb); + + if(Gr < Gg) std::swap(Gr, Gg); + if(Gr < Gb) std::swap(Gr, Gb); + if(Gg < Gb) std::swap(Gg, Gb); + + if(Br < Bg) std::swap(Br, Bg); + if(Br < Bb) std::swap(Br, Bb); + if(Bg < Bb) std::swap(Bg, Bb); + + R = (((4 * Rr + 2 * Rg + Rb) * 160) >> 14) + 32; + G = (((4 * Gr + 2 * Gg + Gb) * 160) >> 14) + 32; + B = (((4 * Br + 2 * Bg + Bb) * 160) >> 14) + 32; + + R = R << 8 | R; + G = G << 8 | G; + B = B << 8 | B; + } else { + R = R << 11 | R << 6 | R << 1 | R >> 4; + G = G << 11 | G << 6 | G << 1 | G >> 4; + B = B << 11 | B << 6 | B << 1 | B >> 4; + } palette[color] = interface->videoColor(color, R, G, B); } @@ -27,4 +65,11 @@ Video::~Video() { delete[] palette; } +const uint8 Video::curve[32] = { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12, + 0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x38, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80, + 0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, +}; + } diff --git a/gba/video/video.hpp b/gba/video/video.hpp index a7fa82dc..9d162855 100644 --- a/gba/video/video.hpp +++ b/gba/video/video.hpp @@ -4,6 +4,9 @@ struct Video { Video(); ~Video(); + +private: + static const uint8 curve[32]; }; extern Video video; diff --git a/nall/string/platform.hpp b/nall/string/platform.hpp index 30b424f6..e71bd32f 100644 --- a/nall/string/platform.hpp +++ b/nall/string/platform.hpp @@ -15,8 +15,8 @@ string activepath() { string realpath(const string& name) { string result; char path[PATH_MAX] = ""; - if(::realpath(name, path)) result = path; - if(result.empty()) result = {activepath(), name}; + if(::realpath(name, path)) result = dir(path); + if(result.empty()) result = activepath(); result.transform("\\", "/"); if(result.endsWith("/") == false) result.append("/"); return result; @@ -25,15 +25,14 @@ string realpath(const string& name) { // /home/username/ // c:/users/username/ string userpath() { - string result; #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path); - result = (const char*)utf8_t(path); + string result = (const char*)utf8_t(path); result.transform("\\", "/"); #else - struct passwd *userinfo = getpwuid(getuid()); - result = userinfo->pw_dir; + struct passwd* userinfo = getpwuid(getuid()); + string result = userinfo->pw_dir; #endif if(result.empty()) result = "."; if(result.endsWith("/") == false) result.append("/"); @@ -43,49 +42,55 @@ string userpath() { // /home/username/.config/ // c:/users/username/appdata/roaming/ string configpath() { - string result; #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - result = (const char*)utf8_t(path); + string result = (const char*)utf8_t(path); result.transform("\\", "/"); #elif defined(PLATFORM_MACOSX) - result = {userpath(), "Library/Application Support/"}; + string result = {userpath(), "Library/Application Support/"}; #else - result = {userpath(), ".config/"}; + string result = {userpath(), ".config/"}; #endif if(result.empty()) result = "."; if(result.endsWith("/") == false) result.append("/"); return result; } +// /usr/share +// /Library/Application Support/ +// c:/ProgramData/ string sharedpath() { - string result; #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - result = (const char*)utf8_t(path); + string result = (const char*)utf8_t(path); result.transform("\\", "/"); #elif defined(PLATFORM_MACOSX) - result = "/Library/Application Support/"; + string result = "/Library/Application Support/"; #else - result = "/usr/share/"; + string result = "/usr/share/"; #endif if(result.empty()) result = "."; if(result.endsWith("/") == false) result.append("/"); return result; } +// /tmp +// c:/users/username/AppData/Local/Temp/ string temppath() { #if defined(PLATFORM_WINDOWS) wchar_t path[PATH_MAX] = L""; GetTempPathW(PATH_MAX, path); string result = (const char*)utf8_t(path); result.transform("\\", "/"); - return result; + #elif defined(P_tmpdir) + string result = P_tmpdir; #else - return "/tmp/"; + string result = "/tmp/"; #endif + if(result.endsWith("/") == false) result.append("/"); + return result; } } diff --git a/phoenix/windows/object.cpp b/phoenix/windows/object.cpp index 419478ca..fc30791f 100644 --- a/phoenix/windows/object.cpp +++ b/phoenix/windows/object.cpp @@ -9,9 +9,9 @@ pObject::pObject(Object& object) : object(object) { locked = false; } -pObject* pObject::find(unsigned id) { - for(auto& item : objects) if(item->id == id) return item; - return 0; +Object* pObject::find(unsigned id) { + for(auto& item : objects) if(item->id == id) return &item->object; + return nullptr; } } diff --git a/phoenix/windows/platform.hpp b/phoenix/windows/platform.hpp index dbc7952a..e8242357 100644 --- a/phoenix/windows/platform.hpp +++ b/phoenix/windows/platform.hpp @@ -71,7 +71,7 @@ struct pObject { bool locked; pObject(Object& object); - static pObject* find(unsigned id); + static Object* find(unsigned id); virtual ~pObject() {} void constructor() {} diff --git a/phoenix/windows/utility.cpp b/phoenix/windows/utility.cpp index 79ee7bd6..1379f398 100644 --- a/phoenix/windows/utility.cpp +++ b/phoenix/windows/utility.cpp @@ -278,10 +278,11 @@ static LRESULT CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT case WM_COMMAND: { unsigned id = LOWORD(wparam); HWND control = GetDlgItem(hwnd, id); - Object* object = control ? (Object*)GetWindowLongPtr(control, GWLP_USERDATA) : (Object*)(&pObject::find(id)->object); + Object* object = control ? (Object*)GetWindowLongPtr(control, GWLP_USERDATA) : pObject::find(id); if(object == nullptr) break; if(dynamic_cast(object)) { ((Item*)object)->p.onActivate(); return FALSE; } if(dynamic_cast(object)) { ((CheckItem*)object)->p.onToggle(); return FALSE; } + if(dynamic_cast(object)) { ((RadioItem*)object)->p.onActivate(); return FALSE; } if(dynamic_cast(object)) { ((Button*)object)->p.onActivate(); return FALSE; } if(dynamic_cast(object)) { ((CheckButton*)object)->p.onToggle(); return FALSE; } if(dynamic_cast(object)) { ((CheckLabel*)object)->p.onToggle(); return FALSE; } diff --git a/sfc/chip/superfx/disasm/disasm.cpp b/sfc/chip/superfx/disassembler/disassembler.cpp similarity index 99% rename from sfc/chip/superfx/disasm/disasm.cpp rename to sfc/chip/superfx/disassembler/disassembler.cpp index ef06f65c..de173288 100644 --- a/sfc/chip/superfx/disasm/disasm.cpp +++ b/sfc/chip/superfx/disassembler/disassembler.cpp @@ -87,7 +87,7 @@ void SuperFX::disassemble_alt0(char* output) { case (0x9f): sprintf(t, "fmult"); break; case16(0xa0): sprintf(t, "ibt r%u,#$%.2x", op0 & 15, op1); break; case16(0xb0): sprintf(t, "from r%u", op0 & 15); break; - case (0xc0): sprintf(t, "hib"); + case (0xc0): sprintf(t, "hib"); break; case15(0xc1): sprintf(t, "or r%u", op0 & 15); break; case15(0xd0): sprintf(t, "inc r%u", op0 & 15); break; case (0xdf): sprintf(t, "getc"); break; diff --git a/sfc/chip/superfx/disasm/disasm.hpp b/sfc/chip/superfx/disassembler/disassembler.hpp similarity index 100% rename from sfc/chip/superfx/disasm/disasm.hpp rename to sfc/chip/superfx/disassembler/disassembler.hpp diff --git a/sfc/chip/superfx/superfx.cpp b/sfc/chip/superfx/superfx.cpp index c01cff24..608beabb 100644 --- a/sfc/chip/superfx/superfx.cpp +++ b/sfc/chip/superfx/superfx.cpp @@ -9,7 +9,7 @@ namespace SuperFamicom { #include "memory/memory.cpp" #include "mmio/mmio.cpp" #include "timing/timing.cpp" -#include "disasm/disasm.cpp" +#include "disassembler/disassembler.cpp" SuperFX superfx; diff --git a/sfc/chip/superfx/superfx.hpp b/sfc/chip/superfx/superfx.hpp index 5109fb11..7a9c00a8 100644 --- a/sfc/chip/superfx/superfx.hpp +++ b/sfc/chip/superfx/superfx.hpp @@ -7,7 +7,7 @@ struct SuperFX : Processor::GSU, Coprocessor { #include "memory/memory.hpp" #include "mmio/mmio.hpp" #include "timing/timing.hpp" - #include "disasm/disasm.hpp" + #include "disassembler/disassembler.hpp" static void Enter(); void enter(); diff --git a/target-ethos/configuration/configuration.cpp b/target-ethos/configuration/configuration.cpp index b21187ce..d40e5532 100644 --- a/target-ethos/configuration/configuration.cpp +++ b/target-ethos/configuration/configuration.cpp @@ -43,6 +43,7 @@ ConfigurationSettings::ConfigurationSettings() { append(server, "Server"); library.append(library.selection = -1, "Selection"); + library.append(library.mediaMode = 0, "MediaMode"); library.append(library.showOnStartup = true, "ShowOnStartup"); append(library, "Library"); diff --git a/target-ethos/configuration/configuration.hpp b/target-ethos/configuration/configuration.hpp index 6501fde8..9591669c 100644 --- a/target-ethos/configuration/configuration.hpp +++ b/target-ethos/configuration/configuration.hpp @@ -48,6 +48,7 @@ struct ConfigurationSettings : Configuration::Document { struct Library : Configuration::Node { signed selection; + unsigned mediaMode; bool showOnStartup; } library; diff --git a/target-ethos/general/library.cpp b/target-ethos/general/library.cpp index 59809955..c4950879 100644 --- a/target-ethos/general/library.cpp +++ b/target-ethos/general/library.cpp @@ -68,6 +68,7 @@ void LibraryBrowser::refresh() { } void LibraryBrowser::setMode() { + config->library.mediaMode = mediaMode.selection(); auto& media = emulator.media[mediaMode.selection()]; pathname = {utility->libraryPath(), media.name, "/"}; @@ -100,9 +101,10 @@ void LibraryImport::onImportActivate() { } function browse = program->ananke.sym("ananke_browse"); if(!browse) return; + audio.clear(); //ananke's browser is modal string pathname = browse(); + pathname.rtrim<1>("/"); if(pathname.empty()) return; - MessageWindow().setText({"Successfully imported ", notdir(pathname.rtrim<1>("/"))}).information(); //after importing game, take user to the relevant game list to show the newly imported title string type = extension(pathname); @@ -115,6 +117,17 @@ void LibraryImport::onImportActivate() { browser->mediaMode.setSelection(mode); libraryManager->libraryFrame.setSelection(selection); libraryManager->onChange(); + + //find game in list and select it + string name = notdir(nall::basename(pathname)); + for(unsigned n = 0; n < browser->folders.rows(); n++) { + if(browser->folders.text(n, 0) == name) { + browser->folders.setSelection(n); + browser->onChange(); + break; + } + } + return; } mode++; @@ -125,6 +138,8 @@ void LibraryImport::onImportActivate() { } LibraryManager::LibraryManager() { + libraryManager = this; + setTitle("Game Library"); setGeometry({128, 128, 640, 680}); windowManager->append(this, "LibraryManager"); @@ -155,6 +170,11 @@ LibraryManager::LibraryManager() { //initial config value of -1 defaults to import tab on first launch of higan if(config->library.selection < 0) config->library.selection = browsers.size(); libraryFrame.setSelection(config->library.selection); + + if(libraryFrame.selection() < browsers.size()) { + browsers[libraryFrame.selection()]->mediaMode.setSelection(config->library.mediaMode); + browsers[libraryFrame.selection()]->setMode(); + } } void LibraryManager::bootstrap() {