1
0
mirror of https://github.com/TASVideos/desmume synced 2024-07-08 20:06:04 +00:00

Cocoa Port: Completely redesign the cheat database viewing system with a whole slew of new features!

- Multiple cheat database files may now be opened simultaneously, each in their own individual windows.
- Cheat database files are now fully browsable.
- Game entries are now searchable by game title, serial, and CRC.
- Cheat entries are now viewed in a hierarchical layout, better representing the FAT format of the database entries.
- All cheats within a directory can now be selected or deselected in just a single click.
- Error handling is now more robust, informative, and nicer looking.
- Cheat database files are no longer assigned in DeSmuME Preferences; they are now opened through the "File > Open Cheat Database File" menu.
- Recent cheat database files are now saved, and can be quickly accessed through the "File > Open Recent Cheat Database File" menu.
- It is now possible to remove all cheats at once from the Cheat Manager's cheat list.
This commit is contained in:
rogerman 2023-08-01 01:41:15 -07:00
parent 4e6a7f0424
commit e3167110b2
23 changed files with 7414 additions and 1647 deletions

View File

@ -2123,8 +2123,9 @@ CheatDBFile::CheatDBFile()
{
_path = "";
_description = "";
_formatString = "---";
_type = CHEATS_DB_R4;
_format = CheatDBFileFormat_Undefined;
_isEncrypted = false;
_size = 0;
_fp = NULL;
@ -2150,15 +2151,25 @@ const char* CheatDBFile::GetDescription() const
return this->_description.c_str();
}
int CheatDBFile::OpenFile(const char *filePath)
CheatDBFileFormat CheatDBFile::GetFormat() const
{
int error = 0;
return this->_format;
}
const char* CheatDBFile::GetFormatString() const
{
return this->_formatString.c_str();
}
CheatSystemError CheatDBFile::OpenFile(const char *filePath)
{
CheatSystemError error = CheatSystemError_NoError;
this->_fp = fopen(filePath, "rb");
if (this->_fp == NULL)
{
printf("ERROR: Failed to open the cheat database.\n");
error = 1;
error = CheatSystemError_FileOpenFailed;
return error;
}
@ -2172,14 +2183,14 @@ int CheatDBFile::OpenFile(const char *filePath)
if (this->_size < strlen(headerID))
{
printf("ERROR: Failed to validate the file header.\n");
error = 2;
error = CheatSystemError_FileFormatInvalid;
return error;
}
if (this->_size < CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY)
{
printf("ERROR: No FAT entries found.\n");
error = 2;
error = CheatSystemError_FileFormatInvalid;
return error;
}
@ -2203,7 +2214,7 @@ int CheatDBFile::OpenFile(const char *filePath)
this->_fp = NULL;
printf("ERROR: Failed to validate the file header.\n");
error = 2;
error = CheatSystemError_FileFormatInvalid;
return error;
}
@ -2213,6 +2224,8 @@ int CheatDBFile::OpenFile(const char *filePath)
this->_isEncrypted = true;
}
this->_format = CheatDBFileFormat_R4;
this->_formatString = "R4";
this->_description = (const char *)(workingBuffer + CHEATDB_OFFSET_FILE_DESCRIPTION);
this->_path = filePath;
@ -2439,7 +2452,7 @@ CHEATSEXPORT::CHEATSEXPORT()
{
_selectedDbGame = NULL;
_cheats = NULL;
_error = 0;
_lastError = CheatSystemError_NoError;
}
CHEATSEXPORT::~CHEATSEXPORT()
@ -2451,8 +2464,8 @@ bool CHEATSEXPORT::load(const char *path)
{
bool didLoadSucceed = false;
this->_error = this->_dbFile.OpenFile(path);
if (this->_error != 0)
this->_lastError = this->_dbFile.OpenFile(path);
if (this->_lastError != CheatSystemError_NoError)
{
return didLoadSucceed;
}
@ -2471,7 +2484,7 @@ bool CHEATSEXPORT::load(const char *path)
};
printf("ERROR: Cheat for game code '%s' not found in database.\n", gameCodeString);
this->_error = 3;
this->_lastError = CheatSystemError_GameNotFound;
return didLoadSucceed;
}
@ -2479,7 +2492,7 @@ bool CHEATSEXPORT::load(const char *path)
if (dbGameBuffer == NULL)
{
printf("ERROR: Failed to read game entries from file.\n");
this->_error = 1;
this->_lastError = CheatSystemError_LoadEntryError;
return didLoadSucceed;
}
@ -2495,7 +2508,7 @@ bool CHEATSEXPORT::load(const char *path)
if (parsedCheatCount == 0)
{
printf("ERROR: export cheats failed\n");
this->_error = 4;
this->_lastError = CheatSystemError_LoadEntryError;
return didLoadSucceed;
}
@ -2546,7 +2559,7 @@ const char* CHEATSEXPORT::getDescription() const
return (const char *)this->_dbFile.GetDescription();
}
u8 CHEATSEXPORT::getErrorCode() const
CheatSystemError CHEATSEXPORT::getErrorCode() const
{
return this->_error;
return this->_lastError;
}

View File

@ -32,6 +32,17 @@
#define CHEAT_TYPE_AR 1
#define CHEAT_TYPE_CODEBREAKER 2
enum CheatSystemError
{
CheatSystemError_NoError = 0,
CheatSystemError_FileOpenFailed = 1,
CheatSystemError_FileFormatInvalid = 2,
CheatSystemError_GameNotFound = 3,
CheatSystemError_LoadEntryError = 4,
CheatSystemError_FileSaveFailed = 5,
CheatSystemError_FileDoesNotExist = 6
};
struct CHEATS_LIST
{
CHEATS_LIST()
@ -163,9 +174,11 @@ public:
#define CHEATDB_OFFSET_FILE_DESCRIPTION 0x00000010
#define CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY 0x00000100
enum CHEATS_DB_TYPE
enum CheatDBFileFormat
{
CHEATS_DB_R4 = 0
CheatDBFileFormat_Undefined = 0,
CheatDBFileFormat_R4 = 1,
CheatDBFileFormat_Unknown = 65535
};
// This struct maps to the FAT entries in the R4 cheat database file.
@ -253,8 +266,9 @@ class CheatDBFile
protected:
std::string _path;
std::string _description;
std::string _formatString;
CHEATS_DB_TYPE _type;
CheatDBFileFormat _format;
bool _isEncrypted;
size_t _size;
@ -272,8 +286,10 @@ public:
FILE* GetFilePtr() const;
bool IsEncrypted() const;
const char* GetDescription() const;
CheatDBFileFormat GetFormat() const;
const char* GetFormatString() const;
int OpenFile(const char *filePath);
CheatSystemError OpenFile(const char *filePath);
void CloseFile();
u32 LoadGameList(const char *gameCode, const u32 gameDatabaseCRC, CheatDBGameList &outList);
@ -286,12 +302,7 @@ private:
CheatDBGameList _tempGameList;
CheatDBGame *_selectedDbGame;
CHEATS_LIST *_cheats;
u8 _error; // 0 - no errors
// 1 - open failed/file not found
// 2 - file format is wrong (no valid header ID)
// 3 - cheat not found in database
// 4 - export error from database
CheatSystemError _lastError;
public:
CHEATSEXPORT();
@ -304,7 +315,7 @@ public:
size_t getCheatsNum() const;
const char* getGameTitle() const;
const char* getDescription() const;
u8 getErrorCode() const;
CheatSystemError getErrorCode() const;
};
CheatDBGame* GetCheatDBGameEntryFromList(const CheatDBGameList &gameList, const char *gameCode, const u32 gameDatabaseCRC);

View File

