added screen init, added splash screens, added visual debug output, added

the posibility to set a delay for checking the pressed key
This commit is contained in:
Alexander Hartmann
2016-02-29 18:36:11 +01:00
parent e1c7e8c819
commit 775dd894d8
12 changed files with 524 additions and 26 deletions
+2 -2
View File
@@ -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
+4 -1
View File
@@ -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
+25
View File
@@ -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, ...);
+2 -2
View File
@@ -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();
+7
View File
@@ -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();
+13
View File
@@ -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);
+8 -2
View File
@@ -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;
}
+95
View File
@@ -0,0 +1,95 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#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;
}
+30 -8
View File
@@ -1,7 +1,13 @@
#include "log.h"
#include "draw.h"
#include "fatfs/ff.h"
#include "i2c.h"
#include "hid.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#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);
}
+35 -11
View File
@@ -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)();
}
}
+262
View File
@@ -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)();
}
+41
View File
@@ -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;
}