From 1e232372d2dc002b470cdddd6f8bd89e818ecd24 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sat, 28 Apr 2018 11:53:47 -0400 Subject: [PATCH] Use shared-font. Setting s_textLang is still disabled, until language.c is updated. Check for setsysInitialize failure. Moved .nxfnt files into data/unused/. Currently text will not display with the pc-build since no font is loaded for it. Disabled y+=baseline in text-drawing, and adjusted all callers y-pos to manually add the original baseline (so that y-pos matches with the different font). --- Makefile.nx | 4 +- Makefile.pc | 7 +- common/common.h | 22 +-- common/font.c | 190 +++++++++++++++++++++-- common/font.h | 22 +-- common/menu-entry.c | 17 +- common/menu.c | 26 ++-- common/message-box.c | 2 +- common/text.c | 22 ++- common/text.h | 1 + data/{ => unused}/interuimedium20.nxfnt | Bin data/{ => unused}/interuimedium30.nxfnt | Bin data/{ => unused}/interuiregular14.nxfnt | Bin data/{ => unused}/interuiregular18.nxfnt | Bin data/{ => unused}/tahoma12.nxfnt | Bin data/{ => unused}/tahoma24.nxfnt | Bin nx_main/main.c | 12 +- 17 files changed, 257 insertions(+), 68 deletions(-) rename data/{ => unused}/interuimedium20.nxfnt (100%) rename data/{ => unused}/interuimedium30.nxfnt (100%) rename data/{ => unused}/interuiregular14.nxfnt (100%) rename data/{ => unused}/interuiregular18.nxfnt (100%) rename data/{ => unused}/tahoma12.nxfnt (100%) rename data/{ => unused}/tahoma24.nxfnt (100%) diff --git a/Makefile.nx b/Makefile.nx index 48b79ca..4152ca1 100644 --- a/Makefile.nx +++ b/Makefile.nx @@ -44,7 +44,7 @@ DIST_PATH := $(TARGET)_v$(APP_VERSION) ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ - $(ARCH) $(DEFINES) + $(ARCH) $(DEFINES) `freetype-config --cflags` CFLAGS += $(INCLUDE) -D__SWITCH__ -DVERSION=\"v$(APP_VERSION)\" @@ -53,7 +53,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lnx -lm -lz +LIBS := `freetype-config --libs` #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Makefile.pc b/Makefile.pc index e6f9c3c..49b5982 100644 --- a/Makefile.pc +++ b/Makefile.pc @@ -23,11 +23,10 @@ test : pc_main/main.cpp pc_main/pc_launch.c \ common/menu-entry.c common/menu-list.c common/message-box.c common/text.c \ common/nanojpeg.c common/ui.c common/math.c common/theme.c \ common/netloader.c \ - build_pc/tahoma24.o build_pc/tahoma12.o build_pc/interuimedium20.o build_pc/interuimedium30.o \ - build_pc/interuiregular14.o build_pc/interuiregular18.o \ build_pc/invalid_icon.bin.o build_pc/folder_icon.bin.o \ - build_pc/button_a_light.bin.o build_pc/button_a_dark.bin.o build_pc/button_b_light.bin.o build_pc/button_b_dark.bin.o build_pc/hbmenu_logo_light.bin.o build_pc/hbmenu_logo_dark.bin.o - gcc -Wall -O2 -g -DVERSION=\"v$(APP_VERSION)\" $(EXTRA_CFLAGS) $^ -lsfml-graphics -lsfml-window -lsfml-system -lstdc++ -lm -lz $(EXTRA_LDFLAGS) -I. -iquote $(DEVKITPRO)/libnx/include -Ibuild_pc -g -o $@ + build_pc/button_a_light.bin.o build_pc/button_a_dark.bin.o build_pc/button_b_light.bin.o build_pc/button_b_dark.bin.o build_pc/hbmenu_logo_light.bin.o build_pc/hbmenu_logo_dark.bin.o \ + #build_pc/tahoma24.o build_pc/tahoma12.o build_pc/interuimedium20.o build_pc/interuimedium30.o build_pc/interuiregular14.o build_pc/interuiregular18.o + gcc -Wall -O2 -g -DVERSION=\"v$(APP_VERSION)\" $(EXTRA_CFLAGS) `freetype-config --cflags` $^ -lsfml-graphics -lsfml-window -lsfml-system -lstdc++ `freetype-config --libs` -lm -lz $(EXTRA_LDFLAGS) -I. -iquote $(DEVKITPRO)/libnx/include -Ibuild_pc -g -o $@ build_pc/tahoma12.o : data/tahoma12.nxfnt mkdir -p $(dir $@) diff --git a/common/common.h b/common/common.h index c352823..c837087 100644 --- a/common/common.h +++ b/common/common.h @@ -22,6 +22,7 @@ typedef uint8_t u8; typedef uint32_t u32; typedef uint64_t u64; +typedef u32 Result; #ifdef _WIN32 @@ -42,6 +43,12 @@ typedef union { }; } color_t; +// when building for pc we need to include these separately +#ifndef __SWITCH__ +#include "switch/nro.h" +#include "switch/nacp.h" +#endif + #include "font.h" #include "menu.h" #include "text.h" @@ -51,12 +58,6 @@ typedef union { #include "math.h" #include "theme.h" -// when building for pc we need to include these separately -#ifndef __SWITCH__ -#include "switch/nro.h" -#include "switch/nacp.h" -#endif - void menuStartup(); void menuLoop(); @@ -147,6 +148,9 @@ static inline color_t FetchPixelColor(uint32_t x, uint32_t y) #endif void DrawPixel(uint32_t x, uint32_t y, color_t clr); -void DrawText(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t clr, const char* text); -void DrawTextTruncate(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text); -void GetTextDimensions(const ffnt_header_t* font, const char* text, uint32_t* width_out, uint32_t* height_out); +void DrawText(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text); +void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text); +void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t* height_out); + +bool fontInitialize(void); +void fontExit(); diff --git a/common/font.c b/common/font.c index 7714716..e108c58 100644 --- a/common/font.c +++ b/common/font.c @@ -1,6 +1,65 @@ #include "common.h" -static inline const ffnt_page_t* FontGetPage(const ffnt_header_t* font, uint32_t page_id) +#include +#include FT_FREETYPE_H + +#ifdef __SWITCH__ +#define FONT_FACES_MAX PlSharedFontType_Total +#else +#define FONT_FACES_MAX 1 +#endif + +static FT_Error s_font_libret=1, s_font_facesret[FONT_FACES_MAX]; + +static FT_Library s_font_library; +static FT_Face s_font_faces[FONT_FACES_MAX]; +static FT_Face s_font_lastusedface; +static size_t s_font_faces_total = 0; + +static bool FontSetType(u32 font) +{ + u32 i=0; + u32 scale=0; + FT_Error ret=0; + + switch(font) + { + case interuiregular14: + scale = 4; + break; + + case interuiregular18: + scale = 5; + break; + + case interuimedium20: + scale = 6; + break; + + case interuimedium30: + scale = 8; + break; + + default: + return false; + break; + } + + for (i=0; i= font->npages) @@ -9,27 +68,69 @@ static inline const ffnt_page_t* FontGetPage(const ffnt_header_t* font, uint32_t if (ent->size == 0) return NULL; return (const ffnt_page_t*)((const uint8_t*)font + ent->offset); -} +}*/ -static inline bool FontLoadGlyph(glyph_t* glyph, const ffnt_header_t* font, uint32_t codepoint) +static inline bool FontLoadGlyph(glyph_t* glyph, u32 font, uint32_t codepoint) { + FT_Face face; + FT_Error ret=0; + FT_GlyphSlot slot; + FT_UInt glyph_index; + FT_Bitmap* bitmap; + u32 i=0; + //__builtin_printf("LoadGlyph %u\n", (unsigned int)codepoint); - const ffnt_page_t* page = FontGetPage(font, codepoint >> 8); + /*const ffnt_page_t* page = FontGetPage(font, codepoint >> 8); if (!page) return false; codepoint &= 0xFF; uint32_t off = page->hdr.pos[codepoint]; if (off == ~(uint32_t)0) - return false; + return false;*/ + + if (s_font_faces_total==0) return false; + + for (i=0; iglyph, /* glyph slot */ + FT_RENDER_MODE_NORMAL); /* render mode */ + } + + if (ret) return false; + + break; + } + + slot = face->glyph; + bitmap = &slot->bitmap; //__builtin_printf("%c %u\n", (char)codepoint, (unsigned int)off); - glyph->width = page->hdr.widths[codepoint]; + /*glyph->width = page->hdr.widths[codepoint]; glyph->height = page->hdr.heights[codepoint]; glyph->advance = page->hdr.advances[codepoint]; glyph->posX = page->hdr.posX[codepoint]; glyph->posY = page->hdr.posY[codepoint]; - glyph->data = &page->data[off]; + glyph->data = &page->data[off];*/ + + glyph->width = bitmap->width; + glyph->height = bitmap->rows; + glyph->pitch = bitmap->pitch; + glyph->data = bitmap->buffer; + glyph->advance = slot->advance.x >> 6; + glyph->posX = slot->bitmap_left; + glyph->posY = slot->bitmap_top; return true; } @@ -38,16 +139,17 @@ static void DrawGlyph(uint32_t x, uint32_t y, color_t clr, const glyph_t* glyph) uint32_t i, j; const uint8_t* data = glyph->data; x += glyph->posX; - y += glyph->posY; + y -= glyph->posY; //y += glyph->posY; //__builtin_printf("DrawGlyph %u %u %08X\n", (unsigned int)x, (unsigned int)y, (unsigned int)clr.abgr); for (j = 0; j < glyph->height; j ++) { for (i = 0; i < glyph->width; i ++) { - clr.a = *data++; + clr.a = data[i]; if (!clr.a) continue; DrawPixel(x+i, y+j, clr); } + data+= glyph->pitch; } } @@ -118,11 +220,15 @@ static inline uint32_t DecodeUTF8(const char** ptr) return 0xFFFD; } -static void DrawText_(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text) +static void DrawText_(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text) { //__builtin_printf("DrawText %u %u %08X %s\n", (unsigned int)x, (unsigned int)y, (unsigned int)clr.abgr, text); - y += font->baseline; + //y += font->baseline; uint32_t origX = x; + if (s_font_faces_total==0) return; + if (!FontSetType(font)) return; + s_font_lastusedface = s_font_faces[0]; + while (*text) { if (max_width && x-origX >= max_width) { @@ -142,7 +248,7 @@ static void DrawText_(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t } x = origX; - y += font->height; + y += s_font_lastusedface->size->metrics.height / 64; continue; } @@ -157,20 +263,24 @@ static void DrawText_(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t } } -void DrawText(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t clr, const char* text) +void DrawText(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text) { DrawText_(font, x, y, clr, text, 0, NULL); } -void DrawTextTruncate(const ffnt_header_t* font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text) +void DrawTextTruncate(u32 font, uint32_t x, uint32_t y, color_t clr, const char* text, uint32_t max_width, const char* end_text) { DrawText_(font, x, y, clr, text, max_width, end_text); } -void GetTextDimensions(const ffnt_header_t* font, const char* text, uint32_t* width_out, uint32_t* height_out) +void GetTextDimensions(u32 font, const char* text, uint32_t* width_out, uint32_t* height_out) { uint32_t x = 0; uint32_t width = 0, height = 0; + if (s_font_faces_total==0) return; + if (!FontSetType(font)) return; + s_font_lastusedface = s_font_faces[0]; + while (*text) { glyph_t glyph; @@ -179,7 +289,7 @@ void GetTextDimensions(const ffnt_header_t* font, const char* text, uint32_t* wi if (codepoint == '\n') { x = 0; - height += font->height; + height += s_font_lastusedface->size->metrics.height / 64; continue; } @@ -198,3 +308,51 @@ void GetTextDimensions(const ffnt_header_t* font, const char* text, uint32_t* wi *width_out = width; *height_out = height; } + +bool fontInitialize(void) +{ + FT_Error ret=0; + u32 i; + + for (i=0; inacp==NULL) return; - strncpy(me->name, me->nacp->lang[lang].name, sizeof(me->name)-1); - strncpy(me->author, me->nacp->lang[lang].author, sizeof(me->author)-1); strncpy(me->version, me->nacp->version, sizeof(me->version)-1); + #ifdef __SWITCH__ + Result rc=0; + rc = nacpGetLanguageEntry(me->nacp, &langentry); + + if (R_SUCCEEDED(rc) && langentry!=NULL) { + #else + langentry = &me->nacp->lang[0]; + if (1) { + #endif + strncpy(me->name, langentry->name, sizeof(me->name)-1); + strncpy(me->author, langentry->author, sizeof(me->author)-1); + } + free(me->nacp); me->nacp = NULL; } diff --git a/common/menu.c b/common/menu.c index 182f5a8..9f8be74 100644 --- a/common/menu.c +++ b/common/menu.c @@ -206,21 +206,21 @@ static void drawEntry(menuEntry_s* me, int off_x, int is_active) { } } - DrawTextTruncate(interuiregular14, start_x + 4, start_y + 4, MakeColor(64, 64, 64, 255), me->name, 140 - 32, "..."); + DrawTextTruncate(interuiregular14, start_x + 4, start_y + 4 + 18, MakeColor(64, 64, 64, 255), me->name, 140 - 32, "..."); if (is_active) { start_x = 1280 - 790; start_y = 135; - DrawTextTruncate(interuimedium30, start_x, start_y, themeCurrent.textColor, me->name, 1280 - start_x - 120 ,"..."); + DrawTextTruncate(interuimedium30, start_x, start_y + 39, themeCurrent.textColor, me->name, 1280 - start_x - 120 ,"..."); if (me->type != ENTRY_TYPE_FOLDER) { memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Author), me->author); - DrawText(interuiregular14, start_x, start_y + 28 + 30, themeCurrent.textColor, tmpstr); + DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18, themeCurrent.textColor, tmpstr); memset(tmpstr, 0, sizeof(tmpstr)); snprintf(tmpstr, sizeof(tmpstr)-1, "%s: %s", textGetString(StrId_AppInfo_Version), me->version); - DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6, themeCurrent.textColor, tmpstr); + DrawText(interuiregular14, start_x, start_y + 28 + 30 + 18 + 6 + 18, themeCurrent.textColor, tmpstr); } } } @@ -322,7 +322,7 @@ void drawTime() { sprintf(timeString, "%02d:%02d:%02d", hours, minutes, seconds); - DrawText(interuimedium20, 1280 - (9 * 16) - 30, 30, MakeColor(255, 255, 255, 255), timeString); + DrawText(interuimedium20, 1280 - (9 * 16) - 30, 30 + 26, MakeColor(255, 255, 255, 255), timeString); } @@ -342,7 +342,7 @@ void drawBackBtn(menu_s* menu, bool emptyDir) { #endif { drawImage(x_image, 720 - 48, 32, 32, themeCurrent.buttonBImage, IMAGE_MODE_RGBA32); - DrawText(interuimedium20, x_text, 720 - 47, themeCurrent.textColor, textGetString(StrId_Actions_Back)); + DrawText(interuimedium20, x_text, 720 - 47 + 26, themeCurrent.textColor, textGetString(StrId_Actions_Back)); } } @@ -364,8 +364,8 @@ void menuLoop() { menuTimer += 0.05; drawImage(40, 20, 140, 60, themeCurrent.hbmenuLogoImage, IMAGE_MODE_RGBA32); - DrawText(interuiregular14, 180, 46, themeCurrent.textColor, VERSION); - DrawTextTruncate(interuiregular18, 40, 720 - 47, themeCurrent.textColor, menu->dirname, 918, "..."); + DrawText(interuiregular14, 180, 46 + 18, themeCurrent.textColor, VERSION); + DrawTextTruncate(interuiregular18, 40, 720 - 47 + 24, themeCurrent.textColor, menu->dirname, 918, "..."); #ifdef PERF_LOG_DRAW//Seperate from the PERF_LOG define since this might affect perf. extern u64 g_tickdiff_vsync; @@ -374,10 +374,10 @@ void menuLoop() { char tmpstr[64]; snprintf(tmpstr, sizeof(tmpstr)-1, "%lu", g_tickdiff_vsync); - DrawText(interuiregular14, 180 + 256, 46, themeCurrent.textColor, tmpstr); + DrawText(interuiregular14, 180 + 256, 46 + 18, themeCurrent.textColor, tmpstr); snprintf(tmpstr, sizeof(tmpstr)-1, "%lu", g_tickdiff_frame); - DrawText(interuiregular14, 180 + 256, 46 + 16, themeCurrent.textColor, tmpstr); + DrawText(interuiregular14, 180 + 256, 46 + 16 + 18, themeCurrent.textColor, tmpstr); #endif //drawTime(); @@ -397,7 +397,7 @@ void menuLoop() { } } } else { - DrawText(interuiregular14, 64, 128, themeCurrent.textColor, textGetString(StrId_NoAppsFound_Msg)); + DrawText(interuiregular14, 64, 128 + 18, themeCurrent.textColor, textGetString(StrId_NoAppsFound_Msg)); } drawBackBtn(menu, true); } @@ -437,11 +437,11 @@ void menuLoop() { if(active_entry != NULL) { if (active_entry->type != ENTRY_TYPE_FOLDER) { drawImage(1280 - 126 - 30 - 32, 720 - 48, 32, 32, themeCurrent.buttonAImage, IMAGE_MODE_RGBA32); - DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47, themeCurrent.textColor, textGetString(StrId_Actions_Launch)); + DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Launch)); } else { drawImage(1280 - 126 - 30 - 32, 720 - 48, 32, 32, themeCurrent.buttonAImage, IMAGE_MODE_RGBA32); - DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47, themeCurrent.textColor, textGetString(StrId_Actions_Open)); + DrawText(interuiregular18, 1280 - 90 - 30 - 32, 720 - 47 + 24, themeCurrent.textColor, textGetString(StrId_Actions_Open)); } } diff --git a/common/message-box.c b/common/message-box.c index 3661856..cd826ef 100644 --- a/common/message-box.c +++ b/common/message-box.c @@ -127,7 +127,7 @@ void menuDrawMsgBox() { DrawText(interuiregular18, start_x + (currMsgBox.width - text_width) / 2, start_y + (currMsgBox.height - text_height - 80) / 2, MakeColor(0, 0, 0, 255), currMsgBox.text); } - DrawText(interuimedium20, start_x + 365, start_y + 245, MakeColor(0, 0, 0, 255), textGetString(StrId_MsgBox_OK)); + DrawText(interuimedium20, start_x + 365, start_y + 245 + 26, MakeColor(0, 0, 0, 255), textGetString(StrId_MsgBox_OK)); shadow_start_y = start_y + currMsgBox.height; diff --git a/common/text.c b/common/text.c index 69e5094..638a8bb 100644 --- a/common/text.c +++ b/common/text.c @@ -1,5 +1,7 @@ #include "text.h" +static u64 s_textLanguageCode = 0; + #ifdef __SWITCH__ static int s_textLang = SetLanguage_ENUS; #else @@ -8,16 +10,16 @@ static int s_textLang = 1; void textInit(void) { #ifdef __SWITCH__ - //u64 LanguageCode=0; - //s32 Language=0; + s32 Language=0; s_textLang = SetLanguage_ENUS; - //TODO: Re-enable this once the font supports all used languages. - /*Result rc = setInitialize(); - if (R_SUCCEEDED(rc)) rc = setGetSystemLanguage(&LanguageCode); - if (R_SUCCEEDED(rc)) rc = setMakeLanguage(LanguageCode, &Language); - if (R_SUCCEEDED(rc) && Language < 16) s_textLang = Language; - setExit();*/ + + Result rc = setInitialize(); + if (R_SUCCEEDED(rc)) rc = setGetSystemLanguage(&s_textLanguageCode); + if (R_SUCCEEDED(rc)) rc = setMakeLanguage(s_textLanguageCode, &Language); + //if (R_SUCCEEDED(rc) && Language < 16) s_textLang = Language;//TODO: Re-enable this once language.c supports all used languages. + setExit(); + if (R_FAILED(rc)) fatalSimple(-8); #else s_textLang = 1; #endif @@ -36,3 +38,7 @@ const char* textGetString(StrId id) { #endif return str; } + +u64 textGetLanguageCode(void) { + return s_textLanguageCode; +} diff --git a/common/text.h b/common/text.h index ca9baf1..b2c47db 100644 --- a/common/text.h +++ b/common/text.h @@ -5,3 +5,4 @@ void textInit(void); int textGetLang(void); const char* textGetString(StrId id); +u64 textGetLanguageCode(void); diff --git a/data/interuimedium20.nxfnt b/data/unused/interuimedium20.nxfnt similarity index 100% rename from data/interuimedium20.nxfnt rename to data/unused/interuimedium20.nxfnt diff --git a/data/interuimedium30.nxfnt b/data/unused/interuimedium30.nxfnt similarity index 100% rename from data/interuimedium30.nxfnt rename to data/unused/interuimedium30.nxfnt diff --git a/data/interuiregular14.nxfnt b/data/unused/interuiregular14.nxfnt similarity index 100% rename from data/interuiregular14.nxfnt rename to data/unused/interuiregular14.nxfnt diff --git a/data/interuiregular18.nxfnt b/data/unused/interuiregular18.nxfnt similarity index 100% rename from data/interuiregular18.nxfnt rename to data/unused/interuiregular18.nxfnt diff --git a/data/tahoma12.nxfnt b/data/unused/tahoma12.nxfnt similarity index 100% rename from data/tahoma12.nxfnt rename to data/unused/tahoma12.nxfnt diff --git a/data/tahoma24.nxfnt b/data/unused/tahoma24.nxfnt similarity index 100% rename from data/tahoma24.nxfnt rename to data/unused/tahoma24.nxfnt diff --git a/nx_main/main.c b/nx_main/main.c index 1f39232..cf6c2bf 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -20,6 +20,7 @@ void audio_exit(void); int main(int argc, char **argv) { Result lastret=0; + Result rc=0; char msg[256]; #ifdef PERF_LOG @@ -31,13 +32,20 @@ int main(int argc, char **argv) appletSetScreenShotPermission(1); ColorSetId theme; - setsysInitialize(); + rc = setsysInitialize(); + if (R_FAILED(rc)) fatalSimple(-5); + setsysGetColorSetId(&theme); + + rc = plInitialize(); + if (R_FAILED(rc)) fatalSimple(-6); + themeStartup((ThemePreset)theme); textInit(); menuStartup(); launchInit(); + if (!fontInitialize()) fatalSimple(-7); #ifdef ENABLE_AUDIO audio_initialize(); @@ -88,7 +96,9 @@ int main(int argc, char **argv) audio_exit(); #endif + fontExit(); launchExit(); + plExit(); setsysExit(); gfxExit();