diff --git a/higan/audio/audio.cpp b/higan/audio/audio.cpp index 9a7fcaa2..8404ced6 100644 --- a/higan/audio/audio.cpp +++ b/higan/audio/audio.cpp @@ -66,7 +66,7 @@ auto Audio::process() -> void { } for(auto c : range(channels)) { - samples[c] /= streams.size(); + samples[c] = max(-1.0, min(+1.0, samples[c] * volume)); if(reverbEnable) { samples[c] *= 0.125; @@ -74,8 +74,6 @@ auto Audio::process() -> void { for(auto n : range(7)) reverb[c][n].write(samples[c]); samples[c] *= 8.000; } - - samples[c] *= volume; } if(channels == 2) { diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 9b0c5f90..53ff9cd3 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -11,7 +11,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "099.15"; + static const string Version = "099.16"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/r65816/memory.hpp b/higan/processor/r65816/memory.hpp index ca862a02..35679e64 100644 --- a/higan/processor/r65816/memory.hpp +++ b/higan/processor/r65816/memory.hpp @@ -20,11 +20,11 @@ alwaysinline auto readLong(uint addr) -> uint8 { } alwaysinline auto readDB(uint addr) -> uint8 { - return read(r.db << 16 | uint16(addr)); + return read(uint24((r.db << 16) + addr)); //DB can cross page boundaries } alwaysinline auto readPB(uint addr) -> uint8 { - return read(r.pc.b << 16 | uint16(addr)); + return read(r.pc.b << 16 | uint16(addr)); //PB cannot cross page boundaries } alwaysinline auto readDP(uint addr) -> uint8 { @@ -61,7 +61,7 @@ alwaysinline auto writeLong(uint addr, uint8 data) -> void { } alwaysinline auto writeDB(uint addr, uint8 data) -> void { - write(r.db << 16 | uint16(addr), data); + write(uint24((r.db << 16) + addr), data); } alwaysinline auto writePB(uint addr, uint8 data) -> void { diff --git a/higan/sfc/ppu/io.cpp b/higan/sfc/ppu/io.cpp index e14980a2..d7443dd4 100644 --- a/higan/sfc/ppu/io.cpp +++ b/higan/sfc/ppu/io.cpp @@ -1,10 +1,10 @@ auto PPU::addressVRAM() const -> uint16 { uint16 address = io.vramAddress; switch(io.vramMapping) { - case 0: return (address); - case 1: return (address & 0xff00) | ((address & 0x001f) << 3) | ((address >> 5) & 7); - case 2: return (address & 0xfe00) | ((address & 0x003f) << 3) | ((address >> 6) & 7); - case 3: return (address & 0xfc00) | ((address & 0x007f) << 3) | ((address >> 7) & 7); + case 0: return address; + case 1: return address.bits( 8,15) << 8 | address.bits(0,4) << 3 | address.bits(5,7); + case 2: return address.bits( 9,15) << 9 | address.bits(0,5) << 3 | address.bits(6,8); + case 3: return address.bits(10,15) << 10 | address.bits(0,6) << 3 | address.bits(7,9); } unreachable; } @@ -37,7 +37,7 @@ auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 { return screen.cgram[addr].byte(byte); } -auto PPU::writeCGRAM(uint8 addr, uint16 data) -> void { +auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void { if(!io.displayDisable && vcounter() > 0 && vcounter() < vdisp() && hcounter() >= 88 && hcounter() < 1096 diff --git a/higan/sfc/ppu/ppu.hpp b/higan/sfc/ppu/ppu.hpp index 00ce4a19..16fb631d 100644 --- a/higan/sfc/ppu/ppu.hpp +++ b/higan/sfc/ppu/ppu.hpp @@ -24,7 +24,7 @@ struct PPU : Thread, PPUcounter { alwaysinline auto readOAM(uint10 addr) -> uint8; alwaysinline auto writeOAM(uint10 addr, uint8 data) -> void; alwaysinline auto readCGRAM(bool byte, uint8 addr) -> uint8; - alwaysinline auto writeCGRAM(uint8 addr, uint16 data) -> void; + alwaysinline auto writeCGRAM(uint8 addr, uint15 data) -> void; auto readIO(uint24 addr, uint8 data) -> uint8; auto writeIO(uint24 addr, uint8 data) -> void; auto latchCounters() -> void; diff --git a/higan/target-tomoko/program/medium.cpp b/higan/target-tomoko/program/medium.cpp index 3d8960af..bb6c6f2b 100644 --- a/higan/target-tomoko/program/medium.cpp +++ b/higan/target-tomoko/program/medium.cpp @@ -2,7 +2,7 @@ auto Program::loadMedium() -> void { if(!mediumQueue) return; string location = mediumQueue.left(); - string type = suffixname(location).trimLeft(".", 1L); + string type = Location::suffix(location).trimLeft(".", 1L); for(auto& emulator : emulators) { for(auto& medium : emulator->media) { diff --git a/higan/target-tomoko/program/program.cpp b/higan/target-tomoko/program/program.cpp index 6164d572..3464fbbb 100644 --- a/higan/target-tomoko/program/program.cpp +++ b/higan/target-tomoko/program/program.cpp @@ -29,6 +29,8 @@ Program::Program(string_vector args) { video->set(Video::Synchronize, settings["Video/Synchronize"].boolean()); if(!video->init()) video = Video::create("None"); + presentation->drawSplashScreen(); + audio = Audio::create(settings["Audio/Driver"].text()); audio->set(Audio::Device, settings["Audio/Device"].text()); audio->set(Audio::Handle, presentation->viewport.handle()); @@ -41,13 +43,13 @@ Program::Program(string_vector args) { input->onChange({&InputManager::onChange, &inputManager()}); if(!input->init()) input = Input::create("None"); - presentation->drawSplashScreen(); - new InputManager; new SettingsManager; new CheatDatabase; new ToolsManager; + presentation->setFocused(); + updateVideoShader(); updateAudioDriver(); updateAudioEffects(); @@ -58,6 +60,10 @@ Program::Program(string_vector args) { presentation->toggleFullScreen(); } else if(directory::exists(argument)) { mediumQueue.append(argument); + } else if(file::exists(argument)) { + if(auto result = execute("icarus", "--import", argument)) { + mediumQueue.append(result.output.strip()); + } } } loadMedium(); diff --git a/higan/target-tomoko/program/state.cpp b/higan/target-tomoko/program/state.cpp index a55484a9..68b37e07 100644 --- a/higan/target-tomoko/program/state.cpp +++ b/higan/target-tomoko/program/state.cpp @@ -21,7 +21,7 @@ auto Program::saveState(uint slot, bool manager) -> bool { auto location = stateName(slot, manager); serializer s = emulator->serialize(); if(s.size() == 0) return showMessage({"Failed to save state to slot ", slot}), false; - directory::create(pathname(location)); + directory::create(Location::path(location)); if(file::write(location, s.data(), s.size()) == false) { return showMessage({"Unable to write to slot ", slot}), false; } diff --git a/higan/target-tomoko/settings/audio.cpp b/higan/target-tomoko/settings/audio.cpp index f43faaa7..dbcacb1b 100644 --- a/higan/target-tomoko/settings/audio.cpp +++ b/higan/target-tomoko/settings/audio.cpp @@ -29,7 +29,7 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { frequencyCombo.setEnabled(false); resamplerLabel.setText("Resampler:"); - resamplerCombo.append(ComboButtonItem().setText("Sinc")); + resamplerCombo.append(ComboButtonItem().setText("IIR - Biquad")); resamplerCombo.setEnabled(false); exclusiveMode.setText("Exclusive Mode"); diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index aab5007c..7fce7784 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -120,7 +120,7 @@ auto BrowserDialogWindow::run() -> string_vector { pathName.onActivate([&] { setPath(pathName.text()); }); pathRefresh.setBordered(false).setIcon(Icon::Action::Refresh).onActivate([&] { setPath(state.path); }); pathHome.setBordered(false).setIcon(Icon::Go::Home).onActivate([&] { setPath(Path::user()); }); - pathUp.setBordered(false).setIcon(Icon::Go::Up).onActivate([&] { setPath(dirname(state.path)); }); + pathUp.setBordered(false).setIcon(Icon::Go::Up).onActivate([&] { setPath(Location::dir(state.path)); }); view.setBatchable(state.action == "openFiles").onActivate([&] { activate(); }).onChange([&] { change(); }); filterList.setVisible(state.action != "selectFolder").onChange([&] { setPath(state.path); }); for(auto& filter : state.filters) { @@ -156,7 +156,7 @@ auto BrowserDialogWindow::run() -> string_vector { auto BrowserDialogWindow::setPath(string path) -> void { path.transform("\\", "/"); - if(!path.endsWith("/")) path.append("/"); + if((path || Path::root() == "/") && !path.endsWith("/")) path.append("/"); pathName.setText(state.path = path); view.reset(); diff --git a/icarus/core/bs-memory.cpp b/icarus/core/bs-memory.cpp index ad41df54..65a46d64 100644 --- a/icarus/core/bs-memory.cpp +++ b/icarus/core/bs-memory.cpp @@ -22,7 +22,7 @@ auto Icarus::bsMemoryManifest(vector& buffer, string location) -> strin if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -32,8 +32,8 @@ auto Icarus::bsMemoryManifest(vector& buffer, string location) -> strin } auto Icarus::bsMemoryImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "BS Memory/", name, ".bs/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/core.cpp b/icarus/core/core.cpp index d6fdce06..e981f7ae 100644 --- a/icarus/core/core.cpp +++ b/icarus/core/core.cpp @@ -28,7 +28,7 @@ auto Icarus::manifest(string location) -> string { location.transform("\\", "/").trimRight("/").append("/"); if(!directory::exists(location)) return ""; - auto type = suffixname(location).downcase(); + auto type = Location::suffix(location).downcase(); if(type == ".fc") return famicomManifest(location); if(type == ".sfc") return superFamicomManifest(location); if(type == ".gb") return gameBoyManifest(location); @@ -47,8 +47,8 @@ auto Icarus::import(string location) -> string { if(!file::exists(location)) return failure("file does not exist"); if(!file::readable(location)) return failure("file is unreadable"); - auto name = prefixname(location); - auto type = suffixname(location).downcase(); + auto name = Location::prefix(location); + auto type = Location::suffix(location).downcase(); if(!name || !type) return failure("invalid file name"); auto buffer = file::read(location); @@ -59,8 +59,8 @@ auto Icarus::import(string location) -> string { if(!zip.open(location)) return failure("ZIP archive is invalid"); if(!zip.file) return failure("ZIP archive is empty"); - name = prefixname(zip.file[0].name); - type = suffixname(zip.file[0].name).downcase(); + name = Location::prefix(zip.file[0].name); + type = Location::suffix(zip.file[0].name).downcase(); buffer = zip.extract(zip.file[0]); } diff --git a/icarus/core/famicom.cpp b/icarus/core/famicom.cpp index 97b03a08..34f28517 100644 --- a/icarus/core/famicom.cpp +++ b/icarus/core/famicom.cpp @@ -24,7 +24,7 @@ auto Icarus::famicomManifest(vector& buffer, string location, uint* prg if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -38,8 +38,8 @@ auto Icarus::famicomManifest(vector& buffer, string location, uint* prg } auto Icarus::famicomImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Famicom/", name, ".fc/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/game-boy-advance.cpp b/icarus/core/game-boy-advance.cpp index 0549f1b6..40cfdbbe 100644 --- a/icarus/core/game-boy-advance.cpp +++ b/icarus/core/game-boy-advance.cpp @@ -22,7 +22,7 @@ auto Icarus::gameBoyAdvanceManifest(vector& buffer, string location) -> if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -32,8 +32,8 @@ auto Icarus::gameBoyAdvanceManifest(vector& buffer, string location) -> } auto Icarus::gameBoyAdvanceImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Game Boy Advance/", name, ".gba/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/game-boy-color.cpp b/icarus/core/game-boy-color.cpp index f92a80b2..db18c821 100644 --- a/icarus/core/game-boy-color.cpp +++ b/icarus/core/game-boy-color.cpp @@ -22,7 +22,7 @@ auto Icarus::gameBoyColorManifest(vector& buffer, string location) -> s if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -32,8 +32,8 @@ auto Icarus::gameBoyColorManifest(vector& buffer, string location) -> s } auto Icarus::gameBoyColorImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Game Boy Color/", name, ".gbc/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/game-boy.cpp b/icarus/core/game-boy.cpp index af9a4ff8..126c824a 100644 --- a/icarus/core/game-boy.cpp +++ b/icarus/core/game-boy.cpp @@ -22,7 +22,7 @@ auto Icarus::gameBoyManifest(vector& buffer, string location) -> string if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -32,8 +32,8 @@ auto Icarus::gameBoyManifest(vector& buffer, string location) -> string } auto Icarus::gameBoyImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Game Boy/", name, ".gb/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/sufami-turbo.cpp b/icarus/core/sufami-turbo.cpp index f03a4c51..6179297f 100644 --- a/icarus/core/sufami-turbo.cpp +++ b/icarus/core/sufami-turbo.cpp @@ -22,7 +22,7 @@ auto Icarus::sufamiTurboManifest(vector& buffer, string location) -> st if(markup = cartridge.markup) { markup.append("\n"); markup.append("information\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -32,8 +32,8 @@ auto Icarus::sufamiTurboManifest(vector& buffer, string location) -> st } auto Icarus::sufamiTurboImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Sufami Turbo/", name, ".st/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/super-famicom.cpp b/icarus/core/super-famicom.cpp index f305e80b..fc4d12d6 100644 --- a/icarus/core/super-famicom.cpp +++ b/icarus/core/super-famicom.cpp @@ -31,7 +31,7 @@ auto Icarus::superFamicomManifest(vector& buffer, string location, bool markup.append("\n"); markup.append("information\n"); markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n"); - markup.append(" title: ", prefixname(location), "\n"); + markup.append(" title: ", Location::prefix(location), "\n"); markup.append(" sha256: ", digest, "\n"); markup.append(" note: ", "heuristically generated by icarus\n"); } @@ -46,8 +46,8 @@ auto Icarus::superFamicomManifestScan(vector& roms, Markup::Node n } auto Icarus::superFamicomImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "Super Famicom/", name, ".sfc/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/wonderswan-color.cpp b/icarus/core/wonderswan-color.cpp index 63a7076f..212daddd 100644 --- a/icarus/core/wonderswan-color.cpp +++ b/icarus/core/wonderswan-color.cpp @@ -26,8 +26,8 @@ auto Icarus::wonderSwanColorManifest(vector& buffer, string location) - } auto Icarus::wonderSwanColorImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "WonderSwan Color/", name, ".wsc/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/core/wonderswan.cpp b/icarus/core/wonderswan.cpp index 34ffe133..df8199be 100644 --- a/icarus/core/wonderswan.cpp +++ b/icarus/core/wonderswan.cpp @@ -26,8 +26,8 @@ auto Icarus::wonderSwanManifest(vector& buffer, string location) -> str } auto Icarus::wonderSwanImport(vector& buffer, string location) -> string { - auto name = prefixname(location); - auto source = pathname(location); + auto name = Location::prefix(location); + auto source = Location::path(location); string target{settings["Library/Location"].text(), "WonderSwan/", name, ".ws/"}; //if(directory::exists(target)) return failure("game already exists"); diff --git a/icarus/heuristics/wonderswan.cpp b/icarus/heuristics/wonderswan.cpp index 40fe3800..7491909b 100644 --- a/icarus/heuristics/wonderswan.cpp +++ b/icarus/heuristics/wonderswan.cpp @@ -45,7 +45,7 @@ WonderSwanCartridge::WonderSwanCartridge(string location, uint8_t* data, uint si manifest.append(" rtc name=rtc.ram size=16\n"); manifest.append("\n"); manifest.append("information\n"); - manifest.append(" title: ", prefixname(location), "\n"); + manifest.append(" title: ", Location::prefix(location), "\n"); manifest.append(" orientation: ", !information.orientation ? "horizontal" : "vertical", "\n"); manifest.append(" sha256: ", Hash::SHA256(data, size).digest(), "\n"); manifest.append("\n"); diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp index 248dc14e..b3df6cd6 100644 --- a/icarus/icarus.cpp +++ b/icarus/icarus.cpp @@ -69,7 +69,7 @@ auto nall::main(string_vector args) -> void { .setFilters("ROM Files|*.fc:*.nes:*.sfc:*.smc:*.gb:*.gbc:*.gba:*.ws:*.wsc:*.bs:*.st:*.zip") .openFile()) { if(string target = icarus.import(source)) { - settings["icarus/Path"].setValue(pathname(source)); + settings["icarus/Path"].setValue(Location::path(source)); return print(target, "\n"); } } diff --git a/icarus/ui/import-dialog.cpp b/icarus/ui/import-dialog.cpp index 46223182..4a88f01d 100644 --- a/icarus/ui/import-dialog.cpp +++ b/icarus/ui/import-dialog.cpp @@ -20,7 +20,7 @@ auto ImportDialog::run(string_vector locations) -> void { setVisible(true); for(auto& location : locations) { - auto name = nall::basename(location); + auto name = Location::base(location); if(abort) { errors.append(string{"[", name, "] aborted"}); diff --git a/icarus/ui/scan-dialog.cpp b/icarus/ui/scan-dialog.cpp index f9c6a2cd..f7c2a33f 100644 --- a/icarus/ui/scan-dialog.cpp +++ b/icarus/ui/scan-dialog.cpp @@ -13,7 +13,7 @@ ScanDialog::ScanDialog() { refresh(); }); upButton.setIcon(Icon::Go::Up).setBordered(false).onActivate([&] { - pathEdit.setText(dirname(settings["icarus/Path"].text())); + pathEdit.setText(Location::dir(settings["icarus/Path"].text())); refresh(); }); scanList.onActivate([&] { activate(); }); @@ -57,13 +57,13 @@ auto ScanDialog::refresh() -> void { for(auto& name : contents) { if(!name.endsWith("/")) continue; - if(gamePakType(suffixname(name))) continue; + if(gamePakType(Location::suffix(name))) continue; scanList.append(ListViewItem().setIcon(Icon::Emblem::Folder).setText(name.trimRight("/"))); } for(auto& name : contents) { if(name.endsWith("/")) continue; - if(!gameRomType(suffixname(name).downcase())) continue; + if(!gameRomType(Location::suffix(name).downcase())) continue; scanList.append(ListViewItem().setCheckable().setIcon(Icon::Emblem::File).setText(name)); } @@ -74,7 +74,7 @@ auto ScanDialog::refresh() -> void { auto ScanDialog::activate() -> void { if(auto item = scanList.selected()) { string location{settings["icarus/Path"].text(), item.text()}; - if(directory::exists(location) && !gamePakType(suffixname(location))) { + if(directory::exists(location) && !gamePakType(Location::suffix(location))) { pathEdit.setText(location); refresh(); } diff --git a/nall/directory.hpp b/nall/directory.hpp index 7939635b..04eaf4b4 100644 --- a/nall/directory.hpp +++ b/nall/directory.hpp @@ -101,7 +101,19 @@ private: } inline auto directory::ufolders(const string& pathname, const string& pattern) -> string_vector { - auto list; + if(!pathname) { + //special root pseudo-folder (return list of drives) + wchar_t drives[PATH_MAX] = {0}; + GetLogicalDriveStrings(PATH_MAX, drives); + wchar_t* p = drives; + while(*p || *(p + 1)) { + if(!*p) *p = ';'; + *p++; + } + return string{(const char*)utf8_t(drives)}.replace("\\", "/").split(";"); + } + + string_vector list; string path = pathname; path.transform("/", "\\"); if(!path.endsWith("\\")) path.append("\\"); @@ -131,6 +143,8 @@ private: } inline auto directory::ufiles(const string& pathname, const string& pattern) -> string_vector { + if(!pathname) return {}; + string_vector list; string path = pathname; path.transform("/", "\\"); @@ -194,6 +208,8 @@ private: } inline auto directory::ufolders(const string& pathname, const string& pattern) -> string_vector { + if(!pathname) return string_vector{"/"}; + string_vector list; DIR* dp; struct dirent* ep; @@ -213,6 +229,8 @@ private: } inline auto directory::ufiles(const string& pathname, const string& pattern) -> string_vector { + if(!pathname) return {}; + string_vector list; DIR* dp; struct dirent* ep; diff --git a/nall/http/response.hpp b/nall/http/response.hpp index 4051665d..2e2c12e4 100644 --- a/nall/http/response.hpp +++ b/nall/http/response.hpp @@ -166,7 +166,7 @@ auto Response::findContentLength() const -> unsigned { auto Response::findContentType() const -> string { if(auto contentType = header["Content-Type"]) return contentType.value(); if(hasData()) return "application/octet-stream"; - if(hasFile()) return findContentType(suffixname(file())); + if(hasFile()) return findContentType(Location::suffix(file())); return "text/html; charset=utf-8"; } diff --git a/nall/string/path.hpp b/nall/location.hpp similarity index 86% rename from nall/string/path.hpp rename to nall/location.hpp index eac881bf..7d89d29a 100644 --- a/nall/string/path.hpp +++ b/nall/location.hpp @@ -1,10 +1,10 @@ #pragma once -namespace nall { +namespace nall { namespace Location { // (/parent/child.type/) // (/parent/child.type/)name.type -auto pathname(string_view self) -> string { +inline auto path(string_view self) -> string { const char* p = self.data() + self.size() - 1; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/') return slice(self, 0, offset + 1); @@ -14,7 +14,7 @@ auto pathname(string_view self) -> string { // /parent/child.type/() // /parent/child.type/(name.type) -auto filename(string_view self) -> string { +inline auto file(string_view self) -> string { const char* p = self.data() + self.size() - 1; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/') return slice(self, offset + 1); @@ -24,7 +24,7 @@ auto filename(string_view self) -> string { // (/parent/)child.type/ // (/parent/child.type/)name.type -auto dirname(string_view self) -> string { +inline auto dir(string_view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -35,7 +35,7 @@ auto dirname(string_view self) -> string { // /parent/(child.type/) // /parent/child.type/(name.type) -auto basename(string_view self) -> string { +inline auto base(string_view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -46,7 +46,7 @@ auto basename(string_view self) -> string { // /parent/(child).type/ // /parent/child.type/(name).type -auto prefixname(string_view self) -> string { +inline auto prefix(string_view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1, suffix = -1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -59,7 +59,7 @@ auto prefixname(string_view self) -> string { // /parent/child(.type)/ // /parent/child.type/name(.type) -auto suffixname(string_view self) -> string { +inline auto suffix(string_view self) -> string { const char* p = self.data() + self.size() - 1, *last = p; for(int offset = self.size() - 1; offset >= 0; offset--, p--) { if(*p == '/' && p == last) continue; @@ -69,4 +69,4 @@ auto suffixname(string_view self) -> string { return ""; //no suffix found } -} +}} diff --git a/nall/nall.hpp b/nall/nall.hpp index 24389e02..fa40e838 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/nall/path.hpp b/nall/path.hpp index 945a144b..360c8d34 100644 --- a/nall/path.hpp +++ b/nall/path.hpp @@ -17,7 +17,7 @@ inline auto active() -> string { inline auto real(string_view name) -> string { string result; char path[PATH_MAX] = ""; - if(::realpath(name, path)) result = pathname(string{path}.transform("\\", "/")); + if(::realpath(name, path)) result = Location::path(string{path}.transform("\\", "/")); if(!result) return active(); result.transform("\\", "/"); if(!result.endsWith("/")) result.append("/"); diff --git a/nall/string.hpp b/nall/string.hpp index 4c3f5ce6..2d190d6d 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -73,15 +73,6 @@ inline auto pointer(uintptr_t value, long precision = 0) -> string; inline auto tokenize(const char* s, const char* p) -> bool; inline auto tokenize(string_vector& list, const char* s, const char* p) -> bool; -//path.hpp -inline auto pathname(string_view self) -> string; -inline auto filename(string_view self) -> string; - -inline auto dirname(string_view self) -> string; -inline auto basename(string_view self) -> string; -inline auto prefixname(string_view self) -> string; -inline auto suffixname(string_view self) -> string; - //utility.hpp inline auto slice(string_view self, int offset = 0, int length = -1) -> string; inline auto fromInteger(char* result, intmax_t value) -> char*; @@ -329,7 +320,6 @@ struct string_format : vector { #include #include #include -#include #include #include #include diff --git a/nall/string/transform/cml.hpp b/nall/string/transform/cml.hpp index de7aa0a9..0d1935b5 100644 --- a/nall/string/transform/cml.hpp +++ b/nall/string/transform/cml.hpp @@ -4,6 +4,8 @@ * revision 0.02 */ +#include + namespace nall { namespace { struct CML { @@ -33,7 +35,7 @@ private: }; auto CML::parse(const string& filename) -> string { - if(!settings.path) settings.path = pathname(filename); + if(!settings.path) settings.path = Location::path(filename); string document = settings.reader ? settings.reader(filename) : string::read(filename); parseDocument(document, settings.path, 0); return state.output; @@ -61,7 +63,7 @@ auto CML::parseDocument(const string& filedata, const string& pathname, uint dep name.trimLeft("include ", 1L); string filename{pathname, name}; string document = settings.reader ? settings.reader(filename) : string::read(filename); - parseDocument(document, nall::pathname(filename), depth + 1); + parseDocument(document, Location::path(filename), depth + 1); continue; } diff --git a/nall/string/transform/dml.hpp b/nall/string/transform/dml.hpp index 32dcf1d8..4e7bda44 100644 --- a/nall/string/transform/dml.hpp +++ b/nall/string/transform/dml.hpp @@ -4,6 +4,8 @@ * revision 0.03 */ +#include + namespace nall { namespace { struct DML { @@ -45,7 +47,7 @@ auto DML::parse(const string& filedata, const string& pathname) -> string { } auto DML::parse(const string& filename) -> string { - if(!settings.path) settings.path = pathname(filename); + if(!settings.path) settings.path = Location::path(filename); string document = settings.reader ? settings.reader(filename) : string::read(filename); parseDocument(document, settings.path, 0); return state.output; @@ -68,7 +70,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool if(block.beginsWith("")) { string filename{pathname, block.trim("", 1L).strip()}; string document = settings.reader ? settings.reader(filename) : string::read(filename); - parseDocument(document, nall::pathname(filename), depth + 1); + parseDocument(document, Location::path(filename), depth + 1); } //html diff --git a/nall/windows/registry.hpp b/nall/windows/registry.hpp index 572a78c2..d58ff186 100644 --- a/nall/windows/registry.hpp +++ b/nall/windows/registry.hpp @@ -80,7 +80,8 @@ struct registry { } static auto contents(const string& name) -> string_vector { - auto part = name.split("/"), result; + string_vector result; + auto part = name.split("/"); HKEY handle, rootKey = root(part.takeLeft()); part.removeRight(); string path = part.merge("\\"); diff --git a/ruby/input/joypad/udev.cpp b/ruby/input/joypad/udev.cpp index 941175c0..6c02a7cf 100644 --- a/ruby/input/joypad/udev.cpp +++ b/ruby/input/joypad/udev.cpp @@ -257,7 +257,7 @@ private: auto createJoypadHID(Joypad& jp) -> void { uint64_t pathID = Hash::CRC32(jp.deviceName.data(), jp.deviceName.size()).value(); - jp.hid->setID(pathID << 32 | hex(jp.vendorID) << 16 | hex(jp.productID) << 0); + jp.hid->setID(pathID << 32 | jp.vendorID.hex() << 16 | jp.productID.hex() << 0); for(unsigned n = 0; n < jp.axes.size(); n++) jp.hid->axes().append(n); for(unsigned n = 0; n < jp.hats.size(); n++) jp.hid->hats().append(n);