Skip to content

Commit

Permalink
upstream:Add basic support for prototype firmware;chs:Show page info …
Browse files Browse the repository at this point in the history
…for cheats menu
  • Loading branch information
R-YaTian committed Dec 10, 2024
1 parent a509b4e commit be42b99
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 17 deletions.
42 changes: 36 additions & 6 deletions arm9/source/firm.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "chainloader.h"

static Firm *firm = (Firm *)0x20001000;
u32 firmProtoVersion = 0;

static __attribute__((noinline)) bool overlaps(u32 as, u32 ae, u32 bs, u32 be)
{
Expand Down Expand Up @@ -203,29 +204,38 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
{
firmVersion = 0xFFFFFFFF;

if(!ISN3DS && *firmType == NATIVE_FIRM)
if(!ISN3DS && (*firmType == NATIVE_FIRM || *firmType == NATIVE_FIRM1X2X))
{
__attribute__((aligned(4))) static const u8 hashes[3][0x20] = {
__attribute__((aligned(4))) static const u8 hashes[4][0x20] = {
{0xD7, 0x43, 0x0F, 0x27, 0x8D, 0xC9, 0x3F, 0x4C, 0x96, 0xB5, 0xA8, 0x91, 0x48, 0xDB, 0x08, 0x8A,
0x7E, 0x46, 0xB3, 0x95, 0x65, 0xA2, 0x05, 0xF1, 0xF2, 0x41, 0x21, 0xF1, 0x0C, 0x59, 0x6A, 0x9D},
{0x39, 0x75, 0xB5, 0x28, 0x24, 0x5E, 0x8B, 0x56, 0xBC, 0x83, 0x79, 0x41, 0x09, 0x2C, 0x42, 0xE6,
0x26, 0xB6, 0x80, 0x59, 0xA5, 0x56, 0xF9, 0xF9, 0x6E, 0xF3, 0x63, 0x05, 0x58, 0xDF, 0x35, 0xEF},
{0x81, 0x9E, 0x71, 0x58, 0xE5, 0x44, 0x73, 0xF7, 0x48, 0x78, 0x7C, 0xEF, 0x5E, 0x30, 0xE2, 0x28,
0x78, 0x0B, 0x21, 0x23, 0x94, 0x63, 0xE8, 0x4E, 0x06, 0xBB, 0xD6, 0x8D, 0xA0, 0x99, 0xAE, 0x98},
{0x1D, 0xD5, 0xB0, 0xC2, 0xD9, 0x4A, 0x4A, 0xF3, 0x23, 0xDD, 0x2F, 0x65, 0x21, 0x95, 0x9B, 0x7E,
0xF2, 0x71, 0x7E, 0xB6, 0x7A, 0x3A, 0x74, 0x78, 0x0D, 0xE3, 0xB5, 0x0C, 0x2B, 0x7F, 0x85, 0x37}
0xF2, 0x71, 0x7E, 0xB6, 0x7A, 0x3A, 0x74, 0x78, 0x0D, 0xE3, 0xB5, 0x0C, 0x2B, 0x7F, 0x85, 0x37},
};

u32 i;
for(i = 0; i < 3; i++) if(memcmp(firm->section[1].hash, hashes[i], 0x20) == 0) break;
for(i = 0; i < 4; i++) if(memcmp(firm->section[1].hash, hashes[i], 0x20) == 0) break;

switch(i)
{
// Beta
case 0:
firmVersion = 0x18;
firmVersion = 0x0;
firmProtoVersion = 243;
*firmType = NATIVE_PROTOTYPE;
break;
// Release
case 1:
firmVersion = 0x1D;
firmVersion = 0x18;
break;
case 2:
firmVersion = 0x1D;
break;
case 3:
firmVersion = 0x1F;
break;
default:
Expand Down Expand Up @@ -737,6 +747,26 @@ u32 patch1x2xNativeAndSafeFirm(void)
return ret;
}

u32 patchPrototypeNative(void)
{
u8 *arm9Section = (u8 *)firm + firm->section[2].offset;

//Find the Process9 .code location, size and memory address
u32 process9Size,
process9MemAddr;
u8 *process9Offset = getProcess9Info(arm9Section, firm->section[2].size, &process9Size, &process9MemAddr);

u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
ret = 0;

ret += patchProtoNandSignatureCheck(process9Offset, process9Size);

//Arm9 exception handlers
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);

return ret;
}

void launchFirm(int argc, char **argv)
{
prepareArm11ForFirmlaunch();
Expand Down
1 change: 1 addition & 0 deletions arm9/source/firm.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
u32 patch1x2xNativeAndSafeFirm(void);
u32 patchPrototypeNative(void);
void launchFirm(int argc, char **argv);
3 changes: 3 additions & 0 deletions arm9/source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,9 @@ void main(int argc, char **argv, u32 magicWord)
case NATIVE_FIRM1X2X:
res = patch1x2xNativeAndSafeFirm();
break;
case NATIVE_PROTOTYPE:
res = patchPrototypeNative();
break;
}

if(res != 0) error("Failed to apply %u FIRM patch(es).", res);
Expand Down
31 changes: 29 additions & 2 deletions arm9/source/patches.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define K11EXT_VA 0x70000000

extern u16 launchedPath[];
extern u32 firmProtoVersion;

u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
{
Expand All @@ -54,10 +55,19 @@ u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)

Cxi *off = (Cxi *)(temp - 0x100);

*process9Size = (off->ncch.exeFsSize - 1) * 0x200;
*process9MemAddr = off->exHeader.systemControlInfo.textCodeSet.address;

return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200;
// Prototype FW has a different NCCH format
if (firmProtoVersion && firmProtoVersion <= 243)
{
*process9Size = off->ncch.exeFsSize;
return (u8 *)off + off->ncch.exeFsOffset;
}
else
{
*process9Size = (off->ncch.exeFsSize - 1) * 0x200;
return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200;
}
}

u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage)
Expand Down Expand Up @@ -834,3 +844,20 @@ u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size)

