From f7e2bbfc3d484bd000a4c921b4dc0780a6f5b354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Wed, 20 Aug 2025 03:40:32 +0200 Subject: [PATCH 1/9] consolidate console documentation and offset usage introduces helper functions to avoid the repetition and mistakes logic was verified equivalent or better by hand but not runtime-tested fixes various issues having to do with out of bounds writes misc changes to extraneous whitespace noticed during the refactor --- gc/ogc/console.h | 46 ++++++----- libogc/console.c | 206 ++++++++++++++++++++++++++++++----------------- 2 files changed, 155 insertions(+), 97 deletions(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index ab3d115be..9ef49f9fe 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -55,9 +55,9 @@ * \brief Initializes the console subsystem with given parameters * * \param[in] framebuffer pointer to the framebuffer used for drawing the characters - * \param[in] xstart,ystart start position of the console output in pixel - * \param[in] xres,yres size of the console in pixel - * \param[in] stride size of one line of the framebuffer in bytes + * \param[in] xstart,ystart start position of the console output, in pixels + * \param[in] xres,yres size of the console, in pixels + * \param[in] stride size of one line of the framebuffer, in bytes * * \return none */ @@ -69,8 +69,8 @@ void CON_Init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stri * \param[in] rmode pointer to the video/render mode configuration * \param[in] conXOrigin starting pixel in X direction of the console output on the external framebuffer * \param[in] conYOrigin starting pixel in Y direction of the console output on the external framebuffer - * \param[in] conWidth width of the console output 'window' to be drawn - * \param[in] conHeight height of the console output 'window' to be drawn + * \param[in] conWidth width of the console output 'window' to be drawn, in pixels + * \param[in] conHeight height of the console output 'window' to be drawn, in pixels * * \return 0 on success, <0 on error */ @@ -80,7 +80,7 @@ s32 CON_InitEx(GXRModeObj *rmode, s32 conXOrigin,s32 conYOrigin,s32 conWidth,s32 * \fn CON_GetMetrics(int *cols, int *rows) * \brief retrieve the columns and rows of the current console * - * \param[out] cols,rows number of columns and rows of the current console + * \param[out] cols,rows number of columns and rows of the current console, in tiles, 1-indexed. * * \return none */ @@ -90,7 +90,7 @@ void CON_GetMetrics(int *cols, int *rows); * \fn CON_GetPosition(int *col, int *row) * \brief retrieve the current cursor position of the current console * - * \param[out] col,row current cursor position + * \param[out] col,row current cursor position, in tiles, 1-indexed. * * \return none */ @@ -100,7 +100,7 @@ void CON_GetPosition(int *cols, int *rows); * \fn CON_EnableGecko(int channel, int safe) * \brief Enable or disable the USB gecko console. * - * \param[in] channel EXI channel, or -1 ¨to disable the gecko console + * \param[in] channel EXI channel, or -1 �to disable the gecko console * \param[in] safe If true, use safe mode (wait for peer) * * \return none @@ -152,22 +152,24 @@ typedef struct PrintConsole ConsoleFont font; ///< Font of the console void *destbuffer; ///< Framebuffer address - int con_xres,con_yres,con_stride; - int target_x,target_y, tgt_stride; + int con_xres, con_yres; ///< Console buffer width/height, in pixels + int con_stride; ///< Size of one row in the console buffer, in bytes + int target_x, target_y; ///< Target buffer x/y offset to start the console, in pixels + int tgt_stride; ///< Size of one row in the target buffer, in bytes - 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 in the window, in tiles, 1-indexed: 1 <= cursorX <= windowWidth, cursorX > windowWidth wraps to the next line and resets to cursorX = 1 + int cursorY; ///< Current Y location of the cursor in the window, in tiles, 1-indexed int prevCursorX; ///< Internal state int prevCursorY; ///< Internal state - int con_cols; ///< Width of the console hardware layer in characters - int con_rows; ///< Height of the console hardware layer in characters + int con_cols; ///< Width of the console hardware layer, in characters (amount of tiles) + int con_rows; ///< Height of the console hardware layer, in characters (amount of tiles) - 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 tiles, 1-indexed, 1 <= windowX < con_cols + int windowY; ///< Window Y location, in tiles, 1-indexed + int windowWidth; ///< Window width, in amount of tiles, 1 <= windowWidth <= con_cols + int windowHeight; ///< Window height, in amount of tiles int tabSize; ///< Size of a tab unsigned int fg; ///< Foreground color @@ -196,10 +198,10 @@ 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. + * @param x X location of the window, in tiles, 1-indexed. + * @param y Y location of the window, in tiles, 1-indexed. + * @param width Width of the window, in tiles, 1-indexed. + * @param height Height of the window, in tiles, 1-indexed. */ void consoleSetWindow(PrintConsole* console, unsigned int x, unsigned int y, unsigned int width, unsigned int height); diff --git a/libogc/console.c b/libogc/console.c index 06afdcf9c..30752d445 100644 --- a/libogc/console.c +++ b/libogc/console.c @@ -149,14 +149,63 @@ PrintConsole currentCopy; PrintConsole* currentConsole = ¤tCopy; -static u32 __console_get_offset() +static void *__console_offset_by_pixels(void *ptr, s32 dy_pixels, u32 stride_bytes, s32 dx_pixels) +{ + const s32 dy_bytes = dy_pixels * stride_bytes; + const s32 dx_bytes = dx_pixels * VI_DISPLAY_PIX_SZ; + return (u8 *)ptr + dy_bytes + dx_bytes; +} + +// cursor_y and cursor_x are 1-indexed tile offsets (to start of tile), window offsets are a type of cursor +// window/console dimensions are a count of tiles, but 0-indexed +static void *__console_offset_by_cursor(void *ptr, u32 cursor_y, u32 stride_bytes, u32 cursor_x) +{ + return __console_offset_by_pixels(ptr, (cursor_y - 1) * FONT_YSIZE, stride_bytes, (cursor_x - 1) * FONT_XSIZE); +} + +static void *__console_get_buffer_start_ptr() { if(!currentConsole) - return 0; - + return NULL; + + // using CON_InitEx automatically copies the console buffer to the framebuffer via __console_vipostcb + // this copy may be to an offset, which is where target_y/target_x/tgt_stride come into play in this case + // detected by _console_buffer being non-NULL (and by construction == currentConsole->destbuffer) + + // using CON_Init uses the provided pointer directly + // then target_y/target_x/tgt_stride must be applied here when writing pixels to the console buffer + + // writing characters/pixels to the console buffer via stdio/etc does not involve those values otherwise + // only console dimensions (con_xres/con_yres/con_stride) and cursor/window values (cursorX/cursorY/con_cols/con_rows/...) + return _console_buffer != NULL - ? 0 - : (currentConsole->target_y * currentConsole->tgt_stride) + (currentConsole->target_x * VI_DISPLAY_PIX_SZ); + ? _console_buffer // same as currentConsole->destbuffer, don't need to load from a struct access + : __console_offset_by_pixels(currentConsole->destbuffer, currentConsole->target_y, currentConsole->tgt_stride, currentConsole->target_x); +} + +static void *__console_get_window_start_ptr() +{ + PrintConsole *con; + if( !(con = currentConsole) ) + return NULL; + + return __console_offset_by_cursor(__console_get_buffer_start_ptr(), con->windowY, con->con_stride, con->windowX); +} + +static void *__console_get_cursor_start_ptr() +{ + PrintConsole *con; + if( !(con = currentConsole) ) + return NULL; + + /* + void *ptr = __console_get_buffer_start_ptr(); + ptr = __console_offset_by_cursor(ptr, con->windowY, con->con_stride, con->windowX); + ptr = __console_offset_by_cursor(ptr, con->cursorY, con->con_stride, con->cursorX); + return ptr; + */ + // equivalent but less calls. -1 for the x/y offsets avoids mistakenly using 2-indexed values + return __console_offset_by_cursor(__console_get_buffer_start_ptr(), con->windowY + con->cursorY - 1, con->con_stride, con->windowX + con->cursorX - 1); } void __console_vipostcb(u32 retraceCnt) @@ -165,14 +214,14 @@ void __console_vipostcb(u32 retraceCnt) do_xfb_copy = true; ptr = currentConsole->destbuffer; - fb = (u8*)((u32)VIDEO_GetCurrentFramebuffer() + (currentConsole->target_y * currentConsole->tgt_stride) + (currentConsole->target_x * VI_DISPLAY_PIX_SZ)); + fb = __console_offset_by_pixels(VIDEO_GetCurrentFramebuffer(), currentConsole->target_y, currentConsole->tgt_stride, currentConsole->target_x); - // Clears 1 line of pixels at a time + // Copies 1 line of pixels at a time for(u16 ycnt = 0; ycnt < currentConsole->con_yres; ycnt++) { memcpy(fb, ptr, currentConsole->con_xres * VI_DISPLAY_PIX_SZ); - ptr+= currentConsole->con_stride; - fb+= currentConsole->tgt_stride; + ptr += currentConsole->con_stride; + fb += currentConsole->tgt_stride; } do_xfb_copy = false; @@ -195,13 +244,12 @@ static void __console_drawc(int c) c -= con->font.asciiOffset; if (c<0 || c>con->font.numChars) return; - ptr = (unsigned int*)(con->destbuffer \ - + ( con->con_stride * (con->windowY - 1 + con->cursorY - 1) * FONT_YSIZE ) \ - + (((con->cursorX - 1 + con->windowX - 1) * FONT_XSIZE / 2) * 4) \ - + __console_get_offset()); + ptr = __console_get_cursor_start_ptr(); pbits = &con->font.gfx[c * FONT_YSIZE]; - nextline = con->con_stride/4 - 4; + // con_stride is in bytes, but we increment ptr which isn't a byte pointer + // and the work in the loop already increments ptr 4 times before needing to go to the next row + nextline = con->con_stride/sizeof(*ptr) - 4; fgcolor = currentConsole->fg; bgcolor = currentConsole->bg; @@ -286,16 +334,25 @@ static void __console_drawc(int c) } } -static void __console_clear_line(int line, int from, int to ) +/* +line, from, to are 1-indexed tile offsets (to starts of tiles) +to convert from 'an amount of tiles' to 'the end of the final tile' (aka 'the start of the past-the-end tile') +simply add 1 to the 'amount of tiles' value +Examples: +a cursor points to (the start of) tile 3, how many tiles to fill to clear until (the start of) tile 7 ? +-> fill tile 3, 4, 5, 6 (= 4 tiles) +a cursor points to (the start of) tile 2 in an area with 5 tiles, how many tiles to fill to clear until the end ? +-> fill tile 2, 3, 4, 5 (= 4 tiles = 5 - 2 + 1, because '5' here is an amount, not an offset) +*/ +static void __console_clear_line(int line, int from, int to) { PrintConsole *con; - u8* p; - - + u8 *p; + if( !(con = currentConsole) ) return; // Each character is FONT_XSIZE * VI_DISPLAY_PIX_SZ wide - const u32 line_width = (to - from + 1) * FONT_XSIZE * VI_DISPLAY_PIX_SZ; + const u32 line_width = (to - from) * FONT_XSIZE * VI_DISPLAY_PIX_SZ; unsigned int bgcolor = con->bg; @@ -303,18 +360,14 @@ static void __console_clear_line(int line, int from, int to ) bgcolor = colorTable[bgcolor]; } - //add the given row & column to the offset & assign the pointer - const u32 offset = __console_get_offset() \ - + ((line - 1 + con->windowY - 1) * con->con_stride * FONT_YSIZE) \ - + (from - 1 + con->windowX - 1) * FONT_XSIZE * VI_DISPLAY_PIX_SZ; - - p = (u8*)((uintptr_t)con->destbuffer + offset); + p = __console_get_window_start_ptr(); + p = __console_offset_by_cursor(p, line, con->con_stride, from); // Clears 1 line of pixels at a time for(u16 ycnt = 0; ycnt < FONT_YSIZE; ycnt++) { - for(u32 xcnt = 0; xcnt < line_width; xcnt += 4) - *(u32*)((uintptr_t)p + xcnt) = bgcolor; + for(u32 xcnt = 0; xcnt < line_width; xcnt += sizeof(u32)) + *(u32*)(p + xcnt) = bgcolor; p += con->con_stride; } @@ -323,24 +376,28 @@ static void __console_clear_line(int line, int from, int to ) static void __console_clear(void) { PrintConsole *con; - u8* p; + u8 *p; if( !(con = currentConsole) ) return; + // Window lines add up to con->windowHeight * FONT_YSIZE pixel lines + const u32 view_height = con->windowHeight * FONT_YSIZE; + // Each window line is con->windowWidth * FONT_XSIZE * VI_DISPLAY_PIX_SZ bytes wide + const u32 line_width = con->windowWidth * FONT_XSIZE * VI_DISPLAY_PIX_SZ; + unsigned int bgcolor = con->bg; if (!(currentConsole->flags & CONSOLE_BG_CUSTOM)) { bgcolor = colorTable[bgcolor]; } //get console pointer - p = (u8*)((uintptr_t)con->destbuffer + __console_get_offset()) \ - + ((con->windowY - 1) * con->con_stride * FONT_YSIZE); + p = __console_get_window_start_ptr(); // Clears 1 line of pixels at a time - for(u16 ycnt = 0; ycnt < con->windowHeight * 16; ycnt++) + for(u16 ycnt = 0; ycnt < view_height; ycnt++) { - for(u32 xcnt = (con->windowX - 1) * 8 * VI_DISPLAY_PIX_SZ; xcnt < (con->windowWidth + con->windowX -1) * 8 * VI_DISPLAY_PIX_SZ; xcnt+=4) - *(u32*)((uintptr_t)p + xcnt) = bgcolor; + for(u32 xcnt = 0; xcnt < line_width; xcnt += sizeof(u32)) + *(u32*)(p + xcnt) = bgcolor; p += con->con_stride; } @@ -359,11 +416,10 @@ static void __console_clear_from_cursor(void) { cur_row = con->cursorY; - __console_clear_line( cur_row, con->cursorX, con->windowWidth ); - - while( cur_row++ < (con->windowY + con->windowHeight) ) - __console_clear_line( cur_row, 1, con->windowWidth ); + __console_clear_line( cur_row, con->cursorX, con->windowWidth + 1 ); + while( cur_row++ < con->windowHeight ) + __console_clear_line( cur_row, 1, con->windowWidth + 1 ); } static void __console_clear_to_cursor(void) { @@ -373,10 +429,10 @@ static void __console_clear_to_cursor(void) { if( !(con = currentConsole) ) return; cur_row = con->cursorY; - __console_clear_line( cur_row, 1, con->cursorX - 1); + __console_clear_line( cur_row, 1, con->cursorX ); - while( cur_row-- ) - __console_clear_line( cur_row, 1, con->windowWidth ); + while( --cur_row ) + __console_clear_line( cur_row, 1, con->windowWidth + 1 ); } static void __set_default_console(void *destbuffer,int xstart,int ystart, int tgt_stride, int con_xres,int con_yres,int con_stride) @@ -447,18 +503,17 @@ void __console_init_ex(void *destbuffer,int tgt_xstart,int tgt_ystart,int tgt_st } - static void consoleClearLine(int mode) { switch(mode) { - case 0: - __console_clear_line( currentConsole->cursorY, currentConsole->cursorX, currentConsole->windowWidth ); + case 0: // cursor to end of line + __console_clear_line( currentConsole->cursorY, currentConsole->cursorX, currentConsole->windowWidth + 1 ); break; - case 1: - __console_clear_line( currentConsole->cursorY, 1, currentConsole->cursorX - 1); + case 1: // beginning of line to cursor + __console_clear_line( currentConsole->cursorY, 1, currentConsole->cursorX ); break; - case 2: - __console_clear_line( currentConsole->cursorY, 1, currentConsole->windowWidth); + case 2: // entire line + __console_clear_line( currentConsole->cursorY, 1, currentConsole->windowWidth + 1); break; } } @@ -745,23 +800,28 @@ static void consoleHandleColorEsc(int argCount) void newRow() { - currentConsole->cursorY++; - /* if bottom border reached, scroll */ + // if bottom border reached, scroll if( currentConsole->cursorY > currentConsole->windowHeight) { - u8* ptr = (u8*)((u32)currentConsole->destbuffer + __console_get_offset()) \ - + (currentConsole->windowX - 1) * FONT_XSIZE * VI_DISPLAY_PIX_SZ \ - + ((currentConsole->windowY - 1 ) * currentConsole->con_stride * FONT_YSIZE); + u8* ptr = __console_get_window_start_ptr(); + + // Each window line is currentConsole->windowWidth * FONT_XSIZE * VI_DISPLAY_PIX_SZ bytes wide + const u32 line_width = currentConsole->windowWidth * FONT_XSIZE * VI_DISPLAY_PIX_SZ; + + // scrolling copies all rows except the very first one (that gets overwritten) + const u32 scroll_height = (currentConsole->windowHeight - 1) * FONT_YSIZE; + // skip 1 tile row's worth of bytes + const u32 row_bytes = currentConsole->con_stride * FONT_YSIZE; - for(u32 ycnt = 0; ycnt < ((currentConsole->windowHeight -1) * FONT_YSIZE); ycnt++) + for(u32 ycnt = 0; ycnt < scroll_height; ycnt++) { - memmove(ptr, ptr + currentConsole->con_stride * FONT_YSIZE, currentConsole->windowWidth * FONT_XSIZE * VI_DISPLAY_PIX_SZ); - ptr+= currentConsole->con_stride; + memmove(ptr, ptr + row_bytes, line_width); + ptr += currentConsole->con_stride; } - //clear last line - __console_clear_line(currentConsole->windowHeight, 1, currentConsole->windowWidth); + // clear last line + __console_clear_line(currentConsole->windowHeight, 1, currentConsole->windowWidth + 1); currentConsole->cursorY = currentConsole->windowHeight; } } @@ -801,20 +861,20 @@ void consolePrintChar(int c) tabspaces = currentConsole->tabSize - ((currentConsole->cursorX - 1) % currentConsole->tabSize); if (currentConsole->cursorX + tabspaces > currentConsole->windowWidth) tabspaces = currentConsole->windowWidth - currentConsole->cursorX; - for(int i=0; icursorX = 1; + currentConsole->cursorX = 1; break; default: - if(currentConsole->cursorX > currentConsole->windowWidth) { - currentConsole->cursorX = 1; + if(currentConsole->cursorX > currentConsole->windowWidth) { + currentConsole->cursorX = 1; newRow(); } __console_drawc(c); - ++currentConsole->cursorX ; + ++currentConsole->cursorX; break; } } @@ -910,7 +970,7 @@ ssize_t __console_write(struct _reent *r,void *fd,const char *ptr, size_t len) if (!escapeSeq.hasArg && !escapeSeq.argIdx) escapeSeq.args[0] = 1; currentConsole->cursorY = currentConsole->cursorY + escapeSeq.args[0]; - if (currentConsole->cursorY >= currentConsole->windowHeight) + if (currentConsole->cursorY > currentConsole->windowHeight) currentConsole->cursorY = currentConsole->windowHeight; escapeSeq.state = ESC_NONE; break; @@ -962,16 +1022,16 @@ ssize_t __console_write(struct _reent *r,void *fd,const char *ptr, size_t len) // Save cursor position //--------------------------------------- case 's': - currentConsole->prevCursorX = currentConsole->cursorX ; - currentConsole->prevCursorY = currentConsole->cursorY ; + currentConsole->prevCursorX = currentConsole->cursorX ; + currentConsole->prevCursorY = currentConsole->cursorY ; escapeSeq.state = ESC_NONE; break; //--------------------------------------- // Load cursor position //--------------------------------------- case 'u': - currentConsole->cursorX = currentConsole->prevCursorX ; - currentConsole->cursorY = currentConsole->prevCursorY ; + currentConsole->cursorX = currentConsole->prevCursorX ; + currentConsole->cursorY = currentConsole->prevCursorY ; escapeSeq.state = ESC_NONE; break; //--------------------------------------- @@ -1110,27 +1170,24 @@ PrintConsole *consoleSelect(PrintConsole* console) void consoleSetFont(PrintConsole* console, ConsoleFont* font) { - if(!console) console = currentConsole; console->font = *font; - } void consoleSetWindow(PrintConsole* console, unsigned int x, unsigned int y, unsigned int width, unsigned int height) { - if(!console) console = currentConsole; // co-ords are 1-based but accept 0 if (x == 0) x = 1; if (y == 0) y = 1; - if ( x >= console->con_cols) return; - if ( y >= console->con_rows) return; + if (x >= console->con_cols) return; + if (y >= console->con_rows) return; - if ( x + width > console->con_cols + 1) width = console->con_cols + 1 - x; - if ( y + height > console->con_rows + 1) height = console->con_rows + 1 - y; + if (x + width > console->con_cols + 1) width = console->con_cols + 1 - x; + if (y + height > console->con_rows + 1) height = console->con_rows + 1 - y; console->windowWidth = width; console->windowHeight = height; @@ -1139,5 +1196,4 @@ void consoleSetWindow(PrintConsole* console, unsigned int x, unsigned int y, uns console->cursorX = 1; console->cursorY = 1; - } From cafc84c181cc5b4bfcfe58af90e158950d5bbd05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Wed, 20 Aug 2025 03:56:00 +0200 Subject: [PATCH 2/9] remove somehow broken character --- gc/ogc/console.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index 9ef49f9fe..061b82cd6 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -100,7 +100,7 @@ void CON_GetPosition(int *cols, int *rows); * \fn CON_EnableGecko(int channel, int safe) * \brief Enable or disable the USB gecko console. * - * \param[in] channel EXI channel, or -1 �to disable the gecko console + * \param[in] channel EXI channel, or -1 to disable the gecko console * \param[in] safe If true, use safe mode (wait for peer) * * \return none From b07ff36a4040debfe2862d5a44e5313f8342bead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Wed, 20 Aug 2025 04:06:43 +0200 Subject: [PATCH 3/9] forgot a word --- libogc/console.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libogc/console.c b/libogc/console.c index 30752d445..fec230462 100644 --- a/libogc/console.c +++ b/libogc/console.c @@ -340,7 +340,7 @@ to convert from 'an amount of tiles' to 'the end of the final tile' (aka 'the st simply add 1 to the 'amount of tiles' value Examples: a cursor points to (the start of) tile 3, how many tiles to fill to clear until (the start of) tile 7 ? --> fill tile 3, 4, 5, 6 (= 4 tiles) +-> fill tile 3, 4, 5, 6 (= 4 tiles = 7 - 3) a cursor points to (the start of) tile 2 in an area with 5 tiles, how many tiles to fill to clear until the end ? -> fill tile 2, 3, 4, 5 (= 4 tiles = 5 - 2 + 1, because '5' here is an amount, not an offset) */ @@ -351,7 +351,7 @@ static void __console_clear_line(int line, int from, int to) if( !(con = currentConsole) ) return; - // Each character is FONT_XSIZE * VI_DISPLAY_PIX_SZ wide + // Each character is FONT_XSIZE * VI_DISPLAY_PIX_SZ bytes wide const u32 line_width = (to - from) * FONT_XSIZE * VI_DISPLAY_PIX_SZ; unsigned int bgcolor = con->bg; From 0c0947e3b451fe4b17ba5ab33c33e7aecfd12f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Thu, 21 Aug 2025 11:11:52 +0200 Subject: [PATCH 4/9] remove false doc (mindless copy-paste), extra punctuation --- gc/ogc/console.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index 061b82cd6..2cd0aefc0 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -80,7 +80,7 @@ s32 CON_InitEx(GXRModeObj *rmode, s32 conXOrigin,s32 conYOrigin,s32 conWidth,s32 * \fn CON_GetMetrics(int *cols, int *rows) * \brief retrieve the columns and rows of the current console * - * \param[out] cols,rows number of columns and rows of the current console, in tiles, 1-indexed. + * \param[out] cols,rows number of columns and rows of the current console, in tiles * * \return none */ @@ -90,7 +90,7 @@ void CON_GetMetrics(int *cols, int *rows); * \fn CON_GetPosition(int *col, int *row) * \brief retrieve the current cursor position of the current console * - * \param[out] col,row current cursor position, in tiles, 1-indexed. + * \param[out] col,row current cursor position, in tiles, 1-indexed * * \return none */ @@ -198,10 +198,10 @@ 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, in tiles, 1-indexed. - * @param y Y location of the window, in tiles, 1-indexed. - * @param width Width of the window, in tiles, 1-indexed. - * @param height Height of the window, in tiles, 1-indexed. + * @param x X location of the window, in tiles, 1-indexed + * @param y Y location of the window, in tiles, 1-indexed + * @param width Width of the window, in tiles + * @param height Height of the window, in tiles */ void consoleSetWindow(PrintConsole* console, unsigned int x, unsigned int y, unsigned int width, unsigned int height); From b07b158823aa43f6b5eddca70e5c405b950a3f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Thu, 21 Aug 2025 18:33:50 +0200 Subject: [PATCH 5/9] reword comment for readability --- libogc/console.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libogc/console.c b/libogc/console.c index fec230462..74a2ff640 100644 --- a/libogc/console.c +++ b/libogc/console.c @@ -247,8 +247,10 @@ static void __console_drawc(int c) ptr = __console_get_cursor_start_ptr(); pbits = &con->font.gfx[c * FONT_YSIZE]; - // con_stride is in bytes, but we increment ptr which isn't a byte pointer - // and the work in the loop already increments ptr 4 times before needing to go to the next row + // con_stride is in bytes, but we increment ptr which is an int pointer + // -> we have to divide to not skip over rows we want to write to + // the work in the loop already writes 4 ints before going to the next row + // -> subtract that 4 here, so nextline can be directly added to ptr later nextline = con->con_stride/sizeof(*ptr) - 4; fgcolor = currentConsole->fg; From dc1135d0c90d9763ef49b853a2271bb15a0a4324 Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Sun, 31 Aug 2025 10:34:46 +0100 Subject: [PATCH 6/9] remove spurious commas --- gc/ogc/console.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index 2cd0aefc0..0bae049b3 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -152,24 +152,24 @@ typedef struct PrintConsole ConsoleFont font; ///< Font of the console void *destbuffer; ///< Framebuffer address - int con_xres, con_yres; ///< Console buffer width/height, in pixels - int con_stride; ///< Size of one row in the console buffer, in bytes - int target_x, target_y; ///< Target buffer x/y offset to start the console, in pixels - int tgt_stride; ///< Size of one row in the target buffer, in bytes + int con_xres, con_yres; ///< Console buffer width/height in pixels + int con_stride; ///< Size of one row in the console buffer in bytes + int target_x, target_y; ///< Target buffer x/y offset to start the console in pixels + int tgt_stride; ///< Size of one row in the target buffer in bytes - int cursorX; ///< Current X location of the cursor in the window, in tiles, 1-indexed: 1 <= cursorX <= windowWidth, cursorX > windowWidth wraps to the next line and resets to cursorX = 1 - int cursorY; ///< Current Y location of the cursor in the window, in tiles, 1-indexed + int cursorX; ///< Current X location of the cursor in the window in tiles, 1-indexed: 1 <= cursorX <= windowWidth, cursorX > windowWidth wraps to the next line and resets to cursorX = 1 + int cursorY; ///< Current Y location of the cursor in the window in tiles, 1-indexed int prevCursorX; ///< Internal state int prevCursorY; ///< Internal state - int con_cols; ///< Width of the console hardware layer, in characters (amount of tiles) - int con_rows; ///< Height of the console hardware layer, in characters (amount of tiles) + int con_cols; ///< Width of the console hardware layer in characters (amount of tiles) + int con_rows; ///< Height of the console hardware layer in characters (amount of tiles) - int windowX; ///< Window X location, in tiles, 1-indexed, 1 <= windowX < con_cols - int windowY; ///< Window Y location, in tiles, 1-indexed - int windowWidth; ///< Window width, in amount of tiles, 1 <= windowWidth <= con_cols - int windowHeight; ///< Window height, in amount of tiles + int windowX; ///< Window X location in tiles, 1-indexed, 1 <= windowX < con_cols + int windowY; ///< Window Y location in tiles, 1-indexed + int windowWidth; ///< Window width in tiles, 1 <= windowWidth <= con_cols + int windowHeight; ///< Window height in tiles int tabSize; ///< Size of a tab unsigned int fg; ///< Foreground color @@ -198,10 +198,10 @@ 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, in tiles, 1-indexed - * @param y Y location of the window, in tiles, 1-indexed - * @param width Width of the window, in tiles - * @param height Height of the window, in tiles + * @param x X location of the window in tiles, 1-indexed + * @param y Y location of the window in tiles, 1-indexed + * @param width Width of the window in tiles + * @param height Height of the window in tiles */ void consoleSetWindow(PrintConsole* console, unsigned int x, unsigned int y, unsigned int width, unsigned int height); From fe29640f1c800811ea3fe01202c84b2b1c55becc Mon Sep 17 00:00:00 2001 From: Dave Murphy Date: Sun, 31 Aug 2025 10:40:19 +0100 Subject: [PATCH 7/9] remove more spurious commas --- gc/ogc/console.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index 0bae049b3..2c958a0e4 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -55,9 +55,9 @@ * \brief Initializes the console subsystem with given parameters * * \param[in] framebuffer pointer to the framebuffer used for drawing the characters - * \param[in] xstart,ystart start position of the console output, in pixels - * \param[in] xres,yres size of the console, in pixels - * \param[in] stride size of one line of the framebuffer, in bytes + * \param[in] xstart,ystart start position of the console output in pixels + * \param[in] xres,yres size of the console in pixels + * \param[in] stride size of one line of the framebuffer in bytes * * \return none */ @@ -69,8 +69,8 @@ void CON_Init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stri * \param[in] rmode pointer to the video/render mode configuration * \param[in] conXOrigin starting pixel in X direction of the console output on the external framebuffer * \param[in] conYOrigin starting pixel in Y direction of the console output on the external framebuffer - * \param[in] conWidth width of the console output 'window' to be drawn, in pixels - * \param[in] conHeight height of the console output 'window' to be drawn, in pixels + * \param[in] conWidth width of the console output 'window' to be drawn in pixels + * \param[in] conHeight height of the console output 'window' to be drawn in pixels * * \return 0 on success, <0 on error */ @@ -80,7 +80,7 @@ s32 CON_InitEx(GXRModeObj *rmode, s32 conXOrigin,s32 conYOrigin,s32 conWidth,s32 * \fn CON_GetMetrics(int *cols, int *rows) * \brief retrieve the columns and rows of the current console * - * \param[out] cols,rows number of columns and rows of the current console, in tiles + * \param[out] cols,rows number of columns and rows of the current console in tiles * * \return none */ @@ -90,7 +90,7 @@ void CON_GetMetrics(int *cols, int *rows); * \fn CON_GetPosition(int *col, int *row) * \brief retrieve the current cursor position of the current console * - * \param[out] col,row current cursor position, in tiles, 1-indexed + * \param[out] col,row current cursor position in tiles, 1-indexed * * \return none */ @@ -163,8 +163,8 @@ typedef struct PrintConsole int prevCursorX; ///< Internal state int prevCursorY; ///< Internal state - int con_cols; ///< Width of the console hardware layer in characters (amount of tiles) - int con_rows; ///< Height of the console hardware layer in characters (amount of tiles) + int con_cols; ///< Width of the console hardware layer in characters (aka tiles) + int con_rows; ///< Height of the console hardware layer in characters (aka tiles) int windowX; ///< Window X location in tiles, 1-indexed, 1 <= windowX < con_cols int windowY; ///< Window Y location in tiles, 1-indexed From 6edb95b72fc467a970a9f58c60bcedae39c4658b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20B=2E?= Date: Wed, 3 Sep 2025 12:28:22 +0200 Subject: [PATCH 8/9] ensure con_xres,con_yres multiples of font size avoids an unwritten right/bottom edge that's not part of a complete tile this caused graphical issues and inconsistencies between Init and InitEx document in the function doxygen comment make values in __console_vipostcb only computed once ptr directly from the global equal to destbuffer, less indirection --- gc/ogc/console.h | 6 +++--- libogc/console.c | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/gc/ogc/console.h b/gc/ogc/console.h index 2c958a0e4..230ba6be7 100644 --- a/gc/ogc/console.h +++ b/gc/ogc/console.h @@ -56,7 +56,7 @@ * * \param[in] framebuffer pointer to the framebuffer used for drawing the characters * \param[in] xstart,ystart start position of the console output in pixels - * \param[in] xres,yres size of the console in pixels + * \param[in] xres,yres size of the console in pixels. Truncated to a multiple of font size if not already one * \param[in] stride size of one line of the framebuffer in bytes * * \return none @@ -69,8 +69,8 @@ void CON_Init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stri * \param[in] rmode pointer to the video/render mode configuration * \param[in] conXOrigin starting pixel in X direction of the console output on the external framebuffer * \param[in] conYOrigin starting pixel in Y direction of the console output on the external framebuffer - * \param[in] conWidth width of the console output 'window' to be drawn in pixels - * \param[in] conHeight height of the console output 'window' to be drawn in pixels + * \param[in] conWidth width of the console output 'window' to be drawn in pixels. Truncated to a multiple of font width if not already one + * \param[in] conHeight height of the console output 'window' to be drawn in pixels. Truncated to a multiple of font height if not already one * * \return 0 on success, <0 on error */ diff --git a/libogc/console.c b/libogc/console.c index 74a2ff640..ca8f25c47 100644 --- a/libogc/console.c +++ b/libogc/console.c @@ -213,13 +213,16 @@ void __console_vipostcb(u32 retraceCnt) u8 *fb,*ptr; do_xfb_copy = true; - ptr = currentConsole->destbuffer; + ptr = _console_buffer; fb = __console_offset_by_pixels(VIDEO_GetCurrentFramebuffer(), currentConsole->target_y, currentConsole->tgt_stride, currentConsole->target_x); + const u32 line_count = currentConsole->con_yres; + const u32 bytes_per_line = currentConsole->con_xres * VI_DISPLAY_PIX_SZ; + // Copies 1 line of pixels at a time - for(u16 ycnt = 0; ycnt < currentConsole->con_yres; ycnt++) + for(u16 ycnt = 0; ycnt < line_count; ycnt++) { - memcpy(fb, ptr, currentConsole->con_xres * VI_DISPLAY_PIX_SZ); + memcpy(fb, ptr, bytes_per_line); ptr += currentConsole->con_stride; fb += currentConsole->tgt_stride; } @@ -1059,6 +1062,9 @@ ssize_t __console_write(struct _reent *r,void *fd,const char *ptr, size_t len) void CON_Init(void *framebuffer,int xstart,int ystart,int xres,int yres,int stride) { + // force xres, yres to be multiples of font size + xres = (xres / FONT_XSIZE) * FONT_XSIZE; + yres = (yres / FONT_YSIZE) * FONT_YSIZE; __console_init(framebuffer,xstart,ystart,xres,yres,stride); } @@ -1068,6 +1074,9 @@ s32 CON_InitEx(GXRModeObj *rmode, s32 conXOrigin,s32 conYOrigin,s32 conWidth,s32 if(_console_buffer) free(_console_buffer); + // force conWidth, conHeight to be multiples of font size + conWidth = (conWidth / FONT_XSIZE) * FONT_XSIZE; + conHeight = (conHeight / FONT_YSIZE) * FONT_YSIZE; _console_buffer = malloc(conWidth*conHeight*VI_DISPLAY_PIX_SZ); if(!_console_buffer) return -1; From bb91b11f74b1543ff57dfdf62022967156683d79 Mon Sep 17 00:00:00 2001 From: DacoTaco Date: Wed, 3 Sep 2025 17:59:05 +0200 Subject: [PATCH 9/9] make new functions inline, making them faster in the callback --- libogc/console.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libogc/console.c b/libogc/console.c index ca8f25c47..73a42ba15 100644 --- a/libogc/console.c +++ b/libogc/console.c @@ -149,7 +149,7 @@ PrintConsole currentCopy; PrintConsole* currentConsole = ¤tCopy; -static void *__console_offset_by_pixels(void *ptr, s32 dy_pixels, u32 stride_bytes, s32 dx_pixels) +static inline void *__console_offset_by_pixels(void *ptr, s32 dy_pixels, u32 stride_bytes, s32 dx_pixels) { const s32 dy_bytes = dy_pixels * stride_bytes; const s32 dx_bytes = dx_pixels * VI_DISPLAY_PIX_SZ; @@ -158,12 +158,12 @@ static void *__console_offset_by_pixels(void *ptr, s32 dy_pixels, u32 stride_byt // cursor_y and cursor_x are 1-indexed tile offsets (to start of tile), window offsets are a type of cursor // window/console dimensions are a count of tiles, but 0-indexed -static void *__console_offset_by_cursor(void *ptr, u32 cursor_y, u32 stride_bytes, u32 cursor_x) +static inline void *__console_offset_by_cursor(void *ptr, u32 cursor_y, u32 stride_bytes, u32 cursor_x) { return __console_offset_by_pixels(ptr, (cursor_y - 1) * FONT_YSIZE, stride_bytes, (cursor_x - 1) * FONT_XSIZE); } -static void *__console_get_buffer_start_ptr() +static inline void *__console_get_buffer_start_ptr() { if(!currentConsole) return NULL; @@ -183,7 +183,7 @@ static void *__console_get_buffer_start_ptr() : __console_offset_by_pixels(currentConsole->destbuffer, currentConsole->target_y, currentConsole->tgt_stride, currentConsole->target_x); } -static void *__console_get_window_start_ptr() +static inline void *__console_get_window_start_ptr() { PrintConsole *con; if( !(con = currentConsole) ) @@ -192,7 +192,7 @@ static void *__console_get_window_start_ptr() return __console_offset_by_cursor(__console_get_buffer_start_ptr(), con->windowY, con->con_stride, con->windowX); } -static void *__console_get_cursor_start_ptr() +static inline void *__console_get_cursor_start_ptr() { PrintConsole *con; if( !(con = currentConsole) )