mirror of
https://github.com/libretro/mgba.git
synced 2024-11-24 08:30:30 +00:00
Perf: De-threadify and make compatible with 3DS
This commit is contained in:
parent
9919fffcb7
commit
9f6837da42
@ -45,7 +45,7 @@ file(GLOB GBA_RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gba/renderers/*.c)
|
|||||||
file(GLOB SIO_SRC ${CMAKE_SOURCE_DIR}/src/gba/sio/lockstep.c)
|
file(GLOB SIO_SRC ${CMAKE_SOURCE_DIR}/src/gba/sio/lockstep.c)
|
||||||
file(GLOB GB_RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gb/renderers/*.c)
|
file(GLOB GB_RENDERER_SRC ${CMAKE_SOURCE_DIR}/src/gb/renderers/*.c)
|
||||||
file(GLOB THIRD_PARTY_SRC ${CMAKE_SOURCE_DIR}/src/third-party/inih/*.c)
|
file(GLOB THIRD_PARTY_SRC ${CMAKE_SOURCE_DIR}/src/third-party/inih/*.c)
|
||||||
list(APPEND GBA_SV_SRC ${CMAKE_SOURCE_DIR}/src/platform/commandline.c)
|
set(CLI_SRC ${CMAKE_SOURCE_DIR}/src/platform/commandline.c)
|
||||||
set(CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-mem.c)
|
set(CORE_VFS_SRC ${CMAKE_SOURCE_DIR}/src/util/vfs/vfs-mem.c)
|
||||||
set(VFS_SRC)
|
set(VFS_SRC)
|
||||||
source_group("ARM core" FILES ${ARM_SRC})
|
source_group("ARM core" FILES ${ARM_SRC})
|
||||||
@ -529,7 +529,8 @@ if(NOT MINIMAL_CORE)
|
|||||||
${SIO_SRC})
|
${SIO_SRC})
|
||||||
endif()
|
endif()
|
||||||
list(APPEND SRC
|
list(APPEND SRC
|
||||||
${FEATURE_SRC})
|
${FEATURE_SRC}
|
||||||
|
${CLI_SRC})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT SKIP_LIBRARY)
|
if(NOT SKIP_LIBRARY)
|
||||||
@ -622,13 +623,13 @@ if(BUILD_QT)
|
|||||||
endif()
|
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 ${CLI_SRC})
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
list(APPEND PERF_LIB rt)
|
list(APPEND PERF_LIB rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(${BINARY_NAME}-perf ${PERF_SRC})
|
add_executable(${BINARY_NAME}-perf ${PERF_SRC})
|
||||||
target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB})
|
target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB})
|
||||||
set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
|
set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
|
||||||
install(TARGETS ${BINARY_NAME}-perf DESTINATION bin COMPONENT ${BINARY_NAME}-perf)
|
install(TARGETS ${BINARY_NAME}-perf DESTINATION bin COMPONENT ${BINARY_NAME}-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)
|
||||||
|
@ -14,8 +14,9 @@ set(OS_DEFINES COLOR_16_BIT COLOR_5_6_5 IOAPI_NO_64)
|
|||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
list(APPEND OS_LIB ctru)
|
list(APPEND OS_LIB ctru)
|
||||||
file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/3ds-*.c)
|
file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/3ds-*.c ${CMAKE_CURRENT_SOURCE_DIR}/ctru-heap.c)
|
||||||
set(OS_SRC ${OS_SRC} PARENT_SCOPE)
|
set(OS_SRC ${OS_SRC} PARENT_SCOPE)
|
||||||
|
set(OS_LIB ${OS_LIB} PARENT_SCOPE)
|
||||||
source_group("3DS-specific code" FILES ${OS_SRC})
|
source_group("3DS-specific code" FILES ${OS_SRC})
|
||||||
|
|
||||||
if(USE_VFS_3DS)
|
if(USE_VFS_3DS)
|
||||||
@ -45,7 +46,7 @@ set_source_files_properties(
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}/uishader.h
|
${CMAKE_CURRENT_BINARY_DIR}/uishader.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h
|
${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h
|
||||||
PROPERTIES GENERATED ON)
|
PROPERTIES GENERATED ON)
|
||||||
add_executable(${BINARY_NAME}.elf ${GUI_SRC} main.c ctru-heap.c)
|
add_executable(${BINARY_NAME}.elf ${GUI_SRC} main.c)
|
||||||
set_target_properties(${BINARY_NAME}.elf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
|
set_target_properties(${BINARY_NAME}.elf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}")
|
||||||
target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${M_LIBRARY} ${OS_LIB})
|
target_link_libraries(${BINARY_NAME}.elf ${BINARY_NAME} ${M_LIBRARY} ${OS_LIB})
|
||||||
|
|
||||||
@ -93,6 +94,12 @@ add_custom_target(${BINARY_NAME}.cia ALL
|
|||||||
add_custom_target(run ${3DSLINK} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx
|
add_custom_target(run ${3DSLINK} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx
|
||||||
DEPENDS ${BINARY_NAME}.3dsx)
|
DEPENDS ${BINARY_NAME}.3dsx)
|
||||||
|
|
||||||
|
if(BUILD_PERF)
|
||||||
|
add_custom_target(${BINARY_NAME}-perf.3dsx ALL
|
||||||
|
${3DSXTOOL} ../${BINARY_NAME}-perf ${BINARY_NAME}-perf.3dsx --smdh=${BINARY_NAME}.smdh
|
||||||
|
DEPENDS ${BINARY_NAME}-perf ${BINARY_NAME}.smdh)
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cia.rsf.in ${CMAKE_CURRENT_BINARY_DIR}/cia.rsf)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cia.rsf.in ${CMAKE_CURRENT_BINARY_DIR}/cia.rsf)
|
||||||
install(FILES
|
install(FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx
|
${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx
|
||||||
|
@ -25,7 +25,7 @@ set(CMAKE_PROGRAM_PATH ${DEVKITARM}/bin)
|
|||||||
set(cross_prefix ${CMAKE_PROGRAM_PATH}/arm-none-eabi-)
|
set(cross_prefix ${CMAKE_PROGRAM_PATH}/arm-none-eabi-)
|
||||||
set(arch_flags "-march=armv6k -mtune=mpcore -mfpu=vfp -mfloat-abi=hard")
|
set(arch_flags "-march=armv6k -mtune=mpcore -mfpu=vfp -mfloat-abi=hard")
|
||||||
set(inc_flags "-I${CTRULIB}/include ${arch_flags} -mword-relocations")
|
set(inc_flags "-I${CTRULIB}/include ${arch_flags} -mword-relocations")
|
||||||
set(link_flags "-L${CTRULIB}/lib -lctru -specs=3dsx.specs ${arch_flags}")
|
set(link_flags "-L${CTRULIB}/lib -specs=3dsx.specs ${arch_flags}")
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name")
|
set(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name")
|
||||||
set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor")
|
set(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor")
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
* 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 "core/config.h"
|
#include "core/config.h"
|
||||||
#include "core/thread.h"
|
|
||||||
#include "gba/core.h"
|
#include "gba/core.h"
|
||||||
#include "gba/gba.h"
|
#include "gba/gba.h"
|
||||||
#include "gba/renderers/video-software.h"
|
#include "gba/renderers/video-software.h"
|
||||||
@ -14,6 +13,10 @@
|
|||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/vfs.h"
|
#include "util/vfs.h"
|
||||||
|
|
||||||
|
#ifdef _3DS
|
||||||
|
#include <3ds.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -37,17 +40,40 @@ struct PerfOpts {
|
|||||||
char* savestate;
|
char* savestate;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void _GBAPerfRunloop(struct mCoreThread* context, int* frames, bool quiet);
|
#ifdef _3DS
|
||||||
static void _GBAPerfShutdown(int signal);
|
extern bool allocateRomBuffer(void);
|
||||||
static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg);
|
FS_Archive sdmcArchive;
|
||||||
static void _loadSavestate(struct mCoreThread* context);
|
#endif
|
||||||
|
|
||||||
|
static void _mPerfRunloop(struct mCore* context, int* frames, bool quiet);
|
||||||
|
static void _mPerfShutdown(int signal);
|
||||||
|
static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg);
|
||||||
|
static void _log(struct mLogger*, int, enum mLogLevel, const char*, va_list);
|
||||||
|
|
||||||
static struct mCoreThread* _thread;
|
|
||||||
static bool _dispatchExiting = false;
|
static bool _dispatchExiting = false;
|
||||||
static struct VFile* _savestate = 0;
|
static struct VFile* _savestate = 0;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
signal(SIGINT, _GBAPerfShutdown);
|
#ifdef _3DS
|
||||||
|
gfxInitDefault();
|
||||||
|
osSetSpeedupEnable(true);
|
||||||
|
consoleInit(GFX_BOTTOM, NULL);
|
||||||
|
if (!allocateRomBuffer()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sdmcArchive = (FS_Archive) {
|
||||||
|
ARCHIVE_SDMC,
|
||||||
|
(FS_Path) { PATH_EMPTY, 1, "" },
|
||||||
|
0
|
||||||
|
};
|
||||||
|
FSUSER_OpenArchive(&sdmcArchive);
|
||||||
|
#else
|
||||||
|
signal(SIGINT, _mPerfShutdown);
|
||||||
|
#endif
|
||||||
|
int didFail = 0;
|
||||||
|
|
||||||
|
struct mLogger logger = { .log = _log };
|
||||||
|
mLogSetDefaultLogger(&logger);
|
||||||
|
|
||||||
struct PerfOpts perfOpts = { false, false, 0, 0, 0 };
|
struct PerfOpts perfOpts = { false, false, 0, 0, 0 };
|
||||||
struct mSubParser subparser = {
|
struct mSubParser subparser = {
|
||||||
@ -57,30 +83,26 @@ int main(int argc, char** argv) {
|
|||||||
.opts = &perfOpts
|
.opts = &perfOpts
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mArguments args;
|
struct mArguments args = {};
|
||||||
bool parsed = parseArguments(&args, argc, argv, &subparser);
|
bool parsed = parseArguments(&args, argc, argv, &subparser);
|
||||||
if (!parsed || args.showHelp) {
|
if (!parsed || args.showHelp) {
|
||||||
usage(argv[0], PERF_USAGE);
|
usage(argv[0], PERF_USAGE);
|
||||||
freeArguments(&args);
|
didFail = !parsed;
|
||||||
return !parsed;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.showVersion) {
|
if (args.showVersion) {
|
||||||
version(argv[0]);
|
version(argv[0]);
|
||||||
freeArguments(&args);
|
goto cleanup;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* outputBuffer = malloc(256 * 256 * 4);
|
void* outputBuffer = malloc(256 * 256 * 4);
|
||||||
|
|
||||||
struct mCore* core = mCoreFind(args.fname);
|
struct mCore* core = mCoreFind(args.fname);
|
||||||
if (!core) {
|
if (!core) {
|
||||||
freeArguments(&args);
|
didFail = 1;
|
||||||
return 1;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
struct mCoreThread context = {
|
|
||||||
.core = core
|
|
||||||
};
|
|
||||||
_thread = &context;
|
|
||||||
|
|
||||||
if (!perfOpts.noVideo) {
|
if (!perfOpts.noVideo) {
|
||||||
core->setVideoBuffer(core, outputBuffer, 256);
|
core->setVideoBuffer(core, outputBuffer, 256);
|
||||||
@ -89,9 +111,6 @@ int main(int argc, char** argv) {
|
|||||||
_savestate = VFileOpen(perfOpts.savestate, O_RDONLY);
|
_savestate = VFileOpen(perfOpts.savestate, O_RDONLY);
|
||||||
free(perfOpts.savestate);
|
free(perfOpts.savestate);
|
||||||
}
|
}
|
||||||
if (_savestate) {
|
|
||||||
context.startCallback = _loadSavestate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Put back debugger
|
// TODO: Put back debugger
|
||||||
char gameCode[5] = { 0 };
|
char gameCode[5] = { 0 };
|
||||||
@ -110,19 +129,14 @@ int main(int argc, char** argv) {
|
|||||||
mCoreConfigLoadDefaults(&core->config, &opts);
|
mCoreConfigLoadDefaults(&core->config, &opts);
|
||||||
mCoreLoadConfig(core);
|
mCoreLoadConfig(core);
|
||||||
|
|
||||||
int didStart = mCoreThreadStart(&context);
|
core->reset(core);
|
||||||
|
if (_savestate) {
|
||||||
if (!didStart) {
|
core->loadState(core, _savestate, 0);
|
||||||
goto cleanup;
|
_savestate->close(_savestate);
|
||||||
}
|
_savestate = NULL;
|
||||||
mCoreThreadInterrupt(&context);
|
|
||||||
if (mCoreThreadHasCrashed(&context)) {
|
|
||||||
mCoreThreadJoin(&context);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GBAGetGameCode(core->board, gameCode);
|
core->getGameCode(core, gameCode);
|
||||||
mCoreThreadContinue(&context);
|
|
||||||
|
|
||||||
int frames = perfOpts.frames;
|
int frames = perfOpts.frames;
|
||||||
if (!frames) {
|
if (!frames) {
|
||||||
@ -131,12 +145,12 @@ int main(int argc, char** argv) {
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
uint64_t start = 1000000LL * tv.tv_sec + tv.tv_usec;
|
uint64_t start = 1000000LL * tv.tv_sec + tv.tv_usec;
|
||||||
_GBAPerfRunloop(&context, &frames, perfOpts.csv);
|
_mPerfRunloop(core, &frames, perfOpts.csv);
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
uint64_t end = 1000000LL * tv.tv_sec + tv.tv_usec;
|
uint64_t end = 1000000LL * tv.tv_sec + tv.tv_usec;
|
||||||
uint64_t duration = end - start;
|
uint64_t duration = end - start;
|
||||||
|
|
||||||
mCoreThreadJoin(&context);
|
core->deinit(core);
|
||||||
|
|
||||||
float scaledFrames = frames * 1000000.f;
|
float scaledFrames = frames * 1000000.f;
|
||||||
if (perfOpts.csv) {
|
if (perfOpts.csv) {
|
||||||
@ -152,49 +166,46 @@ int main(int argc, char** argv) {
|
|||||||
printf("%u frames in %" PRIu64 " microseconds: %g fps (%gx)\n", frames, duration, scaledFrames / duration, scaledFrames / (duration * 60.f));
|
printf("%u frames in %" PRIu64 " microseconds: %g fps (%gx)\n", frames, duration, scaledFrames / duration, scaledFrames / (duration * 60.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (_savestate) {
|
|
||||||
_savestate->close(_savestate);
|
|
||||||
}
|
|
||||||
mCoreConfigFreeOpts(&opts);
|
mCoreConfigFreeOpts(&opts);
|
||||||
freeArguments(&args);
|
|
||||||
mCoreConfigDeinit(&core->config);
|
mCoreConfigDeinit(&core->config);
|
||||||
free(outputBuffer);
|
free(outputBuffer);
|
||||||
|
|
||||||
return !didStart || mCoreThreadHasCrashed(&context);
|
cleanup:
|
||||||
|
freeArguments(&args);
|
||||||
|
|
||||||
|
#ifdef _3DS
|
||||||
|
gfxExit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return didFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBAPerfRunloop(struct mCoreThread* context, int* frames, bool quiet) {
|
static void _mPerfRunloop(struct mCore* core, int* frames, bool quiet) {
|
||||||
struct timeval lastEcho;
|
struct timeval lastEcho;
|
||||||
gettimeofday(&lastEcho, 0);
|
gettimeofday(&lastEcho, 0);
|
||||||
int duration = *frames;
|
int duration = *frames;
|
||||||
*frames = 0;
|
*frames = 0;
|
||||||
int lastFrames = 0;
|
int lastFrames = 0;
|
||||||
while (context->state < THREAD_EXITING) {
|
while (!_dispatchExiting) {
|
||||||
if (mCoreSyncWaitFrameStart(&context->sync)) {
|
core->runFrame(core);
|
||||||
++*frames;
|
++*frames;
|
||||||
++lastFrames;
|
++lastFrames;
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
struct timeval currentTime;
|
struct timeval currentTime;
|
||||||
long timeDiff;
|
long timeDiff;
|
||||||
gettimeofday(¤tTime, 0);
|
gettimeofday(¤tTime, 0);
|
||||||
timeDiff = currentTime.tv_sec - lastEcho.tv_sec;
|
timeDiff = currentTime.tv_sec - lastEcho.tv_sec;
|
||||||
timeDiff *= 1000;
|
timeDiff *= 1000;
|
||||||
timeDiff += (currentTime.tv_usec - lastEcho.tv_usec) / 1000;
|
timeDiff += (currentTime.tv_usec - lastEcho.tv_usec) / 1000;
|
||||||
if (timeDiff >= 1000) {
|
if (timeDiff >= 1000) {
|
||||||
printf("\033[2K\rCurrent FPS: %g (%gx)", lastFrames / (timeDiff / 1000.0f), lastFrames / (float) (60 * (timeDiff / 1000.0f)));
|
printf("\033[2K\rCurrent FPS: %g (%gx)", lastFrames / (timeDiff / 1000.0f), lastFrames / (float) (60 * (timeDiff / 1000.0f)));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
lastEcho = currentTime;
|
lastEcho = currentTime;
|
||||||
lastFrames = 0;
|
lastFrames = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCoreSyncWaitFrameEnd(&context->sync);
|
|
||||||
if (duration > 0 && *frames == duration) {
|
if (duration > 0 && *frames == duration) {
|
||||||
_GBAPerfShutdown(0);
|
break;
|
||||||
}
|
|
||||||
if (_dispatchExiting) {
|
|
||||||
mCoreThreadEnd(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
@ -202,11 +213,9 @@ static void _GBAPerfRunloop(struct mCoreThread* context, int* frames, bool quiet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBAPerfShutdown(int signal) {
|
static void _mPerfShutdown(int signal) {
|
||||||
UNUSED(signal);
|
UNUSED(signal);
|
||||||
// This will come in ON the GBA thread, so we have to handle it carefully
|
|
||||||
_dispatchExiting = true;
|
_dispatchExiting = true;
|
||||||
ConditionWake(&_thread->sync.videoFrameAvailableCond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg) {
|
static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg) {
|
||||||
@ -233,8 +242,10 @@ static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* ar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _loadSavestate(struct mCoreThread* context) {
|
static void _log(struct mLogger* log, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||||
context->core->loadState(context->core, _savestate, 0);
|
UNUSED(log);
|
||||||
_savestate->close(_savestate);
|
UNUSED(category);
|
||||||
_savestate = 0;
|
UNUSED(level);
|
||||||
|
UNUSED(format);
|
||||||
|
UNUSED(args);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user