1 |
|
/* |
2 |
|
* video_sdl.cpp - Video/graphics emulation, SDL specific stuff |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2004 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2005 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
56 |
|
#include "video.h" |
57 |
|
#include "video_defs.h" |
58 |
|
#include "video_blit.h" |
59 |
+ |
#include "vm_alloc.h" |
60 |
|
|
61 |
|
#define DEBUG 0 |
62 |
|
#include "debug.h" |
82 |
|
#endif |
83 |
|
|
84 |
|
// Constants |
85 |
+ |
#ifdef WIN32 |
86 |
+ |
const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes"; |
87 |
+ |
#else |
88 |
|
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; |
89 |
+ |
#endif |
90 |
|
|
91 |
|
|
92 |
|
// Global variables |
101 |
|
static bool redraw_thread_active = false; // Flag: Redraw thread installed |
102 |
|
static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread |
103 |
|
static SDL_Thread *redraw_thread = NULL; // Redraw thread |
104 |
+ |
static volatile bool thread_stop_req = false; |
105 |
+ |
static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req |
106 |
|
|
107 |
|
#ifdef ENABLE_VOSF |
108 |
|
static bool use_vosf = false; // Flag: VOSF enabled |
152 |
|
|
153 |
|
|
154 |
|
/* |
155 |
+ |
* Framebuffer allocation routines |
156 |
+ |
*/ |
157 |
+ |
|
158 |
+ |
static void *vm_acquire_framebuffer(uint32 size) |
159 |
+ |
{ |
160 |
+ |
#ifdef SHEEPSHAVER |
161 |
+ |
#ifdef DIRECT_ADDRESSING_HACK |
162 |
+ |
const uint32 FRAME_BUFFER_BASE = 0x61000000; |
163 |
+ |
uint8 *fb = Mac2HostAddr(FRAME_BUFFER_BASE); |
164 |
+ |
if (vm_acquire_fixed(fb, size) < 0) |
165 |
+ |
fb = VM_MAP_FAILED; |
166 |
+ |
return fb; |
167 |
+ |
#endif |
168 |
+ |
#endif |
169 |
+ |
return vm_acquire(size); |
170 |
+ |
} |
171 |
+ |
|
172 |
+ |
static inline void vm_release_framebuffer(void *fb, uint32 size) |
173 |
+ |
{ |
174 |
+ |
vm_release(fb, size); |
175 |
+ |
} |
176 |
+ |
|
177 |
+ |
|
178 |
+ |
/* |
179 |
|
* SheepShaver glue |
180 |
|
*/ |
181 |
|
|
585 |
|
if (s) |
586 |
|
SDL_FreeSurface(s); |
587 |
|
|
588 |
+ |
// the_buffer shall always be mapped through vm_acquire_framebuffer() |
589 |
+ |
if (the_buffer != VM_MAP_FAILED) { |
590 |
+ |
D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); |
591 |
+ |
vm_release_framebuffer(the_buffer, the_buffer_size); |
592 |
+ |
the_buffer = NULL; |
593 |
+ |
} |
594 |
+ |
|
595 |
|
// Free frame buffer(s) |
596 |
|
if (!use_vosf) { |
559 |
– |
if (the_buffer) { |
560 |
– |
free(the_buffer); |
561 |
– |
the_buffer = NULL; |
562 |
– |
} |
597 |
|
if (the_buffer_copy) { |
598 |
|
free(the_buffer_copy); |
599 |
|
the_buffer_copy = NULL; |
601 |
|
} |
602 |
|
#ifdef ENABLE_VOSF |
603 |
|
else { |
570 |
– |
// the_buffer shall always be mapped through vm_acquire() so that we can vm_protect() it at will |
571 |
– |
if (the_buffer != VM_MAP_FAILED) { |
572 |
– |
D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); |
573 |
– |
vm_release(the_buffer, the_buffer_size); |
574 |
– |
the_buffer = NULL; |
575 |
– |
} |
604 |
|
if (the_host_buffer) { |
605 |
|
D(bug(" freeing the_host_buffer at %p\n", the_host_buffer)); |
606 |
|
free(the_host_buffer); |
611 |
|
free(the_buffer_copy); |
612 |
|
the_buffer_copy = NULL; |
613 |
|
} |
614 |
+ |
|
615 |
+ |
// Deinitialize VOSF |
616 |
+ |
video_vosf_exit(); |
617 |
|
} |
618 |
|
#endif |
619 |
|
} |
663 |
|
// Allocate memory for frame buffer (SIZE is extended to page-boundary) |
664 |
|
the_host_buffer = (uint8 *)s->pixels; |
665 |
|
the_buffer_size = page_extend((aligned_height + 2) * s->pitch); |
666 |
< |
the_buffer = (uint8 *)vm_acquire(the_buffer_size); |
666 |
> |
the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); |
667 |
|
the_buffer_copy = (uint8 *)malloc(the_buffer_size); |
668 |
|
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); |
669 |
|
|
687 |
|
// Allocate memory for frame buffer |
688 |
|
the_buffer_size = (aligned_height + 2) * s->pitch; |
689 |
|
the_buffer_copy = (uint8 *)calloc(1, the_buffer_size); |
690 |
< |
the_buffer = (uint8 *)calloc(1, the_buffer_size); |
690 |
> |
the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); |
691 |
|
D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); |
692 |
|
} |
693 |
|
|
810 |
|
SDL_VideoDriverName(video_driver, sizeof(video_driver)); |
811 |
|
bool video_driver_found = false; |
812 |
|
char line[256]; |
813 |
+ |
int n_keys = 0; |
814 |
|
while (fgets(line, sizeof(line) - 1, f)) { |
815 |
|
// Read line |
816 |
|
int len = strlen(line); |
823 |
|
continue; |
824 |
|
|
825 |
|
if (video_driver_found) { |
826 |
< |
// Skip aliases |
826 |
> |
// Skip aliases as long as we have read keycodes yet |
827 |
> |
// Otherwise, it's another mapping and we have to stop |
828 |
|
static const char sdl_str[] = "sdl"; |
829 |
< |
if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) |
829 |
> |
if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0 && n_keys == 0) |
830 |
|
continue; |
831 |
|
|
832 |
|
// Read keycode |
833 |
|
int x_code, mac_code; |
834 |
|
if (sscanf(line, "%d %d", &x_code, &mac_code) == 2) |
835 |
< |
keycode_table[x_code & 0xff] = mac_code; |
835 |
> |
keycode_table[x_code & 0xff] = mac_code, n_keys++; |
836 |
|
else |
837 |
|
break; |
838 |
|
} else { |
857 |
|
WarningAlert(str); |
858 |
|
return; |
859 |
|
} |
860 |
+ |
|
861 |
+ |
D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver, n_keys)); |
862 |
|
} |
863 |
|
} |
864 |
|
|
959 |
|
int max_width = 640, max_height = 480; |
960 |
|
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); |
961 |
|
if (modes && modes != (SDL_Rect **)-1) { |
962 |
< |
max_width = modes[0]->w; |
963 |
< |
max_height = modes[0]->h; |
962 |
> |
// It turns out that on some implementations, and contrary to the documentation, |
963 |
> |
// the returned list is not sorted from largest to smallest (e.g. Windows) |
964 |
> |
for (int i = 0; modes[i] != NULL; i++) { |
965 |
> |
const int w = modes[i]->w; |
966 |
> |
const int h = modes[i]->h; |
967 |
> |
if (w > max_width && h > max_height) { |
968 |
> |
max_width = w; |
969 |
> |
max_height = h; |
970 |
> |
} |
971 |
> |
} |
972 |
|
if (default_width > max_width) |
973 |
|
default_width = max_width; |
974 |
|
if (default_height > max_height) |
1091 |
|
UNLOCK_FRAME_BUFFER; |
1092 |
|
D(bug(" frame buffer unlocked\n")); |
1093 |
|
|
1051 |
– |
#ifdef ENABLE_VOSF |
1052 |
– |
if (use_vosf) { |
1053 |
– |
// Deinitialize VOSF |
1054 |
– |
video_vosf_exit(); |
1055 |
– |
} |
1056 |
– |
#endif |
1057 |
– |
|
1094 |
|
// Close display |
1095 |
|
delete drv; |
1096 |
|
drv = NULL; |
1249 |
|
csSave->saveData = ReadMacInt32(ParamPtr + csData); |
1250 |
|
csSave->savePage = ReadMacInt16(ParamPtr + csPage); |
1251 |
|
|
1252 |
< |
// Disable interrupts |
1252 |
> |
// Disable interrupts and pause redraw thread |
1253 |
|
DisableInterrupt(); |
1254 |
+ |
thread_stop_ack = false; |
1255 |
+ |
thread_stop_req = true; |
1256 |
+ |
while (!thread_stop_ack) ; |
1257 |
|
|
1258 |
|
cur_mode = i; |
1259 |
|
monitor_desc *monitor = VideoMonitors[0]; |
1264 |
|
csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ |
1265 |
|
csSave->saveMode=VModes[cur_mode].viAppleMode; |
1266 |
|
|
1267 |
< |
// Enable interrupts |
1267 |
> |
// Enable interrupts and resume redraw thread |
1268 |
> |
thread_stop_req = false; |
1269 |
|
EnableInterrupt(); |
1270 |
|
return noErr; |
1271 |
|
} |
1381 |
|
|
1382 |
|
case SDLK_1: case SDLK_EXCLAIM: return 0x12; |
1383 |
|
case SDLK_2: case SDLK_AT: return 0x13; |
1384 |
< |
// case SDLK_3: case SDLK_numbersign: return 0x14; |
1384 |
> |
case SDLK_3: case SDLK_HASH: return 0x14; |
1385 |
|
case SDLK_4: case SDLK_DOLLAR: return 0x15; |
1386 |
< |
// case SDLK_5: case SDLK_percent: return 0x17; |
1386 |
> |
case SDLK_5: return 0x17; |
1387 |
|
case SDLK_6: return 0x16; |
1388 |
|
case SDLK_7: return 0x1a; |
1389 |
|
case SDLK_8: return 0x1c; |
1390 |
|
case SDLK_9: return 0x19; |
1391 |
|
case SDLK_0: return 0x1d; |
1392 |
|
|
1393 |
< |
// case SDLK_BACKQUOTE: case SDLK_asciitilde: return 0x0a; |
1393 |
> |
case SDLK_BACKQUOTE: return 0x0a; |
1394 |
|
case SDLK_MINUS: case SDLK_UNDERSCORE: return 0x1b; |
1395 |
|
case SDLK_EQUALS: case SDLK_PLUS: return 0x18; |
1396 |
< |
// case SDLK_bracketleft: case SDLK_braceleft: return 0x21; |
1397 |
< |
// case SDLK_bracketright: case SDLK_braceright: return 0x1e; |
1398 |
< |
// case SDLK_BACKSLASH: case SDLK_bar: return 0x2a; |
1396 |
> |
case SDLK_LEFTBRACKET: return 0x21; |
1397 |
> |
case SDLK_RIGHTBRACKET: return 0x1e; |
1398 |
> |
case SDLK_BACKSLASH: return 0x2a; |
1399 |
|
case SDLK_SEMICOLON: case SDLK_COLON: return 0x29; |
1400 |
< |
// case SDLK_apostrophe: case SDLK_QUOTEDBL: return 0x27; |
1400 |
> |
case SDLK_QUOTE: case SDLK_QUOTEDBL: return 0x27; |
1401 |
|
case SDLK_COMMA: case SDLK_LESS: return 0x2b; |
1402 |
|
case SDLK_PERIOD: case SDLK_GREATER: return 0x2f; |
1403 |
|
case SDLK_SLASH: case SDLK_QUESTION: return 0x2c; |
1906 |
|
next = GetTicks_usec(); |
1907 |
|
ticks++; |
1908 |
|
|
1909 |
+ |
#ifdef SHEEPSHAVER |
1910 |
+ |
// Pause if requested (during video mode switches) |
1911 |
+ |
if (thread_stop_req) { |
1912 |
+ |
thread_stop_ack = true; |
1913 |
+ |
continue; |
1914 |
+ |
} |
1915 |
+ |
#endif |
1916 |
+ |
|
1917 |
|
// Handle SDL events |
1918 |
|
handle_events(); |
1919 |
|
|