1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 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#if defined(__APPLE__) && defined(__MACH__)
25#include <Carbon/Carbon.h>
26#if USE_QUICKTIME
27#include <QuickTime/Movies.h>
28#endif
29#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
30#include <Carbon.h>
31/* The fullscreen code requires the QuickTime framework, and the window
32   is still at the back on Mac OS X, which is where this code is needed.
33 */
34#if USE_QUICKTIME
35#include <Movies.h>
36#endif
37#else
38#include <Quickdraw.h>
39#include <LowMem.h>
40#include <Gestalt.h>
41#include <Devices.h>
42#include <DiskInit.h>
43#include <QDOffscreen.h>
44#endif
45
46#include "SDL_video.h"
47#include "SDL_syswm.h"
48#include "../SDL_sysvideo.h"
49#include "SDL_romvideo.h"
50#include "../maccommon/SDL_macgl_c.h"
51#include "../maccommon/SDL_macwm_c.h"
52#include "../maccommon/SDL_macmouse_c.h"
53#include "../maccommon/SDL_macevents_c.h"
54
55/* Initialization/Query functions */
56static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat);
57static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
58static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
59static int ROM_SetColors(_THIS, int firstcolor, int ncolors,
60			 SDL_Color *colors);
61static void ROM_VideoQuit(_THIS);
62
63/* Hardware surface functions */
64static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface);
65static int ROM_LockHWSurface(_THIS, SDL_Surface *surface);
66static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface);
67static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface);
68
69#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
70/* Saved state for the menu bar */
71static RgnHandle	gSaveGrayRgn = nil;
72static short		gSaveMenuBar = 0;
73static Boolean		gSaveCSVis = true;
74
75#if powerc
76/* Mixed mode glue to activate the 68K emulator and twiddle a register */
77#define ONEWORDSTUB(p1) \
78		{ 0x41FA, 0x0010, 0x209F, (p1), 0x41FA, \
79		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
80
81#define TWOWORDSTUB(p1,p2) \
82		{ 0x41FA, 0x0012, 0x209F, (p1), (p2), 0x41FA, \
83		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
84
85#define THREEWORDSTUB(p1,p2,p3) \
86		{ 0x41FA, 0x0014, 0x209F, (p1), (p2), (p3), 0x41FA, \
87		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
88
89/* ControlStrip inline glue for PowerPC */
90static pascal Boolean SBIsControlStripVisible(void)
91{
92	static short procData[] = TWOWORDSTUB(0x7000, 0xAAF2);
93	ProcInfoType procInfo = kD0DispatchedPascalStackBased
94				| RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
95            	| DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode);
96
97	return((Boolean) CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x00));
98}
99
100static pascal void SBShowHideControlStrip(Boolean showIt)
101{
102	static short procData[] = THREEWORDSTUB(0x303C, 0x0101, 0xAAF2);
103	ProcInfoType procInfo = kD0DispatchedPascalStackBased
104				| DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
105				| DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Boolean)));
106
107	CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x01, showIt);
108}
109#endif /* powerc */
110#endif /* !TARGET_API_MAC_CARBON */
111
112/* Macintosh toolbox driver bootstrap functions */
113
114static int ROM_Available(void)
115{
116	return(1);
117}
118
119static void ROM_DeleteDevice(SDL_VideoDevice *device)
120{
121	SDL_free(device->hidden);
122	SDL_free(device);
123}
124
125static SDL_VideoDevice *ROM_CreateDevice(int devindex)
126{
127	SDL_VideoDevice *device;
128
129	/* Initialize all variables that we clean on shutdown */
130	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
131	if ( device ) {
132		SDL_memset(device, 0, (sizeof *device));
133		device->hidden = (struct SDL_PrivateVideoData *)
134				SDL_malloc((sizeof *device->hidden));
135	}
136	if ( (device == NULL) || (device->hidden == NULL) ) {
137		SDL_OutOfMemory();
138		if ( device ) {
139			SDL_free(device);
140		}
141		return(0);
142	}
143	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
144
145	/* Set the function pointers */
146	device->VideoInit = ROM_VideoInit;
147	device->ListModes = ROM_ListModes;
148	device->SetVideoMode = ROM_SetVideoMode;
149	device->SetColors = ROM_SetColors;
150	device->UpdateRects = NULL;
151	device->VideoQuit = ROM_VideoQuit;
152	device->AllocHWSurface = ROM_AllocHWSurface;
153	device->CheckHWBlit = NULL;
154	device->FillHWRect = NULL;
155	device->SetHWColorKey = NULL;
156	device->SetHWAlpha = NULL;
157	device->LockHWSurface = ROM_LockHWSurface;
158	device->UnlockHWSurface = ROM_UnlockHWSurface;
159	device->FlipHWSurface = NULL;
160	device->FreeHWSurface = ROM_FreeHWSurface;
161#if SDL_MACCLASSIC_GAMMA_SUPPORT
162	device->SetGammaRamp = Mac_SetGammaRamp;
163	device->GetGammaRamp = Mac_GetGammaRamp;
164#endif
165#if SDL_VIDEO_OPENGL
166	device->GL_MakeCurrent = Mac_GL_MakeCurrent;
167	device->GL_SwapBuffers = Mac_GL_SwapBuffers;
168	device->GL_LoadLibrary = Mac_GL_LoadLibrary;
169	device->GL_GetProcAddress = Mac_GL_GetProcAddress;
170#endif	/* Have OpenGL */
171	device->SetCaption = Mac_SetCaption;
172	device->SetIcon = NULL;
173	device->IconifyWindow = NULL;
174	device->GrabInput = NULL;
175	device->GetWMInfo = NULL;
176	device->FreeWMCursor = Mac_FreeWMCursor;
177	device->CreateWMCursor = Mac_CreateWMCursor;
178	device->ShowWMCursor = Mac_ShowWMCursor;
179	device->WarpWMCursor = Mac_WarpWMCursor;
180	device->InitOSKeymap = Mac_InitOSKeymap;
181	device->PumpEvents = Mac_PumpEvents;
182
183	device->free = ROM_DeleteDevice;
184
185	return device;
186}
187
188VideoBootStrap TOOLBOX_bootstrap = {
189	"toolbox", "MacOS ROM Toolbox",
190	ROM_Available, ROM_CreateDevice
191};
192
193
194static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat)
195{
196	long info;
197
198	/* Check out some things about the system */
199	Gestalt(gestaltQuickdrawVersion, &info);
200	if ( info == gestaltOriginalQD ) {
201		SDL_SetError("Color Quickdraw not available");
202		return(-1);
203	}
204
205	/* Start ROMintosh events */
206	Mac_InitEvents(this);
207
208	/* Get a handle to the main monitor */
209	SDL_Display = GetMainDevice();
210
211	/* Determine the current screen size */
212	this->info.current_w = (**SDL_Display).gdRect.right;
213	this->info.current_h = (**SDL_Display).gdRect.bottom;
214
215	/* Determine pixel format */
216	vformat->BitsPerPixel = (**(**SDL_Display).gdPMap).pixelSize;
217	switch (vformat->BitsPerPixel) {
218		case 16:	/* 5-5-5 RGB */
219			vformat->Rmask = 0x00007c00;
220			vformat->Gmask = 0x000003e0;
221			vformat->Bmask = 0x0000001f;
222			break;
223		default:
224			break;
225	}
226
227	/* Create our palette */
228	SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8);
229	if ( SDL_CTab == nil ) {
230		SDL_OutOfMemory();
231		return(-1);
232	}
233	(**SDL_CTab).ctSeed = GetCTSeed();
234	(**SDL_CTab).ctFlags = 0;
235	(**SDL_CTab).ctSize = 255;
236	CTabChanged(SDL_CTab);
237	SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0);
238
239	/* Get a list of available fullscreen modes */
240	SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *));
241	if ( SDL_modelist ) {
242		SDL_modelist[0] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect));
243		if ( SDL_modelist[0] ) {
244			SDL_modelist[0]->x = 0;
245			SDL_modelist[0]->y = 0;
246			SDL_modelist[0]->w = (**SDL_Display).gdRect.right;
247			SDL_modelist[0]->h = (**SDL_Display).gdRect.bottom;
248		}
249		SDL_modelist[1] = NULL;
250	}
251
252	/* Fill in some window manager capabilities */
253	this->info.wm_available = 1;
254
255	/* We're done! */
256	return(0);
257}
258
259static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
260{
261	if ( this->screen->format->BitsPerPixel == format->BitsPerPixel ) {
262		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
263			return(SDL_modelist);
264		} else {
265			return((SDL_Rect **)-1);
266		}
267	} else {
268		return((SDL_Rect **)0);
269	}
270}
271
272static void ROM_HideMenuBar(_THIS)
273{
274#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
275	RgnHandle		drawRgn = nil;
276	RgnHandle		tempRgn = nil;
277	RgnHandle		grayRgn = nil;
278	WindowPtr		window = nil;
279	GDHandle		gd = nil;
280	GrafPtr			savePort;
281	long			response;
282	short			height;
283	EventRecord		theEvent;
284
285	height = GetMBarHeight();
286
287	if ( height > 0 ) {
288		tempRgn = NewRgn();
289		drawRgn = NewRgn();
290		gSaveGrayRgn = NewRgn();
291		if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) {
292			goto CLEANUP;
293		}
294		grayRgn = GetGrayRgn(); /* No need to check for this */
295
296		GetPort(&savePort);
297
298		/* Hide the control strip if it's present, and record its
299		   previous position into the dirty region for redrawing.
300		   This isn't necessary, but may help catch stray bits. */
301		CopyRgn(grayRgn, tempRgn);
302		if (!Gestalt(gestaltControlStripAttr, &response) &&
303			(response & (1L << gestaltControlStripExists))) {
304			gSaveCSVis = SBIsControlStripVisible();
305			if (gSaveCSVis)
306				SBShowHideControlStrip(false);
307		}
308		DiffRgn(grayRgn, tempRgn, drawRgn);
309
310		/* Save the gray region once the control strip is hidden*/
311		CopyRgn(grayRgn, gSaveGrayRgn);
312
313		/* Change the menu height in lowmem */
314		gSaveMenuBar = height;
315		LMSetMBarHeight(0);
316
317		/* Walk the monitor rectangles, and combine any pieces that
318		   aren't in GrayRgn: menubar, round corners, fake floaters. */
319		for(gd = GetDeviceList(); gd; gd = GetNextDevice(gd))
320			{
321			if (!TestDeviceAttribute(gd, screenDevice)) continue;
322			if (!TestDeviceAttribute(gd, screenActive)) continue;
323
324			RectRgn(tempRgn, &(*gd)->gdRect);	/* Get the whole screen */
325			DiffRgn(tempRgn, grayRgn, tempRgn); /* Subtract out GrayRgn */
326			UnionRgn(tempRgn, drawRgn, drawRgn);/* Combine all the bits */
327			}
328
329		/* Add the bits into the GrayRgn */
330		UnionRgn(drawRgn, grayRgn, grayRgn);
331
332		/* Modify the vis regions of exposed windows */
333		window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L;
334		PaintBehind(window, drawRgn);
335		CalcVisBehind(window, drawRgn);
336
337		SetPort(savePort);
338
339		/* Yield time so that floaters can catch up */
340		EventAvail(0, &theEvent);
341		EventAvail(0, &theEvent);
342		EventAvail(0, &theEvent);
343		EventAvail(0, &theEvent);
344		}
345
346CLEANUP:
347
348	if (tempRgn) DisposeRgn(tempRgn);
349	if (drawRgn) DisposeRgn(drawRgn);
350#endif /* !TARGET_API_MAC_CARBON */
351}
352
353static void ROM_ShowMenuBar(_THIS)
354{
355#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
356	RgnHandle		drawRgn = nil;
357	RgnHandle		menuRgn = nil;
358	RgnHandle		tempRgn = nil;
359	RgnHandle		grayRgn = nil;
360	WindowPtr		window = nil;
361	GrafPtr			wMgrPort;
362	GrafPtr			savePort;
363	Rect			menuRect;
364	long			response;
365	short			height;
366	EventRecord		theEvent;
367	RGBColor		saveRGB;
368	RGBColor		blackRGB = { 0, 0, 0 };
369
370	height = GetMBarHeight();
371
372	if ((height <= 0) && (gSaveMenuBar > 0)) {
373		drawRgn = NewRgn();
374		menuRgn = NewRgn();
375		tempRgn = NewRgn();
376		if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) {
377			goto CLEANUP;
378		}
379		grayRgn = GetGrayRgn(); /* No need to check for this */
380
381		GetPort(&savePort);
382		GetWMgrPort(&wMgrPort);
383
384		/* Set the height properly */
385		LMSetMBarHeight(gSaveMenuBar);
386
387		/* Restore the old GrayRgn: rounded corners, etc, but not
388		   the menubar -- subtract that out first! */
389		if (gSaveGrayRgn)
390			{
391			menuRect = (*GetMainDevice())->gdRect;
392			menuRect.bottom = menuRect.top + gSaveMenuBar;
393			RectRgn(menuRgn, &menuRect);
394
395			DiffRgn(grayRgn, gSaveGrayRgn, drawRgn); 	/* What do we inval? */
396			DiffRgn(drawRgn, menuRgn, drawRgn);			/* Clip out the menu */
397
398			/* Now redraw the corners and other bits black */
399			SetPort(wMgrPort);
400			GetClip(tempRgn);
401			SetClip(drawRgn);
402			GetForeColor(&saveRGB);
403			RGBForeColor(&blackRGB);
404			PaintRgn(drawRgn);
405			RGBForeColor(&saveRGB);
406			SetClip(tempRgn);
407			SetPort(savePort);
408
409			UnionRgn(drawRgn, menuRgn, drawRgn);		/* Put back the menu */
410
411			/* Now actually restore the GrayRgn */
412			CopyRgn(gSaveGrayRgn, grayRgn);
413			DisposeRgn(gSaveGrayRgn);
414			gSaveGrayRgn = nil;
415			}
416
417		/* Modify the vis regions of exposed windows and draw menubar */
418		window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L;
419		PaintBehind(window, drawRgn);
420		CalcVisBehind(window, drawRgn);
421		DrawMenuBar();
422
423		SetPort(savePort);
424		gSaveMenuBar = 0;
425
426		/* Now show the control strip if it's present */
427		if (!Gestalt(gestaltControlStripAttr, &response) &&
428				(response & (1L << gestaltControlStripExists)))
429			{
430			if (gSaveCSVis && !SBIsControlStripVisible())
431				SBShowHideControlStrip(true);
432			gSaveCSVis = true;
433			}
434
435		/* Yield time so that floaters can catch up */
436		EventAvail(0, &theEvent);
437		EventAvail(0, &theEvent);
438		EventAvail(0, &theEvent);
439		EventAvail(0, &theEvent);
440		}
441
442CLEANUP:
443
444	if (drawRgn) DisposeRgn(drawRgn);
445	if (menuRgn) DisposeRgn(menuRgn);
446	if (tempRgn) DisposeRgn(tempRgn);
447#endif /* !TARGET_API_MAC_CARBON */
448}
449
450/* Various screen update functions available */
451static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
452static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
453
454static void ROM_UnsetVideoMode(_THIS, SDL_Surface *current)
455{
456	/* Free the current window, if any */
457	if ( SDL_Window != nil ) {
458		GWorldPtr memworld;
459
460		/* Handle OpenGL support */
461		Mac_GL_Quit(this);
462
463		memworld = (GWorldPtr)GetWRefCon(SDL_Window);
464		if ( memworld != nil ) {
465			UnlockPixels(GetGWorldPixMap(memworld));
466			DisposeGWorld(memworld);
467		}
468		if ( (current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
469#if USE_QUICKTIME
470			EndFullScreen(fullscreen_ctx, nil);
471			SDL_Window = nil;
472#else
473			ROM_ShowMenuBar(this);
474#endif
475		}
476	}
477	current->pixels = NULL;
478	current->flags &= ~(SDL_HWSURFACE|SDL_FULLSCREEN);
479}
480
481static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current,
482				int width, int height, int bpp, Uint32 flags)
483{
484	Rect wrect, orect;
485#if TARGET_API_MAC_CARBON
486	Rect tmprect;
487#endif
488
489	/* Free any previous video mode */
490	ROM_UnsetVideoMode(this, current);
491
492	/* Create the ROM window and SDL video surface */
493	current->flags = 0;		/* Clear flags */
494	current->w = width;
495	current->h = height;
496	SetRect(&wrect, 0, 0, width, height);
497	if ( SDL_Window ) {
498		/* If we recreate the window, don't move it around */
499#if TARGET_API_MAC_CARBON
500		orect = *GetWindowPortBounds(SDL_Window, &tmprect);
501#else
502		orect = SDL_Window->portRect;
503#endif
504		OffsetRect(&wrect, orect.left, orect.top);
505	} else {
506		/* Center the window the first time we show it */
507		OffsetRect(&wrect,
508		(SDL_modelist[0]->w-width)/2, (SDL_modelist[0]->h-height)/2);
509	}
510
511#if defined(__MACOSX__) && !USE_QUICKTIME
512	/* Hum.. fullscreen mode is broken */
513	flags &= ~SDL_FULLSCREEN;
514#endif
515	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
516		/* Create the fullscreen window and use screen bits */
517		current->flags |= SDL_HWSURFACE|SDL_FULLSCREEN;
518		if ( SDL_Window ) {
519			DisposeWindow(SDL_Window);
520		}
521#if USE_QUICKTIME
522		BeginFullScreen(&fullscreen_ctx, nil, 0,0, &SDL_Window, nil, 0);
523#else
524		SDL_Window = NewCWindow(nil, &wrect, "\p", true, plainDBox,
525						(WindowPtr)-1, false, 0);
526		ROM_HideMenuBar(this);
527#endif
528		current->pitch = (**(**SDL_Display).gdPMap).rowBytes & 0x3FFF;
529		current->pixels = (**(**SDL_Display).gdPMap).baseAddr;
530		this->UpdateRects = ROM_DirectUpdate;
531	} else {
532		GWorldPtr memworld;
533		PixMapHandle pixmap;
534		int style;
535
536		style = noGrowDocProc;
537		if ( flags & SDL_NOFRAME ) {
538			style = plainDBox;
539			current->flags |= SDL_NOFRAME;
540		} else
541		if ( flags & SDL_RESIZABLE ) {
542			style = zoomDocProc;
543			current->flags |= SDL_RESIZABLE;
544		}
545		if ( SDL_Window && (style == current_style) ) {
546			/* Resize existing window, if necessary */
547			if ( ((orect.right-orect.left) != width) ||
548			     ((orect.bottom-orect.top) != height) ) {
549				SizeWindow(SDL_Window, width, height, false);
550			}
551		} else {
552			/* Recreate the window in the new style */
553			if ( SDL_Window ) {
554				DisposeWindow(SDL_Window);
555			}
556			SDL_Window = NewCWindow(nil, &wrect, "\p", true,
557			                        style, (WindowPtr)-1, true, 0);
558
559			/* Set the window title, if any */
560			{ char *title;
561				SDL_WM_GetCaption(&title, NULL);
562				if ( title ) {
563					Mac_SetCaption(this, title, NULL);
564				}
565			}
566		}
567		current_style = style;
568		SetPalette(SDL_Window, SDL_CPal, false);
569		ActivatePalette(SDL_Window);
570		if ( NewGWorld(&memworld, 0,
571#if TARGET_API_MAC_CARBON
572			       GetWindowPortBounds(SDL_Window, &tmprect),
573#else
574			       &SDL_Window->portRect,
575#endif
576			       SDL_CTab, nil, 0) != noErr ) {
577			SDL_SetError("NewGWorld() failed");
578			return(NULL);
579		}
580		SetWRefCon(SDL_Window, (long)memworld);
581		pixmap = GetGWorldPixMap(memworld);
582		LockPixels(pixmap);
583		current->pitch = (**pixmap).rowBytes & 0x3FFF;
584		current->pixels = GetPixBaseAddr(pixmap);
585		this->UpdateRects = ROM_WindowUpdate;
586	}
587	SetPortWindowPort(SDL_Window);
588	SelectWindow(SDL_Window);
589
590	/* Handle OpenGL support */
591	if ( flags & SDL_OPENGL ) {
592		if ( Mac_GL_Init(this) == 0 ) {
593			current->flags |= SDL_OPENGL;
594		} else {
595			current = NULL;
596		}
597	}
598
599	if ( (flags & SDL_HWPALETTE) && (flags & SDL_FULLSCREEN) )
600	   current->flags |= SDL_HWPALETTE;
601
602	/* We're live! */
603	return(current);
604}
605
606/* We don't actually allow hardware surfaces other than the main one */
607static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface)
608{
609	return(-1);
610}
611static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface)
612{
613	return;
614}
615static int ROM_LockHWSurface(_THIS, SDL_Surface *surface)
616{
617	return(0);
618}
619static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface)
620{
621	return;
622}
623
624static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
625{
626	/* The application is already updating the visible video memory */
627	return;
628}
629
630static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
631{
632	GWorldPtr memworld;
633	GrafPtr saveport;
634	CGrafPtr thePort;
635	const BitMap *memBits;
636	const BitMap *winBits;
637	int i;
638	Rect update;
639
640	/* Copy from the offscreen GWorld to the window port */
641	GetPort(&saveport);
642	SetPortWindowPort(SDL_Window);
643	thePort = GetWindowPort(SDL_Window);
644	memworld = (GWorldPtr)GetWRefCon(SDL_Window);
645#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
646	memBits = GetPortBitMapForCopyBits((CGrafPtr) memworld);
647#else
648	memBits = &((GrafPtr)memworld)->portBits;
649#endif
650#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
651	winBits = GetPortBitMapForCopyBits(thePort);
652#else
653	winBits = &SDL_Window->portBits;
654#endif
655	for ( i=0; i<numrects; ++i ) {
656		update.left = rects[i].x;
657		update.right = rects[i].x+rects[i].w;
658		update.top = rects[i].y;
659		update.bottom = rects[i].y+rects[i].h;
660		CopyBits(memBits, winBits,
661			 &update, &update, srcCopy, nil);
662	}
663#if TARGET_API_MAC_CARBON
664	if ( QDIsPortBuffered(thePort) ) {
665		QDFlushPortBuffer(thePort, NULL);
666	}
667#endif
668	SetPort(saveport);
669}
670
671static int ROM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
672{
673	CTabHandle cTab;
674	int i;
675
676	/* Get the colortable from the either the display or window */
677	if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
678		cTab = (**(**SDL_Display).gdPMap).pmTable;
679	} else {
680		cTab = SDL_CTab;
681	}
682
683	/* Verify the range of colors */
684	if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) {
685		return(0);
686	}
687
688	/* Set the screen palette and update the display */
689	for ( i=0; i< ncolors; ++i ) {
690	        int j = firstcolor + i;
691		(**cTab).ctTable[j].value = j;
692		(**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r;
693		(**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g;
694		(**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b;
695	}
696
697#if 0
698	if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN )
699#endif
700	{
701		GDevice **odisplay;
702		odisplay = GetGDevice();
703		SetGDevice(SDL_Display);
704		SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable);
705		SetGDevice(odisplay);
706	}
707	return(1);
708}
709
710void ROM_VideoQuit(_THIS)
711{
712	int i;
713
714	/* Free current video mode */
715	ROM_UnsetVideoMode(this, this->screen);
716	if ( SDL_Window ) {
717		DisposeWindow(SDL_Window);
718		SDL_Window = nil;
719	}
720
721	/* Free palette and restore original one */
722	if ( SDL_CTab != nil ) {
723		DisposeHandle((Handle)SDL_CTab);
724		SDL_CTab = nil;
725	}
726	if ( SDL_CPal != nil ) {
727		DisposePalette(SDL_CPal);
728		SDL_CPal = nil;
729	}
730	RestoreDeviceClut(GetMainDevice());
731
732#if SDL_MACCLASSIC_GAMMA_SUPPORT
733	Mac_QuitGamma(this);
734#endif
735
736	/* Free list of video modes */
737	if ( SDL_modelist != NULL ) {
738		for ( i=0; SDL_modelist[i]; ++i ) {
739			SDL_free(SDL_modelist[i]);
740		}
741		SDL_free(SDL_modelist);
742		SDL_modelist = NULL;
743	}
744}
745
746