#ifndef __DNA_COMMON_HPP__ #define __DNA_COMMON_HPP__ #include #include "HECL/HECL.hpp" #include "HECL/Database.hpp" namespace Retro { extern LogVisor::LogModule LogDNACommon; /* This comes up a great deal */ typedef Athena::io::DNA BigDNA; /* FourCC with DNA read/write */ class FourCC final : public BigDNA, public HECL::FourCC { public: FourCC() : HECL::FourCC() {} FourCC(const HECL::FourCC& other) : HECL::FourCC() {num = other.toUint32();} FourCC(const char* name) : HECL::FourCC(name) {} Delete expl; inline void read(Athena::io::IStreamReader& reader) {reader.readUBytesToBuf(fcc, 4);} inline void write(Athena::io::IStreamWriter& writer) const {writer.writeUBytes((atUint8*)fcc, 4);} }; /* PAK 32-bit Unique ID */ class UniqueID32 : public BigDNA { uint32_t m_id; public: Delete expl; inline void read(Athena::io::IStreamReader& reader) {m_id = reader.readUint32();} inline void write(Athena::io::IStreamWriter& writer) const {writer.writeUint32(m_id);} inline bool operator!=(const UniqueID32& other) const {return m_id != other.m_id;} inline bool operator==(const UniqueID32& other) const {return m_id == other.m_id;} inline uint32_t toUint32() const {return m_id;} inline std::string toString() const { char buf[9]; snprintf(buf, 9, "%08X", m_id); return std::string(buf); } }; /* PAK 64-bit Unique ID */ class UniqueID64 : public BigDNA { uint64_t m_id; public: Delete expl; inline void read(Athena::io::IStreamReader& reader) {m_id = reader.readUint64();} inline void write(Athena::io::IStreamWriter& writer) const {writer.writeUint64(m_id);} inline bool operator!=(const UniqueID64& other) const {return m_id != other.m_id;} inline bool operator==(const UniqueID64& other) const {return m_id == other.m_id;} inline uint64_t toUint64() const {return m_id;} inline std::string toString() const { char buf[17]; snprintf(buf, 17, "%016lX", m_id); return std::string(buf); } }; /* PAK 128-bit Unique ID */ class UniqueID128 : public BigDNA { union { uint64_t m_id[2]; #if __SSE__ __m128i m_id128; #endif }; public: Delete expl; inline void read(Athena::io::IStreamReader& reader) { m_id[0] = reader.readUint64(); m_id[1] = reader.readUint64(); } inline void write(Athena::io::IStreamWriter& writer) const { writer.writeUint64(m_id[0]); writer.writeUint64(m_id[1]); } inline bool operator!=(const UniqueID128& other) const { #if __SSE__ __m128i vcmp = _mm_cmpeq_epi32(m_id128, other.m_id128); int vmask = _mm_movemask_epi8(vcmp); return vmask != 0xffff; #else return (m_id[0] != other.m_id[0]) || (m_id[1] != other.m_id[1]); #endif } inline bool operator==(const UniqueID128& other) const { #if __SSE__ __m128i vcmp = _mm_cmpeq_epi32(m_id128, other.m_id128); int vmask = _mm_movemask_epi8(vcmp); return vmask == 0xffff; #else return (m_id[0] == other.m_id[0]) && (m_id[1] == other.m_id[1]); #endif } inline uint64_t toHighUint64() const {return m_id[0];} inline uint64_t toLowUint64() const {return m_id[1];} inline std::string toString() const { char buf[33]; snprintf(buf, 33, "%016lX%016lX", m_id[0], m_id[1]); return std::string(buf); } }; /* RGBA8 structure (GXColor) */ struct GXColor : BigDNA { Value r; Value g; Value b; Value a; Delete expl; void read(Athena::io::IStreamReader& reader) {reader.readUBytesToBuf(&r, 4);} void write(Athena::io::IStreamWriter& writer) const {writer.writeUBytes(&r, 4);} }; /* More GX structures */ enum GXAttrType { GX_NONE, GX_DIRECT, GX_INDEX8, GX_INDEX16 }; enum GXTevColorArg { GX_CC_CPREV = 0, /*!< Use the color value from previous TEV stage */ GX_CC_APREV = 1, /*!< Use the alpha value from previous TEV stage */ GX_CC_C0 = 2, /*!< Use the color value from the color/output register 0 */ GX_CC_A0 = 3, /*!< Use the alpha value from the color/output register 0 */ GX_CC_C1 = 4, /*!< Use the color value from the color/output register 1 */ GX_CC_A1 = 5, /*!< Use the alpha value from the color/output register 1 */ GX_CC_C2 = 6, /*!< Use the color value from the color/output register 2 */ GX_CC_A2 = 7, /*!< Use the alpha value from the color/output register 2 */ GX_CC_TEXC = 8, /*!< Use the color value from texture */ GX_CC_TEXA = 9, /*!< Use the alpha value from texture */ GX_CC_RASC = 10, /*!< Use the color value from rasterizer */ GX_CC_RASA = 11, /*!< Use the alpha value from rasterizer */ GX_CC_ONE = 12, GX_CC_HALF = 13, GX_CC_KONST = 14, GX_CC_ZERO = 15 /*!< Use to pass zero value */ }; enum GXTevAlphaArg { GX_CA_APREV = 0, /*!< Use the alpha value from previous TEV stage */ GX_CA_A0 = 1, /*!< Use the alpha value from the color/output register 0 */ GX_CA_A1 = 2, /*!< Use the alpha value from the color/output register 1 */ GX_CA_A2 = 3, /*!< Use the alpha value from the color/output register 2 */ GX_CA_TEXA = 4, /*!< Use the alpha value from texture */ GX_CA_RASA = 5, /*!< Use the alpha value from rasterizer */ GX_CA_KONST = 6, GX_CA_ZERO = 7 /*!< Use to pass zero value */ }; enum GXTevOp { GX_TEV_ADD = 0, GX_TEV_SUB = 1, GX_TEV_COMP_R8_GT = 8, GX_TEV_COMP_R8_EQ = 9, GX_TEV_COMP_GR16_GT = 10, GX_TEV_COMP_GR16_EQ = 11, GX_TEV_COMP_BGR24_GT = 12, GX_TEV_COMP_BGR24_EQ = 13, GX_TEV_COMP_RGB8_GT = 14, GX_TEV_COMP_RGB8_EQ = 15, GX_TEV_COMP_A8_GT = GX_TEV_COMP_RGB8_GT, // for alpha channel GX_TEV_COMP_A8_EQ = GX_TEV_COMP_RGB8_EQ // for alpha channel }; enum GXTevBias { GX_TB_ZERO = 0, GX_TB_ADDHALF = 1, GX_TB_SUBHALF = 2, }; enum GXTevScale { GX_CS_SCALE_1 = 0, GX_CS_SCALE_2 = 1, GX_CS_SCALE_4 = 2, GX_CS_DIVIDE_2 = 3 }; enum GXTevRegID { GX_TEVPREV = 0, GX_TEVREG0 = 1, GX_TEVREG1 = 2, GX_TEVREG2 = 3 }; /* Case-insensitive comparator for std::map sorting */ struct CaseInsensitiveCompare { inline bool operator()(const std::string& lhs, const std::string& rhs) const { #if _WIN32 if (_stricmp(lhs.c_str(), rhs.c_str()) < 0) #else if (strcasecmp(lhs.c_str(), rhs.c_str()) < 0) #endif return true; return false; } #if _WIN32 inline bool operator()(const std::wstring& lhs, const std::wstring& rhs) const { if (_wcsicmp(lhs.c_str(), rhs.c_str()) < 0) return true; return false; } #endif }; /* PAK entry stream reader */ class PAKEntryReadStream : public Athena::io::IStreamReader { std::unique_ptr m_buf; atUint64 m_sz; atUint64 m_pos; public: PAKEntryReadStream() {} operator bool() const {return m_buf.operator bool();} PAKEntryReadStream(const PAKEntryReadStream& other) = delete; PAKEntryReadStream(PAKEntryReadStream&& other) = default; PAKEntryReadStream& operator=(const PAKEntryReadStream& other) = delete; PAKEntryReadStream& operator=(PAKEntryReadStream&& other) = default; PAKEntryReadStream(std::unique_ptr&& buf, atUint64 sz, atUint64 pos) : m_buf(std::move(buf)), m_sz(sz), m_pos(pos) { if (m_pos >= m_sz) LogDNACommon.report(LogVisor::FatalError, "PAK stream cursor overrun"); } inline void seek(atInt64 pos, Athena::SeekOrigin origin) { if (origin == Athena::Begin) m_pos = pos; else if (origin == Athena::Current) m_pos += pos; else if (origin == Athena::End) m_pos = m_sz + pos; if (m_pos >= m_sz) LogDNACommon.report(LogVisor::FatalError, "PAK stream cursor overrun"); } inline atUint64 position() const {return m_pos;} inline atUint64 length() const {return m_sz;} inline const atUint8* data() const {return m_buf.get();} inline atUint64 readUBytesToBuf(void* buf, atUint64 len) { atUint64 bufEnd = m_pos + len; if (bufEnd > m_sz) len -= bufEnd - m_sz; memcpy(buf, m_buf.get() + m_pos, len); m_pos += len; return len; } }; /* Resource extractor type */ typedef struct { std::function func; const char* fileExt; } ResExtractor; /* Resource cooker function */ typedef std::function ResCooker; /* Language-identifiers */ extern const HECL::FourCC ENGL; extern const HECL::FourCC FREN; extern const HECL::FourCC GERM; extern const HECL::FourCC SPAN; extern const HECL::FourCC ITAL; extern const HECL::FourCC JAPN; /* Resource types */ extern const HECL::FourCC AFSM; extern const HECL::FourCC AGSC; extern const HECL::FourCC ANCS; extern const HECL::FourCC ANIM; extern const HECL::FourCC ATBL; extern const HECL::FourCC CINF; extern const HECL::FourCC CMDL; extern const HECL::FourCC CRSC; extern const HECL::FourCC CSKR; extern const HECL::FourCC CSMP; extern const HECL::FourCC CSNG; extern const HECL::FourCC CTWK; extern const HECL::FourCC DGRP; extern const HECL::FourCC DPSC; extern const HECL::FourCC DUMB; extern const HECL::FourCC ELSC; extern const HECL::FourCC EVNT; extern const HECL::FourCC FONT; extern const HECL::FourCC FRME; extern const HECL::FourCC HINT; extern const HECL::FourCC MAPA; extern const HECL::FourCC MAPU; extern const HECL::FourCC MAPW; extern const HECL::FourCC MLVL; extern const HECL::FourCC MREA; extern const HECL::FourCC PART; extern const HECL::FourCC PATH; extern const HECL::FourCC RFRM; extern const HECL::FourCC ROOM; extern const HECL::FourCC SAVW; extern const HECL::FourCC SCAN; extern const HECL::FourCC STRG; extern const HECL::FourCC SWHC; extern const HECL::FourCC TXTR; extern const HECL::FourCC WPSC; } /* Hash template-specializations for UniqueID types */ namespace std { template<> struct hash { inline size_t operator()(const Retro::FourCC& fcc) const {return fcc.toUint32();} }; template<> struct hash { inline size_t operator()(const Retro::UniqueID32& id) const {return id.toUint32();} }; template<> struct hash { inline size_t operator()(const Retro::UniqueID64& id) const {return id.toUint64();} }; template<> struct hash { inline size_t operator()(const Retro::UniqueID128& id) const {return id.toHighUint64() ^ id.toLowUint64();} }; } #endif // __DNA_COMMON_HPP__