1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program 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
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 //====================================================================================
20 //
21 // System Shock - ©1994-1995 Looking Glass Technologies, Inc.
22 //
23 // ShockBitmap.c - Manages off-screen bitmaps and palettes.
24 //
25 //====================================================================================
26
27
28 //--------------------
29 // Includes
30 //--------------------
31 //#include "OldCarbonHeaders.h"
32 //#include <Palettes.h>
33 #include "Shock.h"
34 #include "InitMac.h"
35 #include "ShockBitmap.h"
36
37 #include "2d.h"
38
39 //#import <Cocoa/Cocoa.h>
40
41 //--------------------
42 // Prototypes
43 //--------------------
44 //int TrackTitleButton(int btn);
45
46 //--------------------
47 // Globals
48 //--------------------
49 SDL_Surface* drawSurface;
50 SDL_Surface* offscreenDrawSurface;
51
52 int cur_bm_width;
53 int cur_bm_height;
54
55 //------------------------------------------------------------------------------------
56 // Setup the main offscreen bitmaps.
57 //------------------------------------------------------------------------------------
SetupOffscreenBitmaps(int width,int height)58 void SetupOffscreenBitmaps(int width, int height)
59 {
60 DEBUG("SetupOffscreenBitmaps %i %i", width, height);
61
62 if(drawSurface != NULL) {
63 SDL_FreeSurface(drawSurface);
64 }
65 if(offscreenDrawSurface != NULL) {
66 SDL_FreeSurface(offscreenDrawSurface);
67 }
68
69 drawSurface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
70 if(!drawSurface) {
71 ERROR("SDL: Failed to create draw surface");
72 return;
73 }
74
75 offscreenDrawSurface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
76 if(!offscreenDrawSurface) {
77 ERROR("SDL: Failed to create offscreen draw surface");
78 return;
79 }
80
81 // Point the renderer at the screen bytes
82 gScreenRowbytes = drawSurface->w;
83 gScreenAddress = drawSurface->pixels;
84
85 grd_mode_cap.vbase = (uchar *)gScreenAddress;
86
87 cur_bm_width = width;
88 cur_bm_height = height;
89 }
90
91 //------------------------------------------------------------------------------------
92 // Reset the CTseeds of the screen & pixmap to be the same
93 //------------------------------------------------------------------------------------
ResetCTSeed(void)94 void ResetCTSeed(void)
95 {
96 //(*gMainColorHand)->ctSeed = (*(*gScreenPixMap)->pmTable)->ctSeed;
97 //(*(**(*(CWindowPtr)gMainWindow).portPixMap).pmTable)->ctSeed = (*gMainColorHand)->ctSeed;
98 }
99
100 //------------------------------------------------------------------------------------
101 // Save the screen pixmap's ctSeed before a suspend.
102 //------------------------------------------------------------------------------------
103 long oldctSeed;
RememberSeed(void)104 void RememberSeed(void)
105 {
106 //oldctSeed = (*(*gScreenPixMap)->pmTable)->ctSeed;
107 }
108
109 //------------------------------------------------------------------------------------
110 // If the palette changed while switched out, then reset it.
111 //------------------------------------------------------------------------------------
FixPalette(void)112 void FixPalette(void)
113 {
114 /*if ((*(*gScreenPixMap)->pmTable)->ctSeed != oldctSeed)
115 {
116 if (CurScreenDepth() == 8)
117 SetEntries(0, 255, (**(gMainColorHand)).ctTable);
118 ResetCTSeed();
119 DrawMenuBar();
120 UpdateWindow(gMainWindow);
121 }*/
122 }
123
124 /*
125 //------------------------------------------------------------------------------------
126 // Setup a new ShockBitmap structure.
127 //------------------------------------------------------------------------------------
128 void NewShockBitmap(ShockBitmap *theMap, short width, short height, Boolean color)
129 {
130 GrafPtr savePort;
131 PixMapPtr pmaptr;
132
133 GetPort(&savePort);
134
135 theMap->Color = color;
136 theMap->bits = 0L;
137 SetRect(&theMap->bounds, 0, 0, width, height);
138
139 if (theMap->Color) // Setup color pixmaps.
140 {
141 theMap->OrigBits = Build8PixMap(&theMap->CPort, width, height);
142
143 SetPort((GrafPtr)&theMap->CPort);
144 EraseRect(&theMap->bounds);
145
146 //pmaptr = *(theMap->CPort.portPixMap);
147 theMap->Address = StripAddress(pmaptr->baseAddr);
148 theMap->RowBytes = (long)(pmaptr->rowBytes & 0x7FFF);
149 theMap->bits = (GrafPtr) &theMap->CPort;
150 }
151 else // setup B&W maps
152 {
153 theMap->BWBits.bounds = theMap->bounds;
154 theMap->BWBits.rowBytes = ((width+15) >> 4)<<1; // round to even
155 theMap->BWBits.baseAddr = malloc(((long) height * (long) theMap->BWBits.rowBytes));
156 FailNIL(theMap->BWBits.baseAddr);
157
158 theMap->BWBits.baseAddr = StripAddress(theMap->BWBits.baseAddr);
159
160 OpenPort(&theMap->BWPort);
161 SetPort(&theMap->BWPort);
162 SetPortBits(&theMap->BWBits);
163
164 // make sure the clip & vis regions are big enough
165 //SetRectRgn(theMap->BWPort.visRgn,theMap->bounds.left,theMap->bounds.top,theMap->bounds.right,theMap->bounds.bottom);
166 //SetRectRgn(theMap->BWPort.clipRgn,theMap->bounds.left,theMap->bounds.top,theMap->bounds.right,theMap->bounds.bottom);
167 EraseRect(&theMap->bounds);
168
169 theMap->Address = theMap->BWBits.baseAddr;
170 theMap->RowBytes = (long) theMap->BWBits.rowBytes;
171 theMap->bits = (GrafPtr) &theMap->BWPort;
172 }
173
174 SetPort(savePort);
175 }
176 */
177
178 //------------------------------------------------------------------------------------
179 // Deallocate a Shock bitmap.
180 //------------------------------------------------------------------------------------
FreeShockBitmap(ShockBitmap * theMap)181 void FreeShockBitmap(ShockBitmap *theMap)
182 {
183 /*if (theMap->Color)
184 {
185 if (theMap->OrigBits != 0L)
186 DisposeHandle(theMap->OrigBits);
187 CloseCPort(&theMap->CPort);
188 }
189 else
190 {
191 ClosePort(&theMap->BWPort);
192 free(theMap->Address);
193 }*/
194 }
195
196 //------------------------------------------------------------------------------------
197 // Code to build an offscreen pixmap (8bit) of a given size, using the current pStd clut
198 // store pixmap in ColorBack cGrafPort.
199 //------------------------------------------------------------------------------------
200 /*
201 Handle Build8PixMap(CGrafPtr theCGrafPtr, short width, short height)
202 {
203 printf("Build8PixMap\n");
204 Rect bRect;
205 PixMapHandle pmap;
206 PixMapPtr pmaptr;
207 long bytes;
208 Handle hand;
209
210 SetRect(&bRect, 0, 0, width, height);
211
212 OpenCPort(theCGrafPtr); // open a new color port Ñ this calls InitCPort
213
214 pmap = NewPixMap();
215 MoveHHi((Handle)pmap);
216 HLock((Handle)pmap);
217
218 //theCGrafPtr->portPixMap = pmap;
219 //pmaptr = *(theCGrafPtr->portPixMap);
220 pmaptr->bounds=bRect;
221
222 pmaptr->rowBytes = ((width+1)>>1)<<1;
223 bytes = (long) height * (long)pmaptr->rowBytes;
224 pmaptr->rowBytes |= 0x8000;
225
226 hand = NewHandle(bytes + 32);
227 FailNIL((Ptr) hand);
228 MoveHHi(hand);
229 HLock(hand);
230 pmaptr->baseAddr = (Ptr)((unsigned long)(*hand+31) & 0xFFFFFFE0);
231
232 pmaptr->pmTable = gMainColorHand;
233
234 // make sure the clip & vis regions are big enough
235 //SetRectRgn(theCGrafPtr->visRgn,bRect.left,bRect.top,bRect.right,bRect.bottom);
236 //SetRectRgn(theCGrafPtr->clipRgn,bRect.left,bRect.top,bRect.right,bRect.bottom);
237
238 PenNormal();
239
240 return (NULL);
241 }
242 */
243 //------------------------------------------------------------------------------------
244 // Draw a pict into a ShockBitmap structure
245 //------------------------------------------------------------------------------------
LoadPictShockBitmap(ShockBitmap * theMap,short PictID)246 void LoadPictShockBitmap(ShockBitmap *theMap, short PictID)
247 {
248 /*PicHandle pic;
249 Rect r;
250 GrafPtr savePort;
251
252 pic = (PicHandle)GetResourceFail('PICT', PictID);
253 if (pic!=0L)
254 {
255 GetPort(&savePort);
256 SetPort(theMap->bits);
257 PaintRect(&theMap->bounds);
258
259 r = (*pic)->picFrame;
260 OffsetRect(&r, -r.left, -r.top);
261 OffsetRect(&r, 0, (PictID == 9003) ? 20 : 0); // The title screen needs to come down
262 DrawPicture(pic,&r); // so title bar won't cover it.
263
264 ReleaseResource((Handle)pic);
265 SetPort(savePort);
266 }*/
267 }
268
269 //------------------------------------------------------------------------------------
270 // Return the main monitor's current screen depth.
271 //------------------------------------------------------------------------------------
CurScreenDepth(void)272 short CurScreenDepth(void)
273 {
274 /*short depth;
275 GDHandle devhandle;
276 PixMapHandle pmhan;
277
278 devhandle = GetMainDevice();
279 pmhan = (*devhandle)->gdPMap;
280 depth = (*pmhan)->pixelSize;
281
282 return(depth);*/
283 return 16;
284 }
285
286 //------------------------------------------------------------------------------------
287 // This routine checks to make sure the bit depth wasn't changed while the player switched out to
288 // the Finder or another program. If it was, then it disables all the menu items until the bit depth
289 // is correctly set.
290 //------------------------------------------------------------------------------------
CheckBitDepth(void)291 void CheckBitDepth(void)
292 {
293 /*short newDepth;
294
295 if (gInForeground)
296 {
297 newDepth = CurScreenDepth();
298 if ((newDepth != gStartupDepth) && (gLastAlertDepth != newDepth))
299 {
300 gLastAlertDepth = newDepth;
301 StringAlert(5);
302
303 // dim all menus until they change back
304 DisableItem(gMainMenus[mFile-128], fileNewGame);
305 DisableItem(gMainMenus[mFile-128], fileOpenGame);
306 DisableItem(gMainMenus[mFile-128], fileSaveGame);
307 DisableItem(gMainMenus[mFile-128], fileEndGame);
308 DisableItem(gMainMenus[mOptions-128], 0);
309 DrawMenuBar();
310 }
311 else if ((newDepth == gStartupDepth) && (gLastAlertDepth != -1))
312 {
313 gLastAlertDepth = -1;
314
315 // restore the dimmed menus
316 EnableItem(gMainMenus[mFile-128], fileNewGame);
317 EnableItem(gMainMenus[mFile-128], fileOpenGame);
318 EnableItem(gMainMenus[mFile-128], fileSaveGame);
319 EnableItem(gMainMenus[mFile-128], fileEndGame);
320 EnableItem(gMainMenus[mOptions-128], 0);
321 // SetMenus();
322 DrawMenuBar();
323
324 if (gStartupDepth == 8)
325 FixPalette();
326 }
327 }*/
328 }
329
330 //------------------------------------------------------------------------------------
331 // Switch back to the original palette (saved when the game was started).
332 //------------------------------------------------------------------------------------
CleanupPalette(void)333 void CleanupPalette(void)
334 {
335 /*if (gChangedColors) // reset palette
336 {
337 if (CurScreenDepth() == 8)
338 SetEntries(0, 255, gOriginalColors);
339 DrawMenuBar(); // redraw with new colors
340 }*/
341 }
342
343
344 //Rect pBtnRect[4];
345
346 //------------------------------------------------------------------------------------
347 // Copy the picture buttons to the title screen (which is already in the offscreen buffer).
348 //------------------------------------------------------------------------------------
SetupTitleScreen(void)349 void SetupTitleScreen(void)
350 {
351 /*PicHandle pic;
352 Rect r;
353 GrafPtr savePort;
354
355 GetPort(&savePort);
356 SetPort(gMainOffScreen.bits);
357
358 pic = (PicHandle)GetResourceFail('PICT', 9010);
359 if (pic)
360 {
361 r = (*pic)->picFrame;
362 OffsetRect(&r, -r.left + 32, -r.top + 262);
363 DrawPicture(pic, &r);
364 ReleaseResource((Handle)pic);
365 pBtnRect[0] = r;
366 }
367 pic = (PicHandle)GetResourceFail('PICT', 9011);
368 if (pic)
369 {
370 r = (*pic)->picFrame;
371 OffsetRect(&r, -r.left + 32, -r.top + 298);
372 DrawPicture(pic, &r);
373 ReleaseResource((Handle)pic);
374 pBtnRect[1] = r;
375 }
376 pic = (PicHandle)GetResourceFail('PICT', 9012);
377 if (pic)
378 {
379 r = (*pic)->picFrame;
380 OffsetRect(&r, -r.left + 32, -r.top + 334);
381 DrawPicture(pic, &r);
382 ReleaseResource((Handle)pic);
383 pBtnRect[2] = r;
384 }
385 pic = (PicHandle)GetResourceFail('PICT', 9013);
386 if (pic)
387 {
388 r = (*pic)->picFrame;
389 OffsetRect(&r, -r.left + 32, -r.top + 390);
390 DrawPicture(pic, &r);
391 ReleaseResource((Handle)pic);
392 pBtnRect[3] = r;
393 }
394
395 SetPort(savePort);*/
396 }
397
398 //------------------------------------------------------------------------------------
399 // Handle clicking in title screen buttons. Returns:
400 // 0 - New Game, 1 - Open Game, 2 - Play Intro, 3 - Quit, -1 - No button
401 //------------------------------------------------------------------------------------
402 /*
403 int DoShockTitleButtons(Point mousePt)
404 {
405 for (int i = 0; i < 4; i++)
406 {
407 if (PtInRect(mousePt, &pBtnRect[i]))
408 return (TrackTitleButton(i));
409 }
410 return (-1);
411 }
412 */
413
414 //------------------------------------------------------------------------------------
415 // Handle mouse tracking for the button. Returns button if clicked, -1 if not.
416 //------------------------------------------------------------------------------------
TrackTitleButton(int btn)417 int TrackTitleButton(int btn)
418 {
419 /*PicHandle phNorm, phClick;
420 Point currPt;
421 Boolean oldState = TRUE;
422 Boolean newState;
423 Rect r = pBtnRect[btn];
424
425 // Get handles to the regular and pressed buttons.
426 phNorm = (PicHandle)GetResourceFail('PICT', 9010 + btn);
427 phClick = (PicHandle)GetResourceFail('PICT', 9020 + btn);
428
429 // Start by drawing the button in the clicked position.
430 DrawPicture(phClick, &r);
431
432 // While the mouse button is down, draw button in different states, as needed.
433 while (StillDown())
434 {
435 GetMouse(&currPt);
436 newState = PtInRect(currPt, &r);
437 if (newState != oldState)
438 {
439 DrawPicture((newState) ? phClick : phNorm, &r);
440 oldState = newState;
441 }
442 }
443
444 // Draw the button in normal state after release of mouse button.
445 DrawPicture(phNorm, &r);
446
447 // Free up the picture resources.
448 ReleaseResource((Handle)phNorm);
449 ReleaseResource((Handle)phClick);
450
451 // If in rect when released, return the button number, else return -1.
452 return ((newState) ? btn : -1);*/
453
454 return 0;
455 }
456