Add loading font from an FRF file

This commit is contained in:
Pk11 2021-08-12 16:56:52 -05:00
parent ce49d1fdf9
commit bba0daa23a
5 changed files with 65 additions and 29 deletions

View File

@ -196,6 +196,8 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
operations.push_back(FileOperation::restoreSave); operations.push_back(FileOperation::restoreSave);
} else if(extension(entry->name, {"img", "sd"})) { } else if(extension(entry->name, {"img", "sd"})) {
operations.push_back(FileOperation::mountImg); operations.push_back(FileOperation::mountImg);
} else if(extension(entry->name, {"frf"})) {
operations.push_back(FileOperation::loadFont);
} }
operations.push_back(FileOperation::hexEdit); operations.push_back(FileOperation::hexEdit);
@ -261,6 +263,9 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
case FileOperation::calculateSHA1: case FileOperation::calculateSHA1:
font->print(3, row++, false, "Calculate SHA1 hash"); font->print(3, row++, false, "Calculate SHA1 hash");
break; break;
case FileOperation::loadFont:
font->print(3, row++, false, "Load font");
break;
case FileOperation::none: case FileOperation::none:
row++; row++;
break; break;
@ -401,6 +406,10 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
} case FileOperation::hexEdit: { } case FileOperation::hexEdit: {
hexEditor(entry->name.c_str(), currentDrive); hexEditor(entry->name.c_str(), currentDrive);
break; break;
} case FileOperation::loadFont: {
delete font;
font = new Font(entry->name.c_str());
break;
} case FileOperation::calculateSHA1: { } case FileOperation::calculateSHA1: {
u8 sha1[20] = {0}; u8 sha1[20] = {0};
bool ret = calculateSHA1(strcat(getcwd(path, PATH_MAX), entry->name.c_str()), sha1); bool ret = calculateSHA1(strcat(getcwd(path, PATH_MAX), entry->name.c_str()), sha1);

View File

@ -47,6 +47,7 @@ enum class FileOperation {
copyFatOut, copyFatOut,
calculateSHA1, calculateSHA1,
hexEdit, hexEdit,
loadFont,
}; };
bool extension(const std::string &filename, const std::vector<std::string> &extensions); bool extension(const std::string &filename, const std::vector<std::string> &extensions);

View File

