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 //		InitMac.c	-	Initialize Mac toolbox managers and setup the application's globals.
24 //
25 //====================================================================================
26 
27 
28 //--------------------
29 //  Includes
30 //--------------------
31 //#include <Carbon/Carbon.h>
32 //#include "OldCarbonLibraries.h"
33 //#include <Palettes.h>
34 //#include <GestaltEqu.h>
35 //#include <Movies.h>
36 //#include <Timer.h>
37 
38 #include "Shock.h"
39 #include "InitMac.h"
40 #include "ShockBitmap.h"
41 
42 //QDGlobals	qd;
43 
44 //--------------------
45 //  Globals
46 //--------------------
47 /*Handle			gExtraMemory = nil;
48 ColorSpec 		*gOriginalColors;
49 unsigned long	gRandSeed;
50 short				gMainVRef;
51 //CursHandle		gWatchCurs;
52 short				gOriginalDepth = -1;
53 short				gLastAlertDepth = -1;
54 short				gStartupDepth;
55 Ptr				gScreenAddress;
56 long				gScreenRowbytes;
57 short				gScreenWide, gScreenHigh;
58 short				gActiveWide, gActiveHigh;
59 short				gActiveLeft, gActiveTop;
60 Rect				gActiveArea, gOffActiveArea;
61 Boolean			gIsPowerPC = false;
62 long				gDataDirID;
63 short				gDataVref;
64 long				gAlogDirID;
65 short				gAlogVref;
66 long				gBarkDirID;
67 short				gBarkVref;*/
68 
69 //---------------------------
70 //  Time Manager routines and globals
71 //---------------------------
72 /*typedef struct
73 {
74 	TMTask			task;					// The actual TimeManager task structure
75 	long				appA5;				// We need this silly thing for 68K programs
76 }
77 ShockTask, *ShockTaskPtr;*/
78 
79 /*#define			kShockTicksFreq		-3571
80 TimerUPP		pShockTicksPtr;				// Globals for the Shock "tickcount" TM task.
81 ShockTask		pShockTicksTask;			// It increments gShockTicks 280 times per second.
82 long				gShockTicks;
83 long 				*tmd_ticks;*/
84 
85 
86 
87 //------------------------------------------------------------------------------------
88 //		Initialize the Macintosh managers.
89 //------------------------------------------------------------------------------------
InitMac(void)90 void InitMac(void)
91 {
92 	short		i;
93 
94 	//InitGraf(&qd.thePort);
95 	/*InitFonts();
96 	InitWindows();
97 	InitMenus();
98 	TEInit();
99 	InitDialogs(nil);
100 	InitCursor();
101 
102 	MaxApplZone();
103 	for (i=0; i<10; i++)										// Get some room for more handles
104 		MoreMasters();
105 
106 	// Allocate memory for various things, initialize others
107 
108 	gExtraMemory = NewHandle(16384L);				// Some extra room in case we have to die
109 
110 	FailNIL(gOriginalColors = (ColorSpec *)malloc(256 * sizeof(ColorSpec)));		// Original palette
111 
112 	GetDateTime(&gRandSeed);								// Start off with a random seed
113 	gRandSeed += TickCount()<<8;
114 
115 	GetVol(nil,	&gMainVRef);									// Where was I launched from?
116 	*/
117 
118 	//gWatchCurs = GetCursor(watchCursor);
119 	//HNoPurge((Handle)gWatchCurs);
120 
121 //	EnterMovies();
122 //	InstallShockTimers();
123  }
124 
125 //------------------------------------------------------------------------------------
126 //		Make sure the game can run on this mo-sheen.
127 //------------------------------------------------------------------------------------
CheckConfig(void)128 void CheckConfig(void)
129 {
130 	/*OSErr				err;
131 	long					resp;
132 	int					depth;
133 	GDHandle     		devhandle;
134 	PixMapHandle 	pmhan;
135 
136 	// Check for System 7
137 	err = Gestalt(gestaltSystemVersion, &resp);
138 	if (err || (!err && resp < 0x0700))
139 	 	ErrorDie(2);
140 
141 	// Check for 32-bit mode
142 	err = Gestalt(gestaltAddressingModeAttr, &resp);
143 	if (err || (!err && (resp & (1 << gestalt32BitAddressing) == 0)))
144 	 	ErrorDie(8);
145 
146 	// Check for Color QD
147 	err = Gestalt(gestaltQuickdrawFeatures, &resp);
148 	if (!err && (resp & (1 << gestaltHasColor)))
149 	{
150 		devhandle = GetMainDevice();
151 		pmhan = (*devhandle)->gdPMap;
152 		depth = (*pmhan)->pixelSize;
153 
154 		// if we're in 8 bit, save off the color table.  If not, check to see if it is available
155 		// and switch to it if we can.  Also save the original color depth.
156 
157 		if (depth == 8)
158 			BlockMove((**((*pmhan)->pmTable)).ctTable, gOriginalColors, 256*sizeof(ColorSpec));
159 		else
160 		{
161 			if (HasDepth(devhandle,8,0,0))
162 			{
163 				InitCursor();
164 				if (StopAlert(1002, nil) == 1)
165 				{
166 					gOriginalDepth = depth;								// Save original depth so we can switch back
167 					SetDepth(devhandle,8,0,0);
168 					devhandle = GetMainDevice();
169 					pmhan = (*devhandle)->gdPMap;
170 					depth = (*pmhan)->pixelSize;
171 				}
172 				else
173 					CleanupAndExit();
174 			}
175 			else
176 				ErrorDie(4);
177 		}
178 	}
179 	else
180 		ErrorDie(4);
181 
182 	// Check for QuickTime 2.0
183 	err = Gestalt(gestaltQuickTime, &resp);
184 	if (err || (!err && resp < 0x02000000))
185 	 	ErrorDie(6);
186 
187 	// Check for Sound Manager 3.0.  We do this by checking for multiple channel support, which is only
188 	// available with SM 3.0.  If it returns an error, then die.
189 	err = Gestalt(gestaltSoundAttr, &resp);
190 	if (err || (!err && (resp & (1 << gestaltMultiChannels) == 0)))
191 	 	ErrorDie(7);
192 
193 	// Record info about the main monitor size.
194 	gStartupDepth = depth;
195 	gScreenRowbytes = (long)((*pmhan)->rowBytes & 0x7FFF);
196 	gScreenAddress = (*pmhan)->baseAddr;
197 	gScreenWide = (*pmhan)->bounds.right - (*pmhan)->bounds.left;
198 	gScreenHigh = (*pmhan)->bounds.bottom - (*pmhan)->bounds.top;
199 
200 	// If the screen is larger than 640x480, then center the "active" area in the screen.
201 	if (gScreenWide >= 640 && gScreenHigh >= 480)
202 	{
203 		gActiveWide = screenMaxX;
204 		gActiveHigh = screenMaxY;
205 	}
206 	else
207 		ErrorDie(11);
208 
209 	gActiveLeft = ((gScreenWide>>1) - (gActiveWide>>1)) & 0x7FFE;		// put it on even byte
210 	gActiveTop = ((gScreenHigh - GetMBarHeight()) >> 1) - (gActiveHigh>>1);
211 
212 	if (gActiveTop < GetMBarHeight())
213 		gActiveTop = 0;
214 	gActiveTop += GetMBarHeight();
215 	SetRect(&gActiveArea, gActiveLeft, gActiveTop, gActiveWide+gActiveLeft, gActiveHigh+gActiveTop);
216 	SetRect(&gOffActiveArea, 0, 0, gActiveWide, gActiveHigh);
217 
218  	// Fix up ScreenAddress (so it really points to the first address of the active area)
219   	gScreenAddress += (gScreenRowbytes * (long)gActiveTop);
220   	gScreenAddress += gActiveLeft;
221 
222 	// Check to see if we're running on a PowerPC
223 	err = Gestalt(gestaltSysArchitecture, &resp);
224 	if (!err && (resp & (1 << gestaltPowerPC)))
225 		gIsPowerPC = true;*/
226 }
227 
228 //------------------------------------------------------------------------------------
229 //		Make a color window the size of the main screen, and black it out.
230 //------------------------------------------------------------------------------------
SetupWindows(WindowPtr * mainWind)231 void SetupWindows(WindowPtr *mainWind)
232 {
233 	/*FailNIL(*mainWind = GetNewCWindow(1000, 0L, (WindowPtr)-1L));
234 
235 	SizeWindow(*mainWind, gScreenWide, gScreenHigh, false);
236 	MoveWindow(*mainWind, 0, 0, true);
237 
238 	SetPort(*mainWind);
239 	SetOrigin(-gActiveLeft, -gActiveTop);								// Set the main window's origin
240 	OffsetRect(&gActiveArea, -gActiveLeft, -gActiveTop);
241 
242 	ShowWindow(*mainWind);*/
243 	//PaintRect(&(*mainWind)->portRect);		// black it out
244  }
245 
246 //------------------------------------------------------------------------------------
247 //  Load and install the standard menus.
248 //------------------------------------------------------------------------------------
249 /*void SetUpMenus(MenuHandle *theMenus, short numMenus)
250 {
251 	short		i;
252 
253 	for (i=0; i<numMenus; i++)
254 		FailNIL(theMenus[i] = GetMenu(128+i));		// get menu resources
255 
256 	AddResMenu(theMenus[0],'DRVR'); 						// add the apple menu items
257 
258 	for (i=0; i<numMenus; i++)
259 		InsertMenu(theMenus[i], 0);							// Insert apple, file, edit, etc.
260 
261 	DrawMenuBar();
262 }*/
263 
264 //------------------------------------------------------------------------------------
265 //  Get the dirID and Vref for any folders Shock uses.
266 //------------------------------------------------------------------------------------
GetFolders(void)267 void GetFolders(void)
268 {
269 	/*long						temp;
270 	HParamBlockRec 	hpb;
271 	OSErr					err;
272 
273 	// Get the location of our current working directory.
274 
275 	hpb.ioParam.ioCompletion = 0L;
276 	hpb.fileParam.ioFDirIndex = 0;
277  	GetWDInfo(gMainVRef, &hpb.fileParam.ioVRefNum, &hpb.fileParam.ioDirID, &temp);
278 
279  	// Now get info on the "Data" directory.
280 
281 	hpb.fileParam.ioNamePtr = "Data";
282 	err = PBGetCatInfo((CInfoPBPtr)&hpb, false);
283 
284 	// If we found it, then set our globals, otherwise die.
285 
286 	if (err == noErr)
287 	{
288 		gDataVref = hpb.fileParam.ioVRefNum;
289 		gDataDirID = hpb.fileParam.ioDirID;
290 	}
291 	else
292 		ErrorDie(12);		// No "Data" folder.
293 
294 	// Now go into the data folder and get the "Alogs" and "Barks" folders.
295 
296 	hpb.fileParam.ioNamePtr = "Alogs";
297 	err = PBGetCatInfo((CInfoPBPtr)&hpb, false);
298 	if (err == noErr)
299 	{
300 		gAlogVref = hpb.fileParam.ioVRefNum;
301 		gAlogDirID = hpb.fileParam.ioDirID;
302 	}
303 	else
304 		ErrorDie(13);		// No "Alogs" folder.
305 
306 	hpb.fileParam.ioVRefNum = gDataVref;
307 	hpb.fileParam.ioDirID = gDataDirID;
308 	hpb.fileParam.ioNamePtr = "Barks";
309 	err = PBGetCatInfo((CInfoPBPtr)&hpb, false);
310 	if (err == noErr)
311 	{
312 		gBarkVref = hpb.fileParam.ioVRefNum;
313 		gBarkDirID = hpb.fileParam.ioDirID;
314 	}
315 	else
316 		ErrorDie(14);		// No "Barks" folder.
317 
318 	*/
319 }
320 
321 //------------------------------------------------------------------------------------
322 //		Check a memory address (handle or pointer) to see if its NIL, and wasn't allocated.
323 // 	If it was, we have to fail out of the program.
324 //------------------------------------------------------------------------------------
FailNIL(void * memory)325 void FailNIL(void *memory)
326 {
327 	/*if (!memory)
328 	{
329 		if (gExtraMemory)
330 			DisposHandle(gExtraMemory);
331 
332 		ErrorDie(1);
333 	}*/
334 }
335 
336 //------------------------------------------------------------------------------------
337 //		Get a resource and fail correctly if it can't be loaded.
338 //------------------------------------------------------------------------------------
GetResourceFail(long id,short num)339 Handle GetResourceFail(long id, short num)
340 {
341 	/*Handle 	h;
342 
343 	h = GetResource(id, num);
344 	if (h) return(h);
345 
346 	// At this point GetResource failed, figure out why.
347 	SetResLoad(false);
348 	h = GetResource(id, num);
349 	SetResLoad(true);
350 
351 	if (gExtraMemory)
352 		DisposHandle(gExtraMemory);
353 
354 	if (h)
355 		ErrorDie(1);		// resource is there, must be a memory problem
356 	else
357 		ErrorDie(3);		// resource not there, somethings bad
358 
359 	return (nil);*/
360 }
361 
362 
363 //------------------------------------------------------------------------------------
364 //  Startup the SystemShock timer.
365 //------------------------------------------------------------------------------------
InstallShockTimers(void)366 void InstallShockTimers(void)
367 {
368 	/*gShockTicks = 0;
369 	tmd_ticks = &gShockTicks;
370 
371 	//pShockTicksPtr = NewTimerProc(ShockTicksProc);		// Make a UPP for the TM task
372 	pShockTicksTask.task.tmAddr = pShockTicksPtr;				// Insert the Shock ticks TM task
373 	pShockTicksTask.task.tmWakeUp = 0;
374 	pShockTicksTask.task.tmReserved = 0;
375 #ifndef __powerc
376 	//pShockTicksTask.appA5 = SetCurrentA5();
377 #endif
378 	InsTime((QElemPtr)&pShockTicksTask);
379 	PrimeTime((QElemPtr)&pShockTicksTask, kShockTicksFreq);	// Increment 280 times a second*/
380 }
381 
382 
383 //------------------------------------------------------------------------------------
384 //  Remove the SystemShock timer.
385 //------------------------------------------------------------------------------------
RemoveShockTimers(void)386 void RemoveShockTimers(void)
387 {
388 	/*RmvTime((QElemPtr)&pShockTicksTask);					// Stop the Shock ticks task
389 	DisposeRoutineDescriptor(pShockTicksPtr);					// Dispose its UPP*/;
390 }
391 
392 
393 //------------------------------------------------------------------------------------
394 //  Display an alert using the str# resource with index strignum, then die.
395 //------------------------------------------------------------------------------------
ErrorDie(short stringnum)396 void ErrorDie(short stringnum)
397 {
398 	/*if (gExtraMemory)
399 		DisposHandle(gExtraMemory);	// free our extra space
400 
401  	StringAlert(stringnum);
402 	CleanupAndExit();*/
403 }
404 
405 //------------------------------------------------------------------------------------
406 // 	Display an alert using the str# resource with index strignum
407 //------------------------------------------------------------------------------------
StringAlert(short stringnum)408 void StringAlert(short stringnum)
409 {
410 	/*Str255		message, explain;
411 
412 	InitCursor();
413 	GetIndString(message, 1000, stringnum);
414 	GetIndString(explain, 1001, stringnum);
415 	ParamText(message, explain, "", "");
416 
417 	if (*explain)
418 		StopAlert(1001, nil);
419 	else
420 		StopAlert(1000, nil);*/
421 }
422 
423 //------------------------------------------------------------------------------------
424 //  Close all our resources, then quit.
425 //------------------------------------------------------------------------------------
CleanupAndExit(void)426 void CleanupAndExit(void)
427 {
428 	/*GDHandle	devhandle;
429 
430 
431 	if (gOriginalDepth != -1)											// If color depth was changed at beginning of app,
432 	{																				// then switch it back to the original.
433 		devhandle = GetMainDevice();
434 		if (devhandle)
435 			if (HasDepth(devhandle, gOriginalDepth, 0, 0))
436 				SetDepth(devhandle, gOriginalDepth, 0, 0);
437 	}
438 	else
439 		CleanupPalette();													// Else switch back to original 8-bit palette.
440 
441 //	ExitMovies();
442 
443 	ExitToShell();*/
444 }
445