Refactor console device, see details:

- Added ConsoleRenderer interface, which abstracts all relevant
  operations needed to set up and write characters to a text mode display
- ConsoleFont now has tileWidth/tileHeight parameters
- PrintConsole now holds a pointer to a ConsoleRenderer
- Added consoleExit for deinitializing the console
- Added consoleUpdate for updating the display every frame
- Corrected lots of obsolete/outdated comments
- Separated console software renderer into its own file (console_sw.c)
- Added getDefaultConsoleRenderer weak function, for selecting the
  default console renderer when none (NULL) is specified in PrintConsole
- Software renderer now takes care of gfxInitDefault/gfxExit
- All these changes are backwards compatible with older programs because:
  - gfxInitDefault has double-init protection
  - Old programs don't call consoleUpdate/Exit, but their implementation
    in the software renderer is identical to what old programs were
    already doing anyway
This commit is contained in:
fincs 2018-09-24 19:59:27 +02:00
parent cc70f19e61
commit 1563df3921
3 changed files with 297 additions and 185 deletions

View File

@ -10,12 +10,9 @@
* *
* General usage is to initialize the console by: * General usage is to initialize the console by:
* @code * @code
* consoleDemoInit() * consoleInit(NULL)
* @endcode
* or to customize the console usage by:
* @code
* consoleInit()
* @endcode * @endcode
* optionally customizing the console usage by passing a pointer to a custom PrintConsole struct.
*/ */
#pragma once #pragma once
#include "../../types.h" #include "../../types.h"
@ -31,15 +28,27 @@
#define CONSOLE_CYAN CONSOLE_ESC(36;1m) #define CONSOLE_CYAN CONSOLE_ESC(36;1m)
#define CONSOLE_WHITE CONSOLE_ESC(37;1m) #define CONSOLE_WHITE CONSOLE_ESC(37;1m)
/// A callback for printing a character. // Forward declaration
typedef bool(*ConsolePrint)(void* con, int c); typedef struct PrintConsole PrintConsole;
/// Renderer interface for the console.
typedef struct ConsoleRenderer
{
bool (*init)(PrintConsole* con);
void (*deinit)(PrintConsole* con);
void (*drawChar)(PrintConsole* con, int x, int y, int c);
void (*scrollWindow)(PrintConsole* con);
void (*flushAndSwap)(PrintConsole* con);
} ConsoleRenderer;
/// A font struct for the console. /// A font struct for the console.
typedef struct ConsoleFont typedef struct ConsoleFont
{ {
u16* gfx; ///< A pointer to the font graphics const void* gfx; ///< A pointer to the font graphics
u16 asciiOffset; ///< Offset to the first valid character in the font table u16 asciiOffset; ///< Offset to the first valid character in the font table
u16 numChars; ///< Number of characters in the font graphics u16 numChars; ///< Number of characters in the font graphics
u16 tileWidth;
u16 tileHeight;
}ConsoleFont; }ConsoleFont;
/** /**
@ -51,10 +60,13 @@ typedef struct ConsoleFont
* { * {
* //Font: * //Font:
* { * {
* (u16*)default_font_bin, //font gfx * default_font_bin, //font gfx
* 0, //first ascii character in the set * 0, //first ascii character in the set
* 128, //number of characters in the font set * 256, //number of characters in the font set
* 16, //tile width
* 16, //tile height
* }, * },
* NULL, //renderer
* 0,0, //cursorX cursorY * 0,0, //cursorX cursorY
* 0,0, //prevcursorX prevcursorY * 0,0, //prevcursorX prevcursorY
* 80, //console width * 80, //console width
@ -64,18 +76,17 @@ typedef struct ConsoleFont
* 80, //window width * 80, //window width
* 45, //window height * 45, //window height
* 3, //tab size * 3, //tab size
* 0, //font character offset * 7, // foreground color
* 0, //print callback * 0, // background color
* 0, // flags
* false //console initialized * false //console initialized
* }; * };
* @endcode * @endcode
*/ */
typedef struct PrintConsole struct PrintConsole
{ {
ConsoleFont font; ///< Font of the console ConsoleFont font; ///< Font of the console
ConsoleRenderer* renderer; ///< Renderer of the console
u32 *frameBuffer; ///< Framebuffer address
u32 *frameBuffer2; ///< Framebuffer address
int cursorX; ///< Current X 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 cursorY; ///< Current Y location of the cursor (as a tile offset by default)
@ -86,20 +97,18 @@ typedef struct PrintConsole
int consoleWidth; ///< Width 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 consoleHeight; ///< Height of the console hardware layer in characters
int windowX; ///< Window X location in characters (not implemented) int windowX; ///< Window X location in characters
int windowY; ///< Window Y location in characters (not implemented) int windowY; ///< Window Y location in characters
int windowWidth; ///< Window width in characters (not implemented) int windowWidth; ///< Window width in characters
int windowHeight; ///< Window height in characters (not implemented) int windowHeight; ///< Window height in characters
int tabSize; ///< Size of a tab int tabSize; ///< Size of a tab
int fg; ///< Foreground color int fg; ///< Foreground color
int bg; ///< Background color int bg; ///< Background color
int flags; ///< Reverse/bright flags 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 bool consoleInitialised; ///< True if the console is initialized
}PrintConsole; };
#define CONSOLE_COLOR_BOLD (1<<0) ///< Bold text #define CONSOLE_COLOR_BOLD (1<<0) ///< Bold text
#define CONSOLE_COLOR_FAINT (1<<1) ///< Faint text #define CONSOLE_COLOR_FAINT (1<<1) ///< Faint text
@ -157,11 +166,24 @@ PrintConsole *consoleSelect(PrintConsole* console);
*/ */
PrintConsole* consoleInit(PrintConsole* console); PrintConsole* consoleInit(PrintConsole* console);
/**
* @brief Deinitialise the console.
* @param console A pointer to the console data to initialize (if it's NULL, the default console will be used).
*/
void consoleExit(PrintConsole* console);
/**
* @brief Updates the console, submitting a new frame to the display.
* @param console A pointer to the console data to initialize (if it's NULL, the default console will be used).
* @remark This function should be called periodically. Failure to call this function will result in lack of screen updating.
*/
void consoleUpdate(PrintConsole* console);
/** /**
* @brief Initializes debug console output on stderr to the specified device. * @brief Initializes debug console output on stderr to the specified device.
* @param device The debug device (or devices) to output debug print statements to. * @param device The debug device (or devices) to output debug print statements to.
*/ */
void consoleDebugInit(debugDevice device); void consoleDebugInit(debugDevice device);
/// Clears the screan by using iprintf("\x1b[2J"); /// Clears the screan by using printf("\x1b[2J");
void consoleClear(void); void consoleClear(void);

