Qt: Display hex values within cheats

This commit is contained in:
Jeffrey Pfau 2015-02-14 22:45:40 -08:00
parent 8741a374a5
commit ca6b2e7b09
7 changed files with 102 additions and 13 deletions

View File

@ -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

View File

@ -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*);

View File

@ -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();
}

View File

@ -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);

View File

@ -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();

View File

@ -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>

View File

@ -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; \
} \