mirror of https://github.com/AxioDL/metaforce.git
Initial proper CTexture RE, fix configuration corruption
This commit is contained in:
parent
5e7b8ebacf
commit
b0a711d5e2
|
@ -129,10 +129,12 @@ void CVarManager::serialize() {
|
||||||
auto container = loadCVars(filename);
|
auto container = loadCVars(filename);
|
||||||
|
|
||||||
u32 minLength = 0;
|
u32 minLength = 0;
|
||||||
|
bool write = false;
|
||||||
for (const auto& pair : m_cvars) {
|
for (const auto& pair : m_cvars) {
|
||||||
const auto& cvar = pair.second;
|
const auto& cvar = pair.second;
|
||||||
|
|
||||||
if (cvar->isArchive() || (cvar->isInternalArchivable() && cvar->wasDeserialized() && !cvar->hasDefaultValue())) {
|
if (cvar->isArchive() || (cvar->isInternalArchivable() && cvar->wasDeserialized() && !cvar->hasDefaultValue())) {
|
||||||
|
write = true;
|
||||||
/* Look for an existing CVar in the file... */
|
/* Look for an existing CVar in the file... */
|
||||||
auto serialized =
|
auto serialized =
|
||||||
std::find_if(container.begin(), container.end(), [&cvar](const auto& c) { return c.m_name == cvar->name(); });
|
std::find_if(container.begin(), container.end(), [&cvar](const auto& c) { return c.m_name == cvar->name(); });
|
||||||
|
@ -143,23 +145,34 @@ void CVarManager::serialize() {
|
||||||
/* Store this value as a new CVar in the config */
|
/* Store this value as a new CVar in the config */
|
||||||
container.emplace_back(StoreCVar::CVar{std::string(cvar->name()), cvar->value()});
|
container.emplace_back(StoreCVar::CVar{std::string(cvar->name()), cvar->value()});
|
||||||
}
|
}
|
||||||
/* Compute length needed for this cvar */
|
|
||||||
minLength += cvar->name().length() + cvar->value().length() + 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Compute length needed for all cvars */
|
||||||
|
std::for_each(container.cbegin(), container.cend(),
|
||||||
|
[&minLength](const auto& cvar) { minLength += cvar.m_name.length() + cvar.m_value.length() + 2; });
|
||||||
|
/* Only write the CVars if any have been modified */
|
||||||
|
if (!write) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate enough space to write all the strings with some space to spare
|
// Allocate enough space to write all the strings with some space to spare
|
||||||
const auto requiredLen = minLength + (4 * container.size());
|
const auto requiredLen = minLength + (4 * container.size());
|
||||||
std::unique_ptr<u8[]> workBuf(new u8[requiredLen]);
|
std::unique_ptr<u8[]> workBuf(new u8[requiredLen]);
|
||||||
CMemoryStreamOut memOut(workBuf.get(), requiredLen);
|
CMemoryStreamOut memOut(workBuf.get(), requiredLen, CMemoryStreamOut::EOwnerShip::NotOwned, 32);
|
||||||
CTextOutStream textOut(memOut);
|
CTextOutStream textOut(memOut);
|
||||||
for (const auto& cvar : container) {
|
for (const auto& cvar : container) {
|
||||||
textOut.WriteString(fmt::format(FMT_STRING("{}: {}"), cvar.m_name, cvar.m_value));
|
auto str = fmt::format(FMT_STRING("{}: {}"), cvar.m_name, cvar.m_value);
|
||||||
|
textOut.WriteString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* file = fopen(filename.c_str(), "wbe");
|
auto* file = fopen(filename.c_str(), "wbe");
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
fwrite(workBuf.get(), 1, memOut.GetWritePosition(), file);
|
u32 writeLen = memOut.GetWritePosition();
|
||||||
|
u32 offset = 0;
|
||||||
|
while (offset < writeLen) {
|
||||||
|
offset += fwrite(workBuf.get() + offset, 1, writeLen - offset, file);
|
||||||
|
}
|
||||||
|
fflush(file);
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,7 @@ struct SClipScreenRect {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ETexelFormat {
|
enum class ETexelFormat {
|
||||||
|
Invalid = -1,
|
||||||
I4 = 0,
|
I4 = 0,
|
||||||
I8 = 1,
|
I8 = 1,
|
||||||
IA4 = 2,
|
IA4 = 2,
|
||||||
|
|
|
@ -10,6 +10,7 @@ set(GRAPHICS_SOURCES
|
||||||
CLineRenderer.hpp CLineRenderer.cpp
|
CLineRenderer.hpp CLineRenderer.cpp
|
||||||
CMetroidModelInstance.cpp CMetroidModelInstance.hpp
|
CMetroidModelInstance.cpp CMetroidModelInstance.hpp
|
||||||
CLight.hpp CLight.cpp
|
CLight.hpp CLight.cpp
|
||||||
|
DolphinCTexture.hpp DolphinCTexture.cpp
|
||||||
CTexture.hpp CTextureBoo.cpp
|
CTexture.hpp CTextureBoo.cpp
|
||||||
CModel.cpp CModel.hpp
|
CModel.cpp CModel.hpp
|
||||||
CSkinnedModel.hpp CSkinnedModel.cpp
|
CSkinnedModel.hpp CSkinnedModel.cpp
|
||||||
|
|
|
@ -704,6 +704,8 @@ static std::string_view TextureFormatString(ETexelFormat format) {
|
||||||
return "CMPRPC"sv;
|
return "CMPRPC"sv;
|
||||||
case ETexelFormat::CMPRPCA:
|
case ETexelFormat::CMPRPCA:
|
||||||
return "CMPRPCA"sv;
|
return "CMPRPCA"sv;
|
||||||
|
default:
|
||||||
|
return "Invalid"sv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
#include "DolphinCTexture.hpp"
|
||||||
|
|
||||||
|
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, bool mipmap, u8 max_lod) {
|
||||||
|
s32 shiftX = 0;
|
||||||
|
s32 shiftY = 0;
|
||||||
|
switch (format) {
|
||||||
|
case GX::TF_I4:
|
||||||
|
case GX::TF_C4:
|
||||||
|
case GX::TF_CMPR:
|
||||||
|
case GX::CTF_R4:
|
||||||
|
case GX::CTF_Z4:
|
||||||
|
shiftX = 3;
|
||||||
|
shiftY = 3;
|
||||||
|
break;
|
||||||
|
case GX::TF_I8:
|
||||||
|
case GX::TF_IA4:
|
||||||
|
case GX::TF_C8:
|
||||||
|
case GX::TF_Z8:
|
||||||
|
case GX::CTF_RA4:
|
||||||
|
case GX::CTF_A8:
|
||||||
|
case GX::CTF_R8:
|
||||||
|
case GX::CTF_G8:
|
||||||
|
case GX::CTF_B8:
|
||||||
|
case GX::CTF_Z8M:
|
||||||
|
case GX::CTF_Z8L:
|
||||||
|
shiftX = 3;
|
||||||
|
shiftY = 2;
|
||||||
|
break;
|
||||||
|
case GX::TF_IA8:
|
||||||
|
case GX::TF_RGB565:
|
||||||
|
case GX::TF_RGB5A3:
|
||||||
|
case GX::TF_RGBA8:
|
||||||
|
case GX::TF_C14X2:
|
||||||
|
case GX::TF_Z16:
|
||||||
|
case GX::TF_Z24X8:
|
||||||
|
case GX::CTF_RA8:
|
||||||
|
case GX::CTF_RG8:
|
||||||
|
case GX::CTF_GB8:
|
||||||
|
case GX::CTF_Z16L:
|
||||||
|
shiftX = 2;
|
||||||
|
shiftY = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
u32 bitSize = format == GX::TF_RGBA8 || format == GX::TF_Z24X8 ? 64 : 32;
|
||||||
|
u32 bufLen = 0;
|
||||||
|
if (mipmap) {
|
||||||
|
while (max_lod != 0) {
|
||||||
|
const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX);
|
||||||
|
const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY);
|
||||||
|
bufLen += bitSize * tileX * tileY;
|
||||||
|
|
||||||
|
if (width == 1 && height == 1) {
|
||||||
|
return bufLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = (width < 2) ? 1 : width / 2;
|
||||||
|
height = (height < 2) ? 1 : height / 2;
|
||||||
|
--max_lod;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const u32 tileX = ((width + (1 << shiftX) - 1) >> shiftX);
|
||||||
|
const u32 tileY = ((height + (1 << shiftY) - 1) >> shiftY);
|
||||||
|
bufLen = bitSize * tileX * tileY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufLen;
|
||||||
|
}
|
||||||
|
namespace metaforce::WIP {
|
||||||
|
|
||||||
|
CTexture::CTexture(ETexelFormat fmt, s16 w, s16 h, s32 mips)
|
||||||
|
: x0_fmt(fmt)
|
||||||
|
, x4_w(w)
|
||||||
|
, x6_h(h)
|
||||||
|
, x8_mips(mips)
|
||||||
|
, x9_bitsPerPixel(TexelFormatBitsPerPixel(fmt))
|
||||||
|
, x64_frameAllocated(sCurrentFrameCount) {
|
||||||
|
InitBitmapBuffers(fmt, w, h, mips);
|
||||||
|
InitTextureObjs();
|
||||||
|
}
|
||||||
|
|
||||||
|
CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) {
|
||||||
|
x64_frameAllocated = sCurrentFrameCount;
|
||||||
|
x0_fmt = ETexelFormat(in.ReadLong());
|
||||||
|
x4_w = in.ReadShort();
|
||||||
|
x6_h = in.ReadShort();
|
||||||
|
x8_mips = in.ReadLong();
|
||||||
|
|
||||||
|
bool hasPalette = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2);
|
||||||
|
if (hasPalette) {
|
||||||
|
x10_graphicsPalette = std::make_unique<CGraphicsPalette>(in);
|
||||||
|
xa_25_hasPalette = true;
|
||||||
|
}
|
||||||
|
x9_bitsPerPixel = TexelFormatBitsPerPixel(x0_fmt);
|
||||||
|
InitBitmapBuffers(x0_fmt, x4_w, x6_h, x8_mips);
|
||||||
|
u32 bufLen = 0;
|
||||||
|
if (x8_mips > 0) {
|
||||||
|
for (u32 i = 0; i < x8_mips; ++i) {
|
||||||
|
u32 curMip = i & 3;
|
||||||
|
const u32 width = ROUND_UP_4(x4_w >> curMip);
|
||||||
|
const u32 height = ROUND_UP_4(x6_h >> curMip);
|
||||||
|
bufLen += (width * height * x9_bitsPerPixel) / 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0, len = 0; i < bufLen; i += len) {
|
||||||
|
len = bufLen - i;
|
||||||
|
if (len > 256) {
|
||||||
|
len = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.Get(x44_aramToken_x4_buff.get() + i, len);
|
||||||
|
//DCFlushRangeNoSync(x44_aramToken_x4_buff.get() + i, ROUND_UP_32(len));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sMangleMips) {
|
||||||
|
for (u32 i = 0; i < x8_mips; ++i) {
|
||||||
|
MangleMipmap(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InitTextureObjs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexture::InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips) {
|
||||||
|
switch (fmt) {
|
||||||
|
case ETexelFormat::I4:
|
||||||
|
x18_gxFormat = GX::TF_I4;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::I8:
|
||||||
|
x18_gxFormat = GX::TF_I8;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::IA4:
|
||||||
|
x18_gxFormat = GX::TF_IA4;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::IA8:
|
||||||
|
x18_gxFormat = GX::TF_IA8;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::C4:
|
||||||
|
x1c_gxCIFormat = GX::TF_C4;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::C8:
|
||||||
|
x1c_gxCIFormat = GX::TF_C8;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::C14X2:
|
||||||
|
x1c_gxCIFormat = GX::TF_C14X2;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::RGB565:
|
||||||
|
x18_gxFormat = GX::TF_RGB565;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::RGB5A3:
|
||||||
|
x18_gxFormat = GX::TF_RGB5A3;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::RGBA8:
|
||||||
|
x18_gxFormat = GX::TF_RGBA8;
|
||||||
|
break;
|
||||||
|
case ETexelFormat::CMPR:
|
||||||
|
x18_gxFormat = GX::TF_CMPR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 format = (x0_fmt == ETexelFormat::C4 || x0_fmt == ETexelFormat::C8 || x0_fmt == ETexelFormat::C14X2)
|
||||||
|
? x1c_gxCIFormat
|
||||||
|
: x18_gxFormat;
|
||||||
|
|
||||||
|
/* I have no idea what they're doing with that last argument... */
|
||||||
|
xc_memoryAllocated = GXGetTexBufferSize(width, height, format, mips > 1, static_cast<u8>(mips > 1) & 11);
|
||||||
|
x44_aramToken_x4_buff.reset(new u8[xc_memoryAllocated]);
|
||||||
|
/*x44_aramToken.PostConstruct(buf, xc_memoryAllocated, 1);*/
|
||||||
|
CountMemory();
|
||||||
|
}
|
||||||
|
void CTexture::InitTextureObjs() {}
|
||||||
|
|
||||||
|
void CTexture::CountMemory() {
|
||||||
|
if (xa_28_counted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xa_28_counted = true;
|
||||||
|
sTotalAllocatedMemory += xc_memoryAllocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexture::MangleMipmap(u32 mip) {
|
||||||
|
// TODO(phil): Mangle mipmap
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CTexture::TexelFormatBitsPerPixel(ETexelFormat fmt) {
|
||||||
|
switch (fmt) {
|
||||||
|
case ETexelFormat::I4:
|
||||||
|
case ETexelFormat::C4:
|
||||||
|
case ETexelFormat::CMPR:
|
||||||
|
return 4;
|
||||||
|
case ETexelFormat::I8:
|
||||||
|
case ETexelFormat::IA4:
|
||||||
|
case ETexelFormat::C8:
|
||||||
|
return 8;
|
||||||
|
case ETexelFormat::IA8:
|
||||||
|
case ETexelFormat::C14X2:
|
||||||
|
case ETexelFormat::RGB565:
|
||||||
|
case ETexelFormat::RGB5A3:
|
||||||
|
return 16;
|
||||||
|
case ETexelFormat::RGBA8:
|
||||||
|
return 32;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CTexture::sCurrentFrameCount = 0;
|
||||||
|
u32 CTexture::sTotalAllocatedMemory = 0;
|
||||||
|
} // namespace metaforce::WIP
|
|
@ -0,0 +1,75 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Runtime/Graphics/CGraphics.hpp"
|
||||||
|
#include "Runtime/Graphics/CGraphicsPalette.hpp"
|
||||||
|
#include "Runtime/Streams/CInputStream.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace metaforce::WIP {
|
||||||
|
class CTexture {
|
||||||
|
class CDumpedBitmapDataReloader {
|
||||||
|
int x0_;
|
||||||
|
u32 x4_;
|
||||||
|
int x8_;
|
||||||
|
u32 xc_;
|
||||||
|
bool x10_;
|
||||||
|
int x14_;
|
||||||
|
void* x18_;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
enum class EClampMode {
|
||||||
|
Clamp,
|
||||||
|
Repeat,
|
||||||
|
Mirror,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EAutoMipmap {
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EBlackKey {
|
||||||
|
Zero,
|
||||||
|
One
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr bool sMangleMips = false;
|
||||||
|
static u32 sCurrentFrameCount;
|
||||||
|
static u32 sTotalAllocatedMemory;
|
||||||
|
ETexelFormat x0_fmt = ETexelFormat::Invalid;
|
||||||
|
u16 x4_w = 0;
|
||||||
|
u16 x6_h = 0;
|
||||||
|
u8 x8_mips = 0;
|
||||||
|
u8 x9_bitsPerPixel = 0;
|
||||||
|
bool xa_24_ : 1 = false;
|
||||||
|
bool xa_25_hasPalette : 1 = false;
|
||||||
|
bool xa_26_ : 1 = false;
|
||||||
|
bool xa_27_ : 1 = true;
|
||||||
|
bool xa_28_counted : 1 = false;
|
||||||
|
bool xa_29_ : 1 = false;
|
||||||
|
u32 xc_memoryAllocated = 0;
|
||||||
|
std::unique_ptr<CGraphicsPalette> x10_graphicsPalette;
|
||||||
|
std::unique_ptr<CDumpedBitmapDataReloader> x14_bitmapReloader;
|
||||||
|
u32 x18_gxFormat = GX::TF_RGB565;
|
||||||
|
u32 x1c_gxCIFormat = GX::TF_C8;
|
||||||
|
/* GXTexObj x20_texObj */
|
||||||
|
EClampMode x40_clampMode = EClampMode::Repeat;
|
||||||
|
/* CARAMToken x44_aramToken */
|
||||||
|
std::unique_ptr<u8[]> x44_aramToken_x4_buff;
|
||||||
|
u32 x64_frameAllocated{};
|
||||||
|
|
||||||
|
void InitBitmapBuffers(ETexelFormat fmt, s16 width, s16 height, s32 mips);
|
||||||
|
void InitTextureObjs();
|
||||||
|
void CountMemory();
|
||||||
|
void MangleMipmap(u32 mip);
|
||||||
|
static u32 TexelFormatBitsPerPixel(ETexelFormat fmt);
|
||||||
|
public:
|
||||||
|
CTexture(ETexelFormat, s16, s16, s32);
|
||||||
|
CTexture(CInputStream& in, EAutoMipmap automip = EAutoMipmap::Zero, EBlackKey blackKey = EBlackKey::Zero);
|
||||||
|
|
||||||
|
const void* GetConstBitMapData(s32 mip) const { /* TODO: get bitmap data for specified mipmap */ return nullptr; }
|
||||||
|
void* GetBitMapData(s32 mip) const { return const_cast<void*>(GetConstBitMapData(mip)); }
|
||||||
|
};
|
||||||
|
} // namespace metaforce::WIP
|
||||||
|
|
|
@ -244,6 +244,37 @@ enum BlendFactor : uint16_t {
|
||||||
BL_INVDSTALPHA
|
BL_INVDSTALPHA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TextureFormat : uint32_t {
|
||||||
|
TF_I4 = 0x0,
|
||||||
|
TF_I8 = 0x1,
|
||||||
|
TF_IA4 = 0x2,
|
||||||
|
TF_IA8 = 0x3,
|
||||||
|
TF_RGB565 = 0x4,
|
||||||
|
TF_RGB5A3 = 0x5,
|
||||||
|
TF_RGBA8 = 0x6,
|
||||||
|
TF_C4 = 0x8,
|
||||||
|
TF_C8 = 0x9,
|
||||||
|
TF_C14X2 = 0xa,
|
||||||
|
TF_CMPR = 0xE,
|
||||||
|
TF_Z8 = 0x11,
|
||||||
|
TF_Z16 = 0x13,
|
||||||
|
TF_Z24X8 = 0x16,
|
||||||
|
CTF_R4 = 0x20,
|
||||||
|
CTF_RA4 = 0x22,
|
||||||
|
CTF_RA8 = 0x23,
|
||||||
|
CTF_YUVA8 = 0x26,
|
||||||
|
CTF_A8 = 0x27,
|
||||||
|
CTF_R8 = 0x28,
|
||||||
|
CTF_G8 = 0x29,
|
||||||
|
CTF_B8 = 0x2a,
|
||||||
|
CTF_RG8 = 0x2b,
|
||||||
|
CTF_GB8 = 0x2c,
|
||||||
|
CTF_Z4 = 0x30,
|
||||||
|
CTF_Z8M = 0x39,
|
||||||
|
CTF_Z8L = 0x3a,
|
||||||
|
CTF_Z16L = 0x3c,
|
||||||
|
};
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
union {
|
union {
|
||||||
uint8_t color[4];
|
uint8_t color[4];
|
||||||
|
|
|
@ -16,7 +16,7 @@ CIOWin::EMessageReturn CStateSetterFlow::OnMessage(const CArchitectureMessage& m
|
||||||
CResLoader* loader = g_ResFactory->GetResLoader();
|
CResLoader* loader = g_ResFactory->GetResLoader();
|
||||||
CAssetId worldId;
|
CAssetId worldId;
|
||||||
for (const auto& pak : loader->GetPaks()) {
|
for (const auto& pak : loader->GetPaks()) {
|
||||||
if (*(pak->GetPath().end() - 6) == '0' + m->m_warpWorldIdx) {
|
if (*(pak->GetPath().end() - 5) == '0' + m->m_warpWorldIdx) {
|
||||||
worldId = pak->GetMLVLId();
|
worldId = pak->GetMLVLId();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -621,7 +621,7 @@ void CMain::Init(const FileStoreManager& storeMgr, CVarManager* cvarMgr, boo::IA
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) {
|
for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) {
|
||||||
if (*(pak->GetPath().end() - 6) == '0' + m_warpWorldIdx) {
|
if (*(pak->GetPath().end() - 5) == '0' + m_warpWorldIdx) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ COutputStream::COutputStream(u8* ptr, s32 len) : x8_bufLen(len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
COutputStream::~COutputStream() {
|
COutputStream::~COutputStream() {
|
||||||
if (x8_bufLen < 64) {
|
if (x8_bufLen > 64) {
|
||||||
delete[] xc_ptr;
|
delete[] xc_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,10 @@ CTextInStream::CTextInStream(CInputStream& in, int len) : m_in(&in), m_len(len)
|
||||||
|
|
||||||
std::string CTextInStream::GetNextLine() {
|
std::string CTextInStream::GetNextLine() {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
while (true) {
|
while (!IsEOF()) {
|
||||||
auto chr = m_in->ReadChar();
|
auto chr = m_in->ReadChar();
|
||||||
ret += chr;
|
ret += chr;
|
||||||
if (ret.back() == '\r' || ret.back() == '\n') {
|
if (ret.back() == '\n') {
|
||||||
if (ret.back() == '\r') {
|
|
||||||
m_in->ReadChar();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue