diff options
author | Arisotura <thetotalworm@gmail.com> | 2020-08-13 00:20:34 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2020-08-13 00:20:34 +0200 |
commit | 4cefff25282fa041dca4b66342ca169b50621959 (patch) | |
tree | f12d3c83b83f0a5a5fe6930f42561256da44c116 /src | |
parent | 28b8f614ee778b67d9b8f573ee34435739742020 (diff) |
add AR code file parser and shit
Diffstat (limited to 'src')
-rw-r--r-- | src/ARCodeFile.cpp | 176 | ||||
-rw-r--r-- | src/ARCodeFile.h (renamed from src/ARCodeList.h) | 44 | ||||
-rw-r--r-- | src/ARCodeList.cpp | 38 | ||||
-rw-r--r-- | src/AREngine.cpp | 139 | ||||
-rw-r--r-- | src/AREngine.h | 4 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/frontend/qt_sdl/CheatsDialog.ui | 3 |
7 files changed, 250 insertions, 156 deletions
diff --git a/src/ARCodeFile.cpp b/src/ARCodeFile.cpp new file mode 100644 index 0000000..d2f47ff --- /dev/null +++ b/src/ARCodeFile.cpp @@ -0,0 +1,176 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include <stdio.h> +#include <string.h> +#include "ARCodeFile.h" +#include "Platform.h" + + +// TODO: import codes from other sources (usrcheat.dat, ...) +// TODO: more user-friendly error reporting + + +ARCodeFile::ARCodeFile(const char* filename) +{ + memset(Filename, 0, sizeof(Filename)); + strncpy(Filename, filename, 1023); + + Error = false; + + Categories.clear(); + + FILE* f = Platform::OpenFile(Filename, "r"); + if (!f) return; + + bool isincat = false; + ARCodeCat curcat; + + bool isincode = false; + ARCode curcode; + + char linebuf[1024]; + while (!feof(f)) + { + fgets(linebuf, 1024, f); + linebuf[1023] = '\0'; + + char* start = linebuf; + while (start[0]==' ' || start[0]=='\t') + start++; + + if (start[0]=='#' || start[0]=='\r' || start[0]=='\n' || start[0]=='\0') + continue; + + if (!strncasecmp(start, "CAT", 3)) + { + char catname[128]; + int ret = sscanf(start, "CAT %127[^\n]", catname); + catname[127] = '\0'; + + if (ret < 1) + { + printf("AR: malformed CAT line: %s\n", start); + fclose(f); + Error = true; + return; + } + + if (isincode) curcat.Codes.push_back(curcode); + isincode = false; + + if (isincat) Categories.push_back(curcat); + isincat = true; + + memcpy(curcat.Name, catname, 128); + curcat.Codes.clear(); + } + else if (!strncasecmp(start, "CODE", 4)) + { + int enable; + char codename[128]; + int ret = sscanf(start, "CODE %d %127[^\n]", &enable, codename); + codename[127] = '\0'; + + if (ret < 2) + { + printf("AR: malformed CODE line: %s\n", start); + fclose(f); + Error = true; + return; + } + + if (!isincat) + { + printf("AR: encountered CODE line with no category started\n"); + fclose(f); + Error = true; + return; + } + + if (isincode) curcat.Codes.push_back(curcode); + isincode = true; + + memcpy(curcode.Name, codename, 128); + curcode.Enabled = enable!=0; + curcode.CodeLen = 0; + } + else + { + u32 c0, c1; + int ret = sscanf(start, "%08X %08X", &c0, &c1); + + if (ret < 2) + { + printf("AR: malformed data line: %s\n", start); + fclose(f); + Error = true; + return; + } + + if (!isincode) + { + printf("AR: encountered data line with no code started\n"); + fclose(f); + Error = true; + return; + } + + if (curcode.CodeLen >= 2*64) + { + printf("AR: code too long!\n"); + fclose(f); + Error = true; + return; + } + + u32 idx = curcode.CodeLen; + curcode.Code[idx+0] = c0; + curcode.Code[idx+1] = c1; + curcode.CodeLen += 2; + } + } + + if (isincode) curcat.Codes.push_back(curcode); + if (isincat) Categories.push_back(curcat); + + fclose(f); + + printf("PARSED OUTPUT\n"); + for (ARCodeCatList::iterator it = Categories.begin(); it != Categories.end(); it++) + { + ARCodeCat& cat = *it; + printf("CAT %s\n", cat.Name); + + for (ARCodeList::iterator jt = cat.Codes.begin(); jt != cat.Codes.end(); jt++) + { + ARCode& code = *jt; + printf("CODE %d %s\n", code.Enabled, code.Name); + + for (u32 i = 0; i < code.CodeLen; i+=2) + { + printf("%08X %08X\n", code.Code[i], code.Code[i+1]); + } + } + } +} + +ARCodeFile::~ARCodeFile() +{ + // +} diff --git a/src/ARCodeList.h b/src/ARCodeFile.h index b46510c..548bfeb 100644 --- a/src/ARCodeList.h +++ b/src/ARCodeFile.h @@ -16,18 +16,48 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -#ifndef ARCODELIST_H -#define ARCODELIST_H +#ifndef ARCODEFILE_H +#define ARCODEFILE_H + +#include <vector> #include "types.h" -#define ARCL_MAJOR 1 -#define ARCL_MINOR 1 +typedef struct +{ + char Name[128]; + bool Enabled; + u32 CodeLen; + u32 Code[2*64]; + +} ARCode; + +typedef std::vector<ARCode> ARCodeList; -class ARCodeList +typedef struct +{ + char Name[128]; + ARCodeList Codes; + +} ARCodeCat; + +typedef std::vector<ARCodeCat> ARCodeCatList; + + +class ARCodeFile { public: - // + ARCodeFile(const char* filename); + ~ARCodeFile(); + + bool Error; + + bool Save(); + + ARCodeCatList Categories; + +private: + char Filename[1024]; }; -#endif // ARCODELIST_H +#endif // ARCODEFILE_H diff --git a/src/ARCodeList.cpp b/src/ARCodeList.cpp deleted file mode 100644 index 380481f..0000000 --- a/src/ARCodeList.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS 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. - - melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include <stdio.h> -#include "ARCodeList.h" - -/* - Action Replay code list format - - header: - 00 - magic MLAR - 04 - version major - 06 - version minor - 08 - length - 0C - number of codes - - code header: - 00 - magic MLCD - 04 - name length - 08 - code length - 0C - enable flag - 10 - code data (UTF8 name then actual code) -*/ diff --git a/src/AREngine.cpp b/src/AREngine.cpp index 2b6df65..8ebf46c 100644 --- a/src/AREngine.cpp +++ b/src/AREngine.cpp @@ -25,119 +25,30 @@ namespace AREngine { -typedef struct -{ - u32 Code[2 * 64]; // TODO: more sensible size for this? allocate on demand? - bool Enabled; - -} CheatEntry; - -// TODO: more sensible size for this? allocate on demand? -CheatEntry CheatCodes[64]; -u32 NumCheatCodes; - - -void ParseTextCode(char* text, int tlen, u32* code, int clen) // or whatever this should be named? -{ - u32 cur_word = 0; - u32 ndigits = 0; - u32 nin = 0; - u32 nout = 0; - - char c; - while ((c = *text++) != '\0') - { - u32 val; - if (c >= '0' && c <= '9') - val = c - '0'; - else if (c >= 'a' && c <= 'f') - val = c - 'a' + 0xA; - else if (c >= 'A' && c <= 'F') - val = c - 'A' + 0xA; - else - continue; - - cur_word <<= 4; - cur_word |= val; - - ndigits++; - if (ndigits >= 8) - { - if (nout >= clen) - { - printf("AR: code too long!\n"); - return; - } - - *code++ = cur_word; - nout++; - - ndigits = 0; - cur_word = 0; - } - - nin++; - if (nin >= tlen) break; - } - - if (nout & 1) - { - printf("AR: code was missing one word\n"); - if (nout >= clen) - { - printf("AR: code too long!\n"); - return; - } - *code++ = 0; - } -} +// AR code file - frontend is responsible for managing this +ARCodeFile* CodeFile; bool Init() { + CodeFile = nullptr; + return true; } void DeInit() { - // } void Reset() { - memset(CheatCodes, 0, sizeof(CheatCodes)); - NumCheatCodes = 0; - - // TODO: acquire codes from a sensible source! - CheatEntry* entry = &CheatCodes[0]; - u32* ptr = &entry->Code[0]; - - /*char* test = R"(9209D09A 00000000 -6209B468 00000000 -B209B468 00000000 -10000672 000003FF -D2000000 00000000 -9209D09A 00000000 -94000130 FCBF0000 -6209B468 00000000 -B209B468 00000000 -200006B3 00000001 -200006B4 00000001 -D2000000 00000000 -9209D09A 00000000 -94000130 FC7F0000 -6209B468 00000000 -B209B468 00000000 -10000672 00000000 -D2000000 00000000)"; - ParseTextCode(test, entry->Code, 2*64); - printf("PARSED CODE:\n"); - for (int i = 0; i < 2*64; i+=2) - { - printf("%08X %08X\n", entry->Code[i], entry->Code[i+1]); - } - entry->Enabled = true; - NumCheatCodes++;*/ + CodeFile = nullptr; +} + + +void SetCodeFile(ARCodeFile* file) +{ + CodeFile = file; } @@ -147,9 +58,9 @@ D2000000 00000000)"; case ((x)+0x08): case ((x)+0x09): case ((x)+0x0A): case ((x)+0x0B): \ case ((x)+0x0C): case ((x)+0x0D): case ((x)+0x0E): case ((x)+0x0F) -void RunCheat(CheatEntry* entry) +void RunCheat(ARCode& arcode) { - u32* code = &entry->Code[0]; + u32* code = &arcode.Code[0]; u32 offset = 0; u32 datareg = 0; @@ -166,9 +77,11 @@ void RunCheat(CheatEntry* entry) for (;;) { + if (code >= &arcode.Code[arcode.CodeLen]) + break; + u32 a = *code++; u32 b = *code++; - if ((a|b) == 0) break; u8 op = a >> 24; @@ -179,7 +92,7 @@ void RunCheat(CheatEntry* entry) if ((op & 0xF0) == 0xE0) { for (u32 i = 0; i < b; i += 8) - *code += 2; + code += 2; } continue; @@ -428,7 +341,7 @@ void RunCheat(CheatEntry* entry) if (bytesleft > 0) { u8* leftover = (u8*)code; - *code += 2; + code += 2; if (bytesleft >= 4) { NDS::ARM7Write32(dstaddr, *(u32*)leftover); dstaddr += 4; @@ -477,13 +390,19 @@ void RunCheat(CheatEntry* entry) void RunCheats() { - // TODO: make it disableable in general + if (!CodeFile) return; - for (u32 i = 0; i < NumCheatCodes; i++) + for (ARCodeCatList::iterator i = CodeFile->Categories.begin(); i != CodeFile->Categories.end(); i++) { - CheatEntry* entry = &CheatCodes[i]; - if (entry->Enabled) - RunCheat(entry); + ARCodeCat& cat = *i; + + for (ARCodeList::iterator j = cat.Codes.begin(); j != cat.Codes.end(); j++) + { + ARCode& code = *j; + + if (code.Enabled) + RunCheat(code); + } } } diff --git a/src/AREngine.h b/src/AREngine.h index a78405f..3b1c5fa 100644 --- a/src/AREngine.h +++ b/src/AREngine.h @@ -19,6 +19,8 @@ #ifndef ARENGINE_H #define ARENGINE_H +#include "ARCodeFile.h" + namespace AREngine { @@ -26,6 +28,8 @@ bool Init(); void DeInit(); void Reset(); +void SetCodeFile(ARCodeFile* file); + void RunCheats(); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd81f52..24a7ecf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ project(core) set (CMAKE_CXX_STANDARD 14) add_library(core STATIC - ARCodeList.cpp + ARCodeFile.cpp AREngine.cpp ARM.cpp ARM_InstrTable.h diff --git a/src/frontend/qt_sdl/CheatsDialog.ui b/src/frontend/qt_sdl/CheatsDialog.ui index 3191ef2..493111d 100644 --- a/src/frontend/qt_sdl/CheatsDialog.ui +++ b/src/frontend/qt_sdl/CheatsDialog.ui @@ -74,6 +74,9 @@ <height>0</height> </size> </property> + <property name="headerHidden"> + <bool>true</bool> + </property> </widget> </item> <item> |