Edition of GBA Pokémon files now working properly

This commit is contained in:
TuxSH 2015-09-13 16:22:29 +02:00
parent 5886bcc100
commit b58c79f42d
17 changed files with 110 additions and 62 deletions

View File

@ -99,7 +99,8 @@ public:
u16 TID;
u32 PID;
u8 encounterType;
u8 GCUnk;
VersionInfo version;
bool obedient;
@ -122,7 +123,8 @@ public:
virtual bool hasSecondAbility(void) const = 0;
virtual void setEggFlag(bool flag) = 0;
virtual void setSecondAbilityFlag(bool flag) = 0;
virtual bool isMarkedAsInvalid(void) const = 0;
virtual void setInvalidPokemonFlag(bool flag) = 0;
struct PokemonComputedPartyData {
s8 pkrsDaysRemaining;

View File

@ -21,7 +21,6 @@
#include <boost/config/warning_disable.hpp>
#include <boost/config.hpp>
#include <boost/predef.h>
#define LIBPKMGC_VERSION 1001000
#define LIBPKMGC_VERSION_MAJOR ((LIBPKMGC_VERSION / 1000000) % 1000)

View File

@ -47,6 +47,12 @@ public:
void setSecondAbilityFlag(bool status);
bool isEgg(void) const;
void setEggFlag(bool status);
bool isMarkedAsInvalid(void) const;
void setInvalidPokemonFlag(bool flag);
bool isTradedFromGC(void) const;
void setTradedFromGCFlag(bool flag);
void swap(Base::Pokemon& other);
Pokemon& operator=(Base::Pokemon const& other);
@ -64,7 +70,7 @@ protected:
private:
u32 _flags;
bool _egg, _secondAbility;
bool _egg, _secondAbility, _invalid, _tradedFromGC;
void decryptOrEncrypt(u8* outData);
};

View File

@ -42,8 +42,10 @@ public:
void setSecondAbilityFlag(bool status);
bool isEgg(void) const;
void setEggFlag(bool status);
bool isMarkedAsInvalid(void) const;
void setInvalidPokemonFlag(bool flag);
u8 GCUnk;
u8 encounterType;
u16 shadowPkmID;
bool pkmFlags[3];

View File

