From 505a17bba14c208e024ff72c2197fc8ac3c5245e Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sat, 16 Jan 2021 21:16:32 +0000 Subject: [PATCH] rosalina: add DSP firm dumping option --- .../rosalina/include/menus/miscellaneous.h | 1 + .../rosalina/source/menus/miscellaneous.c | 98 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/sysmodules/rosalina/include/menus/miscellaneous.h b/sysmodules/rosalina/include/menus/miscellaneous.h index ff38803..8efab34 100644 --- a/sysmodules/rosalina/include/menus/miscellaneous.h +++ b/sysmodules/rosalina/include/menus/miscellaneous.h @@ -37,3 +37,4 @@ void MiscellaneousMenu_SaveSettings(void); void MiscellaneousMenu_InputRedirection(void); void MiscellaneousMenu_UpdateTimeDateNtp(void); void MiscellaneousMenu_NullifyUserTimeOffset(void); +void MiscellaneousMenu_DumpDspFirm(void); diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index ae59e38..2367674 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -36,6 +36,32 @@ #include "minisoc.h" #include "ifile.h" #include "pmdbgext.h" +#include "process_patches.h" + +typedef struct DspFirmSegmentHeader { + u32 offset; + u32 loadAddrHalfwords; + u32 size; + u8 _0x0C[3]; + u8 memType; + u8 hash[0x20]; +} DspFirmSegmentHeader; + +typedef struct DspFirm { + u8 signature[0x100]; + char magic[4]; + u32 totalSize; // no more than 0x10000 + u16 layoutBitfield; + u8 _0x10A[3]; + u8 surroundSegmentMemType; + u8 numSegments; // no more than 10 + u8 flags; + u32 surroundSegmentLoadAddrHalfwords; + u32 surroundSegmentSize; + u8 _0x118[8]; + DspFirmSegmentHeader segmentHdrs[10]; + u8 data[]; +} DspFirm; Menu miscellaneousMenu = { "Miscellaneous options menu", @@ -45,6 +71,7 @@ Menu miscellaneousMenu = { { "Start InputRedirection", METHOD, .method = &MiscellaneousMenu_InputRedirection }, { "Update time and date via NTP", METHOD, .method = &MiscellaneousMenu_UpdateTimeDateNtp }, { "Nullify user time offset", METHOD, .method = &MiscellaneousMenu_NullifyUserTimeOffset }, + { "Dump DSP firmware", METHOD, .method = &MiscellaneousMenu_DumpDspFirm }, { "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings }, {}, } @@ -427,7 +454,6 @@ void MiscellaneousMenu_UpdateTimeDateNtp(void) } - void MiscellaneousMenu_NullifyUserTimeOffset(void) { Result res = ntpNullifyUserTimeOffset(); @@ -450,3 +476,73 @@ void MiscellaneousMenu_NullifyUserTimeOffset(void) } while(!(waitInput() & KEY_B) && !menuShouldExit); } + +static Result MiscellaneousMenu_DumpDspFirmCallback(Handle procHandle, u32 textSz, u32 roSz, u32 rwSz) +{ + (void)procHandle; + Result res = 0; + + // NOTE: we suppose .text, .rodata, .data+.bss are contiguous & in that order + u32 rwStart = 0x00100000 + textSz + roSz; + u32 rwEnd = rwStart + rwSz; + + // Locate the DSP firm (it's in .data, not .rodata, suprisingly) + u32 magic; + memcpy(&magic, "DSP1", 4); + const u32 *off = (u32 *)rwStart; + + for (; off < (u32 *)rwEnd && *off != magic; off++); + + if (off >= (u32 *)rwEnd || off < (u32 *)(rwStart + 0x100)) + return -2; + + // Do some sanity checks + const DspFirm *firm = (const DspFirm *)((u32)off - 0x100); + if (firm->totalSize > 0x10000 || firm->numSegments > 10) + return -3; + if ((u32)firm + firm->totalSize >= rwEnd) + return -3; + + // Dump to SD card (no point in dumping to CTRNAND as 3dsx stuff doesn't work there) + IFile file; + res = IFile_Open( + &file, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), + fsMakePath(PATH_ASCII, "/3ds/dspfirm.cdc"), FS_OPEN_CREATE | FS_OPEN_WRITE + ); + + u64 total; + if(R_SUCCEEDED(res)) + res = IFile_Write(&file, &total, firm, firm->totalSize, 0); + if(R_SUCCEEDED(res)) + res = IFile_SetSize(&file, firm->totalSize); // truncate accordingly + + IFile_Close(&file); + + return res; +} +void MiscellaneousMenu_DumpDspFirm(void) +{ + Result res = OperateOnProcessByName("menu", MiscellaneousMenu_DumpDspFirmCallback); + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu"); + if(R_SUCCEEDED(res)) + Draw_DrawString(10, 30, COLOR_WHITE, "DSP firm. successfully written to /3ds/dspfirm.cdc\non the SD card."); + else + Draw_DrawFormattedString( + 10, 30, COLOR_WHITE, + "Operation failed (0x%08lx).\n\nMake sure that Home Menu is running and that your\nSD card is inserted.", + res + ); + Draw_FlushFramebuffer(); + Draw_Unlock(); + } + while(!(waitInput() & KEY_B) && !menuShouldExit); +}