mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'port/3ds' into port/crucible
This commit is contained in:
commit
64a3065b45
|
@ -28,7 +28,6 @@ file(GLOB GBA_SRC ${CMAKE_SOURCE_DIR}/src/gba/*.c)
|
||||||
file(GLOB GBA_CHEATS_SRC ${CMAKE_SOURCE_DIR}/src/gba/cheats/*.c)
|
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_RR_SRC ${CMAKE_SOURCE_DIR}/src/gba/rr/*.c)
|
||||||
file(GLOB GBA_SV_SRC ${CMAKE_SOURCE_DIR}/src/gba/supervisor/*.c)
|
file(GLOB GBA_SV_SRC ${CMAKE_SOURCE_DIR}/src/gba/supervisor/*.c)
|
||||||
file(GLOB GUI_SRC ${CMAKE_SOURCE_DIR}/src/gui/*.c)
|
|
||||||
file(GLOB UTIL_SRC ${CMAKE_SOURCE_DIR}/src/util/*.[cSs])
|
file(GLOB UTIL_SRC ${CMAKE_SOURCE_DIR}/src/util/*.[cSs])
|
||||||
file(GLOB GUI_SRC ${CMAKE_SOURCE_DIR}/src/util/gui/*.c)
|
file(GLOB GUI_SRC ${CMAKE_SOURCE_DIR}/src/util/gui/*.c)
|
||||||
file(GLOB RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/*.c)
|
file(GLOB RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/*.c)
|
||||||
|
@ -170,9 +169,19 @@ elseif(UNIX)
|
||||||
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/posix/*.c)
|
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/posix/*.c)
|
||||||
source_group("POSIX-specific code" FILES ${OS_SRC})
|
source_group("POSIX-specific code" FILES ${OS_SRC})
|
||||||
elseif(3DS)
|
elseif(3DS)
|
||||||
|
set(M_LIBRARY m)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format")
|
||||||
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
|
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
|
||||||
list(APPEND OS_LIB ctru)
|
execute_process(COMMAND ${RAW2C} ${CMAKE_SOURCE_DIR}/src/platform/3ds/font.raw)
|
||||||
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/3ds/3ds-*.c)
|
include_directories(${CMAKE_BINARY_DIR})
|
||||||
|
list(APPEND OS_LIB sf2d ctru)
|
||||||
|
file(GLOB OS_SRC ${CMAKE_SOURCE_DIR}/src/platform/3ds/*.c ${CMAKE_BINARY_DIR}/font.c)
|
||||||
|
if(USE_VFS_3DS)
|
||||||
|
add_definitions(-DUSE_VFS_3DS)
|
||||||
|
else()
|
||||||
|
add_definitions(-DUSE_VFS_FILE)
|
||||||
|
list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
|
||||||
|
endif()
|
||||||
source_group("3DS-specific code" FILES ${OS_SRC})
|
source_group("3DS-specific code" FILES ${OS_SRC})
|
||||||
elseif(WII)
|
elseif(WII)
|
||||||
list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
|
list(APPEND VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-file.c ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-dirent.c)
|
||||||
|
@ -466,6 +475,12 @@ if(PSP2)
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/psp2 ${CMAKE_BINARY_DIR}/psp2)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/psp2 ${CMAKE_BINARY_DIR}/psp2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(3DS)
|
||||||
|
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()
|
||||||
|
|
||||||
if(BUILD_PERF)
|
if(BUILD_PERF)
|
||||||
set(PERF_SRC ${CMAKE_SOURCE_DIR}/src/platform/test/perf-main.c)
|
set(PERF_SRC ${CMAKE_SOURCE_DIR}/src/platform/test/perf-main.c)
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
@ -478,12 +493,6 @@ if(BUILD_PERF)
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/tools/perf.py DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf)
|
install(FILES ${CMAKE_SOURCE_DIR}/tools/perf.py DESTINATION "${CMAKE_INSTALL_LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(3DS)
|
|
||||||
add_executable(${BINARY_NAME}.elf ${CMAKE_SOURCE_DIR}/src/platform/3ds/main.c)
|
|
||||||
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()
|
|
||||||
|
|
||||||
if(PSP)
|
if(PSP)
|
||||||
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/psp ${CMAKE_BINARY_DIR}/psp)
|
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/psp ${CMAKE_BINARY_DIR}/psp)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "3ds-vfs.h"
|
#include "3ds-vfs.h"
|
||||||
|
|
||||||
|
#ifdef USE_VFS_3DS
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
struct VFile3DS {
|
struct VFile3DS {
|
||||||
struct VFile d;
|
struct VFile d;
|
||||||
|
@ -14,6 +16,20 @@ struct VFile3DS {
|
||||||
u64 offset;
|
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 bool _vf3dClose(struct VFile* vf);
|
||||||
static off_t _vf3dSeek(struct VFile* vf, off_t offset, int whence);
|
static off_t _vf3dSeek(struct VFile* vf, off_t offset, int whence);
|
||||||
static ssize_t _vf3dRead(struct VFile* vf, void* buffer, size_t size);
|
static ssize_t _vf3dRead(struct VFile* vf, void* buffer, size_t size);
|
||||||
|
@ -24,6 +40,13 @@ static void _vf3dTruncate(struct VFile* vf, size_t size);
|
||||||
static ssize_t _vf3dSize(struct VFile* vf);
|
static ssize_t _vf3dSize(struct VFile* vf);
|
||||||
static bool _vf3dSync(struct VFile* vf, const void* buffer, size_t size);
|
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 VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags) {
|
||||||
struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS));
|
struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS));
|
||||||
if (!vf3d) {
|
if (!vf3d) {
|
||||||
|
@ -141,3 +164,85 @@ static bool _vf3dSync(struct VFile* vf, const void* buffer, size_t size) {
|
||||||
FSFILE_Flush(vf3d->handle);
|
FSFILE_Flush(vf3d->handle);
|
||||||
return true;
|
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;
|
||||||
|
vd3d->vde.utf8Name = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
memset(&vd3d->vde.ent, 0, sizeof(vd3d->vde.ent));
|
||||||
|
if (vd3d->vde.utf8Name) {
|
||||||
|
free(vd3d->vde.utf8Name);
|
||||||
|
vd3d->vde.utf8Name = 0;
|
||||||
|
};
|
||||||
|
FSDIR_Read(vd3d->handle, &n, 1, &vd3d->vde.ent);
|
||||||
|
if (!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) {
|
||||||
|
vd3de->utf8Name = utf16to8(vd3de->ent.name, sizeof(vd3de->ent.name) / 2);
|
||||||
|
}
|
||||||
|
return vd3de->utf8Name;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
|
extern FS_archive sdmcArchive;
|
||||||
|
|
||||||
struct VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags);
|
struct VFile* VFileOpen3DS(FS_archive* archive, const char* path, int flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,7 @@ 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(CMAKE_SHARED_LINKER_FLAGS ${link_flags} CACHE INTERNAL "shared link flags")
|
||||||
|
|
||||||
set(3DSXTOOL ${toolchain_bin_dir}/3dsxtool)
|
set(3DSXTOOL ${toolchain_bin_dir}/3dsxtool)
|
||||||
|
set(RAW2C ${toolchain_bin_dir}/raw2c)
|
||||||
|
|
||||||
set(3DS ON)
|
set(3DS ON)
|
||||||
add_definitions(-D_3DS -DARM11)
|
add_definitions(-D_3DS -DARM11)
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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 - metric.padding.left,
|
||||||
|
y - GLYPH_HEIGHT,
|
||||||
|
(c & 15) * CELL_WIDTH,
|
||||||
|
(c >> 4) * CELL_HEIGHT,
|
||||||
|
CELL_WIDTH,
|
||||||
|
CELL_HEIGHT,
|
||||||
|
color);
|
||||||
|
x += metric.width;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,104 +3,150 @@
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "gba/gba.h"
|
|
||||||
#include "gba/video.h"
|
|
||||||
|
|
||||||
#include "gba/renderers/video-software.h"
|
#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 "util/memory.h"
|
||||||
|
|
||||||
#include "3ds-vfs.h"
|
#include "3ds-vfs.h"
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <sf2d.h>
|
||||||
|
|
||||||
|
FS_archive sdmcArchive;
|
||||||
|
|
||||||
static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
|
static void GBA3DSLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
|
||||||
static Handle logFile;
|
static Handle logFile;
|
||||||
|
|
||||||
|
static void _drawStart(void) {
|
||||||
|
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||||
|
}
|
||||||
|
static void _drawEnd(void) {
|
||||||
|
sf2d_end_frame();
|
||||||
|
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() {
|
int main() {
|
||||||
|
struct GBAContext context;
|
||||||
srvInit();
|
srvInit();
|
||||||
aptInit();
|
aptInit();
|
||||||
hidInit(0);
|
hidInit(0);
|
||||||
gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, false);
|
|
||||||
fsInit();
|
fsInit();
|
||||||
|
sdmcInit();
|
||||||
|
|
||||||
FS_archive sdmcArchive = (FS_archive) {
|
sf2d_init();
|
||||||
|
sf2d_set_clear_color(0);
|
||||||
|
sf2d_texture* tex = sf2d_create_texture(256, 256, TEXFMT_RGB565, SF2D_PLACE_RAM);
|
||||||
|
memset(tex->data, 0, 256 * 256 * 2);
|
||||||
|
|
||||||
|
sdmcArchive = (FS_archive) {
|
||||||
ARCH_SDMC,
|
ARCH_SDMC,
|
||||||
(FS_path) { PATH_EMPTY, 1, (u8*)"" },
|
(FS_path) { PATH_EMPTY, 1, (const u8*)"" },
|
||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
FSUSER_OpenArchive(0, &sdmcArchive);
|
FSUSER_OpenArchive(0, &sdmcArchive);
|
||||||
FSUSER_OpenFile(0, &logFile, sdmcArchive, FS_makePath(PATH_CHAR, "/mgba.log"), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE);
|
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,
|
||||||
|
.logLevel = 0,
|
||||||
|
.idleOptimization = IDLE_LOOP_REMOVE
|
||||||
|
};
|
||||||
|
GBAConfigLoadDefaults(&context.config, &opts);
|
||||||
|
context.gba->logHandler = GBA3DSLog;
|
||||||
|
context.gba->logLevel = 0;
|
||||||
|
|
||||||
struct GBAVideoSoftwareRenderer renderer;
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
GBAVideoSoftwareRendererCreate(&renderer);
|
GBAVideoSoftwareRendererCreate(&renderer);
|
||||||
|
renderer.outputBuffer = anonymousMemoryMap(256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||||
|
renderer.outputBufferStride = 256;
|
||||||
|
GBAVideoAssociateRenderer(&context.gba->video, &renderer.d);
|
||||||
|
|
||||||
size_t stride = VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL;
|
if (!font) {
|
||||||
color_t* videoBuffer = anonymousMemoryMap(stride * VIDEO_VERTICAL_PIXELS);
|
goto cleanup;
|
||||||
struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA));
|
}
|
||||||
struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore));
|
|
||||||
int activeKeys = 0;
|
|
||||||
|
|
||||||
renderer.outputBuffer = videoBuffer;
|
struct GUIParams params = {
|
||||||
renderer.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
|
320, 240,
|
||||||
|
font, _drawStart, _drawEnd, _pollInput
|
||||||
|
};
|
||||||
|
|
||||||
struct VFile* rom = VFileOpen3DS(&sdmcArchive, "/rom.gba", FS_OPEN_READ);
|
|
||||||
struct VFile* save = VFileOpen3DS(&sdmcArchive, "/rom.sav", FS_OPEN_READ | FS_OPEN_WRITE);
|
|
||||||
|
|
||||||
GBACreate(gba);
|
|
||||||
ARMSetComponents(cpu, &gba->d, 0, 0);
|
|
||||||
ARMInit(cpu);
|
|
||||||
|
|
||||||
gba->keySource = &activeKeys;
|
|
||||||
gba->sync = 0;
|
|
||||||
|
|
||||||
GBAVideoAssociateRenderer(&gba->video, &renderer.d);
|
|
||||||
|
|
||||||
GBALoadROM(gba, rom, save, 0);
|
|
||||||
|
|
||||||
gba->logHandler = GBA3DSLog;
|
|
||||||
|
|
||||||
ARMReset(cpu);
|
|
||||||
|
|
||||||
int frameCounter = 0;
|
|
||||||
while (aptMainLoop()) {
|
while (aptMainLoop()) {
|
||||||
ARMRunLoop(cpu);
|
char path[256];
|
||||||
|
if (!selectFile(¶ms, "/", path, sizeof(path), "gba")) {
|
||||||
if (frameCounter != gba->video.frameCounter) {
|
break;
|
||||||
u16 width, height;
|
}
|
||||||
u16* screen = (u16*) gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, &height, &width);
|
_drawStart();
|
||||||
u32 startX = (width - VIDEO_HORIZONTAL_PIXELS) / 2;
|
GUIFontPrintf(font, 130, (GUIFontHeight(font) + 240) / 2, GUI_TEXT_LEFT, 0xFFFFFFFF, "Loading...");
|
||||||
u32 startY = (height + VIDEO_VERTICAL_PIXELS) / 2 - 1;
|
_drawEnd();
|
||||||
u32 x, y;
|
if (!GBAContextLoadROM(&context, path, true)) {
|
||||||
for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) {
|
continue;
|
||||||
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
|
}
|
||||||
screen[startY - y + (startX + x) * height] = videoBuffer[y * VIDEO_HORIZONTAL_PIXELS + x];
|
if (!GBAContextStart(&context)) {
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
gfxFlushBuffers();
|
while (aptMainLoop()) {
|
||||||
gfxSwapBuffersGpu();
|
|
||||||
gspWaitForVBlank();
|
|
||||||
hidScanInput();
|
hidScanInput();
|
||||||
activeKeys = hidKeysHeld() & 0x3FF;
|
int activeKeys = hidKeysHeld() & 0x3FF;
|
||||||
if (hidKeysDown() & KEY_X) {
|
if (hidKeysDown() & KEY_X) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
frameCounter = gba->video.frameCounter;
|
GBAContextFrame(&context, activeKeys);
|
||||||
|
GX_SetDisplayTransfer(0, renderer.outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202);
|
||||||
|
GSPGPU_FlushDataCache(0, tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||||
|
gspWaitForPPF();
|
||||||
|
_drawStart();
|
||||||
|
sf2d_draw_texture_scale(tex, 40, 296, 1, -1);
|
||||||
|
_drawEnd();
|
||||||
}
|
}
|
||||||
|
GBAContextStop(&context);
|
||||||
}
|
}
|
||||||
|
GBAContextDeinit(&context);
|
||||||
|
|
||||||
ARMDeinit(cpu);
|
cleanup:
|
||||||
GBADestroy(gba);
|
mappedMemoryFree(renderer.outputBuffer, 0);
|
||||||
|
|
||||||
rom->close(rom);
|
|
||||||
save->close(save);
|
|
||||||
|
|
||||||
mappedMemoryFree(gba, 0);
|
|
||||||
mappedMemoryFree(cpu, 0);
|
|
||||||
|
|
||||||
mappedMemoryFree(videoBuffer, 0);
|
|
||||||
|
|
||||||
FSFILE_Close(logFile);
|
FSFILE_Close(logFile);
|
||||||
|
|
||||||
|
sf2d_free_texture(tex);
|
||||||
|
sf2d_fini();
|
||||||
|
|
||||||
|
sdmcExit();
|
||||||
fsExit();
|
fsExit();
|
||||||
gfxExit();
|
gfxExit();
|
||||||
hidExit();
|
hidExit();
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
DECLARE_VECTOR(FileList, char*);
|
DECLARE_VECTOR(FileList, char*);
|
||||||
DEFINE_VECTOR(FileList, char*);
|
DEFINE_VECTOR(FileList, char*);
|
||||||
|
|
||||||
void _cleanFiles(struct FileList* currentFiles) {
|
static void _cleanFiles(struct FileList* currentFiles) {
|
||||||
size_t size = FileListSize(currentFiles);
|
size_t size = FileListSize(currentFiles);
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
|
@ -21,7 +21,7 @@ void _cleanFiles(struct FileList* currentFiles) {
|
||||||
FileListClear(currentFiles);
|
FileListClear(currentFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _upDirectory(char* currentPath) {
|
static void _upDirectory(char* currentPath) {
|
||||||
char* end = strrchr(currentPath, '/');
|
char* end = strrchr(currentPath, '/');
|
||||||
if (!end) {
|
if (!end) {
|
||||||
return;
|
return;
|
||||||
|
@ -37,7 +37,7 @@ void _upDirectory(char* currentPath) {
|
||||||
// TODO: What if there was a trailing slash?
|
// TODO: What if there was a trailing slash?
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _refreshDirectory(const char* currentPath, struct FileList* currentFiles) {
|
static bool _refreshDirectory(const char* currentPath, struct FileList* currentFiles) {
|
||||||
_cleanFiles(currentFiles);
|
_cleanFiles(currentFiles);
|
||||||
|
|
||||||
struct VDir* dir = VDirOpen(currentPath);
|
struct VDir* dir = VDirOpen(currentPath);
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "platform/psp/sce-vfs.h"
|
#include "platform/psp/sce-vfs.h"
|
||||||
#elif defined(PSP2)
|
#elif defined(PSP2)
|
||||||
#include "platform/psp2/sce-vfs.h"
|
#include "platform/psp2/sce-vfs.h"
|
||||||
|
#elif _3DS
|
||||||
|
#include "platform/3ds/3ds-vfs.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct VFile* VFileOpen(const char* path, int flags) {
|
struct VFile* VFileOpen(const char* path, int flags) {
|
||||||
|
@ -60,7 +62,35 @@ struct VFile* VFileOpen(const char* path, int flags) {
|
||||||
sceFlags |= PSP2_O_CREAT;
|
sceFlags |= PSP2_O_CREAT;
|
||||||
}
|
}
|
||||||
return VFileOpenSce(path, sceFlags, 0666);
|
return VFileOpenSce(path, sceFlags, 0666);
|
||||||
>>>>>>> port/psp2
|
#elif defined(USE_VFS_3DS)
|
||||||
|
int ctrFlags = FS_OPEN_READ;
|
||||||
|
switch (flags & O_ACCMODE) {
|
||||||
|
case O_WRONLY:
|
||||||
|
ctrFlags = FS_OPEN_WRITE;
|
||||||
|
break;
|
||||||
|
case O_RDWR:
|
||||||
|
ctrFlags = FS_OPEN_READ | FS_OPEN_WRITE;
|
||||||
|
break;
|
||||||
|
case O_RDONLY:
|
||||||
|
ctrFlags = FS_OPEN_READ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & O_CREAT) {
|
||||||
|
ctrFlags |= FS_OPEN_CREATE;
|
||||||
|
}
|
||||||
|
struct VFile* vf = VFileOpen3DS(&sdmcArchive, path, ctrFlags);
|
||||||
|
if (!vf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (flags & O_TRUNC) {
|
||||||
|
vf->truncate(vf, 0);
|
||||||
|
}
|
||||||
|
if (flags & O_APPEND) {
|
||||||
|
vf->seek(vf, vf->size(vf), SEEK_SET);
|
||||||
|
}
|
||||||
|
return vf;
|
||||||
|
>>>>>>> port/3ds
|
||||||
#else
|
#else
|
||||||
return VFileOpenFD(path, flags);
|
return VFileOpenFD(path, flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue