index = rel_name(token_list[1])
if index == "-1":
# TODO - Check if an integer was passed.
- syn_error("invalid argument")
+ syn_err("invalid argument")
return bytearray.fromhex("01" + index)
elif token_list[0] == "find":
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
val.reverse()
return bytearray.fromhex("07") + val
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("17") + val
elif token_list[0] == "jmpne":
if s != 2:
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("27") + val
elif token_list[0] == "jmplt":
if s != 2:
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("37") + val
elif token_list[0] == "jmpgt":
if s != 2:
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("47") + val
elif token_list[0] == "jmple":
if s != 2:
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("57") + val
elif token_list[0] == "jmpge":
if s != 2:
if instr_offs == None:
return bytearray.fromhex("070000")
else:
- tok = bytearray.fromhex(token_list[1])
- num = struct.unpack(">H", tok)[0]
+ num = int(token_list[1])
val = bytearray(struct.pack(">H", instr_offs[num]))
+ val.reverse()
return bytearray.fromhex("67") + val
def pad_zero_r(x, c):
offsets += [size]
size += len(bytes)
- offsets += [size+1] # So we can jump past the last instruction for 'exit' type behavior
+ offsets += [size] # So we can jump past the last instruction for 'exit' type behavior
lines = 0
ins.seek(0)
# #############################
-# Sigs (1)
+# New3DS Sigs (1)
seek 0009DF64
test C117491C31D0
-jmpne 0006
+jmpne 8
set 00204EB070BD
-jmp 000D
-# OLD3DS Sigs (6)
-seek 0009D2A8
-test C117491C31D0
-jmpne 000B
-set 00204EB070BD
-jmp 000D
-# Failed to set sigcheck.
-
-# Abort due to failure. (11)
-rewind
-back 01
-
-# The above rewinds the file and moves backwards
-# one byte (which triggers the underflow error in
-# the VM)
-
-# ##############################
-
-# Bootscreen (13)
+# Bootscreen (5)
seek 000D8B8A
-test 01
-jmpne 0012
set 26
-jmp 0016
+jmp 12
+
+#########################
+
+# OLD3DS Sigs (8)
+seek 0009D2A8
+set 00204EB070BD
-# OLD3ds bootscreen (18)
+# OLD3ds bootscreen (10)
seek 000D7A12
-test 01
-jmpne 000B
set 26
-# End (22)
+# #######################
+
+# End (12)
# $ver 01
# $uuid 01
+rel exe_text
+
# Status: needs loader
find 0C18E1D8
# $ver 01
# $uuid 02
+rel exe_text
+
# Status: needs loader
find 30B5F1B0
# $ver 01
# $uuid 03
+rel exe_text
+
# Status: needs loader
find 25790B99
# $uuid 04
# $flags devmode
+rel exe_text
+
# Status: needs loader
find 1400D0E5DB9A9FED
# $uuid 05
# $flags noabort
+rel exe_text
+
# Status: needs loader
find E01EFF2FE1010101
# $flags devmode
# 0: Relative to NATIVE_FIRM, section index [1]
-rel native_s1
+rel native_s1
# 1: Find this byte string.
-find 9705000015E40000
+find 9705000015E40000
# Move backwards until we find what we want.
# LOOP (2):
back 04
test 16640100
-jmpne 0002
+jmpne 2
-and efff
+and ef
# $ver 01
# $uuid 07
+rel exe_text
+
# Status: needs loader
# u"Ver."
# $ver 01
# $uuid 1e
+rel exe_text
+
# This was originally based on the code from @Reisyukaku's pastebin.
# Suggestion from @TuxSH / @Steveice10.
# $ver 01
# $uuid 09
+rel exe_text
+
# Status: needs loader
find 000055E30110A0E3
# $ver 01
# $uuid 0a
+rel exe_text
+
# Status: needs loader
find 30402DE90250A0E1
# $ver 01
# $uuid 0b
+rel exe_text
+
# Status: needs loader
find 06461048FC
# Status: untested, but should work
rel native_s2
+
find 0110A013
fwd 03
set E3
enum type
{
- boolean_val = 0, // Toggle
- ranged_val = 1, // N1 - N2, left and right to pick.
- mask_val = 2, // Bitmask allowed values.
- not_option = 3, // Skip over this.
- call_fun = 4 // Call a function. Treat (a) as (void)(*)(void).
+ boolean_val = 0, // Toggle
+ ranged_val = 1, // N1 - N2, left and right to pick.
+ mask_val = 2, // Bitmask allowed values.
+ not_option = 3, // Skip over this.
+ call_fun = 4, // Call a function. Treat (a) as (void)(*)(void).
+ boolean_val_n3ds = 5 // Toggle, but only show on n3DS
};
struct range_str
void header(char *append);
+extern int is_n3ds;
+
int
show_menu(struct options_s *options, uint8_t *toggles)
{
int i = 0;
while (options[i].index != -1) { // -1 Sentinel.
- if (options[i].allowed == boolean_val) {
+ if (options[i].allowed == boolean_val || (is_n3ds && options[i].allowed == boolean_val_n3ds)) {
if (cursor_y == i)
fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
else
switch (key) {
case BUTTON_UP:
cursor_y -= 1;
- while (options[cursor_y].allowed == not_option && cursor_y >= cursor_min)
+ while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y >= cursor_min)
cursor_y--;
break;
case BUTTON_DOWN:
cursor_y += 1;
- while (options[cursor_y].allowed == not_option && cursor_y < cursor_max)
+ while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y < cursor_max)
cursor_y++;
break;
case BUTTON_LEFT:
cursor_y -= 5;
- while (options[cursor_y].allowed == not_option && cursor_y >= cursor_min)
+ while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y >= cursor_min)
cursor_y--;
break;
case BUTTON_RIGHT:
cursor_y += 5;
- while (options[cursor_y].allowed == not_option && cursor_y < cursor_max)
+ while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y < cursor_max)
cursor_y++;
break;
case BUTTON_A:
- if (options[cursor_y].allowed == boolean_val) {
+ if (options[cursor_y].allowed == boolean_val || options[cursor_y].allowed == boolean_val_n3ds) {
toggles[options[cursor_y].index] = !toggles[options[cursor_y].index];
} else if (options[cursor_y].allowed == ranged_val) {
if (toggles[options[cursor_y].index] == options[cursor_y].b)
boot_cfw()
{
fprintf(BOTTOM_SCREEN, "Loading firmware...\n");
+
+ if (config.options[OPTION_RECONFIGURED]) {
+ config.options[OPTION_RECONFIGURED] = 0;
+ save_config();
+ config.options[OPTION_RECONFIGURED] = 1;
+ }
+
load_firms();
if (config.options[OPTION_RECONFIGURED]) {
abort("Failed to save prepatched agb\n");
}
- if (config.options[OPTION_RECONFIGURED]) {
- config.options[OPTION_RECONFIGURED] = 0;
- save_config();
- }
-
boot_firm();
}
#define OP_VER 0x0D
#define OP_CLF 0x0E
#define OP_SEEK 0x0F
+#define OP_N3DS 0x10
#define OP_JMPEQ 0x17
#define OP_JMPNE 0x27
struct mode modes[21];
int init_bytecode = 0;
+#ifndef LOADER
+extern int is_n3ds;
+#else
+int is_n3ds = 1; // TODO - We don't really need to care, but it should still work from loader
+#endif
+
int
exec_bytecode(uint8_t *bytecode, uint16_t ver, uint32_t len, int debug)
{
eq = !eq;
code += 2;
break;
+ case OP_N3DS:
+ if (debug)
+ log("ver\n");
+ code++;
+ eq = is_n3ds;
+ code += 2;
+ break;
case OP_SEEK: // Jump to offset if greater than or equal
if (debug)
log("seek\n");
int menu_handler();
+int is_n3ds = 0;
+
int doing_autoboot = 0;
void shut_up();
+#define CONFIG_PLATFORM_REG ((volatile uint32_t*)0x10140FFC)
+
int
main()
{
+ if (*CONFIG_PLATFORM_REG == 7)
+ is_n3ds = 1;
+
int c = fmount();
screen_init();
{ 0, "\x1b[32;40mLoader Options\x1b[0m", "", not_option, 0, 0 },
{ OPTION_LOADER, "Use Loader Replacement", "Replaces loader with one capable of the below and also applying bytecode patches.", boolean_val, 0, 0 },
- { OPTION_LOADER_CPU_L2, " CPU - L2 cache (n3ds)", "Forces the system to use the L2 cache. Ignored if not a N3DS.", boolean_val, 0, 0 },
- { OPTION_LOADER_CPU_800MHZ, " CPU - 800Mhz (n3ds)", "Forces the system to run in 800Mhz mode. Ignored if not a N3DS.", boolean_val, 0, 0 },
+ { OPTION_LOADER_CPU_L2, " CPU - L2 cache (n3ds)", "Forces the system to use the L2 cache. Ignored if not a N3DS.", boolean_val_n3ds, 0, 0 },
+ { OPTION_LOADER_CPU_800MHZ, " CPU - 800Mhz (n3ds)", "Forces the system to run in 800Mhz mode. Ignored if not a N3DS.", boolean_val_n3ds, 0, 0 },
{ OPTION_LOADER_LANGEMU, " Language Emulation", "Reads language emulation configuration and imitates the region/language.", boolean_val, 0, 0 },
{ OPTION_LOADER_DUMPCODE, " Dump Code Sections (dev)",
int
menu_reset()
{
+ write_file(enable_list, PATH_TEMP "/PATCHENABLE", FCRAM_SPACING / 2);
+ config.options[OPTION_RECONFIGURED] = 1;
+ save_config(); // Save config, including the reconfigured flag.
+
fumount(); // Unmount SD.
// Reboot.
int
menu_poweroff()
{
+ write_file(enable_list, PATH_TEMP "/PATCHENABLE", FCRAM_SPACING / 2);
+ config.options[OPTION_RECONFIGURED] = 1;
+ save_config(); // Save config, including the reconfigured flag.
+
fumount(); // Unmount SD.
// Reboot.