]> Chaos Git - corbenik/corbenik.git/commitdiff
Partially implement the interpreter (works for sigs)
authorchaoskagami <chaos.kagami@gmail.com>
Thu, 2 Jun 2016 10:38:27 +0000 (06:38 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Thu, 2 Jun 2016 10:38:27 +0000 (06:38 -0400)
15 files changed:
Makefile
doc/bytecode.md
doc/compiling.md
doc/nonos.md
host/bytecode_asm.py
patch/Makefile
patch/sig.pco
source/firm/fcram.h
source/interp.c [new file with mode: 0644]
source/interp.h [new file with mode: 0644]
source/patch/patch_file.h
source/patch/sig.c
source/patch_format.h
source/std/abort.h
source/std/draw.c

index 67a14d110154abc8b70d2b7fb25a212a6015a990..5f768770cc10e79c56b6055ecef486e3b4cd7d0c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ dir_out    := out
 REVISION := r$(shell git rev-list --count HEAD):$(shell git rev-parse HEAD | head -c8)
 
 ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
-CFLAGS  := -MMD -MP -Wall -Wextra -Werror -fno-omit-frame-pointer -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\"
+CFLAGS  := -MMD -MP -Wall -Wextra -Werror -fno-omit-frame-pointer -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" -DBUFFER=1
 FLAGS   := dir_out=$(abspath $(dir_out)) --no-print-directory
 LDFLAGS := -nostdlib -Wl,-z,defs -lgcc -Wl,-Map,$(dir_build)/link.map
 
@@ -29,7 +29,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
                          $(call rwildcard, $(dir_source), *.s *.c)))
 
 .PHONY: all
-all: a9lh external
+all: a9lh patch external
 
 .PHONY: full
 full: host/langemu.conf all
@@ -38,6 +38,10 @@ full: host/langemu.conf all
 external:
        make -C external
 
+.PHONY: patch
+patch:
+       make -C patch
+
 .PHONY: a9lh
 a9lh: $(dir_out)/arm9loaderhax.bin
 
@@ -55,6 +59,7 @@ host/langemu.conf:
 clean:
        rm -f host/langemu.conf
        make -C external clean
+       make -C patch clean
        rm -rf $(dir_out) $(dir_build)
 
 .PHONY: $(dir_out)/arm9loaderhax.bin
index 5bffbf4b31ab6ca98b27d839e84436df3cb9c2f0..e9747ccbc78aaa31c3907def442bcdd7646e2559 100644 (file)
@@ -91,11 +91,14 @@ test <size> <data...> : 2 + size bytes : opcode 0x06
                Pattern to test.
 
 jmp <offset> : 3 bytes : opcode 0x07
-       Jumps to the Nth instruction within the bytecode, and
+       Jumps to offset instruction within the bytecode, and
     resumes execution from there.
 
+       Note that the assembler should be passed the number of instrcution
+       and will automatically calculate the offset needed.
+
        <offset> : 2 bytes
-               Index to jump to.
+               Offset to jump to.
 
 rewind : 1 byte : opcode 0x08
        Resets the location to the beginning of the space we're working off.
index 0eacb7d9719746c370817b96e8846a8b3ee61b24..30aacc4f4e244346da9a1176b3e8f3d3d61a992e 100644 (file)
@@ -1,16 +1,17 @@
 Cloning / Compilation
 --------------------------
 
-Okay, first thing's first. I can't support compiling on Windows. Use Linux. The repo abuses symbolic links, relies on certain software being present which isn't with devkitPro, and has host tools which are untested on Windows and require a native gcc (as in, mingw only.)
+Okay, first thing's first. I can't support compiling on Windows. Use Linux. The repo abuses symbolic links, relies on certain software being present which isn't with devkitPro, and has host tools which are untested on Windows and require a native gcc (as in, mingw only.) Therefore, do NOT attempt to use windows to compile this. No, I will not port the build scripts to Windows. If you want to fix it without invasive changes, be my guest and make a PR. If I deem the maintenance cost too high, I'll tell you.
 
