2016-01-07 08:14:33 +00:00
|
|
|
#pragma once
|
2015-08-02 06:23:13 +00:00
|
|
|
|
|
|
|
//generic abstraction layer for common storage operations against both files and directories
|
|
|
|
//these functions are not recursive; use directory::create() and directory::remove() for recursion
|
|
|
|
|
|
|
|
#include <nall/platform.hpp>
|
|
|
|
#include <nall/string.hpp>
|
|
|
|
|
|
|
|
namespace nall {
|
|
|
|
|
Update to v097r17 release.
byuu says:
Changelog:
- ruby: if DirectSoundCreate fails (no sound device present), return
false from init instead of crashing
- nall: improved edge case return values for
(basename,pathname,dirname,...)
- nall: renamed file_system_object class to inode
- nall: varuint_t replaced with VariadicNatural; which contains
.bit,.bits,.byte ala Natural/Integer
- nall: fixed boolean compilation error on Windows
- WS: popa should not restore SP
- GBA: rewrote the CPU/APU cores to use the .bit,.bits functions;
removed registers.cpp from each
Note that the GBA changes are extremely major. This is about five hours
worth of extremely delicate work. Any slight errors could break
emulation in extremely bad ways. Let's hold off on extensive testing
until the next WIP, after I do the same to the PPU.
So far ... endrift's SOUNDCNT_X I/O test is failing, although that code
didn't change, so clearly I messed up SOUNDCNT_H somehow ...
To compile on Windows:
1. change nall/string/platform.hpp line 47 to
return slice(result, 0, 3);
2. change ruby/video.wgl.cpp line 72 to
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
3. add this line to the very top of hiro/windows/header.cpp:
#define boolean FuckYouMicrosoft
2016-02-23 11:08:44 +00:00
|
|
|
struct inode {
|
2018-09-02 14:06:41 +00:00
|
|
|
enum class time : uint { create, modify, access };
|
2015-08-02 06:23:13 +00:00
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
inode() = delete;
|
|
|
|
inode(const inode&) = delete;
|
|
|
|
auto operator=(const inode&) -> inode& = delete;
|
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
static auto exists(const string& name) -> bool {
|
|
|
|
return access(name, F_OK) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto readable(const string& name) -> bool {
|
|
|
|
return access(name, R_OK) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto writable(const string& name) -> bool {
|
|
|
|
return access(name, W_OK) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto executable(const string& name) -> bool {
|
|
|
|
return access(name, X_OK) == 0;
|
|
|
|
}
|
|
|
|
|
Update to bsnes v107.1 release.
byuu says:
Don't let the point release fool you, there are many significant changes in this
release. I will be keeping bsnes releases using a point system until the new
higan release is ready.
Changelog:
- GUI: added high DPI support
- GUI: fixed the state manager image preview
- Windows: added a new waveOut driver with support for dynamic rate control
- Windows: corrected the XAudio 2.1 dynamic rate control support [BearOso]
- Windows: corrected the Direct3D 9.0 fullscreen exclusive window centering
- Windows: fixed XInput controller support on Windows 10
- SFC: added high-level emulation for the DSP1, DSP2, DSP4, ST010, and Cx4
coprocessors
- SFC: fixed a slight rendering glitch in the intro to Megalomania
If the coprocessor firmware is missing, bsnes will fallback on HLE where it is
supported, which is everything other than SD Gundam GX and the two Hayazashi
Nidan Morita Shougi games.
The Windows dynamic rate control works best with Direct3D in fullscreen
exclusive mode. I recommend the waveOut driver over the XAudio 2.1 driver, as it
is not possible to target a single XAudio2 version on all Windows OS releases.
The waveOut driver should work everywhere out of the box.
Note that with DRC, the synchronization source is your monitor, so you will
want to be running at 60hz (NTSC) or 50hz (PAL). If you have an adaptive sync
monitor, you should instead use the WASAPI (exclusive) or ASIO audio driver.
2019-04-09 01:16:30 +00:00
|
|
|
static auto hidden(const string& name) -> bool {
|
|
|
|
#if defined(PLATFORM_WINDOWS)
|
|
|
|
auto attributes = GetFileAttributes(utf16_t(name));
|
|
|
|
return attributes & FILE_ATTRIBUTE_HIDDEN;
|
|
|
|
#else
|
|
|
|
//todo: is this really the best way to do this? stat doesn't have S_ISHIDDEN ...
|
|
|
|
return name.split("/").last().beginsWith(".");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-09-02 14:06:41 +00:00
|
|
|
static auto mode(const string& name) -> uint {
|
|
|
|
struct stat data{};
|
|
|
|
stat(name, &data);
|
|
|
|
return data.st_mode;
|
|
|
|
}
|
|
|
|
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
static auto uid(const string& name) -> uint {
|
2018-09-02 14:06:41 +00:00
|
|
|
struct stat data{};
|
2015-08-02 06:23:13 +00:00
|
|
|
stat(name, &data);
|
|
|
|
return data.st_uid;
|
|
|
|
}
|
|
|
|
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
static auto gid(const string& name) -> uint {
|
2018-09-02 14:06:41 +00:00
|
|
|
struct stat data{};
|
2015-08-02 06:23:13 +00:00
|
|
|
stat(name, &data);
|
|
|
|
return data.st_gid;
|
|
|
|
}
|
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
static auto owner(const string& name) -> string {
|
|
|
|
#if !defined(PLATFORM_WINDOWS)
|
2018-09-02 14:06:41 +00:00
|
|
|
struct passwd* pw = getpwuid(uid(name));
|
|
|
|
if(pw && pw->pw_name) return pw->pw_name;
|
2018-10-04 10:11:23 +00:00
|
|
|
#endif
|
2018-09-02 14:06:41 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto group(const string& name) -> string {
|
2018-10-04 10:11:23 +00:00
|
|
|
#if !defined(PLATFORM_WINDOWS)
|
2018-09-02 14:06:41 +00:00
|
|
|
struct group* gr = getgrgid(gid(name));
|
|
|
|
if(gr && gr->gr_name) return gr->gr_name;
|
2018-10-04 10:11:23 +00:00
|
|
|
#endif
|
2018-09-02 14:06:41 +00:00
|
|
|
return {};
|
2015-08-02 06:23:13 +00:00
|
|
|
}
|
|
|
|
|
Update to v100r16 release.
byuu says:
(Windows users may need to include <sys/time.h> at the top of
nall/chrono.hpp, not sure.)
Unchangelog:
- forgot to add the Scheduler clock=0 fix because I have the memory of
a goldfish
Changelog:
- new icarus database with nine additional games
- hiro(GTK,Qt) won't constantly write its settings.bml file to disk
anymore
- added latency simulator for fun (settings.bml => Input/Latency in
milliseconds)
So the last one ... I wanted to test out nall::chrono, and I was also
thinking that by polling every emulated frame, it's pretty wasteful when
you are using Fast Forward and hitting 200+fps. As I've said before,
calls to ruby::input::poll are not cheap.
So to get around this, I added a limiter so that if you called the
hardware poll function within N milliseconds, it'll return without
doing any actual work. And indeed, that increases my framerate of Zelda
3 uncapped from 133fps to 142fps. Yay. But it's not a "real" speedup,
as it only helps you when you exceed 100% speed (theoretically, you'd
need to crack 300% speed since the game itself will poll at 16ms at 100%
speed, but yet it sped up Zelda 3, so who am I to complain?)
I threw the latency value into the settings file. It should be 16,
but I set it to 5 since that was the lowest before it started negatively
impacting uncapped speeds. You're wasting your time and CPU cycles setting
it lower than 5, but if people like placebo effects it might work. Maybe
I should let it be a signed integer so people can set it to -16 and think
it's actually faster :P (I'm only joking. I took out the 96000hz audio
placebo effect as well. Not really into psychological tricks anymore.)
But yeah seriously, I didn't do this to start this discussion again for
the billionth time. Please don't go there. And please don't tell me this
WIP has higher/lower latency than before. I don't want to hear it.
The only reason I bring it up is for the fun part that is worth
discussing: put up or shut up time on how sensitive you are to
latency! You can set the value above 5 to see how games feel.
I personally can't really tell a difference until about 50. And I can't
be 100% confident it's worse until about 75. But ... when I set it to
150, games become "extra difficult" ... the higher it goes, the worse
it gets :D
For this WIP, I've left no upper limit cap. I'll probably set a cap of
something like 500ms or 1000ms for the official release. Need to balance
user error/trolling with enjoyability. I'll think about it.
[...]
Now, what I worry about is stupid people seeing it and thinking it's an
"added latency" setting, as if anyone would intentionally make things
worse by default. This is a limiter. So if 5ms have passed since the
game last polled, and that will be the case 99.9% of the time in games,
the next poll will happen just in time, immediately when the game polls
the inputs. Thus, a value below 1/<framerate>ms is not only pointless,
if you go too low it will ruin your fast forward max speeds.
I did say I didn't want to resort to placebo tricks, but I also don't
want to spark up public discussion on this again either. So it might
be best to default Input/Latency to 0ms, and internally have a max(5,
latency) wrapper around the value.
2016-08-03 12:32:40 +00:00
|
|
|
static auto timestamp(const string& name, time mode = time::modify) -> uint64_t {
|
2018-09-02 14:06:41 +00:00
|
|
|
struct stat data{};
|
2015-08-02 06:23:13 +00:00
|
|
|
stat(name, &data);
|
2018-09-02 14:06:41 +00:00
|
|
|
switch(mode) {
|
|
|
|
#if defined(PLATFORM_WINDOWS)
|
2018-09-04 05:44:35 +00:00
|
|
|
//on Windows, the last status change time (ctime) holds the file creation time instead
|
2018-09-02 14:06:41 +00:00
|
|
|
case time::create: return data.st_ctime;
|
2021-08-01 01:41:35 +00:00
|
|
|
#elif defined(__OpenBSD__)
|
|
|
|
// OpenBSD is a special case that must be handled separately from other BSDs
|
|
|
|
case time::create: return min((uint)data.__st_birthtime, (uint)data.st_mtime);
|
|
|
|
#elif defined (__DragonFly__)
|
|
|
|
// DragonFly BSD does not support file creation time, use modified time instead
|
|
|
|
case time::create: return data.st_mtime;
|
2018-09-04 05:44:35 +00:00
|
|
|
#elif defined(PLATFORM_BSD) || defined(PLATFORM_MACOS)
|
|
|
|
//st_birthtime may return -1 or st_atime if it is not supported by the file system
|
2018-09-02 14:06:41 +00:00
|
|
|
//the best that can be done in this case is to return st_mtime if it's older
|
|
|
|
case time::create: return min((uint)data.st_birthtime, (uint)data.st_mtime);
|
2018-09-04 05:44:35 +00:00
|
|
|
#else
|
|
|
|
//Linux simply doesn't support file creation time at all
|
|
|
|
//this is also our fallback case for unsupported operating systems
|
|
|
|
case time::create: return data.st_mtime;
|
2018-09-02 14:06:41 +00:00
|
|
|
#endif
|
2015-08-02 06:23:13 +00:00
|
|
|
case time::modify: return data.st_mtime;
|
2018-09-02 14:06:41 +00:00
|
|
|
//for performance reasons, last access time is usually not enabled on various filesystems
|
|
|
|
//ensure that the last access time is not older than the last modify time (eg for NTFS)
|
|
|
|
case time::access: return max((uint)data.st_atime, data.st_mtime);
|
2015-08-02 06:23:13 +00:00
|
|
|
}
|
2018-09-02 14:06:41 +00:00
|
|
|
return 0;
|
2015-08-02 06:23:13 +00:00
|
|
|
}
|
|
|
|
|
2018-10-04 10:11:23 +00:00
|
|
|
static auto setMode(const string& name, uint mode) -> bool {
|
|
|
|
#if !defined(PLATFORM_WINDOWS)
|
|
|
|
return chmod(name, mode) == 0;
|
|
|
|
#else
|
|
|
|
return _wchmod(utf16_t(name), (mode & 0400 ? _S_IREAD : 0) | (mode & 0200 ? _S_IWRITE : 0)) == 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto setOwner(const string& name, const string& owner) -> bool {
|
|
|
|
#if !defined(PLATFORM_WINDOWS)
|
|
|
|
struct passwd* pwd = getpwnam(owner);
|
|
|
|
if(!pwd) return false;
|
|
|
|
return chown(name, pwd->pw_uid, inode::gid(name)) == 0;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto setGroup(const string& name, const string& group) -> bool {
|
|
|
|
#if !defined(PLATFORM_WINDOWS)
|
|
|
|
struct group* grp = getgrnam(group);
|
|
|
|
if(!grp) return false;
|
|
|
|
return chown(name, inode::uid(name), grp->gr_gid) == 0;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto setTimestamp(const string& name, uint64_t value, time mode = time::modify) -> bool {
|
|
|
|
struct utimbuf timeBuffer;
|
|
|
|
timeBuffer.modtime = mode == time::modify ? value : inode::timestamp(name, time::modify);
|
|
|
|
timeBuffer.actime = mode == time::access ? value : inode::timestamp(name, time::access);
|
|
|
|
return utime(name, &timeBuffer) == 0;
|
|
|
|
}
|
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
//returns true if 'name' already exists
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
static auto create(const string& name, uint permissions = 0755) -> bool {
|
2015-08-02 06:23:13 +00:00
|
|
|
if(exists(name)) return true;
|
|
|
|
if(name.endsWith("/")) return mkdir(name, permissions) == 0;
|
|
|
|
int fd = open(name, O_CREAT | O_EXCL, permissions);
|
|
|
|
if(fd < 0) return false;
|
|
|
|
return close(fd), true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//returns false if 'name' and 'targetname' are on different file systems (requires copy)
|
|
|
|
static auto rename(const string& name, const string& targetname) -> bool {
|
|
|
|
return ::rename(name, targetname) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//returns false if 'name' is a directory that is not empty
|
|
|
|
static auto remove(const string& name) -> bool {
|
Update to v097r17 release.
byuu says:
Changelog:
- ruby: if DirectSoundCreate fails (no sound device present), return
false from init instead of crashing
- nall: improved edge case return values for
(basename,pathname,dirname,...)
- nall: renamed file_system_object class to inode
- nall: varuint_t replaced with VariadicNatural; which contains
.bit,.bits,.byte ala Natural/Integer
- nall: fixed boolean compilation error on Windows
- WS: popa should not restore SP
- GBA: rewrote the CPU/APU cores to use the .bit,.bits functions;
removed registers.cpp from each
Note that the GBA changes are extremely major. This is about five hours
worth of extremely delicate work. Any slight errors could break
emulation in extremely bad ways. Let's hold off on extensive testing
until the next WIP, after I do the same to the PPU.
So far ... endrift's SOUNDCNT_X I/O test is failing, although that code
didn't change, so clearly I messed up SOUNDCNT_H somehow ...
To compile on Windows:
1. change nall/string/platform.hpp line 47 to
return slice(result, 0, 3);
2. change ruby/video.wgl.cpp line 72 to
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
3. add this line to the very top of hiro/windows/header.cpp:
#define boolean FuckYouMicrosoft
2016-02-23 11:08:44 +00:00
|
|
|
#if defined(PLATFORM_WINDOWS)
|
|
|
|
if(name.endsWith("/")) return _wrmdir(utf16_t(name)) == 0;
|
|
|
|
return _wunlink(utf16_t(name)) == 0;
|
|
|
|
#else
|
2015-08-02 06:23:13 +00:00
|
|
|
if(name.endsWith("/")) return rmdir(name) == 0;
|
|
|
|
return unlink(name) == 0;
|
Update to v097r17 release.
byuu says:
Changelog:
- ruby: if DirectSoundCreate fails (no sound device present), return
false from init instead of crashing
- nall: improved edge case return values for
(basename,pathname,dirname,...)
- nall: renamed file_system_object class to inode
- nall: varuint_t replaced with VariadicNatural; which contains
.bit,.bits,.byte ala Natural/Integer
- nall: fixed boolean compilation error on Windows
- WS: popa should not restore SP
- GBA: rewrote the CPU/APU cores to use the .bit,.bits functions;
removed registers.cpp from each
Note that the GBA changes are extremely major. This is about five hours
worth of extremely delicate work. Any slight errors could break
emulation in extremely bad ways. Let's hold off on extensive testing
until the next WIP, after I do the same to the PPU.
So far ... endrift's SOUNDCNT_X I/O test is failing, although that code
didn't change, so clearly I messed up SOUNDCNT_H somehow ...
To compile on Windows:
1. change nall/string/platform.hpp line 47 to
return slice(result, 0, 3);
2. change ruby/video.wgl.cpp line 72 to
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
3. add this line to the very top of hiro/windows/header.cpp:
#define boolean FuckYouMicrosoft
2016-02-23 11:08:44 +00:00
|
|
|
#endif
|
2015-08-02 06:23:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|