diff --git a/source/config.c b/source/config.c index 969bb33..0e2e427 100644 --- a/source/config.c +++ b/source/config.c @@ -185,6 +185,7 @@ void configureCFW(const char *configPath) deinitScreens(); PDN_GPU_CNT = 1; } - - delay(0x1400000); + + u64 t0 = chrono(); + while(chrono() - t0 < 2 * TICKS_PER_SEC); //wait for 1.5s } \ No newline at end of file diff --git a/source/draw.c b/source/draw.c index c8f1fab..1f13e9d 100644 --- a/source/draw.c +++ b/source/draw.c @@ -33,14 +33,15 @@ void clearScreens(void) memset32(fb->bottom, 0, 0x38400); } -void loadSplash(void) +u32 loadSplash(void) { initScreens(); //Don't delay boot if no splash image is on the SD if(fileRead(fb->top_left, "/luma/splash.bin") + fileRead(fb->bottom, "/luma/splashbottom.bin")) - delay(0x1400000); + return 1; + return 0; } void drawCharacter(char character, int posX, int posY, u32 color) diff --git a/source/draw.h b/source/draw.h index a8959bf..18b46d0 100644 --- a/source/draw.h +++ b/source/draw.h @@ -19,7 +19,7 @@ #define COLOR_RED 0x0000FF #define COLOR_BLACK 0x000000 -void loadSplash(void); +u32 loadSplash(void); void clearScreens(void); void drawCharacter(char character, int posX, int posY, u32 color); int drawString(const char *string, int posX, int posY, u32 color); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 4a01557..82dcb04 100755 --- a/source/firm.c +++ b/source/firm.c @@ -23,6 +23,8 @@ u32 config, firmSource, emuOffset; +u64 chronoWhenSplashLoaded = 0; + void main(void) { u32 bootType, @@ -33,6 +35,8 @@ void main(void) needConfig, newConfig, emuHeader; + + startChrono(0); //Start the chronometer. It shouldn't be reset. //Detect the console being used console = PDN_MPCORE_CFG == 7; @@ -145,8 +149,9 @@ void main(void) loadPayload(pressed); //If screens are inited or the corresponding option is set, load splash screen - if(PDN_GPU_CNT != 1 || CONFIG(7)) loadSplash(); - + if(PDN_GPU_CNT != 1 || CONFIG(7)) chronoWhenSplashLoaded = (u64) loadSplash(); + if(chronoWhenSplashLoaded) chronoWhenSplashLoaded = chrono(); + //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one if(pressed & BUTTON_R1) { @@ -446,6 +451,9 @@ static inline void launchFirm(u32 firstSectionToCopy, u32 bootType) for(u32 i = firstSectionToCopy; i < 4 && section[i].size; i++) memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size); + while(chronoWhenSplashLoaded && chrono() - chronoWhenSplashLoaded < 3 * TICKS_PER_SEC); + stopChrono(); + //Determine the ARM11 entry to use vu32 *arm11; if(bootType) arm11 = (u32 *)0x1FFFFFFC; diff --git a/source/utils.c b/source/utils.c index ba0f805..5c10112 100644 --- a/source/utils.c +++ b/source/utils.c @@ -33,13 +33,34 @@ u32 waitInput(void) return key; } -void delay(u64 length) -{ - while(length--) __asm("mov r0, r0"); -} - void mcuReboot(void) { i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(1); +} + +//TODO: add support for TIMER IRQ +void startChrono(u64 initialTicks) +{ + //Based on a NATIVE_FIRM disassembly + + *(vu16 *)(0x10003002 + 4 * 0) = 0; //67MHz + for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 4; //Count-up + + for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i)); + + *(vu16 *)(0x10003002 + 4 * 0) = 0x80; //67MHz; enabled + for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled +} + +u64 chrono(void) +{ + u64 res = 0; + for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i); + return res; +} + +void stopChrono(void) +{ + for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) &= ~0x80; } \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index c95778e..e2ef8ff 100644 --- a/source/utils.h +++ b/source/utils.h @@ -7,5 +7,10 @@ #include "types.h" u32 waitInput(void); -void delay(u64 length); -void mcuReboot(void); \ No newline at end of file +void mcuReboot(void); + +#define TICKS_PER_SEC 67027964ULL + +void startChrono(u64 initialTicks); +u64 chrono(void); +void stopChrono(void); \ No newline at end of file