Skip to content

Commit 35a55e6

Browse files
See desc for more.
- Add GBASettings class for Language, Sound Effect + Music Volume editing. - Properly support Movement Offsets. - Properly update Checksum for the Settings Header as well. - Rename `GetSlot` to `Slot` to keep unique_ptr class return names the same style. - Current Episode can also be edited now, however not really recommended.
1 parent 2fb4a40 commit 35a55e6

13 files changed

Lines changed: 303 additions & 58 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test/*

include/gba/GBACast.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131

3232
class GBACast {
3333
public:
34-
GBACast(const uint8_t Slot, const uint8_t Cast)
35-
: Cast(Cast), Offs((Slot * 0x1000) + 0x46C + (std::min<uint8_t>(25, Cast)) * 0xA) { };
34+
GBACast(const uint32_t Offs, const uint8_t Cast)
35+
: Cast(Cast), Offs(Offs) { };
3636

3737
uint8_t Index() const { return this->Cast; };
3838

include/gba/GBAEpisode.hpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131

3232
class GBAEpisode {
3333
public:
34-
GBAEpisode(const uint8_t Slot, const uint8_t Episode)
35-
: Episode(Episode), Offs((Slot * 0x1000) + EPOffs[std::min<uint8_t>(10, Episode)]) { };
34+
GBAEpisode(const uint8_t Slot, const uint8_t Episode, const uint8_t Move = 0x0)
35+
: Episode(Episode), Offs((Slot * 0x1000) + this->SetOffset(std::min<uint8_t>(Move, 10))) { };
3636

3737
uint8_t Index() const { return this->Episode; };
3838

@@ -46,6 +46,19 @@ class GBAEpisode {
4646
uint32_t Offs = 0;
4747

4848
static constexpr uint32_t EPOffs[11] = { 0x10A, 0x114, 0x128, 0x123, 0x137, 0x12D, 0x150, 0x146, 0x11E, 0x173, 0x16E }; // 11 Episodes.
49+
50+
/* Sets the base offset for the Episodes. */
51+
uint32_t SetOffset(const uint8_t Move) const {
52+
switch(Move) {
53+
case 1:
54+
return this->EPOffs[this->Episode];
55+
56+
case 2:
57+
return this->EPOffs[this->Episode] + 0x6;
58+
}
59+
60+
return this->EPOffs[this->Episode] - 0x6;
61+
};
4962
};
5063

5164
#endif

include/gba/GBASav.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,19 @@
2727
#ifndef _SIM2EDITOR_CPP_CORE_GBA_SAV_HPP
2828
#define _SIM2EDITOR_CPP_CORE_GBA_SAV_HPP
2929

30+
#include "GBASettings.hpp"
3031
#include "GBASlot.hpp"
3132

