From cb3a69f1114e90c1a154d5563cb994f93647610f Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 26 Aug 2020 20:28:14 -0400 Subject: [PATCH 1/4] Add DBBitArray --- CMakeLists.txt | 1 + Makefile.am | 1 + src/lcf/dbbitarray.h | 247 +++++++++++++++++++++++++++++++++++++++++++ tests/dbbitarray.cpp | 190 +++++++++++++++++++++++++++++++++ 4 files changed, 439 insertions(+) create mode 100644 src/lcf/dbbitarray.h create mode 100644 tests/dbbitarray.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f9c329a34..0bfccb024 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,7 @@ set(LCF_HEADERS src/lcf/data.h src/lcf/dbarray.h src/lcf/dbarrayalloc.h + src/lcf/dbbitarray.h src/lcf/dbstring.h src/lcf/encoder.h src/lcf/enum_tags.h diff --git a/Makefile.am b/Makefile.am index b310a0c7b..80e20859d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -204,6 +204,7 @@ lcfinclude_HEADERS = \ src/lcf/data.h \ src/lcf/dbarray.h \ src/lcf/dbarrayalloc.h \ + src/lcf/dbbitarray.h \ src/lcf/dbstring.h \ src/lcf/encoder.h \ src/lcf/enum_tags.h \ diff --git a/src/lcf/dbbitarray.h b/src/lcf/dbbitarray.h new file mode 100644 index 000000000..4f2607dce --- /dev/null +++ b/src/lcf/dbbitarray.h @@ -0,0 +1,247 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 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. + */ + +#ifndef LCF_DBBITARRAY_H +#define LCF_DBBITARRAY_H +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lcf/dbarray.h" + +namespace lcf { + +class DBBitProxy { + public: + using size_type = DBArrayAlloc::size_type; + + constexpr DBBitProxy() = default; + + DBBitProxy& operator=(const DBBitProxy& x) noexcept = default; + DBBitProxy& operator=(bool x) noexcept { + auto& byte = _base[_idx / CHAR_BIT]; + auto bit = _idx % CHAR_BIT; + byte ^= (-size_type(x) ^ byte) & (size_type(1) << bit); + return *this; + } + + operator bool() const noexcept { + auto byte = _base[_idx / CHAR_BIT]; + auto bit = _idx % CHAR_BIT; + return byte & (1 << bit); + } + + void flip() { + auto& byte = _base[_idx / CHAR_BIT]; + auto bit = _idx % CHAR_BIT; + byte ^= (1 << bit); + } + + size_type index() const { + return _idx; + } + + private: + uint8_t* _base = nullptr; + size_type _idx = 0; + + constexpr DBBitProxy(void* base, size_type idx) : _base(static_cast(base)), _idx(idx) {} + + template + friend class DBBitProxyIterator; + friend class DBBitArray; +}; + +template +class DBBitProxyIterator { + public: + using size_type = typename DBBitProxy::size_type; + using ssize_type = typename std::make_signed::type; + + using difference_type = ssize_type; + using value_type = ProxyType; + using pointer = ProxyType*; + using reference = ProxyType&; + using iterator_category = std::bidirectional_iterator_tag; + + constexpr DBBitProxyIterator() = default; + + operator DBBitProxyIterator() const { + return DBBitProxyIterator(_proxy._base, _proxy._idx); + } + + ProxyType& operator*() const { return _proxy; } + ProxyType* operator->() const { return &_proxy; } + + DBBitProxyIterator& operator++() { ++_proxy._idx; return *this; } + DBBitProxyIterator operator++(int) { auto iter = *this; ++(*this); return iter; } + + DBBitProxyIterator& operator--() { --_proxy._idx; return *this; } + DBBitProxyIterator operator--(int) { auto iter = *this; --(*this); return iter; } + + void swap(DBBitProxyIterator& o) { + std::swap(_proxy._base, o._base); + std::swap(_proxy._idx, o._idx); + } + + friend bool operator==(DBBitProxyIterator l, DBBitProxyIterator r) { return l->index() == r->index(); } + friend bool operator!=(DBBitProxyIterator l, DBBitProxyIterator r) { return !(l == r); } + + private: + mutable DBBitProxy _proxy; + + constexpr DBBitProxyIterator(void* base, size_type idx) : _proxy(base, idx) {} + + friend class DBBitArray; +}; + + +// An array data structure optimized for database storage. +// Low memory footprint and not dynamically resizable. +class DBBitArray { + public: + using value_type = bool; + using size_type = DBArrayAlloc::size_type; + + using iterator = DBBitProxyIterator; + using const_iterator = DBBitProxyIterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + constexpr DBBitArray() = default; + explicit DBBitArray(size_type count, bool value = false) : _storage(this->alloc(count)) { + std::memset(_storage, value ? 0xff : 0x00, bytes_up_from_bits(count)); + } + + template ::iterator_category>::value, int>::type = 0 + > + DBBitArray(Iter first, Iter last) : _storage(this->alloc(std::distance(first, last))) { + std::copy(first, last, begin()); + } + + DBBitArray(std::initializer_list ilist) + : DBBitArray(ilist.begin(), ilist.end()) {} + + DBBitArray(const DBBitArray& o) : _storage(this->alloc(o.size())) { + std::memcpy(_storage, o._storage, bytes_up_from_bits(o.size())); + } + DBBitArray(DBBitArray&& o) noexcept { swap(o); } + + DBBitArray& operator=(const DBBitArray& o); + DBBitArray& operator=(DBBitArray&& o) noexcept; + + void swap(DBBitArray& o) noexcept { + std::swap(_storage, o._storage); + } + + ~DBBitArray() { destroy(); } + + DBBitProxy operator[](size_type i) { return DBBitProxy(_storage, i); } + bool operator[](size_type i) const { return DBBitProxy(_storage, i); } + + DBBitProxy front() { return (*this)[0]; } + bool front() const { return (*this)[0]; } + + DBBitProxy back() { return (*this)[size()-1]; } + bool back() const { return (*this)[size()-1]; } + + iterator begin() { return iterator(_storage, 0); } + iterator end() { return iterator(_storage, size()); } + + const_iterator begin() const { return const_iterator(_storage, 0); } + const_iterator end() const { return const_iterator(_storage, size()); } + + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + const_reverse_iterator crbegin() const { return rbegin(); } + const_reverse_iterator crend() const { return rend(); } + + bool empty() const { return size() == 0; } + size_type size() const { return *DBArrayAlloc::get_size_ptr(_storage); } + + void set_all() { std::memset(_storage, 0xff, bytes_up_from_bits(size())); } + void reset_all() { std::memset(_storage, 0, bytes_up_from_bits(size())); } + void flip_all() { + auto* p = static_cast(_storage); + for (size_t i = 0; i < bytes_up_from_bits(size()); ++i) { + p[i] ^= p[i]; + } + } + + void set(size_type i) { (*this)[i] = true; } + void reset(size_type i) { (*this)[i] = false; } + void flip(size_type i) { (*this)[i].flip(); } + + private: + static constexpr size_type bytes_up_from_bits(size_type bits) { + return (bits / CHAR_BIT) + (bits % CHAR_BIT != 0); + } + + void* alloc(size_type bits) { + auto bytes = bytes_up_from_bits(bits); + return DBArrayAlloc::alloc(bytes, bits, alignof(size_type)); + } + + void free(void* p) { + DBArrayAlloc::free(p, alignof(size_type)); + } + + void destroy() noexcept; + private: + void* _storage = DBArrayAlloc::empty_buf(); +}; + +inline bool operator==(const DBBitArray& l, const DBBitArray& r) { return std::equal(l.begin(), l.end(), r.begin(), r.end()); } +inline bool operator!=(const DBBitArray& l, const DBBitArray& r) { return !(l == r); } +inline bool operator<(const DBBitArray& l, const DBBitArray& r) { return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); } +inline bool operator>(const DBBitArray& l, const DBBitArray& r) { return r < l; } +inline bool operator<=(const DBBitArray& l, const DBBitArray& r) { return !(l > r); } +inline bool operator>=(const DBBitArray& l, const DBBitArray& r) { return !(l < r); } + +inline DBBitArray& DBBitArray::operator=(const DBBitArray& o) { + if (this != &o) { + destroy(); + _storage = this->alloc(o.size()); + std::memcpy(_storage, o._storage, bytes_up_from_bits(o.size())); + } + return *this; +} + +inline DBBitArray& DBBitArray::operator=(DBBitArray&& o) noexcept { + if (this != &o) { + destroy(); + swap(o); + } + return *this; +} + +inline void DBBitArray::destroy() noexcept { + if (_storage != DBArrayAlloc::empty_buf()) { + free(_storage); + _storage = DBArrayAlloc::empty_buf(); + } +} + +} // namespace lcf + +#endif diff --git a/tests/dbbitarray.cpp b/tests/dbbitarray.cpp new file mode 100644 index 000000000..6c10b4480 --- /dev/null +++ b/tests/dbbitarray.cpp @@ -0,0 +1,190 @@ +/* + * This file is part of liblcf. Copyright (c) 2020 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/dbbitarray.h" +#include "doctest.h" + +#include +#include +#include + +namespace lcf { + +doctest::String toString(const DBBitArray& a) { + std::ostringstream ss; + ss << "{"; + for (auto& b: a) { + ss << (b ? 1 : 0); + } + ss << "}"; + return doctest::String(ss.str().c_str()); +} + +} + +using namespace lcf; + +TEST_SUITE_BEGIN("DBBitArray"); + +TEST_CASE("ConstructDef") { + DBBitArray x; + + REQUIRE(x.empty()); + REQUIRE_EQ(x.size(), 0); +} + +TEST_CASE("ConstructAll") { + bool value; + SUBCASE("TRUE") { value = true; } + SUBCASE("FALSE") { value = false; } + + CAPTURE(value); + + DBBitArray x(15, value); + const auto& cx = x; + + REQUIRE(!x.empty()); + REQUIRE_EQ(x.size(), 15); + + for (auto& e: x) { REQUIRE_EQ(e, value); } + for (auto& e: cx) { REQUIRE_EQ(e, value); } + + for (DBBitArray::size_type i = 0; i < x.size(); ++i) { + CAPTURE(i); + + REQUIRE_EQ(cx[i], value); + REQUIRE_EQ(x[i], value); + } + + REQUIRE_EQ(x.front(), value); + REQUIRE_EQ(x.back(), value); +} + +TEST_CASE_TEMPLATE("Construct Ilist", T, DBBitArray, const DBBitArray) { + T x = {true, false, true}; + + REQUIRE(!x.empty()); + REQUIRE_EQ(x.size(), 3); + REQUIRE_EQ(x.front(), true); + REQUIRE_EQ(x[0], true); + REQUIRE_EQ(x[1], false); + REQUIRE_EQ(x[2], true); + REQUIRE_EQ(x.back(), true); + + auto iter = x.begin(); + REQUIRE_EQ(*iter, true); + ++iter; + REQUIRE_EQ(*iter, false); + ++iter; + REQUIRE_EQ(*iter, true); + ++iter; + REQUIRE_EQ(iter, x.end()); +} + +TEST_CASE("Assign") { + DBBitArray x = { false, false, false }; + + REQUIRE(!x.empty()); + REQUIRE_EQ(x.size(), 3); + + x[1] = true; + REQUIRE_EQ(x[0], false); + REQUIRE_EQ(x[1], true); + REQUIRE_EQ(x[2], false); +} + +TEST_CASE("Swap") { + DBBitArray a = {false}; + DBBitArray b = {true}; + a.swap(b); + + REQUIRE_EQ(a.front(), true); + REQUIRE_EQ(b.front(), false); +} + +TEST_CASE("Cmp") { + DBBitArray a = {false}; + DBBitArray b = {true}; + + REQUIRE(a == a); + REQUIRE_FALSE(a != a); + REQUIRE_FALSE(a < a); + REQUIRE(a <= a); + REQUIRE_FALSE(a > a); + REQUIRE(a >= a); + + REQUIRE_FALSE(a == b); + REQUIRE(a != b); + REQUIRE(a < b); + REQUIRE(a <= b); + REQUIRE_FALSE(a > b); + REQUIRE_FALSE(a >= b); + + REQUIRE_FALSE(b == a); + REQUIRE(b != a); + REQUIRE_FALSE(b < a); + REQUIRE_FALSE(b <= a); + REQUIRE(b > a); + REQUIRE(b >= a); +} + + +TEST_CASE("Copy") { + const DBBitArray ca = {false}; + const DBBitArray cb = {true}; + + DBBitArray a = {false}; + DBBitArray b = {true}; + + b = a; + REQUIRE_EQ(a, ca); + REQUIRE_EQ(b, ca); + + b = a; + REQUIRE_EQ(a, ca); + REQUIRE_EQ(b, ca); + + b = b; + REQUIRE_EQ(a, ca); + REQUIRE_EQ(b, ca); + + DBBitArray c(b); + REQUIRE_EQ(a, ca); + REQUIRE_EQ(b, ca); + REQUIRE_EQ(c, ca); +} + +TEST_CASE("Move") { + const DBBitArray n = {}; + const DBBitArray ca = {false}; + const DBBitArray cb = {true}; + + DBBitArray a = {false}; + DBBitArray b = {true}; + + b = std::move(a); + REQUIRE_EQ(a, n); + REQUIRE_EQ(b, ca); + + b = std::move(b); + REQUIRE_EQ(a, n); + REQUIRE_EQ(b, ca); + + DBBitArray c(std::move(b)); + REQUIRE_EQ(a, n); + REQUIRE_EQ(b, n); + REQUIRE_EQ(c, ca); + + c = std::move(b); + REQUIRE_EQ(a, n); + REQUIRE_EQ(b, n); + REQUIRE_EQ(c, n); +} + +TEST_SUITE_END(); From 3eb7d6a675b32abe1515195b6f8ea8285c532a95 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 19 Aug 2020 03:54:42 -0400 Subject: [PATCH 2/4] Add DBBitArray to generator script --- generator/generate.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/generator/generate.py b/generator/generate.py index 572bc5eb7..3c4b2c645 100755 --- a/generator/generate.py +++ b/generator/generate.py @@ -35,6 +35,7 @@ 'Int32': 'int32_t', 'String': 'std::string', 'DBString': 'DBString', + 'DBBitArray': 'DBBitArray', } # Additional Jinja 2 functions @@ -104,7 +105,7 @@ def pod_default(field): ftype = field.type # Not a POD, no default - if dfl == '' or dfl == '\'\'' or ftype.startswith('Vector') or ftype.startswith('Array') or ftype.startswith('DBArray'): + if dfl == '' or dfl == '\'\'' or ftype.startswith('Vector') or ftype.startswith('Array') or ftype.startswith('DBArray') or ftype.startswith('DBBitArray'): return "" if ftype == 'Boolean': @@ -171,6 +172,9 @@ def struct_headers(ty, header_map): if ty == 'DBString': return ['"lcf/dbstring.h"'] + if ty == 'DBBitArray': + return ['"lcf/dbbitarray.h"'] + if ty in int_types or ty == "DatabaseVersion": return [''] @@ -347,7 +351,7 @@ def needs_ctor(struct_name): for method, hdrs in setup[struct_name]) def type_is_array(ty): - return re.match(r'(Vector|Array|DBArray)<(.*)>', ty) + return re.match(r'(Vector|Array|DBArray)<(.*)>', ty) or ty == "DBBitArray" def is_monotonic_from_0(enum): expected = 0 From c64fd78da7a903e8974f98d6d78a1087ee82f046 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 19 Aug 2020 03:52:03 -0400 Subject: [PATCH 3/4] Add support for DBBitArray to reader struct + parsers --- src/lcf/reader_lcf.h | 9 +++++++++ src/lcf/writer_lcf.h | 8 ++++++++ src/reader_lcf.cpp | 11 +++++++++++ src/reader_struct.h | 32 ++++++++++++++++++++++++++++++++ src/reader_xml.cpp | 8 ++++++++ src/writer_lcf.cpp | 6 ++++++ src/writer_xml.cpp | 6 ++++++ 7 files changed, 80 insertions(+) diff --git a/src/lcf/reader_lcf.h b/src/lcf/reader_lcf.h index 89578fa36..cb47b1440 100644 --- a/src/lcf/reader_lcf.h +++ b/src/lcf/reader_lcf.h @@ -12,6 +12,7 @@ #include "lcf/config.h" #include "lcf/dbstring.h" +#include "lcf/dbbitarray.h" #include #include @@ -125,6 +126,14 @@ class LcfReader { template void Read(std::vector &buffer, size_t size); + /** + * Reads a DBBitsArray of primitive type. + * + * @param buffer DBBitArray to fill. + * @param size how many bytes to read as bits. + */ + void ReadBits(DBBitArray &buffer, size_t size); + /** * Reads a compressed integer from the stream. * diff --git a/src/lcf/writer_lcf.h b/src/lcf/writer_lcf.h index 96a8f9d41..85a2aa15f 100644 --- a/src/lcf/writer_lcf.h +++ b/src/lcf/writer_lcf.h @@ -11,6 +11,7 @@ #define LCF_WRITER_LCF_H #include "lcf/config.h" +#include "lcf/dbbitarray.h" #include "lcf/dbstring.h" #include @@ -70,6 +71,13 @@ class LcfWriter { void Write(const std::string& str); void Write(const DBString& str); + /** + * Writes a bit array to bytes in the stream. + * + * @param bits the bit array. + */ + void Write(const DBBitArray& bits); + /** * Writes a compressed integer to the stream. * diff --git a/src/reader_lcf.cpp b/src/reader_lcf.cpp index 8d4a564bd..e33974ba4 100644 --- a/src/reader_lcf.cpp +++ b/src/reader_lcf.cpp @@ -184,6 +184,15 @@ void LcfReader::Read(std::vector &buffer, size_t size) { } } +void LcfReader::ReadBits(DBBitArray &buffer, size_t size) { + buffer = DBBitArray(size); + for (size_t i = 0; i < size; ++i) { + uint8_t val; + Read(&val, sizeof(val), 1); + buffer[i] = static_cast(val); + } +} + void LcfReader::ReadString(std::string& ref, size_t size) { ref.resize(size); Read((size > 0 ? &ref.front(): nullptr), 1, size); @@ -196,6 +205,8 @@ void LcfReader::ReadString(DBString& ref, size_t size) { ref = DBString(tmp); } + + bool LcfReader::IsOk() const { return stream.good() && encoder.IsOk(); } diff --git a/src/reader_struct.h b/src/reader_struct.h index a71bcf901..e82a79326 100644 --- a/src/reader_struct.h +++ b/src/reader_struct.h @@ -83,6 +83,7 @@ template <> struct TypeCategory { static const Category::Index value template <> struct TypeCategory { static const Category::Index value = Category::Primitive; }; template <> struct TypeCategory { static const Category::Index value = Category::Primitive; }; template <> struct TypeCategory { static const Category::Index value = Category::Primitive; }; +template <> struct TypeCategory { static const Category::Index value = Category::Primitive; }; template struct TypeCategory> { @@ -337,6 +338,37 @@ struct Primitive { } }; +/** + * DBBitArray specialization. + */ +template <> +struct Primitive { + static void ReadLcf(DBBitArray& ref, LcfReader& stream, uint32_t length) { + stream.ReadBits(ref, length); +#ifdef LCF_DEBUG_TRACE + printf(" "); + for (auto& b: ref) { + print("%d", static_cast(b)); + } + printf("\n"); +#endif + } + static void WriteLcf(const DBBitArray& ref, LcfWriter& stream) { + stream.Write(ref); + } + static int LcfSize(const DBBitArray& ref, LcfWriter& stream) { + return ref.size(); + } + static void WriteXml(const DBBitArray& ref, XmlWriter& stream) { + stream.Write(ref); + } + static void ParseXml(DBBitArray& ref, const std::string& data) { + XmlReader::Read(ref, data); + } +}; + + + /** * Primitive Reader. */ diff --git a/src/reader_xml.cpp b/src/reader_xml.cpp index cd63c33e8..4e1e75579 100644 --- a/src/reader_xml.cpp +++ b/src/reader_xml.cpp @@ -188,6 +188,14 @@ void XmlReader::Read(DBString& val, const std::string& data) { val = DBString(sval); } +template <> +void XmlReader::Read(DBBitArray& val, const std::string& data) { + // FIXME: Adds copies + std::vector tmp; + ReadVector(tmp, data); + val = DBBitArray(tmp.begin(), tmp.end()); +} + template void XmlReader::ReadVector(std::vector& val, const std::string& data) { val.clear(); diff --git a/src/writer_lcf.cpp b/src/writer_lcf.cpp index 8ba4b3d7f..8164c772f 100644 --- a/src/writer_lcf.cpp +++ b/src/writer_lcf.cpp @@ -127,6 +127,12 @@ void LcfWriter::Write(const DBString& _str) { } } +void LcfWriter::Write(const DBBitArray& bits) { + for (auto& b: bits) { + Write(static_cast(b)); + } +} + uint32_t LcfWriter::Tell() { return (uint32_t)stream.tellp(); } diff --git a/src/writer_xml.cpp b/src/writer_xml.cpp index 72e034375..18f2c4647 100644 --- a/src/writer_xml.cpp +++ b/src/writer_xml.cpp @@ -13,6 +13,7 @@ #include "lcf/writer_xml.h" #include "lcf/dbstring.h" #include "lcf/dbarray.h" +#include "lcf/dbbitarray.h" namespace lcf { @@ -176,6 +177,11 @@ void XmlWriter::WriteInt(int val) { Write(val); } +template <> +void XmlWriter::Write(const DBBitArray& val) { + WriteVector(val); +} + template void XmlWriter::WriteVector(const ArrayType& val) { Indent(); From 973eb37b907a3aae4e94a14cc308968b5abb02d6 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 19 Aug 2020 04:02:00 -0400 Subject: [PATCH 4/4] Use DBBitArray --- generator/csv/fields.csv | 28 ++++++++++++++-------------- src/generated/lcf/rpg/item.h | 9 +++++---- src/generated/lcf/rpg/skill.h | 5 +++-- src/generated/lcf/rpg/troop.h | 3 ++- src/generated/ldb_item.cpp | 16 ++++++++-------- src/generated/ldb_skill.cpp | 8 ++++---- src/generated/ldb_troop.cpp | 4 ++-- 7 files changed, 38 insertions(+), 35 deletions(-) diff --git a/generator/csv/fields.csv b/generator/csv/fields.csv index 52fc2f068..030511278 100644 --- a/generator/csv/fields.csv +++ b/generator/csv/fields.csv @@ -158,10 +158,10 @@ Skill,affect_spirit,f,Boolean,0x23,False,0,0,Flag Skill,affect_agility,f,Boolean,0x24,False,0,0,Flag Skill,absorb_damage,f,Boolean,0x25,False,0,0,Flag Skill,ignore_defense,f,Boolean,0x26,False,0,0,Flag -Skill,state_effects,t,Vector,0x29,,0,0,Integer -Skill,state_effects,f,Vector,0x2A,,1,0,Array - Flag -Skill,attribute_effects,t,Vector,0x2B,,0,0,Integer -Skill,attribute_effects,f,Vector,0x2C,,1,0,Array - Flag +Skill,state_effects,t,DBBitArray,0x29,,0,0,Integer +Skill,state_effects,f,DBBitArray,0x2A,,1,0,Array - Flag +Skill,attribute_effects,t,DBBitArray,0x2B,,0,0,Integer +Skill,attribute_effects,f,DBBitArray,0x2C,,1,0,Array - Flag Skill,affect_attr_defence,f,Boolean,0x2D,False,0,0,Flag Skill,battler_animation,f,Ref,0x31,-1,0,1,Integer - RPG2003 Skill,battler_animation_data,f,Array>,0x32,,1,1,? - RPG2003 @@ -215,19 +215,19 @@ Item,skill_id,f,Ref,0x35,1,0,0,Integer Item,switch_id,f,Ref,0x37,1,0,0,Integer Item,occasion_field2,f,Boolean,0x39,True,0,0,Flag Item,occasion_battle,f,Boolean,0x3A,False,0,0,Flag -Item,actor_set,t,Vector,0x3D,,0,0,Integer -Item,actor_set,f,Vector,0x3E,,1,0,Array - Flag -Item,state_set,t,Vector,0x3F,,0,0,Integer -Item,state_set,f,Vector,0x40,,1,0,Array - Flag -Item,attribute_set,t,Vector,0x41,,0,0,Integer -Item,attribute_set,f,Vector,0x42,,1,0,Array - Flag +Item,actor_set,t,DBBitArray,0x3D,,0,0,Integer +Item,actor_set,f,DBBitArray,0x3E,,1,0,Array - Flag +Item,state_set,t,DBBitArray,0x3F,,0,0,Integer +Item,state_set,f,DBBitArray,0x40,,1,0,Array - Flag +Item,attribute_set,t,DBBitArray,0x41,,0,0,Integer +Item,attribute_set,f,DBBitArray,0x42,,1,0,Array - Flag Item,state_chance,f,Int32,0x43,0,0,0,Integer Item,reverse_state_effect,f,Boolean,0x44,False,0,0,Flag Item,weapon_animation,f,Ref,0x45,-1,0,1,Integer - RPG2003 Item,animation_data,f,Array>,0x46,,1,1,Array - RPG2003 Item,use_skill,f,Boolean,0x47,False,0,1,Flag - RPG2003 -Item,class_set,t,Vector,0x48,,0,1,Integer - RPG2003 -Item,class_set,f,Vector,0x49,,1,1,Array - Flag - RPG2003 +Item,class_set,t,DBBitArray,0x48,,0,1,Integer - RPG2003 +Item,class_set,f,DBBitArray,0x49,,1,1,Array - Flag - RPG2003 Item,ranged_trajectory,f,Enum,0x4B,0,0,0,Integer Item,ranged_target,f,Enum,0x4C,0,0,0,Integer EnemyAction,kind,f,Enum,0x01,0,1,0,Integer @@ -299,8 +299,8 @@ TroopPage,event_commands,f,Vector,0x0C,,1,0,Array - rpg::EventComm Troop,name,f,DBString,0x01,'',0,0,String Troop,members,f,Array,0x02,,1,0,Array - rpg::TroopMember Troop,auto_alignment,f,Boolean,0x03,False,0,1,Flag -Troop,terrain_set,t,Vector,0x04,,0,0,Integer -Troop,terrain_set,f,Vector,0x05,,1,0,Array - Flag +Troop,terrain_set,t,DBBitArray,0x04,,0,0,Integer +Troop,terrain_set,f,DBBitArray,0x05,,1,0,Array - Flag Troop,appear_randomly,f,Boolean,0x06,False,0,1,Flag Troop,pages,f,Array,0x0B,,1,0,Array - rpg::TroopPage Terrain,name,f,DBString,0x01,'',0,0,String diff --git a/src/generated/lcf/rpg/item.h b/src/generated/lcf/rpg/item.h index ae63948c6..764b5c4e2 100644 --- a/src/generated/lcf/rpg/item.h +++ b/src/generated/lcf/rpg/item.h @@ -15,6 +15,7 @@ // Headers #include #include +#include "lcf/dbbitarray.h" #include "lcf/dbstring.h" #include "lcf/enum_tags.h" #include "lcf/rpg/itemanimation.h" @@ -117,15 +118,15 @@ namespace rpg { int32_t switch_id = 1; bool occasion_field2 = true; bool occasion_battle = false; - std::vector actor_set; - std::vector state_set; - std::vector attribute_set; + DBBitArray actor_set; + DBBitArray state_set; + DBBitArray attribute_set; int32_t state_chance = 0; bool reverse_state_effect = false; int32_t weapon_animation = -1; std::vector animation_data; bool use_skill = false; - std::vector class_set; + DBBitArray class_set; int32_t ranged_trajectory = 0; int32_t ranged_target = 0; }; diff --git a/src/generated/lcf/rpg/skill.h b/src/generated/lcf/rpg/skill.h index db7a6a01d..57cf20fca 100644 --- a/src/generated/lcf/rpg/skill.h +++ b/src/generated/lcf/rpg/skill.h @@ -15,6 +15,7 @@ // Headers #include #include +#include "lcf/dbbitarray.h" #include "lcf/dbstring.h" #include "lcf/enum_tags.h" #include "lcf/rpg/battleranimationdata.h" @@ -96,8 +97,8 @@ namespace rpg { bool affect_agility = false; bool absorb_damage = false; bool ignore_defense = false; - std::vector state_effects; - std::vector attribute_effects; + DBBitArray state_effects; + DBBitArray attribute_effects; bool affect_attr_defence = false; int32_t battler_animation = -1; std::vector battler_animation_data; diff --git a/src/generated/lcf/rpg/troop.h b/src/generated/lcf/rpg/troop.h index 017277004..600c11d65 100644 --- a/src/generated/lcf/rpg/troop.h +++ b/src/generated/lcf/rpg/troop.h @@ -14,6 +14,7 @@ // Headers #include +#include "lcf/dbbitarray.h" #include "lcf/dbstring.h" #include "lcf/rpg/troopmember.h" #include "lcf/rpg/trooppage.h" @@ -31,7 +32,7 @@ namespace rpg { DBString name; std::vector members; bool auto_alignment = false; - std::vector terrain_set; + DBBitArray terrain_set; bool appear_randomly = false; std::vector pages; }; diff --git a/src/generated/ldb_item.cpp b/src/generated/ldb_item.cpp index 892c206b9..52f3306ce 100644 --- a/src/generated/ldb_item.cpp +++ b/src/generated/ldb_item.cpp @@ -307,39 +307,39 @@ static TypedField static_occasion_battle( 0, 0 ); -static SizeField> static_size_actor_set( +static SizeField static_size_actor_set( &rpg::Item::actor_set, LDB_Reader::ChunkItem::actor_set_size, 0, 0 ); -static TypedField> static_actor_set( +static TypedField static_actor_set( &rpg::Item::actor_set, LDB_Reader::ChunkItem::actor_set, "actor_set", 1, 0 ); -static SizeField> static_size_state_set( +static SizeField static_size_state_set( &rpg::Item::state_set, LDB_Reader::ChunkItem::state_set_size, 0, 0 ); -static TypedField> static_state_set( +static TypedField static_state_set( &rpg::Item::state_set, LDB_Reader::ChunkItem::state_set, "state_set", 1, 0 ); -static SizeField> static_size_attribute_set( +static SizeField static_size_attribute_set( &rpg::Item::attribute_set, LDB_Reader::ChunkItem::attribute_set_size, 0, 0 ); -static TypedField> static_attribute_set( +static TypedField static_attribute_set( &rpg::Item::attribute_set, LDB_Reader::ChunkItem::attribute_set, "attribute_set", @@ -381,13 +381,13 @@ static TypedField static_use_skill( 0, 1 ); -static SizeField> static_size_class_set( +static SizeField static_size_class_set( &rpg::Item::class_set, LDB_Reader::ChunkItem::class_set_size, 0, 1 ); -static TypedField> static_class_set( +static TypedField static_class_set( &rpg::Item::class_set, LDB_Reader::ChunkItem::class_set, "class_set", diff --git a/src/generated/ldb_skill.cpp b/src/generated/ldb_skill.cpp index 06b41defa..8e95db829 100644 --- a/src/generated/ldb_skill.cpp +++ b/src/generated/ldb_skill.cpp @@ -223,26 +223,26 @@ static TypedField static_ignore_defense( 0, 0 ); -static SizeField> static_size_state_effects( +static SizeField static_size_state_effects( &rpg::Skill::state_effects, LDB_Reader::ChunkSkill::state_effects_size, 0, 0 ); -static TypedField> static_state_effects( +static TypedField static_state_effects( &rpg::Skill::state_effects, LDB_Reader::ChunkSkill::state_effects, "state_effects", 1, 0 ); -static SizeField> static_size_attribute_effects( +static SizeField static_size_attribute_effects( &rpg::Skill::attribute_effects, LDB_Reader::ChunkSkill::attribute_effects_size, 0, 0 ); -static TypedField> static_attribute_effects( +static TypedField static_attribute_effects( &rpg::Skill::attribute_effects, LDB_Reader::ChunkSkill::attribute_effects, "attribute_effects", diff --git a/src/generated/ldb_troop.cpp b/src/generated/ldb_troop.cpp index 363080929..8418cfefc 100644 --- a/src/generated/ldb_troop.cpp +++ b/src/generated/ldb_troop.cpp @@ -41,13 +41,13 @@ static TypedField static_auto_alignment( 0, 1 ); -static SizeField> static_size_terrain_set( +static SizeField static_size_terrain_set( &rpg::Troop::terrain_set, LDB_Reader::ChunkTroop::terrain_set_size, 0, 0 ); -static TypedField> static_terrain_set( +static TypedField static_terrain_set( &rpg::Troop::terrain_set, LDB_Reader::ChunkTroop::terrain_set, "terrain_set",