You've already forked pico-loader
mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-01-09 16:28:35 -08:00
Compare commits
15 Commits
v1.3.0
...
feature/ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c8e98a03f | ||
|
|
f1e5f0cddc | ||
|
|
26cec4c421 | ||
|
|
e0e33032b9 | ||
|
|
9be5424f23 | ||
|
|
3e4725c99c | ||
|
|
dcc71ca151 | ||
|
|
2d4f9cb29f | ||
|
|
231f14a783 | ||
|
|
d6080984d1 | ||
|
|
6fb34c75f8 | ||
|
|
992e2d1053 | ||
|
|
842dd8e63a | ||
|
|
92a6c6ecdc | ||
|
|
c380041241 |
1
.github/workflows/nightly.yml
vendored
1
.github/workflows/nightly.yml
vendored
@@ -2,7 +2,6 @@ name: Build Pico Loader
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop"]
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
pull_request:
|
||||
|
||||
@@ -45,7 +45,7 @@ Note that there are still SDK versions and variants for which Pico Loader does n
|
||||
We recommend using WSL (Windows Subsystem for Linux), or MSYS2 to compile this repository.
|
||||
The steps provided will assume you already have one of those environments set up.
|
||||
|
||||
1. Install [BlocksDS](https://blocksds.skylyrac.net/docs/setup/options/)
|
||||
1. Install [BlocksDS](https://blocksds.skylyrac.net/docs/setup/)
|
||||
2. Install [.NET 9.0](https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu-install?tabs=dotnet9&pivots=os-linux-ubuntu-2404) for your system (note: this link points to the instructions for Ubuntu, but links for most OS'es are available on the same page)
|
||||
|
||||
## Compiling
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include "picoAgbAdapter.h"
|
||||
#include "Environment.h"
|
||||
|
||||
#define NOCASH_ID 0x67246F6E
|
||||
#define NOCASH_ID_MELONDS 0x6F6C656D
|
||||
|
||||
u32 Environment::_flags;
|
||||
|
||||
static bool detectIsNitroEmulator()
|
||||
@@ -15,10 +18,10 @@ static bool detectIsNitroEmulator()
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool detectNocashPrintSuppport()
|
||||
static bool detectNocashPrintSupport()
|
||||
{
|
||||
u32 nocashIdentifier = *(vu32*)0x04FFFA00;
|
||||
return nocashIdentifier == 0x67246F6E; //no$g
|
||||
return nocashIdentifier == NOCASH_ID || nocashIdentifier == NOCASH_ID_MELONDS;
|
||||
}
|
||||
|
||||
static bool detectPicoAgbAdapter()
|
||||
@@ -55,7 +58,7 @@ void Environment::Initialize(bool dsiMode)
|
||||
}
|
||||
if (!(_flags & ENVIRONMENT_FLAGS_IS_NITRO_EMULATOR))
|
||||
{
|
||||
if (detectNocashPrintSuppport())
|
||||
if (detectNocashPrintSupport())
|
||||
_flags |= ENVIRONMENT_FLAGS_NOCASH_PRINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,3 +95,8 @@ bool dldi_patchTo(dldi_header_t* stub)
|
||||
{
|
||||
return sDldiDriver.PatchTo(stub);
|
||||
}
|
||||
|
||||
void dldi_copyTo(void* target)
|
||||
{
|
||||
memcpy(target, sDldiBuffer, sizeof(sDldiBuffer));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
bool dldi_init();
|
||||
bool dldi_patchTo(dldi_header_t* stub);
|
||||
void dldi_copyTo(void* target);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -10,5 +10,6 @@ extern u8 __bss_size[];
|
||||
pload_header7_t gLoaderHeader
|
||||
{
|
||||
.entryPoint = (void*)&_start,
|
||||
.apiVersion = PICO_LOADER_API_VERSION
|
||||
.apiVersion = PICO_LOADER_API_VERSION,
|
||||
.launcherPath = "/_picoboot.nds"
|
||||
};
|
||||
@@ -344,6 +344,7 @@ void NdsLoader::Load(BootMode bootMode)
|
||||
if (isHomebrew)
|
||||
{
|
||||
InsertArgv();
|
||||
HandleHomebrewPatching();
|
||||
}
|
||||
|
||||
HandleDldiPatching();
|
||||
@@ -429,6 +430,22 @@ void NdsLoader::InsertArgv()
|
||||
HOMEBREW_ARGV->length = argSize;
|
||||
}
|
||||
|
||||
void NdsLoader::HandleHomebrewPatching()
|
||||
{
|
||||
sendToArm9(IPC_COMMAND_ARM9_APPLY_HOMEBREW_PATCHES);
|
||||
sendToArm9(16 * 1024); // required dldi space
|
||||
void* dldiSpace = (void*)receiveFromArm9();
|
||||
char* launcherPath = (char*)receiveFromArm9();
|
||||
if (dldiSpace != nullptr)
|
||||
{
|
||||
dldi_copyTo(dldiSpace);
|
||||
}
|
||||
if (launcherPath != nullptr)
|
||||
{
|
||||
strncpy(launcherPath, _launcherPath, 256);
|
||||
}
|
||||
}
|
||||
|
||||
void NdsLoader::ApplyArm7Patches()
|
||||
{
|
||||
sendToArm9(IPC_COMMAND_ARM9_APPLY_ARM7_PATCHES);
|
||||
|
||||
@@ -26,6 +26,13 @@ public:
|
||||
_savePath = savePath;
|
||||
}
|
||||
|
||||
/// @brief Sets the \p launcherPath to use.
|
||||
/// @param launcherPath The launcher path to use.
|
||||
void SetLauncherPath(const TCHAR* launcherPath)
|
||||
{
|
||||
_launcherPath = launcherPath;
|
||||
}
|
||||
|
||||
/// @brief Sets the argv arguments to pass to the rom.
|
||||
/// @param arguments The argv arguments.
|
||||
/// @param argumentsLength The length of the argv arguments.
|
||||
@@ -41,8 +48,9 @@ public:
|
||||
|
||||
private:
|
||||
FIL _romFile;
|
||||
const TCHAR* _romPath;
|
||||
const TCHAR* _savePath;
|
||||
const TCHAR* _romPath = nullptr;
|
||||
const TCHAR* _savePath = nullptr;
|
||||
const TCHAR* _launcherPath = nullptr;
|
||||
u32 _argumentsLength = 0;
|
||||
const char* _arguments = nullptr;
|
||||
nds_header_twl_t _romHeader;
|
||||
@@ -71,6 +79,7 @@ private:
|
||||
char driveLetter, const char* deviceName, const char* path, u8 flags, u8 accessRights);
|
||||
void SetupDsiDeviceList();
|
||||
void InsertArgv();
|
||||
void HandleHomebrewPatching();
|
||||
bool TrySetupDsiWareSave();
|
||||
bool TryDecryptSecureArea();
|
||||
ConsoleRegion GetRomRegion(u32 gameCode);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#define DLDI_MAGIC 0xBF8DA5ED
|
||||
#define DLDI_DRIVER_MAGIC_NONE 0x49444C44
|
||||
|
||||
@@ -222,6 +222,7 @@ extern "C" void loaderMain()
|
||||
sLoader.SetRomPath(gLoaderHeader.loadParams.romPath);
|
||||
handleSavePath();
|
||||
sLoader.SetArguments(gLoaderHeader.loadParams.arguments, gLoaderHeader.loadParams.argumentsLength);
|
||||
sLoader.SetLauncherPath(gLoaderHeader.launcherPath);
|
||||
sLoader.Load(BootMode::Normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectOverlayPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectPuyoPuyo7Patch.h"
|
||||
#include "patches/arm9/OverlayPatches/PokemonIr/PokemonIrApPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/KirbySuperStarUltra/KirbySuperStarUltraPatch.h"
|
||||
#include "patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h"
|
||||
#include "patches/arm9/OverlayPatches/GoldenSunDarkDawn/GoldenSunDarkDawnOverlayHookPatch.h"
|
||||
#include "SecureSysCallsUnusedSpaceLocator.h"
|
||||
#include "fastSearch.h"
|
||||
@@ -404,6 +406,22 @@ void Arm9Patcher::AddGameSpecificPatches(
|
||||
patchCollection.AddPatch(new NintendoDSGuideNandSavePatch());
|
||||
break;
|
||||
}
|
||||
// Rabbids Go Home
|
||||
case GAMECODE("VRGE"):
|
||||
case GAMECODE("VRGV"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new RabbidsGoHomePatch());
|
||||
break;
|
||||
}
|
||||
// Kirby Super Star Ultra
|
||||
case GAMECODE("YKWE"):
|
||||
case GAMECODE("YKWJ"):
|
||||
case GAMECODE("YKWK"):
|
||||
case GAMECODE("YKWP"):
|
||||
{
|
||||
overlayHookPatch->AddOverlayPatch(new KirbySuperStarUltraPatch());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "errorDisplay/ErrorDisplay.h"
|
||||
#include "LoaderInfo.h"
|
||||
#include "jumpToArm9EntryPoint.h"
|
||||
#include "patches/homebrew/BootstubPatchCode.h"
|
||||
#include "HomebrewBootstub.h"
|
||||
|
||||
#define HANDSHAKE_PART0 0xA
|
||||
#define HANDSHAKE_PART1 0xB
|
||||
@@ -192,8 +194,8 @@ static void handleGetSdFunctionsCommand()
|
||||
{
|
||||
auto sdReadPatchCode = sLoaderPlatform->CreateSdReadPatchCode(patchCodeCollection, patchHeap);
|
||||
auto sdWritePatchCode = sLoaderPlatform->CreateSdWritePatchCode(patchCodeCollection, patchHeap);
|
||||
*(vu32*)0x037F8000 = (u32)sdReadPatchCode->GetSdReadFunction();
|
||||
*(vu32*)0x037F8004 = (u32)sdWritePatchCode->GetSdWriteFunction();
|
||||
*(vu32*)0x037F8000 = (u32)sdReadPatchCode->GetReadSectorsFunction();
|
||||
*(vu32*)0x037F8004 = (u32)sdWritePatchCode->GetWriteSectorFunction();
|
||||
patchCodeCollection.CopyAllToTarget();
|
||||
}
|
||||
dc_flushAll();
|
||||
@@ -231,6 +233,37 @@ static void handleBootCommand()
|
||||
bootArm9();
|
||||
}
|
||||
|
||||
static void handleApplyHomebrewPatches(u32 dldiRequiredSpace)
|
||||
{
|
||||
// Insert bootstub
|
||||
PatchHeap patchHeap;
|
||||
PatchCodeCollection patchCodeCollection;
|
||||
void* patchSpace = (void*)&HOMEBREW_BOOTSTUB[1];
|
||||
auto romHeader = (const nds_header_ntr_t*)TWL_SHARED_MEMORY->ntrSharedMem.romHeader;
|
||||
if (!romHeader->IsTwlRom())
|
||||
{
|
||||
patchSpace = (u8*)patchSpace - 0x2F00000 + 0x2300000;
|
||||
}
|
||||
patchHeap.AddFreeSpace(patchSpace, 32 * 1024 - sizeof(homebrew_bootstub_t));
|
||||
|
||||
void* dldi = patchHeap.Alloc(dldiRequiredSpace);
|
||||
char* launcherPath = (char*)patchHeap.Alloc(256);
|
||||
|
||||
auto bootstubPatchCode = patchCodeCollection.AddUniquePatchCode<BootstubPatchCode>(
|
||||
patchHeap, dldi, launcherPath, &sLoaderInfo,
|
||||
sLoaderPlatform->CreateSdReadPatchCode(patchCodeCollection, patchHeap));
|
||||
|
||||
HOMEBREW_BOOTSTUB->bootSig = HOMEBREW_BOOTSTUB_BOOTSIG;
|
||||
HOMEBREW_BOOTSTUB->arm9Reboot = (void*)bootstubPatchCode->GetArm9RebootFunction();
|
||||
HOMEBREW_BOOTSTUB->arm7Reboot = (void*)bootstubPatchCode->GetArm7RebootFunction();
|
||||
HOMEBREW_BOOTSTUB->bootSize = 32 * 1024 - sizeof(homebrew_bootstub_t);
|
||||
|
||||
patchCodeCollection.CopyAllToTarget();
|
||||
|
||||
ipc_sendWordDirect((u32)dldi);
|
||||
ipc_sendWordDirect((u32)launcherPath);
|
||||
}
|
||||
|
||||
static void handleArm7Command(u32 command)
|
||||
{
|
||||
switch (command)
|
||||
@@ -295,6 +328,12 @@ static void handleArm7Command(u32 command)
|
||||
handleBootCommand();
|
||||
break;
|
||||
}
|
||||
case IPC_COMMAND_ARM9_APPLY_HOMEBREW_PATCHES:
|
||||
{
|
||||
u32 dldiRequiredSpace = receiveFromArm7();
|
||||
handleApplyHomebrewPatches(dldiRequiredSpace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
13
arm9/source/patches/ISectorRemapPatchCode.h
Normal file
13
arm9/source/patches/ISectorRemapPatchCode.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Interface for sector remapping patch code.
|
||||
class ISectorRemapPatchCode
|
||||
{
|
||||
protected:
|
||||
ISectorRemapPatchCode() { }
|
||||
|
||||
public:
|
||||
/// @brief Gets a pointer to the sector remap function in the patch code.
|
||||
/// @return The pointer to the sector remap function.
|
||||
virtual const void* GetRemapFunction() const = 0;
|
||||
};
|
||||
@@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "SectorRemapPatchCode.h"
|
||||
#include "PatchCode.h"
|
||||
#include "ISectorRemapPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(offsettosectorremap);
|
||||
|
||||
extern "C" u32 offset_to_sector_remap(u32 romOffset);
|
||||
|
||||
class OffsetToSectorRemapPatchCode : public SectorRemapPatchCode
|
||||
class OffsetToSectorRemapPatchCode : public PatchCode, public ISectorRemapPatchCode
|
||||
{
|
||||
public:
|
||||
explicit OffsetToSectorRemapPatchCode(PatchHeap& patchHeap)
|
||||
: SectorRemapPatchCode(SECTION_START(offsettosectorremap), SECTION_SIZE(offsettosectorremap), patchHeap)
|
||||
{ }
|
||||
: PatchCode(SECTION_START(offsettosectorremap), SECTION_SIZE(offsettosectorremap), patchHeap) { }
|
||||
|
||||
const void* GetRemapFunction() const override
|
||||
{
|
||||
@@ -20,15 +20,6 @@ public:
|
||||
while (1);
|
||||
}
|
||||
|
||||
/// @brief Converts a pointer inside the original code block
|
||||
/// to a pointer at the target location in the patch heap.
|
||||
/// @param ptr The pointer to convert.
|
||||
/// @return The converted pointer.
|
||||
const void* GetAddressAtTarget(const void* ptr) const
|
||||
{
|
||||
return (const void*)((u32)ptr - (u32)_code + (u32)_targetAddress);
|
||||
}
|
||||
|
||||
/// @brief Copies the patch code to the target address.
|
||||
void CopyToTarget() const
|
||||
{
|
||||
@@ -44,4 +35,13 @@ protected:
|
||||
|
||||
/// @brief The target address for the code block in the patch heap.
|
||||
void* const _targetAddress;
|
||||
|
||||
/// @brief Converts a pointer inside the original code block
|
||||
/// to a pointer at the target location in the patch heap.
|
||||
/// @param ptr The pointer to convert.
|
||||
/// @return The converted pointer.
|
||||
const void* GetAddressAtTarget(const void* ptr) const
|
||||
{
|
||||
return (const void*)((u32)ptr - (u32)_code + (u32)_targetAddress);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "SectorRemapPatchCode.h"
|
||||
#include "PatchCode.h"
|
||||
#include "ISectorRemapPatchCode.h"
|
||||
#include "fileInfo.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(saveoffsettosdsector);
|
||||
@@ -9,11 +10,11 @@ extern "C" u32 save_offset_to_sd_sector_asm(u32 saveOffset);
|
||||
|
||||
extern u32 saveoffsettosdsector_fatDataPtr;
|
||||
|
||||
class SaveOffsetToSdSectorPatchCode : public SectorRemapPatchCode
|
||||
class SaveOffsetToSdSectorPatchCode : public PatchCode, public ISectorRemapPatchCode
|
||||
{
|
||||
public:
|
||||
SaveOffsetToSdSectorPatchCode(PatchHeap& patchHeap, const save_file_info_t* fatDataPtr)
|
||||
: SectorRemapPatchCode(SECTION_START(saveoffsettosdsector), SECTION_SIZE(saveoffsettosdsector), patchHeap)
|
||||
: PatchCode(SECTION_START(saveoffsettosdsector), SECTION_SIZE(saveoffsettosdsector), patchHeap)
|
||||
{
|
||||
saveoffsettosdsector_fatDataPtr = (u32)fatDataPtr;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
#include "PatchCode.h"
|
||||
|
||||
class SectorRemapPatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
SectorRemapPatchCode(const void* code, u32 size, PatchHeap& patchHeap)
|
||||
: PatchCode(code, size, patchHeap) { }
|
||||
|
||||
virtual const void* GetRemapFunction() const = 0;
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "sections.h"
|
||||
#include "../PatchCode.h"
|
||||
#include "../SectorRemapPatchCode.h"
|
||||
#include "../platform/SdReadPatchCode.h"
|
||||
#include "patches/PatchCode.h"
|
||||
#include "patches/ISectorRemapPatchCode.h"
|
||||
#include "patches/platform/IReadSectorsPatchCode.h"
|
||||
|
||||
DEFINE_SECTION_SYMBOLS(readsave);
|
||||
|
||||
@@ -15,12 +15,12 @@ extern u32 readsave_sdread_asm_address;
|
||||
class ReadSavePatchCode : public PatchCode
|
||||
{
|
||||
public:
|
||||
ReadSavePatchCode(PatchHeap& patchHeap, const SectorRemapPatchCode* sectorRemapPatchCode,
|
||||
const SdReadPatchCode* sdReadPatchCode, void* tmpBuffer)
|
||||
ReadSavePatchCode(PatchHeap& patchHeap, const ISectorRemapPatchCode* sectorRemapPatchCode,
|
||||
const IReadSectorsPatchCode* readSectorsPatchCode, void* tmpBuffer)
|
||||
: PatchCode(SECTION_START(readsave), SECTION_SIZE(readsave), patchHeap)
|
||||
{
|
||||
readsave_save_offset_to_sd_sector_asm_address = (u32)sectorRemapPatchCode->GetRemapFunction();
|
||||
readsave_sdread_asm_address = (u32)sdReadPatchCode->GetSdReadFunction();
|
||||
readsave_sdread_asm_address = (u32)readSectorsPatchCode->GetReadSectorsFunction();
|
||||
readsave_tmpBufferPtr = (u32)tmpBuffer;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user