return 0;
}

u32 patchProtoNandSignatureCheck(u8 *pos, u32 size) {
if (firmProtoVersion == 243) {
static const u8 pattern[] = {0x08, 0x31, 0x9F, 0xE5};

// Signature check function returns 0 if failed and 1 if succeeded.
// Proc9 breaks if the returned value is 0, change it to break if
// the returned value is 2 (never).
u8 *off = memsearch(pos, pattern, size, sizeof(pattern)) + 0x20;
if (!off)
return 1;

*off = 2;
}

return 0;
}
2 changes: 2 additions & 0 deletions arm9/source/patches.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* FIRM partition writes patches by delebile
* Idea for svcBreak patches from yellows8 and others on #3dsdev
* TWL_FIRM patches by Steveice10 and others
* Signature patches for prototype FW by PabloMK7
*/

#pragma once
Expand Down Expand Up @@ -68,3 +69,4 @@ u32 patchTwlShaHashChecks(u8 *pos, u32 size);
u32 patchAgbBootSplash(u8 *pos, u32 size);
void patchTwlBg(u8 *pos, u32 size); // silently fails
u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size);
u32 patchProtoNandSignatureCheck(u8 *pos, u32 size);
3 changes: 2 additions & 1 deletion arm9/source/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ typedef enum FirmwareType
AGB_FIRM,
SAFE_FIRM,
SYSUPDATER_FIRM,
NATIVE_FIRM1X2X
NATIVE_FIRM1X2X,
NATIVE_PROTOTYPE
} FirmwareType;

typedef enum bootType
Expand Down
2 changes: 1 addition & 1 deletion sysmodules/rosalina/include/menus/cheats.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#include <3ds/types.h>

#define CHEATS_PER_MENU_PAGE 10
#define CHEATS_PER_MENU_PAGE 11

void RosalinaMenu_Cheats(void);
void Cheat_SeedRng(u64 seed);
Expand Down
2 changes: 1 addition & 1 deletion sysmodules/rosalina/source/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int NumberOfHotKey(u32 n)

void Draw_CheatHotKey(u32 posY, u32 color, u32 keycode) {
u16 *const fb = (u16 *)FB_BOTTOM_VRAM_ADDR;
//11111111000100001100111111111111
// 11111111000100001100111111111111
uint16_t offset[] = {0,16,32,48,64,80,96,112,128,144,160,176,368,368,192,208,368,368,368,368,224,368,368,368,240,256,272,288,304,320,336,352};
s32 charWidth = 16;
int hkCount = NumberOfHotKey(keycode);
Expand Down
15 changes: 9 additions & 6 deletions sysmodules/rosalina/source/menus/cheats.c
Original file line number Diff line number Diff line change
Expand Up @@ -2077,7 +2077,11 @@ void RosalinaMenu_Cheats(void)
}
if (R_SUCCEEDED(r))
{
Draw_DrawFormattedString(8, 8, COLOR_TITLE, "金手指列表");
Draw_DrawFormattedString(2, 2, COLOR_TITLE, "金手指列表");
char idx[16] = { 0 };
sprintf(idx, "%d/%d 页", (u8) page + 1,
(cheatCount % CHEATS_PER_MENU_PAGE == 0) ? cheatCount / CHEATS_PER_MENU_PAGE : (cheatCount / CHEATS_PER_MENU_PAGE) + 1);
Draw_DrawString(316 - (strlen(idx) - 1) * 8, 2, COLOR_TITLE, idx);

for (s32 i = 0; i < CHEATS_PER_MENU_PAGE && page * CHEATS_PER_MENU_PAGE + i < cheatCount; i++)
{
Expand All @@ -2086,13 +2090,12 @@ void RosalinaMenu_Cheats(void)
const char * checkbox = (cheats[j]->active ? "[X]" : "[ ]");
sprintf(buf, "%s%s", checkbox, cheats[j]->name);
if (cheats[j]->hasKeyCode) {
Draw_DrawString(20, 28 + i * (SPACING_Y+4), COLOR_WHITE, buf);
Draw_CheatHotKey(28 + i * (SPACING_Y+4), COLOR_WHITE, cheats[j]->keyCode);
Draw_DrawString(14, 22 + i * (SPACING_Y+4), COLOR_WHITE, buf);
Draw_CheatHotKey(22 + i * (SPACING_Y+4), COLOR_WHITE, cheats[j]->keyCode);
} else {
Draw_DrawString(20, 28 + i * (SPACING_Y+4), cheats[j]->valid ? COLOR_WHITE : COLOR_RED, buf);
Draw_DrawString(14, 22 + i * (SPACING_Y+4), cheats[j]->valid ? COLOR_WHITE : COLOR_RED, buf);
}
Draw_DrawCharacter(8, 28 + i * (SPACING_Y+4), COLOR_TITLE, j == selected ? '>' : ' ');
// Draw_DrawString(40, 28 + i * (SPACING_Y+4), cheats[j]->active ? COLOR_GREEN : COLOR_RED, cheats[j]->active ? "开" : "关");
Draw_DrawCharacter(2, 22 + i * (SPACING_Y+4), COLOR_TITLE, j == selected ? '>' : ' ');
}
}
else
Expand Down

0 comments on commit be42b99

Please sign in to comment.