From efab931113c36a94df6f12a842b8edb64b7c6455 Mon Sep 17 00:00:00 2001 From: Danilo Date: Wed, 1 May 2024 19:09:43 -0300 Subject: [PATCH] Arquivos Content --- CMakeLists.txt | 2 + framework/CMakeLists.txt | 50 +- framework/content/decstream.cpp | 111 ++++ framework/content/decstream.hpp | 60 +++ framework/content/lzx/decoder.cpp | 5 + framework/content/lzx/decoder.hpp | 649 ++++++++++++++++++++++++ framework/content/lzx/decoderstream.cpp | 40 ++ framework/content/lzx/decoderstream.hpp | 88 ++++ framework/content/reader.cpp | 51 +- framework/content/reader.hpp | 21 +- framework/content/typereadermanager.cpp | 137 +++++ framework/content/typereadermanager.hpp | 114 +++++ framework/csharp/binary.cpp | 84 ++- framework/csharp/binary.hpp | 40 +- framework/csharp/buffer.hpp | 7 +- framework/csharp/object.cpp | 13 + framework/csharp/object.hpp | 13 + framework/csharp/stream.hpp | 29 +- framework/csharp/type.hpp | 32 ++ framework/forward.hpp | 4 + framework/xna.cpp | 5 +- framework/xna.h | 1 + framework/xnaerror.hpp | 3 +- 23 files changed, 1484 insertions(+), 75 deletions(-) create mode 100644 framework/content/decstream.cpp create mode 100644 framework/content/decstream.hpp create mode 100644 framework/content/lzx/decoder.cpp create mode 100644 framework/content/lzx/decoder.hpp create mode 100644 framework/content/lzx/decoderstream.cpp create mode 100644 framework/content/lzx/decoderstream.hpp create mode 100644 framework/content/typereadermanager.cpp create mode 100644 framework/content/typereadermanager.hpp create mode 100644 framework/csharp/object.cpp create mode 100644 framework/csharp/object.hpp create mode 100644 framework/csharp/type.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f8c094..5f9f0f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ if (POLICY CMP0141) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() +set(ENV{VCPKG_ROOT} C:\\vcpkg) + project ("xna") # Include sub-projects. diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index d127244..c84a1a2 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -3,7 +3,43 @@ # # Add source to this project's executable. -add_executable (xna WIN32 "xna.cpp" "xna.h" "platform/window-dx.cpp" "platform/device-dx.cpp" "platform/adapter-dx.cpp" "platform/swapchain-dx.cpp" "platform/rendertarget-dx.cpp" "platform/texture-dx.cpp" "platform/blendstate-dx.cpp" "platform/game-dx.cpp" "platform/clock-dx.cpp" "csharp/stream.cpp" "platform/gdevicemanager-dx.cpp" "platform/vertexinput-dx.cpp" "platform/shader-dx.cpp" "platform/rasterizerstate-dx.cpp" "platform/vertexbuffer-dx.cpp" "platform/indexbuffer-dx.cpp" "common/matrix.cpp" "platform/constbuffer-dx.cpp" "platform/databuffer-dx.cpp" "platform/samplerstate-dx.cpp" "platform/spritebatch-dx.cpp" "platform/spritefont-dx.cpp" "platform/depthstencilstate-dx.cpp" "platform/keyboard-dx.cpp" "platform/mouse-dx.cpp" "platform/gamepad-dx.cpp" "common/vectors.cpp" "platform/soundeffect-dx.cpp" "platform/displaymode-dx.cpp" "platform/presentparameters-dx.cpp" "game/component.cpp" "content/manager.cpp" "content/reader.cpp" "csharp/binary.cpp") +add_executable (xna WIN32 +"xna.cpp" +"platform/window-dx.cpp" +"platform/device-dx.cpp" +"platform/adapter-dx.cpp" +"platform/swapchain-dx.cpp" +"platform/rendertarget-dx.cpp" +"platform/texture-dx.cpp" +"platform/blendstate-dx.cpp" +"platform/game-dx.cpp" +"platform/clock-dx.cpp" +"csharp/stream.cpp" +"platform/gdevicemanager-dx.cpp" +"platform/vertexinput-dx.cpp" +"platform/shader-dx.cpp" +"platform/rasterizerstate-dx.cpp" +"platform/vertexbuffer-dx.cpp" +"platform/indexbuffer-dx.cpp" +"common/matrix.cpp" +"platform/constbuffer-dx.cpp" +"platform/databuffer-dx.cpp" +"platform/samplerstate-dx.cpp" +"platform/spritebatch-dx.cpp" +"platform/spritefont-dx.cpp" +"platform/depthstencilstate-dx.cpp" +"platform/keyboard-dx.cpp" +"platform/mouse-dx.cpp" +"platform/gamepad-dx.cpp" +"common/vectors.cpp" +"platform/soundeffect-dx.cpp" +"platform/displaymode-dx.cpp" +"platform/presentparameters-dx.cpp" +"game/component.cpp" +"content/manager.cpp" +"content/reader.cpp" +"csharp/binary.cpp" +"content/decstream.cpp" "content/lzx/decoder.cpp" "content/lzx/decoderstream.cpp" "content/typereadermanager.cpp" "csharp/object.cpp") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET xna PROPERTY CXX_STANDARD 20) @@ -12,7 +48,6 @@ endif() # TODO: Add tests and install targets if needed. - # -- Biblioteca DirectxTK -- # Url: https://github.com/microsoft/DirectXTK/wiki/DirectXTK # @@ -30,5 +65,14 @@ endif() # "CMAKE_TOOLCHAIN_FILE": "{VCPKG_DIR}\\scripts\\buildsystems\\vcpkg.cmake" # } # +# InstalaƧao do libmspack +# $- vcpkg install libmspack +# find_package(directxtk CONFIG REQUIRED) -target_link_libraries(${PROJECT_NAME} D3d11.lib dxgi.lib dxguid.lib d3dcompiler.lib Microsoft::DirectXTK) + +include_directories($ENV{VCPKG_ROOT}\\packages\\libmspack_x64-windows\\include) + +target_link_libraries(${PROJECT_NAME} + D3d11.lib dxgi.lib dxguid.lib d3dcompiler.lib Microsoft::DirectXTK + $ENV{VCPKG_ROOT}\\packages\\libmspack_x64-windows\\lib\\libmspack.lib +) diff --git a/framework/content/decstream.cpp b/framework/content/decstream.cpp new file mode 100644 index 0000000..7d96ba8 --- /dev/null +++ b/framework/content/decstream.cpp @@ -0,0 +1,111 @@ +#include "decstream.hpp" +#include + +namespace xna { + void DecompressStream::Decompress() + { + String filename = "C:\\Users\\Danilo Borges\\Documents\\xna\\projeto-final\\Game9\\bin\\Debug\\netcoreapp3.1\\Content\\Sprites\\MonsterA\\idle.xnb"; + + + } + + Int DecompressStream::Length() + { + return Int(); + } + + Long DecompressStream::Position() + { + return Long(); + } + + void DecompressStream::Close() + { + } + + Long DecompressStream::Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) + { + return Long(); + } + + Int DecompressStream::Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) + { + return Int(); + } + + Int DecompressStream::Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) + { + return Int(); + } + + Int DecompressStream::ReadByte(xna_error_ptr_arg) + { + return Int(); + } + + void DecompressStream::Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) + { + } + + void DecompressStream::Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) + { + } + + void DecompressStream::WriteByte(Byte value, xna_error_ptr_arg) + { + } + + bool DecompressStream::DecompressNextBuffer() + { + if (decompressedTodo <= 0) + return false; + + do { + if (compressedPosition >= compressedSize) + ReadNextBufferFromDisk(); + + auto sourceSize = compressedSize - compressedPosition; + auto outputSize = 65536; + + //TODO + + if (outputSize == 0 && sourceSize == 0) + return false; + + compressedPosition += sourceSize; + decompressedTodo -= outputSize; + decompressedSize = outputSize; + decompressedPosition = 0; + + } while (decompressedSize == 0); + + return true; + } + + void DecompressStream::ReadNextBufferFromDisk() + { + if (compressedTodo <= 0) + return; + + ReadBufferFromDisk(compressedBuffer, compressedTodo, compressedSize); + compressedPosition = 0; + } + + void DecompressStream::ReadBufferFromDisk(std::vector& buffer, Int& bufferTodo, Int& bufferSize) + { + Int num1 = 65536; + if (num1 > bufferTodo) + num1 = bufferTodo; + + Int num2 = 0; + for (int offset = 0; offset < num1; offset += num2) { + num2 = baseStream->Read(buffer, offset, num1 - offset); + + if (num2 == 0) return; + } + + bufferTodo -= num1; + bufferSize = num1; + } + +} \ No newline at end of file diff --git a/framework/content/decstream.hpp b/framework/content/decstream.hpp new file mode 100644 index 0000000..20219ec --- /dev/null +++ b/framework/content/decstream.hpp @@ -0,0 +1,60 @@ +#ifndef XNA_CONTENT_DECOMPRESS_STREAM_HPP +#define XNA_CONTENT_DECOMPRESS_STREAM_HPP + +#include "../default.hpp" +#include "../csharp/stream.hpp" +#include + +namespace xna { + class DecompressStream : public Stream { + public: + DecompressStream(sptr const& baseStream, Int compressedTodo, Int decompressedTodo): + baseStream(baseStream), compressedTodo(compressedTodo), decompressedTodo(decompressedTodo){ + compressedBuffer = std::vector(CompressedBufferSize); + decompressedBuffer = std::vector(DecompressedBufferSize); + decompressionContext = mspack_create_cab_decompressor(nullptr); + } + + virtual ~DecompressStream() { + if (decompressionContext) { + mspack_destroy_cab_decompressor(decompressionContext); + } + } + + void Decompress(); + + public: + // Inherited via Stream + Int Length() override; + Long Position() override; + void Close() override; + Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override; + Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + Int Read(std::vector& buffer, Int offset, Int count, xna_error_nullarg) override; + Int ReadByte(xna_error_nullarg) override; + void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + void Write(std::vector const& buffer, Int offset, Int count, xna_error_nullarg) override; + void WriteByte(Byte value, xna_error_nullarg) override; + + private: + static constexpr int CompressedBufferSize = 65536; + static constexpr int DecompressedBufferSize = 65536; + sptr baseStream = nullptr; + Int compressedTodo{ 0 }; + Int compressedSize{ 0 }; + Int compressedPosition{ 0 }; + std::vector compressedBuffer; + Int decompressedTodo{ 0 }; + Int decompressedSize{ 0 }; + Int decompressedPosition{ 0 }; + std::vector decompressedBuffer; + mscab_decompressor* decompressionContext = nullptr; + + private: + bool DecompressNextBuffer(); + void ReadNextBufferFromDisk(); + void ReadBufferFromDisk(std::vector& buffer, Int& bufferTodo, Int& bufferSize); + }; +} + +#endif \ No newline at end of file diff --git a/framework/content/lzx/decoder.cpp b/framework/content/lzx/decoder.cpp new file mode 100644 index 0000000..4639276 --- /dev/null +++ b/framework/content/lzx/decoder.cpp @@ -0,0 +1,5 @@ +#include "decoder.hpp" + +namespace xna { + +} \ No newline at end of file diff --git a/framework/content/lzx/decoder.hpp b/framework/content/lzx/decoder.hpp new file mode 100644 index 0000000..e93be4a --- /dev/null +++ b/framework/content/lzx/decoder.hpp @@ -0,0 +1,649 @@ +#ifndef XNA_CONTENT_LZX_LZXDECODE_HPP +#define XNA_CONTENT_LZX_LZXDECODE_HPP + +#include "../../default.hpp" +#include "../../csharp/stream.hpp" +#include + +namespace xna { + struct LzxConstants { + static constexpr Ushort MIN_MATCH = 2; + static constexpr Ushort MAX_MATCH = 257; + static constexpr Ushort NUM_CHARS = 256; + + enum class BLOCKTYPE { + INVALID = 0, + VERBATIM = 1, + ALIGNED = 2, + UNCOMPRESSED = 3 + }; + + static constexpr Ushort PRETREE_NUM_ELEMENTS = 20; + static constexpr Ushort ALIGNED_NUM_ELEMENTS = 8; + static constexpr Ushort NUM_PRIMARY_LENGTHS = 7; + static constexpr Ushort NUM_SECONDARY_LENGTHS = 249; + + static constexpr Ushort PRETREE_MAXSYMBOLS = PRETREE_NUM_ELEMENTS; + static constexpr Ushort PRETREE_TABLEBITS = 6; + static constexpr Ushort MAINTREE_MAXSYMBOLS = NUM_CHARS + 50 * 8; + static constexpr Ushort MAINTREE_TABLEBITS = 12; + static constexpr Ushort LENGTH_MAXSYMBOLS = NUM_SECONDARY_LENGTHS + 1; + static constexpr Ushort LENGTH_TABLEBITS = 12; + static constexpr Ushort ALIGNED_MAXSYMBOLS = ALIGNED_NUM_ELEMENTS; + static constexpr Ushort ALIGNED_TABLEBITS = 7; + + static constexpr Ushort LENTABLE_SAFETY = 64; + }; + + struct LzxState { + Uint R0{ 1 }, R1{ 1 }, R2{ 1 }; /* for the LRU offset system */ + Ushort main_elements{ 0 }; /* number of main tree elements */ + Int header_read{ 0 }; /* have we started decoding at all yet? */ + LzxConstants::BLOCKTYPE block_type{ LzxConstants::BLOCKTYPE::INVALID }; /* type of this block */ + Uint block_length{ 0 }; /* uncompressed length of this block */ + Uint block_remaining{ 0 }; /* uncompressed bytes still left to decode */ + Uint frames_read{ 0 }; /* the number of CFDATA blocks processed */ + Int intel_filesize{ 0 }; /* magic header value used for transform */ + Int intel_curpos{ 0 }; /* current offset in transform space */ + Int intel_started{ 0 }; /* have we seen any translateable data yet? */ + + std::vector PRETREE_table; + std::vector PRETREE_len; + std::vector MAINTREE_table; + std::vector MAINTREE_len; + std::vector LENGTH_table; + std::vector LENGTH_len; + std::vector ALIGNED_table; + std::vector ALIGNED_len; + + // NEEDED MEMBERS + // CAB actualsize + // CAB window + // CAB window_size + // CAB window_posn + Uint actual_size{ 0 }; + std::vector window; + Uint window_size{ 0 }; + Uint window_posn{ 0 }; + }; + + class BitBuffer { + public: + BitBuffer(sptr const& stream) : byteStream(stream) { + InitBitStream(); + } + + constexpr void InitBitStream() { + buffer = 0; + bitsleft = 0; + } + + void EnsureBits(Byte bits) { + while (bitsleft < bits) { + const auto lo = static_cast(byteStream->ReadByte()); + const auto hi = static_cast(byteStream->ReadByte()); + //int amount2shift = sizeofstatic_cast(*8 - 16 - bitsleft; + buffer |= static_cast(((hi << 8) | lo) << (sizeof(Uint) * 8 - 16 - bitsleft)); + bitsleft += 16; + } + } + + constexpr Uint PeekBits(Byte bits) const + { + return (buffer >> ((sizeof(Uint) * 8) - bits)); + } + + constexpr void RemoveBits(Byte bits) { + buffer <<= bits; + bitsleft -= bits; + } + + Uint ReadBits(Byte bits) + { + Uint ret = 0; + + if (bits > 0) + { + EnsureBits(bits); + ret = PeekBits(bits); + RemoveBits(bits); + } + + return ret; + } + + constexpr Uint GetBuffer() const { + return buffer; + } + + constexpr Byte GetBitsLeft() const { + return bitsleft; + } + + private: + Uint buffer{ 0 }; + Byte bitsleft{ 0 }; + sptr byteStream = nullptr; + }; + + class LzxDecoder { + public: + LzxDecoder(Int window) { + Uint wndsize = (Uint)(1 << window); + Int posn_slots = 0; + + // setup proper exception + if (window < 15 || window > 21) + return; + + // let's initialise our state + m_state.window = std::vector(wndsize, 0xDC); + + m_state.actual_size = wndsize; + m_state.window_size = wndsize; + + /* initialize static tables */ + + if (extra_bits.empty()) { + extra_bits.resize(52); + + for (size_t i = 0, j = 0; i <= 50; i += 2) { + extra_bits[i] = extra_bits[i + 1] = static_cast(j); + + if ((i != 0) && (j < 17)) + j++; + } + } + + if (position_base.empty()) { + position_base.resize(51); + + for (size_t i = 0, j = 0; i <= 50; i++) { + position_base[i] = static_cast(j); + j += static_cast(1) << extra_bits[i]; + } + } + + /* calculate required position slots */ + if (window == 20) + posn_slots = 42; + else if (window == 21) + posn_slots = 50; + else + posn_slots = window << 1; + + m_state.main_elements = static_cast(LzxConstants::NUM_CHARS + (posn_slots << 3)); + + // yo dawg i herd u liek arrays so we put arrays in ur arrays so u can array while u array + m_state.PRETREE_table = std::vector((1 << LzxConstants::PRETREE_TABLEBITS) + (LzxConstants::PRETREE_MAXSYMBOLS << 1)); + m_state.PRETREE_len = std::vector(LzxConstants::PRETREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.MAINTREE_table = std::vector((1 << LzxConstants::MAINTREE_TABLEBITS) + (LzxConstants::MAINTREE_MAXSYMBOLS << 1)); + m_state.MAINTREE_len = std::vector(LzxConstants::MAINTREE_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.LENGTH_table = std::vector((1 << LzxConstants::LENGTH_TABLEBITS) + (LzxConstants::LENGTH_MAXSYMBOLS << 1)); + m_state.LENGTH_len = std::vector(LzxConstants::LENGTH_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + m_state.ALIGNED_table = std::vector((1 << LzxConstants::ALIGNED_TABLEBITS) + (LzxConstants::ALIGNED_MAXSYMBOLS << 1)); + m_state.ALIGNED_len = std::vector(LzxConstants::ALIGNED_MAXSYMBOLS + LzxConstants::LENTABLE_SAFETY); + + /* initialise tables to 0 (because deltas will be applied to them) */ + for (size_t i = 0; i < LzxConstants::MAINTREE_MAXSYMBOLS; i++) + m_state.MAINTREE_len[i] = 0; + + for (size_t i = 0; i < LzxConstants::LENGTH_MAXSYMBOLS; i++) + m_state.LENGTH_len[i] = 0; + } + + Int Decompress(sptr& inData, Int inLen, sptr& outData, Int outLen) { + BitBuffer bitbuf(inData); + + auto startpos = inData->Position(); + auto endpos = inData->Position() + inLen; + + auto& window = m_state.window; + + Uint window_posn = m_state.window_posn; + Uint window_size = m_state.window_size; + Uint R0 = m_state.R0; + Uint R1 = m_state.R1; + Uint R2 = m_state.R2; + Uint i = 0; + Uint j = 0; + + Int togo = outLen; + Int this_run = 0; + Int main_element = 0; + Int match_length = 0; + Int match_offset = 0; + Int length_footer = 0; + Int extra = 0; + Int verbatim_bits = 0; + Int rundest = 0; + Int runsrc = 0; + Int copy_length = 0; + Int aligned_bits = 0; + + bitbuf.InitBitStream(); + + /* read header if necessary */ + if (m_state.header_read == 0) + { + const auto intel = bitbuf.ReadBits(1); + if (intel != 0) + { + // read the filesize + i = bitbuf.ReadBits(16); + j = bitbuf.ReadBits(16); + m_state.intel_filesize = static_cast((i << 16) | j); + } + m_state.header_read = 1; + } + + while (togo > 0) + { + /* last block finished, new block expected */ + if (m_state.block_remaining == 0) + { + // TODO may screw something up here + if (m_state.block_type == LzxConstants::BLOCKTYPE::UNCOMPRESSED) { + if ((m_state.block_length & 1) == 1) + inData->ReadByte(); /* realign bitstream to word */ + + bitbuf.InitBitStream(); + } + + m_state.block_type = static_cast(bitbuf.ReadBits(3)); + i = bitbuf.ReadBits(16); + j = bitbuf.ReadBits(8); + m_state.block_remaining = m_state.block_length = static_cast((i << 8) | j); + + switch (m_state.block_type) { + case LzxConstants::BLOCKTYPE::ALIGNED: { + for (i = 0, j = 0; i < 8; i++) { + j = bitbuf.ReadBits(3); + m_state.ALIGNED_len[i] = static_cast(j); + } + + MakeDecodeTable(LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS, + m_state.ALIGNED_len, m_state.ALIGNED_table); + + //O mesmo que verbatim + ReadLengths(m_state.MAINTREE_len, 0, 256, bitbuf); + ReadLengths(m_state.MAINTREE_len, 256, m_state.main_elements, bitbuf); + MakeDecodeTable(LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS, + m_state.MAINTREE_len, m_state.MAINTREE_table); + + if (m_state.MAINTREE_len[0xE8] != 0) + m_state.intel_started = 1; + + ReadLengths(m_state.LENGTH_len, 0, LzxConstants::NUM_SECONDARY_LENGTHS, bitbuf); + MakeDecodeTable(LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS, + m_state.LENGTH_len, m_state.LENGTH_table); + break; + } + case LzxConstants::BLOCKTYPE::VERBATIM: { + ReadLengths(m_state.MAINTREE_len, 0, 256, bitbuf); + ReadLengths(m_state.MAINTREE_len, 256, m_state.main_elements, bitbuf); + MakeDecodeTable(LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS, + m_state.MAINTREE_len, m_state.MAINTREE_table); + + if (m_state.MAINTREE_len[0xE8] != 0) + m_state.intel_started = 1; + + ReadLengths(m_state.LENGTH_len, 0, LzxConstants::NUM_SECONDARY_LENGTHS, bitbuf); + MakeDecodeTable(LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS, + m_state.LENGTH_len, m_state.LENGTH_table); + break; + } + case LzxConstants::BLOCKTYPE::UNCOMPRESSED: { + m_state.intel_started = 1; /* because we can't assume otherwise */ + bitbuf.EnsureBits(16); /* get up to 16 pad bits into the buffer */ + + if (bitbuf.GetBitsLeft() > 16) + inData->Seek(-2, SeekOrigin::Current); /* and align the bitstream! */ + + Byte hi = 0; + Byte mh = 0; + Byte ml = 0; + Byte lo = 0; + + lo = static_cast(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R0 = static_cast(lo | ml << 8 | mh << 16 | hi << 24); + lo = static_cast(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R1 = static_cast(lo | ml << 8 | mh << 16 | hi << 24); + lo = static_cast(inData->ReadByte()); + ml = static_cast(inData->ReadByte()); + mh = static_cast(inData->ReadByte()); + hi = static_cast(inData->ReadByte()); + R2 = static_cast(lo | ml << 8 | mh << 16 | hi << 24); + break; + } + default: + return -1; // TODO throw proper exception + } + } + + return 0; + + /* buffer exhaustion check */ + if (inData->Position() > (startpos + inLen)) + { + /* it's possible to have a file where the next run is less than + * 16 bits in size. In this case, the READ_HUFFSYM() macro used + * in building the tables will exhaust the buffer, so we should + * allow for this, but not allow those accidentally read bits to + * be used (so we check that there are at least 16 bits + * remaining - in this boundary case they aren't really part of + * the compressed data) + */ + //Debug.WriteLine("WTF"); + + if (inData->Position() > (startpos + inLen + 2) || bitbuf.GetBitsLeft() < 16) + return -1; //TODO throw proper exception + } + + while ((this_run = static_cast(m_state.block_remaining)) > 0 && togo > 0) + { + if (this_run > togo) + this_run = togo; + + togo -= this_run; + m_state.block_remaining -= static_cast(this_run); + + /* apply 2^x-1 mask */ + window_posn &= window_size - 1; + /* runs can't straddle the window wraparound */ + if ((window_posn + this_run) > window_size) + return -1; //TODO throw proper exception + + switch (m_state.block_type) + { + case LzxConstants::BLOCKTYPE::VERBATIM: { + while (this_run > 0) + { + main_element = static_cast(ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len, + LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS, + bitbuf)); + + if (main_element < LzxConstants::NUM_CHARS) + { + /* literal: 0 to NUM_CHARS-1 */ + window[window_posn++] = static_cast(main_element); + this_run--; + } + else + { + /* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LzxConstants::NUM_CHARS; + + match_length = main_element & LzxConstants::NUM_PRIMARY_LENGTHS; + if (match_length == LzxConstants::NUM_PRIMARY_LENGTHS) + { + length_footer = static_cast(ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len, + LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS, + bitbuf)); + match_length += length_footer; + } + match_length += LzxConstants::MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) + { + /* not repeated offset */ + if (match_offset != 3) + { + extra = extra_bits[match_offset]; + verbatim_bits = static_cast(bitbuf.ReadBits(static_cast(extra))); + match_offset = static_cast(position_base[match_offset]) - 2 + verbatim_bits; + } + else + { + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = static_cast(match_offset); + } + else if (match_offset == 0) + { + match_offset = (int)R0; + } + else if (match_offset == 1) + { + match_offset = (int)R1; + R1 = R0; R0 = static_cast(match_offset); + } + else /* match_offset == 2 */ + { + match_offset = (int)R2; + R2 = R0; R0 = static_cast(match_offset); + } + + rundest = (int)window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (static_cast(window_posn) >= match_offset) + { + /* no wrap */ + runsrc = rundest - match_offset; + } + else + { + runsrc = rundest + ((int)window_size - match_offset); + copy_length = match_offset - (int)window_posn; + if (copy_length < match_length) + { + match_length -= copy_length; + window_posn += static_cast(copy_length); + while (copy_length-- > 0) window[rundest++] = window[runsrc++]; + runsrc = 0; + } + } + window_posn += static_cast(match_length); + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) window[rundest++] = window[runsrc++]; + } + } + break; + } + case LzxConstants::BLOCKTYPE::ALIGNED: { + while (this_run > 0) + { + main_element = static_cast(ReadHuffSym(m_state.MAINTREE_table, m_state.MAINTREE_len, + LzxConstants::MAINTREE_MAXSYMBOLS, LzxConstants::MAINTREE_TABLEBITS, + bitbuf)); + + if (main_element < LzxConstants::NUM_CHARS) + { + /* literal 0 to NUM_CHARS-1 */ + window[window_posn++] = static_cast(main_element); + this_run--; + } + else + { + /* match: NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ + main_element -= LzxConstants::NUM_CHARS; + + match_length = main_element & LzxConstants::NUM_PRIMARY_LENGTHS; + if (match_length == LzxConstants::NUM_PRIMARY_LENGTHS) + { + length_footer = static_cast(ReadHuffSym(m_state.LENGTH_table, m_state.LENGTH_len, + LzxConstants::LENGTH_MAXSYMBOLS, LzxConstants::LENGTH_TABLEBITS, + bitbuf)); + match_length += length_footer; + } + match_length += LzxConstants::MIN_MATCH; + + match_offset = main_element >> 3; + + if (match_offset > 2) + { + /* not repeated offset */ + extra = extra_bits[match_offset]; + match_offset = static_cast(position_base[match_offset]) - 2; + if (extra > 3) + { + /* verbatim and aligned bits */ + extra -= 3; + verbatim_bits = static_cast(bitbuf.ReadBits(static_cast(extra))); + match_offset += (verbatim_bits << 3); + aligned_bits = static_cast(ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len, + LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS, + bitbuf)); + match_offset += aligned_bits; + } + else if (extra == 3) + { + /* aligned bits only */ + aligned_bits = static_cast(ReadHuffSym(m_state.ALIGNED_table, m_state.ALIGNED_len, + LzxConstants::ALIGNED_MAXSYMBOLS, LzxConstants::ALIGNED_TABLEBITS, + bitbuf)); + match_offset += aligned_bits; + } + else if (extra > 0) /* extra==1, extra==2 */ + { + /* verbatim bits only */ + verbatim_bits = static_cast(bitbuf.ReadBits(static_cast(extra))); + match_offset += verbatim_bits; + } + else /* extra == 0 */ + { + /* ??? */ + match_offset = 1; + } + + /* update repeated offset LRU queue */ + R2 = R1; R1 = R0; R0 = static_cast(match_offset); + } + else if (match_offset == 0) + { + match_offset = (int)R0; + } + else if (match_offset == 1) + { + match_offset = (int)R1; + R1 = R0; R0 = static_cast(match_offset); + } + else /* match_offset == 2 */ + { + match_offset = (int)R2; + R2 = R0; R0 = static_cast(match_offset); + } + + rundest = (int)window_posn; + this_run -= match_length; + + /* copy any wrapped around source data */ + if (static_cast(window_posn) >= match_offset) + { + /* no wrap */ + runsrc = rundest - match_offset; + } + else + { + runsrc = rundest + ((int)window_size - match_offset); + copy_length = match_offset - (int)window_posn; + if (copy_length < match_length) + { + match_length -= copy_length; + window_posn += static_cast(copy_length); + while (copy_length-- > 0) window[rundest++] = window[runsrc++]; + runsrc = 0; + } + } + window_posn += static_cast(match_length); + + /* copy match data - no worries about destination wraps */ + while (match_length-- > 0) window[rundest++] = window[runsrc++]; + } + } + break; + } + case LzxConstants::BLOCKTYPE::UNCOMPRESSED: { + if ((inData->Position() + this_run) > endpos) return -1; //TODO throw proper exception + std::vector temp_buffer(this_run); + inData->Read(temp_buffer, 0, this_run); + + for (size_t offset = 0; offset < temp_buffer.size(); ++offset) + window[window_posn + offset] = temp_buffer[offset]; + + window_posn += static_cast(this_run); + break; + } + default: + return -1; //TODO throw proper exception + } + } + } + + if (togo != 0) + return -1; //TODO throw proper exception + + Int start_window_pos = static_cast(window_posn); + + if (start_window_pos == 0) + start_window_pos = static_cast(window_size); + + start_window_pos -= outLen; + outData->Write(window, start_window_pos, outLen); + + m_state.window_posn = window_posn; + m_state.R0 = R0; + m_state.R1 = R1; + m_state.R2 = R2; + + // TODO finish intel E8 decoding + /* intel E8 decoding */ + if ((m_state.frames_read++ < 32768) && m_state.intel_filesize != 0) + { + if (outLen <= 6 || m_state.intel_started == 0) + { + m_state.intel_curpos += outLen; + } + else + { + Int dataend = outLen - 10; + auto curpos = static_cast(m_state.intel_curpos); + + m_state.intel_curpos = static_cast(curpos) + outLen; + + while (outData->Position() < dataend) + { + if (outData->ReadByte() != 0xE8) { + curpos++; + continue; + } + } + } + + return -1; + } + + return 0; + } + + public: + inline static std::vector position_base; + inline static std::vector extra_bits; + + private: + LzxState m_state; + + Int MakeDecodeTable(Uint nsyms, Uint nbits, std::vector& length, std::vector& table) { + return 0; + } + void ReadLengths(std::vector const& lens, Uint first, Uint last, BitBuffer& bitbuf) {} + Uint ReadHuffSym(std::vector& table, std::vector& lengths, Uint nsyms, Uint nbits, BitBuffer& bitbuf) { + return 0; + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/content/lzx/decoderstream.cpp b/framework/content/lzx/decoderstream.cpp new file mode 100644 index 0000000..b9276f9 --- /dev/null +++ b/framework/content/lzx/decoderstream.cpp @@ -0,0 +1,40 @@ +#include "decoderstream.hpp" + +namespace xna { + Int LzxDecoderStream::Length() + { + return 0; + } + Long LzxDecoderStream::Position() + { + return 0; + } + void LzxDecoderStream::Close() + { + } + Long LzxDecoderStream::Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) + { + return Long(); + } + Int LzxDecoderStream::Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) + { + return decompressedStream->Read(buffer, bufferLength, offset, count, err); + } + Int LzxDecoderStream::Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) + { + return decompressedStream->Read(buffer, offset, count, err); + } + Int LzxDecoderStream::ReadByte(xna_error_ptr_arg) + { + return Int(); + } + void LzxDecoderStream::Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) + { + } + void LzxDecoderStream::Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) + { + } + void LzxDecoderStream::WriteByte(Byte value, xna_error_ptr_arg) + { + } +} \ No newline at end of file diff --git a/framework/content/lzx/decoderstream.hpp b/framework/content/lzx/decoderstream.hpp new file mode 100644 index 0000000..eac4f41 --- /dev/null +++ b/framework/content/lzx/decoderstream.hpp @@ -0,0 +1,88 @@ +#ifndef XNA_CONTENT_LZX_DECODERSTREAM_HPP +#define XNA_CONTENT_LZX_DECODERSTREAM_HPP + +#include "decoder.hpp" + +namespace xna { + class LzxDecoderStream : public Stream { + public: + LzxDecoderStream(sptr& input, Int decompressedSize, Int compressedSize) { + dec = New(16); + Decompress(input, decompressedSize, compressedSize); + } + + private: + void Decompress(sptr& stream, Int decompressedSize, Int compressedSize) { + //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) + // default window size for XNB encoded files is 64Kb (need 16 bits to represent it) + decompressedStream = New(decompressedSize); + auto startPos = stream->Position(); + auto pos = startPos; + + while (pos - startPos < compressedSize) + { + // the compressed stream is seperated into blocks that will decompress + // into 32Kb or some other size if specified. + // normal, 32Kb output blocks will have a short indicating the size + // of the block before the block starts + // blocks that have a defined output will be preceded by a byte of value + // 0xFF (255), then a short indicating the output size and another + // for the block size + // all shorts for these cases are encoded in big endian order + Int hi = stream->ReadByte(); + Int lo = stream->ReadByte(); + Int block_size = (hi << 8) | lo; + Int frame_size = 0x8000; // frame size is 32Kb by default + // does this block define a frame size? + + if (hi == 0xFF) { + hi = lo; + lo = static_cast(stream->ReadByte()); + frame_size = (hi << 8) | lo; + hi = static_cast(stream->ReadByte()); + lo = static_cast(stream->ReadByte()); + block_size = (hi << 8) | lo; + pos += 5; + } + else + pos += 2; + + // either says there is nothing to decode + if (block_size == 0 || frame_size == 0) + break; + + auto decompressed = reinterpret_pointer_cast(decompressedStream); + dec->Decompress(stream, block_size, decompressed, frame_size); + pos += block_size; + + // reset the position of the input just incase the bit buffer + // read in some unused bytes + stream->Seek(pos, SeekOrigin::Begin); + } + + if (decompressedStream->Position() != decompressedSize) + { + return; + } + + decompressedStream->Seek(0, SeekOrigin::Begin); + } + private: + sptr dec = nullptr; + sptrdecompressedStream = nullptr; + + // Inherited via Stream + Int Length() override; + Long Position() override; + void Close() override; + Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override; + Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + Int Read(std::vector& buffer, Int offset, Int count, xna_error_nullarg) override; + Int ReadByte(xna_error_nullarg) override; + void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + void Write(std::vector const& buffer, Int offset, Int count, xna_error_nullarg) override; + void WriteByte(Byte value, xna_error_nullarg) override; + }; +} + +#endif \ No newline at end of file diff --git a/framework/content/reader.cpp b/framework/content/reader.cpp index c229138..160c74a 100644 --- a/framework/content/reader.cpp +++ b/framework/content/reader.cpp @@ -1,9 +1,58 @@ #include "reader.hpp" #include "manager.hpp" +#include "lzx/decoderstream.hpp" namespace xna { - sptr ContentReader::Create(ContentManager* contentManager, Stream& input, String const& assetName) + sptr ContentReader::Create(ContentManager* contentManager, Stream* input, String const& assetName) { return sptr(); } + + sptr ContentReader::PrepareStream(sptr& input, String const* assetName, Int& graphicsProfile) + { + BinaryReader binaryReader = BinaryReader(input); + + if (binaryReader.ReadByte() != 'X' || binaryReader.ReadByte() != 'N' || binaryReader.ReadByte() != 'B') + return nullptr; + + Int num1 = 0; + if (binaryReader.ReadByte() == 'w') + num1 = binaryReader.ReadUInt16(); + else + return nullptr; + + graphicsProfile = (num1 & 32512) >> 8; + bool flag = false; + + switch (num1 & -32513) + { + case 5: + flag = false; + break; + case 32773: + flag = true; + break; + default: + return nullptr; + } + + const auto num2 = binaryReader.ReadInt32(); + + if ((num2 - 10) > input->Length() - input->Position()) + return nullptr; + + if (!flag) + return input; + + const Int compressedTodo = num2 - 14; + const auto decompressedTodo = binaryReader.ReadInt32(); + + auto lzxStream = New(input, compressedTodo, decompressedTodo); + + return reinterpret_pointer_cast(lzxStream); + } + + Int ContentReader::ReadHeader() { + return Int(); + } } diff --git a/framework/content/reader.hpp b/framework/content/reader.hpp index 7d00001..e7382c4 100644 --- a/framework/content/reader.hpp +++ b/framework/content/reader.hpp @@ -2,14 +2,29 @@ #define XNA_CONTENT_READER_HPP #include "../default.hpp" +#include "../csharp/binary.hpp" namespace xna { - class ContentReader { + class ContentReader : public BinaryReader{ public: - static sptr Create(ContentManager* contentManager, Stream& input, String const& assetName); + static sptr Create(ContentManager* contentManager, Stream* input, String const& assetName); + + template + sptr ReadAsset() { + return nullptr; + } private: - //ContentReader(ContentManager* contentManager, Stream& inut) + ContentReader(ContentManager* contentManager, sptrconst& input, String const& assetName) + : BinaryReader(input), _contentManager(contentManager), _assetName(assetName){} + + static sptr PrepareStream(sptr& input, String const* assetName, Int& graphicsProfile); + + Int ReadHeader(); + + private: + ContentManager* _contentManager = nullptr; + String _assetName; }; } diff --git a/framework/content/typereadermanager.cpp b/framework/content/typereadermanager.cpp new file mode 100644 index 0000000..f5148a5 --- /dev/null +++ b/framework/content/typereadermanager.cpp @@ -0,0 +1,137 @@ +#include "typereadermanager.hpp" +#include "reader.hpp" + +namespace xna { + std::vector ContentTypeReaderManager::ReadTypeManifest(Int typeCount, sptr& contentReader, xna_error_ptr_arg) + { + initMaps(); + + auto contentTypeReaderArray = std::vector(typeCount); + std::vector newTypeReaders; + + for (size_t index = 0; index < typeCount; ++index) + { + auto typeReader = ContentTypeReaderManager::GetTypeReader(contentReader->ReadString(), contentReader, newTypeReaders); + + if (contentReader->ReadInt32() != typeReader->TypeVersion()) { + xna_error_apply(err, XnaErrorCode::BAD_TYPE); + ContentTypeReaderManager::RollbackAddReaders(newTypeReaders); + return std::vector(); + } + + contentTypeReaderArray[index] = typeReader; + + if (!newTypeReaders.empty()) { + auto manager = std::shared_ptr(new ContentTypeReaderManager(contentReader)); + + for (size_t i = 0; i < newTypeReaders.size(); ++i) { + auto& contentTypeReader = newTypeReaders[i]; + contentTypeReader->Initialize(manager); + } + } + } + + return contentTypeReaderArray; + } + + sptr ContentTypeReaderManager::GetTypeReader(String const& targetType, sptr& contentReader, xna_error_ptr_arg) + { + if (targetType.empty()) + return nullptr; + + sptr typeReader = nullptr; + + if (!ContentTypeReaderManager::targetTypeToReader.contains(targetType)) { + xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE); + return nullptr; + } + + return ContentTypeReaderManager::targetTypeToReader[targetType]; + } + + ContentTypeReaderManager::ContentTypeReaderManager(sptr& contentReader) { + initMaps(); + } + + sptr ContentTypeReaderManager::GetTypeReader(String const& readerTypeName, sptr& contentReader, std::vector& newTypeReaders, xna_error_ptr_arg) + { + sptr reader = nullptr; + + if (ContentTypeReaderManager::nameToReader.contains(readerTypeName) || !ContentTypeReaderManager::InstantiateTypeReader(readerTypeName, contentReader, reader)) { + return ContentTypeReaderManager::nameToReader[readerTypeName]; + } + + ContentTypeReaderManager::AddTypeReader(readerTypeName, contentReader, reader, err); + + if (xna_error_haserros(err)) return nullptr; + + newTypeReaders.push_back(reader); + + return reader; + } + + bool ContentTypeReaderManager::InstantiateTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader) + { + if (ContentTypeReaderManager::readerTypeToReader.contains(readerTypeName)) { + reader = ContentTypeReaderManager::readerTypeToReader[readerTypeName]; + ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader }); + return false; + } + + reader = ContentTypeReaderActivador::CreateInstance(readerTypeName); + } + + void ContentTypeReaderManager::AddTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader, xna_error_ptr_arg) + { + auto targetType = reader->TargetType(); + + if (ContentTypeReaderManager::targetTypeToReader.contains(targetType)) { + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return; + } + + ContentTypeReaderManager::targetTypeToReader.insert({ targetType, reader }); + ContentTypeReaderManager::readerTypeToReader.insert({ reader->GetType(), reader }); + ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader }); + } + + void ContentTypeReaderManager::RollbackAddReaders(std::vector>& newTypeReaders) + { + if (newTypeReaders.empty()) + return; + + for (size_t i = 0; i < newTypeReaders.size(); ++i) { + auto newTypeReader = newTypeReaders[i]; + ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::nameToReader, newTypeReader); + ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::targetTypeToReader, newTypeReader); + ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::readerTypeToReader, newTypeReader); + } + } + + void ContentTypeReaderManager::RollbackAddReader(std::map>& dictionary, sptr& reader) { + std::map>::iterator it; + + for (it = dictionary.begin(); it != dictionary.end(); it++) { + if (it->second == reader) { + dictionary.erase(it->first); + it = dictionary.begin(); + } + } + } + + void ContentTypeReaderManager::initMaps() + { + if (targetTypeToReader.empty() && readerTypeToReader.empty()) { + auto typeReader = New(); + auto contentTypeReader = reinterpret_pointer_cast(typeReader); + + targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader}); + readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader}); + } + } + + sptr ObjectReader::Read(ContentReader input, sptr existingInstance) + { + return nullptr; + } +} \ No newline at end of file diff --git a/framework/content/typereadermanager.hpp b/framework/content/typereadermanager.hpp new file mode 100644 index 0000000..3e92bdc --- /dev/null +++ b/framework/content/typereadermanager.hpp @@ -0,0 +1,114 @@ +#ifndef XNA_CONTENT_TYPEREADER_HPP +#define XNA_CONTENT_TYPEREADER_HPP + +#include "../default.hpp" +#include +#include + +namespace xna { + //ContentTypeReader + class ContentTypeReader { + public: + virtual Int TypeVersion() { return 0; } + virtual bool CanDeserializeIntoExistingObject() { return 0; } + virtual void Initialize(sptr& manager) {} + + constexpr String TargetType() { return _targetType; } + + virtual String GetType() { return "ContentTypeReader"; } + + protected: + ContentTypeReader(String targetType) : _targetType(targetType) { + } + + virtual sptr Read(ContentReader input, sptr existingInstance) = 0; + + private: + String _targetType = "contentTypeReader"; + }; + + //ContentTypeReaderActivador + class ContentTypeReaderActivador { + public: + using Activador = sptr(*)(); + + static sptr CreateInstance(String const& readerTypeName) { + if (!activators.contains(readerTypeName)) + return nullptr; + + auto activador = activators[readerTypeName]; + + if (!activador) return nullptr; + + return activador(); + } + + static void SetActivador(String const& readerTypeName, Activador activador) { + if (!activators.contains(readerTypeName)) + activators.insert({ readerTypeName, activador }); + } + + private: + inline static std::map activators = + std::map(); + + ContentTypeReaderActivador(); + ContentTypeReaderActivador(ContentTypeReaderActivador&&); + ContentTypeReaderActivador(ContentTypeReaderActivador&); + }; + + using PContentTypeReader = sptr; + + //ContentTypeReaderManager + class ContentTypeReaderManager { + public: + static std::vector ReadTypeManifest(Int typeCount, sptr& contentReader, xna_error_nullarg); + static sptr GetTypeReader(String const& targetType, sptr& contentReader, xna_error_nullarg); + + inline sptr GetTypeReader(String const& targetType, xna_error_nullarg) { + return ContentTypeReaderManager::GetTypeReader(targetType, this->contentReader, err); + } + + inline static bool ContainsTypeReader(String const& targetType) { + return ContentTypeReaderManager::targetTypeToReader.contains(targetType); + } + + private: + ContentTypeReaderManager(sptr& contentReader); + static sptr GetTypeReader(String const& readerTypeName, sptr& contentReader, std::vector& newTypeReaders, xna_error_nullarg); + static bool InstantiateTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader); + static void AddTypeReader(String const& readerTypeName, sptr& contentReader, sptr& reader, xna_error_nullarg); + static void RollbackAddReaders(std::vector>& newTypeReaders); + static void RollbackAddReader(std::map>& dictionary, sptr& reader); + + + private: + sptr contentReader = nullptr; + + inline static std::map nameToReader = std::map(); + inline static std::map targetTypeToReader = std::map(); + inline static std::map readerTypeToReader = std::map(); + + static void initMaps(); + }; + + //ObjectReader + class ObjectReader : public ContentTypeReader { + public: + ObjectReader() : ContentTypeReader("object"){ + ContentTypeReaderActivador::SetActivador("object", []() -> sptr { + auto obj = New (); + return reinterpret_pointer_cast(obj); + }); + } + + // Inherited via ContentTypeReader + sptr Read(ContentReader input, sptr existingInstance) override; + + String GetType() override { + return "ObjectReader"; + } + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/binary.cpp b/framework/csharp/binary.cpp index 20adc25..03c60ce 100644 --- a/framework/csharp/binary.cpp +++ b/framework/csharp/binary.cpp @@ -1,4 +1,5 @@ #include "binary.hpp" +#include "../csharp/buffer.hpp" namespace xna { Int BinaryReader::PeekChar(xna_error_ptr_arg) @@ -6,7 +7,7 @@ namespace xna { if (!stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); return -1; - } + } const auto position = stream->Position(); const auto num = Read(err); @@ -267,7 +268,7 @@ namespace xna { { Int num1 = 0; Long num2 = 0; - Long num3 = stream->Position(); + Long num3 = stream->Position(); if (charBytes.empty()) charBytes.resize(128); @@ -352,7 +353,7 @@ namespace xna { } } - Int BinaryReader::InternalReadChars(char* buffer, size_t bufferSize, Int index, Int count, xna_error_ptr_arg) + Int BinaryReader::InternalReadChars(Char* buffer, size_t bufferSize, size_t index, size_t count, xna_error_ptr_arg) { auto charCount = count; @@ -371,18 +372,18 @@ namespace xna { if (count1 > 128) count1 = 128; - Int num = 0; + Int position = 0; Int byteCount; std::vector numArray; - byteCount = stream->Read(charBytes, 0, count1); + byteCount = stream->Read(charBytes, 0, static_cast(count1), err); numArray = charBytes; if (byteCount == 0) - return count - charCount; + return static_cast(count - charCount); - if (num < 0 || byteCount < 0 || (num + byteCount) > numArray.size()) { + if (position < 0 || byteCount < 0 || (position + byteCount) > numArray.size()) { xna_error_apply(err, XnaErrorCode::ARGUMENT_OUT_OF_RANGE); return -1; } @@ -393,22 +394,28 @@ namespace xna { } auto data = reinterpret_cast(charBytes.data()); - const auto result = std::string((data + num), (data + num) + byteCount); + auto pChars = reinterpret_cast(buffer); + + //const auto result = std::string((data + position), (pChars + index) + byteCount); + const auto result = std::string((data + position), (data + position) + byteCount); + Buffer::BlockCopy(result.c_str(), position, pChars, index, byteCount); - const auto chars = result.size(); + buffer = reinterpret_cast(pChars); - charCount -= static_cast(chars); - index += static_cast(chars); + const auto chars = static_cast(result.size()); + + charCount -= chars; + index += chars; } - return count - charCount; + return static_cast(count - charCount); } Long BinaryWriter::Seek(Int offset, SeekOrigin origin, xna_error_ptr_arg) { if (!_stream) { xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); - return - 1; + return -1; } return _stream->Seek(offset, origin); @@ -648,4 +655,55 @@ namespace xna { _buffer[7] = static_cast(value >> 56); _stream->Write(_buffer, 0, 8); } + + Int BinaryReader::Read7BitEncodedInt(xna_error_ptr_arg) + { + Int num1 = 0; + Int num2 = 0; + + while (num2 != 35) { + auto num3 = ReadByte(err); + + if (xna_error_haserros(err)) + return -1; + + num1 |= (static_cast(num3) & static_cast(SbyteMaxValue)) << num2; + num2 += 7; + + if ((static_cast(num3) & 128) == 0) + return num1; + } + + xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); + return -1; + } + + Int BinaryReader::Read(std::vector& buffer, size_t index, size_t count, xna_error_ptr_arg) + { + return InternalReadChars(buffer.data(), buffer.size(), index, count, err); + } + + std::vector BinaryReader::ReadBytes(size_t count, xna_error_ptr_arg) + { + std::vector result(count); + Int numRead = 0; + + do { + const auto n = stream->Read(result, static_cast(numRead), static_cast(count), err); + + if (n == 0) + break; + + numRead += n; + count -= n; + } while (count > 0); + + if (numRead != result.size()) { + std::vector copy(numRead); + Buffer::BlockCopy(result.data(), 0, copy.data(), 0, numRead); + result = copy; + } + + return result; + } } \ No newline at end of file diff --git a/framework/csharp/binary.hpp b/framework/csharp/binary.hpp index a8ad428..b06249c 100644 --- a/framework/csharp/binary.hpp +++ b/framework/csharp/binary.hpp @@ -7,7 +7,7 @@ namespace xna { class BinaryReader { public: - BinaryReader(Stream* const& input) { + BinaryReader(sptr const& input) { stream = input; buffer = std::vector(bufferLength); } @@ -28,18 +28,14 @@ namespace xna { double ReadDouble(xna_error_nullarg); std::string ReadString(xna_error_nullarg); - Int Read(std::vector& buffer, size_t index, size_t count, xna_error_nullarg) { - return -1; - } + Int Read(std::vector& buffer, size_t index, size_t count, xna_error_nullarg); - std::vector ReadBytes(size_t count, xna_error_nullarg) { - return std::vector(); - } + std::vector ReadBytes(size_t count, xna_error_nullarg); private: static constexpr int maxCharBytesSize = 128; static constexpr int bufferLength = 16; - Stream* stream = nullptr; + sptr stream = nullptr; std::vector charBytes; std::vector singleChar; std::vector buffer; @@ -51,34 +47,14 @@ namespace xna { void FillBuffer(Int numBytes, xna_error_nullarg); - Int Read7BitEncodedInt(xna_error_nullarg) - { - Int num1 = 0; - Int num2 = 0; + Int Read7BitEncodedInt(xna_error_nullarg); - while (num2 != 35) { - auto num3 = ReadByte(err); - - if (xna_error_haserros(err)) - return -1; - - num1 |= (static_cast(num3) & static_cast(SbyteMaxValue)) << num2; - num2 += 7; - - if ((static_cast(num3) & 128) == 0) - return num1; - } - - xna_error_apply(err, XnaErrorCode::INVALID_OPERATION); - return -1; - } - - Int InternalReadChars(char* buffer, size_t bufferSize, Int index, Int count, xna_error_nullarg); + Int InternalReadChars(Char* buffer, size_t bufferSize, size_t index, size_t count, xna_error_nullarg); }; class BinaryWriter { public: - BinaryWriter(Stream* stream) : _stream(stream), _buffer(16) { + BinaryWriter(sptr const& stream) : _stream(stream), _buffer(16) { } Long Seek(Int offset, SeekOrigin origin, xna_error_nullarg); @@ -103,7 +79,7 @@ namespace xna { void Write(const char* _string, size_t stringLength, xna_error_nullarg); public: - Stream* _stream; + sptr _stream = nullptr; private: std::vector _buffer; diff --git a/framework/csharp/buffer.hpp b/framework/csharp/buffer.hpp index 6c5775f..e2a8e75 100644 --- a/framework/csharp/buffer.hpp +++ b/framework/csharp/buffer.hpp @@ -8,12 +8,7 @@ namespace xna { class Buffer { public: template - static void BlockCopy( - T const* src, - rsize_t srcOffset, - T* dst, - rsize_t dstOffset, - rsize_t byteCount) { + static void BlockCopy(T const* src, rsize_t srcOffset, T* dst, rsize_t dstOffset, rsize_t byteCount) { memmove_s(dst + dstOffset, byteCount, src + srcOffset, byteCount); } diff --git a/framework/csharp/object.cpp b/framework/csharp/object.cpp new file mode 100644 index 0000000..067c9ce --- /dev/null +++ b/framework/csharp/object.cpp @@ -0,0 +1,13 @@ +#include "object.hpp" +#include "type.hpp" + +namespace xna { + sptr Object::GetType() + { + auto type = New(); + type->FullName = "Object"; + type->Namespace = "xna"; + type->IsClass = true; + return type; + } +} \ No newline at end of file diff --git a/framework/csharp/object.hpp b/framework/csharp/object.hpp new file mode 100644 index 0000000..a83503c --- /dev/null +++ b/framework/csharp/object.hpp @@ -0,0 +1,13 @@ +#ifndef XNA_CSHARP_OBJECT_HPP +#define XNA_CSHARP_OBJECT_HPP + +#include "../default.hpp" + +namespace xna { + class Object { + public: + virtual sptr GetType(); + }; +} + +#endif \ No newline at end of file diff --git a/framework/csharp/stream.hpp b/framework/csharp/stream.hpp index 4b3fad6..865eb73 100644 --- a/framework/csharp/stream.hpp +++ b/framework/csharp/stream.hpp @@ -10,6 +10,7 @@ namespace xna { class Stream { public: + virtual ~Stream(){} virtual Int Length() = 0; virtual Long Position() = 0; virtual void Close() = 0; @@ -47,13 +48,13 @@ namespace xna { _buffer = std::vector(); } - virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) override; - virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; - virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) override; - virtual Int ReadByte(xna_error_ptr_arg) override; - virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; - virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) override; - virtual void WriteByte(Byte value, xna_error_ptr_arg) override; + virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override; + virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_nullarg) override; + virtual Int ReadByte(xna_error_nullarg) override; + virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_nullarg) override; + virtual void WriteByte(Byte value, xna_error_nullarg) override; public: Int _position{ 0 }; @@ -108,13 +109,13 @@ namespace xna { _fstream.close(); } - virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_ptr_arg) override; - virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; - virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_ptr_arg) override; - virtual Int ReadByte(xna_error_ptr_arg) override; - virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_ptr_arg) override; - virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_ptr_arg) override; - virtual void WriteByte(Byte value, xna_error_ptr_arg) override; + virtual Long Seek(Long offset, SeekOrigin const& origin, xna_error_nullarg) override; + virtual Int Read(Byte* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + virtual Int Read(std::vector& buffer, Int offset, Int count, xna_error_nullarg) override; + virtual Int ReadByte(xna_error_nullarg) override; + virtual void Write(Byte const* buffer, Int bufferLength, Int offset, Int count, xna_error_nullarg) override; + virtual void Write(std::vector const& buffer, Int offset, Int count, xna_error_nullarg) override; + virtual void WriteByte(Byte value, xna_error_nullarg) override; public: std::streampos _filesize{ 0 }; diff --git a/framework/csharp/type.hpp b/framework/csharp/type.hpp new file mode 100644 index 0000000..3fba755 --- /dev/null +++ b/framework/csharp/type.hpp @@ -0,0 +1,32 @@ +#ifndef XNA_CSHARP_TYPE_HPP +#define XNA_CSHARP_TYPE_HPP + +#include "../default.hpp" +#include "object.hpp" + +namespace xna { + class Type { + public: + String Namespace; + String FullName; + bool IsInterface{ false }; + bool IsArray{ false }; + bool IsPointer{ false }; + bool IsClass{ false }; + bool IsCOMObject{ false }; + bool IsEnum{ false }; + bool IsValueType{ false }; + }; + + template + inline sptr typeof(T const& obj) { + auto obj = reinterpret_cast(&obj); + + if (!obj) + return nullptr; + + return obj->GetType(); + } +} + +#endif \ No newline at end of file diff --git a/framework/forward.hpp b/framework/forward.hpp index 4df05f8..e5d3eaf 100644 --- a/framework/forward.hpp +++ b/framework/forward.hpp @@ -15,10 +15,14 @@ namespace xna { class Stream; class FileStream; class MemoryStream; + class Object; + class Type; //Content class ContentManager; class ContentReader; + class ContentTypeReader; + class ContentTypeReaderManager; //Framework class BoundingBox; diff --git a/framework/xna.cpp b/framework/xna.cpp index 615e12d..5cbd3f5 100644 --- a/framework/xna.cpp +++ b/framework/xna.cpp @@ -18,7 +18,8 @@ namespace xna { contentManager = New("Content"); //const auto s = contentManager->_path.string(); // const auto current = std::filesystem::current_path(); - auto s = contentManager->OpenStream("file"); + //auto s = contentManager->OpenStream("file"); + //DecompressStream::Decompress(); } void Initialize() override { @@ -30,7 +31,7 @@ namespace xna { spriteBatch = New(*_graphicsDevice); XnaErrorCode err; - texture = Texture2D::FromStream(*_graphicsDevice, "D:\\sprite.jpg", &err); + texture = Texture2D::FromStream(*_graphicsDevice, "D:\\sprite.jpg", &err); Game::LoadContent(); } diff --git a/framework/xna.h b/framework/xna.h index e81e780..8d73ac0 100644 --- a/framework/xna.h +++ b/framework/xna.h @@ -24,5 +24,6 @@ #include "Windows.h" #include #include "content/manager.hpp" +#include "content/decstream.hpp" // TODO: Reference additional headers your program requires here. diff --git a/framework/xnaerror.hpp b/framework/xnaerror.hpp index bd0a11b..44b69d2 100644 --- a/framework/xnaerror.hpp +++ b/framework/xnaerror.hpp @@ -13,7 +13,8 @@ namespace xna { BAD_CAST, STREAM_ERROR, UNINTIALIZED_RESOURCE, - END_OF_FILE + END_OF_FILE, + BAD_TYPE }; inline void xna_error_apply(XnaErrorCode* source, XnaErrorCode const& value) {