From ef3944a4ddf6f36d83de3cb27a7ff8cfb9e9c25e Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 1 Jun 2019 07:01:42 -0700 Subject: [PATCH] Provide callback API for end-of-video-frame --- src/audio/mockingboard.c | 19 ++++++++---- src/audio/mockingboard.h | 1 - src/video/video.c | 63 ++++++++++++++++++++++++++++++++-------- src/video/video.h | 8 +++++ 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/audio/mockingboard.c b/src/audio/mockingboard.c index 17a5a428..16361e1f 100644 --- a/src/audio/mockingboard.c +++ b/src/audio/mockingboard.c @@ -2341,8 +2341,11 @@ void MB_StartOfCpuExecute() } // Called by ContinueExecution() at the end of every video frame -void MB_EndOfVideoFrame() +static void MB_EndOfVideoFrame(uint8_t unused) { +#if 1 // APPLE2IX + (void)unused; +#endif if(g_SoundcardType == CT_Empty) return; #if MB_TRACING @@ -2616,10 +2619,6 @@ static void mb_prefsChanged(const char *domain) { MB_SetVolumeZeroToTen(goesToTen); } -static __attribute__((constructor)) void _init_mockingboard(void) { - prefs_registerListener(PREF_DOMAIN_AUDIO, &mb_prefsChanged); -} - static bool _sy6522_saveState(StateHelper_s *helper, SY6522 *sy6522) { int fd = helper->fd; @@ -3396,3 +3395,13 @@ void mb_traceEnd(void) { } } #endif + +static void _init_mockingboard(void) { + prefs_registerListener(PREF_DOMAIN_AUDIO, &mb_prefsChanged); + static video_frame_callback_fn frameCallback = &MB_EndOfVideoFrame; + video_registerFrameCallback(&frameCallback); +} + +static __attribute__((constructor)) void __init_mockingboard(void) { + emulator_registerStartupCallback(CTOR_PRIORITY_EARLY, &_init_mockingboard); +} diff --git a/src/audio/mockingboard.h b/src/audio/mockingboard.h index e484b25d..667a2186 100644 --- a/src/audio/mockingboard.h +++ b/src/audio/mockingboard.h @@ -105,7 +105,6 @@ void MB_InitializeIO(char *pCxRomPeripheral, unsigned int uSlot4, unsigned in void MB_Mute(void); void MB_Demute(void); void MB_StartOfCpuExecute(void); -void MB_EndOfVideoFrame(void); void MB_UpdateCycles(void); SS_CARDTYPE MB_GetSoundcardType(void); void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType); diff --git a/src/video/video.c b/src/video/video.c index f130a9b1..d4c3d57c 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -11,6 +11,11 @@ #include "common.h" +typedef struct eof_node_s { + struct eof_node_s *next; + video_frame_callback_fn *cbPtr; +} eof_node_s; + typedef struct backend_node_s { struct backend_node_s *next; long order; @@ -19,10 +24,12 @@ typedef struct backend_node_s { static bool video_initialized = false; static bool null_backend_running = true; -static backend_node_s *head = NULL; +static backend_node_s *backends = NULL; static video_backend_s *currentBackend = NULL; static pthread_t render_thread_id = 0; +static eof_node_s *eofs = NULL; + static unsigned int cyclesFrameLast = 0; static unsigned int cyclesDirty = CYCLES_FRAME; static unsigned long dirty = 0UL; @@ -279,9 +286,10 @@ static void _endOfFrame() { cyclesFrameLast %= CYCLES_FRAME; cycles_video_frame %= CYCLES_FRAME; - static uint8_t textFlashCounter = 0; + // FLASH counter and keyboard auto-strobe mod-16 counter ... + static uint8_t textFlashCounter = 0x0; textFlashCounter = (textFlashCounter+1) & 0xf; - if (!textFlashCounter) { + if (textFlashCounter == 0x0) { video_flashText(); if (!(run_args.softswitches & SS_80COL) && (run_args.softswitches & (SS_TEXT|SS_MIXED))) { cyclesFrameLast = 0; @@ -290,11 +298,17 @@ static void _endOfFrame() { } } - // TODO FIXME : modularize these (and moar) handlers for video frame completion - MB_EndOfVideoFrame(); + // run frame completion callbacks ... + eof_node_s *p = eofs; + while (p) { + video_frame_callback_fn cb = *(p->cbPtr); + if (cb) { + cb(textFlashCounter); + } + p = p->next; + } - // UtAIIe 3-17 : - // - keyboard auto-repeat ... + // Also MAYBE TODO UtAIIe 3-17 : // - power-up reset timing ... } @@ -558,6 +572,31 @@ bool video_loadState(StateHelper_s *helper) { return loaded; } +// ---------------------------------------------------------------------------- +// Video frame completion callback registration + +void video_registerFrameCallback(video_frame_callback_fn *cbPtr) { + assert(!video_initialized); // backends cannot be registered after we've picked one to use + + eof_node_s *node = MALLOC(sizeof(eof_node_s)); + assert((uintptr_t)node); + node->next = NULL; + node->cbPtr = cbPtr; + + eof_node_s *p0 = NULL; + eof_node_s *p = eofs; + while (p) { + p0 = p; + p = p->next; + } + if (p0) { + p0->next = node; + } else { + eofs = node; + } + node->next = p; +} + // ---------------------------------------------------------------------------- // Video backend registration and selection @@ -571,7 +610,7 @@ void video_registerBackend(video_backend_s *backend, long order) { node->backend = backend; backend_node_s *p0 = NULL; - backend_node_s *p = head; + backend_node_s *p = backends; while (p && (order > p->order)) { p0 = p; p = p->next; @@ -579,15 +618,15 @@ void video_registerBackend(video_backend_s *backend, long order) { if (p0) { p0->next = node; } else { - head = node; + backends = node; } node->next = p; - currentBackend = head->backend; + currentBackend = backends->backend; } void video_printBackends(FILE *out) { - backend_node_s *p = head; + backend_node_s *p = backends; int count = 0; while (p) { const char *name = p->backend->name(); @@ -605,7 +644,7 @@ void video_chooseBackend(const char *name) { name = _null_backend_name(); } - backend_node_s *p = head; + backend_node_s *p = backends; while (p) { const char *bname = p->backend->name(); if (strcasecmp(name, bname) == 0) { diff --git a/src/video/video.h b/src/video/video.h index 8f74b6b2..5f8d3075 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -166,6 +166,14 @@ uint16_t video_scannerAddress(OUTPARM bool *ptrIsVBL); */ uint8_t floating_bus(void); +/* + * Video frame completion callbacks + */ + +typedef void (*video_frame_callback_fn)(uint8_t textFlashCounter) CALL_ON_CPU_THREAD; + +void video_registerFrameCallback(video_frame_callback_fn *cbPtr); + #if VIDEO_TRACING void video_scannerTraceBegin(const char *trace_file, unsigned long frameCount); void video_scannerTraceEnd(void);