/* Copyright (C) 2015-2018 Night Dive Studios, LLC. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ //==================================================================================== // // System Shock - ©1994-1995 Looking Glass Technologies, Inc. // // ShockBitmap.c - Manages off-screen bitmaps and palettes. // //==================================================================================== //-------------------- // Includes //-------------------- //#include "OldCarbonHeaders.h" //#include #include "Shock.h" #include "InitMac.h" #include "ShockBitmap.h" #include "2d.h" //#import //-------------------- // Prototypes //-------------------- //int TrackTitleButton(int btn); //-------------------- // Globals //-------------------- SDL_Surface* drawSurface; SDL_Surface* offscreenDrawSurface; int cur_bm_width; int cur_bm_height; //------------------------------------------------------------------------------------ // Setup the main offscreen bitmaps. //------------------------------------------------------------------------------------ void SetupOffscreenBitmaps(int width, int height) { DEBUG("SetupOffscreenBitmaps %i %i", width, height); if(drawSurface != NULL) { SDL_FreeSurface(drawSurface); } if(offscreenDrawSurface != NULL) { SDL_FreeSurface(offscreenDrawSurface); } drawSurface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0); if(!drawSurface) { ERROR("SDL: Failed to create draw surface"); return; } offscreenDrawSurface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0); if(!offscreenDrawSurface) { ERROR("SDL: Failed to create offscreen draw surface"); return; } // Point the renderer at the screen bytes gScreenRowbytes = drawSurface->w; gScreenAddress = drawSurface->pixels; grd_mode_cap.vbase = (uchar *)gScreenAddress; cur_bm_width = width; cur_bm_height = height; } //------------------------------------------------------------------------------------ // Reset the CTseeds of the screen & pixmap to be the same //------------------------------------------------------------------------------------ void ResetCTSeed(void) { //(*gMainColorHand)->ctSeed = (*(*gScreenPixMap)->pmTable)->ctSeed; //(*(**(*(CWindowPtr)gMainWindow).portPixMap).pmTable)->ctSeed = (*gMainColorHand)->ctSeed; } //------------------------------------------------------------------------------------ // Save the screen pixmap's ctSeed before a suspend. //------------------------------------------------------------------------------------ long oldctSeed; void RememberSeed(void) { //oldctSeed = (*(*gScreenPixMap)->pmTable)->ctSeed; } //------------------------------------------------------------------------------------ // If the palette changed while switched out, then reset it. //------------------------------------------------------------------------------------ void FixPalette(void) { /*if ((*(*gScreenPixMap)->pmTable)->ctSeed != oldctSeed) { if (CurScreenDepth() == 8) SetEntries(0, 255, (**(gMainColorHand)).ctTable); ResetCTSeed(); DrawMenuBar(); UpdateWindow(gMainWindow); }*/ } /* //------------------------------------------------------------------------------------ // Setup a new ShockBitmap structure. //------------------------------------------------------------------------------------ void NewShockBitmap(ShockBitmap *theMap, short width, short height, Boolean color) { GrafPtr savePort; PixMapPtr pmaptr; GetPort(&savePort); theMap->Color = color; theMap->bits = 0L; SetRect(&theMap->bounds, 0, 0, width, height); if (theMap->Color) // Setup color pixmaps. { theMap->OrigBits = Build8PixMap(&theMap->CPort, width, height); SetPort((GrafPtr)&theMap->CPort); EraseRect(&theMap->bounds); //pmaptr = *(theMap->CPort.portPixMap); theMap->Address = StripAddress(pmaptr->baseAddr); theMap->RowBytes = (long)(pmaptr->rowBytes & 0x7FFF); theMap->bits = (GrafPtr) &theMap->CPort; } else // setup B&W maps { theMap->BWBits.bounds = theMap->bounds; theMap->BWBits.rowBytes = ((width+15) >> 4)<<1; // round to even theMap->BWBits.baseAddr = malloc(((long) height * (long) theMap->BWBits.rowBytes)); FailNIL(theMap->BWBits.baseAddr); theMap->BWBits.baseAddr = StripAddress(theMap->BWBits.baseAddr); OpenPort(&theMap->BWPort); SetPort(&theMap->BWPort); SetPortBits(&theMap->BWBits); // make sure the clip & vis regions are big enough //SetRectRgn(theMap->BWPort.visRgn,theMap->bounds.left,theMap->bounds.top,theMap->bounds.right,theMap->bounds.bottom); //SetRectRgn(theMap->BWPort.clipRgn,theMap->bounds.left,theMap->bounds.top,theMap->bounds.right,theMap->bounds.bottom); EraseRect(&theMap->bounds); theMap->Address = theMap->BWBits.baseAddr; theMap->RowBytes = (long) theMap->BWBits.rowBytes; theMap->bits = (GrafPtr) &theMap->BWPort; } SetPort(savePort); } */ //------------------------------------------------------------------------------------ // Deallocate a Shock bitmap. //------------------------------------------------------------------------------------ void FreeShockBitmap(ShockBitmap *theMap) { /*if (theMap->Color) { if (theMap->OrigBits != 0L) DisposeHandle(theMap->OrigBits); CloseCPort(&theMap->CPort); } else { ClosePort(&theMap->BWPort); free(theMap->Address); }*/ } //------------------------------------------------------------------------------------ // Code to build an offscreen pixmap (8bit) of a given size, using the current pStd clut // store pixmap in ColorBack cGrafPort. //------------------------------------------------------------------------------------ /* Handle Build8PixMap(CGrafPtr theCGrafPtr, short width, short height) { printf("Build8PixMap\n"); Rect bRect; PixMapHandle pmap; PixMapPtr pmaptr; long bytes; Handle hand; SetRect(&bRect, 0, 0, width, height); OpenCPort(theCGrafPtr); // open a new color port Ñ this calls InitCPort pmap = NewPixMap(); MoveHHi((Handle)pmap); HLock((Handle)pmap); //theCGrafPtr->portPixMap = pmap; //pmaptr = *(theCGrafPtr->portPixMap); pmaptr->bounds=bRect; pmaptr->rowBytes = ((width+1)>>1)<<1; bytes = (long) height * (long)pmaptr->rowBytes; pmaptr->rowBytes |= 0x8000; hand = NewHandle(bytes + 32); FailNIL((Ptr) hand); MoveHHi(hand); HLock(hand); pmaptr->baseAddr = (Ptr)((unsigned long)(*hand+31) & 0xFFFFFFE0); pmaptr->pmTable = gMainColorHand; // make sure the clip & vis regions are big enough //SetRectRgn(theCGrafPtr->visRgn,bRect.left,bRect.top,bRect.right,bRect.bottom); //SetRectRgn(theCGrafPtr->clipRgn,bRect.left,bRect.top,bRect.right,bRect.bottom); PenNormal(); return (NULL); } */ //------------------------------------------------------------------------------------ // Draw a pict into a ShockBitmap structure //------------------------------------------------------------------------------------ void LoadPictShockBitmap(ShockBitmap *theMap, short PictID) { /*PicHandle pic; Rect r; GrafPtr savePort; pic = (PicHandle)GetResourceFail('PICT', PictID); if (pic!=0L) { GetPort(&savePort); SetPort(theMap->bits); PaintRect(&theMap->bounds); r = (*pic)->picFrame; OffsetRect(&r, -r.left, -r.top); OffsetRect(&r, 0, (PictID == 9003) ? 20 : 0); // The title screen needs to come down DrawPicture(pic,&r); // so title bar won't cover it. ReleaseResource((Handle)pic); SetPort(savePort); }*/ } //------------------------------------------------------------------------------------ // Return the main monitor's current screen depth. //------------------------------------------------------------------------------------ short CurScreenDepth(void) { /*short depth; GDHandle devhandle; PixMapHandle pmhan; devhandle = GetMainDevice(); pmhan = (*devhandle)->gdPMap; depth = (*pmhan)->pixelSize; return(depth);*/ return 16; } //------------------------------------------------------------------------------------ // This routine checks to make sure the bit depth wasn't changed while the player switched out to // the Finder or another program. If it was, then it disables all the menu items until the bit depth // is correctly set. //------------------------------------------------------------------------------------ void CheckBitDepth(void) { /*short newDepth; if (gInForeground) { newDepth = CurScreenDepth(); if ((newDepth != gStartupDepth) && (gLastAlertDepth != newDepth)) { gLastAlertDepth = newDepth; StringAlert(5); // dim all menus until they change back DisableItem(gMainMenus[mFile-128], fileNewGame); DisableItem(gMainMenus[mFile-128], fileOpenGame); DisableItem(gMainMenus[mFile-128], fileSaveGame); DisableItem(gMainMenus[mFile-128], fileEndGame); DisableItem(gMainMenus[mOptions-128], 0); DrawMenuBar(); } else if ((newDepth == gStartupDepth) && (gLastAlertDepth != -1)) { gLastAlertDepth = -1; // restore the dimmed menus EnableItem(gMainMenus[mFile-128], fileNewGame); EnableItem(gMainMenus[mFile-128], fileOpenGame); EnableItem(gMainMenus[mFile-128], fileSaveGame); EnableItem(gMainMenus[mFile-128], fileEndGame); EnableItem(gMainMenus[mOptions-128], 0); // SetMenus(); DrawMenuBar(); if (gStartupDepth == 8) FixPalette(); } }*/ } //------------------------------------------------------------------------------------ // Switch back to the original palette (saved when the game was started). //------------------------------------------------------------------------------------ void CleanupPalette(void) { /*if (gChangedColors) // reset palette { if (CurScreenDepth() == 8) SetEntries(0, 255, gOriginalColors); DrawMenuBar(); // redraw with new colors }*/ } //Rect pBtnRect[4]; //------------------------------------------------------------------------------------ // Copy the picture buttons to the title screen (which is already in the offscreen buffer). //------------------------------------------------------------------------------------ void SetupTitleScreen(void) { /*PicHandle pic; Rect r; GrafPtr savePort; GetPort(&savePort); SetPort(gMainOffScreen.bits); pic = (PicHandle)GetResourceFail('PICT', 9010); if (pic) { r = (*pic)->picFrame; OffsetRect(&r, -r.left + 32, -r.top + 262); DrawPicture(pic, &r); ReleaseResource((Handle)pic); pBtnRect[0] = r; } pic = (PicHandle)GetResourceFail('PICT', 9011); if (pic) { r = (*pic)->picFrame; OffsetRect(&r, -r.left + 32, -r.top + 298); DrawPicture(pic, &r); ReleaseResource((Handle)pic); pBtnRect[1] = r; } pic = (PicHandle)GetResourceFail('PICT', 9012); if (pic) { r = (*pic)->picFrame; OffsetRect(&r, -r.left + 32, -r.top + 334); DrawPicture(pic, &r); ReleaseResource((Handle)pic); pBtnRect[2] = r; } pic = (PicHandle)GetResourceFail('PICT', 9013); if (pic) { r = (*pic)->picFrame; OffsetRect(&r, -r.left + 32, -r.top + 390); DrawPicture(pic, &r); ReleaseResource((Handle)pic); pBtnRect[3] = r; } SetPort(savePort);*/ } //------------------------------------------------------------------------------------ // Handle clicking in title screen buttons. Returns: // 0 - New Game, 1 - Open Game, 2 - Play Intro, 3 - Quit, -1 - No button //------------------------------------------------------------------------------------ /* int DoShockTitleButtons(Point mousePt) { for (int i = 0; i < 4; i++) { if (PtInRect(mousePt, &pBtnRect[i])) return (TrackTitleButton(i)); } return (-1); } */ //------------------------------------------------------------------------------------ // Handle mouse tracking for the button. Returns button if clicked, -1 if not. //------------------------------------------------------------------------------------ int TrackTitleButton(int btn) { /*PicHandle phNorm, phClick; Point currPt; Boolean oldState = TRUE; Boolean newState; Rect r = pBtnRect[btn]; // Get handles to the regular and pressed buttons. phNorm = (PicHandle)GetResourceFail('PICT', 9010 + btn); phClick = (PicHandle)GetResourceFail('PICT', 9020 + btn); // Start by drawing the button in the clicked position. DrawPicture(phClick, &r); // While the mouse button is down, draw button in different states, as needed. while (StillDown()) { GetMouse(&currPt); newState = PtInRect(currPt, &r); if (newState != oldState) { DrawPicture((newState) ? phClick : phNorm, &r); oldState = newState; } } // Draw the button in normal state after release of mouse button. DrawPicture(phNorm, &r); // Free up the picture resources. ReleaseResource((Handle)phNorm); ReleaseResource((Handle)phClick); // If in rect when released, return the button number, else return -1. return ((newState) ? btn : -1);*/ return 0; }