]> Chaos Git - corbenik/corbenik.git/commitdiff
stdlib work
authorchaoskagami <chaos.kagami@gmail.com>
Thu, 28 Apr 2016 19:53:16 +0000 (15:53 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Thu, 28 Apr 2016 19:53:16 +0000 (15:53 -0400)
15 files changed:
Makefile
doc/CODE_ORIGIN.md [new file with mode: 0644]
doc/STDLIB.md [new file with mode: 0644]
linker.ld
source/common.h
source/config.c
source/firm/firm.c
source/i2c.c
source/i2c.h
source/main.c
source/std/abort.h [new file with mode: 0644]
source/std/draw.c
source/std/draw.h
source/std/fs.c
source/std/fs.h

index f0a71963a84cf4f54f5dbd6167c9288ba0e5311b..2579ad1ab272bec02cac37caaa1dff64a5d93a39 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,9 +17,9 @@ dir_out    := out
 REVISION := $(shell git rev-list --count HEAD)
 
 ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
-CFLAGS  := -Wall -Wextra -MMD -MP -O2 -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -DVERSION=\"r$(REVISION)\"
-FLAGS   := dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) --no-print-directory
-LDFLAGS := -nostdlib -lgcc
+CFLAGS  := -Wall -Wextra -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"r$(REVISION)\"
+FLAGS   := dir_out=$(abspath $(dir_out)) --no-print-directory
+LDFLAGS := -nostdlib -Wl,-z,defs -lgcc
 
 objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
                          $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
diff --git a/doc/CODE_ORIGIN.md b/doc/CODE_ORIGIN.md
new file mode 100644 (file)
index 0000000..0aa1c28
--- /dev/null
@@ -0,0 +1,5 @@
+While most everything in this repo is original, some parts are derived from existing software, and I make the best effort to document what is derivative in the interest of giving proper credits:
+
+src/firm  - Firmware decryptor originally from CakesFW (http://github.com/mid-kid/CakesForeveryWan)
+src/fatfs - FatFS - http://elm-chan.org/fsw/ff/00index_e.html . This version originates from Decrypt9's repo.
+src/std   - Work was originally based on memfuncs.c and memory.c from Cakes and ReiNand, but contains near none of the original code now.
diff --git a/doc/STDLIB.md b/doc/STDLIB.md
new file mode 100644 (file)
index 0000000..f8197d3
--- /dev/null
@@ -0,0 +1,16 @@
+The stdlib/ directory is a self-contained, mostly conformant implementation of the C Standard Library for 3DS in ARM9 code. It supports a good chunk of standard functions and interfaces which follow:
+
+FILE* fopen(const char* name, const char* mode)
+
+   Opens a file @name@ with access mode @mode@ and returns an opaque FILE pointer.
+
+size_t fread(void* buf, size_t size, size_t elem, FILE* handle)
+
+   Reads @elem@ elements of size @size@ from the file @handle@, storing read data to @buf@.
+
+size_t fread(void* buf, size_t size, size_t elem, FILE* handle)
+
+   Writes @elem@ elements of size @size@ to the file @handle@, reading data to write from @buf@.
+
+void fseek(FILE* file, );
+
index d57403dfe717b03c1db48ae338f6769d91bf2e59..51bd05472562dc27b9c706094c17cf7afa05303d 100644 (file)
--- a/linker.ld
+++ b/linker.ld
@@ -1,11 +1,53 @@
+/* This memory map is mainly to assist in doing stuff in code.
+MEMORY
+{
+    INSTRUCTION_TCM  (rw)   : ORIGIN = 0x00000000, LENGTH = 0x08000000
+    ARM_INTERNAL     (rw)  : ORIGIN = 0x08000000, LENGTH = 0x00100000
+    NEW_INTERNAL     (rw)  : ORIGIN = 0x08100000, LENGTH = 0x00080000
+    IO_MEMORY        (rw)  : ORIGIN = 0x10000000, LENGTH = 0x08000000
+    VRAM             (rw)  : ORIGIN = 0x18000000, LENGTH = 0x00600000
+    DSP_MEMORY       (rw)  : ORIGIN = 0x1FF00000, LENGTH = 0x00080000
+    AXI_WRAM         (rw)  : ORIGIN = 0x1FF80000, LENGTH = 0x00080000
+    FCRAM            (rwx) : ORIGIN = 0x20000000, LENGTH = 0x08000000
+    NEW_FCRAM        (rwx) : ORIGIN = 0x28000000, LENGTH = 0x08000000
+    DATA_TCM         (rw)  : ORIGIN = 0xFFF00000, LENGTH = 0x00004000
+    BOOTROM          (rw)   : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000
+} */
+
 ENTRY(_start)
 SECTIONS
 {
     . = 0x23F00000;
-    .text.start : { *(.text.start) }
-    .text : { *(.text) }
-    .data : { *(.data) }
-    .bss : { *(.bss COMMON) }
-    .rodata : { *(.rodata) }
+
+    START_SECTION = .;
+      .text.start : {
+          *(.text.start)
+      }
+    START_SECTION_END = .;
+
+    TEXT_SECTION = .;
+      .text : {
+          *(.text)
+      }
+    TEXT_SECTION_END = .;
+
+    DATA_SECTION = .;
+      .data : {
+          *(.data)
+      }
+    DATA_SECTION_END = .;
+
+    BSS_SECTION = .;
+      .bss : {
+          *(.bss COMMON)
+      }
+    BSS_SECTION_END = .;
+
+    RODATA_SECTION = .;
+      .rodata : {
+          *(.rodata)
+      }
+    RODATA_SECTION_END = .;
+
     . = ALIGN(4);
 }
index 7f41f50e9722a1f8db1ed8895b43c7e5b428a1a8..f58b083b5f7c595ba3e45ad370430f25ba45afa2 100644 (file)
@@ -6,6 +6,7 @@
 #include "std/font.h"
 #include "std/fs.h"
 #include "std/memory.h"
+#include "std/abort.h"
 
 #include "firm/fcram.h"
 #include "firm/crypto.h"
index 161d77b7e2d7f3b9a15a1f451a0849c9e8edb445..d4e8eaaca6f9dd22f37ed40e30bda6d2a3d1a7b1 100644 (file)
@@ -1,6 +1,6 @@
 #include "common.h"
 
-FILE conf_handle;
+FILE* conf_handle;
 
 void regenerate_config() {
        f_mkdir(PATH_CFW);
@@ -11,33 +11,35 @@ void regenerate_config() {
     f_mkdir(PATH_KEYS);
     f_mkdir(PATH_EXEFS);
 
-    cprintf(BOTTOM_SCREEN, "Created directory structure.\n");
+    fprintf(BOTTOM_SCREEN, "Created directory structure.\n");
 
     memset(&config, 0, sizeof(config));
     memcpy(&(config.magic), CONFIG_MAGIC, 4);
     config.config_ver = config_version;
 
-    fopen(&conf_handle, PATH_CONFIG, "w");
-    fwrite(&config, 1, sizeof(config), &conf_handle);
-    fclose(&conf_handle);
+    if(!(conf_handle = fopen(PATH_CONFIG, "w")))
+        abort("Failed to open config for write?\n");
 
-    cprintf(BOTTOM_SCREEN, "Config file written.\n");
+    fwrite(&config, 1, sizeof(config), conf_handle);
+    fclose(conf_handle);
+
+    fprintf(BOTTOM_SCREEN, "Config file written.\n");
 }
 
 void load_config() {
     // Zero on success.
-    if (fopen(&conf_handle, PATH_CONFIG, "r")) {
-        cprintf(BOTTOM_SCREEN, "Config file is missing:\n"
+    if (!(conf_handle = fopen(PATH_CONFIG, "r"))) {
+        fprintf(BOTTOM_SCREEN, "Config file is missing:\n"
                                "  %s\n"
                                "Will create it with defaults.\n",
                                PATH_CONFIG);
         regenerate_config();
     } else {
-        fread(&config, 1, sizeof(config), &conf_handle);
-        fclose(&conf_handle);
+        fread(&config, 1, sizeof(config), conf_handle);
+        fclose(conf_handle);
 
         if (memcmp(&(config.magic), CONFIG_MAGIC, 4)) {
-            cprintf(BOTTOM_SCREEN, "Config file at:\n"
+            fprintf(BOTTOM_SCREEN, "Config file at:\n"
                                    "  %s\n"
                                    "has incorrect magic:\n"
                                    "  '%c%c%c%c'\n"
@@ -49,7 +51,7 @@ void load_config() {
         }
 
         if (config.config_ver < config_version) {
-            cprintf(BOTTOM_SCREEN, "Config file has outdated version:\n"
+            fprintf(BOTTOM_SCREEN, "Config file has outdated version:\n"
                                    "  %s\n"
                                    "Regenerating with defaults.\n",
                                    PATH_CONFIG);
@@ -58,6 +60,6 @@ void load_config() {
         }
     }
 
-    cprintf(BOTTOM_SCREEN, "Config file loaded.\n");
+    fprintf(BOTTOM_SCREEN, "Config file loaded.\n");
 }
 
index 2f885d8b2e764a00a9ef8bc54c2f207e71f3c1ec..622e8d4857e98207b3e27f0ba5e2cc8ec662e64a 100644 (file)
@@ -26,13 +26,14 @@ void slot0x11key96_init()
     uint8_t key[AES_BLOCK_SIZE];
     if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) ||
         read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE)) {
-        // If we can't read the key, we assume it's not needed, and the firmware is the right version.
-        // Otherwise, we make sure the error message for decrypting arm9bin mentions this.
+        // Read key successfully.
         aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
 
         // Tell boot_firm it needs to regenerate the keys.
         update_96_keys = 1;
     }
+    // If we can't read the key, we assume it's not needed, and the firmware is the right version.
+    // Otherwise, we make sure the error message for decrypting arm9bin mentions this.
 }
 
 int decrypt_cetk_key(void *key, const void *cetk)
@@ -59,7 +60,7 @@ int decrypt_cetk_key(void *key, const void *cetk)
                 // At i, there's 7 keys with 4 bytes padding between them.
                 // We only need the 2nd.
                 memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y));
-                cprintf(BOTTOM_SCREEN, "Found the common key Y\n");
+                fprintf(BOTTOM_SCREEN, "Found the common key Y\n");
 
                 break;
             }
@@ -74,7 +75,7 @@ int decrypt_cetk_key(void *key, const void *cetk)
 
     memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
 
-    cprintf(BOTTOM_SCREEN, "Decrypting key\n");
+    fprintf(BOTTOM_SCREEN, "Decrypting key\n");
     memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
     aes(key, key, 1, iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
 
@@ -87,7 +88,7 @@ int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
     uint8_t exefs_key[16] = {0};
     uint8_t exefs_iv[16] = {0};
 
-    cprintf(BOTTOM_SCREEN, "Decrypting the NCCH\n");
+    fprintf(BOTTOM_SCREEN, "Decrypting the NCCH\n");
     aes_setkey(0x16, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
     aes_use_keyslot(0x16);
     aes(ncch, ncch, *size / AES_BLOCK_SIZE, firm_iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
@@ -102,7 +103,7 @@ int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
     exefs_h *exefs = (exefs_h *)((void *)ncch + ncch->exeFSOffset * MEDIA_UNITS);
     uint32_t exefs_size = ncch->exeFSSize * MEDIA_UNITS;
 
-    cprintf(BOTTOM_SCREEN, "Decrypting the exefs\n");
+    fprintf(BOTTOM_SCREEN, "Decrypting the exefs\n");
     aes_setkey(0x2C, exefs_key, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
     aes_use_keyslot(0x2C);
     aes(exefs, exefs, exefs_size / AES_BLOCK_SIZE, exefs_iv, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
@@ -123,7 +124,7 @@ int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
 int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title) {
     uint8_t slot = 0x15;
 
-    cprintf(BOTTOM_SCREEN, "Decrypting ARM9 FIRM binary\n");
+    fprintf(BOTTOM_SCREEN, "Decrypting ARM9 FIRM binary\n");
 
 //    if (firm_title == NATIVE_FIRM_TITLEID && version > 0x0F) {
     if (firm_title == NATIVE_FIRM_TITLEID) {
@@ -158,28 +159,28 @@ int decrypt_firm(firm_h *dest, char *path_firmkey, char *path_cetk, uint32_t *si
 
     // Firmware is likely encrypted. Decrypt.
     if (!read_file(firm_key, path_firmkey, AES_BLOCK_SIZE)) {
-        cprintf(BOTTOM_SCREEN, "Failed to load FIRM key,\n"
+        fprintf(BOTTOM_SCREEN, "Failed to load FIRM key,\n"
                                "  Attempting to generate with CETK.\n");
 
         if (!read_file(fcram_temp, path_cetk, FCRAM_SPACING)) {
-            cprintf(BOTTOM_SCREEN, "Failed to load CETK\n");
+            fprintf(BOTTOM_SCREEN, "Failed to load CETK\n");
             return 1;
         }
-        cprintf(BOTTOM_SCREEN, "Loaded CETK\n");
+        fprintf(BOTTOM_SCREEN, "Loaded CETK\n");
 
         if (decrypt_cetk_key(firm_key, fcram_temp) != 0) {
-            cprintf(BOTTOM_SCREEN, "Failed to decrypt the CETK\n");
+            fprintf(BOTTOM_SCREEN, "Failed to decrypt the CETK\n");
             return 1;
         }
-        cprintf(BOTTOM_SCREEN, "Saving FIRM key for future use\n");
+        fprintf(BOTTOM_SCREEN, "Saving FIRM key for future use\n");
         write_file(firm_key, path_firmkey, AES_BLOCK_SIZE);
     } else {
-        cprintf(BOTTOM_SCREEN, "Loaded FIRM key\n");
+        fprintf(BOTTOM_SCREEN, "Loaded FIRM key\n");
     }
 
-    cprintf(BOTTOM_SCREEN, "Decrypting FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Decrypting FIRM\n");
     if (decrypt_firm_title(dest, (void *)dest, size, firm_key) != 0) {
-        cprintf(BOTTOM_SCREEN, "Failed to decrypt the firmware\n");
+        fprintf(BOTTOM_SCREEN, "Failed to decrypt the firmware\n");
         return 1;
     }
        return 0;
@@ -190,11 +191,11 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uin
     int firmware_changed = 0;
 
     if (read_file(dest, path, *size)) {
-        cprintf(BOTTOM_SCREEN, "Failed to read FIRM from SD\n");
+        fprintf(BOTTOM_SCREEN, "Failed to read FIRM from SD\n");
 
         // Only whine about this if it's NATIVE_FIRM, which is important.
         if (firm_title == NATIVE_FIRM_TITLEID) {
-            cprintf(BOTTOM_SCREEN, "Failed to load NATIVE_FIRM from:\n"
+            fprintf(BOTTOM_SCREEN, "Failed to load NATIVE_FIRM from:\n"
                                    "  " PATH_NATIVE_F "\n"
                                    "This is fatal. Aborting.\n");
         }
@@ -208,14 +209,14 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uin
         status = decrypt_firm(dest, path_firmkey, path_cetk, size, firm_title);
         if (status != 0) {
             if (firm_title == NATIVE_FIRM_TITLEID) {
-                cprintf(BOTTOM_SCREEN, "Failed to decrypt firmware.\n"
+                fprintf(BOTTOM_SCREEN, "Failed to decrypt firmware.\n"
                                        "This is fatal. Aborting.\n");
             }
             goto exit_error;
         }
         firmware_changed = 1; // Decryption performed.
     } else {
-        cprintf(BOTTOM_SCREEN, "FIRM not encrypted\n");
+        fprintf(BOTTOM_SCREEN, "FIRM not encrypted\n");
     }
 
     // The N3DS firm has an additional encryption layer for ARM9
@@ -236,7 +237,7 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uin
                 if (arm9bin_iscrypt) {
                     // Decrypt the arm9bin.
                     if (decrypt_arm9bin((arm9bin_h *)((uintptr_t)dest + section->offset), firm_title)) {
-                        cprintf(BOTTOM_SCREEN, "Couldn't decrypt ARM9 FIRM binary.\n"
+                        fprintf(BOTTOM_SCREEN, "Couldn't decrypt ARM9 FIRM binary.\n"
                                                "Check if you have the needed key at:\n"
                                                "  " PATH_SLOT0X11KEY96 "\n");
                         status = 1;
@@ -244,7 +245,7 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uin
                     }
                     firmware_changed = 1; // Decryption of arm9bin performed.
                 } else {
-                    cprintf(BOTTOM_SCREEN, "ARM9 FIRM binary not encrypted\n");
+                    fprintf(BOTTOM_SCREEN, "ARM9 FIRM binary not encrypted\n");
 //                    if (firm_type == NATIVE_FIRM && firm_current->version > 0x0F) {
                         slot0x11key96_init(); // This has to be loaded regardless, otherwise boot will fail.
 //                    }
@@ -258,13 +259,13 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uin
 
     // Save firmware.bin if decryption was done.
     if (firmware_changed) {
-        cprintf(BOTTOM_SCREEN, "Saving decrypted FIRM\n");
+        fprintf(BOTTOM_SCREEN, "Saving decrypted FIRM\n");
         write_file(dest, path, *size);
     }
 
     //if (firm_current->console == console_n3ds)
     {
-        cprintf(BOTTOM_SCREEN, "Fixing arm9 entrypoint\n");
+        fprintf(BOTTOM_SCREEN, "Fixing arm9 entrypoint\n");
 
         // Patch the entrypoint to skip arm9loader
         if (firm_title == NATIVE_FIRM_TITLEID) {
@@ -310,7 +311,7 @@ void boot_firm() {
             *(uint8_t *)(keydata + 0xF) += 1;
         }
 
-        cprintf(BOTTOM_SCREEN, "Updated keyX keyslots\n");
+        fprintf(BOTTOM_SCREEN, "Updated keyX keyslots\n");
     }
 
     struct memory_header *memory = (void *)(memory_loc + 1);
@@ -318,43 +319,43 @@ void boot_firm() {
         memcpy((void *)memory->location, memory + 1, memory->size);
         memory = (void *)((uintptr_t)(memory + 1) + memory->size);
     }
-    cprintf(BOTTOM_SCREEN, "Copied memory\n");
+    fprintf(BOTTOM_SCREEN, "Copied memory\n");
 
     for (firm_section_h *section = firm_loc->section;
             section < firm_loc->section + 4 && section->address != 0; section++) {
         memcpy((void *)section->address, (void *)firm_loc + section->offset, section->size);
     }
-    cprintf(BOTTOM_SCREEN, "Copied FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Copied FIRM\n");
 
     *a11_entry = (uint32_t)disable_lcds;
     while (*a11_entry);  // Make sure it jumped there correctly before changing it.
     *a11_entry = (uint32_t)firm_loc->a11Entry;
 
-    cprintf(BOTTOM_SCREEN, "Prepared arm11 entry, jumping to FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Prepared arm11 entry, jumping to FIRM\n");
 
     ((void (*)())firm_loc->a9Entry)();
 }
 
 int load_firms() {
-    cprintf(TOP_SCREEN, "[Loading FIRM]");
+    fprintf(TOP_SCREEN, "[Loading FIRM]");
 
-    cprintf(BOTTOM_SCREEN, "Loading NATIVE_FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Loading NATIVE_FIRM\n");
     if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, PATH_NATIVE_CETK, &firm_size, NATIVE_FIRM_TITLEID) != 0)
         return 1;
 
-    cprintf(BOTTOM_SCREEN, "Loading TWL_FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Loading TWL_FIRM\n");
     if(load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, PATH_TWL_CETK, &twl_firm_size, TWL_FIRM_TITLEID))
-        cprintf(BOTTOM_SCREEN, "TWL_FIRM failed to load.\n");
+        fprintf(BOTTOM_SCREEN, "TWL_FIRM failed to load.\n");
 
-    cprintf(BOTTOM_SCREEN, "Loading AGB_FIRM\n");
+    fprintf(BOTTOM_SCREEN, "Loading AGB_FIRM\n");
     if(load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, PATH_AGB_CETK, &agb_firm_size, AGB_FIRM_TITLEID))
-        cprintf(BOTTOM_SCREEN, "AGB_FIRM failed to load.\n");
+        fprintf(BOTTOM_SCREEN, "AGB_FIRM failed to load.\n");
 
     return 0;
 }
 
 void boot_cfw() {
-    cprintf(TOP_SCREEN, "[Patching]");
+    fprintf(TOP_SCREEN, "[Patching]");
 //    if (patch_firm_all() != 0)
 //        return;
 
@@ -362,34 +363,34 @@ void boot_cfw() {
     //   and either the patches have been modified, or the file doesn't exist.
     if ((save_firm || config.options[OPTION_AUTOBOOT]) &&
             f_stat(PATH_NATIVE_P, NULL) != 0) {
-        cprintf(BOTTOM_SCREEN, "Saving patched NATIVE_FIRM\n");
+        fprintf(BOTTOM_SCREEN, "Saving patched NATIVE_FIRM\n");
         if (write_file(firm_loc, PATH_NATIVE_P, firm_size) != firm_size) {
-            cprintf(BOTTOM_SCREEN, "%pFailed to save patched FIRM.\nWriting SD failed.\nThis is fatal.\n", COLOR(RED, BLACK));
+            fprintf(BOTTOM_SCREEN, "%pFailed to save patched FIRM.\nWriting SD failed.\nThis is fatal.\n", COLOR(RED, BLACK));
             return;
         }
     }
 
     if ((save_firm || config.options[OPTION_AUTOBOOT]) &&
             f_stat(PATH_MEMBIN, NULL) != 0) {
-        cprintf(BOTTOM_SCREEN, "Saving patched memory\n");
+        fprintf(BOTTOM_SCREEN, "Saving patched memory\n");
         if (write_file(memory_loc, PATH_MEMBIN, *memory_loc) != *memory_loc) {
-            cprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
+            fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
             return;
         }
     }
 
     if (f_stat(PATH_TWL_P, NULL) != 0) {
-        cprintf(BOTTOM_SCREEN, "Saving patched TWL_FIRM\n");
+        fprintf(BOTTOM_SCREEN, "Saving patched TWL_FIRM\n");
         if (write_file(twl_firm_loc, PATH_TWL_P, twl_firm_size) != twl_firm_size) {
-            cprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
+            fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
             return;
         }
     }
 
     if (f_stat(PATH_AGB_P, NULL) != 0) {
-        cprintf(BOTTOM_SCREEN, "Saving patched AGB_FIRM\n");
+        fprintf(BOTTOM_SCREEN, "Saving patched AGB_FIRM\n");
         if (write_file(agb_firm_loc, PATH_AGB_P, agb_firm_size) != agb_firm_size) {
-            cprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
+            fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK));
             return;
         }
     }
index fcaab9cfd835098b4b1d413471af71e709f797b2..2053fbb1b6d594684bcbbb1b2407732426a3825b 100644 (file)
@@ -2,7 +2,7 @@
 
 //-----------------------------------------------------------------------------
 
-static const struct { uint8_t bus_id, reg_addr } dev_data[] = {
+static const struct { uint8_t bus_id, reg_addr; } dev_data[] = {
     {0, 0x4A}, {0, 0x7A}, {0, 0x78},
     {1, 0x4A}, {1, 0x78}, {1, 0x2C},
     {1, 0x2E}, {1, 0x40}, {1, 0x44},
@@ -10,11 +10,11 @@ static const struct { uint8_t bus_id, reg_addr } dev_data[] = {
     {2, 0xA4}, {2, 0x9A}, {2, 0xA0},
 };
 
-const uint8_t i2cGetDeviceBusId(uint8_t device_id) {
+uint8_t i2cGetDeviceBusId(uint8_t device_id) {
     return dev_data[device_id].bus_id;
 }
 
-const uint8_t i2cGetDeviceRegAddr(uint8_t device_id) {
+uint8_t i2cGetDeviceRegAddr(uint8_t device_id) {
     return dev_data[device_id].reg_addr;
 }
 
@@ -26,7 +26,7 @@ static volatile uint8_t* const reg_data_addrs[] = {
     (volatile uint8_t*)(I2C3_REG_OFF + I2C_REG_DATA),
 };
 
-volatile uint8_t* const i2cGetDataReg(uint8_t bus_id) {
+volatile uint8_t* i2cGetDataReg(uint8_t bus_id) {
     return reg_data_addrs[bus_id];
 }
 
@@ -38,13 +38,13 @@ static volatile uint8_t* const reg_cnt_addrs[] = {
     (volatile uint8_t*)(I2C3_REG_OFF + I2C_REG_CNT),
 };
 
-volatile uint8_t* const i2cGetCntReg(uint8_t bus_id) {
+volatile uint8_t* i2cGetCntReg(uint8_t bus_id) {
     return reg_cnt_addrs[bus_id];
 }
 
 //-----------------------------------------------------------------------------
 
-int i2cWaitBusy(uint8_t bus_id) {
+void i2cWaitBusy(uint8_t bus_id) {
     while (*i2cGetCntReg(bus_id) & 0x80);
 }
 
index 8620e4ca351b72e5f706e41e98eb60eabe9e646d..ebde4ace88d0ae147370f8761366be509d614586 100644 (file)
 #define I2C_DEV_GYRO 10
 #define I2C_DEV_IR   13
 
-const uint8_t i2cGetDeviceBusId(uint8_t device_id);
-const uint8_t i2cGetDeviceRegAddr(uint8_t device_id);
+uint8_t i2cGetDeviceBusId(uint8_t device_id);
+uint8_t i2cGetDeviceRegAddr(uint8_t device_id);
 
-volatile uint8_t* const i2cGetDataReg(uint8_t bus_id);
-volatile uint8_t* const i2cGetCntReg(uint8_t bus_id);
+volatile uint8_t* i2cGetDataReg(uint8_t bus_id);
+volatile uint8_t* i2cGetCntReg(uint8_t bus_id);
 
-int i2cWaitBusy(uint8_t bus_id);
+void i2cWaitBusy(uint8_t bus_id);
 int i2cGetResult(uint8_t bus_id);
 uint8_t i2cGetData(uint8_t bus_id);
 void i2cStop(uint8_t bus_id, uint8_t arg0);
index 7239aa3575268a5e510e6b14f108d52613110360..7d97e53eb6b1634d288f2ceb3a3253dedaa709cb 100644 (file)
@@ -32,7 +32,7 @@ uint32_t wait_key() {
 }
 
 void header() {
-    cprintf(TOP_SCREEN, "%p[Corbenik - The Rebirth - %s]\n", COLOR(CYAN, BLACK), VERSION);
+    fprintf(stdout, "\x1b[33;40m[.corbenik//%s]\n", VERSION);
 }
 
 int menu_options() { return MENU_MAIN; }
@@ -46,7 +46,7 @@ int menu_help() {
 
     header();
 
-    cprintf(TOP_SCREEN, "Corbenik is a 3DS firmware patcher\n"
+    fprintf(stdout,     "Corbenik is a 3DS firmware patcher\n"
                         "  commonly known as a CFW. It seeks to address\n"
                         "  some faults in other CFWs and is generally\n"
                         "  just another choice for users - but primarily\n"
@@ -78,15 +78,19 @@ int menu_help() {
 }
 
 int menu_reset() {
+    fumount(); // Unmount SD.
+
     // Reboot.
-    cprintf(BOTTOM_SCREEN, "Resetting system.\n");
+    fprintf(BOTTOM_SCREEN, "Resetting system.\n");
     i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
     while(1);
 }
 
 int menu_poweroff() {
+    fumount(); // Unmount SD.
+
     // Reboot.
-    cprintf(BOTTOM_SCREEN, "Powering off system.\n");
+    fprintf(BOTTOM_SCREEN, "Powering off system.\n");
     i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
     while(1);
 }
@@ -95,13 +99,13 @@ int menu_main() {
     set_cursor(TOP_SCREEN, 0, 0);
 
     const char *list[] = {
-        "Options",
-        "Patches",
-        "Info",
-        "Help/Readme",
-        "Reset",
-        "Power off",
-        "Boot firmware"
+        "Options   ",
+        "Patches   ",
+        "Info   ",
+        "Help/Readme   ",
+        "Reset   ",
+        "Power off   ",
+        "Boot firmware   "
     };
 
     header();
@@ -110,10 +114,10 @@ int menu_main() {
 
     for(int i=0; i < menu_max; i++) {
         if (cursor_y == i)
-            cprintf(TOP_SCREEN, "%p>> ", COLOR(GREEN, BLACK));
+            fprintf(TOP_SCREEN, "\x1b[42m>>   ");
         else
-            cprintf(TOP_SCREEN, "   ");
-        cprintf(TOP_SCREEN, "%s\n", list[i]);
+            fprintf(TOP_SCREEN, "   ");
+        fprintf(TOP_SCREEN, "%s\n", list[i]);
     }
 
     uint32_t key = wait_key();
@@ -177,9 +181,9 @@ int menu_handler() {
 void main() {
     if (fmount()) {
         // Failed to mount SD. Bomb out.
-        cprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK));
+        fprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK));
     } else {
-        cprintf(BOTTOM_SCREEN, "Mounted SD card.\n");
+        fprintf(BOTTOM_SCREEN, "Mounted SD card.\n");
     }
 
     load_config(); // Load configuration.
diff --git a/source/std/abort.h b/source/std/abort.h
new file mode 100644 (file)
index 0000000..b672e82
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __ABORT_H
+#define __ABORT_H
+
+#define abort(x...) { \
+  fprintf(2, x); \
+  fumount(); \
+  while(1); \
+}
+
+#endif
index 2883962546fc039ad883b946f24cd669435b749c..081916767fe21b3a23467d5579fb890085b5247e 100644 (file)
@@ -5,6 +5,8 @@
 #include <stdarg.h>
 #include "memory.h"
 #include "font.h"
+#include "../fatfs/ff.h"
+#include "fs.h"
 
 static unsigned int top_cursor_x = 0, top_cursor_y = 0;
 static unsigned int bottom_cursor_x = 0, bottom_cursor_y = 0;
@@ -38,9 +40,9 @@ void clear_screen(uint8_t* screen) {
        uint32_t size = 0;
        char* buffer  = 0;
        uint32_t buffer_size = 0;
-    if (screen == TOP_SCREEN)
+    if ((int)screen == TOP_SCREEN)
         screen = framebuffers->top_left;
-    else if (screen == BOTTOM_SCREEN)
+    else if ((int)screen == BOTTOM_SCREEN)
         screen = framebuffers->bottom;
 
        if(screen == framebuffers->top_left ||
@@ -121,80 +123,83 @@ void draw_character(uint8_t* screen, const char character, const unsigned int bu
     }
 }
 
-void putc(int buf, unsigned char color, const int c) {
-       unsigned int width  = 0;
-       unsigned int height = 0;
-       unsigned int size = 0;
-    unsigned int cursor_x;
-    unsigned int cursor_y;
-    char* colorbuf;
-    char* strbuf;
-
-       if (buf == TOP_SCREEN) {
-               width    = TEXT_TOP_WIDTH;
-               height   = TEXT_TOP_HEIGHT;
-               size     = TEXT_TOP_SIZE;
-        colorbuf = color_buffer_top;
-        strbuf   = text_buffer_top;
-        cursor_x = top_cursor_x;
-        cursor_y = top_cursor_y;
-       } else if (buf == BOTTOM_SCREEN) {
-               width    = TEXT_BOTTOM_WIDTH;
-               height   = TEXT_BOTTOM_HEIGHT;
-               size     = TEXT_BOTTOM_SIZE;
-        colorbuf = color_buffer_bottom;
-        strbuf   = text_buffer_bottom;
-        cursor_x = bottom_cursor_x;
-        cursor_y = bottom_cursor_y;
+void putc(void* buf, unsigned char color, const int c) {
+    if ((int)buf == stdout || (int)buf == stderr) {
+               unsigned int width  = 0;
+               unsigned int height = 0;
+               unsigned int size = 0;
+       unsigned int cursor_x;
+       unsigned int cursor_y;
+       char* colorbuf;
+       char* strbuf;
+
+               if ((int)buf == TOP_SCREEN) {
+                       width    = TEXT_TOP_WIDTH;
+                       height   = TEXT_TOP_HEIGHT;
+                       size     = TEXT_TOP_SIZE;
+           colorbuf = color_buffer_top;
+           strbuf   = text_buffer_top;
+           cursor_x = top_cursor_x;
+           cursor_y = top_cursor_y;
+               } else if ((int)buf == BOTTOM_SCREEN) {
+                       width    = TEXT_BOTTOM_WIDTH;
+                       height   = TEXT_BOTTOM_HEIGHT;
+                       size     = TEXT_BOTTOM_SIZE;
+               colorbuf = color_buffer_bottom;
+               strbuf   = text_buffer_bottom;
+               cursor_x = bottom_cursor_x;
+               cursor_y = bottom_cursor_y;
+               }
+
+               unsigned int offset = width * cursor_y + cursor_x;
+
+               if (offset >= size) {
+               // Scroll a line back. This involves memcpy.
+               // Yes, memcpy overwrites part of the buffer it is reading.
+               memcpy(strbuf, strbuf+width, size-width);
+               memcpy(colorbuf, colorbuf+width, size-width);
+               cursor_y -= 1;
+                       offset = width * cursor_y + cursor_x;
+           }
+
+               if (offset >= size) {
+               // So if we're being real, this won't ever happen.
+               return;
+           }
+
+           switch(c) {
+               case '\n':
+                   cursor_y++;   // Increment line.
+                   cursor_x = 0;
+                   break;
+               case '\r':
+                   cursor_x = 0; // Reset to beginning of line.
+                   break;
+               default:
+                   strbuf[offset] = c;
+                   colorbuf[offset] = color; // White on black.
+                   cursor_x++;
+                   if (cursor_x >= width) {
+                       cursor_y++;
+                       cursor_x = 0;
+                   }
+                   break;
+           }
+
+           if ((int)buf == TOP_SCREEN) {
+               top_cursor_x = cursor_x;
+               top_cursor_y = cursor_y;
+           } else if ((int)buf == BOTTOM_SCREEN) {
+               bottom_cursor_x = cursor_x;
+               bottom_cursor_y = cursor_y;
+           }
        } else {
-               return; // Invalid buffer.
+               // FILE*, not stdin or stdout.
+               fwrite(&c, 1, 1, (FILE*)buf);
        }
-
-       unsigned int offset = width * cursor_y + cursor_x;
-
-       if (offset >= size) {
-        // Scroll a line back. This involves memcpy.
-        // Yes, memcpy overwrites part of the buffer it is reading.
-        memcpy(strbuf, strbuf+width, size-width);
-        memcpy(colorbuf, colorbuf+width, size-width);
-        cursor_y -= 1;
-               offset = width * cursor_y + cursor_x;
-    }
-
-       if (offset >= size) {
-        // So if we're being real, this won't ever happen.
-        return;
-    }
-
-    switch(c) {
-        case '\n':
-            cursor_y++;   // Increment line.
-            cursor_x = 0;
-            break;
-        case '\r':
-            cursor_x = 0; // Reset to beginning of line.
-            break;
-        default:
-            strbuf[offset] = c;
-            colorbuf[offset] = color; // White on black.
-            cursor_x++;
-            if (cursor_x >= width) {
-                cursor_y++;
-                cursor_x = 0;
-            }
-            break;
-    }
-
-    if (buf == TOP_SCREEN) {
-        top_cursor_x = cursor_x;
-        top_cursor_y = cursor_y;
-    } else if (buf == BOTTOM_SCREEN) {
-        bottom_cursor_x = cursor_x;
-        bottom_cursor_y = cursor_y;
-    }
 }
 
-void puts(int buf, unsigned char color, const char *string) {
+void puts(void* buf, unsigned char color, const char *string) {
     char *ref = (char*)string;
 
     while(*ref != '\0') {
@@ -203,10 +208,10 @@ void puts(int buf, unsigned char color, const char *string) {
     }
 }
 
-void put_int(int channel, unsigned char color, int n) {
-    char conv[16], out[16];
-    memset(conv, 0, 16);
-    memset(out, 0, 16);
+void put_int64(void* channel, unsigned char color, int64_t n, int length) {
+    char conv[32], out[32];
+    memset(conv, 0, 32);
+    memset(out, 0, 32);
 
     int i = 0, sign = 0;
     if (n < 0) {
@@ -222,6 +227,9 @@ void put_int(int channel, unsigned char color, int n) {
     if (sign)
         conv[i++] = '-';
 
+    if (length > 0)
+        out[length] = '\0';
+
     int len = strlen(conv);
     for(int i=0; i < len; i++)
         out[i] = conv[(len-1) - i];
@@ -229,16 +237,19 @@ void put_int(int channel, unsigned char color, int n) {
     puts(channel, color, out);
 }
 
-void put_uint(int channel, unsigned char color, unsigned int n) {
-    char conv[16], out[16];
-    memset(conv, 0, 16);
-    memset(out, 0, 16);
+void put_uint64(void* channel, unsigned char color, uint64_t n, int length) {
+    char conv[32], out[32];
+    memset(conv, 0, 32);
+    memset(out, 0, 32);
 
     int i = 0;
     do {
         conv[i++] = (n % 10) + '0';
     } while((n /= 10) != 0);
 
+    if (length > 0)
+        out[length] = '\0';
+
     int len = strlen(conv);
     for(int i=0; i < len; i++)
         out[i] = conv[(len-1) - i];
@@ -246,8 +257,16 @@ void put_uint(int channel, unsigned char color, unsigned int n) {
     puts(channel, color, out);
 }
 
-void cflush(int channel) {
-    if (channel == TOP_SCREEN) {
+void put_uint(void* channel, unsigned char color, unsigned int n, int length) {
+    put_uint64(channel, color, n, length);
+}
+
+void put_int(void* channel, unsigned char color, int n, int length) {
+    put_int64(channel, color, n, length);
+}
+
+void fflush(void* channel) {
+    if ((int)channel == TOP_SCREEN) {
                for(int x=0; x < TEXT_TOP_WIDTH; x++) {
                        for(int y=0; y < TEXT_TOP_HEIGHT; y++) {
                char c = text_buffer_top[y*TEXT_TOP_WIDTH+x];
@@ -256,7 +275,7 @@ void cflush(int channel) {
                                draw_character(framebuffers->top_left, c, x, y, color_fg, color_bg);
                        }
                }
-    } else if (channel == BOTTOM_SCREEN) {
+    } else if ((int)channel == BOTTOM_SCREEN) {
                for(int x=0; x < TEXT_BOTTOM_WIDTH; x++) {
                        for(int y=0; y < TEXT_BOTTOM_HEIGHT; y++) {
                char c = text_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x];
@@ -265,10 +284,12 @@ void cflush(int channel) {
                                draw_character(framebuffers->bottom, c, x, y, color_fg, color_bg);
                        }
                }
+       } else {
+               f_sync(&(((FILE*)channel)->handle)); // Sync to disk.
        }
 }
 
-void cprintf(int channel, const char* format, ...) {
+void fprintf(void* channel, const char* format, ...) {
     va_list ap;
     va_start( ap, format );
 
@@ -276,15 +297,63 @@ void cprintf(int channel, const char* format, ...) {
     unsigned char color = 0xf0;
 
     while(*ref != '\0') {
-        if(*ref == '%') {
+               if (*ref == 0x1B && *(++ref) == '[' && ( (int)channel == stdout || (int)channel == stderr) ) {
+ansi_codes:
+            // Ansi escape code.
+            ++ref;
+            // [30-37] Set text color
+            if (*ref == '3') {
+                ++ref;
+                if(*ref >= '0' && *ref <= '7') {
+                    // Valid FG color.
+                    color &= 0x0f; // Remove fg color.
+                    color |= (*ref - '0') << 4;
+                }
+            }
+            // [40-47] Set bg color
+            else if (*ref == '4') {
+                ++ref;
+                if(*ref >= '0' && *ref <= '7') {
+                    // Valid BG color.
+                    color &= 0xf0; // Remove bg color.
+                    color |= *ref - '0';
+                }
+            }
+
+            ++ref;
+
+            if (*ref == ';') {
+                goto ansi_codes; // Another code.
+            }
+
+            // Loop until the character is somewhere 0x40 - 0x7E, which terminates an ANSI sequence
+            while(!(*ref >= 0x40 && *ref <= 0x7E)) ref++;
+        } else if (*ref == '%') {
+            int type_size = 0;
+            int length = -1;
+check_format:
             // Format string.
-            ref++;
+            ++ref;
             switch(*ref) {
                 case 'd':
-                    put_int(channel, color, va_arg( ap, int ));
+                    switch(type_size) {
+                        case 2:
+                            put_int64(channel, color, va_arg( ap, int64_t ), length);
+                            break;
+                        default:
+                            put_int(channel, color, va_arg( ap, int ), length);
+                            break;
+                    }
                     break;
                 case 'u':
-                    put_uint(channel, color, va_arg( ap, unsigned int ));
+                    switch(type_size) {
+                        case 2:
+                            put_uint64(channel, color, va_arg( ap, uint64_t ), length);
+                            break;
+                        default:
+                            put_uint(channel, color, va_arg( ap, unsigned int ), length);
+                            break;
+                    }
                     break;
                 case 's':
                     puts(channel, color, va_arg( ap, char* ));
@@ -298,17 +367,26 @@ void cprintf(int channel, const char* format, ...) {
                 case '%':
                     putc(channel, color, '%');
                     break;
+                case 'h':
+                    goto check_format; // Integers get promoted. No point here.
+                case 'l':
+                    ++type_size;
+                    goto check_format;
                 default:
+                    if (*ref >= '0' && *ref <= '9') {
+                        length = *ref - '0';
+                        goto check_format;
+                    }
                     break;
             }
         } else {
             putc(channel, color, *ref);
         }
-        ref++;
+        ++ref;
     }
 
     va_end( ap );
 
-    cflush(channel);
+    fflush(channel);
 }
 
index a79eb0bec3d1d9aab7b6982eb8127b83504c1e12..be36d3700ed849b30aefaa6ec555e11d70212a1c 100644 (file)
@@ -49,22 +49,30 @@ void clear_screens();
 void draw_character(uint8_t* screen, const char character, const unsigned int pos_x, const unsigned int pos_y, const uint32_t color_fg, const uint32_t color_bg);
 
 #define TOP_SCREEN    0
-#define BOTTOM_SCREEN 1
+#define BOTTOM_SCREEN 2
 
-void putc(int buf, unsigned char color, const int c);
-void puts(int buf, unsigned char color, const char *string);
-void cflush(int channel);
+#define stdout TOP_SCREEN
+#define stderr BOTTOM_SCREEN
 
-void put_int(int channel, unsigned char color, int n);
-void put_uint(int channel, unsigned char color, unsigned int n);
+void putc(void* buf, unsigned char color, const int c);
+void puts(void* buf, unsigned char color, const char *string);
+void fflush(void* channel);
 
 void set_cursor(int channel, unsigned int x, unsigned int y);
 
 // Like printf. Supports the following format specifiers:
-//   %s %c %d %u
-// The following non-standard formats are also supported (but are subject to replacement)
-//   %p - unsigned char, changes color of text (will be replaced with ANSI codes eventually)
-void cprintf(int channel, const char* format, ...);
+//  %s - char*
+//  %c - char
+//  %d - int
+//  %u - unsigned int
+// The following non-standard
+// The following prefixes are also supported:
+//  %h  - word (stub)
+//  %hh - byte (stub)
+//  %[0-9][0-9]
+// Formats are also supported (but are subject to replacement)
+//  %p - unsigned char, changes color of text (will be replaced with ANSI codes eventually) 
+void fprintf(void* channel, const char* format, ...);
 
 #define BLACK     0
 #define BLUE      1
index e25a7a3ad4c2414f7d9ea605c9b505d1b4183828..bb5fe545276d7564a43a95aae091e06374140d98 100644 (file)
@@ -2,30 +2,63 @@
 #include "fs.h"
 #include "memory.h"
 #include "../fatfs/ff.h"
+#include "draw.h"
 
 static FATFS fs;
 
+static FILE files[MAX_FILES_OPEN];
+
 int fmount(void) {
-    if (f_mount(&fs, "0:", 1)) return 1;
+    if (f_mount(&fs, "0:", 1))
+        return 1;
+
+    for(int i=0; i < MAX_FILES_OPEN; i++)
+        memset(&files[i], 0, sizeof(FILE));
+
     return 0;
 }
 
 int fumount(void) {
-    if (f_mount(NULL, "0:", 1)) return 1;
+    for(int i=0; i < MAX_FILES_OPEN; i++)
+        if (files[i].is_open)
+            fclose(&files[i]);
+
+    if (f_mount(NULL, "0:", 1))
+        return 1;
+
     return 0;
 }
 
-int fopen(FILE* fp, const char *filename, const char *mode) {
+FILE* fopen(const char *filename, const char *mode) {
     if (*mode != 'r' && *mode != 'w' && *mode != 'a')
-        return 1; // Mode not valid.
+        return NULL; // Mode not valid.
+
+    FILE* fp;
+    int i;
+    for(i=0; i < MAX_FILES_OPEN; i++) {
+        if(!files[i].is_open) {
+           fp = &files[i];
+           break;
+        }
+    }
+
+    if (i == MAX_FILES_OPEN)
+        return NULL; // Out of handles.
 
        fp->mode = (*mode == 'r' ? FA_READ : (FA_WRITE | FA_OPEN_ALWAYS));
 
-    return f_open(&(fp->handle), filename, fp->mode);
+    if (f_open(&(fp->handle), filename, fp->mode))
+        return NULL;
+
+    fp->is_open = 1;
+
+    return fp;
 }
 
 void fclose(FILE* fp) {
     f_close(&(fp->handle));
+
+    memset(fp, 0, sizeof(FILE));
 }
 
 void fseek(FILE* fp, int64_t offset, int whence) {
@@ -78,19 +111,27 @@ size_t fread(void *buffer, size_t elementSize, size_t elementCnt, FILE* fp) {
 }
 
 size_t write_file(void* data, char* path, size_t size) {
-    FILE temp;
-    fopen(&temp, path, "w");
-    size_t written = fwrite(data, 1, size, &temp);
-    fclose(&temp);
-    return written;
+    FILE* temp = fopen(path, "w");
+
+    if (!temp)
+        return 0;
+
+    size_t wrote = fwrite(data, 1, size, temp);
+
+    fclose(temp);
+
+    return wrote;
 }
 
 size_t read_file(void* data, char* path, size_t size) {
-    FILE temp;
-    fopen(&temp, path, "r");
+    FILE* temp = fopen(path, "r");
+
+    if (!temp)
+        return 0;
+
+    size_t read = fread(data, 1, size, temp);
 
-    size_t read = fread(data, 1, size, &temp);
-    fclose(&temp);
+    fclose(temp);
 
     return read;
 }
index 16f6f4779a39342efe77ba7fb474c956dcc085ba..b53fc348a942b0b9a4e40caa0493ae8ae8b4ecd5 100644 (file)
@@ -5,12 +5,15 @@
 #include "memory.h"
 #include "../fatfs/ff.h"
 
+#define MAX_FILES_OPEN 64
+
 typedef struct {
        FIL handle;
        uint32_t mode;
        size_t size;
        size_t at;
-} FILE;
+    uint8_t is_open;
+} __attribute__((packed)) FILE;
 
 #define SEEK_SET 0
 #define SEEK_CUR 1
@@ -19,7 +22,7 @@ typedef struct {
 int    fmount   (void);
 int    fumount  (void);
 
-int    fopen     (FILE* fp, const char *filename, const char *mode);
+FILE*  fopen     (const char *filename, const char *mode);
 
 void   fclose    (FILE* fp);