3 * The Cheat - The legendary universal game trainer for Mac OS X.
4 * http://www.brokenzipper.com/trac/wiki/TheCheat
6 * Copyright (c) 2003-2011, Charles McGarvey et al.
8 * Distributable under the terms and conditions of the 2-clause BSD
9 * license; see the file COPYING for the legal text of the license.
13 #import "CheatDocument.h"
16 @implementation CheatDocument ( DocCheaterDelegate
)
19 - (void)cheaterDidConnect
:(Cheater
*)cheater
21 ChazLog( @
"cheaterDidConnect:" );
22 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
23 // update the interface
24 [self updateInterface
];
27 - (void)cheaterDidDisconnect
:(Cheater
*)cheater
29 ChazLog( @
"cheaterDidDisonnect:" );
30 [self disconnectFromCheater
];
32 [self showError
:@
"Disconnected by server."];
33 [ibStatusBar setIndeterminate
:NO
];
34 [ibStatusBar setDoubleValue
:0.0];
35 [ibStatusBar stopAnimation
:self];
36 // update the interface
37 [self updateInterface
];
41 - (void)cheaterRequiresAuthentication
:(Cheater
*)cheater
43 ChazLog( @
"cheaterRequiresAuthentication:" );
45 [self ibRunPasswordSheet
:nil];
48 - (void)cheaterRejectedPassword
:(Cheater
*)cheater
50 ChazLog( @
"cheaterRejectedPassword" );
55 - (void)cheaterAcceptedPassword
:(Cheater
*)cheater
57 ChazLog( @
"cheaterAcceptedPassword" );
59 [ibStatusText setTemporaryStatus
:@
"Password Accepted"];
63 - (void)cheater
:(Cheater
*)cheater didFindProcesses
:(NSArray
*)processes
70 Process
*selectThis
= nil;
72 ChazLog( @
"cheater:didFindProcesses:" );
74 // create and set the server popup menu
75 processMenu
= [[NSMenu alloc
] init
];
76 [processMenu setAutoenablesItems
:YES
];
80 len
= [processes count
];
81 for ( i
= 0; i
< len
; i
++ ) {
82 Process
*item
= [processes objectAtIndex
:i
];
84 menuItem
= [[NSMenuItem alloc
] init
];
85 [menuItem setTarget
:self];
86 [menuItem setAction
:@selector(ibSetProcess
:)];
87 [menuItem setTitle
:[item name
]];
88 [menuItem setImage
:[item icon
]];
89 [menuItem setRepresentedObject
:item
];
90 [processMenu addItem
:menuItem
];
93 // check and see if our document uses this application
94 if ( [self isLoadedFromFile
] && [[_cheatData process
] sameApplicationAs
:item
] ) {
99 [ibProcessPopup setMenu
:processMenu
];
100 [processMenu release
];
102 // if we're loaded from a file, select the process matching
103 // the one saved, if it is launched.
105 [_cheater setTarget
:selectThis
];
107 // otherwise, select the global target
108 else if ( selectThis
= [CheatDocument globalTarget
] ) {
109 ChazLog( @
"setting global target" );
110 [_cheater setTarget
:selectThis
];
112 // otherwise, select the first process in this list
113 else if ( len
> 0 ) {
114 [_cheater setTarget
:[processes objectAtIndex
:0]];
118 - (void)cheater
:(Cheater
*)cheater didAddProcess
:(Process
*)process
120 NSMenu
*processMenu
= [ibProcessPopup menu
];
121 NSMenuItem
*menuItem
;
123 Process
*savedTarget
= [_cheatData process
];
125 // add the newly found process to the process popup
126 menuItem
= [[NSMenuItem alloc
] init
];
127 [menuItem setTarget
:self];
128 [menuItem setAction
:@selector(ibSetProcess
:)];
129 [menuItem setTitle
:[process name
]];
130 [menuItem setImage
:[process icon
]];
131 [menuItem setRepresentedObject
:process
];
132 [processMenu addItem
:menuItem
];
135 // make this the target if appropiate
136 if ( _status
== TCIdleStatus
&&
137 ![_searchData hasSearchedOnce
] &&
138 [savedTarget sameApplicationAs
:process
] &&
139 ![savedTarget sameApplicationAs
:_process
] ) {
140 [_cheater setTarget
:process
];
144 - (void)cheater
:(Cheater
*)cheater didRemoveProcess
:(Process
*)process
146 NSMenu
*processes
= [ibProcessPopup menu
];
147 // remove the service from the menu
148 [processes removeItemWithRepresentedObject
:process
];
150 // if this is the current process, select the first one
151 if ( [_process isEqual
:process
] ) {
155 if ( [processes numberOfItems
] > 0 ) {
156 [_cheater setTarget
:[[processes itemAtIndex
:0] representedObject
]];
162 - (void)cheater
:(Cheater
*)cheater didSetTarget
:(Process
*)target
164 ChazLog( @
"cheater:setTarget:" );
166 // save a reference to the process
168 _process
= [target retain
];
170 [CheatDocument setGlobalTarget
:_process
];
172 // make sure the correct item is selected
173 [ibProcessPopup selectItemAtIndex
:[ibProcessPopup indexOfItemWithRepresentedObject
:target
]];
174 //[ibProcessPopup selectItemWithTitle:[target name]];
176 // apply the name and version to the document if the doc isn't saved
177 if ( ![self isLoadedFromFile
] ) {
178 [_cheatData setProcess
:target
];
181 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Target is %@.", [target name
]] duration
:2.0];
182 [self updateInterface
];
185 - (void)cheaterPausedTarget
:(Cheater
*)cheater
187 _isTargetPaused
= YES
;
188 [ibStatusText setTemporaryStatus
:@
"Target Paused"];
191 - (void)cheaterResumedTarget
:(Cheater
*)cheater
193 _isTargetPaused
= NO
;
194 [ibStatusText setTemporaryStatus
:@
"Target Resumed"];
198 - (void)cheater
:(Cheater
*)cheater didFindVariables
:(TCArray
)variables actualAmount
:(unsigned)count
200 if ( _status
== TCSearchingStatus
) {
201 _status
= TCIdleStatus
;
203 // do something with the variables
204 [_searchData setAddresses
:variables
];
205 [_searchData didAddResults
];
206 [ibSearchVariableTable reloadData
];
208 [self setActualResults
:count
];
210 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
212 NSColor
*green
= [NSColor colorWithCalibratedRed
:0.0 green
:0.7 blue
:0.0 alpha
:1.0];
213 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found one result.", count
] color
:green duration
:6.0];
215 else if ( count
== 0 ) {
216 NSColor
*red
= [NSColor colorWithCalibratedRed
:0.7 green
:0.0 blue
:0.0 alpha
:1.0];
217 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found no results.", count
] color
:red duration
:6.0];
220 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found %i results.", count
] duration
:6.0];
222 [ibStatusBar setIndeterminate
:NO
];
223 [ibStatusBar setDoubleValue
:0.0];
224 [ibStatusBar stopAnimation
:self];
226 [self updateInterface
];
227 if ( _mode
== TCSearchMode
) {
228 [ibWindow makeFirstResponder
:ibSearchValueField
];
233 - (void)cheater
:(Cheater
*)cheater didFindValues
:(TCArray
)values
235 [_searchData setValues
:values
];
236 [ibSearchVariableTable reloadData
];
238 [self watchVariables
];
241 - (void)cheaterDidCancelSearch
:(Cheater
*)cheater
243 ChazLog( @
"cheaterDidCancelSearch:" );
245 if ( _isCancelingTask
) {
246 _status
= TCIdleStatus
;
247 _isCancelingTask
= NO
;
249 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
250 [ibStatusText setTemporaryStatus
:@
"Search cancelled." duration
:2.0];
251 [ibStatusBar setIndeterminate
:NO
];
252 [ibStatusBar setDoubleValue
:0.0];
253 [ibStatusBar stopAnimation
:self];
255 [self updateInterface
];
256 if ( _mode
== TCSearchMode
) {
257 [ibWindow makeFirstResponder
:ibSearchValueField
];
262 - (void)cheaterDidClearSearch
:(Cheater
*)cheater
264 [_searchData clearResults
];
265 [ibSearchVariableTable reloadData
];
267 [self setActualResults
:0];
269 [ibStatusText setTemporaryStatus
:@
"The search was cleared." duration
:2.0];
270 [self updateInterface
];
274 - (void)cheater
:(Cheater
*)cheater didDumpMemory
:(NSData
*)memoryDump
278 ChazLog( @
"cheater:didDumpMemory:" );
280 ChazLog( @
"status: %i", _status
);
281 if ( _status
== TCDumpingStatus
) {
282 _status
= TCIdleStatus
;
284 panel
= [NSSavePanel savePanel
];
285 [panel setRequiredFileType
:@
"dump"];
286 [panel setExtensionHidden
:NO
];
287 [panel setCanSelectHiddenExtension
:YES
];
288 if ( MacOSXVersion() >= 0x1030 ) {
289 [panel setMessage
:@
"Dump files are huge! Exercise patience while saving."];
292 [panel beginSheetForDirectory
:nil
293 file
:[NSString stringWithFormat
:[NSString stringWithFormat
:@
"%@.dump", [_process name
]]]
294 modalForWindow
:ibWindow
296 didEndSelector
:@selector(saveMemoryDumpDidEnd
:returnCode
:contextInfo
:)
297 contextInfo
:memoryDump
];
302 - (void)saveMemoryDumpDidEnd
:(NSSavePanel
*)sheet returnCode
:(int)returnCode contextInfo
:(void *)contextInfo
304 NSData
*dump
= (NSData
*)contextInfo
;
306 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
308 if ( returnCode
== NSOKButton
) {
310 [dump writeToFile
:[sheet filename
] atomically
:YES
];
312 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Successfully dumped %@'s memory.", [_process name
]]];
315 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
320 [ibStatusBar stopAnimation
:self];
321 [ibStatusBar setIndeterminate
:NO
];
323 [self updateInterface
];
324 if ( _mode
== TCSearchMode
) {
325 [ibWindow makeFirstResponder
:ibSearchValueField
];
329 - (void)cheaterDidCancelMemoryDump
:(Cheater
*)cheater
331 ChazLog( @
"cheaterDidCancelMemoryDump:" );
333 if ( _isCancelingTask
) {
334 _status
= TCIdleStatus
;
335 _isCancelingTask
= NO
;
337 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
338 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
339 [ibStatusBar stopAnimation
:self];
340 [ibStatusBar setIndeterminate
:NO
];
342 [self updateInterface
];
343 if ( _mode
== TCSearchMode
) {
344 [ibWindow makeFirstResponder
:ibSearchValueField
];
350 - (void)cheater
:(Cheater
*)cheater didChangeVariables
:(unsigned)changeCount
352 ChazLog( @
"CHEATER changed %u variables.", changeCount
);
353 if ( ![_cheatData repeats
] ) {
354 _status
= TCIdleStatus
;
357 if ( changeCount
== 0 ) {
358 [ibStatusText setTemporaryStatus
:@
"No variables were changed." duration
:2.0];
360 else if ( changeCount
== 1 ) {
361 [ibStatusText setTemporaryStatus
:@
"Changed one variable." duration
:2.0];
364 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Changed %i variables.", changeCount
] duration
:2.0];
367 [self updateInterface
];
370 - (void)cheaterDidStopChangingVariables
:(Cheater
*)cheater
372 _status
= TCIdleStatus
;
373 _isCancelingTask
= NO
;
375 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
376 [ibStatusBar stopAnimation
:self];
377 [ibStatusBar setIndeterminate
:NO
];
379 [self updateInterface
];
380 if ( _mode
== TCSearchMode
) {
381 [ibWindow makeFirstResponder
:ibSearchValueField
];
386 - (void)cheater
:(Cheater
*)cheater didReportProgress
:(int)progress
388 if ( _status
== TCSearchingStatus
&& !_isCancelingTask
) {
389 [ibStatusBar setDoubleValue
:(double)progress
];
394 - (void)cheater
:(Cheater
*)cheater didRevertToVariables
:(TCArray
)variables actualAmount
:(unsigned)count
396 // do something with the variables
397 [_searchData setAddresses
:variables
];
398 [ibSearchVariableTable reloadData
];
400 [self setActualResults
:count
];
402 [self updateInterface
];
406 - (void)cheaterDidUndo
:(Cheater
*)cheater
408 [_searchData didUndo
];
410 [ibStatusText setTemporaryStatus
:@
"Reverted to previous results." duration
:2.0];
413 - (void)cheaterDidRedo
:(Cheater
*)cheater
415 [_searchData didRedo
];
417 [ibStatusText setTemporaryStatus
:@
"Reverted to saved results." duration
:2.0];
421 - (void)cheater
:(Cheater
*)cheater variableAtIndex
:(unsigned)index didChangeTo
:(Variable
*)variable
423 [_searchData setValue
:variable atIndex
:index
];
424 [ibSearchVariableTable reloadData
];
428 - (void)cheater
:(Cheater
*)cheater didFailLastRequest
:(NSString
*)reason
430 _status
= TCIdleStatus
;
432 // echo the reason to the status
433 [self showError
:reason
];
434 [ibStatusBar setIndeterminate
:NO
];
435 [ibStatusBar setDoubleValue
:0.0];
436 [ibStatusBar stopAnimation
:self];
438 [self updateInterface
];
441 - (void)cheater
:(Cheater
*)cheater echo
:(NSString
*)message
443 // echo the message to the status
444 [ibStatusText setTemporaryStatus
:message duration
:7.0];