mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 09:16:49 +02:00
Merge remote-tracking branch 'origin/develop' into feature/cheats
This commit is contained in:
162
CHANGELOG.md
Normal file
162
CHANGELOG.md
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support for the SuperChis slot 2 card - by @edo9300
|
||||||
|
- Most of the remaining SDK 2-4 DMA patches - by @taxicat1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Star Wars Jedi Alliance patch - by @taxicat1
|
||||||
|
|
||||||
|
## [v1.5.0] - 1 Feb 2026 - Puppy Palace Release 🐶
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> With this release a new file `patchlist.bin` is introduced that needs to be copied to the `/_pico` folder on your SD card.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- AP patch for Last Window: The Secret of Cape West - by @taxicat1
|
||||||
|
- Missing CARDi_ReadRomIdCore signature for Top Spin 2 (USA) - by @taxicat1
|
||||||
|
- Fixes Top Spin 2 (USA) on DSTT and slot 2 cards
|
||||||
|
- Patch list with misc arm9 patches and metafortress addresses - Implementation by @Gericom, patch list contents by @taxicat1
|
||||||
|
- Puppy Palace (USA), My Puppy Shop (Europe), Machi no Pet-ya-san DS - 200 Piki Wan-chan Daishuugou (Japan)
|
||||||
|
- Castlevania - Portrait of Ruin (USA) and (Europe), Akumajou Dracula - Gallery of Labyrinth (Japan), Akumajou Dracula - Gallery of Labyrinth (Japan) (Rev 1)
|
||||||
|
- Luminous Arc 2 (USA) and (Europe), Luminous Arc 2 - Will (Japan)
|
||||||
|
- Children of Mana (USA) and (Europe), Seiken Densetsu DS - Children of Mana (Japan)
|
||||||
|
- Dementium II (USA) and (Europe), Tozasareta Byoutou - Dementium II (Japan)
|
||||||
|
- Grand Theft Auto - Chinatown Wars (USA), (Europe) and (Japan)
|
||||||
|
- Star Wars - The Clone Wars - Jedi Alliance (USA) and (Europe)
|
||||||
|
- C.O.P. - The Recruit (USA) and (Europe)
|
||||||
|
- Battle of Giants - Dragons (USA) (Rev 1), Combat of Giants - Dragons (Europe)
|
||||||
|
- Battle of Giants - Mutant Insects (USA), Combat of Giants - Mutant Insects (Europe)
|
||||||
|
- Captain America - Super Soldier (USA) and (Europe)
|
||||||
|
- Imagine - Resort Owner (USA), Imagine - Dream Resort (Europe)
|
||||||
|
- Might & Magic - Clash of Heroes (USA) and (Europe)
|
||||||
|
- Prince of Persia - The Forgotten Sands (USA) and (Europe)
|
||||||
|
- Kirby - Mass Attack (USA) and (Europe), Atsumete! Kirby (Japan), Moyeora! Kirby (Korea)
|
||||||
|
- Keep a valid stack pointer when booting the arm9
|
||||||
|
- Fixes Battle of Giants - Mutant Insects (USA), Combat of Giants - Mutant Insects (Europe) together with the patch in the patch list
|
||||||
|
- System for adjusting addresses for autoload - by @taxicat1
|
||||||
|
- Fixes New Super Mario Bros (USA)
|
||||||
|
- Attempt to fix rom hacks that decompress the arm9, but don't set compressedEnd to zero
|
||||||
|
- Fixes Pokemon SoulSilver Deluxe (together with the fix for roms repacked in unusual ways)
|
||||||
|
- Support for CARDi_ReadCard signature used by Chou Soujuu Mecha MG - by @taxicat1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Reduce size of some patch codes - by @edo9300 and @Gericom
|
||||||
|
- Fixes Dragon Quest Heroes - Rocket Slime (USA), Imagine - Fashion Designer (Europe) and Mugen Kouro (Japan)
|
||||||
|
- Improve handling of module params and locating of unused libsyscall space to support rom hacks that repack roms in unusual ways
|
||||||
|
- Fixes Coropata (English translation)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Ignore rom reads into null pointer destinations - by @taxicat1
|
||||||
|
- Fixes Tony Hawk's Downhill Jam
|
||||||
|
|
||||||
|
## [v1.4.0] - 11 Jan 2026
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Overlay patch to fix race condition in Kirby Super Star Ultra - by @taxicat1
|
||||||
|
- Overlay patch for hombrew AP in Rabbids Go Home - by @taxicat1
|
||||||
|
- Bypass region locking on iQue games - by @R-YaTian
|
||||||
|
- Properly set MBK9 (twl wram locking) settings - by @R-YaTian
|
||||||
|
- Support for SDK variant with a lot of inlining
|
||||||
|
- Fixes Tropix! ...Your Island Getaway and Think - Training für den Kopf - Kids - Spiel Dich Schlau!
|
||||||
|
- Note that these two games don't work yet on platforms that need card id patches (DSTT and slot2 platforms)
|
||||||
|
- Support for Slot 2 flashcarts using Compact Flash - by @edo9300
|
||||||
|
- Supercard CF (SUPERCARDCF)
|
||||||
|
- GBA Media Player CF (MPCF)
|
||||||
|
- M3 Adapter CF (M3CF)
|
||||||
|
- Max Media Dock CF (MMCF)
|
||||||
|
- Proper detection of DS mode DSiWare
|
||||||
|
- Fixes DS Download Play and Pictochat DSiWare apps
|
||||||
|
- Support for the homebrew bootstub that allows to return to the launcher application
|
||||||
|
- The Pico Loader API was updated to v2 for this purpose. The new `launcherPath` field needs to be set to the path of the launcher rom. The bootstub is only inserted when `launcherPath` is specified. As such, you will also need to update your launcher. If you are using Pico Launcher, support was added in v1.1.0.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Duplicate entries removed from save list and missing title added - by @synthic
|
||||||
|
- Fixes Disney Two Pack - Frozen Olaf's Quest + Big Hero 6 - Battle in the Bay (USA)
|
||||||
|
- Improve nocash print support detection to also detect melon ds - by @synthic
|
||||||
|
- Lock scfg9 when switching from DSi to DS mode
|
||||||
|
- Fixes homebrew with a DS mode header that tries to detect DSi mode. This for example fixes touch in DSCraft.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- DATEL: Make read sector function vram safe - by @edo9300
|
||||||
|
- Fixes some games that read directly to vram and fixes games that use OS_ResetSystem on the DATEL platform
|
||||||
|
- Proper handling of blx branches in CardiTryReadCardDmaPatch - by @taxicat1
|
||||||
|
- Fixes Ninja Gaiden - Dragon Sword (USA)
|
||||||
|
- Fix sCARDiTryReadCardDmaPatternSdk3017530 matching multiple variants - by @taxicat1
|
||||||
|
- Fixes Unou no Tatsujin - Soukai! Machigai Museum 2 (Japan), Trioncube (Europe) (En,Fr,De,Es,It), Tetris DS (Korea), Original Frisbee Disc Sports - Ultimate & Golf (USA) and LifeSigns - Surgical Unit (USA)
|
||||||
|
- Fix Shaberu! DS Oryouri Navi (Japan) (rev 0 and 1) by accounting for a spurious CARDi_ReadCard match
|
||||||
|
|
||||||
|
## [v1.3.1] - 29 Dec 2025
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- DATEL: Put back the full spi cycle routine when sending commands - by @edo9300
|
||||||
|
- Fixes issues with some SD cards on the DATEL platform
|
||||||
|
|
||||||
|
## [v1.3.0] - 28 Dec 2025
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Properly set the supported language, user language, and region based on the ROM's region - by @R-YaTian
|
||||||
|
- This bypasses the region lock or language lock in some dsiware games.
|
||||||
|
- Missing OS_ResetSystem signature - by @taxicat1
|
||||||
|
- Fixes crashes in Tetris DS and other games that have this signature.
|
||||||
|
- Support for roms with a writable NAND chip.
|
||||||
|
- Fixes WarioWare D.I.Y., Face Training, Jam with the Band and Nintendo DS Guide.
|
||||||
|
- Special save initialization for Jam with the Band and Daigassou! Band-Brothers DX
|
||||||
|
- New supported platform: Datel (Games n' Music and Action Replay DS(i)) - by @edo9300
|
||||||
|
- New supported platform: Stargate 3DS - by @lifehackerhansol
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Optimized space usage of supercard platform - by @edo9300
|
||||||
|
- Check in CardiTaskThreadPatch that the required slot is actually mapped to arm7.
|
||||||
|
- Fixes Power Rangers - Samurai.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix CardiTaskThreadPatch to apply the right patch for all signatures
|
||||||
|
- This fixes various games, including Chibi Robo! Park Patrol, Rainbow Islands Revolution, MechAssault - Phantom War and Diddy Kong Racing DS (USA).
|
||||||
|
|
||||||
|
## [v1.2.0] - 22 Dec 2025
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support for DSProtect patches in static arm9 - by @taxicat1
|
||||||
|
- Support for unusual DSProtect configurations - by @taxicat1
|
||||||
|
- Fixes Dragon Ball: Origins 2 and Puyo Puyo 7
|
||||||
|
- Proper implementation of save verification
|
||||||
|
- Fixes Madagascar, Bleach: Dark Souls and Final Fantasy Crystal Chronicles: Echoes of Time
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improve Pokémon IR sensor AP patches - by @taxicat1
|
||||||
|
- Fixes Pokémon HeartGold and SoulSilver
|
||||||
|
- Always boot roms with slot 1 and 2 mapped to arm7
|
||||||
|
- Fixes FastVideoDSPlayer homebrew
|
||||||
|
- Improve Sdk5DsiSdCardRedirectPatch
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix some retail roms being detected as homebrew
|
||||||
|
- Fixes Scooby Doo! - Unmasked and Kim Possible - Kimmunicator
|
||||||
|
- Fix some system tool DSi roms being misdetected as DSiWare
|
||||||
|
|
||||||
|
## [v1.1.0] - 4 Dec 2025
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support for EZ-Flash Parallel platform - by @lifehackerhansol
|
||||||
|
- Add a few more games to the DLDI patch blacklist
|
||||||
|
- Fixes Final Fantasy Crystal Chronicles - Ring of Fates (EU and US) and Nanashi no Geemu
|
||||||
|
- Clear all arm9 CPU registers before booting a game
|
||||||
|
- Fixes the Cake Ninja DSiWare titles
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- Simplified and improved DSProtect patches - by @taxicat1
|
||||||
|
- Fixes Saga 3: Shadow or Light and Solatorobo: Red the Hunter
|
||||||
|
|
||||||
|
## [v1.0.1] - 29 Nov 2025
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Add Mario vs. Donkey Kong - Mini-Land Mayhem! US rev 2 (V2GE) to the AP list - by @IceKareemCheese
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fix the DSProtect v2.03 patch (thanks @taxicat1)
|
||||||
|
- Fixes Professor Layton and the Last Specter among others
|
||||||
|
|
||||||
|
## [v1.0.0] - 25 Nov 2025
|
||||||
|
- Initial release
|
||||||
@@ -7,14 +7,14 @@
|
|||||||
#include "patches/arm9/RomOffsetToSdSectorPatchCode.h"
|
#include "patches/arm9/RomOffsetToSdSectorPatchCode.h"
|
||||||
#include "CardiTryReadCardDmaPatch.h"
|
#include "CardiTryReadCardDmaPatch.h"
|
||||||
|
|
||||||
static const u32 sCARDiTryReadCardDmaPatternPingPals[] = { 0xE92D47F0u, 0xE1A0A000u, 0xE59F9120u, 0xE3A08000u };
|
static const u32 sCARDiTryReadCardDmaPatternPingPals[] = { 0xE92D47F0u, 0xE1A0A000u, 0xE59F9120u, 0xE3A08000u }; // unimplemented
|
||||||
static const u32 sCARDiTryReadCardDmaPatternUnknown[] = { 0xE92D47F0u, 0xE59F9138u, 0xE3A06000u, 0xE5998020u };
|
static const u32 sCARDiTryReadCardDmaPatternUnknown[] = { 0xE92D47F0u, 0xE59F9138u, 0xE3A06000u, 0xE5998020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternUnknown2[] = { 0xE92D47F0u, 0xE59F4134u, 0xE3A06000u, 0xE5949020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk03007532HarvestMoon[] = { 0xE92D47F0u, 0xE59F4134u, 0xE3A06000u, 0xE5949020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternUnknown3[] = { 0xE92D4FF8u, 0xE59FB140u, 0xE3A05000u, 0xE59B8020u };
|
static const u32 sCARDiTryReadCardDmaPatternUnknown3[] = { 0xE92D4FF8u, 0xE59FB140u, 0xE3A05000u, 0xE59B8020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternUnknown4[] = { 0xE92D47F0u, 0xE59F9138u, 0xE3A06000u, 0xE599801Cu };
|
static const u32 sCARDiTryReadCardDmaPatternSdk02027533PokemonRanger[] = { 0xE92D47F0u, 0xE59F9138u, 0xE3A06000u, 0xE599801Cu };
|
||||||
static const u32 sCARDiTryReadCardDmaPattern20029A7[] = { 0xE92D47F0u, 0xE59F9128u, 0xE3A07000u, 0xE599401Cu };
|
static const u32 sCARDiTryReadCardDmaPattern20029A7[] = { 0xE92D47F0u, 0xE59F9128u, 0xE3A07000u, 0xE599401Cu };
|
||||||
static const u32 sCARDiTryReadCardDmaPattern2012774[] = { 0xE92D47F0u, 0xE59F9134u, 0xE3A07000u, 0xE599401Cu };
|
static const u32 sCARDiTryReadCardDmaPattern2012774[] = { 0xE92D47F0u, 0xE59F9134u, 0xE3A07000u, 0xE599401Cu };
|
||||||
static const u32 sCARDiTryReadCardDmaPattern2017532[] = { 0xE92D47F0u, 0xE59F9130u, 0xE3A07000u, 0xE599401Cu };
|
static const u32 sCARDiTryReadCardDmaPattern2017532BrainAge[] = { 0xE92D47F0u, 0xE59F9130u, 0xE3A07000u, 0xE599401Cu };
|
||||||
static const u32 sCARDiTryReadCardDmaPattern2027530[] = { 0xE92D47F0u, 0xE59F913Cu, 0xE3A06000u, 0xE599801Cu };
|
static const u32 sCARDiTryReadCardDmaPattern2027530[] = { 0xE92D47F0u, 0xE59F913Cu, 0xE3A06000u, 0xE599801Cu };
|
||||||
static const u32 sCARDiTryReadCardDmaPattern[] = { 0xE92D47F0u, 0xE59F913Cu, 0xE3A06000u, 0xE5998020u };
|
static const u32 sCARDiTryReadCardDmaPattern[] = { 0xE92D47F0u, 0xE59F913Cu, 0xE3A06000u, 0xE5998020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk3017530[] = { 0xE92D4FF0u, 0xE24DD004u, 0xE59FB14Cu, 0xE3A07000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk3017530[] = { 0xE92D4FF0u, 0xE24DD004u, 0xE59FB14Cu, 0xE3A07000u };
|
||||||
@@ -23,24 +23,21 @@ static const u32 sCARDiTryReadCardDmaPatternSdk3027530[] = { 0xE92D4FF0u, 0xE24D
|
|||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4007530[] = { 0xE92D4FF8u, 0xE59FB144u, 0xE3A05000u, 0xE59B8020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4007530[] = { 0xE92D4FF8u, 0xE59FB144u, 0xE3A05000u, 0xE59B8020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4007532[] = { 0xE92D4FF8u, 0xE59F416Cu, 0xE3A06000u, 0xE5949020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4007532[] = { 0xE92D4FF8u, 0xE59F416Cu, 0xE3A06000u, 0xE5949020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4027539SpiritTracks[] = { 0xE92D4FF8u, 0xE59F4174u, 0xE3A06000u, 0xE5949020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4027539SpiritTracks[] = { 0xE92D4FF8u, 0xE59F4174u, 0xE3A06000u, 0xE5949020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternJpnPokemonDownloader[] = { 0xE92D4FF8u, 0xE59FB138u, 0xE3A05000u, 0xE59B8020u };
|
static const u32 sCARDiTryReadCardDmaPatternJpnPokemonDownloader[] = { 0xE92D4FF8u, 0xE59FB138u, 0xE3A05000u, 0xE59B8020u }; // unimplemented
|
||||||
|
|
||||||
static const u32 sCARDiTryReadCardDmaPatternThumbChouSoujuu[] = { 0xB083B5F0u, 0x48399000u, 0x6A0469C5u, 0x96012600u };
|
static const u32 sCARDiTryReadCardDmaPatternThumbChouSoujuu[] = { 0xB083B5F0u, 0x48399000u, 0x6A0469C5u, 0x96012600u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk2004F4CThumb[] = { 0xB083B5F0u, 0x4D359000u, 0x94012400u, 0x90020020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk2004F4CThumb[] = { 0xB083B5F0u, 0x4D359000u, 0x94012400u, 0x90020020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk2007531Thumb[] = { 0xB083B5F0u, 0x4D379000u, 0x94012400u, 0x90020020u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk2007531Thumb[] = { 0xB083B5F0u, 0x4D379000u, 0x94012400u, 0x90020020u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk2027530Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A0469C5u, 0x96012600u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk2027530Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A0469C5u, 0x96012600u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk3007530Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A446A05u, 0x96012600u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk3007530Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A446A05u, 0x96012600u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk3012776Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A446A05u, 0x90012600u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk3012776Thumb[] = { 0xB083B5F0u, 0x483A9000u, 0x6A446A05u, 0x90012600u }; // TODO does this exist?
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk3017531Thumb[] = { 0xB085B5F0u, 0x483C9000u, 0x6A446A05u, 0x90012000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk3017531Thumb[] = { 0xB085B5F0u, 0x483C9000u, 0x6A446A05u, 0x90012000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk3027530Thumb[] = { 0xB085B5F0u, 0x483D9000u, 0x6A446A05u, 0x90012000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk3027530Thumb[] = { 0xB085B5F0u, 0x483D9000u, 0x6A446A05u, 0x90012000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdkThumb[] = { 0xB084B5F8u, 0x483D9000u, 0x6A446A05u, 0x90032000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdkThumb[] = { 0xB084B5F8u, 0x483D9000u, 0x6A446A05u, 0x90032000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4007531Thumb[] = { 0xB084B5F8u, 0x483E9000u, 0x6A446A05u, 0x90032000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4007531Thumb[] = { 0xB084B5F8u, 0x483E9000u, 0x6A446A05u, 0x90032000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4017530Thumb[] = { 0xB084B5F8u, 0x48479000u, 0x6A446A05u, 0x90032000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4017530Thumb[] = { 0xB084B5F8u, 0x48479000u, 0x6A446A05u, 0x90032000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4027530Thumb[] = { 0xB084B5F8u, 0x48479000u, 0x6A446A05u, 0x90032000u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4027530Thumb[] = { 0xB084B5F8u, 0x48479000u, 0x6A446A05u, 0x90032000u };
|
||||||
static const u32 sCARDiTryReadCardDmaPatternSdk4027531ThumbInlined[] = { 0xB083B5F0u, 0x485D9000u, 0x6A062500u, 0x1C286A44u };
|
static const u32 sCARDiTryReadCardDmaPatternSdk4027531ThumbInlined[] = { 0xB083B5F0u, 0x485D9000u, 0x6A062500u, 0x1C286A44u }; // unimplemented
|
||||||
|
|
||||||
static const u16 sReturnFalsePatchThumb[] = { THUMB_MOVS_IMM(0, 0), THUMB_BX_LR };
|
|
||||||
static const u32 sReturnFalsePatchArm[] = { 0xE3A00000, 0xE12FFF1E }; // mov r0, #0; bx lr
|
|
||||||
|
|
||||||
void CardiTryReadCardDmaPatch::TryPattern(PatchContext& patchContext, const u32* pattern)
|
void CardiTryReadCardDmaPatch::TryPattern(PatchContext& patchContext, const u32* pattern)
|
||||||
{
|
{
|
||||||
@@ -51,6 +48,20 @@ void CardiTryReadCardDmaPatch::TryPattern(PatchContext& patchContext, const u32*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardiTryReadCardDmaPatch::ApplyReturnFalsePatch()
|
||||||
|
{
|
||||||
|
if (_thumb)
|
||||||
|
{
|
||||||
|
((u16*)_cardiTryReadCardDma)[0] = THUMB_MOVS_IMM(0, 0);
|
||||||
|
((u16*)_cardiTryReadCardDma)[1] = THUMB_BX_LR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_cardiTryReadCardDma[0] = 0xE3A00000; // mov r0, #0
|
||||||
|
_cardiTryReadCardDma[1] = 0xE12FFF1E; // bx lr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CardiTryReadCardDmaPatch::FindPatchTarget(PatchContext& patchContext)
|
bool CardiTryReadCardDmaPatch::FindPatchTarget(PatchContext& patchContext)
|
||||||
{
|
{
|
||||||
if (patchContext.GetSdkVersion() >= 0x4007532)
|
if (patchContext.GetSdkVersion() >= 0x4007532)
|
||||||
@@ -107,7 +118,7 @@ bool CardiTryReadCardDmaPatch::FindPatchTarget(PatchContext& patchContext)
|
|||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPatternSdk3017530);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPatternSdk3017530);
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPatternUnknown2);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPatternSdk03007532HarvestMoon);
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPatternUnknown3);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPatternUnknown3);
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
@@ -117,11 +128,11 @@ bool CardiTryReadCardDmaPatch::FindPatchTarget(PatchContext& patchContext)
|
|||||||
if (patchContext.GetSdkVersion() < 0x3000000)
|
if (patchContext.GetSdkVersion() < 0x3000000)
|
||||||
{
|
{
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPattern2017532);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPattern2017532BrainAge);
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPatternPingPals);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPatternPingPals);
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
TryPattern(patchContext, sCARDiTryReadCardDmaPatternUnknown4);
|
TryPattern(patchContext, sCARDiTryReadCardDmaPatternSdk02027533PokemonRanger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patchContext.GetSdkVersion() >= 0x4000000)
|
if (patchContext.GetSdkVersion() >= 0x4000000)
|
||||||
@@ -170,41 +181,222 @@ bool CardiTryReadCardDmaPatch::FindPatchTarget(PatchContext& patchContext)
|
|||||||
return true; //_cardiTryReadCardDma != nullptr;
|
return true; //_cardiTryReadCardDma != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 resolveCallWithAutoload(u32 callLocation, const IAutoloadAdjuster* autoloadAdjuster, bool isThumb)
|
||||||
|
{
|
||||||
|
s32 callOffset;
|
||||||
|
if (isThumb)
|
||||||
|
{
|
||||||
|
callOffset = ArmHelper::GetThumbCallOffset(((u16*)callLocation)[0], ((u16*)callLocation)[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callOffset = ArmHelper::GetArmCallOffset(*(u32*)callLocation);
|
||||||
|
}
|
||||||
|
if (autoloadAdjuster)
|
||||||
|
{
|
||||||
|
callLocation = autoloadAdjuster->AdjustInitialToFinal(callLocation);
|
||||||
|
}
|
||||||
|
u32 callDestination = callLocation + callOffset;
|
||||||
|
if (isThumb && (callDestination & 3) == 2)
|
||||||
|
{
|
||||||
|
// fix non-aligned Thumb call to ARM
|
||||||
|
callDestination &= ~2u;
|
||||||
|
}
|
||||||
|
return callDestination;
|
||||||
|
}
|
||||||
|
|
||||||
void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
||||||
{
|
{
|
||||||
if (!_cardiTryReadCardDma)
|
if (!_cardiTryReadCardDma)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_thumb)
|
if (!patchContext.GetLoaderPlatform()->HasDmaSdReads())
|
||||||
{
|
{
|
||||||
((u16*)_cardiTryReadCardDma)[0] = sReturnFalsePatchThumb[0];
|
LOG_DEBUG("Platform does not support DMA\n");
|
||||||
((u16*)_cardiTryReadCardDma)[1] = sReturnFalsePatchThumb[1];
|
ApplyReturnFalsePatch();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
bool enableDma = patchContext.GetLoaderPlatform()->HasDmaSdReads();
|
|
||||||
if (enableDma)
|
|
||||||
{
|
|
||||||
u32 cardiCommon;
|
u32 cardiCommon;
|
||||||
u32 cardiOnReadCard;
|
u32 cardiOnReadCard;
|
||||||
u32 cardiSetCardDma;
|
u32 cardiSetCardDma;
|
||||||
u32 cardiSetCardDmaDmaCopyCallOffset;
|
u32 cardiSetCardDmaDmaCopyCallOffset;
|
||||||
u32 cardiOnReadCardOffset;
|
u32 cardiOnReadCardDisableIrqCallOffset;
|
||||||
if (_foundPattern == sCARDiTryReadCardDmaPattern20029A7)
|
u32 cardiOnReadCardPatchOffset;
|
||||||
|
bool patchUsingPool = false; // needed for some SDK 2-3 Thumb
|
||||||
|
u32 cardiOnReadCardPoolOffset;
|
||||||
|
if (_thumb)
|
||||||
{
|
{
|
||||||
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x134);
|
if (_foundPattern == sCARDiTryReadCardDmaPatternThumbChouSoujuu)
|
||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x144);
|
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x124));
|
|
||||||
if (*(u32*)cardiOnReadCard == 0xE92D40F0u)
|
|
||||||
{
|
{
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xEC);
|
||||||
cardiOnReadCardOffset = 0x40;
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x110) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xE2)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0x94;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk2004F4CThumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xDC);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x100) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xCE)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0x50;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk2007531Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xE4);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x108) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xD6)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0x50;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk2027530Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xF0);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x114) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xE2)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0x9C;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3007530Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xF0) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x114) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xE2)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0xA0;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3017531Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xF8) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x11C) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xEA)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0xA0;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3027530Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xFC) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x120) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xEC)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0xC;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x28;
|
||||||
|
cardiOnReadCardPatchOffset = 0x28;
|
||||||
|
patchUsingPool = true;
|
||||||
|
cardiOnReadCardPoolOffset = 0xA0;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdkThumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0xFC) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x110) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xF2)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x10;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x32;
|
||||||
|
cardiOnReadCardPatchOffset = 0x30;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4007531Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x100) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x114) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0xF4)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x10;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x32;
|
||||||
|
cardiOnReadCardPatchOffset = 0x30;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4017530Thumb || _foundPattern == sCARDiTryReadCardDmaPatternSdk4027530Thumb)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x124) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x138) & ~1u;
|
||||||
|
cardiSetCardDma = ArmHelper::GetThumbCallAddress((u16*)((u8*)_cardiTryReadCardDma + 0x118)) & ~1u;
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x10;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x32;
|
||||||
|
cardiOnReadCardPatchOffset = 0x30;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// old version is not supported yet
|
LOG_DEBUG("Unsupported Thumb CARDi_TryReadCardDma signature\n");
|
||||||
_cardiTryReadCardDma[0] = sReturnFalsePatchArm[0];
|
ApplyReturnFalsePatch();
|
||||||
_cardiTryReadCardDma[1] = sReturnFalsePatchArm[1];
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_foundPattern == sCARDiTryReadCardDmaPatternUnknown)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x144) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x154);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x138));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk03007532HarvestMoon)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x140) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x150);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x134));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x4C;
|
||||||
|
cardiOnReadCardPatchOffset = 0x48;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternUnknown3)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x14C) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x15C);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x140));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x4C;
|
||||||
|
cardiOnReadCardPatchOffset = 0x48;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk02027533PokemonRanger)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x148);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x158);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x138));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPattern20029A7)
|
||||||
|
{
|
||||||
|
if (*(u32*)((u8*)_cardiTryReadCardDma + 0x140) == 0xE12FFF1E)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x144);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x154);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x134);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x144);
|
||||||
|
}
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x124));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
if (!ArmHelper::IsArmUnconditionalBl(*(u32*)(cardiSetCardDma + cardiSetCardDmaDmaCopyCallOffset)))
|
||||||
|
{
|
||||||
|
// some versions have inlined MIi_CardDmaCopy32
|
||||||
|
LOG_DEBUG("Failed to patch sCARDiTryReadCardDmaPattern20029A7\n");
|
||||||
|
ApplyReturnFalsePatch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +406,26 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x150);
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x150);
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x130));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x130));
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
cardiOnReadCardOffset = 0x40;
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPattern2017532BrainAge)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x13C);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x14C);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x130));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPattern2027530)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x148);
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x158);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x138));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sCARDiTryReadCardDmaPattern)
|
else if (_foundPattern == sCARDiTryReadCardDmaPattern)
|
||||||
{
|
{
|
||||||
@@ -222,7 +433,8 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x158);
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x158);
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x138));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x138));
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
cardiOnReadCardOffset = 0x40;
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3017530)
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3017530)
|
||||||
{
|
{
|
||||||
@@ -237,7 +449,17 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x14C));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x14C));
|
||||||
}
|
}
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
cardiOnReadCardOffset = 0x40;
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3017534)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x158) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x168);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x148));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3027530)
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk3027530)
|
||||||
{
|
{
|
||||||
@@ -245,7 +467,17 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x170);
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x170);
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x14C));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x14C));
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
cardiSetCardDmaDmaCopyCallOffset = 0x18;
|
||||||
cardiOnReadCardOffset = 0x40;
|
cardiOnReadCardDisableIrqCallOffset = 0x44;
|
||||||
|
cardiOnReadCardPatchOffset = 0x40;
|
||||||
|
}
|
||||||
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4007530)
|
||||||
|
{
|
||||||
|
cardiCommon = *(u32*)((u8*)_cardiTryReadCardDma + 0x150) + 4;
|
||||||
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x160);
|
||||||
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x144));
|
||||||
|
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
||||||
|
cardiOnReadCardDisableIrqCallOffset = 0x4C;
|
||||||
|
cardiOnReadCardPatchOffset = 0x48;
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4007532)
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4007532)
|
||||||
{
|
{
|
||||||
@@ -253,7 +485,8 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x188);
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x188);
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x16C));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x16C));
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
||||||
cardiOnReadCardOffset = 0x48;
|
cardiOnReadCardDisableIrqCallOffset = 0x4C;
|
||||||
|
cardiOnReadCardPatchOffset = 0x48;
|
||||||
}
|
}
|
||||||
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4027539SpiritTracks)
|
else if (_foundPattern == sCARDiTryReadCardDmaPatternSdk4027539SpiritTracks)
|
||||||
{
|
{
|
||||||
@@ -261,14 +494,16 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x190);
|
cardiOnReadCard = *(u32*)((u8*)_cardiTryReadCardDma + 0x190);
|
||||||
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x174));
|
cardiSetCardDma = ArmHelper::GetArmCallAddress((u32*)((u8*)_cardiTryReadCardDma + 0x174));
|
||||||
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
cardiSetCardDmaDmaCopyCallOffset = 0x1C;
|
||||||
cardiOnReadCardOffset = 0x48;
|
cardiOnReadCardDisableIrqCallOffset = 0x4C;
|
||||||
|
cardiOnReadCardPatchOffset = 0x48;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_cardiTryReadCardDma[0] = sReturnFalsePatchArm[0];
|
LOG_DEBUG("Unsupported ARM CARDi_TryReadCardDma signature\n");
|
||||||
_cardiTryReadCardDma[1] = sReturnFalsePatchArm[1];
|
ApplyReturnFalsePatch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// correct all addresses for autoload, if libcard is in an autoload block (New Super Mario Bros.)
|
// correct all addresses for autoload, if libcard is in an autoload block (New Super Mario Bros.)
|
||||||
auto autoloadAdjuster = patchContext.GetAutoloadAdjuster();
|
auto autoloadAdjuster = patchContext.GetAutoloadAdjuster();
|
||||||
@@ -279,25 +514,11 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
cardiOnReadCard = autoloadAdjuster->AdjustFinalToInitial(cardiOnReadCard);
|
cardiOnReadCard = autoloadAdjuster->AdjustFinalToInitial(cardiOnReadCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MIi_CardDmaCopy32 is relative, but we need its final location to call it later
|
// MIi_CardDmaCopy32 and OS_DisableIrqMask are relative, but we need their final locations to call them later
|
||||||
u32 miiCardDmaCopy32CallLocation = cardiSetCardDma + cardiSetCardDmaDmaCopyCallOffset;
|
u32 miiCardDmaCopy32 = resolveCallWithAutoload(cardiSetCardDma + cardiSetCardDmaDmaCopyCallOffset, autoloadAdjuster, _thumb);
|
||||||
s32 miiCardDmaCopy32CallOffset = ArmHelper::GetArmCallOffset(*(u32*)miiCardDmaCopy32CallLocation);
|
u32 osDisableIrqMask = resolveCallWithAutoload(cardiOnReadCard + cardiOnReadCardDisableIrqCallOffset, autoloadAdjuster, _thumb);
|
||||||
if (autoloadAdjuster)
|
|
||||||
{
|
|
||||||
miiCardDmaCopy32CallLocation = autoloadAdjuster->AdjustInitialToFinal(miiCardDmaCopy32CallLocation);
|
|
||||||
}
|
|
||||||
u32 miiCardDmaCopy32 = miiCardDmaCopy32CallLocation + miiCardDmaCopy32CallOffset;
|
|
||||||
|
|
||||||
// same as above with OS_DisableIrqMask
|
// begin with patching
|
||||||
u32 osDisableIrqMaskCallLocation = cardiOnReadCard + cardiOnReadCardOffset + 4;
|
|
||||||
s32 osDisableIrqMaskCallOffset = ArmHelper::GetArmCallOffset(*(u32*)osDisableIrqMaskCallLocation);
|
|
||||||
if (autoloadAdjuster)
|
|
||||||
{
|
|
||||||
osDisableIrqMaskCallLocation = autoloadAdjuster->AdjustInitialToFinal(osDisableIrqMaskCallLocation);
|
|
||||||
}
|
|
||||||
u32 osDisableIrqMask = osDisableIrqMaskCallLocation + osDisableIrqMaskCallOffset;
|
|
||||||
|
|
||||||
// patch CARDi_SetCardDma
|
|
||||||
auto sdReadDmaPatchCode = patchContext.GetLoaderPlatform()->CreateSdReadDmaPatchCode(
|
auto sdReadDmaPatchCode = patchContext.GetLoaderPlatform()->CreateSdReadDmaPatchCode(
|
||||||
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap(), (const void*)miiCardDmaCopy32);
|
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap(), (const void*)miiCardDmaCopy32);
|
||||||
auto romOffsetToSdSectorPatchCode = patchContext.GetPatchCodeCollection().GetOrAddSharedPatchCode([&]
|
auto romOffsetToSdSectorPatchCode = patchContext.GetPatchCodeCollection().GetOrAddSharedPatchCode([&]
|
||||||
@@ -313,20 +534,39 @@ void CardiTryReadCardDmaPatch::ApplyPatch(PatchContext& patchContext)
|
|||||||
(const void*)cardiCommon,
|
(const void*)cardiCommon,
|
||||||
(const void*)osDisableIrqMask
|
(const void*)osDisableIrqMask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (_thumb)
|
||||||
|
{
|
||||||
|
// patch CARDi_SetCardDma
|
||||||
|
*(u16*)(cardiSetCardDma + 0) = 0x4800; // ldr r0,= entryAddress
|
||||||
|
*(u16*)(cardiSetCardDma + 2) = 0x4700; // bx r0
|
||||||
|
*(u32*)(cardiSetCardDma + 4) = (u32)cardiSetCardDmaPatchCode->GetCardiSetCardDmaFunction();
|
||||||
|
|
||||||
|
// patch CARDi_OnReadCard
|
||||||
|
if (patchUsingPool)
|
||||||
|
{
|
||||||
|
*(u16*)(cardiOnReadCard + cardiOnReadCardPatchOffset) = 0x4780; // blx r0 (pre-loaded from pool)
|
||||||
|
*(u32*)(cardiOnReadCard + cardiOnReadCardPoolOffset) = (u32)cardiSetCardDmaPatchCode->GetCardiOnReadCardPatchFunction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(u16*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 0) = 0x4800; // ldr r0,= entryAddress
|
||||||
|
*(u16*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 2) = 0x4780; // blx r0
|
||||||
|
*(u32*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 4) = (u32)cardiSetCardDmaPatchCode->GetCardiOnReadCardPatchFunction();
|
||||||
|
*(u16*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 8) = 0x4600; // nop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// patch CARDi_SetCardDma
|
||||||
*(u32*)(cardiSetCardDma + 0) = 0xE51FF004; // ldr pc,= entryAddress
|
*(u32*)(cardiSetCardDma + 0) = 0xE51FF004; // ldr pc,= entryAddress
|
||||||
*(u32*)(cardiSetCardDma + 4) = (u32)cardiSetCardDmaPatchCode->GetCardiSetCardDmaFunction();
|
*(u32*)(cardiSetCardDma + 4) = (u32)cardiSetCardDmaPatchCode->GetCardiSetCardDmaFunction();
|
||||||
|
|
||||||
// patch CARDi_OnReadCard
|
// patch CARDi_OnReadCard
|
||||||
*(u32*)(cardiOnReadCard + cardiOnReadCardOffset + 0) = 0xE59F0000; // ldr r0,= entryAddress
|
*(u32*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 0) = 0xE59F0000; // ldr r0,= entryAddress
|
||||||
*(u32*)(cardiOnReadCard + cardiOnReadCardOffset + 4) = 0xE12FFF30; // blx r0
|
*(u32*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 4) = 0xE12FFF30; // blx r0
|
||||||
*(u32*)(cardiOnReadCard + cardiOnReadCardOffset + 8) = (u32)cardiSetCardDmaPatchCode->GetCardiOnReadCardPatchFunction();
|
*(u32*)(cardiOnReadCard + cardiOnReadCardPatchOffset + 8) = (u32)cardiSetCardDmaPatchCode->GetCardiOnReadCardPatchFunction();
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("DMA enabled\n");
|
LOG_DEBUG("DMA enabled\n");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_cardiTryReadCardDma[0] = sReturnFalsePatchArm[0];
|
|
||||||
_cardiTryReadCardDma[1] = sReturnFalsePatchArm[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ private:
|
|||||||
const u32* _foundPattern = nullptr;
|
const u32* _foundPattern = nullptr;
|
||||||
|
|
||||||
void TryPattern(PatchContext& patchContext, const u32* pattern);
|
void TryPattern(PatchContext& patchContext, const u32* pattern);
|
||||||
|
void ApplyReturnFalsePatch();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
{
|
{
|
||||||
"type": "replace",
|
"type": "replace",
|
||||||
"address": "0205653C",
|
"address": "0205653C",
|
||||||
"data": "03 00 58 6F 01 38 08 D0 05 DF 58 6F 01 38 04 D0 90 20 18 58 01 28 00 D0",
|
"data": "20 B5 05 00 68 6F 01 38 07 D0 05 DF 68 6F 01 38 03 D0 90 21 68 58 40 00 01 38 20 BD",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -295,7 +295,7 @@
|
|||||||
{
|
{
|
||||||
"type": "replace",
|
"type": "replace",
|
||||||
"address": "0205653C",
|
"address": "0205653C",
|
||||||
"data": "03 00 58 6F 01 38 08 D0 05 DF 58 6F 01 38 04 D0 90 20 18 58 01 28 00 D0",
|
"data": "20 B5 05 00 68 6F 01 38 07 D0 05 DF 68 6F 01 38 03 D0 90 21 68 58 40 00 01 38 20 BD",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user