Move screen management code to screen.c and fix cache-related issues
- Screen brightness is now updated as soon as the user selects a brightness option, on all boot environments - Payloads can now be 1KB bigger - Some cache-related bugs may have been fixed
This commit is contained in:
parent
f78dd5365c
commit
e593584a47
8
Makefile
8
Makefile
@ -17,7 +17,6 @@ revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-
|
|||||||
dir_source := source
|
dir_source := source
|
||||||
dir_patches := patches
|
dir_patches := patches
|
||||||
dir_loader := loader
|
dir_loader := loader
|
||||||
dir_screeninit := screeninit
|
|
||||||
dir_injector := injector
|
dir_injector := injector
|
||||||
dir_mset := CakeHax
|
dir_mset := CakeHax
|
||||||
dir_ninjhax := CakeBrah
|
dir_ninjhax := CakeBrah
|
||||||
@ -33,7 +32,7 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||||
|
|
||||||
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/injector.h $(dir_build)/loader.h $(dir_build)/screeninit.h
|
bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/injector.h $(dir_build)/loader.h
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: launcher a9lh ninjhax
|
all: launcher a9lh ninjhax
|
||||||
@ -55,7 +54,6 @@ clean:
|
|||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||||
@$(MAKE) -C $(dir_loader) clean
|
@$(MAKE) -C $(dir_loader) clean
|
||||||
@$(MAKE) -C $(dir_screeninit) clean
|
|
||||||
@$(MAKE) -C $(dir_injector) clean
|
@$(MAKE) -C $(dir_injector) clean
|
||||||
@rm -rf $(dir_out) $(dir_build)
|
@rm -rf $(dir_out) $(dir_build)
|
||||||
|
|
||||||
@ -102,10 +100,6 @@ $(dir_build)/loader.h: $(dir_loader)/Makefile
|
|||||||
@$(MAKE) -C $(dir_loader)
|
@$(MAKE) -C $(dir_loader)
|
||||||
@bin2c -o $@ -n loader $(@D)/loader.bin
|
@bin2c -o $@ -n loader $(@D)/loader.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)/memory.o: CFLAGS += -O3
|
||||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x24FFFB00;
|
. = 0x24FFFF00;
|
||||||
.text.start : { *(.text.start) }
|
.text.start : { *(.text.start) }
|
||||||
.text : { *(.text) }
|
.text : { *(.text) }
|
||||||
.data : { *(.data) }
|
.data : { *(.data) }
|
||||||
|
@ -4,7 +4,8 @@ void main(void)
|
|||||||
{
|
{
|
||||||
void *payloadAddress = (void *)0x23F00000;
|
void *payloadAddress = (void *)0x23F00000;
|
||||||
|
|
||||||
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFB04);
|
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04);
|
||||||
|
cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
|
|
||||||
((void (*)())payloadAddress)();
|
((void (*)())payloadAddress)();
|
||||||
}
|
}
|
@ -7,4 +7,9 @@ void memcpy(void *dest, const void *src, u32 size)
|
|||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
for(u32 i = 0; i < size; i++)
|
||||||
destc[i] = srcc[i];
|
destc[i] = srcc[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanInvalidateDCacheAndDMB(void)
|
||||||
|
{
|
||||||
|
((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM?
|
||||||
}
|
}
|
@ -2,4 +2,14 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size);
|
void memcpy(void *dest, const void *src, u32 size);
|
||||||
|
|
||||||
|
/***
|
||||||
|
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
|
||||||
|
- jumping to a payload (?)
|
||||||
|
***/
|
||||||
|
void cleanInvalidateDCacheAndDMB(void);
|
@ -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=<path to>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)
|
|
@ -1,12 +0,0 @@
|
|||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x24FFFC00;
|
|
||||||
.text.start : { *(.text.start) }
|
|
||||||
.text : { *(.text) }
|
|
||||||
.data : { *(.data) }
|
|
||||||
.bss : { *(.bss COMMON) }
|
|
||||||
.rodata : { *(.rodata) }
|
|
||||||
. = ALIGN(4);
|
|
||||||
}
|
|
||||||
|
|
@ -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)();
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
.section .text.start
|
|
||||||
.align 4
|
|
||||||
.global _start
|
|
||||||
_start:
|
|
||||||
@ Disable interrupts
|
|
||||||
CPSID aif
|
|
||||||
|
|
||||||
b main
|
|
||||||
|
|
||||||
.word 0
|
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
//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;
|
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "screeninit.h"
|
#include "screen.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
@ -156,7 +156,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'
|
//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 < multiOptionsAmount)
|
||||||
|
{
|
||||||
|
if(selectedOption == 0)
|
||||||
|
updateBrightness(multiOptions[selectedOption].enabled);
|
||||||
|
|
||||||
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 singleSelected = selectedOption - multiOptionsAmount;
|
u32 singleSelected = selectedOption - multiOptionsAmount;
|
||||||
|
@ -5,18 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "screeninit.h"
|
#include "screen.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "font.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)
|
static inline int strlen(const char *string)
|
||||||
{
|
{
|
||||||
char *stringEnd = (char *)string;
|
char *stringEnd = (char *)string;
|
||||||
@ -26,13 +19,6 @@ static inline int strlen(const char *string)
|
|||||||
return stringEnd - 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)
|
u32 loadSplash(void)
|
||||||
{
|
{
|
||||||
initScreens();
|
initScreens();
|
||||||
|
@ -20,6 +20,5 @@
|
|||||||
#define COLOR_BLACK 0x000000
|
#define COLOR_BLACK 0x000000
|
||||||
|
|
||||||
u32 loadSplash(void);
|
u32 loadSplash(void);
|
||||||
void clearScreens(void);
|
|
||||||
void drawCharacter(char character, int posX, int posY, u32 color);
|
void drawCharacter(char character, int posX, int posY, u32 color);
|
||||||
int drawString(const char *string, int posX, int posY, u32 color);
|
int drawString(const char *string, int posX, int posY, u32 color);
|
@ -11,7 +11,7 @@
|
|||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "screeninit.h"
|
#include "screen.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "../build/injector.h"
|
#include "../build/injector.h"
|
||||||
|
|
||||||
@ -376,6 +376,8 @@ static inline void launchFirm(u32 firmType, u32 bootType)
|
|||||||
arm11 = (u32 *)0x1FFFFFF8;
|
arm11 = (u32 *)0x1FFFFFF8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
|
|
||||||
//Set ARM11 kernel entrypoint
|
//Set ARM11 kernel entrypoint
|
||||||
*arm11 = (u32)firm->arm11Entry;
|
*arm11 = (u32)firm->arm11Entry;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "screeninit.h"
|
#include "screen.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "../build/loader.h"
|
#include "../build/loader.h"
|
||||||
@ -76,7 +76,7 @@ void loadPayload(u32 pressed)
|
|||||||
{
|
{
|
||||||
initScreens();
|
initScreens();
|
||||||
|
|
||||||
u32 *const loaderAddress = (u32 *)0x24FFFB00;
|
u32 *const loaderAddress = (u32 *)0x24FFFF00;
|
||||||
|
|
||||||
memcpy(loaderAddress, loader, loader_size);
|
memcpy(loaderAddress, loader, loader_size);
|
||||||
|
|
||||||
@ -85,6 +85,7 @@ void loadPayload(u32 pressed)
|
|||||||
|
|
||||||
loaderAddress[1] = fileRead((void *)0x24F00000, path);
|
loaderAddress[1] = fileRead((void *)0x24F00000, path);
|
||||||
|
|
||||||
|
cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
((void (*)())loaderAddress)();
|
((void (*)())loaderAddress)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,4 +60,9 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanInvalidateDCacheAndDMB(void)
|
||||||
|
{
|
||||||
|
((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM?
|
||||||
}
|
}
|
@ -11,4 +11,14 @@
|
|||||||
void memcpy(void *dest, const void *src, u32 size);
|
void memcpy(void *dest, const void *src, u32 size);
|
||||||
void memset32(void *dest, u32 filler, u32 size);
|
void memset32(void *dest, u32 filler, u32 size);
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
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
|
||||||
|
- jumping to a payload (?)
|
||||||
|
***/
|
||||||
|
void cleanInvalidateDCacheAndDMB(void);
|
237
source/screen.c
Normal file
237
source/screen.c
Normal file
@ -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 = (u32)arm11Stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
23
source/screen.h
Normal file
23
source/screen.h
Normal file
@ -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);
|
@ -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;
|
|
||||||
}
|
|
@ -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);
|
|
@ -23,15 +23,15 @@ start:
|
|||||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||||
|
|
||||||
@ Sets MPU permissions and cache settings
|
@ Sets MPU permissions and cache settings
|
||||||
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
||||||
ldr r1, =0x3000801B @ fff00000 16k | dtcm
|
ldr r1, =0x3000801B @ fff00000 16k | dtcm
|
||||||
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
||||||
ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||||
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||||
ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||||
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||||
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||||
mov r8, #0x25
|
mov r8, #0x29
|
||||||
mcr p15, 0, r0, c6, c0, 0
|
mcr p15, 0, r0, c6, c0, 0
|
||||||
mcr p15, 0, r1, c6, c1, 0
|
mcr p15, 0, r1, c6, c1, 0
|
||||||
mcr p15, 0, r2, c6, c2, 0
|
mcr p15, 0, r2, c6, c2, 0
|
||||||
@ -40,9 +40,9 @@ start:
|
|||||||
mcr p15, 0, r5, c6, c5, 0
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
mcr p15, 0, r6, c6, c6, 0
|
mcr p15, 0, r6, c6, c6, 0
|
||||||
mcr p15, 0, r7, c6, c7, 0
|
mcr p15, 0, r7, c6, c7, 0
|
||||||
mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 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, 2, 5
|
mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 3, 5
|
||||||
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 5
|
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 3, 5
|
||||||
|
|
||||||
@ Enable dctm
|
@ Enable dctm
|
||||||
ldr r0, =0x3000800A @ set dtcm
|
ldr r0, =0x3000800A @ set dtcm
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
u32 waitInput(void)
|
u32 waitInput(void)
|
||||||
{
|
{
|
||||||
@ -35,6 +36,8 @@ u32 waitInput(void)
|
|||||||
|
|
||||||
void mcuReboot(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);
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user