mirror of https://github.com/mgba-emu/mgba.git
Core: Video log enhancements
This commit is contained in:
parent
b230b6e0f6
commit
3cce95b287
|
@ -104,6 +104,7 @@ void mVideoLoggerAttachChannel(struct mVideoLogger* logger, struct mVideoLogCont
|
||||||
struct mCore;
|
struct mCore;
|
||||||
struct mVideoLogContext* mVideoLogContextCreate(struct mCore* core);
|
struct mVideoLogContext* mVideoLogContextCreate(struct mCore* core);
|
||||||
|
|
||||||
|
void mVideoLogContextSetCompression(struct mVideoLogContext*, bool enable);
|
||||||
void mVideoLogContextSetOutput(struct mVideoLogContext*, struct VFile*);
|
void mVideoLogContextSetOutput(struct mVideoLogContext*, struct VFile*);
|
||||||
void mVideoLogContextWriteHeader(struct mVideoLogContext*, struct mCore* core);
|
void mVideoLogContextWriteHeader(struct mVideoLogContext*, struct mCore* core);
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ struct mVideoLogContext {
|
||||||
struct mVideoLogChannel channels[mVL_MAX_CHANNELS];
|
struct mVideoLogChannel channels[mVL_MAX_CHANNELS];
|
||||||
|
|
||||||
bool write;
|
bool write;
|
||||||
|
bool compression;
|
||||||
uint32_t activeChannel;
|
uint32_t activeChannel;
|
||||||
struct VFile* backing;
|
struct VFile* backing;
|
||||||
};
|
};
|
||||||
|
@ -465,6 +466,12 @@ struct mVideoLogContext* mVideoLogContextCreate(struct mCore* core) {
|
||||||
context->initialStateSize = 0;
|
context->initialStateSize = 0;
|
||||||
context->initialState = NULL;
|
context->initialState = NULL;
|
||||||
|
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
context->compression = true;
|
||||||
|
#else
|
||||||
|
context->compression = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (core) {
|
if (core) {
|
||||||
context->initialStateSize = core->stateSize(core);
|
context->initialStateSize = core->stateSize(core);
|
||||||
context->initialState = anonymousMemoryMap(context->initialStateSize);
|
context->initialState = anonymousMemoryMap(context->initialStateSize);
|
||||||
|
@ -482,6 +489,10 @@ void mVideoLogContextSetOutput(struct mVideoLogContext* context, struct VFile* v
|
||||||
vf->seek(vf, 0, SEEK_SET);
|
vf->seek(vf, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mVideoLogContextSetCompression(struct mVideoLogContext* context, bool compression) {
|
||||||
|
context->compression = compression;
|
||||||
|
}
|
||||||
|
|
||||||
void mVideoLogContextWriteHeader(struct mVideoLogContext* context, struct mCore* core) {
|
void mVideoLogContextWriteHeader(struct mVideoLogContext* context, struct mCore* core) {
|
||||||
struct mVideoLogHeader header = { { 0 } };
|
struct mVideoLogHeader header = { { 0 } };
|
||||||
memcpy(header.magic, mVL_MAGIC, sizeof(header.magic));
|
memcpy(header.magic, mVL_MAGIC, sizeof(header.magic));
|
||||||
|
@ -499,21 +510,24 @@ void mVideoLogContextWriteHeader(struct mVideoLogContext* context, struct mCore*
|
||||||
struct mVLBlockHeader chheader = { 0 };
|
struct mVLBlockHeader chheader = { 0 };
|
||||||
STORE_32LE(mVL_BLOCK_INITIAL_STATE, 0, &chheader.blockType);
|
STORE_32LE(mVL_BLOCK_INITIAL_STATE, 0, &chheader.blockType);
|
||||||
#ifdef USE_ZLIB
|
#ifdef USE_ZLIB
|
||||||
STORE_32LE(mVL_FLAG_BLOCK_COMPRESSED, 0, &chheader.flags);
|
if (context->compression) {
|
||||||
|
STORE_32LE(mVL_FLAG_BLOCK_COMPRESSED, 0, &chheader.flags);
|
||||||
|
|
||||||
struct VFile* vfm = VFileMemChunk(NULL, 0);
|
struct VFile* vfm = VFileMemChunk(NULL, 0);
|
||||||
struct VFile* src = VFileFromConstMemory(context->initialState, context->initialStateSize);
|
struct VFile* src = VFileFromConstMemory(context->initialState, context->initialStateSize);
|
||||||
_compress(vfm, src);
|
_compress(vfm, src);
|
||||||
src->close(src);
|
src->close(src);
|
||||||
STORE_32LE(vfm->size(vfm), 0, &chheader.length);
|
STORE_32LE(vfm->size(vfm), 0, &chheader.length);
|
||||||
context->backing->write(context->backing, &chheader, sizeof(chheader));
|
context->backing->write(context->backing, &chheader, sizeof(chheader));
|
||||||
_copyVf(context->backing, vfm);
|
_copyVf(context->backing, vfm);
|
||||||
vfm->close(vfm);
|
vfm->close(vfm);
|
||||||
#else
|
} else
|
||||||
STORE_32LE(context->initialStateSize, 0, &chheader.length);
|
|
||||||
context->backing->write(context->backing, &chheader, sizeof(chheader));
|
|
||||||
context->backing->write(context->backing, context->initialState, context->initialStateSize);
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
STORE_32LE(context->initialStateSize, 0, &chheader.length);
|
||||||
|
context->backing->write(context->backing, &chheader, sizeof(chheader));
|
||||||
|
context->backing->write(context->backing, context->initialState, context->initialStateSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -647,9 +661,10 @@ static void _flushBufferCompressed(struct mVideoLogContext* context) {
|
||||||
|
|
||||||
static void _flushBuffer(struct mVideoLogContext* context) {
|
static void _flushBuffer(struct mVideoLogContext* context) {
|
||||||
#ifdef USE_ZLIB
|
#ifdef USE_ZLIB
|
||||||
// TODO: Make optional
|
if (context->compression) {
|
||||||
_flushBufferCompressed(context);
|
_flushBufferCompressed(context);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct CircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
struct CircleBuffer* buffer = &context->channels[context->activeChannel].buffer;
|
||||||
|
|
|
@ -879,9 +879,11 @@ static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* co
|
||||||
static void _GBCoreEndVideoLog(struct mCore* core) {
|
static void _GBCoreEndVideoLog(struct mCore* core) {
|
||||||
struct GBCore* gbcore = (struct GBCore*) core;
|
struct GBCore* gbcore = (struct GBCore*) core;
|
||||||
struct GB* gb = core->board;
|
struct GB* gb = core->board;
|
||||||
GBVideoProxyRendererUnshim(&gb->video, &gbcore->proxyRenderer);
|
if (gbcore->proxyRenderer.logger) {
|
||||||
free(gbcore->proxyRenderer.logger);
|
GBVideoProxyRendererUnshim(&gb->video, &gbcore->proxyRenderer);
|
||||||
gbcore->proxyRenderer.logger = NULL;
|
free(gbcore->proxyRenderer.logger);
|
||||||
|
gbcore->proxyRenderer.logger = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -990,9 +990,11 @@ static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* c
|
||||||
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->proxyRenderer);
|
if (gbacore->proxyRenderer.logger) {
|
||||||
free(gbacore->proxyRenderer.logger);
|
GBAVideoProxyRendererUnshim(&gba->video, &gbacore->proxyRenderer);
|
||||||
gbacore->proxyRenderer.logger = NULL;
|
free(gbacore->proxyRenderer.logger);
|
||||||
|
gbacore->proxyRenderer.logger = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -809,26 +809,39 @@ void CoreController::clearOverride() {
|
||||||
m_override.reset();
|
m_override.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::startVideoLog(const QString& path) {
|
void CoreController::startVideoLog(const QString& path, bool compression) {
|
||||||
if (m_vl) {
|
if (m_vl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VFile* vf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC);
|
||||||
|
if (!vf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startVideoLog(vf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreController::startVideoLog(VFile* vf, bool compression) {
|
||||||
|
if (m_vl || !vf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Interrupter interrupter(this);
|
Interrupter interrupter(this);
|
||||||
m_vl = mVideoLogContextCreate(m_threadContext.core);
|
m_vl = mVideoLogContextCreate(m_threadContext.core);
|
||||||
m_vlVf = VFileDevice::open(path, O_WRONLY | O_CREAT | O_TRUNC);
|
m_vlVf = vf;
|
||||||
mVideoLogContextSetOutput(m_vl, m_vlVf);
|
mVideoLogContextSetOutput(m_vl, m_vlVf);
|
||||||
|
mVideoLogContextSetCompression(m_vl, compression);
|
||||||
mVideoLogContextWriteHeader(m_vl, m_threadContext.core);
|
mVideoLogContextWriteHeader(m_vl, m_threadContext.core);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::endVideoLog() {
|
void CoreController::endVideoLog(bool closeVf) {
|
||||||
if (!m_vl) {
|
if (!m_vl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interrupter interrupter(this);
|
Interrupter interrupter(this);
|
||||||
mVideoLogContextDestroy(m_threadContext.core, m_vl);
|
mVideoLogContextDestroy(m_threadContext.core, m_vl);
|
||||||
if (m_vlVf) {
|
if (m_vlVf && closeVf) {
|
||||||
m_vlVf->close(m_vlVf);
|
m_vlVf->close(m_vlVf);
|
||||||
m_vlVf = nullptr;
|
m_vlVf = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,8 +161,9 @@ public slots:
|
||||||
|
|
||||||
void clearOverride();
|
void clearOverride();
|
||||||
|
|
||||||
void startVideoLog(const QString& path);
|
void startVideoLog(const QString& path, bool compression = true);
|
||||||
void endVideoLog();
|
void startVideoLog(VFile* vf, bool compression = true);
|
||||||
|
void endVideoLog(bool closeVf = true);
|
||||||
|
|
||||||
void setFramebufferHandle(int fb);
|
void setFramebufferHandle(int fb);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue