Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/Graphics.c
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ |
//¥ Copyright © 1996-1999 Apple Computer, Inc., All Rights Reserved |
//¥ |
//¥ |
//¥ You may incorporate this sample code into your applications without |
//¥ restriction, though the sample code has been provided "AS IS" and the |
//¥ responsibility for its operation is 100% yours. However, what you are |
//¥ not permitted to do is to redistribute the source as "DSC Sample Code" |
//¥ after having made changes. If you're going to re-distribute the source, |
//¥ we require that you make it clear in the source that the code was |
//¥ descended from Apple Sample Code, but that you've made changes. |
//¥ |
//¥ Authors: |
//¥ Chris De Salvo |
//¥ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ ------------------------------ Includes |
#include <Types.h> |
#include <Resources.h> |
#include <string.h> |
#include "DrawSprocket.h" |
#include "ErrorHandler.h" |
#include "Graphics.h" |
#include "MemoryHandler.h" |
#include "SIResources.h" |
#include "Sprite.h" |
//¥ ------------------------------ Private Definitions |
#define kFirstIconColor 1 |
#define kLastIconColor 33 |
#define kFirstBGColor 34 |
#define kLastBGColor 183 |
#define kFirstSpriteColor 184 |
#define kLastSpriteColor 254 |
//¥ ------------------------------ Private Types |
//¥ ------------------------------ Private Variables |
static DSpAltBufferReference gUnderlay; |
static CTabHandle gGameCLUT; |
//¥ ------------------------------ Private Functions |
static void GraphicsUpdateScreenPalette(UInt16 inFirstColor, UInt16 inLastColor); |
static void GraphicsCreateUnderlay(void); |
static void GraphicsSelectContext(SInt16 modifiers); |
static void GraphicsInitAttributes(DSpContextAttributes *inAttributes); |
//¥ ------------------------------ Public Variables |
DSpContextReference gDisplayContext; |
DSpContextAttributes gDisplayAttributes; |
GDHandle gGameGDH; |
const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 }; |
const RGBColor rgbWhite = { 0xFFFF, 0xFFFF, 0xFFFF }; |
const RGBColor rgbRed = { 0xFFFF, 0x0000, 0x0000 }; |
const RGBColor rgbBlue = { 0x0000, 0x0000, 0xFFFF }; |
const RGBColor rgbYellow = { 0xFFFF, 0xFFFF, 0x0000 }; |
const RGBColor rgbGreen = { 0x0000, 0xFFFF, 0x0000 }; |
#pragma mark ÑÑÑÑÑ Startup/Shutdown ÑÑÑÑÑ |
//¥ -------------------- GraphicsInit |
void |
GraphicsInit(SInt16 modifiers) |
{ |
CGrafPtr backBuffer; |
OSErr theErr; |
Rect r = { 40, 40, 100, 100 }; |
theErr = DSpStartup(); |
if (theErr) |
FatalError("GraphicsInit: DSpStartup() failed!!!!"); |
//¥ CLUT 8 is the standard 8-bit color system color table and is |
//¥ always present |
gGameCLUT = GetCTable(8); |
DetachResource((Handle) gGameCLUT); |
//¥ Define and create our drawing context |
GraphicsSelectContext(modifiers); |
//¥ Add our various colors to the color table |
GraphicsMergeCLUT(128, kFirstIconColor, kLastIconColor); |
GraphicsMergeCLUT(kPICTGasCloud, kFirstBGColor, kLastBGColor); |
GraphicsMergeCLUT(kCLUTSprites, kFirstSpriteColor, kLastSpriteColor); |
//¥ Create our underlay and load a picture into it |
GraphicsCreateUnderlay(); |
GraphicsLoadBackground(kPICTGasCloud); |
//¥ Swap the buffers once to get the underlay image on the screen |
DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &backBuffer); |
DSpContext_InvalBackBufferRect(gDisplayContext, &backBuffer->portRect); |
GraphicsUpdateScreen(); |
//¥ Fade up from black and then put the context in the paused state |
//¥ so that the user has access to the menu bar. |
DSpContext_FadeGammaIn(nil, nil); |
GraphicsPaused(); |
} |
//¥ -------------------- GraphicsReset |
void |
GraphicsReset(void) |
{ |
DSpContext_FadeGammaOut(nil, nil); |
GraphicsInactive(); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(gDisplayContext); |
DSpShutdown(); |
} |
#pragma mark ÑÑÑÑÑ Context Management ÑÑÑÑÑ |
//¥ -------------------- GraphicsSelectContext |
static void |
GraphicsSelectContext(SInt16 modifiers) |
{ |
OSStatus theError; |
DisplayIDType displayID; |
//¥ Initialize our context description |
GraphicsInitAttributes(&gDisplayAttributes); |
//¥ Tell DrawSprocket the exact needs we have for our game |
gDisplayAttributes.displayWidth = 640; |
gDisplayAttributes.displayHeight = 480; |
gDisplayAttributes.colorNeeds = kDSpColorNeeds_Require; |
gDisplayAttributes.backBufferDepthMask = kDSpDepthMask_8; |
gDisplayAttributes.displayDepthMask = kDSpDepthMask_8; |
gDisplayAttributes.backBufferBestDepth = 8; |
gDisplayAttributes.displayBestDepth = 8; |
gDisplayAttributes.pageCount = 2; |
gDisplayAttributes.colorTable = gGameCLUT; |
//¥ Find the best context for these attributes |
//¥ This call will check to see if multiple monitors can handle the request |
//¥ If there is more than one valid device it will put up the selection interface |
theError = DSpUserSelectContext(&gDisplayAttributes, 0L, nil, &gDisplayContext); |
if (theError) |
FatalError("A suitable display context could not be found."); |
if (modifiers & optionKey) |
gDisplayAttributes.contextOptions |= kDSpContextOption_DontSyncVBL; |
//¥ Page flipping only works on 7500/7600/8500/8600 machines and only when |
//¥ there is >= 4 MB of VRAM. There are very few of these machines in |
//¥ existance so turning on this option is not recommended. |
//¥ gDisplayAttributes.contextOptions |= kDSpContextOption_PageFlip; |
//¥ Set the blanking color to black |
DSpSetBlankingColor(&rgbBlack); |
//¥ Find the DisplayID for this draw context and then find the GDevice |
//¥ that goes along with it. We need this because if we need to perform |
//¥ QuickDraw operations in a context that isn't on the main monitor then |
//¥ we need to have the proper GDevice set or QuickDraw loses its mind. |
theError = DSpContext_GetDisplayID(gDisplayContext, &displayID); |
if (theError) |
FatalError("DSpContext_GetDisplayID() had an error."); |
theError = DMGetGDeviceByDisplayID(displayID, &gGameGDH, false); |
if (theError) |
FatalError("DMGetGDeviceByDisplayID() had an error."); |
//¥ Reserve the draw context so that we get the attributes we want |
theError = DSpContext_Reserve(gDisplayContext, &gDisplayAttributes); |
if (theError) |
FatalError("Could not reserve display context."); |
//¥ Fade the screen to black and make our context active |
DSpContext_FadeGammaOut(nil, nil); |
GraphicsActive(); |
} |
//¥ -------------------- GraphicsInitAttributes |
static void |
GraphicsInitAttributes(DSpContextAttributes *inAttributes) |
{ |
if (! inAttributes) |
FatalError("Nil context passed to MyInitAttributes()."); |
memset(inAttributes, 0, sizeof (DSpContextAttributes)); |
} |
//¥ -------------------- GraphicaCreateUnderlay |
static void |
GraphicsCreateUnderlay(void) |
{ |
OSStatus theError; |
//¥ Create a new alt buffer which mimics the onscreen display |
theError = DSpAltBuffer_New(gDisplayContext, true, 0L, &gUnderlay); |
if (theError) |
FatalError("Could not create underlay buffer."); |
//¥ Make it the active underlay |
theError = DSpContext_SetUnderlayAltBuffer(gDisplayContext, gUnderlay); |
if (theError) |
FatalError("Could not set underlay buffer."); |
} |
//¥ -------------------- GraphicsGetUnderlayGrafPort |
void |
GraphicsGetUnderlayGrafPort(CGrafPtr *underlay, GDHandle *device) |
{ |
DSpAltBuffer_GetCGrafPtr(gUnderlay, kDSpBufferKind_Normal, underlay, device); |
} |
#pragma mark ÑÑÑÑÑ Image Management ÑÑÑÑÑ |
//¥ -------------------- GraphicsLoadBackground |
void |
GraphicsLoadBackground(SInt16 whichBG) |
{ |
GrafPtr oldPort; |
GDHandle oldDevice; |
GDHandle underlayDevice; |
PicHandle thePict; |
CGrafPtr backBuff; |
Rect r; |
thePict = GetPicture(whichBG); |
if (! thePict) |
FatalError("Could not load background."); |
//¥ Get a CGrafPtr reference to the underlay graphics buffer |
DSpAltBuffer_GetCGrafPtr(gUnderlay, kDSpBufferKind_Normal, &backBuff, &underlayDevice); |
GetPort(&oldPort); |
oldDevice = GetGDevice(); |
SetPort((GrafPtr) backBuff); |
SetGDevice(underlayDevice); |
RGBForeColor(&rgbBlack); |
RGBBackColor(&rgbWhite); |
//¥ Fill the background with black |
PaintRect(&backBuff->portRect); |
HLock((Handle) thePict); |
SetRect(&r, 0, 0, 640, 440); |
DrawPicture(thePict, &r); |
KillPictureZ(&thePict); |
//¥ Invalidate the entire underlay so that all other back buffers |
//¥ get the new image copied up to them. |
DSpAltBuffer_InvalRect(gUnderlay, &backBuff->portRect); |
SetPort(oldPort); |
SetGDevice(oldDevice); |
} |
//¥ -------------------- GraphicsMergeCLUT |
void |
GraphicsMergeCLUT(SInt16 clutID, UInt16 firstColor, UInt16 lastColor) |
{ |
CTabHandle ct; |
UInt32 i; |
//¥ Load the appropritate 'CLUT' resource |
ct = GetCTable(clutID); |
if (! ct) |
FatalError("Could not load color table for merge."); |
HLock((Handle) ct); |
//¥ Copy colors from it to our game color table |
for (i = firstColor; i <= lastColor; i++) |
{ |
(**gGameCLUT).ctTable[i].rgb.red = (**ct).ctTable[i].rgb.red; |
(**gGameCLUT).ctTable[i].rgb.green = (**ct).ctTable[i].rgb.green; |
(**gGameCLUT).ctTable[i].rgb.blue = (**ct).ctTable[i].rgb.blue; |
} |
HUnlock((Handle) ct); |
ReleaseResource((Handle) ct); |
//¥ Make the new game color table the active color environment |
GraphicsUpdateScreenPalette(firstColor, lastColor); |
} |
//¥ -------------------- GraphicsUpdateScreenPalette |
static void |
GraphicsUpdateScreenPalette(UInt16 inFirstColor, UInt16 inLastColor) |
{ |
OSStatus theError; |
//¥ Copy our game color table to our DrawSprocket context. This also |
//¥ updates the color environment of any buffers that we've allocated with |
//¥ DrawSprocket. |
theError = DSpContext_SetCLUTEntries(gDisplayContext, (**gGameCLUT).ctTable, inFirstColor, inLastColor - inFirstColor); |
if( theError ) |
DebugStr("\p error from CLUT "); |
} |
//¥ -------------------- GraphicsSetRectDirty |
void |
GraphicsSetRectDirty(RectPtr r) |
{ |
DSpContext_InvalBackBufferRect(gDisplayContext, r); |
} |
//¥ -------------------- GraphicsSetUnderlayRectDirty |
void |
GraphicsSetUnderlayRectDirty(RectPtr r) |
{ |
DSpAltBuffer_InvalRect(gUnderlay, r); |
} |
//¥ -------------------- GraphicsUpdateScreen |
void |
GraphicsUpdateScreen(void) |
{ |
DSpContext_SwapBuffers(gDisplayContext, nil, nil); |
} |
#pragma mark ÑÑÑÑÑ Context State ÑÑÑÑÑ |
//¥ -------------------- GraphicsActive |
void |
GraphicsActive(void) |
{ |
OSStatus theErr; |
HideCursor(); |
theErr = DSpContext_SetState(gDisplayContext, kDSpContextState_Active); |
if (theErr) |
DebugStr("\pSetState active failed in GraphicsActive()."); |
} |
//¥ -------------------- GraphicsPaused |
void |
GraphicsPaused(void) |
{ |
DSpContext_SetState(gDisplayContext, kDSpContextState_Paused); |
ShowCursor(); |
DrawMenuBar(); |
} |
//¥ -------------------- GraphicsInactive |
void |
GraphicsInactive(void) |
{ |
DSpContext_SetState(gDisplayContext, kDSpContextState_Inactive); |
ShowCursor(); |
} |
//¥ -------------------- GraphicsDoUpdateEvent |
void |
GraphicsDoUpdateEvent(void) |
{ |
GrafPtr savePort; |
GDHandle saveGDH; |
CGrafPtr backBuffer; |
CGrafPtr frontBuffer; |
DSpContext_GetFrontBuffer(gDisplayContext, &frontBuffer); |
DSpContext_GetBackBuffer(gDisplayContext, kDSpBufferKind_Normal, &backBuffer); |
GetPort(&savePort); |
saveGDH = GetGDevice(); |
SetPort((GrafPtr) frontBuffer); |
SetGDevice(gGameGDH); |
ForeColor(blackColor); |
BackColor(whiteColor); |
CopyBits((BitMapPtr) *backBuffer->portPixMap, (BitMapPtr) *frontBuffer->portPixMap, |
&backBuffer->portRect, &frontBuffer->portRect, srcCopy, nil); |
SetPort(savePort); |
SetGDevice(saveGDH); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14