diff --git a/Makefile.arm11 b/Makefile.arm11 index e5806b9..cf15fda 100644 --- a/Makefile.arm11 +++ b/Makefile.arm11 @@ -43,7 +43,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11 ASFLAGS := -g $(INCLUDE) $(ARCH) -DARM11 -D_3DS $(DEFINES) -LDFLAGS = -nostartfiles -T../$(LDNAME) $(CFLAGS) -Wl,-Map,$(notdir $*.map),--use-blx,--gc-sections +LDFLAGS = -nostartfiles -T../$(LDNAME) $(CFLAGS) -Wl,-Map,$(notdir $*.map),--use-blx,--gc-sections,--emit-relocs #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project (order is important) diff --git a/Makefile.arm9 b/Makefile.arm9 index 96f31a2..e4e7d83 100644 --- a/Makefile.arm9 +++ b/Makefile.arm9 @@ -43,7 +43,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11 ASFLAGS := -g $(INCLUDE) $(ARCH) -DARM9 $(DEFINES) -LDFLAGS = -nostartfiles -T../$(LDNAME) $(CFLAGS) -Wl,-Map,$(notdir $*.map),--use-blx,--gc-sections +LDFLAGS = -nostartfiles -T../$(LDNAME) $(CFLAGS) -Wl,-Map,$(notdir $*.map),--use-blx,--gc-sections,--emit-relocs #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project (order is important) diff --git a/arm11.ld b/arm11.ld index d571b2e..93ac9e7 100644 --- a/arm11.ld +++ b/arm11.ld @@ -2,178 +2,179 @@ OUTPUT_ARCH(arm) ENTRY(_start) -MEMORY { - - memregion : ORIGIN = 0x1FF80000, LENGTH = 100K +PHDRS +{ + code PT_LOAD FLAGS(5) /* Read | Execute */; + rodata PT_LOAD FLAGS(4) /* Read */; + data PT_LOAD FLAGS(6) /* Read | Write */; } -__memregion_start = ORIGIN(memregion); -__memregion_top = ORIGIN(memregion)+ LENGTH(memregion); - SECTIONS { - .init : - { - __text_start = . ; - KEEP (*(.init)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .plt : - { - *(.plt) - } >memregion = 0xff + /* =========== CODE section =========== */ - .text : /* ALIGN (4): */ - { + . = 0x1FF80000; + __start__ = . ; - *(.text*) - *(.stub) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) + .text ALIGN(4) : + { + /* .init */ + KEEP( *(.crt0) ) + KEEP( *(.init) ) + . = ALIGN(4); + + /* .text */ + *(.text) + *(.text.*) *(.glue_7) *(.glue_7t) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); - .fini : - { - KEEP (*(.fini)) - } >memregion =0xff + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(4); + } : code - __text_end = . ; + /* =========== RODATA section =========== */ - .rodata : + .rodata ALIGN(4) : { *(.rodata) - *all.rodata*(*) *(.roda) *(.rodata.*) + *all.rodata*(*) *(.gnu.linkonce.r*) SORT(CONSTRUCTORS) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff + . = ALIGN(4); + } : rodata - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >memregion + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } : rodata __exidx_start = .; - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >memregion + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } : rodata __exidx_end = .; -/* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { KEEP (*(.preinit_array)) } >memregion = 0xff - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { KEEP (*(.init_array)) } >memregion = 0xff - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { KEEP (*(.fini_array)) } >memregion = 0xff - PROVIDE (__fini_array_end = .); + /* =========== DATA section =========== */ - .ctors : + .data ALIGN(4) : { - /* gcc uses crtbegin.o to find the start of the constructors, so - we make sure it is first. Because this is a wildcard, it - doesn't matter if the user does not actually link against - crtbegin.o; the linker won't look for a file to match a - wildcard. The wildcard also means that it doesn't matter which - directory crtbegin.o is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .eh_frame : - { - KEEP (*(.eh_frame)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .gcc_except_table : - { - *(.gcc_except_table) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - .jcr : { KEEP (*(.jcr)) } >memregion = 0 - .got : { *(.got.plt) *(.got) } >memregion = 0 - - - .memregion ALIGN(4) : - { - __memregion_start = ABSOLUTE(.) ; - *(.memregion) - *memregion.*(.text) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - __memregion_end = ABSOLUTE(.) ; - } >memregion = 0xff - - - .data ALIGN(4) : { - __data_start = ABSOLUTE(.); *(.data) *(.data.*) *(.gnu.linkonce.d*) CONSTRUCTORS . = ALIGN(4); - __data_end = ABSOLUTE(.) ; - } >memregion = 0xff + } : data + .tdata ALIGN(4) : + { + __tdata_lma = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + . = ALIGN(4); + __tdata_lma_end = .; + } : data + .tbss ALIGN(4) : + { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + *(.tcommon) + . = ALIGN(4); + } : data + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : data + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } : data + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } : data + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } : data + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } : data + + __bss_start__ = .; .bss ALIGN(4) : { - __bss_start = ABSOLUTE(.); - __bss_start__ = ABSOLUTE(.); *(.dynbss) + *(.bss) + *(.bss.*) *(.gnu.linkonce.b*) - *(.bss*) *(COMMON) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion + . = ALIGN(4); - __bss_end = . ; - __bss_end__ = . ; + /* Reserve space for the TLS segment of the main thread */ + __tls_start = .; + . += + SIZEOF(.tdata) + SIZEOF(.tbss); + __tls_end = .; + } : data + __bss_end__ = .; - _end = . ; - __end__ = . ; - PROVIDE (end = _end); + __end__ = ABSOLUTE(.) ; - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } @@ -182,11 +183,4 @@ .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - .stack 0x80000 : { _stack = .; *(.stack) } - /* These must appear regardless of . */ } diff --git a/arm9.ld b/arm9.ld index 83a9739..c63146c 100644 --- a/arm9.ld +++ b/arm9.ld @@ -2,178 +2,179 @@ OUTPUT_ARCH(arm) ENTRY(_start) -MEMORY { - - memregion : ORIGIN = 0x08000040, LENGTH = 300K +PHDRS +{ + code PT_LOAD FLAGS(5) /* Read | Execute */; + rodata PT_LOAD FLAGS(4) /* Read */; + data PT_LOAD FLAGS(6) /* Read | Write */; } -__memregion_start = ORIGIN(memregion); -__memregion_top = ORIGIN(memregion)+ LENGTH(memregion); - SECTIONS { - .init : - { - __text_start = . ; - KEEP (*(.init)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .plt : - { - *(.plt) - } >memregion = 0xff + /* =========== CODE section =========== */ - .text : /* ALIGN (4): */ - { + . = 0x08000040; + __start__ = . ; - *(.text*) - *(.stub) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) + .text ALIGN(4) : + { + /* .init */ + KEEP( *(.crt0) ) + KEEP( *(.init) ) + . = ALIGN(4); + + /* .text */ + *(.text) + *(.text.*) *(.glue_7) *(.glue_7t) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); - .fini : - { - KEEP (*(.fini)) - } >memregion =0xff + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(4); + } : code - __text_end = . ; + /* =========== RODATA section =========== */ - .rodata : + .rodata ALIGN(4) : { *(.rodata) - *all.rodata*(*) *(.roda) *(.rodata.*) + *all.rodata*(*) *(.gnu.linkonce.r*) SORT(CONSTRUCTORS) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff + . = ALIGN(4); + } : rodata - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >memregion + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } : rodata __exidx_start = .; - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >memregion + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } : rodata __exidx_end = .; -/* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { KEEP (*(.preinit_array)) } >memregion = 0xff - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { KEEP (*(.init_array)) } >memregion = 0xff - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { KEEP (*(.fini_array)) } >memregion = 0xff - PROVIDE (__fini_array_end = .); + /* =========== DATA section =========== */ - .ctors : + .data ALIGN(4) : { - /* gcc uses crtbegin.o to find the start of the constructors, so - we make sure it is first. Because this is a wildcard, it - doesn't matter if the user does not actually link against - crtbegin.o; the linker won't look for a file to match a - wildcard. The wildcard also means that it doesn't matter which - directory crtbegin.o is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .eh_frame : - { - KEEP (*(.eh_frame)) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - - .gcc_except_table : - { - *(.gcc_except_table) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion = 0xff - .jcr : { KEEP (*(.jcr)) } >memregion = 0 - .got : { *(.got.plt) *(.got) } >memregion = 0 - - - .memregion ALIGN(4) : - { - __memregion_start = ABSOLUTE(.) ; - *(.memregion) - *memregion.*(.text) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - __memregion_end = ABSOLUTE(.) ; - } >memregion = 0xff - - - .data ALIGN(4) : { - __data_start = ABSOLUTE(.); *(.data) *(.data.*) *(.gnu.linkonce.d*) CONSTRUCTORS . = ALIGN(4); - __data_end = ABSOLUTE(.) ; - } >memregion = 0xff + } : data + .tdata ALIGN(4) : + { + __tdata_lma = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + . = ALIGN(4); + __tdata_lma_end = .; + } : data + .tbss ALIGN(4) : + { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + *(.tcommon) + . = ALIGN(4); + } : data + .preinit_array ALIGN(4) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : data + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } : data + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } : data + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } : data + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } : data + + __bss_start__ = .; .bss ALIGN(4) : { - __bss_start = ABSOLUTE(.); - __bss_start__ = ABSOLUTE(.); *(.dynbss) + *(.bss) + *(.bss.*) *(.gnu.linkonce.b*) - *(.bss*) *(COMMON) - . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ - } >memregion + . = ALIGN(4); - __bss_end = . ; - __bss_end__ = . ; + /* Reserve space for the TLS segment of the main thread */ + __tls_start = .; + . += + SIZEOF(.tdata) + SIZEOF(.tbss); + __tls_end = .; + } : data + __bss_end__ = .; - _end = . ; - __end__ = . ; - PROVIDE (end = _end); + __end__ = ABSOLUTE(.) ; - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ .debug_info 0 : { *(.debug_info) } .debug_abbrev 0 : { *(.debug_abbrev) } @@ -182,11 +183,4 @@ .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - .stack 0x80000 : { _stack = .; *(.stack) } - /* These must appear regardless of . */ } diff --git a/include/arm9/console.h b/include/arm9/console.h index ce216c6..f71b835 100644 --- a/include/arm9/console.h +++ b/include/arm9/console.h @@ -1,132 +1,170 @@ - - -/*! \file console.h - \brief 3ds stdio support. - -
-Provides stdio integration for printing to the 3DS screen as well as debug print -functionality provided by stderr. - -General usage is to initialize the console by: -consoleDemoInit() -or to customize the console usage by: -consoleInit() - -*/ +/** + * @file console.h + * @brief 3ds stdio support. + * + * Provides stdio integration for printing to the 3DS screen as well as debug print + * functionality provided by stderr. + * + * General usage is to initialize the console by: + * @code + * consoleDemoInit() + * @endcode + * or to customize the console usage by: + * @code + * consoleInit() + * @endcode + */ +#pragma once #include "types.h" +#include "gfx.h" -#define SCREEN_TOP 1 -#define SCREEN_LOW 0 +#ifdef __cplusplus +extern "C" { +#endif -typedef bool(* ConsolePrint)(void* con, int c); +#define SCREEN_TOP 1 +#define SCREEN_LOW 0 -//! a font struct for the console. +#define CONSOLE_ESC(x) "\x1b[" #x +#define CONSOLE_RESET CONSOLE_ESC(0m) +#define CONSOLE_BLACK CONSOLE_ESC(30m) +#define CONSOLE_RED CONSOLE_ESC(31;1m) +#define CONSOLE_GREEN CONSOLE_ESC(32;1m) +#define CONSOLE_YELLOW CONSOLE_ESC(33;1m) +#define CONSOLE_BLUE CONSOLE_ESC(34;1m) +#define CONSOLE_MAGENTA CONSOLE_ESC(35;1m) +#define CONSOLE_CYAN CONSOLE_ESC(36;1m) +#define CONSOLE_WHITE CONSOLE_ESC(37;1m) + +/// A callback for printing a character. +typedef bool(*ConsolePrint)(void* con, int c); + +/// A font struct for the console. typedef struct ConsoleFont { - const u8* gfx; //!< A pointer to the font graphics - u16 asciiOffset; //!< Offset to the first valid character in the font table - u16 numChars; //!< Number of characters in the font graphics - + const u8* gfx; ///< A pointer to the font graphics + u16 asciiOffset; ///< Offset to the first valid character in the font table + u16 numChars; ///< Number of characters in the font graphics }ConsoleFont; -/** \brief console structure used to store the state of a console render context. - -Default values from consoleGetDefault(); -
-PrintConsole defaultConsole =
-{
-	//Font:
-	{
-		(u8*)default_font_bin, //font gfx
-		0, //first ascii character in the set
-		128, //number of characters in the font set
-	},
-	0,0, //cursorX cursorY
-	0,0, //prevcursorX prevcursorY
-	40, //console width
-	30, //console height
-	0,  //window x
-	0,  //window y
-	32, //window width
-	24, //window height
-	3, //tab size
-	0, //font character offset
-	false //console initialized
-};
-
-*/ +/** + * @brief Console structure used to store the state of a console render context. + * + * Default values from consoleGetDefault(); + * @code + * PrintConsole defaultConsole = + * { + * //Font: + * { + * (u8*)default_font_bin, //font gfx + * 0, //first ascii character in the set + * 128, //number of characters in the font set + * }, + * 0,0, //cursorX cursorY + * 0,0, //prevcursorX prevcursorY + * 40, //console width + * 30, //console height + * 0, //window x + * 0, //window y + * 32, //window width + * 24, //window height + * 3, //tab size + * 0, //font character offset + * 0, //print callback + * false //console initialized + * }; + * @endcode + */ typedef struct PrintConsole { - ConsoleFont font; //!< font of the console. + ConsoleFont font; ///< Font of the console - u32 *frameBuffer; //!< framebuffer address. + u16 *frameBuffer; ///< Framebuffer address - int cursorX; /*!< Current X location of the cursor (as a tile offset by default) */ - int cursorY; /*!< Current Y location of the cursor (as a tile offset by default) */ + int cursorX; ///< Current X location of the cursor (as a tile offset by default) + int cursorY; ///< Current Y location of the cursor (as a tile offset by default) - int prevCursorX; /*!< Internal state */ - int prevCursorY; /*!< Internal state */ + int prevCursorX; ///< Internal state + int prevCursorY; ///< Internal state - int consoleWidth; /*!< Width of the console hardware layer in characters */ - int consoleHeight; /*!< Height of the console hardware layer in characters */ + int consoleWidth; ///< Width of the console hardware layer in characters + int consoleHeight; ///< Height of the console hardware layer in characters - int windowX; /*!< Window X location in characters (not implemented) */ - int windowY; /*!< Window Y location in characters (not implemented) */ - int windowWidth; /*!< Window width in characters (not implemented) */ - int windowHeight; /*!< Window height in characters (not implemented) */ + int windowX; ///< Window X location in characters (not implemented) + int windowY; ///< Window Y location in characters (not implemented) + int windowWidth; ///< Window width in characters (not implemented) + int windowHeight; ///< Window height in characters (not implemented) - int tabSize; /*!< Size of a tab*/ - u32 fg; /*!< foreground color*/ - u32 bg; /*!< background color*/ - int flags; /*!< reverse/bright flags*/ - - bool consoleInitialised; /*!< True if the console is initialized */ + int tabSize; ///< Size of a tab + int fg; ///< Foreground color + int bg; ///< Background color + int flags; ///< Reverse/bright flags + + ConsolePrint PrintChar; ///< Callback for printing a character. Should return true if it has handled rendering the graphics (else the print engine will attempt to render via tiles). + + bool consoleInitialised; ///< True if the console is initialized }PrintConsole; -#define CONSOLE_COLOR_BOLD (1<<0) -#define CONSOLE_COLOR_FAINT (1<<1) -#define CONSOLE_ITALIC (1<<2) -#define CONSOLE_UNDERLINE (1<<3) -#define CONSOLE_BLINK_SLOW (1<<4) -#define CONSOLE_BLINK_FAST (1<<5) -#define CONSOLE_COLOR_REVERSE (1<<6) -#define CONSOLE_CONCEAL (1<<7) -#define CONSOLE_CROSSED_OUT (1<<8) +#define CONSOLE_COLOR_BOLD (1<<0) ///< Bold text +#define CONSOLE_COLOR_FAINT (1<<1) ///< Faint text +#define CONSOLE_ITALIC (1<<2) ///< Italic text +#define CONSOLE_UNDERLINE (1<<3) ///< Underlined text +#define CONSOLE_BLINK_SLOW (1<<4) ///< Slow blinking text +#define CONSOLE_BLINK_FAST (1<<5) ///< Fast blinking text +#define CONSOLE_COLOR_REVERSE (1<<6) ///< Reversed color text +#define CONSOLE_CONCEAL (1<<7) ///< Concealed text +#define CONSOLE_CROSSED_OUT (1<<8) ///< Crossed out text -/*! \brief Loads the font into the console - \param console pointer to the console to update, if NULL it will update the current console - \param font the font to load -*/ +/// Console debug devices supported by libnds. +typedef enum { + debugDevice_NULL, ///< Swallows prints to stderr + debugDevice_3DMOO, ///< Directs stderr debug statements to 3dmoo + debugDevice_CONSOLE, ///< Directs stderr debug statements to 3DS console window +} debugDevice; + +/** + * @brief Loads the font into the console. + * @param console Pointer to the console to update, if NULL it will update the current console. + * @param font The font to load. + */ void consoleSetFont(PrintConsole* console, ConsoleFont* font); -/*! \brief Sets the print window - \param console console to set, if NULL it will set the current console window - \param x x location of the window - \param y y location of the window - \param width width of the window - \param height height of the window -*/ +/** + * @brief Sets the print window. + * @param console Console to set, if NULL it will set the current console window. + * @param x X location of the window. + * @param y Y location of the window. + * @param width Width of the window. + * @param height Height of the window. + */ void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height); -/*! \brief Gets a pointer to the console with the default values - this should only be used when using a single console or without changing the console that is returned, other wise use consoleInit() - \return A pointer to the console with the default values -*/ +/** + * @brief Gets a pointer to the console with the default values. + * This should only be used when using a single console or without changing the console that is returned, otherwise use consoleInit(). + * @return A pointer to the console with the default values. + */ PrintConsole* consoleGetDefault(void); -/*! \brief Make the specified console the render target - \param console A pointer to the console struct (must have been initialized with consoleInit(PrintConsole* console) - \return a pointer to the previous console -*/ +/** + * @brief Make the specified console the render target. + * @param console A pointer to the console struct (must have been initialized with consoleInit(PrintConsole* console)). + * @return A pointer to the previous console. + */ PrintConsole *consoleSelect(PrintConsole* console); -/*! \brief Initialise the console. - \param screen The screen to use for the console - \param console A pointer to the console data to initialze (if it's NULL, the default console will be used) - \return A pointer to the current console. -*/ +/** + * @brief Initialise the console. + * @param screen The screen to use for the console. + * @param console A pointer to the console data to initialize (if it's NULL, the default console will be used). + * @return A pointer to the current console. + */ PrintConsole* consoleInit(int screen, PrintConsole* console); -//! Clears the screan by using iprintf("\x1b[2J"); +/// Clears the screan by using iprintf("\x1b[2J"); void consoleClear(void); + +#ifdef __cplusplus +} +#endif diff --git a/include/gfx.h b/include/gfx.h index 1d0d47a..cf284c2 100644 --- a/include/gfx.h +++ b/include/gfx.h @@ -1,5 +1,7 @@ #pragma once +#include "types.h" + #define SCREEN_HEIGHT_TOP 240 #define SCREEN_WIDTH_TOP 400 #define SCREEN_HEIGHT_SUB 240 @@ -7,8 +9,11 @@ #define FRAMEBUF_TOP_A_1 0x18000000 #define FRAMEBUF_TOP_A_2 0x18000000 -#define FRAMEBUF_SUB_A_1 0x1805DC00 -#define FRAMEBUF_SUB_A_2 0x1805DC00 +#define FRAMEBUF_SUB_A_1 0x1802EE00 +#define FRAMEBUF_SUB_A_2 0x1802EE00 + +/// Converts packed RGB8 to packed RGB565. +#define RGB8_to_565(r,g,b) (((b)>>3)&0x1f)|((((g)>>2)&0x3f)<<5)|((((r)>>3)&0x1f)<<11) void gfx_init(); diff --git a/source/arm11/gfx.c b/source/arm11/gfx.c index 0dc9cce..c40ace5 100644 --- a/source/arm11/gfx.c +++ b/source/arm11/gfx.c @@ -37,11 +37,11 @@ *((vu32 *)(0x10400400+0x44)) = 0; *((vu32 *)(0x10400400+0x48)) = 0x0; *((vu32 *)(0x10400400+0x5C)) = 0x19000F0; // framebuf width & height, 400x240 - *((vu32 *)(0x10400400+0x90)) = 0x3C0; // framebuf stride, observed to be 0 + *((vu32 *)(0x10400400+0x90)) = 0x1E0; // 0x3C0; // framebuf stride, observed to be 0 *((vu32 *)(0x10400400+0x68)) = FRAMEBUF_TOP_A_1; // framebuf A first address *((vu32 *)(0x10400400+0x6C)) = FRAMEBUF_TOP_A_2; // framebuf A second address *((vu32 *)(0x10400400+0x9C)) = 0x1920000; - *((vu32 *)(0x10400400+0x70)) = 0x80040; // Framebuffer format: main screen, GL_RGBA8_OES + *((vu32 *)(0x10400400+0x70)) = 0x80042; // 0x80040; // Framebuffer format: main screen, GL_RGBA8_OES *((vu32 *)(0x10400400+0x74)) = 0x10700; // gets set to 0x10501 later on *((vu32 *)(0x10400400+0x78)) = 0x70100; // gets set to 0x0 later on *((vu32 *)(0x10400400+0x80)) = 0x0; @@ -78,11 +78,11 @@ *((vu32 *)(0x10400500+0x44)) = 0; *((vu32 *)(0x10400500+0x48)) = 0x11; *((vu32 *)(0x10400500+0x5C)) = 0x14000F0; // framebuf width & height - *((vu32 *)(0x10400500+0x90)) = 0x3C0; // framebuf stride, observed to be 0 + *((vu32 *)(0x10400500+0x90)) = 0x1E0; // 0x3C0; // framebuf stride, observed to be 0 *((vu32 *)(0x10400500+0x68)) = FRAMEBUF_SUB_A_1; // framebuf A first address *((vu32 *)(0x10400500+0x6C)) = FRAMEBUF_SUB_A_2; // framebuf A second address *((vu32 *)(0x10400500+0x9C)) = 0x1920000; - *((vu32 *)(0x10400500+0x70)) = 0x80000; // Framebuffer format: sub screen, GL_RGBA8_OES + *((vu32 *)(0x10400500+0x70)) = 0x80002; // 0x80000; // Framebuffer format: sub screen, GL_RGBA8_OES *((vu32 *)(0x10400500+0x74)) = 0x10700; // gets set to 0x10501 later on *((vu32 *)(0x10400500+0x78)) = 0x70100; // gets set to 0x0 later on *((vu32 *)(0x10400500+0x80)) = 0x0; diff --git a/source/arm11/start.s b/source/arm11/start.s index 03d0d42..6cafffc 100644 --- a/source/arm11/start.s +++ b/source/arm11/start.s @@ -16,7 +16,7 @@ .extern __bss_start__ .extern __bss_end__ -.section .init +.section ".init" diff --git a/source/arm9/console.c b/source/arm9/console.c index bac7930..244bce6 100644 --- a/source/arm9/console.c +++ b/source/arm9/console.c @@ -1,22 +1,41 @@ -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include #include "types.h" -#include "cache.h" #include "gfx.h" #include "console.h" + #include "default_font_bin.h" -#define TAB_SIZE 4 +//set up the palette for color printing +static u16 colorTable[] = { + RGB8_to_565( 0, 0, 0), // black + RGB8_to_565(128, 0, 0), // red + RGB8_to_565( 0,128, 0), // green + RGB8_to_565(128,128, 0), // yellow + RGB8_to_565( 0, 0,128), // blue + RGB8_to_565(128, 0,128), // magenta + RGB8_to_565( 0,128,128), // cyan + RGB8_to_565(192,192,192), // white -ssize_t con_write(struct _reent *r,int fd,const char *ptr, size_t len); + RGB8_to_565(128,128,128), // bright black + RGB8_to_565(255, 0, 0), // bright red + RGB8_to_565( 0,255, 0), // bright green + RGB8_to_565(255,255, 0), // bright yellow + RGB8_to_565( 0, 0,255), // bright blue + RGB8_to_565(255, 0,255), // bright magenta + RGB8_to_565( 0,255,255), // bright cyan + RGB8_to_565(255,255,255), // bright white + + RGB8_to_565( 0, 0, 0), // faint black + RGB8_to_565( 64, 0, 0), // faint red + RGB8_to_565( 0, 64, 0), // faint green + RGB8_to_565( 64, 64, 0), // faint yellow + RGB8_to_565( 0, 0, 64), // faint blue + RGB8_to_565( 64, 0, 64), // faint magenta + RGB8_to_565( 0, 64, 64), // faint cyan + RGB8_to_565( 96, 96, 96), // faint white +}; PrintConsole defaultConsole = { @@ -26,7 +45,7 @@ 0, //first ascii character in the set 256 //number of characters in the font set }, - (u32*)NULL, + (u16*)NULL, 0,0, //cursorX cursorY 0,0, //prevcursorX prevcursorY 40, //console width @@ -36,66 +55,13 @@ 40, //window width 30, //window height 3, //tab size - 15, // foreground color + 7, // foreground color 0, // background color 0, // flags + 0, //print callback false //console initialized }; -static const devoptab_t dotab_stdout = { - "con", - 0, - NULL, - NULL, - con_write, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -// Format: RGBA -static const u32 colorTable[] = -{ - // Normal - 0x00000000, // Black - 0xAA000000, // Red - 0x00AA0000, // Green - 0xAAAA0000, // Yellow - 0x000000AA, // Blue - 0xAA00AA00, // Magenta - 0x00AAAA00, // Cyan - 0xC0C0C000, // Gray - - // Bright - 0xAAAAAA00, // Darkgray - 0xFF000000, // Red - 0x00FF0000, // Green - 0xFFFF0000, // Yellow - 0x0000FF00, // Blue - 0xFF00FF00, // Magenta - 0x00FFFF00, // Cyan - 0xFFFFFF00 // White -}; - PrintConsole currentCopy; PrintConsole* currentConsole = ¤tCopy; @@ -154,9 +120,7 @@ currentConsole->cursorX = 0; break; } - default: ; } - //gfxFlushBuffers(); } //--------------------------------------------------------------------------------- static void consoleClearLine(char mode) { @@ -208,9 +172,7 @@ break; } - default: ; } - //gfxFlushBuffers(); } @@ -227,12 +189,10 @@ i = 0; - while((size_t)i 0x8100000) panic(); // ptr poisoned. if ( chr == 0x1b && *tmp == '[' ) { bool escaping = true; @@ -244,9 +204,6 @@ chr = *(tmp++); i++; count++; escapelen++; int parameter, assigned, consumed; - - if((u32) tmp > 0x8100000) panic(); // ptr poisoned. - if((u32) escapeseq > 0x8100000) panic(); // ptr poisoned. // make sure parameters are positive values and delimited by semicolon if((chr >= '0' && chr <= '9') || chr == ';') @@ -378,12 +335,9 @@ parameter = 0; if (escapelen == 1) { consumed = 1; + } else if (strchr(escapeseq,';')) { + sscanf(escapeseq,"%d;%n", ¶meter, &consumed); } else { - if((u32) escapeseq > 0x8100000) panic(); // ptr poisoned. - if (strchr(escapeseq,';')) { - sscanf(escapeseq,"%d;%n", ¶meter, &consumed); - } - else sscanf(escapeseq,"%dm%n", ¶meter, &consumed); } @@ -468,7 +422,7 @@ break; case 30 ... 37: // writing color - currentConsole->fg = (u32)parameter - 30; + currentConsole->fg = parameter - 30; break; case 39: // reset foreground color @@ -476,13 +430,12 @@ break; case 40 ... 47: // screen color - currentConsole->bg = (u32)parameter - 40; + currentConsole->bg = parameter - 40; break; case 49: // reset background color currentConsole->fg = 0; break; - default: ; } } while (escapelen > 0); @@ -501,18 +454,44 @@ consolePrintChar(chr); } - //flushDCacheRange((void*)FRAMEBUF_TOP_A_1, 0xA8C00); - return count; } +static const devoptab_t dotab_stdout = { + "con", + 0, + NULL, + NULL, + con_write, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; static const devoptab_t dotab_null = { "null", 0, NULL, NULL, - con_write, + NULL, NULL, NULL, NULL, @@ -541,11 +520,11 @@ //--------------------------------------------------------------------------------- static bool firstConsoleInit = true; - + if(firstConsoleInit) { devoptab_list[STD_OUT] = &dotab_stdout; devoptab_list[STD_ERR] = &dotab_stdout; - + setvbuf(stdout, NULL , _IONBF, 0); setvbuf(stderr, NULL , _IONBF, 0); @@ -563,12 +542,12 @@ console->consoleInitialised = 1; if(screen==1) { - console->frameBuffer = (u32*)FRAMEBUF_TOP_A_1; + console->frameBuffer = (u16*)FRAMEBUF_TOP_A_1; console->consoleWidth = 50; console->windowWidth = 50; } - else - console->frameBuffer = (u32*)FRAMEBUF_SUB_A_1; + else console->frameBuffer = (u16*)FRAMEBUF_SUB_A_1; + consoleCls('2'); @@ -604,21 +583,20 @@ if(currentConsole->cursorY >= currentConsole->windowHeight) { currentConsole->cursorY --; - u32 *dst = ¤tConsole->frameBuffer[(currentConsole->windowX * 8 * 240) + (239 - (currentConsole->windowY * 8))]; - u32 *src = dst - 8; + u16 *dst = ¤tConsole->frameBuffer[(currentConsole->windowX * 8 * 240) + (239 - (currentConsole->windowY * 8))]; + u16 *src = dst - 8; int i,j; for (i=0; iwindowWidth*8; i++) { - u32 *from = src; - u32 *to = dst; - for (j=0;j<((currentConsole->windowHeight-1)*8);j++) *(to--) = *(from--); + u32 *from = (u32*)((int)src & ~3); + u32 *to = (u32*)((int)dst & ~3); + for (j=0;j<(((currentConsole->windowHeight-1)*8)/2);j++) *(to--) = *(from--); dst += 240; src += 240; } consoleClearLine('2'); - //gfxFlushBuffers(); } } //--------------------------------------------------------------------------------- @@ -627,10 +605,10 @@ c -= currentConsole->font.asciiOffset; if ( c < 0 || c > currentConsole->font.numChars ) return; - const u8 *fontdata = currentConsole->font.gfx + (8 * c); + u8 *fontdata = currentConsole->font.gfx + (8 * c); - u32 writingColor = currentConsole->fg; - u32 screenColor = currentConsole->bg; + int writingColor = currentConsole->fg; + int screenColor = currentConsole->bg; if (currentConsole->flags & CONSOLE_COLOR_BOLD) { writingColor += 8; @@ -639,13 +617,13 @@ } if (currentConsole->flags & CONSOLE_COLOR_REVERSE) { - u32 tmp = writingColor; + int tmp = writingColor; writingColor = screenColor; screenColor = tmp; } - u32 bg = colorTable[screenColor]; - u32 fg = colorTable[writingColor]; + u16 bg = colorTable[screenColor]; + u16 fg = colorTable[writingColor]; u8 b1 = *(fontdata++); u8 b2 = *(fontdata++); @@ -668,7 +646,7 @@ int x = (currentConsole->cursorX + currentConsole->windowX) * 8; int y = ((currentConsole->cursorY + currentConsole->windowY) *8 ); - u32 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; + u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; for (i=0;i<8;i++) { if (b8 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; } @@ -690,6 +668,10 @@ //--------------------------------------------------------------------------------- if (c==0) return; + if(currentConsole->PrintChar) + if(currentConsole->PrintChar(currentConsole, c)) + return; + if(currentConsole->cursorX >= currentConsole->windowWidth) { currentConsole->cursorX = 0; @@ -728,7 +710,6 @@ newRow(); case 13: currentConsole->cursorX = 0; - //gfxFlushBuffers(); break; default: consoleDrawChar(c); @@ -778,13 +759,13 @@ printf("starty: %i\n", starty); */ - u32 color = colorTable[colorIndex]; + u16 color = colorTable[colorIndex]; // upper line for(int y = starty; y < starty + thickness; y++) for(int x = startx; x < endx; x++) { - u32 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; + u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; *screen = color; } @@ -792,7 +773,7 @@ for(int y = endy; y > endy - thickness; y--) for(int x = startx; x < endx; x++) { - u32 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; + u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))]; *screen = color; } @@ -801,7 +782,7 @@ { for(int i = 0; i < thickness; i++) { - u32 *screen = ¤tConsole->frameBuffer[((startx + i) * 240) + (239 - (y + 7))]; + u16 *screen = ¤tConsole->frameBuffer[((startx + i) * 240) + (239 - (y + 7))]; *screen = color; screen = ¤tConsole->frameBuffer[((endx - thickness + i) * 240) + (239 - (y + 7))]; *screen = color; diff --git a/source/arm9/debug.c b/source/arm9/debug.c index 79c643a..45d5431 100644 --- a/source/arm9/debug.c +++ b/source/arm9/debug.c @@ -11,10 +11,10 @@ void hashCodeRoData() { - extern u32 *__text_start; + extern u32 *__start__; extern u32 *__exidx_start; - u32 *start = __text_start; + u32 *start = __start__; u32 *end = __exidx_start; debugHash = 0; diff --git a/source/arm9/start.s b/source/arm9/start.s index 8456715..9ef2a77 100644 --- a/source/arm9/start.s +++ b/source/arm9/start.s @@ -23,7 +23,7 @@ .extern fake_heap_start .extern fake_heap_end -.section .init +.section ".init" diff --git a/source/arm9/system.s b/source/arm9/system.s index 2019e99..979e93d 100644 --- a/source/arm9/system.s +++ b/source/arm9/system.s @@ -17,6 +17,8 @@ .extern prefetchAbortHandler .extern dataAbortHandler +.section ".init" + setupSystem: