mirror of https://github.com/mgba-emu/mgba.git
Qt: Display hex values within cheats
This commit is contained in:
parent
8741a374a5
commit
ca6b2e7b09
|
@ -15,6 +15,7 @@ const uint32_t GBA_CHEAT_DEVICE_ID = 0xABADC0DE;
|
|||
|
||||
DEFINE_VECTOR(GBACheatList, struct GBACheat);
|
||||
DEFINE_VECTOR(GBACheatSets, struct GBACheatSet*);
|
||||
DEFINE_VECTOR(StringList, char*);
|
||||
|
||||
static const uint32_t _gsa1S[4] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 };
|
||||
static const uint32_t _par3S[4] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
|
||||
|
@ -188,6 +189,10 @@ static const char* _hex16(const char* line, uint16_t* out) {
|
|||
return line;
|
||||
}
|
||||
|
||||
static void _registerLine(struct GBACheatSet* cheats, const char* line) {
|
||||
*StringListAppend(&cheats->lines) = strdup(line);
|
||||
}
|
||||
|
||||
// http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
|
||||
static void _decryptGameShark(uint32_t* op1, uint32_t* op2, const uint32_t* seeds) {
|
||||
uint32_t sum = 0xC6EF3720;
|
||||
|
@ -405,6 +410,7 @@ void GBACheatDeviceDestroy(struct GBACheatDevice* device) {
|
|||
|
||||
void GBACheatSetInit(struct GBACheatSet* set, const char* name) {
|
||||
GBACheatListInit(&set->list, 4);
|
||||
StringListInit(&set->lines, 4);
|
||||
set->incompleteCheat = 0;
|
||||
set->gsaVersion = 0;
|
||||
set->remainingAddresses = 0;
|
||||
|
@ -422,6 +428,10 @@ void GBACheatSetInit(struct GBACheatSet* set, const char* name) {
|
|||
|
||||
void GBACheatSetDeinit(struct GBACheatSet* set) {
|
||||
GBACheatListDeinit(&set->list);
|
||||
size_t i;
|
||||
for (i = 0; i < StringListSize(&set->lines); ++i) {
|
||||
free(*StringListGetPointer(&set->lines, i));
|
||||
}
|
||||
if (set->name) {
|
||||
free(set->name);
|
||||
}
|
||||
|
@ -463,6 +473,10 @@ void GBACheatRemoveSet(struct GBACheatDevice* device, struct GBACheatSet* cheats
|
|||
}
|
||||
|
||||
bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t op2) {
|
||||
char line[14] = "XXXXXXXX XXXX";
|
||||
snprintf(line, sizeof(line), "%08X %04X", op1, op2);
|
||||
_registerLine(cheats, line);
|
||||
|
||||
enum GBACodeBreakerType type = op1 >> 28;
|
||||
struct GBACheat* cheat = 0;
|
||||
|
||||
|
@ -592,6 +606,10 @@ bool GBACheatAddCodeBreakerLine(struct GBACheatSet* cheats, const char* line) {
|
|||
bool GBACheatAddGameShark(struct GBACheatSet* set, uint32_t op1, uint32_t op2) {
|
||||
uint32_t o1 = op1;
|
||||
uint32_t o2 = op2;
|
||||
char line[18] = "XXXXXXXX XXXXXXXX";
|
||||
snprintf(line, sizeof(line), "%08X %08X", op1, op2);
|
||||
_registerLine(set, line);
|
||||
|
||||
switch (set->gsaVersion) {
|
||||
case 0:
|
||||
_setGameSharkVersion(set, 1);
|
||||
|
@ -623,6 +641,10 @@ bool GBACheatAddGameSharkLine(struct GBACheatSet* cheats, const char* line) {
|
|||
bool GBACheatAddAutodetect(struct GBACheatSet* set, uint32_t op1, uint32_t op2) {
|
||||
uint32_t o1 = op1;
|
||||
uint32_t o2 = op2;
|
||||
char line[18] = "XXXXXXXX XXXXXXXX";
|
||||
snprintf(line, sizeof(line), "%08X %08X", op1, op2);
|
||||
_registerLine(set, line);
|
||||
|
||||
switch (set->gsaVersion) {
|
||||
case 0:
|
||||
// Try to detect GameShark version
|
||||
|
|
|
@ -142,6 +142,7 @@ struct GBACheatHook {
|
|||
};
|
||||
|
||||
DECLARE_VECTOR(GBACheatList, struct GBACheat);
|
||||
DECLARE_VECTOR(StringList, char*);
|
||||
|
||||
struct GBACheatSet {
|
||||
struct GBACheatHook* hook;
|
||||
|
@ -162,6 +163,7 @@ struct GBACheatSet {
|
|||
int remainingAddresses;
|
||||
|
||||
char* name;
|
||||
struct StringList lines;
|
||||
};
|
||||
|
||||
DECLARE_VECTOR(GBACheatSets, struct GBACheatSet*);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "CheatsModel.h"
|
||||
|
||||
#include <QFont>
|
||||
|
||||
extern "C" {
|
||||
#include "gba/cheats.h"
|
||||
#include "util/vfs.h"
|
||||
|
@ -23,8 +25,22 @@ QVariant CheatsModel::data(const QModelIndex& index, int role) const {
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
if (index.parent().isValid()) {
|
||||
int row = index.row();
|
||||
GBACheatSet* cheats = static_cast<GBACheatSet*>(index.internalPointer());
|
||||
const char* line = *StringListGetPointer(&cheats->lines, row);
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return line;
|
||||
case Qt::FontRole:
|
||||
return QFont("Courier New", 13);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
const GBACheatSet* cheats = static_cast<const GBACheatSet*>(index.internalPointer());
|
||||
const GBACheatSet* cheats = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
|
@ -37,12 +53,12 @@ QVariant CheatsModel::data(const QModelIndex& index, int role) const {
|
|||
}
|
||||
|
||||
bool CheatsModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
if (!index.isValid()) {
|
||||
if (!index.isValid() || index.parent().isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
GBACheatSet* cheats = static_cast<GBACheatSet*>(index.internalPointer());
|
||||
GBACheatSet* cheats = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
|
@ -60,10 +76,26 @@ bool CheatsModel::setData(const QModelIndex& index, const QVariant& value, int r
|
|||
}
|
||||
|
||||
QModelIndex CheatsModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
return createIndex(row, column, *GBACheatSetsGetPointer(&m_device->cheats, row));
|
||||
if (parent.isValid()) {
|
||||
return createIndex(row, column, *GBACheatSetsGetPointer(&m_device->cheats, parent.row()));
|
||||
} else {
|
||||
return createIndex(row, column, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex CheatsModel::parent(const QModelIndex& index) const {
|
||||
if (!index.isValid()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
const GBACheatSet* cheats = static_cast<const GBACheatSet*>(index.internalPointer());
|
||||
if (!cheats) {
|
||||
return QModelIndex();
|
||||
}
|
||||
for (size_t i = 0; i < GBACheatSetsSize(&m_device->cheats); ++i) {
|
||||
if (cheats == *GBACheatSetsGetPointer(&m_device->cheats, i)) {
|
||||
return createIndex(i, 0, nullptr);
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
@ -72,6 +104,10 @@ Qt::ItemFlags CheatsModel::flags(const QModelIndex &index) const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (index.parent().isValid()) {
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
|
@ -81,7 +117,11 @@ int CheatsModel::columnCount(const QModelIndex& parent) const {
|
|||
|
||||
int CheatsModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
if (parent.internalPointer()) {
|
||||
return 0;
|
||||
}
|
||||
const GBACheatSet* set = *GBACheatSetsGetPointer(&m_device->cheats, parent.row());
|
||||
return StringListSize(&set->lines);
|
||||
}
|
||||
return GBACheatSetsSize(&m_device->cheats);
|
||||
}
|
||||
|
@ -90,15 +130,18 @@ GBACheatSet* CheatsModel::itemAt(const QModelIndex& index) {
|
|||
if (!index.isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<GBACheatSet*>(index.internalPointer());
|
||||
if (index.parent().isValid()) {
|
||||
return static_cast<GBACheatSet*>(index.internalPointer());
|
||||
}
|
||||
return *GBACheatSetsGetPointer(&m_device->cheats, index.row());
|
||||
}
|
||||
|
||||
void CheatsModel::removeAt(const QModelIndex& index) {
|
||||
if (!index.isValid()) {
|
||||
if (!index.isValid() || index.parent().isValid()) {
|
||||
return;
|
||||
}
|
||||
int row = index.row();
|
||||
GBACheatSet* set = static_cast<GBACheatSet*>(index.internalPointer());
|
||||
GBACheatSet* set = *GBACheatSetsGetPointer(&m_device->cheats, index.row());
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
GBACheatRemoveSet(m_device, set);
|
||||
GBACheatSetDeinit(set);
|
||||
|
@ -107,6 +150,18 @@ void CheatsModel::removeAt(const QModelIndex& index) {
|
|||
|
||||
}
|
||||
|
||||
void CheatsModel::beginAppendRow(const QModelIndex& index) {
|
||||
if (index.parent().isValid()) {
|
||||
beginInsertRows(index.parent(), rowCount(index.parent()), rowCount(index.parent()));
|
||||
return;
|
||||
}
|
||||
beginInsertRows(index, rowCount(index), rowCount(index));
|
||||
}
|
||||
|
||||
void CheatsModel::endAppendRow() {
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CheatsModel::loadFile(const QString& path) {
|
||||
VFile* vf = VFileOpen(path.toLocal8Bit().constData(), O_RDONLY);
|
||||
if (!vf) {
|
||||
|
@ -119,7 +174,7 @@ void CheatsModel::loadFile(const QString& path) {
|
|||
}
|
||||
|
||||
void CheatsModel::addSet(GBACheatSet* set) {
|
||||
beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats) + 1);
|
||||
beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats));
|
||||
GBACheatAddSet(m_device, set);
|
||||
endInsertRows();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
GBACheatSet* itemAt(const QModelIndex& index);
|
||||
void removeAt(const QModelIndex& index);
|
||||
|
||||
void beginAppendRow(const QModelIndex& index);
|
||||
void endAppendRow();
|
||||
|
||||
void loadFile(const QString& path);
|
||||
void addSet(GBACheatSet* set);
|
||||
|
||||
|
|
|
@ -60,11 +60,13 @@ void CheatsView::addSet() {
|
|||
void CheatsView::removeSet() {
|
||||
GBACheatSet* set;
|
||||
QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
|
||||
if (selection.count() != 1) {
|
||||
if (selection.count() < 1) {
|
||||
return;
|
||||
}
|
||||
m_controller->threadInterrupt();
|
||||
m_model.removeAt(selection[0]);
|
||||
for (const QModelIndex& index : selection) {
|
||||
m_model.removeAt(selection[0]);
|
||||
}
|
||||
m_controller->threadContinue();
|
||||
}
|
||||
|
||||
|
@ -81,7 +83,9 @@ void CheatsView::enterCheat(std::function<bool(GBACheatSet*, const char*)> callb
|
|||
m_controller->threadInterrupt();
|
||||
QStringList cheats = m_ui.codeEntry->toPlainText().split('\n', QString::SkipEmptyParts);
|
||||
for (const QString& string : cheats) {
|
||||
m_model.beginAppendRow(selection[0]);
|
||||
callback(set, string.toLocal8Bit().constData());
|
||||
m_model.endAppendRow();
|
||||
}
|
||||
m_controller->threadContinue();
|
||||
m_ui.codeEntry->clear();
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
void NAME ## Shift(struct NAME* vector, size_t location, size_t difference); \
|
||||
void NAME ## Unshift(struct NAME* vector, size_t location, size_t difference); \
|
||||
void NAME ## EnsureCapacity(struct NAME* vector, size_t capacity); \
|
||||
size_t NAME ## Size(struct NAME* vector); \
|
||||
size_t NAME ## Size(const struct NAME* vector); \
|
||||
|
||||
#define DEFINE_VECTOR(NAME, TYPE) \
|
||||
void NAME ## Init(struct NAME* vector, size_t capacity) { \
|
||||
|
@ -72,7 +72,7 @@
|
|||
NAME ## Resize(vector, difference); \
|
||||
memmove(&vector->vector[location + difference], &vector->vector[location], (vector->size - location - difference) * sizeof(TYPE)); \
|
||||
} \
|
||||
size_t NAME ## Size(struct NAME* vector) { \
|
||||
size_t NAME ## Size(const struct NAME* vector) { \
|
||||
return vector->size; \
|
||||
} \
|
||||
|
||||
|
|
Loading…
Reference in New Issue