#include "std/fs.h"
#include "std/memory.h"
#include "std/abort.h"
+#include "std/unused.h"
#include "firm/fcram.h"
#include "firm/crypto.h"
#include "patch_format.h"
#include "config.h"
#include "input.h"
+#include "patcher.h"
#include "i2c.h"
#ifndef __CONFIG_H
#define __CONFIG_H
-static unsigned int config_version = 1;
+_UNUSED static unsigned int config_version = 1;
#define CONFIG_MAGIC "OVAN"
uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an arbitrary limit - contact me if you hit it.
}__attribute__((packed));
-static struct config_file config;
+_UNUSED static struct config_file config;
-#define OPTION_AUTOBOOT 0 // Skip menu unless L is held.
-#define OPTION_SILENCE 1 // Don't print debug information.
-#define OPTION_TRACE 2 // Pause for A key on each step.
+#define OPTION_SIGPATCH 0 // Use builtin signature patch.
+#define OPTION_LOADER 1 // Use builtin loader module replacer.
+#define OPTION_ARM9THREAD 2 // Use builtin ARM9 thread injector.
-#define OPTION_TRANSP_BG 3 // Background color is not drawn under text.
-#define OPTION_NO_CLEAR_BG 4 // Framebuffer is preserved from whatever ran before us.
-#define OPTION_READ_ME 5 // Remove Help/Readme from menu.
+#define OPTION_AUTOBOOT 3 // Skip menu unless L is held.
+#define OPTION_SILENCE 4 // Don't print debug information.
+#define OPTION_TRACE 5 // Pause for A key on each step.
-#define IGNORE_PATCH_DEPS 6 // Ignore patch UUID dependencies. Not recommended.
-#define IGNORE_BROKEN_SHIT 7 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
+#define OPTION_TRANSP_BG 6 // Background color is not drawn under text.
+#define OPTION_NO_CLEAR_BG 7 // Framebuffer is preserved from whatever ran before us.
+#define OPTION_READ_ME 8 // Remove Help/Readme from menu.
-#define HEADER_COLOR 8 // Color of header text.
-#define BG_COLOR 9 // Color of background.
-#define TEXT_COLOR 10 // Color of most text.
-#define ARROW_COLOR 11 // Color of Arrow.
+#define IGNORE_PATCH_DEPS 9 // Ignore patch UUID dependencies. Not recommended.
+#define IGNORE_BROKEN_SHIT 10 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
+
+#define HEADER_COLOR 11 // Color of header text.
+#define BG_COLOR 12 // Color of background.
+#define TEXT_COLOR 13 // Color of most text.
+#define ARROW_COLOR 14 // Color of Arrow.
void load_config();
#include <stdint.h>
+#include "../std/unused.h"
+
extern void *fcram_temp;
// Space between most of the locations
// patch.c
#define FCRAM_MEMORY_LOC (FCRAM_START + FCRAM_SPACING * 4)
-static uint8_t *memory_loc = (uint8_t *)FCRAM_MEMORY_LOC;
-static void *current_memory_loc;
+_UNUSED static uint8_t *memory_loc = (uint8_t *)FCRAM_MEMORY_LOC;
+_UNUSED static void *current_memory_loc;
#endif
firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC;
static uint32_t firm_size = FCRAM_SPACING;
+firm_section_h firm_proc9;
firm_h *twl_firm_loc = (firm_h *)FCRAM_TWL_FIRM_LOC;
static uint32_t twl_firm_size = FCRAM_SPACING * 2;
+firm_section_h twl_firm_proc9;
firm_h *agb_firm_loc = (firm_h *)FCRAM_AGB_FIRM_LOC;
static uint32_t agb_firm_size = FCRAM_SPACING;
+firm_section_h agb_firm_proc9;
static int update_96_keys = 0;
static int save_firm = 0;
// Otherwise, we make sure the error message for decrypting arm9bin mentions this.
}
-int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
-{
+int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key) {
uint8_t firm_iv[16] = {0};
uint8_t exefs_key[16] = {0};
uint8_t exefs_iv[16] = {0};
else return 0;
}
-int decrypt_firm(firm_h *dest, char *path_firmkey, char *path_cetk, uint32_t *size, uint64_t firm_title) {
+int decrypt_firm(firm_h *dest, char *path_firmkey, uint32_t *size) {
uint8_t firm_key[AES_BLOCK_SIZE];
// Firmware is likely encrypted. Decrypt.
return 0;
}
-int load_firm(firm_h *dest, char *path, char *path_firmkey, char *path_cetk, uint32_t *size, uint64_t firm_title) {
+int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint64_t firm_title) {
int status = 0;
int firmware_changed = 0;
// Check and decrypt FIRM if it is encrypted.
if (dest->magic != FIRM_MAGIC) {
- status = decrypt_firm(dest, path_firmkey, path_cetk, size, firm_title);
+ status = decrypt_firm(dest, path_firmkey, size);
if (status != 0) {
if (firm_title == NATIVE_FIRM_TITLEID) {
fprintf(BOTTOM_SCREEN, "Failed to decrypt firmware.\n"
((void (*)())firm_loc->a9Entry)();
}
+int find_proc9(firm_h* firm, firm_section_h* process9) {
+ for (firm_section_h *section = firm->section; section < firm->section + 4; section++) {
+ if (section->address == 0)
+ break;
+
+ if (section->type == FIRM_TYPE_ARM9) {
+ void* arm9section = (void*)firm + section->offset;
+ while (arm9section < arm9section + section->size) {
+ if (!memcmp(arm9section, "Process9", 8)) { // Process9
+ ncch_h *ncch = (ncch_h*)(arm9section - sizeof(ncch_h));
+ if (ncch->magic == NCCH_MAGIC) {
+ // Found Process9
+ ncch_ex_h *p9exheader = (ncch_ex_h *)(ncch + 1);
+ exefs_h *p9exefs = (exefs_h *)(p9exheader + 1);
+ process9->address = p9exheader->sci.textCodeSet.address;
+ process9->size = p9exefs->fileHeaders[0].size;
+ process9->offset = (void*)(p9exefs + 1) - (void*)firm;
+ fprintf(BOTTOM_SCREEN, "Found Process9 for FIRM.\n");
+ return 0;
+ }
+ }
+ ++arm9section;
+ }
+ }
+ }
+ fprintf(BOTTOM_SCREEN, "Couldn't find Process9 for FIRM?\n");
+ return 1;
+}
+
int load_firms() {
fprintf(TOP_SCREEN, "[Loading FIRM]");
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)
+ if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size, NATIVE_FIRM_TITLEID) != 0)
return 1;
+ find_proc9(firm_loc, &firm_proc9);
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))
+ if(load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size, TWL_FIRM_TITLEID))
fprintf(BOTTOM_SCREEN, "TWL_FIRM failed to load.\n");
+ else
+ find_proc9(twl_firm_loc, &twl_firm_proc9);
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))
+ if(load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size, AGB_FIRM_TITLEID))
fprintf(BOTTOM_SCREEN, "AGB_FIRM failed to load.\n");
+ else
+ find_proc9(agb_firm_loc, &agb_firm_proc9);
return 0;
}
void boot_cfw() {
fprintf(TOP_SCREEN, "[Patching]");
-// if (patch_firm_all() != 0)
-// return;
+ if (patch_firm_all() != 0)
+ return;
// Only save the firm if that option is required (or it's needed for autoboot),
// and either the patches have been modified, or the file doesn't exist.
}
}
-// boot_firm();
+ boot_firm();
}
}
if (buf_size != 1) {
- for (int i = 0; i < buf_size - 1; i++) {
+ for (size_t i = 0; i < buf_size - 1; i++) {
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xF0;
i2cWaitBusy(bus_id);
#include "common.h"
+#include "firm/firm.h"
void init_system() {}
-#define MENU_BOOTME -1
-#define MENU_MAIN 1
+int menu_handler();
-#define MENU_OPTIONS 2
-#define MENU_PATCHES 3
-#define MENU_INFO 4
-#define MENU_HELP 5
-#define MENU_RESET 6
-#define MENU_POWER 7
-
-static int cursor_y = 0;
-static int which_menu = 1;
-
-uint32_t wait_key() {
- uint32_t get = 0;
- while(get == 0) {
- if(HID_PAD & BUTTON_UP)
- get = BUTTON_UP;
- else if (HID_PAD & BUTTON_DOWN)
- get = BUTTON_DOWN;
- else if (HID_PAD & BUTTON_A)
- get = BUTTON_A;
- else if (HID_PAD & BUTTON_B)
- get = BUTTON_B;
- }
- while(HID_PAD&get);
- return get;
-}
-
-void header() {
- fprintf(stdout, "\x1b[33;40m[.corbenik//%s]\x1b[0m\n", VERSION);
-}
-
-int menu_options() { return MENU_MAIN; }
-
-int menu_patches() { return MENU_MAIN; }
-
-int menu_info() { return MENU_MAIN; }
-
-int menu_help() {
- set_cursor(TOP_SCREEN, 0, 0);
-
- header();
-
- fprintf(stdout, "\nCorbenik 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"
- " the kind of person who runs Gentoo or LFS. ;P\n"
- "\n "
- "Credits to people who've helped me put this\n"
- " together either by having written GPL code,\n"
- " or being just generally helpful/cool people:\n"
- " @mid-kid, @Wolfvak, @Reisyukaku, @AuroraWright\n"
- " @d0k3, and others\n"
- "\n "
- "The name of this comes from the .hack//series.\n"
- " Look it up, if you don't already know it.\n"
- "\n "
- "Any bugs filed including the letters S, A\n"
- " and O will be closed with no discussion.\n"
- "\n "
- " <https://github.com/chaoskagami/corbenik>\n"
- "\n "
- "Press any button to return.\n");
- while (1) {
- if (wait_key() & BUTTON_ANY)
- break;
- }
-
- clear_screen(TOP_SCREEN);
-
- return MENU_MAIN;
-}
-
-int menu_reset() {
- fumount(); // Unmount SD.
-
- // Reboot.
- fprintf(BOTTOM_SCREEN, "Resetting system.\n");
- i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
- while(1);
-}
-
-int menu_poweroff() {
- fumount(); // Unmount SD.
-
- // Reboot.
- fprintf(BOTTOM_SCREEN, "Powering off system.\n");
- i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
- while(1);
-}
-
-int menu_main() {
- set_cursor(TOP_SCREEN, 0, 0);
-
- const char *list[] = {
- "Options ",
- "Patches ",
- "Info ",
- "Help/Readme ",
- "Reset ",
- "Power off ",
- "Boot firmware "
- };
-
- header();
-
- int menu_max = 6;
-
- for(int i=0; i < menu_max; i++) {
- if (cursor_y == i)
- fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
- else
- fprintf(TOP_SCREEN, " ");
- fprintf(TOP_SCREEN, "%s\n", list[i]);
- }
-
- uint32_t key = wait_key();
- int entry = cursor_y + 2;
- if (cursor_y > MENU_POWER)
- entry = MENU_BOOTME;
-
- switch(key) {
- case BUTTON_UP:
- cursor_y -= 1;
- break;
- case BUTTON_DOWN:
- cursor_y += 1;
- break;
- case BUTTON_A:
- return entry;
- break;
- }
-
- // Loop around the cursor.
- if (cursor_y < 0)
- cursor_y = menu_max -1;
- if (cursor_y > menu_max - 1)
- cursor_y = 0;
-
- return 0;
-}
-
-int menu_handler() {
- int to_menu = 0;
- switch(which_menu) {
- case MENU_MAIN:
- to_menu = menu_main();
- break;
- case MENU_OPTIONS:
- to_menu = menu_options();
- break;
- case MENU_PATCHES:
- to_menu = menu_patches();
- break;
- case MENU_INFO:
- to_menu = menu_info();
- break;
- case MENU_HELP:
- to_menu = menu_help();
- break;
- case MENU_BOOTME:
- return 0;
- case MENU_RESET:
- menu_reset();
- case MENU_POWER:
- menu_poweroff();
- }
-
- if (to_menu != 0)
- which_menu = to_menu;
-
- return 1;
-}
-
-void main() {
+int main() {
if (fmount()) {
// Failed to mount SD. Bomb out.
fprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK));
--- /dev/null
+#include "common.h"
+#include "firm/firm.h"
+
+#define MENU_BOOTME -1
+#define MENU_MAIN 1
+
+#define MENU_OPTIONS 2
+#define MENU_PATCHES 3
+#define MENU_INFO 4
+#define MENU_HELP 5
+#define MENU_RESET 6
+#define MENU_POWER 7
+
+static int cursor_y = 0;
+static int which_menu = 1;
+
+uint32_t wait_key() {
+ uint32_t get = 0;
+ while(get == 0) {
+ if(HID_PAD & BUTTON_UP)
+ get = BUTTON_UP;
+ else if (HID_PAD & BUTTON_DOWN)
+ get = BUTTON_DOWN;
+ else if (HID_PAD & BUTTON_A)
+ get = BUTTON_A;
+ else if (HID_PAD & BUTTON_B)
+ get = BUTTON_B;
+ }
+ while(HID_PAD&get);
+ return get;
+}
+
+void header() {
+ fprintf(stdout, "\x1b[33;40m[.corbenik//%s]\x1b[0m\n", VERSION);
+}
+
+int menu_patches() { return MENU_MAIN; }
+
+int menu_options() {
+ clear_screen(TOP_SCREEN);
+
+ set_cursor(TOP_SCREEN, 0, 0);
+
+ const char *list[] = {
+ "Signature patch (builtin)",
+ "Loader module (builtin)",
+ "ARM9 thread (builtin)",
+
+ "Autoboot",
+ "Silence debug output",
+ "Trace steps with (A)",
+
+ "Don't draw background color",
+ "Preserve current framebuffer",
+ "Hide Readme/Help from menu",
+
+ "Ignore dependencies",
+ "Allow enabling broken",
+ };
+ const int menu_max = 11;
+
+ header();
+
+ for(int i=0; i < menu_max; i++) {
+ if (cursor_y == i)
+ fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
+ else
+ fprintf(TOP_SCREEN, " ");
+
+ fprintf(TOP_SCREEN, "[%c] %s\n", (config.options[i] ? 'X' : ' '), list[i]);
+ }
+
+ uint32_t key = wait_key();
+
+ switch(key) {
+ case BUTTON_UP:
+ cursor_y -= 1;
+ break;
+ case BUTTON_DOWN:
+ cursor_y += 1;
+ break;
+ case BUTTON_A:
+ // TODO - Value options
+ config.options[cursor_y] = !config.options[cursor_y];
+ break;
+ case BUTTON_B:
+ return MENU_MAIN;
+ break;
+ }
+
+ // Loop around the cursor.
+ if (cursor_y < 0)
+ cursor_y = menu_max - 1;
+ if (cursor_y > menu_max - 1)
+ cursor_y = 0;
+
+ return 0;
+}
+
+int menu_info() { return MENU_MAIN; }
+
+int menu_help() {
+ clear_screen(TOP_SCREEN);
+
+ set_cursor(TOP_SCREEN, 0, 0);
+
+ header();
+
+ fprintf(stdout, "\nCorbenik 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"
+ " the kind of person who runs Gentoo or LFS. ;P\n"
+ "\n"
+ "Credits to people who've helped me put this\n"
+ " together either by having written GPL code,\n"
+ " or being just generally helpful/cool people:\n"
+ " @mid-kid, @Wolfvak, @Reisyukaku, @AuroraWright\n"
+ " @d0k3, and others\n"
+ "\n"
+ "The name of this comes from the .hack//series.\n"
+ " Look it up, if you don't already know it.\n"
+ "\n"
+ "Any bugs filed including the letters S, A\n"
+ " and O will be closed with no discussion.\n"
+ "\n"
+ " <https://github.com/chaoskagami/corbenik>\n"
+ "\n");
+ while (1) {
+ if (wait_key() & BUTTON_ANY)
+ break;
+ }
+
+ return MENU_MAIN;
+}
+
+int menu_reset() {
+ fumount(); // Unmount SD.
+
+ // Reboot.
+ fprintf(BOTTOM_SCREEN, "Resetting system.\n");
+ i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
+ while(1);
+}
+
+int menu_poweroff() {
+ fumount(); // Unmount SD.
+
+ // Reboot.
+ fprintf(BOTTOM_SCREEN, "Powering off system.\n");
+ i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
+ while(1);
+}
+
+int menu_main() {
+ clear_screen(TOP_SCREEN);
+
+ set_cursor(TOP_SCREEN, 0, 0);
+
+ const char *list[] = {
+ "Options",
+ "Patches",
+ "Info",
+ "Help/Readme",
+ "Reset",
+ "Power off",
+ "Boot firmware"
+ };
+ int menu_max = 6;
+
+ header();
+
+ for(int i=0; i < menu_max; i++) {
+ if (!(i+2 == MENU_HELP && config.options[OPTION_READ_ME])) {
+ if (cursor_y == i)
+ fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
+ else
+ fprintf(TOP_SCREEN, " ");
+ fprintf(TOP_SCREEN, "%s\n", list[i]);
+ }
+ }
+
+ uint32_t key = wait_key();
+
+ switch(key) {
+ case BUTTON_UP:
+ cursor_y -= 1;
+ if (config.options[OPTION_READ_ME] && cursor_y+2 == MENU_HELP)
+ cursor_y -= 1; // Disable help.
+ break;
+ case BUTTON_DOWN:
+ cursor_y += 1;
+ if (config.options[OPTION_READ_ME] && cursor_y+2 == MENU_HELP)
+ cursor_y += 1; // Disable help.
+ break;
+ case BUTTON_A:
+ return cursor_y+2;
+ break;
+ }
+
+ // Loop around the cursor.
+ if (cursor_y < 0)
+ cursor_y = menu_max -1;
+ if (cursor_y > menu_max - 1)
+ cursor_y = 0;
+
+ return 0;
+}
+
+int menu_handler() {
+ int to_menu = 0;
+ switch(which_menu) {
+ case MENU_MAIN:
+ to_menu = menu_main();
+ break;
+ case MENU_OPTIONS:
+ to_menu = menu_options();
+ break;
+ case MENU_PATCHES:
+ to_menu = menu_patches();
+ break;
+ case MENU_INFO:
+ to_menu = menu_info();
+ break;
+ case MENU_HELP:
+ to_menu = menu_help();
+ break;
+ case MENU_BOOTME:
+ return 0;
+ case MENU_RESET:
+ menu_reset();
+ case MENU_POWER:
+ menu_poweroff();
+ }
+
+ if (to_menu != 0)
+ which_menu = to_menu;
+
+ return 1;
+}
+
--- /dev/null
+#include <stdint.h>
+#include "std/unused.h"
+#include "std/memory.h"
+#include "config.h"
+
+#define SIGNATURE_CHECK {0x00, 0x20}
+#define SIGNATURE_CHECK_FIX {0x70, 0x60, 0x70, 0x47}
+
+int patch_firm_all() {
+ // Use builtin signature patcher?
+ if (config.options[OPTION_SIGPATCH]) {
+ // Yes.
+ // memfind(
+ }
+
+ // Replace loader?
+ if (config.options[OPTION_LOADER]) {
+ // Yes.
+
+ // This requires OPTION_SIGPATCH.
+ }
+
+ // Use ARM9 hook thread?
+ if (config.options[OPTION_ARM9THREAD]) {
+ // Yes.
+ // FIXME - NYI
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef __PATCHER__
+#define __PATCHER__
+
+int patch_firm_all();
+
+#endif
#ifndef __ABORT_H
#define __ABORT_H
+#include "draw.h"
+
#define abort(x...) { \
- fprintf(2, x); \
+ fprintf(stderr, x); \
fumount(); \
while(1); \
}
#include "font.h"
#include "../fatfs/ff.h"
#include "fs.h"
+#include "unused.h"
static unsigned int top_cursor_x = 0, top_cursor_y = 0;
static unsigned int bottom_cursor_x = 0, bottom_cursor_y = 0;
uint32_t size = 0;
char* buffer = 0;
uint32_t buffer_size = 0;
- if ((int)screen == TOP_SCREEN)
+
+ if (screen == TOP_SCREEN)
screen = framebuffers->top_left;
- else if ((int)screen == BOTTOM_SCREEN)
+ else if (screen == BOTTOM_SCREEN)
screen = framebuffers->bottom;
if(screen == framebuffers->top_left ||
memset(buffer, 0, buffer_size);
}
-void set_cursor(int channel, unsigned int x, unsigned int y) {
- switch(channel) {
- case TOP_SCREEN:
- top_cursor_x = x;
- top_cursor_y = y;
- break;
- case BOTTOM_SCREEN:
- bottom_cursor_x = x;
- bottom_cursor_y = y;
- break;
+void set_cursor(void* channel, unsigned int x, unsigned int y) {
+ if (channel == TOP_SCREEN) {
+ top_cursor_x = x;
+ top_cursor_y = y;
+ } else if (channel == BOTTOM_SCREEN) {
+ bottom_cursor_x = x;
+ bottom_cursor_y = y;
}
}
if (!isprint(character))
return; // Don't output non-printables.
- int width = 0;
+ _UNUSED int width = 0;
int height = 0;
if(screen == framebuffers->top_left ||
screen == framebuffers->top_right) {
unsigned char color_bottom = 0xf0;
void putc(void* buf, const int c) {
- if ((int)buf == stdout || (int)buf == stderr) {
+ if (buf == stdout || buf == stderr) {
unsigned int width = 0;
- unsigned int height = 0;
+ _UNUSED unsigned int height = 0;
unsigned int size = 0;
unsigned int cursor_x;
unsigned int cursor_y;
unsigned char* color = NULL;
- if ((int)buf == TOP_SCREEN) {
+ if (buf == TOP_SCREEN) {
width = TEXT_TOP_WIDTH;
height = TEXT_TOP_HEIGHT;
size = TEXT_TOP_SIZE;
cursor_x = top_cursor_x;
cursor_y = top_cursor_y;
color = &color_top;
- } else if ((int)buf == BOTTOM_SCREEN) {
+ } else if (buf == BOTTOM_SCREEN) {
width = TEXT_BOTTOM_WIDTH;
height = TEXT_BOTTOM_HEIGHT;
size = TEXT_BOTTOM_SIZE;
break;
}
- if ((int)buf == TOP_SCREEN) {
+ if (buf == TOP_SCREEN) {
top_cursor_x = cursor_x;
top_cursor_y = cursor_y;
- } else if ((int)buf == BOTTOM_SCREEN) {
+ } else if (buf == BOTTOM_SCREEN) {
bottom_cursor_x = cursor_x;
bottom_cursor_y = cursor_y;
}
}
void fflush(void* channel) {
- if ((int)channel == TOP_SCREEN) {
+ if (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];
draw_character(framebuffers->top_left, c, x, y, color_fg, color_bg);
}
}
- } else if ((int)channel == BOTTOM_SCREEN) {
+ } else if (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];
char *ref = (char*)format;
unsigned char* color;
- if ((int)channel == TOP_SCREEN)
+ if (channel == TOP_SCREEN)
color = &color_top;
- else if ((int)channel == TOP_SCREEN)
+ else if (channel == TOP_SCREEN)
color = &color_bottom;
while(*ref != '\0') {
- if (*ref == 0x1B && *(++ref) == '[' && ( (int)channel == stdout || (int)channel == stderr) ) {
+ if (*ref == 0x1B && *(++ref) == '[' && ( channel == stdout || channel == stderr) ) {
ansi_codes:
// Ansi escape code.
++ref;
screen_bottom
};
-static struct framebuffers {
+#include "unused.h"
+
+_UNUSED static struct framebuffers {
uint8_t *top_left;
uint8_t *top_right;
uint8_t *bottom;
} *framebuffers = (struct framebuffers *)0x23FFFE00;
+// This is marked unused since it occurs in all files.
#define TOP_FB framebuffers->top_left
#define BOTTOM_FB framebuffers->bottom
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 2
+#define TOP_SCREEN ((void*)0)
+#define BOTTOM_SCREEN ((void*)2)
#define stdout TOP_SCREEN
#define stderr BOTTOM_SCREEN
void puts(void* buf, const char *string);
void fflush(void* channel);
-void set_cursor(int channel, unsigned int x, unsigned int y);
+void set_cursor(void* channel, unsigned int x, unsigned int y);
// Like printf. Supports the following format specifiers:
// %s - char*
--- /dev/null
+#define _UNUSED __attribute__((unused))