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.
14 @interface Variable ( PrivateAPI
)
16 - (void)_setType
:(TCVariableType
)type
;
17 - (void)_setIntegerSign
:(TCIntegerSign
)sign
;
22 @implementation Variable
27 return [self initWithType
:TCInt32 integerSign
:TCSigned
];
30 - (id)initWithType
:(TCVariableType
)type
32 return [self initWithType
:type integerSign
:TCSigned
];
35 - (id)initWithType
:(TCVariableType
)type integerSign
:(TCIntegerSign
)sign
// DESIGNATED
37 if ( self = [super init
] ) {
41 [self _setIntegerSign
:sign
];
46 - (void)setProcess
:(Process
*)newProcess
48 if (process
!= newProcess
&& [newProcess pid
] > 0)
50 _isEmulated
= [newProcess isEmulated
];
77 // #############################################################################
79 // #############################################################################
81 - (id)initWithCoder
:(NSCoder
*)coder
83 if ( self = [super init
] ) {
84 [coder decodeValueOfObjCType
:@encode(TCVariableType
) at
:&_type
];
85 [coder decodeValueOfObjCType
:@encode(TCIntegerSign
) at
:&_integerSign
];
86 [coder decodeValueOfObjCType
:@encode(TCAddress
) at
:&_address
];
88 void *value
= [coder decodeBytesWithReturnedLength
:&_size
];
90 if (_type
== TCString || _type
== TCInt8
)
92 [self setValue
:value
];
94 else if (_type
== TCInt16
)
96 int16_t newVariable
= CFSwapInt16BigToHost(*((int16_t
*)value
));
97 [self setValue
:&newVariable
];
99 else if (_type
== TCInt32
)
101 int32_t newVariable
= CFSwapInt32BigToHost(*((int32_t
*)value
));
102 [self setValue
:&newVariable
];
104 else if (_type
== TCInt64
)
106 int64_t newVariable
= CFSwapInt64BigToHost(*((int64_t
*)value
));
107 [self setValue
:&newVariable
];
109 else if (_type
== TCFloat
)
111 #ifdef __LITTLE_ENDIAN__
112 CFSwappedFloat32 newVariable
= CFConvertFloat32HostToSwapped(*((float *)value
));
113 [self setValue
:&(newVariable.v
)];
116 [self setValue
:value
];
119 else if (_type
== TCDouble
)
121 #ifdef __LITTLE_ENDIAN__
122 CFSwappedFloat64 newVariable
= CFConvertDoubleHostToSwapped(*((double *)value
));
123 [self setValue
:&(newVariable.v
)];
125 [self setValue
:value
];
129 [coder decodeValueOfObjCType
:@encode(BOOL) at
:&_isValueValid
];
130 [coder decodeValueOfObjCType
:@encode(BOOL) at
:&_enabled
];
131 [coder decodeValueOfObjCType
:@encode(int) at
:&_tag
];
136 - (void)encodeWithCoder
:(NSCoder
*)coder
138 [coder encodeValueOfObjCType
:@encode(TCVariableType
) at
:&_type
];
139 [coder encodeValueOfObjCType
:@encode(TCIntegerSign
) at
:&_integerSign
];
140 [coder encodeValueOfObjCType
:@encode(TCAddress
) at
:&_address
];
142 if (_type
== TCString || _type
== TCInt8
)
144 [coder encodeBytes
:_value length
:_size
];
146 else if (_type
== TCInt16
)
148 int16_t newVariable
= CFSwapInt16HostToBig(*((int16_t
*)_value
));
149 [coder encodeBytes
:&newVariable length
:_size
];
151 else if (_type
== TCInt32
)
153 int32_t newVariable
= CFSwapInt32HostToBig(*((int32_t
*)_value
));
154 [coder encodeBytes
:&newVariable length
:_size
];
156 else if (_type
== TCInt64
)
158 int64_t newVariable
= CFSwapInt64HostToBig(*((int64_t
*)_value
));
159 [coder encodeBytes
:&newVariable length
:_size
];
161 else if (_type
== TCFloat
)
163 #ifdef __LITTLE_ENDIAN__
164 CFSwappedFloat32 newVariable
= CFConvertFloat32HostToSwapped(*((float *)_value
));
165 [coder encodeBytes
:&newVariable length
:_size
];
167 [coder encodeBytes
:&_value length
:_size
];
170 else if (_type
== TCDouble
)
172 #ifdef __LITTLE_ENDIAN__
173 CFSwappedFloat64 newVariable
= CFConvertDoubleHostToSwapped(*((double *)_value
));
174 [coder encodeBytes
:&newVariable length
:_size
];
176 [coder encodeBytes
:_value length
:_size
];
180 [coder encodeValueOfObjCType
:@encode(BOOL) at
:&_isValueValid
];
181 [coder encodeValueOfObjCType
:@encode(BOOL) at
:&_enabled
];
182 [coder encodeValueOfObjCType
:@encode(int) at
:&_tag
];
186 // #############################################################################
187 #pragma mark Accessors
188 // #############################################################################
190 - (TCVariableType
)type
195 - (void)_setType
:(TCVariableType
)type
198 // set the size of the value
201 case TCDouble
: _size
= 8;
204 case TCFloat
: _size
= 4;
206 case TCInt16
: _size
= 2;
208 case TCInt8
: _size
= 1;
213 _value
= calloc( 1, _size
);
217 - (TCIntegerSign
)integerSign
222 - (void)_setIntegerSign
:(TCIntegerSign
)sign
228 - (NSString
*)typeString
231 case TCDouble
: return @
"Double";
232 case TCFloat
: return @
"Float";
233 case TCString
: return @
"ASCII String";
235 if ( _integerSign
== TCUnsigned
) {
237 case TCInt64
: return @
"64-bit Unsigned Integer";
238 case TCInt32
: return @
"32-bit Unsigned Integer";
239 case TCInt16
: return @
"16-bit Unsigned Integer";
240 case TCInt8
: return @
"08-bit Unsigned Integer";
245 case TCInt64
: return @
"64-bit Integer";
246 case TCInt32
: return @
"32-bit Integer";
247 case TCInt16
: return @
"16-bit Integer";
248 case TCInt8
: return @
"08-bit Integer";
260 - (void)setAddress
:(TCAddress
)addr
266 - (NSString
*)addressString
268 // return [NSString stringWithFormat:@"%0.8X", _address];
269 return [NSString stringWithFormat
:(_address
& 0xffffffff00000000ULL
) ? @
"%0.16qX": @
"%0.8X", _address
];
272 - (BOOL)setAddressString
:(NSString
*)string
274 NSScanner
*scanner
= [NSScanner scannerWithString
:string
];
277 if ( [scanner scanHexLongLong
:(unsigned long long *)(&address
)] ) {
278 [self setAddress
:address
];
285 - (void const *)value
290 - (void)setValue
:(void const *)value
293 _value
= malloc( _size
);
297 memcpy( _value
, value
, _size
);
300 - (void)setValue
:(void const *)value size
:(unsigned)size
302 // make sure the size doesn't exceed the maximum
303 size
= MIN( size
, TC_MAX_VAR_SIZE
);
304 // only string variables can have the value size changed
305 if ( (_type
== TCString
) && (_size
!= size
) && _value
) {
306 void *newValue
= realloc( _value
, size
);
312 _size
= MIN( _size
, size
);
314 [self setValue
:value
];
318 - (NSString
*)stringValue
321 case TCDouble
: return [NSString stringWithFormat
:@
"%.1lf", *(double *)[self value
]];
322 case TCFloat
: return [NSString stringWithFormat
:@
"%.1f", *(float *)[self value
]];
323 case TCString
: return [[[NSString alloc
] initWithBytes
:[self value
] length
:[self valueSize
] encoding
:NSUTF8StringEncoding
] autorelease
];
325 if ( _integerSign
== TCUnsigned
) {
327 case TCInt64
: return [NSString stringWithFormat
:@
"%llu", *(UInt64
*)[self value
]];
328 case TCInt32
: return [NSString stringWithFormat
:@
"%u", *(UInt32
*)[self value
]];
329 case TCInt16
: return [NSString stringWithFormat
:@
"%u", *(UInt16
*)[self value
]];
330 case TCInt8
: return [NSString stringWithFormat
:@
"%u", *(UInt8
*)[self value
]];
335 case TCInt64
: return [NSString stringWithFormat
:@
"%lli", *(SInt64
*)[self value
]];
336 case TCInt32
: return [NSString stringWithFormat
:@
"%i", *(SInt32
*)[self value
]];
337 case TCInt16
: return [NSString stringWithFormat
:@
"%i", *(SInt16
*)[self value
]];
338 case TCInt8
: return [NSString stringWithFormat
:@
"%i", *(SInt8
*)[self value
]];
344 - (BOOL)setStringValue
:(NSString
*)string
346 NSScanner
*scanner
= [NSScanner scannerWithString
:string
];
348 // invalid until proven valid
355 if ( [scanner scanLongLong
:(long long *)(&value
)] ) {
356 [self setValue
:&value
];
363 // if ( [scanner scanInt:(int *)(&value)] ) {
365 if ( [scanner scanInt
:&integer
] ) {
367 [self setValue
:&value
];
375 if ( [scanner scanInt
:&integer
] ) {
377 [self setValue
:&value
];
385 if ( [scanner scanInt
:&integer
] ) {
387 [self setValue
:&value
];
393 char *str
= (char *)[string cStringUsingEncoding
:NSUTF8StringEncoding
];
394 unsigned len
= strlen( str
);
395 [self setValue
:str size
:len
];
401 if ( [scanner scanFloat
:&value
] ) {
402 [self setValue
:&value
];
409 if ( [scanner scanDouble
:&value
] ) {
410 [self setValue
:&value
];
415 return [self isValueValid
];
418 // this only converts the byte order of the value at buffer if the process is running under rosetta on an intel mac
419 // floats and double's byte ordering should not be changed when searching for values because they may be swapped to '0.0'
420 void bigEndianValue(void *buffer
, Variable
*variable
)
422 if (variable
->_isEmulated
)
424 if (variable
->_type
== TCInt16
)
426 int16_t newValue
= CFSwapInt16HostToBig(*((int16_t
*)buffer
));
427 memcpy(buffer
, &newValue
, sizeof(int16_t
));
429 else if (variable
->_type
== TCInt32
)
431 int32_t newValue
= CFSwapInt32HostToBig(*((int32_t
*)buffer
));
432 memcpy(buffer
, &newValue
, sizeof(int32_t
));
434 else if (variable
->_type
== TCInt64
)
436 int64_t newValue
= CFSwapInt64HostToBig(*((int64_t
*)buffer
));
437 memcpy(buffer
, &newValue
, sizeof(int64_t
));
439 else if (variable
->_type
== TCFloat
)
441 CFSwappedFloat32 newValue
= CFConvertFloat32HostToSwapped(*((float *)buffer
));
442 memcpy(buffer
, &(newValue.v
), sizeof(float));
444 else if (variable
->_type
== TCDouble
)
446 CFSwappedFloat64 newValue
= CFConvertDoubleHostToSwapped(*((double *)buffer
));
447 memcpy(buffer
, &(newValue.v
), sizeof(double));
452 - (unsigned)valueSize
459 return _isValueValid
;
468 - (void)setEnabled
:(BOOL)enabled
479 - (void)setTag
:(NSInteger
)tag