snes9x/macosx/mac-cheatfinder.mm

1238 lines
40 KiB
Plaintext
Executable File

/*****************************************************************************\
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 Michael Donald Buckley
***********************************************************************************/
#include "snes9x.h"
#include "memmap.h"
#include "cheats.h"
#include "mac-prefix.h"
#include "mac-audio.h"
#include "mac-dialog.h"
#include "mac-os.h"
#include "mac-screenshot.h"
#include "mac-stringtools.h"
#include "mac-cheatfinder.h"
#define kCFNumBytesPop 'Size'
#define kCFViewModeRad 'Mode'
#define kCFCompModePop 'Math'
#define kCFCompStoredRad 'RSto'
#define kCFCompLastRad 'RLst'
#define kCFCompThisRad 'RThs'
#define kCFCompValueTxt 'CTxt'
#define kCFSearchBtn 'BSea'
#define kCFStoreValueBtn 'BSto'
#define kCFWatchBtn 'BWat'
#define kCFDrawerBtn 'Drwr'
#define kCFWatchAddrTxt 'WTxt'
#define kCFRestoreBtn 'BRes'
#define kCFRemoveBtn 'BRem'
#define kCFAddEntryBtn 'BAdd'
#define kCFUserPane 'Pane'
#define kCFSheetAddrTxt 'AEad'
#define kCFSheetCurrentValueTxt 'AEcv'
#define kCFSheetCheetValueTxt 'AEtx'
#define kCFSheetDescriptionTxt 'AEde'
#define kCFSheetAddBtn 'SHTa'
#define kCFSheetCancelBtn 'SHTc'
#define kCFListView 'List'
#define kCFUpperViews 'UI_T'
#define kCFLowerViews 'UI_B'
#define kEventScrollableScrollThere 'ESST'
#define kEventCheatFinderList 'ECFL'
#define kControlListLinePart 172
#define MAIN_MEMORY_SIZE 0x20000
#define kCheatFinderListViewClassID CFSTR("com.snes9x.macos.snes9x.cheatfinder")
enum
{
kCFHexadecimal = 1,
kCFSignedDecimal,
kCFUnsignedDecimal
};
enum
{
kCFCompWithStored = 1,
kCFCompWithLast,
kCFCompWithThis
};
enum
{
kCFSearchEqual = 1,
kCFSearchNotEqual,
kCFSearchGreater,
kCFSearchGreaterOrEqual,
kCFSearchLess,
kCFSearchLessOrEqual
};
typedef struct
{
IBNibRef nibRef;
WindowRef main;
WindowRef sheet;
WindowRef drawer;
HIViewRef list;
HIViewRef scroll;
EventHandlerRef sEref;
EventHandlerUPP sUPP;
} WindowData;
typedef struct
{
HIViewRef view;
HIPoint originPoint;
HISize lineSize;
Boolean inFocus;
} ListViewData;
Boolean cfIsWatching = false;
extern SCheatData Cheat;
static UInt8 *cfStoredRAM;
static UInt8 *cfLastRAM;
static UInt8 *cfCurrentRAM;
static UInt8 *cfStatusFlag;
static UInt32 *cfAddress;
static SInt32 cfNumRows;
static SInt32 cfListSelection;
static SInt32 cfViewMode;
static SInt32 cfCompMode;
static SInt32 cfCompWith;
static UInt32 cfViewNumBytes;
static UInt32 cfWatchAddr;
static Boolean cfIsNewGame;
static Boolean cfIsStored;
static Boolean cfDrawerShow;
static int cfListAddrColumnWidth;
static char cfWatchTextFormat[32];
static CTFontRef cfListLineCTFontRef;
#ifdef MAC_TIGER_PANTHER_SUPPORT
static ATSUStyle cfListLineATSUStyle;
#endif
static HIViewID kCheatFinderListViewID = { 'CHET', 'FNDR' };
static void CheatFinderSearch (WindowData *);
static void CheatFinderRestoreList (WindowData *);
static void CheatFinderRemoveFromList (WindowData *);
static void CheatFinderAdjustButtons (WindowData *);
static void CheatFinderBuildResultList (void);
static void CheatFinderHandleAddEntryButton (WindowData *);
static void CheatFinderMakeValueFormat (char *);
static void CheatFinderAddEntry (SInt64, char *);
static void CheatFinderBeginAddEntrySheet (WindowData *);
static void CheatFinderEndAddEntrySheet (WindowData *);
static void CheatFinderListViewScrollToThere (float, ListViewData *);
static void CheatFinderListViewDraw (CGContextRef, HIRect *, ListViewData *);
static float CheatFinderListViewSanityCheck (float, ListViewData *);
static SInt64 CheatFinderReadBytes (UInt8 *, UInt32);
static SInt64 CheatFinderGetValueEditText (ControlRef);
static Boolean CheatFinderCompare (SInt64, SInt64);
static HIViewPartCode CheatFinderListViewFindPart (EventRef, ListViewData *, SInt32 *);
void InitCheatFinder (void)
{
cfStoredRAM = new UInt8 [MAIN_MEMORY_SIZE + 10];
cfLastRAM = new UInt8 [MAIN_MEMORY_SIZE + 10];
cfCurrentRAM = new UInt8 [MAIN_MEMORY_SIZE + 10];
cfStatusFlag = new UInt8 [MAIN_MEMORY_SIZE + 10];
cfAddress = new UInt32[MAIN_MEMORY_SIZE + 10];
if (!cfStoredRAM || !cfLastRAM || !cfCurrentRAM || !cfStatusFlag || !cfAddress)
QuitWithFatalError(@"cheatfinder 01");
memset(cfCurrentRAM, 0x00, MAIN_MEMORY_SIZE + 10);
cfViewMode = kCFUnsignedDecimal;
cfViewNumBytes = 2;
cfCompMode = kCFSearchEqual;
cfCompWith = kCFCompWithThis;
cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Lucida Sans Typewriter Regular"), 11.0f, NULL);
if (cfListLineCTFontRef == NULL)
{
cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Menlo"), 11.0f, NULL);
if (cfListLineCTFontRef == NULL)
{
cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Monaco"), 11.0f, NULL);
if (cfListLineCTFontRef == NULL)
QuitWithFatalError(@"cheatfinder 02");
}
}
}
void ResetCheatFinder (void)
{
memset(cfStoredRAM, 0x00, MAIN_MEMORY_SIZE);
memset(cfLastRAM, 0x00, MAIN_MEMORY_SIZE);
memset(cfStatusFlag, 0xFF, MAIN_MEMORY_SIZE);
cfWatchAddr = 0;
cfIsNewGame = true;
cfIsWatching = false;
cfIsStored = false;
cfDrawerShow = false;
CheatFinderMakeValueFormat(cfWatchTextFormat);
}
void DeinitCheatFinder (void)
{
CFRelease(cfListLineCTFontRef);
delete [] cfStoredRAM;
delete [] cfLastRAM;
delete [] cfCurrentRAM;
delete [] cfStatusFlag;
delete [] cfAddress;
}
void CheatFinder (void)
{
// static HIObjectClassRef cfListViewClass = NULL;
//
// OSStatus err;
// HIViewRef ctl;
// HIViewID cid;
// char num[256];
// WindowData cf;
// EventHandlerRef wEref, pEref;
// EventHandlerUPP wUPP, pUPP;
// EventTypeSpec wEvents[] = { { kEventClassCommand, kEventCommandProcess },
// { kEventClassCommand, kEventCommandUpdateStatus },
// { kEventClassWindow, kEventWindowClose } },
// pEvents[] = { { kEventClassControl, kEventControlDraw } },
// cEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct },
// { kEventClassHIObject, kEventHIObjectInitialize },
// { kEventClassHIObject, kEventHIObjectDestruct },
// { kEventClassScrollable, kEventScrollableGetInfo },
// { kEventClassScrollable, kEventScrollableScrollTo },
// { kEventCheatFinderList, kEventScrollableScrollThere },
// { kEventClassControl, kEventControlHitTest },
// { kEventClassControl, kEventControlTrack },
// { kEventClassControl, kEventControlValueFieldChanged },
// { kEventClassControl, kEventControlDraw } };
//
// if (!cartOpen)
// return;
//
// err = CreateNibReference(kMacS9XCFString, &(cf.nibRef));
// if (err == noErr)
// {
// err = CreateWindowFromNib(cf.nibRef, CFSTR("CheatFinder"), &(cf.main));
// if (err == noErr)
// {
// err = CreateWindowFromNib(cf.nibRef, CFSTR("CFDrawer"), &(cf.drawer));
// if (err == noErr)
// {
// memcpy(cfCurrentRAM, Memory.RAM, MAIN_MEMORY_SIZE);
// CheatFinderBuildResultList();
//
// err = noErr;
// if (!cfListViewClass)
// err = HIObjectRegisterSubclass(kCheatFinderListViewClassID, kHIViewClassID, 0, CheatFinderListViewHandler, GetEventTypeCount(cEvents), cEvents, NULL, &cfListViewClass);
// if (err == noErr)
// {
// HIObjectRef hiObject;
// HIViewRef userpane, scrollview, listview, imageview, root;
// HILayoutInfo layoutinfo;
// HIRect frame;
// HISize minSize;
// CGImageRef image;
// Rect rct;
// float pich;
//
// GetWindowBounds(cf.main, kWindowContentRgn, &rct);
//
// minSize.width = (float) (rct.right - rct.left);
// minSize.height = (float) (rct.bottom - rct.top );
// err = SetWindowResizeLimits(cf.main, &minSize, NULL);
//
// root = HIViewGetRoot(cf.main);
// cid.id = 0;
// cid.signature = kCFUserPane;
// HIViewFindByID(root, cid, &userpane);
//
// err = HIScrollViewCreate(kHIScrollViewOptionsVertScroll, &scrollview);
// HIViewAddSubview(userpane, scrollview);
// HIViewGetBounds(userpane, &frame);
// cfListAddrColumnWidth = (int) (frame.size.width * 0.4);
// frame.origin.y += 16.0f;
// frame.size.height -= 16.0f;
// frame = CGRectInset(frame, 1.0f, 1.0f);
// HIViewSetFrame(scrollview, &frame);
// HIViewSetVisible(scrollview, true);
// cf.scroll = scrollview;
//
// layoutinfo.version = kHILayoutInfoVersionZero;
// HIViewGetLayoutInfo(scrollview, &layoutinfo);
//
// layoutinfo.binding.top.toView = userpane;
// layoutinfo.binding.top.kind = kHILayoutBindTop;
// layoutinfo.binding.bottom.toView = userpane;
// layoutinfo.binding.bottom.kind = kHILayoutBindBottom;
// layoutinfo.binding.left.toView = userpane;
// layoutinfo.binding.left.kind = kHILayoutBindLeft;
// layoutinfo.binding.right.toView = userpane;
// layoutinfo.binding.right.kind = kHILayoutBindRight;
// HIViewSetLayoutInfo(scrollview, &layoutinfo);
//
// err = HIObjectCreate(kCheatFinderListViewClassID, NULL, &hiObject);
// listview = (HIViewRef) hiObject;
// HIViewAddSubview(scrollview, listview);
// SetControl32BitMinimum(listview, 1);
// SetControl32BitMaximum(listview, cfNumRows);
// SetControl32BitValue(listview, 1);
// HIViewSetVisible(listview, true);
// cf.list = listview;
//
// cid.signature = kCFNumBytesPop;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfViewNumBytes);
//
// cid.signature = kCFViewModeRad;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfViewMode);
//
// cid.signature = kCFCompModePop;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfCompMode);
//
// if (cfIsNewGame || (!cfIsStored && (cfCompWith == kCFCompWithStored)))
// cfCompWith = kCFCompWithThis;
//
// cid.signature = kCFCompStoredRad;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfCompWith == kCFCompWithStored);
// if (cfIsStored)
// ActivateControl(ctl);
// else
// DeactivateControl(ctl);
//
// cid.signature = kCFCompLastRad;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfCompWith == kCFCompWithLast);
// if (!cfIsNewGame)
// ActivateControl(ctl);
// else
// DeactivateControl(ctl);
//
// cid.signature = kCFCompThisRad;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfCompWith == kCFCompWithThis);
//
// cid.signature = kCFCompValueTxt;
// HIViewFindByID(root, cid, &ctl);
// SetEditTextCFString(ctl, CFSTR(""), false);
// err = SetKeyboardFocus(cf.main, ctl, kControlFocusNextPart);
//
// cid.signature = kCFWatchBtn;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfIsWatching);
//
// cid.signature = kCFDrawerBtn;
// HIViewFindByID(root, cid, &ctl);
// SetControl32BitValue(ctl, cfDrawerShow);
//
// cid.signature = kCFWatchAddrTxt;
// HIViewFindByID(root, cid, &ctl);
// if (cfIsWatching)
// {
// sprintf(num, "%06lX", cfWatchAddr + 0x7E0000);
// SetStaticTextCStr(ctl, num, false);
// }
// else
// SetStaticTextCFString(ctl, CFSTR(""), false);
//
// CheatFinderAdjustButtons(&cf);
//
// pUPP = NewEventHandlerUPP(CheatFinderListFrameEventHandler);
// err = InstallControlEventHandler(userpane, pUPP, GetEventTypeCount(pEvents), pEvents, (void *) userpane, &pEref);
//
// wUPP = NewEventHandlerUPP(CheatFinderWindowEventHandler);
// err = InstallWindowEventHandler (cf.main, wUPP, GetEventTypeCount(wEvents), wEvents, (void *) &cf, &wEref);
//
// pich = (float) (IPPU.RenderedScreenHeight >> ((IPPU.RenderedScreenHeight > 256) ? 1 : 0));
//
// err = SetDrawerParent(cf.drawer, cf.main);
// err = SetDrawerOffsets(cf.drawer, 0.0f, (float) ((rct.bottom - rct.top) - (pich + 37)));
//
// image = CreateGameScreenCGImage();
// if (image)
// {
// err = HIImageViewCreate(image, &imageview);
// if (err == noErr)
// {
// HIViewFindByID(HIViewGetRoot(cf.drawer), kHIViewWindowContentID, &ctl);
//
// HIViewAddSubview(ctl, imageview);
// HIImageViewSetOpaque(imageview, false);
// HIImageViewSetScaleToFit(imageview, true);
// HIViewSetVisible(imageview, true);
//
// frame.origin.x = 8.0f;
// frame.origin.y = 8.0f;
// frame.size.width = (float) SNES_WIDTH;
// frame.size.height = pich;
// HIViewSetFrame(imageview, &frame);
// }
// }
//
// MoveWindowPosition(cf.main, kWindowCheatFinder, true);
// ShowWindow(cf.main);
//
// if (cfDrawerShow)
// err = OpenDrawer(cf.drawer, kWindowEdgeDefault, false);
//
// err = RunAppModalLoopForWindow(cf.main);
//
// HideWindow(cf.main);
// SaveWindowPosition(cf.main, kWindowCheatFinder);
//
// err = RemoveEventHandler(pEref);
// DisposeEventHandlerUPP(pUPP);
//
// err = RemoveEventHandler(wEref);
// DisposeEventHandlerUPP(wUPP);
//
// if (image)
// CGImageRelease(image);
// }
//
// CFRelease(cf.drawer);
// }
//
// CFRelease(cf.main);
// }
//
// DisposeNibReference(cf.nibRef);
//
// memcpy(cfLastRAM, Memory.RAM, MAIN_MEMORY_SIZE);
// cfIsNewGame = false;
// }
}
static SInt64 CheatFinderReadBytes (UInt8 *mem, UInt32 addr)
{
switch (cfViewMode)
{
case kCFSignedDecimal:
{
switch (cfViewNumBytes)
{
case 1: return ((SInt64) (SInt8) mem[addr]);
case 2: return ((SInt64) (SInt16) (mem[addr] | (mem[addr + 1] << 8)));
case 4: return ((SInt64) (SInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16) | (mem[addr + 3] << 24)));
case 3: return ((SInt64) (((SInt32) ((mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16)) << 8)) >> 8));
}
break;
}
case kCFUnsignedDecimal:
case kCFHexadecimal:
{
switch (cfViewNumBytes)
{
case 1: return ((SInt64) (UInt8) mem[addr]);
case 2: return ((SInt64) (UInt16) (mem[addr] | (mem[addr + 1] << 8)));
case 3: return ((SInt64) (UInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16)));
case 4: return ((SInt64) (UInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16) | (mem[addr + 3] << 24)));
}
break;
}
}
return (0);
}
static SInt64 CheatFinderGetValueEditText (HIViewRef control)
{
SInt64 result = 0;
UInt32 uvalue;
SInt32 svalue;
char num[256];
GetEditTextCStr(control, num);
if (num[0] == 0)
{
SetEditTextCFString(control, CFSTR("0"), true);
return (0);
}
switch (cfViewMode)
{
case kCFSignedDecimal:
{
if (sscanf(num, "%ld", &svalue) == 1)
{
switch (cfViewNumBytes)
{
case 1:
{
if (svalue > 127)
{
svalue = 127;
SetEditTextCFString(control, CFSTR("127"), true);
}
else
if (svalue < -128)
{
svalue = -128;
SetEditTextCFString(control, CFSTR("-128"), true);
}
break;
}
case 2:
{
if (svalue > 32767)
{
svalue = 32767;
SetEditTextCFString(control, CFSTR("32767"), true);
}
else
if (svalue < -32768)
{
svalue = -32768;
SetEditTextCFString(control, CFSTR("-32768"), true);
}
break;
}
case 3:
{
if (svalue > 8388607)
{
svalue = 8388607;
SetEditTextCFString(control, CFSTR("8388607"), true);
}
else
if (svalue < -8388608)
{
svalue = -8388608;
SetEditTextCFString(control, CFSTR("-8388608"), true);
}
break;
}
}
}
else
{
svalue = 0;
SetEditTextCFString(control, CFSTR("0"), true);
}
result = (SInt64) svalue;
break;
}
case kCFUnsignedDecimal:
{
if (sscanf(num, "%lu", &uvalue) == 1)
{
switch (cfViewNumBytes)
{
case 1:
{
if (uvalue > 255)
{
uvalue = 255;
SetEditTextCFString(control, CFSTR("255"), true);
}
break;
}
case 2:
{
if (uvalue > 65535)
{
uvalue = 65535;
SetEditTextCFString(control, CFSTR("65535"), true);
}
break;
}
case 3:
{
if (uvalue > 16777215)
{
uvalue = 16777215;
SetEditTextCFString(control, CFSTR("16777215"), true);
}
break;
}
}
}
else
{
uvalue = 0;
SetEditTextCFString(control, CFSTR("0"), true);
}
result = (SInt64) uvalue;
break;
}
case kCFHexadecimal:
{
if (sscanf(num, "%lx", &uvalue) == 1)
{
switch (cfViewNumBytes)
{
case 1:
{
if (uvalue > 0xFF)
{
uvalue = 0xFF;
SetEditTextCFString(control, CFSTR("FF"), true);
}
break;
}
case 2:
{
if (uvalue > 0xFFFF)
{
uvalue = 0xFFFF;
SetEditTextCFString(control, CFSTR("FFFF"), true);
}
break;
}
case 3:
{
if (uvalue > 0xFFFFFF)
{
uvalue = 0xFFFFFF;
SetEditTextCFString(control, CFSTR("FFFFFF"), true);
}
break;
}
}
}
else
{
uvalue = 0;
SetEditTextCFString(control, CFSTR("0"), true);
}
result = (SInt64) uvalue;
break;
}
}
return (result);
}
static void CheatFinderSearch (WindowData *cf)
{
// SInt64 cmpvalue;
// UInt8 *mem;
//
// if (cfCompWith == kCFCompWithThis)
// {
// HIViewRef ctl;
// HIViewID cid = { kCFCompValueTxt, 0 };
//
// HIViewFindByID(HIViewGetRoot(cf->main), cid, &ctl);
// cmpvalue = CheatFinderGetValueEditText(ctl);
//
// for (int i = 0; i < cfNumRows; i++)
// if (!CheatFinderCompare(CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]), cmpvalue))
// cfStatusFlag[cfAddress[i]] = 0;
// }
// else
// {
// mem = (cfCompWith == kCFCompWithStored) ? cfStoredRAM : cfLastRAM;
//
// for (int i = 0; i < cfNumRows; i++)
// if (!CheatFinderCompare(CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]), CheatFinderReadBytes(mem, cfAddress[i])))
// cfStatusFlag[cfAddress[i]] = 0;
// }
//
// CheatFinderBuildResultList();
//
// SetControl32BitMaximum(cf->list, cfNumRows);
// SetControl32BitValue(cf->list, 1);
}
static Boolean CheatFinderCompare (SInt64 ramvalue, SInt64 cmpvalue)
{
switch (cfCompMode)
{
case kCFSearchEqual: return (ramvalue == cmpvalue);
case kCFSearchNotEqual: return (ramvalue != cmpvalue);
case kCFSearchGreater: return (ramvalue > cmpvalue);
case kCFSearchGreaterOrEqual: return (ramvalue >= cmpvalue);
case kCFSearchLess: return (ramvalue < cmpvalue);
case kCFSearchLessOrEqual: return (ramvalue <= cmpvalue);
}
return (false);
}
static void CheatFinderBuildResultList (void)
{
cfNumRows = 0;
for (int i = 0; i < MAIN_MEMORY_SIZE; i++)
{
if (cfStatusFlag[i] == 0xFF)
{
cfAddress[cfNumRows] = i;
cfNumRows++;
}
}
cfListSelection = 0;
}
static void CheatFinderAdjustButtons (WindowData *cf)
{
// HIViewRef ctl, root;
// HIViewID cid;
//
// cid.id = 0;
// root = HIViewGetRoot(cf->main);
//
// if (cfNumRows > 0)
// {
// cid.signature = kCFAddEntryBtn;
// HIViewFindByID(root, cid, &ctl);
// ActivateControl(ctl);
//
// cid.signature = kCFRemoveBtn;
// HIViewFindByID(root, cid, &ctl);
// ActivateControl(ctl);
//
// cid.signature = kCFWatchBtn;
// HIViewFindByID(root, cid, &ctl);
// ActivateControl(ctl);
// }
// else
// {
// cid.signature = kCFAddEntryBtn;
// HIViewFindByID(root, cid, &ctl);
// DeactivateControl(ctl);
//
// cid.signature = kCFRemoveBtn;
// HIViewFindByID(root, cid, &ctl);
// DeactivateControl(ctl);
//
// if (!cfIsWatching)
// {
// cid.signature = kCFWatchBtn;
// HIViewFindByID(root, cid, &ctl);
// DeactivateControl(ctl);
// }
// }
}
static void CheatFinderRemoveFromList (WindowData *cf)
{
// if (cfNumRows > 0)
// {
// cfStatusFlag[cfAddress[cfListSelection]] = 0;
//
// if (cfNumRows == 1)
// {
// cfNumRows = 0;
//
// SetControl32BitMaximum(cf->list, 0);
// SetControl32BitValue(cf->list, 1);
// }
// else
// {
// for (int i = cfListSelection; i < cfNumRows - 1; i++)
// cfAddress[i] = cfAddress[i + 1];
//
// cfNumRows--;
// if (cfListSelection >= cfNumRows)
// cfListSelection = cfNumRows - 1;
//
// SetControl32BitMaximum(cf->list, cfNumRows);
// SetControl32BitValue(cf->list, cfListSelection + 1);
// }
// }
}
static void CheatFinderRestoreList (WindowData *cf)
{
// memset(cfStatusFlag, 0xFF, MAIN_MEMORY_SIZE);
// CheatFinderBuildResultList();
//
// SetControl32BitMaximum(cf->list, cfNumRows);
// SetControl32BitValue(cf->list, 1);
}
static void CheatFinderMakeValueFormat (char *text)
{
// switch (cfViewMode)
// {
// case kCFSignedDecimal:
// case kCFUnsignedDecimal:
// {
// strcpy(text, "%lld");
// break;
// }
//
// case kCFHexadecimal:
// {
// sprintf(text, "%%0%lullX", cfViewNumBytes * 2);
// break;
// }
// }
}
void CheatFinderDrawWatchAddr (void)
{
// static char code[256];
//
// uint16 *basePtr;
// int len;
//
// sprintf(code, cfWatchTextFormat, CheatFinderReadBytes(Memory.RAM, cfWatchAddr));
//
// basePtr = GFX.Screen + 1;
// len = strlen(code);
//
// for (int i = 0; i < len; i++)
// {
// S9xDisplayChar(basePtr, code[i]);
// basePtr += (8 - 1);
// }
}
static void CheatFinderHandleAddEntryButton (WindowData *cf)
{
// if (cfAddress[cfListSelection] > (0x20000 - cfViewNumBytes))
// NSBeep();
// else
// if (Cheat.g.size() + cfViewNumBytes > MAC_MAX_CHEATS)
// AppearanceAlert(kAlertCautionAlert, kS9xMacAlertCFCantAddEntry, kS9xMacAlertCFCantAddEntryHint);
// else
// CheatFinderBeginAddEntrySheet(cf);
}
static void CheatFinderBeginAddEntrySheet (WindowData *cf)
{
// OSStatus err;
// HIViewRef ctl, root;
// HIViewID cid;
// UInt32 addr;
// char str[256], form[256];
// EventTypeSpec sEvents[] = { { kEventClassCommand, kEventCommandProcess },
// { kEventClassCommand, kEventCommandUpdateStatus } };
//
// err = CreateWindowFromNib(cf->nibRef, CFSTR("CFAddEntry"), &(cf->sheet));
// if (err == noErr)
// {
// addr = cfAddress[cfListSelection];
//
// root = HIViewGetRoot(cf->sheet);
// cid.id = 0;
//
// cid.signature = kCFSheetAddrTxt;
// HIViewFindByID(root, cid, &ctl);
// sprintf(str, "%06lX", addr + 0x7E0000);
// SetStaticTextCStr(ctl, str, false);
//
// cid.signature = kCFSheetCurrentValueTxt;
// HIViewFindByID(root, cid, &ctl);
// CheatFinderMakeValueFormat(form);
// sprintf(str, form, CheatFinderReadBytes(cfCurrentRAM, addr));
// SetStaticTextCStr(ctl, str, false);
//
// cid.signature = kCFSheetCheetValueTxt;
// HIViewFindByID(root, cid, &ctl);
// SetEditTextCStr(ctl, str, false);
//
// err = ClearKeyboardFocus(cf->sheet);
// err = SetKeyboardFocus(cf->sheet, ctl, kControlFocusNextPart);
//
// cid.signature = kCFSheetDescriptionTxt;
// HIViewFindByID(root, cid, &ctl);
// sprintf(str, "%06lX-%06lX", addr + 0x7E0000, addr + cfViewNumBytes - 1 + 0x7E0000);
// SetStaticTextCStr(ctl, str, false);
//
// cf->sUPP = NewEventHandlerUPP(CheatFinderSheetEventHandler);
// err = InstallWindowEventHandler(cf->sheet, cf->sUPP, GetEventTypeCount(sEvents), sEvents, (void *) cf, &(cf->sEref));
//
// err = ShowSheetWindow(cf->sheet, cf->main);
// }
}
static void CheatFinderEndAddEntrySheet (WindowData *cf)
{
// if (cf->sheet)
// {
// OSStatus err;
//
// err = HideSheetWindow(cf->sheet);
//
// err = RemoveEventHandler(cf->sEref);
// DisposeEventHandlerUPP(cf->sUPP);
//
// CFRelease(cf->sheet);
// }
}
static void CheatFinderAddEntry (SInt64 value, char *description)
{
UInt32 addr, v;
addr = cfAddress[cfListSelection];
v = (UInt32) (SInt32) value;
for (unsigned int i = 0; i < cfViewNumBytes; i++)
{
char code[10];
snprintf(code, 10, "%x=%x", addr + i + 0x7E0000, (UInt8) ((v & (0x000000FF << (i * 8))) >> (i * 8)));
int index = S9xAddCheatGroup(description, code);
if(index >= 0)
S9xEnableCheatGroup(index);
}
}
static void CheatFinderListViewDraw (CGContextRef ctx, HIRect *bounds, ListViewData *myData)
{
// static Boolean init = true;
//
// if (systemVersion >= 0x1050)
// {
// static CGRect aRct, vRct;
//
// CTLineRef line;
// CFDictionaryRef attr;
// CFAttributedStringRef astr;
// CFStringRef str;
// HIRect lineBounds;
// SInt32 start, end, val, max;
// float ax, vx, y, f;
// char format[32], t1[64], t2[64];
//
// CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
// CFTypeRef bval[] = { cfListLineCTFontRef, CGColorGetConstantColor(kCGColorBlack) },
// wval[] = { cfListLineCTFontRef, CGColorGetConstantColor(kCGColorWhite) };
//
// CheatFinderMakeValueFormat(format);
//
// start = (SInt32) (myData->originPoint.y / myData->lineSize.height);
// end = (SInt32) ((myData->originPoint.y + bounds->size.height) / myData->lineSize.height) + 1;
//
// y = start * myData->lineSize.height - myData->originPoint.y;
//
// lineBounds = *bounds;
// lineBounds.size.height = myData->lineSize.height;
// lineBounds.origin.y = y;
//
// val = GetControl32BitValue(myData->view) - 1;
// max = GetControl32BitMaximum(myData->view);
//
// attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &bval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
//
// CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
//
// if (init)
// {
// CGContextSetTextPosition(ctx, 0.0f, 0.0f);
//
// astr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("FFFFFF"), attr);
// line = CTLineCreateWithAttributedString(astr);
// aRct = CTLineGetImageBounds(line, ctx);
// CFRelease(line);
// CFRelease(astr);
//
// astr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("FFFFFFFFFFF"), attr);
// line = CTLineCreateWithAttributedString(astr);
// vRct = CTLineGetImageBounds(line, ctx);
// CFRelease(line);
// CFRelease(astr);
//
// init = false;
// }
//
// ax = (float) (int) (((float) cfListAddrColumnWidth - 2.0 - aRct.size.width) / 2.0);
// vx = (float) (int) (lineBounds.origin.x + lineBounds.size.width - vRct.size.width - 12.0);
//
// for (int i = start; i <= end; i++)
// {
// if ((i == val) && cfNumRows)
// CGContextSetRGBFillColor(ctx, 59.0f / 256.0f, 124.0f / 256.0f, 212.0f / 256.0f, 1.0f);
// else
// if ((i - start) % 2 == 0)
// CGContextSetRGBFillColor(ctx, 256.0f / 256.0f, 256.0f / 256.0f, 256.0f / 256.0f, 1.0f);
// else
// CGContextSetRGBFillColor(ctx, 237.0f / 256.0f, 244.0f / 256.0f, 254.0f / 256.0f, 1.0f);
//
// CGContextFillRect(ctx, lineBounds);
//
// if (i < max)
// {
// CGContextScaleCTM(ctx, 1, -1);
//
// if (i == val)
// {
// CFRelease(attr);
// attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &wval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// }
//
// f = -(y + 12.0f);
//
// sprintf(t1, "%06lX", cfAddress[i] + 0x7E0000);
// str = CFStringCreateWithCString(kCFAllocatorDefault, t1, kCFStringEncodingUTF8);
// astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attr);
// line = CTLineCreateWithAttributedString(astr);
// CGContextSetTextPosition(ctx, ax, f);
// CTLineDraw(line, ctx);
// CFRelease(line);
// CFRelease(astr);
// CFRelease(str);
//
// sprintf(t2, format, CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]));
// strcpy(t1, " ");
// t1[11 - strlen(t2)] = 0;
// strcat(t1, t2);
// str = CFStringCreateWithCString(kCFAllocatorDefault, t1, kCFStringEncodingUTF8);
// astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attr);
// line = CTLineCreateWithAttributedString(astr);
// CGContextSetTextPosition(ctx, vx, f);
// CTLineDraw(line, ctx);
// CFRelease(line);
// CFRelease(astr);
// CFRelease(str);
//
// CGContextScaleCTM(ctx, 1, -1);
//
// if (i == val)
// {
// CFRelease(attr);
// attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &bval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// }
// }
//
// y += myData->lineSize.height;
// lineBounds.origin.y += myData->lineSize.height;
// }
//
// CFRelease(attr);
// }
//#ifdef MAC_TIGER_PANTHER_SUPPORT
// else
// {
// static Rect aRect = { 0, 0, 0, 0 }, vRect = { 0, 0, 0, 0 };
//
// OSStatus err;
// ATSUTextLayout layout;
// HIRect lineBounds;
// UniCharCount runLength[1], len;
// SInt32 start, end, val, max;
// Fixed ax, vx, f;
// float y;
// UniChar unistr[64];
// char format[32], t1[64], t2[64];
//
// ATSUAttributeTag theTags[] = { kATSUCGContextTag };
// ByteCount theSizes[] = { sizeof(CGContextRef) };
// ATSUAttributeValuePtr theValues[] = { &ctx };
//
// CheatFinderMakeValueFormat(format);
//
// start = (SInt32) (myData->originPoint.y / myData->lineSize.height);
// end = (SInt32) ((myData->originPoint.y + bounds->size.height) / myData->lineSize.height) + 1;
//
// y = start * myData->lineSize.height - myData->originPoint.y;
//
// lineBounds = *bounds;
// lineBounds.size.height = myData->lineSize.height;
// lineBounds.origin.y = y;
//
// val = GetControl32BitValue(myData->view) - 1;
// max = GetControl32BitMaximum(myData->view);
//
// if (init)
// {
// f = Long2Fix(0);
// for (unsigned int n = 0; n < 11; n++)
// unistr[n] = 'F';
//
// len = runLength[0] = 6;
// err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout);
// err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues);
// err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, f, f, &aRect);
// err = ATSUDisposeTextLayout(layout);
//
// len = runLength[0] = 11;
// err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout);
// err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues);
// err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, f, f, &vRect);
// err = ATSUDisposeTextLayout(layout);
//
// init = false;
// }
//
// ax = Long2Fix((cfListAddrColumnWidth - 2 - (aRect.right - aRect.left)) >> 1);
// vx = Long2Fix((int) (lineBounds.origin.x + lineBounds.size.width) - (vRect.right - vRect.left) - 13);
//
// for (int i = start; i <= end; i++)
// {
// if ((i == val) && cfNumRows)
// CGContextSetRGBFillColor(ctx, 59.0f / 256.0f, 124.0f / 256.0f, 212.0f / 256.0f, 1.0f);
// else
// if ((i - start) % 2 == 0)
// CGContextSetRGBFillColor(ctx, 256.0f / 256.0f, 256.0f / 256.0f, 256.0f / 256.0f, 1.0f);
// else
// CGContextSetRGBFillColor(ctx, 237.0f / 256.0f, 244.0f / 256.0f, 254.0f / 256.0f, 1.0f);
//
// CGContextFillRect(ctx, lineBounds);
//
// if (i < max)
// {
// CGContextScaleCTM(ctx, 1, -1);
//
// if (i == val)
// CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
// else
// CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f);
//
// f = Long2Fix(-((int) y + 12));
//
// sprintf(t1, "%06lX", cfAddress[i] + 0x7E0000);
// len = runLength[0] = strlen(t1);
// for (unsigned int n = 0; n < len; n++)
// unistr[n] = t1[n];
// err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout);
// err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues);
// err = ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, ax, f);
// err = ATSUDisposeTextLayout(layout);
//
// sprintf(t2, format, CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]));
// strcpy(t1, " ");
// t1[11 - strlen(t2)] = 0;
// strcat(t1, t2);
// len = runLength[0] = strlen(t1);
// for (unsigned int n = 0; n < len; n++)
// unistr[n] = t1[n];
// err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout);
// err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues);
// err = ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, vx, f);
// err = ATSUDisposeTextLayout(layout);
//
// CGContextScaleCTM(ctx, 1, -1);
// }
//
// y += myData->lineSize.height;
// lineBounds.origin.y += myData->lineSize.height;
// }
// }
//#endif
}
static HIViewPartCode CheatFinderListViewFindPart (EventRef inEvent, ListViewData *myData, SInt32 *whichLine)
{
// OSStatus err;
// HIViewPartCode part;
// HIPoint hipt;
// SInt32 start, line;
// float y;
//
// part = kControlNoPart;
//
// start = (SInt32) (myData->originPoint.y / myData->lineSize.height);
// y = start * myData->lineSize.height - myData->originPoint.y;
//
// err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(hipt), NULL, &hipt);
// if (err == noErr)
// {
// line = start + (SInt32) ((hipt.y - y - 1) / myData->lineSize.height) + 1;
//
// if (line <= GetControl32BitMaximum(myData->view))
// part = kControlListLinePart;
//
// if (whichLine != NULL)
// *whichLine = line;
// }
//
// return (part);
return 0;
}
static float CheatFinderListViewSanityCheck (float where, ListViewData *myData)
{
HIRect bounds;
HISize imageSize;
// HIViewGetBounds(myData->view, &bounds);
// imageSize = myData->lineSize;
// imageSize.height *= GetControl32BitMaximum(myData->view);
if (where + bounds.size.height > imageSize.height)
where = imageSize.height - bounds.size.height;
if (where < 0)
where = 0;
return (where);
}
static void CheatFinderListViewScrollToThere (float where, ListViewData *myData)
{
OSStatus err;
EventRef theEvent;
HIPoint whereP = { 0.0f, where };
err = CreateEvent(kCFAllocatorDefault, kEventCheatFinderList, kEventScrollableScrollThere, GetCurrentEventTime(), kEventAttributeUserEvent, &theEvent);
if (err == noErr)
{
err = SetEventParameter(theEvent, kEventParamOrigin, typeHIPoint, sizeof(whereP), &whereP);
// if (err == noErr)
// err = SendEventToEventTarget(theEvent, GetControlEventTarget(myData->view));
ReleaseEvent(theEvent);
}
}