GBA RR: Add way to play movies from startup

This commit is contained in:
Jeffrey Pfau 2015-03-05 14:10:23 -08:00
parent bb77d278dd
commit f69d9db9d4
8 changed files with 75 additions and 17 deletions

View File

@ -17,6 +17,8 @@ enum {
INVALID_INPUT = 0x8000
};
static void GBAMGMContextDestroy(struct GBARRContext*);
static bool GBAMGMStartPlaying(struct GBARRContext*, bool autorecord);
static void GBAMGMStopPlaying(struct GBARRContext*);
static bool GBAMGMStartRecording(struct GBARRContext*);
@ -56,6 +58,8 @@ static struct VFile* GBAMGMOpenSavestate(struct GBARRContext*, int flags);
void GBAMGMContextCreate(struct GBAMGMContext* mgm) {
memset(mgm, 0, sizeof(*mgm));
mgm->d.destroy = GBAMGMContextDestroy;
mgm->d.startPlaying = GBAMGMStartPlaying;
mgm->d.stopPlaying = GBAMGMStopPlaying;
mgm->d.startRecording = GBAMGMStartRecording;
@ -75,20 +79,11 @@ void GBAMGMContextCreate(struct GBAMGMContext* mgm) {
mgm->d.openSavestate = GBAMGMOpenSavestate;
}
void GBAMGMContextDestroy(struct GBAMGMContext* mgm) {
if (mgm->d.isPlaying(&mgm->d)) {
mgm->d.stopPlaying(&mgm->d);
}
if (mgm->d.isRecording(&mgm->d)) {
mgm->d.stopRecording(&mgm->d);
}
void GBAMGMContextDestroy(struct GBARRContext* rr) {
struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
if (mgm->metadataFile) {
mgm->metadataFile->close(mgm->metadataFile);
}
if (mgm->d.savedata) {
mgm->d.savedata->close(mgm->d.savedata);
mgm->d.savedata = 0;
}
}
bool GBAMGMSetStream(struct GBAMGMContext* mgm, struct VDir* stream) {

View File

@ -75,7 +75,6 @@ struct GBAMGMContext {
};
void GBAMGMContextCreate(struct GBAMGMContext*);
void GBAMGMContextDestroy(struct GBAMGMContext*);
bool GBAMGMSetStream(struct GBAMGMContext* mgm, struct VDir* stream);
bool GBAMGMCreateStream(struct GBAMGMContext* mgm, enum GBARRInitFrom initFrom);

View File

@ -7,7 +7,7 @@
#include "util/vfs.h"
void GBARRSaveState(struct GBA* gba) {
void GBARRInitRecord(struct GBA* gba) {
if (!gba || !gba->rr) {
return;
}
@ -34,7 +34,7 @@ void GBARRSaveState(struct GBA* gba) {
}
}
void GBARRLoadState(struct GBA* gba) {
void GBARRInitPlay(struct GBA* gba) {
if (!gba || !gba->rr) {
return;
}
@ -57,3 +57,17 @@ void GBARRLoadState(struct GBA* gba) {
ARMReset(gba->cpu);
}
}
void GBARRDestroy(struct GBARRContext* rr) {
if (rr->isPlaying(rr)) {
rr->stopPlaying(rr);
}
if (rr->isRecording(rr)) {
rr->stopRecording(rr);
}
if (rr->savedata) {
rr->savedata->close(rr->savedata);
rr->savedata = 0;
}
rr->destroy(rr);
}

View File

@ -20,6 +20,8 @@ enum GBARRInitFrom {
};
struct GBARRContext {
void (*destroy)(struct GBARRContext*);
bool (*startPlaying)(struct GBARRContext*, bool autorecord);
void (*stopPlaying)(struct GBARRContext*);
bool (*startRecording)(struct GBARRContext*);
@ -47,4 +49,9 @@ struct GBARRContext {
struct VFile* savedata;
};
void GBARRDestroy(struct GBARRContext*);
void GBARRInitRecord(struct GBA*);
void GBARRInitPlay(struct GBA*);
#endif

View File

@ -10,6 +10,7 @@
#include "gba/cheats.h"
#include "gba/serialize.h"
#include "gba/supervisor/config.h"
#include "gba/rr/mgm.h"
#include "debugger/debugger.h"
@ -117,6 +118,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
struct GBACheatDevice cheatDevice;
struct GBAThread* threadContext = context;
struct ARMComponent* components[GBA_COMPONENT_MAX] = {};
struct GBARRContext* movie = 0;
int numComponents = GBA_COMPONENT_MAX;
#if !defined(_WIN32) && defined(USE_PTHREADS)
@ -170,7 +172,32 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
}
}
if (threadContext->movie) {
struct VDir* movieDir = VDirOpen(threadContext->movie);
#ifdef ENABLE_LIBZIP
if (!movieDir) {
movieDir = VDirOpenZip(threadContext->movie, 0);
}
#endif
if (movieDir) {
struct GBAMGMContext* mgm = malloc(sizeof(*mgm));
GBAMGMContextCreate(mgm);
if (!GBAMGMSetStream(mgm, movieDir)) {
mgm->d.destroy(&mgm->d);
} else {
movie = &mgm->d;
}
}
}
ARMReset(&cpu);
if (movie) {
gba.rr = movie;
movie->startPlaying(movie, false);
GBARRInitPlay(&gba);
}
if (threadContext->skipBios) {
GBASkipBIOS(&cpu);
}
@ -256,6 +283,11 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
GBACheatDeviceDestroy(&cheatDevice);
}
if (movie) {
movie->destroy(movie);
free(movie);
}
threadContext->sync.videoFrameOn = false;
ConditionWake(&threadContext->sync.videoFrameAvailableCond);
ConditionWake(&threadContext->sync.audioRequiredCond);
@ -309,6 +341,7 @@ void GBAMapArgumentsToContext(const struct GBAArguments* args, struct GBAThread*
threadContext->fname = args->fname;
threadContext->patch = VFileOpen(args->patch, O_RDONLY);
threadContext->cheatsFile = VFileOpen(args->cheatsFile, O_RDONLY);
threadContext->movie = args->movie;
}
bool GBAThreadStart(struct GBAThread* threadContext) {

View File

@ -72,6 +72,7 @@ struct GBAThread {
struct VFile* patch;
struct VFile* cheatsFile;
const char* fname;
const char* movie;
int activeKeys;
struct GBAAVStream* stream;
struct Configuration* overrides;

View File

@ -34,8 +34,8 @@
static const struct option _options[] = {
{ "bios", required_argument, 0, 'b' },
{ "cheats", required_argument, 0, 'c' },
{ "dirmode", required_argument, 0, 'D' },
{ "cheats", required_argument, 0, 'c' },
{ "dirmode", required_argument, 0, 'D' },
{ "frameskip", required_argument, 0, 's' },
#ifdef USE_CLI_DEBUGGER
{ "debug", no_argument, 0, 'd' },
@ -43,6 +43,7 @@ static const struct option _options[] = {
#ifdef USE_GDB_STUB
{ "gdb", no_argument, 0, 'g' },
#endif
{ "movie", required_argument, 0, 'v' },
{ "patch", required_argument, 0, 'p' },
{ 0, 0, 0, 0 }
};
@ -52,7 +53,7 @@ bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int o
bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser) {
int ch;
char options[64] =
"b:c:Dl:p:s:"
"b:c:Dl:p:s:v:"
#ifdef USE_CLI_DEBUGGER
"d"
#endif
@ -101,6 +102,9 @@ bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int arg
case 's':
GBAConfigSetDefaultValue(config, "frameskip", optarg);
break;
case 'v':
opts->movie = strdup(optarg);
break;
default:
if (subparser) {
if (!subparser->parse(subparser, config, ch, optarg)) {
@ -125,6 +129,9 @@ void freeArguments(struct GBAArguments* opts) {
free(opts->patch);
opts->patch = 0;
free(opts->movie);
opts->movie = 0;
}
void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts) {
@ -211,6 +218,7 @@ void usage(const char* arg0, const char* extraOptions) {
#ifdef USE_GDB_STUB
puts(" -g, --gdb Start GDB session (default port 2345)");
#endif
puts(" -v, --movie FILE Play back a movie of recorded input");
puts(" -p, --patch FILE Apply a specified patch file when running");
puts(" -s, --frameskip N Skip every N frames");
if (extraOptions) {

View File

@ -26,6 +26,7 @@ struct GBAArguments {
char* patch;
char* cheatsFile;
bool dirmode;
char* movie;
enum DebuggerType debuggerType;
bool debugAtStart;