From 2c804cc0e459985e34ade93080a65e69645dd919 Mon Sep 17 00:00:00 2001 From: Simon Aarons Date: Wed, 9 Jan 2019 03:45:02 +1100 Subject: [PATCH] Update for libnx 2.0.0 Also now uses a shared font to display text. --- Makefile | 25 ++++---------- README.md | 4 ++- source/main.c | 91 ++++++++++++++++++++++----------------------------- source/text.c | 79 ++++++++++++++++++++++++++++++++++++++++++++ source/text.h | 27 +++++++++++++++ 5 files changed, 155 insertions(+), 71 deletions(-) create mode 100644 source/text.c create mode 100644 source/text.h diff --git a/Makefile b/Makefile index a7f0fce..b3f0f4e 100755 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules APP_TITLE := Shared Font Dumper -APP_AUTHOR := SimonMKWii -APP_VERSION := 1.0.1337 -TARGET := $(notdir $(CURDIR)) +APP_AUTHOR := Simon Aarons +APP_VERSION := 2.1 +TARGET := sfdumper BUILD := build SOURCES := source DATA := data @@ -24,17 +24,16 @@ EXEFS_SRC := exefs_src #--------------------------------------------------------------------------------- ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -CFLAGS := -g -Wall -O2 -ffunction-sections \ - $(ARCH) $(DEFINES) +CFLAGS := $(ARCH) $(DEFINES) -s -O3 -CFLAGS += $(INCLUDE) -DSWITCH +CFLAGS += $(INCLUDE) -DSWITCH `freetype-config --cflags` 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 +LIBS := -lnx `freetype-config --libs` #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -137,18 +136,8 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all : $(OUTPUT).pfs0 $(OUTPUT).nro - -$(OUTPUT).pfs0 : $(OUTPUT).nso - -$(OUTPUT).nso : $(OUTPUT).elf - -ifeq ($(strip $(NO_NACP)),) +all : $(OUTPUT).nro $(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp -else -$(OUTPUT).nro : $(OUTPUT).elf -endif - $(OUTPUT).elf : $(OFILES) #--------------------------------------------------------------------------------- diff --git a/README.md b/README.md index 52886b3..fba2edc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # SharedFontDumper -Dumps the Switch's shared fonts to individual .ttfs or dumps the entire memory region to .bin for use in Ryujinx and yuzu. +Dumps the Switch's shared fonts to individual .ttfs, or dumps the entire memory region to .bin for use in Ryujinx and yuzu. + +Huge thanks to shchmue for her help with text rendering. diff --git a/source/main.c b/source/main.c index 2ca5522..d682abf 100755 --- a/source/main.c +++ b/source/main.c @@ -1,115 +1,102 @@ -#include -#include -#include -#include -#include +#include "text.h" -#include - -#define MEMSIZE 0x1100000 -#define DIRNAME "fonts" -#define SUCCESS "\n\nSuccessfully dumped shared fonts!\n\n\n\nPress + to exit." -#define IOERROR "Error: Failed to open file for writing.\n" - -int DumpMem(void) { +void DumpMem() { FILE *outFile; u8 *buf = malloc(MEMSIZE); if (!(outFile = fopen("fonts/shared_font.bin", "wb"))) { - fputs(IOERROR, stderr); + draw_text(0x10, 0x60, RED, IOERROR); goto exit; } - puts("\nDumping shared font memory...\n"); + draw_text(0x10, 0x60, SKYBLUE, "Dumping shared font memory..."); + text_update(); memcpy(buf, plGetSharedmemAddr(), MEMSIZE); - fwrite(buf, MEMSIZE, 1, outFile); + fwrite(buf, sizeof(u8), MEMSIZE, outFile); free(buf); exit: fclose(outFile); - - gfxFlushBuffers(); - gfxSwapBuffers(); - gfxWaitForVsync(); - - return 0; } -int DumpFont(PlSharedFontType type, char *name) { +int Dumped = 0; + +void DumpFont(PlSharedFontType type, char *name) { FILE *outFile; - char *newName = malloc(strlen(DIRNAME) + strlen(name) + 1); + + char *newName = malloc(strlen(DIRNAME) + strlen(name) + 2), + *str = malloc(strlen(name) + 0x10); PlFontData font; sprintf(newName, "%s/%s", DIRNAME, name); - printf("Dumping %s...\n", name); - + if (!(outFile = fopen(newName, "wb"))) { - fputs(IOERROR, stderr); + draw_text(0x10, 0x60, RED, IOERROR); goto exit; } - + + sprintf(str, "Dumping %s...\n", name); + + draw_text(0x10, 0x60 + 0x20 * Dumped++, SKYBLUE, str); + text_update(); + plGetSharedFontByType(&font, type); u8 *buf = malloc(font.size); memcpy(buf, font.address, font.size); - fwrite(buf, font.size, 1, outFile); + fwrite(buf, sizeof(u8), font.size, outFile); free(buf); exit: + free(newName); + free(str); fclose(outFile); - - gfxFlushBuffers(); - gfxSwapBuffers(); - gfxWaitForVsync(); - - return 0; } -int main(void) { +void main() { int kDown, isDone = 0; struct stat *sb = memalign(0x1000, sizeof *sb); - gfxInitDefault(); - consoleInit(NULL); - plInitialize(); + plInitialize(); + text_init(); - puts("Press A to dump fonts as ttf, or press X to dump the shared font memory.\n\n"); - if (stat(DIRNAME, sb)) mkdir(DIRNAME, 0777); + draw_text(0x10, 0x20, WHITE, "Press A to dump fonts as ttf, or press X to dump the shared font memory."); + text_update(); + while (appletMainLoop()) { hidScanInput(); kDown = hidKeysDown(CONTROLLER_P1_AUTO); if (kDown & KEY_A && !isDone++) { - DumpFont(PlSharedFontType_Standard, "FontStandard.ttf"); + DumpFont(PlSharedFontType_Standard, "FontStandard.ttf"); DumpFont(PlSharedFontType_ChineseSimplified, "FontChineseSimplified.ttf"); DumpFont(PlSharedFontType_ExtChineseSimplified, "FontExtendedChineseSimplified.ttf"); DumpFont(PlSharedFontType_ChineseTraditional, "FontChineseTraditional.ttf"); - DumpFont(PlSharedFontType_KO, "FontKorean.ttf"); - DumpFont(PlSharedFontType_NintendoExt, "FontNintendoExtended.ttf"); - puts(SUCCESS); + DumpFont(PlSharedFontType_KO, "FontKorean.ttf"); + DumpFont(PlSharedFontType_NintendoExt, "FontNintendoExtended.ttf"); + draw_text(0x10, 0x80 + 0x20 * Dumped, GREEN, SUCCESS); } if (kDown & KEY_X && !isDone++) { DumpMem(); - puts(SUCCESS); + draw_text(0x10, 0xa0, GREEN, SUCCESS); } if (kDown & KEY_PLUS) break; - gfxFlushBuffers(); - gfxSwapBuffers(); - gfxWaitForVsync(); + text_update(); } - - gfxExit(); + + free(sb); + + text_exit(); plExit(); - return 0; } diff --git a/source/text.c b/source/text.c new file mode 100644 index 0000000..6b85b64 --- /dev/null +++ b/source/text.c @@ -0,0 +1,79 @@ +/* All code in this document was adapted from shchmue's Lockpick! */ + +#include "text.h" + +static u32 framebuf_width = 0; +static u32 stride; +static u32 *framebuf; +static Framebuffer fb; +static FT_Library library; +static FT_Face face; + +void draw_glyph(FT_Bitmap *bitmap, u32 x, u32 y, u32 color) { + u32 framex, framey; + u8* imageptr = bitmap->buffer; + + for (u32 tmpy = 0; tmpy < bitmap->rows; tmpy++) { + for (u32 tmpx = 0; tmpx < bitmap->width; tmpx++) { + framex = x + tmpx; + framey = y + tmpy; + + framebuf[framey * framebuf_width + framex] = RGBA8_MAXALPHA(imageptr[tmpx], imageptr[tmpx], imageptr[tmpx]) & color; + } + + imageptr += bitmap->pitch; + } +} + +void draw_text(u32 x, u32 y, u32 color, const char *str) { + u32 tmpx = x; + FT_UInt glyph_index; + FT_GlyphSlot slot = face->glyph; + + for (size_t i = 0; i < strlen(str); i++) { + if (str[i] == '\n') { + tmpx = x; + y += face->size->metrics.height >> 6; + continue; + } + + glyph_index = FT_Get_Char_Index(face, (FT_ULong)str[i]); + + if (R_FAILED(FT_Load_Glyph(face, glyph_index, FT_LOAD_COLOR) || + FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL) != 0)) + return; + + draw_glyph(&slot->bitmap, tmpx + slot->bitmap_left, y - slot->bitmap_top, color); + + tmpx += slot->advance.x >> 6; + y += slot->advance.y >> 6; + } +} + +void text_init() { + PlFontData font; + plGetSharedFontByType(&font, PlSharedFontType_Standard); + + FT_Init_FreeType(&library); + FT_New_Memory_Face(library, font.address, font.size, 0, &face); + FT_Set_Char_Size(face, 0, 6*64, 300, 300); + + framebufferCreate(&fb, nwindowGetDefault(), 1280, 720, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&fb); + framebuf = (u32 *)framebufferBegin(&fb, &stride); + framebuf_width = stride / sizeof(u32); + memset(framebuf, 0, stride*720); + framebufferEnd(&fb); +} + +void text_update() { + framebufferBegin(&fb, &stride); + framebufferEnd(&fb); +} + +void text_exit() { + framebufferClose(&fb); + + FT_Done_Face(face); + FT_Done_FreeType(library); +} diff --git a/source/text.h b/source/text.h new file mode 100644 index 0000000..7e8aa46 --- /dev/null +++ b/source/text.h @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include FT_FREETYPE_H + +#define MEMSIZE 0x1100000 + +#define RED RGBA8_MAXALPHA(0xff, 0, 0) +#define GREEN RGBA8_MAXALPHA(0, 0xff, 0) +#define WHITE RGBA8_MAXALPHA(0xff, 0xff, 0xff) +#define SKYBLUE RGBA8_MAXALPHA(0xa0, 0xff, 0xff) + +#define DIRNAME "fonts" +#define SUCCESS "Successfully dumped shared fonts!\n\nPress + to exit." +#define IOERROR "Error: Failed to open file for writing.\n" + +void draw_glyph(FT_Bitmap *bitmap, u32 x, u32 y, u32 color); +void draw_text(u32 x, u32 y, u32 color, const char *str); +void text_init(); +void text_update(); +void text_exit();