1 /***********************************************************************************
2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4 (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
5 Jerremy Koot (jkoot@snes9x.com)
6
7 (c) Copyright 2002 - 2004 Matthew Kendora
8
9 (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
10
11 (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
12
13 (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
14
15 (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
16 Kris Bleakley (codeviolation@hotmail.com)
17
18 (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
19 Nach (n-a-c-h@users.sourceforge.net),
20
21 (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com)
22
23 (c) Copyright 2006 - 2007 nitsuja
24
25 (c) Copyright 2009 - 2016 BearOso,
26 OV2
27
28
29 BS-X C emulator code
30 (c) Copyright 2005 - 2006 Dreamer Nom,
31 zones
32
33 C4 x86 assembler and some C emulation code
34 (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
35 Nach,
36 zsKnight (zsknight@zsnes.com)
37
38 C4 C++ code
39 (c) Copyright 2003 - 2006 Brad Jorsch,
40 Nach
41
42 DSP-1 emulator code
43 (c) Copyright 1998 - 2006 _Demo_,
44 Andreas Naive (andreasnaive@gmail.com),
45 Gary Henderson,
46 Ivar (ivar@snes9x.com),
47 John Weidman,
48 Kris Bleakley,
49 Matthew Kendora,
50 Nach,
51 neviksti (neviksti@hotmail.com)
52
53 DSP-2 emulator code
54 (c) Copyright 2003 John Weidman,
55 Kris Bleakley,
56 Lord Nightmare (lord_nightmare@users.sourceforge.net),
57 Matthew Kendora,
58 neviksti
59
60 DSP-3 emulator code
61 (c) Copyright 2003 - 2006 John Weidman,
62 Kris Bleakley,
63 Lancer,
64 z80 gaiden
65
66 DSP-4 emulator code
67 (c) Copyright 2004 - 2006 Dreamer Nom,
68 John Weidman,
69 Kris Bleakley,
70 Nach,
71 z80 gaiden
72
73 OBC1 emulator code
74 (c) Copyright 2001 - 2004 zsKnight,
75 pagefault (pagefault@zsnes.com),
76 Kris Bleakley
77 Ported from x86 assembler to C by sanmaiwashi
78
79 SPC7110 and RTC C++ emulator code used in 1.39-1.51
80 (c) Copyright 2002 Matthew Kendora with research by
81 zsKnight,
82 John Weidman,
83 Dark Force
84
85 SPC7110 and RTC C++ emulator code used in 1.52+
86 (c) Copyright 2009 byuu,
87 neviksti
88
89 S-DD1 C emulator code
90 (c) Copyright 2003 Brad Jorsch with research by
91 Andreas Naive,
92 John Weidman
93
94 S-RTC C emulator code
95 (c) Copyright 2001 - 2006 byuu,
96 John Weidman
97
98 ST010 C++ emulator code
99 (c) Copyright 2003 Feather,
100 John Weidman,
101 Kris Bleakley,
102 Matthew Kendora
103
104 Super FX x86 assembler emulator code
105 (c) Copyright 1998 - 2003 _Demo_,
106 pagefault,
107 zsKnight
108
109 Super FX C emulator code
110 (c) Copyright 1997 - 1999 Ivar,
111 Gary Henderson,
112 John Weidman
113
114 Sound emulator code used in 1.5-1.51
115 (c) Copyright 1998 - 2003 Brad Martin
116 (c) Copyright 1998 - 2006 Charles Bilyue'
117
118 Sound emulator code used in 1.52+
119 (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
120
121 S-SMP emulator code used in 1.54+
122 (c) Copyright 2016 byuu
123
124 SH assembler code partly based on x86 assembler code
125 (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
126
127 2xSaI filter
128 (c) Copyright 1999 - 2001 Derek Liauw Kie Fa
129
130 HQ2x, HQ3x, HQ4x filters
131 (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
132
133 NTSC filter
134 (c) Copyright 2006 - 2007 Shay Green
135
136 GTK+ GUI code
137 (c) Copyright 2004 - 2016 BearOso
138
139 Win32 GUI code
140 (c) Copyright 2003 - 2006 blip,
141 funkyass,
142 Matthew Kendora,
143 Nach,
144 nitsuja
145 (c) Copyright 2009 - 2016 OV2
146
147 Mac OS GUI code
148 (c) Copyright 1998 - 2001 John Stiles
149 (c) Copyright 2001 - 2011 zones
150
151
152 Specific ports contains the works of other authors. See headers in
153 individual files.
154
155
156 Snes9x homepage: http://www.snes9x.com/
157
158 Permission to use, copy, modify and/or distribute Snes9x in both binary
159 and source form, for non-commercial purposes, is hereby granted without
160 fee, providing that this license information and copyright notice appear
161 with all copies and any derived work.
162
163 This software is provided 'as-is', without any express or implied
164 warranty. In no event shall the authors be held liable for any damages
165 arising from the use of this software or it's derivatives.
166
167 Snes9x is freeware for PERSONAL USE only. Commercial users should
168 seek permission of the copyright holders first. Commercial use includes,
169 but is not limited to, charging money for Snes9x or software derived from
170 Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
171 using Snes9x as a promotion for your commercial product.
172
173 The copyright holders request that bug fixes and improvements to the code
174 should be forwarded to them so everyone can benefit from the modifications
175 in future versions.
176
177 Super NES and Super Nintendo Entertainment System are trademarks of
178 Nintendo Co., Limited and its subsidiary companies.
179 ***********************************************************************************/
180
181 /***********************************************************************************
182 SNES9X for Mac OS (c) Copyright John Stiles
183
184 Snes9x for Mac OS X
185
186 (c) Copyright 2001 - 2011 zones
187 (c) Copyright 2002 - 2005 107
188 (c) Copyright 2002 PB1400c
189 (c) Copyright 2004 Alexander and Sander
190 (c) Copyright 2004 - 2005 Steven Seeger
191 (c) Copyright 2005 Ryan Vogt
192 ***********************************************************************************/
193
194
195 #include "snes9x.h"
196 #include "memmap.h"
197 #include "apu.h"
198 #include "snapshot.h"
199 #include "cheats.h"
200 #include "movie.h"
201 #include "display.h"
202
203 #include <wchar.h>
204
205 #include "mac-prefix.h"
206 #include "mac-audio.h"
207 #include "mac-cart.h"
208 #include "mac-cheatfinder.h"
209 #include "mac-dialog.h"
210 #include "mac-file.h"
211 #include "mac-multicart.h"
212 #include "mac-os.h"
213 #include "mac-quicktime.h"
214 #include "mac-screenshot.h"
215 #include "mac-stringtools.h"
216 #include "mac-snes9x.h"
217
218 extern wchar_t macRecordWChar[MOVIE_MAX_METADATA];
219
220
SNES9X_Go(void)221 void SNES9X_Go (void)
222 {
223 if (cartOpen)
224 running = true;
225 }
226
SNES9X_OpenCart(FSRef * inRef)227 bool8 SNES9X_OpenCart (FSRef *inRef)
228 {
229 OSStatus err;
230 FSRef cartRef;
231 char filename[PATH_MAX + 1];
232
233 DeinitGameWindow();
234
235 if (cartOpen)
236 {
237 SNES9X_SaveSRAM();
238 S9xResetSaveTimer(false);
239 S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
240 }
241
242 ResetCheatFinder();
243
244 if (!inRef)
245 {
246 if (!NavOpenROMImage(&cartRef))
247 {
248 cartOpen = false;
249 return (false);
250 }
251 }
252 else
253 cartRef = *inRef;
254
255 spcFileCount = pngFileCount = 0;
256
257 CheckSaveFolder(&cartRef);
258
259 Settings.ForceLoROM = (romDetect == kLoROMForce );
260 Settings.ForceHiROM = (romDetect == kHiROMForce );
261 Settings.ForceHeader = (headerDetect == kHeaderForce );
262 Settings.ForceNoHeader = (headerDetect == kNoHeaderForce );
263 Settings.ForceInterleaved = (interleaveDetect == kInterleaveForce );
264 Settings.ForceInterleaved2 = (interleaveDetect == kInterleave2Force );
265 Settings.ForceInterleaveGD24 = (interleaveDetect == kInterleaveGD24 );
266 Settings.ForceNotInterleaved = (interleaveDetect == kNoInterleaveForce);
267 Settings.ForcePAL = (videoDetect == kPALForce );
268 Settings.ForceNTSC = (videoDetect == kNTSCForce );
269
270 GFX.InfoString = NULL;
271 GFX.InfoStringTimeout = 0;
272
273 S9xResetSaveTimer(true);
274
275 err = FSRefMakePath(&cartRef, (unsigned char *) filename, PATH_MAX);
276
277 SNES9X_InitSound();
278
279 if (Memory.LoadROM(filename))
280 {
281 cartOpen = true;
282
283 SNES9X_LoadSRAM();
284
285 ChangeTypeAndCreator(filename, 'CART', '~9X~');
286
287 AddRecentItem(&cartRef);
288 BuildRecentMenu();
289
290 ApplyNSRTHeaderControllers();
291
292 for (int a = 0; a < MAC_MAX_PLAYERS; a++)
293 for (int b = 0; b < 12; b++)
294 autofireRec[a].nextTime[b] = 0;
295
296 return (true);
297 }
298 else
299 {
300 cartOpen = false;
301 return (false);
302 }
303 }
304
SNES9X_OpenMultiCart(void)305 bool8 SNES9X_OpenMultiCart (void)
306 {
307 Boolean r;
308 char cart[2][PATH_MAX + 1];
309
310 DeinitGameWindow();
311
312 if (cartOpen)
313 {
314 SNES9X_SaveSRAM();
315 S9xResetSaveTimer(false);
316 S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
317 }
318
319 ResetCheatFinder();
320
321 if (!MultiCartDialog())
322 {
323 cartOpen = false;
324 return (false);
325 }
326
327 spcFileCount = pngFileCount = 0;
328
329 Settings.ForceHeader = (headerDetect == kHeaderForce );
330 Settings.ForceNoHeader = (headerDetect == kNoHeaderForce);
331 Settings.ForcePAL = (videoDetect == kPALForce );
332 Settings.ForceNTSC = (videoDetect == kNTSCForce );
333
334 GFX.InfoString = NULL;
335 GFX.InfoStringTimeout = 0;
336
337 S9xResetSaveTimer(true);
338
339 for (int i = 0; i < 2; i++)
340 {
341 cart[i][0] = 0;
342 if (multiCartPath[i])
343 r = CFStringGetCString(multiCartPath[i], cart[i], PATH_MAX, kCFStringEncodingUTF8);
344 }
345
346 SNES9X_InitSound();
347
348 if (Memory.LoadMultiCart(cart[0], cart[1]))
349 {
350 cartOpen = true;
351
352 SNES9X_LoadSRAM();
353
354 for (int i = 0; i < 2; i++)
355 {
356 if (cart[i][0])
357 ChangeTypeAndCreator(cart[i], 'CART', '~9X~');
358 }
359
360 ApplyNSRTHeaderControllers();
361
362 for (int a = 0; a < MAC_MAX_PLAYERS; a++)
363 for (int b = 0; b < 12; b++)
364 autofireRec[a].nextTime[b] = 0;
365
366 return (true);
367 }
368 else
369 {
370 cartOpen = false;
371 return (false);
372 }
373 }
374
SNES9X_LoadSRAM(void)375 void SNES9X_LoadSRAM (void)
376 {
377 if (cartOpen)
378 Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR));
379 }
380
SNES9X_SaveSRAM(void)381 void SNES9X_SaveSRAM (void)
382 {
383 const char *sramFilename;
384
385 if (cartOpen)
386 {
387 sramFilename = S9xGetFilename(".srm", SRAM_DIR);
388 Memory.SaveSRAM(sramFilename);
389 ChangeTypeAndCreator(sramFilename, 'SRAM', '~9X~');
390 }
391 }
392
SNES9X_Reset(void)393 void SNES9X_Reset (void)
394 {
395 if (cartOpen)
396 {
397 SNES9X_SaveSRAM();
398 S9xReset();
399 SNES9X_LoadSRAM();
400 }
401 }
402
SNES9X_SoftReset(void)403 void SNES9X_SoftReset (void)
404 {
405 if (cartOpen)
406 {
407 SNES9X_SaveSRAM();
408 S9xSoftReset();
409 SNES9X_LoadSRAM();
410 }
411 }
412
SNES9X_Freeze(void)413 bool8 SNES9X_Freeze (void)
414 {
415 OSStatus err;
416 FSRef ref;
417 int which;
418 const char *filename;
419
420 if (cartOpen)
421 {
422 MacStopSound();
423
424 which = PromptFreezeDefrost(true);
425
426 if (which >= 0)
427 {
428 filename = S9xGetFreezeFilename(which);
429
430 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
431 if (!err)
432 FSDeleteObject(&ref);
433
434 S9xFreezeGame(filename);
435 ChangeTypeAndCreator(filename, 'SAVE', '~9X~');
436 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
437 WriteThumbnailToResourceFork(&ref, 128, 120);
438
439 SNES9X_Go();
440
441 MacStartSound();
442 return (true);
443 }
444 else
445 {
446 MacStartSound();
447 return (false);
448 }
449 }
450 else
451 return (false);
452 }
453
SNES9X_Defrost(void)454 bool8 SNES9X_Defrost (void)
455 {
456 int which;
457 const char *filename;
458
459 if (cartOpen)
460 {
461 MacStopSound();
462
463 which = PromptFreezeDefrost(false);
464
465 if (which >= 0)
466 {
467 filename = S9xGetFreezeFilename(which);
468 S9xUnfreezeGame(filename);
469
470 SNES9X_Go();
471
472 MacStartSound();
473 return (true);
474 }
475 else
476 {
477 MacStartSound();
478 return (false);
479 }
480 }
481 else
482 return (false);
483 }
484
SNES9X_FreezeTo(void)485 bool8 SNES9X_FreezeTo (void)
486 {
487 OSStatus err;
488 FSRef ref;
489 char filename[PATH_MAX + 1];
490
491 if (cartOpen)
492 {
493 if (NavFreezeTo(filename))
494 {
495 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
496 if (!err)
497 FSDeleteObject(&ref);
498
499 S9xFreezeGame(filename);
500 ChangeTypeAndCreator(filename, 'SAVE', '~9X~');
501 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
502 WriteThumbnailToResourceFork(&ref, 128, 120);
503
504 return (true);
505 }
506 }
507
508 return (false);
509 }
510
SNES9X_DefrostFrom(void)511 bool8 SNES9X_DefrostFrom (void)
512 {
513 char filename[PATH_MAX + 1];
514
515 if (cartOpen)
516 {
517 if (NavDefrostFrom(filename))
518 {
519 S9xUnfreezeGame(filename);
520
521 SNES9X_Go();
522
523 return (true);
524 }
525 }
526
527 return (false);
528 }
529
SNES9X_RecordMovie(void)530 bool8 SNES9X_RecordMovie (void)
531 {
532 OSStatus err;
533 FSRef ref;
534 char filename[PATH_MAX + 1];
535
536 if (cartOpen)
537 {
538 if (NavRecordMovieTo(filename))
539 {
540 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
541 if (!err)
542 FSDeleteObject(&ref);
543
544 int r;
545 uint8 opt = 0, mask = 0;
546
547 for (int i = 0; i <= 4; i++)
548 if (macRecordFlag & (1 << i))
549 mask |= (1 << i);
550
551 if (macRecordFlag & (1 << 5))
552 opt |= MOVIE_OPT_FROM_RESET;
553 else
554 opt |= MOVIE_OPT_FROM_SNAPSHOT;
555
556 r = S9xMovieCreate(filename, mask, opt, macRecordWChar, wcslen(macRecordWChar));
557 if (r == SUCCESS)
558 {
559 ChangeTypeAndCreator(filename, 'SMOV', '~9X~');
560
561 if ((macRecordFlag & (1 << 5)) == 0)
562 {
563 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
564 WriteThumbnailToResourceFork(&ref, 128, 120);
565 }
566
567 SNES9X_Go();
568
569 return (true);
570 }
571 }
572 }
573
574 return (false);
575 }
576
SNES9X_PlayMovie(void)577 bool8 SNES9X_PlayMovie (void)
578 {
579 char filename[PATH_MAX + 1];
580
581 if (cartOpen)
582 {
583 if (NavPlayMovieFrom(filename))
584 {
585 int r;
586
587 r = S9xMovieOpen(filename, macPlayFlag & 1);
588 if (r == SUCCESS)
589 {
590 SNES9X_Go();
591
592 return (true);
593 }
594 }
595 }
596
597 return (false);
598 }
599
SNES9X_QTMovieRecord(void)600 bool8 SNES9X_QTMovieRecord (void)
601 {
602 char filename[PATH_MAX + 1];
603
604 if (cartOpen)
605 {
606 if (NavQTMovieRecordTo(filename))
607 {
608 MacQTStartRecording(filename);
609 macQTRecord = true;
610 SNES9X_Go();
611
612 return (true);
613 }
614 }
615
616 macQTRecord = false;
617
618 return (false);
619 }
620
SNES9X_Quit(void)621 void SNES9X_Quit (void)
622 {
623 DeinitGameWindow();
624
625 if (cartOpen)
626 {
627 SNES9X_SaveSRAM();
628 S9xResetSaveTimer(false);
629 S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
630 }
631
632 finished = true;
633 }
634
SNES9X_InitSound(void)635 void SNES9X_InitSound (void)
636 {
637 S9xInitSound(macSoundBuffer_ms, macSoundLagEnable ? macSoundBuffer_ms / 2 : 0);
638 }
639