Implement splash screen loading and display in fusee stage2

Splash loader will look for a file called `splash.bmp` on the root of the SD card and display it. If the file does not exist, or it can't be read for whatever reason,
it will display the default splash linked into the binary.

Stage2 binary is now quite large (>3MB) as a result of statically linking in the default splash screen.
This commit is contained in:
Sorixelle 2018-05-10 17:22:18 +10:00
parent 75169790ff
commit 9edda14be4
No known key found for this signature in database
GPG Key ID: 4366AA8AA3A99CF9
10 changed files with 65 additions and 18 deletions

View File

@ -15,6 +15,7 @@ extern void (*__program_exit_callback)(int rc);
static void *g_framebuffer;
static char g_bct0_buffer[BCTO_MAX_SIZE];
#define I_KNOW_WHAT_I_AM_DOING
#define DEFAULT_BCT0_FOR_DEBUG \
"BCT0\n"\
"[stage1]\n"\

View File

@ -11,6 +11,7 @@ name := fusee-secondary
dir_source := src
dir_build := build
dir_out := out
dir_data := data
ARCH := -march=armv4t -mtune=arm7tdmi -marm
@ -34,7 +35,8 @@ LDFLAGS = -specs=linker.specs -g $(ARCH)
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c)))
$(call rwildcard, $(dir_source), *.s *.c))) \
$(dir_build)/default_splash.bmp.o
define bin2o
bin2s $< | $(AS) -o $(@)
@ -58,6 +60,9 @@ $(dir_build)/$(name).elf: $(objects)
$(dir_build)/%.bin.o: $(dir_build)/%.bin
@$(bin2o)
$(dir_build)/default_splash.bmp.o: $(dir_data)/default_splash.bmp
@$(bin2o)
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
@ -65,3 +70,5 @@ $(dir_build)/%.o: $(dir_source)/%.c
$(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)"
$(COMPILE.c) -x assembler-with-cpp $(OUTPUT_OPTION) $<

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

View File

@ -7,6 +7,7 @@
#include <sys/iosupport.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#include "lib/fatfs/ff.h"

View File

@ -11,6 +11,7 @@
#include "sd_utils.h"
#include "fs_dev.h"
#include "display/video_fb.h"
#include "splash_screen.h"
extern void (*__program_exit_callback)(int rc);
@ -77,7 +78,7 @@ int main(int argc, void **argv) {
g_do_nxboot = loader_ctx->chainload_entrypoint == 0;
if (g_do_nxboot) {
nxboot_main();
nxboot_main((uint8_t*)g_framebuffer);
} else {
/* TODO: What else do we want to do in terms of argc/argv? */
const char *path = get_loader_ctx()->file_paths[get_loader_ctx()->file_id_of_entrypoint];

View File

@ -99,7 +99,7 @@ static int init_bcpkg2_device(void) {
}
/* This is the main function responsible for booting Horizon. */
void nxboot_main(void) {
void nxboot_main(uint8_t *fb_addr) {
loader_ctx_t *loader_ctx = get_loader_ctx();
/* TODO: this is not always necessary */
@ -149,7 +149,7 @@ void nxboot_main(void) {
}
/* Display splash screen. */
display_splash_screen_bmp(loader_ctx->custom_splash_path);
display_splash_screen_bmp(loader_ctx->custom_splash_path, fb_addr);
rawmmcdev_unmount_all();

View File

@ -22,6 +22,6 @@
#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL)
void nxboot_main(void);
void nxboot_main(uint8_t *fb_addr);
#endif

View File

@ -1,20 +1,59 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "utils.h"
#include "timers.h"
#include "splash_screen.h"
#include "sd_utils.h"
#include "display/video_fb.h"
void display_splash_screen_bmp(const char *custom_splash_path) {
uint8_t *splash_screen = g_default_splash_screen;
if (custom_splash_path != NULL && custom_splash_path[0] != '\x00') {
if (!read_sd_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) {
printf("Error: Failed to read custom splash screen from %s!\n", custom_splash_path);
generic_panic();
uint8_t *load_default_splash() {
printf("Failed to read custom splash. Falling back to default splash");
uint8_t *buffer = calloc(default_splash_bmp_size, sizeof(uint8_t));
memcpy(buffer, default_splash_bmp, default_splash_bmp_size);
return buffer;
}
void display_splash_screen_bmp(const char *custom_splash_path, uint8_t* fb_addr) {
/* Cast the framebuffer to a 2-dimensional array, for easy addressing */
uint8_t (*fb)[3072] = (uint8_t(*)[3072])fb_addr;
uint8_t *splash_screen = NULL;
/* Stat the splash file to set size information, and see if it's there */
struct stat info;
if (!stat(custom_splash_path, &info)) {
/* Prepare the buffer */
splash_screen = calloc(info.st_size, sizeof(uint8_t));
/* Read the BMP from the SD card */
if (!read_sd_file(splash_screen, info.st_size, custom_splash_path)) {
splash_screen = load_default_splash();
}
} else {
splash_screen = load_default_splash();
}
/* BMP pixel data offset (dword @ 0xA) */
int data_offset = (splash_screen[0xA] & 0xFF) |
((splash_screen[0xB] & 0xFF00) << 8) |
((splash_screen[0xC] & 0xFF0000) << 16) |
((splash_screen[0xD] & 0xFF000000) << 24);
int count = 0;
for (int y = 719; y >= 0; y--) {
for (int x = 1280; x > 0; x--) {
/* Fill the framebuffer w/ necessary pixel format translations (framebuffer is RGBA, BMP is BGRA) */
fb[x][y * 4] = splash_screen[data_offset + count + 2];
fb[x][y * 4 + 1] = splash_screen[data_offset + count + 1];
fb[x][y * 4 + 2] = splash_screen[data_offset + count];
fb[x][y * 4 + 3] = splash_screen[data_offset + count + 3];
count += 4;
}
}
/* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */
/* Free the splash buffer; we're done with it. */
free(splash_screen);
/* Display the splash screen for three seconds. */
wait(3000000);

View File

@ -3,9 +3,10 @@
#include <stdint.h>
/* TODO: Actually make this a real thing. */
extern unsigned char g_default_splash_screen[1];
extern uint8_t default_splash_bmp[];
extern uint32_t default_splash_bmp_size;
void display_splash_screen_bmp(const char *custom_splash_path);
void display_splash_screen_bmp(const char *custom_splash_path, uint8_t *fb_addr);
uint8_t *load_default_splash();
#endif

View File

@ -1,3 +0,0 @@
#include "splash_screen.h"
uint8_t g_default_splash_screen[1] = {0};