From ff8fd4265469372ff8a57095cb7fd48657e1d1f8 Mon Sep 17 00:00:00 2001 From: Andress Barajas Date: Mon, 21 Oct 2024 20:57:57 -0700 Subject: [PATCH] Add icon printf support Add dc/vmu icon draw functions, fix bios offsets, organized code --- examples/dreamcast/video/bfont/bfont.c | 56 +-- kernel/arch/dreamcast/exports-pristine.txt | 5 + kernel/arch/dreamcast/hardware/biosfont.c | 357 ++++++++++++++++++-- kernel/arch/dreamcast/include/dc/biosfont.h | 202 ++++++++--- 4 files changed, 519 insertions(+), 101 deletions(-) diff --git a/examples/dreamcast/video/bfont/bfont.c b/examples/dreamcast/video/bfont/bfont.c index 2d4192b16..b26c74b8d 100644 --- a/examples/dreamcast/video/bfont/bfont.c +++ b/examples/dreamcast/video/bfont/bfont.c @@ -9,7 +9,7 @@ #include int main(int argc, char **argv) { - int x, y, o; + int x, y; for(y = 0; y < 480; y++) for(x = 0; x < 640; x++) { @@ -21,45 +21,45 @@ int main(int argc, char **argv) { /* Set our starting offset to one letter height away from the top of the screen and two widths from the left */ - o = (640 * BFONT_HEIGHT) + (BFONT_THIN_WIDTH * 2); + x = BFONT_WIDE_WIDTH; + y = BFONT_HEIGHT; /* Test with ISO8859-1 encoding */ bfont_set_encoding(BFONT_CODE_ISO8859_1); - bfont_draw_str(vram_s + o, 640, 1, "Test of basic ASCII"); - /* After each string, we'll increment the offset down by one row */ - o += 640 * BFONT_HEIGHT; - bfont_draw_str(vram_s + o, 640, 1, "Parlez-vous français?"); - o += 640 * BFONT_HEIGHT; - + bfont_draw_str_vram_fmt(x, y, true, + "Test of basic ASCII\nParlez-vous fran�ais?"); + y += 2 * BFONT_HEIGHT; /* Do a second set drawn transparently */ - bfont_draw_str(vram_s + o, 640, 0, "Test of basic ASCII"); - o += 640 * BFONT_HEIGHT; - bfont_draw_str(vram_s + o, 640, 0, "Parlez-vous français?"); - o += 640 * BFONT_HEIGHT; + bfont_draw_str_vram_fmt(x, y, false, + "Test of basic ASCII\nParlez-vous fran�ais?"); + + y += 2 * BFONT_HEIGHT; /* Test with EUC encoding */ bfont_set_encoding(BFONT_CODE_EUC); - bfont_draw_str(vram_s + o, 640, 1, "¤³¤ó¤Ë¤Á¤Ï EUC!"); - o += 640 * BFONT_HEIGHT; - bfont_draw_str(vram_s + o, 640, 0, "¤³¤ó¤Ë¤Á¤Ï EUC!"); - o += 640 * BFONT_HEIGHT; + bfont_draw_str_vram_fmt(x, y, true, "����ˤ��� EUC!"); + y += BFONT_HEIGHT; + bfont_draw_str_vram_fmt(x, y, false, "����ˤ��� EUC!"); + + y += BFONT_HEIGHT; /* Test with Shift-JIS encoding */ bfont_set_encoding(BFONT_CODE_SJIS); - bfont_draw_str(vram_s + o, 640, 1, "ƒAƒhƒŒƒX•ÏŠ· SJIS"); - o += 640 * BFONT_HEIGHT; - bfont_draw_str(vram_s + o, 640, 0, "ƒAƒhƒŒƒX•ÏŠ· SJIS"); - o += 640 * BFONT_HEIGHT; + bfont_draw_str_vram_fmt(x, y, true, "�A�h���X�ϊ� SJIS"); + y += BFONT_HEIGHT; + bfont_draw_str_vram_fmt(x, y, false, "�A�h���X�ϊ� SJIS"); - /* Drawing the special symbols is a bit convoluted. First we'll draw some - standard text as above. */ - bfont_set_encoding(BFONT_CODE_ISO8859_1); - bfont_draw_str(vram_s + o, 640, 1, "To exit, press "); + y += 2 * BFONT_HEIGHT; - /* Then we set the mode to raw to draw the special character. */ - bfont_set_encoding(BFONT_CODE_RAW); - /* Adjust the writing to start after "To exit, press " and draw the one char */ - bfont_draw_wide(vram_s + o + (BFONT_THIN_WIDTH * 15), 640, 1, BFONT_STARTBUTTON); + bfont_set_encoding(BFONT_CODE_ISO8859_1); + bfont_draw_str_vram_fmt(x, y, true, + "We now support DC/VMU icons in printf statements!\n" + "Use diXX for DC icons and viXX for VMU icons in your\n" + "strings. Enhance your text with visual icons like \n" + "\\di03\\di04\\di05\\di06 for navigation, and make your UI more\n" + "intuitive. You can display buttons like \\di0B\\di0C\\di0F\\di10\n" + "\\di12\\di13 and icons like \\vi01\\vi05\\vi21\\vi18\\vi1C effortlessly.\n\n" + "\tTo exit, press \\di14"); /* If Start is pressed, exit the app */ cont_btn_callback(0, CONT_START, (cont_btn_callback_t)arch_exit); diff --git a/kernel/arch/dreamcast/exports-pristine.txt b/kernel/arch/dreamcast/exports-pristine.txt index 5d4d82676..0051081a0 100644 --- a/kernel/arch/dreamcast/exports-pristine.txt +++ b/kernel/arch/dreamcast/exports-pristine.txt @@ -100,6 +100,7 @@ bfont_find_char bfont_find_char_jp bfont_find_char_jp_half bfont_find_icon +bfont_find_dc_icon bfont_draw_ex bfont_draw bfont_draw_thin @@ -111,6 +112,10 @@ bfont_draw_str bfont_draw_str_fmt bfont_draw_str_vram_vfmt bfont_draw_str_vram_fmt +bfont_draw_vmu_icon_ex +bfont_draw_vmu_icon +bfont_draw_dc_icon_ex +bfont_draw_dc_icon # CD-Rom cdrom_reinit diff --git a/kernel/arch/dreamcast/hardware/biosfont.c b/kernel/arch/dreamcast/hardware/biosfont.c index e95e23027..ee67e2556 100644 --- a/kernel/arch/dreamcast/hardware/biosfont.c +++ b/kernel/arch/dreamcast/hardware/biosfont.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -308,12 +309,265 @@ size_t bfont_draw_wide(void *buffer, uint32_t bufwidth, bool opaque, uint32_t c) bits_per_pixel(), opaque, c, true, false); } +size_t bfont_draw_vmu_icon_ex(void *buffer, uint32_t bufwidth, uint32_t fg, + uint32_t bg, uint8_t bpp, bool opaque, + bfont_vmu_icon_t icon) { + uint8_t *buf8; + uint16_t *buf16; + uint32_t *buf32; + uint8_t row, col; + uint32_t color, bitmask; + uint32_t row_offset, icon_row_data; + uint8_t *icon_data = bfont_find_icon(icon); + + if(!icon_data) { + dbglog(DBG_ERROR, "bfont_draw_vmu_icon_ex: Invalid icon\n"); + return 0; + } + + /* Iterate over each row of the 32x32 icon */ + for(row = 0; row < BFONT_ICON_DIMEN; ++row) { + /* Calculate the starting position of the current row in the buffer */ + row_offset = row * bufwidth; + + /* Retrieve the 32-bit word for this row from the icon data */ + icon_row_data = __builtin_bswap32(((uint32_t *)icon_data)[row]); + + /* Start with the bitmask for the highest bit in a 32-bit word */ + bitmask = 0x80000000; + + /* Handle different bits-per-pixel cases */ + switch(bpp) { + case 4: + buf8 = (uint8_t *)buffer + (row_offset * bpp) / 8; + for(col = 0; col < BFONT_ICON_DIMEN; ++col) { + color = (icon_row_data & bitmask) ? + fg & 0x0F : (opaque ? bg & 0x0F : 0); + if(!(icon_row_data & bitmask) && !opaque) { + color = (col % 2 == 0) ? + (buf8[col / 2] >> 4) & 0x0F : buf8[col / 2] & 0x0F; + } + buf8[col / 2] = (col % 2 == 0) ? + (buf8[col / 2] & 0x0F) | (color << 4) : + (buf8[col / 2] & 0xF0) | color; + bitmask >>= 1; + } + break; + + case 8: + buf8 = (uint8_t *)buffer + row_offset; + for(col = 0; col < BFONT_ICON_DIMEN; ++col) { + color = (icon_row_data & bitmask) ? + fg & 0xFF : (opaque ? bg & 0xFF : buf8[col]); + buf8[col] = color; + bitmask >>= 1; + } + break; + + case 16: + buf16 = (uint16_t *)buffer + row_offset; + for(col = 0; col < BFONT_ICON_DIMEN; ++col) { + color = (icon_row_data & bitmask) ? + fg & 0xFFFF : (opaque ? bg & 0xFFFF : buf16[col]); + buf16[col] = color; + bitmask >>= 1; + } + break; + + case 32: + buf32 = (uint32_t *)buffer + row_offset; + for(col = 0; col < BFONT_ICON_DIMEN; ++col) { + color = (icon_row_data & bitmask) ? + fg : (opaque ? bg : buf32[col]); + buf32[col] = color; + bitmask >>= 1; + } + break; + + default: + dbglog(DBG_ERROR, "bfont_draw_vmu_icon_ex: Unsupported bpp %d\n", bpp); + return 0; + } + } + + /* Return the horizontal distance covered in bytes */ + return (BFONT_ICON_DIMEN * bpp) / 8; +} + +/* Draw a VMU icon to a buffer */ +size_t bfont_draw_vmu_icon(void *buffer, uint32_t bufwidth, bool opaque, + bfont_vmu_icon_t icon) { + return bfont_draw_vmu_icon_ex(buffer, bufwidth, bfont_fgcolor, bfont_bgcolor, + bits_per_pixel(), opaque, icon); +} + +size_t bfont_draw_dc_icon_ex(void *buffer, uint32_t bufwidth, uint32_t fg, + uint32_t bg, uint8_t bpp, bool opaque, + bfont_dc_icon_t icon) { + uint8_t *buf8; + uint16_t *buf16; + uint32_t *buf32; + uint32_t color; + uint32_t row_offset; + uint8_t row, col, byte, icon_byte, bitmask; + uint8_t *icon_data = bfont_find_dc_icon(icon); + + if(!icon_data) { + dbglog(DBG_ERROR, "bfont_draw_dc_icon_ex: Invalid DC icon\n"); + return 0; + } + + /* Iterate over each row of the 24x24 icon */ + for(row = 0; row < BFONT_HEIGHT; ++row) { + /* Calculate the starting position of the current row in the buffer */ + row_offset = row * bufwidth; + + /* Start with the first byte in the row of the 24x24 icon data */ + for(byte = 0; byte < 3; ++byte) { + /* Grab the 8 bits (1 byte) of icon data */ + icon_byte = icon_data[row * 3 + byte]; + + /* Process each bit in this byte */ + bitmask = 0x80; + + for(col = byte * 8; col < (byte + 1) * 8 && col < BFONT_WIDE_WIDTH; ++col) { + /* Handle different bits-per-pixel cases */ + switch (bpp) { + case 4: + buf8 = (uint8_t *)buffer + (row_offset * bpp) / 8; + color = (icon_byte & bitmask) ? (fg & 0x0F) : (opaque ? (bg & 0x0F) : 0); + if (!(icon_byte & bitmask) && !opaque) { + color = (col % 2 == 0) ? + ((buf8[col / 2] >> 4) & 0x0F) : (buf8[col / 2] & 0x0F); + } + buf8[col / 2] = (col % 2 == 0) ? + ((buf8[col / 2] & 0x0F) | (color << 4)) : + ((buf8[col / 2] & 0xF0) | color); + break; + + case 8: + buf8 = (uint8_t *)buffer + row_offset; + color = (icon_byte & bitmask) ? + (fg & 0xFF) : (opaque ? (bg & 0xFF) : buf8[col]); + buf8[col] = color; + break; + + case 16: + buf16 = (uint16_t *)buffer + row_offset; + color = (icon_byte & bitmask) ? + (fg & 0xFFFF) : (opaque ? (bg & 0xFFFF) : buf16[col]); + buf16[col] = color; + break; + + case 32: + buf32 = (uint32_t *)buffer + row_offset; + color = (icon_byte & bitmask) ? + fg : (opaque ? bg : buf32[col]); + buf32[col] = color; + break; + + default: + dbglog(DBG_ERROR, "bfont_draw_dc_icon_ex: Unsupported bpp %d\n", bpp); + return 0; + } + + /* Shift the bitmask to the next bit */ + bitmask >>= 1; + } + } + } + + /* Return the horizontal distance covered in bytes */ + return (BFONT_WIDE_WIDTH * bpp) / 8; +} + +/* Draw a DC icon to a buffer */ +size_t bfont_draw_dc_icon(void *buffer, uint32_t bufwidth, bool opaque, + bfont_dc_icon_t icon) { + return bfont_draw_dc_icon_ex(buffer, bufwidth, bfont_fgcolor, bfont_bgcolor, + bits_per_pixel(), opaque, icon); +} + +/* Scans a string to see if it contains a vmu icon */ +static bool contains_vmu_icon(const char *str) { + const char *scan_str = str; + + while(*scan_str && *scan_str != '\n') { + /* Check for the VMU icon escape sequence: \viXX */ + if(*scan_str == '\\' && *(scan_str + 1) == 'v' && *(scan_str + 2) == 'i') + return true; + scan_str++; + } + + return false; +} + +/* Draw vertical padding for 24 pixel high characters that are on the same line + as VMU icons */ +static void draw_vertical_padding(void *buffer, uint32_t bufwidth, uint32_t bg, + uint8_t bpp, uint8_t chr_width) { + uint8_t *buf8; + uint16_t *buf16; + uint32_t *buf32; + uint8_t padding_rows = BFONT_ICON_DIMEN - BFONT_HEIGHT; + uint32_t row, col; + + /* Iterate over each row of padding */ + for(row = 0; row < padding_rows; ++row) { + switch(bpp) { + case 4: + buf8 = (uint8_t *)buffer + (row * bufwidth * bpp) / 8; + for(col = 0; col < chr_width; ++col) { + /* Write background color in 4bpp (two pixels per byte) */ + if(col % 2 == 0) /* High nibble */ + buf8[col / 2] = (bg & 0x0F) << 4 | (buf8[col / 2] & 0x0F); + else /* Low nibble */ + buf8[col / 2] = (buf8[col / 2] & 0xF0) | (bg & 0x0F); + } + break; + + case 8: + buf8 = (uint8_t *)buffer + row * bufwidth; + for(col = 0; col < chr_width; ++col) + buf8[col] = bg & 0xFF; + break; + + case 16: + buf16 = (uint16_t *)buffer + row * bufwidth; + for(col = 0; col < chr_width; ++col) + buf16[col] = bg & 0xFFFF; + break; + + case 32: + buf32 = (uint32_t *)buffer + row * bufwidth; + for(col = 0; col < chr_width; ++col) + buf32[col] = bg; + break; + + default: + dbglog(DBG_ERROR, "draw_vertical_padding: Unsupported bpp %d\n", bpp); + return; + } + } +} + void bfont_draw_str_ex(void *buffer, uint32_t width, uint32_t fg, uint32_t bg, uint8_t bpp, bool opaque, const char *str) { bool wideChr; uint16_t nChr, nMask; uint32_t line_start = 0; + char icon_hex[3]; + uint32_t row_offset = 0; + uint8_t row_height = BFONT_HEIGHT; + bfont_dc_icon_t dc_icon_code; + bfont_vmu_icon_t vmu_icon_code; uint8_t *buf = (uint8_t *)buffer; + + /* Check the line for VMU icons and adjust row height/offset */ + if(contains_vmu_icon(str)) { + row_height = BFONT_ICON_DIMEN; + row_offset = (BFONT_ICON_DIMEN - BFONT_HEIGHT) * width * (bpp / 8); + } while(*str) { wideChr = false; @@ -321,32 +575,76 @@ void bfont_draw_str_ex(void *buffer, uint32_t width, uint32_t fg, uint32_t bg, if(nChr == '\n') { /* Move to the beginning of the next line */ - buf = (uint8_t *)buffer + line_start + (width * BFONT_HEIGHT * (bpp / 8)); + buf = (uint8_t *)buffer + line_start + (width * row_height * (bpp / 8)); line_start = buf - (uint8_t *)buffer; + + /* Reset row height and row_offset for the new line */ + row_height = BFONT_HEIGHT; + row_offset = 0; + + /* Check the new line for VMU icons and adjust row height/offset */ + if(contains_vmu_icon(str+1)) { + row_height = BFONT_ICON_DIMEN; + row_offset = (BFONT_ICON_DIMEN - BFONT_HEIGHT) * width * (bpp / 8); + } + str++; continue; } else if(nChr == '\t') { /* Draw four spaces on the current line */ if(opaque) { + if(row_height == BFONT_ICON_DIMEN) + draw_vertical_padding(buf, width, bg, bpp, 4 * BFONT_THIN_WIDTH); + nChr = bfont_code_mode == BFONT_CODE_ISO8859_1 ? 0x20 : 0xa0; - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, false); - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, false); - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, false); - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, false); + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, false); + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, false); + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, false); + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, false); } else /* Spaces are always thin width characters */ - buf += (4 * ((BFONT_THIN_WIDTH * bpp)/8)); - + buf += (4 * ((BFONT_THIN_WIDTH * bpp) / 8)); + str++; continue; } + /* Check for the DC icon escape sequence: \diXX */ + else if(nChr == '\\' && *(str + 1) == 'd' && *(str + 2) == 'i') { + /* Parse the two hexadecimal characters following \di */ + icon_hex[0] = *(str + 3); + icon_hex[1] = *(str + 4); + icon_hex[2] = '\0'; + dc_icon_code = (bfont_dc_icon_t)strtol(icon_hex, NULL, 16); + + if(opaque && row_height == BFONT_ICON_DIMEN) + draw_vertical_padding(buf, width, bg, bpp, BFONT_WIDE_WIDTH); + + buf += bfont_draw_dc_icon_ex(buf + row_offset, width, fg, bg, bpp, opaque, dc_icon_code); + + /* Advance the string pointer by 5 to skip \diXX */ + str += 5; + continue; + } + /* Check for the VMU icon escape sequence: \viXX */ + else if(nChr == '\\' && *(str + 1) == 'v' && *(str + 2) == 'i') { + /* Parse the two hexadecimal characters following \vi */ + icon_hex[0] = *(str + 3); + icon_hex[1] = *(str + 4); + icon_hex[2] = '\0'; + vmu_icon_code = (bfont_vmu_icon_t)strtol(icon_hex, NULL, 16); + + buf += bfont_draw_vmu_icon_ex(buf, width, fg, bg, bpp, opaque, vmu_icon_code); + + /* Advance the string pointer by 5 to skip \viXX */ + str += 5; + continue; + } /* Non-western, non-ASCII character */ if(bfont_code_mode != BFONT_CODE_ISO8859_1 && (nChr & 0x80)) { switch(bfont_code_mode) { case BFONT_CODE_EUC: - /* Check if the character is the 'SS2' character in EUC-JP */ if(nChr == 0x8e) { str++; @@ -358,16 +656,15 @@ void bfont_draw_str_ex(void *buffer, uint32_t width, uint32_t fg, uint32_t bg, } else wideChr = true; - break; + case BFONT_CODE_SJIS: nMask = nChr & 0xf0; - /* Check if the character is part of the valid Shift ranges */ if((nMask == 0x80) || (nMask == 0x90) || (nMask == 0xe0)) wideChr = true; - break; + default: assert_msg(0, "Unknown bfont encoding mode"); } @@ -375,13 +672,24 @@ void bfont_draw_str_ex(void *buffer, uint32_t width, uint32_t fg, uint32_t bg, if(wideChr) { str++; nChr = (nChr << 8) | (*str & 0xff); - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, true, false); + if(opaque && row_height == BFONT_ICON_DIMEN) + draw_vertical_padding(buf, width, bg, bpp, BFONT_WIDE_WIDTH); + + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, true, false); + } + else { + if(opaque && row_height == BFONT_ICON_DIMEN) + draw_vertical_padding(buf, width, bg, bpp, BFONT_THIN_WIDTH); + + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, true); } - else - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, true); } - else - buf += bfont_draw_ex(buf, width, fg, bg, bpp, opaque, nChr, false, false); + else { + if(opaque && row_height == BFONT_ICON_DIMEN) + draw_vertical_padding(buf, width, bg, bpp, BFONT_THIN_WIDTH); + + buf += bfont_draw_ex(buf + row_offset, width, fg, bg, bpp, opaque, nChr, false, false); + } str++; } @@ -455,11 +763,22 @@ void bfont_draw_str_vram_fmt(uint32_t x, uint32_t y, bool opaque, } uint8_t *bfont_find_icon(bfont_vmu_icon_t icon) { - if(icon > BFONT_ICON_EMBROIDERY) + if(icon < BFONT_ICON_INVALID_VMU || icon > BFONT_ICON_EMBROIDERY) + return NULL; + + uint32_t icon_offset = BFONT_VMU_DREAMCAST_SPECIFIC + + (icon * BFONT_BYTES_PER_VMU_ICON); + uint8_t *fa = get_font_address(); + + return fa + icon_offset; +} + +uint8_t *bfont_find_dc_icon(bfont_dc_icon_t icon) { + if(icon < BFONT_ICON_CIRCLECOPYRIGHT || icon > BFONT_ICON_VMU) return NULL; - int icon_offset = BFONT_VMU_DREAMCAST_SPECIFIC + - (icon * BFONT_ICON_DIMEN * BFONT_ICON_DIMEN / 8); + uint32_t icon_offset = BFONT_DREAMCAST_SPECIFIC + + (icon * BFONT_BYTES_PER_WIDE_CHAR); uint8_t *fa = get_font_address(); return fa + icon_offset; diff --git a/kernel/arch/dreamcast/include/dc/biosfont.h b/kernel/arch/dreamcast/include/dc/biosfont.h index 23794449c..d02fc11b0 100644 --- a/kernel/arch/dreamcast/include/dc/biosfont.h +++ b/kernel/arch/dreamcast/include/dc/biosfont.h @@ -39,28 +39,38 @@ __BEGIN_DECLS #include /** \defgroup bfont BIOS - \brief API for the Dreamcast's built-in BIOS font + \brief API for the Dreamcast's built-in BIOS font. \ingroup video_fonts @{ */ /** \defgroup bfont_size Dimensions - \brief Font size definitions for the BIOS fonts + \brief Font size definitions for the BIOS fonts. @{ */ #define BFONT_THIN_WIDTH 12 /**< \brief Width of Thin Font (ISO8859_1, half-JP) */ #define BFONT_WIDE_WIDTH (BFONT_THIN_WIDTH * 2) /**< \brief Width of Wide Font (full-JP) */ #define BFONT_HEIGHT 24 /**< \brief Height of All Fonts */ +#define BFONT_ICON_DIMEN 32 /**< \brief Dimension of vmu icons */ /** @} */ +/** \defgroup bfont_byte_size Byte Sizes + \brief Byte size definitions for the BIOS fonts. + @{ +*/ /** \brief Number of bytes to represent a single thin character within the BIOS font. */ #define BFONT_BYTES_PER_CHAR (BFONT_THIN_WIDTH * BFONT_HEIGHT / 8) /** \brief Number of bytes to represent a single wide character within the BIOS font. */ #define BFONT_BYTES_PER_WIDE_CHAR (BFONT_WIDE_WIDTH * BFONT_HEIGHT / 8) +/** \brief Number of bytes to represent a vmu icon within the BIOS font. */ +#define BFONT_BYTES_PER_VMU_ICON (BFONT_ICON_DIMEN * BFONT_ICON_DIMEN / 8) + +/** @} */ + /** \defgroup bfont_indicies Structure - \brief Structure of the Bios Font + \brief Structure of the Bios Font. @{ */ /** \brief Start of Narrow Characters in Font Block */ @@ -73,58 +83,62 @@ __BEGIN_DECLS /* JISX-0208 Rows 1-7 and 16-84 are encoded between BFONT_WIDE_START and BFONT_DREAMCAST_SPECIFIC. Only the box-drawing characters (row 8) are missing. */ /** \brief Size of a row for JISX-0208 characters */ -#define JISX_0208_ROW_SIZE 94 +#define JISX_0208_ROW_SIZE 94 /** \brief Start of Wide Characters in Font Block */ -#define BFONT_WIDE_START (288 * BFONT_BYTES_PER_CHAR) +#define BFONT_WIDE_START (288 * BFONT_BYTES_PER_CHAR) /** \brief Start of JISX-0208 Rows 1-7 in Font Block */ -#define BFONT_JISX_0208_ROW1 BFONT_WIDE_START +#define BFONT_JISX_0208_ROW1 BFONT_WIDE_START /** \brief Start of JISX-0208 Row 16-47 (Start of Level 1) in Font Block */ -#define BFONT_JISX_0208_ROW16 (BFONT_WIDE_START + (658 * BFONT_BYTES_PER_CHAR)) +#define BFONT_JISX_0208_ROW16 (BFONT_WIDE_START + (658 * BFONT_BYTES_PER_WIDE_CHAR)) /** \brief JISX-0208 Row 48-84 (Start of Level 2) in Font Block */ -#define BFONT_JISX_0208_ROW48 (BFONT_JISX_0208_ROW16 + ((32 * JISX_0208_ROW_SIZE) * BFONT_BYTES_PER_CHAR)) +#define BFONT_JISX_0208_ROW48 (BFONT_JISX_0208_ROW16 + ((32 * JISX_0208_ROW_SIZE) * BFONT_BYTES_PER_WIDE_CHAR)) -/** \brief Start of DC Specific Characters in Font Block */ -#define BFONT_DREAMCAST_SPECIFIC (BFONT_WIDE_START + (7056 * BFONT_BYTES_PER_CHAR)) -/** \brief Takes a DC-specific icon index and returns a character offset. */ -#define BFONT_DC_ICON(offset) (BFONT_DREAMCAST_SPECIFIC + ((offset) * BFONT_BYTES_PER_CHAR)) +/** \brief Start of DC Specific Icons in Font Block */ +#define BFONT_DREAMCAST_SPECIFIC (BFONT_WIDE_START + (7056 * BFONT_BYTES_PER_WIDE_CHAR)) + +/** \brief Start of VMU Specific Icons in Font Block */ +#define BFONT_VMU_DREAMCAST_SPECIFIC (BFONT_DREAMCAST_SPECIFIC+(22 * BFONT_BYTES_PER_WIDE_CHAR)) -/** \defgroup bfont_dc_indices Dreamcast-Specific - \brief Dreamcast-specific BIOS icon offsets. - @{ -*/ -#define BFONT_CIRCLECOPYRIGHT BFONT_DC_ICON(0) /**< \brief Circle copyright */ -#define BFONT_CIRCLER BFONT_DC_ICON(1) /**< \brief Circle restricted */ -#define BFONT_TRADEMARK BFONT_DC_ICON(2) /**< \brief Trademark */ -#define BFONT_UPARROW BFONT_DC_ICON(3) /**< \brief Up arrow */ -#define BFONT_DOWNARROW BFONT_DC_ICON(4) /**< \brief Down arrow */ -#define BFONT_LEFTARROW BFONT_DC_ICON(5) /**< \brief Left arrow */ -#define BFONT_RIGHTARROW BFONT_DC_ICON(6) /**< \brief Right arrow */ -#define BFONT_UPRIGHTARROW BFONT_DC_ICON(7) /**< \brief Up right arrow */ -#define BFONT_DOWNRIGHTARROW BFONT_DC_ICON(8) /**< \brief Down right arrow */ -#define BFONT_DOWNLEFTARROW BFONT_DC_ICON(9) /**< \brief Down left arrow */ -#define BFONT_UPLEFTARROW BFONT_DC_ICON(10) /**< \brief Up left arrow */ -#define BFONT_ABUTTON BFONT_DC_ICON(11) /**< \brief A button */ -#define BFONT_BBUTTON BFONT_DC_ICON(12) /**< \brief B button */ -#define BFONT_CBUTTON BFONT_DC_ICON(13) /**< \brief C button */ -#define BFONT_DBUTTON BFONT_DC_ICON(14) /**< \brief D button */ -#define BFONT_XBUTTON BFONT_DC_ICON(15) /**< \brief X button */ -#define BFONT_YBUTTON BFONT_DC_ICON(16) /**< \brief Y button */ -#define BFONT_ZBUTTON BFONT_DC_ICON(17) /**< \brief Z button */ -#define BFONT_LTRIGGER BFONT_DC_ICON(18) /**< \brief L trigger */ -#define BFONT_RTRIGGER BFONT_DC_ICON(19) /**< \brief R trigger */ -#define BFONT_STARTBUTTON BFONT_DC_ICON(20) /**< \brief Start button */ -#define BFONT_VMUICON BFONT_DC_ICON(21) /**< \brief VMU icon */ /** @} */ -#define BFONT_ICON_DIMEN 32 /**< \brief Dimension of vmu icons */ -#define BFONT_VMU_DREAMCAST_SPECIFIC (BFONT_DREAMCAST_SPECIFIC+(22 * BFONT_BYTES_PER_CHAR)) +/** \brief Builtin DC Icons + \ingroup bfont_indicies + + Builtin DC user icons. + @{ +*/ +typedef enum bfont_dc_icon { + BFONT_ICON_CIRCLECOPYRIGHT = 0x00, /**< \brief Circle copyright */ + BFONT_CIRCLER = 0x01, /**< \brief Circle restricted */ + BFONT_ICON_TRADEMARK = 0x02, /**< \brief Trademark */ + BFONT_ICON_UPARROW = 0x03, /**< \brief Up arrow */ + BFONT_ICON_DOWNARROW = 0x04, /**< \brief Down arrow */ + BFONT_ICON_LEFTARROW = 0x05, /**< \brief Left arrow */ + BFONT_ICON_RIGHTARROW = 0x06, /**< \brief Right arrow */ + BFONT_ICON_UPRIGHTARROW = 0x07, /**< \brief Up right arrow */ + BFONT_ICON_DOWNRIGHTARROW = 0x08, /**< \brief Down right arrow */ + BFONT_ICON_DOWNLEFTARROW = 0x09, /**< \brief Down left arrow */ + BFONT_ICON_UPLEFTARROW = 0x0A, /**< \brief Up left arrow */ + BFONT_ICON_ABUTTON = 0x0B, /**< \brief A button */ + BFONT_ICON_BBUTTON = 0x0C, /**< \brief B button */ + BFONT_ICON_CBUTTON = 0x0D, /**< \brief C button */ + BFONT_ICON_DBUTTON = 0x0E, /**< \brief D button */ + BFONT_ICON_XBUTTON = 0x0F, /**< \brief X button */ + BFONT_ICON_YBUTTON = 0x10, /**< \brief Y button */ + BFONT_ICON_ZBUTTON = 0x11, /**< \brief Z button */ + BFONT_ICON_LTRIGGER = 0x12, /**< \brief L trigger */ + BFONT_ICON_RTRIGGER = 0x13, /**< \brief R trigger */ + BFONT_ICON_STARTBUTTON = 0x14, /**< \brief Start button */ + BFONT_ICON_VMU = 0x15 /**< \brief VMU icon */ +} bfont_dc_icon_t; /** @} */ /** \brief Builtin VMU Icons \ingroup bfont_indicies - Builtin VMU volume user icons. The Dreamcast's - BIOS allows the user to set these when formatting the VMU. + Builtin VMU volume user icons. The Dreamcast's BIOS allows the + user to set these when formatting the VMU. + @{ */ typedef enum bfont_vmu_icon { BFONT_ICON_INVALID_VMU = 0x00, /**< \brief Invalid */ @@ -364,6 +378,18 @@ uint8_t *bfont_find_char_jp_half(uint32_t ch); */ uint8_t *bfont_find_icon(bfont_vmu_icon_t icon); +/** \brief Find a DC icon. + + This function retrieves a pointer to the icon data for the specified DC + icon in the bios, if its available. Each dc icon has dimensions 24x24 pixels + and is 72 bytes long. + + \param icon The DC icon index to look up. + \return A pointer to the raw icon data or NULL if icon value + is incorrect. +*/ +uint8_t *bfont_find_dc_icon(bfont_dc_icon_t icon); + /** @} */ /** \name Character Drawing @@ -371,24 +397,24 @@ uint8_t *bfont_find_icon(bfont_vmu_icon_t icon); @{ */ -/** \brief Draw a single character of any sort to the buffer. +/** \brief Draw a single character of any sort to a buffer. This function draws a single character in the set encoding to the given buffer. This function sits under draw, draw_thin, and draw_wide, while exposing the colors and bitdepths desired. This will allow the writing of bfont characters to paletted textures. - \param buffer The buffer to draw to. - \param bufwidth The width of the buffer in pixels. - \param fg The foreground color to use. - \param bg The background color to use. - \param bpp The number of bits per pixel in the buffer. - \param opaque If true, overwrite background areas with black, - otherwise do not change them from what they are. - \param c The character to draw. - \param wide Draw a wide character. - \param iskana Draw a half-width kana character. - \return Amount of width covered in bytes. + \param buffer The buffer to draw to + \param bufwidth The width of the buffer in pixels + \param fg The foreground color to use + \param bg The background color to use + \param bpp The number of bits per pixel in the buffer + \param opaque If true, overwrite background areas with black, + otherwise do not change them from what they are + \param c The character to draw + \param wide Draw a wide character + \param iskana Draw a half-width kana character + \return Amount of width covered in bytes */ size_t bfont_draw_ex(void *buffer, uint32_t bufwidth, uint32_t fg, uint32_t bg, uint8_t bpp, bool opaque, uint32_t c, @@ -440,6 +466,72 @@ size_t bfont_draw_thin(void *buffer, uint32_t bufwidth, bool opaque, size_t bfont_draw_wide(void *buffer, uint32_t bufwidth, bool opaque, uint32_t c); +/** \brief Draw a VMU icon to the buffer. + + This function draws a 32x32 VMU icon to the given buffer, supporting + multiple color depths (4, 8, 16, and 32 bits per pixel). + + \param buffer The buffer to draw to (at least 32 x 32 pixels) + \param bufwidth The width of the buffer in pixels + \param fg The foreground color to use + \param bg The background color to use + \param bpp The number of bits per pixel in the buffer + \param opaque If true, overwrite background areas with black, + otherwise do not change them from what they are + \param icon The VMU icon to draw + \return Amount of width covered in bytes +*/ +size_t bfont_draw_vmu_icon_ex(void *buffer, uint32_t bufwidth, uint32_t fg, + uint32_t bg, uint8_t bpp, bool opaque, + bfont_vmu_icon_t icon); + +/** \brief Draw a VMU icon to a buffer. + + This function draws a 32x32 VMU icon to the given buffer. + + \param buffer The buffer to draw to (at least 32 x 32 pixels) + \param bufwidth The width of the buffer in pixels + \param opaque If true, overwrite blank areas with black, + otherwise do not change them from what they are + \param icon The VMU icon to draw + \return Amount of width covered in bytes. +*/ +size_t bfont_draw_vmu_icon(void *buffer, uint32_t bufwidth, bool opaque, + bfont_vmu_icon_t icon); + +/** \brief Draw a DC icon to the buffer. + + This function draws a 24x24 DC icon to the given buffer, supporting + multiple color depths (4, 8, 16, and 32 bits per pixel). + + \param buffer The buffer to draw to (at least 24 x 24 pixels) + \param bufwidth The width of the buffer in pixels + \param fg The foreground color to use + \param bg The background color to use + \param bpp The number of bits per pixel in the buffer + \param opaque If true, overwrite background areas with black, + otherwise do not change them from what they are + \param icon The DC icon to draw + \return Amount of width covered in bytes +*/ +size_t bfont_draw_dc_icon_ex(void *buffer, uint32_t bufwidth, uint32_t fg, + uint32_t bg, uint8_t bpp, bool opaque, + bfont_dc_icon_t icon); + +/** \brief Draw a DC icon to a buffer. + + This function draws a 24x24 DC icon to the given buffer. + + \param buffer The buffer to draw to (at least 24 x 24 pixels) + \param bufwidth The width of the buffer in pixels + \param opaque If true, overwrite blank areas with black, + otherwise do not change them from what they are + \param icon The DC icon to draw + \return Amount of width covered in bytes. +*/ +size_t bfont_draw_dc_icon(void *buffer, uint32_t bufwidth, bool opaque, + bfont_dc_icon_t icon); + /** @} */ /** \name String Drawing @@ -580,6 +672,8 @@ void bfont_draw_str_vram_fmt(uint32_t x, uint32_t y, bool opaque, const char *fm /** @} */ +/** @} */ + __END_DECLS #endif /* __DC_BIOSFONT_H */