Mercurial > sdl-ios-xcode
comparison src/video/gem/SDL_gemvideo.c @ 281:c5010ab8ba35
Added initial support for Atari (thanks Patrice!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 17 Feb 2002 19:54:28 +0000 |
parents | |
children | f6ffac90895c |
comparison
equal
deleted
inserted
replaced
280:0ddcea45d829 | 281:c5010ab8ba35 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* | |
29 * GEM SDL video driver implementation | |
30 * inspired from the Dummy SDL driver | |
31 * | |
32 * Patrice Mandin | |
33 * and work from | |
34 * Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard | |
35 */ | |
36 | |
37 #include <stdio.h> | |
38 #include <stdlib.h> | |
39 #include <string.h> | |
40 | |
41 /* Mint includes */ | |
42 #include <gem.h> | |
43 #include <gemx.h> | |
44 #include <mint/osbind.h> | |
45 #include <sys/cookie.h> | |
46 | |
47 #include "SDL.h" | |
48 #include "SDL_error.h" | |
49 #include "SDL_video.h" | |
50 #include "SDL_mouse.h" | |
51 #include "SDL_sysvideo.h" | |
52 #include "SDL_pixels_c.h" | |
53 #include "SDL_events_c.h" | |
54 | |
55 #include "SDL_ataric2p_s.h" | |
56 #include "SDL_ataric2p060_c.h" | |
57 #include "SDL_atarieddi_s.h" | |
58 #include "SDL_atarimxalloc_c.h" | |
59 #include "SDL_gemvideo.h" | |
60 #include "SDL_gemevents_c.h" | |
61 #include "SDL_gemmouse_c.h" | |
62 #include "SDL_gemwm_c.h" | |
63 | |
64 /* Defines */ | |
65 | |
66 #define GEM_VID_DRIVER_NAME "gem" | |
67 | |
68 /* Variables */ | |
69 | |
70 static unsigned char vdi_index[256] = { | |
71 0, 2, 3, 6, 4, 7, 5, 8, | |
72 9, 10, 11, 14, 12, 15, 13, 255 | |
73 }; | |
74 | |
75 static const unsigned char empty_name[]=""; | |
76 | |
77 /* Initialization/Query functions */ | |
78 static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
79 static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
80 static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
81 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
82 static void GEM_VideoQuit(_THIS); | |
83 | |
84 /* Hardware surface functions */ | |
85 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface); | |
86 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface); | |
87 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface); | |
88 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
89 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface); | |
90 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | |
91 #if 0 | |
92 static int GEM_ToggleFullScreen(_THIS, int on); | |
93 #endif | |
94 | |
95 /* Internal functions */ | |
96 static void GEM_FreeBuffers(_THIS); | |
97 static void refresh_window(_THIS, int winhandle, short *rect); | |
98 | |
99 /* GEM driver bootstrap functions */ | |
100 | |
101 static int GEM_Available(void) | |
102 { | |
103 short ap_id; | |
104 const char *envr = getenv("SDL_VIDEODRIVER"); | |
105 | |
106 /* Check if user asked a different video driver */ | |
107 if ((envr) && (strcmp(envr, GEM_VID_DRIVER_NAME)!=0)) { | |
108 return 0; | |
109 } | |
110 | |
111 /* Test if AES available */ | |
112 ap_id = appl_init(); | |
113 if (ap_id == -1) | |
114 return 0; | |
115 | |
116 appl_exit(); | |
117 return 1; | |
118 } | |
119 | |
120 static void GEM_DeleteDevice(SDL_VideoDevice *device) | |
121 { | |
122 free(device->hidden); | |
123 free(device); | |
124 } | |
125 | |
126 static SDL_VideoDevice *GEM_CreateDevice(int devindex) | |
127 { | |
128 SDL_VideoDevice *device; | |
129 | |
130 /* Initialize all variables that we clean on shutdown */ | |
131 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
132 if ( device ) { | |
133 memset(device, 0, (sizeof *device)); | |
134 device->hidden = (struct SDL_PrivateVideoData *) | |
135 malloc((sizeof *device->hidden)); | |
136 } | |
137 if ( (device == NULL) || (device->hidden == NULL) ) { | |
138 SDL_OutOfMemory(); | |
139 if ( device ) { | |
140 free(device); | |
141 } | |
142 return(0); | |
143 } | |
144 memset(device->hidden, 0, (sizeof *device->hidden)); | |
145 | |
146 atari_test_cpu060_present(); | |
147 | |
148 /* Set the function pointers */ | |
149 device->VideoInit = GEM_VideoInit; | |
150 device->ListModes = GEM_ListModes; | |
151 device->SetVideoMode = GEM_SetVideoMode; | |
152 device->SetColors = GEM_SetColors; | |
153 device->UpdateRects = NULL /*GEM_UpdateRects*/; | |
154 device->VideoQuit = GEM_VideoQuit; | |
155 device->AllocHWSurface = GEM_AllocHWSurface; | |
156 device->LockHWSurface = GEM_LockHWSurface; | |
157 device->UnlockHWSurface = GEM_UnlockHWSurface; | |
158 device->FlipHWSurface = GEM_FlipHWSurface; | |
159 device->FreeHWSurface = GEM_FreeHWSurface; | |
160 device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/; | |
161 | |
162 /* Window manager */ | |
163 device->SetCaption = GEM_SetCaption; | |
164 device->SetIcon = NULL /*GEM_SetIcon*/; | |
165 device->IconifyWindow = GEM_IconifyWindow; | |
166 device->GrabInput = GEM_GrabInput; | |
167 | |
168 /* Events */ | |
169 device->InitOSKeymap = GEM_InitOSKeymap; | |
170 device->PumpEvents = GEM_PumpEvents; | |
171 | |
172 /* Mouse */ | |
173 device->FreeWMCursor = GEM_FreeWMCursor; | |
174 device->CreateWMCursor = GEM_CreateWMCursor; | |
175 device->ShowWMCursor = GEM_ShowWMCursor; | |
176 device->WarpWMCursor = GEM_WarpWMCursor; | |
177 device->CheckMouseMode = GEM_CheckMouseMode; | |
178 | |
179 device->free = GEM_DeleteDevice; | |
180 | |
181 return device; | |
182 } | |
183 | |
184 VideoBootStrap GEM_bootstrap = { | |
185 GEM_VID_DRIVER_NAME, "Atari GEM video driver", | |
186 GEM_Available, GEM_CreateDevice | |
187 }; | |
188 | |
189 static void VDI_ReadExtInfo(_THIS, short *work_out) | |
190 { | |
191 unsigned long EdDI_version; | |
192 unsigned long cookie_EdDI; | |
193 Uint32 num_colours; | |
194 Uint16 clut_type, num_bits; | |
195 | |
196 /* Read EdDI informations */ | |
197 if (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) { | |
198 return; | |
199 } | |
200 | |
201 EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI); | |
202 | |
203 vq_scrninfo(VDI_handle, work_out); | |
204 | |
205 VDI_format = work_out[0]; | |
206 clut_type = work_out[1]; | |
207 num_bits = work_out[2]; | |
208 num_colours = *((Uint32 *) &work_out[3]); | |
209 | |
210 /* With EdDI>=1.1, we can have screen pitch, address and format | |
211 * so we can directly write to screen without using vro_cpyfm | |
212 */ | |
213 if (EdDI_version >= EDDI_11) { | |
214 VDI_pitch = work_out[5]; | |
215 VDI_screen = (void *) *((unsigned long *) &work_out[6]); | |
216 | |
217 switch(num_colours) { | |
218 case 32768UL: | |
219 if (work_out[14] & (1<<7)) { | |
220 /* Little endian */ | |
221 if (work_out[14] & (1<<1)) { | |
222 /* Falcon */ | |
223 VDI_alphamask = 1 << 13; | |
224 VDI_redmask = 31 << 3; | |
225 VDI_greenmask = (3 << 14) | 7; | |
226 VDI_bluemask = 31 << 8; | |
227 } else { | |
228 /* Others */ | |
229 VDI_alphamask = 1 << 7; | |
230 VDI_redmask = 31 << 2; | |
231 VDI_greenmask = (7 << 13) | 3; | |
232 VDI_bluemask = 31 << 8; | |
233 } | |
234 } else { | |
235 /* Big endian */ | |
236 if (work_out[14] & (1<<1)) { | |
237 /* Falcon */ | |
238 VDI_alphamask = 1 << 5; | |
239 VDI_redmask = 31 << 11; | |
240 VDI_greenmask = 31 << 6; | |
241 VDI_bluemask = 31; | |
242 } else { | |
243 /* Others */ | |
244 VDI_alphamask = 1 << 15; | |
245 VDI_redmask = 31 << 10; | |
246 VDI_greenmask = 31 << 5; | |
247 VDI_bluemask = 31; | |
248 } | |
249 } | |
250 break; | |
251 case 65536UL: | |
252 if (work_out[14] & (1<<7)) { | |
253 /* Little endian */ | |
254 VDI_alphamask = 0; | |
255 VDI_redmask = 31 << 3; | |
256 VDI_greenmask = (7 << 13) | 7; | |
257 VDI_bluemask = 31 << 8; | |
258 } else { | |
259 /* Big endian */ | |
260 VDI_alphamask = 0; | |
261 VDI_redmask = 31 << 11; | |
262 VDI_greenmask = 63 << 5; | |
263 VDI_bluemask = 31; | |
264 } | |
265 break; | |
266 case 16777216UL: | |
267 if (work_out[14] & (1<<7)) { | |
268 /* Little endian */ | |
269 switch(num_bits) { | |
270 case 24: | |
271 VDI_alphamask = 0; | |
272 VDI_redmask = 255; | |
273 VDI_greenmask = 255 << 8; | |
274 VDI_bluemask = 255 << 16; | |
275 break; | |
276 case 32: | |
277 VDI_alphamask = 255; | |
278 VDI_redmask = 255 << 8; | |
279 VDI_greenmask = 255 << 16; | |
280 VDI_bluemask = 255 << 24; | |
281 break; | |
282 } | |
283 } else { | |
284 /* Big endian */ | |
285 switch(num_bits) { | |
286 case 24: | |
287 VDI_alphamask = 0; | |
288 VDI_redmask = 255 << 16; | |
289 VDI_greenmask = 255 << 8; | |
290 VDI_bluemask = 255; | |
291 break; | |
292 case 32: | |
293 VDI_alphamask = 255 << 24; | |
294 VDI_redmask = 255 << 16; | |
295 VDI_greenmask = 255 << 8; | |
296 VDI_bluemask = 255; | |
297 break; | |
298 } | |
299 } | |
300 break; | |
301 } | |
302 } | |
303 | |
304 switch(clut_type) { | |
305 case VDI_CLUT_HARDWARE: | |
306 { | |
307 int i; | |
308 Uint16 *tmp_p; | |
309 | |
310 tmp_p = (Uint16 *)&work_out[16]; | |
311 | |
312 for (i=0;i<256;i++) { | |
313 vdi_index[i] = *tmp_p++; | |
314 } | |
315 } | |
316 break; | |
317 case VDI_CLUT_SOFTWARE: | |
318 if (EdDI_version < EDDI_11) { | |
319 int component; /* red, green, blue, alpha, overlay */ | |
320 int num_bit; | |
321 unsigned short *tmp_p; | |
322 | |
323 /* We can build masks with info here */ | |
324 tmp_p = (unsigned short *) &work_out[16]; | |
325 for (component=0;component<5;component++) { | |
326 for (num_bit=0;num_bit<16;num_bit++) { | |
327 unsigned short valeur; | |
328 | |
329 valeur = *tmp_p++; | |
330 | |
331 if (valeur == 0xffff) { | |
332 continue; | |
333 } | |
334 | |
335 switch(component) { | |
336 case 0: | |
337 VDI_redmask |= 1<< valeur; | |
338 break; | |
339 case 1: | |
340 VDI_greenmask |= 1<< valeur; | |
341 break; | |
342 case 2: | |
343 VDI_bluemask |= 1<< valeur; | |
344 break; | |
345 case 3: | |
346 VDI_alphamask |= 1<< valeur; | |
347 break; | |
348 } | |
349 } | |
350 } | |
351 | |
352 /* Remove lower green bits for Intel endian screen */ | |
353 if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) { | |
354 VDI_greenmask &= ~(7<<13); | |
355 } | |
356 } | |
357 break; | |
358 case VDI_CLUT_NONE: | |
359 break; | |
360 } | |
361 } | |
362 | |
363 int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
364 { | |
365 int i; | |
366 short work_in[12], work_out[272], dummy; | |
367 | |
368 /* Open AES (Application Environment Services) */ | |
369 GEM_ap_id = appl_init(); | |
370 if (GEM_ap_id == -1) { | |
371 fprintf(stderr,"Can not open AES\n"); | |
372 return 1; | |
373 } | |
374 | |
375 /* Read version and features */ | |
376 GEM_version = aes_global[0]; | |
377 if (GEM_version >= 0x0400) { | |
378 short ap_gout[4]; | |
379 | |
380 GEM_wfeatures=0; | |
381 if (appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3])==0) { | |
382 GEM_wfeatures=ap_gout[0]; | |
383 } | |
384 } | |
385 | |
386 /* Ask VDI physical workstation handle opened by AES */ | |
387 VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy); | |
388 if (VDI_handle<1) { | |
389 fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle); | |
390 return 1; | |
391 } | |
392 | |
393 /* Open virtual VDI workstation */ | |
394 work_in[0]=Getrez()+2; | |
395 for(i = 1; i < 10; i++) | |
396 work_in[i] = 1; | |
397 work_in[10] = 2; | |
398 | |
399 v_opnvwk(work_in, &VDI_handle, work_out); | |
400 if (VDI_handle == 0) { | |
401 fprintf(stderr,"Can not open VDI virtual workstation\n"); | |
402 return 1; | |
403 } | |
404 | |
405 /* Read fullscreen size */ | |
406 VDI_w = work_out[0] + 1; | |
407 VDI_h = work_out[1] + 1; | |
408 | |
409 /* Read desktop size and position */ | |
410 if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) { | |
411 fprintf(stderr,"Can not read desktop properties\n"); | |
412 return 1; | |
413 } | |
414 | |
415 /* Read bit depth */ | |
416 vq_extnd(VDI_handle, 1, work_out); | |
417 VDI_bpp = work_out[4]; | |
418 VDI_oldnumcolors=0; | |
419 | |
420 switch(VDI_bpp) { | |
421 case 8: | |
422 VDI_pixelsize=1; | |
423 break; | |
424 case 15: | |
425 case 16: | |
426 VDI_pixelsize=2; | |
427 break; | |
428 case 24: | |
429 VDI_pixelsize=3; | |
430 break; | |
431 case 32: | |
432 VDI_pixelsize=4; | |
433 break; | |
434 default: | |
435 fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp); | |
436 return 1; | |
437 } | |
438 | |
439 /* Setup hardware -> VDI palette mapping */ | |
440 for(i = 16; i < 255; i++) { | |
441 vdi_index[i] = i; | |
442 } | |
443 vdi_index[255] = 1; | |
444 | |
445 /* Save current palette */ | |
446 if (VDI_bpp>8) { | |
447 VDI_oldnumcolors=1<<8; | |
448 } else { | |
449 VDI_oldnumcolors=1<<VDI_bpp; | |
450 } | |
451 | |
452 for(i = 0; i < VDI_oldnumcolors; i++) { | |
453 short rgb[3]; | |
454 | |
455 vq_color(VDI_handle, i, 0, rgb); | |
456 | |
457 VDI_oldpalette[i][0] = rgb[0]; | |
458 VDI_oldpalette[i][1] = rgb[1]; | |
459 VDI_oldpalette[i][2] = rgb[2]; | |
460 } | |
461 | |
462 /* Setup screen info */ | |
463 GEM_title_name = empty_name; | |
464 GEM_icon_name = empty_name; | |
465 | |
466 GEM_handle = -1; | |
467 GEM_locked = SDL_FALSE; | |
468 GEM_win_fulled = SDL_FALSE; | |
469 | |
470 VDI_screen = NULL; | |
471 VDI_ReadExtInfo(this, work_out); | |
472 if (VDI_screen == NULL) { | |
473 VDI_pitch = VDI_w * ((VDI_bpp)>>3); | |
474 VDI_format = VDI_FORMAT_UNKNOWN; | |
475 VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0; | |
476 } | |
477 | |
478 /* Setup destination mfdb */ | |
479 VDI_dst_mfdb.fd_addr = NULL; | |
480 | |
481 /* Update hardware info */ | |
482 this->info.hw_available = 0; | |
483 this->info.video_mem = 0; | |
484 | |
485 /* TC, screen : no shadow (direct) | |
486 * 8P, screen: no shadow (direct) | |
487 * 8I, screen: shadow, c2p (shadow -> c2p) | |
488 * TC, no screen: shadow (vro_cpyfm) | |
489 * 8P, no screen: shadow (vro_cpyfm) | |
490 * 8I/U, no screen: shadow, shadow_c2p, c2p (shadow -> c2p -> vro_cpyfm) | |
491 */ | |
492 | |
493 /* Determine the screen depth */ | |
494 /* we change this during the SDL_SetVideoMode implementation... */ | |
495 vformat->BitsPerPixel = VDI_bpp; | |
496 | |
497 /* Set mouse cursor to arrow */ | |
498 graf_mouse(ARROW, NULL); | |
499 | |
500 /* Init chunky to planar routine */ | |
501 Atari_C2pInit = Atari_C2pInit8; | |
502 if (atari_cpu060_avail) { | |
503 Atari_C2pConvert = Atari_C2pConvert8_060; | |
504 } else { | |
505 Atari_C2pConvert = Atari_C2pConvert8; | |
506 } | |
507 Atari_C2pInit(); | |
508 | |
509 /* We're done! */ | |
510 return(0); | |
511 } | |
512 | |
513 SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
514 { | |
515 if (format->BitsPerPixel == VDI_bpp) { | |
516 return((SDL_Rect **)-1); | |
517 } else { | |
518 return ((SDL_Rect **)NULL); | |
519 } | |
520 } | |
521 | |
522 static void GEM_FreeBuffers(_THIS) | |
523 { | |
524 /* Release buffer */ | |
525 if ( GEM_buffer ) { | |
526 free( GEM_buffer ); | |
527 GEM_buffer=NULL; | |
528 } | |
529 | |
530 /* Destroy window */ | |
531 if (GEM_handle>=0) { | |
532 wind_close(GEM_handle); | |
533 wind_delete(GEM_handle); | |
534 GEM_handle=-1; | |
535 } | |
536 } | |
537 | |
538 SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, | |
539 int width, int height, int bpp, Uint32 flags) | |
540 { | |
541 int maxwidth, maxheight; | |
542 Uint32 modeflags, screensize; | |
543 SDL_bool use_shadow; | |
544 | |
545 modeflags = SDL_HWPALETTE; | |
546 GEM_FreeBuffers(this); | |
547 | |
548 /*--- Verify if asked mode can be used ---*/ | |
549 if (flags & SDL_FULLSCREEN) { | |
550 maxwidth=VDI_w; | |
551 maxheight=VDI_h; | |
552 } else { | |
553 /* Windowed mode */ | |
554 maxwidth=GEM_desk_w; | |
555 maxheight=GEM_desk_h; | |
556 } | |
557 | |
558 if ((maxwidth < width) || (maxheight < height) || (VDI_bpp != bpp)) { | |
559 SDL_SetError("Couldn't find requested mode in list"); | |
560 return(NULL); | |
561 } | |
562 | |
563 /*--- Allocate the new pixel format for the screen ---*/ | |
564 if ( ! SDL_ReallocFormat(current, VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, VDI_alphamask) ) { | |
565 SDL_SetError("Couldn't allocate new pixel format for requested mode"); | |
566 return(NULL); | |
567 } | |
568 | |
569 /*--- Allocate shadow buffer if needed ---*/ | |
570 use_shadow=SDL_FALSE; | |
571 if (flags & SDL_FULLSCREEN) { | |
572 if (!VDI_screen) { | |
573 use_shadow=SDL_TRUE; | |
574 } else if (VDI_format==VDI_FORMAT_INTER) { | |
575 use_shadow=SDL_TRUE; | |
576 } | |
577 } else { | |
578 use_shadow=SDL_TRUE; | |
579 } | |
580 | |
581 if (use_shadow) { | |
582 screensize = width * height * VDI_pixelsize; | |
583 | |
584 GEM_buffer = Atari_SysMalloc(screensize, MX_PREFTTRAM); | |
585 if (GEM_buffer==NULL) { | |
586 fprintf(stderr,"Unable to allocate shadow buffer\n"); | |
587 return NULL; | |
588 } | |
589 memset(GEM_buffer, 0, screensize); | |
590 } | |
591 | |
592 /*--- Initialize screen ---*/ | |
593 if (flags & SDL_FULLSCREEN) { | |
594 short rgb[3]={0,0,0}; | |
595 short pxy[4]; | |
596 | |
597 if (!GEM_locked) { | |
598 /* Reserve memory space, used to be sure of compatibility */ | |
599 form_dial( FMD_START, 0,0,0,0, 0,0,VDI_w,VDI_h); | |
600 /* Lock AES */ | |
601 while (!wind_update(BEG_UPDATE|BEG_MCTRL)); | |
602 | |
603 GEM_locked=SDL_TRUE; | |
604 } | |
605 | |
606 /* Clear screen */ | |
607 pxy[0] = pxy[1] = 0; | |
608 pxy[2] = VDI_w - 1; | |
609 pxy[3] = VDI_h - 1; | |
610 vs_color(VDI_handle, vdi_index[0], rgb); | |
611 vsf_color(VDI_handle,0); | |
612 vsf_interior(VDI_handle,1); | |
613 vsf_perimeter(VDI_handle,0); | |
614 v_bar(VDI_handle,pxy); | |
615 | |
616 modeflags |= SDL_FULLSCREEN; | |
617 if (VDI_screen && (VDI_format==VDI_FORMAT_PACK)) { | |
618 modeflags |= SDL_HWSURFACE; | |
619 } else { | |
620 modeflags |= SDL_SWSURFACE; | |
621 } | |
622 } else { | |
623 int posx,posy; | |
624 short x2,y2,w2,h2; | |
625 | |
626 if (GEM_locked) { | |
627 /* Restore screen memory, and send REDRAW to all apps */ | |
628 form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h); | |
629 /* Unlock AES */ | |
630 wind_update(END_UPDATE|END_MCTRL); | |
631 GEM_locked=SDL_FALSE; | |
632 } | |
633 | |
634 /* Center our window */ | |
635 posx = GEM_desk_x; | |
636 posy = GEM_desk_y; | |
637 if (width<GEM_desk_w) | |
638 posx += (GEM_desk_w - width) >> 1; | |
639 if (height<GEM_desk_h) | |
640 posy += (GEM_desk_h - height) >> 1; | |
641 | |
642 /* Calculate our window size and position */ | |
643 if (!(flags & SDL_NOFRAME)) { | |
644 GEM_win_type=NAME|MOVER|CLOSER|SMALLER; | |
645 if (flags & SDL_RESIZABLE) { | |
646 GEM_win_type |= FULLER|SIZER; | |
647 modeflags |= SDL_RESIZABLE; | |
648 } | |
649 } else { | |
650 GEM_win_type=0; | |
651 modeflags |= SDL_NOFRAME; | |
652 } | |
653 | |
654 if (!wind_calc(0, GEM_win_type, posx, posy, width, height, &x2, &y2, &w2, &h2)) { | |
655 GEM_FreeBuffers(this); | |
656 fprintf(stderr,"Can not calculate window attributes\n"); | |
657 return NULL; | |
658 } | |
659 | |
660 /* Create window */ | |
661 GEM_handle=wind_create(GEM_win_type, x2, y2, w2, h2); | |
662 if (GEM_handle<0) { | |
663 GEM_FreeBuffers(this); | |
664 fprintf(stderr,"Can not create window\n"); | |
665 return NULL; | |
666 } | |
667 | |
668 /* Setup window name */ | |
669 wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0); | |
670 | |
671 /* Open the window */ | |
672 wind_open(GEM_handle,x2,y2,w2,h2); | |
673 | |
674 modeflags |= SDL_SWSURFACE; | |
675 } | |
676 | |
677 /* Set up the new mode framebuffer */ | |
678 current->flags = modeflags; | |
679 current->w = width; | |
680 current->h = height; | |
681 if (use_shadow) { | |
682 current->pixels = GEM_buffer; | |
683 current->pitch = width * (VDI_bpp >> 3); | |
684 } else { | |
685 current->pixels = VDI_screen; | |
686 current->pixels += VDI_pitch * ((VDI_h - height) >> 1); | |
687 current->pixels += VDI_pixelsize * ((VDI_w - width) >> 1); | |
688 current->pitch = VDI_pitch; | |
689 } | |
690 | |
691 this->UpdateRects = GEM_UpdateRects; | |
692 | |
693 /* We're done */ | |
694 return(current); | |
695 } | |
696 | |
697 /* We don't actually allow hardware surfaces other than the main one */ | |
698 static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface) | |
699 { | |
700 return -1; | |
701 } | |
702 static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface) | |
703 { | |
704 return; | |
705 } | |
706 | |
707 /* We need to wait for vertical retrace on page flipped displays */ | |
708 static int GEM_LockHWSurface(_THIS, SDL_Surface *surface) | |
709 { | |
710 return(0); | |
711 } | |
712 | |
713 static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
714 { | |
715 return; | |
716 } | |
717 | |
718 static void GEM_UpdateRectsFullscreen(_THIS, int numrects, SDL_Rect *rects) | |
719 { | |
720 SDL_Surface *surface; | |
721 | |
722 surface = this->screen; | |
723 | |
724 if (VDI_screen) { | |
725 if (VDI_format==VDI_FORMAT_INTER) { | |
726 void *destscr; | |
727 int destx; | |
728 | |
729 destscr = VDI_screen; | |
730 destscr += VDI_pitch * ((VDI_h - surface->h) >> 1); | |
731 destx = (VDI_w - surface->w) >> 1; | |
732 destx &= ~15; | |
733 destscr += VDI_pixelsize * destx; | |
734 | |
735 /* Convert chunky to planar screen */ | |
736 Atari_C2pConvert( | |
737 surface->pixels, | |
738 destscr, | |
739 surface->w, | |
740 surface->h, | |
741 SDL_FALSE, | |
742 surface->pitch, | |
743 VDI_pitch | |
744 ); | |
745 } | |
746 } else { | |
747 MFDB mfdb_src; | |
748 short blitcoords[8]; | |
749 int i; | |
750 | |
751 mfdb_src.fd_addr=surface->pixels; | |
752 mfdb_src.fd_w=surface->w; | |
753 mfdb_src.fd_h=surface->h; | |
754 mfdb_src.fd_wdwidth=(surface->w) >> 4; | |
755 mfdb_src.fd_stand=0; | |
756 mfdb_src.fd_nplanes=surface->format->BitsPerPixel; | |
757 mfdb_src.fd_r1=0; | |
758 mfdb_src.fd_r2=0; | |
759 mfdb_src.fd_r3=0; | |
760 | |
761 for ( i=0; i<numrects; ++i ) { | |
762 blitcoords[0] = rects[i].x; | |
763 blitcoords[1] = rects[i].y; | |
764 blitcoords[2] = blitcoords[0] + rects[i].w - 1; | |
765 blitcoords[3] = blitcoords[1] + rects[i].h - 1; | |
766 | |
767 blitcoords[4] = rects[i].x + ((VDI_w - surface->w) >> 1); | |
768 blitcoords[5] = rects[i].y + ((VDI_h - surface->h) >> 1); | |
769 blitcoords[6] = blitcoords[4] + rects[i].w - 1; | |
770 blitcoords[7] = blitcoords[5] + rects[i].h - 1; | |
771 | |
772 vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); | |
773 } | |
774 } | |
775 } | |
776 | |
777 static void GEM_UpdateRectsWindowed(_THIS, int numrects, SDL_Rect *rects) | |
778 { | |
779 short pxy[8], wind_pxy[8]; | |
780 int i; | |
781 | |
782 wind_get(GEM_handle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3]); | |
783 | |
784 for ( i=0; i<numrects; ++i ) { | |
785 pxy[0] = wind_pxy[0] + rects[i].x; | |
786 pxy[1] = wind_pxy[1] + rects[i].y; | |
787 pxy[2] = rects[i].w; | |
788 pxy[3] = rects[i].h; | |
789 | |
790 GEM_wind_redraw(this, GEM_handle, pxy); | |
791 } | |
792 } | |
793 | |
794 static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | |
795 { | |
796 SDL_Surface *surface; | |
797 | |
798 surface = this->screen; | |
799 | |
800 if (surface->flags & SDL_FULLSCREEN) { | |
801 GEM_UpdateRectsFullscreen(this, numrects, rects); | |
802 } else { | |
803 GEM_UpdateRectsWindowed(this, numrects, rects); | |
804 } | |
805 } | |
806 | |
807 static int GEM_FlipHWSurfaceFullscreen(_THIS, SDL_Surface *surface) | |
808 { | |
809 if (VDI_screen) { | |
810 if (VDI_format==VDI_FORMAT_INTER) { | |
811 void *destscr; | |
812 int destx; | |
813 | |
814 /* Center on destination screen */ | |
815 destscr = VDI_screen; | |
816 destscr += VDI_pitch * ((VDI_h - surface->h) >> 1); | |
817 destx = (VDI_w - surface->w) >> 1; | |
818 destx &= ~15; | |
819 destscr += VDI_pixelsize * destx; | |
820 | |
821 /* Convert chunky to planar screen */ | |
822 Atari_C2pConvert( | |
823 surface->pixels, | |
824 destscr, | |
825 surface->w, | |
826 surface->h, | |
827 SDL_FALSE, | |
828 surface->pitch, | |
829 VDI_pitch | |
830 ); | |
831 } | |
832 } else { | |
833 MFDB mfdb_src; | |
834 short blitcoords[8]; | |
835 | |
836 mfdb_src.fd_addr=surface->pixels; | |
837 mfdb_src.fd_w=surface->w; | |
838 mfdb_src.fd_h=surface->h; | |
839 mfdb_src.fd_wdwidth=(surface->w) >> 4; | |
840 mfdb_src.fd_stand=0; | |
841 mfdb_src.fd_nplanes=surface->format->BitsPerPixel; | |
842 mfdb_src.fd_r1=0; | |
843 mfdb_src.fd_r2=0; | |
844 mfdb_src.fd_r3=0; | |
845 | |
846 blitcoords[0] = 0; | |
847 blitcoords[1] = 0; | |
848 blitcoords[2] = surface->w - 1; | |
849 blitcoords[3] = surface->h - 1; | |
850 blitcoords[4] = (VDI_w - surface->w) >> 1; | |
851 blitcoords[5] = (VDI_h - surface->h) >> 1; | |
852 blitcoords[6] = blitcoords[4] + surface->w - 1; | |
853 blitcoords[7] = blitcoords[5] + surface->h - 1; | |
854 | |
855 vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); | |
856 } | |
857 | |
858 return(0); | |
859 } | |
860 | |
861 static int GEM_FlipHWSurfaceWindowed(_THIS, SDL_Surface *surface) | |
862 { | |
863 short pxy[8]; | |
864 | |
865 /* Update the whole window */ | |
866 wind_get(GEM_handle, WF_WORKXYWH, &pxy[0], &pxy[1], &pxy[2], &pxy[3]); | |
867 | |
868 GEM_wind_redraw(this, GEM_handle, pxy); | |
869 | |
870 return(0); | |
871 } | |
872 | |
873 static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface) | |
874 { | |
875 if (surface->flags & SDL_FULLSCREEN) { | |
876 return GEM_FlipHWSurfaceFullscreen(this, surface); | |
877 } else { | |
878 return GEM_FlipHWSurfaceWindowed(this, surface); | |
879 } | |
880 } | |
881 | |
882 static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
883 { | |
884 int i; | |
885 SDL_Surface *surface; | |
886 | |
887 /* Do not change palette in True Colour */ | |
888 surface = this->screen; | |
889 if (surface->format->BitsPerPixel > 8) { | |
890 return 1; | |
891 } | |
892 | |
893 | |
894 for(i = 0; i < ncolors; i++) | |
895 { | |
896 int r, g, b; | |
897 short rgb[3]; | |
898 | |
899 r = colors[i].r; | |
900 g = colors[i].g; | |
901 b = colors[i].b; | |
902 | |
903 rgb[0] = (1000 * r) / 255; | |
904 rgb[1] = (1000 * g) / 255; | |
905 rgb[2] = (1000 * b) / 255; | |
906 | |
907 vs_color(VDI_handle, vdi_index[firstcolor+i], rgb); | |
908 } | |
909 | |
910 return(1); | |
911 } | |
912 | |
913 #if 0 | |
914 static int GEM_ToggleFullScreen(_THIS, int on) | |
915 { | |
916 if (on) { | |
917 if (!GEM_locked) { | |
918 /* Lock AES */ | |
919 while (!wind_update(BEG_UPDATE|BEG_MCTRL)); | |
920 GEM_locked=SDL_TRUE; | |
921 } | |
922 } else { | |
923 if (GEM_locked) { | |
924 /* Unlock AES */ | |
925 wind_update(END_UPDATE|END_MCTRL); | |
926 GEM_locked=SDL_FALSE; | |
927 } | |
928 /* Redraw all screen */ | |
929 } | |
930 | |
931 return(1); | |
932 } | |
933 #endif | |
934 | |
935 /* Note: If we are terminated, this could be called in the middle of | |
936 another SDL video routine -- notably UpdateRects. | |
937 */ | |
938 void GEM_VideoQuit(_THIS) | |
939 { | |
940 GEM_FreeBuffers(this); | |
941 | |
942 if (GEM_locked) { | |
943 /* Restore screen memory, and send REDRAW to all apps */ | |
944 form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h); | |
945 /* Unlock AES */ | |
946 wind_update(END_UPDATE|END_MCTRL); | |
947 GEM_locked=SDL_FALSE; | |
948 } | |
949 | |
950 /* Close AES application */ | |
951 appl_exit(); | |
952 | |
953 /* Restore palette */ | |
954 if (VDI_oldnumcolors) { | |
955 int i; | |
956 | |
957 for(i = 0; i < VDI_oldnumcolors; i++) { | |
958 short rgb[3]; | |
959 | |
960 rgb[0] = VDI_oldpalette[i][0]; | |
961 rgb[1] = VDI_oldpalette[i][1]; | |
962 rgb[2] = VDI_oldpalette[i][2]; | |
963 | |
964 vs_color(VDI_handle, i, rgb); | |
965 } | |
966 } | |
967 | |
968 /* Close VDI workstation */ | |
969 if (VDI_handle) { | |
970 v_clsvwk(VDI_handle); | |
971 } | |
972 | |
973 /* Free mode list */ | |
974 if (SDL_modelist[0]) { | |
975 free(SDL_modelist[0]); | |
976 SDL_modelist[0]=NULL; | |
977 } | |
978 | |
979 this->screen->pixels = NULL; | |
980 } | |
981 | |
982 void GEM_wind_redraw(_THIS, int winhandle, short *inside) | |
983 { | |
984 short todo[4]; | |
985 | |
986 /* Tell AES we are going to update */ | |
987 while (!wind_update(BEG_UPDATE)); | |
988 | |
989 v_hide_c(VDI_handle); | |
990 | |
991 /* Browse the rectangle list to redraw */ | |
992 wind_get(winhandle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3]); | |
993 | |
994 while (todo[2] && todo[3]) { | |
995 | |
996 if (rc_intersect((GRECT *)inside,(GRECT *)todo)) { | |
997 todo[2] += todo[0]-1; | |
998 todo[3] += todo[1]-1; | |
999 refresh_window(this, winhandle, todo); | |
1000 } | |
1001 | |
1002 wind_get(winhandle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3]); | |
1003 } | |
1004 | |
1005 /* Update finished */ | |
1006 wind_update(END_UPDATE); | |
1007 | |
1008 v_show_c(VDI_handle,1); | |
1009 } | |
1010 | |
1011 static void refresh_window(_THIS, int winhandle, short *rect) | |
1012 { | |
1013 MFDB mfdb_src; | |
1014 short pxy[8], wind_pxy[8]; | |
1015 int iconified; | |
1016 SDL_Surface *surface; | |
1017 | |
1018 surface=this->screen; | |
1019 | |
1020 /* Is window iconified ? */ | |
1021 iconified = 0; | |
1022 if (GEM_wfeatures & (1<<WF_ICONIFY)) { | |
1023 wind_get(winhandle, WF_ICONIFY, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3]); | |
1024 iconified = pxy[0]; | |
1025 } | |
1026 | |
1027 wind_get(winhandle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3]); | |
1028 | |
1029 if (iconified) { | |
1030 /* Refresh icon */ | |
1031 mfdb_src.fd_addr=surface->pixels; /* Should be icon image */ | |
1032 mfdb_src.fd_w=surface->w; | |
1033 mfdb_src.fd_h=surface->h; | |
1034 mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4; | |
1035 mfdb_src.fd_stand=0; | |
1036 mfdb_src.fd_nplanes=surface->format->BitsPerPixel; | |
1037 mfdb_src.fd_r1=0; | |
1038 mfdb_src.fd_r2=0; | |
1039 mfdb_src.fd_r3=0; | |
1040 } else { | |
1041 /* Refresh window */ | |
1042 mfdb_src.fd_addr=surface->pixels; | |
1043 mfdb_src.fd_w=surface->w; | |
1044 mfdb_src.fd_h=surface->h; | |
1045 mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4; | |
1046 mfdb_src.fd_stand=0; | |
1047 mfdb_src.fd_nplanes=surface->format->BitsPerPixel; | |
1048 mfdb_src.fd_r1=0; | |
1049 mfdb_src.fd_r2=0; | |
1050 mfdb_src.fd_r3=0; | |
1051 } | |
1052 | |
1053 pxy[0] = rect[0] - wind_pxy[0]; | |
1054 pxy[1] = rect[1] - wind_pxy[1]; | |
1055 pxy[2] = pxy[0] + rect[2] - rect[0]; | |
1056 pxy[3] = pxy[1] + rect[3] - rect[1]; | |
1057 | |
1058 pxy[4] = rect[0]; | |
1059 pxy[5] = rect[1]; | |
1060 pxy[6] = rect[2]; | |
1061 pxy[7] = rect[3]; | |
1062 | |
1063 vro_cpyfm( VDI_handle, S_ONLY, pxy, &mfdb_src, &VDI_dst_mfdb); | |
1064 } |