View File

@ -3,51 +3,21 @@
#include <sys/iosupport.h> #include <sys/iosupport.h>
#include "runtime/devices/console.h" #include "runtime/devices/console.h"
#include "kernel/svc.h" #include "kernel/svc.h"
#include "display/gfx.h"
#include "default_font_bin.h" #include "default_font_bin.h"
//set up the palette for color printing
static u32 colorTable[] = {
RGBA8_MAXALPHA( 0, 0, 0), // black
RGBA8_MAXALPHA(128, 0, 0), // red
RGBA8_MAXALPHA( 0,128, 0), // green
RGBA8_MAXALPHA(128,128, 0), // yellow
RGBA8_MAXALPHA( 0, 0,128), // blue
RGBA8_MAXALPHA(128, 0,128), // magenta
RGBA8_MAXALPHA( 0,128,128), // cyan
RGBA8_MAXALPHA(192,192,192), // white
RGBA8_MAXALPHA(128,128,128), // bright black
RGBA8_MAXALPHA(255, 0, 0), // bright red
RGBA8_MAXALPHA( 0,255, 0), // bright green
RGBA8_MAXALPHA(255,255, 0), // bright yellow
RGBA8_MAXALPHA( 0, 0,255), // bright blue
RGBA8_MAXALPHA(255, 0,255), // bright magenta
RGBA8_MAXALPHA( 0,255,255), // bright cyan
RGBA8_MAXALPHA(255,255,255), // bright white
RGBA8_MAXALPHA( 0, 0, 0), // faint black
RGBA8_MAXALPHA( 64, 0, 0), // faint red
RGBA8_MAXALPHA( 0, 64, 0), // faint green
RGBA8_MAXALPHA( 64, 64, 0), // faint yellow
RGBA8_MAXALPHA( 0, 0, 64), // faint blue
RGBA8_MAXALPHA( 64, 0, 64), // faint magenta
RGBA8_MAXALPHA( 0, 64, 64), // faint cyan
RGBA8_MAXALPHA( 96, 96, 96), // faint white
};
//The below width/height is for 720p. //The below width/height is for 720p.
PrintConsole defaultConsole = static PrintConsole defaultConsole =
{ {
//Font: //Font:
{ {
(u16*)default_font_bin, //font gfx default_font_bin, //font gfx
0, //first ascii character in the set 0, //first ascii character in the set
256 //number of characters in the font set 256, //number of characters in the font set
16, //tile width
16, //tile height
}, },
(u32*)NULL, NULL, //renderer
(u32*)NULL,
0,0, //cursorX cursorY 0,0, //cursorX cursorY
0,0, //prevcursorX prevcursorY 0,0, //prevcursorX prevcursorY
80, //console width 80, //console width
@ -60,18 +30,18 @@ PrintConsole defaultConsole =
7, // foreground color 7, // foreground color
0, // background color 0, // background color
0, // flags 0, // flags
0, //print callback
false //console initialized false //console initialized
}; };
PrintConsole currentCopy; static PrintConsole currentCopy;
PrintConsole* currentConsole = &currentCopy; static PrintConsole* currentConsole = &currentCopy;
PrintConsole* consoleGetDefault(void){return &defaultConsole;} PrintConsole* consoleGetDefault(void){return &defaultConsole;}
void consolePrintChar(int c); static void consoleNewRow(void);
void consoleDrawChar(int c); static void consolePrintChar(int c);
static void consoleDrawChar(int c);
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static void consoleCls(char mode) { static void consoleCls(char mode) {
@ -123,9 +93,6 @@ static void consoleCls(char mode) {
break; break;
} }
} }
//gfxFlushBuffers();
//gfxSwapBuffers();
//gfxWaitForVsync();
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static void consoleClearLine(char mode) { static void consoleClearLine(char mode) {
@ -178,9 +145,6 @@ static void consoleClearLine(char mode) {
break; break;
} }
} }
//gfxFlushBuffers();
//gfxSwapBuffers();
//gfxWaitForVsync();
} }
@ -526,6 +490,8 @@ static const devoptab_t dotab_null = {
NULL NULL
}; };
ConsoleRenderer* getDefaultConsoleRenderer(void);
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
PrintConsole* consoleInit(PrintConsole* console) { PrintConsole* consoleInit(PrintConsole* console) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -549,27 +515,44 @@ PrintConsole* consoleInit(PrintConsole* console) {
} }
*currentConsole = defaultConsole; *currentConsole = defaultConsole;
if (!console->renderer) {
console->renderer = getDefaultConsoleRenderer();
}
console->consoleInitialised = 1; if (console->renderer->init(console)) {
console->consoleInitialised = true;
gfxSetMode(GfxMode_TiledDouble);
console->frameBuffer = (u32*)gfxGetFramebuffer(NULL, NULL);
gfxSwapBuffers();
console->frameBuffer2 = (u32*)gfxGetFramebuffer(NULL, NULL);
//gfxFlushBuffers();
//gfxSwapBuffers();
//gfxWaitForVsync();
consoleCls('2'); consoleCls('2');
return console;
}
return currentConsole; return currentConsole;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void consoleDebugInit(debugDevice device){ void consoleExit(PrintConsole* console) {
//---------------------------------------------------------------------------------
if (!console) console = currentConsole;
if (console->consoleInitialised) {
console->renderer->deinit(console);
console->consoleInitialised = false;
}
}
//---------------------------------------------------------------------------------
void consoleUpdate(PrintConsole* console) {
//---------------------------------------------------------------------------------
if (!console) console = currentConsole;
if (console->consoleInitialised) {
console->renderer->flushAndSwap(console);
}
}
//---------------------------------------------------------------------------------
void consoleDebugInit(debugDevice device) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
int buffertype = _IONBF; int buffertype = _IONBF;
@ -592,7 +575,7 @@ void consoleDebugInit(debugDevice device){
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
PrintConsole *consoleSelect(PrintConsole* console){ PrintConsole *consoleSelect(PrintConsole* console) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
PrintConsole *tmp = currentConsole; PrintConsole *tmp = currentConsole;
currentConsole = console; currentConsole = console;
@ -600,7 +583,7 @@ PrintConsole *consoleSelect(PrintConsole* console){
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void consoleSetFont(PrintConsole* console, ConsoleFont* font){ void consoleSetFont(PrintConsole* console, ConsoleFont* font) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
if(!console) console = currentConsole; if(!console) console = currentConsole;
@ -610,99 +593,28 @@ void consoleSetFont(PrintConsole* console, ConsoleFont* font){
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
static void newRow(void) { void consoleNewRow(void) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
currentConsole->cursorY ++; currentConsole->cursorY ++;
if(currentConsole->cursorY >= currentConsole->windowHeight) { if(currentConsole->cursorY >= currentConsole->windowHeight) {
currentConsole->cursorY --; currentConsole->cursorY --;
currentConsole->renderer->scrollWindow(currentConsole);
int i,j;
u32 x, y;
x = currentConsole->windowX * 16;
y = currentConsole->windowY * 16;
for (i=0; i<currentConsole->windowWidth*16; i++) {
u32 *from;
u32 *to;
for (j=0;j<(currentConsole->windowHeight-1)*16;j++) {
to = &currentConsole->frameBuffer[gfxGetFramebufferDisplayOffset(x + i, y + j)];
from = &currentConsole->frameBuffer[gfxGetFramebufferDisplayOffset(x + i, y + 16 + j)];
*to = *from;
to = &currentConsole->frameBuffer2[gfxGetFramebufferDisplayOffset(x + i, y + j)];
from = &currentConsole->frameBuffer2[gfxGetFramebufferDisplayOffset(x + i, y + 16 + j)];
*to = *from;
}
}
consoleClearLine('2'); consoleClearLine('2');
} }
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void consoleDrawChar(int c) { void consoleDrawChar(int c) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
c -= currentConsole->font.asciiOffset; c -= currentConsole->font.asciiOffset;
if ( c < 0 || c > currentConsole->font.numChars ) return; if ( c < 0 || c > currentConsole->font.numChars ) return;
u16 *fontdata = currentConsole->font.gfx + (16 * c); currentConsole->renderer->drawChar(
currentConsole,
int writingColor = currentConsole->fg; currentConsole->cursorX + currentConsole->windowX,
int screenColor = currentConsole->bg; currentConsole->cursorY + currentConsole->windowY,
c);
if (currentConsole->flags & CONSOLE_COLOR_BOLD) {
writingColor += 8;
} else if (currentConsole->flags & CONSOLE_COLOR_FAINT) {
writingColor += 16;
}
if (currentConsole->flags & CONSOLE_COLOR_REVERSE) {
int tmp = writingColor;
writingColor = screenColor;
screenColor = tmp;
}
u32 bg = colorTable[screenColor];
u32 fg = colorTable[writingColor];
u128 *tmp = (u128*)fontdata;
u128 bvaltop = tmp[0];
u128 bvalbtm = tmp[1];
if (currentConsole->flags & CONSOLE_UNDERLINE) bvalbtm |= (u128)0xffffULL << 7*16;
if (currentConsole->flags & CONSOLE_CROSSED_OUT) bvaltop |= (u128)0xffffULL << 7*16;
u16 mask = 0x8000;
int i, j;
int x = (currentConsole->cursorX + currentConsole->windowX) * 16;
int y = ((currentConsole->cursorY + currentConsole->windowY) *16 );
u32 *screen;
for (i=0;i<16;i++) {
for (j=0;j<8;j++) {
uint32_t screenOffset = gfxGetFramebufferDisplayOffset(x + i, y + j);
screen = &currentConsole->frameBuffer[screenOffset];
if (bvaltop >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screen = &currentConsole->frameBuffer2[screenOffset];
if (bvaltop >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screenOffset = gfxGetFramebufferDisplayOffset(x + i, y + j + 8);
screen = &currentConsole->frameBuffer[screenOffset];
if (bvalbtm >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screen = &currentConsole->frameBuffer2[screenOffset];
if (bvalbtm >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
}
mask >>= 1;
}
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -710,14 +622,10 @@ void consolePrintChar(int c) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
if (c==0) return; if (c==0) return;
if(currentConsole->PrintChar)
if(currentConsole->PrintChar(currentConsole, c))
return;
if(currentConsole->cursorX >= currentConsole->windowWidth) { if(currentConsole->cursorX >= currentConsole->windowWidth) {
currentConsole->cursorX = 0; currentConsole->cursorX = 0;
newRow(); consoleNewRow();
} }
switch(c) { switch(c) {
@ -730,7 +638,7 @@ void consolePrintChar(int c) {
Reason: VT sequences are more specific to the task of cursor placement. Reason: VT sequences are more specific to the task of cursor placement.
The special escape sequences \b \f & \v are archaic and non-portable. The special escape sequences \b \f & \v are archaic and non-portable.
*/ */
case 8: case '\b':
currentConsole->cursorX--; currentConsole->cursorX--;
if(currentConsole->cursorX < 0) { if(currentConsole->cursorX < 0) {
@ -745,16 +653,13 @@ void consolePrintChar(int c) {
consoleDrawChar(' '); consoleDrawChar(' ');
break; break;
case 9: case '\t':
currentConsole->cursorX += currentConsole->tabSize - ((currentConsole->cursorX)%(currentConsole->tabSize)); currentConsole->cursorX += currentConsole->tabSize - ((currentConsole->cursorX)%(currentConsole->tabSize));
break; break;
case 10: case '\n':
newRow(); consoleNewRow();
case 13: case '\r':
currentConsole->cursorX = 0; currentConsole->cursorX = 0;
//gfxFlushBuffers();
//gfxSwapBuffers();
//gfxWaitForVsync();
break; break;
default: default:
consoleDrawChar(c); consoleDrawChar(c);
@ -766,11 +671,11 @@ void consolePrintChar(int c) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void consoleClear(void) { void consoleClear(void) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
iprintf("\x1b[2J"); printf("\x1b[2J");
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height){ void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height) {
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
if(!console) console = currentConsole; if(!console) console = currentConsole;
@ -784,6 +689,3 @@ void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height
console->cursorY = 0; console->cursorY = 0;
} }

View File

@ -0,0 +1,188 @@
#include <stdio.h>
#include <string.h>
#include <sys/iosupport.h>
#include "result.h"
#include "runtime/devices/console.h"
#include "display/gfx.h"
//set up the palette for color printing
static const u32 colorTable[] = {
RGBA8_MAXALPHA( 0, 0, 0), // black
RGBA8_MAXALPHA(128, 0, 0), // red
RGBA8_MAXALPHA( 0,128, 0), // green
RGBA8_MAXALPHA(128,128, 0), // yellow
RGBA8_MAXALPHA( 0, 0,128), // blue
RGBA8_MAXALPHA(128, 0,128), // magenta
RGBA8_MAXALPHA( 0,128,128), // cyan
RGBA8_MAXALPHA(192,192,192), // white
RGBA8_MAXALPHA(128,128,128), // bright black
RGBA8_MAXALPHA(255, 0, 0), // bright red
RGBA8_MAXALPHA( 0,255, 0), // bright green
RGBA8_MAXALPHA(255,255, 0), // bright yellow
RGBA8_MAXALPHA( 0, 0,255), // bright blue
RGBA8_MAXALPHA(255, 0,255), // bright magenta
RGBA8_MAXALPHA( 0,255,255), // bright cyan
RGBA8_MAXALPHA(255,255,255), // bright white
RGBA8_MAXALPHA( 0, 0, 0), // faint black
RGBA8_MAXALPHA( 64, 0, 0), // faint red
RGBA8_MAXALPHA( 0, 64, 0), // faint green
RGBA8_MAXALPHA( 64, 64, 0), // faint yellow
RGBA8_MAXALPHA( 0, 0, 64), // faint blue
RGBA8_MAXALPHA( 64, 0, 64), // faint magenta
RGBA8_MAXALPHA( 0, 64, 64), // faint cyan
RGBA8_MAXALPHA( 96, 96, 96), // faint white
};
struct ConsoleSwRenderer
{
ConsoleRenderer base;
u32 *frameBuffer; ///< Framebuffer address
u32 *frameBuffer2; ///< Framebuffer address
};
static struct ConsoleSwRenderer* ConsoleSwRenderer(PrintConsole* con)
{
return (struct ConsoleSwRenderer*)con->renderer;
}
static bool ConsoleSwRenderer_init(PrintConsole* con)
{
struct ConsoleSwRenderer* sw = ConsoleSwRenderer(con);
if (con->font.tileWidth != 16 || con->font.tileHeight != 16) {
// Only 16x16 tiles are supported for the font
return false;
}
if (R_FAILED(gfxInitDefault())) {
// Graphics failed to initialize
return false;
}
u32 width, height;
gfxGetFramebufferResolution(&width, &height);
if (con->consoleWidth > (width/16) || con->consoleHeight > (height/16)) {
// Unsupported console size
return false;
}
gfxSetMode(GfxMode_TiledDouble);
sw->frameBuffer = (u32*)gfxGetFramebuffer(NULL, NULL);
gfxSwapBuffers();
sw->frameBuffer2 = (u32*)gfxGetFramebuffer(NULL, NULL);
return true;
}
static void ConsoleSwRenderer_deinit(PrintConsole* con)
{
gfxExit();
}
static void ConsoleSwRenderer_drawChar(PrintConsole* con, int x, int y, int c)
{
struct ConsoleSwRenderer* sw = ConsoleSwRenderer(con);
const u16 *fontdata = (const u16*)con->font.gfx + (16 * c);
int writingColor = con->fg;
int screenColor = con->bg;
if (con->flags & CONSOLE_COLOR_BOLD) {
writingColor += 8;
} else if (con->flags & CONSOLE_COLOR_FAINT) {
writingColor += 16;
}
if (con->flags & CONSOLE_COLOR_REVERSE) {
int tmp = writingColor;
writingColor = screenColor;
screenColor = tmp;
}
u32 bg = colorTable[screenColor];
u32 fg = colorTable[writingColor];
u128 *tmp = (u128*)fontdata;
u128 bvaltop = tmp[0];
u128 bvalbtm = tmp[1];
if (con->flags & CONSOLE_UNDERLINE) bvalbtm |= (u128)0xffffULL << 7*16;
if (con->flags & CONSOLE_CROSSED_OUT) bvaltop |= (u128)0xffffULL << 7*16;
u16 mask = 0x8000;
int i, j;
x *= 16;
y *= 16;
u32 *screen;
for (i=0;i<16;i++) {
for (j=0;j<8;j++) {
uint32_t screenOffset = gfxGetFramebufferDisplayOffset(x + i, y + j);
screen = &sw->frameBuffer[screenOffset];
if (bvaltop >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screen = &sw->frameBuffer2[screenOffset];
if (bvaltop >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screenOffset = gfxGetFramebufferDisplayOffset(x + i, y + j + 8);
screen = &sw->frameBuffer[screenOffset];
if (bvalbtm >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
screen = &sw->frameBuffer2[screenOffset];
if (bvalbtm >> (16*j) & mask) { *screen = fg; }else{ *screen = bg; }
}
mask >>= 1;
}
}
static void ConsoleSwRenderer_scrollWindow(PrintConsole* con)
{
struct ConsoleSwRenderer* sw = ConsoleSwRenderer(con);
int i,j;
u32 x, y;
x = con->windowX * 16;
y = con->windowY * 16;
for (i=0; i<con->windowWidth*16; i++) {
u32 *from;
u32 *to;
for (j=0;j<(con->windowHeight-1)*16;j++) {
to = &sw->frameBuffer[gfxGetFramebufferDisplayOffset(x + i, y + j)];
from = &sw->frameBuffer[gfxGetFramebufferDisplayOffset(x + i, y + 16 + j)];
*to = *from;
to = &sw->frameBuffer2[gfxGetFramebufferDisplayOffset(x + i, y + j)];
from = &sw->frameBuffer2[gfxGetFramebufferDisplayOffset(x + i, y + 16 + j)];
*to = *from;
}
}
}
static void ConsoleSwRenderer_flushAndSwap(PrintConsole* con)
{
gfxFlushBuffers();
gfxSwapBuffers();
}
static struct ConsoleSwRenderer s_consoleSwRenderer =
{
{
ConsoleSwRenderer_init,
ConsoleSwRenderer_deinit,
ConsoleSwRenderer_drawChar,
ConsoleSwRenderer_scrollWindow,
ConsoleSwRenderer_flushAndSwap,
}, //base
NULL, //frameBuffer
NULL, //frameBuffer2
};
__attribute__((weak)) ConsoleRenderer* getDefaultConsoleRenderer(void)
{
return &s_consoleSwRenderer.base;
}