3233
class GBASAV {
3334
public:
3435
GBASAV(const std::string &SAVFile);
3536

37+
bool SlotExist(const uint8_t Slot);
38+
3639
/* Core Returns and Actions. */
37-
std::unique_ptr<GBASlot> GetSlot(const uint8_t Slot);
40+
std::unique_ptr<GBASlot> Slot(const uint8_t Slot);
41+
std::unique_ptr<GBASettings> Settings() const;
3842
void Finish();
39-
bool SlotExist(const uint8_t Slot);
4043

4144
/* Some Returns. */
4245
uint32_t GetSize() const { return this->SAVSize; };

include/gba/GBASettings.hpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* This file is part of Sim2Editor-CPPCore
3+
* Copyright (C) 2020-2021 SuperSaiyajinStackZ, Universal-Team
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
19+
* * Requiring preservation of specified reasonable legal notices or
20+
* author attributions in that material or in the Appropriate Legal
21+
* Notices displayed by works containing it.
22+
* * Prohibiting misrepresentation of the origin of that material,
23+
* or requiring that modified versions of such material be marked in
24+
* reasonable ways as different from the original version.
25+
*/
26+
27+
#ifndef _SIM2EDITOR_CPP_CORE_GBA_SETTINGS_HPP
28+
#define _SIM2EDITOR_CPP_CORE_GBA_SETTINGS_HPP
29+
30+
#include "../shared/CoreCommon.hpp"
31+
32+
/* GBA Languages. */
33+
enum class GBALanguage : uint8_t {
34+
EN, // English
35+
NL, // Nederlands
36+
FR, // Français
37+
DE, // Deutsch
38+
IT, // Italiano
39+
ES // Español
40+
};
41+
42+
class GBASettings {
43+
public:
44+
GBASettings() { };
45+
46+
uint8_t SFX() const;
47+
void SFX(const uint8_t V);
48+
49+
uint8_t Music() const;
50+
void Music(const uint8_t V);
51+
52+
GBALanguage Language() const;
53+
void Language(const GBALanguage V);
54+
55+
void UpdateChecksum();
56+
private:
57+
static constexpr uint8_t MusicLevels[11] = { 0x0, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF, 0xC8, 0xE1, 0xFF };
58+
static constexpr uint8_t SFXLevels[11] = { 0x0, 0x0C, 0x18, 0x24, 0x30, 0x3C, 0x48, 0x54, 0x60, 0x6C, 0x80 };
59+
};
60+
61+
#endif

include/gba/GBASlot.hpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
class GBASlot {
3636
public:
37-
GBASlot(const uint8_t Slot) : Slot(Slot), Offs(Slot * 0x1000) { };
37+
GBASlot(const uint8_t Slot, const uint8_t AddOffs = 0) : Move(AddOffs), Slot(Slot), Offs(Slot * 0x1000) { };
3838

3939
uint16_t Time() const;
4040
void Time(const uint16_t V);
@@ -68,14 +68,38 @@ class GBASlot {
6868
uint8_t FuelrodsPrice() const;
6969
void FuelrodsPrice(const uint8_t V);
7070

71+
uint8_t CurrentEpisode() const;
72+
void CurrentEpisode(const uint8_t V, const bool ValidCheck = true);
73+
7174
std::unique_ptr<GBAEpisode> Episode(const uint8_t EP) const;
7275
std::unique_ptr<GBACast> Cast(const uint8_t CST) const;
7376
std::unique_ptr<GBASocialMove> SocialMove(const uint8_t Move) const;
7477

7578
bool FixChecksum();
7679
private:
80+
uint8_t Move = 0;
7781
uint8_t Slot = 0;
7882
uint32_t Offs = 0;
83+
84+
/* The Sims 2 GBA is annoying and their movement crap, so this is necessary. */
85+
uint32_t Offset(const uint32_t DefaultOffs = 0x0, const uint32_t MoveOffs1 = 0x0, const uint32_t MoveOffs2 = 0x0) const {
86+
switch(this->Move) {
87+
case 1:
88+
return this->Offs + MoveOffs1;
89+
90+
case 2:
91+
return this->Offs + MoveOffs2;
92+
}
93+
94+
return this->Offs + DefaultOffs;
95+
};
96+
97+
/* This contains all official Episode Values found at offset (Slot * 0x1000) + 0x1A9. */
98+
static constexpr uint8_t EPVals[12] = {
99+
0x0, 0x1, 0x3, 0x7, // Tutorial + Season 1.
100+
0x6, 0xA, 0x8, 0xF, // Season 2.
101+
0xD, 0x5, 0x16, 0x15 // Season 3.
102+
};
79103
};
80104

81105
#endif

include/gba/GBASocialMove.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ enum class SocialMoveFlag : uint8_t {
3737

3838
class GBASocialMove {
3939
public:
40-
GBASocialMove(const uint8_t Slot, const uint8_t Move)
41-
: Move(Move), Offs((Slot * 0x1000) + 0x3F0 + (std::min<uint8_t>(14, Move)) * 0x8) { };
40+
GBASocialMove(const uint32_t Offs, const uint8_t Move)
41+
: Move(Move), Offs(Offs) { };
4242

4343
uint8_t Index() const { return this->Move; };
4444

include/shared/Checksum.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@
3030
#include "CoreCommon.hpp"
3131

3232
namespace Checksum {
33-
/* GBA Checksum. */
33+
/* GBA Main Slot Checksum. */
3434
uint16_t CalcGBASlot(const uint8_t *Buffer, const uint8_t Slot);
3535
bool GBASlotChecksumValid(const uint8_t *Buffer, const uint8_t Slot, const uint16_t CHKS);
3636

37+
/* GBA Settings Checksum Calculation. */
38+
uint16_t CalcGBASettings(const uint8_t *Buffer);
39+
bool GBASettingsValid(const uint8_t *Buffer, const uint16_t CHKS);
40+
3741
/* NDS Checksum. The NDS version has multiple ones though. */
3842
uint16_t CalcNDSSlot(const uint8_t *Buffer, const uint8_t Slot);
3943
bool NDSSlotChecksumValid(const uint8_t *Buffer, const uint8_t Slot, const uint16_t CHKS);

source/gba/GBASav.cpp

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,46 @@ GBASAV::GBASAV(const std::string &SAVFile) {
4545
fclose(SAV);
4646

4747
this->SAVValid = true;
48+
if (this->SAVData.get()[0xA] > 5) { // Language Index is 6 or larger, which is "blank" and can break the game.
49+
this->SAVData.get()[0xA] = 0; // English.
50+
this->SetChangesMade(true);
51+
}
52+
}
53+
};
54+
55+
/*
56+
Return, wheter a Slot is valid / exist.
57+
58+
const uint8_t Slot: The Slot to check.
59+
*/
60+
bool GBASAV::SlotExist(const uint8_t Slot) {
61+
if (Slot < 1 || Slot > 4 || !this->GetValid()) return false;
62+
63+
for (uint8_t Idx = 0; Idx < 10; Idx++) {
64+
if (this->SAVData.get()[(Slot * 0x1000) + Idx] != 0) return true;
4865
}
66+
67+
return false;
4968
};
5069

5170
/*
5271
Return a GBASlot class.
5372
5473
const uint8_t Slot: The GBASAV Slot ( 1 - 4 ).
5574
*/
56-
std::unique_ptr<GBASlot> GBASAV::GetSlot(const uint8_t Slot) {
75+
std::unique_ptr<GBASlot> GBASAV::Slot(const uint8_t Slot) {
5776
if (!this->SlotExist(Slot)) return nullptr;
5877

59-
return std::make_unique<GBASlot>(Slot);
78+
return std::make_unique<GBASlot>(Slot, this->SAVData.get()[(Slot * 0x1000) + 0xD6]);
6079
};
6180

81+
/* Get a Settings class. */
82+
std::unique_ptr<GBASettings> GBASAV::Settings() const { return std::make_unique<GBASettings>(); };
83+
6284
/*
6385
Finish call before writting to file.
6486
65-
Fix the Checksum of all existing Slots, if invalid.
87+
Fix the Checksum of all existing Slots and the Settings, if invalid.
6688
*/
6789
void GBASAV::Finish() {
6890
if (!this->GetValid()) return;
@@ -74,19 +96,7 @@ void GBASAV::Finish() {
7496
}
7597
}
7698
}
77-
};
78-
79-
/*
80-
Return, wheter a Slot is valid / exist.
8199

82-
const uint8_t Slot: The Slot to check.
83-
*/
84-
bool GBASAV::SlotExist(const uint8_t Slot) {
85-
if (Slot < 1 || Slot > 4 || !this->GetValid()) return false;
86-
87-
for (uint8_t Idx = 0; Idx < 10; Idx++) {
88-
if (this->SAVData.get()[(Slot * 0x1000) + Idx] != 0) return true;
89-
}
90-
91-
return false;
100+
/* Do the same with the Settings. */
101+
this->Settings()->UpdateChecksum();
92102
};

source/gba/GBASettings.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* This file is part of Sim2Editor-CPPCore
3+
* Copyright (C) 2020-2021 SuperSaiyajinStackZ, Universal-Team
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
19+
* * Requiring preservation of specified reasonable legal notices or
20+
* author attributions in that material or in the Appropriate Legal
21+
* Notices displayed by works containing it.
22+
* * Prohibiting misrepresentation of the origin of that material,
23+
* or requiring that modified versions of such material be marked in
24+
* reasonable ways as different from the original version.
25+
*/
26+
27+
#include "GBASettings.hpp"
28+
#include "../shared/Checksum.hpp"
29+
#include "../shared/SAVUtils.hpp"
30+
31+
/* Get and Set the Sound Effect Volume. */
32+
uint8_t GBASettings::SFX() const { return GBASAVUtils::Read<uint8_t>(0x8); };
33+
void GBASettings::SFX(const uint8_t V) {
34+
if (V > 10) return; // 0 - 10 only valid.
35+
GBASAVUtils::Write<uint8_t>(0x8, this->SFXLevels[V]);
36+
};
37+
38+
/* Get and Set the Music Volume. */
39+
uint8_t GBASettings::Music() const { return GBASAVUtils::Read<uint8_t>(0x9); };
40+
void GBASettings::Music(const uint8_t V) {
41+
if (V > 10) return; // 0 - 10 only valid.
42+
GBASAVUtils::Write<uint8_t>(0x9, this->MusicLevels[V]);
43+
};
44+
45+
/* Get and Set the Language. */
46+
GBALanguage GBASettings::Language() const {
47+
if (GBASAVUtils::Read<uint8_t>(0xA) > 5) return GBALanguage::EN; // Technically, that would be a "blank" Language in game, but ehh that's not good.
48+
return (GBALanguage)GBASAVUtils::Read<uint8_t>(0xA);
49+
};
50+
void GBASettings::Language(const GBALanguage V) {
51+
GBASAVUtils::Write<uint8_t>(0xA, (uint8_t)V);
52+
};
53+
54+
/* Update the Checksum of the GBA Settings. */
55+
void GBASettings::UpdateChecksum() {
56+
if (!Checksum::GBASettingsValid(GBASAVUtils::SAV->GetData(), GBASAVUtils::Read<uint16_t>(0xE))) { // Update if not valid.
57+
GBASAVUtils::Write<uint16_t>(0xE, Checksum::CalcGBASettings(GBASAVUtils::SAV->GetData()));
58+
}
59+
};

0 commit comments

Comments
 (0)