mirror of https://github.com/mgba-emu/mgba.git
Feature: Make thread proxy generic
This commit is contained in:
parent
b8593bdb7b
commit
3b69fb767c
|
@ -16,10 +16,10 @@ CXX_GUARD_START
|
||||||
struct GBAVideoProxyRenderer {
|
struct GBAVideoProxyRenderer {
|
||||||
struct GBAVideoRenderer d;
|
struct GBAVideoRenderer d;
|
||||||
struct GBAVideoRenderer* backend;
|
struct GBAVideoRenderer* backend;
|
||||||
struct mVideoLogger logger;
|
struct mVideoLogger* logger;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend, bool readonly);
|
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend);
|
||||||
void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
||||||
void GBAVideoProxyRendererUnshim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
void GBAVideoProxyRendererUnshim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* 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 <mgba/internal/gba/renderers/thread-proxy.h>
|
#include "thread-proxy.h"
|
||||||
|
|
||||||
#include <mgba/core/tile-cache.h>
|
#include <mgba/core/tile-cache.h>
|
||||||
#include <mgba/internal/gba/gba.h>
|
#include <mgba/internal/gba/gba.h>
|
||||||
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
|
|
||||||
static void GBAVideoThreadProxyRendererInit(struct mVideoLogger* logger);
|
static void mVideoThreadProxyInit(struct mVideoLogger* logger);
|
||||||
static void GBAVideoThreadProxyRendererReset(struct mVideoLogger* logger);
|
static void mVideoThreadProxyReset(struct mVideoLogger* logger);
|
||||||
static void GBAVideoThreadProxyRendererDeinit(struct mVideoLogger* logger);
|
static void mVideoThreadProxyDeinit(struct mVideoLogger* logger);
|
||||||
|
|
||||||
static THREAD_ENTRY _proxyThread(void* renderer);
|
static THREAD_ENTRY _proxyThread(void* renderer);
|
||||||
|
|
||||||
|
@ -25,25 +25,25 @@ static void _unlock(struct mVideoLogger* logger);
|
||||||
static void _wait(struct mVideoLogger* logger);
|
static void _wait(struct mVideoLogger* logger);
|
||||||
static void _wake(struct mVideoLogger* logger, int y);
|
static void _wake(struct mVideoLogger* logger, int y);
|
||||||
|
|
||||||
void GBAVideoThreadProxyRendererCreate(struct GBAVideoThreadProxyRenderer* renderer, struct GBAVideoRenderer* backend) {
|
void mVideoThreadProxyCreate(struct mVideoThreadProxy* renderer) {
|
||||||
renderer->d.logger.block = true;
|
mVideoLoggerRendererCreate(&renderer->d, false);
|
||||||
GBAVideoProxyRendererCreate(&renderer->d, backend, false);
|
renderer->d.block = true;
|
||||||
|
|
||||||
renderer->d.logger.init = GBAVideoThreadProxyRendererInit;
|
renderer->d.init = mVideoThreadProxyInit;
|
||||||
renderer->d.logger.reset = GBAVideoThreadProxyRendererReset;
|
renderer->d.reset = mVideoThreadProxyReset;
|
||||||
renderer->d.logger.deinit = GBAVideoThreadProxyRendererDeinit;
|
renderer->d.deinit = mVideoThreadProxyDeinit;
|
||||||
renderer->d.logger.lock = _lock;
|
renderer->d.lock = _lock;
|
||||||
renderer->d.logger.unlock = _unlock;
|
renderer->d.unlock = _unlock;
|
||||||
renderer->d.logger.wait = _wait;
|
renderer->d.wait = _wait;
|
||||||
renderer->d.logger.wake = _wake;
|
renderer->d.wake = _wake;
|
||||||
|
|
||||||
renderer->d.logger.writeData = _writeData;
|
renderer->d.writeData = _writeData;
|
||||||
renderer->d.logger.readData = _readData;
|
renderer->d.readData = _readData;
|
||||||
renderer->d.logger.vf = NULL;
|
renderer->d.vf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoThreadProxyRendererInit(struct mVideoLogger* logger) {
|
void mVideoThreadProxyInit(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
ConditionInit(&proxyRenderer->fromThreadCond);
|
ConditionInit(&proxyRenderer->fromThreadCond);
|
||||||
ConditionInit(&proxyRenderer->toThreadCond);
|
ConditionInit(&proxyRenderer->toThreadCond);
|
||||||
MutexInit(&proxyRenderer->mutex);
|
MutexInit(&proxyRenderer->mutex);
|
||||||
|
@ -53,8 +53,8 @@ void GBAVideoThreadProxyRendererInit(struct mVideoLogger* logger) {
|
||||||
ThreadCreate(&proxyRenderer->thread, _proxyThread, proxyRenderer);
|
ThreadCreate(&proxyRenderer->thread, _proxyThread, proxyRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoThreadProxyRendererReset(struct mVideoLogger* logger) {
|
void mVideoThreadProxyReset(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
while (proxyRenderer->threadState == PROXY_THREAD_BUSY) {
|
while (proxyRenderer->threadState == PROXY_THREAD_BUSY) {
|
||||||
ConditionWake(&proxyRenderer->toThreadCond);
|
ConditionWake(&proxyRenderer->toThreadCond);
|
||||||
|
@ -63,8 +63,8 @@ void GBAVideoThreadProxyRendererReset(struct mVideoLogger* logger) {
|
||||||
MutexUnlock(&proxyRenderer->mutex);
|
MutexUnlock(&proxyRenderer->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoThreadProxyRendererDeinit(struct mVideoLogger* logger) {
|
void mVideoThreadProxyDeinit(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
bool waiting = false;
|
bool waiting = false;
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
while (proxyRenderer->threadState == PROXY_THREAD_BUSY) {
|
while (proxyRenderer->threadState == PROXY_THREAD_BUSY) {
|
||||||
|
@ -85,7 +85,7 @@ void GBAVideoThreadProxyRendererDeinit(struct mVideoLogger* logger) {
|
||||||
MutexDeinit(&proxyRenderer->mutex);
|
MutexDeinit(&proxyRenderer->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _proxyThreadRecover(struct GBAVideoThreadProxyRenderer* proxyRenderer) {
|
void _proxyThreadRecover(struct mVideoThreadProxy* proxyRenderer) {
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
if (proxyRenderer->threadState != PROXY_THREAD_STOPPED) {
|
if (proxyRenderer->threadState != PROXY_THREAD_STOPPED) {
|
||||||
MutexUnlock(&proxyRenderer->mutex);
|
MutexUnlock(&proxyRenderer->mutex);
|
||||||
|
@ -99,7 +99,7 @@ void _proxyThreadRecover(struct GBAVideoThreadProxyRenderer* proxyRenderer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _writeData(struct mVideoLogger* logger, const void* data, size_t length) {
|
static bool _writeData(struct mVideoLogger* logger, const void* data, size_t length) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
while (!RingFIFOWrite(&proxyRenderer->dirtyQueue, data, length)) {
|
while (!RingFIFOWrite(&proxyRenderer->dirtyQueue, data, length)) {
|
||||||
mLOG(GBA_VIDEO, DEBUG, "Can't write %"PRIz"u bytes. Proxy thread asleep?", length);
|
mLOG(GBA_VIDEO, DEBUG, "Can't write %"PRIz"u bytes. Proxy thread asleep?", length);
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
|
@ -116,7 +116,7 @@ static bool _writeData(struct mVideoLogger* logger, const void* data, size_t len
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _readData(struct mVideoLogger* logger, void* data, size_t length, bool block) {
|
static bool _readData(struct mVideoLogger* logger, void* data, size_t length, bool block) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
bool read = false;
|
bool read = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
read = RingFIFORead(&proxyRenderer->dirtyQueue, data, length);
|
read = RingFIFORead(&proxyRenderer->dirtyQueue, data, length);
|
||||||
|
@ -133,12 +133,12 @@ static bool _readData(struct mVideoLogger* logger, void* data, size_t length, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _lock(struct mVideoLogger* logger) {
|
static void _lock(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _wait(struct mVideoLogger* logger) {
|
static void _wait(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
if (proxyRenderer->threadState == PROXY_THREAD_STOPPED) {
|
if (proxyRenderer->threadState == PROXY_THREAD_STOPPED) {
|
||||||
mLOG(GBA_VIDEO, ERROR, "Proxy thread stopped prematurely!");
|
mLOG(GBA_VIDEO, ERROR, "Proxy thread stopped prematurely!");
|
||||||
_proxyThreadRecover(proxyRenderer);
|
_proxyThreadRecover(proxyRenderer);
|
||||||
|
@ -151,19 +151,19 @@ static void _wait(struct mVideoLogger* logger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _unlock(struct mVideoLogger* logger) {
|
static void _unlock(struct mVideoLogger* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
MutexUnlock(&proxyRenderer->mutex);
|
MutexUnlock(&proxyRenderer->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _wake(struct mVideoLogger* logger, int y) {
|
static void _wake(struct mVideoLogger* logger, int y) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = logger->context;
|
struct mVideoThreadProxy* proxyRenderer = (struct mVideoThreadProxy*) logger;
|
||||||
if ((y & 15) == 15) {
|
if ((y & 15) == 15) {
|
||||||
ConditionWake(&proxyRenderer->toThreadCond);
|
ConditionWake(&proxyRenderer->toThreadCond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static THREAD_ENTRY _proxyThread(void* renderer) {
|
static THREAD_ENTRY _proxyThread(void* logger) {
|
||||||
struct GBAVideoThreadProxyRenderer* proxyRenderer = renderer;
|
struct mVideoThreadProxy* proxyRenderer = logger;
|
||||||
ThreadSetName("Proxy Renderer Thread");
|
ThreadSetName("Proxy Renderer Thread");
|
||||||
|
|
||||||
MutexLock(&proxyRenderer->mutex);
|
MutexLock(&proxyRenderer->mutex);
|
||||||
|
@ -174,7 +174,7 @@ static THREAD_ENTRY _proxyThread(void* renderer) {
|
||||||
}
|
}
|
||||||
proxyRenderer->threadState = PROXY_THREAD_BUSY;
|
proxyRenderer->threadState = PROXY_THREAD_BUSY;
|
||||||
MutexUnlock(&proxyRenderer->mutex);
|
MutexUnlock(&proxyRenderer->mutex);
|
||||||
if (!mVideoLoggerRendererRun(&proxyRenderer->d.logger, false)) {
|
if (!mVideoLoggerRendererRun(&proxyRenderer->d, false)) {
|
||||||
// FIFO was corrupted
|
// FIFO was corrupted
|
||||||
proxyRenderer->threadState = PROXY_THREAD_STOPPED;
|
proxyRenderer->threadState = PROXY_THREAD_STOPPED;
|
||||||
mLOG(GBA_VIDEO, ERROR, "Proxy thread queue got corrupted!");
|
mLOG(GBA_VIDEO, ERROR, "Proxy thread queue got corrupted!");
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2013-2015 Jeffrey Pfau
|
/* Copyright (c) 2013-2017 Jeffrey Pfau
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
@ -11,29 +11,29 @@
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
#include <mgba/internal/gba/video.h>
|
#include <mgba/internal/gba/video.h>
|
||||||
#include <mgba/internal/gba/renderers/proxy.h>
|
#include "video-logger.h"
|
||||||
#include <mgba-util/threading.h>
|
#include <mgba-util/threading.h>
|
||||||
#include <mgba-util/ring-fifo.h>
|
#include <mgba-util/ring-fifo.h>
|
||||||
|
|
||||||
enum GBAVideoThreadProxyState {
|
enum mVideoThreadProxyState {
|
||||||
PROXY_THREAD_STOPPED = 0,
|
PROXY_THREAD_STOPPED = 0,
|
||||||
PROXY_THREAD_IDLE,
|
PROXY_THREAD_IDLE,
|
||||||
PROXY_THREAD_BUSY
|
PROXY_THREAD_BUSY
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GBAVideoThreadProxyRenderer {
|
struct mVideoThreadProxy {
|
||||||
struct GBAVideoProxyRenderer d;
|
struct mVideoLogger d;
|
||||||
|
|
||||||
Thread thread;
|
Thread thread;
|
||||||
Condition fromThreadCond;
|
Condition fromThreadCond;
|
||||||
Condition toThreadCond;
|
Condition toThreadCond;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
enum GBAVideoThreadProxyState threadState;
|
enum mVideoThreadProxyState threadState;
|
||||||
|
|
||||||
struct RingFIFO dirtyQueue;
|
struct RingFIFO dirtyQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBAVideoThreadProxyRendererCreate(struct GBAVideoThreadProxyRenderer* renderer, struct GBAVideoRenderer* backend);
|
void mVideoThreadProxyCreate(struct mVideoThreadProxy* renderer);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
#include <mgba/internal/gba/extra/cli.h>
|
#include <mgba/internal/gba/extra/cli.h>
|
||||||
#include <mgba/internal/gba/overrides.h>
|
#include <mgba/internal/gba/overrides.h>
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
#include <mgba/internal/gba/renderers/thread-proxy.h>
|
#include "feature/thread-proxy.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include <mgba/internal/gba/renderers/proxy.h>
|
||||||
#include <mgba/internal/gba/renderers/video-software.h>
|
#include <mgba/internal/gba/renderers/video-software.h>
|
||||||
#include <mgba/internal/gba/savedata.h>
|
#include <mgba/internal/gba/savedata.h>
|
||||||
#include <mgba/internal/gba/serialize.h>
|
#include <mgba/internal/gba/serialize.h>
|
||||||
|
@ -43,11 +44,11 @@ const static struct mCoreChannelInfo _GBAAudioChannels[] = {
|
||||||
struct GBACore {
|
struct GBACore {
|
||||||
struct mCore d;
|
struct mCore d;
|
||||||
struct GBAVideoSoftwareRenderer renderer;
|
struct GBAVideoSoftwareRenderer renderer;
|
||||||
struct GBAVideoProxyRenderer logProxy;
|
struct GBAVideoProxyRenderer proxyRenderer;
|
||||||
struct mVideoLogContext* logContext;
|
struct mVideoLogContext* logContext;
|
||||||
struct mCoreCallbacks logCallbacks;
|
struct mCoreCallbacks logCallbacks;
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
struct GBAVideoThreadProxyRenderer threadProxy;
|
struct mVideoThreadProxy threadProxy;
|
||||||
int threadedVideo;
|
int threadedVideo;
|
||||||
#endif
|
#endif
|
||||||
int keys;
|
int keys;
|
||||||
|
@ -88,8 +89,9 @@ static bool _GBACoreInit(struct mCore* core) {
|
||||||
|
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
gbacore->threadedVideo = false;
|
gbacore->threadedVideo = false;
|
||||||
GBAVideoThreadProxyRendererCreate(&gbacore->threadProxy, &gbacore->renderer.d);
|
mVideoThreadProxyCreate(&gbacore->threadProxy);
|
||||||
#endif
|
#endif
|
||||||
|
gbacore->proxyRenderer.logger = NULL;
|
||||||
|
|
||||||
gbacore->keys = 0;
|
gbacore->keys = 0;
|
||||||
gba->keySource = &gbacore->keys;
|
gba->keySource = &gbacore->keys;
|
||||||
|
@ -295,7 +297,9 @@ static void _GBACoreReset(struct mCore* core) {
|
||||||
struct GBAVideoRenderer* renderer = &gbacore->renderer.d;
|
struct GBAVideoRenderer* renderer = &gbacore->renderer.d;
|
||||||
#ifndef DISABLE_THREADING
|
#ifndef DISABLE_THREADING
|
||||||
if (gbacore->threadedVideo) {
|
if (gbacore->threadedVideo) {
|
||||||
renderer = &gbacore->threadProxy.d.d;
|
gbacore->proxyRenderer.logger = &gbacore->threadProxy.d;
|
||||||
|
GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, renderer);
|
||||||
|
renderer = &gbacore->proxyRenderer.d;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
GBAVideoAssociateRenderer(&gba->video, renderer);
|
GBAVideoAssociateRenderer(&gba->video, renderer);
|
||||||
|
@ -656,8 +660,6 @@ static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* c
|
||||||
struct GBA* gba = core->board;
|
struct GBA* gba = core->board;
|
||||||
gbacore->logContext = context;
|
gbacore->logContext = context;
|
||||||
|
|
||||||
GBAVideoProxyRendererCreate(&gbacore->logProxy, gba->video.renderer, false);
|
|
||||||
|
|
||||||
context->initialStateSize = core->stateSize(core);
|
context->initialStateSize = core->stateSize(core);
|
||||||
context->initialState = anonymousMemoryMap(context->initialStateSize);
|
context->initialState = anonymousMemoryMap(context->initialStateSize);
|
||||||
core->saveState(core, context->initialState);
|
core->saveState(core, context->initialState);
|
||||||
|
@ -671,16 +673,22 @@ static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* c
|
||||||
context->channels[0].initialStateSize = 0;
|
context->channels[0].initialStateSize = 0;
|
||||||
context->channels[0].channelData = vf;
|
context->channels[0].channelData = vf;
|
||||||
context->channels[0].type = 0;
|
context->channels[0].type = 0;
|
||||||
gbacore->logProxy.logger.vf = vf;
|
gbacore->proxyRenderer.logger = malloc(sizeof(struct mVideoLogger));
|
||||||
gbacore->logProxy.logger.block = false;
|
mVideoLoggerRendererCreate(gbacore->proxyRenderer.logger, false);
|
||||||
|
|
||||||
GBAVideoProxyRendererShim(&gba->video, &gbacore->logProxy);
|
gbacore->proxyRenderer.logger->vf = vf;
|
||||||
|
gbacore->proxyRenderer.logger->block = false;
|
||||||
|
|
||||||
|
GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, &gbacore->renderer.d);
|
||||||
|
GBAVideoProxyRendererShim(&gba->video, &gbacore->proxyRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBACoreEndVideoLog(struct mCore* core) {
|
static void _GBACoreEndVideoLog(struct mCore* core) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
struct GBA* gba = core->board;
|
struct GBA* gba = core->board;
|
||||||
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->logProxy);
|
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->proxyRenderer);
|
||||||
|
free(gbacore->proxyRenderer.logger);
|
||||||
|
gbacore->proxyRenderer.logger = NULL;
|
||||||
|
|
||||||
mappedMemoryFree(gbacore->logContext->initialState, gbacore->logContext->initialStateSize);
|
mappedMemoryFree(gbacore->logContext->initialState, gbacore->logContext->initialStateSize);
|
||||||
gbacore->logContext->channels[0].channelData->close(gbacore->logContext->channels[0].channelData);
|
gbacore->logContext->channels[0].channelData->close(gbacore->logContext->channels[0].channelData);
|
||||||
|
@ -769,11 +777,11 @@ static void _GBAVLPStartFrameCallback(void *context) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
struct GBA* gba = core->board;
|
struct GBA* gba = core->board;
|
||||||
|
|
||||||
if (!mVideoLoggerRendererRun(&gbacore->logProxy.logger, true)) {
|
if (!mVideoLoggerRendererRun(gbacore->proxyRenderer.logger, true)) {
|
||||||
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->logProxy);
|
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->proxyRenderer);
|
||||||
gbacore->logProxy.logger.vf->seek(gbacore->logProxy.logger.vf, 0, SEEK_SET);
|
gbacore->proxyRenderer.logger->vf->seek(gbacore->proxyRenderer.logger->vf, 0, SEEK_SET);
|
||||||
core->loadState(core, gbacore->logContext->initialState);
|
core->loadState(core, gbacore->logContext->initialState);
|
||||||
GBAVideoProxyRendererShim(&gba->video, &gbacore->logProxy);
|
GBAVideoProxyRendererShim(&gba->video, &gbacore->proxyRenderer);
|
||||||
|
|
||||||
// Make sure CPU loop never spins
|
// Make sure CPU loop never spins
|
||||||
GBAHalt(gba);
|
GBAHalt(gba);
|
||||||
|
@ -784,15 +792,17 @@ static void _GBAVLPStartFrameCallback(void *context) {
|
||||||
|
|
||||||
static bool _GBAVLPInit(struct mCore* core) {
|
static bool _GBAVLPInit(struct mCore* core) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
GBAVideoProxyRendererCreate(&gbacore->logProxy, NULL, true);
|
if (!_GBACoreInit(core)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gbacore->proxyRenderer.logger = malloc(sizeof(struct mVideoLogger));
|
||||||
|
mVideoLoggerRendererCreate(gbacore->proxyRenderer.logger, true);
|
||||||
|
GBAVideoProxyRendererCreate(&gbacore->proxyRenderer, NULL);
|
||||||
memset(&gbacore->logCallbacks, 0, sizeof(gbacore->logCallbacks));
|
memset(&gbacore->logCallbacks, 0, sizeof(gbacore->logCallbacks));
|
||||||
gbacore->logCallbacks.videoFrameStarted = _GBAVLPStartFrameCallback;
|
gbacore->logCallbacks.videoFrameStarted = _GBAVLPStartFrameCallback;
|
||||||
gbacore->logCallbacks.context = core;
|
gbacore->logCallbacks.context = core;
|
||||||
if (_GBACoreInit(core)) {
|
core->addCoreCallbacks(core, &gbacore->logCallbacks);
|
||||||
core->addCoreCallbacks(core, &gbacore->logCallbacks);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _GBAVLPDeinit(struct mCore* core) {
|
static void _GBAVLPDeinit(struct mCore* core) {
|
||||||
|
@ -806,17 +816,17 @@ static void _GBAVLPDeinit(struct mCore* core) {
|
||||||
static void _GBAVLPReset(struct mCore* core) {
|
static void _GBAVLPReset(struct mCore* core) {
|
||||||
struct GBACore* gbacore = (struct GBACore*) core;
|
struct GBACore* gbacore = (struct GBACore*) core;
|
||||||
struct GBA* gba = (struct GBA*) core->board;
|
struct GBA* gba = (struct GBA*) core->board;
|
||||||
if (gba->video.renderer == &gbacore->logProxy.d) {
|
if (gba->video.renderer == &gbacore->proxyRenderer.d) {
|
||||||
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->logProxy);
|
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->proxyRenderer);
|
||||||
} else if (gbacore->renderer.outputBuffer) {
|
} else if (gbacore->renderer.outputBuffer) {
|
||||||
struct GBAVideoRenderer* renderer = &gbacore->renderer.d;
|
struct GBAVideoRenderer* renderer = &gbacore->renderer.d;
|
||||||
GBAVideoAssociateRenderer(&gba->video, renderer);
|
GBAVideoAssociateRenderer(&gba->video, renderer);
|
||||||
}
|
}
|
||||||
gbacore->logProxy.logger.vf->seek(gbacore->logProxy.logger.vf, 0, SEEK_SET);
|
gbacore->proxyRenderer.logger->vf->seek(gbacore->proxyRenderer.logger->vf, 0, SEEK_SET);
|
||||||
|
|
||||||
ARMReset(core->cpu);
|
ARMReset(core->cpu);
|
||||||
core->loadState(core, gbacore->logContext->initialState);
|
core->loadState(core, gbacore->logContext->initialState);
|
||||||
GBAVideoProxyRendererShim(&gba->video, &gbacore->logProxy);
|
GBAVideoProxyRendererShim(&gba->video, &gbacore->proxyRenderer);
|
||||||
|
|
||||||
// Make sure CPU loop never spins
|
// Make sure CPU loop never spins
|
||||||
GBAHalt(gba);
|
GBAHalt(gba);
|
||||||
|
@ -832,7 +842,7 @@ static bool _GBAVLPLoadROM(struct mCore* core, struct VFile* vf) {
|
||||||
gbacore->logContext = NULL;
|
gbacore->logContext = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
gbacore->logProxy.logger.vf = gbacore->logContext->channels[0].channelData;
|
gbacore->proxyRenderer.logger->vf = gbacore->logContext->channels[0].channelData;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,7 @@ static void GBAVideoProxyRendererPutPixels(struct GBAVideoRenderer* renderer, si
|
||||||
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet);
|
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* packet);
|
||||||
static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address);
|
static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address);
|
||||||
|
|
||||||
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend, bool readonly) {
|
void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend) {
|
||||||
mVideoLoggerRendererCreate(&renderer->logger, readonly);
|
|
||||||
|
|
||||||
renderer->d.init = GBAVideoProxyRendererInit;
|
renderer->d.init = GBAVideoProxyRendererInit;
|
||||||
renderer->d.reset = GBAVideoProxyRendererReset;
|
renderer->d.reset = GBAVideoProxyRendererReset;
|
||||||
renderer->d.deinit = GBAVideoProxyRendererDeinit;
|
renderer->d.deinit = GBAVideoProxyRendererDeinit;
|
||||||
|
@ -45,33 +43,33 @@ void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct
|
||||||
renderer->d.disableBG[3] = false;
|
renderer->d.disableBG[3] = false;
|
||||||
renderer->d.disableOBJ = false;
|
renderer->d.disableOBJ = false;
|
||||||
|
|
||||||
renderer->logger.context = renderer;
|
renderer->logger->context = renderer;
|
||||||
renderer->logger.parsePacket = _parsePacket;
|
renderer->logger->parsePacket = _parsePacket;
|
||||||
renderer->logger.vramBlock = _vramBlock;
|
renderer->logger->vramBlock = _vramBlock;
|
||||||
renderer->logger.paletteSize = SIZE_PALETTE_RAM;
|
renderer->logger->paletteSize = SIZE_PALETTE_RAM;
|
||||||
renderer->logger.vramSize = SIZE_VRAM;
|
renderer->logger->vramSize = SIZE_VRAM;
|
||||||
renderer->logger.oamSize = SIZE_OAM;
|
renderer->logger->oamSize = SIZE_OAM;
|
||||||
|
|
||||||
renderer->backend = backend;
|
renderer->backend = backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _init(struct GBAVideoProxyRenderer* proxyRenderer) {
|
static void _init(struct GBAVideoProxyRenderer* proxyRenderer) {
|
||||||
mVideoLoggerRendererInit(&proxyRenderer->logger);
|
mVideoLoggerRendererInit(proxyRenderer->logger);
|
||||||
|
|
||||||
if (proxyRenderer->logger.block) {
|
if (proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->palette = proxyRenderer->logger.palette;
|
proxyRenderer->backend->palette = proxyRenderer->logger->palette;
|
||||||
proxyRenderer->backend->vram = proxyRenderer->logger.vram;
|
proxyRenderer->backend->vram = proxyRenderer->logger->vram;
|
||||||
proxyRenderer->backend->oam = (union GBAOAM*) proxyRenderer->logger.oam;
|
proxyRenderer->backend->oam = (union GBAOAM*) proxyRenderer->logger->oam;
|
||||||
proxyRenderer->backend->cache = NULL;
|
proxyRenderer->backend->cache = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _reset(struct GBAVideoProxyRenderer* proxyRenderer) {
|
static void _reset(struct GBAVideoProxyRenderer* proxyRenderer) {
|
||||||
memcpy(proxyRenderer->logger.oam, &proxyRenderer->d.oam->raw, SIZE_OAM);
|
memcpy(proxyRenderer->logger->oam, &proxyRenderer->d.oam->raw, SIZE_OAM);
|
||||||
memcpy(proxyRenderer->logger.palette, proxyRenderer->d.palette, SIZE_PALETTE_RAM);
|
memcpy(proxyRenderer->logger->palette, proxyRenderer->d.palette, SIZE_PALETTE_RAM);
|
||||||
memcpy(proxyRenderer->logger.vram, proxyRenderer->d.vram, SIZE_VRAM);
|
memcpy(proxyRenderer->logger->vram, proxyRenderer->d.vram, SIZE_VRAM);
|
||||||
|
|
||||||
mVideoLoggerRendererReset(&proxyRenderer->logger);
|
mVideoLoggerRendererReset(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer) {
|
void GBAVideoProxyRendererShim(struct GBAVideo* video, struct GBAVideoProxyRenderer* renderer) {
|
||||||
|
@ -98,7 +96,7 @@ void GBAVideoProxyRendererUnshim(struct GBAVideo* video, struct GBAVideoProxyRen
|
||||||
renderer->backend->vram = video->vram;
|
renderer->backend->vram = video->vram;
|
||||||
renderer->backend->oam = &video->oam;
|
renderer->backend->oam = &video->oam;
|
||||||
|
|
||||||
mVideoLoggerRendererDeinit(&renderer->logger);
|
mVideoLoggerRendererDeinit(renderer->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoProxyRendererInit(struct GBAVideoRenderer* renderer) {
|
void GBAVideoProxyRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
|
@ -122,7 +120,7 @@ void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) {
|
||||||
|
|
||||||
proxyRenderer->backend->deinit(proxyRenderer->backend);
|
proxyRenderer->backend->deinit(proxyRenderer->backend);
|
||||||
|
|
||||||
mVideoLoggerRendererDeinit(&proxyRenderer->logger);
|
mVideoLoggerRendererDeinit(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
|
static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerDirtyInfo* item) {
|
||||||
|
@ -183,8 +181,8 @@ uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* render
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
mVideoLoggerRendererWriteVideoRegister(&proxyRenderer->logger, address, value);
|
mVideoLoggerRendererWriteVideoRegister(proxyRenderer->logger, address, value);
|
||||||
if (!proxyRenderer->logger.block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, address, value);
|
proxyRenderer->backend->writeVideoRegister(proxyRenderer->backend, address, value);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
@ -192,8 +190,8 @@ uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* render
|
||||||
|
|
||||||
void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
|
void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
mVideoLoggerRendererWriteVRAM(&proxyRenderer->logger, address);
|
mVideoLoggerRendererWriteVRAM(proxyRenderer->logger, address);
|
||||||
if (!proxyRenderer->logger.block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address);
|
proxyRenderer->backend->writeVRAM(proxyRenderer->backend, address);
|
||||||
}
|
}
|
||||||
if (renderer->cache) {
|
if (renderer->cache) {
|
||||||
|
@ -203,8 +201,8 @@ void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t
|
||||||
|
|
||||||
void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
|
void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
mVideoLoggerRendererWritePalette(&proxyRenderer->logger, address, value);
|
mVideoLoggerRendererWritePalette(proxyRenderer->logger, address, value);
|
||||||
if (!proxyRenderer->logger.block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value);
|
proxyRenderer->backend->writePalette(proxyRenderer->backend, address, value);
|
||||||
}
|
}
|
||||||
if (renderer->cache) {
|
if (renderer->cache) {
|
||||||
|
@ -214,59 +212,59 @@ void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32
|
||||||
|
|
||||||
void GBAVideoProxyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam) {
|
void GBAVideoProxyRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
if (!proxyRenderer->logger.block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->writeOAM(proxyRenderer->backend, oam);
|
proxyRenderer->backend->writeOAM(proxyRenderer->backend, oam);
|
||||||
}
|
}
|
||||||
mVideoLoggerRendererWriteOAM(&proxyRenderer->logger, oam, proxyRenderer->d.oam->raw[oam]);
|
mVideoLoggerRendererWriteOAM(proxyRenderer->logger, oam, proxyRenderer->d.oam->raw[oam]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
|
void GBAVideoProxyRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
if (!proxyRenderer->logger.block) {
|
if (!proxyRenderer->logger->block) {
|
||||||
proxyRenderer->backend->drawScanline(proxyRenderer->backend, y);
|
proxyRenderer->backend->drawScanline(proxyRenderer->backend, y);
|
||||||
}
|
}
|
||||||
mVideoLoggerRendererDrawScanline(&proxyRenderer->logger, y);
|
mVideoLoggerRendererDrawScanline(proxyRenderer->logger, y);
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wake) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wake) {
|
||||||
proxyRenderer->logger.wake(&proxyRenderer->logger, y);
|
proxyRenderer->logger->wake(proxyRenderer->logger, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
void GBAVideoProxyRendererFinishFrame(struct GBAVideoRenderer* renderer) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.lock(&proxyRenderer->logger);
|
proxyRenderer->logger->lock(proxyRenderer->logger);
|
||||||
proxyRenderer->logger.wait(&proxyRenderer->logger);
|
proxyRenderer->logger->wait(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
mVideoLoggerRendererFlush(&proxyRenderer->logger);
|
mVideoLoggerRendererFlush(proxyRenderer->logger);
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.unlock(&proxyRenderer->logger);
|
proxyRenderer->logger->unlock(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) {
|
static void GBAVideoProxyRendererGetPixels(struct GBAVideoRenderer* renderer, size_t* stride, const void** pixels) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.lock(&proxyRenderer->logger);
|
proxyRenderer->logger->lock(proxyRenderer->logger);
|
||||||
// Insert an extra item into the queue to make sure it gets flushed
|
// Insert an extra item into the queue to make sure it gets flushed
|
||||||
mVideoLoggerRendererFlush(&proxyRenderer->logger);
|
mVideoLoggerRendererFlush(proxyRenderer->logger);
|
||||||
proxyRenderer->logger.wait(&proxyRenderer->logger);
|
proxyRenderer->logger->wait(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
|
proxyRenderer->backend->getPixels(proxyRenderer->backend, stride, pixels);
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.unlock(&proxyRenderer->logger);
|
proxyRenderer->logger->unlock(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GBAVideoProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) {
|
static void GBAVideoProxyRendererPutPixels(struct GBAVideoRenderer* renderer, size_t stride, const void* pixels) {
|
||||||
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.lock(&proxyRenderer->logger);
|
proxyRenderer->logger->lock(proxyRenderer->logger);
|
||||||
// Insert an extra item into the queue to make sure it gets flushed
|
// Insert an extra item into the queue to make sure it gets flushed
|
||||||
mVideoLoggerRendererFlush(&proxyRenderer->logger);
|
mVideoLoggerRendererFlush(proxyRenderer->logger);
|
||||||
proxyRenderer->logger.wait(&proxyRenderer->logger);
|
proxyRenderer->logger->wait(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
proxyRenderer->backend->putPixels(proxyRenderer->backend, stride, pixels);
|
proxyRenderer->backend->putPixels(proxyRenderer->backend, stride, pixels);
|
||||||
if (proxyRenderer->logger.block && proxyRenderer->logger.wait) {
|
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
|
||||||
proxyRenderer->logger.unlock(&proxyRenderer->logger);
|
proxyRenderer->logger->unlock(proxyRenderer->logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue