Repository navigation
Integrating 3DS analog controls cheats - #38
Merged
Merged
Conversation
shocoman's Circle Pad patches let a DS game read a 3DS stick: an ARM7/ARM11 relay copies the stick into guest RAM at 0x027FFDF0, and an ARM9 hook in the game reads it. An emulator has no relay and needs none, so the frontend captures both sticks and the triggers and the core writes that block every frame, once a stripped CPAD code is enabled. pad.analog (off, left, right, dual) picks the sticks, with pad.analog_deadzone, pad.analog_invert_y and a sensitivity per stick. Stick Y is flipped by default, as SDL's up is negative and a 3DS's is positive. ZL and ZR come with two sticks, past 3/4 travel, and not under a hotkey chord. The settings are a pause-menu page of their own, after Controls, opening with a link to the game's analog cheats; the Cheats page lists the rest. Hooks expect one of two arrangements, which collide at +6, so reads_extended_analog looks for how the enabled code takes the nub; pad.analog_layout can overrule it. A code counts as analog by its CPAD name. paths.analog_cheats names a second database for these patches, merged for an exact ROM match only, because a hook patches fixed addresses and best_entry's first-revision fallback would install it over the wrong code. The DSIN log goes to version 3 to carry the sticks; v1 and v2 still replay. Cheat persistence enforces exclusive groups, since two schemes over the same addresses cannot run at once, and every way out of the menu applies cheat changes: Reset and Load used to run a new code with the channel still off. A game picked from the list now gets its .ini's pad settings; other keys in it wait for the next start.
An analog code patches branch sites and installs a hook body, and a disabled code stopped running but left all of that in guest RAM. Worse, a scheme's install guard tests only the hook's first word, which two schemes for one game can share, so switching took the old body for its own and a new branch landed inside it. The engine now journals the bytes an analog code writes and restores them when it is disabled, if each byte still holds what the code wrote. Only analog codes are journaled: other cheats write game data the game goes on changing, and putting an old value back would be wrong. A save state holds guest RAM with the hook in it, so the journal travels in an optional CHJR chunk, keyed by a hash of each code's words so a revised code does not inherit its predecessor's hook. The next run() keeps what enabled codes own and restores the rest, which needs a VBlank hook that still runs when the code list is empty. Reader::peek lets the chunk be absent: older states and cheat-free ones load as before, and the frontend's own chunks follow it. Also adds docs/techniques/07, which describes the whole feature.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is it?
The 3DS has a number of cheats that enable analog stick, circle pad pro, ZR/ZL and even gyroscope functionality. They do this by utilizing some bits in the RTC register and then the Action Reply code reads from it and patches in game functions. The one-sentence version: a CPAD patch is three mechanisms stacked — a transport, a relay and a game hook — and an emulator only needs the hook.
see: https://github.com/shocoman/Analog-Controls-for-NDS-Games-on-3DS and https://gbatemp.net/threads/circle-pad-patches-for-super-mario-64-ds-and-other-games-in-twilightmenu-with-twpatcher-and-rtcom.623267/#post-10026852
DSperate doesn't need the full Action Reply codes, so an intermediate repo (https://github.com/bmpriest/ds-emu-dac) serves to convert the codes into compatible codes for the emulator.
What changes in DSperate
For convenience, DSperate uses a separate usrcheat.dat for the analog cheats. usrcheat-analog.zip These cheats as well as control specifics live in an Analog menu where specific cheats can be enabled/disabled, as well as some stick settings like deadzones, invert Y, and sensitivity.
There's also various bits to disable gracefully when turning off the analog cheats, making them exclusive in cases where there are more than one, preventing save states from getting weird, and tests.
What works
I have tested DSperate with a NextUI compatible pak and played a decent bit of Super Mario 64 DS, Metroid Prime Hunters, Star Fox Command, and Animal Crossing on my RG35XXH.
What it needs
Because these cheats map analog functionality to the sticks, there needs to thought given to current touch screen functionality. If the stylus is mapped to the right stick in Metroid Prime Hunters, for example, using the right stick will move the DS stylus as well as moving the player's view.
I'd recommend either a shortcut to disable the analog cheats temporarily, or an additional hotkey to enable stylus support: for example, L2 plus Right Stick for stylus input.