Prevent Vulkan Swap before display context is assigned.
Prevent resize while fullscreen (like in windows impl).
Use superclass Resize implementation to reduce code duplication.
Remove recursive call to GTKWindow::Close().
Destroy xcb window after superclass Close().
Set hwnd to null after closing on windows implementation.
Games like Forza use NtQueryInformationFile to get the size of the file, to make sure that there's enough room inside it to write data.
Previously, updating the file size (via SetInfoFile(EndOfFile) or WriteFile) wouldn't update the vfs::Entry size field, which NtQueryInfo uses to return the size of the file.
This resulted in the game thinking that the file was smaller than it actually is, and trying to correct that by using SetInfoFile(EndOfFile), which then truncated the file and deleted important data that was written to it.
Check TracerPid in /proc/self/status for attached debugger.
Add SIGTRAP handler to prevent signal from halting app while not running
in a debugger.
Log DebugPrint in clog (stderr).
va_list are not guarenteed to maintain their values after being used.
With clang on Linux, args is undefined after fetching length and will print
"(null)".
Copy args into another va_list before getting length to prevent this.
Add tests.
Expand find_base_path to support unix-style and local files.
Remove trailing path separators from find_base_path output.
Fix cases of local files such as `find_base_path("local_file")`
Fix logger creating directories such as xenia.log/ when run from a local
directory such as with ./build/bin/xenia under linux creating a directory
called xenia.log/ and then being unable to create a log of the same name.
Add tests to validate find_base_path.
Add suspend count to thread implementation.
Increment suspend count on suspend and decrement on resume.
Wait on suspend count to be decremented to 0.
Return suspend count on suspend and on resume before incr/decr.
Fix naming of resume suspend count to make clear that suspend count is
before incr/decr.
Add test.
Shorten names to 16.
Rename Win32 to Windowing.
Shorten GraphicsSystem thread names due to 16 length limit of pthread.
Without this change, both show up as GraphicsSystem.
Remove redundant "Worker" and "Thread" from names.
Remove redundant thread handle from thread name.
Add thread local bool for alertable state.
Use real-time event interrupt to run callback.
Fix sleep duration from miliseconds (microseconds / 1000) to seconds in sleep
command.
Add note for future implementation.
Ignore real-time event 37 in .gdbinit which is used to signal callback.
Test AlertableSleep
Test Thread QueueUserCallback.
TODO: Test alerted wait result when using IO functions.
Use real-time event interrupt to communicate suspend in timely manner.
Use conditional_variable to implement suspend wait and resume trigger.
Ignore real-time event 36 in .gdbinit which is used to signal suspend.
Test suspending threads.
Test Manual Reset and Synchronization timers single threaded.
Test Cancelling timers.
Test WaitMultiple.
Ignore real-time event 35 in .gdbinit which is used to signal timer.
Callbacks don't seem to be called so testing them is difficult.
Keep track of recursive locks with owner and count of locks.
Only allow recursive locks from same thread and increment count.
Only allow first locks from when count is zero.
Test acquiring and releasing mutant on same and on different threads.
Test Release return values.
Test WaitAll and WaitAny.
Test acquiring and releasing semaphores on same and on different threads.
Test previous_count values.
Test WaitAll and WaitAny.
Add tests for invalid semaphore creation parameters but disactivated as
they do not pass on any platform. These should be enabled and the
implementations fixed to match documentation.
Add PosixConditionBase as base class for Waitables to use common
primitives mutex and conditional variable
Add abstract signaled() and post_execution() to use single WaitMultiple
implementation.
Remove file-descriptor specific wait implementation to PosixFdHandle class
which breaks on waits of non-fd handles.
Replace with PosixConditionHandle and extend to support auto reset and
initial values.
Simplify mutex and conditional variable use with stdlib versions which
wrap these primitives but provide better C++ interface.
Test Event and Reset
Fix issue in clang where args were inverted last to first due to the way
c++ implements function calls.
The function make_tuple, being a function, has undefined ordering of
resolution of the values of its parameters `Ps(init)` and would vary
between compilers. Namely clang would resolve them in order and msvc would
resolve them in reverse order.
This normally would not matter except for the fact that init maintains a
mutable state which is affected my the order of operations: init.ordinal
is a counter and also defines where in memory a value is stored.
The C++ standard doesn't define an order of resolution of parameters in a
function but it will define an order in a brace-initializer.
Switching make_tuple for a brace-initializer enforces an order which is the
same between all compilers (tested gcc, clang and msvc).
Prior code was written to decrement ordinal due to the reverse traversal.
This has been switched to incrementing thanks to the in-order traversal.
shm_unlink(name) is the proper way to close a shared memory in linux.
Prior to this, xenia was creating and not cleaning up shared memory handle
which would accumulate in /dev/shm. shm_unlink is the proper way of doing
this.
Add filename to CloseFileMappingHandle signature.
Add simple test to open and close.
CreateFileMappingHandle now takes shared memory name without a prefix.
The doc of shm_open recommends not using slashes and prefixing with "/".
The prefixing has been moved to the os implementation layer.
Invocations of CreateFileMappingHandle were all using "Local\\" so these
prefixes were removed.
Remove atomic boolean in fence. Variable signaled_ is already protected
by mutex.
Remove wait loop with single predicate wait protected with mutex.
Add Fence Signal and Wait tests
Test signaling without waiting.
Test signaling before waiting.
Test signaling twice before waiting.
Test synchronizing threads with fence.
Few REQUIRES were used to test as there are no return codes.
A failing test may hang indefinitely or cause a segfault which would still
register as a fail.
Implement HighResolutionTimer for Posix by using native timers.
Callbacks are triggered with realtime interrupts if they are supported.
Create an enum to track user-defined interrupts as well as an initializer and
handler to register these interrupts per thread.
Add test cases for timers for both single and multiple.
Fix Sleep function to continue sleeping if interrupted by system.
Add local .gdbinit to ignore signal 34 which is used by high res timer
Add Sleep Test for 50ms.
Fix Sleep under linux that was using microseconds as nanoseconds.
Factor timespec creation to template function using div/mod and nanoseconds
from duration cast.
Test logical_processor_count() 3 times to test static return value stays
correct.
Run EnableAffinityConfiguration(). No asserts possible.
Test setting thread id, test using uint32_t max to reset.
Test setting thread name. No asserts possible.
Test running MaybeYield(). No obvious more complex test case.
Test running SyncMemory(). No obvious more complex test case.
This should let Xenia load in Account files from an actual 360, one step closer to fully supporting 360 profiles!
Only decrypts/reads atm, but the code is there for re-encrypting, maybe once new UI is ready we can make use of that for creating new 360-compatible profiles?
Also added more error checking, and changed XELOG statements that use %ws to use %s & xe::to_string instead, seems to_string handles some non-latin strings better than %ws does.
For example if a user applies a TU that adds achievements after already running the non-patched game, this should add any new achievements it finds.
Will also update the last_played time of a title when the SPA gets loaded in (on game launch), and also set the unlock_time when unlocking achievements.
Unlocking also only updates the title GPD (+ dash GPD) now, instead of needing to rewrite every GPD.
Velocity should now load Xenia-created GPDs fine :D
To try it just make a new profile package in Velocity, inject GPDs from Xenia, and inject random Account file from a 360 profile.
Then close created package, use Tools -> Profile Tools -> Profile Editor to open the package you just created, and if all goes well the profile should load up fine.
Seems to work fine, tested with Tetris TGM ACE which uses achievements to track progression & unlock things in the game, and unlocking achievements in the GPDs does unlock things in game as intended.
Haven't actually tested unlocking the achievements in-game and then checking though (my tetris skills are awful :P), but I think it should work fine.
Strings aren't copied into it yet since I didn't want to alloc guest memory for every CreateEnumerator call...
Not many games actually have in-game achievement lists though, but I've added a placeholder string for any that might.
Like said in the comment, maybe we should alloc those strings in guest mem when the game GPD/SPA is first loaded in?
XGIUserWriteAchievements seems to be the main (only?) way achievements are unlocked, when used that'll now try getting the GPD from UserProfile and unlock the achievements passed to it.
Dash GPD info is recalced and GPDs get written to disk whenever achievements are unlocked, letting achievements persist across instances.
TODO:
- "Achievement Unlocked!" UI, writing to log isn't much of an indicator :P
- XamUserCreateAchievementEnumerator, needs to return XACHIEVEMENT_DETAILS structs, which also contain pointers to strings in guest memory...
- Copy over more data from SPA? (need to check what data 360 copies to it)
- Optimize GPD writing, atm every GPD gets rewritten even if it hasn't been changed...
- Change profile folder path? Maybe allow using 360 profiles eventually?
- GPD settings
UserProfile will now try loading dash GPD + any game GPDs from the "profile" folder when initialized.
After loading an XEX the title's SPA data gets passed to UserProfile, which will then either set current GPD based on title ID in the SPA, or create new GPD and copy achievements/images over to it.
Eventually user_profile would read dash GPD, loop through XdbfTitlePlayed entries, load GPD for each one...
Also eventually settings will be stored in dash GPD (eg. the ones currently defined in user_profile.cc)
XdbfWrapper would only wrap existing in-memory data, making modifying data (or creating new data) non-trivial.
The new XdbfFile class parses all the XDBF stuff into different vectors, making modifications a lot easier.
GpdFile and SpaFile are both children of XdbfWrapper, SpaFile has the same functions as the older XdbfGameData class, but now includes support for parsing achievements too.
The GpdFile class also supports achievements, and both classes parse into a common XdbfAchievement struct, which makes it simple to eg. copy achievements from a SPA file into a new GPD file.
TODO:
- images?
- GPD settings (user_profile has some code for this, not sure how much we can use here though...)
- modify user_profile to make use of this