SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
Cocoa/GBCheatWindowController.m
1 #import "GBCheatWindowController.h"
2 #import "GBWarningPopover.h"
3 #import "GBCheatTextFieldCell.h"
4
5 @implementation GBCheatWindowController
6
7 + (NSString *)addressStringFromCheat:(const GB_cheat_t *)cheat
8 {
9 if (cheat->bank != GB_CHEAT_ANY_BANK) {
10 return [NSString stringWithFormat:@"$%x:$%04x", cheat->bank, cheat->address];
11 }
12 return [NSString stringWithFormat:@"$%04x", cheat->address];
13 }
14
15 + (NSString *)actionDescriptionForCheat:(const GB_cheat_t *)cheat
16 {
17 if (cheat->use_old_value) {
18 return [NSString stringWithFormat:@"[%@]($%02x) = $%02x", [self addressStringFromCheat:cheat], cheat->old_value, cheat->value];
19 }
20 return [NSString stringWithFormat:@"[%@] = $%02x", [self addressStringFromCheat:cheat], cheat->value];
21 }
22
23 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
24 {
25 GB_gameboy_t *gb = self.document.gameboy;
26 if (!gb) return 0;
27 size_t cheatCount;
28 GB_get_cheats(gb, &cheatCount);
29 return cheatCount + 1;
30 }
31
32 - (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
33 {
34 GB_gameboy_t *gb = self.document.gameboy;
35 if (!gb) return nil;
36 size_t cheatCount;
37 GB_get_cheats(gb, &cheatCount);
38 NSUInteger columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
39 if (row >= cheatCount && columnIndex == 0) {
40 return [[NSCell alloc] init];
41 }
42 return nil;
43 }
44
45 - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
46 {
47 size_t cheatCount;
48 GB_gameboy_t *gb = self.document.gameboy;
49 if (!gb) return nil;
50 const GB_cheat_t *const *cheats = GB_get_cheats(gb, &cheatCount);
51 NSUInteger columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
52 if (row >= cheatCount) {
53 switch (columnIndex) {
54 case 0:
55 return @YES;
56
57 case 1:
58 return @NO;
59
60 case 2:
61 return @"Add Cheat…";
62
63 case 3:
64 return @"";
65 }
66 }
67
68 switch (columnIndex) {
69 case 0:
70 return @NO;
71
72 case 1:
73 return @(cheats[row]->enabled);
74
75 case 2:
76 return @(cheats[row]->description);
77
78 case 3:
79 return [GBCheatWindowController actionDescriptionForCheat:cheats[row]];
80 }
81
82 return nil;
83 }
84
85 - (IBAction)importCheat:(id)sender
86 {
87 GB_gameboy_t *gb = self.document.gameboy;
88 if (!gb) return;
89
90 [self.document performAtomicBlock:^{
91 if (GB_import_cheat(gb,
92 self.importCodeField.stringValue.UTF8String,
93 self.importDescriptionField.stringValue.UTF8String,
94 true)) {
95 dispatch_async(dispatch_get_main_queue(), ^{
96 self.importCodeField.stringValue = @"";
97 self.importDescriptionField.stringValue = @"";
98 [self.cheatsTable reloadData];
99 [self tableViewSelectionDidChange:nil];
100 });
101 }
102 else {
103 dispatch_async(dispatch_get_main_queue(), ^{
104 NSBeep();
105 [GBWarningPopover popoverWithContents:@"This code is not a valid GameShark or Game Genie code" onView:self.importCodeField];
106 });
107 }
108 }];
109 }
110
111 - (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
112 {
113 GB_gameboy_t *gb = self.document.gameboy;
114 if (!gb) return;
115 size_t cheatCount;
116 const GB_cheat_t *const *cheats = GB_get_cheats(gb, &cheatCount);
117 NSUInteger columnIndex = [[tableView tableColumns] indexOfObject:tableColumn];
118 [self.document performAtomicBlock:^{
119 if (columnIndex == 1) {
120 if (row >= cheatCount) {
121 GB_add_cheat(gb, "New Cheat", 0, 0, 0, 0, false, true);
122 }
123 else {
124 GB_update_cheat(gb, cheats[row], cheats[row]->description, cheats[row]->address, cheats[row]->bank, cheats[row]->value, cheats[row]->old_value, cheats[row]->use_old_value, !cheats[row]->enabled);
125 }
126 }
127 else if (row < cheatCount) {
128 GB_remove_cheat(gb, cheats[row]);
129 }
130 }];
131 [self.cheatsTable reloadData];
132 [self tableViewSelectionDidChange:nil];
133 }
134
135 - (void)tableViewSelectionDidChange:(NSNotification *)notification
136 {
137 GB_gameboy_t *gb = self.document.gameboy;
138 if (!gb) return;
139
140 size_t cheatCount;
141 const GB_cheat_t *const *cheats = GB_get_cheats(gb, &cheatCount);
142 unsigned row = self.cheatsTable.selectedRow;
143 const GB_cheat_t *cheat = NULL;
144 if (row >= cheatCount) {
145 static const GB_cheat_t template = {
146 .address = 0,
147 .bank = 0,
148 .value = 0,
149 .old_value = 0,
150 .use_old_value = false,
151 .enabled = false,
152 .description = "New Cheat",
153 };
154 cheat = &template;
155 }
156 else {
157 cheat = cheats[row];
158 }
159
160 self.addressField.stringValue = [GBCheatWindowController addressStringFromCheat:cheat];
161 self.valueField.stringValue = [NSString stringWithFormat:@"$%02x", cheat->value];
162 self.oldValueField.stringValue = [NSString stringWithFormat:@"$%02x", cheat->old_value];
163 self.oldValueCheckbox.state = cheat->use_old_value;
164 self.descriptionField.stringValue = @(cheat->description);
165 }
166
167 - (void)awakeFromNib
168 {
169 [self tableViewSelectionDidChange:nil];
170 ((GBCheatTextFieldCell *)self.addressField.cell).usesAddressFormat = true;
171 }
172
173 - (void)controlTextDidChange:(NSNotification *)obj
174 {
175 [self updateCheat:nil];
176 }
177
178 - (IBAction)updateCheat:(id)sender
179 {
180 GB_gameboy_t *gb = self.document.gameboy;
181 if (!gb) return;
182
183 uint16_t address = 0;
184 uint16_t bank = GB_CHEAT_ANY_BANK;
185 if ([self.addressField.stringValue rangeOfString:@":"].location != NSNotFound) {
186 sscanf(self.addressField.stringValue.UTF8String, "$%hx:$%hx", &bank, &address);
187 }
188 else {
189 sscanf(self.addressField.stringValue.UTF8String, "$%hx", &address);
190 }
191
192 uint8_t value = 0;
193 if ([self.valueField.stringValue characterAtIndex:0] == '$') {
194 sscanf(self.valueField.stringValue.UTF8String, "$%02hhx", &value);
195 }
196 else {
197 sscanf(self.valueField.stringValue.UTF8String, "%hhd", &value);
198 }
199
200 uint8_t oldValue = 0;
201 if ([self.oldValueField.stringValue characterAtIndex:0] == '$') {
202 sscanf(self.oldValueField.stringValue.UTF8String, "$%02hhx", &oldValue);
203 }
204 else {
205 sscanf(self.oldValueField.stringValue.UTF8String, "%hhd", &oldValue);
206 }
207
208 size_t cheatCount;
209 const GB_cheat_t *const *cheats = GB_get_cheats(gb, &cheatCount);
210 unsigned row = self.cheatsTable.selectedRow;
211
212 [self.document performAtomicBlock:^{
213 if (row >= cheatCount) {
214 GB_add_cheat(gb,
215 self.descriptionField.stringValue.UTF8String,
216 address,
217 bank,
218 value,
219 oldValue,
220 self.oldValueCheckbox.state,
221 false);
222 }
223 else {
224 GB_update_cheat(gb,
225 cheats[row],
226 self.descriptionField.stringValue.UTF8String,
227 address,
228 bank,
229 value,
230 oldValue,
231 self.oldValueCheckbox.state,
232 cheats[row]->enabled);
233 }
234 }];
235 [self.cheatsTable reloadData];
236 }
237
238 - (void)cheatsUpdated
239 {
240 [self.cheatsTable reloadData];
241 [self tableViewSelectionDidChange:nil];
242 }
243
244 @end
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.