Turns out the entrypoint under firmlaunch for ARM11 is at 0x1FFFFFFC, not 0x1FFFFFF8 like arm9loaderhax / brahma
That also explains why screeninit fails on firmlaunch; the wrong entry is used.
Either way I still want to do some cleanup, but it works now.
I'm going to slap a big thank you here to the authors of Luma3DS. I never would have realized the entrypoint was different unless I looked at their code.
#include <malloc.h> // for memalign
#include <std/draw.h> // for framebuffers
+int screen_is_init = 0;
+
struct framebuffers *framebuffers;
volatile uint32_t *const arm11Entry = (volatile uint32_t *)0x1FFFFFF8;
}
}
+int get_screen_is_init() {
+ return screen_is_init;
+}
+
void screen_mode(uint32_t mode, uint32_t bright_level) {
static uint32_t stride, init_top, init_bottom, bright;
// i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 1);
//Turn on backlight
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
+
+ screen_is_init = 1;
}
+
extern uint16_t titleid_passthru[8];
+int is_firmlaunch() {
+ for (int i=0; i < 8; i++)
+ if (titleid_passthru[i] != 0)
+ return 1;
+ return 0;
+}
+
int get_firmtype() {
if (titleid_passthru[5] >= u'0' && titleid_passthru[5] <= u'2')
return titleid_passthru[5] - u'0';
int
main(int argc, char** argv)
{
- if (get_firmtype() != 0)
- ctr_system_poweroff();
-
int have_bg = 0;
int si = 0;
load_config(); // Load configuration.
+ // Check key down for autoboot
+ set_fb_struct();
+
+ if (is_firmlaunch()) {
+ shut_up();
+
+ const char* firm_paths[] = { PATH_NATIVE_P, PATH_TWL_P, PATH_AGB_P };
+
+ firmlaunch_file(firm_paths[get_firmtype()]);
+
+ ctr_system_poweroff();
+ }
+
install_interrupts(); // Get some free debug info.
installArm11Stub();
set_font(PATH_TERMFONT); // Read the font before all else.
- // Check key down for autoboot
- set_fb_struct();
-
clear_bg();
// This is a menuhax splash (90deg rotated BGR8 pixel data)
#include "std/draw.h" // for crflush, stderr
#include "std/fs.h" // for crumount
+#include "patcher.h"
+#include <ctr9/ctr_system.h>
+
static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
+static volatile uint32_t *const a11_entry_fl = (volatile uint32_t *)0x1FFFFFFC;
void firmlaunch(firm_h* firm) {
// Get entrypoints
crumount(); // Unmount SD.
- deinitScreens(); // Turn off display
+ if (get_screen_is_init())
+ deinitScreens(); // Turn off display if on
- *a11_entry = (uint32_t)entry11; // Start kernel11
+ if (is_firmlaunch())
+ *a11_entry_fl = (uint32_t)entry11; // Start kernel11
+ else
+ *a11_entry = (uint32_t)entry11; // Start kernel11
entry9(); // Start process9
}
+void firmlaunch_file(const char* path) {
+ FILE* f = cropen(path, "r");
+ size_t s = crsize(f);
+ uint8_t* mem = malloc(s);
+ crread(mem, 1, s, f);
+ crclose(f);
+
+ firmlaunch((firm_h*)mem);
+}
+
#define ARM11_STUB_ADDRESS (0x25000000 - 0x30) //It's currently only 0x28 bytes large. We're putting 0x30 just to be sure here
#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)();
+int get_screen_is_init();
+
/* Initializes the screen and sets the display mode.
*
* \param mode Screen mode to initialize in, one of RGBA8, BGR8, RGB565_OES, RGB5_A1_OES, or RGBA4_OES
*/
firm_h* load_firm(const char *path, size_t *size_out);
+void firmlaunch_file(const char* path);
+
exefs_h* find_proc9(firm_h *firm);
#endif
#ifndef __PATCHER_H
#define __PATCHER_H
+int is_firmlaunch();
+int get_firmtype();
+
/* Patches firmware with the current configuration.
*
* \return zero on success