mirror of https://github.com/bsnes-emu/bsnes.git
Update to v099r16 release (public beta).
byuu says: Changelog: - hiro: BrowserDialog can navigate up to drive selection on Windows - nall: (file,path,dir,base,prefix,suffix)name => Location::(file,path,dir,base,prefix,suffix) - higan/tomoko: rename audio filter label from "Sinc" to "IIR - Biquad" - higan/tomoko: allow loading files via icarus on the command-line once again - higan/tomoko: (begrudging) quick hack to fix presentation window focus on startup - higan/audio: don't divide output audio volume by number of streams - processor/r65816: fix a regression in (read,write)DB; fixes Taz-Mania - fixed compilation regressions on Windows and Linux I'm happy with where we are at with code cleanups and stability, so I'd like to release v100. But even though I'm not assigning any special significance to this version, we should probably test it more thoroughly first.
This commit is contained in:
parent
8d5cc0c35e
commit
13ad9644a2
|
@ -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) {
|
||||
|
|
|
@ -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/";
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -22,7 +22,7 @@ auto Icarus::bsMemoryManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location) -> strin
|
|||
}
|
||||
|
||||
auto Icarus::bsMemoryImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ auto Icarus::famicomManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location, uint* prg
|
|||
}
|
||||
|
||||
auto Icarus::famicomImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ auto Icarus::gameBoyAdvanceManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location) ->
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyAdvanceImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ auto Icarus::gameBoyColorManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location) -> s
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyColorImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ auto Icarus::gameBoyManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location) -> string
|
|||
}
|
||||
|
||||
auto Icarus::gameBoyImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ auto Icarus::sufamiTurboManifest(vector<uint8_t>& 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<uint8_t>& buffer, string location) -> st
|
|||
}
|
||||
|
||||
auto Icarus::sufamiTurboImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ auto Icarus::superFamicomManifest(vector<uint8_t>& 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<Markup::Node>& roms, Markup::Node n
|
|||
}
|
||||
|
||||
auto Icarus::superFamicomImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ auto Icarus::wonderSwanColorManifest(vector<uint8_t>& buffer, string location) -
|
|||
}
|
||||
|
||||
auto Icarus::wonderSwanColorImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ auto Icarus::wonderSwanManifest(vector<uint8_t>& buffer, string location) -> str
|
|||
}
|
||||
|
||||
auto Icarus::wonderSwanImport(vector<uint8_t>& 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");
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"});
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}}
|
|
@ -32,6 +32,7 @@
|
|||
#include <nall/inode.hpp>
|
||||
#include <nall/interpolation.hpp>
|
||||
#include <nall/intrinsics.hpp>
|
||||
#include <nall/location.hpp>
|
||||
#include <nall/map.hpp>
|
||||
#include <nall/matrix.hpp>
|
||||
#include <nall/maybe.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("/");
|
||||
|
|
|
@ -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<string> {
|
|||
#include <nall/string/format.hpp>
|
||||
#include <nall/string/list.hpp>
|
||||
#include <nall/string/match.hpp>
|
||||
#include <nall/string/path.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
#include <nall/string/split.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* revision 0.02
|
||||
*/
|
||||
|
||||
#include <nall/location.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* revision 0.03
|
||||
*/
|
||||
|
||||
#include <nall/location.hpp>
|
||||
|
||||
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("<include ") && block.endsWith(">")) {
|
||||
string filename{pathname, block.trim("<include ", ">", 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
|
||||
|
|
|
@ -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("\\");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue