mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
- refactored arm11/sys.c
- moved common.h from the ARM9 tree to the common code tree - does proper deinit now on the ARM11 side the bug that caused it to fail to launch some FIRMs has been fixed - it can even boot stock FIRMs
This commit is contained in:
parent
016eac6982
commit
5e56cd2f77
@ -1,4 +1,6 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
#include <arm.h>
|
#include <arm.h>
|
||||||
|
|
||||||
#include "arm/mmu.h"
|
#include "arm/mmu.h"
|
||||||
@ -68,44 +70,26 @@ static MMU_Lvl2_Table *Alloc_Lvl2(void)
|
|||||||
|
|
||||||
|
|
||||||
/* functions to convert from internal page flag format to ARM */
|
/* functions to convert from internal page flag format to ARM */
|
||||||
|
|
||||||
|
/* {TEX, CB} */
|
||||||
|
static const u8 MMU_TypeLUT[MEMORY_TYPES][2] = {
|
||||||
|
[STRONGLY_ORDERED] = {0, 0},
|
||||||
|
[NON_CACHEABLE] = {1, 0},
|
||||||
|
[DEVICE_SHARED] = {0, 1},
|
||||||
|
[DEVICE_NONSHARED] = {2, 0},
|
||||||
|
[CACHED_WT] = {0, 2},
|
||||||
|
[CACHED_WB] = {1, 3},
|
||||||
|
[CACHED_WB_ALLOC] = {1, 3},
|
||||||
|
};
|
||||||
|
|
||||||
static u32 MMU_GetTEX(u32 f)
|
static u32 MMU_GetTEX(u32 f)
|
||||||
{
|
{
|
||||||
switch(MMU_FLAGS_TYPE(f)) {
|
return MMU_TypeLUT[MMU_FLAGS_TYPE(f)][0];
|
||||||
default:
|
|
||||||
case STRONGLY_ORDERED:
|
|
||||||
case CACHED_WT:
|
|
||||||
case DEVICE_SHARED:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case CACHED_WB:
|
|
||||||
case NON_CACHEABLE:
|
|
||||||
case CACHED_WB_ALLOC:
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case DEVICE_NONSHARED:
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 MMU_GetCB(u32 f)
|
static u32 MMU_GetCB(u32 f)
|
||||||
{
|
{
|
||||||
switch(MMU_FLAGS_TYPE(f)) {
|
return MMU_TypeLUT[MMU_FLAGS_TYPE(f)][1];
|
||||||
default:
|
|
||||||
case STRONGLY_ORDERED:
|
|
||||||
case NON_CACHEABLE:
|
|
||||||
case DEVICE_NONSHARED:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case DEVICE_SHARED:
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case CACHED_WT:
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
case CACHED_WB:
|
|
||||||
case CACHED_WB_ALLOC:
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 MMU_GetAP(u32 f)
|
static u32 MMU_GetAP(u32 f)
|
||||||
@ -114,10 +98,8 @@ static u32 MMU_GetAP(u32 f)
|
|||||||
default:
|
default:
|
||||||
case NO_ACCESS:
|
case NO_ACCESS:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case READ_ONLY:
|
case READ_ONLY:
|
||||||
return 0x21;
|
return 0x21;
|
||||||
|
|
||||||
case READ_WRITE:
|
case READ_WRITE:
|
||||||
return 0x01;
|
return 0x01;
|
||||||
}
|
}
|
||||||
@ -281,11 +263,10 @@ u32 MMU_Map(u32 va, u32 pa, u32 size, u32 flags)
|
|||||||
.mapfn = MMU_MapPage,
|
.mapfn = MMU_MapPage,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
static const size_t VMapperCount = sizeof(VMappers)/sizeof(*VMappers);
|
|
||||||
|
|
||||||
while(size > 0) {
|
while(size > 0) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < VMapperCount; i++) {
|
for (i = 0; i < countof(VMappers); i++) {
|
||||||
u32 abits = VMappers[i].bits;
|
u32 abits = VMappers[i].bits;
|
||||||
|
|
||||||
if (MMU_MappingFits(va, pa, size, abits)) {
|
if (MMU_MappingFits(va, pa, size, abits)) {
|
||||||
@ -303,7 +284,7 @@ u32 MMU_Map(u32 va, u32 pa, u32 size, u32 flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == VMapperCount)
|
if (i == countof(VMappers))
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ enum MMU_MemoryType {
|
|||||||
CACHED_WT,
|
CACHED_WT,
|
||||||
CACHED_WB,
|
CACHED_WB,
|
||||||
CACHED_WB_ALLOC,
|
CACHED_WB_ALLOC,
|
||||||
|
MEMORY_TYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MMU_MemoryAccess {
|
enum MMU_MemoryAccess {
|
||||||
|
@ -45,20 +45,24 @@ __boot:
|
|||||||
b 1b
|
b 1b
|
||||||
|
|
||||||
corezero_start:
|
corezero_start:
|
||||||
|
@ assume __bss_len is 16 byte aligned
|
||||||
ldr r0, =__bss_pa
|
ldr r0, =__bss_pa
|
||||||
ldr r1, =__bss_len
|
ldr r1, =__bss_len
|
||||||
mov r2, #0
|
mov r2, #0
|
||||||
|
mov r3, #0
|
||||||
|
mov r4, #0
|
||||||
|
mov r5, #0
|
||||||
add r1, r0, r1
|
add r1, r0, r1
|
||||||
.Lclearbss:
|
.Lclearbss:
|
||||||
cmp r0, r1
|
cmp r0, r1
|
||||||
strlt r2, [r0], #4
|
stmltia r0!, {r2-r5}
|
||||||
blt .Lclearbss
|
blt .Lclearbss
|
||||||
|
|
||||||
|
bl SYS_CoreZeroInit
|
||||||
|
|
||||||
coresmp_start:
|
coresmp_start:
|
||||||
bl SYS_CoreInit
|
bl SYS_CoreInit
|
||||||
bl MPCoreMain
|
b MainLoop
|
||||||
|
|
||||||
b __boot
|
|
||||||
|
|
||||||
.section .bss.stack
|
.section .bss.stack
|
||||||
.align 3
|
.align 3
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
#include "hw/i2c.h"
|
#include "hw/i2c.h"
|
||||||
#include "hw/mcu.h"
|
#include "hw/mcu.h"
|
||||||
|
|
||||||
static bool legacy;
|
#include "system/sys.h"
|
||||||
void SYS_CoreShutdown(void);
|
|
||||||
|
static bool legacy = false;
|
||||||
|
|
||||||
void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||||
{
|
{
|
||||||
@ -98,21 +99,18 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPCoreMain(void)
|
void MainLoop(void)
|
||||||
{
|
{
|
||||||
legacy = false;
|
|
||||||
GIC_Enable(IRQ_PXI_RX, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
|
GIC_Enable(IRQ_PXI_RX, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
|
||||||
|
|
||||||
|
// ARM9 won't try anything funny until this point
|
||||||
PXI_Barrier(ARM11_READY_BARRIER);
|
PXI_Barrier(ARM11_READY_BARRIER);
|
||||||
ARM_EnableInterrupts();
|
|
||||||
|
|
||||||
// Process IRQs until the ARM9 tells us it's time to boot something else
|
// Process IRQs until the ARM9 tells us it's time to boot something else
|
||||||
do {
|
do {
|
||||||
ARM_WFI();
|
ARM_WFI();
|
||||||
} while(!legacy);
|
} while(!legacy);
|
||||||
|
|
||||||
// Perform any needed deinit stuff
|
SYS_CoreZeroShutdown();
|
||||||
ARM_DisableInterrupts();
|
|
||||||
|
|
||||||
SYS_CoreShutdown();
|
SYS_CoreShutdown();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
#define DEF_SECT_(n) extern u32 __##n##_pa, __##n##_va, __##n##_len; static const u32 n##_pa = (u32)&__##n##_pa, n##_va = (u32)&__##n##_va;
|
#define DEF_SECT_(n) extern u32 __##n##_pa, __##n##_va, __##n##_len; static const u32 n##_pa = (u32)&__##n##_pa, n##_va = (u32)&__##n##_va;
|
||||||
DEF_SECT_(vector)
|
DEF_SECT_(vector)
|
||||||
DEF_SECT_(text)
|
DEF_SECT_(text)
|
@ -8,14 +8,13 @@
|
|||||||
|
|
||||||
#include "hw/i2c.h"
|
#include "hw/i2c.h"
|
||||||
|
|
||||||
|
#include "system/sections.h"
|
||||||
|
|
||||||
#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300))
|
#define CFG11_MPCORE_CLKCNT ((vu16*)(0x10141300))
|
||||||
#define CFG11_SOCINFO ((vu16*)(0x10140FFC))
|
#define CFG11_SOCINFO ((vu16*)(0x10140FFC))
|
||||||
|
|
||||||
#define LEGACY_BOOT_ENTRY ((vu32*)0x1FFFFFFC)
|
#define LEGACY_BOOT_ENTRYPOINT ((vu32*)0x1FFFFFFC)
|
||||||
|
#define LEGACY_BOOT_ROUTINE_SMP (0x0001004C)
|
||||||
#define INIT_DONE (0xDDEEFFAA)
|
|
||||||
|
|
||||||
static volatile u32 sys_init_state = 0;
|
|
||||||
|
|
||||||
static bool SYS_IsNewConsole(void)
|
static bool SYS_IsNewConsole(void)
|
||||||
{
|
{
|
||||||
@ -45,16 +44,11 @@ static void SYS_EnableClkMult(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "sections.h"
|
void SYS_CoreZeroInit(void)
|
||||||
|
|
||||||
#define MMU_FLAGS_DEF MMU_FLAGS(STRONGLY_ORDERED, READ_WRITE, 0, 1)
|
|
||||||
|
|
||||||
static void SYS_CoreZeroInit(void)
|
|
||||||
{
|
{
|
||||||
GIC_GlobalReset();
|
GIC_GlobalReset();
|
||||||
GIC_LocalReset();
|
|
||||||
|
|
||||||
*LEGACY_BOOT_ENTRY = 0;
|
*LEGACY_BOOT_ENTRYPOINT = 0;
|
||||||
|
|
||||||
SYS_EnableClkMult();
|
SYS_EnableClkMult();
|
||||||
|
|
||||||
@ -77,11 +71,13 @@ static void SYS_CoreZeroInit(void)
|
|||||||
MMU_Map(0x18000000, 0x18000000, 6UL << 20, MMU_FLAGS(CACHED_WT, READ_WRITE, 1, 1));
|
MMU_Map(0x18000000, 0x18000000, 6UL << 20, MMU_FLAGS(CACHED_WT, READ_WRITE, 1, 1));
|
||||||
|
|
||||||
// FCRAM
|
// FCRAM
|
||||||
MMU_Map(0x20000000, 0x20000000, 128UL << 20, MMU_FLAGS(CACHED_WB, READ_WRITE, 1, 1));
|
if (SYS_IsNewConsole()) {
|
||||||
}
|
MMU_Map(0x20000000, 0x20000000, 256UL << 20, MMU_FLAGS(CACHED_WB, READ_WRITE, 1, 1));
|
||||||
|
} else {
|
||||||
|
MMU_Map(0x20000000, 0x20000000, 128UL << 20, MMU_FLAGS(CACHED_WB, READ_WRITE, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
static void SYS_InitPeripherals(void)
|
// Initialize peripherals
|
||||||
{
|
|
||||||
PXI_Reset();
|
PXI_Reset();
|
||||||
I2C_init();
|
I2C_init();
|
||||||
//MCU_init();
|
//MCU_init();
|
||||||
@ -89,19 +85,13 @@ static void SYS_InitPeripherals(void)
|
|||||||
|
|
||||||
void SYS_CoreInit(void)
|
void SYS_CoreInit(void)
|
||||||
{
|
{
|
||||||
if (!ARM_CoreID()) {
|
// Reset local GIC registers
|
||||||
SYS_CoreZeroInit();
|
GIC_LocalReset();
|
||||||
} else {
|
|
||||||
while(sys_init_state != INIT_DONE)
|
|
||||||
ARM_WFE();
|
|
||||||
|
|
||||||
GIC_LocalReset();
|
// Set up MMU registers
|
||||||
}
|
|
||||||
|
|
||||||
// set up MMU registers
|
|
||||||
MMU_Init();
|
MMU_Init();
|
||||||
|
|
||||||
// enable fancy ARM11 stuff
|
// Enable fancy ARM11 features
|
||||||
ARM_SetACR(ARM_GetACR() |
|
ARM_SetACR(ARM_GetACR() |
|
||||||
ACR_RETSTK | ACR_DBPRED | ACR_SBPRED | ACR_FOLDING | ACR_SMP);
|
ACR_RETSTK | ACR_DBPRED | ACR_SBPRED | ACR_FOLDING | ACR_SMP);
|
||||||
|
|
||||||
@ -110,32 +100,20 @@ void SYS_CoreInit(void)
|
|||||||
|
|
||||||
ARM_DSB();
|
ARM_DSB();
|
||||||
|
|
||||||
if (!ARM_CoreID()) {
|
ARM_EnableInterrupts();
|
||||||
SYS_InitPeripherals();
|
}
|
||||||
|
|
||||||
sys_init_state = INIT_DONE;
|
void SYS_CoreZeroShutdown(void)
|
||||||
ARM_DSB();
|
{
|
||||||
ARM_SEV();
|
ARM_DisableInterrupts();
|
||||||
}
|
GIC_GlobalReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// assumes all cores have been initialized
|
|
||||||
void SYS_CoreShutdown(void)
|
void SYS_CoreShutdown(void)
|
||||||
{
|
{
|
||||||
u32 core = ARM_CoreID();
|
u32 core = ARM_CoreID();
|
||||||
|
|
||||||
if (!core) {
|
ARM_DisableInterrupts();
|
||||||
// wait for the other cores to do their thing
|
|
||||||
while(sys_init_state != (INIT_DONE - MAX_CPU + 1)) {
|
|
||||||
ARM_WFE();
|
|
||||||
ARM_DSB();
|
|
||||||
}
|
|
||||||
|
|
||||||
GIC_GlobalReset();
|
|
||||||
} else {
|
|
||||||
__atomic_sub_fetch(&sys_init_state, 1, __ATOMIC_SEQ_CST);
|
|
||||||
ARM_SEV();
|
|
||||||
}
|
|
||||||
|
|
||||||
GIC_LocalReset();
|
GIC_LocalReset();
|
||||||
|
|
||||||
@ -148,11 +126,11 @@ void SYS_CoreShutdown(void)
|
|||||||
~(ACR_RETSTK | ACR_DBPRED | ACR_SBPRED | ACR_FOLDING | ACR_SMP));
|
~(ACR_RETSTK | ACR_DBPRED | ACR_SBPRED | ACR_FOLDING | ACR_SMP));
|
||||||
|
|
||||||
if (!core) {
|
if (!core) {
|
||||||
while(*LEGACY_BOOT_ENTRY == 0);
|
while(*LEGACY_BOOT_ENTRYPOINT == 0);
|
||||||
((void (*)(void))(*LEGACY_BOOT_ENTRY))();
|
((void (*)(void))(*LEGACY_BOOT_ENTRYPOINT))();
|
||||||
} else {
|
} else {
|
||||||
// Branch to bootrom function that does SMP reinit magic
|
// Branch to bootrom function that does SMP reinit magic
|
||||||
// (waits for IPI + branches to word @ 0x1FFFFFDC)
|
// (waits for IPI + branches to word @ 0x1FFFFFDC)
|
||||||
((void (*)(void))0x0001004C)();
|
((void (*)(void))LEGACY_BOOT_ROUTINE_SMP)();
|
||||||
}
|
}
|
||||||
}
|
}
|
20
arm11/source/system/sys.h
Executable file
20
arm11/source/system/sys.h
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
how to run the SYS_Core(Zero){Init,Shutdown} functions:
|
||||||
|
for init:
|
||||||
|
- FIRST run CoreZeroInit ONCE
|
||||||
|
- all cores must run CoreInit ONCE
|
||||||
|
|
||||||
|
for shutdown:
|
||||||
|
- all non-zero cores must call CoreShutdown
|
||||||
|
- core zero must call CoreZeroShutdown, then CoreShutdown
|
||||||
|
*/
|
||||||
|
|
||||||
|
void SYS_CoreZeroInit(void);
|
||||||
|
void SYS_CoreInit(void);
|
||||||
|
|
||||||
|
void SYS_CoreZeroShutdown(void);
|
||||||
|
void SYS_CoreShutdown(void);
|
140
arm9/source/common/common.h → common/common.h
Normal file → Executable file
140
arm9/source/common/common.h → common/common.h
Normal file → Executable file
@ -1,59 +1,81 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <types.h>
|
#include <stdalign.h>
|
||||||
#include <stdalign.h>
|
|
||||||
|
#include <types.h>
|
||||||
#ifdef MONITOR_HEAP
|
|
||||||
#include "mymalloc.h"
|
#ifdef ARM9
|
||||||
#define malloc my_malloc
|
# ifdef MONITOR_HEAP
|
||||||
#define free my_free
|
#include "mymalloc.h"
|
||||||
#endif
|
#define malloc my_malloc
|
||||||
|
#define free my_free
|
||||||
#define max(a,b) \
|
# endif
|
||||||
(((a) > (b)) ? (a) : (b))
|
#endif
|
||||||
#define min(a,b) \
|
|
||||||
(((a) < (b)) ? (a) : (b))
|
#define max(a,b) \
|
||||||
|
(((a) > (b)) ? (a) : (b))
|
||||||
#define getbe16(d) \
|
|
||||||
(((d)[0]<<8) | (d)[1])
|
#define min(a,b) \
|
||||||
#define getbe32(d) \
|
(((a) < (b)) ? (a) : (b))
|
||||||
((((u32) getbe16(d))<<16) | ((u32) getbe16(d+2)))
|
|
||||||
#define getbe64(d) \
|
#define getbe16(d) \
|
||||||
((((u64) getbe32(d))<<32) | ((u64) getbe32(d+4)))
|
(((d)[0]<<8) | (d)[1])
|
||||||
|
#define getbe32(d) \
|
||||||
#define getle16(d) \
|
((((u32) getbe16(d))<<16) | ((u32) getbe16((d)+2)))
|
||||||
(((d)[1]<<8) | (d)[0])
|
#define getbe64(d) \
|
||||||
#define getle32(d) \
|
((((u64) getbe32(d))<<32) | ((u64) getbe32((d)+4)))
|
||||||
((((u32) getle16(d+2))<<16) | ((u32) getle16(d)))
|
|
||||||
#define getle64(d) \
|
#define getle16(d) \
|
||||||
((((u64) getle32(d+4))<<32) | ((u64) getle32(d)))
|
(((d)[1]<<8) | (d)[0])
|
||||||
|
#define getle32(d) \
|
||||||
#define align(v,a) \
|
((((u32) getle16((d)+2))<<16) | ((u32) getle16(d)))
|
||||||
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
#define getle64(d) \
|
||||||
|
((((u64) getle32((d)+4))<<32) | ((u64) getle32(d)))
|
||||||
#define countof(x) \
|
|
||||||
(sizeof(x) / sizeof((x)[0]))
|
#define align(v,a) \
|
||||||
|
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
||||||
#define bkpt \
|
|
||||||
asm("bkpt\n\t")
|
#define countof(x) \
|
||||||
|
(sizeof(x) / sizeof(*(x)))
|
||||||
#define STATIC_ASSERT(...) \
|
|
||||||
_Static_assert((__VA_ARGS__), #__VA_ARGS__)
|
#define bkpt \
|
||||||
|
asm volatile("bkpt\n\t")
|
||||||
// standard output path (support file paths are in support.h)
|
|
||||||
#define OUTPUT_PATH "0:/gm9/out"
|
#define STATIC_ASSERT(...) \
|
||||||
|
_Static_assert((__VA_ARGS__), #__VA_ARGS__)
|
||||||
// used in several places
|
|
||||||
#define STD_BUFFER_SIZE 0x100000 // must be a multiple of 0x200
|
static inline u32 xbits(u32 *map, u32 start, u32 n)
|
||||||
|
{
|
||||||
// buffer area defines (in use by image.c, for RAMdrive)
|
u32 ret, mask, off, shift;
|
||||||
#define RAMDRV_BUFFER ((u8*)0x22800000) // top of STACK
|
|
||||||
#define RAMDRV_SIZE_O3DS (0x5800000) // 88MB
|
if (n > 32)
|
||||||
#define RAMDRV_SIZE_N3DS (0xD800000) // 216MB
|
return -1;
|
||||||
|
|
||||||
|
mask = ((u32)(1 << n)) - 1;
|
||||||
|
off = start / 32;
|
||||||
|
shift = start % 32;
|
||||||
|
|
||||||
|
ret = map[off] >> shift;
|
||||||
|
if ((n + shift) > 32)
|
||||||
|
ret |= map[off+1] << (32 - shift);
|
||||||
|
return ret & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// standard output path (support file paths are in support.h)
|
||||||
|
#define OUTPUT_PATH "0:/gm9/out"
|
||||||
|
|
||||||
|
// used in several places
|
||||||
|
#define STD_BUFFER_SIZE 0x100000 // must be a multiple of 0x200
|
||||||
|
|
||||||
|
// buffer area defines (in use by image.c, for RAMdrive)
|
||||||
|
#define RAMDRV_BUFFER ((u8*)0x22800000) // top of STACK
|
||||||
|
#define RAMDRV_SIZE_O3DS (0x5800000) // 88MB
|
||||||
|
#define RAMDRV_SIZE_N3DS (0xD800000) // 216MB
|
Loading…
x
Reference in New Issue
Block a user