-If you want to fix windows builds, be my guest. I'll merge it so long as it A) doesn't break my machine's builds and B) uses mingw/cygwin as the native compiler. No msvcisms will be allowed on my watch.
+It may or may not compile with an OSX based cross compiler. I dunno.
 
 You'll need the following to compile:
 
  * git
+ * python2
  * gcc (as in, host gcc)
- * arm-none-eabi-gcc (as in, devkitarm OR baremetal gcc (the latter isn't well tested, but may work)
- * a brain (hard requirement)
+ * arm-none-eabi-gcc (as in, devkitarm OR baremetal gcc (the latter isn't well tested, but may work. Compiling devkitPro using https://github.com/devkitPro/buildscripts is highly recommended.)
+ * bash (as /bin/bash)
 
 To clone: use `git clone --recursive`. Some parts of this CFW are submodules.
 
index 524e584eb7de973f55c24156b6fbdde923049e2a..e77b5ee1c173157b0de194828fecd0f416f1f69b 100644 (file)
@@ -1,4 +1,4 @@
-Things I won't implement
+Things I won't implement (for a number of reasons)
 ==========================
 
  * Memekey Support.
@@ -13,18 +13,15 @@ I don't see this as a feature unless it's opt-in rather than opt-out or mandator
 
  * Gateway launcher dat
 
-Screw off. Need I explain why? Do it yourself. No support will be offered to gateway users. You're paying for a piracy tool. Seriously, why?
+Screw off. Do it yourself. No support will be offered to gateway users. You're paying for a piracy tool. Not to mention, I only integrate code I'm capable of testing safely, so this won't ever be a part of corbenik.
 
  * 3dsx
 
-Get a9lh. Seriously. You might be able to use Brahma, but hell if I know. a9lh is the only supported method of running this, and no 3dsx launcher will be provided.
+You might be able to use Brahma, but hell if I know. Either way, I'm not going to attempt to get stuff on menuhax since there's limits on version now. I recommend any menuhax users get a9lh.
 
 Not bugs
 =========
 
  * CETK decryption
 
-No, I can't fix this on a9lh. Here's how to do it; boot another CFW, go into system settings, then boot corbenik. You'll get the keys you need. This works with Cakes as well. After this, you'll never need a key again.
-
-Another thing to know is only NATIVE_FIRM is required to boot, so you can boot Corbenik without AGB and TWL suceeding, reboot from settings and they'll decrypt if the CETK is there.
-
+This has been removed from the FIRM decryptor, since it's unreliable on a9lh. I may re-add it someday.
index 19e611636a78e7682002fbf51ee0f9792f467e84..f82e0dffd57254129bc1e61ce153086b31aab19f 100755 (executable)
@@ -205,10 +205,12 @@ with open(in_file, "r") as ins:
                data += struct.pack('I', len(title))
                data += struct.pack('I', len(deps))
                data += struct.pack('I', size)
-               for f in title:
-                       data += bytearray.fromhex(f)
-               for f in deps:
-                       data += pad_zero_r(bytearray.fromhex(f), 8)
+               if title:
+                       for f in title:
+                               data += bytearray.fromhex(f)
+               if deps:
+                       for f in deps:
+                               data += pad_zero_r(bytearray.fromhex(f), 8)
                data += bytecode
                writ.write(data)
 
index 8d6fd627ccea96790e2e384f1a5a9c6dfa3ec5d1..b70576462da38ff1268dfa1cf564496f0486dc90 100644 (file)
@@ -1,5 +1,7 @@
 .PHONY: all
 all: $(patsubst %.pco, %.vco, $(wildcard *.pco))
+       mkdir -p ../out/corbenik/bin
+       cp *.vco ../out/corbenik/bin/
 
 %.vco: %.pco
        ../host/bytecode_asm.py $< $@
index 73ea077c60a9a11e6d413287bf0664812d26e45f..b952980425d30f534ddd4b61b73cf874a3504025 100644 (file)
@@ -18,4 +18,5 @@ rewind
 
 # Pattern 2.
 find b5224d0c
+back 01
 set  00207047
index 5bd78ef8975a0d7d1ae7df079b3c021f07867302..a91b60831a5c653f953338f1adf0d647e1a19177 100644 (file)
@@ -26,7 +26,7 @@ extern void* fcram_temp;
 
 // 243
 // patch.c
-#define FCRAM_PATCHBIN_EXEC_LOC (FCRAM_START + FCRAM_SPACING * 4)
+#define FCRAM_PATCH_LOC (FCRAM_START + FCRAM_SPACING * 4)
 
 // 244
 // Throwaway temporary space. Don't expect it to stay sane.
diff --git a/source/interp.c b/source/interp.c
new file mode 100644 (file)
index 0000000..8031d42
--- /dev/null
@@ -0,0 +1,265 @@
+#include <stdint.h>
+#include "std/unused.h"
+#include "std/memory.h"
+#include "firm/firm.h"
+#include "config.h"
+#include "common.h"
+
+#define OP_NOP    0x00
+#define OP_REL    0x01
+#define OP_FIND   0x02
+#define OP_BACK   0x03
+#define OP_FWD    0x04
+#define OP_SET    0x05
+#define OP_TEST   0x06
+#define OP_JMP    0x07
+#define OP_REWIND 0x08
+#define OP_AND    0x09
+#define OP_TITLE  0x0A
+
+struct mode {
+       uint8_t* memory;
+       uint32_t size;
+};
+
+struct mode modes[19];
+int init_bytecode = 0;
+
+int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) {
+       if (!init_bytecode) {
+               modes[0].memory = (uint8_t*)firm_loc;
+               modes[0].size   = FCRAM_SPACING; // NATIVE_FIRM
+
+               modes[1].memory = (uint8_t*)agb_firm_loc;
+               modes[1].size   = FCRAM_SPACING; // AGB_FIRM
+
+               modes[2].memory = (uint8_t*)twl_firm_loc;
+               modes[2].size   = FCRAM_SPACING; // TWL_FIRM
+
+               // NATIVE_FIRM Process9 (This is also the default mode.)
+               modes[3].memory = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
+               modes[3].size   = firm_p9_exefs->fileHeaders[0].size;
+               // AGB_FIRM Process9
+               modes[4].memory = (uint8_t*)agb_firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
+               modes[4].size   = firm_p9_exefs->fileHeaders[0].size;
+               // TWL_FIRM Process9
+               modes[5].memory = (uint8_t*)twl_firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
+               modes[5].size   = firm_p9_exefs->fileHeaders[0].size;
+
+               // NATIVE_FIRM Sect 0
+               modes[6].memory = (uint8_t*)&firm_loc->section[0] + firm_loc->section[0].offset;
+               modes[6].size   = firm_loc->section[0].size;
+               // NATIVE_FIRM Sect 1
+               modes[7].memory = (uint8_t*)&firm_loc->section[1] + firm_loc->section[1].offset;
+               modes[7].size   = firm_loc->section[1].size;
+               // NATIVE_FIRM Sect 2
+               modes[8].memory = (uint8_t*)&firm_loc->section[2] + firm_loc->section[2].offset;
+               modes[8].size   = firm_loc->section[2].size;
+               // NATIVE_FIRM Sect 3
+               modes[9].memory = (uint8_t*)&firm_loc->section[3] + firm_loc->section[3].offset;
+               modes[9].size   = firm_loc->section[3].size;
+
+               // AGB_FIRM Sect 0
+               modes[10].memory = (uint8_t*)&agb_firm_loc->section[0] + agb_firm_loc->section[0].offset;
+               modes[10].size   = agb_firm_loc->section[0].size;
+               // AGB_FIRM Sect 1
+               modes[11].memory = (uint8_t*)&agb_firm_loc->section[1] + agb_firm_loc->section[1].offset;
+               modes[11].size   = agb_firm_loc->section[1].size;
+               // AGB_FIRM Sect 2
+               modes[12].memory = (uint8_t*)&agb_firm_loc->section[2] + agb_firm_loc->section[2].offset;
+               modes[12].size   = agb_firm_loc->section[2].size;
+               // AGB_FIRM Sect 3
+               modes[13].memory = (uint8_t*)&agb_firm_loc->section[3] + agb_firm_loc->section[3].offset;
+               modes[13].size   = agb_firm_loc->section[3].size;
+
+               // TWL_FIRM Sect 0
+               modes[14].memory = (uint8_t*)&twl_firm_loc->section[0] + twl_firm_loc->section[0].offset;
+               modes[14].size   = twl_firm_loc->section[0].size;
+               // TWL_FIRM Sect 1
+               modes[15].memory = (uint8_t*)&twl_firm_loc->section[1] + twl_firm_loc->section[1].offset;
+               modes[15].size   = twl_firm_loc->section[1].size;
+               // TWL_FIRM Sect 2
+               modes[16].memory = (uint8_t*)&twl_firm_loc->section[2] + twl_firm_loc->section[2].offset;
+               modes[16].size   = twl_firm_loc->section[2].size;
+               // TWL_FIRM Sect 3
+               modes[17].memory = (uint8_t*)&twl_firm_loc->section[3] + twl_firm_loc->section[3].offset;
+               modes[17].size   = twl_firm_loc->section[3].size;
+
+               // Loader (not valid in bootmode)
+               // modes[18] = { 0, 0 };
+
+               init_bytecode = 1;
+       }
+
+       struct   mode* current_mode = &modes[3];
+       uint32_t offset = 0;
+       uint8_t  test_was_false = 0;
+
+       uint32_t set_mode = 0;
+
+       uint32_t i;
+
+       uint8_t* code = bytecode;
+       uint8_t* end = code + len;
+       while (code < end && code >= bytecode) {
+               switch(*code) {
+                       case OP_NOP:
+                               if (debug)
+                                       fprintf(stderr, "nop\n");
+                               code++;
+                               test_was_false = 0;
+                               break;
+                       case OP_REL: // Change relativity.
+                               if (debug)
+                                       fprintf(stderr, "rel\n");
+                               code++;
+                               if (!test_was_false)
+                                       current_mode = &modes[*code];
+                               else
+                                       test_was_false = 0;
+                               set_mode = *code;
+                               code++;
+                               break;
+                       case OP_FIND: // Find pattern.
+                               if (debug)
+                                       fprintf(stderr, "find\n");
+                               code += 2;
+                               if (!test_was_false) {
+                                       offset = (uint32_t)memfind(current_mode->memory+offset, current_mode->size - offset, code, *(code-1));
+                                       if ((uint8_t*)offset == NULL) {
+                                               // Error. Abort.
+                                               abort("Find opcode failed.\n");
+                                       } else if (debug) {
+                                               fprintf(stderr, "Match @ %x\n", offset);
+                                       }
+                                       offset = offset - (uint32_t)current_mode->memory;
+                               } else {
+                                       test_was_false = 0;
+                               }
+                               code += *(code-1);
+                               break;
+                       case OP_BACK:
+                               if (debug)
+                                       fprintf(stderr, "back\n");
+                               code++;
+                               if (!test_was_false) {
+                                       if (offset < *code) {
+                                               // Went out of bounds. Error.
+                                               abort("Back underflowed.\n");
+                                       }
+                                       offset -= *code;
+                               } else {
+                                       test_was_false = 0;
+                               }
+                               code++;
+                               break;
+                       case OP_FWD:
+                               if (debug)
+                                       fprintf(stderr, "fwd\n");
+                               code++;
+                               if (!test_was_false) {
+                                       offset += *code;
+                                       if (offset >= current_mode->size) {
+                                               // Went out of bounds. Error.
+                                               abort("Fwd overflowed.\n");
+                                       }
+                               } else {
+                                       test_was_false = 0;
+                               }
+                               code++;
+                               break;
+                       case OP_SET: // Set data.
+                               if (debug)
+                                       fprintf(stderr, "set\n");
+                               code += 2;
+                               if (!test_was_false)
+                                       memcpy(current_mode->memory+offset, code, *(code-1));
+                               else
+                                       test_was_false = 0;
+                               offset += *(code-1);
+                               code   += *(code-1);
+                               break;
+                       case OP_TEST: // Test data.
+                               if (debug)
+                                       fprintf(stderr, "test\n");
+                               code += 2;
+                               if(memcmp(current_mode->memory+offset, code, *(code-1))) {
+                                       test_was_false = 1;
+                               }
+                               offset += *(code-1);
+                               code   += *(code-1);
+                               break;
+                       case OP_JMP: // Jump to offset.
+                               if (debug)
+                                       fprintf(stderr, "jmp\n");
+                               code++;
+                               if (!test_was_false)
+                                       code = bytecode + *((uint16_t*)code);
+                               else
+                                       test_was_false = 0;
+                               break;
+                       case OP_REWIND:
+                               if (debug)
+                                       fprintf(stderr, "rewind\n");
+                               code++;
+                               if (!test_was_false)
+                                       offset = 0;
+                               else
+                                       test_was_false = 0;
+                               break;
+                       case OP_AND:
+                               if (debug)
+                                       fprintf(stderr, "and\n");
+                               code += 2;
+                               if (!test_was_false) {
+                                       for(i=0; i < *(code-1); i++) {
+                                               *(current_mode->memory + offset) &= code[i];
+                                       }
+                                       offset += *(code-1);
+                               } else {
+                                       test_was_false = 0;
+                               }
+                               code   += *(code-1);
+                               break;
+                       case OP_TITLE:
+                               if (debug)
+                                       fprintf(stderr, "title\n");
+                               // FIXME - NYI
+                       default:
+                               // Panic; not proper opcode.
+                               fprintf(stderr, "Invalid opcode. State:\n"
+                                                               "  Relative:  %u\n"
+                                                               "    Actual:  %x:%u\n"
+                                                               "  Memory:    %x\n"
+                                                               "    Actual:  %x\n"
+                                                               "  Code Loc:  %x\n"
+                                                               "    Actual:  %x\n"
+                                                               "  Opcode:    %u\n",
+                                                               set_mode,
+                                                               current_mode->memory, current_mode->size,
+                                                               offset,
+                                                               current_mode->memory + offset,
+                                                               code - bytecode,
+                                                               code,
+                                                               *code);
+                               abort("Halting startup.\n");
+                               break;
+               }
+       }
+
+       return 0;
+}
+
+int execb(char* filename) {
+       FILE* f = fopen(filename, "r");
+       size_t len = fsize(f);
+       fread((uint8_t*)FCRAM_PATCH_LOC, 1, len, f);
+       fclose(f);
+
+       struct system_patch* patch = (struct system_patch*)FCRAM_PATCH_LOC;
+       fprintf(stderr, "Name: %s\nDesc: %s\n", patch->name, patch->desc);
+       uint8_t* patch_mem = (uint8_t*)patch + sizeof(struct system_patch) + (patch->depends * 8) + (patch->titles * 8);
+       uint32_t patch_len = patch->size;
+
+       return exec_bytecode(patch_mem, patch_len, 1);
+}
diff --git a/source/interp.h b/source/interp.h
new file mode 100644 (file)
index 0000000..9f33612
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __INTERP_H
+#define __INTERP_H
+
+uint8_t* execb(char* filename);
+int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug);
+
+#endif
index 81c1fa81aca2e70af6cf29954e6e8764678e5683..5772e83fff44e48e319453ad727fdaf57152c331 100644 (file)
@@ -14,6 +14,7 @@
 #include "../firm/fcram.h"
 #include "../config.h"
 #include "../common.h"
+#include "../interp.h"
 
 exefs_h* get_firm_proc9_exefs();
 exefs_h* get_twl_proc9_exefs();
index 66bbe7e2bac1880dc40915f3527ddf58828d722e..fda935c3d03a18b2acc9a8d40e14066b4a7dccc2 100644 (file)
@@ -15,7 +15,7 @@ extern exefs_h* firm_p9_exefs;
 
 PATCH(signatures)
 {
-
+/*
     // Look for signature checks
 
     uint8_t pat1[] = { 0xC0, 0x1C, 0x76, 0xE7 };
@@ -52,6 +52,8 @@ PATCH(signatures)
     memcpy(off2, sigpatch, 4);
 
     fprintf(stderr, "Signature patch succeded.\n");
+*/
+       execb(PATH_PATCHES "/sig.vco");
 
     return 0;
 }
index 3f83e7815df7ab5c55ebe6447607baa5b0cca24a..9c9186426bdedd3209caa46a5c625541ad9917f4 100644 (file)
     "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up
                          // paths.
 
+#define PATCH_FLAG_REQUIRE (1 << 0) // Force enable patch unless 'Unsafe Options' is checked.
+#define PATCH_FLAG_DEVMODE (1 << 1) // Require 'Developer Options' to be checked.
+#define PATCH_FLAG_NOABORT (1 << 2) // Don't abort on error.
+
 // Structure of a patch file.
 struct system_patch
 {
     char     magic[4];     // "AIDA" for shits and giggles and because we like .hack.
-    uint32_t version;      // Version of the patch itself.
+    uint8_t  version;      // Version of the patch itself.
 
     char     name[64];     // User-readable name for patch in menu.
     char     desc[256];    // User-readable description for patch in menu.
     uint64_t uuid;         // Unique ID for patch. Each unique patch should provide
                            // a unique ID.
 
-    uint8_t  flags;        // Extra flags for patch.
-
-       #define PATCH_FLAG_REQUIRE (1 << 0) // Force enable patch unless 'Unsafe Options' is checked.
-       #define PATCH_FLAG_DEVMODE (1 << 1) // Require 'Developer Options' to be checked.
-       #define PATCH_FLAG_NOABORT (1 << 2) // Don't abort on error.
+    uint32_t flags;       // Extra flags for patch.
 
-    uint32_t titles;       // What title this patch is intended for. Certain values are
-                           // specially handled.
+    uint32_t titles;       // How many titles this patch should be applied to (listed later)
 
     uint32_t depends;      // How many deps there are.
 
index 8140563c9c61e032116b2cccb4c13c756ff37ac9..6b74d4c7f6c0a68d8f70baf1572bcc941a222515 100644 (file)
@@ -3,12 +3,14 @@
 
 #include "draw.h"
 
+int menu_poweroff();
+uint32_t wait_key();
+
 #define abort(x...)                                                            \
     {                                                                          \
-        fprintf(stderr, x);                                                    \
-        fumount();                                                             \
-        while (1)                                                              \
-            ;                                                                  \
+        fprintf(stderr, x);                                      \
+               wait_key(); \
+               menu_poweroff(); \
     }
 
 #endif
index 4828f235f91fcdc94672105770e3836ad243a718..14a09f634980c7d29ba6e114569524e07d88b4b0 100644 (file)
@@ -223,6 +223,8 @@ putc(void* buf, const int c)
             memset(&colorbuf[(height - 1) * width], 0, width);
 
             clear_disp(buf); // Clear screen.
+
+            cursor_y[0]--;
 #else
                        clear_disp(buf);
                        cursor_x[0] = 0;
@@ -233,7 +235,6 @@ putc(void* buf, const int c)
                                memmove(&screen[x * col + one_c], &screen[x * col + one_c], col - one_c);
                        } */
 #endif
-            cursor_y[0]--;
         }
 
         switch (c) {