From 261ae2efaeeae91c108ca5b6fc536544b80100b8 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 6 Feb 2016 21:23:40 -0800 Subject: [PATCH] Refactor to not use video_backend in so many places --- Android/jni/jnihooks.c | 6 +- Android/jni/jniprefs.c | 14 +- Apple2Mac/Apple2Mac/AppleViewController.m | 8 +- Apple2Mac/Classes/OSX/EmulatorGLView.m | 9 +- .../Classes/OSX/EmulatorWindowController.m | 8 +- Apple2Mac/Classes/iOS/EAGLView.m | 14 +- src/common.h | 2 +- src/disk.c | 4 +- src/display.c | 2 + src/display.h | 298 ++++++++++++++++++ src/interface.c | 8 +- src/keys.c | 12 +- src/video/glalert.c | 16 +- src/video/glnode.c | 7 +- src/video/glnode.h | 1 + src/video/gltouchjoy.c | 4 +- src/video/gltouchkbd.c | 4 +- src/video/gltouchmenu.c | 4 +- src/video/glvideo.c | 2 +- src/video/video.h | 276 +--------------- src/video/xvideo.c | 1 + 21 files changed, 366 insertions(+), 334 deletions(-) create mode 100644 src/display.h diff --git a/Android/jni/jnihooks.c b/Android/jni/jnihooks.c index d2f21328..ea520ffb 100644 --- a/Android/jni/jnihooks.c +++ b/Android/jni/jnihooks.c @@ -356,13 +356,13 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeChooseDisk(JNIEnv *env, jcl if (disk6_insert(drive, gzPath, ro)) { char *diskImageUnreadable = "Disk Image Unreadable"; unsigned int cols = strlen(diskImageUnreadable); - video_backend->animation_showMessage(diskImageUnreadable, cols, 1); + video_animations->animation_showMessage(diskImageUnreadable, cols, 1); } else { - video_backend->animation_showDiskChosen(drive); + video_animations->animation_showDiskChosen(drive); } ASPRINTF_FREE(gzPath); } else { - video_backend->animation_showDiskChosen(drive); + video_animations->animation_showDiskChosen(drive); } (*env)->ReleaseStringUTFChars(env, jPath, path); } diff --git a/Android/jni/jniprefs.c b/Android/jni/jniprefs.c index 54c5b274..614eb5ca 100644 --- a/Android/jni/jniprefs.c +++ b/Android/jni/jniprefs.c @@ -83,20 +83,20 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetCurrentTouchDevice(JN keydriver_setTouchKeyboardOwnsScreen(false); joydriver_setTouchJoystickOwnsScreen(true); joydriver_setTouchVariant(EMULATED_JOYSTICK); - video_backend->animation_showTouchJoystick(); + video_animations->animation_showTouchJoystick(); break; case TOUCH_DEVICE_JOYSTICK_KEYPAD: keydriver_setTouchKeyboardOwnsScreen(false); joydriver_setTouchJoystickOwnsScreen(true); joydriver_setTouchVariant(EMULATED_KEYPAD); - video_backend->animation_showTouchJoystick(); + video_animations->animation_showTouchJoystick(); break; case TOUCH_DEVICE_KEYBOARD: keydriver_setTouchKeyboardOwnsScreen(true); joydriver_setTouchJoystickOwnsScreen(false); - video_backend->animation_showTouchKeyboard(); + video_animations->animation_showTouchKeyboard(); break; case TOUCH_DEVICE_NONE: @@ -137,8 +137,8 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchMenuEnabled(JNIE void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetShowDiskOperationAnimation(JNIEnv *env, jclass cls, jboolean enabled) { LOG("enabled : %d", enabled); - if (video_backend && video_backend->animation_setEnableShowTrackSector) { - video_backend->animation_setEnableShowTrackSector(enabled); + if (video_animations && video_animations->animation_setEnableShowTrackSector) { + video_animations->animation_setEnableShowTrackSector(enabled); } } @@ -305,8 +305,8 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetCPUSpeed(JNIEnv *env, cpu_scale_factor = CPU_SCALE_SLOWEST; } - if (video_backend->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + if (video_animations->animation_showCPUSpeed) { + video_animations->animation_showCPUSpeed(); } timing_initialize(); diff --git a/Apple2Mac/Apple2Mac/AppleViewController.m b/Apple2Mac/Apple2Mac/AppleViewController.m index 6dc86c85..fb169066 100644 --- a/Apple2Mac/Apple2Mac/AppleViewController.m +++ b/Apple2Mac/Apple2Mac/AppleViewController.m @@ -80,9 +80,9 @@ { cpu_pause(); timing_toggleCPUSpeed(); - if (video_backend && video_backend->animation_showCPUSpeed) + if (video_animations && video_animations->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + video_animations->animation_showCPUSpeed(); } cpu_resume(); } @@ -108,9 +108,9 @@ { cpu_resume(); } - if (video_backend && video_backend->animation_showPaused) + if (video_animations && video_animations->animation_showPaused) { - video_backend->animation_showPaused(); + video_animations->animation_showPaused(); } } diff --git a/Apple2Mac/Classes/OSX/EmulatorGLView.m b/Apple2Mac/Classes/OSX/EmulatorGLView.m index 36d83057..919ae676 100644 --- a/Apple2Mac/Classes/OSX/EmulatorGLView.m +++ b/Apple2Mac/Classes/OSX/EmulatorGLView.m @@ -198,10 +198,9 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt // Init our renderer. Use 0 for the defaultFBO which is appropriate for // OSX (but not iOS since iOS apps must create their own FBO) #if TARGET_OS_MAC - video_backend->init(0); + video_init(); #elif TARGET_OS_IPHONE -# error "FBO FIXME TODO" - video_backend->init(otherFBO); +# error this is OSX specific #else # error "unknown/unsupported Apple platform #endif @@ -248,7 +247,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt #endif // !SUPPORT_RETINA_RESOLUTION // Set the new dimensions in our renderer - video_backend->reshape((int)viewRectPixels.size.width, (int)viewRectPixels.size.height); + video_reshape((int)viewRectPixels.size.width, (int)viewRectPixels.size.height); CGLUnlockContext([[self openGLContext] CGLContextObj]); } @@ -278,7 +277,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt - (void)drawView { CGLLockContext([[self openGLContext] CGLContextObj]); - video_backend->render(); + video_render(); CGLFlushDrawable([[self openGLContext] CGLContextObj]); CGLUnlockContext([[self openGLContext] CGLContextObj]); [[NSNotificationCenter defaultCenter] postNotificationName:(NSString *)kDrawTimerNotification object:nil]; diff --git a/Apple2Mac/Classes/OSX/EmulatorWindowController.m b/Apple2Mac/Classes/OSX/EmulatorWindowController.m index bca5c5e0..ca96e0ee 100644 --- a/Apple2Mac/Classes/OSX/EmulatorWindowController.m +++ b/Apple2Mac/Classes/OSX/EmulatorWindowController.m @@ -106,9 +106,9 @@ { cpu_pause(); timing_toggleCPUSpeed(); - if (video_backend && video_backend->animation_showCPUSpeed) + if (video_animations && video_animations->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + video_animations->animation_showCPUSpeed(); } cpu_resume(); } @@ -141,9 +141,9 @@ [[self pauseItem] setLabel:@"Running"]; cpu_resume(); } - if (video_backend && video_backend->animation_showPaused) + if (video_animations && video_animations->animation_showPaused) { - video_backend->animation_showPaused(); + video_animations->animation_showPaused(); } } diff --git a/Apple2Mac/Classes/iOS/EAGLView.m b/Apple2Mac/Classes/iOS/EAGLView.m index 45e119f6..557f67b5 100644 --- a/Apple2Mac/Classes/iOS/EAGLView.m +++ b/Apple2Mac/Classes/iOS/EAGLView.m @@ -84,7 +84,7 @@ // start emulator from paused state cpu_pause(); emulator_start(); - video_backend->init(0); + video_init(); _animating = NO; _renderFrameInterval = 1; @@ -136,11 +136,11 @@ } - (void)drawView:(id)sender -{ +{ [EAGLContext setCurrentContext:_context]; glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBOName); - video_backend->render(); + video_render(); glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer); [_context presentRenderbuffer:GL_RENDERBUFFER]; @@ -158,7 +158,7 @@ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); - video_backend->reshape((int)backingWidth, (int)backingHeight); + video_reshape((int)backingWidth, (int)backingHeight); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { @@ -261,21 +261,21 @@ static inline void _handleTouch(EAGLView *self, SEL _cmd, UITouch *touch, interf { keydriver_setTouchKeyboardOwnsScreen(true); joydriver_setTouchJoystickOwnsScreen(false); - video_backend->animation_showTouchKeyboard(); + video_animations->animation_showTouchKeyboard(); } else if ((flags & TOUCH_FLAGS_JOY) != 0) { keydriver_setTouchKeyboardOwnsScreen(false); joydriver_setTouchJoystickOwnsScreen(true); joydriver_setTouchVariant(EMULATED_JOYSTICK); - video_backend->animation_showTouchJoystick(); + video_animations->animation_showTouchJoystick(); } else if ((flags & TOUCH_FLAGS_JOY_KPAD) != 0) { keydriver_setTouchKeyboardOwnsScreen(false); joydriver_setTouchJoystickOwnsScreen(true); joydriver_setTouchVariant(EMULATED_KEYPAD); - video_backend->animation_showTouchJoystick(); + video_animations->animation_showTouchJoystick(); } else { diff --git a/src/common.h b/src/common.h index 4b652cc9..b41e6d21 100644 --- a/src/common.h +++ b/src/common.h @@ -69,7 +69,7 @@ #include "vm.h" #include "timing.h" #include "cpu.h" -#include "video/video.h" +#include "display.h" #include "disk.h" #include "interface.h" #include "keys.h" diff --git a/src/disk.c b/src/disk.c index a0db1c5a..2a4f55ff 100644 --- a/src/disk.c +++ b/src/disk.c @@ -457,7 +457,7 @@ static void save_track_data(int drive) { } static inline void animate_disk_track_sector(void) { - if (video_backend && video_backend->animation_showTrackSector) { + if (video_animations && video_animations->animation_showTrackSector) { static int previous_sect = 0; int sect_width = disk6.disk[disk6.drive].track_width>>4; // div-by-16 do { @@ -467,7 +467,7 @@ static inline void animate_disk_track_sector(void) { int sect = disk6.disk[disk6.drive].run_byte/sect_width; if (sect != previous_sect) { previous_sect = sect; - video_backend->animation_showTrackSector(disk6.drive, disk6.disk[disk6.drive].phase>>1, sect); + video_animations->animation_showTrackSector(disk6.drive, disk6.disk[disk6.drive].phase>>1, sect); } } while (0); } diff --git a/src/display.c b/src/display.c index a25c91ee..f61975d8 100644 --- a/src/display.c +++ b/src/display.c @@ -14,6 +14,7 @@ */ #include "common.h" +#include "video/video.h" #define SCANSTEP (SCANWIDTH-12) #define SCANDSTEP (SCANWIDTH-6) @@ -25,6 +26,7 @@ static uint8_t vga_mem_page_0[SCANWIDTH*SCANHEIGHT] = { 0 }; static uint8_t vga_mem_page_1[SCANWIDTH*SCANHEIGHT] = { 0 }; A2Color_s colormap[256] = { { 0 } }; +video_animation_s *video_animations = NULL; video_backend_s *video_backend = NULL; static pthread_t render_thread_id = 0; diff --git a/src/display.h b/src/display.h new file mode 100644 index 00000000..84c013e7 --- /dev/null +++ b/src/display.h @@ -0,0 +1,298 @@ +/* + * Apple // emulator for *ix + * + * This software package is subject to the GNU General Public License + * version 3 or later (your choice) as published by the Free Software + * Foundation. + * + * Copyright 2016 Aaron Culliney + * + */ + +#ifndef _DISPLAY_H_ +#define _DISPLAY_H_ + +typedef struct video_animation_s { + +#if INTERFACE_TOUCH + // touch HUD functions + void (*animation_showTouchKeyboard)(void); + void (*animation_hideTouchKeyboard)(void); + void (*animation_showTouchJoystick)(void); + void (*animation_hideTouchJoystick)(void); + void (*animation_showTouchMenu)(void); + void (*animation_hideTouchMenu)(void); +#endif + + // misc animations + void (*animation_showMessage)(char *message, unsigned int cols, unsigned int rows); + void (*animation_showPaused)(void); + void (*animation_showCPUSpeed)(void); + void (*animation_showDiskChosen)(int drive); + void (*animation_showTrackSector)(int drive, int track, int sect); + void (*animation_setEnableShowTrackSector)(bool enabled); + +} video_animation_s; + +/* + * The registered video animations. + */ +extern video_animation_s *video_animations; + +/* + * Prepare the video system, converting console to graphics mode, or + * opening X window, or whatever. This is called only once when the + * emulator is run + */ +void video_init(void); + +/* + * Enters emulator-managed main video loop--if backend rendering system requires it. Currently only used by desktop X11 + * and desktop OpenGL/GLUT. + */ +void video_main_loop(void); + +/* + * Shutdown video system. Should only be called on the render thread (unless render thread is in emulator-managed main + * video loop). + */ +void video_shutdown(bool emulatorShuttingDown); + +/* + * Begin a render pass (only for non-emulator-managed main video). This should only be called on the render thread. + */ +void video_render(void); + +/* + * Set the render thread ID. Use with caution. + */ +void _video_setRenderThread(pthread_t id); + +/* + * Reshape the display to particular dimensions. + */ +void video_reshape(int w, int h); + +/* + * Setup the display. This may be called multiple times in a run, and is + * used when graphics parameters may have changed. + * + * This function is responsible for inserting any needed video-specific hooks + * into the 6502 memory indirection table. It should *not* hook the + * soft-switches. + * + */ +void video_reset(void); + +/* + * Set the font used by the display. QTY characters are loaded starting + * with FIRST, from DATA. DATA contains 8 bytes for each character, each + * byte representing a row (top-to-bottom). The row byte contains 7 + * pixels in little-endian format. + * + * MODE selects the colors to use + * + * 0 - Normal text + * 1 - MouseText (usually treat as Normal) + * 2 - Inverse + * 3 - Flash + * + * The extra MouseText mode is in case we want to emulate certain RGB + * adaptors which color normal text and MouseText differently. I had one + * once for a //c. + */ +void video_loadfont(int first, int qty, const uint8_t *data, int mode); + +/* + * Redraw the display. This is called after exiting an interface display, + * when changes have been made to the Apple's emulated framebuffer that + * bypass the driver's hooks, or when the video mode has changed. + */ +void video_redraw(void); + +/* + * Toggles FLASHing text between NORMAL and INVERSE character sets. + */ +void video_flashText(void); + +/* + * Clear the current display. + */ +void video_clear(void); + +/* + * Change the displayed video page to PAGE + * 0 - Page 1: $400-$7ff/$2000-$3fff + * 1 - Page 2: $800-$bff/$4000-$5fff + */ +void video_setpage(int page); + +/* + * Get a reference to current internal framebuffer + */ +const uint8_t * const video_current_framebuffer(); + +// do not access directly, but through inline accessor methods +extern volatile unsigned long _backend_vid_dirty; + +/* + * True if anything changed in framebuffer and not yet drawn + */ +static inline bool video_isDirty(void) { + return _backend_vid_dirty; +} + +/* + * Atomically set dirty bit, return previous value + */ +static inline unsigned long video_setDirty(void) { + return __sync_fetch_and_or(&_backend_vid_dirty, 1UL); +} + +/* + * Atomically clear dirty bit, return previous value + */ +static inline unsigned long video_clearDirty(void) { + return __sync_fetch_and_and(&_backend_vid_dirty, 0UL); +} + +extern bool video_saveState(StateHelper_s *helper); +extern bool video_loadState(StateHelper_s *helper); + +// ---------------------------------------------------------------------------- + +/* + * VBL routines + */ +uint16_t video_scanner_get_address(bool *vblBarOut); +uint8_t floating_bus(void); +uint8_t floating_bus_hibit(const bool hibit); + +#define TEXT_ROWS 24 +#define BEGIN_MIX 20 +#define TEXT_COLS 40 +#define TEXT80_COLS (TEXT_COLS*2) + +#define FONT_HEIGHT_PIXELS 16 +#define FONT_WIDTH_PIXELS 14 +#define FONT80_WIDTH_PIXELS (FONT_WIDTH_PIXELS>>1) + +#define _SCANWIDTH (TEXT_COLS * FONT_WIDTH_PIXELS) // 560 +#define SCANHEIGHT (TEXT_ROWS * FONT_HEIGHT_PIXELS) // 384 + +// Extra bytes on each side of internal framebuffers for color interpolation hack +#define _INTERPOLATED_PIXEL_ADJUSTMENT_PRE 4 +#define _INTERPOLATED_PIXEL_ADJUSTMENT_POST 4 +#define INTERPOLATED_PIXEL_ADJUSTMENT (_INTERPOLATED_PIXEL_ADJUSTMENT_PRE+_INTERPOLATED_PIXEL_ADJUSTMENT_POST) +#define SCANWIDTH (_SCANWIDTH+INTERPOLATED_PIXEL_ADJUSTMENT) + +#define FONT_GLYPH_X (7+/*unused*/1) // generated font.c uses a single byte (8bits) per font glyph line +#define FONT_GLYPH_Y (FONT_HEIGHT_PIXELS>>1) // ... 8 bytes total for whole glyph +#define FONT_GLYPH_SCALE_Y (FONT_HEIGHT_PIXELS/FONT_GLYPH_Y) // FIXME NOTE : implicit 2x scaling in display.c ... + +#define MOUSETEXT_BEGIN 0x80 // offset + 0x20 length +#define MOUSETEXT_RETURN (MOUSETEXT_BEGIN+0x0d) +#define MOUSETEXT_UP (MOUSETEXT_BEGIN+0x0b) +#define MOUSETEXT_LEFT (MOUSETEXT_BEGIN+0x08) +#define MOUSETEXT_RIGHT (MOUSETEXT_BEGIN+0x15) +#define MOUSETEXT_DOWN (MOUSETEXT_BEGIN+0x0a) +#define MOUSETEXT_OPENAPPLE (MOUSETEXT_BEGIN+0x01) +#define MOUSETEXT_CLOSEDAPPLE (MOUSETEXT_BEGIN+0x00) +#define MOUSETEXT_HOURGLASS (MOUSETEXT_BEGIN+0x03) +#define MOUSETEXT_CHECKMARK (MOUSETEXT_BEGIN+0x04) + +#define ICONTEXT_BEGIN 0xA0 // offset + 0x22 length +#define ICONTEXT_MENU_BEGIN ICONTEXT_BEGIN +#define ICONTEXT_MENU_END (ICONTEXT_MENU_BEGIN+0x0A) + +#define ICONTEXT_DISK_UL (ICONTEXT_BEGIN+0x0B) +#define ICONTEXT_DISK_UR (ICONTEXT_BEGIN+0x0C) +#define ICONTEXT_DISK_LL (ICONTEXT_BEGIN+0x0D) +#define ICONTEXT_DISK_LR (ICONTEXT_BEGIN+0x0E) +#define ICONTEXT_UNLOCK (ICONTEXT_BEGIN+0x0F) +#define ICONTEXT_GOTO (ICONTEXT_BEGIN+0x10) +#define ICONTEXT_SPACE_VISUAL (ICONTEXT_BEGIN+0x11) + +#define ICONTEXT_MENU_SPROUT (MOUSETEXT_BEGIN+0x1B) +#define ICONTEXT_MENU_TOUCHJOY (ICONTEXT_BEGIN+0x12) +#define ICONTEXT_MENU_TOUCHJOY_KPAD (ICONTEXT_BEGIN+0x18) + +#define ICONTEXT_KBD_BEGIN (ICONTEXT_BEGIN+0x13) +#define ICONTEXT_CTRL (ICONTEXT_KBD_BEGIN+0x00) +#define ICONTEXT_LOWERCASE (ICONTEXT_KBD_BEGIN+0x01) +#define ICONTEXT_UPPERCASE (ICONTEXT_KBD_BEGIN+0x02) +#define ICONTEXT_SHOWALT1 (ICONTEXT_KBD_BEGIN+0x03) +#define ICONTEXT_BACKSPACE (ICONTEXT_KBD_BEGIN+0x04) + +#define ICONTEXT_LEFTSPACE (ICONTEXT_KBD_BEGIN+0x06) +#define ICONTEXT_MIDSPACE (ICONTEXT_KBD_BEGIN+0x07) +#define ICONTEXT_RIGHTSPACE (ICONTEXT_KBD_BEGIN+0x08) +#define ICONTEXT_ESC (ICONTEXT_KBD_BEGIN+0x09) +#define ICONTEXT_RETURN_L (ICONTEXT_KBD_BEGIN+0x0A) +#define ICONTEXT_RETURN_R (ICONTEXT_KBD_BEGIN+0x0B) +#define ICONTEXT_NONACTIONABLE (ICONTEXT_KBD_BEGIN+0x0C) + +#define ICONTEXT_LEFT_TAB (ICONTEXT_KBD_BEGIN+0x..) +#define ICONTEXT_RIGHT_TAB (ICONTEXT_KBD_BEGIN+0x..) + +#define COLOR_BLACK 0 + +#define COLOR_DARK_RED 35 +#define COLOR_MEDIUM_RED 36 +#define COLOR_LIGHT_RED 37 /* hgr used */ + +#define COLOR_DARK_GREEN 38 +#define COLOR_MEDIUM_GREEN 39 +#define COLOR_LIGHT_GREEN 40 /* hgr used */ + +#define COLOR_DARK_YELLOW 41 +#define COLOR_MEDIUM_YELLOW 42 +#define COLOR_LIGHT_YELLOW 43 + +#define COLOR_DARK_BLUE 44 +#define COLOR_MEDIUM_BLUE 45 +#define COLOR_LIGHT_BLUE 46 /* hgr used */ + +#define COLOR_DARK_PURPLE 47 +#define COLOR_MEDIUM_PURPLE 48 +#define COLOR_LIGHT_PURPLE 49 /* hgr used */ + +#define COLOR_DARK_CYAN 50 +#define COLOR_MEDIUM_CYAN 51 +#define COLOR_LIGHT_CYAN 52 + +#define COLOR_DARK_WHITE 53 +#define COLOR_MEDIUM_WHITE 54 +#define COLOR_LIGHT_WHITE 55 + +#define COLOR_FLASHING_BLACK 56 +#define COLOR_FLASHING_WHITE 57 +#define COLOR_FLASHING_UNGREEN 58 +#define COLOR_FLASHING_GREEN 59 + + +/* ---------------------------------- + generic graphics globals + ---------------------------------- */ + +/* + * Pointers to framebuffer (can be VGA memory or host buffer) + */ +extern uint8_t *video__fb1; +extern uint8_t *video__fb2; + +/* + * Current visual page + */ +extern READONLY int video__current_page; + +/* + * font glyph data + */ +extern const unsigned char ucase_glyphs[0x200]; +extern const unsigned char lcase_glyphs[0x100]; +extern const unsigned char mousetext_glyphs[0x100]; +extern const unsigned char interface_glyphs[88]; + +#endif // whole file + diff --git a/src/interface.c b/src/interface.c index 97de63af..2c718f4a 100644 --- a/src/interface.c +++ b/src/interface.c @@ -587,8 +587,8 @@ void c_interface_select_diskette( int drive ) } else { - if (video_backend->animation_showDiskChosen) { - video_backend->animation_showDiskChosen(drive); + if (video_animations->animation_showDiskChosen) { + video_animations->animation_showDiskChosen(drive); } } @@ -655,8 +655,8 @@ void c_interface_select_diskette( int drive ) } else { - if (video_backend->animation_showDiskChosen) { - video_backend->animation_showDiskChosen(drive); + if (video_animations->animation_showDiskChosen) { + video_animations->animation_showDiskChosen(drive); } } diff --git a/src/keys.c b/src/keys.c index bc890166..e5d77b56 100644 --- a/src/keys.c +++ b/src/keys.c @@ -254,8 +254,8 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked) cpu_pause(); timing_toggleCPUSpeed(); cpu_resume(); - if (video_backend->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + if (video_animations->animation_showCPUSpeed) { + video_animations->animation_showCPUSpeed(); } break; } @@ -285,8 +285,8 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked) cpu_scale_factor = scale; } - if (video_backend->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + if (video_animations->animation_showCPUSpeed) { + video_animations->animation_showCPUSpeed(); } cpu_pause(); @@ -315,8 +315,8 @@ void c_keys_handle_input(int scancode, int pressed, int is_cooked) cpu_scale_factor = scale; } - if (video_backend->animation_showCPUSpeed) { - video_backend->animation_showCPUSpeed(); + if (video_animations->animation_showCPUSpeed) { + video_animations->animation_showCPUSpeed(); } cpu_pause(); diff --git a/src/video/glalert.c b/src/video/glalert.c index 3d38767d..62a88554 100644 --- a/src/video/glalert.c +++ b/src/video/glalert.c @@ -357,9 +357,9 @@ static void _animation_showTrackSector(int drive, int track, int sect) { static void _animation_setEnableShowTrackSector(bool enabled) { if (enabled) { - video_backend->animation_showTrackSector = &_animation_showTrackSector; + video_animations->animation_showTrackSector = &_animation_showTrackSector; } else { - video_backend->animation_showTrackSector = NULL; + video_animations->animation_showTrackSector = NULL; } } @@ -367,12 +367,12 @@ __attribute__((constructor(CTOR_PRIORITY_LATE))) static void _init_glalert(void) { LOG("Initializing message animation subsystem"); - video_backend->animation_showMessage = &_animation_showMessage; - video_backend->animation_showPaused = &_animation_showPaused; - video_backend->animation_showCPUSpeed = &_animation_showCPUSpeed; - video_backend->animation_showDiskChosen = &_animation_showDiskChosen; - video_backend->animation_showTrackSector = &_animation_showTrackSector; - video_backend->animation_setEnableShowTrackSector = &_animation_setEnableShowTrackSector; + video_animations->animation_showMessage = &_animation_showMessage; + video_animations->animation_showPaused = &_animation_showPaused; + video_animations->animation_showCPUSpeed = &_animation_showCPUSpeed; + video_animations->animation_showDiskChosen = &_animation_showDiskChosen; + video_animations->animation_showTrackSector = &_animation_showTrackSector; + video_animations->animation_setEnableShowTrackSector = &_animation_setEnableShowTrackSector; glnode_registerNode(RENDER_MIDDLE, (GLNode){ .setup = &alert_init, diff --git a/src/video/glnode.c b/src/video/glnode.c index cac3d30f..c2712942 100644 --- a/src/video/glnode.c +++ b/src/video/glnode.c @@ -27,6 +27,7 @@ static glnode_array_node_s *head = NULL; static glnode_array_node_s *tail = NULL; static video_backend_s glnode_backend = { 0 }; +static video_animation_s glnode_animations = { 0 }; #if USE_GLUT static bool glut_in_main_loop = false; @@ -237,17 +238,21 @@ static void glnode_mainLoop(void) { //---------------------------------------------------------------------------- -__attribute__((constructor(CTOR_PRIORITY_LATE))) +__attribute__((constructor(CTOR_PRIORITY_EARLY))) static void _init_glnode_manager(void) { LOG("Initializing GLNode manager subsystem"); assert((video_backend == NULL) && "there can only be one!"); + assert((video_animations == NULL) && "there can only be one!"); + glnode_backend.init = &glnode_setupNodes; glnode_backend.main_loop = &glnode_mainLoop; glnode_backend.reshape = &glnode_reshapeNodes; glnode_backend.render = &glnode_renderNodes; glnode_backend.shutdown = &glnode_shutdownNodes; + video_backend = &glnode_backend; + video_animations = &glnode_animations; #if INTERFACE_TOUCH interface_onTouchEvent = &glnode_onTouchEvent; diff --git a/src/video/glnode.h b/src/video/glnode.h index 5fc80555..cc0d2934 100644 --- a/src/video/glnode.h +++ b/src/video/glnode.h @@ -13,6 +13,7 @@ #define _GLNODE_H_ #include "common.h" +#include "video/video.h" #include "video_util/modelUtil.h" #include "video_util/matrixUtil.h" #include "video_util/sourceUtil.h" diff --git a/src/video/gltouchjoy.c b/src/video/gltouchjoy.c index 67654caa..074dade5 100644 --- a/src/video/gltouchjoy.c +++ b/src/video/gltouchjoy.c @@ -1017,8 +1017,8 @@ static void _init_gltouchjoy(void) { joyglobals.axisIsOnLeft = true; joyglobals.switchThreshold = BUTTON_SWITCH_THRESHOLD_DEFAULT; - video_backend->animation_showTouchJoystick = &_animation_showTouchJoystick; - video_backend->animation_hideTouchJoystick = &_animation_hideTouchJoystick; + video_animations->animation_showTouchJoystick = &_animation_showTouchJoystick; + video_animations->animation_hideTouchJoystick = &_animation_hideTouchJoystick; joydriver_isTouchJoystickAvailable = &gltouchjoy_isTouchJoystickAvailable; joydriver_setTouchJoystickEnabled = &gltouchjoy_setTouchJoystickEnabled; diff --git a/src/video/gltouchkbd.c b/src/video/gltouchkbd.c index f862ea67..03864346 100644 --- a/src/video/gltouchkbd.c +++ b/src/video/gltouchkbd.c @@ -977,8 +977,8 @@ static void _init_gltouchkbd(void) { _initialize_keyboard_templates(); - video_backend->animation_showTouchKeyboard = &_animation_showTouchKeyboard; - video_backend->animation_hideTouchKeyboard = &_animation_hideTouchKeyboard; + video_animations->animation_showTouchKeyboard = &_animation_showTouchKeyboard; + video_animations->animation_hideTouchKeyboard = &_animation_hideTouchKeyboard; keydriver_isTouchKeyboardAvailable = &gltouchkbd_isTouchKeyboardAvailable; keydriver_setTouchKeyboardEnabled = &gltouchkbd_setTouchKeyboardEnabled; diff --git a/src/video/gltouchmenu.c b/src/video/gltouchmenu.c index bc5facd9..8515da1f 100644 --- a/src/video/gltouchmenu.c +++ b/src/video/gltouchmenu.c @@ -552,8 +552,8 @@ __attribute__((constructor(CTOR_PRIORITY_LATE))) static void _init_gltouchmenu(void) { LOG("Registering OpenGL software touch menu"); - video_backend->animation_showTouchMenu = &_animation_showTouchMenu; - video_backend->animation_hideTouchMenu = &_animation_hideTouchMenu; + video_animations->animation_showTouchMenu = &_animation_showTouchMenu; + video_animations->animation_hideTouchMenu = &_animation_hideTouchMenu; interface_isTouchMenuAvailable = &gltouchmenu_isTouchMenuAvailable; interface_setTouchMenuEnabled = &gltouchmenu_setTouchMenuEnabled; diff --git a/src/video/glvideo.c b/src/video/glvideo.c index 5366383a..f6ba7801 100644 --- a/src/video/glvideo.c +++ b/src/video/glvideo.c @@ -418,7 +418,7 @@ static int64_t glvideo_onTouchEvent(interface_touch_event_t action, int pointer_ //---------------------------------------------------------------------------- -__attribute__((constructor(CTOR_PRIORITY_EARLY))) +__attribute__((constructor(CTOR_PRIORITY_LATE))) static void _init_glvideo(void) { LOG("Initializing OpenGL renderer"); diff --git a/src/video/video.h b/src/video/video.h index beb57f61..5f50fe30 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -17,30 +17,11 @@ #define A2_VIDEO_H typedef struct video_backend_s { - - // mandatory video backend functions void (*init)(void *context); void (*main_loop)(void); void (*reshape)(int width, int height); void (*render)(void); void (*shutdown)(bool emulatorShuttingDown); - - // touch HUD functions - void (*animation_showTouchKeyboard)(void); - void (*animation_hideTouchKeyboard)(void); - void (*animation_showTouchJoystick)(void); - void (*animation_hideTouchJoystick)(void); - void (*animation_showTouchMenu)(void); - void (*animation_hideTouchMenu)(void); - - // misc animations - void (*animation_showMessage)(char *message, unsigned int cols, unsigned int rows); - void (*animation_showPaused)(void); - void (*animation_showCPUSpeed)(void); - void (*animation_showDiskChosen)(int drive); - void (*animation_showTrackSector)(int drive, int track, int sect); - void (*animation_setEnableShowTrackSector)(bool enabled); - } video_backend_s; /* @@ -60,262 +41,7 @@ typedef struct A2Color_s { /* * Reference to the internal 8bit-indexed color format */ -extern A2Color_s colormap[]; - -/* - * Prepare the video system, converting console to graphics mode, or - * opening X window, or whatever. This is called only once when the - * emulator is run - */ -void video_init(void); - -/* - * Enters emulator-managed main video loop--if backend rendering system requires it. Currently only used by desktop X11 - * and desktop OpenGL/GLUT. - */ -void video_main_loop(void); - -/* - * Shutdown video system. Should only be called on the render thread (unless render thread is in emulator-managed main - * video loop). - */ -void video_shutdown(bool emulatorShuttingDown); - -/* - * Begin a render pass (only for non-emulator-managed main video). This should only be called on the render thread. - */ -void video_render(void); - -/* - * Set the render thread ID. Use with caution. - */ -void _video_setRenderThread(pthread_t id); - -/* - * Reshape the display to particular dimensions. - */ -void video_reshape(int w, int h); - -/* - * Setup the display. This may be called multiple times in a run, and is - * used when graphics parameters may have changed. - * - * This function is responsible for inserting any needed video-specific hooks - * into the 6502 memory indirection table. It should *not* hook the - * soft-switches. - * - */ -void video_reset(void); - -/* - * Set the font used by the display. QTY characters are loaded starting - * with FIRST, from DATA. DATA contains 8 bytes for each character, each - * byte representing a row (top-to-bottom). The row byte contains 7 - * pixels in little-endian format. - * - * MODE selects the colors to use - * - * 0 - Normal text - * 1 - MouseText (usually treat as Normal) - * 2 - Inverse - * 3 - Flash - * - * The extra MouseText mode is in case we want to emulate certain RGB - * adaptors which color normal text and MouseText differently. I had one - * once for a //c. - */ -void video_loadfont(int first, int qty, const uint8_t *data, int mode); - -/* - * Redraw the display. This is called after exiting an interface display, - * when changes have been made to the Apple's emulated framebuffer that - * bypass the driver's hooks, or when the video mode has changed. - */ -void video_redraw(void); - -/* - * Toggles FLASHing text between NORMAL and INVERSE character sets. - */ -void video_flashText(void); - -/* - * Clear the current display. - */ -void video_clear(void); - -/* - * Change the displayed video page to PAGE - * 0 - Page 1: $400-$7ff/$2000-$3fff - * 1 - Page 2: $800-$bff/$4000-$5fff - */ -void video_setpage(int page); - -/* - * Get a reference to current internal framebuffer - */ -const uint8_t * const video_current_framebuffer(); - -// do not access directly, but through inline accessor methods -extern volatile unsigned long _backend_vid_dirty; - -/* - * True if anything changed in framebuffer and not yet drawn - */ -static inline bool video_isDirty(void) { - return _backend_vid_dirty; -} - -/* - * Atomically set dirty bit, return previous value - */ -static inline unsigned long video_setDirty(void) { - return __sync_fetch_and_or(&_backend_vid_dirty, 1UL); -} - -/* - * Atomically clear dirty bit, return previous value - */ -static inline unsigned long video_clearDirty(void) { - return __sync_fetch_and_and(&_backend_vid_dirty, 0UL); -} - -extern bool video_saveState(StateHelper_s *helper); -extern bool video_loadState(StateHelper_s *helper); - -// ---------------------------------------------------------------------------- - -/* - * VBL routines - */ -uint16_t video_scanner_get_address(bool *vblBarOut); -uint8_t floating_bus(void); -uint8_t floating_bus_hibit(const bool hibit); - -#define TEXT_ROWS 24 -#define BEGIN_MIX 20 -#define TEXT_COLS 40 -#define TEXT80_COLS (TEXT_COLS*2) - -#define FONT_HEIGHT_PIXELS 16 -#define FONT_WIDTH_PIXELS 14 -#define FONT80_WIDTH_PIXELS (FONT_WIDTH_PIXELS>>1) - -#define _SCANWIDTH (TEXT_COLS * FONT_WIDTH_PIXELS) // 560 -#define SCANHEIGHT (TEXT_ROWS * FONT_HEIGHT_PIXELS) // 384 - -// Extra bytes on each side of internal framebuffers for color interpolation hack -#define _INTERPOLATED_PIXEL_ADJUSTMENT_PRE 4 -#define _INTERPOLATED_PIXEL_ADJUSTMENT_POST 4 -#define INTERPOLATED_PIXEL_ADJUSTMENT (_INTERPOLATED_PIXEL_ADJUSTMENT_PRE+_INTERPOLATED_PIXEL_ADJUSTMENT_POST) -#define SCANWIDTH (_SCANWIDTH+INTERPOLATED_PIXEL_ADJUSTMENT) - -#define FONT_GLYPH_X (7+/*unused*/1) // generated font.c uses a single byte (8bits) per font glyph line -#define FONT_GLYPH_Y (FONT_HEIGHT_PIXELS>>1) // ... 8 bytes total for whole glyph -#define FONT_GLYPH_SCALE_Y (FONT_HEIGHT_PIXELS/FONT_GLYPH_Y) // FIXME NOTE : implicit 2x scaling in display.c ... - -#define MOUSETEXT_BEGIN 0x80 // offset + 0x20 length -#define MOUSETEXT_RETURN (MOUSETEXT_BEGIN+0x0d) -#define MOUSETEXT_UP (MOUSETEXT_BEGIN+0x0b) -#define MOUSETEXT_LEFT (MOUSETEXT_BEGIN+0x08) -#define MOUSETEXT_RIGHT (MOUSETEXT_BEGIN+0x15) -#define MOUSETEXT_DOWN (MOUSETEXT_BEGIN+0x0a) -#define MOUSETEXT_OPENAPPLE (MOUSETEXT_BEGIN+0x01) -#define MOUSETEXT_CLOSEDAPPLE (MOUSETEXT_BEGIN+0x00) -#define MOUSETEXT_HOURGLASS (MOUSETEXT_BEGIN+0x03) -#define MOUSETEXT_CHECKMARK (MOUSETEXT_BEGIN+0x04) - -#define ICONTEXT_BEGIN 0xA0 // offset + 0x22 length -#define ICONTEXT_MENU_BEGIN ICONTEXT_BEGIN -#define ICONTEXT_MENU_END (ICONTEXT_MENU_BEGIN+0x0A) - -#define ICONTEXT_DISK_UL (ICONTEXT_BEGIN+0x0B) -#define ICONTEXT_DISK_UR (ICONTEXT_BEGIN+0x0C) -#define ICONTEXT_DISK_LL (ICONTEXT_BEGIN+0x0D) -#define ICONTEXT_DISK_LR (ICONTEXT_BEGIN+0x0E) -#define ICONTEXT_UNLOCK (ICONTEXT_BEGIN+0x0F) -#define ICONTEXT_GOTO (ICONTEXT_BEGIN+0x10) -#define ICONTEXT_SPACE_VISUAL (ICONTEXT_BEGIN+0x11) - -#define ICONTEXT_MENU_SPROUT (MOUSETEXT_BEGIN+0x1B) -#define ICONTEXT_MENU_TOUCHJOY (ICONTEXT_BEGIN+0x12) -#define ICONTEXT_MENU_TOUCHJOY_KPAD (ICONTEXT_BEGIN+0x18) - -#define ICONTEXT_KBD_BEGIN (ICONTEXT_BEGIN+0x13) -#define ICONTEXT_CTRL (ICONTEXT_KBD_BEGIN+0x00) -#define ICONTEXT_LOWERCASE (ICONTEXT_KBD_BEGIN+0x01) -#define ICONTEXT_UPPERCASE (ICONTEXT_KBD_BEGIN+0x02) -#define ICONTEXT_SHOWALT1 (ICONTEXT_KBD_BEGIN+0x03) -#define ICONTEXT_BACKSPACE (ICONTEXT_KBD_BEGIN+0x04) - -#define ICONTEXT_LEFTSPACE (ICONTEXT_KBD_BEGIN+0x06) -#define ICONTEXT_MIDSPACE (ICONTEXT_KBD_BEGIN+0x07) -#define ICONTEXT_RIGHTSPACE (ICONTEXT_KBD_BEGIN+0x08) -#define ICONTEXT_ESC (ICONTEXT_KBD_BEGIN+0x09) -#define ICONTEXT_RETURN_L (ICONTEXT_KBD_BEGIN+0x0A) -#define ICONTEXT_RETURN_R (ICONTEXT_KBD_BEGIN+0x0B) -#define ICONTEXT_NONACTIONABLE (ICONTEXT_KBD_BEGIN+0x0C) - -#define ICONTEXT_LEFT_TAB (ICONTEXT_KBD_BEGIN+0x..) -#define ICONTEXT_RIGHT_TAB (ICONTEXT_KBD_BEGIN+0x..) - -#define COLOR_BLACK 0 - -#define COLOR_DARK_RED 35 -#define COLOR_MEDIUM_RED 36 -#define COLOR_LIGHT_RED 37 /* hgr used */ - -#define COLOR_DARK_GREEN 38 -#define COLOR_MEDIUM_GREEN 39 -#define COLOR_LIGHT_GREEN 40 /* hgr used */ - -#define COLOR_DARK_YELLOW 41 -#define COLOR_MEDIUM_YELLOW 42 -#define COLOR_LIGHT_YELLOW 43 - -#define COLOR_DARK_BLUE 44 -#define COLOR_MEDIUM_BLUE 45 -#define COLOR_LIGHT_BLUE 46 /* hgr used */ - -#define COLOR_DARK_PURPLE 47 -#define COLOR_MEDIUM_PURPLE 48 -#define COLOR_LIGHT_PURPLE 49 /* hgr used */ - -#define COLOR_DARK_CYAN 50 -#define COLOR_MEDIUM_CYAN 51 -#define COLOR_LIGHT_CYAN 52 - -#define COLOR_DARK_WHITE 53 -#define COLOR_MEDIUM_WHITE 54 -#define COLOR_LIGHT_WHITE 55 - -#define COLOR_FLASHING_BLACK 56 -#define COLOR_FLASHING_WHITE 57 -#define COLOR_FLASHING_UNGREEN 58 -#define COLOR_FLASHING_GREEN 59 - - -/* ---------------------------------- - generic graphics globals - ---------------------------------- */ - -/* - * Pointers to framebuffer (can be VGA memory or host buffer) - */ -extern uint8_t *video__fb1; -extern uint8_t *video__fb2; - -/* - * Current visual page - */ -extern READONLY int video__current_page; - -/* - * font glyph data - */ -extern const unsigned char ucase_glyphs[0x200]; -extern const unsigned char lcase_glyphs[0x100]; -extern const unsigned char mousetext_glyphs[0x100]; -extern const unsigned char interface_glyphs[88]; +extern A2Color_s colormap[256]; #endif /* !A2_VIDEO_H */ diff --git a/src/video/xvideo.c b/src/video/xvideo.c index b1fe7a0f..3767a25a 100644 --- a/src/video/xvideo.c +++ b/src/video/xvideo.c @@ -14,6 +14,7 @@ */ #include "common.h" +#include "video/video.h" #include #include