Skip to content

Commit 5ff0c67

Browse files
committed
Add button remapping
Closes #1787
1 parent 53bf275 commit 5ff0c67

File tree

34 files changed

+766
-98
lines changed

34 files changed

+766
-98
lines changed

retail/arm9/include/configuration.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ typedef struct configuration {
6767
// int colorMode;
6868
u8 romRead_LED;
6969
u8 dmaRomRead_LED;
70+
u8 remappedKeyA;
71+
u8 remappedKeyB;
72+
u8 remappedKeySELECT;
73+
u8 remappedKeySTART;
74+
u8 remappedKeyR;
75+
u8 remappedKeyL;
76+
u8 remappedKeyX;
77+
u8 remappedKeyY;
7078
bool asyncCardRead;
7179
int cardReadDMA;
7280
bool boostCpu;

retail/arm9/source/conf_sd.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,16 @@ static void load_conf(configuration* conf, const char* fn) {
409409
// DMA ROM read LED
410410
conf->dmaRomRead_LED = strtol(config_file.fetch("NDS-BOOTSTRAP", "DMA_ROMREAD_LED", "0").c_str(), NULL, 0);
411411

412+
// Remapped buttons
413+
conf->remappedKeyA = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_A", "0").c_str(), NULL, 0);
414+
conf->remappedKeyB = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_B", "1").c_str(), NULL, 0);
415+
conf->remappedKeySELECT = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_SELECT", "2").c_str(), NULL, 0);
416+
conf->remappedKeySTART = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_START", "3").c_str(), NULL, 0);
417+
conf->remappedKeyR = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_R", "8").c_str(), NULL, 0);
418+
conf->remappedKeyL = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_L", "9").c_str(), NULL, 0);
419+
conf->remappedKeyX = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_X", "10").c_str(), NULL, 0);
420+
conf->remappedKeyY = strtol(config_file.fetch("NDS-BOOTSTRAP", "REMAPPED_KEY_Y", "11").c_str(), NULL, 0);
421+
412422
// get the gamecode
413423
FILE* romFile = fopen(conf->ndsPath, "rb");
414424
char gameTid[5];

retail/arm9/source/nds_loader_arm9.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,14 @@ int runNds(u32 cluster, u32 saveCluster, u32 donorTwlCluster, /* u32 gbaCluster,
307307
loader->language = conf->language;
308308
loader->region = conf->region;
309309
loader->dsiMode = conf->dsiMode; // SDK 5
310+
loader->remappedKeyA = conf->remappedKeyA;
311+
loader->remappedKeyB = conf->remappedKeyB;
312+
loader->remappedKeySELECT = conf->remappedKeySELECT;
313+
loader->remappedKeySTART = conf->remappedKeySTART;
314+
loader->remappedKeyR = conf->remappedKeyR;
315+
loader->remappedKeyL = conf->remappedKeyL;
316+
loader->remappedKeyX = conf->remappedKeyX;
317+
loader->remappedKeyY = conf->remappedKeyY;
310318
loader->valueBits2 = conf->valueBits2;
311319
loader->donorSdkVer = conf->donorSdkVer;
312320
loader->patchMpuRegion = conf->patchMpuRegion;

retail/bootloader/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ CFLAGS := -g -Wall -O2\
3737
-ffast-math \
3838
$(ARCH)
3939

40-
CFLAGS += $(INCLUDE) -DARM7 -D_NO_SDMMC -DB4DS -DLOADERTYPE0 -std=gnu99
40+
CFLAGS += $(INCLUDE) -DARM7 -D_NO_SDMMC -DB4DS -DBUILDFATTABLE -DLOADERTYPE0 -std=gnu99
4141

4242
ASFLAGS := -g $(ARCH) $(INCLUDE)
4343
LDFLAGS = -nostartfiles -T $(TOPDIR)/load.ld -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(TARGET).map

retail/bootloader/include/patch.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ u32 patchCardNdsArm9(
151151
const tNDSHeader* ndsHeader,
152152
const module_params_t* moduleParams,
153153
u32 patchMpuRegion,
154-
const bool usesCloneboot
154+
const bool usesCloneboot,
155+
const bool buttonsRemapped
155156
);
156157
void patchCardNdsArm9Cont(
157158
cardengineArm9* ce9,
@@ -162,7 +163,8 @@ u32 patchCardNdsArm7(
162163
cardengineArm7* ce7,
163164
tNDSHeader* ndsHeader,
164165
const module_params_t* moduleParams,
165-
u32 saveFileCluster
166+
u32 saveFileCluster,
167+
const bool buttonsRemapped
166168
);
167169
u32 patchCardNds(
168170
cardengineArm7* ce7,
@@ -171,6 +173,7 @@ u32 patchCardNds(
171173
const module_params_t* moduleParams,
172174
u32 patchMpuRegion,
173175
const bool usesCloneboot,
176+
const bool buttonsRemapped,
174177
u32 saveFileCluster,
175178
u32 saveSize
176179
);

retail/bootloader/source/arm7/hook_arm7.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ int hookNdsRetailArm7(
208208

209209
const bool laterSdk = ((moduleParams->sdk_version >= 0x2008000 && moduleParams->sdk_version != 0x2012774) || moduleParams->sdk_version == 0x20029A8);
210210

211+
extern u8 remappedKeyA;
212+
extern u8 remappedKeyB;
213+
extern u8 remappedKeySELECT;
214+
extern u8 remappedKeySTART;
215+
extern u8 remappedKeyR;
216+
extern u8 remappedKeyL;
217+
extern u8 remappedKeyX;
218+
extern u8 remappedKeyY;
219+
211220
u32 cheatEngineAddr = CHEAT_ENGINE_LOCATION_B4DS;
212221
if (!extendedMemory && strncmp(romTid, "CLJ", 3) == 0) { // Mario & Luigi: Bowser's Inside Story
213222
cheatEngineAddr = 0x02002000;
@@ -241,6 +250,14 @@ int hookNdsRetailArm7(
241250
if (strcmp(romTid, "AKYP") == 0) { // Etrian Odyssey (EUR)
242251
ce7->languageAddr = (u32*)0x020DC5DC;
243252
}
253+
ce7->remappedKeyA = remappedKeyA;
254+
ce7->remappedKeyB = remappedKeyB;
255+
ce7->remappedKeySELECT = remappedKeySELECT;
256+
ce7->remappedKeySTART = remappedKeySTART;
257+
ce7->remappedKeyR = remappedKeyR;
258+
ce7->remappedKeyL = remappedKeyL;
259+
ce7->remappedKeyX = remappedKeyX;
260+
ce7->remappedKeyY = remappedKeyY;
244261
ce7->RumblePakType = RumblePakType;
245262

246263
*vblankHandler = ce7->patches->vblankHandler;

retail/bootloader/source/arm7/load_crt0.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@
7676
.global language
7777
.global region
7878
.global dsiMode
79+
.global remappedKeyA
80+
.global remappedKeyB
81+
.global remappedKeySELECT
82+
.global remappedKeySTART
83+
.global remappedKeyR
84+
.global remappedKeyL
85+
.global remappedKeyX
86+
.global remappedKeyY
7987
.global valueBits2
8088
.global donorSdkVer
8189
.global consoleModel
@@ -210,6 +218,22 @@ region:
210218
.byte 0
211219
dsiMode:
212220
.byte 0
221+
remappedKeyA:
222+
.byte 0
223+
remappedKeyB:
224+
.byte 1
225+
remappedKeySELECT:
226+
.byte 2
227+
remappedKeySTART:
228+
.byte 3
229+
remappedKeyR:
230+
.byte 8
231+
remappedKeyL:
232+
.byte 9
233+
remappedKeyX:
234+
.byte 10
235+
remappedKeyY:
236+
.byte 11
213237
valueBits2:
214238
.byte 0
215239
donorSdkVer:

retail/bootloader/source/arm7/main.arm7.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ extern u32 patchMpuSize;
116116
extern u8 patchMpuRegion;
117117
extern u8 language;
118118
extern s8 region;
119+
extern u8 remappedKeyA;
120+
extern u8 remappedKeyB;
121+
extern u8 remappedKeySELECT;
122+
extern u8 remappedKeySTART;
123+
extern u8 remappedKeyR;
124+
extern u8 remappedKeyL;
125+
extern u8 remappedKeyX;
126+
extern u8 remappedKeyY;
119127
extern u8 donorSdkVer;
120128
extern u8 soundFreq;
121129
extern char version[20];
@@ -285,7 +293,7 @@ static void resetMemory_ARM7(void) {
285293
memset_addrs_arm7(0x03800000 - 0x8000, 0x03800000 + 0x10000);
286294
toncset((u32*)0x02380000, 0, 0x38000); // clear part of EWRAM - except before 0x023B8000, which has the DSiWare ROM's arm9i code, and 0x023BF000, which has the bootloader arm9 code
287295
toncset((u32*)0x023C0000, 0, 0x20000);
288-
toncset((u32*)0x023F0000, 0, 0xD000);
296+
toncset((u32*)0x023F0000, 0, 0xCE00);
289297
toncset((u32*)0x023FE000, 0, 0x400);
290298
toncset((u32*)0x023FF000, 0, 0x1000);
291299

@@ -1376,15 +1384,15 @@ int arm7_main(void) {
13761384
overlayPatch = true; // Allow overlay patching for SM64DS ROM hacks (ex. Mario's Holiday)
13771385
}
13781386

1387+
tonccpy((u8*)CARDENGINE_ARM7_LOCATION, (u8*)CARDENGINE_ARM7_LOCATION_BUFFERED, 0x1200);
1388+
toncset((u8*)CARDENGINE_ARM7_LOCATION_BUFFERED, 0, 0x1200);
1389+
13791390
ce9Location = *(u32*)CARDENGINE_ARM9_LOCATION_BUFFERED;
13801391
ce9Alt = (ce9Location == CARDENGINE_ARM9_LOCATION_DLDI_ALT || ce9Location == CARDENGINE_ARM9_LOCATION_DLDI_ALT2);
13811392
// const bool ce9NotInHeap = (ce9Alt || ce9Location == CARDENGINE_ARM9_LOCATION_DLDI_START);
13821393
tonccpy((u32*)ce9Location, (u32*)CARDENGINE_ARM9_LOCATION_BUFFERED, ce9Alt ? 0x2800 : 0x3800);
13831394
toncset((u32*)0x023E0000, 0, 0x10000);
13841395

1385-
tonccpy((u8*)CARDENGINE_ARM7_LOCATION, (u8*)CARDENGINE_ARM7_LOCATION_BUFFERED, 0x1000);
1386-
toncset((u8*)CARDENGINE_ARM7_LOCATION_BUFFERED, 0, 0x1000);
1387-
13881396
aFile musicsFile;
13891397
getFileFromCluster(&musicsFile, musicCluster);
13901398
if (((accessControl & BIT(4)) || arm7mbk == 0x080037C0) && musicCluster != 0) {
@@ -1597,6 +1605,7 @@ int arm7_main(void) {
15971605
moduleParams,
15981606
1,
15991607
usesCloneboot,
1608+
(remappedKeyA != 0) || (remappedKeyB != 1) || (remappedKeySELECT != 2) || (remappedKeySTART != 3) || (remappedKeyR != 8) || (remappedKeyL != 9) || (remappedKeyX != 10) || (remappedKeyY != 11),
16001609
saveFileCluster,
16011610
saveSize
16021611
);
@@ -1640,7 +1649,7 @@ int arm7_main(void) {
16401649
errorOutput();
16411650
}
16421651

1643-
toncset((u32*)0x0380C000, 0, 0x2780);
1652+
toncset((u32*)0x0380C000, 0, 0x2380);
16441653

16451654
errorCode = hookNdsRetailArm7(
16461655
(cardengineArm7*)CARDENGINE_ARM7_LOCATION,

retail/bootloader/source/arm7/patch_arm7.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static void patchSleepMode(const tNDSHeader* ndsHeader) {
320320
}
321321

322322

323-
static void patchSleepInputWrite(const tNDSHeader* ndsHeader, const module_params_t* moduleParams) {
323+
static void patchSleepInputWrite(cardengineArm7* ce7, const tNDSHeader* ndsHeader, const module_params_t* moduleParams, const bool useRelocSrc) {
324324
u32* offset = patchOffsetCache.sleepInputWriteOffset;
325325
if (!patchOffsetCache.sleepInputWriteOffset) {
326326
offset = findSleepInputWriteOffset(ndsHeader, moduleParams);
@@ -332,15 +332,54 @@ static void patchSleepInputWrite(const tNDSHeader* ndsHeader, const module_param
332332
return;
333333
}
334334

335+
const bool isArm = (*offset == 0x13A04902 || *offset == 0x11A05004);
336+
335337
if (!sleepMode) {
336-
if (*offset == 0x13A04902 || *offset == 0x11A05004) {
338+
if (isArm) {
337339
*offset = 0xE1A00000; // nop
338340
} else {
339341
u16* offsetThumb = (u16*)offset;
340342
*offsetThumb = 0x46C0; // nop
341343
}
342344
}
343345

346+
if (useRelocSrc) {
347+
bool found = false;
348+
u32 offsetAdjust = (u32)offset;
349+
if (isArm) {
350+
for (int i = 0; i < 6; i++) {
351+
offsetAdjust += 4;
352+
if (*(u32*)offsetAdjust == 0xE1C010B0) {
353+
found = true;
354+
break;
355+
}
356+
}
357+
358+
if (found) {
359+
const u32 srcAddr = (u32)offsetAdjust - vAddrOfRelocSrc + (*(u32*)0x02FFE1A0==0x080037C0 ? 0x37C0000 : 0x37F8000);
360+
*(u32*)offsetAdjust = generateA7Instr(srcAddr, (u32)ce7->patches->patchKeyInputs);
361+
}
362+
} else {
363+
for (int i = 0; i < 10; i++) {
364+
offsetAdjust += 2;
365+
if (*(u16*)offsetAdjust == 0x8001) {
366+
found = true;
367+
break;
368+
}
369+
}
370+
371+
if (found) {
372+
*(u16*)offsetAdjust = 0x46C0; // nop
373+
offsetAdjust += 2;
374+
ce7->patches->patchKeyInputsThumb[3] = *(u16*)offsetAdjust;
375+
*(u16*)offsetAdjust = 0x4B00; // ldr r3, =patchKeyInputsThumb
376+
*(u16*)(offsetAdjust + 2) = 0x4718; // bx r3
377+
*(u32*)(offsetAdjust + 4) = (u32)ce7->patches->patchKeyInputsThumb;
378+
*(u32*)(offsetAdjust + 4) += 1;
379+
}
380+
}
381+
}
382+
344383
dbg_printf("Sleep input write location : ");
345384
dbg_hexa((u32)offset);
346385
dbg_printf("\n\n");
@@ -458,7 +497,8 @@ u32 patchCardNdsArm7(
458497
cardengineArm7* ce7,
459498
tNDSHeader* ndsHeader,
460499
const module_params_t* moduleParams,
461-
u32 saveFileCluster
500+
u32 saveFileCluster,
501+
const bool buttonsRemapped
462502
) {
463503
arm7newUnitCode = ndsHeader->unitCode;
464504
newArm7binarySize = ndsHeader->arm7binarySize;
@@ -524,7 +564,6 @@ u32 patchCardNdsArm7(
524564
patchPostBoot(ndsHeader);
525565

526566
patchSleepMode(ndsHeader);
527-
patchSleepInputWrite(ndsHeader, moduleParams);
528567

529568
patchRamClear(ndsHeader, moduleParams);
530569

@@ -548,6 +587,7 @@ u32 patchCardNdsArm7(
548587
}
549588

550589
if (a7GetReloc(ndsHeader, moduleParams)) {
590+
patchSleepInputWrite(ce7, ndsHeader, moduleParams, buttonsRemapped);
551591
u32 saveResult = 0;
552592
// Save Relocation Switch
553593
// Only when saveRelocation is turning off(FLASE) and GameCodeMatch is matching(TRUE),
@@ -603,6 +643,8 @@ u32 patchCardNdsArm7(
603643
if (!saveResult) {
604644
patchOffsetCache.savePatchType = 0;
605645
}
646+
} else {
647+
patchSleepInputWrite(ce7, ndsHeader, moduleParams, false);
606648
}
607649

608650
if (strcmp(romTid, "UBRP") == 0) {

retail/bootloader/source/arm7/patch_arm9.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,29 @@ void patchHiHeapPointer(cardengineArm9* ce9, const module_params_t* moduleParams
12831283
dbg_printf(!(nandAccess && extendedMemory) ? "Hi Heap Shrink Successful\n\n" : "Hi Heap Grow Successful\n\n");
12841284
}
12851285

1286+
void patchKeyInputs(const tNDSHeader* ndsHeader, const module_params_t* moduleParams) {
1287+
const u32 signature = 0x04000130;
1288+
const u32 signatureHeader = isSdk5(moduleParams) ? 0x02FFFFA8 : 0x027FFFA8;
1289+
const u32 newOffset = isSdk5(moduleParams) ? 0x02FFFF78 : 0x027FFF78;
1290+
1291+
u32* offset = ndsHeader->arm9destination;
1292+
for (int i = 0; i < ndsHeader->arm9binarySize/4; i++) {
1293+
if (*offset == signature) {
1294+
if (offset[-2] == signatureHeader || offset[-1] == signatureHeader || offset[1] == signatureHeader || offset[2] == signatureHeader) {
1295+
*offset = newOffset;
1296+
1297+
dbg_printf("KEYINPUT found: ");
1298+
dbg_hexa((u32)offset);
1299+
dbg_printf("\n");
1300+
}
1301+
}
1302+
offset++;
1303+
}
1304+
dbg_printf("\n");
1305+
1306+
*(u16*)newOffset = 0x3FF;
1307+
}
1308+
12861309
u32 relocateBssPart(const tNDSHeader* ndsHeader, u32 bssEnd, u32 bssPartStart, u32 bssPartEnd, u32 newPartStart) {
12871310
extern u32 iUncompressedSize;
12881311

@@ -2705,7 +2728,7 @@ static void operaRamPatch(void) {
27052728
}
27062729
}
27072730

2708-
u32 patchCardNdsArm9(cardengineArm9* ce9, const tNDSHeader* ndsHeader, const module_params_t* moduleParams, u32 patchMpuRegion, const bool usesCloneboot) {
2731+
u32 patchCardNdsArm9(cardengineArm9* ce9, const tNDSHeader* ndsHeader, const module_params_t* moduleParams, u32 patchMpuRegion, const bool usesCloneboot, const bool buttonsRemapped) {
27092732
bool usesThumb;
27102733
int readType;
27112734
int sdk5ReadType; // SDK 5
@@ -2775,6 +2798,10 @@ u32 patchCardNdsArm9(cardengineArm9* ce9, const tNDSHeader* ndsHeader, const mod
27752798

27762799
patchHiHeapPointer(ce9, moduleParams, ndsHeader);
27772800

2801+
if (buttonsRemapped) {
2802+
patchKeyInputs(ndsHeader, moduleParams);
2803+
}
2804+
27782805
if (isPawsAndClaws(ndsHeader)) {
27792806
patchCardId(ce9, ndsHeader, moduleParams, false, NULL); // Patch card ID first
27802807
}

0 commit comments

Comments
 (0)