From 94e329a58cf3cef6bc6d3ce39944f4847e3a44a0 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 6 Aug 2015 15:29:46 -0700 Subject: [PATCH] Wii: Add file selector from PSP2 port --- CMakeLists.txt | 9 ++- res/font.png | Bin 0 -> 5383 bytes src/platform/wii/CMakeToolchain.txt | 2 + src/platform/wii/font.tpl | Bin 0 -> 131136 bytes src/platform/wii/gui-font.c | 87 ++++++++++++++++++++ src/platform/wii/main.c | 94 +++++++++++++++++---- src/util/gui.h | 35 ++++++++ src/util/gui/file-select.c | 121 ++++++++++++++++++++++++++++ src/util/gui/file-select.h | 13 +++ src/util/gui/font.h | 25 ++++++ 10 files changed, 369 insertions(+), 17 deletions(-) create mode 100644 res/font.png create mode 100644 src/platform/wii/font.tpl create mode 100644 src/platform/wii/gui-font.c create mode 100644 src/util/gui.h create mode 100644 src/util/gui/file-select.c create mode 100644 src/util/gui/file-select.h create mode 100644 src/util/gui/font.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f2128351e..8e3dbef18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ file(GLOB GBA_CHEATS_SRC ${CMAKE_SOURCE_DIR}/src/gba/cheats/*.c) file(GLOB GBA_RR_SRC ${CMAKE_SOURCE_DIR}/src/gba/rr/*.c) file(GLOB GBA_SV_SRC ${CMAKE_SOURCE_DIR}/src/gba/supervisor/*.c) file(GLOB UTIL_SRC ${CMAKE_SOURCE_DIR}/src/util/*.[cSs]) +file(GLOB GUI_SRC ${CMAKE_SOURCE_DIR}/src/util/gui/*.c) file(GLOB RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/*.c) file(GLOB SIO_SRC ${CMAKE_SOURCE_DIR}/src/gba/sio/lockstep.c) file(GLOB THIRD_PARTY_SRC ${CMAKE_SOURCE_DIR}/src/third-party/inih/*.c) @@ -163,9 +164,10 @@ elseif(UNIX) file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/posix/*.c) source_group("POSIX-specific code" FILES ${OS_SRC}) elseif(WII) - list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c) + list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5 -DUSE_VFS_FILE) - file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/wii-*.c) + include_directories(${CMAKE_BINARY_DIR}) + file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/wii/*.c) list(APPEND OS_LIB fat ogc) source_group("Wii-specific code" FILES ${OS_SRC}) endif() @@ -192,7 +194,8 @@ endif() if(WII) add_definitions(-U__STRICT_ANSI__) - add_executable(${BINARY_NAME}.elf ${CMAKE_SOURCE_DIR}/src/platform/wii/main.c) + execute_process(COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/wii/font.tpl OUTPUT_QUIET ERROR_QUIET) + add_executable(${BINARY_NAME}.elf ${GUI_SRC} ${CMAKE_BINARY_DIR}/font.c) target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${OS_LIB}) add_custom_command(TARGET ${BINARY_NAME}.elf POST_BUILD COMMAND ${ELF2DOL} ${BINARY_NAME}.elf ${BINARY_NAME}.dol) endif() diff --git a/res/font.png b/res/font.png new file mode 100644 index 0000000000000000000000000000000000000000..73b9893c564395a0318693a381cdc5ee3dba44a5 GIT binary patch literal 5383 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 literal 0 HcmV?d00001 diff --git a/src/platform/wii/CMakeToolchain.txt b/src/platform/wii/CMakeToolchain.txt index c33265feb..9e78b43ce 100644 --- a/src/platform/wii/CMakeToolchain.txt +++ b/src/platform/wii/CMakeToolchain.txt @@ -34,6 +34,8 @@ set(CMAKE_MODULE_LINKER_FLAGS ${link_flags} CACHE INTERNAL "module link flags") set(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags") set(ELF2DOL ${toolchain_bin_dir}/elf2dol) +set(GXTEXCONV ${toolchain_bin_dir}/gxtexconv) +set(RAW2C ${toolchain_bin_dir}/raw2c) set(WII ON) add_definitions(-DGEKKO) diff --git a/src/platform/wii/font.tpl b/src/platform/wii/font.tpl new file mode 100644 index 0000000000000000000000000000000000000000..e0b1a1c552dfe35b94e89c7f9c163dbb8224024e GIT binary patch literal 131136 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 Q9?VEQdGPlNeD(VMe@bo=EdT%j literal 0 HcmV?d00001 diff --git a/src/platform/wii/gui-font.c b/src/platform/wii/gui-font.c new file mode 100644 index 000000000..7c0b0997a --- /dev/null +++ b/src/platform/wii/gui-font.c @@ -0,0 +1,87 @@ +/* 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 "font.h" + +#include + +#define GLYPH_HEIGHT 11 +#define GLYPH_WIDTH 14 +#define FONT_TRACKING 10 +#define CELL_HEIGHT 16 +#define CELL_WIDTH 16 + +struct GUIFont { + TPLFile tdf; +}; + +struct GUIFont* GUIFontCreate(void) { + struct GUIFont* guiFont = malloc(sizeof(struct GUIFont)); + if (!guiFont) { + return 0; + } + + // libogc's TPL code modifies and frees this itself... + void* fontTpl = memalign(32, font_size); + if (!fontTpl) { + free(guiFont); + return 0; + } + memcpy(fontTpl, font, font_size); + TPL_OpenTPLFromMemory(&guiFont->tdf, fontTpl, font_size); + return guiFont; +} + +void GUIFontDestroy(struct GUIFont* font) { + TPL_CloseTPLFile(&font->tdf); + 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; + GXTexObj tex; + // Grumble grumble, libogc is bad about const-correctness + struct GUIFont* ncfont = font; + TPL_GetTexture(&ncfont->tdf, 0, &tex); + GX_LoadTexObj(&tex, GX_TEXMAP0); + + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + for (i = 0; i < len; ++i) { + char c = buffer[i]; + if (c > 0x7F) { + c = 0; + } + s16 tx = (c & 15) * CELL_WIDTH + ((CELL_WIDTH - GLYPH_WIDTH) >> 1); + s16 ty = (c >> 4) * CELL_HEIGHT + ((CELL_HEIGHT - GLYPH_HEIGHT) >> 1) - 1; + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + GX_Position2s16(x, y - GLYPH_HEIGHT); + GX_TexCoord2f32(tx / 256.f, ty / 128.f); + + GX_Position2s16(x + GLYPH_WIDTH, y - GLYPH_HEIGHT); + GX_TexCoord2f32((tx + CELL_WIDTH) / 256.f, ty / 128.f); + + GX_Position2s16(x + GLYPH_WIDTH, y); + GX_TexCoord2f32((tx + CELL_WIDTH) / 256.f, (ty + CELL_HEIGHT) / 128.f); + + GX_Position2s16(x, y); + GX_TexCoord2f32(tx / 256.f, (ty + CELL_HEIGHT) / 128.f); + GX_End(); + x += FONT_TRACKING; + } +} diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index dcbc80cf4..a4898335a 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -16,6 +16,9 @@ #include "gba/serialize.h" #include "gba/supervisor/overrides.h" #include "gba/video.h" +#include "util/gui.h" +#include "util/gui/file-select.h" +#include "util/gui/font.h" #include "util/vfs.h" #define SAMPLES 1024 @@ -27,6 +30,10 @@ static bool GBAWiiLoadGame(const char* path); static void _postVideoFrame(struct GBAAVStream*, struct GBAVideoRenderer* renderer); static void _audioDMA(void); +static void _drawStart(void); +static void _drawEnd(void); +static int _pollInput(void); + static struct GBA gba; static struct ARMCore cpu; static struct GBAVideoSoftwareRenderer renderer; @@ -46,6 +53,8 @@ static struct GBAStereoSample audioBuffer[3][SAMPLES] __attribute__((__aligned__ static volatile size_t audioBufferSize = 0; static volatile int currentAudioBuffer = 0; +static struct GUIFont* font; + int main() { VIDEO_Init(); PAD_Init(); @@ -108,8 +117,6 @@ int main() { GX_InvalidateTexAll(); Mtx44 proj; - guOrtho(proj, 0, VIDEO_VERTICAL_PIXELS, 0, VIDEO_HORIZONTAL_PIXELS, 0, 300); - GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC); guVector cam = { 0.0f, 0.0f, 0.0f }; guVector up = { 0.0f, 1.0f, 0.0f }; @@ -125,6 +132,8 @@ int main() { memset(texmem, 0, 256 * 256 * BYTES_PER_PIXEL); GX_InitTexObj(&tex, texmem, 256, 256, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); + font = GUIFontCreate(); + fatInitDefault(); logfile = fopen("/mgba.log", "w"); @@ -154,10 +163,23 @@ int main() { blip_set_rates(gba.audio.right, GBA_ARM7TDMI_FREQUENCY, 48000); #endif - if (!GBAWiiLoadGame("/rom.gba")) { + char path[256]; + guOrtho(proj, 0, 240, 0, 400, 0, 300); + GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC); + + struct GUIParams params = { + 400, 240, + font, _drawStart, _drawEnd, _pollInput + }; + if (!selectFile(¶ms, "sd:", path, sizeof(path), "gba") || !GBAWiiLoadGame(path)) { + free(renderer.outputBuffer); + GUIFontDestroy(font); return 1; } + guOrtho(proj, 0, VIDEO_VERTICAL_PIXELS, 0, VIDEO_HORIZONTAL_PIXELS, 0, 300); + GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC); + while (true) { #if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF int available = blip_samples_avail(gba.audio.left); @@ -224,6 +246,9 @@ int main() { rom->close(rom); save->close(save); + free(renderer.outputBuffer); + GUIFontDestroy(font); + return 0; } @@ -243,10 +268,10 @@ static void GBAWiiFrame(void) { } DCFlushRange(texdest, 256 * 256 * BYTES_PER_PIXEL); - GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); - GX_SetColorUpdate(GX_TRUE); + _drawStart(); - GX_SetViewport(0, 0, mode->fbWidth, mode->efbHeight, 0, 1); + GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); GX_InvalidateTexAll(); GX_LoadTexObj(&tex, GX_TEXMAP0); @@ -264,16 +289,14 @@ static void GBAWiiFrame(void) { GX_TexCoord2s16(0, 0); GX_End(); - GX_DrawDone(); - - whichFb = !whichFb; - - GX_CopyDisp(framebuffer[whichFb], GX_TRUE); - VIDEO_SetNextFramebuffer(framebuffer[whichFb]); - VIDEO_Flush(); + _drawEnd(); } bool GBAWiiLoadGame(const char* path) { + _drawStart(); + GUIFontPrintf(font, 0, 30, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading..."); + _drawEnd(); + rom = VFileOpen(path, O_RDONLY); if (!rom) { @@ -283,7 +306,7 @@ bool GBAWiiLoadGame(const char* path) { return false; } - save = VFileOpen("test.sav", O_RDWR | O_CREAT); + save = VDirOptionalOpenFile(0, path, 0, ".sav", O_RDWR | O_CREAT); GBALoadROM(&gba, rom, save, path); @@ -321,3 +344,46 @@ static void _audioDMA(void) { currentAudioBuffer = (currentAudioBuffer + 1) % 3; audioBufferSize = 0; } + +static void _drawStart(void) { + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + + GX_SetViewport(0, 0, mode->fbWidth, mode->efbHeight, 0, 1); +} + +static void _drawEnd(void) { + GX_DrawDone(); + + whichFb = !whichFb; + + GX_CopyDisp(framebuffer[whichFb], GX_TRUE); + VIDEO_SetNextFramebuffer(framebuffer[whichFb]); + VIDEO_Flush(); +} + +static int _pollInput(void) { + PAD_ScanPads(); + u16 padkeys = PAD_ButtonsHeld(0); + int keys = 0; + gba.keySource = &keys; + if (padkeys & PAD_BUTTON_A) { + keys |= 1 << GUI_INPUT_SELECT; + } + if (padkeys & PAD_BUTTON_B) { + keys |= 1 << GUI_INPUT_BACK; + } + if (padkeys & PAD_BUTTON_LEFT) { + keys |= 1 << GUI_INPUT_LEFT; + } + if (padkeys & PAD_BUTTON_RIGHT) { + keys |= 1 << GUI_INPUT_RIGHT; + } + if (padkeys & PAD_BUTTON_UP) { + keys |= 1 << GUI_INPUT_UP; + } + if (padkeys & PAD_BUTTON_DOWN) { + keys |= 1 << GUI_INPUT_DOWN; + } + return keys; +} diff --git a/src/util/gui.h b/src/util/gui.h new file mode 100644 index 000000000..d8b2bb058 --- /dev/null +++ b/src/util/gui.h @@ -0,0 +1,35 @@ +/* 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/. */ +#ifndef GUI_H +#define GUI_H + +#include "util/common.h" + +struct GUIFont; + +enum GUIInput { + GUI_INPUT_NONE = -1, + GUI_INPUT_SELECT = 0, + GUI_INPUT_BACK, + GUI_INPUT_CANCEL, + + GUI_INPUT_UP, + GUI_INPUT_DOWN, + GUI_INPUT_LEFT, + GUI_INPUT_RIGHT, +}; + +struct GUIParams { + int width; + int height; + const struct GUIFont* font; + + void (*drawStart)(void); + void (*drawEnd)(void); + int (*pollInput)(void); +}; + +#endif diff --git a/src/util/gui/file-select.c b/src/util/gui/file-select.c new file mode 100644 index 000000000..cc13a2b81 --- /dev/null +++ b/src/util/gui/file-select.c @@ -0,0 +1,121 @@ +/* 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 "file-select.h" + +#include "util/gui/font.h" +#include "util/vector.h" +#include "util/vfs.h" + +DECLARE_VECTOR(FileList, char*); +DEFINE_VECTOR(FileList, char*); + +void _cleanFiles(struct FileList* currentFiles) { + size_t size = FileListSize(currentFiles); + size_t i; + for (i = 0; i < size; ++i) { + free(*FileListGetPointer(currentFiles, i)); + } + FileListClear(currentFiles); +} + +void _upDirectory(char* currentPath) { + char* end = strrchr(currentPath, '/'); + if (!end) { + return; + } + end[0] = '\0'; + if (end[1]) { + return; + } + // TODO: What if there was a trailing slash? +} + +bool _refreshDirectory(const char* currentPath, struct FileList* currentFiles) { + _cleanFiles(currentFiles); + + struct VDir* dir = VDirOpen(currentPath); + if (!dir) { + return false; + } + struct VDirEntry* de; + while ((de = dir->listNext(dir))) { + if (de->name(de)[0] == '.') { + continue; + } + *FileListAppend(currentFiles) = strdup(de->name(de)); + } + dir->close(dir); + return true; +} + +bool selectFile(const struct GUIParams* params, const char* basePath, char* outPath, size_t outLen, const char* suffix) { + char currentPath[256]; + strncpy(currentPath, basePath, sizeof(currentPath)); + int oldInput = -1; + size_t fileIndex = 0; + + struct FileList currentFiles; + FileListInit(¤tFiles, 0); + _refreshDirectory(currentPath, ¤tFiles); + + while (true) { + int input = params->pollInput(); + int newInput = input & (oldInput ^ input); + oldInput = input; + + if (newInput & (1 << GUI_INPUT_UP) && fileIndex > 0) { + --fileIndex; + } + if (newInput & (1 << GUI_INPUT_DOWN) && fileIndex < FileListSize(¤tFiles) - 1) { + ++fileIndex; + } + if (newInput & (1 << GUI_INPUT_CANCEL)) { + _cleanFiles(¤tFiles); + FileListDeinit(¤tFiles); + return false; + } + if (newInput & (1 << GUI_INPUT_SELECT)) { + snprintf(currentPath, sizeof(currentPath), "%s%c%s", currentPath, '/', *FileListGetPointer(¤tFiles, fileIndex)); + if (!_refreshDirectory(currentPath, ¤tFiles)) { + strncpy(outPath, currentPath, outLen); + return true; + } + fileIndex = 0; + } + if (newInput & (1 << GUI_INPUT_BACK)) { + if (strncmp(currentPath, basePath, sizeof(currentPath)) == 0) { + _cleanFiles(¤tFiles); + FileListDeinit(¤tFiles); + return false; + } + _upDirectory(currentPath); + _refreshDirectory(currentPath, ¤tFiles); + fileIndex = 0; + } + + params->drawStart(); + int y = GUIFontHeight(params->font); + GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, "Current directory: %s", currentPath); + y += 2 * GUIFontHeight(params->font); + size_t i; + for (i = 0; i < FileListSize(¤tFiles); ++i) { + int color = 0xE0A0A0A0; + char bullet = ' '; + if (i == fileIndex) { + color = 0xFFFFFFFF; + bullet = '>'; + } + GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, *FileListGetPointer(¤tFiles, i)); + y += GUIFontHeight(params->font); + if (y + GUIFontHeight(params->font) > params->height) { + break; + } + } + y += GUIFontHeight(params->font) * 2; + + params->drawEnd(); + } +} diff --git a/src/util/gui/file-select.h b/src/util/gui/file-select.h new file mode 100644 index 000000000..c96f821c0 --- /dev/null +++ b/src/util/gui/file-select.h @@ -0,0 +1,13 @@ +/* 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/. */ +#ifndef GUI_FILE_CHOOSER_H +#define GUI_FILE_CHOOSER_H + +#include "util/gui.h" + +bool selectFile(const struct GUIParams*, const char* basePath, char* outPath, size_t outLen, const char* suffix); + +#endif diff --git a/src/util/gui/font.h b/src/util/gui/font.h new file mode 100644 index 000000000..4120814c2 --- /dev/null +++ b/src/util/gui/font.h @@ -0,0 +1,25 @@ +/* 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/. */ +#ifndef GUI_FONT_H +#define GUI_FONT_H + +#include "util/common.h" + +struct GUIFont; +struct GUIFont* GUIFontCreate(void); +void GUIFontDestroy(struct GUIFont*); + +enum GUITextAlignment { + GUI_TEXT_LEFT = 0, + GUI_TEXT_CENTER, + GUI_TEXT_RIGHT +}; + +int GUIFontHeight(const struct GUIFont*); + +void GUIFontPrintf(const struct GUIFont*, int x, int y, enum GUITextAlignment, uint32_t color, const char* text, ...); + +#endif