@ -24,7 +24,7 @@ bool Font::isNumber(char16_t c) {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
Font::Font(const char *path) { bool Font::load(const char *path) {
FILE *file = fopen(path, "rb"); FILE *file = fopen(path, "rb");
const u8 *fileBuffer = font_default_frf; const u8 *fileBuffer = font_default_frf;
@ -35,7 +35,7 @@ Font::Font(const char *path) {
fileBuffer = new u8[size]; fileBuffer = new u8[size];
if(!fileBuffer) { if(!fileBuffer) {
fclose(file); fclose(file);
return; return false;
} }
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
@ -44,8 +44,12 @@ Font::Font(const char *path) {
const u8 *ptr = fileBuffer; const u8 *ptr = fileBuffer;
// Check header magic, then skip over // Check header magic, then skip over
if(memcmp(ptr, "RIFF", 4) != 0) if(memcmp(ptr, "RIFF", 4) != 0) {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
return false;
}
ptr += 8; ptr += 8;
@ -55,21 +59,32 @@ Font::Font(const char *path) {
tileHeight = ptr[9]; tileHeight = ptr[9];
tonccpy(&tileCount, ptr + 10, sizeof(u16)); tonccpy(&tileCount, ptr + 10, sizeof(u16));
if(tileWidth > TILE_MAX_WIDTH || tileHeight > TILE_MAX_HEIGHT) if(tileWidth > TILE_MAX_WIDTH || tileHeight > TILE_MAX_HEIGHT) {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
return false;
}
u32 section_size; u32 section_size;
tonccpy(&section_size, ptr + 4, sizeof(u32)); tonccpy(&section_size, ptr + 4, sizeof(u32));
ptr += 8 + section_size; ptr += 8 + section_size;
} else { } else {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
return false;
} }
// Character data // Character data
if(memcmp(ptr, "CDAT", 4) == 0) { if(memcmp(ptr, "CDAT", 4) == 0) {
fontTiles = new u8[tileHeight * tileCount]; fontTiles = new u8[tileHeight * tileCount];
if(!fontTiles) if(!fontTiles) {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
return false;
}
tonccpy(fontTiles, ptr + 8, tileHeight * tileCount); tonccpy(fontTiles, ptr + 8, tileHeight * tileCount);
@ -77,14 +92,23 @@ Font::Font(const char *path) {
tonccpy(&section_size, ptr + 4, sizeof(u32)); tonccpy(&section_size, ptr + 4, sizeof(u32));
ptr += 8 + section_size; ptr += 8 + section_size;
} else { } else {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
return false;
} }
// character map // character map
if(memcmp(ptr, "CMAP", 4) == 0) { if(memcmp(ptr, "CMAP", 4) == 0) {
fontMap = new u16[tileCount]; fontMap = new u16[tileCount];
if(!fontMap) if(!fontMap) {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
delete[] fontTiles;
return false;
}
tonccpy(fontMap, ptr + 8, sizeof(u16) * tileCount); tonccpy(fontMap, ptr + 8, sizeof(u16) * tileCount);
@ -92,7 +116,12 @@ Font::Font(const char *path) {
tonccpy(&section_size, ptr + 4, sizeof(u32)); tonccpy(&section_size, ptr + 4, sizeof(u32));
ptr += 8 + section_size; ptr += 8 + section_size;
} else { } else {
goto cleanup; if(fileBuffer != font_default_frf)
delete[] fileBuffer;
delete[] fontTiles;
return false;
} }
questionMark = getCharIndex('?'); questionMark = getCharIndex('?');
@ -103,9 +132,16 @@ Font::Font(const char *path) {
tonccpy(BG_PALETTE_SUB + i * 0x10, palette[i], 4); tonccpy(BG_PALETTE_SUB + i * 0x10, palette[i], 4);
} }
cleanup:
if(fileBuffer != font_default_frf) if(fileBuffer != font_default_frf)
delete[] fileBuffer; delete[] fileBuffer;
return true;
}
Font::Font(const char *path) {
if(!load(path)) {
load(nullptr);
}
} }
Font::~Font(void) { Font::~Font(void) {

View File

@ -60,6 +60,8 @@ class Font {
u8 *fontTiles = nullptr; u8 *fontTiles = nullptr;
u16 *fontMap = nullptr; u16 *fontMap = nullptr;
bool load(const char *path);
u16 getCharIndex(char16_t c); u16 getCharIndex(char16_t c);
public: public:
static std::u16string utf8to16(std::string_view text); static std::u16string utf8to16(std::string_view text);

View File

@ -97,7 +97,7 @@ int main(int argc, char **argv) {
vramSetBankI(VRAM_I_SUB_SPRITE); vramSetBankI(VRAM_I_SUB_SPRITE);
// Init built-in font // Init built-in font
font = new Font("/font.frf"); font = new Font(nullptr);
// Display GM9i logo // Display GM9i logo
bg3 = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0); bg3 = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
@ -176,21 +176,9 @@ int main(int argc, char **argv) {
bgHide(bg3); bgHide(bg3);
// TODO: better // Reinit font, try to load default from SD this time
delete font; delete font;
font = new Font("/font.frf"); font = new Font(sdFound() ? "sd:/gm9i/font.frf" : "fat:/gm9i/font.frf");
// Overwrite background white color
BG_PALETTE[15+(7*16)] = 0x656A;
BG_PALETTE_SUB[15+(7*16)] = 0x656A;
// Custom yellow color
BG_PALETTE[15+(3*16)] = 0x3339;
BG_PALETTE_SUB[15+(3*16)] = 0x3339;
// Overwrite 2nd smiley face with filled tile
dmaFillWords(0xFFFFFFFF, (void*)0x6000040, 8*8); // Top screen
dmaFillWords(0xFFFFFFFF, (void*)0x6200040, 8*8); // Bottom screen
keysSetRepeat(25,5); keysSetRepeat(25,5);