aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2020-08-13 00:20:34 +0200
committerArisotura <thetotalworm@gmail.com>2020-08-13 00:20:34 +0200
commit4cefff25282fa041dca4b66342ca169b50621959 (patch)
treef12d3c83b83f0a5a5fe6930f42561256da44c116 /src
parent28b8f614ee778b67d9b8f573ee34435739742020 (diff)
add AR code file parser and shit
Diffstat (limited to 'src')
-rw-r--r--src/ARCodeFile.cpp176
-rw-r--r--src/ARCodeFile.h (renamed from src/ARCodeList.h)44
-rw-r--r--src/ARCodeList.cpp38
-rw-r--r--src/AREngine.cpp139
-rw-r--r--src/AREngine.h4
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/frontend/qt_sdl/CheatsDialog.ui3
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>