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 "port.h"
196 #include "cheats.h"
197
198 #define __STDC_FORMAT_MACROS
199 #include <inttypes.h>
200
201 #include "mac-prefix.h"
202 #include "mac-dialog.h"
203 #include "mac-os.h"
204 #include "mac-stringtools.h"
205 #include "mac-cheat.h"
206
207 #define kDataBrowser 'BRSR'
208 #define kCmCheckBox 'CHK_'
209 #define kCmAddress 'ADDR'
210 #define kCmValue 'VALU'
211 #define kCmDescription 'DESC'
212 #define kNewButton 'NEW_'
213 #define kDelButton 'DEL_'
214 #define kAllButton 'ALL_'
215
216 extern SCheatData Cheat;
217
218 typedef struct
219 {
220 uint32 id;
221 uint32 address;
222 uint8 value;
223 bool8 valid;
224 bool8 enabled;
225 char description[22];
226 } CheatItem;
227
228 static WindowRef wRef;
229 static HIViewRef dbRef;
230 static CheatItem citem[MAX_CHEATS];
231 static uint32 numofcheats;
232
233 static void InitCheatItems (void);
234 static void ImportCheatItems (void);
235 static void DetachCheatItems (void);
236 static void AddCheatItem (void);
237 static void DeleteCheatItem (void);
238 static void EnableAllCheatItems (void);
239 static pascal void DBItemNotificationCallBack (HIViewRef, DataBrowserItemID, DataBrowserItemNotification);
240 static pascal Boolean DBCompareCallBack (HIViewRef, DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID);
241 static pascal OSStatus DBClientDataCallback (HIViewRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean);
242 static pascal OSStatus CheatEventHandler (EventHandlerCallRef, EventRef, void *);
243
244
InitCheatItems(void)245 static void InitCheatItems (void)
246 {
247 for (unsigned int i = 0; i < MAX_CHEATS; i++)
248 {
249 citem[i].id = i + 1;
250 citem[i].valid = false;
251 citem[i].enabled = false;
252 citem[i].address = 0;
253 citem[i].value = 0;
254 sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id);
255 }
256 }
257
ImportCheatItems(void)258 static void ImportCheatItems (void)
259 {
260 for (unsigned int i = 0; i < Cheat.num_cheats; i++)
261 {
262 citem[i].valid = true;
263 citem[i].enabled = Cheat.c[i].enabled;
264 citem[i].address = Cheat.c[i].address;
265 citem[i].value = Cheat.c[i].byte;
266 strcpy(citem[i].description, Cheat.c[i].name);
267 }
268 }
269
DetachCheatItems(void)270 static void DetachCheatItems (void)
271 {
272 S9xDeleteCheats(); // Cheat.num_cheats = 0
273
274 for (unsigned int i = 0; i < MAX_CHEATS; i++)
275 {
276 if (citem[i].valid)
277 {
278 strcpy(Cheat.c[Cheat.num_cheats].name, citem[i].description);
279 S9xAddCheat(citem[i].enabled, false, citem[i].address, citem[i].value); // Cheat.num_cheats++
280 }
281 }
282
283 S9xApplyCheats();
284 }
285
ConfigureCheat(void)286 void ConfigureCheat (void)
287 {
288 if (!cartOpen)
289 return;
290
291 OSStatus err;
292 IBNibRef nibRef;
293
294 err = CreateNibReference(kMacS9XCFString, &nibRef);
295 if (err == noErr)
296 {
297 err = CreateWindowFromNib(nibRef, CFSTR("CheatEntry"), &wRef);
298 if (err == noErr)
299 {
300 DataBrowserCallbacks callbacks;
301 EventHandlerRef eref;
302 EventHandlerUPP eUPP;
303 EventTypeSpec events[] = { { kEventClassCommand, kEventCommandProcess },
304 { kEventClassCommand, kEventCommandUpdateStatus },
305 { kEventClassWindow, kEventWindowClose } };
306 HIViewRef ctl, root;
307 HIViewID cid;
308
309 root = HIViewGetRoot(wRef);
310 cid.id = 0;
311 cid.signature = kDataBrowser;
312 HIViewFindByID(root, cid, &dbRef);
313
314 #ifdef MAC_PANTHER_SUPPORT
315 if (systemVersion < 0x1040)
316 {
317 HISize minSize;
318 Rect rct;
319
320 GetWindowBounds(wRef, kWindowContentRgn, &rct);
321 minSize.width = (float) (rct.right - rct.left);
322 minSize.height = (float) (rct.bottom - rct.top );
323 err = SetWindowResizeLimits(wRef, &minSize, NULL);
324 }
325 #endif
326
327 callbacks.version = kDataBrowserLatestCallbacks;
328 err = InitDataBrowserCallbacks(&callbacks);
329 callbacks.u.v1.itemDataCallback = NewDataBrowserItemDataUPP(DBClientDataCallback);
330 callbacks.u.v1.itemCompareCallback = NewDataBrowserItemCompareUPP(DBCompareCallBack);
331 callbacks.u.v1.itemNotificationCallback = NewDataBrowserItemNotificationUPP(DBItemNotificationCallBack);
332 err = SetDataBrowserCallbacks(dbRef, &callbacks);
333
334 if (systemVersion >= 0x1040)
335 err = DataBrowserChangeAttributes(dbRef, kDataBrowserAttributeListViewAlternatingRowColors, kDataBrowserAttributeNone);
336
337 InitCheatItems();
338 ImportCheatItems();
339
340 DataBrowserItemID *id;
341
342 id = new DataBrowserItemID[MAX_CHEATS];
343 if (!id)
344 QuitWithFatalError(0, "cheat 01");
345
346 numofcheats = 0;
347
348 for (unsigned int i = 0; i < MAX_CHEATS; i++)
349 {
350 if (citem[i].valid)
351 {
352 id[numofcheats] = citem[i].id;
353 numofcheats++;
354 }
355 }
356
357 if (numofcheats)
358 err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, numofcheats, id, kDataBrowserItemNoProperty);
359
360 delete [] id;
361
362 cid.signature = kNewButton;
363 HIViewFindByID(root, cid, &ctl);
364 if (numofcheats == MAX_CHEATS)
365 err = DeactivateControl(ctl);
366 else
367 err = ActivateControl(ctl);
368
369 cid.signature = kAllButton;
370 HIViewFindByID(root, cid, &ctl);
371 if (numofcheats == 0)
372 err = DeactivateControl(ctl);
373 else
374 err = ActivateControl(ctl);
375
376 cid.signature = kDelButton;
377 HIViewFindByID(root, cid, &ctl);
378 err = DeactivateControl(ctl);
379
380 eUPP = NewEventHandlerUPP(CheatEventHandler);
381 err = InstallWindowEventHandler(wRef, eUPP, GetEventTypeCount(events), events, (void *) wRef, &eref);
382
383 err = SetKeyboardFocus(wRef, dbRef, kControlFocusNextPart);
384
385 MoveWindowPosition(wRef, kWindowCheatEntry, true);
386 ShowWindow(wRef);
387 err = RunAppModalLoopForWindow(wRef);
388 HideWindow(wRef);
389 SaveWindowPosition(wRef, kWindowCheatEntry);
390
391 err = RemoveEventHandler(eref);
392 DisposeEventHandlerUPP(eUPP);
393
394 DisposeDataBrowserItemNotificationUPP(callbacks.u.v1.itemNotificationCallback);
395 DisposeDataBrowserItemCompareUPP(callbacks.u.v1.itemCompareCallback);
396 DisposeDataBrowserItemDataUPP(callbacks.u.v1.itemDataCallback);
397
398 CFRelease(wRef);
399
400 DetachCheatItems();
401 }
402
403 DisposeNibReference(nibRef);
404 }
405 }
406
AddCheatItem(void)407 static void AddCheatItem (void)
408 {
409 OSStatus err;
410 HIViewRef ctl, root;
411 HIViewID cid;
412 DataBrowserItemID id[1];
413 unsigned int i;
414
415 if (numofcheats == MAX_CHEATS)
416 return;
417
418 for (i = 0; i < MAX_CHEATS; i++)
419 if (citem[i].valid == false)
420 break;
421
422 if (i == MAX_CHEATS)
423 return;
424
425 numofcheats++;
426 citem[i].valid = true;
427 citem[i].enabled = false;
428 citem[i].address = 0;
429 citem[i].value = 0;
430 sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id);
431
432 id[0] = citem[i].id;
433 err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty);
434 err = RevealDataBrowserItem(dbRef, id[0], kCmAddress, true);
435
436 root = HIViewGetRoot(wRef);
437 cid.id = 0;
438
439 if (numofcheats == MAX_CHEATS)
440 {
441 cid.signature = kNewButton;
442 HIViewFindByID(root, cid, &ctl);
443 err = DeactivateControl(ctl);
444 }
445
446 if (numofcheats)
447 {
448 cid.signature = kAllButton;
449 HIViewFindByID(root, cid, &ctl);
450 err = ActivateControl(ctl);
451 }
452 }
453
DeleteCheatItem(void)454 static void DeleteCheatItem (void)
455 {
456 OSStatus err;
457 HIViewRef ctl, root;
458 HIViewID cid;
459 Handle selectedItems;
460 ItemCount selectionCount;
461
462 selectedItems = NewHandle(0);
463 if (!selectedItems)
464 return;
465
466 err = GetDataBrowserItems(dbRef, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems);
467 selectionCount = (GetHandleSize(selectedItems) / sizeof(DataBrowserItemID));
468
469 if (selectionCount == 0)
470 {
471 DisposeHandle(selectedItems);
472 return;
473 }
474
475 err = RemoveDataBrowserItems(dbRef, kDataBrowserNoItem, selectionCount, (DataBrowserItemID *) *selectedItems, kDataBrowserItemNoProperty);
476
477 for (unsigned int i = 0; i < selectionCount; i++)
478 {
479 citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].valid = false;
480 citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].enabled = false;
481 numofcheats--;
482 }
483
484 DisposeHandle(selectedItems);
485
486 root = HIViewGetRoot(wRef);
487 cid.id = 0;
488
489 if (numofcheats < MAX_CHEATS)
490 {
491 cid.signature = kNewButton;
492 HIViewFindByID(root, cid, &ctl);
493 err = ActivateControl(ctl);
494 }
495
496 if (numofcheats == 0)
497 {
498 cid.signature = kAllButton;
499 HIViewFindByID(root, cid, &ctl);
500 err = DeactivateControl(ctl);
501 }
502 }
503
EnableAllCheatItems(void)504 static void EnableAllCheatItems (void)
505 {
506 OSStatus err;
507
508 for (unsigned int i = 0; i < MAX_CHEATS; i++)
509 if (citem[i].valid)
510 citem[i].enabled = true;
511
512 err = UpdateDataBrowserItems(dbRef, kDataBrowserNoItem, kDataBrowserNoItem, NULL, kDataBrowserItemNoProperty, kCmCheckBox);
513 }
514
DBClientDataCallback(HIViewRef browser,DataBrowserItemID itemID,DataBrowserPropertyID property,DataBrowserItemDataRef itemData,Boolean changeValue)515 static pascal OSStatus DBClientDataCallback (HIViewRef browser, DataBrowserItemID itemID, DataBrowserPropertyID property, DataBrowserItemDataRef itemData, Boolean changeValue)
516 {
517 OSStatus err, result;
518 CFStringRef str;
519 Boolean r;
520 uint32 address;
521 uint8 value;
522 char code[256];
523
524 result = noErr;
525
526 switch (property)
527 {
528 case kCmCheckBox:
529 ThemeButtonValue buttonValue;
530
531 if (changeValue)
532 {
533 err = GetDataBrowserItemDataButtonValue(itemData, &buttonValue);
534 citem[itemID - 1].enabled = (buttonValue == kThemeButtonOn) ? true : false;
535 }
536 else
537 err = SetDataBrowserItemDataButtonValue(itemData, citem[itemID - 1].enabled ? kThemeButtonOn : kThemeButtonOff);
538
539 break;
540
541 case kCmAddress:
542 if (changeValue)
543 {
544 err = GetDataBrowserItemDataText(itemData, &str);
545 r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding());
546 CFRelease(str);
547 if (r)
548 {
549 Boolean translated;
550
551 if (S9xProActionReplayToRaw(code, address, value) == NULL)
552 translated = true;
553 else
554 if (S9xGameGenieToRaw(code, address, value) == NULL)
555 translated = true;
556 else
557 {
558 translated = false;
559 if (sscanf(code, "%" SCNx32, &address) != 1)
560 address = 0;
561 else
562 address &= 0xFFFFFF;
563 }
564
565 citem[itemID - 1].address = address;
566 sprintf(code, "%06" PRIX32, address);
567 str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
568 err = SetDataBrowserItemDataText(itemData, str);
569 CFRelease(str);
570
571 if (translated)
572 {
573 DataBrowserItemID id[1];
574
575 citem[itemID - 1].value = value;
576 id[0] = itemID;
577 err = UpdateDataBrowserItems(browser, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty, kCmValue);
578 }
579 }
580 }
581 else
582 {
583 sprintf(code, "%06" PRIX32, citem[itemID - 1].address);
584 str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
585 err = SetDataBrowserItemDataText(itemData, str);
586 CFRelease(str);
587 }
588
589 break;
590
591 case kCmValue:
592 if (changeValue)
593 {
594 err = GetDataBrowserItemDataText(itemData, &str);
595 r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding());
596 CFRelease(str);
597 if (r)
598 {
599 uint32 byte;
600
601 if (sscanf(code, "%" SCNx32, &byte) == 1)
602 citem[itemID - 1].value = (uint8) byte;
603 else
604 {
605 citem[itemID - 1].value = 0;
606 err = SetDataBrowserItemDataText(itemData, CFSTR("00"));
607 }
608 }
609 }
610 else
611 {
612 sprintf(code, "%02" PRIX8, citem[itemID - 1].value);
613 str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
614 err = SetDataBrowserItemDataText(itemData, str);
615 CFRelease(str);
616 }
617
618 break;
619
620 case kCmDescription:
621 if (changeValue)
622 {
623 code[0] = 0;
624 err = GetDataBrowserItemDataText(itemData, &str);
625 strcpy(code, GetMultiByteCharacters(str, 19));
626 CFRelease(str);
627
628 if (code[0] == 0)
629 {
630 code[0] = ' ';
631 code[1] = 0;
632 }
633
634 strcpy(citem[itemID - 1].description, code);
635 }
636 else
637 {
638 str = CFStringCreateWithCString(kCFAllocatorDefault, citem[itemID - 1].description, CFStringGetSystemEncoding());
639 err = SetDataBrowserItemDataText(itemData, str);
640 CFRelease(str);
641 }
642
643 break;
644
645 case kDataBrowserItemIsActiveProperty:
646 err = SetDataBrowserItemDataBooleanValue(itemData, true);
647 break;
648
649 case kDataBrowserItemIsEditableProperty:
650 err = SetDataBrowserItemDataBooleanValue(itemData, true);
651 break;
652
653 default:
654 result = errDataBrowserPropertyNotSupported;
655 }
656
657 return (result);
658 }
659
DBCompareCallBack(HIViewRef browser,DataBrowserItemID itemOne,DataBrowserItemID itemTwo,DataBrowserPropertyID sortProperty)660 static pascal Boolean DBCompareCallBack (HIViewRef browser, DataBrowserItemID itemOne, DataBrowserItemID itemTwo, DataBrowserPropertyID sortProperty)
661 {
662 Boolean result = false;
663
664 switch (sortProperty)
665 {
666 case kCmCheckBox:
667 result = (citem[itemOne - 1].enabled && !(citem[itemTwo - 1].enabled)) ? true : false;
668 break;
669
670 case kCmAddress:
671 result = (citem[itemOne - 1].address < citem[itemTwo - 1].address) ? true : false;
672 break;
673
674 case kCmValue:
675 result = (citem[itemOne - 1].value < citem[itemTwo - 1].value) ? true : false;
676 break;
677
678 case kCmDescription:
679 result = (strcmp(citem[itemOne - 1].description, citem[itemTwo - 1].description) < 0) ? true : false;
680 }
681
682 return (result);
683 }
684
DBItemNotificationCallBack(HIViewRef browser,DataBrowserItemID itemID,DataBrowserItemNotification message)685 static pascal void DBItemNotificationCallBack (HIViewRef browser, DataBrowserItemID itemID, DataBrowserItemNotification message)
686 {
687 OSStatus err;
688 HIViewRef ctl;
689 HIViewID cid = { kDelButton, 0 };
690 ItemCount selectionCount;
691
692 switch (message)
693 {
694 case kDataBrowserSelectionSetChanged:
695 HIViewFindByID(HIViewGetRoot(wRef), cid, &ctl);
696
697 err = GetDataBrowserItemCount(browser, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, &selectionCount);
698 if (selectionCount == 0)
699 err = DeactivateControl(ctl);
700 else
701 err = ActivateControl(ctl);
702 }
703 }
704
CheatEventHandler(EventHandlerCallRef inHandlerCallRef,EventRef inEvent,void * inUserData)705 static pascal OSStatus CheatEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
706 {
707 OSStatus err, result = eventNotHandledErr;
708 WindowRef tWindowRef;
709
710 tWindowRef = (WindowRef) inUserData;
711
712 switch (GetEventClass(inEvent))
713 {
714 case kEventClassWindow:
715 switch (GetEventKind(inEvent))
716 {
717 case kEventWindowClose:
718 QuitAppModalLoopForWindow(tWindowRef);
719 result = noErr;
720 break;
721 }
722
723 break;
724
725 case kEventClassCommand:
726 switch (GetEventKind(inEvent))
727 {
728 HICommand tHICommand;
729
730 case kEventCommandUpdateStatus:
731 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
732 if (err == noErr && tHICommand.commandID == 'clos')
733 {
734 UpdateMenuCommandStatus(true);
735 result = noErr;
736 }
737
738 break;
739
740 case kEventCommandProcess:
741 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
742 if (err == noErr)
743 {
744 switch (tHICommand.commandID)
745 {
746 case kNewButton:
747 AddCheatItem();
748 result = noErr;
749 break;
750
751 case kDelButton:
752 DeleteCheatItem();
753 result = noErr;
754 break;
755
756 case kAllButton:
757 EnableAllCheatItems();
758 result = noErr;
759 }
760 }
761 }
762 }
763
764 return (result);
765 }
766