Skip to content

Commit

Permalink
Merge pull request #455 from Ghabry/strvec
Browse files Browse the repository at this point in the history
Support Vector<DBString>
  • Loading branch information
fdelapena authored Apr 24, 2023
2 parents de7ede0 + 7a1e970 commit d1fc1b4
Show file tree
Hide file tree
Showing 16 changed files with 313 additions and 49 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(CMAKE_CXX_EXTENSIONS ON)
# lcf library files
set(LCF_SOURCES
src/dbarray.cpp
src/dbstring_struct.cpp
src/encoder.cpp
src/ini.cpp
src/inireader.cpp
Expand Down
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ liblcf_la_LDFLAGS = \
-no-undefined
liblcf_la_SOURCES = \
src/dbarray.cpp \
src/dbstring_struct.cpp \
src/encoder.cpp \
src/ini.cpp \
src/inireader.cpp \
Expand Down
2 changes: 1 addition & 1 deletion generator/csv/fields.csv
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ Database,animations,f,Array<Animation>,0x13,,1,0,rpg::Animation
Database,chipsets,f,Array<Chipset>,0x14,,1,0,rpg::Chipset
Database,terms,f,Terms,0x15,,1,0,rpg::Terms
Database,system,f,System,0x16,,1,0,rpg::System
Database,switches,f,Array<Switch>,0x17,,1,0,rpg::Switchs
Database,switches,f,Array<Switch>,0x17,,1,0,rpg::Switches
Database,variables,f,Array<Variable>,0x18,,1,0,rpg::Variables
Database,commonevents,f,Array<CommonEvent>,0x19,,1,0,rpg::CommonEvent
Database,version,f,DatabaseVersion,0x1A,0,0,0,Indicates version of database. When 1 the database was converted to RPG Maker 2000 v1.61
Expand Down
1 change: 1 addition & 0 deletions generator/csv/fields_easyrpg.csv
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ SaveEasyRpgText,font_size,f,Int32,0x05,12,0,0,Font size
SaveEasyRpgText,letter_spacing,f,Int32,0x06,0,0,0,Additional spacing between letters
SaveEasyRpgText,line_spacing,f,Int32,0x07,4,0,0,Additional spacing between lines
SaveEasyRpgText,flags,f,SaveEasyRpgText_Flags,0x08,3,0,0,Various text settings
SaveSystem,maniac_strings,f,Vector<DBString>,0x24,,0,0,rpg::Strings
SaveSystem,maniac_frameskip,,Int32,0x88,0,0,0,"FatalMix Frameskip (0=None, 1=1/5, 2=1/3, 3=1/2)"
SaveSystem,maniac_picture_limit,,Int32,0x89,0,0,0,FatalMix Picture Limit
SaveSystem,maniac_options,,Vector<UInt8>,0x8A,,0,0,"Various FatalMix options (XX XA XB XC). A: MsgSkip OFF/RShift (0/4) B: TestPlay Keep/ON/OFF (0/2/4), C: Pause focus lost Wait/Run (0/1)"
Expand Down
211 changes: 211 additions & 0 deletions src/dbstring_struct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*
* This file is part of liblcf. Copyright (c) 2021 liblcf authors.
* https://github.com/EasyRPG/liblcf - https://easyrpg.org
*
* liblcf is Free/Libre Open Source Software, released under the MIT License.
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code.
*/

#include "lcf/dbstring.h"
#include "reader_struct.h"
#include <iostream>

namespace lcf {

/*
DBString has the structure of a Pascal String (Length + Data).
It could be a primitive type but vector<DBString> needs special handling.
Vector<DBString> is Maniac Patch and is sparse:
When size is > 0xFFFFFFFF there is a gap of "0x800000000 - size"
In other cases it is as above: Size Data ... Size Data
*/

template <>
struct RawStruct<DBString> {
static void ReadLcf(DBString& ref, LcfReader& stream, uint32_t length);
static void WriteLcf(const DBString& ref, LcfWriter& stream);
static int LcfSize(const DBString& ref, LcfWriter& stream);
static void WriteXml(const DBString& ref, XmlWriter& stream);
static void BeginXml(DBString& ref, XmlReader& stream);
};

template <>
struct RawStruct<std::vector<DBString> > {
static void ReadLcf(std::vector<DBString>& ref, LcfReader& stream, uint32_t length);
static void WriteLcf(const std::vector<DBString>& ref, LcfWriter& stream);
static int LcfSize(const std::vector<DBString>& ref, LcfWriter& stream);
static void WriteXml(const std::vector<DBString>& ref, XmlWriter& stream);
static void BeginXml(std::vector<DBString>& ref, XmlReader& stream);
};

void RawStruct<DBString>::ReadLcf(DBString& ref, LcfReader& stream, uint32_t length) {
stream.ReadString(ref, length);
#ifdef LCF_DEBUG_TRACE
printf(" %s\n", ref.c_str());
#endif
}

void RawStruct<DBString>::WriteLcf(const DBString& ref, LcfWriter& stream) {
stream.Write(ref);
}

int RawStruct<DBString>::LcfSize(const DBString& ref, LcfWriter& stream) {
return stream.Decode(ref).size();
}

void RawStruct<DBString>::WriteXml(const DBString& ref, XmlWriter& stream) {
stream.Write(ref);
}

class DbStringXmlHandler : public XmlHandler {
private:
DBString& ref;
public:
DbStringXmlHandler(DBString& ref) :
ref(ref) {}
void StartElement(XmlReader& stream, const char* name, const char** /* atts */) {
// no-op
}
void EndElement(XmlReader& /* stream */, const char* /* name */) {
// no-op
}
void CharacterData(XmlReader& /* stream */, const std::string& data) {
ref = DBString(data);
}
};

void RawStruct<DBString>::BeginXml(DBString& /* ref */, XmlReader& /* stream */) {
// no-op
}

void RawStruct<std::vector<DBString>>::ReadLcf(std::vector<DBString>& ref, LcfReader& stream, uint32_t length) {
int index = 0;
DBString string_var;

uint32_t startpos = stream.Tell();
uint32_t endpos = startpos + length;
while (stream.Tell() < endpos) {
// If size is bigger than 4 bytes, size indicates the gap size
// Otherwise it indicates the size of the next string
auto size = stream.ReadUInt64();
if (size > std::numeric_limits<uint32_t>::max()) {
index += static_cast<uint32_t>(0x800000000 - size);

ref.resize(index);
} else {
stream.ReadString(string_var, size);
#ifdef LCF_DEBUG_TRACE
fprintf(stderr, "t[%d]: %s\n", index + 1, string_var.c_str());
#endif
ref.push_back(string_var);

++index;
}
}

if (stream.Tell() != endpos) {
#ifdef LCF_DEBUG_TRACE
fprintf(stderr, "Misaligned!\n");
#endif
stream.Seek(endpos);
}
}

void RawStruct<std::vector<DBString>>::WriteLcf(const std::vector<DBString>& ref, LcfWriter& stream) {
int gap_size = 0;

for (size_t i = 0; i < ref.size(); ++i) {
const auto& e = ref[i];
if (e.empty()) {
++gap_size;
continue;
}

if (gap_size > 0) {
stream.WriteUInt64(0x800000000 - static_cast<uint64_t>(gap_size));
gap_size = 0;
}

auto len = RawStruct<DBString>::LcfSize(e, stream);
stream.WriteInt(len);
RawStruct<DBString>::WriteLcf(e, stream);
}
}

int RawStruct<std::vector<DBString>>::LcfSize(const std::vector<DBString>& ref, LcfWriter& stream) {
int result = 0;
int gap_size = 0;

for (size_t i = 0; i < ref.size(); ++i) {
const auto& e = ref[i];
if (e.empty()) {
++gap_size;
continue;
}

if (gap_size > 0) {
result += LcfReader::UInt64Size(0x800000000 - static_cast<uint64_t>(gap_size));
gap_size = 0;
}

int size = RawStruct<DBString>::LcfSize(e, stream);
result += LcfReader::IntSize(size);
result += size;
}

return result;
}

void RawStruct<std::vector<DBString>>::WriteXml(const std::vector<DBString>& ref, XmlWriter& stream) {
for (size_t i = 0; i < ref.size(); ++i) {
const auto& e = ref[i];
if (e.empty()) {
continue;
}

stream.BeginElement("item", i + 1);
RawStruct<DBString>::WriteXml(e, stream);
stream.EndElement("item");
}
}

class DbStringVectorXmlHandler : public XmlHandler {
public:
DbStringVectorXmlHandler(std::vector<DBString>& ref) : ref(ref) {}

void StartElement(XmlReader& stream, const char* name, const char** atts) {
if (strcmp(name, "item") != 0) {
stream.Error("Expecting %s but got %s", "item", name);
return;
}

int last_id = -1;
int id = -1;
for (int i = 0; atts[i] != NULL && atts[i + 1] != NULL; i += 2) {
if (strcmp(atts[i], "id") == 0) {
id = atoi(atts[i + 1]);
break;
}
}

if (id <= last_id || id < -1) {
stream.Error("Bad Id %d / %d", id, last_id);
return;
}

ref.resize(id);
DBString& obj = ref.back();

stream.SetHandler(new DbStringXmlHandler(obj));
}
private:
std::vector<DBString>& ref;
};

void RawStruct<std::vector<DBString>>::BeginXml(std::vector<DBString>& obj, XmlReader& stream) {
stream.SetHandler(new DbStringVectorXmlHandler(obj));
}

} //namspace lcf
2 changes: 1 addition & 1 deletion src/generated/lcf/ldb/chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,7 @@ namespace LDB_Reader {
terms = 0x15,
/** rpg::System */
system = 0x16,
/** rpg::Switchs */
/** rpg::Switches */
switches = 0x17,
/** rpg::Variables */
variables = 0x18,
Expand Down
2 changes: 2 additions & 0 deletions src/generated/lcf/lsd/chunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ namespace LSD_Reader {
save_slot = 0x84,
/** ATB mode of RPG 2003 battle system. */
atb_mode = 0x8C,
/** rpg::Strings */
maniac_strings = 0x24,
/** FatalMix Frameskip (0=None, 1=1/5, 2=1/3, 3=1/2) */
maniac_frameskip = 0x88,
/** FatalMix Picture Limit */
Expand Down
3 changes: 3 additions & 0 deletions src/generated/lcf/rpg/savesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdint.h>
#include <string>
#include <vector>
#include "lcf/dbstring.h"
#include "lcf/enum_tags.h"
#include "lcf/rpg/music.h"
#include "lcf/rpg/sound.h"
Expand Down Expand Up @@ -116,6 +117,7 @@ namespace rpg {
int32_t save_count = 0;
int32_t save_slot = 1;
int32_t atb_mode = 0;
std::vector<DBString> maniac_strings;
int32_t maniac_frameskip = 0;
int32_t maniac_picture_limit = 0;
std::vector<uint8_t> maniac_options;
Expand Down Expand Up @@ -186,6 +188,7 @@ namespace rpg {
&& l.save_count == r.save_count
&& l.save_slot == r.save_slot
&& l.atb_mode == r.atb_mode
&& l.maniac_strings == r.maniac_strings
&& l.maniac_frameskip == r.maniac_frameskip
&& l.maniac_picture_limit == r.maniac_picture_limit
&& l.maniac_options == r.maniac_options
Expand Down
8 changes: 8 additions & 0 deletions src/generated/lsd_savesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,13 @@ static TypedField<rpg::SaveSystem, int32_t> static_atb_mode(
0,
1
);
static TypedField<rpg::SaveSystem, std::vector<DBString>> static_maniac_strings(
&rpg::SaveSystem::maniac_strings,
LSD_Reader::ChunkSaveSystem::maniac_strings,
"maniac_strings",
0,
0
);
static TypedField<rpg::SaveSystem, int32_t> static_maniac_frameskip(
&rpg::SaveSystem::maniac_frameskip,
LSD_Reader::ChunkSaveSystem::maniac_frameskip,
Expand Down Expand Up @@ -506,6 +513,7 @@ Field<rpg::SaveSystem> const* Struct<rpg::SaveSystem>::fields[] = {
&static_save_count,
&static_save_slot,
&static_atb_mode,
&static_maniac_strings,
&static_maniac_frameskip,
&static_maniac_picture_limit,
&static_maniac_options,
Expand Down
5 changes: 5 additions & 0 deletions src/generated/rpg_savesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ std::ostream& operator<<(std::ostream& os, const SaveSystem& obj) {
os << ", save_count="<< obj.save_count;
os << ", save_slot="<< obj.save_slot;
os << ", atb_mode="<< obj.atb_mode;
os << ", maniac_strings=";
for (size_t i = 0; i < obj.maniac_strings.size(); ++i) {
os << (i == 0 ? "[" : ", ") << obj.maniac_strings[i];
}
os << "]";
os << ", maniac_frameskip="<< obj.maniac_frameskip;
os << ", maniac_picture_limit="<< obj.maniac_picture_limit;
os << ", maniac_options=";
Expand Down
15 changes: 15 additions & 0 deletions src/lcf/reader_lcf.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ class LcfReader {
*/
int ReadInt();

/**
* Reads a compressed 64bit unsigned integer from the stream.
*
* @return The decompressed integer.
*/
uint64_t ReadUInt64();

/**
* Reads a string.
*
Expand Down Expand Up @@ -204,6 +211,14 @@ class LcfReader {
*/
static int IntSize(unsigned int x);

/**
* Calculates the size of a compressed 64bit unsigned integer
*
* @param x the integer.
* @return the compressed size.
*/
static int UInt64Size(uint64_t x);

/** @return a buffer which can be reused for parsing */
std::vector<int32_t>& IntBuffer();

Expand Down
7 changes: 7 additions & 0 deletions src/lcf/writer_lcf.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ class LcfWriter {
*/
void WriteInt(int val);

/**
* Write a compressed 64bit unsigned integer to the stream.
*
* @return The integer.
*/
void WriteUInt64(uint64_t val);

/**
* Write a vector of primitive values to the stream.
*
Expand Down
Loading

0 comments on commit d1fc1b4

Please sign in to comment.