mirror of https://github.com/mgba-emu/mgba.git
3DS: Add GUIFont
This commit is contained in:
parent
56dd9c4158
commit
1b78b21338
|
@ -169,10 +169,13 @@ elseif(UNIX)
|
|||
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/posix/*.c)
|
||||
source_group("POSIX-specific code" FILES ${OS_SRC})
|
||||
elseif(3DS)
|
||||
set(M_LIBRARY m)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format")
|
||||
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
|
||||
execute_process(COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw)
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
list(APPEND OS_LIB sf2d ctru)
|
||||
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/3ds/3ds-*.c)
|
||||
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/3ds/*.c ${CMAKE_BINARY_DIR}/font.c)
|
||||
source_group("3DS-specific code" FILES ${OS_SRC})
|
||||
endif()
|
||||
|
||||
|
@ -443,7 +446,7 @@ if(BUILD_QT)
|
|||
endif()
|
||||
|
||||
if(3DS)
|
||||
add_executable(${BINARY_NAME}.elf ${CMAKE_SOURCE_DIR}/src/platform/3ds/main.c)
|
||||
add_executable(${BINARY_NAME}.elf ${GUI_SRC})
|
||||
target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} m ${OS_LIB})
|
||||
add_custom_command(TARGET ${BINARY_NAME}.elf POST_BUILD COMMAND ${3DSXTOOL} ${BINARY_NAME}.elf ${BINARY_NAME}.3dsx)
|
||||
endif()
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "3ds-vfs.h"
|
||||
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
struct VFile3DS {
|
||||
struct VFile d;
|
||||
|
@ -14,6 +15,20 @@ struct VFile3DS {
|
|||
u64 offset;
|
||||
};
|
||||
|
||||
struct VDirEntry3DS {
|
||||
struct VDirEntry d;
|
||||
FS_dirent ent;
|
||||
char* utf8Name;
|
||||
};
|
||||
|
||||
struct VDir3DS {
|
||||
struct VDir d;
|
||||
|
||||
char* path;
|
||||
Handle handle;
|
||||
struct VDirEntry3DS vde;
|
||||
};
|
||||
|
||||
static bool _vf3dClose(struct VFile* vf);
|
||||
static off_t _vf3dSeek(struct VFile* vf, off_t offset, int whence);
|
||||
static ssize_t _vf3dRead(struct VFile* vf, void* buffer, size_t size);
|
||||
|
@ -24,6 +39,13 @@ static void _vf3dTruncate(struct VFile* vf, size_t size);
|
|||
static ssize_t _vf3dSize(struct VFile* vf);
|
||||
static bool _vf3dSync(struct VFile* vf, const void* buffer, size_t size);
|
||||
|
||||
static bool _vd3dClose(struct VDir* vd);
|
||||
static void _vd3dRewind(struct VDir* vd);
|
||||
static struct VDirEntry* _vd3dListNext(struct VDir* vd);
|
||||
static struct VFile* _vd3dOpenFile(struct VDir* vd, const char* path, int mode);
|
||||
|
||||
static const char* _vd3deName(struct VDirEntry* vde);
|
||||
|
||||
struct VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags) {
|
||||
struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS));
|
||||
if (!vf3d) {
|
||||
|
@ -141,3 +163,79 @@ static bool _vf3dSync(struct VFile* vf, const void* buffer, size_t size) {
|
|||
FSFILE_Flush(vf3d->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct VDir* VDirOpen(const char* path) {
|
||||
struct VDir3DS* vd3d = malloc(sizeof(struct VDir3DS));
|
||||
if (!vd3d) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
FS_path newPath = FS_makePath(PATH_CHAR, path);
|
||||
Result res = FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath);
|
||||
if (res & 0xFFFC03FF) {
|
||||
free(vd3d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vd3d->path = strdup(path);
|
||||
|
||||
vd3d->d.close = _vd3dClose;
|
||||
vd3d->d.rewind = _vd3dRewind;
|
||||
vd3d->d.listNext = _vd3dListNext; //// Crashes here for no good reason
|
||||
vd3d->d.openFile = _vd3dOpenFile;
|
||||
|
||||
vd3d->vde.d.name = _vd3deName;
|
||||
|
||||
return &vd3d->d;
|
||||
}
|
||||
|
||||
static bool _vd3dClose(struct VDir* vd) {
|
||||
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
||||
FSDIR_Close(vd3d->handle);
|
||||
free(vd3d->path);
|
||||
if (vd3d->vde.utf8Name) {
|
||||
free(vd3d->vde.utf8Name);
|
||||
}
|
||||
free(vd3d);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _vd3dRewind(struct VDir* vd) {
|
||||
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
||||
FSDIR_Close(vd3d->handle);
|
||||
FS_path newPath = FS_makePath(PATH_CHAR, vd3d->path);
|
||||
FSUSER_OpenDirectory(0, &vd3d->handle, sdmcArchive, newPath);
|
||||
}
|
||||
|
||||
static struct VDirEntry* _vd3dListNext(struct VDir* vd) {
|
||||
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
||||
u32 n = 0;
|
||||
Result res = FSDIR_Read(vd3d->handle, &n, 1, &vd3d->vde.ent);
|
||||
if (res & 0xFFFC03FF || !n) {
|
||||
return 0;
|
||||
}
|
||||
return &vd3d->vde.d;
|
||||
}
|
||||
|
||||
static struct VFile* _vd3dOpenFile(struct VDir* vd, const char* path, int mode) {
|
||||
struct VDir3DS* vd3d = (struct VDir3DS*) vd;
|
||||
if (!path) {
|
||||
return 0;
|
||||
}
|
||||
const char* dir = vd3d->path;
|
||||
char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2));
|
||||
sprintf(combined, "%s/%s", dir, path);
|
||||
|
||||
struct VFile* file = VFileOpen(combined, mode);
|
||||
free(combined);
|
||||
return file;
|
||||
}
|
||||
|
||||
static const char* _vd3deName(struct VDirEntry* vde) {
|
||||
struct VDirEntry3DS* vd3de = (struct VDirEntry3DS*) vde;
|
||||
if (vd3de->utf8Name) {
|
||||
free(vd3de->utf8Name);
|
||||
}
|
||||
vd3de->utf8Name = utf16to8(vd3de->ent.name, sizeof(vd3de->ent.name) / 2);
|
||||
return vd3de->utf8Name;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,65 @@
|
|||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "util/gui/font.h"
|
||||
#include "util/gui/font-metrics.h"
|
||||
#include "util/png-io.h"
|
||||
#include "util/vfs.h"
|
||||
#include "font.h"
|
||||
|
||||
#include <sf2d.h>
|
||||
|
||||
#define CELL_HEIGHT 16
|
||||
#define CELL_WIDTH 16
|
||||
#define GLYPH_HEIGHT 12
|
||||
|
||||
struct GUIFont {
|
||||
sf2d_texture* tex;
|
||||
};
|
||||
|
||||
struct GUIFont* GUIFontCreate(void) {
|
||||
struct GUIFont* guiFont = malloc(sizeof(struct GUIFont));
|
||||
if (!guiFont) {
|
||||
return 0;
|
||||
}
|
||||
guiFont->tex = sf2d_create_texture(256, 128, TEXFMT_RGB5A1, SF2D_PLACE_RAM);
|
||||
memcpy(guiFont->tex->data, font, font_size);
|
||||
guiFont->tex->tiled = 1;
|
||||
return guiFont;
|
||||
}
|
||||
|
||||
void GUIFontDestroy(struct GUIFont* font) {
|
||||
sf2d_free_texture(font->tex);
|
||||
free(font);
|
||||
}
|
||||
|
||||
int GUIFontHeight(const struct GUIFont* font) {
|
||||
UNUSED(font);
|
||||
return GLYPH_HEIGHT;
|
||||
}
|
||||
|
||||
void GUIFontPrintf(const struct GUIFont* font, int x, int y, enum GUITextAlignment align, uint32_t color, const char* text, ...) {
|
||||
UNUSED(align); // TODO
|
||||
char buffer[256];
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
int len = vsnprintf(buffer, sizeof(buffer), text, args);
|
||||
va_end(args);
|
||||
int i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
char c = buffer[i];
|
||||
if (c > 0x7F) {
|
||||
c = 0;
|
||||
}
|
||||
struct GUIFontGlyphMetric metric = defaultFontMetrics[c];
|
||||
sf2d_draw_texture_part_blend(font->tex, x, y - GLYPH_HEIGHT + metric.padding.top,
|
||||
(c & 15) * CELL_WIDTH + metric.padding.left,
|
||||
(c >> 4) * CELL_HEIGHT + metric.padding.top,
|
||||
CELL_WIDTH - (metric.padding.left + metric.padding.right),
|
||||
CELL_HEIGHT - (metric.padding.top + metric.padding.bottom),
|
||||
color);
|
||||
x += metric.width;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,9 @@
|
|||
#include "gba/renderers/video-software.h"
|
||||
#include "gba/supervisor/context.h"
|
||||
#include "gba/video.h"
|
||||
#include "util/gui.h"
|
||||
#include "util/gui/file-select.h"
|
||||
#include "util/gui/font.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
#include "3ds-vfs.h"
|
||||
|
@ -27,6 +30,34 @@ static void _drawEnd(void) {
|
|||
sf2d_swapbuffers();
|
||||
}
|
||||
|
||||
static int _pollInput(void) {
|
||||
hidScanInput();
|
||||
int keys = 0;
|
||||
int activeKeys = hidKeysHeld();
|
||||
if (activeKeys & KEY_X) {
|
||||
keys |= 1 << GUI_INPUT_CANCEL;
|
||||
}
|
||||
if (activeKeys & KEY_B) {
|
||||
keys |= 1 << GUI_INPUT_BACK;
|
||||
}
|
||||
if (activeKeys & KEY_A) {
|
||||
keys |= 1 << GUI_INPUT_SELECT;
|
||||
}
|
||||
if (activeKeys & KEY_LEFT) {
|
||||
keys |= 1 << GUI_INPUT_LEFT;
|
||||
}
|
||||
if (activeKeys & KEY_RIGHT) {
|
||||
keys |= 1 << GUI_INPUT_RIGHT;
|
||||
}
|
||||
if (activeKeys & KEY_UP) {
|
||||
keys |= 1 << GUI_INPUT_UP;
|
||||
}
|
||||
if (activeKeys & KEY_DOWN) {
|
||||
keys |= 1 << GUI_INPUT_DOWN;
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct GBAContext context;
|
||||
srvInit();
|
||||
|
@ -46,6 +77,8 @@ int main() {
|
|||
FSUSER_OpenArchive(0, &sdmcArchive);
|
||||
FSUSER_OpenFile(0, &logFile, sdmcArchive, FS_makePath(PATH_CHAR, "/mgba.log"), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
|
||||
|
||||
struct GUIFont* font = GUIFontCreate();
|
||||
|
||||
GBAContextInit(&context, 0);
|
||||
struct GBAOptions opts = {
|
||||
.useBios = true,
|
||||
|
@ -54,6 +87,7 @@ int main() {
|
|||
};
|
||||
GBAConfigLoadDefaults(&context.config, &opts);
|
||||
context.gba->logHandler = GBA3DSLog;
|
||||
context.gba->logLevel = 0;
|
||||
|
||||
struct GBAVideoSoftwareRenderer renderer;
|
||||
GBAVideoSoftwareRendererCreate(&renderer);
|
||||
|
@ -61,7 +95,21 @@ int main() {
|
|||
renderer.outputBufferStride = 256;
|
||||
GBAVideoAssociateRenderer(&context.gba->video, &renderer.d);
|
||||
|
||||
GBAContextLoadROM(&context, "/rom.gba", true);
|
||||
if (!font) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
struct GUIParams params = {
|
||||
320, 240,
|
||||
font, _drawStart, _drawEnd, _pollInput
|
||||
};
|
||||
_drawStart();
|
||||
GUIFontPrintf(font, 20, 20, GUI_TEXT_LEFT, 0xFFFFFFFF, "Loading...");
|
||||
_drawEnd();
|
||||
char path[256] = "/rom.gba";
|
||||
if (!selectFile(¶ms, "/", path, sizeof(path), "gba") || !GBAContextLoadROM(&context, path, true)) {
|
||||
goto cleanup;
|
||||
}
|
||||
GBAContextStart(&context);
|
||||
|
||||
while (aptMainLoop()) {
|
||||
|
|
Loading…
Reference in New Issue