Skip to content

Commit

Permalink
Added IPS and UPS patch support (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
spitzeqc committed Jul 14, 2022
1 parent b1d2b5a commit 834c0ff
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "libn3ds"]
path = libn3ds
url = https://github.com/profi200/libn3ds.git
url = https://github.com/profi200/libn3ds
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ X+LEFT - Turn off LCD backlight.

X+RIGHT - Turn on LCD backlight.

Hold the X button while launching a game to skip applying patches (if present)

Hold the power button to turn off the 3DS.

## Configuration
Expand Down Expand Up @@ -80,6 +82,9 @@ Game-specific settings. Only intended to be used in the per-game settings (romNa
`u8 saveSlot` - Savegame slot (0-9)
* Default: `0`

`u8 saveType` - Override to use a specific save type, see values for `defaultSave` (0-15, 255)
* Default: `255` (disabled)

### Advanced
Options for advanced users. No pun intended.

Expand All @@ -98,6 +103,10 @@ Options for advanced users. No pun intended.
* `14`: SRAM 256k
* `15`: None

## Patches
open_agb_firm supports automatically applying IPS and UPS patches. To use a patch, rename the patch file to match the ROM file name (without the extension).
* If you wanted to apply an IPS patch to `example.gba`, rename the patch file to `example.ips`

## Known Issues
This section is reserved for a listing of known issues. At present only this remains:
* Sleep mode is not fully implemented.
Expand Down
2 changes: 1 addition & 1 deletion include/arm11/open_agb_firm.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ Result oafParseConfigEarly(void);
void changeBacklight(s16 amount);
Result oafInitAndRun(void);
void oafUpdate(void);
void oafFinish(void);
void oafFinish(void);
3 changes: 3 additions & 0 deletions include/arm11/patch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

Result patchRom(const char *const gamePath, u32 *romSize);
28 changes: 20 additions & 8 deletions source/arm11/open_agb_firm.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "arm11/drivers/lcd.h"
#include "arm11/gpu_cmd_lists.h"
#include "arm11/drivers/mcu.h"
#include "arm11/patch.h"
#include "kernel.h"
#include "kevent.h"

Expand All @@ -58,7 +59,6 @@
"saveOverride=false\n" \
"defaultSave=14"


typedef struct
{
// [general]
Expand All @@ -76,7 +76,7 @@ typedef struct

// [game]
u8 saveSlot;
// TODO: Per-game save type override.
u8 saveType;

// [advanced]
bool saveOverride;
Expand Down Expand Up @@ -110,23 +110,21 @@ static OafConfig g_oafConfig =

// [game]
0, // saveSlot
0xFF, // saveType

// [advanced]
false, // saveOverride
14 // defaultSave
};
static KHandle g_frameReadyEvent = 0;



static u32 fixRomPadding(u32 romFileSize)
{
// Pad unused ROM area with 0xFFs (trimmed ROMs).
// Smallest retail ROM chip is 8 Mbit (1 MiB).
u32 romSize = nextPow2(romFileSize);
if(romSize < 0x100000u) romSize = 0x100000u;
memset((void*)(ROM_LOC + romFileSize), 0xFFFFFFFFu, romSize - romFileSize);

if(romSize > 0x100000u) // >1 MiB.
{
// Fake "open bus" padding.
Expand All @@ -140,6 +138,7 @@ static u32 fixRomPadding(u32 romFileSize)
}
else
{

// ROM mirroring (Classic NES Series/possibly others with 8 Mbit ROM).
// Mirror ROM across the entire 32 MiB area.
for(uintptr_t i = ROM_LOC + romSize; i < ROM_LOC + MAX_ROM_SIZE; i += romSize)
Expand Down Expand Up @@ -167,9 +166,10 @@ static Result loadGbaRom(const char *const path, u32 *const romSizeOut)

u32 read;
res = fRead(f, (u8*)ROM_LOC, fileSize, &read);
if(read == fileSize) *romSizeOut = fixRomPadding(fileSize);

fClose(f);

if(read == fileSize) *romSizeOut = fixRomPadding(fileSize); //, path);

}

return res;
Expand Down Expand Up @@ -549,6 +549,8 @@ static int cfgIniCallback(void* user, const char* section, const char* name, con
{
if(strcmp(name, "saveSlot") == 0)
config->saveSlot = (u8)strtoul(value, NULL, 10);
if(strcmp(name, "saveType") == 0)
config->saveType = (u8)strtoul(value, NULL, 10);
}
else if(strcmp(section, "advanced") == 0)
{
Expand Down Expand Up @@ -751,6 +753,11 @@ Result oafInitAndRun(void)
}
else if(res != RES_OK) break;

//make copy of rom path
char *const romFilePath = (char*)calloc(strlen(filePath)+1, 1);
if(romFilePath == NULL) { res = RES_OUT_OF_MEM; break; }
strcpy(romFilePath, filePath);

// Load the ROM file.
u32 romSize;
if((res = loadGbaRom(filePath, &romSize)) != RES_OK) break;
Expand All @@ -762,11 +769,16 @@ Result oafInitAndRun(void)
// Adjust the path for the save file and get save type.
gameCfg2SavePath(filePath, g_oafConfig.saveSlot);
u16 saveType;
if(g_oafConfig.useGbaDb || g_oafConfig.saveOverride)
if(g_oafConfig.saveType != 0xFF)
saveType = g_oafConfig.saveType;
else if(g_oafConfig.useGbaDb || g_oafConfig.saveOverride)
saveType = getSaveType(romSize, filePath);
else
saveType = detectSaveType(romSize);

patchRom(romFilePath, &romSize);
free(romFilePath);

// Prepare ARM9 for GBA mode + save loading.
if((res = LGY_prepareGbaMode(g_oafConfig.directBoot, saveType, filePath)) == RES_OK)
{
Expand Down

0 comments on commit 834c0ff

Please sign in to comment.