796 lines
19 KiB
C
796 lines
19 KiB
C
/* sim_video.c: Bitmap video output
|
|
|
|
Copyright (c) 2011-2013, Matt Burke
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of the author shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from the author.
|
|
|
|
11-Jun-2013 MB First version
|
|
*/
|
|
|
|
#include "sim_video.h"
|
|
|
|
t_bool vid_active = FALSE;
|
|
|
|
#if HAVE_LIBSDL
|
|
#include <SDL.h>
|
|
#include <SDL_thread.h>
|
|
|
|
extern int32 sim_is_running;
|
|
|
|
#define EVENT_REDRAW 1 /* redraw event for SDL */
|
|
#define EVENT_CLOSE 2 /* close event for SDL */
|
|
#define MAX_EVENTS 20 /* max events in queue */
|
|
|
|
typedef struct {
|
|
SIM_KEY_EVENT events[MAX_EVENTS];
|
|
SDL_sem *sem;
|
|
int32 head;
|
|
int32 tail;
|
|
int32 count;
|
|
} KEY_EVENT_QUEUE;
|
|
|
|
typedef struct {
|
|
SIM_MOUSE_EVENT events[MAX_EVENTS];
|
|
SDL_sem *sem;
|
|
int32 head;
|
|
int32 tail;
|
|
int32 count;
|
|
t_bool b1_state;
|
|
t_bool b2_state;
|
|
t_bool b3_state;
|
|
} MOUSE_EVENT_QUEUE;
|
|
|
|
int vid_thread (void* arg);
|
|
|
|
t_bool vid_key_state[SDLK_LAST];
|
|
t_bool vid_mouse_captured;
|
|
int32 vid_width;
|
|
int32 vid_height;
|
|
SDL_Surface *vid_image; /* video buffer */
|
|
SDL_Surface *vid_window; /* window handle */
|
|
SDL_Thread *vid_thread_id; /* event thread handle */
|
|
SDL_Color vid_palette[256];
|
|
KEY_EVENT_QUEUE vid_key_events; /* keyboard events */
|
|
MOUSE_EVENT_QUEUE vid_mouse_events; /* mouse events */
|
|
|
|
t_stat vid_open (uint32 width, uint32 height)
|
|
{
|
|
if (!vid_active) {
|
|
vid_active = TRUE;
|
|
vid_width = width;
|
|
vid_height = height;
|
|
vid_mouse_captured = FALSE;
|
|
|
|
vid_key_events.head = 0;
|
|
vid_key_events.tail = 0;
|
|
vid_key_events.count = 0;
|
|
vid_key_events.sem = SDL_CreateSemaphore (1);
|
|
vid_mouse_events.head = 0;
|
|
vid_mouse_events.tail = 0;
|
|
vid_mouse_events.count = 0;
|
|
vid_mouse_events.sem = SDL_CreateSemaphore (1);
|
|
|
|
vid_thread_id = SDL_CreateThread (vid_thread, NULL);
|
|
if (vid_thread_id == NULL) {
|
|
vid_active = FALSE;
|
|
return SCPE_OPENERR;
|
|
}
|
|
|
|
vid_image = SDL_CreateRGBSurface (SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
|
|
|
|
vid_palette[0].r = 0;
|
|
vid_palette[0].g = 0;
|
|
vid_palette[0].b = 0;
|
|
vid_palette[1].r = 255;
|
|
vid_palette[1].g = 255;
|
|
vid_palette[1].b = 255;
|
|
SDL_SetColors (vid_image, vid_palette, 0, 2);
|
|
|
|
memset (&vid_key_state, 0, sizeof(vid_key_state));
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vid_close (void)
|
|
{
|
|
SDL_Event user_event;
|
|
|
|
if (vid_active) {
|
|
vid_active = FALSE;
|
|
user_event.type = SDL_USEREVENT;
|
|
user_event.user.code = EVENT_CLOSE;
|
|
user_event.user.data1 = NULL;
|
|
user_event.user.data2 = NULL;
|
|
|
|
SDL_PushEvent (&user_event);
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vid_poll_kb (SIM_KEY_EVENT *ev)
|
|
{
|
|
if (SDL_SemTryWait (vid_key_events.sem) == 0) { /* get lock */
|
|
if (vid_key_events.count > 0) { /* events in queue? */
|
|
*ev = vid_key_events.events[vid_key_events.head++];
|
|
vid_key_events.count--;
|
|
if (vid_key_events.head == MAX_EVENTS)
|
|
vid_key_events.head = 0;
|
|
SDL_SemPost (vid_key_events.sem);
|
|
return SCPE_OK;
|
|
}
|
|
SDL_SemPost (vid_key_events.sem);
|
|
}
|
|
return SCPE_EOF;
|
|
}
|
|
|
|
t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev)
|
|
{
|
|
if (SDL_SemTryWait (vid_mouse_events.sem) == 0) {
|
|
if (vid_mouse_events.count > 0) {
|
|
*ev = vid_mouse_events.events[vid_mouse_events.head++];
|
|
vid_mouse_events.count--;
|
|
if (vid_mouse_events.head == MAX_EVENTS)
|
|
vid_mouse_events.head = 0;
|
|
SDL_SemPost (vid_mouse_events.sem);
|
|
return SCPE_OK;
|
|
}
|
|
SDL_SemPost (vid_mouse_events.sem);
|
|
}
|
|
return SCPE_EOF;
|
|
}
|
|
|
|
void vid_draw (int32 x, int32 y, int32 w, int32 h, uint8 *buf)
|
|
{
|
|
int32 i, j;
|
|
uint8* pix;
|
|
|
|
pix = (uint8 *)vid_image->pixels;
|
|
pix = pix + (y * vid_width) + x;
|
|
|
|
for (i = y; i < (y + h); i++) {
|
|
for (j = x; j < (x + w); j++) {
|
|
*pix++ = *buf++;
|
|
}
|
|
pix = pix + vid_width;
|
|
}
|
|
}
|
|
|
|
void vid_refresh (void)
|
|
{
|
|
SDL_Event user_event;
|
|
|
|
user_event.type = SDL_USEREVENT;
|
|
user_event.user.code = EVENT_REDRAW;
|
|
user_event.user.data1 = NULL;
|
|
user_event.user.data2 = NULL;
|
|
|
|
SDL_PushEvent (&user_event);
|
|
}
|
|
|
|
int vid_map_key (int key)
|
|
{
|
|
switch (key) {
|
|
|
|
case SDLK_BACKSPACE:
|
|
return SIM_KEY_BACKSPACE;
|
|
|
|
case SDLK_TAB:
|
|
return SIM_KEY_TAB;
|
|
|
|
case SDLK_RETURN:
|
|
return SIM_KEY_ENTER;
|
|
|
|
case SDLK_PAUSE:
|
|
return SIM_KEY_PAUSE;
|
|
|
|
case SDLK_ESCAPE:
|
|
return SIM_KEY_ESC;
|
|
|
|
case SDLK_SPACE:
|
|
return SIM_KEY_SPACE;
|
|
|
|
case SDLK_QUOTE:
|
|
return SIM_KEY_SINGLE_QUOTE;
|
|
|
|
case SDLK_COMMA:
|
|
return SIM_KEY_COMMA;
|
|
|
|
case SDLK_MINUS:
|
|
return SIM_KEY_MINUS;
|
|
|
|
case SDLK_PERIOD:
|
|
return SIM_KEY_PERIOD;
|
|
|
|
case SDLK_SLASH:
|
|
return SIM_KEY_SLASH;
|
|
|
|
case SDLK_0:
|
|
return SIM_KEY_0;
|
|
|
|
case SDLK_1:
|
|
return SIM_KEY_1;
|
|
|
|
case SDLK_2:
|
|
return SIM_KEY_2;
|
|
|
|
case SDLK_3:
|
|
return SIM_KEY_3;
|
|
|
|
case SDLK_4:
|
|
return SIM_KEY_4;
|
|
|
|
case SDLK_5:
|
|
return SIM_KEY_5;
|
|
|
|
case SDLK_6:
|
|
return SIM_KEY_6;
|
|
|
|
case SDLK_7:
|
|
return SIM_KEY_7;
|
|
|
|
case SDLK_8:
|
|
return SIM_KEY_8;
|
|
|
|
case SDLK_9:
|
|
return SIM_KEY_9;
|
|
|
|
case SDLK_SEMICOLON:
|
|
return SIM_KEY_SEMICOLON;
|
|
|
|
case SDLK_EQUALS:
|
|
return SIM_KEY_EQUALS;
|
|
|
|
case SDLK_LEFTBRACKET:
|
|
return SIM_KEY_LEFT_BRACKET;
|
|
|
|
case SDLK_BACKSLASH:
|
|
return SIM_KEY_BACKSLASH;
|
|
|
|
case SDLK_RIGHTBRACKET:
|
|
return SIM_KEY_RIGHT_BRACKET;
|
|
|
|
case SDLK_BACKQUOTE:
|
|
return SIM_KEY_BACKQUOTE;
|
|
|
|
case SDLK_a:
|
|
return SIM_KEY_A;
|
|
|
|
case SDLK_b:
|
|
return SIM_KEY_B;
|
|
|
|
case SDLK_c:
|
|
return SIM_KEY_C;
|
|
|
|
case SDLK_d:
|
|
return SIM_KEY_D;
|
|
|
|
case SDLK_e:
|
|
return SIM_KEY_E;
|
|
|
|
case SDLK_f:
|
|
return SIM_KEY_F;
|
|
|
|
case SDLK_g:
|
|
return SIM_KEY_G;
|
|
|
|
case SDLK_h:
|
|
return SIM_KEY_H;
|
|
|
|
case SDLK_i:
|
|
return SIM_KEY_I;
|
|
|
|
case SDLK_j:
|
|
return SIM_KEY_J;
|
|
|
|
case SDLK_k:
|
|
return SIM_KEY_K;
|
|
|
|
case SDLK_l:
|
|
return SIM_KEY_L;
|
|
|
|
case SDLK_m:
|
|
return SIM_KEY_M;
|
|
|
|
case SDLK_n:
|
|
return SIM_KEY_N;
|
|
|
|
case SDLK_o:
|
|
return SIM_KEY_O;
|
|
|
|
case SDLK_p:
|
|
return SIM_KEY_P;
|
|
|
|
case SDLK_q:
|
|
return SIM_KEY_Q;
|
|
|
|
case SDLK_r:
|
|
return SIM_KEY_R;
|
|
|
|
case SDLK_s:
|
|
return SIM_KEY_S;
|
|
|
|
case SDLK_t:
|
|
return SIM_KEY_T;
|
|
|
|
case SDLK_u:
|
|
return SIM_KEY_U;
|
|
|
|
case SDLK_v:
|
|
return SIM_KEY_V;
|
|
|
|
case SDLK_w:
|
|
return SIM_KEY_W;
|
|
|
|
case SDLK_x:
|
|
return SIM_KEY_X;
|
|
|
|
case SDLK_y:
|
|
return SIM_KEY_Y;
|
|
|
|
case SDLK_z:
|
|
return SIM_KEY_Z;
|
|
|
|
case SDLK_DELETE:
|
|
return SIM_KEY_DELETE;
|
|
|
|
case SDLK_KP0:
|
|
return SIM_KEY_KP_INSERT;
|
|
|
|
case SDLK_KP1:
|
|
return SIM_KEY_KP_END;
|
|
|
|
case SDLK_KP2:
|
|
return SIM_KEY_KP_DOWN;
|
|
|
|
case SDLK_KP3:
|
|
return SIM_KEY_KP_PAGE_DOWN;
|
|
|
|
case SDLK_KP4:
|
|
return SIM_KEY_KP_LEFT;
|
|
|
|
case SDLK_KP5:
|
|
return SIM_KEY_KP_5;
|
|
|
|
case SDLK_KP6:
|
|
return SIM_KEY_KP_RIGHT;
|
|
|
|
case SDLK_KP7:
|
|
return SIM_KEY_KP_HOME;
|
|
|
|
case SDLK_KP8:
|
|
return SIM_KEY_KP_UP;
|
|
|
|
case SDLK_KP9:
|
|
return SIM_KEY_KP_PAGE_UP;
|
|
|
|
case SDLK_KP_PERIOD:
|
|
return SIM_KEY_KP_DELETE;
|
|
|
|
case SDLK_KP_DIVIDE:
|
|
return SIM_KEY_KP_DIVIDE;
|
|
|
|
case SDLK_KP_MULTIPLY:
|
|
return SIM_KEY_KP_MULTIPLY;
|
|
|
|
case SDLK_KP_MINUS:
|
|
return SIM_KEY_KP_SUBTRACT;
|
|
|
|
case SDLK_KP_PLUS:
|
|
return SIM_KEY_KP_ADD;
|
|
|
|
case SDLK_KP_ENTER:
|
|
return SIM_KEY_KP_ENTER;
|
|
|
|
case SDLK_UP:
|
|
return SIM_KEY_UP;
|
|
|
|
case SDLK_DOWN:
|
|
return SIM_KEY_DOWN;
|
|
|
|
case SDLK_RIGHT:
|
|
return SIM_KEY_RIGHT;
|
|
|
|
case SDLK_LEFT:
|
|
return SIM_KEY_LEFT;
|
|
|
|
case SDLK_INSERT:
|
|
return SIM_KEY_INSERT;
|
|
|
|
case SDLK_HOME:
|
|
return SIM_KEY_HOME;
|
|
|
|
case SDLK_END:
|
|
return SIM_KEY_END;
|
|
|
|
case SDLK_PAGEUP:
|
|
return SIM_KEY_PAGE_UP;
|
|
|
|
case SDLK_PAGEDOWN:
|
|
return SIM_KEY_PAGE_DOWN;
|
|
|
|
case SDLK_F1:
|
|
return SIM_KEY_F1;
|
|
|
|
case SDLK_F2:
|
|
return SIM_KEY_F2;
|
|
|
|
case SDLK_F3:
|
|
return SIM_KEY_F3;
|
|
|
|
case SDLK_F4:
|
|
return SIM_KEY_F4;
|
|
|
|
case SDLK_F5:
|
|
return SIM_KEY_F5;
|
|
|
|
case SDLK_F6:
|
|
return SIM_KEY_F6;
|
|
|
|
case SDLK_F7:
|
|
return SIM_KEY_F7;
|
|
|
|
case SDLK_F8:
|
|
return SIM_KEY_F8;
|
|
|
|
case SDLK_F9:
|
|
return SIM_KEY_F9;
|
|
|
|
case SDLK_F10:
|
|
return SIM_KEY_F10;
|
|
|
|
case SDLK_F11:
|
|
return SIM_KEY_F11;
|
|
|
|
case SDLK_F12:
|
|
return SIM_KEY_F12;
|
|
|
|
case SDLK_NUMLOCK:
|
|
return SIM_KEY_NUM_LOCK;
|
|
|
|
case SDLK_CAPSLOCK:
|
|
return SIM_KEY_CAPS_LOCK;
|
|
|
|
case SDLK_SCROLLOCK:
|
|
return SIM_KEY_SCRL_LOCK;
|
|
|
|
case SDLK_RSHIFT:
|
|
return SIM_KEY_SHIFT_R;
|
|
|
|
case SDLK_LSHIFT:
|
|
return SIM_KEY_SHIFT_L;
|
|
|
|
case SDLK_RCTRL:
|
|
return SIM_KEY_CTRL_R;
|
|
|
|
case SDLK_LCTRL:
|
|
return SIM_KEY_CTRL_L;
|
|
|
|
case SDLK_RALT:
|
|
return SIM_KEY_ALT_R;
|
|
|
|
case SDLK_LALT:
|
|
return SIM_KEY_ALT_L;
|
|
|
|
case SDLK_RMETA:
|
|
return SIM_KEY_ALT_R;
|
|
|
|
case SDLK_LMETA:
|
|
return SIM_KEY_WIN_L;
|
|
|
|
case SDLK_LSUPER:
|
|
return SIM_KEY_WIN_L;
|
|
|
|
case SDLK_RSUPER:
|
|
return SIM_KEY_WIN_R;
|
|
|
|
case SDLK_PRINT:
|
|
return SIM_KEY_PRINT;
|
|
|
|
case SDLK_BREAK:
|
|
return SIM_KEY_PAUSE;
|
|
|
|
case SDLK_MENU:
|
|
return SIM_KEY_MENU;
|
|
|
|
default:
|
|
return SIM_KEY_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
void vid_key (SDL_KeyboardEvent *event)
|
|
{
|
|
SIM_KEY_EVENT ev;
|
|
|
|
if (vid_mouse_captured) {
|
|
static Uint8 *KeyStates = NULL;
|
|
static int numkeys;
|
|
|
|
if (!KeyStates)
|
|
KeyStates = SDL_GetKeyState(&numkeys);
|
|
if ((event->state == SDL_PRESSED) && KeyStates[SDLK_RSHIFT] && (KeyStates[SDLK_LCTRL] || KeyStates[SDLK_RCTRL])) {
|
|
SDL_WM_GrabInput (SDL_GRAB_OFF); /* relese cursor */
|
|
SDL_ShowCursor (SDL_ENABLE); /* show cursor */
|
|
vid_mouse_captured = FALSE;
|
|
return;
|
|
}
|
|
}
|
|
if (!sim_is_running)
|
|
return;
|
|
if (SDL_SemWait (vid_key_events.sem) == 0) {
|
|
if (vid_key_events.count < MAX_EVENTS) {
|
|
if (event->state == SDL_PRESSED) {
|
|
if (!vid_key_state[event->keysym.sym]) { /* Key was not down before */
|
|
vid_key_state[event->keysym.sym] = TRUE;
|
|
ev.key = vid_map_key (event->keysym.sym);
|
|
ev.state = SIM_KEYPRESS_DOWN;
|
|
}
|
|
else {
|
|
ev.key = vid_map_key (event->keysym.sym);
|
|
ev.state = SIM_KEYPRESS_REPEAT;
|
|
}
|
|
}
|
|
else {
|
|
vid_key_state[event->keysym.sym] = FALSE;
|
|
ev.key = vid_map_key (event->keysym.sym);
|
|
ev.state = SIM_KEYPRESS_UP;
|
|
}
|
|
vid_key_events.events[vid_key_events.tail++] = ev;
|
|
vid_key_events.count++;
|
|
if (vid_key_events.tail == MAX_EVENTS)
|
|
vid_key_events.tail = 0;
|
|
}
|
|
SDL_SemPost (vid_key_events.sem);
|
|
}
|
|
}
|
|
|
|
void vid_mouse_move (SDL_MouseMotionEvent *event)
|
|
{
|
|
SDL_Event dummy_event;
|
|
int32 cx;
|
|
int32 cy;
|
|
SIM_MOUSE_EVENT ev;
|
|
|
|
if (!vid_mouse_captured)
|
|
return;
|
|
|
|
if ((event->x == 0) ||
|
|
(event->y == 0) ||
|
|
(event->x == (vid_width - 1)) ||
|
|
(event->y == (vid_height - 1))) { /* reached edge of window? */
|
|
cx = vid_width / 2;
|
|
cy = vid_height / 2;
|
|
SDL_WarpMouse (cx, cy); /* back to centre */
|
|
SDL_PumpEvents ();
|
|
while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)) {};
|
|
}
|
|
if (!sim_is_running)
|
|
return;
|
|
if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
|
if (vid_mouse_events.count < MAX_EVENTS) {
|
|
ev.x_rel = event->xrel;
|
|
ev.y_rel = (-event->yrel);
|
|
ev.b1_state = (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? TRUE : FALSE;
|
|
ev.b2_state = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? TRUE : FALSE;
|
|
ev.b3_state = (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? TRUE : FALSE;
|
|
vid_mouse_events.b1_state = ev.b1_state;
|
|
vid_mouse_events.b2_state = ev.b2_state;
|
|
vid_mouse_events.b3_state = ev.b3_state;
|
|
vid_mouse_events.events[vid_mouse_events.tail++] = ev;
|
|
vid_mouse_events.count++;
|
|
if (vid_mouse_events.tail == MAX_EVENTS)
|
|
vid_mouse_events.tail = 0;
|
|
}
|
|
SDL_SemPost (vid_mouse_events.sem);
|
|
}
|
|
}
|
|
|
|
void vid_mouse_button (SDL_MouseButtonEvent *event)
|
|
{
|
|
SDL_Event dummy_event;
|
|
int32 cx;
|
|
int32 cy;
|
|
SIM_MOUSE_EVENT ev;
|
|
t_bool state;
|
|
|
|
if (!vid_mouse_captured) {
|
|
if ((event->state == SDL_PRESSED) &&
|
|
(event->button == SDL_BUTTON_LEFT)) { /* left click and cursor not captured? */
|
|
SDL_WM_GrabInput (SDL_GRAB_ON); /* lock cursor to window */
|
|
SDL_ShowCursor (SDL_DISABLE); /* hide cursor */
|
|
cx = vid_width / 2;
|
|
cy = vid_height / 2;
|
|
SDL_WarpMouse (cx, cy); /* move cursor to centre of window */
|
|
SDL_PumpEvents ();
|
|
while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)) {};
|
|
vid_mouse_captured = TRUE;
|
|
}
|
|
return;
|
|
}
|
|
if (!sim_is_running)
|
|
return;
|
|
if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
|
if (vid_mouse_events.count < MAX_EVENTS) {
|
|
state = (event->state == SDL_PRESSED) ? TRUE : FALSE;
|
|
ev.x_rel = 0;
|
|
ev.y_rel = 0;
|
|
switch (event->button) {
|
|
case SDL_BUTTON_LEFT:
|
|
vid_mouse_events.b1_state = state;
|
|
break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
vid_mouse_events.b2_state = state;
|
|
break;
|
|
case SDL_BUTTON_RIGHT:
|
|
vid_mouse_events.b3_state = state;
|
|
break;
|
|
}
|
|
ev.b1_state = vid_mouse_events.b1_state;
|
|
ev.b2_state = vid_mouse_events.b2_state;
|
|
ev.b3_state = vid_mouse_events.b3_state;
|
|
vid_mouse_events.events[vid_mouse_events.tail++] = ev;
|
|
vid_mouse_events.count++;
|
|
if (vid_mouse_events.tail == MAX_EVENTS)
|
|
vid_mouse_events.tail = 0;
|
|
}
|
|
SDL_SemPost (vid_mouse_events.sem);
|
|
}
|
|
}
|
|
|
|
void vid_update (void)
|
|
{
|
|
SDL_Rect vid_dst;
|
|
|
|
vid_dst.x = 0;
|
|
vid_dst.y = 0;
|
|
vid_dst.w = vid_width;
|
|
vid_dst.h = vid_height;
|
|
|
|
SDL_BlitSurface (vid_image, NULL, vid_window, &vid_dst);
|
|
SDL_UpdateRects (vid_window, 1, &vid_dst);
|
|
}
|
|
|
|
int vid_thread (void* arg)
|
|
{
|
|
int vid_bpp = 8;
|
|
int vid_flags = 0;
|
|
SDL_Event event;
|
|
|
|
if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0) {
|
|
return SCPE_OPENERR;
|
|
}
|
|
|
|
vid_window = SDL_SetVideoMode (vid_width, vid_height, vid_bpp, vid_flags);
|
|
|
|
if (vid_window == NULL) {
|
|
return SCPE_OPENERR;
|
|
}
|
|
|
|
if (SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL) < 0) {
|
|
return SCPE_OPENERR;
|
|
}
|
|
|
|
SDL_WM_SetCaption (&sim_name[0], &sim_name[0]);
|
|
|
|
while (vid_active) {
|
|
if (SDL_WaitEvent (&event)) {
|
|
switch (event.type) {
|
|
|
|
case SDL_KEYDOWN:
|
|
case SDL_KEYUP:
|
|
vid_key ((SDL_KeyboardEvent*)&event);
|
|
break;
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
case SDL_MOUSEBUTTONUP:
|
|
vid_mouse_button ((SDL_MouseButtonEvent*)&event);
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
vid_mouse_move ((SDL_MouseMotionEvent*)&event);
|
|
break;
|
|
|
|
case SDL_USEREVENT:
|
|
if (event.user.code == EVENT_REDRAW)
|
|
vid_update ();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
SDL_Quit ();
|
|
return 0;
|
|
}
|
|
|
|
const char *vid_version(void)
|
|
{
|
|
static char SDLVersion[80];
|
|
const SDL_version *ver = SDL_Linked_Version();
|
|
|
|
sprintf(SDLVersion, "SDL Version %d.%d.%d", ver->major, ver->minor, ver->patch);
|
|
return (const char *)SDLVersion;
|
|
}
|
|
|
|
t_stat vid_set_release_key (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|
{
|
|
return SCPE_NOFNC;
|
|
}
|
|
|
|
t_stat vid_show_release_key (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|
{
|
|
fprintf (st, "ReleaseKey=Ctrl-Right-Shift");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
#else
|
|
|
|
/* Non-implemented versions */
|
|
|
|
t_stat vid_open (uint32 width, uint32 height)
|
|
{
|
|
return SCPE_NOFNC;
|
|
}
|
|
|
|
t_stat vid_close (void)
|
|
{
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vid_poll_kb (SIM_KEY_EVENT *ev)
|
|
{
|
|
return SCPE_EOF;
|
|
}
|
|
|
|
t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev)
|
|
{
|
|
return SCPE_EOF;
|
|
}
|
|
|
|
void vid_draw (int32 x, int32 y, int32 w, int32 h, uint8 *buf)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void vid_refresh (void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const char *vid_version (void)
|
|
{
|
|
return "No Video Support";
|
|
}
|
|
|
|
t_stat vid_set_release_key (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|
{
|
|
return SCPE_NOFNC;
|
|
}
|
|
|
|
t_stat vid_show_release_key (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|
{
|
|
fprintf (st, "no release key");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
|
|
#endif
|