diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 5e61f4bd..4697c77e 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -8,7 +8,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "094.35"; + static const string Version = "094.36"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/gba/cpu/prefetch.cpp b/gba/cpu/prefetch.cpp index 56d12e7c..c91b730e 100644 --- a/gba/cpu/prefetch.cpp +++ b/gba/cpu/prefetch.cpp @@ -10,16 +10,16 @@ auto CPU::prefetch_step(unsigned clocks) -> void { step(clocks); if(!regs.wait.control.prefetch || active.dma) return; - prefetch.wait -= clocks; - while(!prefetch.full() && prefetch.wait <= 0) { + while(!prefetch.full() && clocks--) { + if(--prefetch.wait) continue; prefetch.slot[prefetch.load >> 1 & 7] = cartridge.rom_read(Half, prefetch.load); prefetch.load += 2; - prefetch.wait += bus_wait(Half | Sequential, prefetch.load); + prefetch.wait = bus_wait(Half | Sequential, prefetch.load); } } auto CPU::prefetch_wait() -> void { - if(!regs.wait.control.prefetch || prefetch.full()) return; + if(!regs.wait.control.prefetch || active.dma || prefetch.full()) return; prefetch_step(prefetch.wait); prefetch.wait = bus_wait(Half | Nonsequential, prefetch.load); diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index 758d13c9..1673b7a7 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -170,20 +170,22 @@ auto BrowserDialogWindow::setPath(string path) -> void { for(auto content : contents) { if(!content.endsWith("/")) continue; - if(folderMode && isMatch(content.rtrim("/"))) continue; + content.rtrim("/"); + if(folderMode && isMatch(content)) continue; view.append(ListViewItem() - .append(ListViewCell().setText(content.rtrim("/")).setIcon(Icon::Emblem::Folder)) + .append(ListViewCell().setText(content).setIcon(Icon::Emblem::Folder)) .append(ListViewCell().setText(octal<3>(storage::mode({path, content}) & 0777))) ); } for(auto content : contents) { - if(content.endsWith("/") && !folderMode) continue; - if(!isMatch(content.rtrim("/"))) continue; + if(content.endsWith("/") != folderMode) continue; //file mode shows files; folder mode shows folders + content.rtrim("/"); + if(!isMatch(content)) continue; view.append(ListViewItem() - .append(ListViewCell().setText(content.rtrim("/")).setIcon(folderMode ? Icon::Action::Open : Icon::Emblem::File)) + .append(ListViewCell().setText(content).setIcon(folderMode ? Icon::Action::Open : Icon::Emblem::File)) .append(ListViewCell().setText(octal<3>(storage::mode({path, content}) & 0777))) ); } diff --git a/hiro/windows/platform.hpp b/hiro/windows/platform.hpp index 94515a7b..b9961d50 100644 --- a/hiro/windows/platform.hpp +++ b/hiro/windows/platform.hpp @@ -10,6 +10,7 @@ struct pWidget; struct AppMessage { enum : unsigned { None = WM_APP, + ListView_doPaint, ListView_onActivate, ListView_onChange, }; diff --git a/hiro/windows/utility.cpp b/hiro/windows/utility.cpp index cbe5d8d1..a87e81e2 100644 --- a/hiro/windows/utility.cpp +++ b/hiro/windows/utility.cpp @@ -324,6 +324,13 @@ static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT ms } #if defined(Hiro_ListView) + case AppMessage::ListView_doPaint: { + if(auto listView = (mListView*)lparam) { + if(auto self = listView->self()) InvalidateRect(self->hwnd, nullptr, true); + } + break; + } + case AppMessage::ListView_onActivate: { if(auto listView = (mListView*)lparam) listView->doActivate(); break; diff --git a/hiro/windows/widget/list-view-cell.cpp b/hiro/windows/widget/list-view-cell.cpp index 90a41184..4cde02fa 100644 --- a/hiro/windows/widget/list-view-cell.cpp +++ b/hiro/windows/widget/list-view-cell.cpp @@ -18,6 +18,12 @@ auto pListViewCell::setIcon(const image& icon) -> void { } auto pListViewCell::setText(const string& text) -> void { + if(auto parent = _parent()) { + if(auto listView = parent->_parent()) { + //ListView uses a custom drawing routine; so we need to tell the control to repaint itself manually + PostMessageOnce(listView->_parentHandle(), AppMessage::ListView_doPaint, 0, (LPARAM)&listView->reference); + } + } } auto pListViewCell::_parent() -> maybe { diff --git a/sfc/chip/superfx/superfx.cpp b/sfc/chip/superfx/superfx.cpp index e339312d..8aec89c2 100644 --- a/sfc/chip/superfx/superfx.cpp +++ b/sfc/chip/superfx/superfx.cpp @@ -28,9 +28,9 @@ auto SuperFX::enter() -> void { continue; } - unsigned opcode = (regs.sfr & 0x0300) + peekpipe(); + unsigned opcode = regs.sfr.alt2 << 9 | regs.sfr.alt1 << 8 | peekpipe(); (this->*opcode_table[opcode])(); - if(r15_modified == false) regs.r[15]++; + if(!r15_modified) regs.r[15]++; } } diff --git a/target-tomoko/configuration/configuration.cpp b/target-tomoko/configuration/configuration.cpp index 333db7c9..92a7bc60 100644 --- a/target-tomoko/configuration/configuration.cpp +++ b/target-tomoko/configuration/configuration.cpp @@ -42,14 +42,14 @@ ConfigurationManager::ConfigurationManager() { timing.append(timing.audio, "Audio"); append(timing, "Timing"); - load({configpath(), "tomoko/settings.bml"}); + load(locate({configpath(), "tomoko/"}, "settings.bml")); if(!library.location) library.location = {userpath(), "Emulation/"}; if(!video.driver) video.driver = ruby::Video::safestDriver(); if(!audio.driver) audio.driver = ruby::Audio::safestDriver(); if(!input.driver) input.driver = ruby::Input::safestDriver(); - save({configpath(), "tomoko/settings.bml"}); + save(locate({configpath(), "tomoko/"}, "settings.bml")); } auto ConfigurationManager::quit() -> void { - save({configpath(), "tomoko/settings.bml"}); + save(locate({configpath(), "tomoko/"}, "settings.bml")); } diff --git a/target-tomoko/input/input.cpp b/target-tomoko/input/input.cpp index 88d74c10..6b08f8e2 100644 --- a/target-tomoko/input/input.cpp +++ b/target-tomoko/input/input.cpp @@ -172,8 +172,8 @@ InputManager::InputManager() { } appendHotkeys(); - config.load({configpath(), "tomoko/input.bml"}); - config.save({configpath(), "tomoko/input.bml"}); + config.load(locate({configpath(), "tomoko/"}, "input.bml")); + config.save(locate({configpath(), "tomoko/"}, "input.bml")); } auto InputManager::bind() -> void { @@ -217,7 +217,7 @@ auto InputManager::onChange(shared_pointer device, unsigned group, } auto InputManager::quit() -> void { - config.save({configpath(), "tomoko/input.bml"}); + config.save(locate({configpath(), "tomoko/"}, "input.bml")); emulators.reset(); hotkeys.reset(); } diff --git a/target-tomoko/program/media.cpp b/target-tomoko/program/media.cpp index de65f08b..74195095 100644 --- a/target-tomoko/program/media.cpp +++ b/target-tomoko/program/media.cpp @@ -16,7 +16,7 @@ auto Program::loadMedia(string location) -> void { auto Program::loadMedia(Emulator::Interface& _emulator, Emulator::Interface::Media& media, const string& location) -> void { unloadMedia(); - mediaPaths(0) = {userpath(), "Emulation/System/", media.name, ".sys/"}; + mediaPaths(0) = locate({userpath(), "Emulation/System/"}, {media.name, ".sys/"}); mediaPaths(media.id) = location; folderPaths.append(location); diff --git a/target-tomoko/tomoko.cpp b/target-tomoko/tomoko.cpp index 02e86748..e033fde2 100644 --- a/target-tomoko/tomoko.cpp +++ b/target-tomoko/tomoko.cpp @@ -4,6 +4,14 @@ Audio* audio = nullptr; Input* input = nullptr; Emulator::Interface* emulator = nullptr; +//if file already exists in the same path as the binary; use it (portable mode) +//if not, use default requested path (*nix/user mode) +auto locate(string pathname, string filename) -> string { + string location = {programpath(), filename}; + if(storage::exists(location)) return location; + return {pathname, filename}; +} + #include auto nall::main(lstring args) -> void { Application::setName("tomoko"); diff --git a/target-tomoko/tomoko.hpp b/target-tomoko/tomoko.hpp index f225240b..301c7220 100644 --- a/target-tomoko/tomoko.hpp +++ b/target-tomoko/tomoko.hpp @@ -17,3 +17,5 @@ extern Emulator::Interface* emulator; #include "settings/settings.hpp" #include "tools/tools.hpp" #include "presentation/presentation.hpp" + +auto locate(string pathname, string filename) -> string; diff --git a/target-tomoko/tools/cheat-database.cpp b/target-tomoko/tools/cheat-database.cpp index 553cb644..f6fd8a37 100644 --- a/target-tomoko/tools/cheat-database.cpp +++ b/target-tomoko/tools/cheat-database.cpp @@ -17,7 +17,7 @@ auto CheatDatabase::findCodes() -> void { if(!emulator) return; auto sha256 = emulator->sha256(); - auto contents = string::read({localpath(), "tomoko/cheats.bml"}); + auto contents = string::read(locate({localpath(), "tomoko/"}, "cheats.bml")); auto document = BML::unserialize(contents); for(auto cartridge : document.find("cartridge")) { diff --git a/target-tomoko/tools/state-manager.cpp b/target-tomoko/tools/state-manager.cpp index 0c739e51..ebca1b81 100644 --- a/target-tomoko/tools/state-manager.cpp +++ b/target-tomoko/tools/state-manager.cpp @@ -20,6 +20,8 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) { loadButton.setText("Load").onActivate([&] { doLoad(); }); resetButton.setText("Reset").onActivate([&] { doReset(); }); eraseButton.setText("Erase").onActivate([&] { doErase(); }); + + doUpdateControls(); } auto StateManager::doUpdateControls() -> void { @@ -33,7 +35,7 @@ auto StateManager::doUpdateControls() -> void { loadButton.setEnabled(true); eraseButton.setEnabled(true); } else { - descriptionValue.setEnabled(false); + descriptionValue.setEnabled(false).setText(""); loadButton.setEnabled(false); eraseButton.setEnabled(false); } @@ -43,18 +45,17 @@ auto StateManager::doChangeSelected() -> void { vector buffer; if(auto item = stateList.selected()) { buffer = file::read(program->stateName(1 + item.offset(), true)); + if(buffer.size() >= 584) { + string description; + description.reserve(512); + memory::copy(description.pointer(), buffer.data() + 72, 512); + description.resize(description.length()); + descriptionValue.setEnabled(true).setText(description); + return doUpdateControls(); + } } - if(buffer.size() >= 584) { - string description; - description.reserve(512); - memory::copy(description.pointer(), buffer.data() + 72, 512); - description.resize(description.length()); - descriptionValue.setText(description); - } else { - descriptionValue.setText(""); - } - + descriptionValue.setEnabled(false).setText(""); doUpdateControls(); }