mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 01:06:50 +02:00
Added support for NAND saving in WarioWare D.I.Y. and Jam with the Band (#6)
Also improved speed of creating save files
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
#include "patches/arm9/OSResetSystemPatch.h"
|
||||
#include "patches/arm9/PokemonDownloaderArm9Patch.h"
|
||||
#include "patches/arm9/DSProtectArm9Patch.h"
|
||||
#include "patches/arm9/NandSave/JamWithTheBandNandSavePatch.h"
|
||||
#include "patches/arm9/NandSave/WarioWareDiyNandSavePatch.h"
|
||||
#include "patches/arm9/OverlayPatches/FsStartOverlayHookPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectOverlayPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectPuyoPuyo7Patch.h"
|
||||
@@ -374,6 +376,20 @@ void Arm9Patcher::AddGameSpecificPatches(
|
||||
overlayHookPatch->AddOverlayPatch(new PokemonIrApPatch(PokemonIrVersion::Bw2));
|
||||
break;
|
||||
}
|
||||
// WarioWare: D.I.Y.
|
||||
case GAMECODE("UORE"):
|
||||
case GAMECODE("UORP"):
|
||||
case GAMECODE("UORJ"):
|
||||
{
|
||||
patchCollection.AddPatch(new WarioWareDiyNandSavePatch());
|
||||
break;
|
||||
}
|
||||
// Jam with the Band
|
||||
case GAMECODE("UXBP"):
|
||||
{
|
||||
patchCollection.AddPatch(new JamWithTheBandNandSavePatch());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "../SectorRemapPatchCode.h"
|
||||
#include "SectorRemapPatchCode.h"
|
||||
#include "fileInfo.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(saveoffsettosdsector);
|
||||
@@ -8,8 +8,7 @@
|
||||
#include "patches/arm7/VerifySaveAsm.h"
|
||||
#include "patches/FunctionSignature.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/arm7/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/OffsetToSectorRemapAsm.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/arm7/CardiTaskThreadPatchAsm.h"
|
||||
#include "thumbInstructions.h"
|
||||
#include "CardiTaskThreadPatch.h"
|
||||
@@ -95,14 +94,11 @@ void CardiTaskThreadPatch::ApplyPatch(PatchContext& patchContext)
|
||||
u32 patch1Size = SECTION_SIZE(patch_carditaskthread);
|
||||
void* patch1Address = patchContext.GetPatchHeap().Alloc(patch1Size);
|
||||
auto loaderPlatform = patchContext.GetLoaderPlatform();
|
||||
const SdReadPatchCode* readPatchCode;
|
||||
const SdWritePatchCode* writePatchCode;
|
||||
const SectorRemapPatchCode* sectorRemapPatchCode;
|
||||
readPatchCode = loaderPlatform->CreateSdReadPatchCode(
|
||||
auto readPatchCode = loaderPlatform->CreateSdReadPatchCode(
|
||||
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap());
|
||||
writePatchCode = loaderPlatform->CreateSdWritePatchCode(
|
||||
auto writePatchCode = loaderPlatform->CreateSdWritePatchCode(
|
||||
patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap());
|
||||
sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>
|
||||
auto sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
(const save_file_info_t*)((u32)SHARED_SAVE_FILE_INFO - 0x02F00000 + 0x02700000)
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
#include "patches/arm7/ReadSaveAsm.h"
|
||||
#include "patches/arm7/WriteSaveAsm.h"
|
||||
#include "patches/arm7/VerifySaveAsm.h"
|
||||
#include "patches/arm7/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/OffsetToSectorRemapAsm.h"
|
||||
#include "patches/arm7/CardiTaskThreadPatchAsm.h"
|
||||
#include "CardiDoTaskFromArm9Patch.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "common.h"
|
||||
#include "gameCode.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "ReadNandSaveAsm.h"
|
||||
#include "WriteNandSaveAsm.h"
|
||||
#include "JamWithTheBandNandSavePatch.h"
|
||||
|
||||
// This code was based on nds-bootstrap:
|
||||
// https://github.com/DS-Homebrew/nds-bootstrap/blob/89f27d1392a68436695d0050992ee84258ef41bc/retail/bootloader/source/arm7/patch_arm9.c#L2531
|
||||
|
||||
bool JamWithTheBandNandSavePatch::FindPatchTarget(PatchContext& patchContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void JamWithTheBandNandSavePatch::ApplyPatch(PatchContext& patchContext)
|
||||
{
|
||||
auto sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
(const save_file_info_t*)((u32)SHARED_SAVE_FILE_INFO - 0x02F00000 + 0x02700000)
|
||||
);
|
||||
auto loaderPlatform = patchContext.GetLoaderPlatform();
|
||||
auto readNandSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadNandSavePatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
loaderPlatform->CreateSdReadPatchCode(patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap())
|
||||
);
|
||||
auto writeNandSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteNandSavePatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
loaderPlatform->CreateSdWritePatchCode(patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap())
|
||||
);
|
||||
|
||||
// u32 nandInit(void* data)
|
||||
*(u32*)0x020613CC = 0xE3A00001; // mov r0, #1
|
||||
*(u32*)0x020613D0 = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandResume(void)
|
||||
*(u32*)0x02061A4C = 0xE3A00000; // mov r0, #0
|
||||
*(u32*)0x02061A50 = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandError(void)
|
||||
*(u32*)0x02061C24 = 0xE3A00000; // mov r0, #0
|
||||
*(u32*)0x02061C28 = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandWrite(const void* memory, u32 flash, u32 size, u32 dmaChannel)
|
||||
*(u32*)0x0206176C = 0xE51FF004; // ldr pc,= patch_writeNandSave
|
||||
*(u32*)0x02061770 = (u32)writeNandSavePatchCode->GetWriteNandSaveFunction();
|
||||
|
||||
// u32 nandRead(void* memory, u32 flash, u32 size, u32 dmaChannel)
|
||||
*(u32*)0x02061AC4 = 0xE51FF004; // ldr pc,= patch_readNandSave
|
||||
*(u32*)0x02061AC8 = (u32)readNandSavePatchCode->GetReadNandSaveFunction();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "patches/Patch.h"
|
||||
|
||||
class FunctionSignature;
|
||||
|
||||
/// @brief Arm9 patch to redirect Jam with the Band nand saving to the SD card.
|
||||
class JamWithTheBandNandSavePatch : public Patch
|
||||
{
|
||||
public:
|
||||
bool FindPatchTarget(PatchContext& patchContext) override;
|
||||
void ApplyPatch(PatchContext& patchContext) override;
|
||||
};
|
||||
29
arm9/source/patches/arm9/NandSave/ReadNandSaveAsm.h
Normal file
29
arm9/source/patches/arm9/NandSave/ReadNandSaveAsm.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "patches/PatchCode.h"
|
||||
#include "sections.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/platform/SdReadPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(patch_readnandsave);
|
||||
|
||||
extern "C" bool patch_readNandSave(void* dst, u32 nandByteOffset, u32 byteLength, u32 dmaChannel);
|
||||
|
||||
extern u32 patch_readNandSave_save_offset_to_sd_sector_asm_address;
|
||||
extern u32 patch_readNandSave_sdread_asm_address;
|
||||
|
||||
class ReadNandSavePatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
ReadNandSavePatchCode(PatchHeap& patchHeap, const SaveOffsetToSdSectorPatchCode* saveOffsetToSdSectorPatchCode,
|
||||
const SdReadPatchCode* sdReadPatchCode)
|
||||
: PatchCode(SECTION_START(patch_readnandsave), SECTION_SIZE(patch_readnandsave), patchHeap)
|
||||
{
|
||||
patch_readNandSave_save_offset_to_sd_sector_asm_address = (u32)saveOffsetToSdSectorPatchCode->GetRemapFunction();
|
||||
patch_readNandSave_sdread_asm_address = (u32)sdReadPatchCode->GetSdReadFunction();
|
||||
}
|
||||
|
||||
const void* GetReadNandSaveFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)patch_readNandSave);
|
||||
}
|
||||
};
|
||||
57
arm9/source/patches/arm9/NandSave/ReadNandSaveAsm.s
Normal file
57
arm9/source/patches/arm9/NandSave/ReadNandSaveAsm.s
Normal file
@@ -0,0 +1,57 @@
|
||||
.cpu arm946e-s
|
||||
.section "patch_readnandsave", "ax"
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
// r0 = memory dst
|
||||
// r1 = nand byte offset
|
||||
// r2 = byte length
|
||||
// returns r0 = bool success
|
||||
.global patch_readNandSave
|
||||
.type patch_readNandSave, %function
|
||||
patch_readNandSave:
|
||||
push {r0,r1,r2,r4,r5,r6,lr}
|
||||
pop {r4,r5,r6}
|
||||
lsrs r6, r6, #9 // remaining number of sectors = byte length / 512
|
||||
loop:
|
||||
// while remaining number of sectors > 0
|
||||
cmp r6, #0
|
||||
beq end
|
||||
|
||||
movs r0, r5 // nand byte offset
|
||||
ldr r3, patch_readNandSave_save_offset_to_sd_sector_asm_address
|
||||
blx r3
|
||||
|
||||
mov r2, lr // sectors to read
|
||||
// if sectors to read > remaining number of sectors
|
||||
cmp r2, r6
|
||||
bls 1f
|
||||
movs r2, r6 // sectors to read = remaining number of sectors
|
||||
1:
|
||||
subs r6, r2 // remaining number of sectors -= sectors to read
|
||||
movs r1, r4 // memory dst
|
||||
lsls r3, r2, #9
|
||||
adds r4, r3 // memory dst += sectors to read * 512
|
||||
adds r5, r3 // nand byte offset += sectors to read * 512
|
||||
|
||||
ldr r3, patch_readNandSave_sdread_asm_address
|
||||
blx r3
|
||||
|
||||
b loop
|
||||
|
||||
end:
|
||||
movs r0, #1
|
||||
pop {r4,r5,r6,pc}
|
||||
|
||||
.balign 4
|
||||
.pool
|
||||
|
||||
.global patch_readNandSave_save_offset_to_sd_sector_asm_address
|
||||
patch_readNandSave_save_offset_to_sd_sector_asm_address:
|
||||
.word 0
|
||||
|
||||
.global patch_readNandSave_sdread_asm_address
|
||||
patch_readNandSave_sdread_asm_address:
|
||||
.word 0
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "common.h"
|
||||
#include "gameCode.h"
|
||||
#include "patches/platform/LoaderPlatform.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "ReadNandSaveAsm.h"
|
||||
#include "WriteNandSaveAsm.h"
|
||||
#include "WarioWareDiyNandSavePatch.h"
|
||||
|
||||
// This code was based on nds-bootstrap:
|
||||
// https://github.com/DS-Homebrew/nds-bootstrap/blob/89f27d1392a68436695d0050992ee84258ef41bc/retail/bootloader/source/arm7/patch_arm9.c#L2531
|
||||
|
||||
bool WarioWareDiyNandSavePatch::FindPatchTarget(PatchContext& patchContext)
|
||||
{
|
||||
_sdPatchEntry = nullptr;
|
||||
switch (patchContext.GetGameCode())
|
||||
{
|
||||
case GAMECODE("UORE"):
|
||||
{
|
||||
_sdPatchEntry = (u8*)0x02002C04;
|
||||
break;
|
||||
}
|
||||
case GAMECODE("UORP"):
|
||||
{
|
||||
_sdPatchEntry = (u8*)0x02002CA4;
|
||||
break;
|
||||
}
|
||||
case GAMECODE("UORJ"):
|
||||
{
|
||||
_sdPatchEntry = (u8*)0x02002BE4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _sdPatchEntry != nullptr;
|
||||
}
|
||||
|
||||
void WarioWareDiyNandSavePatch::ApplyPatch(PatchContext& patchContext)
|
||||
{
|
||||
if (_sdPatchEntry == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto sectorRemapPatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<SaveOffsetToSdSectorPatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
(const save_file_info_t*)((u32)SHARED_SAVE_FILE_INFO - 0x02F00000 + 0x02700000)
|
||||
);
|
||||
auto loaderPlatform = patchContext.GetLoaderPlatform();
|
||||
auto readNandSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<ReadNandSavePatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
loaderPlatform->CreateSdReadPatchCode(patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap())
|
||||
);
|
||||
auto writeNandSavePatchCode = patchContext.GetPatchCodeCollection().AddUniquePatchCode<WriteNandSavePatchCode>
|
||||
(
|
||||
patchContext.GetPatchHeap(),
|
||||
sectorRemapPatchCode,
|
||||
loaderPlatform->CreateSdWritePatchCode(patchContext.GetPatchCodeCollection(), patchContext.GetPatchHeap())
|
||||
);
|
||||
|
||||
// u32 nandInit(void* data)
|
||||
*(u32*)(_sdPatchEntry + 0x50C) = 0xE3A00001; // mov r0, #1
|
||||
*(u32*)(_sdPatchEntry + 0x510) = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandWait(void)
|
||||
*(u32*)(_sdPatchEntry + 0xC9C) = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandState(void)
|
||||
*(u32*)(_sdPatchEntry + 0xEB0) = 0xE3A00003; // mov r0, #3
|
||||
*(u32*)(_sdPatchEntry + 0xEB4) = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandError(void)
|
||||
*(u32*)(_sdPatchEntry + 0xEC8) = 0xE3A00000; // mov r0, #0
|
||||
*(u32*)(_sdPatchEntry + 0xECC) = 0xE12FFF1E; // bx lr
|
||||
|
||||
// u32 nandWrite(void* memory, u32 flash, u32 size, u32 dmaChannel)
|
||||
*(u32*)(_sdPatchEntry + 0x958) = 0xE51FF004; // ldr pc,= patch_writeNandSave
|
||||
*(u32*)(_sdPatchEntry + 0x95C) = (u32)writeNandSavePatchCode->GetWriteNandSaveFunction();
|
||||
|
||||
// u32 nandRead(void* memory, u32 flash, u32 size, u32 dmaChannel)
|
||||
*(u32*)(_sdPatchEntry + 0xD24) = 0xE51FF004; // ldr pc,= patch_readNandSave
|
||||
*(u32*)(_sdPatchEntry + 0xD28) = (u32)readNandSavePatchCode->GetReadNandSaveFunction();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "patches/Patch.h"
|
||||
|
||||
class FunctionSignature;
|
||||
|
||||
/// @brief Arm9 patch to redirect WarioWare D.I.Y. nand saving to the SD card.
|
||||
class WarioWareDiyNandSavePatch : public Patch
|
||||
{
|
||||
public:
|
||||
bool FindPatchTarget(PatchContext& patchContext) override;
|
||||
void ApplyPatch(PatchContext& patchContext) override;
|
||||
|
||||
private:
|
||||
u8* _sdPatchEntry = nullptr;
|
||||
};
|
||||
29
arm9/source/patches/arm9/NandSave/WriteNandSaveAsm.h
Normal file
29
arm9/source/patches/arm9/NandSave/WriteNandSaveAsm.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "patches/PatchCode.h"
|
||||
#include "sections.h"
|
||||
#include "patches/SaveOffsetToSdSectorAsm.h"
|
||||
#include "patches/platform/SdWritePatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(patch_writenandsave);
|
||||
|
||||
extern "C" bool patch_writeNandSave(const void* src, u32 nandByteOffset, u32 byteLength, u32 dmaChannel);
|
||||
|
||||
extern u32 patch_writeNandSave_save_offset_to_sd_sector_asm_address;
|
||||
extern u32 patch_writeNandSave_sdwrite_asm_address;
|
||||
|
||||
class WriteNandSavePatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
WriteNandSavePatchCode(PatchHeap& patchHeap, const SaveOffsetToSdSectorPatchCode* saveOffsetToSdSectorPatchCode,
|
||||
const SdWritePatchCode* sdWritePatchCode)
|
||||
: PatchCode(SECTION_START(patch_writenandsave), SECTION_SIZE(patch_writenandsave), patchHeap)
|
||||
{
|
||||
patch_writeNandSave_save_offset_to_sd_sector_asm_address = (u32)saveOffsetToSdSectorPatchCode->GetRemapFunction();
|
||||
patch_writeNandSave_sdwrite_asm_address = (u32)sdWritePatchCode->GetSdWriteFunction();
|
||||
}
|
||||
|
||||
const void* GetWriteNandSaveFunction() const
|
||||
{
|
||||
return GetAddressAtTarget((void*)patch_writeNandSave);
|
||||
}
|
||||
};
|
||||
57
arm9/source/patches/arm9/NandSave/WriteNandSaveAsm.s
Normal file
57
arm9/source/patches/arm9/NandSave/WriteNandSaveAsm.s
Normal file
@@ -0,0 +1,57 @@
|
||||
.cpu arm946e-s
|
||||
.section "patch_writenandsave", "ax"
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
// r0 = memory src
|
||||
// r1 = nand byte offset
|
||||
// r2 = byte length
|
||||
// returns r0 = bool success
|
||||
.global patch_writeNandSave
|
||||
.type patch_writeNandSave, %function
|
||||
patch_writeNandSave:
|
||||
push {r0,r1,r2,r4,r5,r6,lr}
|
||||
pop {r4,r5,r6}
|
||||
lsrs r6, r6, #9 // remaining number of sectors = byte length / 512
|
||||
loop:
|
||||
// while remaining number of sectors > 0
|
||||
cmp r6, #0
|
||||
beq end
|
||||
|
||||
movs r0, r5 // nand byte offset
|
||||
ldr r3, patch_writeNandSave_save_offset_to_sd_sector_asm_address
|
||||
blx r3
|
||||
|
||||
mov r2, lr // sectors to read
|
||||
// if sectors to read > remaining number of sectors
|
||||
cmp r2, r6
|
||||
bls 1f
|
||||
movs r2, r6 // sectors to read = remaining number of sectors
|
||||
1:
|
||||
subs r6, r2 // remaining number of sectors -= sectors to read
|
||||
movs r1, r4 // memory src
|
||||
lsls r3, r2, #9
|
||||
adds r4, r3 // memory src += sectors to read * 512
|
||||
adds r5, r3 // nand byte offset += sectors to read * 512
|
||||
|
||||
ldr r3, patch_writeNandSave_sdwrite_asm_address
|
||||
blx r3
|
||||
|
||||
b loop
|
||||
|
||||
end:
|
||||
movs r0, #1
|
||||
pop {r4,r5,r6,pc}
|
||||
|
||||
.balign 4
|
||||
.pool
|
||||
|
||||
.global patch_writeNandSave_save_offset_to_sd_sector_asm_address
|
||||
patch_writeNandSave_save_offset_to_sd_sector_asm_address:
|
||||
.word 0
|
||||
|
||||
.global patch_writeNandSave_sdwrite_asm_address
|
||||
patch_writeNandSave_sdwrite_asm_address:
|
||||
.word 0
|
||||
|
||||
.end
|
||||
Reference in New Issue
Block a user