e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | /* |
25 | * Xbios SDL video driver |
26 | * |
27 | * Patrice Mandin |
28 | */ |
29 | |
30 | #include <sys/stat.h> |
31 | #include <unistd.h> |
32 | |
33 | /* Mint includes */ |
34 | #include <mint/cookie.h> |
35 | #include <mint/osbind.h> |
36 | #include <mint/falcon.h> |
37 | |
38 | #include "SDL_video.h" |
39 | #include "SDL_mouse.h" |
40 | #include "../SDL_sysvideo.h" |
41 | #include "../SDL_pixels_c.h" |
42 | #include "../../events/SDL_events_c.h" |
43 | |
44 | #include "../ataricommon/SDL_ataric2p_s.h" |
45 | #include "../ataricommon/SDL_atarievents_c.h" |
46 | #include "../ataricommon/SDL_atarimxalloc_c.h" |
47 | #include "../ataricommon/SDL_atarigl_c.h" |
48 | #include "SDL_xbios.h" |
49 | #include "SDL_xbios_blowup.h" |
50 | #include "SDL_xbios_centscreen.h" |
51 | #include "SDL_xbios_sb3.h" |
52 | #include "SDL_xbios_tveille.h" |
53 | #include "SDL_xbios_milan.h" |
54 | |
55 | #define XBIOS_VID_DRIVER_NAME "xbios" |
56 | |
57 | #ifndef C_fVDI |
58 | #define C_fVDI 0x66564449L |
59 | #endif |
60 | |
61 | /* Debug print info */ |
62 | #if 0 |
63 | #define DEBUG_PRINT(what) \ |
64 | { \ |
65 | printf what; \ |
66 | } |
67 | #define DEBUG_VIDEO_XBIOS 1 |
68 | #else |
69 | #define DEBUG_PRINT(what) |
70 | #undef DEBUG_VIDEO_XBIOS |
71 | #endif |
72 | |
73 | /* Initialization/Query functions */ |
74 | static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat); |
75 | static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); |
76 | static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
77 | static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); |
78 | static void XBIOS_VideoQuit(_THIS); |
79 | |
80 | /* Hardware surface functions */ |
81 | static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface); |
82 | static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface); |
83 | static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface); |
84 | static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface); |
85 | static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface); |
86 | static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); |
87 | |
88 | #if SDL_VIDEO_OPENGL |
89 | /* OpenGL functions */ |
90 | static void XBIOS_GL_SwapBuffers(_THIS); |
91 | #endif |
92 | |
93 | /* To setup palette */ |
94 | |
95 | static unsigned short TT_palette[256]; |
96 | static unsigned long F30_palette[256]; |
97 | |
98 | /* Default list of video modes */ |
99 | |
100 | static const xbiosmode_t stmodes[1]={ |
101 | {ST_LOW>>8,320,200,4, XBIOSMODE_C2P} |
102 | }; |
103 | |
104 | static const xbiosmode_t ttmodes[2]={ |
105 | {TT_LOW,320,480,8, XBIOSMODE_C2P}, |
106 | {TT_LOW,320,240,8, XBIOSMODE_C2P|XBIOSMODE_DOUBLELINE} |
107 | }; |
108 | |
109 | static const xbiosmode_t falconrgbmodes[16]={ |
110 | {BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,0}, |
111 | {BPS16|COL80|OVERSCAN,768,240,16,0}, |
112 | {BPS16|COL80|VERTFLAG,640,400,16,0}, |
113 | {BPS16|COL80,640,200,16,0}, |
114 | {BPS16|OVERSCAN|VERTFLAG,384,480,16,0}, |
115 | {BPS16|OVERSCAN,384,240,16,0}, |
116 | {BPS16|VERTFLAG,320,400,16,0}, |
117 | {BPS16,320,200,16,0}, |
118 | {BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,XBIOSMODE_C2P}, |
119 | {BPS8|COL80|OVERSCAN,768,240,8,XBIOSMODE_C2P}, |
120 | {BPS8|COL80|VERTFLAG,640,400,8,XBIOSMODE_C2P}, |
121 | {BPS8|COL80,640,200,8,XBIOSMODE_C2P}, |
122 | {BPS8|OVERSCAN|VERTFLAG,384,480,8,XBIOSMODE_C2P}, |
123 | {BPS8|OVERSCAN,384,240,8,XBIOSMODE_C2P}, |
124 | {BPS8|VERTFLAG,320,400,8,XBIOSMODE_C2P}, |
125 | {BPS8,320,200,8,XBIOSMODE_C2P} |
126 | }; |
127 | |
128 | static const xbiosmode_t falconvgamodes[6]={ |
129 | {BPS16,320,480,16,0}, |
130 | {BPS16|VERTFLAG,320,240,16,0}, |
131 | {BPS8|COL80,640,480,8,XBIOSMODE_C2P}, |
132 | {BPS8|COL80|VERTFLAG,640,240,8,XBIOSMODE_C2P}, |
133 | {BPS8,320,480,8,XBIOSMODE_C2P}, |
134 | {BPS8|VERTFLAG,320,240,8,XBIOSMODE_C2P} |
135 | }; |
136 | |
137 | /* Xbios driver bootstrap functions */ |
138 | |
139 | static int XBIOS_Available(void) |
140 | { |
141 | unsigned long cookie_vdo, cookie_mil, cookie_hade, cookie_scpn; |
142 | unsigned long cookie_fvdi; |
143 | const char *envr = SDL_getenv("SDL_VIDEODRIVER"); |
144 | |
145 | /* Milan/Hades Atari clones do not have an Atari video chip */ |
146 | if ( /*(Getcookie(C__MIL, &cookie_mil) == C_FOUND) ||*/ |
147 | (Getcookie(C_hade, &cookie_hade) == C_FOUND) ) { |
148 | return 0; |
149 | } |
150 | |
151 | /* fVDI means graphic card, so no Xbios with it */ |
152 | if (Getcookie(C_fVDI, &cookie_fvdi) == C_FOUND) { |
153 | if (!envr) { |
154 | return 0; |
155 | } |
156 | if (SDL_strcmp(envr, XBIOS_VID_DRIVER_NAME)!=0) { |
157 | return 0; |
158 | } |
159 | /* Except if we force Xbios usage, through env var */ |
160 | } |
161 | |
162 | /* Cookie _VDO present ? if not, assume ST machine */ |
163 | if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) { |
164 | cookie_vdo = VDO_ST << 16; |
165 | } |
166 | |
167 | /* Test if we have a monochrome monitor plugged in */ |
168 | switch( cookie_vdo >>16) { |
169 | case VDO_ST: |
170 | case VDO_STE: |
171 | if ( Getrez() == (ST_HIGH>>8) ) |
172 | return 0; |
173 | break; |
174 | case VDO_TT: |
175 | if ( (EgetShift() & ES_MODE) == TT_HIGH) |
176 | return 0; |
177 | break; |
178 | case VDO_F30: |
179 | if ( VgetMonitor() == MONITOR_MONO) |
180 | return 0; |
181 | if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { |
182 | if (!SDL_XBIOS_SB3Usable((scpn_cookie_t *)cookie_scpn)) { |
183 | return 0; |
184 | } |
185 | } |
186 | break; |
187 | case VDO_MILAN: |
188 | break; |
189 | default: |
190 | return 0; |
191 | } |
192 | |
193 | return 1; |
194 | } |
195 | |
196 | static void XBIOS_DeleteDevice(SDL_VideoDevice *device) |
197 | { |
198 | SDL_free(device->hidden); |
199 | SDL_free(device); |
200 | } |
201 | |
202 | static SDL_VideoDevice *XBIOS_CreateDevice(int devindex) |
203 | { |
204 | SDL_VideoDevice *device; |
205 | |
206 | /* Initialize all variables that we clean on shutdown */ |
207 | device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); |
208 | if ( device ) { |
209 | SDL_memset(device, 0, (sizeof *device)); |
210 | device->hidden = (struct SDL_PrivateVideoData *) |
211 | SDL_malloc((sizeof *device->hidden)); |
212 | device->gl_data = (struct SDL_PrivateGLData *) |
213 | SDL_malloc((sizeof *device->gl_data)); |
214 | } |
215 | if ( (device == NULL) || (device->hidden == NULL) ) { |
216 | SDL_OutOfMemory(); |
217 | if ( device ) { |
218 | SDL_free(device); |
219 | } |
220 | return(0); |
221 | } |
222 | SDL_memset(device->hidden, 0, (sizeof *device->hidden)); |
223 | SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); |
224 | |
225 | /* Video functions */ |
226 | device->VideoInit = XBIOS_VideoInit; |
227 | device->ListModes = XBIOS_ListModes; |
228 | device->SetVideoMode = XBIOS_SetVideoMode; |
229 | device->SetColors = XBIOS_SetColors; |
230 | device->UpdateRects = NULL; |
231 | device->VideoQuit = XBIOS_VideoQuit; |
232 | device->AllocHWSurface = XBIOS_AllocHWSurface; |
233 | device->LockHWSurface = XBIOS_LockHWSurface; |
234 | device->UnlockHWSurface = XBIOS_UnlockHWSurface; |
235 | device->FlipHWSurface = XBIOS_FlipHWSurface; |
236 | device->FreeHWSurface = XBIOS_FreeHWSurface; |
237 | |
238 | #if SDL_VIDEO_OPENGL |
239 | /* OpenGL functions */ |
240 | device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; |
241 | device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; |
242 | device->GL_GetAttribute = SDL_AtariGL_GetAttribute; |
243 | device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; |
244 | device->GL_SwapBuffers = XBIOS_GL_SwapBuffers; |
245 | #endif |
246 | |
247 | /* Events */ |
248 | device->InitOSKeymap = Atari_InitOSKeymap; |
249 | device->PumpEvents = Atari_PumpEvents; |
250 | |
251 | device->free = XBIOS_DeleteDevice; |
252 | |
253 | return device; |
254 | } |
255 | |
256 | VideoBootStrap XBIOS_bootstrap = { |
257 | XBIOS_VID_DRIVER_NAME, "Atari Xbios driver", |
258 | XBIOS_Available, XBIOS_CreateDevice |
259 | }; |
260 | |
261 | void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo) |
262 | { |
263 | int i = 0; |
264 | |
265 | switch(modeinfo->depth) { |
266 | case 15: |
267 | case 16: |
268 | i = 1; |
269 | break; |
270 | case 24: |
271 | i = 2; |
272 | break; |
273 | case 32: |
274 | i = 3; |
275 | break; |
276 | } |
277 | |
278 | if ( actually_add ) { |
279 | SDL_Rect saved_rect[2]; |
280 | xbiosmode_t saved_mode[2]; |
281 | int b, j; |
282 | |
283 | /* Add the mode, sorted largest to smallest */ |
284 | b = 0; |
285 | j = 0; |
286 | while ( (SDL_modelist[i][j]->w > modeinfo->width) || |
287 | (SDL_modelist[i][j]->h > modeinfo->height) ) { |
288 | ++j; |
289 | } |
290 | /* Skip modes that are already in our list */ |
291 | if ( (SDL_modelist[i][j]->w == modeinfo->width) && |
292 | (SDL_modelist[i][j]->h == modeinfo->height) ) { |
293 | return; |
294 | } |
295 | /* Insert the new mode */ |
296 | saved_rect[b] = *SDL_modelist[i][j]; |
297 | SDL_memcpy(&saved_mode[b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); |
298 | SDL_modelist[i][j]->w = modeinfo->width; |
299 | SDL_modelist[i][j]->h = modeinfo->height; |
300 | SDL_memcpy(SDL_xbiosmode[i][j], modeinfo, sizeof(xbiosmode_t)); |
301 | /* Everybody scoot down! */ |
302 | if ( saved_rect[b].w && saved_rect[b].h ) { |
303 | for ( ++j; SDL_modelist[i][j]->w; ++j ) { |
304 | saved_rect[!b] = *SDL_modelist[i][j]; |
305 | memcpy(&saved_mode[!b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); |
306 | *SDL_modelist[i][j] = saved_rect[b]; |
307 | SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); |
308 | b = !b; |
309 | } |
310 | *SDL_modelist[i][j] = saved_rect[b]; |
311 | SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); |
312 | } |
313 | } else { |
314 | ++SDL_nummodes[i]; |
315 | } |
316 | } |
317 | |
318 | static void XBIOS_ListSTModes(_THIS, int actually_add) |
319 | { |
320 | SDL_XBIOS_AddMode(this, actually_add, &stmodes[0]); |
321 | } |
322 | |
323 | static void XBIOS_ListTTModes(_THIS, int actually_add) |
324 | { |
325 | int i; |
326 | |
327 | for (i=0; i<2; i++) { |
328 | SDL_XBIOS_AddMode(this, actually_add, &ttmodes[i]); |
329 | } |
330 | } |
331 | |
332 | static void XBIOS_ListFalconRgbModes(_THIS, int actually_add) |
333 | { |
334 | int i; |
335 | |
336 | for (i=0; i<16; i++) { |
337 | xbiosmode_t modeinfo; |
338 | |
339 | SDL_memcpy(&modeinfo, &falconrgbmodes[i], sizeof(xbiosmode_t)); |
340 | modeinfo.number &= ~(VGA|PAL); |
341 | modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); |
342 | |
343 | SDL_XBIOS_AddMode(this, actually_add, &modeinfo); |
344 | } |
345 | } |
346 | |
347 | static void XBIOS_ListFalconVgaModes(_THIS, int actually_add) |
348 | { |
349 | int i; |
350 | |
351 | for (i=0; i<6; i++) { |
352 | xbiosmode_t modeinfo; |
353 | |
354 | SDL_memcpy(&modeinfo, &falconvgamodes[i], sizeof(xbiosmode_t)); |
355 | modeinfo.number &= ~(VGA|PAL); |
356 | modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); |
357 | |
358 | SDL_XBIOS_AddMode(this, actually_add, &modeinfo); |
359 | } |
360 | } |
361 | |
362 | static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat) |
363 | { |
364 | int i,j8,j16; |
365 | xbiosmode_t *current_mode; |
366 | unsigned long cookie_blow, cookie_scpn, cookie_cnts; |
367 | |
368 | /* Initialize all variables that we clean on shutdown */ |
369 | for ( i=0; i<NUM_MODELISTS; ++i ) { |
370 | SDL_nummodes[i] = 0; |
371 | SDL_modelist[i] = NULL; |
372 | SDL_xbiosmode[i] = NULL; |
373 | } |
374 | |
375 | /* Cookie _VDO present ? if not, assume ST machine */ |
376 | if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) { |
377 | XBIOS_cvdo = VDO_ST << 16; |
378 | } |
379 | |
380 | /* Allocate memory for old palette */ |
381 | XBIOS_oldpalette = (void *)SDL_malloc(256*sizeof(long)); |
382 | if ( !XBIOS_oldpalette ) { |
383 | SDL_SetError("Unable to allocate memory for old palette\n"); |
384 | return(-1); |
385 | } |
386 | |
387 | /* Initialize video mode list */ |
388 | /* and save current screen status (palette, screen address, video mode) */ |
389 | XBIOS_centscreen = SDL_FALSE; |
390 | XBIOS_oldvbase = Physbase(); |
391 | |
392 | /* Determine the current screen size */ |
393 | this->info.current_w = 0; |
394 | this->info.current_h = 0; |
395 | |
396 | /* Determine the screen depth (use default 8-bit depth) */ |
397 | vformat->BitsPerPixel = 8; |
398 | |
399 | /* First allocate room for needed video modes */ |
400 | switch (XBIOS_cvdo >>16) { |
401 | case VDO_ST: |
402 | case VDO_STE: |
403 | { |
404 | short *oldpalette; |
405 | |
406 | XBIOS_oldvmode=Getrez(); |
407 | switch(XBIOS_oldvmode << 8) { |
408 | case ST_LOW: |
409 | XBIOS_oldnumcol=16; |
410 | break; |
411 | case ST_MED: |
412 | XBIOS_oldnumcol=4; |
413 | break; |
414 | case ST_HIGH: |
415 | XBIOS_oldnumcol=2; |
416 | break; |
417 | } |
418 | |
419 | oldpalette= (short *) XBIOS_oldpalette; |
420 | for (i=0;i<XBIOS_oldnumcol;i++) { |
421 | *oldpalette++=Setcolor(i,-1); |
422 | } |
423 | |
424 | XBIOS_ListSTModes(this, 0); |
425 | } |
426 | break; |
427 | case VDO_TT: |
428 | XBIOS_oldvmode=EgetShift(); |
429 | |
430 | switch(XBIOS_oldvmode & ES_MODE) { |
431 | case TT_LOW: |
432 | XBIOS_oldnumcol=256; |
433 | break; |
434 | case ST_LOW: |
435 | case TT_MED: |
436 | XBIOS_oldnumcol=16; |
437 | break; |
438 | case ST_MED: |
439 | XBIOS_oldnumcol=4; |
440 | break; |
441 | case ST_HIGH: |
442 | case TT_HIGH: |
443 | XBIOS_oldnumcol=2; |
444 | break; |
445 | } |
446 | if (XBIOS_oldnumcol) { |
447 | EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
448 | } |
449 | |
450 | XBIOS_ListTTModes(this, 0); |
451 | break; |
452 | case VDO_F30: |
453 | XBIOS_oldvmode=VsetMode(-1); |
454 | |
455 | XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS)); |
456 | if (XBIOS_oldnumcol > 256) { |
457 | XBIOS_oldnumcol = 0; |
458 | } |
459 | if (XBIOS_oldnumcol) { |
460 | VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
461 | } |
462 | |
463 | vformat->BitsPerPixel = 16; |
464 | |
465 | /* ScreenBlaster 3 ? */ |
466 | if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { |
467 | SDL_XBIOS_ListSB3Modes(this, 0, (scpn_cookie_t *)cookie_scpn); |
468 | } else |
469 | /* Centscreen ? */ |
470 | if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { |
471 | XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 0); |
472 | XBIOS_centscreen = SDL_TRUE; |
473 | } else |
474 | /* Standard, with or without Blowup */ |
475 | { |
476 | switch (VgetMonitor()) |
477 | { |
478 | case MONITOR_RGB: |
479 | case MONITOR_TV: |
480 | XBIOS_ListFalconRgbModes(this, 0); |
481 | break; |
482 | case MONITOR_VGA: |
483 | XBIOS_ListFalconVgaModes(this, 0); |
484 | break; |
485 | } |
486 | |
487 | if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { |
488 | SDL_XBIOS_ListBlowupModes(this, 0, (blow_cookie_t *)cookie_blow); |
489 | } |
490 | } |
491 | break; |
492 | case VDO_MILAN: |
493 | { |
494 | SCREENINFO si; |
495 | |
496 | /* Read infos about current mode */ |
497 | VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_GETMODE); |
498 | |
499 | si.size = sizeof(SCREENINFO); |
500 | si.devID = XBIOS_oldvmode; |
501 | si.scrFlags = 0; |
502 | VsetScreen(-1, &si, MI_MAGIC, CMD_GETINFO); |
503 | |
504 | this->info.current_w = si.scrWidth; |
505 | this->info.current_h = si.scrHeight; |
506 | |
507 | XBIOS_oldnumcol = 0; |
508 | if (si.scrFlags & SCRINFO_OK) { |
509 | if (si.scrPlanes <= 8) { |
510 | XBIOS_oldnumcol = 1<<si.scrPlanes; |
511 | } |
512 | } |
513 | if (XBIOS_oldnumcol) { |
514 | VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
515 | } |
516 | |
517 | SDL_XBIOS_ListMilanModes(this, 0); |
518 | } |
519 | break; |
520 | } |
521 | |
522 | for ( i=0; i<NUM_MODELISTS; ++i ) { |
523 | int j; |
524 | |
525 | SDL_xbiosmode[i] = (xbiosmode_t **) |
526 | SDL_malloc((SDL_nummodes[i]+1)*sizeof(xbiosmode_t *)); |
527 | if ( SDL_xbiosmode[i] == NULL ) { |
528 | SDL_OutOfMemory(); |
529 | return(-1); |
530 | } |
531 | for ( j=0; j<SDL_nummodes[i]; ++j ) { |
532 | SDL_xbiosmode[i][j]=(xbiosmode_t *)SDL_malloc(sizeof(xbiosmode_t)); |
533 | if ( SDL_xbiosmode[i][j] == NULL ) { |
534 | SDL_OutOfMemory(); |
535 | return(-1); |
536 | } |
537 | SDL_memset(SDL_xbiosmode[i][j], 0, sizeof(xbiosmode_t)); |
538 | } |
539 | SDL_xbiosmode[i][j] = NULL; |
540 | |
541 | SDL_modelist[i] = (SDL_Rect **) |
542 | SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); |
543 | if ( SDL_modelist[i] == NULL ) { |
544 | SDL_OutOfMemory(); |
545 | return(-1); |
546 | } |
547 | for ( j=0; j<SDL_nummodes[i]; ++j ) { |
548 | SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); |
549 | if ( SDL_modelist[i][j] == NULL ) { |
550 | SDL_OutOfMemory(); |
551 | return(-1); |
552 | } |
553 | SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); |
554 | } |
555 | SDL_modelist[i][j] = NULL; |
556 | } |
557 | |
558 | /* Now fill the mode list */ |
559 | switch (XBIOS_cvdo >>16) { |
560 | case VDO_ST: |
561 | case VDO_STE: |
562 | XBIOS_ListSTModes(this, 1); |
563 | break; |
564 | case VDO_TT: |
565 | XBIOS_ListTTModes(this, 1); |
566 | break; |
567 | case VDO_F30: |
568 | /* ScreenBlaster 3 ? */ |
569 | if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { |
570 | SDL_XBIOS_ListSB3Modes(this, 1, (scpn_cookie_t *)cookie_scpn); |
571 | } else |
572 | /* Centscreen ? */ |
573 | if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { |
574 | XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 1); |
575 | XBIOS_centscreen = SDL_TRUE; |
576 | } else |
577 | /* Standard, with or without Blowup */ |
578 | { |
579 | switch (VgetMonitor()) |
580 | { |
581 | case MONITOR_RGB: |
582 | case MONITOR_TV: |
583 | XBIOS_ListFalconRgbModes(this, 1); |
584 | break; |
585 | case MONITOR_VGA: |
586 | XBIOS_ListFalconVgaModes(this, 1); |
587 | break; |
588 | } |
589 | |
590 | if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { |
591 | SDL_XBIOS_ListBlowupModes(this, 1, (blow_cookie_t *)cookie_blow); |
592 | } |
593 | } |
594 | break; |
595 | case VDO_MILAN: |
596 | SDL_XBIOS_ListMilanModes(this, 1); |
597 | break; |
598 | } |
599 | |
600 | XBIOS_screens[0]=NULL; |
601 | XBIOS_screens[1]=NULL; |
602 | XBIOS_shadowscreen=NULL; |
603 | |
604 | /* Update hardware info */ |
605 | this->info.hw_available = 1; |
606 | this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM); |
607 | |
608 | /* Init chunky to planar routine */ |
609 | SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; |
610 | |
611 | #if SDL_VIDEO_OPENGL |
612 | SDL_AtariGL_InitPointers(this); |
613 | #endif |
614 | |
615 | /* Disable screensavers */ |
616 | if (SDL_XBIOS_TveillePresent(this)) { |
617 | SDL_XBIOS_TveilleDisable(this); |
618 | } |
619 | |
620 | /* We're done! */ |
621 | return(0); |
622 | } |
623 | |
624 | static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
625 | { |
626 | return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); |
627 | } |
628 | |
629 | static void XBIOS_FreeBuffers(_THIS) |
630 | { |
631 | int i; |
632 | |
633 | for (i=0;i<2;i++) { |
634 | if (XBIOS_screensmem[i]!=NULL) { |
635 | if ((XBIOS_cvdo>>16) == VDO_MILAN) { |
636 | if (i==1) { |
637 | VsetScreen(-1, -1, MI_MAGIC, CMD_FREEPAGE); |
638 | } |
639 | } else { |
640 | Mfree(XBIOS_screensmem[i]); |
641 | } |
642 | XBIOS_screensmem[i]=NULL; |
643 | } |
644 | } |
645 | |
646 | if (XBIOS_shadowscreen!=NULL) { |
647 | Mfree(XBIOS_shadowscreen); |
648 | XBIOS_shadowscreen=NULL; |
649 | } |
650 | } |
651 | |
652 | static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, |
653 | int width, int height, int bpp, Uint32 flags) |
654 | { |
655 | int mode, new_depth; |
656 | int i, num_buffers; |
657 | xbiosmode_t *new_video_mode; |
658 | Uint32 new_screen_size; |
659 | Uint32 modeflags; |
660 | |
661 | /* Free current buffers */ |
662 | XBIOS_FreeBuffers(this); |
663 | |
664 | /* Try to set the requested linear video mode */ |
665 | bpp = (bpp+7)/8-1; |
666 | for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { |
667 | if ( (SDL_modelist[bpp][mode]->w == width) && |
668 | (SDL_modelist[bpp][mode]->h == height) ) { |
669 | break; |
670 | } |
671 | } |
672 | if ( SDL_modelist[bpp][mode] == NULL ) { |
673 | SDL_SetError("Couldn't find requested mode in list"); |
674 | return(NULL); |
675 | } |
676 | new_video_mode = SDL_xbiosmode[bpp][mode]; |
677 | |
678 | modeflags = SDL_FULLSCREEN | SDL_PREALLOC; |
679 | |
680 | /* Allocate needed buffers: simple/double buffer and shadow surface */ |
681 | new_depth = new_video_mode->depth; |
682 | if (new_depth == 4) { |
683 | SDL_Atari_C2pConvert = SDL_Atari_C2pConvert4; |
684 | new_depth=8; |
685 | modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; |
686 | } else if (new_depth == 8) { |
687 | SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; |
688 | modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; |
689 | } else { |
690 | modeflags |= SDL_HWSURFACE; |
691 | } |
692 | |
693 | new_screen_size = width * height * ((new_depth)>>3); |
694 | new_screen_size += 256; /* To align on a 256 byte adress */ |
695 | |
696 | if (new_video_mode->flags & XBIOSMODE_C2P) { |
697 | XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM); |
698 | |
699 | if (XBIOS_shadowscreen == NULL) { |
700 | SDL_SetError("Can not allocate %d KB for shadow buffer", new_screen_size>>10); |
701 | return (NULL); |
702 | } |
703 | SDL_memset(XBIOS_shadowscreen, 0, new_screen_size); |
704 | } |
705 | |
706 | /* Output buffer needs to be twice in size for the software double-line mode */ |
707 | if (new_video_mode->flags & XBIOSMODE_DOUBLELINE) { |
708 | new_screen_size <<= 1; |
709 | } |
710 | |
711 | /* Double buffer ? */ |
712 | num_buffers = 1; |
713 | |
714 | #if SDL_VIDEO_OPENGL |
715 | if (flags & SDL_OPENGL) { |
716 | if (this->gl_config.double_buffer) { |
717 | flags |= SDL_DOUBLEBUF; |
718 | } |
719 | } |
720 | #endif |
721 | if ((flags & SDL_DOUBLEBUF) && ((XBIOS_cvdo>>16) != VDO_MILAN)) { |
722 | num_buffers = 2; |
723 | modeflags |= SDL_DOUBLEBUF; |
724 | } |
725 | |
726 | /* Allocate buffers */ |
727 | for (i=0; i<num_buffers; i++) { |
728 | if ((XBIOS_cvdo>>16) == VDO_MILAN) { |
729 | if (i==0) { |
730 | XBIOS_screensmem[i] = XBIOS_oldvbase; |
731 | } else { |
732 | VsetScreen(-1, &XBIOS_screensmem[i], MI_MAGIC, CMD_ALLOCPAGE); |
733 | } |
734 | } else { |
735 | XBIOS_screensmem[i] = Atari_SysMalloc(new_screen_size, MX_STRAM); |
736 | } |
737 | |
738 | if (XBIOS_screensmem[i]==NULL) { |
739 | XBIOS_FreeBuffers(this); |
740 | SDL_SetError("Can not allocate %d KB for buffer %d", new_screen_size>>10, i); |
741 | return (NULL); |
742 | } |
743 | SDL_memset(XBIOS_screensmem[i], 0, new_screen_size); |
744 | |
745 | XBIOS_screens[i]=(void *) (( (long) XBIOS_screensmem[i]+256) & 0xFFFFFF00UL); |
746 | } |
747 | |
748 | /* Allocate the new pixel format for the screen */ |
749 | if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) { |
750 | XBIOS_FreeBuffers(this); |
751 | SDL_SetError("Couldn't allocate new pixel format for requested mode"); |
752 | return(NULL); |
753 | } |
754 | |
755 | XBIOS_current = new_video_mode; |
756 | current->w = width; |
757 | current->h = height; |
758 | current->pitch = (width * new_depth)>>3; |
759 | |
760 | /* this is for C2P conversion */ |
761 | XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3; |
762 | |
763 | if (new_video_mode->flags & XBIOSMODE_C2P) |
764 | current->pixels = XBIOS_shadowscreen; |
765 | else |
766 | current->pixels = XBIOS_screens[0]; |
767 | |
768 | XBIOS_fbnum = 0; |
769 | |
770 | #if SDL_VIDEO_OPENGL |
771 | if (flags & SDL_OPENGL) { |
772 | if (!SDL_AtariGL_Init(this, current)) { |
773 | XBIOS_FreeBuffers(this); |
774 | SDL_SetError("Can not create OpenGL context"); |
775 | return NULL; |
776 | } |
777 | |
778 | modeflags |= SDL_OPENGL; |
779 | } |
780 | #endif |
781 | |
782 | current->flags = modeflags; |
783 | |
784 | #ifndef DEBUG_VIDEO_XBIOS |
785 | /* Now set the video mode */ |
786 | if ((XBIOS_cvdo>>16) == VDO_MILAN) { |
787 | VsetScreen(-1, XBIOS_screens[0], MI_MAGIC, CMD_SETADR); |
788 | } else { |
789 | Setscreen(-1,XBIOS_screens[0],-1); |
790 | } |
791 | |
792 | switch(XBIOS_cvdo >> 16) { |
793 | case VDO_ST: |
794 | Setscreen(-1,-1,new_video_mode->number); |
795 | |
796 | /* Reset palette */ |
797 | for (i=0;i<16;i++) { |
798 | TT_palette[i]= ((i>>1)<<8) | (((i*8)/17)<<4) | (i>>1); |
799 | } |
800 | Setpalette(TT_palette); |
801 | break; |
802 | case VDO_STE: |
803 | Setscreen(-1,-1,new_video_mode->number); |
804 | |
805 | /* Reset palette */ |
806 | for (i=0;i<16;i++) |
807 | { |
808 | int c; |
809 | |
810 | c=((i&1)<<3)|((i>>1)&7); |
811 | TT_palette[i]=(c<<8)|(c<<4)|c; |
812 | } |
813 | Setpalette(TT_palette); |
814 | break; |
815 | case VDO_TT: |
816 | EsetShift(new_video_mode->number); |
817 | break; |
818 | case VDO_F30: |
819 | if (XBIOS_centscreen) { |
820 | SDL_XBIOS_CentscreenSetmode(this, width, height, new_depth); |
821 | } else { |
822 | VsetMode(new_video_mode->number); |
823 | } |
824 | |
825 | /* Set hardware palette to black in True Colour */ |
826 | if (new_depth > 8) { |
827 | SDL_memset(F30_palette, 0, sizeof(F30_palette)); |
828 | VsetRGB(0,256,F30_palette); |
829 | } |
830 | break; |
831 | case VDO_MILAN: |
832 | VsetScreen(-1, new_video_mode->number, MI_MAGIC, CMD_SETMODE); |
833 | |
834 | /* Set hardware palette to black in True Colour */ |
835 | if (new_depth > 8) { |
836 | SDL_memset(F30_palette, 0, sizeof(F30_palette)); |
837 | VsetRGB(0,256,F30_palette); |
838 | } |
839 | break; |
840 | } |
841 | |
842 | Vsync(); |
843 | #endif |
844 | |
845 | this->UpdateRects = XBIOS_UpdateRects; |
846 | |
847 | return (current); |
848 | } |
849 | |
850 | /* We don't actually allow hardware surfaces other than the main one */ |
851 | static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface) |
852 | { |
853 | return(-1); |
854 | } |
855 | |
856 | static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface) |
857 | { |
858 | return; |
859 | } |
860 | |
861 | static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface) |
862 | { |
863 | return(0); |
864 | } |
865 | |
866 | static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface) |
867 | { |
868 | return; |
869 | } |
870 | |
871 | static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) |
872 | { |
873 | SDL_Surface *surface; |
874 | |
875 | surface = this->screen; |
876 | |
877 | if (XBIOS_current->flags & XBIOSMODE_C2P) { |
878 | int i; |
879 | int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); |
880 | |
881 | for (i=0;i<numrects;i++) { |
882 | void *source,*destination; |
883 | int x1,x2; |
884 | |
885 | x1 = rects[i].x & ~15; |
886 | x2 = rects[i].x+rects[i].w; |
887 | if (x2 & 15) { |
888 | x2 = (x2 | 15) +1; |
889 | } |
890 | |
891 | source = surface->pixels; |
892 | source += surface->pitch * rects[i].y; |
893 | source += x1; |
894 | |
895 | destination = XBIOS_screens[XBIOS_fbnum]; |
896 | destination += XBIOS_pitch * rects[i].y; |
897 | destination += x1; |
898 | |
899 | /* Convert chunky to planar screen */ |
900 | SDL_Atari_C2pConvert( |
901 | source, |
902 | destination, |
903 | x2-x1, |
904 | rects[i].h, |
905 | doubleline, |
906 | surface->pitch, |
907 | XBIOS_pitch |
908 | ); |
909 | } |
910 | } |
911 | |
912 | #ifndef DEBUG_VIDEO_XBIOS |
913 | if ((XBIOS_cvdo>>16) == VDO_MILAN) { |
914 | VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); |
915 | } else { |
916 | Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); |
917 | } |
918 | |
919 | Vsync(); |
920 | #endif |
921 | |
922 | if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { |
923 | XBIOS_fbnum ^= 1; |
924 | if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { |
925 | surface->pixels=XBIOS_screens[XBIOS_fbnum]; |
926 | } |
927 | } |
928 | } |
929 | |
930 | static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface) |
931 | { |
932 | if (XBIOS_current->flags & XBIOSMODE_C2P) { |
933 | void *destscr; |
934 | int destx; |
935 | int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); |
936 | |
937 | /* Center on destination screen */ |
938 | destscr = XBIOS_screens[XBIOS_fbnum]; |
939 | destscr += XBIOS_pitch * ((XBIOS_current->height - surface->h) >> 1); |
940 | destx = (XBIOS_current->width - surface->w) >> 1; |
941 | destx &= ~15; |
942 | destscr += destx; |
943 | |
944 | /* Convert chunky to planar screen */ |
945 | SDL_Atari_C2pConvert( |
946 | surface->pixels, |
947 | destscr, |
948 | surface->w, |
949 | surface->h, |
950 | doubleline, |
951 | surface->pitch, |
952 | XBIOS_pitch |
953 | ); |
954 | } |
955 | |
956 | #ifndef DEBUG_VIDEO_XBIOS |
957 | if ((XBIOS_cvdo>>16) == VDO_MILAN) { |
958 | VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); |
959 | } else { |
960 | Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); |
961 | } |
962 | |
963 | Vsync(); |
964 | #endif |
965 | |
966 | if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { |
967 | XBIOS_fbnum ^= 1; |
968 | if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { |
969 | surface->pixels=XBIOS_screens[XBIOS_fbnum]; |
970 | } |
971 | } |
972 | |
973 | return(0); |
974 | } |
975 | |
976 | static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
977 | { |
978 | #ifndef DEBUG_VIDEO_XBIOS |
979 | int i; |
980 | int r,v,b; |
981 | |
982 | switch( XBIOS_cvdo >> 16) { |
983 | case VDO_ST: |
984 | case VDO_STE: |
985 | for (i=0;i<ncolors;i++) |
986 | { |
987 | r = colors[i].r; |
988 | v = colors[i].g; |
989 | b = colors[i].b; |
990 | |
991 | TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100; |
992 | } |
993 | SDL_Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */ |
994 | break; |
995 | case VDO_TT: |
996 | for(i = 0; i < ncolors; i++) |
997 | { |
998 | r = colors[i].r; |
999 | v = colors[i].g; |
1000 | b = colors[i].b; |
1001 | |
1002 | TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4); |
1003 | } |
1004 | EsetPalette(firstcolor,ncolors,TT_palette); |
1005 | break; |
1006 | case VDO_F30: |
1007 | case VDO_MILAN: |
1008 | for(i = 0; i < ncolors; i++) |
1009 | { |
1010 | r = colors[i].r; |
1011 | v = colors[i].g; |
1012 | b = colors[i].b; |
1013 | |
1014 | F30_palette[i]=(r<<16)|(v<<8)|b; |
1015 | } |
1016 | VsetRGB(firstcolor,ncolors,F30_palette); |
1017 | break; |
1018 | } |
1019 | #endif |
1020 | |
1021 | return(1); |
1022 | } |
1023 | |
1024 | /* Note: If we are terminated, this could be called in the middle of |
1025 | another SDL video routine -- notably UpdateRects. |
1026 | */ |
1027 | static void XBIOS_VideoQuit(_THIS) |
1028 | { |
1029 | int i,j; |
1030 | |
1031 | Atari_ShutdownEvents(); |
1032 | |
1033 | /* Restore video mode and palette */ |
1034 | #ifndef DEBUG_VIDEO_XBIOS |
1035 | switch(XBIOS_cvdo >> 16) { |
1036 | case VDO_ST: |
1037 | case VDO_STE: |
1038 | Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode); |
1039 | if (XBIOS_oldnumcol) { |
1040 | Setpalette(XBIOS_oldpalette); |
1041 | } |
1042 | break; |
1043 | case VDO_TT: |
1044 | Setscreen(-1,XBIOS_oldvbase,-1); |
1045 | EsetShift(XBIOS_oldvmode); |
1046 | if (XBIOS_oldnumcol) { |
1047 | EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
1048 | } |
1049 | break; |
1050 | case VDO_F30: |
1051 | Setscreen(-1, XBIOS_oldvbase, -1); |
1052 | if (XBIOS_centscreen) { |
1053 | SDL_XBIOS_CentscreenRestore(this, XBIOS_oldvmode); |
1054 | } else { |
1055 | VsetMode(XBIOS_oldvmode); |
1056 | } |
1057 | if (XBIOS_oldnumcol) { |
1058 | VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
1059 | } |
1060 | break; |
1061 | case VDO_MILAN: |
1062 | VsetScreen(-1, &XBIOS_oldvbase, MI_MAGIC, CMD_SETADR); |
1063 | VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_SETMODE); |
1064 | if (XBIOS_oldnumcol) { |
1065 | VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); |
1066 | } |
1067 | break; |
1068 | } |
1069 | Vsync(); |
1070 | #endif |
1071 | |
1072 | #if SDL_VIDEO_OPENGL |
1073 | if (gl_active) { |
1074 | SDL_AtariGL_Quit(this, SDL_TRUE); |
1075 | } |
1076 | #endif |
1077 | |
1078 | if (XBIOS_oldpalette) { |
1079 | SDL_free(XBIOS_oldpalette); |
1080 | XBIOS_oldpalette=NULL; |
1081 | } |
1082 | XBIOS_FreeBuffers(this); |
1083 | |
1084 | /* Free mode list */ |
1085 | for ( i=0; i<NUM_MODELISTS; ++i ) { |
1086 | if ( SDL_modelist[i] != NULL ) { |
1087 | for ( j=0; SDL_modelist[i][j]; ++j ) |
1088 | SDL_free(SDL_modelist[i][j]); |
1089 | SDL_free(SDL_modelist[i]); |
1090 | SDL_modelist[i] = NULL; |
1091 | } |
1092 | if ( SDL_xbiosmode[i] != NULL ) { |
1093 | for ( j=0; SDL_xbiosmode[i][j]; ++j ) |
1094 | SDL_free(SDL_xbiosmode[i][j]); |
1095 | SDL_free(SDL_xbiosmode[i]); |
1096 | SDL_xbiosmode[i] = NULL; |
1097 | } |
1098 | } |
1099 | |
1100 | this->screen->pixels = NULL; |
1101 | |
1102 | /* Restore screensavers */ |
1103 | if (SDL_XBIOS_TveillePresent(this)) { |
1104 | SDL_XBIOS_TveilleRestore(this); |
1105 | } |
1106 | } |
1107 | |
1108 | #if SDL_VIDEO_OPENGL |
1109 | |
1110 | static void XBIOS_GL_SwapBuffers(_THIS) |
1111 | { |
1112 | SDL_AtariGL_SwapBuffers(this); |
1113 | XBIOS_FlipHWSurface(this, this->screen); |
1114 | SDL_AtariGL_MakeCurrent(this); |
1115 | } |
1116 | |
1117 | #endif |