- no longer modifying cheat txt file thanks to dimoks code in usb loader gx. #238

This commit is contained in:
Fledge68 2021-10-11 10:51:50 -05:00
parent 2a827f6ce3
commit 26790615de
4 changed files with 237 additions and 231 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 MiB

After

Width:  |  Height:  |  Size: 4.4 MiB

View File

@ -1,254 +1,231 @@
#include <iostream> /****************************************************************************
#include <fstream> * Copyright (C) 2009 nIxx
* Copyright (C) 2012 Dimok
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "gct.h" #include "gct.h"
#define ERRORRANGE "Error: CheatNr out of range" #define ERRORRANGE "Error: CheatNr out of range"
//Header and Footer
static const char GCT_Header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde };
static const char GCT_Footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
GCTCheats::GCTCheats(void) GCTCheats::GCTCheats(void)
{ {
Reset();
} }
GCTCheats::~GCTCheats(void) GCTCheats::~GCTCheats(void)
{ {
string sGameID ="";
string sGameTitle = "";
} }
unsigned int GCTCheats::getCnt() void GCTCheats::Clear(void)
{ {
return iCntCheats; cheatList.clear();
sGameID.clear();
sGameTitle.clear();
sCheatSelected.clear();
} }
string GCTCheats::getGameName(void) std::string GCTCheats::getGameName(void)
{ {
return sGameTitle; return sGameTitle;
} }
string GCTCheats::getGameID(void) std::string GCTCheats::getGameID(void)
{ {
return sGameID; return sGameID;
} }
string GCTCheats::getCheat(unsigned int nr) std::vector<unsigned int> GCTCheats::getCheat(int nr)
{ {
if (nr <= (iCntCheats-1)) if((unsigned int)nr >= cheatList.size())
return sCheats[nr]; return std::vector<unsigned int>();
return ERRORRANGE;
return cheatList[nr].sCheats;
} }
string GCTCheats::getCheatName(unsigned int nr) std::string GCTCheats::getCheatName(int nr)
{ {
if (nr <= (iCntCheats-1)) if((unsigned int)nr >= cheatList.size())
return sCheatName[nr]; return ERRORRANGE;
return ERRORRANGE;
return cheatList[nr].sCheatName;
} }
string GCTCheats::getCheatComment(unsigned int nr) std::string GCTCheats::getCheatComment(int nr)
{ {
if (nr <= (iCntCheats-1)) if((unsigned int)nr >= cheatList.size())
return sCheatComment[nr]; return ERRORRANGE;
return ERRORRANGE;
return cheatList[nr].sCheatComment;
} }
//creates gct from internal array int GCTCheats::createGCT(const char *filename)
int GCTCheats::createGCT(const char * filename)
{ {
std::ofstream filestr; if (!filename)
filestr.open(filename); return 0;
if (filestr.fail()) return 0;
//Header and Footer FILE *pFile = fopen(filename, "wb");
char header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde};
char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
filestr.write(header,sizeof(header)); if (!pFile)
return 0;
for (unsigned int i=0; i < iCntCheats; ++i) fwrite(GCT_Header, sizeof(GCT_Header), 1, pFile);
if (sCheatSelected[i] == true)
{
// cheat is selected, export it
string buf = getCheat(i);
int x = 0; for(unsigned int i = 0; i < cheatList.size(); ++i)
while (x < (int)buf.size())
{
string temp = buf.substr(x,2);
long int li = strtol(temp.c_str(),NULL,16);
temp = li;
filestr.write(temp.c_str(),1);
x +=2;
}
}
filestr.write(footer,sizeof(footer));
filestr.close();
return 1;
}
//rewrite and save code.txt to mark which codes are #selected#
int GCTCheats::createTXT(const char * filename)
{
// save txt file
std::fstream file;
file.open(filename, std::ios::out);
file << sGameID << std::endl;
file << sGameTitle << std::endl << std::endl;
for (unsigned int i=0; i < iCntCheats; ++i)
if (sCheatSelected[i])
{
file << sCheatName[i] << std::endl;
for (unsigned int j=0; j+8 < sCheats[i].size(); j+=16)
file << sCheats[i].substr(j,8) << " " << sCheats[i].substr(j+8,8) << std::endl;
file << "#selected#" << sCheatComment[i] << std::endl;
file << std::endl;
}
for (unsigned int i=0; i < iCntCheats; ++i)
if (!sCheatSelected[i])
{
file << sCheatName[i] << std::endl;
for (unsigned int j=0; j+8 < sCheats[i].size(); j+=16)
file << sCheats[i].substr(j,8) << " " << sCheats[i].substr(j+8,8) << std::endl;
if (sCheatComment[i].size() > 1)
file << sCheatComment[i] << std::endl;
file << std::endl;
}
file.close();
return 1;
}
int GCTCheats::openTxtfile(const char * filename)
{
Reset();
std::ifstream filestr;
filestr.open(filename);
if (filestr.fail()) return 0;
int i = 0;
string str;
filestr.seekg(0, std::ios_base::end);
int size = filestr.tellg();
if (size <= 0) return -1;
filestr.seekg(0, std::ios_base::beg);
getline(filestr,sGameID);
if (sGameID[sGameID.length() - 1] == '\r')
sGameID.erase(sGameID.length() - 1);
getline(filestr,sGameTitle);
if (sGameTitle[sGameTitle.length() - 1] == '\r')
sGameTitle.erase(sGameTitle.length() - 1);
while (!filestr.eof())
{ {
getline(filestr,sCheatName[i]); if(sCheatSelected[i])
if (sCheatName[i][sCheatName[i].length() - 1] == '\r')
sCheatName[i].erase(sCheatName[i].length() - 1);
if (sCheatName[i].length() == 0)
continue;
string cheatdata;
while (!filestr.eof())
{ {
getline(filestr,str); std::vector<unsigned int> &cheatBuf = cheatList[i].sCheats;
if (str[str.length() - 1] == '\r') if(cheatBuf.size() > 0)
str.erase(str.length() - 1); fwrite((char*)&cheatBuf[0], cheatBuf.size() * sizeof(unsigned int), 1, pFile);
}
if (str == "" || str[0] == '\r' || str[0] == '\n') }
fwrite(GCT_Footer, sizeof(GCT_Footer), 1, pFile);
fclose(pFile);
return 1;
}
static inline void RemoveLineEnds(char *str)
{
const char *strPtr = str;
while(*strPtr != 0)
{
if(*strPtr == '\n' || *strPtr == '\r')
{
strPtr++;
continue;
}
*str = *strPtr;
str++;
strPtr++;
}
*str = 0;
}
int GCTCheats::openTxtfile(const char *filename)
{
//! clear already loaded things
Clear();
FILE *pFile = fopen(filename, "rb");
if (!pFile)
return 0;
fseek(pFile, 0, SEEK_END);
int size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
if (size <= 0) {
fclose(pFile);
return -1;
}
const int max_line_size = 4096;
char *line = new (std::nothrow) char[max_line_size];
if (!line)
{
fclose(pFile);
return -1;
}
fgets(line, max_line_size, pFile);
RemoveLineEnds(line);
sGameID = line;
fgets(line, max_line_size, pFile);
RemoveLineEnds(line);
sGameTitle = line;
while (fgets(line, max_line_size, pFile))
{
RemoveLineEnds(line);
if (*line == 0)
continue;
// first line is the cheat name
CheatEntry cheatEntry;
cheatEntry.sCheatName = line;
while (fgets(line, max_line_size, pFile))
{
RemoveLineEnds(line);
if (*line == 0) // empty line means start of new cheat
break; break;
if (IsCode(str)) if (IsCode(line))
{ {
// remove any garbage (comment) after code // remove any garbage (comment) after code
while (str.size() > 17) line[8] = 0;
str.erase(str.length() - 1); line[17] = 0;
cheatdata.append(str); cheatEntry.sCheats.push_back(strtoul(&line[0], 0, 16));
size_t found=cheatdata.find(' '); cheatEntry.sCheats.push_back(strtoul(&line[9], 0, 16));
cheatdata.replace(found,1,"");
} }
else else
sCheatComment[i] = str; {
cheatEntry.sCheatComment = line;
}
} }
if (cheatdata.size() > 0) if (!cheatEntry.sCheats.empty())
{ cheatList.push_back(cheatEntry);
sCheats[i] = cheatdata;
sCheatSelected[i] = false;
// wiiflow rewrites and saves code.txt with #selected# added to comments if cheat selected
if (sCheatComment[i].compare(0,10,"#selected#") == 0)
{
sCheatSelected[i] = true;
sCheatComment[i].erase(0,10);
}
i++;
}
else
sCheatComment[i] = "";
if (i == MAXCHEATS) break;
} }
iCntCheats = i; fclose(pFile);
filestr.close(); delete [] line;
return 1; return 1;
} }
bool GCTCheats::IsCode(const std::string& str) bool GCTCheats::IsCode(const char *str)
{ {
if (str[8] == ' ' && str.size() >= 17) if (strlen(str) >= 17 && str[8] == ' ')
{ {
// accept strings longer than 17 in case there is a comment on the same line as the code // accept strings longer than 17 in case there is a comment on the same line as the code
char part1[9]; char part1[9];
char part2[9]; char part2[9];
snprintf(part1,sizeof(part1),"%c%c%c%c%c%c%c%c",str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7]); snprintf(part1, sizeof(part1), "%c%c%c%c%c%c%c%c", str[0], str[1], str[2], str[3], str[4], str[5], str[6],
snprintf(part2,sizeof(part2),"%c%c%c%c%c%c%c%c",str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16]); str[7]);
if ((strtok(part1,"0123456789ABCDEFabcdef") == NULL) && (strtok(part2,"0123456789ABCDEFabcdef") == NULL)) snprintf(part2, sizeof(part2), "%c%c%c%c%c%c%c%c", str[9], str[10], str[11], str[12], str[13], str[14],
str[15], str[16]);
if ((strtok(part1, "0123456789ABCDEFabcdef") == NULL) && (strtok(part2, "0123456789ABCDEFabcdef") == NULL))
{
return true; return true;
}
} }
return false; return false;
} }
bool GCTCheats::IsCheatIncluded(int iCheat, const unsigned char *gctBuf, unsigned int gctSize)
int GCTCheats::IsCodeEx(const std::string& str)
{ {
int status = 2; if(!gctBuf || (unsigned int)iCheat >= cheatList.size())
if (str[8] == ' ' && str.size() >= 17) return false;
std::vector<unsigned int> &Cheat = cheatList[iCheat].sCheats;
int len = Cheat.size() * sizeof(unsigned int);
for(unsigned int i = sizeof(GCT_Header); i + len <= gctSize - sizeof(GCT_Footer); i += 4)
{ {
// accept strings longer than 17 in case there is a comment on the same line as the code if(memcmp(&Cheat[0], &gctBuf[i], len) == 0)
for (int i = 0; i < 17; ++i) return true;
{
if (!(str[i] == '0' || str[i] == '1' || str[i] == '2' || str[i] == '3' ||
str[i] == '4' || str[i] == '5' || str[i] == '6' || str[i] == '7' ||
str[i] == '8' || str[i] == '9' || str[i] == 'a' || str[i] == 'b' ||
str[i] == 'c' || str[i] == 'd' || str[i] == 'e' || str[i] == 'f' ||
str[i] == 'A' || str[i] == 'B' || str[i] == 'C' || str[i] == 'D' ||
str[i] == 'E' || str[i] == 'F' || str[i] == 'x' || str[i] == 'X') && i!=8 )
status = 0; // not even x -> no code
if ((str[i] == 'x' || str[i] == 'X') && i!=8 && status >= 1)
status = 1;
}
return status;
} }
return 0; // no code return false;
} }
void GCTCheats::Reset()
{
iCntCheats = 0;
for (int i=0;i<MAXCHEATS;++i)
sCheatSelected[i] = false;
}

