From 213977f7fccafbe76d820102793f1c117f9c70f8 Mon Sep 17 00:00:00 2001 From: retro100 Date: Fri, 30 Apr 2021 19:31:18 +0200 Subject: [PATCH] Add virtual console to menu to show logs/messages from dosbox. --- src/debug/debug_gui.cpp | 3 + src/dos/dos_programs.cpp | 3 + src/gui/sdlmain.cpp | 27 ++++ src/platform/wii/filelist.h | 8 + src/platform/wii/font8x8_basic.h | 158 ++++++++++++++++++++ src/platform/wii/font8x8_to_png.c.txt | 131 ++++++++++++++++ src/platform/wii/images/bg_console.png | Bin 0 -> 3107 bytes src/platform/wii/images/font8x8_basic.png | Bin 0 -> 1730 bytes src/platform/wii/libwiigui/gui.h | 58 +++++++ src/platform/wii/libwiigui/gui_monotext.cpp | 156 +++++++++++++++++++ src/platform/wii/libwiigui/gui_text.cpp | 1 + src/platform/wii/menu.cpp | 97 ++++++++++++ src/platform/wii/pngu.c | 1 + src/platform/wii/stdio_wrapper.h | 17 +++ src/platform/wii/vconsole.c | 133 ++++++++++++++++ src/platform/wii/vconsole.h | 67 +++++++++ src/platform/wii/wiihardware.cpp | 2 + src/platform/wii/wiiio.c | 90 +++++++++++ src/platform/wii/wiiio.h | 34 +++++ 19 files changed, 986 insertions(+) create mode 100644 src/platform/wii/font8x8_basic.h create mode 100644 src/platform/wii/font8x8_to_png.c.txt create mode 100644 src/platform/wii/images/bg_console.png create mode 100644 src/platform/wii/images/font8x8_basic.png create mode 100644 src/platform/wii/libwiigui/gui_monotext.cpp create mode 100644 src/platform/wii/stdio_wrapper.h create mode 100644 src/platform/wii/vconsole.c create mode 100644 src/platform/wii/vconsole.h create mode 100644 src/platform/wii/wiiio.c create mode 100644 src/platform/wii/wiiio.h diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index 8905144..fe2990c 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -32,6 +32,9 @@ #include "regs.h" #include "debug.h" #include "debug_inc.h" +#ifdef HW_RVL +#include +#endif struct _LogGroup { char const* front; diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 56928d0..b7a5601 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -38,6 +38,9 @@ #include "control.h" #include "inout.h" #include "dma.h" +#ifdef HW_RVL +#include +#endif #if defined(OS2) diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 467088f..94fcb56 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -34,6 +34,7 @@ #ifdef HW_RVL #include #include +#include #endif #include "cross.h" @@ -53,6 +54,9 @@ #include "cpu.h" #include "cross.h" #include "control.h" +#ifdef HW_RVL +#include +#endif #define MAPPERFILE "mapper-" VERSION ".map" //#define DISABLE_JOYSTICK @@ -1770,6 +1774,16 @@ static BOOL WINAPI ConsoleEventHandler(DWORD event) { * Fixes some bugs when -noconsole is used in a read only directory */ static bool no_stdout = false; void GFX_ShowMsg(char const* format,...) { +#ifdef HW_RVL + if (no_stdout) { + return; + } + va_list msg; + va_start(msg,format); + wiiio_vprintf(format, msg); + va_end(msg); + wiiio_print("\n"); +#else char buf[512]; va_list msg; @@ -1779,6 +1793,7 @@ void GFX_ShowMsg(char const* format,...) { buf[sizeof(buf) - 1] = '\0'; if (!no_stdout) puts(buf); //Else buf is parsed again. (puts adds end of line) +#endif } @@ -2052,6 +2067,18 @@ int main(int argc, char* argv[]) { try { #ifdef HW_RVL WiiInit(); + if (argc > 0) { + wiiio_print("args:"); + for (int i = 0; i < argc; ++i) { + if (argv[i] != NULL) { + wiiio_printf(" %s", argv[i]); + } + else { + wiiio_print(" (null)"); + } + } + wiiio_print("\n\n"); + } if(argc > 0 && argv[0] != NULL) CreateAppPath(argv[0]); #endif diff --git a/src/platform/wii/filelist.h b/src/platform/wii/filelist.h index c9160ec..cf51c4a 100644 --- a/src/platform/wii/filelist.h +++ b/src/platform/wii/filelist.h @@ -72,6 +72,12 @@ extern const u32 battery_bar_png_size; extern const u8 credits_box_png[]; extern const u32 credits_box_png_size; +extern const u8 bg_console_png[]; +extern const u32 bg_console_png_size; + +extern const u8 font8x8_basic_png[]; +extern const u32 font8x8_basic_png_size; + extern const u8 keyboard_textbox_png[]; extern const u32 keyboard_textbox_png_size; @@ -134,6 +140,8 @@ extern const u32 player4_point_png_size; #include "battery_bar_png.h" #include "credits_box_png.h" +#include "bg_console_png.h" +#include "font8x8_basic_png.h" #include "keyboard_textbox_png.h" #include "keyboard_key_png.h" diff --git a/src/platform/wii/font8x8_basic.h b/src/platform/wii/font8x8_basic.h new file mode 100644 index 0000000..98448cf --- /dev/null +++ b/src/platform/wii/font8x8_basic.h @@ -0,0 +1,158 @@ +// see https://raw.githubusercontent.com/dhepper/font8x8/master/font8x8_basic.h +// changes: +// change type for font8x8_basic from char to unsigned char + +// header file only used by the converter program font8x8_to_png.c.txt + +/** + * 8x8 monochrome bitmap fonts for rendering + * Author: Daniel Hepper + * + * License: Public Domain + * + * Based on: + * // Summary: font8x8.h + * // 8x8 monochrome bitmap fonts for rendering + * // + * // Author: + * // Marcel Sondaar + * // International Business Machines (public domain VGA fonts) + * // + * // License: + * // Public Domain + * + * Fetched from: http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm + **/ + +// Constant: font8x8_basic +// Contains an 8x8 font map for unicode points U+0000 - U+007F (basic latin) +unsigned char font8x8_basic[128][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space) + { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!) + { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (") + { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#) + { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($) + { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%) + { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&) + { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (') + { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (() + { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ()) + { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*) + { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,) + { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.) + { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/) + { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0) + { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1) + { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2) + { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3) + { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4) + { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5) + { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6) + { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7) + { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8) + { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9) + { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:) + { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//) + { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<) + { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=) + { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>) + { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?) + { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@) + { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A) + { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B) + { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C) + { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D) + { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E) + { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F) + { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G) + { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H) + { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I) + { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J) + { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K) + { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L) + { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M) + { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N) + { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O) + { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P) + { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q) + { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R) + { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S) + { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T) + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U) + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V) + { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W) + { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X) + { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y) + { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z) + { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([) + { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\) + { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (]) + { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_) + { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`) + { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a) + { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b) + { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c) + { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d) + { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e) + { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f) + { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g) + { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h) + { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i) + { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j) + { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k) + { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l) + { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m) + { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n) + { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o) + { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p) + { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q) + { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r) + { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s) + { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v) + { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w) + { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x) + { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y) + { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z) + { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({) + { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|) + { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (}) + { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F +}; diff --git a/src/platform/wii/font8x8_to_png.c.txt b/src/platform/wii/font8x8_to_png.c.txt new file mode 100644 index 0000000..587646d --- /dev/null +++ b/src/platform/wii/font8x8_to_png.c.txt @@ -0,0 +1,131 @@ +// a simple hack for convert the monospace font from font8x8_basic.h into a png file + +// rename font8x8_to_png.c.txt to font8x8_to_png.c and +// compile with gcc -Wall font8x8_to_png.c -lpng -o font8x8_to_png +// to create the png file font8x8_basic.png execute following command: +// ./font8x8_to_png font8x8_basic.png + +#include +#include +#include +#include "font8x8_basic.h" + +// return 1 for error +int writeImage(char* filename, int width, int height, float *buffer, char* title) +{ + FILE *fp = fopen(filename, "wb"); + if (!fp) { + fprintf(stderr, "Could not open file %s for writing\n", filename); + return 1; + } + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fprintf(stderr, "Could not allocate write struct\n"); + fclose(fp); + return 1; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fprintf(stderr, "Could not allocate info struct\n"); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(fp); + return 1; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + fprintf(stderr, "Error during png creation\n"); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(fp); + return 1; + } + + png_init_io(png_ptr, fp); + + // Write header + png_set_IHDR(png_ptr, info_ptr, width, height, 8, + PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (title) { + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.key = "Title"; + title_text.text = title; + png_set_text(png_ptr, info_ptr, &title_text, 1); + } + + png_write_info(png_ptr, info_ptr); + + png_bytep row = (png_bytep) malloc(4 * width * sizeof(png_byte)); + + for (int y = 0 ; y < height ; ++y) { + for (int x = 0 ; x < width ; ++x) { + row[x*4] = buffer[(y*width + x)*4]; + row[x*4+1] = buffer[(y*width + x)*4+1]; + row[x*4+2] = buffer[(y*width + x)*4+2]; + row[x*4+3] = buffer[(y*width + x)*4+3]; + } + png_write_row(png_ptr, row); + } + + // End write + png_write_end(png_ptr, NULL); + + + free(row); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + fclose(fp); + + return 0; +} + +#define FONT_WIDTH 8 +#define FONT_HEIGHT 8 +#define SPACE_LEFT 1 +#define SPACE_RIGHT 1 +#define SPACE_TOP 1 +#define SPACE_BOTTOM 1 + +#define CHARCOUNT_X 16 +#define CHARCOUNT_Y 6 +#define FIRST_CHAR 32 // space 0x20 + +int main(int argc, char**argv) { + if (argc < 2) { + printf("no filename for writing a png file\n"); + return 1; + } + // 96 chars from 32 to 127 + // 16 chars per row + // --> 16x6 + int width = (FONT_WIDTH + SPACE_LEFT + SPACE_RIGHT) * CHARCOUNT_X; + int height = (FONT_HEIGHT + SPACE_TOP + SPACE_BOTTOM) * CHARCOUNT_Y; + float *buffer = calloc(sizeof(float), width * height * 4); + for (int ci = FIRST_CHAR; ci < 128; ++ci) { + int cx = (ci - FIRST_CHAR) % CHARCOUNT_X; + int cy = (ci - FIRST_CHAR) / CHARCOUNT_X; + unsigned char* glyph = font8x8_basic[ci]; + for (int gy = 0; gy < FONT_HEIGHT; ++gy) { + unsigned char glyph_row = glyph[gy]; + for (int gx = 0; gx < FONT_WIDTH; ++gx) { + unsigned char bitflag = 1 << gx; + int is_used = (glyph_row & bitflag); + int x = cx * (FONT_WIDTH + SPACE_LEFT + SPACE_RIGHT) + SPACE_LEFT + gx; + int y = cy * (FONT_HEIGHT + SPACE_TOP + SPACE_BOTTOM) + SPACE_TOP + gy; + int offset = (y*width +x)*4; + //buffer[offset] = is_used ? 255.0f : 0.0f; + buffer[offset] = 255.0f; + buffer[offset + 1] = 255.0f; + buffer[offset + 2] = 255.0f; + buffer[offset + 3] = is_used ? 255.0f : 0.0f; + } + } + + } + writeImage(argv[1], width, height, buffer, "font8x8_basic"); + return 0; +} diff --git a/src/platform/wii/images/bg_console.png b/src/platform/wii/images/bg_console.png new file mode 100644 index 0000000000000000000000000000000000000000..ddac0c0a4e3a7b8558488cd74ce353d720d39e72 GIT binary patch literal 3107 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 #include #include +#include #include #include #include @@ -636,6 +637,63 @@ class GuiImage : public GuiElement int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture }; +typedef struct vconsole vconsole_t; + +// by retro100 +// The class GuiMonoText is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. +class GuiMonoText : public GuiImage +{ + public: + //! Constructor + //! + //! The full glyph width is glyphMarginLeft + glyphWidth + glyphMarginRight + //! The full glyph height is glyphMarginTop + glyphHeight + glyphMarginBottom + //! + //!\param glyphCountX Count of glyphs in X direction inside the image/tileset + //!\param glyphCountY Count of glyphs in Y direction inside the image/tileset + //!\param firstGlyphAsciiCode e.g. 0 if all 128 glyphs are inside or 32 if the first glyph is a blank + //!\param glyphWidth width of one glyph in pixels WITHOUT extra margin between glyphs + //!\param glyphHeight height of one glyph in pixels without margin + //!\param glyphMarginLeft extra margin at the left side of each glyph (e.g. 0 or 1 px) + //!\param glyphMarginRight extra margin at the right side of each glyph (e.g. 0 or 1 px) + //!\param glyphMarginTop extra margin at the top side of each glyph (e.g. 0 or 1 px) + //!\param glyphMarginBottom extra margin at the bottom side of each glyph (e.g. 0 or 1 px) + GuiMonoText(GuiImageData * img, + unsigned int glyphCountX, + unsigned int glyphCountY, + unsigned int firstGlyphAsciiCode, + unsigned int glyphWidth, + unsigned int glyphHeight, + unsigned int glyphMarginLeft, + unsigned int glyphMarginRight, + unsigned int glyphMarginTop, + unsigned int glyphMarginBottom); + ~GuiMonoText(); + void SetText(const std::string& text); + void SetVirtualConsole(vconsole_t* vc, float lineSpace); + virtual void Draw(); + private: + unsigned int glyphCountX; + unsigned int glyphCountY; + char firstGlyphAsciiCode; + float glyphWidthF; + float glyphHeightF; + float glyphMarginLeftF; + float glyphMarginTopF; + float fullGlyphWidthF; + float fullGlyphHeightF; + float texFullGlyphWidth; + float texFullGlyphHeight; + std::string text; + vconsole_t* vc; + float lineSpace; + + void DrawText(float xpos, float ypos, const char* str); + void DrawVirtualConsole(float xpos, float ypos); +}; + //!Display, manage, and manipulate text in the GUI class GuiText : public GuiElement { diff --git a/src/platform/wii/libwiigui/gui_monotext.cpp b/src/platform/wii/libwiigui/gui_monotext.cpp new file mode 100644 index 0000000..67ee5b9 --- /dev/null +++ b/src/platform/wii/libwiigui/gui_monotext.cpp @@ -0,0 +1,156 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#include "gui.h" +#include "../vconsole.h" + +GuiMonoText::GuiMonoText(GuiImageData * img, + unsigned int glyphCountX, + unsigned int glyphCountY, + unsigned int firstGlyphAsciiCode, + unsigned int glyphWidth, + unsigned int glyphHeight, + unsigned int glyphMarginLeft, + unsigned int glyphMarginRight, + unsigned int glyphMarginTop, + unsigned int glyphMarginBottom) + :GuiImage(img), + glyphCountX(glyphCountX), + glyphCountY(glyphCountY), + firstGlyphAsciiCode(firstGlyphAsciiCode), + text(), + vc(NULL), + lineSpace(0.0f) +{ + unsigned int fullGlyphWidth = glyphMarginLeft + glyphWidth + glyphMarginRight; + unsigned int fullGlyphHeight = glyphMarginTop + glyphHeight + glyphMarginBottom; + unsigned int tilesetWidth = fullGlyphWidth * glyphCountX; + unsigned int tilesetHeight = fullGlyphHeight * glyphCountY; + // Normally tilesetWidth should have the same value as the image width and + // tilesetHeight should have the same value as the image height. + // Only if the tileset image has a extra border (free space) at the right side + // and/or at the bottom then the values are different. (which is also no problem) + + float texTilesetWidth = (float)tilesetWidth / (float)width; + float texTilesetHeight = (float)tilesetHeight / (float)height; + texFullGlyphWidth = texTilesetWidth / (float) glyphCountX; + texFullGlyphHeight = texTilesetHeight / (float) glyphCountY; + glyphWidthF = glyphWidth; + glyphHeightF = glyphHeight; + glyphMarginLeftF = glyphMarginLeft; + glyphMarginTopF = glyphMarginTop; + fullGlyphWidthF = fullGlyphWidth; + fullGlyphHeightF = fullGlyphHeight; +} + +GuiMonoText::~GuiMonoText() +{ +} + +void GuiMonoText::SetText(const std::string& text) +{ + this->text = text; +} + +void GuiMonoText::SetVirtualConsole(vconsole_t* vc, float lineSpace) +{ + this->vc = vc; + this->lineSpace = lineSpace; +} + +void GuiMonoText::Draw() +{ + if(!image || !this->IsVisible() || (text.empty() && !vc)) + return; + + f32 xpos = this->GetLeft(); + f32 ypos = this->GetTop(); + u8* data = image; + //u8 alpha = this->GetAlpha(); + + GXTexObj texObj; + + GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE); + GX_LoadTexObj(&texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + if (vc) { + DrawVirtualConsole(xpos, ypos); + } + else { + DrawText(xpos, ypos, text.c_str()); + } + + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); +} + +void GuiMonoText::DrawText(float xpos, float ypos, const char* str) +{ + size_t count = strlen(str); + + xpos -= glyphMarginLeftF; + ypos -= glyphMarginTopF; + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4 * count); + + for (size_t i = 0; i < count; ++i, xpos += glyphWidthF) { + unsigned char ch = (unsigned char)str[i]; + if (ch < firstGlyphAsciiCode || ch >= 128) { + ch = '?'; + } + unsigned int glyphIndex = ch - firstGlyphAsciiCode; + unsigned int xi = glyphIndex % glyphCountX; + unsigned int yi = glyphIndex / glyphCountX; + float texX = float(xi) * texFullGlyphWidth; + float texY = float(yi) * texFullGlyphHeight; + + // left top + GX_Position3f32(xpos, ypos, 0); + GX_Color4u8(0x00, 0x00, 0x00, alpha); + GX_TexCoord2f32(texX, texY); + + // right top + GX_Position3f32(xpos + fullGlyphWidthF, ypos, 0); + GX_Color4u8(0x00, 0x00, 0x00, alpha); + GX_TexCoord2f32(texX + texFullGlyphWidth, texY); + + // right bottom + GX_Position3f32(xpos + fullGlyphWidthF, ypos + fullGlyphHeightF, 0); + GX_Color4u8(0x00, 0x00, 0x00, alpha); + GX_TexCoord2f32(texX + texFullGlyphWidth, texY + texFullGlyphHeight); + + // left bottom + GX_Position3f32(xpos, ypos + fullGlyphHeightF, 0); + GX_Color4u8(0x00, 0x00, 0x00, alpha); + GX_TexCoord2f32(texX, texY + texFullGlyphHeight); + } + + GX_End(); +} + +void GuiMonoText::DrawVirtualConsole(float xpos, float ypos) +{ + int current_line_count = vc->line_count; + int current_line_index = vc->vc_current_line_index; + + if (current_line_count < VCONSOLE_HEIGHT) { + for (int i = 0; i <= current_line_index; ++i, ypos += glyphHeightF + lineSpace) { + DrawText(xpos, ypos, vc->vc_text_lines[i]); + } + } + else { + for (int i = current_line_index + 1; i < VCONSOLE_HEIGHT; ++i, ypos += glyphHeightF + lineSpace) { + DrawText(xpos, ypos, vc->vc_text_lines[i]); + } + for (int i = 0; i <= current_line_index; ++i, ypos += glyphHeightF + lineSpace) { + DrawText(xpos, ypos, vc->vc_text_lines[i]); + } + } +} + diff --git a/src/platform/wii/libwiigui/gui_text.cpp b/src/platform/wii/libwiigui/gui_text.cpp index 88e277c..54a7d4d 100644 --- a/src/platform/wii/libwiigui/gui_text.cpp +++ b/src/platform/wii/libwiigui/gui_text.cpp @@ -38,6 +38,7 @@ GuiText::GuiText(const char * t, int s, GXColor c) color = c; alpha = c.a; style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE; + monoPercentage = 100; maxWidth = 0; wrap = false; textDynNum = 0; diff --git a/src/platform/wii/menu.cpp b/src/platform/wii/menu.cpp index 750bc38..432f854 100644 --- a/src/platform/wii/menu.cpp +++ b/src/platform/wii/menu.cpp @@ -21,6 +21,8 @@ #include "wiihardware.h" #include "menu.h" #include "cpu.h" +#include "vconsole.h" +#include "wiiio.h" #define THREAD_SLEEP 100 #define APPVERSION "1.7" @@ -131,6 +133,81 @@ HaltGui() guithread = LWP_THREAD_NULL; } +static void OnScreenConsole() +{ + vconsole_t& vc = *wiiio_get_vconsole(); + GuiWindow terminal(screenwidth, screenheight); + + GuiImageData backgroundData(bg_console_png); + GuiImage backgroundImg(&backgroundData); + backgroundImg.SetParent(&terminal); + backgroundImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + backgroundImg.SetPosition(23, 38); + terminal.Append(&backgroundImg); + + GuiImageData fontData(font8x8_basic_png); + GuiMonoText terminalOutput(&fontData, + 16, //glyphCountX + 6, //glyphCountY + 32, //firstGlyphAsciiCode + 8, //glyphWidth + 8, //glyphHeight + 1, //glyphMarginLeft + 1, //glyphMarginRight + 1, //glyphMarginTop + 1); //glyphMarginBottom + terminalOutput.SetParent(&terminal); + terminalOutput.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + terminalOutput.SetPosition(31, 48); + terminalOutput.SetVirtualConsole(&vc, 2.0f); + terminal.Append(&terminalOutput); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiText okBtnTxt("Close", 22, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(80, -35); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetTrigger(&trigA); + okBtn.SetEffectGrow(); + + terminal.Append(&okBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&terminal); + mainWindow->ChangeFocus(&terminal); + ResumeGui(); + + for (;;) { + usleep(THREAD_SLEEP); + + if(okBtn.GetState() == STATE_CLICKED) { + break; + // for testing: comment the break and uncomment this. + //okBtn.ResetState(); + //vconsole_print(&vc, "012345678901234567890123456789"); + } + } + + HaltGui(); + mainWindow->Remove(&terminal); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + /**************************************************************************** * OnScreenKeyboard * @@ -473,6 +550,20 @@ void HomeMenu () exitBtn.SetTrigger(&trigA); exitBtn.SetEffectGrow(); + GuiText logBtnTxt("Logging", 24, (GXColor){0, 0, 0, 255}); + GuiImage logBtnImg(&btnLargeOutline); + GuiImage logBtnImgOver(&btnLargeOutlineOver); + GuiButton logBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + logBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + logBtn.SetPosition(-125, 240); + logBtn.SetLabel(&logBtnTxt); + logBtn.SetImage(&logBtnImg); + logBtn.SetImageOver(&logBtnImgOver); + logBtn.SetSoundOver(&btnSoundOver); + logBtn.SetSoundClick(&btnSoundClick); + logBtn.SetTrigger(&trigA); + logBtn.SetEffectGrow(); + GuiText keyboardBtnTxt("Keyboard", 24, (GXColor){0, 0, 0, 255}); GuiImage keyboardBtnImg(&btnLargeOutline); GuiImage keyboardBtnImgOver(&btnLargeOutlineOver); @@ -556,6 +647,7 @@ void HomeMenu () w.Append(logoBtn); w.Append(&closeBtn); w.Append(&exitBtn); + w.Append(&logBtn); w.Append(&cycleText); w.Append(&fskipText); w.Append(&cycleDecBtn); @@ -645,6 +737,11 @@ void HomeMenu () { ExitRequested = 1; } + else if(logBtn.GetState() == STATE_CLICKED) + { + logBtn.ResetState(); + OnScreenConsole(); + } else if(keyboardBtn.GetState() == STATE_CLICKED) { keyboardBtn.ResetState(); diff --git a/src/platform/wii/pngu.c b/src/platform/wii/pngu.c index acc0e03..f3455c3 100644 --- a/src/platform/wii/pngu.c +++ b/src/platform/wii/pngu.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pngu.h" #include diff --git a/src/platform/wii/stdio_wrapper.h b/src/platform/wii/stdio_wrapper.h new file mode 100644 index 0000000..b663769 --- /dev/null +++ b/src/platform/wii/stdio_wrapper.h @@ -0,0 +1,17 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#ifndef STDIO_WRAPPER_H +#define STDIO_WRAPPER_H + +#include "wiiio.h" + +#ifdef printf +#undef printf +#endif + +#define printf(fmt, ...) wiiio_printf(fmt, ##__VA_ARGS__) + +#endif diff --git a/src/platform/wii/vconsole.c b/src/platform/wii/vconsole.c new file mode 100644 index 0000000..385e534 --- /dev/null +++ b/src/platform/wii/vconsole.c @@ -0,0 +1,133 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#include "vconsole.h" + +#include +#include +#include +#include + +#define MAX_PRINTF_LEN 512 + +static void vc_jump_to_next_line(vconsole_t* vc) { + // terminate the current line + vc->vc_current_line[vc->vc_current_xpos_cursor_position] = '\0'; + + // jump to next line + vc->vc_current_xpos_cursor_position = 0; + vc->explicit_new_line = 0; + // increase vc_current_line_index to a tmp variable and + // only update to the increased value if it is allowed + // --> Avoids a momentary invalid value at vc->vc_current_line_index. + // --> Race conditions not really a problem (no sync is needed). + int next_line_index = vc->vc_current_line_index + 1; + if (next_line_index >= VCONSOLE_HEIGHT) { + vc->vc_current_line_index = 0; + } + else { + vc->vc_current_line_index = next_line_index; + } + vc->vc_current_line = vc->vc_text_lines[vc->vc_current_line_index]; + + // clear the line content of the new line. + // Using memset instead of simple + // vc_current_line[vc_current_xpos_cursor_position] = '\0'; + // because if there are race conditions of different threads + // at the current line then it always has a termination + // at any position. + memset(vc->vc_current_line, 0, VCONSOLE_WIDTH); + + ++vc->line_count; +} + +void vconsole_init(vconsole_t* vc) +{ + memset(vc->vc_text_lines, 0, sizeof(vc->vc_text_lines)); + //memset(vc->vc_text_lines, 0, VCONSOLE_HEIGHT * VCONSOLE_WIDTH); + vc->vc_current_line_index = 0; + vc->vc_current_xpos_cursor_position = 0; + vc->explicit_new_line = 1; + vc->vc_current_line = vc->vc_text_lines[0]; + vc->line_count = 0; +} + +void vconsole_destroy(vconsole_t* vc) +{ + // currently nothing to to +} + +int vconsole_printf(vconsole_t* vc, const char *format, ...) +{ + va_list args; + va_start (args, format); + int rv = vconsole_vprintf(vc, format, args); + va_end (args); + return rv; +} + +int vconsole_vprintf(vconsole_t* vc, const char *format, va_list ap) +{ + char msg[MAX_PRINTF_LEN]; + vsnprintf(msg, MAX_PRINTF_LEN, format, ap); + msg[MAX_PRINTF_LEN - 1] = '\0'; + return vconsole_print(vc, msg); +} + +int vconsole_print(vconsole_t* vc, const char* text) +{ + size_t len = strlen(text); + vconsole_write(vc, text, len); + return len; +} + +void vconsole_write(vconsole_t* vc, const void* buf, unsigned int len) +{ + const char* text = buf; + for (unsigned int i = 0; i < len; ++i) { + char ch = text[i]; + if (ch == '\0') { + // ignore it + } + else if (ch == '\n') { + if (vc->vc_current_xpos_cursor_position > 0 || vc->explicit_new_line) { + vc_jump_to_next_line(vc); + vc->explicit_new_line = 1; + } + } + else if (ch == '\r') { + // ignore it. + // --> For a new line \r\n or \n must be used. + // Only \r makes no new line. + } + else if (ch == '\t') { + if (vc->vc_current_xpos_cursor_position >= VCONSOLE_WIDTH - 4) { + vc_jump_to_next_line(vc); + } + vc->vc_current_line[vc->vc_current_xpos_cursor_position] += ' '; + vc->vc_current_line[vc->vc_current_xpos_cursor_position + 1] += ' '; + vc->vc_current_line[vc->vc_current_xpos_cursor_position + 2] += ' '; + vc->vc_current_line[vc->vc_current_xpos_cursor_position + 3] += ' '; + + vc->vc_current_xpos_cursor_position += 4; + if (vc->vc_current_xpos_cursor_position >= VCONSOLE_WIDTH - 1) { + vc_jump_to_next_line(vc); + } + } + else { + if (ch < 0x20 || ch >= 0x7f) { + ch = '?'; + } + vc->vc_current_line[vc->vc_current_xpos_cursor_position] = ch; + ++vc->vc_current_xpos_cursor_position; + if (vc->vc_current_xpos_cursor_position >= VCONSOLE_WIDTH - 1) { + vc_jump_to_next_line(vc); + } + } + } + // terminate the new added content + vc->vc_current_line[vc->vc_current_xpos_cursor_position] = '\0'; +} + diff --git a/src/platform/wii/vconsole.h b/src/platform/wii/vconsole.h new file mode 100644 index 0000000..85b1b11 --- /dev/null +++ b/src/platform/wii/vconsole.h @@ -0,0 +1,67 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#ifndef VCONSOLE_H +#define VCONSOLE_H + +#include + +#define VCONSOLE_WIDTH 73 // usable are 72 +#define VCONSOLE_HEIGHT 33 + +/* +by retro100 + +If the macro SHOW_DEBUGVC is defined then +a virtual console with a size of 86x40 can +be used to print messages. +The output of the virtual console scrolls +if a new line is added. +\n and also \t are supported. +The font is NOT monospace. The effective length +of the rendered output depends on the used characters. +*/ + +#ifdef SHOW_DEBUGVC +#define DEBUG_vc_printf(fmt, ...) DEBUG_vc_printf__(fmt, ##__VA_ARGS__) +#define DEBUG_vc_print(text) DEBUG_vc_print__(text) +#define DEBUG_vc_render_console_with_init(r, g, b, a) DEBUG_vc_render_console_with_init__(r, g, b, a) +#define DEBUG_vc_render_console() DEBUG_vc_render_console__() +#else +#define DEBUG_vc_printf(fmt, ...) +#define DEBUG_vc_print(fmt, ...) +#define DEBUG_vc_render_console_with_init(r, g, b, a) +#define DEBUG_vc_render_console() +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vconsole +{ + char vc_text_lines[VCONSOLE_HEIGHT][VCONSOLE_WIDTH]; + int vc_current_line_index; + int vc_current_xpos_cursor_position; + int explicit_new_line; + char *vc_current_line; + int line_count; +} vconsole_t; + +void vconsole_init(vconsole_t* vc); +void vconsole_destroy(vconsole_t* vc); +int vconsole_printf(vconsole_t* vc, const char *format, ...) + __attribute__ ((format(printf, 2, 3))); +int vconsole_vprintf(vconsole_t* vc, const char *format, va_list ap); +int vconsole_print(vconsole_t* vc, const char* text); +void vconsole_write(vconsole_t* vc, const void* buf, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/platform/wii/wiihardware.cpp b/src/platform/wii/wiihardware.cpp index f4da19c..b120235 100644 --- a/src/platform/wii/wiihardware.cpp +++ b/src/platform/wii/wiihardware.cpp @@ -21,6 +21,7 @@ #include "input.h" #include "filelist.h" #include "SDL_events.h" +#include "wiiio.h" extern "C" { extern void __exception_setreload(int t); @@ -205,6 +206,7 @@ void WiiInit() extern const devoptab_t dotab_stdnull; devoptab_list[STD_OUT] = &dotab_stdnull; devoptab_list[STD_ERR] = &dotab_stdnull; + wiiio_init(); //USBGeckoOutput(); // uncomment to enable USB gecko output __exception_setreload(8); fatInitDefault(); diff --git a/src/platform/wii/wiiio.c b/src/platform/wii/wiiio.c new file mode 100644 index 0000000..379aedc --- /dev/null +++ b/src/platform/wii/wiiio.c @@ -0,0 +1,90 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "wiiio.h" +#include "vconsole.h" +#include +#include + +static vconsole_t* vc = NULL; + +static ssize_t vc_memfile_write(void *c, const char *buf, size_t size) +{ + vconsole_write(vc, buf, size); + return size; +} + +static ssize_t vc_memfile_read(void *c, char *buf, size_t size) +{ + return 0; +} + +static int vc_memfile_seek(void *c, off_t *offset, int whence) +{ + return 0; // or maybe -1 should be returned? +} + +static int vc_memfile_close(void *c) +{ + return 0; +} + +void wiiio_init() +{ + if (!vc) { + vc = malloc(sizeof(vconsole_t)); + vconsole_init(vc); + } +} + +FILE* wiiio_fopen() +{ + cookie_io_functions_t vc_memfile_func = { + .read = vc_memfile_read, + .write = vc_memfile_write, + .seek = vc_memfile_seek, + .close = vc_memfile_close + }; + FILE* fp = fopencookie(vc, "w+", vc_memfile_func); + if (!fp) { + vconsole_print(vc, "open failed!\n"); + } + return fp; +} + +vconsole_t* wiiio_get_vconsole() +{ + return vc; +} + +int wiiio_printf(const char *format, ...) +{ + va_list args; + va_start (args, format); + int rv = wiiio_vprintf(format, args); + va_end (args); + return rv; +} + +int wiiio_vprintf(const char *format, va_list ap) +{ + return vconsole_vprintf(vc, format, ap); +} + +int wiiio_print(const char* text) +{ + return vconsole_print(vc, text); +} + +int wiiio_puts(const char* text) +{ + int rv = vconsole_print(vc, text); + rv += vconsole_print(vc, "\n"); + return rv; +} + diff --git a/src/platform/wii/wiiio.h b/src/platform/wii/wiiio.h new file mode 100644 index 0000000..3955beb --- /dev/null +++ b/src/platform/wii/wiiio.h @@ -0,0 +1,34 @@ +// by retro100 +// This file is dual licensed for you to choose from. +// public domain. no warranty implied; use at your own risk. +// also licensed under the zlib license. + +#ifndef WIIIO_H +#define WIIIO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vconsole vconsole_t; + +void wiiio_init(); + +FILE* wiiio_fopen(); +vconsole_t* wiiio_get_vconsole(); + +int wiiio_printf(const char *format, ...) + __attribute__ ((format(printf, 1, 2))); +int wiiio_vprintf(const char *format, va_list ap); +int wiiio_print(const char* text); + +// wiiio_puts() writes the string text and a trailing newline. +int wiiio_puts(const char* text); + +#ifdef __cplusplus +} +#endif + +#endif