diff --git a/Makefile b/Makefile index 8411fc0..a35ebe6 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ INCLUDES := source source/common source/font source/filesys source/crypto source #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -mthumb -mthumb-interwork -flto +ARCH := -marm -mthumb-interwork -flto CFLAGS := -g -Wall -Wextra -Wpedantic -Wcast-align -Wno-main -O2\ -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -std=gnu11\ @@ -120,7 +120,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: common clean all gateway firm binary cakehax cakerop brahma release +.PHONY: common clean all gateway firm binary cakehax cakerop brahma screeninit release #--------------------------------------------------------------------------------- all: firm @@ -132,11 +132,14 @@ common: submodules: @-git submodule update --init --recursive +screeninit: + @$(MAKE) dir_out=$(OUTPUT_D) -C screeninit + binary: common @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile -firm: binary - @firmtool build $(OUTPUT).firm -n 0x23F00000 -e 0 -D $(OUTPUT).elf -A 0x23F00000 -C NDMA -i +firm: binary screeninit + firmtool build $(OUTPUT).firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA gateway: binary @cp resources/LauncherTemplate.dat $(OUTPUT_D)/Launcher.dat @@ -184,6 +187,7 @@ clean: @-$(MAKE) clean --no-print-directory -C CakeHax @-$(MAKE) clean --no-print-directory -C CakesROP @-$(MAKE) clean --no-print-directory -C BrahmaLoader + @-$(MAKE) clean --no-print-directory -C screeninit @rm -fr $(BUILD) $(OUTPUT_D) $(RELEASE) diff --git a/screeninit/Makefile b/screeninit/Makefile new file mode 100644 index 0000000..8f563e6 --- /dev/null +++ b/screeninit/Makefile @@ -0,0 +1,42 @@ +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)/base_tools + +name := $(shell basename $(CURDIR)) + +dir_source := source +dir_build := build +dir_out := ../$(dir_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_out)/$(name).bin + +.PHONY: clean +clean: + @rm -rf $(dir_build) + +$(dir_out)/$(name).bin: $(dir_out)/$(name).elf + $(OBJCOPY) -S -O binary $< $@ + +$(dir_out)/$(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) $< diff --git a/screeninit/build/main.d b/screeninit/build/main.d new file mode 100644 index 0000000..8382701 --- /dev/null +++ b/screeninit/build/main.d @@ -0,0 +1,3 @@ +build/main.o: source/main.c source/types.h + +source/types.h: diff --git a/screeninit/linker.ld b/screeninit/linker.ld new file mode 100644 index 0000000..fc311e9 --- /dev/null +++ b/screeninit/linker.ld @@ -0,0 +1,16 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +ENTRY(__boot) +SECTIONS +{ + . = 0x1FF80000; + + .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } + .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } + .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } + + . = ALIGN(4); + + __stack_top = 0x1FFFF800; +} diff --git a/screeninit/source/boot.s b/screeninit/source/boot.s new file mode 100644 index 0000000..711c766 --- /dev/null +++ b/screeninit/source/boot.s @@ -0,0 +1,31 @@ +@ This file was kindly provided by Wolfvak - thank you! + +.section .text.boot +.arm + +.global __boot +__boot: + @ Disable interrupts and switch to Supervisor + cpsid aif, #0x13 + + @ Writeback and invalidate caches + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 + mcr p15, 0, r0, c7, c14, 0 + mcr p15, 0, r0, c7, c10, 4 + + ldr sp, =__stack_top + + @ Reset values + ldr r0, =0x00054078 + ldr r1, =0x0000000F + ldr r2, =0x00000000 + + @ MMU disabled, Caches disabled, other misc crap going on + mcr p15, 0, r0, c1, c0, 0 + mcr p15, 0, r1, c1, c0, 1 + mcr p15, 0, r2, c1, c0, 2 + + bl main + + b __boot diff --git a/screeninit/source/main.c b/screeninit/source/main.c new file mode 100644 index 0000000..0c907cb --- /dev/null +++ b/screeninit/source/main.c @@ -0,0 +1,129 @@ +// screeninit source taken over from https://github.com/AuroraWright/arm9loaderhax/tree/master/payload_stage2/arm11 +// check there for license info +// thanks go to AuroraWright +#include "types.h" + +// see: https://github.com/AuroraWright/Luma3DS/blob/53209b9be0c264af00fb81b32146d27f0d9498ac/source/screen.h#L32-L34 +#define PDN_GPU_CNT (*(vu8 *)0x10141200) +#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1) + +#define BRIGHTNESS 0x39 + +void main(void) +{ + vu32 *arm11Entry = (vu32 *)0x1FFFFFFC; + if (ARESCREENSINITIALIZED) return; // nothing to do in that case + + *(vu32 *)0x10141200 = 0x1007F; + *(vu32 *)0x10202014 = 0x00000001; + *(vu32 *)0x1020200C &= 0xFFFEFFFE; + + *(vu32 *)0x10202240 = BRIGHTNESS; + *(vu32 *)0x10202A40 = BRIGHTNESS; + *(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; + + //Set CakeBrah framebuffers + fb->top_left = (u8 *)0x18300000; + fb->top_right = (u8 *)0x18300000; + fb->bottom = (u8 *)0x18346500; + + *(vu32 *)0x10400468 = (u32)fb->top_left; + *(vu32 *)0x1040046c = (u32)fb->top_left; + *(vu32 *)0x10400494 = (u32)fb->top_right; + *(vu32 *)0x10400498 = (u32)fb->top_right; + *(vu32 *)0x10400568 = (u32)fb->bottom; + *(vu32 *)0x1040056c = (u32)fb->bottom; + + vu32 *REGs_PSC0 = (vu32 *)0x10400010, + *REGs_PSC1 = (vu32 *)0x10400020; + + REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address + REGs_PSC0[1] = (u32)(fb->top_left + SCREEN_TOP_FBSIZE) >> 3; //End address + REGs_PSC0[2] = 0; //Fill value + REGs_PSC0[3] = (2 << 8) | 1; //32-bit pattern; start + + REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address + REGs_PSC1[1] = (u32)(fb->bottom + SCREEN_BOTTOM_FBSIZE) >> 3; //End address + REGs_PSC1[2] = 0; //Fill value + REGs_PSC1[3] = (2 << 8) | 1; //32-bit pattern; start + + while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); + + //Clear ARM11 entrypoint + *arm11Entry = 0; + + //Wait for the entrypoint to be set + while(!*arm11Entry); + + //Jump to it + ((void (*)())*arm11Entry)(); +} diff --git a/screeninit/source/types.h b/screeninit/source/types.h new file mode 100644 index 0000000..3f04590 --- /dev/null +++ b/screeninit/source/types.h @@ -0,0 +1,25 @@ +#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; + +#define SCREEN_TOP_WIDTH 400 +#define SCREEN_BOTTOM_WIDTH 320 +#define SCREEN_HEIGHT 240 +#define SCREEN_TOP_FBSIZE (3 * SCREEN_TOP_WIDTH * SCREEN_HEIGHT) +#define SCREEN_BOTTOM_FBSIZE (3 * SCREEN_BOTTOM_WIDTH * SCREEN_HEIGHT) + +static volatile struct fb { + u8 *top_left; + u8 *top_right; + u8 *bottom; +} *const fb = (volatile struct fb *)0x23FFFE00; diff --git a/source/main.c b/source/main.c index 0cfc161..72d795f 100644 --- a/source/main.c +++ b/source/main.c @@ -1,12 +1,16 @@ #include "common.h" #include "godmode.h" #include "ui.h" +#include "i2c.h" #include "power.h" u8 *top_screen, *bottom_screen; void main(int argc, char** argv) { + // Turn on backlight + I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); + // Fetch the framebuffer addresses if(argc >= 2) { // newer entrypoints @@ -18,6 +22,7 @@ void main(int argc, char** argv) top_screen = (u8*)(*(u32*)0x23FFFE00); bottom_screen = (u8*)(*(u32*)0x23FFFE08); } - u32 godmode_exit = GodMode(); - (godmode_exit == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff(); + + // Run the main program + (GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff(); }