diff src/video/macrom/SDL_romvideo.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children 45b1c4303f87
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/macrom/SDL_romvideo.c	Thu Apr 26 16:45:43 2001 +0000
@@ -0,0 +1,730 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if TARGET_API_MAC_CARBON
+#include <Carbon.h>
+/* The fullscreen code requires the QuickTime framework, and the window
+   is still at the back on MacOS X, which is where this code is needed.
+ */
+#if USE_QUICKTIME
+#include <Movies.h>
+#endif
+#else
+#include <LowMem.h>
+#include <Gestalt.h>
+#include <Devices.h>
+#include <DiskInit.h>
+#include <QDOffscreen.h>
+#endif
+
+#include "SDL_video.h"
+#include "SDL_error.h"
+#include "SDL_syswm.h"
+#include "SDL_sysvideo.h"
+#include "SDL_romvideo.h"
+#include "SDL_macgl_c.h"
+#include "SDL_macwm_c.h"
+#include "SDL_macmouse_c.h"
+#include "SDL_macevents_c.h"
+
+/* Initialization/Query functions */
+static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat);
+static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
+static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
+static int ROM_SetColors(_THIS, int firstcolor, int ncolors,
+			 SDL_Color *colors);
+static void ROM_VideoQuit(_THIS);
+
+/* Hardware surface functions */
+static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface);
+static int ROM_LockHWSurface(_THIS, SDL_Surface *surface);
+static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface);
+static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface);
+
+#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
+/* Saved state for the menu bar */
+static RgnHandle	gSaveGrayRgn = nil;
+static short		gSaveMenuBar = 0;
+static Boolean		gSaveCSVis = true;
+
+#if powerc
+/* Mixed mode glue to activate the 68K emulator and twiddle a register */
+#define ONEWORDSTUB(p1) \
+		{ 0x41FA, 0x0010, 0x209F, (p1), 0x41FA, \
+		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
+
+#define TWOWORDSTUB(p1,p2) \
+		{ 0x41FA, 0x0012, 0x209F, (p1), (p2), 0x41FA, \
+		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
+
+#define THREEWORDSTUB(p1,p2,p3) \
+		{ 0x41FA, 0x0014, 0x209F, (p1), (p2), (p3), 0x41FA, \
+		  0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 }
+
+/* ControlStrip inline glue for PowerPC */
+static pascal Boolean SBIsControlStripVisible(void)
+{
+	static short procData[] = TWOWORDSTUB(0x7000, 0xAAF2);
+	ProcInfoType procInfo = kD0DispatchedPascalStackBased
+				| RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
+            	| DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode);
+            				
+	return((Boolean) CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x00));
+}
+
+static pascal void SBShowHideControlStrip(Boolean showIt)
+{
+	static short procData[] = THREEWORDSTUB(0x303C, 0x0101, 0xAAF2);
+	ProcInfoType procInfo = kD0DispatchedPascalStackBased
+				| DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
+				| DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Boolean)));
+
+	CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x01, showIt);
+}
+#endif /* powerc */
+#endif /* !TARGET_API_MAC_CARBON */
+
+/* Macintosh toolbox driver bootstrap functions */
+
+static int ROM_Available(void)
+{
+	return(1);
+}
+
+static void ROM_DeleteDevice(SDL_VideoDevice *device)
+{
+	free(device->hidden);
+	free(device);
+}
+
+static SDL_VideoDevice *ROM_CreateDevice(int devindex)
+{
+	SDL_VideoDevice *device;
+
+	/* Initialize all variables that we clean on shutdown */
+	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
+	if ( device ) {
+		memset(device, 0, (sizeof *device));
+		device->hidden = (struct SDL_PrivateVideoData *)
+				malloc((sizeof *device->hidden));
+	}
+	if ( (device == NULL) || (device->hidden == NULL) ) {
+		SDL_OutOfMemory();
+		if ( device ) {
+			free(device);
+		}
+		return(0);
+	}
+	memset(device->hidden, 0, (sizeof *device->hidden));
+
+	/* Set the function pointers */
+	device->VideoInit = ROM_VideoInit;
+	device->ListModes = ROM_ListModes;
+	device->SetVideoMode = ROM_SetVideoMode;
+	device->SetColors = ROM_SetColors;
+	device->UpdateRects = NULL;
+	device->VideoQuit = ROM_VideoQuit;
+	device->AllocHWSurface = ROM_AllocHWSurface;
+	device->CheckHWBlit = NULL;
+	device->FillHWRect = NULL;
+	device->SetHWColorKey = NULL;
+	device->SetHWAlpha = NULL;
+	device->LockHWSurface = ROM_LockHWSurface;
+	device->UnlockHWSurface = ROM_UnlockHWSurface;
+	device->FlipHWSurface = NULL;
+	device->FreeHWSurface = ROM_FreeHWSurface;
+#ifdef HAVE_OPENGL
+	device->GL_MakeCurrent = Mac_GL_MakeCurrent;
+	device->GL_SwapBuffers = Mac_GL_SwapBuffers;
+#endif
+	device->SetCaption = Mac_SetCaption;
+	device->SetIcon = NULL;
+	device->IconifyWindow = NULL;
+	device->GrabInput = NULL;
+	device->GetWMInfo = NULL;
+	device->FreeWMCursor = Mac_FreeWMCursor;
+	device->CreateWMCursor = Mac_CreateWMCursor;
+	device->ShowWMCursor = Mac_ShowWMCursor;
+	device->WarpWMCursor = Mac_WarpWMCursor;
+	device->InitOSKeymap = Mac_InitOSKeymap;
+	device->PumpEvents = Mac_PumpEvents;
+
+	device->free = ROM_DeleteDevice;
+
+	return device;
+}
+
+VideoBootStrap TOOLBOX_bootstrap = {
+	"toolbox", "MacOS ROM Toolbox",
+	ROM_Available, ROM_CreateDevice
+};
+
+
+static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat)
+{
+	long info;
+	
+	/* Check out some things about the system */
+	Gestalt(gestaltQuickdrawVersion, &info);
+	if ( info == gestaltOriginalQD ) {
+		SDL_SetError("Color Quickdraw not available");
+		return(-1);
+	}
+
+	/* Start ROMintosh events */
+	Mac_InitEvents(this);
+
+	/* Get a handle to the main monitor */
+	SDL_Display = GetMainDevice();
+
+	/* Determine pixel format */
+	vformat->BitsPerPixel = (**(**SDL_Display).gdPMap).pixelSize;
+	switch (vformat->BitsPerPixel) {
+		case 16:	/* 5-5-5 RGB */
+			vformat->Rmask = 0x00007c00;
+			vformat->Gmask = 0x000003e0;
+			vformat->Bmask = 0x0000001f;
+			break;
+		default:
+			break;
+	}
+
+	/* Create our palette */
+	SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8);
+	if ( SDL_CTab == nil ) {
+		SDL_OutOfMemory();
+		return(-1);
+	}
+	(**SDL_CTab).ctSeed = GetCTSeed();
+	(**SDL_CTab).ctFlags = 0;
+	(**SDL_CTab).ctSize = 255;
+	CTabChanged(SDL_CTab);
+	SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0);
+
+	/* Get a list of available fullscreen modes */
+	SDL_modelist = (SDL_Rect **)malloc((1+1)*sizeof(SDL_Rect *));
+	if ( SDL_modelist ) {
+		SDL_modelist[0] = (SDL_Rect *)malloc(sizeof(SDL_Rect));
+		if ( SDL_modelist[0] ) {
+			SDL_modelist[0]->x = 0;
+			SDL_modelist[0]->y = 0;
+			SDL_modelist[0]->w = (**SDL_Display).gdRect.right;
+			SDL_modelist[0]->h = (**SDL_Display).gdRect.bottom;
+		}
+		SDL_modelist[1] = NULL;
+	}
+
+	/* Fill in some window manager capabilities */
+	this->info.wm_available = 1;
+
+	/* We're done! */
+	return(0);
+}
+
+static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
+{
+	if ( this->screen->format->BitsPerPixel == format->BitsPerPixel ) {
+		if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
+			return(SDL_modelist);
+		} else {
+			return((SDL_Rect **)-1);
+		}
+	} else {
+		return((SDL_Rect **)0);
+	}
+}
+
+static void ROM_HideMenuBar(_THIS)
+{
+#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
+	RgnHandle		drawRgn = nil;
+	RgnHandle		tempRgn = nil;
+	RgnHandle		grayRgn = nil;
+	WindowPtr		window = nil;
+	GDHandle		gd = nil;
+	GrafPtr			savePort;
+	long			response;
+	short			height;
+	EventRecord		theEvent;
+
+	height = GetMBarHeight();
+	
+	if ( height > 0 ) {
+		tempRgn = NewRgn();
+		drawRgn = NewRgn();
+		gSaveGrayRgn = NewRgn();
+		if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) {
+			goto CLEANUP;
+		}
+		grayRgn = GetGrayRgn(); /* No need to check for this */
+	
+		GetPort(&savePort);
+
+		/* Hide the control strip if it's present, and record its 
+		   previous position into the dirty region for redrawing. 
+		   This isn't necessary, but may help catch stray bits. */
+		CopyRgn(grayRgn, tempRgn);
+		if (!Gestalt(gestaltControlStripAttr, &response) && 
+			(response & (1L << gestaltControlStripExists))) {
+			gSaveCSVis = SBIsControlStripVisible();
+			if (gSaveCSVis)
+				SBShowHideControlStrip(false);
+		}
+		DiffRgn(grayRgn, tempRgn, drawRgn);
+
+		/* Save the gray region once the control strip is hidden*/
+		CopyRgn(grayRgn, gSaveGrayRgn);
+
+		/* Change the menu height in lowmem */
+		gSaveMenuBar = height;
+		LMSetMBarHeight(0);
+		
+		/* Walk the monitor rectangles, and combine any pieces that
+		   aren't in GrayRgn: menubar, round corners, fake floaters. */
+		for(gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) 
+			{
+			if (!TestDeviceAttribute(gd, screenDevice)) continue;
+			if (!TestDeviceAttribute(gd, screenActive)) continue;
+
+			RectRgn(tempRgn, &(*gd)->gdRect);	/* Get the whole screen */
+			DiffRgn(tempRgn, grayRgn, tempRgn); /* Subtract out GrayRgn */
+			UnionRgn(tempRgn, drawRgn, drawRgn);/* Combine all the bits */
+			}
+			
+		/* Add the bits into the GrayRgn */
+		UnionRgn(drawRgn, grayRgn, grayRgn);
+
+		/* Modify the vis regions of exposed windows */
+		window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L;
+		PaintBehind(window, drawRgn);
+		CalcVisBehind(window, drawRgn);
+
+		SetPort(savePort);
+		
+		/* Yield time so that floaters can catch up */
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		}
+
+CLEANUP:
+
+	if (tempRgn) DisposeRgn(tempRgn);
+	if (drawRgn) DisposeRgn(drawRgn);
+#endif /* !TARGET_API_MAC_CARBON */
+}
+	
+static void ROM_ShowMenuBar(_THIS)
+{
+#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */
+	RgnHandle		drawRgn = nil;
+	RgnHandle		menuRgn = nil;
+	RgnHandle		tempRgn = nil;
+	RgnHandle		grayRgn = nil;
+	WindowPtr		window = nil;
+	GrafPtr			wMgrPort;
+	GrafPtr			savePort;
+	Rect			menuRect;
+	long			response;
+	short			height;
+	EventRecord		theEvent;
+	RGBColor		saveRGB;
+	RGBColor		blackRGB = { 0, 0, 0 };
+
+	height = GetMBarHeight();
+	
+	if ((height <= 0) && (gSaveMenuBar > 0)) {
+		drawRgn = NewRgn();
+		menuRgn = NewRgn();
+		tempRgn = NewRgn();
+		if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) {
+			goto CLEANUP;
+		}
+		grayRgn = GetGrayRgn(); /* No need to check for this */
+	
+		GetPort(&savePort);
+		GetWMgrPort(&wMgrPort);
+
+		/* Set the height properly */
+		LMSetMBarHeight(gSaveMenuBar);
+
+		/* Restore the old GrayRgn: rounded corners, etc, but not
+		   the menubar -- subtract that out first! */
+		if (gSaveGrayRgn)
+			{
+			menuRect = (*GetMainDevice())->gdRect;
+			menuRect.bottom = menuRect.top + gSaveMenuBar;
+			RectRgn(menuRgn, &menuRect);
+
+			DiffRgn(grayRgn, gSaveGrayRgn, drawRgn); 	/* What do we inval? */
+			DiffRgn(drawRgn, menuRgn, drawRgn);			/* Clip out the menu */
+			
+			/* Now redraw the corners and other bits black */
+			SetPort(wMgrPort);
+			GetClip(tempRgn);
+			SetClip(drawRgn);
+			GetForeColor(&saveRGB);
+			RGBForeColor(&blackRGB);
+			PaintRgn(drawRgn);
+			RGBForeColor(&saveRGB);
+			SetClip(tempRgn);
+			SetPort(savePort);
+			
+			UnionRgn(drawRgn, menuRgn, drawRgn);		/* Put back the menu */
+
+			/* Now actually restore the GrayRgn */
+			CopyRgn(gSaveGrayRgn, grayRgn);
+			DisposeRgn(gSaveGrayRgn);
+			gSaveGrayRgn = nil;
+			}
+
+		/* Modify the vis regions of exposed windows and draw menubar */
+		window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L;
+		PaintBehind(window, drawRgn);
+		CalcVisBehind(window, drawRgn);
+		DrawMenuBar();
+
+		SetPort(savePort);
+		gSaveMenuBar = 0;
+
+		/* Now show the control strip if it's present */
+		if (!Gestalt(gestaltControlStripAttr, &response) && 
+				(response & (1L << gestaltControlStripExists)))
+			{
+			if (gSaveCSVis && !SBIsControlStripVisible())
+				SBShowHideControlStrip(true);
+			gSaveCSVis = true;
+			}
+
+		/* Yield time so that floaters can catch up */
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		EventAvail(0, &theEvent);
+		}
+
+CLEANUP:
+
+	if (drawRgn) DisposeRgn(drawRgn);
+	if (menuRgn) DisposeRgn(menuRgn);
+	if (tempRgn) DisposeRgn(tempRgn);
+#endif /* !TARGET_API_MAC_CARBON */
+}
+
+/* Various screen update functions available */
+static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
+static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
+
+static void ROM_UnsetVideoMode(_THIS, SDL_Surface *current)
+{
+	/* Free the current window, if any */
+	if ( SDL_Window != nil ) {
+		GWorldPtr memworld;
+		
+		/* Handle OpenGL support */
+		Mac_GL_Quit(this);
+
+		memworld = (GWorldPtr)GetWRefCon(SDL_Window);
+		if ( memworld != nil ) {
+			UnlockPixels(GetGWorldPixMap(memworld));
+			DisposeGWorld(memworld);
+		}
+		if ( (current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
+#if USE_QUICKTIME
+			EndFullScreen(fullscreen_ctx, nil);
+			SDL_Window = nil;
+#else
+			ROM_ShowMenuBar(this);
+#endif
+		}
+	}
+	current->pixels = NULL;
+	current->flags &= ~(SDL_HWSURFACE|SDL_FULLSCREEN);
+}
+
+static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current,
+				int width, int height, int bpp, Uint32 flags)
+{
+	Rect wrect, orect;
+#if TARGET_API_MAC_CARBON
+	Rect tmprect;
+#endif
+
+	/* Free any previous video mode */
+	ROM_UnsetVideoMode(this, current);
+
+	/* Create the ROM window and SDL video surface */
+	current->flags = 0;		/* Clear flags */
+	current->w = width;
+	current->h = height;
+	SetRect(&wrect, 0, 0, width, height);
+	if ( SDL_Window ) {
+		/* If we recreate the window, don't move it around */
+#if TARGET_API_MAC_CARBON
+		orect = *GetWindowPortBounds(SDL_Window, &tmprect);
+#else
+		orect = SDL_Window->portRect;
+#endif
+		OffsetRect(&wrect, orect.left, orect.top);
+	} else {
+		/* Center the window the first time we show it */
+		OffsetRect(&wrect,
+		(SDL_modelist[0]->w-width)/2, (SDL_modelist[0]->h-height)/2);
+	}
+
+#if MACOSX && !USE_QUICKTIME
+	/* Hum.. fullscreen mode is broken */
+	flags &= ~SDL_FULLSCREEN;
+#endif
+	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
+		/* Create the fullscreen window and use screen bits */
+		current->flags |= SDL_HWSURFACE|SDL_FULLSCREEN;
+		if ( SDL_Window ) {
+			DisposeWindow(SDL_Window);
+		}
+#if USE_QUICKTIME
+		BeginFullScreen(&fullscreen_ctx, nil, 0,0, &SDL_Window, nil, 0);
+#else
+		SDL_Window = NewCWindow(nil, &wrect, "\p", true, plainDBox,
+						(WindowPtr)-1, false, 0);
+		ROM_HideMenuBar(this);
+#endif
+		current->pitch = (**(**SDL_Display).gdPMap).rowBytes & 0x3FFF;
+		current->pixels = (**(**SDL_Display).gdPMap).baseAddr;
+		this->UpdateRects = ROM_DirectUpdate;
+	} else {
+		GWorldPtr memworld;
+		PixMapHandle pixmap;
+		int style;
+
+		style = noGrowDocProc;
+		if ( flags & SDL_NOFRAME ) {
+			style = plainDBox;
+			current->flags |= SDL_NOFRAME;
+		} else
+		if ( flags & SDL_RESIZABLE ) {
+			style = zoomDocProc;
+			current->flags |= SDL_RESIZABLE;
+		}
+		if ( SDL_Window && (style == current_style) ) {
+			/* Resize existing window, if necessary */
+			if ( ((orect.right-orect.left) != width) ||
+			     ((orect.bottom-orect.top) != height) ) {
+				SizeWindow(SDL_Window, width, height, false);
+			}
+		} else {
+			/* Recreate the window in the new style */
+			if ( SDL_Window ) {
+				DisposeWindow(SDL_Window);
+			}
+			SDL_Window = NewCWindow(nil, &wrect, "\p", true,
+			                        style, (WindowPtr)-1, true, 0);
+
+			/* Set the window title, if any */
+			{ char *title;
+				SDL_WM_GetCaption(&title, NULL);
+				if ( title ) {
+					Mac_SetCaption(this, title, NULL);
+				}
+			}
+		}
+		current_style = style;
+		SetPalette(SDL_Window, SDL_CPal, false);
+		ActivatePalette(SDL_Window);
+		if ( NewGWorld(&memworld, 0,
+#if TARGET_API_MAC_CARBON
+			       GetWindowPortBounds(SDL_Window, &tmprect),
+#else
+			       &SDL_Window->portRect,
+#endif
+			       SDL_CTab, nil, 0) != noErr ) {
+			SDL_SetError("NewGWorld() failed");
+			return(NULL);
+		}
+		SetWRefCon(SDL_Window, (long)memworld);
+		pixmap = GetGWorldPixMap(memworld);
+		LockPixels(pixmap);
+		current->pitch = (**pixmap).rowBytes & 0x3FFF;
+		current->pixels = GetPixBaseAddr(pixmap);
+		this->UpdateRects = ROM_WindowUpdate;
+	}
+	SetPortWindowPort(SDL_Window);
+	SelectWindow(SDL_Window);
+
+	/* Handle OpenGL support */
+	if ( flags & SDL_OPENGL ) {
+		if ( Mac_GL_Init(this) == 0 ) {
+			current->flags |= SDL_OPENGL;
+		} else {
+			current = NULL;
+		}
+	}
+	
+	if ( (flags & SDL_HWPALETTE) && (flags & SDL_FULLSCREEN) )
+	   current->flags |= SDL_HWPALETTE;
+	   
+	/* We're live! */
+	return(current);
+}
+
+/* We don't actually allow hardware surfaces other than the main one */
+static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+	return(-1);
+}
+static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+	return;
+}
+static int ROM_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+	return(0);
+}
+static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+	return;
+}
+
+static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+	/* The application is already updating the visible video memory */
+	return;
+}
+
+static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
+{
+	GWorldPtr memworld;
+	GrafPtr saveport;
+	CGrafPtr thePort;
+	const BitMap *memBits;
+	const BitMap *winBits;
+	int i;
+	Rect update;
+	
+	/* Copy from the offscreen GWorld to the window port */
+	GetPort(&saveport);
+	SetPortWindowPort(SDL_Window);
+	thePort = GetWindowPort(SDL_Window);
+	memworld = (GWorldPtr)GetWRefCon(SDL_Window);
+#if TARGET_API_MAC_CARBON
+	memBits = GetPortBitMapForCopyBits((CGrafPtr) memworld);
+#else
+	memBits = &((GrafPtr)memworld)->portBits;
+#endif
+#if TARGET_API_MAC_CARBON
+	winBits = GetPortBitMapForCopyBits(thePort);
+#else
+	winBits = &SDL_Window->portBits;
+#endif
+	for ( i=0; i<numrects; ++i ) {
+		update.left = rects[i].x;
+		update.right = rects[i].x+rects[i].w;
+		update.top = rects[i].y;
+		update.bottom = rects[i].y+rects[i].h;
+		CopyBits(memBits, winBits,
+			 &update, &update, srcCopy, nil);
+	}
+#if TARGET_API_MAC_CARBON
+	if ( QDIsPortBuffered(thePort) ) {
+		QDFlushPortBuffer(thePort, NULL);
+	}
+#endif
+	SetPort(saveport);
+}
+
+static int ROM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
+{
+	CTabHandle cTab;
+	int i;
+
+	/* Get the colortable from the either the display or window */
+	if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
+		cTab = (**(**SDL_Display).gdPMap).pmTable;
+	} else {
+		cTab = SDL_CTab;
+	}
+
+	/* Verify the range of colors */
+	if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) {
+		return(0);
+	}
+	
+	/* Set the screen palette and update the display */
+	for ( i=0; i< ncolors; ++i ) {
+	        int j = firstcolor + i;
+		(**cTab).ctTable[j].value = j;
+		(**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r;
+		(**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g;
+		(**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b;
+	}
+//	if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) 
+{
+		GDevice **odisplay;
+		odisplay = GetGDevice();
+		SetGDevice(SDL_Display);
+		SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable);
+		SetGDevice(odisplay);
+	}
+	return(1);
+}
+
+void ROM_VideoQuit(_THIS)
+{
+	int i;
+
+	/* Free current video mode */
+	ROM_UnsetVideoMode(this, this->screen);
+	if ( SDL_Window ) {
+		DisposeWindow(SDL_Window);
+		SDL_Window = nil;
+	}
+
+	/* Free palette and restore original one */
+	if ( SDL_CTab != nil ) {
+		DisposeHandle((Handle)SDL_CTab);
+		SDL_CTab = nil;
+	}
+	if ( SDL_CPal != nil ) {
+		DisposePalette(SDL_CPal);
+		SDL_CPal = nil;
+	}
+	RestoreDeviceClut(GetMainDevice());
+
+	/* Free list of video modes */
+	if ( SDL_modelist != NULL ) {
+		for ( i=0; SDL_modelist[i]; ++i ) {
+			free(SDL_modelist[i]);
+		}
+		free(SDL_modelist);
+		SDL_modelist = NULL;
+	}
+}
+