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