2 // **********************************************************************
3 // The Cheat - A universal game cheater for Mac OS X
4 // (C) 2003-2005 Chaz McGarvey (BrokenZipper)
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 1, or (at your option)
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #import "CheatDocument.h"
25 @implementation CheatDocument ( DocCheaterDelegate
)
28 - (void)cheaterDidConnect
:(Cheater
*)cheater
30 ChazLog( @
"cheaterDidConnect:" );
31 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
32 // update the interface
33 [self updateInterface
];
36 - (void)cheaterDidDisconnect
:(Cheater
*)cheater
38 ChazLog( @
"cheaterDidDisonnect:" );
39 [self disconnectFromCheater
];
41 [self showError
:@
"Disconnected by server."];
42 [ibStatusBar setIndeterminate
:NO
];
43 [ibStatusBar setDoubleValue
:0.0];
44 [ibStatusBar stopAnimation
:self];
45 // update the interface
46 [self updateInterface
];
50 - (void)cheaterRequiresAuthentication
:(Cheater
*)cheater
52 ChazLog( @
"cheaterRequiresAuthentication:" );
54 [self ibRunPasswordSheet
:nil];
57 - (void)cheaterRejectedPassword
:(Cheater
*)cheater
59 ChazLog( @
"cheaterRejectedPassword" );
64 - (void)cheaterAcceptedPassword
:(Cheater
*)cheater
66 ChazLog( @
"cheaterAcceptedPassword" );
68 [ibStatusText setTemporaryStatus
:@
"Password Accepted"];
72 - (void)cheater
:(Cheater
*)cheater didFindProcesses
:(NSArray
*)processes
79 Process
*selectThis
= nil;
81 ChazLog( @
"cheater:didFindProcesses:" );
83 // create and set the server popup menu
84 processMenu
= [[NSMenu alloc
] init
];
85 [processMenu setAutoenablesItems
:YES
];
89 len
= [processes count
];
90 for ( i
= 0; i
< len
; i
++ ) {
91 Process
*item
= [processes objectAtIndex
:i
];
93 menuItem
= [[NSMenuItem alloc
] init
];
94 [menuItem setTarget
:self];
95 [menuItem setAction
:@selector(ibSetProcess
:)];
96 [menuItem setTitle
:[item name
]];
97 [menuItem setImage
:[item icon
]];
98 [menuItem setRepresentedObject
:item
];
99 [processMenu addItem
:menuItem
];
102 // check and see if our document uses this application
103 if ( [self isLoadedFromFile
] && [[_cheatData process
] sameApplicationAs
:item
] ) {
108 [ibProcessPopup setMenu
:processMenu
];
109 [processMenu release
];
111 // if we're loaded from a file, select the process matching
112 // the one saved, if it is launched.
114 [_cheater setTarget
:selectThis
];
116 // otherwise, select the global target
117 else if ( selectThis
= [CheatDocument globalTarget
] ) {
118 ChazLog( @
"setting global target" );
119 [_cheater setTarget
:selectThis
];
121 // otherwise, select the first process in this list
122 else if ( len
> 0 ) {
123 [_cheater setTarget
:[processes objectAtIndex
:0]];
127 - (void)cheater
:(Cheater
*)cheater didAddProcess
:(Process
*)process
129 NSMenu
*processMenu
= [ibProcessPopup menu
];
130 NSMenuItem
*menuItem
;
132 Process
*savedTarget
= [_cheatData process
];
134 // add the newly found process to the process popup
135 menuItem
= [[NSMenuItem alloc
] init
];
136 [menuItem setTarget
:self];
137 [menuItem setAction
:@selector(ibSetProcess
:)];
138 [menuItem setTitle
:[process name
]];
139 [menuItem setImage
:[process icon
]];
140 [menuItem setRepresentedObject
:process
];
141 [processMenu addItem
:menuItem
];
144 // make this the target if appropiate
145 if ( _status
== TCIdleStatus
&&
146 ![_searchData hasSearchedOnce
] &&
147 [savedTarget sameApplicationAs
:process
] &&
148 ![savedTarget sameApplicationAs
:_process
] ) {
149 [_cheater setTarget
:process
];
153 - (void)cheater
:(Cheater
*)cheater didRemoveProcess
:(Process
*)process
155 NSMenu
*processes
= [ibProcessPopup menu
];
156 // remove the service from the menu
157 [processes removeItemWithRepresentedObject
:process
];
159 // if this is the current process, select the first one
160 if ( [_process isEqual
:process
] ) {
164 if ( [processes numberOfItems
] > 0 ) {
165 [_cheater setTarget
:[[processes itemAtIndex
:0] representedObject
]];
171 - (void)cheater
:(Cheater
*)cheater didSetTarget
:(Process
*)target
173 ChazLog( @
"cheater:setTarget:" );
175 // save a reference to the process
177 _process
= [target retain
];
179 [CheatDocument setGlobalTarget
:_process
];
181 // make sure the correct item is selected
182 [ibProcessPopup selectItemAtIndex
:[ibProcessPopup indexOfItemWithRepresentedObject
:target
]];
183 //[ibProcessPopup selectItemWithTitle:[target name]];
185 // apply the name and version to the document if the doc isn't saved
186 if ( ![self isLoadedFromFile
] ) {
187 [_cheatData setProcess
:target
];
190 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Target is %@.", [target name
]] duration
:2.0];
191 [self updateInterface
];
194 - (void)cheaterPausedTarget
:(Cheater
*)cheater
196 _isTargetPaused
= YES
;
197 [ibStatusText setTemporaryStatus
:@
"Target Paused"];
200 - (void)cheaterResumedTarget
:(Cheater
*)cheater
202 _isTargetPaused
= NO
;
203 [ibStatusText setTemporaryStatus
:@
"Target Resumed"];
207 - (void)cheater
:(Cheater
*)cheater didFindVariables
:(TCArray
)variables actualAmount
:(unsigned)count
209 if ( _status
== TCSearchingStatus
) {
210 _status
= TCIdleStatus
;
212 // do something with the variables
213 [_searchData setAddresses
:variables
];
214 [_searchData didAddResults
];
215 [ibSearchVariableTable reloadData
];
217 [self setActualResults
:count
];
219 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
221 NSColor
*green
= [NSColor colorWithCalibratedRed
:0.0 green
:0.7 blue
:0.0 alpha
:1.0];
222 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found one result.", count
] color
:green duration
:6.0];
224 else if ( count
== 0 ) {
225 NSColor
*red
= [NSColor colorWithCalibratedRed
:0.7 green
:0.0 blue
:0.0 alpha
:1.0];
226 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found no results.", count
] color
:red duration
:6.0];
229 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found %i results.", count
] duration
:6.0];
231 [ibStatusBar setIndeterminate
:NO
];
232 [ibStatusBar setDoubleValue
:0.0];
233 [ibStatusBar stopAnimation
:self];
235 [self updateInterface
];
236 if ( _mode
== TCSearchMode
) {
237 [ibWindow makeFirstResponder
:ibSearchValueField
];
242 - (void)cheater
:(Cheater
*)cheater didFindValues
:(TCArray
)values
244 [_searchData setValues
:values
];
245 [ibSearchVariableTable reloadData
];
247 [self watchVariables
];
250 - (void)cheaterDidCancelSearch
:(Cheater
*)cheater
252 ChazLog( @
"cheaterDidCancelSearch:" );
254 if ( _isCancelingTask
) {
255 _status
= TCIdleStatus
;
256 _isCancelingTask
= NO
;
258 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
259 [ibStatusText setTemporaryStatus
:@
"Search cancelled." duration
:2.0];
260 [ibStatusBar setIndeterminate
:NO
];
261 [ibStatusBar setDoubleValue
:0.0];
262 [ibStatusBar stopAnimation
:self];
264 [self updateInterface
];
265 if ( _mode
== TCSearchMode
) {
266 [ibWindow makeFirstResponder
:ibSearchValueField
];
271 - (void)cheaterDidClearSearch
:(Cheater
*)cheater
273 [_searchData clearResults
];
274 [ibSearchVariableTable reloadData
];
276 [self setActualResults
:0];
278 [ibStatusText setTemporaryStatus
:@
"The search was cleared." duration
:2.0];
279 [self updateInterface
];
283 - (void)cheater
:(Cheater
*)cheater didDumpMemory
:(NSData
*)memoryDump
287 ChazLog( @
"cheater:didDumpMemory:" );
289 ChazLog( @
"status: %i", _status
);
290 if ( _status
== TCDumpingStatus
) {
291 _status
= TCIdleStatus
;
293 panel
= [NSSavePanel savePanel
];
294 [panel setRequiredFileType
:@
"dump"];
295 [panel setExtensionHidden
:NO
];
296 [panel setCanSelectHiddenExtension
:YES
];
297 if ( MacOSXVersion() >= 0x1030 ) {
298 [panel setMessage
:@
"Dump files are huge! Exercise patience while saving."];
301 [panel beginSheetForDirectory
:nil
302 file
:[NSString stringWithFormat
:[NSString stringWithFormat
:@
"%@.dump", [_process name
]]]
303 modalForWindow
:ibWindow
305 didEndSelector
:@selector(saveMemoryDumpDidEnd
:returnCode
:contextInfo
:)
306 contextInfo
:memoryDump
];
311 - (void)saveMemoryDumpDidEnd
:(NSSavePanel
*)sheet returnCode
:(int)returnCode contextInfo
:(void *)contextInfo
313 NSData
*dump
= (NSData
*)contextInfo
;
315 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
317 if ( returnCode
== NSOKButton
) {
319 [dump writeToFile
:[sheet filename
] atomically
:YES
];
321 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Successfully dumped %@'s memory.", [_process name
]]];
324 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
329 [ibStatusBar stopAnimation
:self];
330 [ibStatusBar setIndeterminate
:NO
];
332 [self updateInterface
];
333 if ( _mode
== TCSearchMode
) {
334 [ibWindow makeFirstResponder
:ibSearchValueField
];
338 - (void)cheaterDidCancelMemoryDump
:(Cheater
*)cheater
340 ChazLog( @
"cheaterDidCancelMemoryDump:" );
342 if ( _isCancelingTask
) {
343 _status
= TCIdleStatus
;
344 _isCancelingTask
= NO
;
346 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
347 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
348 [ibStatusBar stopAnimation
:self];
349 [ibStatusBar setIndeterminate
:NO
];
351 [self updateInterface
];
352 if ( _mode
== TCSearchMode
) {
353 [ibWindow makeFirstResponder
:ibSearchValueField
];
359 - (void)cheater
:(Cheater
*)cheater didChangeVariables
:(unsigned)changeCount
361 ChazLog( @
"CHEATER changed %u variables.", changeCount
);
362 if ( ![_cheatData repeats
] ) {
363 _status
= TCIdleStatus
;
366 if ( changeCount
== 0 ) {
367 [ibStatusText setTemporaryStatus
:@
"No variables were changed." duration
:2.0];
369 else if ( changeCount
== 1 ) {
370 [ibStatusText setTemporaryStatus
:@
"Changed one variable." duration
:2.0];
373 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Changed %i variables.", changeCount
] duration
:2.0];
376 [self updateInterface
];
379 - (void)cheaterDidStopChangingVariables
:(Cheater
*)cheater
381 _status
= TCIdleStatus
;
382 _isCancelingTask
= NO
;
384 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
385 [ibStatusBar stopAnimation
:self];
386 [ibStatusBar setIndeterminate
:NO
];
388 [self updateInterface
];
389 if ( _mode
== TCSearchMode
) {
390 [ibWindow makeFirstResponder
:ibSearchValueField
];
395 - (void)cheater
:(Cheater
*)cheater didReportProgress
:(int)progress
397 if ( _status
== TCSearchingStatus
&& !_isCancelingTask
) {
398 [ibStatusBar setDoubleValue
:(double)progress
];
403 - (void)cheater
:(Cheater
*)cheater didRevertToVariables
:(TCArray
)variables actualAmount
:(unsigned)count
405 // do something with the variables
406 [_searchData setAddresses
:variables
];
407 [ibSearchVariableTable reloadData
];
409 [self setActualResults
:count
];
411 [self updateInterface
];
415 - (void)cheaterDidUndo
:(Cheater
*)cheater
417 [_searchData didUndo
];
419 [ibStatusText setTemporaryStatus
:@
"Reverted to previous results." duration
:2.0];
422 - (void)cheaterDidRedo
:(Cheater
*)cheater
424 [_searchData didRedo
];
426 [ibStatusText setTemporaryStatus
:@
"Reverted to saved results." duration
:2.0];
430 - (void)cheater
:(Cheater
*)cheater variableAtIndex
:(unsigned)index didChangeTo
:(Variable
*)variable
432 [_searchData setValue
:variable atIndex
:index
];
433 [ibSearchVariableTable reloadData
];
437 - (void)cheater
:(Cheater
*)cheater didFailLastRequest
:(NSString
*)reason
439 _status
= TCIdleStatus
;
441 // echo the reason to the status
442 [self showError
:reason
];
443 [ibStatusBar setIndeterminate
:NO
];
444 [ibStatusBar setDoubleValue
:0.0];
445 [ibStatusBar stopAnimation
:self];
447 [self updateInterface
];
450 - (void)cheater
:(Cheater
*)cheater echo
:(NSString
*)message
452 // echo the message to the status
453 [ibStatusText setTemporaryStatus
:message duration
:7.0];