@ -239,7 +239,7 @@ void Pokemon::swap(Pokemon& other) {
SW(TID);
SW(PID);
if(fixedSize == other.fixedSize) SW(encounterType);
SW(GCUnk);
SW(version);
SW(partyData);
@ -263,6 +263,9 @@ void Pokemon::swap(Pokemon& other) {
bool a1 = hasSecondAbility(), a2 = other.hasSecondAbility();
setSecondAbilityFlag(a2); setSecondAbilityFlag(a1);
bool i1 = isMarkedAsInvalid(), i2 = other.isMarkedAsInvalid();
setInvalidPokemonFlag(i2); setInvalidPokemonFlag(i1);
}
void Pokemon::copyNonVirtual(Pokemon const& other) {
@ -284,7 +287,7 @@ void Pokemon::copyNonVirtual(Pokemon const& other) {
CP(TID);
CP(PID);
if (fixedSize == other.fixedSize) CP(encounterType);
CP(GCUnk);
CP(version);
CP_ARRAY(specialRibbons, 12);
@ -311,6 +314,7 @@ Pokemon & Pokemon::operator=(Pokemon const & other){
*name = *(other.name);
setEggFlag(other.isEgg());
setSecondAbilityFlag(other.hasSecondAbility());
setInvalidPokemonFlag(other.isMarkedAsInvalid());
}
return *this;
}

View File

@ -54,7 +54,6 @@ PokemonString::~PokemonString(void) {
PokemonString & PokemonString::operator=(PokemonString const & other) {
if (this != &other) {
assert(isGBA() == other.isGBA());
hasChanged = true;
strSz = other.strSz;
_japanese = other._japanese;

View File

@ -17,9 +17,11 @@
*/
#include <LibPkmGC/Core/Crypto.h>
#include <boost/predef.h>
#include <cstring>
using namespace LibPkmGC;
#define os_memcpy memcpy
#define os_memset memset

View File

@ -82,7 +82,7 @@ u8 PokemonMarkings::save(void) const {
u16 pokemonStatusToBitField(PokemonStatus status, s8 turnsOfBadPoison, s8 turnsOfSleepRemaining) {
static const u8 reverseStatuses[] = { 3, 7, 6, 4, 5 };
u16 st;
u16 st = 0;
status = (status != NoStatus && status < Poisoned && status > Asleep) ? NoStatus : status;
if (status == Asleep) st = turnsOfSleepRemaining;
else if (status != NoStatus) st = reverseStatuses[status - 3];
@ -94,7 +94,7 @@ PokemonStatus pokemonStatusFromBitField(u16 status, s8 * turnsOfBadPoison, s8 *
{
static const PokemonStatus statuses[] = { Poisoned, Burnt, Frozen, Paralyzed, BadlyPoisoned };
PokemonStatus ret;
PokemonStatus ret = NoStatus;
s8 tobp = 0, tosr = 0;
tosr = (s8)(status & 7);
tobp = (s8)((status >> 8) & 0xf);
@ -102,7 +102,7 @@ PokemonStatus pokemonStatusFromBitField(u16 status, s8 * turnsOfBadPoison, s8 *
status >>= 3;
for (size_t i = 0; i < 5 && ret == NoStatus; ++i) {
if ((status & 1) != 0) status = statuses[i];
if ((status & 1) != 0) ret = statuses[i];
status >>= 1;
}

View File

@ -37,18 +37,11 @@ void Pokemon::swap(Base::Pokemon & other) {
if (LIBPKMGC_IS_GBA(Pokemon, &other)) swap((Pokemon&)other);
else {
GC::Pokemon& gco = static_cast<GC::Pokemon&>(other);
//bool inval = (GCFlags & 1) != 0; by default always true until the Pkm is traded to Colo/XD
bool inval = !checkChecksum(false);
u8 GCUnk = GCFlags >> 3;
Base::Pokemon::swap(other);
std::swap(GCUnk, gco.GCUnk);
std::swap(inval, gco.pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG]);
bool tradedFromColoXD = true;
bool flgs[] = { _egg, inval, tradedFromColoXD };
setTradedFromGCFlag(true);
GCFlags &= 7;
if (GCUnk > 31) GCUnk = 31;
GCFlags = GCUnk << 3;
for (size_t i = 0; i < 3; ++i)
GCFlags |= flgs[i] << (2 - i);
GCFlags |= GCUnk << 3;
}
}
@ -61,13 +54,10 @@ Pokemon& Pokemon::operator=(Base::Pokemon const& other) {
initWithEmptyData(1);
Base::Pokemon::operator=(other);
GC::Pokemon const& gco = static_cast<GC::Pokemon const&>(other);
bool tradedFromColoXD = true;
bool flgs[] = { _egg, gco.pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG], tradedFromColoXD };
GCFlags = gco.GCUnk << 3;
for (size_t i = 0; i < 3; ++i)
GCFlags |= flgs[i] << (2 - i);
setTradedFromGCFlag(true);
GCFlags &= 7;
if (GCUnk > 31) GCUnk = 31;
GCFlags |= GCUnk << 3;
return *this;
}
}
@ -91,9 +81,7 @@ Pokemon& Pokemon::operator=(Base::Pokemon const& other) {
deleteFields();
initWithEmptyData();
Base::Pokemon::operator=(other);
GBA::Pokemon const& gbao = static_cast<GBA::Pokemon const&>(other);
GCUnk = gbao.GCFlags >> 3;
pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG] = !(((GBA::Pokemon&)(other)).checkChecksum(false));
if (GCUnk > 31) GCUnk = 31;
return *this;
}
else return operator=((Pokemon const&)other);

View File

@ -52,6 +52,7 @@ Pokemon::Pokemon(Pokemon const& other) : Base::Pokemon(other) {
CL(name);
setEggFlag(other.isEgg());
setSecondAbilityFlag(other.hasSecondAbility());
setInvalidPokemonFlag(other.isMarkedAsInvalid());
}
void Pokemon::swap(Pokemon& other) {
Base::Pokemon::swap(other);
@ -96,9 +97,29 @@ bool Pokemon::isEgg(void) const {
void Pokemon::setEggFlag(bool status) {
_egg = status;
GCFlags &= ~4;
GCFlags |= ((_egg) ? 1 : 0) << 2;
}
bool Pokemon::isMarkedAsInvalid(void) const {
return _invalid;
}
void Pokemon::setInvalidPokemonFlag(bool flag) {
_invalid = flag;
GCFlags &= ~1;
GCFlags |= ((_invalid) ? 1 : 0);
}
bool Pokemon::isTradedFromGC(void) const {
return _tradedFromGC;
}
void Pokemon::setTradedFromGCFlag(bool flag) {
_tradedFromGC = flag;
GCFlags &= ~2;
GCFlags |= ((_tradedFromGC) ? 1 : 0) << 1;
}
void Pokemon::reload(const u8 * data, u32 inFlags) {
if (data == NULL) return;
@ -182,6 +203,10 @@ void Pokemon::loadFields(void) {
markings.load(data[27]);
LD_FIELD(u8, GCFlags, 19);
_invalid = (GCFlags & 1) != 0;
_tradedFromGC = (GCFlags & 2) != 0;
GCUnk = GCFlags >> 3;
LD_FIELD(u16, checksum, 28);
LD_FIELD(u16, unk1, 30);
LD_FIELD_E(u16, species, 32, PokemonSpeciesIndex);
@ -200,7 +225,8 @@ void Pokemon::loadFields(void) {
u16 origins;
LD_FIELD(u16, origins, 70);
encounterType = (u8)(origins & 0x7f);
levelMet = (u8)(origins & 0x7f);
if (levelMet > 100) levelMet = 100;
origins >>= 7;
u8 gm = (u8)(origins & 0xf);
origins >>= 4;
@ -268,6 +294,8 @@ void Pokemon::loadFields(void) {
normalizePkrs();
normalizeStatus();
if (!checkChecksum(false)) setInvalidPokemonFlag(true);
}
@ -283,7 +311,7 @@ bool Pokemon::checkChecksum(bool fix) {
}
bool Pokemon::isEmptyOrInvalid(void) const {
return Base::Pokemon::isEmptyOrInvalid() || !const_cast<Pokemon*>(this)->checkChecksum(false);
return Base::Pokemon::isEmptyOrInvalid() || !const_cast<Pokemon*>(this)->checkChecksum(false) || (GCFlags & 2) == 0;
}
void Pokemon::save(void) {
@ -302,6 +330,12 @@ void Pokemon::save(void) {
SV_FIELD(u16, TID, 4);
SV_FIELD(u16, SID, 6);
setTradedFromGCFlag(_tradedFromGC);
setInvalidPokemonFlag(_invalid);
setEggFlag(_egg);
GCFlags &= 7;
if (GCUnk > 31) GCUnk = 31;
GCFlags |= GCUnk << 3;
SV_FIELD(u8, GCFlags, 19);
SV_FIELD(u16, unk1, 30);
SV_FIELD_E(u16, species, 32, PokemonSpeciesIndex);
@ -318,8 +352,8 @@ void Pokemon::save(void) {
SV_FIELD(u8, locationCaught, 69);
u16 origins = 0;
if (encounterType > 0x7f) encounterType = 0x7f;
origins |= encounterType;
if (levelMet > 100) levelMet = 100;
origins |= levelMet;
origins |= (u16) gm << 7;
if (ballCaughtWith == 0 || ballCaughtWith > PremierBall) ballCaughtWith = PokeBall;
origins |= (u16)ballCaughtWith << 11;

View File

@ -30,26 +30,36 @@ Pokemon::~Pokemon(void)
{
}
Pokemon::Pokemon(Pokemon const& other) : Base::Pokemon(other), shadowPkmID(other.shadowPkmID), GCUnk(other.GCUnk) {
Pokemon::Pokemon(Pokemon const& other) : Base::Pokemon(other), shadowPkmID(other.shadowPkmID), encounterType(other.encounterType) {
CL(OTName);
CL(name);
CP_ARRAY(pkmFlags, 3);
setEggFlag(other.isEgg());
setSecondAbilityFlag(other.hasSecondAbility());
}
void Pokemon::swap(Pokemon& other) {
Base::Pokemon::swap(other);
SW(GCUnk);
if (other.fixedSize == fixedSize) SW(shadowPkmID);
if (fixedSize == other.fixedSize) {
SW(encounterType);
SW(shadowPkmID);
}
else {
other.encounterType = encounterType = 0;
other.shadowPkmID = shadowPkmID = 0;
}
SW_ARRAY(pkmFlags, 3);
}
Pokemon& Pokemon::operator=(Pokemon const& other) {
if (this != &other) {
Base::Pokemon::operator=(other);
CP(GCUnk);
if(other.fixedSize == fixedSize) CP(shadowPkmID);
else shadowPkmID = 0;
if (other.fixedSize == fixedSize) {
CP(encounterType);
CP(shadowPkmID);
}
else {
encounterType = 0;
shadowPkmID = 0;
}
CP_ARRAY(pkmFlags, 3);
}
return *this;
@ -71,5 +81,13 @@ void Pokemon::setEggFlag(bool status) {
pkmFlags[LIBPKMGC_GC_EGG_FLAG] = status;
}
bool Pokemon::isMarkedAsInvalid(void) const {
return pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG];
}
void Pokemon::setInvalidPokemonFlag(bool status) {
pkmFlags[LIBPKMGC_GC_INVALID_POKEMON_FLAG] = status;
}
}
}

View File

@ -164,7 +164,6 @@ void PokemonString::fromUTF8(const char * str) {
if (s < 0) break;
dataSz += s;
}
assert(dataSz % 2 == 0);
_data[dataSz++] = 0;
_data[dataSz++] = 0;
hasChanged = true;
@ -172,7 +171,6 @@ void PokemonString::fromUTF8(const char * str) {
const char * PokemonString::toUTF8(void) const {
if (!hasChanged) return _str;
assert(dataSz % 2 == 0);
strSz = 3 * (dataSz / 2);
resizeStr();
@ -183,8 +181,6 @@ const char * PokemonString::toUTF8(void) const {
size_t offset = 0;
while (offset < dataSz) {
assert(strSz < 3 * (dataSz / 2));
u32 c;
s = ucs2be_mbtowc(NULL, &c, (const unsigned char*)_data + offset, 2);
if (s < 0) break;

View File

@ -10,6 +10,7 @@ find_package(Qt5Widgets REQUIRED)
find_package(Qt5LinguistTools)
file(GLOB_RECURSE source_files src/*)
LIST(APPEND source_files resources/PkmGCSaveEditor.rc)
include_directories(${LIBPKMGC_INCLUDE_DIRS} src/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "PkmGCSaveEditor.ico"

View File

@ -477,18 +477,6 @@ void PokemonUI::parseData(void){
partyPrksDaysRemainingFld->setValue(pkm->pkrsStatus >> 4);
updatePkrsDaysRemaining();
/*if ((pkm->pkrsStatus & 0xf) == 0) {
pkrsDaysRemainingFld->setValue(0);
pkrsDaysRemainingFld->setDisabled(true);
partyPrksDaysRemainingFld->setValue(-1);
partyPrksDaysRemainingFld->setDisabled(true);
}
else {
pkrsDaysRemainingFld->setUnsignedRange(0, (pkm->pkrsStatus & 0x3) + 1);
partyPrksDaysRemainingFld->setRange(0, (pkm->pkrsStatus & 0x3) + 1);
pkrsDaysRemainingFld->setUnsignedValue(pkm->pkrsStatus >> 4);
partyPrksDaysRemainingFld->setValue(pkm->pkrsStatus >> 4);
}*/
connect(pkrsStrainFld, SIGNAL(valueChanged(int)), this, SLOT(updatePkrsDaysRemaining()));
@ -556,7 +544,10 @@ void PokemonUI::saveChanges(void){
pkm->happiness = (u8)happinessFld->unsignedValue();
pkm->pkrsStatus = (u8)((pkrsDaysRemainingFld->unsignedValue() << 4) | pkrsStrainFld->unsignedValue());
pkm->partyData.pkrsDaysRemaining = (s8)(partyPrksDaysRemainingFld->value());
pkm->partyData.status = (statusFld->currentIndex() == 0) ? NoStatus : (PokemonStatus)(2 + statusFld->currentIndex());
pkm->partyData.turnsOfBadPoison = (s8)turnsOfBadPoisonFld->value();
pkm->partyData.turnsOfSleepRemaining = (s8)turnsOfSleepRemainingFld->value();
QCheckBox* g1[] = { eggFlagCheckBox, secondAbilityFlagCheckBox, invalidPokemonCheckBox,
notTradableInGameFlagCheckBox, unknownFlagCheckBox, caughtFlagCheckBox };

View File

@ -10,6 +10,9 @@
#include <QApplication>
#include <QDir>
const QString appName = QString("PkmGCSaveEditor v%1.%2").arg(PKMGCSAVEEDITOR_VERSION_MAJOR).arg(PKMGCSAVEEDITOR_VERSION_MINOR);
using namespace GCUIs;
using namespace XDUIs;
using namespace LibPkmGC;
@ -77,6 +80,8 @@ void MWCentralWidget::openPurifierUI(void) {
MainWindow::MainWindow() : QMainWindow(), centralWidget(new MWCentralWidget) {
this->setWindowTitle(appName);
this->setWindowIcon(QIcon(":/PkmGCSaveEditor.ico"));
fileMenu = menuBar()->addMenu(tr("&File"));
openFileAction = new QAction(this);
@ -369,12 +374,12 @@ void MainWindow::openSaveFile(void) {
if (currentSaveSlot == NULL) {
currentSaveFileName = "";
this->setWindowTitle("PkmGCSaveEditor");
this->setWindowTitle(appName);
saveFileAction->setDisabled(true);
saveFileAsAction->setDisabled(true);
}
else {
this->setWindowTitle("PkmGCSaveEditor - " + currentSaveFileName);
this->setWindowTitle(appName + " - " + currentSaveFileName);
saveFileAction->setDisabled(false);
saveFileAsAction->setDisabled(false);
}
@ -434,7 +439,7 @@ void MainWindow::saveSaveFileAs(void) {
}
else {
lastSaveDirectory = QFileInfo(currentSaveFileName).canonicalPath();
this->setWindowTitle("PkmGCSaveEditor - " + currentSaveFileName);
this->setWindowTitle(appName + " - " + currentSaveFileName);
}
}