mirror of https://github.com/snes9xgit/snes9x.git
Mac: Cheat entry
This commit is contained in:
parent
8685db48a7
commit
6b9f79a9e3
|
@ -15,12 +15,13 @@
|
|||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 - 2021 Michael Donald Buckley
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <snes9x_framework/snes9x_framework.h>
|
||||
#import "S9xPreferences/S9xPreferencesWindowController.h"
|
||||
#import "Cheats/S9xCheatsViewController.h"
|
||||
|
||||
extern NSWindowFrameAutosaveName const kMainWindowIdentifier;
|
||||
|
||||
|
@ -31,6 +32,7 @@ extern NSWindowFrameAutosaveName const kMainWindowIdentifier;
|
|||
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *keys;
|
||||
@property (nonatomic, strong) NSWindow *gameWindow;
|
||||
@property (nonatomic, strong) S9xPreferencesWindowController *preferencesWindowController;
|
||||
@property (nonatomic, strong) NSWindowController *cheatsWindowController;
|
||||
@property (nonatomic, readonly, assign) S9xDeviceSetting deviceSetting;
|
||||
|
||||
- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 Michael Donald Buckley
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
|
@ -23,6 +23,7 @@
|
|||
#import "S9xPreferencesConstants.h"
|
||||
|
||||
NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
|
||||
NSWindowFrameAutosaveName const kCheatsWindowIdentifier = @"s9xCheatsWindow";
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
@ -194,6 +195,9 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
|
|||
[self importKeySettings];
|
||||
[self importGraphicsSettings];
|
||||
[self applyEmulationSettings];
|
||||
|
||||
self.s9xEngine.cheatsEnabled = [defaults boolForKey:kEnableCheatsPref];
|
||||
|
||||
[defaults synchronize];
|
||||
}
|
||||
|
||||
|
@ -463,6 +467,11 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
|
|||
[s9xView.leftAnchor constraintGreaterThanOrEqualToAnchor:gameWindow.contentView.leftAnchor].active = YES;
|
||||
[s9xView.rightAnchor constraintLessThanOrEqualToAnchor:gameWindow.contentView.rightAnchor].active = YES;
|
||||
|
||||
if (self.cheatsWindowController != nil)
|
||||
{
|
||||
[((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) deselectAll];
|
||||
[((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) reloadData];
|
||||
}
|
||||
|
||||
[gameWindow makeKeyAndOrderFront:self];
|
||||
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:url];
|
||||
|
@ -481,6 +490,17 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
|
|||
else if (action == @selector(updateDeviceSetting:)) {
|
||||
menuItem.state = (self.deviceSetting == (S9xDeviceSetting)menuItem.tag) ? NSOnState : NSOffState;
|
||||
}
|
||||
else if (action == @selector(toggleCheats:))
|
||||
{
|
||||
if (self.s9xEngine.cheatsEnabled)
|
||||
{
|
||||
menuItem.title = NSLocalizedString(@"Disable Cheats", nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItem.title = NSLocalizedString(@"Enable Cheats", nil);
|
||||
}
|
||||
}
|
||||
|
||||
return !self.isRunningEmulation;
|
||||
}
|
||||
|
@ -587,4 +607,35 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
|
|||
}
|
||||
|
||||
|
||||
- (IBAction)openCheatsWindow:(id)sender
|
||||
{
|
||||
if (self.cheatsWindowController == nil)
|
||||
{
|
||||
NSWindow *window = [NSWindow windowWithContentViewController:[[S9xCheatsViewController alloc] initWithNibName:@"S9xCheatsViewController" bundle:nil]];
|
||||
self.cheatsWindowController = [[NSWindowController alloc] initWithWindow:window];
|
||||
|
||||
window = self.cheatsWindowController.window;
|
||||
|
||||
window.title = NSLocalizedString(@"Cheats", nil);
|
||||
window.restorationClass = self.class;
|
||||
window.frameAutosaveName = kCheatsWindowIdentifier;
|
||||
window.releasedWhenClosed = NO;
|
||||
|
||||
if ( ![window setFrameUsingName:kCheatsWindowIdentifier] )
|
||||
{
|
||||
[window center];
|
||||
}
|
||||
}
|
||||
|
||||
[self.cheatsWindowController showWindow:nil];
|
||||
[self.cheatsWindowController.window makeKeyAndOrderFront:nil];
|
||||
[self.cheatsWindowController.window makeKeyWindow];
|
||||
}
|
||||
|
||||
- (IBAction)toggleCheats:(id)sender
|
||||
{
|
||||
self.s9xEngine.cheatsEnabled = !self.s9xEngine.cheatsEnabled;
|
||||
[NSUserDefaults.standardUserDefaults setBool:self.s9xEngine.cheatsEnabled forKey:kEnableCheatsPref];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.3"/>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
|
@ -94,6 +95,225 @@
|
|||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="hfX-Gc-Rmh">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="d1i-Nq-o0y">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="CRw-8g-dqq">
|
||||
<connections>
|
||||
<action selector="undo:" target="-1" id="oqy-wX-XcR"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="CdC-5F-VDh">
|
||||
<connections>
|
||||
<action selector="redo:" target="-1" id="kJD-Xz-Zty"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="nRT-Cs-jI0"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="U6Z-3p-PPh">
|
||||
<connections>
|
||||
<action selector="cut:" target="-1" id="yHv-Hk-RPa"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="5cj-G2-7gk">
|
||||
<connections>
|
||||
<action selector="copy:" target="-1" id="6Ld-tc-P6r"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="TeD-Jo-cdQ">
|
||||
<connections>
|
||||
<action selector="paste:" target="-1" id="Iux-BI-cfB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="bjo-AI-m9c">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="-1" id="GAC-Wa-wBS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="5ri-yU-J0H">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="-1" id="CQu-g4-54R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="7lE-39-sok">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="-1" id="knb-10-R70"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="tAo-56-xcT"/>
|
||||
<menuItem title="Find" id="zSy-Xx-KQa">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="GEm-kH-bZL">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="uIF-VE-Z6k">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="IPt-dD-fAN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="QtG-Fs-n6K">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="9BN-tN-3DT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="nnl-za-IbF">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="bSc-gk-JuQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="qWR-cm-W1V">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="tv2-yd-vpb"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="o3Q-m6-FJO">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="-1" id="M9V-9P-thc"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="G0a-qW-Bbf">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="nhp-QW-gWb"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="ZhJ-ys-AG3">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="0bK-KI-BgN">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="Mcv-I1-eIG">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="-1" id="clh-Fo-Ijh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="8OB-ZV-Y89">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="-1" id="Zsb-I1-m2z"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kmA-62-3BG"/>
|
||||
<menuItem title="Check Spelling While Typing" id="9uJ-Lj-27Z">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="tbo-iz-xWm"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="7Pr-2A-IZz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="-1" id="vVM-cJ-76v"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="H8Z-ar-hDG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="DeB-zv-squ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="Tg6-1Z-oYb">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="nYE-gK-pd5">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="sKx-tp-8do">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="hLR-Cc-W4X"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="J6a-TH-0cM"/>
|
||||
<menuItem title="Smart Copy/Paste" id="6zQ-rA-n4t">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="-1" id="L3I-lk-Rc1"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="6gP-bb-GhK">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="zIF-Bj-nHr"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="6Kf-xg-whp">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="TVL-NZ-cgx"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="529-ZM-vx1">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="6Tb-yQ-xJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="auV-3d-GUN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="cXL-of-q81"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="Jg7-Zo-CgX">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="lN5-BH-4vr"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="pMI-ev-WNp">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="1hV-QX-gUc">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="3je-Bq-QuL">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="-1" id="n26-tf-uhF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="Dep-YV-sBp">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="-1" id="UeC-6R-cAp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="M87-rn-9bP">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="-1" id="j3f-7O-Fq2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="ycZ-G4-VRG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="vH3-f7-pA9">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="n7w-d1-Ucd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="-1" id="Lp4-Sq-aS1"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="ibA-8o-W5l">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="-1" id="vLl-Od-P5E"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Emulation" id="Kjk-eO-rPI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Emulation" id="s2F-Pd-YT5">
|
||||
|
@ -174,6 +394,25 @@
|
|||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Cheats" id="ee5-dW-h20">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Cheats" id="Bsy-Nq-yAm">
|
||||
<items>
|
||||
<menuItem title="Enable Cheats" id="5Gg-4s-ZCo">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleCheats:" target="-1" id="IZg-ZR-9iA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show Cheats" id="9oz-Uu-GkA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="openCheatsWindow:" target="-1" id="VdR-bM-JgN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
/***********************************************************************************
|
||||
SNES9X for Mac OS (c) Copyright John Stiles
|
||||
|
||||
Snes9x for Mac OS X
|
||||
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
(c) Copyright 2002 - 2005 107
|
||||
(c) Copyright 2002 PB1400c
|
||||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class S9xCheatItem;
|
||||
|
||||
@interface S9xCheatEditViewController : NSViewController
|
||||
|
||||
- (instancetype)initWithCheatItem:(nullable S9xCheatItem *)cheatItem saveCallback:(void (^)(void))saveCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,150 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
/***********************************************************************************
|
||||
SNES9X for Mac OS (c) Copyright John Stiles
|
||||
|
||||
Snes9x for Mac OS X
|
||||
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
(c) Copyright 2002 - 2005 107
|
||||
(c) Copyright 2002 PB1400c
|
||||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <snes9x_framework/snes9x_framework.h>
|
||||
|
||||
#import "S9xCheatEditViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface S9xCheatEditViewController () <NSTextFieldDelegate>
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *codeField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *descriptionField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *addressField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *valueField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *invalidCodeLabel;
|
||||
@property (nonatomic, weak) IBOutlet NSButton *saveButton;
|
||||
|
||||
@property (nonatomic, strong) S9xCheatItem *cheatItem;
|
||||
@property (nonatomic, copy) void (^saveBlock)(void);
|
||||
@end
|
||||
|
||||
@implementation S9xCheatEditViewController
|
||||
|
||||
- (instancetype)initWithCheatItem:(nullable S9xCheatItem *)cheatItem saveCallback:(void (^)(void))saveCallback
|
||||
{
|
||||
if (self = [super initWithNibName:@"S9xCheatEditViewController" bundle:nil])
|
||||
{
|
||||
_cheatItem = cheatItem;
|
||||
_saveBlock = saveCallback;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
if (self.cheatItem != nil)
|
||||
{
|
||||
self.descriptionField.stringValue = self.cheatItem.cheatDescription;
|
||||
self.addressField.objectValue = self.cheatItem.address;
|
||||
self.valueField.objectValue = self.cheatItem.value;
|
||||
}
|
||||
|
||||
[self updateSaveButton];
|
||||
}
|
||||
|
||||
- (void)controlTextDidChange:(NSNotification *)notification
|
||||
{
|
||||
if (notification.object == self.codeField)
|
||||
{
|
||||
if (self.codeField.stringValue.length > 0 )
|
||||
{
|
||||
uint32 address = 0;
|
||||
uint8 value = 0;
|
||||
|
||||
if ( CheatValuesFromCode(self.codeField.stringValue, &address, &value) )
|
||||
{
|
||||
self.addressField.objectValue = @(address);
|
||||
self.valueField.objectValue = @(value);
|
||||
self.invalidCodeLabel.hidden = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.addressField.stringValue = @"";
|
||||
self.valueField.stringValue = @"";
|
||||
self.invalidCodeLabel.hidden = NO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.cheatItem != nil)
|
||||
{
|
||||
self.addressField.objectValue = self.cheatItem.address;
|
||||
self.valueField.objectValue = self.cheatItem.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.addressField.stringValue = @"";
|
||||
self.valueField.stringValue = @"";
|
||||
}
|
||||
|
||||
self.invalidCodeLabel.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
else if (notification.object == self.addressField || notification.object == self.valueField)
|
||||
{
|
||||
self.codeField.stringValue = @"";
|
||||
}
|
||||
|
||||
[self updateSaveButton];
|
||||
}
|
||||
|
||||
- (void)updateSaveButton
|
||||
{
|
||||
self.saveButton.enabled = (self.addressField.stringValue.length > 0 && self.valueField.stringValue.length > 0);
|
||||
}
|
||||
|
||||
- (IBAction)save:(id)sender
|
||||
{
|
||||
if ( self.cheatItem != nil )
|
||||
{
|
||||
self.cheatItem.address = self.addressField.objectValue;
|
||||
self.cheatItem.value = self.valueField.objectValue;
|
||||
self.cheatItem.cheatDescription = self.descriptionField.stringValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.codeField.stringValue.length > 0)
|
||||
{
|
||||
CreateCheatFromCode(self.codeField.stringValue, self.descriptionField.stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateCheatFromAddress(self.addressField.objectValue, self.valueField.objectValue, self.descriptionField.stringValue);
|
||||
}
|
||||
}
|
||||
|
||||
[self dismissViewController:self];
|
||||
|
||||
self.saveBlock();
|
||||
}
|
||||
|
||||
- (IBAction)cancelOperation:(nullable id)sender
|
||||
{
|
||||
[self dismissViewController:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,176 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="S9xCheatEditViewController">
|
||||
<connections>
|
||||
<outlet property="addressField" destination="D6y-BE-IK3" id="d5P-wa-Smp"/>
|
||||
<outlet property="codeField" destination="0sv-1S-EIB" id="NgH-hC-0w9"/>
|
||||
<outlet property="descriptionField" destination="nEa-pB-Mzq" id="oxa-VB-Fxd"/>
|
||||
<outlet property="invalidCodeLabel" destination="KZs-5Q-3p9" id="grc-UN-oat"/>
|
||||
<outlet property="saveButton" destination="hSd-vC-YVB" id="eXA-qI-8s2"/>
|
||||
<outlet property="valueField" destination="Dhp-d5-iPA" id="swy-G0-yNz"/>
|
||||
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="Hz6-mo-xeY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="161"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GCw-FQ-ML2">
|
||||
<rect key="frame" x="18" y="125" width="95" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Code:" id="MsD-CX-uiA">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ocx-0r-xce">
|
||||
<rect key="frame" x="18" y="94" width="95" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Description:" id="qGa-0B-bfl">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0sv-1S-EIB">
|
||||
<rect key="frame" x="119" y="122" width="341" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="rUK-Hh-f2D">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="skT-dO-kOt"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nEa-pB-Mzq">
|
||||
<rect key="frame" x="119" y="91" width="341" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="Xx1-4E-gVH">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="Otl-uB-yiJ"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="D6y-BE-IK3">
|
||||
<rect key="frame" x="119" y="60" width="167" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="dDB-jS-8FL">
|
||||
<customFormatter key="formatter" id="h5V-Ki-4jN" customClass="S9xAddressFormatter"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="2Hq-IC-08n"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WBj-hA-3op">
|
||||
<rect key="frame" x="18" y="63" width="95" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Address (Hex):" id="JjJ-Y6-aDd">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="W3i-GO-VrX">
|
||||
<rect key="frame" x="292" y="63" width="78" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Value (Hex):" id="xcZ-Zz-oEB">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Dhp-d5-iPA">
|
||||
<rect key="frame" x="376" y="60" width="84" height="21"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="zvh-hx-r62">
|
||||
<customFormatter key="formatter" id="5Nt-dm-EVe" customClass="S9xValueFormatter"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="tcg-Mr-bad"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hSd-vC-YVB">
|
||||
<rect key="frame" x="391" y="13" width="76" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BeG-Mv-fdl">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
DQ
|
||||
</string>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="save:" target="-2" id="YtB-HR-yIq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="D7Q-2q-Pzm">
|
||||
<rect key="frame" x="317" y="1" width="76" height="56"/>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="MYe-Fc-BPg">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
Gw
|
||||
</string>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="cancelOperation:" target="-2" id="VQ1-m5-QEe"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField hidden="YES" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KZs-5Q-3p9">
|
||||
<rect key="frame" x="18" y="20" width="96" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Code is invalid." id="afl-tf-lbT">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Dhp-d5-iPA" secondAttribute="trailing" constant="20" symbolic="YES" id="21W-9V-32u"/>
|
||||
<constraint firstAttribute="bottom" secondItem="KZs-5Q-3p9" secondAttribute="bottom" constant="20" symbolic="YES" id="4HP-HF-AEl"/>
|
||||
<constraint firstItem="Dhp-d5-iPA" firstAttribute="top" secondItem="nEa-pB-Mzq" secondAttribute="bottom" constant="10" symbolic="YES" id="63A-Ma-OtX"/>
|
||||
<constraint firstItem="GCw-FQ-ML2" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="8qY-Ac-0CN"/>
|
||||
<constraint firstItem="nEa-pB-Mzq" firstAttribute="leading" secondItem="ocx-0r-xce" secondAttribute="trailing" constant="8" symbolic="YES" id="9k6-tR-gwZ"/>
|
||||
<constraint firstItem="GCw-FQ-ML2" firstAttribute="firstBaseline" secondItem="0sv-1S-EIB" secondAttribute="firstBaseline" id="Ac2-1g-SE0"/>
|
||||
<constraint firstAttribute="bottom" secondItem="hSd-vC-YVB" secondAttribute="bottom" constant="20" symbolic="YES" id="DPN-xe-MNJ"/>
|
||||
<constraint firstItem="Dhp-d5-iPA" firstAttribute="leading" secondItem="W3i-GO-VrX" secondAttribute="trailing" constant="8" symbolic="YES" id="Fb0-7T-6fc"/>
|
||||
<constraint firstItem="D7Q-2q-Pzm" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="KZs-5Q-3p9" secondAttribute="trailing" constant="8" symbolic="YES" id="G6I-4t-cuH"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0sv-1S-EIB" secondAttribute="trailing" constant="20" symbolic="YES" id="IwN-oX-xyo"/>
|
||||
<constraint firstItem="ocx-0r-xce" firstAttribute="trailing" secondItem="GCw-FQ-ML2" secondAttribute="trailing" id="JBV-A1-7IM"/>
|
||||
<constraint firstItem="D7Q-2q-Pzm" firstAttribute="width" secondItem="hSd-vC-YVB" secondAttribute="width" id="JPv-Je-6IC"/>
|
||||
<constraint firstItem="D6y-BE-IK3" firstAttribute="leading" secondItem="WBj-hA-3op" secondAttribute="trailing" constant="8" symbolic="YES" id="Jdf-zp-HN9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nEa-pB-Mzq" secondAttribute="trailing" constant="20" symbolic="YES" id="MHZ-MZ-8lM"/>
|
||||
<constraint firstItem="KZs-5Q-3p9" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="MrD-kz-LlV"/>
|
||||
<constraint firstAttribute="trailing" secondItem="hSd-vC-YVB" secondAttribute="trailing" constant="20" symbolic="YES" id="P79-Hp-Ies"/>
|
||||
<constraint firstItem="W3i-GO-VrX" firstAttribute="firstBaseline" secondItem="Dhp-d5-iPA" secondAttribute="firstBaseline" id="U8n-RJ-aA2"/>
|
||||
<constraint firstItem="0sv-1S-EIB" firstAttribute="leading" secondItem="GCw-FQ-ML2" secondAttribute="trailing" constant="8" symbolic="YES" id="YjZ-qJ-VXK"/>
|
||||
<constraint firstItem="WBj-hA-3op" firstAttribute="trailing" secondItem="ocx-0r-xce" secondAttribute="trailing" id="cEn-lY-sMy"/>
|
||||
<constraint firstItem="D7Q-2q-Pzm" firstAttribute="top" secondItem="Dhp-d5-iPA" secondAttribute="bottom" constant="8" symbolic="YES" id="dVU-1H-i8D"/>
|
||||
<constraint firstItem="ocx-0r-xce" firstAttribute="firstBaseline" secondItem="nEa-pB-Mzq" secondAttribute="firstBaseline" id="izn-Ex-sfI"/>
|
||||
<constraint firstItem="hSd-vC-YVB" firstAttribute="leading" secondItem="D7Q-2q-Pzm" secondAttribute="trailing" constant="12" symbolic="YES" id="jCl-Gz-4aW"/>
|
||||
<constraint firstItem="ocx-0r-xce" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="ldp-5m-ybj"/>
|
||||
<constraint firstItem="W3i-GO-VrX" firstAttribute="leading" secondItem="D6y-BE-IK3" secondAttribute="trailing" constant="8" symbolic="YES" id="lgL-8G-EGj"/>
|
||||
<constraint firstItem="nEa-pB-Mzq" firstAttribute="top" secondItem="0sv-1S-EIB" secondAttribute="bottom" constant="10" symbolic="YES" id="omD-qz-g1p"/>
|
||||
<constraint firstItem="hSd-vC-YVB" firstAttribute="top" secondItem="Dhp-d5-iPA" secondAttribute="bottom" constant="20" id="qJd-d3-538"/>
|
||||
<constraint firstItem="D7Q-2q-Pzm" firstAttribute="centerY" secondItem="hSd-vC-YVB" secondAttribute="centerY" id="rvp-aK-XTi"/>
|
||||
<constraint firstItem="WBj-hA-3op" firstAttribute="firstBaseline" secondItem="D6y-BE-IK3" secondAttribute="firstBaseline" id="vGc-Td-vr8"/>
|
||||
<constraint firstItem="D6y-BE-IK3" firstAttribute="top" secondItem="nEa-pB-Mzq" secondAttribute="bottom" constant="10" symbolic="YES" id="vR3-eW-lq8"/>
|
||||
<constraint firstItem="D6y-BE-IK3" firstAttribute="width" secondItem="Dhp-d5-iPA" secondAttribute="width" multiplier="2" id="wAO-sa-aRw"/>
|
||||
<constraint firstItem="WBj-hA-3op" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="wEF-3Q-1FL"/>
|
||||
<constraint firstItem="GCw-FQ-ML2" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" symbolic="YES" id="yb8-0y-zZn"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="140" y="101.5"/>
|
||||
</customView>
|
||||
</objects>
|
||||
</document>
|
|
@ -0,0 +1,30 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
/***********************************************************************************
|
||||
SNES9X for Mac OS (c) Copyright John Stiles
|
||||
|
||||
Snes9x for Mac OS X
|
||||
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
(c) Copyright 2002 - 2005 107
|
||||
(c) Copyright 2002 PB1400c
|
||||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface S9xCheatsViewController : NSViewController
|
||||
- (void)deselectAll;
|
||||
- (void)reloadData;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,266 @@
|
|||
/*****************************************************************************\
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
This file is licensed under the Snes9x License.
|
||||
For further information, consult the LICENSE file in the root directory.
|
||||
\*****************************************************************************/
|
||||
|
||||
/***********************************************************************************
|
||||
SNES9X for Mac OS (c) Copyright John Stiles
|
||||
|
||||
Snes9x for Mac OS X
|
||||
|
||||
(c) Copyright 2001 - 2011 zones
|
||||
(c) Copyright 2002 - 2005 107
|
||||
(c) Copyright 2002 PB1400c
|
||||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
#import <snes9x_framework/snes9x_framework.h>
|
||||
|
||||
#import "S9xCheatsViewController.h"
|
||||
#import "S9xCheatEditViewController.h"
|
||||
|
||||
@interface S9xCheatsViewController () <NSTableViewDataSource, NSTableViewDelegate>
|
||||
|
||||
@property (nonatomic, weak) IBOutlet NSTableView *tableView;
|
||||
@property (nonatomic, weak) IBOutlet NSSegmentedControl *segmentedControl;
|
||||
|
||||
@property (nonatomic, strong) NSArray<S9xCheatItem *> *cheats;
|
||||
|
||||
@end
|
||||
|
||||
@implementation S9xCheatsViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.segmentedControl setEnabled:YES forSegment:0];
|
||||
[self.segmentedControl setEnabled:NO forSegment:1];
|
||||
[self.segmentedControl setEnabled:NO forSegment:2];
|
||||
|
||||
self.tableView.doubleAction = @selector(editSelectedCheat);
|
||||
self.tableView.target = self;
|
||||
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)deselectAll
|
||||
{
|
||||
[self.tableView deselectAll:nil];
|
||||
}
|
||||
|
||||
- (void)reloadData
|
||||
{
|
||||
NSSet<NSNumber *> *selectedIDs = [NSSet setWithArray:[[self.cheats objectsAtIndexes:self.tableView.selectedRowIndexes] valueForKey:@"cheatID"]];
|
||||
|
||||
CGPoint scrollPosition = self.tableView.visibleRect.origin;
|
||||
|
||||
self.cheats = [GetAllCheats() sortedArrayUsingDescriptors:self.tableView.sortDescriptors];
|
||||
[self.tableView reloadData];
|
||||
|
||||
NSMutableIndexSet *indexSet = [NSMutableIndexSet new];
|
||||
for (NSUInteger i = 0; i < self.tableView.numberOfRows; ++i)
|
||||
{
|
||||
if ([selectedIDs containsObject:@(self.cheats[i].cheatID)])
|
||||
{
|
||||
[indexSet addIndex:i];
|
||||
}
|
||||
}
|
||||
|
||||
[self.tableView scrollPoint:scrollPosition];
|
||||
|
||||
[self.tableView selectRowIndexes:indexSet byExtendingSelection:NO];
|
||||
}
|
||||
|
||||
- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors
|
||||
{
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||||
{
|
||||
return self.cheats.count;
|
||||
}
|
||||
|
||||
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
{
|
||||
NSTableCellView *view = [self.tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
|
||||
view.objectValue = self.cheats[row];
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification *)notification
|
||||
{
|
||||
[self.segmentedControl setEnabled:self.tableView.selectedRowIndexes.count > 0 forSegment:1];
|
||||
[self.segmentedControl setEnabled:self.tableView.selectedRowIndexes.count == 1 forSegment:2];
|
||||
}
|
||||
|
||||
- (IBAction)segmentedControlAction:(NSSegmentedControl *)sender
|
||||
{
|
||||
switch(sender.selectedSegment)
|
||||
{
|
||||
case 0:
|
||||
[self addNewCheat];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
[self deleteSelectedCheats];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
[self editSelectedCheat];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addNewCheat
|
||||
{
|
||||
S9xCheatEditViewController *vc = [[S9xCheatEditViewController alloc] initWithCheatItem:nil saveCallback:^
|
||||
{
|
||||
[self reloadData];
|
||||
}];
|
||||
|
||||
[self presentViewControllerAsSheet:vc];
|
||||
}
|
||||
|
||||
- (void)deleteSelectedCheats
|
||||
{
|
||||
|
||||
NSIndexSet *selectedRows = self.tableView.selectedRowIndexes;
|
||||
|
||||
if (selectedRows.count > 0)
|
||||
{
|
||||
NSArray *cheatsToDelete = [[self.cheats objectsAtIndexes:selectedRows] sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"cheatID" ascending:NO]]];
|
||||
|
||||
for (S9xCheatItem *item in cheatsToDelete)
|
||||
{
|
||||
[item delete];
|
||||
}
|
||||
}
|
||||
|
||||
[self.tableView deselectAll:self];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)editSelectedCheat
|
||||
{
|
||||
NSIndexSet *selectedRows = self.tableView.selectedRowIndexes;
|
||||
|
||||
if (selectedRows.count == 1)
|
||||
{
|
||||
S9xCheatItem *item = self.cheats[selectedRows.firstIndex];
|
||||
|
||||
S9xCheatEditViewController *vc = [[S9xCheatEditViewController alloc] initWithCheatItem:item saveCallback:^
|
||||
{
|
||||
[self reloadData];
|
||||
}];
|
||||
|
||||
[self presentViewControllerAsSheet:vc];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface S9xHexNumberFormatter : NSFormatter
|
||||
@end
|
||||
|
||||
@implementation S9xHexNumberFormatter
|
||||
|
||||
+ (NSUInteger)maxLength
|
||||
{
|
||||
return NSUIntegerMax;
|
||||
}
|
||||
|
||||
- (BOOL)getObjectValue:(out id _Nullable __autoreleasing *)obj forString:(NSString *)string errorDescription:(out NSString * _Nullable __autoreleasing *)error
|
||||
{
|
||||
if (string.length > 0)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
NSScanner *scanner = [NSScanner scannerWithString:string];
|
||||
[scanner scanHexInt:&value];
|
||||
*obj = @(value);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSNumber *)numberFromString:(NSString *)string
|
||||
{
|
||||
unsigned int value = 0;
|
||||
NSScanner *scanner = [NSScanner scannerWithString:string];
|
||||
[scanner scanHexInt:&value];
|
||||
return @(value);
|
||||
}
|
||||
|
||||
- (NSString *)stringForObjectValue:(id)obj
|
||||
{
|
||||
if ([obj isKindOfClass:NSNumber.class])
|
||||
{
|
||||
return [NSString stringWithFormat:@"%X", ((NSNumber *)obj).unsignedIntValue];
|
||||
}
|
||||
else if ([obj isKindOfClass:NSString.class])
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (BOOL)isPartialStringValid:(NSString * _Nonnull * _Nonnull)partialStringPtr proposedSelectedRange:(nullable NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString * _Nullable * _Nullable)error
|
||||
{
|
||||
static NSCharacterSet *hexCharacterSet;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
hexCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"] invertedSet];
|
||||
});
|
||||
|
||||
if ( [*partialStringPtr rangeOfCharacterFromSet:hexCharacterSet].location != NSNotFound )
|
||||
{
|
||||
*partialStringPtr = nil;
|
||||
return NO;
|
||||
}
|
||||
|
||||
*partialStringPtr = (*partialStringPtr).uppercaseString;
|
||||
|
||||
if ( (*partialStringPtr).length > self.class.maxLength )
|
||||
{
|
||||
*partialStringPtr = [*partialStringPtr substringToIndex:self.class.maxLength];
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface S9xAddressFormatter : S9xHexNumberFormatter
|
||||
@end
|
||||
|
||||
@implementation S9xAddressFormatter
|
||||
|
||||
+ (NSUInteger)maxLength
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface S9xValueFormatter : S9xHexNumberFormatter
|
||||
@end
|
||||
|
||||
@implementation S9xValueFormatter
|
||||
|
||||
+ (NSUInteger)maxLength
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,249 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="S9xCheatsViewController">
|
||||
<connections>
|
||||
<outlet property="segmentedControl" destination="KjP-h3-jKc" id="Bt4-rc-1xy"/>
|
||||
<outlet property="tableView" destination="pGm-DH-gAd" id="ajm-xs-Jfs"/>
|
||||
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="Hz6-mo-xeY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="540" height="369"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vFP-V1-oDR">
|
||||
<rect key="frame" x="20" y="49" width="500" height="300"/>
|
||||
<clipView key="contentView" id="W9Q-F6-649">
|
||||
<rect key="frame" x="1" y="1" width="498" height="298"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="automatic" headerView="Mok-FY-WnT" viewBased="YES" id="pGm-DH-gAd">
|
||||
<rect key="frame" x="0.0" y="0.0" width="505" height="270"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="17" height="0.0"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="EnabledView" width="20" minWidth="20" maxWidth="1000" id="cC0-lr-AA9">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="1Q4-Vz-lfX">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="enabled"/>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="EnabledView" id="Ut8-IY-g7e">
|
||||
<rect key="frame" x="8" y="0.0" width="18" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mUE-de-1Om">
|
||||
<rect key="frame" x="0.0" y="3" width="18" height="18"/>
|
||||
<buttonCell key="cell" type="check" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="rPf-Je-vka">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="Ut8-IY-g7e" name="value" keyPath="objectValue.enabled" id="ssD-Mp-PzQ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="mUE-de-1Om" firstAttribute="leading" secondItem="Ut8-IY-g7e" secondAttribute="leading" constant="2" id="9IH-oE-Wmh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="mUE-de-1Om" secondAttribute="trailing" constant="2" id="BtE-A8-6pc"/>
|
||||
<constraint firstItem="mUE-de-1Om" firstAttribute="top" secondItem="Ut8-IY-g7e" secondAttribute="top" constant="5" id="ErO-uP-PnI"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mUE-de-1Om" secondAttribute="bottom" constant="5" id="dkw-y0-pbo"/>
|
||||
</constraints>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
<tableColumn identifier="AddressView" width="70" minWidth="40" maxWidth="1000" id="6PK-fF-GEp">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Address">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Os8-ci-czY">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="address"/>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="AddressView" id="n6t-oy-t7z">
|
||||
<rect key="frame" x="43" y="0.0" width="70" height="24"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="C4e-ke-M8L">
|
||||
<rect key="frame" x="0.0" y="4" width="4" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" sendsActionOnEndEditing="YES" id="J15-ri-abw">
|
||||
<customFormatter key="formatter" id="Ufa-zW-hvg" customClass="S9xAddressFormatter"/>
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="n6t-oy-t7z" name="value" keyPath="objectValue.address" id="J5m-Hv-eBy"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="C4e-ke-M8L" secondAttribute="bottom" constant="4" id="Qbc-Zs-F2E"/>
|
||||
<constraint firstItem="C4e-ke-M8L" firstAttribute="top" secondItem="n6t-oy-t7z" secondAttribute="top" constant="4" id="VUK-22-7nl"/>
|
||||
<constraint firstItem="C4e-ke-M8L" firstAttribute="leading" secondItem="n6t-oy-t7z" secondAttribute="leading" constant="2" id="ee1-LL-m6k"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="C4e-ke-M8L" id="RY8-UH-zpf"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
<tableColumn identifier="ValueView" width="42" minWidth="10" maxWidth="3.4028234663852886e+38" id="da7-KY-Srx">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Value">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="orR-4T-Np6">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="value"/>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="ValueView" id="fpL-E3-Qdj">
|
||||
<rect key="frame" x="130" y="0.0" width="42" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="mo4-7p-pED">
|
||||
<rect key="frame" x="0.0" y="-3" width="42" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" sendsActionOnEndEditing="YES" id="1j5-js-5aw">
|
||||
<customFormatter key="formatter" id="CGB-sD-2m4" customClass="S9xValueFormatter"/>
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="fpL-E3-Qdj" name="value" keyPath="objectValue.value" id="bVa-Le-aZs"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="mo4-7p-pED" secondAttribute="trailing" constant="2" id="0N3-q3-LaN"/>
|
||||
<constraint firstItem="mo4-7p-pED" firstAttribute="leading" secondItem="fpL-E3-Qdj" secondAttribute="leading" constant="2" id="6ng-aJ-Fes"/>
|
||||
<constraint firstItem="mo4-7p-pED" firstAttribute="top" secondItem="fpL-E3-Qdj" secondAttribute="top" constant="4" id="fkT-dL-tWB"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="mo4-7p-pED" id="74M-Dw-j3G"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
<tableColumn identifier="DescriptionView" width="310" minWidth="10" maxWidth="3.4028234663852886e+38" id="xr9-0R-rR5">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Description">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="Gyh-cB-AzL">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="description"/>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="DescriptionView" id="cgm-Sc-PIV">
|
||||
<rect key="frame" x="189" y="0.0" width="307" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="Zqt-oO-fx4">
|
||||
<rect key="frame" x="0.0" y="-3" width="289" height="16"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Table View Cell" id="UIU-WQ-1xK">
|
||||
<font key="font" usesAppearanceFont="YES"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="cgm-Sc-PIV" name="value" keyPath="objectValue.cheatDescription" id="b05-vX-fT6"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Zqt-oO-fx4" firstAttribute="top" secondItem="cgm-Sc-PIV" secondAttribute="top" constant="4" id="eqE-l5-rlz"/>
|
||||
<constraint firstItem="Zqt-oO-fx4" firstAttribute="leading" secondItem="cgm-Sc-PIV" secondAttribute="leading" constant="2" id="n3o-YT-L8Q"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zqt-oO-fx4" secondAttribute="trailing" constant="20" symbolic="YES" id="sqE-Bc-4i5"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="Zqt-oO-fx4" id="ny1-SA-vLX"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-2" id="DKU-ha-EyO"/>
|
||||
<outlet property="delegate" destination="-2" id="IXr-Op-DSZ"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="300" id="2Zw-DZ-iMB"/>
|
||||
<constraint firstAttribute="width" constant="500" id="hrh-eQ-Siq"/>
|
||||
</constraints>
|
||||
<scroller key="horizontalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="8UU-uM-WYf">
|
||||
<rect key="frame" x="1" y="283" width="498" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="N3O-e7-I8W">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<tableHeaderView key="headerView" wantsLayer="YES" id="Mok-FY-WnT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="505" height="28"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableHeaderView>
|
||||
</scrollView>
|
||||
<segmentedControl verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KjP-h3-jKc">
|
||||
<rect key="frame" x="20" y="19" width="92" height="23"/>
|
||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="smallSquare" trackingMode="momentary" id="ID9-7o-zKN">
|
||||
<font key="font" metaFont="system"/>
|
||||
<segments>
|
||||
<segment toolTip="Add" image="NSAddTemplate" width="21"/>
|
||||
<segment toolTip="Remove" image="NSRemoveTemplate" width="21" tag="1"/>
|
||||
<segment label="Edit" toolTip="Edit" width="42"/>
|
||||
</segments>
|
||||
</segmentedCell>
|
||||
<connections>
|
||||
<action selector="segmentedControlAction:" target="-2" id="4O4-uP-ch7"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="vFP-V1-oDR" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="0eo-dm-pUd"/>
|
||||
<constraint firstItem="KjP-h3-jKc" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="20" symbolic="YES" id="7kU-fr-tCu"/>
|
||||
<constraint firstItem="KjP-h3-jKc" firstAttribute="top" secondItem="vFP-V1-oDR" secondAttribute="bottom" constant="8" symbolic="YES" id="9DQ-M4-0ND"/>
|
||||
<constraint firstItem="vFP-V1-oDR" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" symbolic="YES" id="Zcq-Qu-Aq3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vFP-V1-oDR" secondAttribute="trailing" constant="20" symbolic="YES" id="dBe-ee-mae"/>
|
||||
<constraint firstAttribute="bottom" secondItem="KjP-h3-jKc" secondAttribute="bottom" constant="20" symbolic="YES" id="uIa-MN-siZ"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="236" y="188.5"/>
|
||||
</customView>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSAddTemplate" width="15" height="13"/>
|
||||
<image name="NSRemoveTemplate" width="15" height="4"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -38,4 +38,6 @@ extern NSString * const kAllowInvalidVRAMAccessPref;
|
|||
extern NSString * const kSeparateEchoBufferFromRAMPref;
|
||||
extern NSString * const kDisableSpriteLimitPref;
|
||||
|
||||
extern NSString * const kEnableCheatsPref;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -35,3 +35,5 @@ NSString * const kApplyGameSpecificHacksPref = @"ApplyGameSpecificHacks";
|
|||
NSString * const kAllowInvalidVRAMAccessPref = @"AllowInvalidVRAMAccess";
|
||||
NSString * const kSeparateEchoBufferFromRAMPref = @"SeparateEchoBufferFromRAM";
|
||||
NSString * const kDisableSpriteLimitPref = @"DisableSpriteLimit";
|
||||
|
||||
NSString * const kEnableCheatsPref = @"EnableCheats";
|
||||
|
|
|
@ -15,13 +15,34 @@
|
|||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 Michael Donald Buckley
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
#ifndef _mac_cheat_h_
|
||||
#define _mac_cheat_h_
|
||||
|
||||
void ConfigureCheat (void);
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface S9xCheatItem : NSView
|
||||
@property (nonatomic, assign) uint32 cheatID;
|
||||
@property (nonatomic, strong) NSNumber *address;
|
||||
@property (nonatomic, strong) NSNumber *value;
|
||||
@property (nonatomic, strong) NSNumber *enabled;
|
||||
@property (nonatomic, strong) NSString *cheatDescription;
|
||||
|
||||
- (void)delete;
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
bool CheatValuesFromCode(NSString *code, uint32 *address, uint8 *value);
|
||||
void CreateCheatFromAddress(NSNumber *address, NSNumber *value, NSString *cheatDescription);
|
||||
void CreateCheatFromCode(NSString *code, NSString *cheatDescription);
|
||||
NSArray<S9xCheatItem *> *GetAllCheats(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
(c) Copyright 2004 Alexander and Sander
|
||||
(c) Copyright 2004 - 2005 Steven Seeger
|
||||
(c) Copyright 2005 Ryan Vogt
|
||||
(c) Copyright 2019 Michael Donald Buckley
|
||||
(c) Copyright 2019 - 2022 Michael Donald Buckley
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
|
@ -42,510 +42,137 @@
|
|||
|
||||
extern SCheatData Cheat;
|
||||
|
||||
typedef struct
|
||||
@implementation S9xCheatItem
|
||||
|
||||
- (void)setAddress:(uint32)address value:(uint8)value cheatDescription:(const char *)cheatDescription
|
||||
{
|
||||
uint32 id;
|
||||
uint32 address;
|
||||
uint8 value;
|
||||
bool8 valid;
|
||||
bool8 enabled;
|
||||
char description[22];
|
||||
} CheatItem;
|
||||
bool enabled = self.enabled.boolValue;
|
||||
|
||||
static WindowRef wRef;
|
||||
static HIViewRef dbRef;
|
||||
static CheatItem citem[MAC_MAX_CHEATS];
|
||||
static uint32 numofcheats;
|
||||
char code[256];
|
||||
sprintf(code, "%x=%x", address, value);
|
||||
S9xModifyCheatGroup(self.cheatID, cheatDescription, code);
|
||||
|
||||
static void InitCheatItems (void);
|
||||
static void ImportCheatItems (void);
|
||||
static void DetachCheatItems (void);
|
||||
static void AddCheatItem (void);
|
||||
static void DeleteCheatItem (void);
|
||||
static void EnableAllCheatItems (void);
|
||||
static void DBItemNotificationCallBack (HIViewRef, DataBrowserItemID, DataBrowserItemNotification);
|
||||
static OSStatus CheatEventHandler (EventHandlerCallRef, EventRef, void *);
|
||||
|
||||
|
||||
static void InitCheatItems (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < MAC_MAX_CHEATS; i++)
|
||||
if (enabled)
|
||||
{
|
||||
citem[i].id = i + 1;
|
||||
citem[i].valid = false;
|
||||
citem[i].enabled = false;
|
||||
citem[i].address = 0;
|
||||
citem[i].value = 0;
|
||||
sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id);
|
||||
S9xEnableCheatGroup(self.cheatID);
|
||||
}
|
||||
}
|
||||
|
||||
static void ImportCheatItems (void)
|
||||
@dynamic address;
|
||||
- (NSNumber *)address
|
||||
{
|
||||
int cheat_num = std::min((int)Cheat.g.size(), MAC_MAX_CHEATS);
|
||||
for (unsigned int i = 0; i < cheat_num; i++)
|
||||
return @(Cheat.g[self.cheatID].c[0].address);
|
||||
}
|
||||
|
||||
- (void)setAddress:(NSNumber *)address
|
||||
{
|
||||
[self setAddress:address.unsignedIntValue value:Cheat.g[self.cheatID].c[0].byte cheatDescription:self.cheatDescription.UTF8String];
|
||||
}
|
||||
|
||||
@dynamic value;
|
||||
- (NSNumber *)value
|
||||
{
|
||||
return @(Cheat.g[self.cheatID].c[0].byte);
|
||||
}
|
||||
|
||||
- (void)setValue:(NSNumber *)value
|
||||
{
|
||||
[self setAddress:Cheat.g[self.cheatID].c[0].address value:value.unsignedCharValue cheatDescription:self.cheatDescription.UTF8String];
|
||||
}
|
||||
|
||||
@dynamic enabled;
|
||||
- (NSNumber *)enabled
|
||||
{
|
||||
return @(Cheat.g[self.cheatID].enabled);
|
||||
}
|
||||
|
||||
- (void)setEnabled:(NSNumber *)enabled
|
||||
{
|
||||
if (enabled.boolValue)
|
||||
{
|
||||
citem[i].valid = true;
|
||||
citem[i].enabled = Cheat.g[i].enabled;
|
||||
citem[i].address = Cheat.g[i].c[0].address; // mac dialog only supports one cheat per group at the moment
|
||||
citem[i].value = Cheat.g[i].c[0].byte;
|
||||
strncpy(citem[i].description, Cheat.g[i].name, 21);
|
||||
citem[i].description[21] = '\0';
|
||||
S9xEnableCheatGroup(self.cheatID);
|
||||
}
|
||||
else
|
||||
{
|
||||
S9xDisableCheatGroup(self.cheatID);
|
||||
}
|
||||
}
|
||||
|
||||
static void DetachCheatItems (void)
|
||||
@dynamic cheatDescription;
|
||||
- (NSString *)cheatDescription
|
||||
{
|
||||
S9xDeleteCheats();
|
||||
return [NSString stringWithUTF8String:Cheat.g[self.cheatID].name];
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < MAC_MAX_CHEATS; i++)
|
||||
- (void)setCheatDescription:(NSString *)cheatDescription
|
||||
{
|
||||
[self setAddress:Cheat.g[self.cheatID].c[0].address value:Cheat.g[self.cheatID].c[0].byte cheatDescription:cheatDescription.UTF8String];
|
||||
}
|
||||
|
||||
- (void)delete
|
||||
{
|
||||
S9xDeleteCheatGroup(self.cheatID);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
bool CheatValuesFromCode(NSString *code, uint32 *address, uint8 *value)
|
||||
{
|
||||
const char *text = code.UTF8String;
|
||||
|
||||
if (!S9xGameGenieToRaw (text, *address, *value))
|
||||
{
|
||||
if (citem[i].valid)
|
||||
{
|
||||
char code[10];
|
||||
snprintf(code, 10, "%x=%x", citem[i].address, citem[i].value);
|
||||
int index = S9xAddCheatGroup(citem[i].description, code);
|
||||
if(citem[i].enabled && index >= 0)
|
||||
S9xEnableCheatGroup(index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!S9xProActionReplayToRaw (text, *address, *value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x = %x", (unsigned int *)address, (unsigned int *)value) == 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (sscanf (text, "%x / %x", (unsigned int *)address, (unsigned int *)value) == 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConfigureCheat (void)
|
||||
void CreateCheatFromAddress(NSNumber *address, NSNumber *value, NSString *cheatDescription)
|
||||
{
|
||||
if (!cartOpen)
|
||||
return;
|
||||
|
||||
// OSStatus err;
|
||||
// IBNibRef nibRef;
|
||||
//
|
||||
// err = CreateNibReference(kMacS9XCFString, &nibRef);
|
||||
// if (err == noErr)
|
||||
// {
|
||||
// err = CreateWindowFromNib(nibRef, CFSTR("CheatEntry"), &wRef);
|
||||
// if (err == noErr)
|
||||
// {
|
||||
// DataBrowserCallbacks callbacks;
|
||||
// EventHandlerRef eref;
|
||||
// EventHandlerUPP eUPP;
|
||||
// EventTypeSpec events[] = { { kEventClassCommand, kEventCommandProcess },
|
||||
// { kEventClassCommand, kEventCommandUpdateStatus },
|
||||
// { kEventClassWindow, kEventWindowClose } };
|
||||
// HIViewRef ctl, root;
|
||||
// HIViewID cid;
|
||||
//
|
||||
// root = HIViewGetRoot(wRef);
|
||||
// cid.id = 0;
|
||||
// cid.signature = kDataBrowser;
|
||||
// HIViewFindByID(root, cid, &dbRef);
|
||||
//
|
||||
// #ifdef MAC_PANTHER_SUPPORT
|
||||
// if (systemVersion < 0x1040)
|
||||
// {
|
||||
// HISize minSize;
|
||||
// Rect rct;
|
||||
//
|
||||
// GetWindowBounds(wRef, kWindowContentRgn, &rct);
|
||||
// minSize.width = (float) (rct.right - rct.left);
|
||||
// minSize.height = (float) (rct.bottom - rct.top );
|
||||
// err = SetWindowResizeLimits(wRef, &minSize, NULL);
|
||||
// }
|
||||
// #endif
|
||||
//
|
||||
// callbacks.version = kDataBrowserLatestCallbacks;
|
||||
// err = InitDataBrowserCallbacks(&callbacks);
|
||||
// callbacks.u.v1.itemDataCallback = NewDataBrowserItemDataUPP(DBClientDataCallback);
|
||||
// callbacks.u.v1.itemCompareCallback = NewDataBrowserItemCompareUPP(DBCompareCallBack);
|
||||
// callbacks.u.v1.itemNotificationCallback = NewDataBrowserItemNotificationUPP(DBItemNotificationCallBack);
|
||||
// err = SetDataBrowserCallbacks(dbRef, &callbacks);
|
||||
//
|
||||
// if (systemVersion >= 0x1040)
|
||||
// err = DataBrowserChangeAttributes(dbRef, kDataBrowserAttributeListViewAlternatingRowColors, kDataBrowserAttributeNone);
|
||||
//
|
||||
// InitCheatItems();
|
||||
// ImportCheatItems();
|
||||
//
|
||||
// DataBrowserItemID *id;
|
||||
//
|
||||
// id = new DataBrowserItemID[MAC_MAX_CHEATS];
|
||||
// if (!id)
|
||||
// QuitWithFatalError(@"cheat 01");
|
||||
//
|
||||
// numofcheats = 0;
|
||||
//
|
||||
// for (unsigned int i = 0; i < MAC_MAX_CHEATS; i++)
|
||||
// {
|
||||
// if (citem[i].valid)
|
||||
// {
|
||||
// id[numofcheats] = citem[i].id;
|
||||
// numofcheats++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (numofcheats)
|
||||
// err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, numofcheats, id, kDataBrowserItemNoProperty);
|
||||
//
|
||||
// delete [] id;
|
||||
//
|
||||
// cid.signature = kNewButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// if (numofcheats == MAC_MAX_CHEATS)
|
||||
// err = DeactivateControl(ctl);
|
||||
// else
|
||||
// err = ActivateControl(ctl);
|
||||
//
|
||||
// cid.signature = kAllButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// if (numofcheats == 0)
|
||||
// err = DeactivateControl(ctl);
|
||||
// else
|
||||
// err = ActivateControl(ctl);
|
||||
//
|
||||
// cid.signature = kDelButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// err = DeactivateControl(ctl);
|
||||
//
|
||||
// eUPP = NewEventHandlerUPP(CheatEventHandler);
|
||||
// err = InstallWindowEventHandler(wRef, eUPP, GetEventTypeCount(events), events, (void *) wRef, &eref);
|
||||
//
|
||||
// err = SetKeyboardFocus(wRef, dbRef, kControlFocusNextPart);
|
||||
//
|
||||
// MoveWindowPosition(wRef, kWindowCheatEntry, true);
|
||||
// ShowWindow(wRef);
|
||||
// err = RunAppModalLoopForWindow(wRef);
|
||||
// HideWindow(wRef);
|
||||
// SaveWindowPosition(wRef, kWindowCheatEntry);
|
||||
//
|
||||
// err = RemoveEventHandler(eref);
|
||||
// DisposeEventHandlerUPP(eUPP);
|
||||
//
|
||||
// DisposeDataBrowserItemNotificationUPP(callbacks.u.v1.itemNotificationCallback);
|
||||
// DisposeDataBrowserItemCompareUPP(callbacks.u.v1.itemCompareCallback);
|
||||
// DisposeDataBrowserItemDataUPP(callbacks.u.v1.itemDataCallback);
|
||||
//
|
||||
// CFRelease(wRef);
|
||||
//
|
||||
// DetachCheatItems();
|
||||
// }
|
||||
//
|
||||
// DisposeNibReference(nibRef);
|
||||
// }
|
||||
char code[256];
|
||||
sprintf(code, "%x=%x", address.unsignedIntValue, value.unsignedCharValue);
|
||||
S9xAddCheatGroup(cheatDescription.UTF8String, code);
|
||||
S9xEnableCheatGroup(Cheat.g.size() - 1);
|
||||
}
|
||||
|
||||
static void AddCheatItem (void)
|
||||
void CreateCheatFromCode(NSString *code, NSString *cheatDescription)
|
||||
{
|
||||
// OSStatus err;
|
||||
// HIViewRef ctl, root;
|
||||
// HIViewID cid;
|
||||
// DataBrowserItemID id[1];
|
||||
// unsigned int i;
|
||||
//
|
||||
// if (numofcheats == MAC_MAX_CHEATS)
|
||||
// return;
|
||||
//
|
||||
// for (i = 0; i < MAC_MAX_CHEATS; i++)
|
||||
// if (citem[i].valid == false)
|
||||
// break;
|
||||
//
|
||||
// if (i == MAC_MAX_CHEATS)
|
||||
// return;
|
||||
//
|
||||
// numofcheats++;
|
||||
// citem[i].valid = true;
|
||||
// citem[i].enabled = false;
|
||||
// citem[i].address = 0;
|
||||
// citem[i].value = 0;
|
||||
// sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id);
|
||||
//
|
||||
// id[0] = citem[i].id;
|
||||
// err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty);
|
||||
// err = RevealDataBrowserItem(dbRef, id[0], kCmAddress, true);
|
||||
//
|
||||
// root = HIViewGetRoot(wRef);
|
||||
// cid.id = 0;
|
||||
//
|
||||
// if (numofcheats == MAC_MAX_CHEATS)
|
||||
// {
|
||||
// cid.signature = kNewButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// err = DeactivateControl(ctl);
|
||||
// }
|
||||
//
|
||||
// if (numofcheats)
|
||||
// {
|
||||
// cid.signature = kAllButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// err = ActivateControl(ctl);
|
||||
// }
|
||||
S9xAddCheatGroup(cheatDescription.UTF8String, code.UTF8String);
|
||||
S9xEnableCheatGroup(Cheat.g.size() - 1);
|
||||
}
|
||||
|
||||
static void DeleteCheatItem (void)
|
||||
NSArray<S9xCheatItem *> *GetAllCheats(void)
|
||||
{
|
||||
// OSStatus err;
|
||||
// HIViewRef ctl, root;
|
||||
// HIViewID cid;
|
||||
// Handle selectedItems;
|
||||
// ItemCount selectionCount;
|
||||
//
|
||||
// selectedItems = NewHandle(0);
|
||||
// if (!selectedItems)
|
||||
// return;
|
||||
//
|
||||
// err = GetDataBrowserItems(dbRef, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems);
|
||||
// selectionCount = (GetHandleSize(selectedItems) / sizeof(DataBrowserItemID));
|
||||
//
|
||||
// if (selectionCount == 0)
|
||||
// {
|
||||
// DisposeHandle(selectedItems);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// err = RemoveDataBrowserItems(dbRef, kDataBrowserNoItem, selectionCount, (DataBrowserItemID *) *selectedItems, kDataBrowserItemNoProperty);
|
||||
//
|
||||
// for (unsigned int i = 0; i < selectionCount; i++)
|
||||
// {
|
||||
// citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].valid = false;
|
||||
// citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].enabled = false;
|
||||
// numofcheats--;
|
||||
// }
|
||||
//
|
||||
// DisposeHandle(selectedItems);
|
||||
//
|
||||
// root = HIViewGetRoot(wRef);
|
||||
// cid.id = 0;
|
||||
//
|
||||
// if (numofcheats < MAC_MAX_CHEATS)
|
||||
// {
|
||||
// cid.signature = kNewButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// err = ActivateControl(ctl);
|
||||
// }
|
||||
//
|
||||
// if (numofcheats == 0)
|
||||
// {
|
||||
// cid.signature = kAllButton;
|
||||
// HIViewFindByID(root, cid, &ctl);
|
||||
// err = DeactivateControl(ctl);
|
||||
// }
|
||||
}
|
||||
NSMutableArray *cheats = [NSMutableArray new];
|
||||
uint32 cheatID = 0;
|
||||
|
||||
static void EnableAllCheatItems (void)
|
||||
{
|
||||
// OSStatus err;
|
||||
//
|
||||
// for (unsigned int i = 0; i < MAC_MAX_CHEATS; i++)
|
||||
// if (citem[i].valid)
|
||||
// citem[i].enabled = true;
|
||||
//
|
||||
// err = UpdateDataBrowserItems(dbRef, kDataBrowserNoItem, kDataBrowserNoItem, NULL, kDataBrowserItemNoProperty, kCmCheckBox);
|
||||
}
|
||||
for (auto it : Cheat.g)
|
||||
{
|
||||
S9xCheatItem *cheat = [S9xCheatItem new];
|
||||
cheat.cheatID = cheatID++;
|
||||
|
||||
static OSStatus DBClientDataCallback (HIViewRef browser, DataBrowserItemID itemID, DataBrowserPropertyID property, DataBrowserItemDataRef itemData, Boolean changeValue)
|
||||
{
|
||||
// OSStatus err, result;
|
||||
// CFStringRef str;
|
||||
// Boolean r;
|
||||
// uint32 address;
|
||||
// uint8 value;
|
||||
// char code[256];
|
||||
//
|
||||
// result = noErr;
|
||||
//
|
||||
// switch (property)
|
||||
// {
|
||||
// case kCmCheckBox:
|
||||
// ThemeButtonValue buttonValue;
|
||||
//
|
||||
// if (changeValue)
|
||||
// {
|
||||
// err = GetDataBrowserItemDataButtonValue(itemData, &buttonValue);
|
||||
// citem[itemID - 1].enabled = (buttonValue == kThemeButtonOn) ? true : false;
|
||||
// }
|
||||
// else
|
||||
// err = SetDataBrowserItemDataButtonValue(itemData, citem[itemID - 1].enabled ? kThemeButtonOn : kThemeButtonOff);
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kCmAddress:
|
||||
// if (changeValue)
|
||||
// {
|
||||
// err = GetDataBrowserItemDataText(itemData, &str);
|
||||
// r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding());
|
||||
// CFRelease(str);
|
||||
// if (r)
|
||||
// {
|
||||
// Boolean translated;
|
||||
//
|
||||
// if (S9xProActionReplayToRaw(code, address, value) == NULL)
|
||||
// translated = true;
|
||||
// else
|
||||
// if (S9xGameGenieToRaw(code, address, value) == NULL)
|
||||
// translated = true;
|
||||
// else
|
||||
// {
|
||||
// translated = false;
|
||||
// if (sscanf(code, "%" SCNx32, &address) != 1)
|
||||
// address = 0;
|
||||
// else
|
||||
// address &= 0xFFFFFF;
|
||||
// }
|
||||
//
|
||||
// citem[itemID - 1].address = address;
|
||||
// sprintf(code, "%06" PRIX32, address);
|
||||
// str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
|
||||
// err = SetDataBrowserItemDataText(itemData, str);
|
||||
// CFRelease(str);
|
||||
//
|
||||
// if (translated)
|
||||
// {
|
||||
// DataBrowserItemID id[1];
|
||||
//
|
||||
// citem[itemID - 1].value = value;
|
||||
// id[0] = itemID;
|
||||
// err = UpdateDataBrowserItems(browser, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty, kCmValue);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// sprintf(code, "%06" PRIX32, citem[itemID - 1].address);
|
||||
// str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
|
||||
// err = SetDataBrowserItemDataText(itemData, str);
|
||||
// CFRelease(str);
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kCmValue:
|
||||
// if (changeValue)
|
||||
// {
|
||||
// err = GetDataBrowserItemDataText(itemData, &str);
|
||||
// r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding());
|
||||
// CFRelease(str);
|
||||
// if (r)
|
||||
// {
|
||||
// uint32 byte;
|
||||
//
|
||||
// if (sscanf(code, "%" SCNx32, &byte) == 1)
|
||||
// citem[itemID - 1].value = (uint8) byte;
|
||||
// else
|
||||
// {
|
||||
// citem[itemID - 1].value = 0;
|
||||
// err = SetDataBrowserItemDataText(itemData, CFSTR("00"));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// sprintf(code, "%02" PRIX8, citem[itemID - 1].value);
|
||||
// str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding());
|
||||
// err = SetDataBrowserItemDataText(itemData, str);
|
||||
// CFRelease(str);
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kCmDescription:
|
||||
// if (changeValue)
|
||||
// {
|
||||
// code[0] = 0;
|
||||
// err = GetDataBrowserItemDataText(itemData, &str);
|
||||
// strcpy(code, GetMultiByteCharacters(str, 19));
|
||||
// CFRelease(str);
|
||||
//
|
||||
// if (code[0] == 0)
|
||||
// {
|
||||
// code[0] = ' ';
|
||||
// code[1] = 0;
|
||||
// }
|
||||
//
|
||||
// strcpy(citem[itemID - 1].description, code);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// str = CFStringCreateWithCString(kCFAllocatorDefault, citem[itemID - 1].description, CFStringGetSystemEncoding());
|
||||
// err = SetDataBrowserItemDataText(itemData, str);
|
||||
// CFRelease(str);
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kDataBrowserItemIsActiveProperty:
|
||||
// err = SetDataBrowserItemDataBooleanValue(itemData, true);
|
||||
// break;
|
||||
//
|
||||
// case kDataBrowserItemIsEditableProperty:
|
||||
// err = SetDataBrowserItemDataBooleanValue(itemData, true);
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// result = errDataBrowserPropertyNotSupported;
|
||||
// }
|
||||
//
|
||||
// return (result);
|
||||
return 0;
|
||||
}
|
||||
[cheats addObject:cheat];
|
||||
}
|
||||
|
||||
|
||||
static OSStatus CheatEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
|
||||
{
|
||||
// OSStatus err, result = eventNotHandledErr;
|
||||
// WindowRef tWindowRef;
|
||||
//
|
||||
// tWindowRef = (WindowRef) inUserData;
|
||||
//
|
||||
// switch (GetEventClass(inEvent))
|
||||
// {
|
||||
// case kEventClassWindow:
|
||||
// switch (GetEventKind(inEvent))
|
||||
// {
|
||||
// case kEventWindowClose:
|
||||
// QuitAppModalLoopForWindow(tWindowRef);
|
||||
// result = noErr;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kEventClassCommand:
|
||||
// switch (GetEventKind(inEvent))
|
||||
// {
|
||||
// HICommand tHICommand;
|
||||
//
|
||||
// case kEventCommandUpdateStatus:
|
||||
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
|
||||
// if (err == noErr && tHICommand.commandID == 'clos')
|
||||
// {
|
||||
// UpdateMenuCommandStatus(true);
|
||||
// result = noErr;
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// case kEventCommandProcess:
|
||||
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand);
|
||||
// if (err == noErr)
|
||||
// {
|
||||
// switch (tHICommand.commandID)
|
||||
// {
|
||||
// case kNewButton:
|
||||
// AddCheatItem();
|
||||
// result = noErr;
|
||||
// break;
|
||||
//
|
||||
// case kDelButton:
|
||||
// DeleteCheatItem();
|
||||
// result = noErr;
|
||||
// break;
|
||||
//
|
||||
// case kAllButton:
|
||||
// EnableAllCheatItems();
|
||||
// result = noErr;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return (result);
|
||||
return 0;
|
||||
return cheats;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,6 +177,8 @@ extern id<S9xInputDelegate> inputDelegate;
|
|||
|
||||
@property (nonatomic, weak) id<S9xInputDelegate> inputDelegate;
|
||||
|
||||
@property (nonatomic, assign) BOOL cheatsEnabled;
|
||||
|
||||
- (void)recreateS9xView;
|
||||
|
||||
- (void)start;
|
||||
|
|
|
@ -3409,6 +3409,17 @@ void QuitWithFatalError ( NSString *message)
|
|||
return inputDelegate;
|
||||
}
|
||||
|
||||
@dynamic cheatsEnabled;
|
||||
- (BOOL)cheatsEnabled
|
||||
{
|
||||
return Cheat.enabled;
|
||||
}
|
||||
|
||||
- (void)setCheatsEnabled:(BOOL)cheatsEnabled
|
||||
{
|
||||
Cheat.enabled = cheatsEnabled;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation S9xJoypad
|
||||
|
|
|
@ -16,5 +16,5 @@ FOUNDATION_EXPORT const unsigned char snes9x_frameworkVersionString[];
|
|||
|
||||
#import <snes9x_framework/port.h>
|
||||
#import <snes9x_framework/mac-os.h>
|
||||
|
||||
#import <snes9x_framework/mac-cheat.h>
|
||||
|
||||
|
|
|
@ -74,6 +74,11 @@
|
|||
30A6F62423B2771A00630584 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30A6F62323B2771A00630584 /* MetalKit.framework */; };
|
||||
30A6F62623B29EF500630584 /* shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 30A6F62523B29EF500630584 /* shaders.metal */; };
|
||||
30A6F62823B29F8200630584 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30A6F62723B29F8200630584 /* Metal.framework */; };
|
||||
30CF849527AEF5AF002B37A9 /* S9xCheatsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CF849327AEF5AF002B37A9 /* S9xCheatsViewController.m */; };
|
||||
30CF849627AEF5B0002B37A9 /* S9xCheatsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 30CF849427AEF5AF002B37A9 /* S9xCheatsViewController.xib */; };
|
||||
30CF849727AEFD4F002B37A9 /* mac-cheat.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67304AC7FCE00A80003 /* mac-cheat.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
30CF849C27AF0C61002B37A9 /* S9xCheatEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30CF849A27AF0C61002B37A9 /* S9xCheatEditViewController.m */; };
|
||||
30CF849D27AF0C61002B37A9 /* S9xCheatEditViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 30CF849B27AF0C61002B37A9 /* S9xCheatEditViewController.xib */; };
|
||||
30D15CF322CE6B5A005BC352 /* snes9x_framework.h in Headers */ = {isa = PBXBuildFile; fileRef = 30D15CF122CE6B5A005BC352 /* snes9x_framework.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
30D15CFC22CE6B74005BC352 /* sha256.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85FEF90A20DDB18D00C038E9 /* sha256.cpp */; };
|
||||
30D15CFE22CE6B74005BC352 /* bml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 85FEF90620DDB15B00C038E9 /* bml.cpp */; };
|
||||
|
@ -328,6 +333,12 @@
|
|||
30AD1D2122FBB2EA000EE989 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Snes9x.xib; sourceTree = "<group>"; };
|
||||
30C49EF6250C0F2B007D04F8 /* Snes9xDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Snes9xDebug.entitlements; sourceTree = "<group>"; };
|
||||
30CCAD422290472E00549AED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = /Users/buckley/Projects/snes9x/macosx/Info.plist; sourceTree = "<absolute>"; };
|
||||
30CF849227AEF5AF002B37A9 /* S9xCheatsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xCheatsViewController.h; sourceTree = "<group>"; };
|
||||
30CF849327AEF5AF002B37A9 /* S9xCheatsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xCheatsViewController.m; sourceTree = "<group>"; };
|
||||
30CF849427AEF5AF002B37A9 /* S9xCheatsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = S9xCheatsViewController.xib; sourceTree = "<group>"; };
|
||||
30CF849927AF0C61002B37A9 /* S9xCheatEditViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xCheatEditViewController.h; sourceTree = "<group>"; };
|
||||
30CF849A27AF0C61002B37A9 /* S9xCheatEditViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xCheatEditViewController.m; sourceTree = "<group>"; };
|
||||
30CF849B27AF0C61002B37A9 /* S9xCheatEditViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = S9xCheatEditViewController.xib; sourceTree = "<group>"; };
|
||||
30D15CEF22CE6B5A005BC352 /* snes9x_framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = snes9x_framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
30D15CF122CE6B5A005BC352 /* snes9x_framework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = snes9x_framework.h; sourceTree = "<group>"; };
|
||||
30D15CF222CE6B5A005BC352 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -669,6 +680,7 @@
|
|||
30714716230E379500917F82 /* Snes9x */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
30CF849827AF0C3E002B37A9 /* Cheats */,
|
||||
600546BE250F8F1700EC0977 /* S9xPreferences */,
|
||||
30C49EF6250C0F2B007D04F8 /* Snes9xDebug.entitlements */,
|
||||
30714717230E379500917F82 /* AppDelegate.h */,
|
||||
|
@ -696,6 +708,19 @@
|
|||
path = ReClassicfication;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
30CF849827AF0C3E002B37A9 /* Cheats */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
30CF849227AEF5AF002B37A9 /* S9xCheatsViewController.h */,
|
||||
30CF849327AEF5AF002B37A9 /* S9xCheatsViewController.m */,
|
||||
30CF849427AEF5AF002B37A9 /* S9xCheatsViewController.xib */,
|
||||
30CF849927AF0C61002B37A9 /* S9xCheatEditViewController.h */,
|
||||
30CF849A27AF0C61002B37A9 /* S9xCheatEditViewController.m */,
|
||||
30CF849B27AF0C61002B37A9 /* S9xCheatEditViewController.xib */,
|
||||
);
|
||||
path = Cheats;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
30D15CF022CE6B5A005BC352 /* snes9x framework */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1118,6 +1143,7 @@
|
|||
30D15DD522CE6BC9005BC352 /* 7z.h in Headers */,
|
||||
30D15DD622CE6BC9005BC352 /* aribitcd.h in Headers */,
|
||||
30D15DD722CE6BC9005BC352 /* ariconst.h in Headers */,
|
||||
30CF849727AEFD4F002B37A9 /* mac-cheat.h in Headers */,
|
||||
30D15DD822CE6BC9005BC352 /* ariprice.h in Headers */,
|
||||
30D15DD922CE6BC9005BC352 /* btreecd.h in Headers */,
|
||||
30D15DDA22CE6BC9005BC352 /* crc32.h in Headers */,
|
||||
|
@ -1239,9 +1265,11 @@
|
|||
30D709B5236F731B00AAB7C3 /* folder_SRAMs.icns in Resources */,
|
||||
30D709B2236F731B00AAB7C3 /* CART.icns in Resources */,
|
||||
30D709B7236F731B00AAB7C3 /* musicbox_ledon.icns in Resources */,
|
||||
30CF849D27AF0C61002B37A9 /* S9xCheatEditViewController.xib in Resources */,
|
||||
30D709B6236F731B00AAB7C3 /* folder_Freezes.icns in Resources */,
|
||||
30D709C2236F7E3200AAB7C3 /* S9xPreferencesWindowController.xib in Resources */,
|
||||
306937E32636352100007ABB /* S9xEmulationPreferencesViewController.xib in Resources */,
|
||||
30CF849627AEF5B0002B37A9 /* S9xCheatsViewController.xib in Resources */,
|
||||
3071471E230E379600917F82 /* MainMenu.xib in Resources */,
|
||||
306937DD26362B2400007ABB /* S9xSoundPreferencesViewController.xib in Resources */,
|
||||
);
|
||||
|
@ -1270,12 +1298,14 @@
|
|||
309C54802627F3060055DD95 /* S9xControlsPreferencesViewController.m in Sources */,
|
||||
30D709C5236F90DF00AAB7C3 /* S9xButtonConfigTextField.m in Sources */,
|
||||
306937E82636365100007ABB /* S9xFilesPreferencesViewController.m in Sources */,
|
||||
30CF849C27AF0C61002B37A9 /* S9xCheatEditViewController.m in Sources */,
|
||||
306937D02636253900007ABB /* S9xPreferencesTabViewController.m in Sources */,
|
||||
30714721230E379600917F82 /* main.m in Sources */,
|
||||
306937CA2635EE5800007ABB /* S9xDisplayPreferencesViewController.m in Sources */,
|
||||
30714719230E379500917F82 /* AppDelegate.m in Sources */,
|
||||
306937DC26362B2400007ABB /* S9xSoundPreferencesViewController.m in Sources */,
|
||||
3082C42A2379199F0081CA7C /* S9xApplication.m in Sources */,
|
||||
30CF849527AEF5AF002B37A9 /* S9xCheatsViewController.m in Sources */,
|
||||
30D709C1236F7E3200AAB7C3 /* S9xPreferencesWindowController.m in Sources */,
|
||||
304B366C262E82B800F8DC8E /* S9xPreferencesConstants.m in Sources */,
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue