diff --git a/bootloader/Makefile b/bootloader/Makefile index 637c06f..0edb343 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -25,7 +25,7 @@ INCLUDES := include source/fatfs source/inih source/fatfs/sdmmc #--------------------------------------------------------------------------------- # Setup some defines #--------------------------------------------------------------------------------- - +VERSION := $(shell git describe --abbrev=4 --always --dirty --tags || echo "UNKNOWN") #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- @@ -34,7 +34,7 @@ ARCH := -mthumb -mthumb-interwork CFLAGS := -g -Wall -O2\ -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ -ffast-math -std=c99\ - $(ARCH) + $(ARCH) -DVERSION_STRING="\"$(VERSION)\"" CFLAGS += $(INCLUDE) -DARM9 diff --git a/bootloader/include/config.h b/bootloader/include/config.h index 39a2cf9..b9764a7 100644 --- a/bootloader/include/config.h +++ b/bootloader/include/config.h @@ -11,7 +11,10 @@ typedef struct { char path[64]; unsigned long long delay; unsigned long payload; - unsigned long offset; + unsigned long offset; + int splash; + char splash_image[64]; + unsigned int screenEnabled; } configuration; #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 diff --git a/bootloader/include/draw.h b/bootloader/include/draw.h new file mode 100644 index 0000000..41b5c50 --- /dev/null +++ b/bootloader/include/draw.h @@ -0,0 +1,25 @@ +#pragma once + +#include "common.h" + +#define BYTES_PER_PIXEL 3 +#define SCREEN_WIDTH 240 +#define SCREEN_HEIGHT 400 + +#define SCREEN_SIZE (BYTES_PER_PIXEL * SCREEN_WIDTH * SCREEN_HEIGHT) + +#define RGB(r,g,b) (r<<24|b<<16|g<<8|r) + +#define TOP_SCREEN0 (u8*)(0x18300000) +#define BOT_SCREEN0 (u8*)(0x18346500) +extern int current_y; + +void ClearScreen(unsigned char *screen, int color); +void clearScreens(); +void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor); +void DrawHex(unsigned char *screen, unsigned int hex, int x, int y, int color, int bgcolor); +u32 DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor); +void DrawStringF(int x, int y, const char *format, ...); +void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor); + +void drawDebug(const char *format, ...); diff --git a/bootloader/include/log.h b/bootloader/include/log.h index 1a55653..a477729 100644 --- a/bootloader/include/log.h +++ b/bootloader/include/log.h @@ -5,6 +5,6 @@ int initLog(); void closeLogFile(); -void debug(const char *msg); -void panic(const char *msg); +void debug(const char *format, ...); +void panic(const char *format, ...); void shutdown(); \ No newline at end of file diff --git a/bootloader/include/screen.h b/bootloader/include/screen.h new file mode 100644 index 0000000..c12b44a --- /dev/null +++ b/bootloader/include/screen.h @@ -0,0 +1,7 @@ +#include "common.h" + +typedef void (*arm11Function)(void); +void screenInit(); +void screenDeinit(); +void __attribute__((naked)) disable_lcds(); +void __attribute__ ((naked)) enable_lcd(); \ No newline at end of file diff --git a/bootloader/include/splash.h b/bootloader/include/splash.h new file mode 100644 index 0000000..a7b7575 --- /dev/null +++ b/bootloader/include/splash.h @@ -0,0 +1,13 @@ +#pragma once + +#include "common.h" + +#define ASCII_ART_TEMPLATE (" _ __\n" \ + "|_) _ _ _|_/ _|_ __\n" \ + "|_)(_)(_) |_\\__ |_ |\n" \ + "%s\n" \ + "\n" \ + "is loading...") + +int splash_ascii(void); +int splash_image(char *splash_path); diff --git a/bootloader/source/config.c b/bootloader/source/config.c index 7d3545e..3fc3c90 100644 --- a/bootloader/source/config.c +++ b/bootloader/source/config.c @@ -104,7 +104,13 @@ int handler(void *user, const char *section, const char *name, const char *value } else if (MATCH(pconfig->section, "payload")) { pconfig->payload = myAtoi(value); } else if (MATCH(pconfig->section, "offset")) { - pconfig->offset = numberToInt(value); - } + pconfig->offset = numberToInt(value); + } else if (MATCH(pconfig->section, "splash")) { + pconfig->splash = myAtoi(value); + } else if (MATCH(pconfig->section, "splash_image")) { + strcpy (pconfig->splash_image,value); + } else if (MATCH(pconfig->section, "screenEnabled")) { + pconfig->screenEnabled = myAtoi(value); + } return 1; } diff --git a/bootloader/source/draw.c b/bootloader/source/draw.c new file mode 100644 index 0000000..7240d0f --- /dev/null +++ b/bootloader/source/draw.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include "font.h" +#include "draw.h" + +int current_y = 0; + +void ClearScreen(unsigned char *screen, int color) +{ + int i; + unsigned char *screenPos = screen; + for (i = 0; i < (SCREEN_HEIGHT * SCREEN_WIDTH); i++) { + *(screenPos++) = color >> 16; // B + *(screenPos++) = color >> 8; // G + *(screenPos++) = color & 0xFF; // R + } +} + +void clearScreens() +{ + ClearScreen(TOP_SCREEN0,0); + ClearScreen(BOT_SCREEN0,0); +} + +void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor) +{ + int yy, xx; + for (yy = 0; yy < 8; yy++) { + int xDisplacement = (x * BYTES_PER_PIXEL * SCREEN_WIDTH); + int yDisplacement = ((SCREEN_WIDTH - (y + yy) - 1) * BYTES_PER_PIXEL); + unsigned char *screenPos = screen + xDisplacement + yDisplacement; + + unsigned char charPos = font[character * 8 + yy]; + for (xx = 7; xx >= 0; xx--) { + if ((charPos >> xx) & 1) { + *(screenPos + 0) = color >> 16; // B + *(screenPos + 1) = color >> 8; // G + *(screenPos + 2) = color & 0xFF; // R + } else { + *(screenPos + 0) = bgcolor >> 16; // B + *(screenPos + 1) = bgcolor >> 8; // G + *(screenPos + 2) = bgcolor & 0xFF; // R + } + screenPos += BYTES_PER_PIXEL * SCREEN_WIDTH; + } + } +} + +u32 DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor) +{ + int i,position=0; + for (i = 0; i < strlen(str); i++) + { + if(str[i]=='\n') + { + y+=10; + position=0; + } + else + { + DrawCharacter(screen, str[i], x + position, y, color, bgcolor); + position+=8; + } + } + return y; +} + +void DrawStringF(int x, int y, const char *format, ...) +{ + char str[256]; + va_list va; + + va_start(va, format); + vsnprintf(str, 256, format, va); + va_end(va); + + DrawString(TOP_SCREEN0, str, x, y, RGB(255, 255, 255), RGB(0, 0, 0)); +} + +void drawDebug(const char *format, ...) +{ + char str[256]; + va_list va; + + va_start(va, format); + vsnprintf(str, 256, format, va); + va_end(va); + + current_y = DrawString(BOT_SCREEN0, str, 10, current_y, RGB(255, 255, 255), RGB(0, 0, 0)); + + current_y += 10; +} diff --git a/bootloader/source/log.c b/bootloader/source/log.c index 32b4484..9a643cd 100644 --- a/bootloader/source/log.c +++ b/bootloader/source/log.c @@ -1,7 +1,13 @@ #include "log.h" +#include "draw.h" #include "fatfs/ff.h" #include "i2c.h" +#include "hid.h" +#include +#include +#include +#include #define LOGNAME "/arm9loaderhax/arm9bootloader.log" #define LOGNAME_BACKUP "/arm9bootloader.log" @@ -33,31 +39,47 @@ void closeLogFile() } } -void debug(const char *msg) +void debug(const char *format, ...) { + char str[256]; + va_list va; + + va_start(va, format); + vsnprintf(str, 256, format, va); + va_end(va); + if(logFileOpened) { - f_puts (msg, &logFile); + f_puts (str, &logFile); f_putc ('\n', &logFile); f_sync (&logFile); } + drawDebug(str); } -void panic(const char *msg) +void panic(const char *format, ...) { + char str[256]; + va_list va; + + va_start(va, format); + vsnprintf(str, 256, format, va); + va_end(va); + if(logFileOpened) { debug("ERROR:"); - debug(msg); + debug(str); } - + drawDebug(str); + drawDebug("Press any key to shutdown"); + InputWait(); shutdown(); } void shutdown() { - //debug("shutdown"); - //closeLogFile(); + debug("shutdown"); + closeLogFile(); i2cWriteRegister(I2C_DEV_MCU, 0x20, (u8)(1<<0)); - //exit(0); while(1); } \ No newline at end of file diff --git a/bootloader/source/main.c b/bootloader/source/main.c index b0d75ee..28406e2 100644 --- a/bootloader/source/main.c +++ b/bootloader/source/main.c @@ -6,19 +6,24 @@ #include "hid.h" #include "log.h" #include "i2c.h" +#include "screen.h" +#include "splash.h" - -#define DEFAULT_PATH {0} -#define DEFAULT_DELAY 2000 /* ms */ +#define DEFAULT_PATH {0} +#define DEFAULT_DELAY 100 /* ms */ #define DEFAULT_PAYLOAD -1 /* <0 - auto, 0 - disable, >0 - enabled */ -#define DEFAULT_OFFSET 0x12000 +#define DEFAULT_OFFSET 0x12000 #define DEFAULT_SECTION "GLOBAL" -#define INI_FILE "/arm9loaderhax/boot_config.ini" +#define DEFAULT_SCREEN 1 +#define DEFAULT_SPLASH 3 /* 0 - disabled, 1 - splash screen, 2 - entry info, 3 - both */ +#define DEFAULT_SPLASH_IMAGE {0} +#define INI_FILE "/arm9loaderhax/boot_config.ini" #define INI_FILE_BOOTCTR "/boot_config.ini" + #define PAYLOAD_ADDRESS 0x23F00000 #define PAYLOAD_SIZE 0x00100000 - +#define SCREEN_SIZE 400 * 240 * 3 / 4 //yes I know this is more than the size of the bootom screen bool file_exists(const char* path) { FIL fd; @@ -57,9 +62,18 @@ int main() { .delay = DEFAULT_DELAY, .payload = DEFAULT_PAYLOAD, .offset = DEFAULT_OFFSET, + .splash = DEFAULT_SPLASH, + .splash_image = DEFAULT_SPLASH_IMAGE, + .screenEnabled = DEFAULT_SCREEN, }; FATFS fs; FIL payload; + if(*((u8*)0x101401C0) == 0x0) + { + screenInit(); + debug("Enabeling screen"); + } + clearScreens(); if(f_mount(&fs, "0:", 1) == FR_OK) { @@ -69,7 +83,10 @@ int main() { iniparse(INI_FILE, handler, &app); debug("Checking input"); + for(volatile u64 i=0;i<0xEFF*app.delay;i++); u32 key = GetInput(); + app.delay=0; + // using X-macros to generate each switch-case rules // https://en.wikibooks.org/wiki/C_Programming/Preprocessor#X-Macros #define KEY(k) \ @@ -79,8 +96,7 @@ int main() { #include "keys.def" app.section = "DEFAULT"; - debug("Key checked - selected section:"); - debug(app.section); + debug("Key checked-selected section: %s",app.section); int config_err = iniparse(INI_FILE, handler, &app); @@ -96,7 +112,7 @@ int main() { if (!app.path) panic("Section [DEFAULT] not found or \"path\" not set."); } else if (!file_exists(app.path)) { - debug("[ERROR] Target payload not found:"); + debug("[ERROR] Target payload not found:\n%s",app.path); panic(app.path); } break; @@ -105,14 +121,14 @@ int main() { break; case -2: // should not happen, however better be safe than sorry - panic("Config file is too big.");//, INI_FILE); + panic("Config file is too big."); break; default: panic("Error found in config file");//, //INI_FILE, config_err); break; } - + debug("Checking payload"); if(app.payload==0) { @@ -123,6 +139,10 @@ int main() { debug("[ERROR] Target payload not found:"); panic(app.path); } + + debug("Loading Splash image"); + splash_image(app.splash_image); + for(volatile u64 i=0;i<0xEFF*app.delay;i++); debug("Loading Payload:"); debug(app.path); @@ -145,6 +165,10 @@ int main() { closeLogFile(); f_mount(&fs, "0:", 1); debug("Jumping to the payload"); + if(app.screenEnabled==0) + { + screenDeinit(); + } ((void (*)())PAYLOAD_ADDRESS)(); } } diff --git a/bootloader/source/screen.c b/bootloader/source/screen.c new file mode 100644 index 0000000..4e2d9b4 --- /dev/null +++ b/bootloader/source/screen.c @@ -0,0 +1,262 @@ +#include "screen.h" +#include "i2c.h" + +//got code for disabeling from CakesForeveryWan +volatile u32 *a11_entry = (volatile u32 *)0x1FFFFFF8; + +void screenInit() +{ + *a11_entry = (u32)enable_lcd; + for(volatile unsigned int i = 0; i < 0xF; ++i); + i2cWriteRegister(3, 0x22, 0x2A); // 0x2A -> boot into firm with no backlight + + *(volatile uint32_t*)0x80FFFC0 = 0x18300000; // framebuffer 1 top left + *(volatile uint32_t*)0x80FFFC4 = 0x18300000; // framebuffer 2 top left + *(volatile uint32_t*)0x80FFFC8 = 0x18300000; // framebuffer 1 top right + *(volatile uint32_t*)0x80FFFCC = 0x18300000; // framebuffer 2 top right + *(volatile uint32_t*)0x80FFFD0 = 0x18346500; // framebuffer 1 bottom + *(volatile uint32_t*)0x80FFFD4 = 0x18346500; // framebuffer 2 bottom + *(volatile uint32_t*)0x80FFFD8 = 1; // framebuffer select top + *(volatile uint32_t*)0x80FFFDC = 1; // framebuffer select bottom + + //cakehax + *(u32*)0x23FFFE00 = 0x18300000; + *(u32*)0x23FFFE04 = 0x18300000; + *(u32*)0x23FFFE08 = 0x18346500; +} + +void screenDeinit() +{ + *a11_entry = (u32)disable_lcds; + for(volatile unsigned int i = 0; i < 0xF; ++i); +} + +void __attribute__((naked)) disable_lcds() +{ + *a11_entry = 0; // Don't wait for us + + *(volatile u32 *)0x10202A44 = 0; + *(volatile u32 *)0x10202244 = 0; + *(volatile u32 *)0x1020200C = 0; + *(volatile u32 *)0x10202014 = 0; + + while (!*a11_entry); + ((void (*)())*a11_entry)(); +} +void regSet(); +void __attribute__ ((naked)) enable_lcd() +{ + //__asm__ ("ldr r0,=0x1FFF4D80\n\t mov sp, r0"); + regSet(); +} + +void regSet() +{ + + *((volatile u32*)0x1FFFFFFD) = 0; + *((volatile u32*)0x1FFFFFF8) = 0; + + // pdn sub_101D98 + *((volatile u32*)0x10141200) = 0x10000; // PDN_GPU_CNT + // Delay here pls + for(volatile int i = 0xC; i > 0; i-=2); + *((volatile u32*)0x10141200) = 0x1007F; // PDN_GPU_CNT + + // gsp sub_1021F4 init_screen_maybe + *((volatile u32*)0x10400004) |= 0x100; + *((volatile u32*)0x10400030) &= 0xFFFFF0FF; + + // sub_107A34 + // Top screen + *((volatile u32*)0x10400400) = 0x000001c2; + *((volatile u32*)0x10400404) = 0x000000d1; + *((volatile u32*)0x10400408) = 0x000001c1; + *((volatile u32*)0x1040040c) = 0x000001c1; + *((volatile u32*)0x10400410) = 0x00000000; + *((volatile u32*)0x10400414) = 0x000000cf; + *((volatile u32*)0x10400418) = 0x000000d1; + *((volatile u32*)0x1040041c) = 0x01c501c1; + *((volatile u32*)0x10400420) = 0x00010000; + *((volatile u32*)0x10400424) = 0x0000019d; + *((volatile u32*)0x10400428) = 0x00000002; + *((volatile u32*)0x1040042c) = 0x00000192; + *((volatile u32*)0x10400430) = 0x00000192; + *((volatile u32*)0x10400434) = 0x00000192; + *((volatile u32*)0x10400438) = 0x00000001; + *((volatile u32*)0x1040043c) = 0x00000002; + *((volatile u32*)0x10400440) = 0x01960192; + *((volatile u32*)0x10400444) = 0x00000000; + *((volatile u32*)0x10400448) = 0x00000000; + *((volatile u32*)0x1040044c) = 0x0000ff00; + *((volatile u32*)0x1040045c) = 0x019000f0; + *((volatile u32*)0x10400460) = 0x01c100d1; + *((volatile u32*)0x10400464) = 0x01920002; + *((volatile u32*)0x10400490) = 0x000003c0; + *((volatile u32*)0x1040049c) = 0x00000000; + *((volatile u32*)0x10400468) = 0x18000000; + *((volatile u32*)0x1040046c) = 0x18000000; + *((volatile u32*)0x10400494) = 0x18000000; + *((volatile u32*)0x10400498) = 0x18000000; + *((volatile u32*)0x10400470) = 0x00080340; + *((volatile u32*)0x10400480) = 0x00000000; + + for(int i = 0; i < 256; i++) + *((volatile u32*)0x10400484) = 0x10101 * i; + + // Bottom screen + *((volatile u32*)0x10400500) = 0x000001c2; + *((volatile u32*)0x10400504) = 0x000000d1; + *((volatile u32*)0x10400508) = 0x000001c1; + *((volatile u32*)0x1040050c) = 0x000001c1; + *((volatile u32*)0x10400510) = 0x000000cd; + *((volatile u32*)0x10400514) = 0x000000cf; + *((volatile u32*)0x10400518) = 0x000000d1; + *((volatile u32*)0x1040051c) = 0x01c501c1; + *((volatile u32*)0x10400520) = 0x00010000; + *((volatile u32*)0x10400524) = 0x0000019d; + *((volatile u32*)0x10400528) = 0x00000052; + *((volatile u32*)0x1040052c) = 0x00000192; + *((volatile u32*)0x10400530) = 0x00000192; + *((volatile u32*)0x10400534) = 0x0000004f; + *((volatile u32*)0x10400538) = 0x00000050; + *((volatile u32*)0x1040053c) = 0x00000052; + *((volatile u32*)0x10400540) = 0x01970193; + *((volatile u32*)0x10400544) = 0x00000000; + *((volatile u32*)0x10400548) = 0x00000011; + *((volatile u32*)0x1040054c) = 0x000000ff; + *((volatile u32*)0x1040055c) = 0x014000f0; + *((volatile u32*)0x10400560) = 0x01c100d1; + *((volatile u32*)0x10400564) = 0x01920052; + *((volatile u32*)0x10400590) = 0x000003c0; + *((volatile u32*)0x1040059c) = 0x00000000; + *((volatile u32*)0x10400568) = 0x18000000; + *((volatile u32*)0x1040056c) = 0x18000000; + *((volatile u32*)0x10400594) = 0x18000000; + *((volatile u32*)0x10400598) = 0x18000000; + *((volatile u32*)0x10400570) = 0x00080301; + *((volatile u32*)0x10400580) = 0x00000000; + + for(int i = 0; i < 256; i++) + *((volatile u32*)0x10400584) = 0x10101 * i; + + *((volatile u32*)0x10400478) = 0x00000000; + *((volatile u32*)0x10400578) = 0x00000000; + *((volatile u32*)0x10400474) = 0x00010501; + *((volatile u32*)0x10400574) = 0x00010501; + + // sub_10915C + *((volatile u32*)0x10202014) = 0x00000001; + *((volatile u32*)0x10202204) = 0x00000000; // color fill disable + *((volatile u32*)0x10202a04) = 0x00000000; // color fill disable + *((volatile u32*)0x1020200C) &= 0xFFFEFFFE;// wtf register + + *((volatile u32*)0x10202240) = 0xFF; + *((volatile u32*)0x10202244) = 0x1023E; + + *((volatile u32*)0x10202A40) = 0xFF; + *((volatile u32*)0x10202A44) = 0x1023E; + + // After hm call cmd 0x00160042 to acquire rights + // and cmd 00130042 RegisterInterruptRelayQueue + *((volatile u32*)0x10401000) = 0; + *((volatile u32*)0x10401080) = 0x12345678; + *((volatile u32*)0x104010C0) = 0xFFFFFFF0; + *((volatile u32*)0x104010D0) = 1; + *((volatile u32*)0x10400400) = 0x000001c2; + *((volatile u32*)0x10400404) = 0x000000d1; + *((volatile u32*)0x10400408) = 0x000001c1; + *((volatile u32*)0x1040040c) = 0x000001c1; + *((volatile u32*)0x10400410) = 0x00000000; + *((volatile u32*)0x10400414) = 0x000000cf; + *((volatile u32*)0x10400418) = 0x000000d1; + *((volatile u32*)0x1040041c) = 0x01c501c1; + *((volatile u32*)0x10400420) = 0x00010000; + *((volatile u32*)0x10400424) = 0x0000019d; + *((volatile u32*)0x10400428) = 0x00000002; + *((volatile u32*)0x1040042c) = 0x00000192; + *((volatile u32*)0x10400430) = 0x00000192; + *((volatile u32*)0x10400434) = 0x00000192; + *((volatile u32*)0x10400438) = 0x00000001; + *((volatile u32*)0x1040043c) = 0x00000002; + *((volatile u32*)0x10400440) = 0x01960192; + *((volatile u32*)0x10400444) = 0x00000000; + *((volatile u32*)0x10400448) = 0x00000000; + *((volatile u32*)0x1040045c) = 0x019000f0; + *((volatile u32*)0x10400460) = 0x01c100d1; + *((volatile u32*)0x10400464) = 0x01920002; + *((volatile u32*)0x10400470) = 0x00080340; + *((volatile u32*)0x1040049C) = 0x00000000; + // (122500 log) + *((volatile u32*)0x10400500) = 0x000001c2; + *((volatile u32*)0x10400504) = 0x000000d1; + *((volatile u32*)0x10400508) = 0x000001c1; + *((volatile u32*)0x1040050c) = 0x000001c1; + *((volatile u32*)0x10400510) = 0x000000cd;//diff + *((volatile u32*)0x10400514) = 0x000000cf; + *((volatile u32*)0x10400518) = 0x000000d1; + *((volatile u32*)0x1040051c) = 0x01c501c1; + *((volatile u32*)0x10400520) = 0x00010000; + *((volatile u32*)0x10400524) = 0x0000019d; + *((volatile u32*)0x10400528) = 0x00000052;//diff + *((volatile u32*)0x1040052c) = 0x00000192; + *((volatile u32*)0x10400530) = 0x00000192; + *((volatile u32*)0x10400534) = 0x0000004f;//diff + *((volatile u32*)0x10400538) = 0x00000050;//diff + *((volatile u32*)0x1040053c) = 0x00000052;//diff + *((volatile u32*)0x10400540) = 0x01980194;//diff + *((volatile u32*)0x10400544) = 0x00000000; + *((volatile u32*)0x10400548) = 0x00000011;//diff + *((volatile u32*)0x1040055c) = 0x014000f0;//diff + *((volatile u32*)0x10400560) = 0x01c100d1; + *((volatile u32*)0x10400564) = 0x01920052;//diff + *((volatile u32*)0x1040059C) = 0x00000000; + //(122860 log) + + *((volatile u32*)0x10400468) = 0x18300000; + *((volatile u32*)0x1040046c) = 0x18300000; + *((volatile u32*)0x10400494) = 0x18300000; + *((volatile u32*)0x10400498) = 0x18300000; + + *((volatile u32*)0x10400568) = 0x18300000 + 0x46500; + *((volatile u32*)0x1040056c) = 0x18300000 + 0x46500; + + *((volatile u32*)0x10400478) = 0x00000001; + *((volatile u32*)0x10400578) = 0x00000001; + + // dma stuffs + // skipped + + // called by hm + *((volatile u32*)0x10400004) = 0x00070100; + + //(123030 log) + *((volatile u32*)0x1040001C) &= 0xFFFFFFFD; + *((volatile u32*)0x1040002C) &= 0xFFFFFFFD; + *((volatile u32*)0x10400050) = 0x22221200; + *((volatile u32*)0x10400054) = 0xFF2; + + //(123097 log) + *((volatile u32*)0x10400474) = 0x00010501; + *((volatile u32*)0x10400574) = 0x00010501; + + // from hm + // command list skipped + *((volatile u32*)0x10400470) = 0x00080341; + *((volatile u32*)0x10400490) = 0x000002D0; + + *((volatile u32*)0x10400570) = 0x00080301; + *((volatile u32*)0x10400590) = 0x000002D0; + + *((volatile u32*)0x10401000) = 0x00000000; + + // Reset the entry + *a11_entry = 0; + + // Wait for entry to be set + while(!*a11_entry); + + // Jump + ((void (*)())*a11_entry)(); + +} + diff --git a/bootloader/source/splash.c b/bootloader/source/splash.c new file mode 100644 index 0000000..5060c1c --- /dev/null +++ b/bootloader/source/splash.c @@ -0,0 +1,41 @@ +#include "splash.h" +#include "draw.h" +#include "log.h" +#include "fatfs/sdmmc/sdmmc.h" +#include "fatfs/ff.h" + +int splash_ascii(void) +{ + // print BootCtr logo + // http://patorjk.com/software/taag/#p=display&f=Bigfig&t=BootCtr + ClearScreen(TOP_SCREEN0,0); + DrawStringF(5,5,ASCII_ART_TEMPLATE, VERSION_STRING); + return 0; +} + +int splash_image(char *splash_path) +{ + // load image in memory, doing proper error checking + FIL splash_file; + unsigned int br; + if(strlen(splash_path)==0) + { + debug("Splash image not set, use default screen"); + // force ASCII splash art in case of error + splash_ascii(); + return -1; + } + if(f_open(&splash_file, splash_path, FA_READ | FA_OPEN_EXISTING) != FR_OK) + { + debug("Couldn't open splash image %s.", splash_path); + // force ASCII splash art in case of error + splash_ascii(); + return -1; + } + + // copy splash image to framebuffer + f_read(&splash_file, (void*)(*(u32*)0x23FFFE00), 0x00600000, &br); + + return 0; +} +