diff --git a/Makefile b/Makefile index a100954..d0ae78a 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,6 @@ dir_patches := patches dir_loader := loader dir_arm9_exceptions := exceptions/arm9 dir_arm11_exceptions := exceptions/arm11 -dir_screeninit := screeninit dir_injector := injector dir_mset := CakeHax dir_ninjhax := CakeBrah @@ -35,7 +34,8 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h $(dir_build)/screeninit.h +bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h + .PHONY: all all: launcher a9lh ninjhax @@ -57,8 +57,7 @@ clean: @$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean @$(MAKE) -C $(dir_loader) clean @$(MAKE) -C $(dir_arm9_exceptions) clean - @$(MAKE) -C $(dir_arm11_exceptions) clean - @$(MAKE) -C $(dir_screeninit) clean + @$(MAKE) -C $(dir_arm11_exceptions) clean @$(MAKE) -C $(dir_injector) clean @rm -rf $(dir_out) $(dir_build) @@ -115,10 +114,6 @@ $(dir_build)/arm11_exceptions.h: $(dir_arm11_exceptions)/Makefile @$(MAKE) -C $(dir_arm11_exceptions) @bin2c -o $@ -n arm11_exceptions $(@D)/arm11_exceptions.bin -$(dir_build)/screeninit.h: $(dir_screeninit)/Makefile - @$(MAKE) -C $(dir_screeninit) - @bin2c -o $@ -n screeninit $(@D)/screeninit.bin - $(dir_build)/memory.o: CFLAGS += -O3 $(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) (dev) configuration\"" diff --git a/exceptions/arm11/source/mainHandler.c b/exceptions/arm11/source/mainHandler.c index 6c2f35e..b5e5dea 100644 --- a/exceptions/arm11/source/mainHandler.c +++ b/exceptions/arm11/source/mainHandler.c @@ -91,7 +91,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize; *(ExceptionDumpHeader *)final = dumpHeader; - + clearDCacheAndDMB(); - mcuReboot(); + mcuReboot(); //Also contains DCache-cleaning code } diff --git a/exceptions/arm9/source/mainHandler.c b/exceptions/arm9/source/mainHandler.c index bb37aeb..6dd6ad5 100644 --- a/exceptions/arm9/source/mainHandler.c +++ b/exceptions/arm9/source/mainHandler.c @@ -67,6 +67,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type for(u32 i = 0; i < dumpHeader.stackDumpSize / 4; i++) *final++ = sp[i]; + ((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot while(1); } \ No newline at end of file diff --git a/loader/linker.ld b/loader/linker.ld index 6fbf471..2ca0165 100644 --- a/loader/linker.ld +++ b/loader/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x24FFFB00; + . = 0x24FFFF00; .text.start : { *(.text.start) } .text : { *(.text) } .data : { *(.data) } diff --git a/loader/source/main.c b/loader/source/main.c index ca42a16..b611bfe 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -4,7 +4,7 @@ void main(void) { void *payloadAddress = (void *)0x23F00000; - memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFB04); + memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04); ((void (*)())payloadAddress)(); } \ No newline at end of file diff --git a/screeninit/Makefile b/screeninit/Makefile deleted file mode 100755 index 0096fd8..0000000 --- a/screeninit/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/3ds_rules - -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -LD := arm-none-eabi-ld -OC := arm-none-eabi-objcopy - -name := $(shell basename $(CURDIR)) - -dir_source := source -dir_build := build - -ASFLAGS := -mcpu=mpcore -mfloat-abi=hard -CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib - -objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ - $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ - $(call rwildcard, $(dir_source), *.s *.c))) - -.PHONY: all -all: ../$(dir_build)/$(name).bin - -.PHONY: clean -clean: - @rm -rf $(dir_build) - -../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf - $(OC) -S -O binary $< $@ - -$(dir_build)/$(name).elf: $(objects) - $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ - -$(dir_build)/%.o: $(dir_source)/%.c - @mkdir -p "$(@D)" - $(COMPILE.c) $(OUTPUT_OPTION) $< - -$(dir_build)/%.o: $(dir_source)/%.s - @mkdir -p "$(@D)" - $(COMPILE.s) $(OUTPUT_OPTION) $< -include $(call rwildcard, $(dir_build), *.d) diff --git a/screeninit/linker.ld b/screeninit/linker.ld deleted file mode 100755 index 9ae0eaa..0000000 --- a/screeninit/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -ENTRY(_start) -SECTIONS -{ - . = 0x24FFFC00; - .text.start : { *(.text.start) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - .rodata : { *(.rodata) } - . = ALIGN(4); -} - diff --git a/screeninit/source/main.c b/screeninit/source/main.c deleted file mode 100755 index 78cba49..0000000 --- a/screeninit/source/main.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "types.h" - -void main(void) -{ - const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; - u32 brightnessLevel = *(vu32 *)0x24FFFC08; - vu32 *const arm11 = (u32 *)0x1FFFFFF8; - - *(vu32 *)0x10141200 = 0x1007F; - *(vu32 *)0x10202014 = 0x00000001; - *(vu32 *)0x1020200C &= 0xFFFEFFFE; - *(vu32 *)0x10202240 = brightness[brightnessLevel]; - *(vu32 *)0x10202A40 = brightness[brightnessLevel]; - *(vu32 *)0x10202244 = 0x1023E; - *(vu32 *)0x10202A44 = 0x1023E; - - // Top screen - *(vu32 *)0x10400400 = 0x000001c2; - *(vu32 *)0x10400404 = 0x000000d1; - *(vu32 *)0x10400408 = 0x000001c1; - *(vu32 *)0x1040040c = 0x000001c1; - *(vu32 *)0x10400410 = 0x00000000; - *(vu32 *)0x10400414 = 0x000000cf; - *(vu32 *)0x10400418 = 0x000000d1; - *(vu32 *)0x1040041c = 0x01c501c1; - *(vu32 *)0x10400420 = 0x00010000; - *(vu32 *)0x10400424 = 0x0000019d; - *(vu32 *)0x10400428 = 0x00000002; - *(vu32 *)0x1040042c = 0x00000192; - *(vu32 *)0x10400430 = 0x00000192; - *(vu32 *)0x10400434 = 0x00000192; - *(vu32 *)0x10400438 = 0x00000001; - *(vu32 *)0x1040043c = 0x00000002; - *(vu32 *)0x10400440 = 0x01960192; - *(vu32 *)0x10400444 = 0x00000000; - *(vu32 *)0x10400448 = 0x00000000; - *(vu32 *)0x1040045C = 0x00f00190; - *(vu32 *)0x10400460 = 0x01c100d1; - *(vu32 *)0x10400464 = 0x01920002; - *(vu32 *)0x10400468 = 0x18300000; - *(vu32 *)0x10400470 = 0x80341; - *(vu32 *)0x10400474 = 0x00010501; - *(vu32 *)0x10400478 = 0; - *(vu32 *)0x10400490 = 0x000002D0; - *(vu32 *)0x1040049C = 0x00000000; - - // Disco register - for(u32 i = 0; i < 256; i++) - *(vu32 *)0x10400484 = 0x10101 * i; - - // Bottom screen - *(vu32 *)0x10400500 = 0x000001c2; - *(vu32 *)0x10400504 = 0x000000d1; - *(vu32 *)0x10400508 = 0x000001c1; - *(vu32 *)0x1040050c = 0x000001c1; - *(vu32 *)0x10400510 = 0x000000cd; - *(vu32 *)0x10400514 = 0x000000cf; - *(vu32 *)0x10400518 = 0x000000d1; - *(vu32 *)0x1040051c = 0x01c501c1; - *(vu32 *)0x10400520 = 0x00010000; - *(vu32 *)0x10400524 = 0x0000019d; - *(vu32 *)0x10400528 = 0x00000052; - *(vu32 *)0x1040052c = 0x00000192; - *(vu32 *)0x10400530 = 0x00000192; - *(vu32 *)0x10400534 = 0x0000004f; - *(vu32 *)0x10400538 = 0x00000050; - *(vu32 *)0x1040053c = 0x00000052; - *(vu32 *)0x10400540 = 0x01980194; - *(vu32 *)0x10400544 = 0x00000000; - *(vu32 *)0x10400548 = 0x00000011; - *(vu32 *)0x1040055C = 0x00f00140; - *(vu32 *)0x10400560 = 0x01c100d1; - *(vu32 *)0x10400564 = 0x01920052; - *(vu32 *)0x10400568 = 0x18300000 + 0x46500; - *(vu32 *)0x10400570 = 0x80301; - *(vu32 *)0x10400574 = 0x00010501; - *(vu32 *)0x10400578 = 0; - *(vu32 *)0x10400590 = 0x000002D0; - *(vu32 *)0x1040059C = 0x00000000; - - // Disco register - for(u32 i = 0; i < 256; i++) - *(vu32 *)0x10400584 = 0x10101 * i; - - *(vu32 *)0x10400468 = 0x18300000; - *(vu32 *)0x1040046c = 0x18300000; - *(vu32 *)0x10400494 = 0x18300000; - *(vu32 *)0x10400498 = 0x18300000; - *(vu32 *)0x10400568 = 0x18346500; - *(vu32 *)0x1040056c = 0x18346500; - - //Set CakeBrah framebuffers - *((vu32 *)0x23FFFE00) = 0x18300000; - *((vu32 *)0x23FFFE04) = 0x18300000; - *((vu32 *)0x23FFFE08) = 0x18346500; - - //Clear ARM11 entry offset - *arm11 = 0; - - //Wait for the entry to be set - while(!*arm11); - - //Jump to it - ((void (*)())*arm11)(); -} \ No newline at end of file diff --git a/screeninit/source/start.s b/screeninit/source/start.s deleted file mode 100644 index 40392d1..0000000 --- a/screeninit/source/start.s +++ /dev/null @@ -1,10 +0,0 @@ -.section .text.start -.align 4 -.global _start -_start: - @ Disable interrupts - CPSID aif - - b main - - .word 0 diff --git a/screeninit/source/types.h b/screeninit/source/types.h deleted file mode 100755 index d27412b..0000000 --- a/screeninit/source/types.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -//Common data types -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef volatile u8 vu8; -typedef volatile u16 vu16; -typedef volatile u32 vu32; -typedef volatile u64 vu64; \ No newline at end of file diff --git a/source/config.c b/source/config.c index 2fad88f..7fc5c81 100644 --- a/source/config.c +++ b/source/config.c @@ -4,7 +4,7 @@ #include "config.h" #include "utils.h" -#include "screeninit.h" +#include "screen.h" #include "draw.h" #include "fs.h" #include "i2c.h" @@ -158,7 +158,12 @@ void configureCFW(const char *configPath) //In any case, if the current option is enabled (or a multiple choice option is selected) we must display a red 'x' if(selectedOption < multiOptionsAmount) + { + if(selectedOption == 0) + updateBrightness(multiOptions[selectedOption].enabled); + drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED); + } else { u32 singleSelected = selectedOption - multiOptionsAmount; diff --git a/source/draw.c b/source/draw.c index 1f13e9d..e818847 100644 --- a/source/draw.c +++ b/source/draw.c @@ -5,18 +5,11 @@ */ #include "draw.h" -#include "screeninit.h" +#include "screen.h" #include "utils.h" #include "fs.h" -#include "memory.h" #include "font.h" -static const struct fb { - u8 *top_left; - u8 *top_right; - u8 *bottom; -} *const fb = (struct fb *)0x23FFFE00; - static inline int strlen(const char *string) { char *stringEnd = (char *)string; @@ -26,13 +19,6 @@ static inline int strlen(const char *string) return stringEnd - string; } -void clearScreens(void) -{ - memset32(fb->top_left, 0, 0x46500); - memset32(fb->top_right, 0, 0x46500); - memset32(fb->bottom, 0, 0x38400); -} - u32 loadSplash(void) { initScreens(); diff --git a/source/draw.h b/source/draw.h index 18b46d0..e21b0d5 100644 --- a/source/draw.h +++ b/source/draw.h @@ -20,6 +20,5 @@ #define COLOR_BLACK 0x000000 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/exceptions.c b/source/exceptions.c index b0c0d02..df0d2f8 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -6,7 +6,7 @@ #include "exceptions.h" #include "fs.h" #include "memory.h" -#include "screeninit.h" +#include "screen.h" #include "draw.h" #include "i2c.h" #include "utils.h" @@ -192,8 +192,6 @@ void detectAndProcessExceptionDumps(void) for(u32 i = 0; i < size / 4; i++) dump[i] = 0; clearScreens(); - - i2cWriteRegister(I2C_DEV_MCU, 0x20, 1); //Shutdown - while(1); + mcuPowerOff(); } } \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index f078a61..90e8f01 100755 --- a/source/firm.c +++ b/source/firm.c @@ -12,7 +12,7 @@ #include "crypto.h" #include "exceptions.h" #include "draw.h" -#include "screeninit.h" +#include "screen.h" #include "buttons.h" #include "../build/injector.h" @@ -422,6 +422,8 @@ static inline void launchFirm(u32 firmType, u32 bootType) arm11 = (u32 *)0x1FFFFFF8; } + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed + //Set ARM11 kernel entrypoint *arm11 = (u32)firm->arm11Entry; diff --git a/source/fs.c b/source/fs.c index 1eeb7fe..9d5570e 100644 --- a/source/fs.c +++ b/source/fs.c @@ -4,7 +4,7 @@ #include "fs.h" #include "memory.h" -#include "screeninit.h" +#include "screen.h" #include "fatfs/ff.h" #include "buttons.h" #include "../build/loader.h" @@ -77,7 +77,7 @@ void loadPayload(u32 pressed) { initScreens(); - u32 *const loaderAddress = (u32 *)0x24FFFB00; + u32 *const loaderAddress = (u32 *)0x24FFFF00; memcpy(loaderAddress, loader, loader_size); diff --git a/source/memory.c b/source/memory.c index b5027bd..e6b2e56 100644 --- a/source/memory.c +++ b/source/memory.c @@ -60,4 +60,9 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize) } return NULL; +} + +void cleanInvalidateDCacheAndDMB(void) +{ + ((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM? } \ No newline at end of file diff --git a/source/memory.h b/source/memory.h index 2982a0f..c120581 100644 --- a/source/memory.h +++ b/source/memory.h @@ -11,4 +11,13 @@ void memcpy(void *dest, const void *src, u32 size); void memset32(void *dest, u32 filler, u32 size); int memcmp(const void *buf1, const void *buf2, u32 size); -u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); \ No newline at end of file +u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); + +/*** + Cleans and invalidates the data cache, then waits for all memory transfers to be finished. + This function MUST be called before doing the following: + - rebooting + - powering down + - setting the ARM11 entrypoint to execute a function +***/ +void cleanInvalidateDCacheAndDMB(void); \ No newline at end of file diff --git a/source/screen.c b/source/screen.c new file mode 100644 index 0000000..e55c4bb --- /dev/null +++ b/source/screen.c @@ -0,0 +1,237 @@ +/* +* screen.c +* +* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. +* Screen deinit code by tiniVi. +*/ + +#include "screen.h" +#include "config.h" +#include "memory.h" +#include "draw.h" +#include "i2c.h" + +#define ARM11_STUB_ADDRESS (0x25000000 - 0x40) //It's currently only 0x28 bytes large. We're putting 0x40 just to be sure here +#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)(); +vu32 *arm11Entry = (vu32 *)0x1FFFFFF8; + +void __attribute__((naked)) arm11Stub(void) +{ + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Wait for the entry to be set + while(*arm11Entry == ARM11_STUB_ADDRESS); + + //Jump to it + ((void (*)())*arm11Entry)(); +} + +static inline void invokeArm11Function(void (*func)()) +{ + static u32 hasCopiedStub = 0; + if(!hasCopiedStub++) memcpy((void *)ARM11_STUB_ADDRESS, arm11Stub, 0x40); + + cleanInvalidateDCacheAndDMB(); + + *arm11Entry = (u32)func; + while(*arm11Entry); + *arm11Entry = ARM11_STUB_ADDRESS; +} + +static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; + +void deinitScreens(void) +{ + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Shutdown LCDs + *(vu32 *)0x10202A44 = 0; + *(vu32 *)0x10202244 = 0; + *(vu32 *)0x10202014 = 0; + + WAIT_FOR_ARM9(); + } + + if(PDN_GPU_CNT != 1) invokeArm11Function(ARM11); +} + +void updateBrightness(u32 brightnessLevel) +{ + static int brightnessValue; + + brightnessValue = brightness[brightnessLevel]; + + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Change brightness + *(vu32 *)0x10202240 = brightnessValue; + *(vu32 *)0x10202A40 = brightnessValue; + + WAIT_FOR_ARM9(); + } + + invokeArm11Function(ARM11); +} + +void clearScreens(void) +{ + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Setting up two simultaneous memory fills using the GPU + + vu32 *REGs_PSC0 = (vu32 *)0x10400010; + REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address + REGs_PSC0[1] = (u32)(fb->top_left + 0x46500) >> 3; //End address + REGs_PSC0[2] = 0; //Fill value + REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start + + vu32 *REGs_PSC1 = (vu32 *)0x10400020; + REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address + REGs_PSC1[1] = (u32)(fb->bottom + 0x38400) >> 3; //End address + REGs_PSC1[2] = 0; //Fill value + REGs_PSC1[3] = (2 << 8) | 1; //32-bit patter; start + + while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); + + if(fb->top_right != fb->top_left) + { + REGs_PSC0[0] = (u32)fb->top_right >> 3; //Start address + REGs_PSC0[1] = (u32)(fb->top_right + 0x46500) >> 3; //End address + REGs_PSC0[2] = 0; //Fill value + REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start + + while(!(REGs_PSC0[3] & 2)); + } + + WAIT_FOR_ARM9(); + } + + invokeArm11Function(ARM11); +} + +u32 initScreens(void) +{ + u32 needToInit = PDN_GPU_CNT == 1; + + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + u32 brightnessLevel = MULTICONFIG(0); + + *(vu32 *)0x10141200 = 0x1007F; + *(vu32 *)0x10202014 = 0x00000001; + *(vu32 *)0x1020200C &= 0xFFFEFFFE; + *(vu32 *)0x10202240 = brightness[brightnessLevel]; + *(vu32 *)0x10202A40 = brightness[brightnessLevel]; + *(vu32 *)0x10202244 = 0x1023E; + *(vu32 *)0x10202A44 = 0x1023E; + + // Top screen + *(vu32 *)0x10400400 = 0x000001c2; + *(vu32 *)0x10400404 = 0x000000d1; + *(vu32 *)0x10400408 = 0x000001c1; + *(vu32 *)0x1040040c = 0x000001c1; + *(vu32 *)0x10400410 = 0x00000000; + *(vu32 *)0x10400414 = 0x000000cf; + *(vu32 *)0x10400418 = 0x000000d1; + *(vu32 *)0x1040041c = 0x01c501c1; + *(vu32 *)0x10400420 = 0x00010000; + *(vu32 *)0x10400424 = 0x0000019d; + *(vu32 *)0x10400428 = 0x00000002; + *(vu32 *)0x1040042c = 0x00000192; + *(vu32 *)0x10400430 = 0x00000192; + *(vu32 *)0x10400434 = 0x00000192; + *(vu32 *)0x10400438 = 0x00000001; + *(vu32 *)0x1040043c = 0x00000002; + *(vu32 *)0x10400440 = 0x01960192; + *(vu32 *)0x10400444 = 0x00000000; + *(vu32 *)0x10400448 = 0x00000000; + *(vu32 *)0x1040045C = 0x00f00190; + *(vu32 *)0x10400460 = 0x01c100d1; + *(vu32 *)0x10400464 = 0x01920002; + *(vu32 *)0x10400468 = 0x18300000; + *(vu32 *)0x10400470 = 0x80341; + *(vu32 *)0x10400474 = 0x00010501; + *(vu32 *)0x10400478 = 0; + *(vu32 *)0x10400490 = 0x000002D0; + *(vu32 *)0x1040049C = 0x00000000; + + // Disco register + for(u32 i = 0; i < 256; i++) + *(vu32 *)0x10400484 = 0x10101 * i; + + // Bottom screen + *(vu32 *)0x10400500 = 0x000001c2; + *(vu32 *)0x10400504 = 0x000000d1; + *(vu32 *)0x10400508 = 0x000001c1; + *(vu32 *)0x1040050c = 0x000001c1; + *(vu32 *)0x10400510 = 0x000000cd; + *(vu32 *)0x10400514 = 0x000000cf; + *(vu32 *)0x10400518 = 0x000000d1; + *(vu32 *)0x1040051c = 0x01c501c1; + *(vu32 *)0x10400520 = 0x00010000; + *(vu32 *)0x10400524 = 0x0000019d; + *(vu32 *)0x10400528 = 0x00000052; + *(vu32 *)0x1040052c = 0x00000192; + *(vu32 *)0x10400530 = 0x00000192; + *(vu32 *)0x10400534 = 0x0000004f; + *(vu32 *)0x10400538 = 0x00000050; + *(vu32 *)0x1040053c = 0x00000052; + *(vu32 *)0x10400540 = 0x01980194; + *(vu32 *)0x10400544 = 0x00000000; + *(vu32 *)0x10400548 = 0x00000011; + *(vu32 *)0x1040055C = 0x00f00140; + *(vu32 *)0x10400560 = 0x01c100d1; + *(vu32 *)0x10400564 = 0x01920052; + *(vu32 *)0x10400568 = 0x18300000 + 0x46500; + *(vu32 *)0x10400570 = 0x80301; + *(vu32 *)0x10400574 = 0x00010501; + *(vu32 *)0x10400578 = 0; + *(vu32 *)0x10400590 = 0x000002D0; + *(vu32 *)0x1040059C = 0x00000000; + + // Disco register + for(u32 i = 0; i < 256; i++) + *(vu32 *)0x10400584 = 0x10101 * i; + + *(vu32 *)0x10400468 = 0x18300000; + *(vu32 *)0x1040046c = 0x18300000; + *(vu32 *)0x10400494 = 0x18300000; + *(vu32 *)0x10400498 = 0x18300000; + *(vu32 *)0x10400568 = 0x18346500; + *(vu32 *)0x1040056c = 0x18346500; + + //Set CakeBrah framebuffers + fb->top_left = (u8 *)0x18300000; + fb->top_right = (u8 *)0x18300000; + fb->bottom = (u8 *)0x18346500; + + WAIT_FOR_ARM9(); + } + + if(needToInit) + { + invokeArm11Function(ARM11); + + //Turn on backlight + i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); + } + else + updateBrightness(MULTICONFIG(0)); + + clearScreens(); + + return needToInit; +} \ No newline at end of file diff --git a/source/screen.h b/source/screen.h new file mode 100644 index 0000000..5f2bf1d --- /dev/null +++ b/source/screen.h @@ -0,0 +1,23 @@ +/* +* screen.h +* +* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. +* Screen deinit code by tiniVi. +*/ + +#pragma once + +#include "types.h" + +#define PDN_GPU_CNT (*(vu8 *)0x10141200) + +static volatile struct fb { + u8 *top_left; + u8 *top_right; + u8 *bottom; +} *const fb = (volatile struct fb *)0x23FFFE00; + +void deinitScreens(void); +void updateBrightness(u32 brightnessLevel); +void clearScreens(void); +u32 initScreens(void); \ No newline at end of file diff --git a/source/screeninit.c b/source/screeninit.c deleted file mode 100644 index 86f1390..0000000 --- a/source/screeninit.c +++ /dev/null @@ -1,69 +0,0 @@ -/* -* screeninit.c -* -* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. -* Screen deinit code by tiniVi. -*/ - -#include "screeninit.h" -#include "config.h" -#include "memory.h" -#include "draw.h" -#include "i2c.h" -#include "../build/screeninit.h" - -vu32 *arm11Entry = (u32 *)0x1FFFFFF8; - -void deinitScreens(void) -{ - void __attribute__((naked)) ARM11(void) - { - //Disable interrupts - __asm(".word 0xF10C01C0"); - - //Clear ARM11 entry offset - *arm11Entry = 0; - - //Shutdown LCDs - *(vu32 *)0x10202A44 = 0; - *(vu32 *)0x10202244 = 0; - *(vu32 *)0x10202014 = 0; - - //Wait for the entry to be set - while(!*arm11Entry); - - //Jump to it - ((void (*)())*arm11Entry)(); - } - - if(PDN_GPU_CNT != 1) - { - *arm11Entry = (u32)ARM11; - while(*arm11Entry); - } -} - -u32 initScreens(void) -{ - u32 needToInit = PDN_GPU_CNT == 1; - - if(needToInit) - { - u32 *const screenInitAddress = (u32 *)0x24FFFC00; - - memcpy(screenInitAddress, screeninit, screeninit_size); - - //Write brightness level for the stub to pick up - screenInitAddress[2] = MULTICONFIG(0); - - *arm11Entry = (u32)screenInitAddress; - while(*arm11Entry); - - //Turn on backlight - i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); - } - - clearScreens(); - - return needToInit; -} \ No newline at end of file diff --git a/source/screeninit.h b/source/screeninit.h deleted file mode 100644 index 2c778ce..0000000 --- a/source/screeninit.h +++ /dev/null @@ -1,15 +0,0 @@ -/* -* screeninit.h -* -* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. -* Screen deinit code by tiniVi. -*/ - -#pragma once - -#include "types.h" - -#define PDN_GPU_CNT (*(vu8 *)0x10141200) - -void deinitScreens(void); -u32 initScreens(void); \ No newline at end of file diff --git a/source/start.s b/source/start.s index d446a4f..1171c49 100644 --- a/source/start.s +++ b/source/start.s @@ -23,15 +23,15 @@ start: mcr p15, 0, r0, c5, c0, 3 @ write instruction access @ Sets MPU permissions and cache settings - ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) - ldr r1, =0x3000801B @ fff00000 16k | dtcm - ldr r2, =0x01FF801D @ 01ff8000 32k | itcm - ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) - ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) - ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) - ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram - ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) - mov r8, #0x25 + ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) + ldr r1, =0x3000801B @ fff00000 16k | dtcm + ldr r2, =0x01FF801D @ 01ff8000 32k | itcm + ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) + ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) + ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) + ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram + ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) + mov r8, #0x29 mcr p15, 0, r0, c6, c0, 0 mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r2, c6, c2, 0 @@ -40,9 +40,9 @@ start: mcr p15, 0, r5, c6, c5, 0 mcr p15, 0, r6, c6, c6, 0 mcr p15, 0, r7, c6, c7, 0 - mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 5 - mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 5 - mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 5 + mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 3, 5 + mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 3, 5 + mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 3, 5 @ Enable dctm ldr r0, =0x3000800A @ set dtcm diff --git a/source/utils.c b/source/utils.c index 5497437..125a21c 100644 --- a/source/utils.c +++ b/source/utils.c @@ -5,6 +5,7 @@ #include "utils.h" #include "i2c.h" #include "buttons.h" +#include "memory.h" u32 waitInput(void) { @@ -35,10 +36,20 @@ u32 waitInput(void) void mcuReboot(void) { + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(1); } +void mcuPowerOff(void) +{ + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed + + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); + while(1); +} + //TODO: add support for TIMER IRQ static inline void startChrono(u64 initialTicks) { diff --git a/source/utils.h b/source/utils.h index 25a3f5f..fbf39c6 100644 --- a/source/utils.h +++ b/source/utils.h @@ -8,6 +8,7 @@ u32 waitInput(void); void mcuReboot(void); +void mcuPowerOff(void); #define TICKS_PER_SEC 67027964ULL #define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i)