View File

@ -1,32 +1,41 @@
/* /****************************************************************************
* gct.h * Copyright (C) 2009 nIxx
* Class to handle Ocarina TXT Cheatfiles * Copyright (C) 2012 Dimok
* *
*/ * This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _GCT_H #ifndef _GCT_H
#define _GCT_H #define _GCT_H
#include <sstream> #include <string>
#include <vector>
#define MAXCHEATS 100
using std::string;
//!Handles Ocarina TXT Cheatfiles //!Handles Ocarina TXT Cheatfiles
class GCTCheats class GCTCheats
{ {
private: private:
string sGameID; std::string sGameID;
string sGameTitle; std::string sGameTitle;
string sCheatName[MAXCHEATS]; struct CheatEntry
string sCheatComment[MAXCHEATS]; {
string sCheats[MAXCHEATS]; std::string sCheatName;
unsigned int iCntCheats; std::string sCheatComment;
std::vector<unsigned int> sCheats;
};
std::vector<CheatEntry> cheatList;
public: public:
//!Array which shows which cheat is selected std::vector<bool> sCheatSelected;
bool sCheatSelected[MAXCHEATS];
//!Constructor //!Constructor
GCTCheats(void); GCTCheats(void);
//!Destructor //!Destructor
@ -34,42 +43,38 @@ class GCTCheats
//!Open txt file with cheats //!Open txt file with cheats
//!\param filename name of TXT file //!\param filename name of TXT file
//!\return error code //!\return error code
int openTxtfile(const char * filename); int openTxtfile(const char *filename);
//!Creates GCT file //!Creates GCT file
//!\param nr[] array of selected Cheat Numbers
//!\param cnt size of array
//!\param filename name of GCT file //!\param filename name of GCT file
//!\return error code //!\return error code
int createGCT(const char * filename); int createGCT(const char *filename);
//!Creates TXT file
//!\param filename name of GCT file
//!\return error code
int createTXT(const char * filename);
//!Gets Count cheats //!Gets Count cheats
//!\return Count cheats //!\return Count cheats
unsigned int getCnt(); unsigned int getCnt() const { return cheatList.size(); }
//!Gets Game Name //!Gets Game Name
//!\return Game Name //!\return Game Name
string getGameName(void); std::string getGameName(void);
//!Gets GameID //!Gets GameID
//!\return GameID //!\return GameID
string getGameID(void); std::string getGameID(void);
//!Gets cheat data //!Gets cheat data
//!\return cheat data //!\return cheat data
string getCheat(unsigned int nr); std::vector<unsigned int> getCheat(int nr);
//!Gets Cheat Name //!Gets Cheat Name
//!\return Cheat Name //!\return Cheat Name
string getCheatName(unsigned int nr); std::string getCheatName(int nr);
//!Gets Cheat Comment //!Gets Cheat Comment
//!\return Cheat Comment //!\return Cheat Comment
string getCheatComment(unsigned int nr); std::string getCheatComment(int nr);
//!Clear all loaded cheats
void Clear(void);
//!Check if string is a code //!Check if string is a code
//!\return true/false //!\return true/false
bool IsCode(const std::string& s); bool IsCode(const char *s);
//!Check if string is a code //!Check if cheat is included in GCT buffer
//!\return 0=ok, 1="X", 2=no code bool IsCheatIncluded(int iCheat, const unsigned char *gctBuf, unsigned int gctSize);
int IsCodeEx(const std::string& s);
private:
//!Resets the internal state, as if no file was loaded
void Reset();
}; };
#endif /* _GCT_H */ #endif /* _GCT_H */

