metaforce/Runtime/IOStreams.cpp

132 lines
3.3 KiB
C++
Raw Normal View History

2015-08-23 23:58:07 +00:00
#include "IOStreams.hpp"
#include "CMemory.hpp"
2016-03-04 23:04:53 +00:00
namespace urde
2015-08-23 23:58:07 +00:00
{
2016-03-19 19:19:43 +00:00
/*!
* \brief CBitStreamReader::ReadBit
* Reads and decodes an encoded value from a bitstream.
* \param bitCount How many bits to read
* \return s32 The encoded value
*/
s32 CBitStreamReader::ReadEncoded(u32 bitCount)
{
2016-03-19 19:19:43 +00:00
s32 ret = 0;
if (bitCount < x20_bitOffset)
{
2016-03-19 19:19:43 +00:00
u32 diff = 0x20 - bitCount;
u32 baseVal = -1;
if (x20_bitOffset != 0x20)
baseVal = (1 << bitCount) - 1;
x20_bitOffset -= bitCount;
ret = baseVal & (x1c_val >> diff);
x1c_val <<= bitCount;
}
else
{
2016-03-19 19:19:43 +00:00
u32 diff = bitCount - x20_bitOffset;
u32 baseVal = -1;
if (x20_bitOffset != 32)
baseVal = (1 << x20_bitOffset) - 1;
2016-03-20 04:10:29 +00:00
baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff;
2016-03-19 19:19:43 +00:00
x20_bitOffset = 0;
2016-03-23 20:38:01 +00:00
u32 bit = diff & 7;
u32 count = (diff >> 3) + ((-bit | bit) >> 31);
readUBytesToBuf(&x1c_val, count);
2016-03-19 19:19:43 +00:00
/* The game uses Big Endian, which doesn't work for us */
/* Little Endian sucks */
athena::utility::BigUint32(x1c_val);
2016-03-19 19:19:43 +00:00
u32 baseVal2 = -1;
if (diff != 32)
baseVal2 = (1 << diff) - 1;
2016-03-19 19:19:43 +00:00
ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset;
2016-03-23 20:38:01 +00:00
x20_bitOffset = (count << 3) - diff;
2016-03-19 19:19:43 +00:00
x1c_val <<= diff;
}
return ret;
}
2016-03-20 04:10:29 +00:00
void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount)
{
if (x18_bitOffset >= bitCount)
{
int baseVal = -1;
if (bitCount != 32)
baseVal = (1 << bitCount) - 1;
x14_val |= (val & baseVal) << (x18_bitOffset - bitCount);
x18_bitOffset -= bitCount;
}
else
{
u32 diff = bitCount - x18_bitOffset;
u32 baseVal = -1;
if (x18_bitOffset != 32)
baseVal = (1 << x18_bitOffset) - 1;
x14_val |= (val >> diff) & baseVal;
x18_bitOffset = 0;
u32 tmp = x14_val;
athena::utility::BigUint32(tmp);
2016-03-23 20:38:01 +00:00
u32 bit = (32 - x18_bitOffset) & 7;
u32 count = ((32 - x18_bitOffset) >> 3) + ((-bit | bit) >> 31);
writeBytes(&tmp, count);
2016-03-20 04:10:29 +00:00
u32 rem = 32 - diff;
baseVal = -1;
if (diff != 32)
baseVal = (1 << diff) - 1;
x14_val = (val & baseVal) << rem;
x18_bitOffset -= diff;
}
}
2015-08-23 23:58:07 +00:00
class CZipSupport
{
public:
static void* Alloc(void*, u32 c, u32 n)
{
return new u8[c*n];
2015-08-23 23:58:07 +00:00
}
static void Free(void*, void* buf)
{
delete[] static_cast<u8*>(buf);
}
};
CZipInputStream::CZipInputStream(std::unique_ptr<CInputStream>&& strm)
: x24_compBuf(new u8[4096]), x28_strm(std::move(strm))
2015-08-23 23:58:07 +00:00
{
x30_zstrm.next_in = x24_compBuf.get();
x30_zstrm.avail_in = 0;
x30_zstrm.zalloc = CZipSupport::Alloc;
x30_zstrm.zfree = CZipSupport::Free;
inflateInit(&x30_zstrm);
}
CZipInputStream::~CZipInputStream()
{
inflateEnd(&x30_zstrm);
}
atUint64 CZipInputStream::readUBytesToBuf(void *buf, atUint64 len)
{
x30_zstrm.next_out = (Bytef*)buf;
x30_zstrm.avail_out = len;
if (!x30_zstrm.avail_in)
{
atUint64 readSz = x28_strm->readUBytesToBuf(x24_compBuf.get(), 4096);
x30_zstrm.avail_in = readSz;
x30_zstrm.next_in = x24_compBuf.get();
}
inflate(&x30_zstrm, Z_NO_FLUSH);
return x30_zstrm.total_out;
}
}