By using a shm memory segment for the fast_block_map that is sparsely
allocated (i.e. on write by the OS) instead of a statically allocated
array we can make the block lookup faster by:
* Having a bigger space available for lookup that doesn't take up
too much memory, because the OS will only allocate the needed
pages when written to.
* Decrease the time spent to lookup a block in the assembly dispatcher
due to less comparisions and shorter code (for example the pc check
has been entirely dropped since only the msrBits need to be validated).
When the JIT block cache is full the shm segment will also be released
and reallocated to avoid allocating too much memory. It will also be
reset when the instruction cache is flushed by the PPC code to avoid
having stale entries.
Also fallback to the original method in case the memory segment couldn't
be allocated.
FSCore implements the core functionality that can also be used outside of emulation. FSDevice implements the IOS device and is only available during emulation.
ESCore implements the core functionality that can also be used outside of emulation. ESDevice implements the IOS device and is only available during emulation.
DoFrame is a function called every frame by the emulator so that rcheevos can be properly updated and processed. It requires a memory peeker and an event handler to be passed in; the memory peeker is called repeatedly each frame to measure what's in memory and compare to achievement definitions, and any events thrown by that comparison are sent to the event handler.
Also, DoFrame checks for the current system time to determine when to ping rich presence. Rich Presence on the RetroAchievements website updates every two minutes, so if two minutes have elapsed since the previous ping, another ping is sent.
GenerateRichPresence calls rc_runtime_get_richpresence in rhceevos on the achievement runtime to get the current Rich Presence string, a description of the player's current in-game state based on its memory as fed into a custom-developed script downloaded via FetchGameData. This gets passed into PingRichPresence, but is separated into its own method so it can be used elsewhere locally.
MemoryPeeker is a function passed by pointer into rcheevos DoFrame functionality that forms the lynchpin of the rcheevos runtime - it provides the interface by which rcheevos accesses memory and determines if the fields provided by achievement, leaderboard, and rich presence definitions are meeting the criteria needed.
AchievementEventHandler simply checks which kind of event is triggered and calls the appropriate function. Its primary purpose is as a function to be pointed to.
HandleAchievementTriggeredEvent is an asynchronous method that processes an event and places a synchronous AwardAchievement call on the work queue. In the process, it also updates the unlock map and makes the ActivateDeactivateAchievement call to determine and adjust the achievement's current active state.
PingRichPresence makes a "ping" API request to the RetroAchievements website with the provided RichPresence string parameter. While there has been talk about tying ping in with session, in its current state the primary purpose of ping is to send the player's Rich Presence to the website.
AwardAchievement performs the API call to notify the site that an achievement has been unlocked. As one of the parameters is the game hash (something I overlooked previously; I thought it was the game ID) this change also moves the game hash into a member field.