SDL-1.2.14
[sdl_omap.git] / src / video / xbios / SDL_xbios.c
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