mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-07-04 00:22:15 +02:00
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:
parent
75169790ff
commit
9edda14be4
@ -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"\
|
||||
|
@ -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) $<
|
||||
|
||||
|
||||
|
BIN
fusee/fusee-secondary/data/default_splash.bmp
Normal file
BIN
fusee/fusee-secondary/data/default_splash.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 MiB |
@ -7,6 +7,7 @@
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib/fatfs/ff.h"
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,3 +0,0 @@
|
||||
#include "splash_screen.h"
|
||||
|
||||
uint8_t g_default_splash_screen[1] = {0};
|
Loading…
Reference in New Issue
Block a user