View File

@ -47,11 +47,24 @@ int CMenu::_downloadCheatFileAsync()
void CMenu::_CheatSettings() void CMenu::_CheatSettings()
{ {
SetupInput(); SetupInput();
m_cheatSettingsPage = 1;
const char *id = CoverFlow.getId(); const char *id = CoverFlow.getId();
txtavailable = m_cheatfile.openTxtfile(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id));
m_cheatSettingsPage = 1;
txtavailable = m_cheatfile.openTxtfile(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id)); u32 gctSize = 0;
u8 *gctBuf = NULL;
if(txtavailable > 0)
gctBuf = fsop_ReadFile(fmt("%s/%s.gct", m_cheatDir.c_str(), id), &gctSize);
u8 chtsCnt = m_cheatfile.getCnt();
for(u8 i = 0; i < chtsCnt; ++i)
{
if(gctBuf && m_cheatfile.IsCheatIncluded(i, gctBuf, gctSize))
m_cheatfile.sCheatSelected.push_back(true);
else
m_cheatfile.sCheatSelected.push_back(false);
}
_textCheatSettings(); _textCheatSettings();
_showCheatSettings(); _showCheatSettings();
@ -130,7 +143,7 @@ void CMenu::_CheatSettings()
m_gcfg2.remove(id, "cheat"); m_gcfg2.remove(id, "cheat");
m_gcfg2.remove(id, "hooktype"); m_gcfg2.remove(id, "hooktype");
} }
m_cheatfile.createTXT(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id)); //m_cheatfile.createTXT(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id));
break; break;
} }
else if (m_btnMgr.selected(m_cheatBtnDownload)) else if (m_btnMgr.selected(m_cheatBtnDownload))
@ -173,6 +186,17 @@ void CMenu::_CheatSettings()
} }
} }
txtavailable = m_cheatfile.openTxtfile(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id)); txtavailable = m_cheatfile.openTxtfile(fmt("%s/%s.txt", m_txtCheatDir.c_str(), id));
if(txtavailable > 0)
gctBuf = fsop_ReadFile(fmt("%s/%s.gct", m_cheatDir.c_str(), id), &gctSize);
chtsCnt = m_cheatfile.getCnt();
for(u8 i = 0; i < chtsCnt; ++i)
{
if(gctBuf && m_cheatfile.IsCheatIncluded(i, gctBuf, gctSize))
m_cheatfile.sCheatSelected.push_back(true);
else
m_cheatfile.sCheatSelected.push_back(false);
}
_showCheatSettings(); _showCheatSettings();
} }
} }