@ -1543,6 +1543,27 @@
AB681025187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */; };
AB681027187D4AEF0049F2C2 /* Icon_Piano_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */; };
AB68A0DD16B139BC00DE0546 /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; };
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */; };
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */; };
AB74EC8A1738499C0026C41E /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB74EC891738499C0026C41E /* Carbon.framework */; };
AB78B5C11E384F2100297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
AB78B5C21E384F2200297FED /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4401E262943003E2B24 /* Metal.framework */; settings = {ATTRIBUTES = (Required, ); }; };
@ -4012,6 +4033,9 @@
AB681018187D4AEF0049F2C2 /* Icon_PaddleKnob_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_PaddleKnob_256x256.png; path = images/Icon_PaddleKnob_256x256.png; sourceTree = "<group>"; };
AB681019187D4AEF0049F2C2 /* Icon_Piano_256x256.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Piano_256x256.png; path = images/Icon_Piano_256x256.png; sourceTree = "<group>"; };
AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OGLRender_3_2.cpp; sourceTree = "<group>"; };
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
AB6E18002A6B218D003A564D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
AB6FBEF5139B6258007BB045 /* slot1_retail_nand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot1_retail_nand.cpp; sourceTree = "<group>"; };
AB74EC891738499C0026C41E /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
AB75226D14C7BB51009B97B3 /* AppIcon_FirmwareConfig.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_FirmwareConfig.icns; sourceTree = "<group>"; };
@ -4935,6 +4959,7 @@
ABC2ECD613B1C87000FAAA2A /* Images */,
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */,
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */,
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
8D1107310486CEB800E47090 /* Info.plist */,
AB02791814415E4C0075E58C /* Info (Debug).plist */,
@ -5227,6 +5252,7 @@
children = (
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
AB6E17F32A675BF1003A564D /* CheatDatabaseWindowController.h */,
AB3BF4361E25D6B4003E2B24 /* DisplayViewCALayer.h */,
AB8967D716D2ED0700F826F1 /* DisplayWindowController.h */,
AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */,
@ -5246,6 +5272,7 @@
AB3FBD7E2176DE95005722D0 /* WifiSettingsPanel.h */,
AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */,
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
AB6E17F42A675BF1003A564D /* CheatDatabaseWindowController.mm */,
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
AB3BF4371E25D9AE003E2B24 /* DisplayViewCALayer.mm */,
AB8967D816D2ED0700F826F1 /* DisplayWindowController.mm */,
@ -6451,6 +6478,7 @@
8C43E79727E3CD0100A35F65 /* Icon_Input_420x420.png in Resources */,
8C43E79827E3CD0100A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
8C43E79927E3CD0100A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18032A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8C43E79A27E3CD0100A35F65 /* Icon_OpenROM_420x420.png in Resources */,
8C43E79B27E3CD0100A35F65 /* Icon_Reset_420x420.png in Resources */,
8C43E79C27E3CD0100A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6570,6 +6598,7 @@
8C43E8F527E3CD4C00A35F65 /* Icon_Input_420x420.png in Resources */,
8C43E8F627E3CD4C00A35F65 /* Icon_AutoholdSet_420x420.png in Resources */,
8C43E8F727E3CD4C00A35F65 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18042A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8C43E8F827E3CD4C00A35F65 /* Icon_OpenROM_420x420.png in Resources */,
8C43E8F927E3CD4C00A35F65 /* Icon_Reset_420x420.png in Resources */,
8C43E8FA27E3CD4C00A35F65 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6689,6 +6718,7 @@
8CCD840827E40B730024BDD5 /* Icon_Input_420x420.png in Resources */,
8CCD840927E40B730024BDD5 /* Icon_AutoholdSet_420x420.png in Resources */,
8CCD840A27E40B730024BDD5 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E180B2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
8CCD840B27E40B730024BDD5 /* Icon_OpenROM_420x420.png in Resources */,
8CCD840C27E40B730024BDD5 /* Icon_Reset_420x420.png in Resources */,
8CCD840D27E40B730024BDD5 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6808,6 +6838,7 @@
AB36C78827F2C8AE00C763C8 /* Icon_Input_420x420.png in Resources */,
AB36C78927F2C8AE00C763C8 /* Icon_AutoholdSet_420x420.png in Resources */,
AB36C78A27F2C8AE00C763C8 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18082A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB36C78B27F2C8AE00C763C8 /* Icon_OpenROM_420x420.png in Resources */,
AB36C78C27F2C8AE00C763C8 /* Icon_Reset_420x420.png in Resources */,
AB36C78D27F2C8AE00C763C8 /* Icon_RotateCCW_420x420.png in Resources */,
@ -6927,6 +6958,7 @@
AB497A0E27F2E97A00E8A244 /* Icon_Input_420x420.png in Resources */,
AB497A0F27F2E97A00E8A244 /* Icon_AutoholdSet_420x420.png in Resources */,
AB497A1027F2E97A00E8A244 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18072A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB497A1127F2E97A00E8A244 /* Icon_OpenROM_420x420.png in Resources */,
AB497A1227F2E97A00E8A244 /* Icon_Reset_420x420.png in Resources */,
AB497A1327F2E97A00E8A244 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7046,6 +7078,7 @@
AB790193215B84F20082AE82 /* Icon_Input_420x420.png in Resources */,
AB790194215B84F20082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
AB790195215B84F20082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18062A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB790196215B84F20082AE82 /* Icon_OpenROM_420x420.png in Resources */,
AB790197215B84F20082AE82 /* Icon_Reset_420x420.png in Resources */,
AB790198215B84F20082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7165,6 +7198,7 @@
AB796CE015CDCBA200C59155 /* Icon_Input_420x420.png in Resources */,
AB7EC7F6189B2B92009D198A /* Icon_AutoholdSet_420x420.png in Resources */,
ABB0FBCC1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18012A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB796CE215CDCBA200C59155 /* Icon_OpenROM_420x420.png in Resources */,
AB796CE315CDCBA200C59155 /* Icon_Reset_420x420.png in Resources */,
AB796CE415CDCBA200C59155 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7284,6 +7318,7 @@
AB790036215B84E50082AE82 /* Icon_Input_420x420.png in Resources */,
AB790037215B84E50082AE82 /* Icon_AutoholdSet_420x420.png in Resources */,
AB790038215B84E50082AE82 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18052A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB790039215B84E50082AE82 /* Icon_OpenROM_420x420.png in Resources */,
AB79003A215B84E50082AE82 /* Icon_Reset_420x420.png in Resources */,
AB79003B215B84E50082AE82 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7403,6 +7438,7 @@
AB8F3C5F1A53AC2600A80BF6 /* Icon_Input_420x420.png in Resources */,
AB8F3C601A53AC2600A80BF6 /* Icon_AutoholdSet_420x420.png in Resources */,
ABB0FBCE1A9EED350060C55A /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18022A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
AB8F3C621A53AC2600A80BF6 /* Icon_OpenROM_420x420.png in Resources */,
AB8F3C631A53AC2600A80BF6 /* Icon_Reset_420x420.png in Resources */,
AB8F3C641A53AC2600A80BF6 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7532,6 +7568,7 @@
ABC8588628273FEE00A03EA9 /* Icon_Input_420x420.png in Resources */,
ABC8588728273FEE00A03EA9 /* Icon_AutoholdSet_420x420.png in Resources */,
ABC8588828273FEE00A03EA9 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E18092A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
ABC8588928273FEE00A03EA9 /* Icon_OpenROM_420x420.png in Resources */,
ABC8588A28273FEE00A03EA9 /* Icon_Reset_420x420.png in Resources */,
ABC8588B28273FEE00A03EA9 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7651,6 +7688,7 @@
ABD2CD3C26E05CB000FB15F7 /* Icon_Input_420x420.png in Resources */,
ABD2CD3D26E05CB000FB15F7 /* Icon_AutoholdSet_420x420.png in Resources */,
ABD2CD3E26E05CB000FB15F7 /* Icon_MicrophoneBlack_256x256.png in Resources */,
AB6E180A2A6B218D003A564D /* CheatDatabaseViewer.xib in Resources */,
ABD2CD3F26E05CB000FB15F7 /* Icon_OpenROM_420x420.png in Resources */,
ABD2CD4026E05CB000FB15F7 /* Icon_Reset_420x420.png in Resources */,
ABD2CD4126E05CB000FB15F7 /* Icon_RotateCCW_420x420.png in Resources */,
@ -7920,6 +7958,7 @@
8C43E7F027E3CD0100A35F65 /* ClientExecutionControl.cpp in Sources */,
8C43E7F127E3CD0100A35F65 /* rsemaphore.c in Sources */,
8C43E7F227E3CD0100A35F65 /* movie.cpp in Sources */,
AB6E17F72A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8C43E7F327E3CD0100A35F65 /* slot1comp_rom.cpp in Sources */,
8C43E7F427E3CD0100A35F65 /* NDSSystem.cpp in Sources */,
8C43E7F527E3CD0100A35F65 /* MacBaseCaptureTool.mm in Sources */,
@ -8162,6 +8201,7 @@
8C43E97827E3CD4C00A35F65 /* slot2_rumblepak.cpp in Sources */,
8C43E97927E3CD4C00A35F65 /* sndOSX.cpp in Sources */,
8C43E97A27E3CD4C00A35F65 /* SndOut.cpp in Sources */,
AB6E17F82A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8C43E97B27E3CD4C00A35F65 /* psnames.c in Sources */,
8C43E97C27E3CD4C00A35F65 /* Slot2WindowDelegate.mm in Sources */,
8C43E97D27E3CD4C00A35F65 /* truetype.c in Sources */,
@ -8319,6 +8359,7 @@
8CCD846127E40B730024BDD5 /* ClientExecutionControl.cpp in Sources */,
8CCD846227E40B730024BDD5 /* slot1.cpp in Sources */,
8CCD846327E40B730024BDD5 /* slot1_none.cpp in Sources */,
AB6E17FE2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
8CCD846427E40B730024BDD5 /* slot1_r4.cpp in Sources */,
8CCD846527E40B730024BDD5 /* cff.c in Sources */,
8CCD846627E40B730024BDD5 /* MacBaseCaptureTool.mm in Sources */,
@ -8653,6 +8694,7 @@
AB36C86B27F2C8AE00C763C8 /* macosx_10_5_compat.cpp in Sources */,
AB36C86C27F2C8AE00C763C8 /* OGLRender_3_2.cpp in Sources */,
AB36C86D27F2C8AE00C763C8 /* ftfntfmt.c in Sources */,
AB6E17FB2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB36C86E27F2C8AE00C763C8 /* EmuControllerDelegate.mm in Sources */,
AB36C86F27F2C8AE00C763C8 /* ClientAVCaptureObject.cpp in Sources */,
AB36C87027F2C8AE00C763C8 /* cocoa_GPU.mm in Sources */,
@ -8710,6 +8752,7 @@
AB79006E215B84E50082AE82 /* emufile.cpp in Sources */,
AB79006F215B84E50082AE82 /* fatdir.cpp in Sources */,
AB790070215B84E50082AE82 /* ftbase.c in Sources */,
AB6E17F92A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB790071215B84E50082AE82 /* fatfile.cpp in Sources */,
AB790072215B84E50082AE82 /* FIFO.cpp in Sources */,
AB790073215B84E50082AE82 /* sfnt.c in Sources */,
@ -9010,6 +9053,7 @@
AB790211215B84F20082AE82 /* type1.c in Sources */,
AB790212215B84F20082AE82 /* slot2_paddle.cpp in Sources */,
AB790213215B84F20082AE82 /* slot2_piano.cpp in Sources */,
AB6E17FA2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB790214215B84F20082AE82 /* slot2_rumblepak.cpp in Sources */,
AB790215215B84F20082AE82 /* sndOSX.cpp in Sources */,
AB790216215B84F20082AE82 /* SndOut.cpp in Sources */,
@ -9167,6 +9211,7 @@
AB796D0415CDCBA200C59155 /* emufile.cpp in Sources */,
AB796D0515CDCBA200C59155 /* fatdir.cpp in Sources */,
ABFEA8011BB4EC1000B08C25 /* ftbase.c in Sources */,
AB6E17F52A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB796D0615CDCBA200C59155 /* fatfile.cpp in Sources */,
AB796D0715CDCBA200C59155 /* FIFO.cpp in Sources */,
ABFEA8A31BB4EC1100B08C25 /* sfnt.c in Sources */,
@ -9467,6 +9512,7 @@
ABA731701BB51FDC00B26147 /* type1.c in Sources */,
AB8F3CBA1A53AC2600A80BF6 /* slot2_paddle.cpp in Sources */,
AB8F3CBB1A53AC2600A80BF6 /* slot2_piano.cpp in Sources */,
AB6E17F62A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
AB8F3CBC1A53AC2600A80BF6 /* slot2_rumblepak.cpp in Sources */,
AB8F3CBD1A53AC2600A80BF6 /* sndOSX.cpp in Sources */,
AB8F3CBE1A53AC2600A80BF6 /* SndOut.cpp in Sources */,
@ -9796,6 +9842,7 @@
ABC858BF28273FEE00A03EA9 /* filetime.cpp in Sources */,
ABC858C028273FEE00A03EA9 /* FIRFilter.cpp in Sources */,
ABC858C128273FEE00A03EA9 /* firmware.cpp in Sources */,
AB6E17FC2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
ABC858C228273FEE00A03EA9 /* async_job.c in Sources */,
ABC858C328273FEE00A03EA9 /* gfx3d.cpp in Sources */,
ABC858C428273FEE00A03EA9 /* DisplayViewCALayer.mm in Sources */,
@ -10024,6 +10071,7 @@
ABD2CD7326E05CB000FB15F7 /* filetime.cpp in Sources */,
ABD2CD7426E05CB000FB15F7 /* FIRFilter.cpp in Sources */,
ABD2CD7526E05CB000FB15F7 /* firmware.cpp in Sources */,
AB6E17FD2A675BF1003A564D /* CheatDatabaseWindowController.mm in Sources */,
ABD2CD7626E05CB000FB15F7 /* async_job.c in Sources */,
ABD2CD7726E05CB000FB15F7 /* gfx3d.cpp in Sources */,
ABD2CD7826E05CB000FB15F7 /* DisplayViewCALayer.mm in Sources */,
@ -10239,6 +10287,14 @@
name = HID_usage_strings.plist;
sourceTree = "<group>";
};
AB6E17FF2A6B218D003A564D /* CheatDatabaseViewer.xib */ = {
isa = PBXVariantGroup;
children = (
AB6E18002A6B218D003A564D /* English */,
);
name = CheatDatabaseViewer.xib;
sourceTree = "<group>";
};
AB8967DB16D2ED2700F826F1 /* DisplayWindow.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -1558,6 +1558,11 @@
ABD59849187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABD5984A187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABD5984B187D4A6C00069403 /* Icon_PaddleKnob_256x256.png in Resources */ = {isa = PBXBuildFile; fileRef = ABD59846187D4A6C00069403 /* Icon_PaddleKnob_256x256.png */; };
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */; };
ABECB50918A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
ABECB50A18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
ABECB50B18A460710052D52A /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABECB50818A460710052D52A /* xbrz.cpp */; };
@ -1572,6 +1577,11 @@
ABEF84831873578F00E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEF84841873579400E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEF84851873579700E99ADC /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB8C6E56186CD07E00E3EC64 /* ForceFeedback.framework */; };
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */ = {isa = PBXBuildFile; fileRef = ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */; };
ABF50ABA169F5FDA0018C08D /* assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7B169F5FDA0018C08D /* assembler.cpp */; };
ABF50ABB169F5FDA0018C08D /* assert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7D169F5FDA0018C08D /* assert.cpp */; };
ABF50ABC169F5FDA0018C08D /* buffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABF50A7F169F5FDA0018C08D /* buffer.cpp */; };
@ -2326,6 +2336,8 @@
ABE6702A1415DE6C00E8E4C9 /* tinyxmlparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyxmlparser.cpp; sourceTree = "<group>"; };
ABE7F53C13EE1C7900FD3A71 /* cocoa_firmware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_firmware.h; sourceTree = "<group>"; };
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_firmware.mm; sourceTree = "<group>"; };
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheatDatabaseWindowController.h; sourceTree = "<group>"; };
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CheatDatabaseWindowController.mm; sourceTree = "<group>"; };
ABECB50718A460710052D52A /* xbrz.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xbrz.h; sourceTree = "<group>"; };
ABECB50818A460710052D52A /* xbrz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbrz.cpp; sourceTree = "<group>"; };
ABECB51218A460910052D52A /* OGLDisplayOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OGLDisplayOutput.h; sourceTree = "<group>"; };
@ -2334,6 +2346,7 @@
ABEFCF5E141AB82A000CC0CD /* AppIcon_DeSmuME.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_DeSmuME.icns; sourceTree = "<group>"; };
ABEFCF5F141AB82A000CC0CD /* AppIcon_NintendoDS_ROM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_NintendoDS_ROM.icns; sourceTree = "<group>"; };
ABEFCF60141AB82A000CC0CD /* AppIcon_SaveState.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon_SaveState.icns; sourceTree = "<group>"; };
ABEFFDDD2A78CB67009C3A2D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = translations/English.lproj/CheatDatabaseViewer.xib; sourceTree = "<group>"; };
ABF50A74169F5FDA0018C08D /* AsmJit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsmJit.h; sourceTree = "<group>"; };
ABF50A75169F5FDA0018C08D /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = "<group>"; };
ABF50A76169F5FDA0018C08D /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
@ -2657,6 +2670,7 @@
AB05E8201BBFD41200065D18 /* source-sans-pro */,
ABC2ECD613B1C87000FAAA2A /* Images */,
AB00E87C14205EBC00DE561F /* MainMenu.xib */,
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */,
AB700DB816CDDBC400FBD336 /* DisplayWindow.xib */,
AB350D3A147A1D93007165AC /* HID_usage_strings.plist */,
8D1107310486CEB800E47090 /* Info.plist */,
@ -3199,6 +3213,7 @@
isa = PBXGroup;
children = (
AB3ACB6614C2361100D7D192 /* appDelegate.h */,
ABEBCE352A703E260028CE8A /* CheatDatabaseWindowController.h */,
AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */,
AB3E69811E25FBBF00D4CC75 /* DisplayViewCALayer.h */,
AB700DDC16CDE4C300FBD336 /* DisplayWindowController.h */,
@ -3217,6 +3232,7 @@
ABA0356E169127BB00817C69 /* troubleshootingWindowDelegate.h */,
AB4B5A1F217E47E400381363 /* WifiSettingsPanel.h */,
AB3ACB6714C2361100D7D192 /* appDelegate.mm */,
ABEBCE362A703E260028CE8A /* CheatDatabaseWindowController.mm */,
AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */,
AB3E69821E25FBBF00D4CC75 /* DisplayViewCALayer.mm */,
AB700DDD16CDE4C300FBD336 /* DisplayWindowController.mm */,
@ -4014,6 +4030,7 @@
ABA1659B2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA1659C2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78942809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDDF2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4133,6 +4150,7 @@
ABA165A92808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165AA2808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78952809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE02A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4252,6 +4270,7 @@
ABA165D32808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165D42808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78982809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDDE2A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4371,6 +4390,7 @@
ABA165C52808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165C62808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78972809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE22A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4490,6 +4510,7 @@
ABA165B72808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16.png in Resources */,
ABA165B82808BD6A00C8CFF5 /* Icon_VolumeTwoThird_DarkMode_16x16@2x.png in Resources */,
AB6D78962809FA43007C6B0A /* Icon_MicrophoneIdleNoHardware_256x256.png in Resources */,
ABEFFDE12A78CB67009C3A2D /* CheatDatabaseViewer.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4835,6 +4856,7 @@
ABD1267720AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267820AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A22217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE382A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5029,6 +5051,7 @@
ABD1267920AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267A20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A23217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE392A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5253,6 +5276,7 @@
ABD1267520AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267620AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A21217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE372A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5477,6 +5501,7 @@
ABD1267D20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267E20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A25217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE3B2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5671,6 +5696,7 @@
ABD1267B20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
ABD1267C20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
AB4B5A24217E47E400381363 /* WifiSettingsPanel.mm in Sources */,
ABEBCE3A2A703E260028CE8A /* CheatDatabaseWindowController.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5717,6 +5743,14 @@
name = Localizable.strings;
sourceTree = "<group>";
};
ABEFFDDC2A78CB67009C3A2D /* CheatDatabaseViewer.xib */ = {
isa = PBXVariantGroup;
children = (
ABEFFDDD2A78CB67009C3A2D /* English */,
);
name = CheatDatabaseViewer.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@ -4,6 +4,8 @@
<dict>
<key>Advanscene_AutoDetectRomSaveType</key>
<true/>
<key>CheatDatabase_RecentFilePath</key>
<array/>
<key>CoreControl_EnableAutoFrameSkip</key>
<true/>
<key>CoreControl_FramesToSkipSetting</key>

View File

@ -18,9 +18,11 @@
#include <string>
#include <vector>
#import <Cocoa/Cocoa.h>
#include "../../cheatSystem.h"
#undef BOOL
#import <Cocoa/Cocoa.h>
class CHEATS;
class CHEATS_LIST;
class CHEATSEARCH;
@ -54,16 +56,6 @@ enum CheatSearchCompareStyle
CheatSearchCompareStyle_NotEquals = 3
};
enum CheatSystemError
{
CheatSystemError_NoError = 0,
CheatSystemError_FileOpenFailed = 1,
CheatSystemError_FileFormatInvalid = 2,
CheatSystemError_CheatNotFound = 3,
CheatSystemError_ExportError = 4,
CheatSystemError_FileSaveFailed = 5
};
union DesmumeCheatSearchItem
{
uint64_t data;
@ -95,8 +87,8 @@ protected:
bool _willAddFromDB;
CheatType _cheatType;
std::string _descriptionMajorString;
std::string _descriptionMinorString;
std::string _nameString;
std::string _commentString;
// Internal cheat type parameters
CheatFreezeType _freezeType;
@ -133,8 +125,11 @@ public:
void SetType(CheatType requestedType);
bool IsSupportedType() const;
const char* GetMajorDescription() const;
void SetMajorDescription(const char *descriptionString);
const char* GetName() const;
void SetName(const char *nameString);
const char* GetComments() const;
void SetComments(const char *commentString);
CheatFreezeType GetFreezeType() const;
void SetFreezeType(CheatFreezeType theFreezeType);
@ -346,6 +341,8 @@ public:
- (void) destroyWorkingCopy;
- (void) mergeToParent;
+ (void) setIconDirectory:(NSImage *)iconImage;
+ (NSImage *) iconDirectory;
+ (void) setIconInternalCheat:(NSImage *)iconImage;
+ (NSImage *) iconInternalCheat;
+ (void) setIconActionReplay:(NSImage *)iconImage;
@ -355,11 +352,83 @@ public:
@end
@interface CocoaDSCheatDBEntry : NSObject
{
CheatDBEntry *_dbEntry;
CocoaDSCheatDBEntry *parent;
NSMutableArray *child;
NSInteger willAdd;
NSString *codeString;
BOOL needSetMixedState;
}
@property (readonly, nonatomic) NSString *name;
@property (readonly, nonatomic) NSString *comment;
@property (readonly, nonatomic) NSImage *icon;
@property (readonly, nonatomic) NSInteger entryCount;
@property (readonly, nonatomic) NSString *codeString;
@property (readonly, nonatomic) BOOL isDirectory;
@property (readonly, nonatomic) BOOL isCheatItem;
@property (assign) NSInteger willAdd;
@property (assign) BOOL needSetMixedState;
@property (assign) CocoaDSCheatDBEntry *parent;
@property (readonly, nonatomic) NSMutableArray *child;
- (id) initWithDBEntry:(const CheatDBEntry *)dbEntry;
- (ClientCheatItem *) newClientItem;
@end
@interface CocoaDSCheatDBGame : NSObject
{
CheatDBGame *_dbGame;
CocoaDSCheatDBEntry *entryRoot;
NSUInteger index;
}
@property (assign) NSUInteger index;
@property (readonly, nonatomic) NSString *title;
@property (readonly, nonatomic) NSString *serial;
@property (readonly, nonatomic) NSUInteger crc;
@property (readonly, nonatomic) NSString *crcString;
@property (readonly, nonatomic) NSInteger dataSize;
@property (readonly, nonatomic) NSString *dataSizeString;
@property (readonly, nonatomic) BOOL isDataLoaded;
@property (readonly, nonatomic) NSInteger cheatItemCount;
@property (readonly, nonatomic) CocoaDSCheatDBEntry *entryRoot;
- (id) initWithGameEntry:(const CheatDBGame *)gameEntry;
- (CocoaDSCheatDBEntry *) loadEntryDataFromFilePtr:(FILE *)fp isEncrypted:(BOOL)isEncrypted;
@end
@interface CocoaDSCheatDatabase : NSObject
{
CheatDBFile *_dbFile;
CheatDBGameList *_dbGameList;
NSMutableArray *gameList;
NSURL *lastFileURL;
}
@property (readonly) NSURL *lastFileURL;
@property (readonly, nonatomic) NSString *description;
@property (readonly, nonatomic) NSString *formatString;
@property (readonly, nonatomic) BOOL isEncrypted;
@property (readonly) NSMutableArray *gameList;
- (id) initWithFileURL:(NSURL *)fileURL error:(CheatSystemError *)errorCode;
- (CocoaDSCheatDBGame *) getGameEntryUsingCode:(const char *)gameCode crc:(NSUInteger)crc;
- (CocoaDSCheatDBEntry *) loadGameEntry:(CocoaDSCheatDBGame *)dbGame;
@end
@interface CocoaDSCheatManager : NSObject
{
ClientCheatManager *_internalCheatManager;
NSMutableArray *sessionList;
NSMutableArray *databaseList;
NSMutableArray *searchResultsList;
pthread_rwlock_t *rwlockCoreExecute;
@ -367,11 +436,10 @@ public:
@property (readonly, nonatomic, getter=internalManager) ClientCheatManager *_internalCheatManager;
@property (readonly) NSMutableArray *sessionList;
@property (readonly, nonatomic) NSString *currentGameCode;
@property (readonly, nonatomic) NSUInteger currentGameCRC;
@property (readonly, nonatomic) NSUInteger itemTotalCount;
@property (readonly, nonatomic) NSUInteger itemActiveCount;
@property (readonly) NSMutableArray *databaseList;
@property (readonly, nonatomic) NSString *databaseTitle;
@property (readonly, nonatomic) NSString *databaseDate;
@property (readonly) NSMutableArray *searchResultsList;
@property (readonly, nonatomic) BOOL searchDidStart;
@property (readonly, nonatomic) NSUInteger searchCount;
@ -390,8 +458,7 @@ public:
- (void) loadFromMaster;
- (void) applyToMaster;
- (NSMutableArray *) databaseListLoadFromFile:(NSURL *)fileURL errorCode:(NSInteger *)error;
- (NSUInteger) databaseAddSelected;
- (NSUInteger) databaseAddSelectedInEntry:(CocoaDSCheatDBEntry *)theEntry;
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (NSUInteger) runComparativeSearch:(NSInteger)typeID byteSize:(UInt8)byteSize signType:(NSInteger)signType;

View File

@ -20,7 +20,6 @@
#import "cocoa_globals.h"
#import "cocoa_util.h"
#include "../../cheatSystem.h"
#include "../../MMU.h"
#undef BOOL
@ -178,8 +177,8 @@ ClientCheatItem::ClientCheatItem()
_willAddFromDB = false;
_cheatType = CheatType_Internal;
_descriptionMajorString = "No description.";
_descriptionMinorString = "";
_nameString = "No description.";
_commentString = "";
_freezeType = CheatFreezeType_Normal;
_address = 0x02000000;
strncpy(_addressString, "0x02000000", sizeof(_addressString));
@ -203,8 +202,8 @@ void ClientCheatItem::Init(const CHEATS_LIST &inCheatItem)
this->_isEnabled = (inCheatItem.enabled) ? true : false;
this->_cheatType = (CheatType)inCheatItem.type;
this->_descriptionMajorString = inCheatItem.description;
this->_descriptionMinorString = "";
this->_nameString = inCheatItem.description;
this->_commentString = "";
this->_freezeType = (CheatFreezeType)inCheatItem.freezeType;
this->_valueLength = inCheatItem.size + 1; // CHEATS_LIST.size value range is [1...4], but starts counting from 0.
@ -240,7 +239,8 @@ void ClientCheatItem::Init(const CHEATS_LIST &inCheatItem)
void ClientCheatItem::Init(const ClientCheatItem &inCheatItem)
{
this->SetEnabled(inCheatItem.IsEnabled());
this->SetMajorDescription(inCheatItem.GetMajorDescription());
this->SetName(inCheatItem.GetName());
this->SetComments(inCheatItem.GetComments());
this->SetType(inCheatItem.GetType());
this->SetFreezeType(inCheatItem.GetFreezeType());
@ -324,20 +324,37 @@ bool ClientCheatItem::IsSupportedType() const
return (this->_cheatType != CheatType_CodeBreaker);
}
const char* ClientCheatItem::GetMajorDescription() const
const char* ClientCheatItem::GetName() const
{
return this->_descriptionMajorString.c_str();
return this->_nameString.c_str();
}
void ClientCheatItem::SetMajorDescription(const char *descriptionString)
void ClientCheatItem::SetName(const char *nameString)
{
if (descriptionString == NULL)
if (nameString == NULL)
{
this->_descriptionMajorString = "";
this->_nameString = "";
}
else
{
this->_descriptionMajorString = descriptionString;
this->_nameString = nameString;
}
}
const char* ClientCheatItem::GetComments() const
{
return this->_commentString.c_str();
}
void ClientCheatItem::SetComments(const char *commentString)
{
if (commentString == NULL)
{
this->_commentString = "";
}
else
{
this->_commentString = commentString;
}
}
@ -610,7 +627,7 @@ void ClientCheatItem::ClientToDesmumeCheatItem(CHEATS_LIST *outCheatItem) const
outCheatItem->type = this->_cheatType;
outCheatItem->enabled = (this->_isEnabled) ? 1 : 0;
strncpy(outCheatItem->description, this->_descriptionMajorString.c_str(), sizeof(outCheatItem->description));
strncpy(outCheatItem->description, this->_nameString.c_str(), sizeof(outCheatItem->description));
switch (this->_cheatType)
{
@ -1110,7 +1127,7 @@ ClientCheatList* ClientCheatDatabase::LoadFromFile(const char *dbFilePath)
}
else
{
dbError = (CheatSystemError)exporter->getErrorCode();
dbError = exporter->getErrorCode();
}
delete exporter;
@ -1244,11 +1261,11 @@ ClientCheatItem* ClientCheatManager::NewItem()
char newDesc[16];
snprintf(newDesc, sizeof(newDesc), "Untitled %ld", (unsigned long)this->_untitledCount);
newItem->SetMajorDescription(newDesc);
newItem->SetName(newDesc);
}
else
{
newItem->SetMajorDescription("Untitled");
newItem->SetName("Untitled");
}
if (newItem->IsEnabled())
@ -1511,6 +1528,7 @@ void ClientCheatManager::ApplyPendingInternalCheatWrites()
@implementation CocoaDSCheatItem
static NSImage *iconDirectory = nil;
static NSImage *iconInternalCheat = nil;
static NSImage *iconActionReplay = nil;
static NSImage *iconCodeBreaker = nil;
@ -1625,18 +1643,18 @@ static NSImage *iconCodeBreaker = nil;
- (NSString *) description
{
return [NSString stringWithCString:_internalData->GetMajorDescription() encoding:NSUTF8StringEncoding];
return [NSString stringWithCString:_internalData->GetName() encoding:NSUTF8StringEncoding];
}
- (void) setDescription:(NSString *)desc
{
if (desc == nil)
{
_internalData->SetMajorDescription(NULL);
_internalData->SetName(NULL);
}
else
{
_internalData->SetMajorDescription([desc cStringUsingEncoding:NSUTF8StringEncoding]);
_internalData->SetName([desc cStringUsingEncoding:NSUTF8StringEncoding]);
}
if ((workingCopy != nil) && !_disableWorkingCopyUpdate)
@ -1647,7 +1665,7 @@ static NSImage *iconCodeBreaker = nil;
- (char *) descriptionCString
{
return (char *)_internalData->GetMajorDescription();
return (char *)_internalData->GetName();
}
- (NSInteger) cheatType
@ -1661,7 +1679,7 @@ static NSImage *iconCodeBreaker = nil;
switch (theType)
{
case CHEAT_TYPE_INTERNAL:
case CheatType_Internal:
[self setCheatTypeIcon:iconInternalCheat];
[self setIsSupportedCheatType:YES];
[self setMemAddress:[self memAddress]];
@ -1669,13 +1687,13 @@ static NSImage *iconCodeBreaker = nil;
[self setBytes:[self bytes]];
break;
case CHEAT_TYPE_ACTION_REPLAY:
case CheatType_ActionReplay:
[self setCheatTypeIcon:iconActionReplay];
[self setIsSupportedCheatType:YES];
[self setCode:[self code]];
break;
case CHEAT_TYPE_CODE_BREAKER:
case CheatType_CodeBreaker:
[self setCheatTypeIcon:iconCodeBreaker];
[self setIsSupportedCheatType:NO];
[self setCode:[self code]];
@ -1702,15 +1720,15 @@ static NSImage *iconCodeBreaker = nil;
switch ([self cheatType])
{
case CHEAT_TYPE_INTERNAL:
case CheatType_Internal:
theIcon = iconInternalCheat;
break;
case CHEAT_TYPE_ACTION_REPLAY:
case CheatType_ActionReplay:
theIcon = iconActionReplay;
break;
case CHEAT_TYPE_CODE_BREAKER:
case CheatType_CodeBreaker:
theIcon = iconCodeBreaker;
break;
@ -1874,7 +1892,7 @@ static NSImage *iconCodeBreaker = nil;
[self setCheatType:[self cheatType]];
[self setFreezeType:[self freezeType]];
if ([self cheatType] == CHEAT_TYPE_INTERNAL)
if ([self cheatType] == CheatType_Internal)
{
[self setMemAddressSixDigitString:[self memAddressSixDigitString]];
[self setValue:[self value]];
@ -1903,7 +1921,7 @@ static NSImage *iconCodeBreaker = nil;
[self setCheatType:[cdsCheatItem cheatType]];
[self setFreezeType:[cdsCheatItem freezeType]];
if ([self cheatType] == CHEAT_TYPE_INTERNAL)
if ([self cheatType] == CheatType_Internal)
{
[self setMemAddress:[cdsCheatItem memAddress]];
[self setValue:[cdsCheatItem value]];
@ -1952,6 +1970,16 @@ static NSImage *iconCodeBreaker = nil;
[parent copyFrom:self];
}
+ (void) setIconDirectory:(NSImage *)iconImage
{
iconDirectory = iconImage;
}
+ (NSImage *) iconDirectory
{
return iconDirectory;
}
+ (void) setIconInternalCheat:(NSImage *)iconImage
{
iconInternalCheat = iconImage;
@ -1984,16 +2012,615 @@ static NSImage *iconCodeBreaker = nil;
@end
@implementation CocoaDSCheatDBEntry
@dynamic name;
@dynamic comment;
@dynamic icon;
@dynamic entryCount;
@dynamic codeString;
@dynamic isDirectory;
@dynamic isCheatItem;
@dynamic willAdd;
@synthesize needSetMixedState;
@synthesize parent;
@synthesize child;
- (id)init
{
return [self initWithDBEntry:NULL];
}
- (id) initWithDBEntry:(const CheatDBEntry *)dbEntry
{
self = [super init];
if (self == nil)
{
return self;
}
if (dbEntry == NULL)
{
[self release];
self = nil;
return self;
}
if (dbEntry->codeLength == NULL)
{
const NSUInteger entryCount = dbEntry->child.size();
child = [[NSMutableArray alloc] initWithCapacity:entryCount];
if (child == nil)
{
[self release];
self = nil;
return self;
}
for (NSUInteger i = 0; i < entryCount; i++)
{
const CheatDBEntry &childEntry = dbEntry->child[i];
CocoaDSCheatDBEntry *newCocoaEntry = [[CocoaDSCheatDBEntry alloc] initWithDBEntry:&childEntry];
[newCocoaEntry setParent:self];
[child addObject:newCocoaEntry];
}
}
else
{
child = nil;
}
_dbEntry = (CheatDBEntry *)dbEntry;
codeString = nil;
willAdd = NO;
needSetMixedState = NO;
parent = nil;
return self;
}
- (void)dealloc
{
[child release];
child = nil;
[codeString release];
codeString = nil;
[super dealloc];
}
- (NSString *) name
{
if (_dbEntry->name != NULL)
{
return [NSString stringWithCString:_dbEntry->name encoding:NSUTF8StringEncoding];
}
return @"";
}
- (NSString *) comment
{
if (_dbEntry->note != NULL)
{
return [NSString stringWithCString:_dbEntry->note encoding:NSUTF8StringEncoding];
}
return @"";
}
- (NSImage *) icon
{
if (_dbEntry->codeLength == NULL)
{
return [CocoaDSCheatItem iconDirectory];
}
return [CocoaDSCheatItem iconActionReplay];
}
- (NSInteger) entryCount
{
return (NSInteger)_dbEntry->child.size();
}
- (NSString *) codeString
{
if ( (codeString == nil) && [self isCheatItem] )
{
char codeStr[8+8+1+1+1] = {0};
const size_t codeCount = *_dbEntry->codeLength / 2;
u32 code0 = _dbEntry->codeData[0];
u32 code1 = _dbEntry->codeData[1];
snprintf(codeStr, sizeof(codeStr), "%08X %08X", code0, code1);
std::string code = codeStr;
for (size_t i = 1; i < codeCount; i++)
{
code0 = _dbEntry->codeData[(i * 2) + 0];
code1 = _dbEntry->codeData[(i * 2) + 1];
snprintf(codeStr, sizeof(codeStr), "\n%08X %08X", code0, code1);
code += codeStr;
}
codeString = [[NSString alloc] initWithCString:code.c_str() encoding:NSUTF8StringEncoding];
}
return codeString;
}
- (BOOL) isDirectory
{
return (_dbEntry->codeLength == NULL) ? YES : NO;
}
- (BOOL) isCheatItem
{
return (_dbEntry->codeLength != NULL) ? YES : NO;
}
- (void) setWillAdd:(NSInteger)theState
{
if ((theState == GUI_STATE_MIXED) && ![self needSetMixedState])
{
theState = GUI_STATE_ON;
}
if (willAdd == theState)
{
return;
}
else
{
willAdd = theState;
}
if (theState == GUI_STATE_MIXED)
{
if (parent != nil)
{
[parent willChangeValueForKey:@"willAdd"];
[parent setNeedSetMixedState:YES];
[parent setWillAdd:GUI_STATE_MIXED];
[parent setNeedSetMixedState:NO];
[parent didChangeValueForKey:@"willAdd"];
}
return;
}
if (_dbEntry->codeLength == NULL)
{
for (CocoaDSCheatDBEntry *childEntry in child)
{
[childEntry willChangeValueForKey:@"willAdd"];
[childEntry setWillAdd:theState];
[childEntry didChangeValueForKey:@"willAdd"];
}
}
if (parent != nil)
{
NSInteger firstEntryState = [(CocoaDSCheatDBEntry *)[[parent child] objectAtIndex:0] willAdd];
BOOL isMixedStateFound = (firstEntryState == GUI_STATE_MIXED);
if (!isMixedStateFound)
{
for (CocoaDSCheatDBEntry *childEntry in [parent child])
{
const NSInteger childEntryState = [childEntry willAdd];
isMixedStateFound = (firstEntryState != childEntryState) || (childEntryState == GUI_STATE_MIXED);
if (isMixedStateFound)
{
[parent willChangeValueForKey:@"willAdd"];
[parent setNeedSetMixedState:YES];
[parent setWillAdd:GUI_STATE_MIXED];
[parent setNeedSetMixedState:NO];
[parent didChangeValueForKey:@"willAdd"];
break;
}
}
}
if (!isMixedStateFound)
{
[parent willChangeValueForKey:@"willAdd"];
[parent setWillAdd:firstEntryState];
[parent didChangeValueForKey:@"willAdd"];
}
}
}
- (NSInteger) willAdd
{
return willAdd;
}
- (ClientCheatItem *) newClientItem
{
ClientCheatItem *newItem = NULL;
if (![self isCheatItem])
{
return newItem;
}
newItem = new ClientCheatItem;
newItem->SetType(CheatType_ActionReplay); // Default to Action Replay for now
newItem->SetFreezeType(CheatFreezeType_Normal);
newItem->SetEnabled(false);
newItem->SetComments(_dbEntry->note);
CheatDBEntry *entryParent = _dbEntry->parent;
// TODO: Replace this flattening out of names/comments with separated names/comments and tags.
std::string descString = "";
std::string itemString = "";
if ( ((_dbEntry->name != NULL) && (*_dbEntry->name != '\0')) ||
((_dbEntry->note != NULL) && (*_dbEntry->note != '\0')) )
{
if ( (_dbEntry->name != NULL) && (*_dbEntry->name != '\0') )
{
itemString += _dbEntry->name;
}
if ( (_dbEntry->note != NULL) && (*_dbEntry->note != '\0') )
{
if ( (_dbEntry->name != NULL) && (*_dbEntry->name != '\0') )
{
itemString += " | ";
}
itemString += _dbEntry->note;
}
}
else
{
itemString = "No description.";
}
// If this entry is root or child of root, then don't add the directory
// name or comments to the new cheat item's description.
if ( (entryParent == NULL) || (entryParent->parent == NULL) )
{
descString = itemString;
}
else
{
if ( (entryParent->name != NULL) && (*entryParent->name != '\0') )
{
descString += entryParent->name;
}
if ( (entryParent->note != NULL) && (*entryParent->note != '\0') )
{
if ( (entryParent->name != NULL) && (*entryParent->name != '\0') )
{
descString += " ";
}
descString += "[";
descString += entryParent->note;
descString += "]";
}
descString += ": ";
descString += itemString;
}
newItem->SetName(descString.c_str());
newItem->SetRawCodeString([[self codeString] cStringUsingEncoding:NSUTF8StringEncoding], true);
return newItem;
}
@end
@implementation CocoaDSCheatDBGame
@synthesize index;
@dynamic title;
@dynamic serial;
@dynamic crc;
@dynamic crcString;
@dynamic dataSize;
@dynamic isDataLoaded;
@dynamic cheatItemCount;
@synthesize entryRoot;
- (id)init
{
return [self initWithGameEntry:NULL];
}
- (id) initWithGameEntry:(const CheatDBGame *)gameEntry
{
self = [super init];
if (self == nil)
{
return self;
}
_dbGame = (CheatDBGame *)gameEntry;
entryRoot = nil;
index = 0;
return self;
}
- (void)dealloc
{
[entryRoot release];
entryRoot = nil;
[super dealloc];
}
- (NSString *) title
{
return [NSString stringWithCString:_dbGame->GetTitle() encoding:NSUTF8StringEncoding];
}
- (NSString *) serial
{
return [NSString stringWithCString:_dbGame->GetSerial() encoding:NSUTF8StringEncoding];
}
- (NSUInteger) crc
{
return (NSUInteger)_dbGame->GetCRC();
}
- (NSString *) crcString
{
const u32 crc = _dbGame->GetCRC();
return [NSString stringWithFormat:@"%08lX", (unsigned long)crc];
}
- (NSInteger) dataSize
{
return (NSInteger)_dbGame->GetRawDataSize();
}
- (NSString *) dataSizeString
{
const u32 dataSize = _dbGame->GetRawDataSize();
const float dataSizeKB = (float)dataSize / 1024.0f;
if (dataSize > ((1024 * 100) - 1))
{
return [NSString stringWithFormat:@"%1.1f KB", dataSizeKB];
}
else if (dataSize > ((1024 * 10) - 1))
{
return [NSString stringWithFormat:@"%1.2f KB", dataSizeKB];
}
return [NSString stringWithFormat:@"%lu bytes", (unsigned long)dataSize];
}
- (BOOL) isDataLoaded
{
return (_dbGame->IsEntryDataLoaded()) ? YES : NO;
}
- (NSInteger) cheatItemCount
{
return (NSInteger)_dbGame->GetCheatItemCount();
}
- (CocoaDSCheatDBEntry *) loadEntryDataFromFilePtr:(FILE *)fp isEncrypted:(BOOL)isEncrypted
{
[entryRoot release];
entryRoot = nil;
u8 *entryData = _dbGame->LoadEntryData(fp, (isEncrypted) ? true : false);
if (entryData == NULL)
{
return entryRoot;
}
entryRoot = [[CocoaDSCheatDBEntry alloc] initWithDBEntry:&_dbGame->GetEntryRoot()];
return entryRoot;
}
@end
@implementation CocoaDSCheatDatabase
@synthesize lastFileURL;
@dynamic description;
@dynamic formatString;
@dynamic isEncrypted;
@synthesize gameList;
- (id)init
{
return [self initWithFileURL:nil error:NULL];
}
- (id) initWithFileURL:(NSURL *)fileURL error:(CheatSystemError *)errorCode
{
self = [super init];
if (self == nil)
{
return self;
}
if (fileURL == nil)
{
[self release];
self = nil;
return self;
}
lastFileURL = [fileURL copy];
CheatDBFile *newDBFile = new CheatDBFile();
if (newDBFile == NULL)
{
[lastFileURL release];
[self release];
self = nil;
return self;
}
CheatSystemError error = newDBFile->OpenFile([CocoaDSUtil cPathFromFileURL:fileURL]);
if (error != CheatSystemError_NoError)
{
delete newDBFile;
if (errorCode != nil)
{
*errorCode = error;
}
[lastFileURL release];
[self release];
self = nil;
return self;
}
_dbGameList = new CheatDBGameList;
if (_dbGameList == NULL)
{
delete newDBFile;
if (errorCode == nil)
{
*errorCode = error;
}
[lastFileURL release];
[self release];
self = nil;
return self;
}
newDBFile->LoadGameList(NULL, 0, *_dbGameList);
const size_t gameCount = _dbGameList->size();
gameList = [[NSMutableArray alloc] initWithCapacity:gameCount];
if (gameList == nil)
{
delete newDBFile;
if (errorCode == nil)
{
*errorCode = error;
}
[lastFileURL release];
[self release];
self = nil;
return self;
}
for (size_t i = 0; i < gameCount; i++)
{
const CheatDBGame &dbGame = (*_dbGameList)[i];
CocoaDSCheatDBGame *newCocoaDBGame = [[[CocoaDSCheatDBGame alloc] initWithGameEntry:&dbGame] autorelease];
[gameList addObject:newCocoaDBGame];
[newCocoaDBGame setIndex:[gameList indexOfObject:newCocoaDBGame]];
}
_dbFile = newDBFile;
return self;
}
- (void)dealloc
{
[gameList release];
[lastFileURL release];
delete _dbGameList;
_dbGameList = NULL;
delete _dbFile;
_dbFile = NULL;
[super dealloc];
}
- (NSString *) description
{
return [NSString stringWithCString:_dbFile->GetDescription() encoding:NSUTF8StringEncoding];
}
- (NSString *) formatString
{
return [NSString stringWithCString:_dbFile->GetFormatString() encoding:NSUTF8StringEncoding];
}
- (BOOL) isEncrypted
{
return (_dbFile->IsEncrypted()) ? YES : NO;
}
- (CocoaDSCheatDBGame *) getGameEntryUsingCode:(const char *)gameCode crc:(NSUInteger)crc
{
if (gameCode == nil)
{
return nil;
}
const char gameCodeTerminated[5] = {
gameCode[0],
gameCode[1],
gameCode[2],
gameCode[3],
'\0'
};
NSString *gameCodeString = [NSString stringWithCString:gameCodeTerminated encoding:NSUTF8StringEncoding];
for (CocoaDSCheatDBGame *dbGame in gameList)
{
if ( ([dbGame crc] == crc) && [[dbGame serial] isEqualToString:gameCodeString] )
{
return dbGame;
}
}
return nil;
}
- (CocoaDSCheatDBEntry *) loadGameEntry:(CocoaDSCheatDBGame *)dbGame
{
CocoaDSCheatDBEntry *entryRoot = nil;
if (dbGame == nil)
{
return entryRoot;
}
else if ([dbGame isDataLoaded])
{
entryRoot = [dbGame entryRoot];
}
else
{
entryRoot = [dbGame loadEntryDataFromFilePtr:_dbFile->GetFilePtr() isEncrypted:_dbFile->IsEncrypted()];
}
return entryRoot;
}
@end
@implementation CocoaDSCheatManager
@synthesize _internalCheatManager;
@synthesize sessionList;
@dynamic currentGameCode;
@dynamic currentGameCRC;
@dynamic itemTotalCount;
@dynamic itemActiveCount;
@synthesize databaseList;
@dynamic databaseTitle;
@dynamic databaseDate;
@synthesize searchResultsList;
@dynamic searchCount;
@dynamic searchDidStart;
@ -2023,20 +2650,10 @@ static NSImage *iconCodeBreaker = nil;
return self;
}
databaseList = [[NSMutableArray alloc] initWithCapacity:100];
if (databaseList == nil)
{
[sessionList release];
[self release];
self = nil;
return self;
}
searchResultsList = [[NSMutableArray alloc] initWithCapacity:100];
if (searchResultsList == nil)
{
[sessionList release];
[databaseList release];
[self release];
self = nil;
return self;
@ -2055,9 +2672,6 @@ static NSImage *iconCodeBreaker = nil;
[sessionList release];
sessionList = nil;
[databaseList release];
databaseList = nil;
[searchResultsList release];
searchResultsList = nil;
@ -2067,14 +2681,22 @@ static NSImage *iconCodeBreaker = nil;
[super dealloc];
}
- (NSString *) databaseTitle
- (NSString *) currentGameCode
{
return [NSString stringWithCString:_internalCheatManager->GetDatabaseTitle() encoding:NSUTF8StringEncoding];
const char gameCodeTerminated[5] = {
gameInfo.header.gameCode[0],
gameInfo.header.gameCode[1],
gameInfo.header.gameCode[2],
gameInfo.header.gameCode[3],
'\0'
};
return [NSString stringWithCString:gameCodeTerminated encoding:NSUTF8StringEncoding];
}
- (NSString *) databaseDate
- (NSUInteger) currentGameCRC
{
return [NSString stringWithCString:_internalCheatManager->GetDatabaseDescription() encoding:NSUTF8StringEncoding];
return (NSUInteger)gameInfo.crcForCheatsDb;
}
- (NSUInteger) itemTotalCount
@ -2251,59 +2873,38 @@ static NSImage *iconCodeBreaker = nil;
_internalCheatManager->ApplyToMaster();
}
- (NSMutableArray *) databaseListLoadFromFile:(NSURL *)fileURL errorCode:(NSInteger *)error
- (NSUInteger) databaseAddSelectedInEntry:(CocoaDSCheatDBEntry *)theEntry
{
if (fileURL == nil)
NSUInteger willAddCount = 0;
if (theEntry == nil)
{
return nil;
return willAddCount;
}
[self willChangeValueForKey:@"databaseTitle"];
[self willChangeValueForKey:@"databaseDate"];
ClientCheatList *dbList = _internalCheatManager->DatabaseListLoadFromFile([CocoaDSUtil cPathFromFileURL:fileURL]);
[self didChangeValueForKey:@"databaseTitle"];
[self didChangeValueForKey:@"databaseDate"];
if (dbList != NULL)
NSMutableArray *entryChildren = [theEntry child];
if (entryChildren == nil)
{
[databaseList removeAllObjects];
const size_t itemCount = dbList->GetTotalCheatCount();
for (size_t i = 0; i < itemCount; i++)
return willAddCount;
}
for (CocoaDSCheatDBEntry *entry in entryChildren)
{
if ([entry isDirectory])
{
CocoaDSCheatItem *cheatItem = [[CocoaDSCheatItem alloc] initWithCheatItem:dbList->GetItemAtIndex(i)];
if (cheatItem != nil)
{
[databaseList addObject:[cheatItem autorelease]];
}
willAddCount += [self databaseAddSelectedInEntry:entry];
}
}
return databaseList;
}
- (NSUInteger) databaseAddSelected
{
NSUInteger addedItemCount = 0;
for (CocoaDSCheatItem *dbItem in databaseList)
{
if ([dbItem willAdd])
else if ([entry willAdd])
{
ClientCheatItem *newCheatItem = new ClientCheatItem;
newCheatItem->Init(*[dbItem clientData]);
ClientCheatItem *newCheatItem = [entry newClientItem];
CocoaDSCheatItem *newCocoaCheatItem = [self addExistingItem:newCheatItem];
if (newCocoaCheatItem != nil)
{
addedItemCount++;
willAddCount++;
}
}
}
return addedItemCount;
return willAddCount;
}
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012-2022 DeSmuME Team
Copyright (C) 2012-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@
#define NSSTRING_TITLE_EXPORT_ROM_SAVE_PANEL NSLocalizedString(@"Export ROM Save File", nil)
#define NSSTRING_TITLE_SELECT_ROM_PANEL NSLocalizedString(@"Select ROM", nil)
#define NSSTRING_TITLE_SELECT_ADVANSCENE_DB_PANEL NSLocalizedString(@"Select ADVANsCEne Database", nil)
#define NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL NSLocalizedString(@"Select R4 Cheat Database", nil)
#define NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL NSLocalizedString(@"Open Cheat Database", nil)
#define NSSTRING_TITLE_SELECT_ARM7_IMAGE_PANEL NSLocalizedString(@"Select ARM7 BIOS Image", nil)
#define NSSTRING_TITLE_SELECT_ARM9_IMAGE_PANEL NSLocalizedString(@"Select ARM9 BIOS Image", nil)
#define NSSTRING_TITLE_SELECT_FIRMWARE_IMAGE_PANEL NSLocalizedString(@"Select Firmware Image", nil)
@ -303,41 +303,12 @@ enum
SPU_SYNC_METHOD_P = 2
};
enum
{
CHEAT_TYPE_INTERNAL = 0,
CHEAT_TYPE_ACTION_REPLAY = 1,
CHEAT_TYPE_CODE_BREAKER = 2
};
enum
{
CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE = 0,
CHEATSEARCH_SEARCHSTYLE_COMPARATIVE = 1
};
enum
{
CHEATSEARCH_COMPARETYPE_GREATER_THAN = 0,
CHEATSEARCH_COMPARETYPE_LESSER_THAN = 1,
CHEATSEARCH_COMPARETYPE_EQUALS_TO = 2,
CHEATSEARCH_COMPARETYPE_NOT_EQUALS_TO = 3
};
enum
{
CHEATSEARCH_UNSIGNED = 0,
CHEATSEARCH_SIGNED = 1
};
enum
{
CHEATEXPORT_ERROR_FILE_NOT_FOUND = 1,
CHEATEXPORT_ERROR_WRONG_FILE_FORMAT = 2,
CHEATEXPORT_ERROR_SERIAL_NOT_FOUND = 3,
CHEATEXPORT_ERROR_EXPORT_FAILED = 4
};
/*
PORT MESSAGES
*/

View File

@ -1199,7 +1199,8 @@ void UpdateDisplayPropertiesFromStates(uint64_t displayModeStates, ClientDisplay
ClientCheatItem *newCheatItem = new ClientCheatItem;
newCheatItem->SetType(CheatType_ActionReplay); // Default to Action Replay for now
newCheatItem->SetFreezeType(CheatFreezeType_Normal);
newCheatItem->SetMajorDescription(NULL); // OpenEmu takes care of this
newCheatItem->SetName(NULL); // OpenEmu takes care of this
newCheatItem->SetComments(NULL); // OpenEmu does not support cheat item comments
newCheatItem->SetRawCodeString([code cStringUsingEncoding:NSUTF8StringEncoding], true);
newCheatItem->SetEnabled((enabled) ? true : false);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/*
Copyright (C) 2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#import <Cocoa/Cocoa.h>
@class CocoaDSCheatDatabase;
@class CheatWindowDelegate;
@class CocoaDSCheatDBGame;
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
@interface CheatDatabaseWindowController : NSWindowController <NSWindowDelegate, NSTableViewDelegate>
#else
@interface CheatDatabaseWindowController : NSWindowController
#endif
{
NSObject *dummyObject;
NSWindow *errorSheet;
NSString *defaultWindowTitle;
NSArrayController *gameListController;
NSTreeController *entryListController;
NSSplitView *splitView;
NSTableView *gameTable;
NSOutlineView *entryOutline;
NSFont *codeViewerFont;
CheatWindowDelegate *cheatManagerDelegate;
CocoaDSCheatDatabase *database;
NSString *filePath;
BOOL isFileLoading;
BOOL isCurrentGameFound;
BOOL isSelectedGameTheCurrentGame;
NSInteger currentGameTableRowIndex;
NSString *currentGameIndexString;
NSString *errorMajorString;
NSString *errorMinorString;
NSDictionary *initProperties;
}
@property (readonly) IBOutlet NSObject *dummyObject;
@property (readonly) IBOutlet NSWindow *errorSheet;
@property (readonly) IBOutlet NSArrayController *gameListController;
@property (readonly) IBOutlet NSTreeController *entryListController;
@property (readonly) IBOutlet NSSplitView *splitView;
@property (readonly) IBOutlet NSTableView *gameTable;
@property (readonly) IBOutlet NSOutlineView *entryOutline;
@property (retain) CheatWindowDelegate *cheatManagerDelegate;
@property (assign) NSFont *codeViewerFont;
@property (retain, nonatomic) CocoaDSCheatDatabase *database;
@property (readonly) NSString *filePath;
@property (readonly) NSString *databaseFormatString;
@property (readonly) NSInteger gameCount;
@property (readonly) NSString *isEncryptedString;
@property (assign) BOOL isFileLoading;
@property (assign) BOOL isCurrentGameFound;
@property (assign) BOOL isSelectedGameTheCurrentGame;
@property (assign) NSString *errorMajorString;
@property (assign) NSString *errorMinorString;
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate;
- (void) loadFileStart:(NSURL *)theURL;
- (void) loadFileOnThread:(id)object;
- (void) loadFileDidFinish:(NSNotification *)aNotification;
- (void) updateWindow;
- (void) validateGameTableFonts;
+ (void) validateGameTableFontsForAllWindows;
- (BOOL) validateWillAddColumn;
+ (void) validateWillAddColumnForAllWindows;
- (void) showErrorSheet:(NSInteger)errorCode;
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
- (IBAction) openFile:(id)sender;
- (IBAction) selectAll:(id)sender;
- (IBAction) selectNone:(id)sender;
- (IBAction) addSelected:(id)sender;
- (IBAction) selectCurrentGame:(id)sender;
- (IBAction) closeErrorSheet:(id)sender;
@end

View File

@ -0,0 +1,759 @@
/*
Copyright (C) 2023 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#import "CheatDatabaseWindowController.h"
#import "cheatWindowDelegate.h"
#import "../cocoa_globals.h"
#import "../cocoa_cheat.h"
#import "../cocoa_util.h"
NSMutableArray *cheatDatabaseWindowList = nil;
@implementation CheatDatabaseWindowController
@synthesize dummyObject;
@synthesize errorSheet;
@synthesize gameListController;
@synthesize entryListController;
@synthesize splitView;
@synthesize gameTable;
@synthesize entryOutline;
@synthesize cheatManagerDelegate;
@synthesize codeViewerFont;
@dynamic database;
@dynamic filePath;
@dynamic databaseFormatString;
@dynamic gameCount;
@dynamic isEncryptedString;
@synthesize isFileLoading;
@synthesize isCurrentGameFound;
@synthesize isSelectedGameTheCurrentGame;
@synthesize errorMajorString;
@synthesize errorMinorString;
- (id) initWithWindowNibName:(NSString *)windowNibName delegate:(CheatWindowDelegate *)theDelegate
{
self = [super initWithWindowNibName:windowNibName];
if (self == nil)
{
return self;
}
cheatManagerDelegate = [theDelegate retain];
codeViewerFont = [NSFont fontWithName:@"Monaco" size:13.0];
dummyObject = nil;
defaultWindowTitle = [[NSString alloc] initWithString:@"Cheat Database Viewer"];
database = nil;
isFileLoading = NO;
isCurrentGameFound = NO;
isSelectedGameTheCurrentGame = NO;
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
currentGameTableRowIndex = NSNotFound;
errorMajorString = @"No error has occurred!";
errorMinorString = @"This is just a placeholder message for initialization purposes.";
if (cheatDatabaseWindowList == nil)
{
cheatDatabaseWindowList = [[NSMutableArray alloc] initWithObjects:self, nil];
}
else
{
[cheatDatabaseWindowList addObject:self];
}
return self;
}
- (void)dealloc
{
[self setCheatManagerDelegate:nil];
[self setDatabase:nil];
[currentGameIndexString release];
[defaultWindowTitle release];
[super dealloc];
}
- (void) loadFileStart:(NSURL *)theURL
{
if (theURL == nil)
{
return;
}
// First check if another cheat database window has already opened the file at this URL.
CheatDatabaseWindowController *foundWindowController = nil;
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
{
NSURL *databaseURL = [[windowController database] lastFileURL];
NSString *foundDatabaseFilePath = [databaseURL path];
if ( (foundDatabaseFilePath != nil) && ([foundDatabaseFilePath isEqualToString:[theURL path]]) )
{
foundWindowController = windowController;
break;
}
}
if (foundWindowController != nil)
{
// If the file is already open, then simply assign that database file to this window.
[self setDatabase:[foundWindowController database]];
[self updateWindow];
}
else
{
// If the file is not open, then we need to open it now. Let's do this on a separate
// thread so that we don't lock up the main thread.
[self setIsFileLoading:YES];
[self setDatabase:nil];
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[theURL absoluteString]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadFileDidFinish:)
name:fullThreadName
object:nil];
[theURL retain];
[NSThread detachNewThreadSelector:@selector(loadFileOnThread:) toTarget:self withObject:theURL];
}
}
- (void) loadFileOnThread:(id)object
{
NSAutoreleasePool *threadPool = [[NSAutoreleasePool alloc] init];
NSURL *workingURL = (NSURL *)object;
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
CheatSystemError error = CheatSystemError_NoError;
CocoaDSCheatDatabase *newDatabase = [[CocoaDSCheatDatabase alloc] initWithFileURL:workingURL error:&error];
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:
workingURL, @"URL",
[NSNumber numberWithInteger:(NSInteger)error], @"ErrorCode",
nil];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:fullThreadName object:newDatabase userInfo:userInfo];
[threadPool release];
}
- (void) loadFileDidFinish:(NSNotification *)aNotification
{
CocoaDSCheatDatabase *newDatabase = [aNotification object];
NSDictionary *userInfo = [aNotification userInfo];
NSURL *workingURL = (NSURL *)[userInfo valueForKey:@"URL"];
CheatSystemError errorCode = (CheatSystemError)[(NSNumber *)[userInfo valueForKey:@"ErrorCode"] integerValue];
NSString *threadNamePrefix = @"org.desmume.DeSmuME.loadDatabaseDidFinish_";
NSString *fullThreadName = [threadNamePrefix stringByAppendingString:[workingURL absoluteString]];
[[NSNotificationCenter defaultCenter] removeObserver:self name:fullThreadName object:nil];
[self setIsFileLoading:NO];
[self setDatabase:[newDatabase autorelease]];
[self updateWindow];
if (errorCode != CheatSystemError_NoError)
{
[self showErrorSheet:errorCode];
}
if (database == nil)
{
return;
}
// Begin the generation of the cheat database recents menu.
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
NSArray *dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[dbRecentsList count] + 1];
if (useLegacyFilePath)
{
// We need to check if the legacy file path also exists in the recents list.
// If it does, then the recents list version takes priority.
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
{
useLegacyFilePath = NO;
break;
}
}
}
if (useLegacyFilePath)
{
// The legacy file path must always be the first entry of the recents list.
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
[legacyFilePath lastPathComponent], @"FileName",
nil];
[newRecentsList addObject:legacyRecentItem];
}
// Next, we need to add back all of the recent items in the same order in which
// they appear in user defaults, with the exception of our newest item.
NSString *newFilePath = [[database lastFileURL] path];
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ( ![newFilePath isEqualToString:dbRecentItemFilePath] )
{
[newRecentsList addObject:dbRecentItem];
}
}
// Create our new recent item...
NSDictionary *newRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:newFilePath, @"FilePath",
[newFilePath lastPathComponent], @"FileName",
[NSDate date], @"AddedDate",
[[self window] stringWithSavedFrame], @"WindowFrame",
[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height], @"WindowSplitViewDividerPosition",
nil];
// ...and then add the newest recent item, ensuring that it is always last in the list.
[newRecentsList addObject:newRecentItem];
// We're done generating the new recent items list, so write it back to user defaults, and then
// send a notification that UI elements needs to be updated.
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu" object:[newRecentsList retain] userInfo:nil];
}
- (void) updateWindow
{
if ([self database] == nil)
{
[[self window] setTitle:defaultWindowTitle];
}
else
{
[[self window] setTitle:[database description]];
}
[[self window] setRepresentedURL:[database lastFileURL]];
[gameListController setContent:[database gameList]];
NSIndexSet *selectedRows = [gameTable selectedRowIndexes];
[gameTable deselectAll:nil];
[gameTable selectRowIndexes:selectedRows byExtendingSelection:NO];
[self validateGameTableFonts];
[self selectCurrentGame:nil];
}
- (void) validateGameTableFonts
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if ( (delegate == nil) || (cheatManager == nil) )
{
currentGameTableRowIndex = NSNotFound;
[currentGameIndexString release];
currentGameIndexString = [[NSString alloc] initWithString:@"NSNotFound"];
[self setIsCurrentGameFound:NO];
return;
}
NSString *currentGameCode = [cheatManager currentGameCode];
const NSUInteger currentGameCRC = [cheatManager currentGameCRC];
for (CocoaDSCheatDBGame *game in [gameListController content])
{
if ( ([game crc] == currentGameCRC) && ([[game serial] isEqualToString:currentGameCode]) )
{
[currentGameIndexString release];
currentGameIndexString = [[NSString alloc] initWithFormat:@"%llu", (unsigned long long)[game index]];
[self setIsCurrentGameFound:YES];
break;
}
}
}
+ (void) validateGameTableFontsForAllWindows
{
if (cheatDatabaseWindowList == nil)
{
return;
}
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
{
[windowController validateGameTableFonts];
[[windowController gameTable] setNeedsDisplay];
}
}
- (BOOL) validateWillAddColumn
{
BOOL showWillAddColumn = NO;
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
NSArray *selectedObjects = [gameListController selectedObjects];
if ( (selectedObjects == nil) || ([selectedObjects count] == 0) )
{
return showWillAddColumn;
}
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
if ( (delegate != nil) && (cheatManager != nil) && ([selectedGame serial] != nil) )
{
showWillAddColumn = ([[selectedGame serial] isEqualToString:[cheatManager currentGameCode]]) && ([selectedGame crc] == [cheatManager currentGameCRC]);
}
NSTableColumn *willAddColumn = [entryOutline tableColumnWithIdentifier:@"willAdd"];
[willAddColumn setHidden:!showWillAddColumn];
[self setIsSelectedGameTheCurrentGame:showWillAddColumn];
return showWillAddColumn;
}
+ (void) validateWillAddColumnForAllWindows
{
if (cheatDatabaseWindowList == nil)
{
return;
}
for (CheatDatabaseWindowController *windowController in cheatDatabaseWindowList)
{
[windowController validateWillAddColumn];
}
}
- (void) showErrorSheet:(NSInteger)errorCode
{
switch (errorCode)
{
case CheatSystemError_NoError:
[self setErrorMajorString:@"No error has occurred."];
[self setErrorMinorString:@"This message is a placeholder. You are seeing this error as a test for this app's error handling.\n\nError Code: %i"];
break;
case CheatSystemError_FileOpenFailed:
[self setErrorMajorString:@"Failed to open file."];
[self setErrorMinorString:[NSString stringWithFormat:@"The system could not open the cheat database file. This problem is usually because another app is using it, or because the file permissions disallow read access.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_FileFormatInvalid:
[self setErrorMajorString:@"Invalid file format."];
[self setErrorMinorString:[NSString stringWithFormat:@"DeSmuME could not recognize the file format of the cheat database file. Currently, DeSmuME only recognizes the R4 file format. It is also possible that the file data is corrupted.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_GameNotFound:
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
[self setErrorMajorString:@"Current game not found in database."];
[self setErrorMinorString:[NSString stringWithFormat:@"The current game (Serial='%@', CRC=%llu) could not be found in the cheat database.\n\nError Code: %i", [cheatManager currentGameCode], (unsigned long long)[cheatManager currentGameCRC], (int)errorCode]];
break;
}
case CheatSystemError_LoadEntryError:
[self setErrorMajorString:@"Could not read cheat entries."];
[self setErrorMinorString:[NSString stringWithFormat:@"The entry data for the selected game could not be read. This is usually due to file data corruption.\n\nError Code: %i", (int)errorCode]];
break;
case CheatSystemError_FileDoesNotExist:
[self setErrorMajorString:@"The file does not exist."];
[self setErrorMinorString:[NSString stringWithFormat:@"If this file was selected from the Recents Menu, then it has been removed.\n\nError Code: %i", (int)errorCode]];
break;
default:
[self setErrorMajorString:@"An unknown error has occurred."];
[self setErrorMinorString:[NSString stringWithFormat:@"Error Code: %i", (int)errorCode]];
break;
}
#if defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
if ([[self window] respondsToSelector:@selector(beginSheet:completionHandler:)])
{
[[self window] beginSheet:errorSheet
completionHandler:^(NSModalResponse response) {
[self didEndErrorSheet:nil returnCode:response contextInfo:nil];
} ];
}
else
#endif
{
SILENCE_DEPRECATION_MACOS_10_10( [NSApp beginSheet:errorSheet
modalForWindow:[self window]
modalDelegate:self
didEndSelector:@selector(didEndErrorSheet:returnCode:contextInfo:)
contextInfo:nil] );
}
}
- (void) didEndErrorSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
#pragma mark -
#pragma mark Dynamic Properties
- (void) setDatabase:(CocoaDSCheatDatabase *)theDatabase
{
[self willChangeValueForKey:@"filePath"];
[self willChangeValueForKey:@"databaseFormatString"];
[self willChangeValueForKey:@"gameCount"];
[self willChangeValueForKey:@"isEncryptedString"];
[theDatabase retain];
[database release];
database = theDatabase;
[self didChangeValueForKey:@"filePath"];
[self didChangeValueForKey:@"databaseFormatString"];
[self didChangeValueForKey:@"gameCount"];
[self didChangeValueForKey:@"isEncryptedString"];
}
- (CocoaDSCheatDatabase *) database
{
return database;
}
- (NSString *) filePath
{
if ( (database != nil) && ([database lastFileURL] != nil) )
{
return [[database lastFileURL] path];
}
else if ([self isFileLoading])
{
return @"Loading database file...";
}
return @"No database file loaded.";
}
- (NSString *) databaseFormatString
{
if (database != nil)
{
return [database formatString];
}
return @"---";
}
- (NSInteger) gameCount
{
if (database != nil)
{
return [[database gameList] count];
}
return 0;
}
- (NSString *) isEncryptedString
{
if (database != nil)
{
return [database isEncrypted] ? @"Yes" : @"No";
}
return @"---";
}
#pragma mark -
#pragma mark IBActions
- (IBAction) openFile:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_OPEN_CHEAT_DB_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
if (IsOSXVersionSupported(10, 6, 0))
{
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:[self window]
completionHandler:^(NSInteger result) {
[self chooseCheatDatabaseDidEnd:panel returnCode:(int)result contextInfo:nil];
} ];
}
else
#endif
{
SILENCE_DEPRECATION_MACOS_10_6( [panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:[self window]
modalDelegate:self
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
contextInfo:nil] );
}
}
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == GUI_RESPONSE_CANCEL)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
[self loadFileStart:selectedFileURL];
}
- (IBAction) selectAll:(id)sender
{
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
for (CocoaDSCheatDBEntry *entry in entryTree)
{
[entry setWillAdd:YES];
}
[entryOutline setNeedsDisplay];
}
- (IBAction) selectNone:(id)sender
{
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
for (CocoaDSCheatDBEntry *entry in entryTree)
{
[entry setWillAdd:NO];
}
[entryOutline setNeedsDisplay];
}
- (IBAction) addSelected:(id)sender
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
if (delegate == nil)
{
return;
}
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if (cheatManager == nil)
{
return;
}
NSString *currentGameCode = [cheatManager currentGameCode];
NSUInteger currentGameCRC = [cheatManager currentGameCRC];
if ( (currentGameCode == nil) || (currentGameCRC == 0) )
{
return;
}
NSMutableArray *entryTree = [entryListController content];
if (entryTree == nil)
{
return;
}
NSInteger selectedIndex = [gameTable selectedRow];
CocoaDSCheatDBGame *selectedGame = (CocoaDSCheatDBGame *)[[gameListController arrangedObjects] objectAtIndex:selectedIndex];
if ( (![[selectedGame serial] isEqualToString:currentGameCode]) || ([selectedGame crc] != currentGameCRC) )
{
return;
}
CocoaDSCheatDBEntry *rootEntry = [selectedGame entryRoot];
if (rootEntry == nil)
{
return;
}
const NSInteger addedItemCount = [cheatManager databaseAddSelectedInEntry:[selectedGame entryRoot]];
if (addedItemCount > 0)
{
[[delegate cheatListController] setContent:[cheatManager sessionList]];
[cheatManager save];
}
}
- (IBAction) selectCurrentGame:(id)sender
{
CheatWindowDelegate *delegate = [self cheatManagerDelegate];
if (delegate == nil)
{
return;
}
CocoaDSCheatManager *cheatManager = [delegate cdsCheats];
if (cheatManager == nil)
{
return;
}
NSString *currentGameCode = [cheatManager currentGameCode];
NSUInteger currentGameCRC = [cheatManager currentGameCRC];
if ( (currentGameCode == nil) || (currentGameCRC == 0) )
{
return;
}
NSUInteger selectionIndex = NSNotFound;
NSArray *arrangedObjects = (NSArray *)[gameListController arrangedObjects];
for (CocoaDSCheatDBGame *game in arrangedObjects)
{
if ( ([game crc] == currentGameCRC) && ([[game serial] isEqualToString:currentGameCode]) )
{
selectionIndex = [arrangedObjects indexOfObject:game];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:selectionIndex];
[gameTable selectRowIndexes:indexSet byExtendingSelection:NO];
[gameTable scrollRowToVisible:selectionIndex];
break;
}
}
}
- (IBAction) closeErrorSheet:(id)sender
{
NSWindow *sheet = [(NSControl *)sender window];
const NSInteger code = [(NSControl *)sender tag];
[CocoaDSUtil endSheet:sheet returnCode:code];
}
#pragma mark -
#pragma mark NSWindowDelegate Protocol
- (void)windowDidLoad
{
// Save a copy of the default window title before we replace it
// with the database file's description.
NSString *oldDefaultWindowTitle = defaultWindowTitle;
defaultWindowTitle = [[[self window] title] copy];
[oldDefaultWindowTitle release];
}
- (void)windowWillClose:(NSNotification *)notification
{
NSArray *userDefaultsRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
if ( (userDefaultsRecentsList != nil) && ([userDefaultsRecentsList count] > 0) )
{
NSMutableArray *dbRecentsList = [NSMutableArray arrayWithCapacity:[userDefaultsRecentsList count]];
for (NSDictionary *recentItem in userDefaultsRecentsList)
{
NSString *thisFilePath = [[database lastFileURL] path];
NSString *recentItemPath = (NSString *)[recentItem objectForKey:@"FilePath"];
if ( (thisFilePath != nil) && ([recentItemPath isEqualToString:thisFilePath]) )
{
NSMutableDictionary *newRecentItem = [NSMutableDictionary dictionaryWithDictionary:recentItem];
[newRecentItem setObject:[[self window] stringWithSavedFrame] forKey:@"WindowFrame"];
[newRecentItem setObject:[NSNumber numberWithFloat:[[[splitView subviews] objectAtIndex:0] frame].size.height] forKey:@"WindowSplitViewDividerPosition"];
[dbRecentsList addObject:newRecentItem];
}
else
{
[dbRecentsList addObject:recentItem];
}
}
[[NSUserDefaults standardUserDefaults] setObject:dbRecentsList forKey:@"CheatDatabase_RecentFilePath"];
}
[cheatDatabaseWindowList removeObject:self];
[self release];
}
#pragma mark -
#pragma mark NSTableViewDelegate Protocol
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
NSTableView *table = (NSTableView *)[aNotification object];
NSInteger rowIndex = [table selectedRow];
if (table == gameTable)
{
if (rowIndex >= 0)
{
NSArray *selectedObjects = [gameListController selectedObjects];
CocoaDSCheatDBGame *selectedGame = [selectedObjects objectAtIndex:0];
CocoaDSCheatDBEntry *entryRoot = [database loadGameEntry:selectedGame];
[self validateWillAddColumn];
[entryListController setContent:[entryRoot child]];
if (entryRoot == nil)
{
[self showErrorSheet:CheatSystemError_LoadEntryError];
}
}
else
{
[entryListController setContent:nil];
}
}
}
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSString *cellString = [cell stringValue];
if ( (cellString != nil) && [cellString isEqualToString:currentGameIndexString] )
{
currentGameTableRowIndex = row;
}
if ( (cellString != nil) && (row == currentGameTableRowIndex) )
{
[cell setFont:[NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]]];
}
else
{
[cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
currentGameTableRowIndex = NSNotFound;
}
}
@end

View File

@ -54,8 +54,8 @@ class AudioSampleBlockGenerator;
NSObjectController *cheatWindowController;
NSObjectController *slot2WindowController;
NSArrayController *inputDeviceListController;
NSArrayController *cheatListController;
NSArrayController *cheatDatabaseController;
NSMenu *cheatDatabaseRecentsMenu;
RomInfoPanel *romInfoPanel;
@ -148,8 +148,8 @@ class AudioSampleBlockGenerator;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSObjectController *slot2WindowController;
@property (readonly) IBOutlet NSArrayController *inputDeviceListController;
@property (readonly) IBOutlet NSArrayController *cheatListController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSMenu *cheatDatabaseRecentsMenu;
@property (readonly) IBOutlet RomInfoPanel *romInfoPanel;
@ -214,6 +214,9 @@ class AudioSampleBlockGenerator;
- (IBAction) stopReplay:(id)sender;
- (IBAction) importRomSave:(id)sender;
- (IBAction) exportRomSave:(id)sender;
- (IBAction) openCheatDatabaseFile:(id)sender;
- (IBAction) clearCheatDatabaseRecents:(id)sender;
- (IBAction) openRecentCheatDatabase:(id)sender;
// Emulation Menu
- (IBAction) toggleSpeedLimiter:(id)sender;
@ -299,6 +302,7 @@ class AudioSampleBlockGenerator;
- (BOOL) loadRomByURL:(NSURL *)romURL asynchronous:(BOOL)willLoadAsync;
- (void) loadRomDidFinish:(NSNotification *)aNotification;
- (BOOL) unloadRom;
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification;
- (void) addOutputToCore:(CocoaDSOutput *)theOutput;
- (void) removeOutputFromCore:(CocoaDSOutput *)theOutput;

View File

@ -19,6 +19,7 @@
#import "DisplayWindowController.h"
#import "InputManager.h"
#import "cheatWindowDelegate.h"
#import "CheatDatabaseWindowController.h"
#import "Slot2WindowDelegate.h"
#import "MacAVCaptureTool.h"
#import "MacScreenshotCaptureTool.h"
@ -56,11 +57,11 @@
@synthesize cdsCoreController;
@synthesize cdsSoundController;
@synthesize cheatWindowController;
@synthesize cheatListController;
@synthesize cheatDatabaseController;
@synthesize slot2WindowController;
@synthesize inputDeviceListController;
@synthesize cheatDatabaseRecentsMenu;
@synthesize romInfoPanel;
@synthesize displayRotationPanel;
@ -196,6 +197,11 @@
name:@"org.desmume.DeSmuME.handleEmulatorExecutionState"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateCheatDatabaseRecentsMenu:)
name:@"org.desmume.DeSmuME.updateCheatDatabaseRecentsMenu"
object:nil];
return self;
}
@ -804,6 +810,96 @@
[self restoreCoreState];
}
- (IBAction) openCheatDatabaseFile:(id)sender
{
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
[[newWindowController window] makeKeyAndOrderFront:sender];
[[newWindowController window] makeMainWindow];
[newWindowController openFile:sender];
}
- (IBAction) clearCheatDatabaseRecents:(id)sender
{
NSArray *menuItemList = [cheatDatabaseRecentsMenu itemArray];
for (NSMenuItem *menuItem in menuItemList)
{
if ( ([menuItem action] == @selector(openRecentCheatDatabase:)) || [menuItem isSeparatorItem] )
{
[cheatDatabaseRecentsMenu removeItem:menuItem];
}
}
NSArray *emptyArray = [[[NSArray alloc] init] autorelease];
[[NSUserDefaults standardUserDefaults] setObject:emptyArray forKey:@"CheatDatabase_RecentFilePath"];
// Also remove the legacy setting.
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"R4Cheat_DatabasePath"];
}
- (IBAction) openRecentCheatDatabase:(id)sender
{
CheatDatabaseWindowController *newWindowController = [[CheatDatabaseWindowController alloc] initWithWindowNibName:@"CheatDatabaseViewer" delegate:cheatWindowDelegate];
[newWindowController window]; // Just reference the window to force the NSWindow object to load.
[[newWindowController window] makeKeyAndOrderFront:self];
[[newWindowController window] makeMainWindow];
NSArray *recentDBFilePathsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
NSInteger index = [CocoaDSUtil getIBActionSenderTag:sender];
NSDictionary *recentItem = (NSDictionary *)[recentDBFilePathsList objectAtIndex:index];
NSString *recentItemFilePath = nil;
if (recentItem != nil)
{
// Set up the window properties.
NSString *windowFrameString = (NSString *)[recentItem objectForKey:@"WindowFrame"];
if (windowFrameString != nil)
{
[[newWindowController window] setFrameFromString:windowFrameString];
}
NSNumber *windowSplitViewDividerPositionNumber = (NSNumber *)[recentItem objectForKey:@"WindowSplitViewDividerPosition"];
if (windowSplitViewDividerPositionNumber != nil)
{
CGFloat dividerPosition = [windowSplitViewDividerPositionNumber floatValue];
[[newWindowController splitView] setPosition:dividerPosition ofDividerAtIndex:0];
}
// Check for the file's existence at its path, and then handle appropriately.
recentItemFilePath = (NSString *)[recentItem objectForKey:@"FilePath"];
NSFileManager *fileManager = [[NSFileManager alloc] init];
BOOL doesFileExist = [fileManager fileExistsAtPath:recentItemFilePath];
[fileManager release];
if (!doesFileExist)
{
// If the file does not exist, then report the error to the user, and the remove the
// nonexistent file from the recents menu.
[newWindowController showErrorSheet:CheatSystemError_FileDoesNotExist];
NSMutableArray *newRecentsList = [NSMutableArray arrayWithCapacity:[recentDBFilePathsList count]];
for (NSDictionary *theItem in recentDBFilePathsList)
{
if (theItem != recentItem)
{
[newRecentsList addObject:theItem];
}
}
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
[self updateCheatDatabaseRecentsMenu:nil];
return;
}
}
NSURL *dbFileURL = [NSURL fileURLWithPath:recentItemFilePath];
[newWindowController loadFileStart:dbFileURL];
}
- (IBAction) toggleExecutePause:(id)sender
{
[inputManager dispatchCommandUsingIBAction:_cmd sender:sender];
@ -2029,6 +2125,93 @@
return result;
}
- (void) updateCheatDatabaseRecentsMenu:(NSNotification *)aNotification
{
NSArray *dbRecentsList = (NSArray *)[aNotification object];
BOOL needReleaseObject = (dbRecentsList != nil);
if ( (dbRecentsList == nil) || ([dbRecentsList count] == 0) )
{
dbRecentsList = [[NSUserDefaults standardUserDefaults] arrayForKey:@"CheatDatabase_RecentFilePath"];
}
NSMutableArray *newRecentsList = [NSMutableArray arrayWithArray:dbRecentsList];
// Note that we're relying on the notification object to retain this prior to
// sending the notification.
if (needReleaseObject)
{
[dbRecentsList release];
}
NSString *legacyFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
BOOL useLegacyFilePath = ( (legacyFilePath != nil) && ([legacyFilePath length] > 0) );
if (useLegacyFilePath)
{
// We need to check if the legacy file path also exists in the recents list.
// If it does, then the recents list version takes priority.
for (NSDictionary *dbRecentItem in dbRecentsList)
{
NSString *dbRecentItemFilePath = (NSString *)[dbRecentItem valueForKey:@"FilePath"];
if ([dbRecentItemFilePath isEqualToString:legacyFilePath])
{
useLegacyFilePath = NO;
break;
}
}
}
if (useLegacyFilePath)
{
// The legacy file path must always be the first entry of the recents list.
NSDictionary *legacyRecentItem = [NSDictionary dictionaryWithObjectsAndKeys:legacyFilePath, @"FilePath",
[legacyFilePath lastPathComponent], @"FileName",
nil];
[newRecentsList insertObject:legacyRecentItem atIndex:0];
if ([newRecentsList count] == 1)
{
// If the legacy file path is the only item in the recents list, then we can write it
// back to user defaults right now.
[[NSUserDefaults standardUserDefaults] setObject:newRecentsList forKey:@"CheatDatabase_RecentFilePath"];
}
}
NSArray *recentsMenuItems = [cheatDatabaseRecentsMenu itemArray];
for (NSMenuItem *menuItem in recentsMenuItems)
{
if ( [menuItem action] == @selector(openRecentCheatDatabase:) )
{
[cheatDatabaseRecentsMenu removeItem:menuItem];
}
}
if ([newRecentsList count] > 0)
{
if ( ![[cheatDatabaseRecentsMenu itemAtIndex:0] isSeparatorItem] )
{
[cheatDatabaseRecentsMenu insertItem:[NSMenuItem separatorItem] atIndex:0];
}
}
// Recent files are added in reverse order, in which least recent files appear below
// more recent files in the menu. The most recent file should be at the top of the menu.
for (NSDictionary *recentItem in newRecentsList)
{
NSString *menuNameString = [recentItem objectForKey:@"FileName"];
if ( (menuNameString == nil) || ([menuNameString length] == 0) )
{
menuNameString = [recentItem objectForKey:@"FilePath"];
}
NSMenuItem *newMenuItem = [[[NSMenuItem alloc] initWithTitle:menuNameString action:@selector(openRecentCheatDatabase:) keyEquivalent:@""] autorelease];
[newMenuItem setTag:[newRecentsList indexOfObject:recentItem]];
[newMenuItem setTarget:self];
[cheatDatabaseRecentsMenu insertItem:newMenuItem atIndex:0];
}
}
- (void) handleNDSError:(NSNotification *)aNotification
{
[self setIsUserInterfaceBlockingExecution:YES];
@ -2980,6 +3163,13 @@
enable = NO;
}
}
else if (theAction == @selector(clearCheatDatabaseRecents:))
{
if ([cheatDatabaseRecentsMenu numberOfItems] < 2)
{
enable = NO;
}
}
else if (theAction == @selector(changeCoreSpeed:))
{
NSInteger speedScalar = (NSInteger)([cdsCore speedScalar] * 100.0);

View File

@ -36,6 +36,8 @@
NSObjectController *emuControlController;
NSObjectController *prefWindowController;
NSObjectController *cdsCoreController;
NSObjectController *databaseFileController;
NSArrayController *gameListController;
FileMigrationDelegate *migrationDelegate;
MacAVCaptureToolDelegate *avCaptureToolDelegate;
WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;
@ -63,6 +65,8 @@
@property (readonly) IBOutlet NSObjectController *emuControlController;
@property (readonly) IBOutlet NSObjectController *prefWindowController;
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
@property (readonly) IBOutlet NSObjectController *databaseFileController;
@property (readonly) IBOutlet NSArrayController *gameListController;
@property (readonly) IBOutlet FileMigrationDelegate *migrationDelegate;
@property (readonly) IBOutlet MacAVCaptureToolDelegate *avCaptureToolDelegate;
@property (readonly) IBOutlet WifiSettingsPanelDelegate *wifiSettingsPanelDelegate;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2011-2022 DeSmuME Team
Copyright (C) 2011-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@
#import "inputPrefsView.h"
#import "cocoa_core.h"
#import "cocoa_cheat.h"
#import "cocoa_GPU.h"
#import "cocoa_file.h"
#import "cocoa_firmware.h"
@ -50,6 +51,8 @@
@synthesize emuControlController;
@synthesize prefWindowController;
@synthesize cdsCoreController;
@synthesize databaseFileController;
@synthesize gameListController;
@synthesize avCaptureToolDelegate;
@synthesize wifiSettingsPanelDelegate;
@synthesize migrationDelegate;
@ -312,6 +315,7 @@
// Bring the application to the front
[NSApp activateIgnoringOtherApps:YES];
[emuControl restoreDisplayWindowStates];
[emuControl updateCheatDatabaseRecentsMenu:nil];
// Load a new ROM on launch per user preferences.
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"General_AutoloadROMOnLaunch"] != nil)

View File

@ -37,7 +37,6 @@
NSTableView *cheatSearchListTable;
NSArrayController *cheatListController;
NSArrayController *cheatSearchListController;
NSArrayController *cheatDatabaseController;
NSObjectController *cheatWindowController;
NSObjectController *cheatSelectedItemController;
@ -54,13 +53,14 @@
NSSearchField *searchField;
NSWindow *cheatDatabaseSheet;
NSFont *codeEditorFont;
NSMutableDictionary *bindings;
CocoaDSCheatItem *workingCheat;
CocoaDSCheatManager *cdsCheats;
NSString *currentGameCode;
NSInteger currentGameCRC;
}
@property (assign) IBOutlet NSObject *dummyObject;
@ -71,7 +71,6 @@
@property (readonly) IBOutlet NSTableView *cheatSearchListTable;
@property (readonly) IBOutlet NSArrayController *cheatListController;
@property (readonly) IBOutlet NSArrayController *cheatSearchListController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSObjectController *cheatSelectedItemController;
@ -87,19 +86,19 @@
@property (readonly) IBOutlet NSSearchField *searchField;
@property (readonly) IBOutlet NSWindow *cheatDatabaseSheet;
@property (assign) NSFont *codeEditorFont;
@property (readonly) NSMutableDictionary *bindings;
@property (retain) CocoaDSCheatItem *workingCheat;
@property (retain) CocoaDSCheatManager *cdsCheats;
@property (retain) NSString *currentGameCode;
@property (assign) NSInteger currentGameCRC;
- (BOOL) cheatSystemStart:(CocoaDSCheatManager *)theManager;
- (void) cheatSystemEnd;
- (IBAction) addToList:(id)sender;
- (IBAction) removeFromList:(id)sender;
- (IBAction) viewDatabase:(id)sender;
- (IBAction) removeAllFromList:(id)sender;
- (IBAction) setInternalCheatValue:(id)sender;
- (IBAction) applyConfiguration:(id)sender;
- (IBAction) selectCheatType:(id)sender;
@ -112,11 +111,4 @@
- (void) setCheatConfigViewByType:(NSInteger)cheatTypeID;
- (void) setCheatSearchViewByStyle:(NSInteger)searchStyleID;
- (void) databaseLoadFromFile:(NSURL *)fileURL;
- (void) addSelectedFromCheatDatabase;
- (IBAction) selectAllCheatsInDatabase:(id)sender;
- (IBAction) selectNoneCheatsInDatabase:(id)sender;
- (IBAction) closeCheatDatabaseSheet:(id)sender;
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo;
@end

View File

@ -17,6 +17,7 @@
*/
#import "cheatWindowDelegate.h"
#import "CheatDatabaseWindowController.h"
#import "cocoa_globals.h"
#import "cocoa_cheat.h"
@ -33,7 +34,6 @@
@synthesize cheatSearchListTable;
@synthesize cheatListController;
@synthesize cheatSearchListController;
@synthesize cheatDatabaseController;
@synthesize cheatWindowController;
@synthesize cheatSelectedItemController;
@ -48,12 +48,12 @@
@synthesize searchField;
@synthesize cheatDatabaseSheet;
@synthesize codeEditorFont;
@synthesize bindings;
@synthesize cdsCheats;
@synthesize workingCheat;
@synthesize currentGameCode;
@synthesize currentGameCRC;
- (id)init
{
@ -71,24 +71,26 @@
return self;
}
currentGameCode = nil;
currentGameCRC = 0;
workingCheat = nil;
currentView = nil;
currentSearchStyleView = nil;
codeEditorFont = [NSFont fontWithName:@"Monaco" size:13.0];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasSelection"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isRunningSearch"];
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"isSearchStarted"];
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE] forKey:@"cheatSearchStyle"];
[bindings setValue:[NSNumber numberWithInteger:CheatSearchStyle_ExactValue] forKey:@"cheatSearchStyle"];
[bindings setValue:[NSNumber numberWithInteger:CHEATSEARCH_UNSIGNED] forKey:@"cheatSearchSignType"];
[bindings setValue:@"Search not started." forKey:@"cheatSearchAddressCount"];
if ([CocoaDSCheatItem iconInternalCheat] == nil || [CocoaDSCheatItem iconActionReplay] == nil || [CocoaDSCheatItem iconCodeBreaker] == nil)
if ([CocoaDSCheatItem iconDirectory] == nil || [CocoaDSCheatItem iconInternalCheat] == nil || [CocoaDSCheatItem iconActionReplay] == nil || [CocoaDSCheatItem iconCodeBreaker] == nil)
{
[CocoaDSCheatItem setIconInternalCheat:[NSImage imageNamed:@"NSApplicationIcon"]];
[CocoaDSCheatItem setIconActionReplay:[NSImage imageNamed:@"Icon_ActionReplay_128x128"]];
[CocoaDSCheatItem setIconCodeBreaker:[NSImage imageNamed:@"Icon_CodeBreaker_128x128"]];
[CocoaDSCheatItem setIconDirectory:[[NSImage imageNamed:@"NSFolder"] retain]];
[CocoaDSCheatItem setIconInternalCheat:[[NSImage imageNamed:@"NSApplicationIcon"] retain]];
[CocoaDSCheatItem setIconActionReplay:[[NSImage imageNamed:@"Icon_ActionReplay_128x128"] retain]];
[CocoaDSCheatItem setIconCodeBreaker:[[NSImage imageNamed:@"Icon_CodeBreaker_128x128"] retain]];
}
return self;
@ -98,6 +100,7 @@
{
[self setWorkingCheat:nil];
[self setCdsCheats:nil];
[self setCurrentGameCode:nil];
[bindings release];
[super dealloc];
@ -113,19 +116,14 @@
}
[self setCdsCheats:cheatManager];
[self setCurrentGameCode:[cheatManager currentGameCode]];
[self setCurrentGameCRC:[cheatManager currentGameCRC]];
[cheatManager loadFromMaster];
[cheatListController setContent:[cheatManager sessionList]];
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
[cheatWindowBindings setValue:self forKey:@"cheatWindowDelegateKey"];
NSString *dbFilePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
if (dbFilePath != nil)
{
[self databaseLoadFromFile:[NSURL fileURLWithPath:dbFilePath]];
}
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE];
[self setCheatSearchViewByStyle:CheatSearchStyle_ExactValue];
[CheatDatabaseWindowController validateWillAddColumnForAllWindows];
[CheatDatabaseWindowController validateGameTableFontsForAllWindows];
didStartSuccessfully = YES;
return didStartSuccessfully;
@ -139,16 +137,14 @@
[cheatManager save];
}
[cheatDatabaseController setContent:nil];
[cheatListController setContent:nil];
[self resetSearch:nil];
[self setCurrentGameCode:nil];
[self setCurrentGameCRC:0];
[self setCdsCheats:nil];
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"No ROM loaded." forKey:@"cheatDBDate"];
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
[cheatWindowBindings setValue:nil forKey:@"cheatWindowDelegateKey"];
[CheatDatabaseWindowController validateWillAddColumnForAllWindows];
[CheatDatabaseWindowController validateGameTableFontsForAllWindows];
}
- (IBAction) addToList:(id)sender
@ -162,7 +158,6 @@
if (newCheatItem != nil)
{
[cheatListController setContent:[[self cdsCheats] sessionList]];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
[[self cdsCheats] save];
}
}
@ -202,31 +197,27 @@
[cheatListTable selectRowIndexes:indexSet byExtendingSelection:NO];
}
else
{
[bindings setValue:[NSNumber numberWithBool:NO] forKey:@"hasItems"];
}
}
- (IBAction) viewDatabase:(id)sender
- (IBAction) removeAllFromList:(id)sender
{
#if defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9)
if ([window respondsToSelector:@selector(beginSheet:completionHandler:)])
CocoaDSCheatManager *cheatManager = [self cdsCheats];
if (cheatManager == nil)
{
[window beginSheet:cheatDatabaseSheet
completionHandler:^(NSModalResponse response) {
[self didEndCheatDatabaseSheet:nil returnCode:response contextInfo:nil];
} ];
return;
}
else
#endif
[cheatListTable deselectAll:sender];
NSUInteger itemCount = [[cheatManager sessionList] count];
for (NSUInteger i = 0; i < itemCount; i++)
{
SILENCE_DEPRECATION_MACOS_10_10( [NSApp beginSheet:cheatDatabaseSheet
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(didEndCheatDatabaseSheet:returnCode:contextInfo:)
contextInfo:nil] );
[cheatManager removeAtIndex:0];
}
[cheatListController setContent:[cheatManager sessionList]];
[cheatManager save];
}
- (IBAction) setInternalCheatValue:(id)sender
@ -316,9 +307,9 @@
[cheatSearchListController setContent:[[self cdsCheats] searchResultsList]];
NSInteger searchStyle = [(NSNumber *)[bindings valueForKey:@"cheatSearchStyle"] integerValue];
if (searchStyle == CHEATSEARCH_SEARCHSTYLE_COMPARATIVE)
if (searchStyle == CheatSearchStyle_Comparative)
{
[self setCheatSearchViewByStyle:CHEATSEARCH_SEARCHSTYLE_COMPARATIVE];
[self setCheatSearchViewByStyle:CheatSearchStyle_Comparative];
}
if (!wasSearchAlreadyStarted)
@ -354,15 +345,15 @@
switch (cheatTypeID)
{
case CHEAT_TYPE_INTERNAL:
case CheatType_Internal:
newView = viewConfigureInternalCheat;
break;
case CHEAT_TYPE_ACTION_REPLAY:
case CheatType_ActionReplay:
newView = viewConfigureActionReplayCheat;
break;
case CHEAT_TYPE_CODE_BREAKER:
case CheatType_CodeBreaker:
newView = viewConfigureCodeBreakerCheat;
break;
@ -391,11 +382,11 @@
switch (searchStyleID)
{
case CHEATSEARCH_SEARCHSTYLE_EXACT_VALUE:
case CheatSearchStyle_ExactValue:
newView = viewSearchExactValue;
break;
case CHEATSEARCH_SEARCHSTYLE_COMPARATIVE:
case CheatSearchStyle_Comparative:
if ([cdsCheats searchDidStart] == 0)
{
newView = viewSearchComparativeStart;
@ -420,136 +411,6 @@
}
}
- (void) databaseLoadFromFile:(NSURL *)fileURL
{
CocoaDSCheatManager *cheatManager = [self cdsCheats];
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
if ( (fileURL == nil) || (cheatManager == nil) || (cheatWindowBindings == nil) )
{
return;
}
NSInteger error = 0;
NSMutableArray *dbList = [cheatManager databaseListLoadFromFile:fileURL errorCode:&error];
if (dbList != nil)
{
[cheatDatabaseController setContent:dbList];
NSString *titleString = [cheatManager databaseTitle];
NSString *dateString = [cheatManager databaseDate];
[cheatWindowBindings setValue:titleString forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:dateString forKey:@"cheatDBDate"];
[cheatWindowBindings setValue:[NSString stringWithFormat:@"%ld", (unsigned long)[dbList count]] forKey:@"cheatDBItemCount"];
}
else
{
[cheatWindowBindings setValue:@"---" forKey:@"cheatDBItemCount"];
switch (error)
{
case CHEATEXPORT_ERROR_FILE_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not load the database file!");
[cheatWindowBindings setValue:@"Database not loaded." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_WRONG_FILE_FORMAT:
NSLog(@"R4 Cheat Database read failed! Wrong file format!");
[cheatWindowBindings setValue:@"Database load error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"FAILED TO LOAD FILE" forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_SERIAL_NOT_FOUND:
NSLog(@"R4 Cheat Database read failed! Could not find the serial number for this game in the database!");
[cheatWindowBindings setValue:@"ROM not found in database." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"ROM not found." forKey:@"cheatDBDate"];
break;
case CHEATEXPORT_ERROR_EXPORT_FAILED:
NSLog(@"R4 Cheat Database read failed! Could not read the database file!");
[cheatWindowBindings setValue:@"Database read error." forKey:@"cheatDBTitle"];
[cheatWindowBindings setValue:@"CANNOT READ FILE" forKey:@"cheatDBDate"];
break;
default:
break;
}
}
}
- (void) addSelectedFromCheatDatabase
{
CocoaDSCheatManager *cheatManager = [self cdsCheats];
if (cheatManager == nil)
{
return;
}
const NSInteger addedItemCount = [cheatManager databaseAddSelected];
if (addedItemCount > 0)
{
[cheatListController setContent:[[self cdsCheats] sessionList]];
[[self cdsCheats] save];
[bindings setValue:[NSNumber numberWithBool:YES] forKey:@"hasItems"];
}
}
- (IBAction) selectAllCheatsInDatabase:(id)sender
{
NSMutableArray *dbList = [cheatDatabaseController content];
if (dbList == nil)
{
return;
}
for (CocoaDSCheatItem *cheatItem in dbList)
{
[cheatItem setWillAdd:YES];
}
}
- (IBAction) selectNoneCheatsInDatabase:(id)sender
{
NSMutableArray *dbList = [cheatDatabaseController content];
if (dbList == nil)
{
return;
}
for (CocoaDSCheatItem *cheatItem in dbList)
{
[cheatItem setWillAdd:NO];
}
}
- (IBAction) closeCheatDatabaseSheet:(id)sender
{
NSWindow *sheet = [(NSControl *)sender window];
const NSInteger code = [(NSControl *)sender tag];
[CocoaDSUtil endSheet:sheet returnCode:code];
}
- (void) didEndCheatDatabaseSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
switch (returnCode)
{
case GUI_RESPONSE_CANCEL:
return;
case GUI_RESPONSE_OK:
[self addSelectedFromCheatDatabase];
break;
default:
break;
}
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
[cheatWindowController setContent:bindings];

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012-2022 DeSmuME Team
Copyright (C) 2012-2023 DeSmuME Team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -55,7 +55,6 @@ class OGLImage;
NSObjectController *emuController;
NSObjectController *prefWindowController;
NSObjectController *cheatWindowController;
NSArrayController *cheatDatabaseController;
NSToolbarItem *toolbarItemGeneral;
NSToolbarItem *toolbarItemInput;
@ -105,7 +104,6 @@ class OGLImage;
@property (readonly) IBOutlet NSObjectController *emuController;
@property (readonly) IBOutlet NSObjectController *prefWindowController;
@property (readonly) IBOutlet NSObjectController *cheatWindowController;
@property (readonly) IBOutlet NSArrayController *cheatDatabaseController;
@property (readonly) IBOutlet NSToolbarItem *toolbarItemGeneral;
@property (readonly) IBOutlet NSToolbarItem *toolbarItemInput;
@property (readonly) IBOutlet NSToolbarItem *toolbarItemDisplay;
@ -139,8 +137,6 @@ class OGLImage;
- (void) chooseAdvansceneDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) chooseRomForAutoload:(id)sender;
- (void) chooseRomForAutoloadDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) chooseCheatDatabase:(id)sender;
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (IBAction) selectDisplayRotation:(id)sender;
- (void) updateDisplayRotationMenu:(double)displayRotation;

View File

@ -36,7 +36,6 @@
#endif
#pragma mark -
@implementation DisplayPreviewView
@dynamic filtersPreferGPU;
@ -294,7 +293,6 @@
@synthesize emuController;
@synthesize prefWindowController;
@synthesize cheatWindowController;
@synthesize cheatDatabaseController;
@synthesize toolbarItemGeneral;
@synthesize toolbarItemInput;
@ -525,70 +523,6 @@
[bindings setValue:[selectedFile lastPathComponent] forKey:@"AdvansceneDatabaseName"];
}
- (IBAction) chooseCheatDatabase:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseDirectories:NO];
[panel setCanChooseFiles:YES];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:NO];
[panel setTitle:NSSTRING_TITLE_SELECT_R4_CHEAT_DB_PANEL];
NSArray *fileTypes = [NSArray arrayWithObjects:@FILE_EXT_R4_CHEAT_DB, nil];
// The NSOpenPanel/NSSavePanel method -(void)beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo
// is deprecated in Mac OS X v10.6.
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
if (IsOSXVersionSupported(10, 6, 0))
{
[panel setAllowedFileTypes:fileTypes];
[panel beginSheetModalForWindow:window
completionHandler:^(NSInteger result) {
[self chooseCheatDatabaseDidEnd:panel returnCode:(int)result contextInfo:nil];
} ];
}
else
#endif
{
SILENCE_DEPRECATION_MACOS_10_6( [panel beginSheetForDirectory:nil
file:nil
types:fileTypes
modalForWindow:window
modalDelegate:self
didEndSelector:@selector(chooseCheatDatabaseDidEnd:returnCode:contextInfo:)
contextInfo:nil] );
}
}
- (void) chooseCheatDatabaseDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
if (returnCode == GUI_RESPONSE_CANCEL)
{
return;
}
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
if(selectedFileURL == nil)
{
return;
}
NSString *selectedFile = [selectedFileURL path];
[[NSUserDefaults standardUserDefaults] setObject:selectedFile forKey:@"R4Cheat_DatabasePath"];
[bindings setValue:[selectedFile lastPathComponent] forKey:@"R4CheatDatabaseName"];
const BOOL isRomLoaded = [(EmuControllerDelegate *)[emuController content] currentRom] != nil;
NSMutableDictionary *cheatWindowBindings = (NSMutableDictionary *)[cheatWindowController content];
CheatWindowDelegate *cheatWindowDelegate = (CheatWindowDelegate *)[cheatWindowBindings valueForKey:@"cheatWindowDelegateKey"];
if ( (isRomLoaded == YES) && (cheatWindowDelegate != nil) )
{
[cheatWindowDelegate databaseLoadFromFile:selectedFileURL];
}
}
- (IBAction) selectDisplayRotation:(id)sender
{
const NSInteger displayRotation = [(NSMenuItem *)sender tag];
@ -1078,12 +1012,6 @@
[bindings setValue:[advansceneDatabasePath lastPathComponent] forKey:@"AdvansceneDatabaseName"];
}
NSString *cheatDatabasePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"R4Cheat_DatabasePath"];
if (cheatDatabasePath != nil)
{
[bindings setValue:[cheatDatabasePath lastPathComponent] forKey:@"R4CheatDatabaseName"];
}
NSString *autoloadRomPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"General_AutoloadROMSelectedPath"];
if (autoloadRomPath != nil)
{

View File

@ -1639,19 +1639,31 @@ bool CheatsExportDialog(HWND hwnd)
else
{
char buf2[512] = {0};
if (cheatsExport->getErrorCode() == 1)
sprintf(buf2, "Error loading cheats database. File not found\n\"%s\"\nCheck your path (Menu->Config->Path Settings->\"Cheats\")\n\nYou can download it from http://www.codemasters-project.net/vb/forumdisplay.php?44-Nintendo-DS", buf);
else
if (cheatsExport->getErrorCode() == 2)
CheatSystemError theError = cheatsExport->getErrorCode();
switch (theError)
{
case CheatSystemError_FileOpenFailed:
sprintf(buf2, "Error loading cheats database. File not found\n\"%s\"\nCheck your path (Menu->Config->Path Settings->\"Cheats\")\n\nYou can download it from http://www.codemasters-project.net/vb/forumdisplay.php?44-Nintendo-DS", buf);
break;
case CheatSystemError_FileFormatInvalid:
sprintf(buf2, "File \"%s\" is not R4 cheats database.\nWrong file format!", buf);
else
if (cheatsExport->getErrorCode() == 3)
sprintf(buf2, "CRC %8X not found in database.", gameInfo.crcForCheatsDb);
else
if (cheatsExport->getErrorCode() == 4)
sprintf(buf2, "Error export from database");
else
sprintf(buf2, "Unknown error!!!");
break;
case CheatSystemError_GameNotFound:
sprintf(buf2, "CRC %8X not found in database.", gameInfo.crcForCheatsDb);
break;
case CheatSystemError_LoadEntryError:
sprintf(buf2, "Error export from database");
break;
default:
sprintf(buf2, "Unknown error!!!");
break;
}
MessageBox(hwnd, buf2, "DeSmuME", MB_OK | MB_ICONERROR);
}