1 /*****************************************************************************\
2      Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3                 This file is licensed under the Snes9x License.
4    For further information, consult the LICENSE file in the root directory.
5 \*****************************************************************************/
6 
7 /***********************************************************************************
8   SNES9X for Mac OS (c) Copyright John Stiles
9 
10   Snes9x for Mac OS X
11 
12   (c) Copyright 2001 - 2011  zones
13   (c) Copyright 2002 - 2005  107
14   (c) Copyright 2002         PB1400c
15   (c) Copyright 2004         Alexander and Sander
16   (c) Copyright 2004 - 2005  Steven Seeger
17   (c) Copyright 2005         Ryan Vogt
18  ***********************************************************************************/
19 
20 
21 #include "snes9x.h"
22 #include "memmap.h"
23 #include "apu.h"
24 #include "snapshot.h"
25 #include "cheats.h"
26 #include "movie.h"
27 #include "display.h"
28 
29 #include <wchar.h>
30 
31 #include "mac-prefix.h"
32 #include "mac-audio.h"
33 #include "mac-cart.h"
34 #include "mac-cheatfinder.h"
35 #include "mac-dialog.h"
36 #include "mac-file.h"
37 #include "mac-multicart.h"
38 #include "mac-os.h"
39 #include "mac-quicktime.h"
40 #include "mac-screenshot.h"
41 #include "mac-stringtools.h"
42 #include "mac-snes9x.h"
43 
44 extern wchar_t  macRecordWChar[MOVIE_MAX_METADATA];
45 
46 
SNES9X_Go(void)47 void SNES9X_Go (void)
48 {
49 	if (cartOpen)
50 		running = true;
51 }
52 
SNES9X_OpenCart(FSRef * inRef)53 bool8 SNES9X_OpenCart (FSRef *inRef)
54 {
55 	OSStatus	err;
56 	FSRef		cartRef;
57 	char		filename[PATH_MAX + 1];
58 
59 	DeinitGameWindow();
60 
61 	if (cartOpen)
62 	{
63 		SNES9X_SaveSRAM();
64 		S9xResetSaveTimer(false);
65 		S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
66 	}
67 
68 	ResetCheatFinder();
69 
70 	if (!inRef)
71 	{
72 		if (!NavOpenROMImage(&cartRef))
73 		{
74 			cartOpen = false;
75 			return (false);
76 		}
77 	}
78 	else
79 		cartRef = *inRef;
80 
81 	spcFileCount = pngFileCount = 0;
82 
83 	CheckSaveFolder(&cartRef);
84 
85 	Settings.ForceLoROM          = (romDetect        == kLoROMForce       );
86 	Settings.ForceHiROM          = (romDetect        == kHiROMForce       );
87 	Settings.ForceHeader         = (headerDetect     == kHeaderForce      );
88 	Settings.ForceNoHeader       = (headerDetect     == kNoHeaderForce    );
89 	Settings.ForceInterleaved    = (interleaveDetect == kInterleaveForce  );
90 	Settings.ForceInterleaved2   = (interleaveDetect == kInterleave2Force );
91 	Settings.ForceInterleaveGD24 = (interleaveDetect == kInterleaveGD24   );
92 	Settings.ForceNotInterleaved = (interleaveDetect == kNoInterleaveForce);
93 	Settings.ForcePAL            = (videoDetect      == kPALForce         );
94 	Settings.ForceNTSC           = (videoDetect      == kNTSCForce        );
95 
96 	GFX.InfoString = NULL;
97 	GFX.InfoStringTimeout = 0;
98 
99 	S9xResetSaveTimer(true);
100 
101 	err = FSRefMakePath(&cartRef, (unsigned char *) filename, PATH_MAX);
102 
103 	SNES9X_InitSound();
104 
105 	if (Memory.LoadROM(filename))
106 	{
107 		cartOpen = true;
108 
109 		SNES9X_LoadSRAM();
110 
111 		ChangeTypeAndCreator(filename, 'CART', '~9X~');
112 
113 		AddRecentItem(&cartRef);
114 		BuildRecentMenu();
115 
116 		ApplyNSRTHeaderControllers();
117 
118 		for (int a = 0; a < MAC_MAX_PLAYERS; a++)
119 			for (int b = 0; b < 12; b++)
120 				autofireRec[a].nextTime[b] = 0;
121 
122 		return (true);
123 	}
124 	else
125 	{
126 		cartOpen = false;
127 		return (false);
128 	}
129 }
130 
SNES9X_OpenMultiCart(void)131 bool8 SNES9X_OpenMultiCart (void)
132 {
133 	Boolean	r;
134 	char	cart[2][PATH_MAX + 1];
135 
136 	DeinitGameWindow();
137 
138 	if (cartOpen)
139 	{
140 		SNES9X_SaveSRAM();
141 		S9xResetSaveTimer(false);
142 		S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
143 	}
144 
145 	ResetCheatFinder();
146 
147 	if (!MultiCartDialog())
148 	{
149 		cartOpen = false;
150 		return (false);
151 	}
152 
153 	spcFileCount = pngFileCount = 0;
154 
155 	Settings.ForceHeader   = (headerDetect     == kHeaderForce  );
156 	Settings.ForceNoHeader = (headerDetect     == kNoHeaderForce);
157 	Settings.ForcePAL      = (videoDetect      == kPALForce     );
158 	Settings.ForceNTSC     = (videoDetect      == kNTSCForce    );
159 
160 	GFX.InfoString = NULL;
161 	GFX.InfoStringTimeout = 0;
162 
163 	S9xResetSaveTimer(true);
164 
165 	for (int i = 0; i < 2; i++)
166 	{
167 		cart[i][0] = 0;
168 		if (multiCartPath[i])
169 			r = CFStringGetCString(multiCartPath[i], cart[i], PATH_MAX, kCFStringEncodingUTF8);
170 	}
171 
172 	SNES9X_InitSound();
173 
174 	if (Memory.LoadMultiCart(cart[0], cart[1]))
175 	{
176 		cartOpen = true;
177 
178 		SNES9X_LoadSRAM();
179 
180 		for (int i = 0; i < 2; i++)
181 		{
182 			if (cart[i][0])
183 				ChangeTypeAndCreator(cart[i], 'CART', '~9X~');
184 		}
185 
186 		ApplyNSRTHeaderControllers();
187 
188 		for (int a = 0; a < MAC_MAX_PLAYERS; a++)
189 			for (int b = 0; b < 12; b++)
190 				autofireRec[a].nextTime[b] = 0;
191 
192 		return (true);
193 	}
194 	else
195 	{
196 		cartOpen = false;
197 		return (false);
198 	}
199 }
200 
SNES9X_LoadSRAM(void)201 void SNES9X_LoadSRAM (void)
202 {
203 	if (cartOpen)
204 		Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR));
205 }
206 
SNES9X_SaveSRAM(void)207 void SNES9X_SaveSRAM (void)
208 {
209 	const char	*sramFilename;
210 
211 	if (cartOpen)
212 	{
213 		sramFilename = S9xGetFilename(".srm", SRAM_DIR);
214 		Memory.SaveSRAM(sramFilename);
215 		ChangeTypeAndCreator(sramFilename, 'SRAM', '~9X~');
216 	}
217 }
218 
SNES9X_Reset(void)219 void SNES9X_Reset (void)
220 {
221 	if (cartOpen)
222 	{
223 		SNES9X_SaveSRAM();
224 		S9xReset();
225 		SNES9X_LoadSRAM();
226 	}
227 }
228 
SNES9X_SoftReset(void)229 void SNES9X_SoftReset (void)
230 {
231 	if (cartOpen)
232 	{
233 		SNES9X_SaveSRAM();
234 		S9xSoftReset();
235 		SNES9X_LoadSRAM();
236 	}
237 }
238 
SNES9X_Freeze(void)239 bool8 SNES9X_Freeze (void)
240 {
241 	OSStatus	err;
242 	FSRef		ref;
243 	int			which;
244     const char	*filename;
245 
246 	if (cartOpen)
247 	{
248 		MacStopSound();
249 
250 		which = PromptFreezeDefrost(true);
251 
252 		if (which >= 0)
253 		{
254 			filename = S9xGetFreezeFilename(which);
255 
256 			err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
257 			if (!err)
258 				FSDeleteObject(&ref);
259 
260 			S9xFreezeGame(filename);
261 			ChangeTypeAndCreator(filename, 'SAVE', '~9X~');
262 			err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
263 			WriteThumbnailToResourceFork(&ref, 128, 120);
264 
265 			SNES9X_Go();
266 
267 			MacStartSound();
268 			return (true);
269 		}
270 		else
271 		{
272 			MacStartSound();
273 			return (false);
274 		}
275 	}
276 	else
277 		return (false);
278 }
279 
SNES9X_Defrost(void)280 bool8 SNES9X_Defrost (void)
281 {
282 	int			which;
283 	const char	*filename;
284 
285 	if (cartOpen)
286 	{
287 		MacStopSound();
288 
289 		which = PromptFreezeDefrost(false);
290 
291 		if (which >= 0)
292 		{
293 			filename = S9xGetFreezeFilename(which);
294 			S9xUnfreezeGame(filename);
295 
296 			SNES9X_Go();
297 
298 			MacStartSound();
299 			return (true);
300 		}
301 		else
302 		{
303 			MacStartSound();
304 			return (false);
305 		}
306 	}
307 	else
308 		return (false);
309 }
310 
SNES9X_FreezeTo(void)311 bool8 SNES9X_FreezeTo (void)
312 {
313 	OSStatus	err;
314 	FSRef		ref;
315     char		filename[PATH_MAX + 1];
316 
317 	if (cartOpen)
318 	{
319 		if (NavFreezeTo(filename))
320 		{
321 			err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
322 			if (!err)
323 				FSDeleteObject(&ref);
324 
325 			S9xFreezeGame(filename);
326 			ChangeTypeAndCreator(filename, 'SAVE', '~9X~');
327 			err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
328 			WriteThumbnailToResourceFork(&ref, 128, 120);
329 
330 			return (true);
331 		}
332 	}
333 
334 	return (false);
335 }
336 
SNES9X_DefrostFrom(void)337 bool8 SNES9X_DefrostFrom (void)
338 {
339 	char	filename[PATH_MAX + 1];
340 
341 	if (cartOpen)
342 	{
343 		if (NavDefrostFrom(filename))
344 		{
345 			S9xUnfreezeGame(filename);
346 
347 			SNES9X_Go();
348 
349 			return (true);
350 		}
351 	}
352 
353 	return (false);
354 }
355 
SNES9X_RecordMovie(void)356 bool8 SNES9X_RecordMovie (void)
357 {
358 	OSStatus	err;
359 	FSRef		ref;
360     char		filename[PATH_MAX + 1];
361 
362 	if (cartOpen)
363 	{
364 		if (NavRecordMovieTo(filename))
365 		{
366 			err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
367 			if (!err)
368 				FSDeleteObject(&ref);
369 
370 			int		r;
371 			uint8   opt = 0, mask = 0;
372 
373 			for (int i = 0; i <= 4; i++)
374 				if (macRecordFlag & (1 << i))
375 					mask |= (1 << i);
376 
377 			if (macRecordFlag & (1 << 5))
378 				opt |= MOVIE_OPT_FROM_RESET;
379 			else
380 				opt |= MOVIE_OPT_FROM_SNAPSHOT;
381 
382 			r = S9xMovieCreate(filename, mask, opt, macRecordWChar, wcslen(macRecordWChar));
383 			if (r == SUCCESS)
384 			{
385 				ChangeTypeAndCreator(filename, 'SMOV', '~9X~');
386 
387 				if ((macRecordFlag & (1 << 5)) == 0)
388 				{
389 					err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
390 					WriteThumbnailToResourceFork(&ref, 128, 120);
391 				}
392 
393 				SNES9X_Go();
394 
395 				return (true);
396 			}
397 		}
398 	}
399 
400 	return (false);
401 }
402 
SNES9X_PlayMovie(void)403 bool8 SNES9X_PlayMovie (void)
404 {
405 	char	filename[PATH_MAX + 1];
406 
407 	if (cartOpen)
408 	{
409 		if (NavPlayMovieFrom(filename))
410 		{
411 			int r;
412 
413 			r = S9xMovieOpen(filename, macPlayFlag & 1);
414 			if (r == SUCCESS)
415 			{
416 				SNES9X_Go();
417 
418 				return (true);
419 			}
420 		}
421 	}
422 
423 	return (false);
424 }
425 
SNES9X_QTMovieRecord(void)426 bool8 SNES9X_QTMovieRecord (void)
427 {
428     char	filename[PATH_MAX + 1];
429 
430 	if (cartOpen)
431 	{
432 		if (NavQTMovieRecordTo(filename))
433 		{
434 			MacQTStartRecording(filename);
435 			macQTRecord = true;
436 			SNES9X_Go();
437 
438 			return (true);
439 		}
440 	}
441 
442 	macQTRecord = false;
443 
444 	return (false);
445 }
446 
SNES9X_Quit(void)447 void SNES9X_Quit (void)
448 {
449 	DeinitGameWindow();
450 
451 	if (cartOpen)
452 	{
453 		SNES9X_SaveSRAM();
454 		S9xResetSaveTimer(false);
455 		S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
456 	}
457 
458 	finished = true;
459 }
460 
SNES9X_InitSound(void)461 void SNES9X_InitSound (void)
462 {
463 	S9xInitSound(0);
464 }
465