diff --git a/CMakeLists.txt b/CMakeLists.txt index e23aff055..00b215cbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,5 +40,9 @@ else() include_directories(${SDL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) endif() +if(BUILD_PERF) + set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/perf-main.c) +endif() + add_executable(${BINARY_NAME} ${ARM_SRC} ${GBA_SRC} ${DEBUGGER_SRC} ${RENDERER_SRC} ${UTIL_SRC} ${PLATFORM_SRC} ${MAIN_SRC}) target_link_libraries(${BINARY_NAME} m pthread ${DEBUGGER_LIB} ${SDL_LIBRARY} ${OPENGL_LIBRARY}) diff --git a/src/platform/perf-main.c b/src/platform/perf-main.c new file mode 100644 index 000000000..dde8f65f5 --- /dev/null +++ b/src/platform/perf-main.c @@ -0,0 +1,77 @@ +#include "gba-thread.h" +#include "gba.h" +#include "renderers/video-software.h" + +#include +#include +#include +#include +#include +#include + +static void _GBAPerfRunloop(struct GBAThread* context, int* frames); +static void _GBAPerfShutdown(int signal); + +static struct GBAThread* _thread; + +int main(int argc, char** argv) { + const char* fname = "test.rom"; + if (argc > 1) { + fname = argv[1]; + } + int fd = open(fname, O_RDONLY); + if (fd < 0) { + return 1; + } + + signal(SIGINT, _GBAPerfShutdown); + + struct GBAThread context; + struct GBAVideoSoftwareRenderer renderer; + GBAVideoSoftwareRendererCreate(&renderer); + + renderer.outputBuffer = malloc(256 * 256 * 4); + renderer.outputBufferStride = 256; + + context.fd = fd; + context.fname = fname; + context.useDebugger = 0; + context.renderer = &renderer.d; + context.frameskip = 0; + context.sync.videoFrameWait = 0; + context.sync.audioWait = 0; + context.startCallback = 0; + context.cleanCallback = 0; + _thread = &context; + GBAThreadStart(&context); + + int frames = 0; + time_t start = time(0); + _GBAPerfRunloop(&context, &frames); + time_t end = time(0); + int duration = end - start; + + GBAThreadJoin(&context); + close(fd); + + free(renderer.outputBuffer); + + printf("%u frames in %i seconds: %g fps (%gx)\n", frames, duration, frames / (float) duration, frames / (duration * 60.f)); + + return 0; +} + +static void _GBAPerfRunloop(struct GBAThread* context, int* frames) { + while (context->state < THREAD_EXITING) { + if (GBASyncWaitFrameStart(&context->sync, 0)) { + ++*frames; + } + GBASyncWaitFrameEnd(&context->sync); + } +} + +static void _GBAPerfShutdown(int signal) { + pthread_mutex_lock(&_thread->stateMutex); + _thread->state = THREAD_EXITING; + pthread_mutex_unlock(&_thread->stateMutex); +}