diff --git a/.gitmodules b/.gitmodules index 4449521..90eeac9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,18 +16,12 @@ [submodule "libs/curl-android-ios"] path = libs/curl-android-ios url = https://bitbucket.org/omigamedev/curl-android-ios.git -[submodule "libs/jpeg"] - path = libs/jpeg - url = https://github.com/richgel999/jpeg-compressor.git [submodule "libs/poly2tri"] path = libs/poly2tri url = https://github.com/greenm01/poly2tri [submodule "libs/base64"] path = libs/base64 url = https://github.com/tkislan/base64 -[submodule "libs/bugtrap"] - path = libs/bugtrap - url = https://github.com/bchavez/BugTrap.git [submodule "libs/bugtrap-client"] path = libs/bugtrap-client url = https://bitbucket.org/omigamedev/bugtrap-client-x64.git @@ -51,4 +45,4 @@ url = https://github.com/stbrumme/hash-library [submodule "libs/native_app_glue"] path = libs/native_app_glue - url = https://bitbucket.org/omigamedev/native_app_glue.git + url = https://bitbucket.org/omigamedev/native_app_glue.git \ No newline at end of file diff --git a/PanoPainter.vcxproj b/PanoPainter.vcxproj index 8873223..5afadfe 100644 --- a/PanoPainter.vcxproj +++ b/PanoPainter.vcxproj @@ -181,6 +181,7 @@ NotUsing NotUsing + @@ -312,6 +313,7 @@ + diff --git a/PanoPainter.vcxproj.filters b/PanoPainter.vcxproj.filters index 33b5b47..accaeb7 100644 --- a/PanoPainter.vcxproj.filters +++ b/PanoPainter.vcxproj.filters @@ -288,6 +288,9 @@ libs\hash + + Source Files + @@ -512,6 +515,9 @@ libs\hash + + Header Files + diff --git a/src/abr.cpp b/src/abr.cpp new file mode 100644 index 0000000..a7a6970 --- /dev/null +++ b/src/abr.cpp @@ -0,0 +1,224 @@ +#include "pch.h" +#include "abr.h" + +//std::map> ABR::m_parser_table; +//{ +// { "VlLs", std::bind(&ABR::parse_vlls, this) }, +// { "TEXT", std::bind(&ABR::parse_text, this) }, +// { "Objc", std::bind(&ABR::parse_objc, this) }, +// { "UntF", std::bind(&ABR::parse_untf, this) }, +// { "bool", std::bind(&ABR::parse_bool, this) }, +// { "long", std::bind(&ABR::parse_long, this) }, +// { "doub", std::bind(&ABR::parse_doub, this) }, +// { "enum", std::bind(&ABR::parse_enum, this) }, +// //{ "Dmtr", &ABR::parse_prop }, +// //{ "Hrdn", &ABR::parse_prop }, +// //{ "Angl", &ABR::parse_prop }, +// //{ "Rndn", &ABR::parse_prop }, +// //{ "Spcn", &ABR::parse_prop }, +// //{ "Intr", &ABR::parse_prop }, +// //{ "flipX", &ABR::parse_prop }, +// //{ "flipY", &ABR::parse_prop }, +// //{ "useTipDynamics", &ABR::parse_prop }, +// //{ "useScatter", &ABR::parse_prop }, +// //{ "dualBrush", &ABR::parse_prop }, +// //{ "useDualBrush", &ABR::parse_prop }, +// //{ "brushGroup", &ABR::parse_prop }, +// //{ "useBrushGroup", &ABR::parse_prop }, +// //{ "useTexture", &ABR::parse_prop }, +// //{ "usePaintDynamics", &ABR::parse_prop }, +// //{ "useColorDynamics", &ABR::parse_prop }, +// //{ "Wtdg", &ABR::parse_prop }, +// //{ "Nose", &ABR::parse_prop }, +// //{ "Rpt ", &ABR::parse_prop }, +// //{ "useBrushSize", &ABR::parse_prop }, +// //{ "useBrushPose", &ABR::parse_prop }, +//}; + +bool ABR::section_desc() +{ + auto sz = align4(ru32()); + auto n1 = ri32(); // some integer + auto s = rwstring(); // maybe a string + auto null = rkey_or_string(); + auto null_val = ri32(); // integer following the null + auto name = rkey_or_string(); + auto list = rstring(4); + auto list_val = call(list); + return true; +} + +bool ABR::section_samp() +{ + auto sz = align4(ru32()); + skip(sz); + return true; +} + +bool ABR::section_patt() +{ + auto sz = align4(ru32()); + skip(sz); + return true; +} + +std::shared_ptr ABR::parse_vlls() +{ + auto ret = std::make_shared(); + auto count = ru32(); + printf("list: %d\n", count); + for (int i = 0; i < count; i++) + { + auto type = rstring(4); + auto item = call(type); + if (!item) + return nullptr; + ret->children.push_back(item); + } + return ret; +} + +std::shared_ptr ABR::parse_text() +{ + auto ret = std::make_shared(); + ret->value = rwstring(); + wprintf(L"text: %s\n", ret->value.c_str()); + return ret; +} + +//ABR::Type::Ref ABR::parse_prop() +//{ +// auto name = rstring(4); +// //printf("prop type %s\n", t.c_str()); +// if (!call(name)) +// return false; +//} + +std::shared_ptr ABR::parse_objc() +{ + auto ret = std::make_shared(); + ret->name = rwstring(); + ret->class_id = rkey_or_string(); + auto count = ru32(); + printf("objc type %s, %d props\n", ret->class_id.c_str(), count); + for (int i = 0; i < count; i++) + { + auto key = rkey_or_string(); + auto type = rstring(4); + //printf("prop %s\n", t.c_str()); + auto property = call(type); + if (!property) + return nullptr; + if (ret->props.find(key) != ret->props.end()) + printf("DUPLICATE prop %d\n", key.c_str()); + ret->props[key] = property; + } + return ret; +} + +std::shared_ptr ABR::parse_untf() +{ + auto ret = std::make_shared(); + ret->unit = rstring(4); + ret->value = rdbl(); + printf("float %s: %f\n", ret->unit.c_str(), ret->value); + return ret; +} + +std::shared_ptr ABR::parse_bool() +{ + auto ret = std::make_shared(); + ret->value = ru8(); + printf("bool: %s\n", ret->value ? "true" : "false"); + return ret; +} + +std::shared_ptr ABR::parse_long() +{ + auto ret = std::make_shared(); + ret->value = ru32(); + printf("long: %d\n", ret->value); + return ret; +} + +std::shared_ptr ABR::parse_doub() +{ + auto ret = std::make_shared(); + ret->value = rdbl(); + printf("double: %d\n", ret->value); + return ret; +} + +std::shared_ptr ABR::parse_enum() +{ + auto ret = std::make_shared(); + auto t = rkey_or_string(); + auto e = rkey_or_string(); + printf("enum: %s %s\n", t.c_str(), e.c_str()); + return ret; +} + +ABR::ABR() +{ + m_parser_table = std::map> + { + { "VlLs", std::bind(&ABR::parse_vlls, this) }, + { "TEXT", std::bind(&ABR::parse_text, this) }, + { "Objc", std::bind(&ABR::parse_objc, this) }, + { "UntF", std::bind(&ABR::parse_untf, this) }, + { "bool", std::bind(&ABR::parse_bool, this) }, + { "long", std::bind(&ABR::parse_long, this) }, + { "doub", std::bind(&ABR::parse_doub, this) }, + { "enum", std::bind(&ABR::parse_enum, this) }, + //{ "Dmtr", &ABR::parse_prop }, + //{ "Hrdn", &ABR::parse_prop }, + //{ "Angl", &ABR::parse_prop }, + //{ "Rndn", &ABR::parse_prop }, + //{ "Spcn", &ABR::parse_prop }, + //{ "Intr", &ABR::parse_prop }, + //{ "flipX", &ABR::parse_prop }, + //{ "flipY", &ABR::parse_prop }, + //{ "useTipDynamics", &ABR::parse_prop }, + //{ "useScatter", &ABR::parse_prop }, + //{ "dualBrush", &ABR::parse_prop }, + //{ "useDualBrush", &ABR::parse_prop }, + //{ "brushGroup", &ABR::parse_prop }, + //{ "useBrushGroup", &ABR::parse_prop }, + //{ "useTexture", &ABR::parse_prop }, + //{ "usePaintDynamics", &ABR::parse_prop }, + //{ "useColorDynamics", &ABR::parse_prop }, + //{ "Wtdg", &ABR::parse_prop }, + //{ "Nose", &ABR::parse_prop }, + //{ "Rpt ", &ABR::parse_prop }, + //{ "useBrushSize", &ABR::parse_prop }, + //{ "useBrushPose", &ABR::parse_prop }, + }; +} + +bool ABR::open(const std::string& path) +{ + m_parser_table[""] = std::bind(&ABR::parse_bool, this); + Asset asset; + if (asset.open(path.c_str())) + { + init(asset.read_all(), asset.m_len, BinaryStream::ByteOrder::BigEndian); + auto version_major = ru16(); + auto version_minor = ru16(); + while (!eof()) + { + if (rstring(4) != "8BIM") + return false; + auto t = rstring(4); + if (t == "desc") + { + section_desc(); + } + else + { + printf("skip section %s\n", t.c_str()); + skip(align4(ru32())); + } + } + } + return false; +} diff --git a/src/abr.h b/src/abr.h new file mode 100644 index 0000000..3f44f4c --- /dev/null +++ b/src/abr.h @@ -0,0 +1,229 @@ +#pragma once +#include "asset.h" +#include + +class BinaryStream +{ +public: + enum class ByteOrder : uint8_t { BigEndian, LittleEndian, Host }; + static ByteOrder sys_order() + { + union { + uint32_t i; + char c[4]; + } bint { 0x01020304 }; + + return bint.c[0] == 1 ? ByteOrder::BigEndian : ByteOrder::LittleEndian; + } + BinaryStream(const BinaryParam&) = delete; + BinaryStream() = default; + ~BinaryStream() + { + if (m_ptr) + delete m_ptr; + m_ptr = m_cur = nullptr; + m_size = 0; + } + void init(uint8_t* owned_data_ptr, size_t size, ByteOrder byte_order = ByteOrder::Host) + { + m_ptr = m_cur = owned_data_ptr; + m_size = size; + m_byte_order = byte_order; + m_swap = byte_order == ByteOrder::Host ? false : byte_order != sys_order(); + } + inline void skip(size_t bytes) { m_cur += bytes; } + inline bool eof() { return std::distance(m_ptr, m_cur) >= m_size; } + inline bool has_data(size_t sz) { return std::distance(m_ptr, m_cur + sz) < m_size; } + uint8_t ru8() { return read(); } + uint16_t ru16() { return m_swap ? swap(read()) : read(); } + uint32_t ru32() { return m_swap ? swap(read()) : read(); } + uint64_t ru64() { return m_swap ? swap(read()) : read(); } + int8_t ri8() { return read(); } + int16_t ri16() { return m_swap ? swap(read()) : read(); } + int32_t ri32() { return m_swap ? swap(read()) : read(); } + int64_t ri64() { return m_swap ? swap(read()) : read(); } + float rflt() { return read(); } + double rdbl() { return read(); } + std::string pick(size_t chars) { return { (char*)m_cur, chars }; } + std::string rstring() { auto len = ru32(); return { advance(len), len }; } + std::string rstring(size_t len) { return { advance(len), len }; } + std::wstring rwstring() { auto len = ru32(); return rwstring(len); } + std::wstring rwstring(size_t len) { + //std::wstring_convert> conv; + char* ptr = advance(len * 2); + for (int i = 0; i < len; i++) + std::swap(ptr[i * 2], ptr[i * 2 + 1]); + //auto s = conv.from_bytes(ptr, ptr + len); + wchar_t* wptr = (wchar_t*)ptr; + //std::wstring_convert> convert; + //std::string utf8 = convert.to_bytes(wptr, wptr + len); + //std::wstring ws(len, 0); + //mbsrtowcs((wchar_t*)ws.data(), (const char**)&ptr, len, nullptr); + return std::wstring(wptr, len); + } +protected: + template inline T align4(T x) { return ((x - T{1}) & (~(T{3}))) + T{4}; } + template T read() + { + T ret{}; + if (m_ptr) + { + if (has_data(sizeof(T))) + ret = *reinterpret_cast(m_cur); + m_cur += sizeof(T); + } + return ret; + } + template T* advance(size_t bytes) + { + T* ret = nullptr; + if (m_ptr) + { + if (has_data(bytes)) + ret = reinterpret_cast(m_cur); + m_cur += bytes; + } + return ret; + } + template T swap(T x) + { +#if _MSC_VER >= 1400 + if (sizeof(T) == 2) + return _byteswap_ushort(x); + else if (sizeof(T) == 4) + return _byteswap_ulong(x); + else if (sizeof(T) == 8) + return _byteswap_uint64(x); +#else + auto p = reinterpret_cast(&x); + if (sizeof(T) == 2) + { + std::swap(p[0], p[1]); + } + else if (sizeof(T) == 4) + { + std::swap(p[0], p[3]); + std::swap(p[1], p[2]); + } + else if (sizeof(T) == 8) + { + std::swap(p[0], p[7]); + std::swap(p[1], p[6]); + std::swap(p[2], p[5]); + std::swap(p[3], p[4]); + } + else + { + static_assert(true, "Should not reach here"); + } + return x; +#endif + } +private: + uint8_t *m_ptr = nullptr; + uint8_t *m_cur = nullptr; + size_t m_size = 0; + bool m_swap = false; + ByteOrder m_byte_order = ByteOrder::Host; +}; + +static constexpr const uint32_t abr_s2sig(const char s[4]) +{ + return (uint32_t)(s[0]) << 0 + | (uint32_t)(s[1]) << 8 + | (uint32_t)(s[2]) << 16 + | (uint32_t)(s[3]) << 24; +} + +static constexpr const std::array abr_sig2sz(uint32_t x) +{ + return { + (char)(x >> 0 ), + (char)(x >> 8 ), + (char)(x >> 16), + (char)(x >> 24), + 0 + }; +} + +class ABR : public BinaryStream +{ + struct Type { + using Vec = std::vector>; + using Map = std::map>; + using Ref = std::shared_ptr; + virtual std::string str() const { return "type"; } + }; + struct Class : public Type { }; + struct Property : public Type { }; + struct Reference : public Type { }; + struct List : public Type{ + Type::Vec children; + }; + struct Double : public Type { double value; }; + struct UnitFloat : public Type { std::string unit; double value; }; + struct String : public Type { std::wstring value; }; + struct Enum : public Type { }; + struct EnumRef : public Type { }; + struct Offset : public Type { }; + struct Identifier : public Type { }; + struct Index : public Type { }; + struct Name : public Type { }; + struct Integer : public Type + { + int32_t value; + }; + struct LargeInteger : public Type { }; + struct Boolean : public Type + { + bool value; + virtual std::string str() const override { return "Boolean: " + ; } + }; + struct Alias : public Type { }; + struct Descriptor : public Type + { + std::wstring name; + std::string class_id; + Type::Map props; + }; + +public: + ABR(); + bool open(const std::string& path); +private: + inline std::string rkey_or_string() + { + auto len = ru32(); + if (len == 0) + len = 4; + return rstring(len); + } + bool section_desc(); + bool section_samp(); + bool section_patt(); + std::shared_ptr parse_vlls(); + std::shared_ptr parse_text(); + std::shared_ptr parse_objc(); + std::shared_ptr parse_untf(); + std::shared_ptr parse_bool(); + std::shared_ptr parse_long(); + std::shared_ptr parse_doub(); + std::shared_ptr parse_enum(); + //Type::Ref parse_prop(); + Type::Ref call(std::string t) + { + if (m_parser_table.find(t) != m_parser_table.end()) + { + auto& method = m_parser_table[t]; + return method(); + } + else if (m_parser_table.find(pick(4)) != m_parser_table.end()) + { + auto& method = m_parser_table[rstring(4)]; + return method(); + } + return nullptr; + } + std::map> m_parser_table; +}; +