This commit is contained in:
UnknownShadow200 2018-05-02 10:04:07 +10:00
parent 658eb3658d
commit 463c3db248
9 changed files with 106 additions and 93 deletions

View File

@ -153,7 +153,7 @@ enum INFLATE_STATE_ {
}; };
/* Insert this byte into the bit buffer */ /* Insert this byte into the bit buffer */
#define Inflate_GetByte(state) state->AvailIn--; state->Bits |= (UInt32)(state->Input[state->NextIn]) << state->NumBits; state->NextIn++; state->NumBits += 8; #define Inflate_GetByte(state) state->AvailIn--; state->Bits |= (UInt32)(*state->NextIn) << state->NumBits; state->NextIn++; state->NumBits += 8;
/* Retrieves bits from the bit buffer */ /* Retrieves bits from the bit buffer */
#define Inflate_PeekBits(state, bits) (state->Bits & ((1UL << (bits)) - 1UL)) #define Inflate_PeekBits(state, bits) (state->Bits & ((1UL << (bits)) - 1UL))
/* Consumes/eats up bits from the bit buffer */ /* Consumes/eats up bits from the bit buffer */
@ -315,7 +315,7 @@ void Inflate_Init(InflateState* state, Stream* source) {
state->Bits = 0; state->Bits = 0;
state->NumBits = 0; state->NumBits = 0;
state->AvailIn = 0; state->AvailIn = 0;
state->NextIn = 0; state->NextIn = state->Input;
state->LastBlock = false; state->LastBlock = false;
state->AvailOut = 0; state->AvailOut = 0;
state->Output = NULL; state->Output = NULL;
@ -467,9 +467,10 @@ void Inflate_Process(InflateState* state) {
UInt32 copyLen = min(state->AvailIn, state->AvailOut); UInt32 copyLen = min(state->AvailIn, state->AvailOut);
copyLen = min(copyLen, state->Index); copyLen = min(copyLen, state->Index);
if (copyLen > 0) { if (copyLen > 0) {
Platform_MemCpy(state->Output, state->Input, copyLen); Platform_MemCpy(state->Output, state->NextIn, copyLen);
/* TODO: Copy output to window!!! */ /* TODO: Copy output to window!!! */
state->Output += copyLen; state->AvailOut -= copyLen; state->Output += copyLen; state->AvailOut -= copyLen;
state->NextIn += copyLen;
state->AvailIn -= copyLen; state->AvailIn -= copyLen;
state->Index -= copyLen; state->Index -= copyLen;
} }
@ -656,11 +657,12 @@ ReturnCode Inflate_StreamRead(Stream* stream, UInt8* data, UInt32 count, UInt32*
if (state->State == INFLATE_STATE_DONE) break; if (state->State == INFLATE_STATE_DONE) break;
if (state->AvailIn == 0) { if (state->AvailIn == 0) {
/* Fully used up input buffer. Cycle back to start. */ /* Fully used up input buffer. Cycle back to start. */
if (state->NextIn == INFLATE_MAX_INPUT) state->NextIn = 0; UInt8* inputEnd = state->Input + INFLATE_MAX_INPUT;
if (state->NextIn == inputEnd) state->NextIn = state->Input;
UInt8* ptr = &state->Input[state->NextIn]; UInt8* cur = state->NextIn;
UInt32 read, remaining = INFLATE_MAX_INPUT - state->NextIn; UInt32 read, remaining = (UInt32)(inputEnd - state->NextIn);
ReturnCode code = state->Source->Read(state->Source, ptr, remaining, &read); ReturnCode code = state->Source->Read(state->Source, cur, remaining, &read);
/* Did we fail to read in more input data? */ /* Did we fail to read in more input data? */
/* If there's a few bits of data in the bit buffer it doesn't matter since Inflate_Process /* If there's a few bits of data in the bit buffer it doesn't matter since Inflate_Process
@ -699,8 +701,9 @@ void Inflate_MakeStream(Stream* stream, InflateState* state, Stream* underlying)
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------Deflate (compress)----------------------------------------------------* *---------------------------------------------------Deflate (compress)----------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
ReturnCode Deflate_Flush(DeflateState* state, UInt32 size) { ReturnCode Deflate_Flush(DeflateState* state, UInt32 size, bool lastBlock) {
/* TODO: actually compress here */ /* TODO: actually compress here */
Stream_WriteU8(state->Source, lastBlock);
Stream_WriteU16_BE(state->Source, size); Stream_WriteU16_BE(state->Source, size);
Stream_WriteU16_BE(state->Source, size ^ 0xFFFFFUL); Stream_WriteU16_BE(state->Source, size ^ 0xFFFFFUL);
Stream_Write(state->Source, state->InputBuffer, size); Stream_Write(state->Source, state->InputBuffer, size);
@ -724,7 +727,7 @@ ReturnCode Deflate_StreamWrite(Stream* stream, UInt8* data, UInt32 count, UInt32
data += toWrite; data += toWrite;
if (state->InputPosition == DEFLATE_BUFFER_SIZE) { if (state->InputPosition == DEFLATE_BUFFER_SIZE) {
ReturnCode result = Deflate_Flush(state, DEFLATE_BUFFER_SIZE); ReturnCode result = Deflate_Flush(state, DEFLATE_BUFFER_SIZE, false);
if (result != 0) return result; if (result != 0) return result;
} }
} }
@ -733,10 +736,7 @@ ReturnCode Deflate_StreamWrite(Stream* stream, UInt8* data, UInt32 count, UInt32
ReturnCode Deflate_StreamClose(Stream* stream) { ReturnCode Deflate_StreamClose(Stream* stream) {
DeflateState* state = stream->Meta_Inflate; DeflateState* state = stream->Meta_Inflate;
if (state->InputPosition > 0) { return Deflate_Flush(state, DEFLATE_BUFFER_SIZE - state->InputPosition, true);
return Deflate_Flush(state, DEFLATE_BUFFER_SIZE - state->InputPosition);
}
return 0;
} }
void Deflate_MakeStream(Stream* stream, DeflateState* state, Stream* underlying) { void Deflate_MakeStream(Stream* stream, DeflateState* state, Stream* underlying) {
@ -760,8 +760,9 @@ ReturnCode GZip_StreamClose(Stream* stream) {
if (result != 0) return result; if (result != 0) return result;
GZipState* state = stream->Meta_Inflate; GZipState* state = stream->Meta_Inflate;
Stream_WriteU32_LE(stream, state->Crc32); UInt32 crc32 = state->Crc32 ^ 0xFFFFFFFFUL;
Stream_WriteU32_LE(stream, state->Size); Stream_WriteU32_LE(state->Base.Source, crc32);
Stream_WriteU32_LE(state->Base.Source, state->Size);
return 0; return 0;
} }
@ -771,27 +772,30 @@ ReturnCode GZip_StreamWrite(Stream* stream, UInt8* data, UInt32 count, UInt32* m
GZipState* state = stream->Meta_Inflate; GZipState* state = stream->Meta_Inflate;
state->Size += count; state->Size += count;
UInt32 i, crc32 = state->Crc32 ^ 0xFFFFFFFFUL; /* TODO: should we move this to initalisation and finalisation */ UInt32 i, crc32 = state->Crc32;
/* TODO: WinRAR says this crc32 is invalid */
/* TODO: Optimise this calculation */ /* TODO: Optimise this calculation */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
crc32 = Utils_Crc32Table[(crc32 ^ data[i]) & 0xFF] ^ (crc32 >> 8); crc32 = Utils_Crc32Table[(crc32 ^ data[i]) & 0xFF] ^ (crc32 >> 8);
} }
state->Crc32 = crc32 ^ 0xFFFFFFFFUL; state->Crc32 = crc32;
return 0; return 0;
} }
ReturnCode GZip_StreamWriteFirst(Stream* stream, UInt8* data, UInt32 count, UInt32* modified) { ReturnCode GZip_StreamWriteFirst(Stream* stream, UInt8* data, UInt32 count, UInt32* modified) {
static UInt8 gz_header[10] = { 0x1F, 0x8B, 0x08 }; static UInt8 gz_header[10] = { 0x1F, 0x8B, 0x08 };
Stream_Write(stream, gz_header, sizeof(gz_header)); GZipState* state = stream->Meta_Inflate;
Stream_Write(state->Base.Source, gz_header, sizeof(gz_header));
stream->Write = GZip_StreamWrite; stream->Write = GZip_StreamWrite;
return GZip_StreamWrite(stream, data, count, modified); return GZip_StreamWrite(stream, data, count, modified);
} }
void GZip_MakeStream(Stream* stream, GZipState* state, Stream* underlying) { void GZip_MakeStream(Stream* stream, GZipState* state, Stream* underlying) {
Deflate_MakeStream(stream, &state->Base, underlying); Deflate_MakeStream(stream, &state->Base, underlying);
state->Crc32 = 0; state->Crc32 = 0xFFFFFFFFUL;
state->Size = 0; state->Size = 0;
stream->Write = GZip_StreamWriteFirst; stream->Write = GZip_StreamWriteFirst;
stream->Close = GZip_StreamClose; stream->Close = GZip_StreamClose;
@ -806,7 +810,7 @@ ReturnCode ZLib_StreamClose(Stream* stream) {
if (result != 0) return result; if (result != 0) return result;
ZLibState* state = stream->Meta_Inflate; ZLibState* state = stream->Meta_Inflate;
Stream_WriteU32_BE(stream, state->Adler32); Stream_WriteU32_BE(state->Base.Source, state->Adler32);
return 0; return 0;
} }
@ -830,8 +834,10 @@ ReturnCode ZLib_StreamWrite(Stream* stream, UInt8* data, UInt32 count, UInt32* m
} }
ReturnCode ZLib_StreamWriteFirst(Stream* stream, UInt8* data, UInt32 count, UInt32* modified) { ReturnCode ZLib_StreamWriteFirst(Stream* stream, UInt8* data, UInt32 count, UInt32* modified) {
static UInt8 zl_header[2] = { 0x78, 0x01 }; /* TODO: verify this is correct */ static UInt8 zl_header[2] = { 0x78, 0x9C };
Stream_Write(stream, zl_header, sizeof(zl_header)); ZLibState* state = stream->Meta_Inflate;
Stream_Write(state->Base.Source, zl_header, sizeof(zl_header));
stream->Write = ZLib_StreamWrite; stream->Write = ZLib_StreamWrite;
return ZLib_StreamWrite(stream, data, count, modified); return ZLib_StreamWrite(stream, data, count, modified);
} }

View File

@ -44,12 +44,12 @@ typedef struct HuffmanTable_ {
typedef struct InflateState_ { typedef struct InflateState_ {
UInt8 State; UInt8 State;
Stream* Source;
bool LastBlock; /* Whether the last DEFLATE block has been encounted in the stream */ bool LastBlock; /* Whether the last DEFLATE block has been encounted in the stream */
Stream* Source;
UInt32 Bits; /* Holds bits across byte boundaries*/ UInt32 Bits; /* Holds bits across byte boundaries*/
UInt32 NumBits; /* Number of bits in Bits buffer*/ UInt32 NumBits; /* Number of bits in Bits buffer*/
UInt32 NextIn; /* Index within Input of byte being read */ UInt8* NextIn; /* Pointer within Input of byte being read */
UInt32 AvailIn; /* Number of bytes that can be read from Input */ UInt32 AvailIn; /* Number of bytes that can be read from Input */
UInt8* Output; /* Pointer for output data */ UInt8* Output; /* Pointer for output data */
UInt32 AvailOut; /* Max number of bytes to output */ UInt32 AvailOut; /* Max number of bytes to output */
@ -76,7 +76,7 @@ void Inflate_MakeStream(Stream* stream, InflateState* state, Stream* underlying)
typedef struct DeflateState_ { typedef struct DeflateState_ {
UInt32 InputPosition; UInt32 InputPosition;
Stream* Source; Stream* Source;
UInt8 InputBuffer[DEFLATE_BUFFER_SIZE] UInt8 InputBuffer[DEFLATE_BUFFER_SIZE];
} DeflateState; } DeflateState;
void Deflate_MakeStream(Stream* stream, DeflateState* state, Stream* underlying); void Deflate_MakeStream(Stream* stream, DeflateState* state, Stream* underlying);

View File

@ -698,7 +698,7 @@ void Dat_ReadFieldData(Stream* stream, JFieldDesc* field) {
case JFIELD_OBJECT: { case JFIELD_OBJECT: {
/* Luckily for us, we only have to account for blockMap object */ /* Luckily for us, we only have to account for blockMap object */
/* The player object is stored after the fields we actually care about, so can be ignored */ /* Other objects (e.g. player) are stored after the fields we actually care about, so ignore them */
String fieldName = String_FromRawArray(field->FieldName); String fieldName = String_FromRawArray(field->FieldName);
if (!String_CaselessEqualsConst(&fieldName, "blockMap")) break; if (!String_CaselessEqualsConst(&fieldName, "blockMap")) break;
@ -927,9 +927,9 @@ void Cw_WriteMetadataCompound(Stream* stream) {
Cw_WriteCpeExtCompound(stream, "BlockDefinitions", 1); Cw_WriteCpeExtCompound(stream, "BlockDefinitions", 1);
Int32 block; Int32 block;
for ( block = 1; block < 256; block++) { for (block = 1; block < 256; block++) {
if (Block_IsCustomDefined((BlockID)block)) { if (Block_IsCustomDefined((BlockID)block)) {
WriteBlockDefinitionCompound((BlockID)block); Cw_WriteBlockDefinitionCompound(stream, (BlockID)block);
} }
} }
Nbt_WriteU8(stream, NBT_TAG_END); Nbt_WriteU8(stream, NBT_TAG_END);

View File

@ -652,9 +652,10 @@ void Game_TakeScreenshot(void) {
void* file; void* file;
ReturnCode result = Platform_FileCreate(&file, &path); ReturnCode result = Platform_FileCreate(&file, &path);
ErrorHandler_CheckOrFail(result, "Taking screenshot - opening file"); ErrorHandler_CheckOrFail(result, "Taking screenshot - opening file");
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
Gfx_TakeScreenshot(&stream, Game_Width, Game_Height); Gfx_TakeScreenshot(&stream, Game_Width, Game_Height);
}
result = stream.Close(&stream); result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "Taking screenshot - closing file"); ErrorHandler_CheckOrFail(result, "Taking screenshot - closing file");
@ -784,8 +785,6 @@ void AsyncDownloader_PurgeOldEntriesTask(ScheduledTask* task) { }
DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; } DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; }
void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { } void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { }
void Cw_Save(Stream* stream) { }
void Schematic_Save(Stream* stream) { }
void Gfx_MakeApiInfo(void) { } void Gfx_MakeApiInfo(void) { }
void AdvLightingBuilder_SetActive(void) { } void AdvLightingBuilder_SetActive(void) { }

View File

@ -1319,6 +1319,7 @@ void SaveLevelScreen_Schematic(GuiElement* screenElem, GuiElement* widget) {
void SaveLevelScreen_Init(GuiElement* elem) { void SaveLevelScreen_Init(GuiElement* elem) {
SaveLevelScreen* screen = (SaveLevelScreen*)elem; SaveLevelScreen* screen = (SaveLevelScreen*)elem;
screen->TextPath = String_InitAndClearArray(screen->TextPathBuffer);
MenuScreen_Init(elem); MenuScreen_Init(elem);
Key_KeyRepeat = true; Key_KeyRepeat = true;
screen->ContextRecreated(elem); screen->ContextRecreated(elem);
@ -1335,16 +1336,19 @@ void SaveLevelScreen_Render(GuiElement* elem, Real64 delta) {
String path = screen->TextPath; String path = screen->TextPath;
void* file; void* file;
ReturnCode code = Platform_FileCreate(&file, &path); ReturnCode result = Platform_FileCreate(&file, &path);
ErrorHandler_CheckOrFail(code, "Saving map"); ErrorHandler_CheckOrFail(result, "Saving map - opening file");
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
String cw = String_FromConst(".cw"); String cw = String_FromConst(".cw");
if (String_CaselessEnds(&path, &cw)) { if (String_CaselessEnds(&path, &cw)) {
Cw_Save(&stream); Cw_Save(&stream);
} else { } else {
Schematic_Save(&stream); Schematic_Save(&stream);
} }
}
result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "Saving map - closing file");
UInt8 msgBuffer[String_BufferSize(STRING_SIZE * 2)]; UInt8 msgBuffer[String_BufferSize(STRING_SIZE * 2)];
String msg = String_InitAndClearArray(msgBuffer); String msg = String_InitAndClearArray(msgBuffer);
@ -1554,11 +1558,6 @@ void LoadLevelScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
String_Format2(&path, "maps%r%s", &Platform_DirectorySeparator, &filename); String_Format2(&path, "maps%r%s", &Platform_DirectorySeparator, &filename);
if (!Platform_FileExists(&path)) return; if (!Platform_FileExists(&path)) return;
void* file;
ReturnCode code = Platform_FileOpen(&file, &path);
ErrorHandler_CheckOrFail(code, "Failed to open map file");
Stream stream; Stream_FromFile(&stream, file, &path);
World_Reset(); World_Reset();
Event_RaiseVoid(&WorldEvents_NewMap); Event_RaiseVoid(&WorldEvents_NewMap);
@ -1569,6 +1568,11 @@ void LoadLevelScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
Block_Reset(); Block_Reset();
Inventory_SetDefaultMapping(); Inventory_SetDefaultMapping();
void* file;
ReturnCode result = Platform_FileOpen(&file, &path);
ErrorHandler_CheckOrFail(result, "Loading map - open file");
Stream stream; Stream_FromFile(&stream, file, &path);
{
String cw = String_FromConst(".cw"); String lvl = String_FromConst(".lvl"); String cw = String_FromConst(".cw"); String lvl = String_FromConst(".lvl");
String fcm = String_FromConst(".fcm"); String dat = String_FromConst(".dat"); String fcm = String_FromConst(".fcm"); String dat = String_FromConst(".dat");
if (String_CaselessEnds(&path, &dat)) { if (String_CaselessEnds(&path, &dat)) {
@ -1580,8 +1584,11 @@ void LoadLevelScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
} else if (String_CaselessEnds(&path, &lvl)) { } else if (String_CaselessEnds(&path, &lvl)) {
Lvl_Load(&stream); Lvl_Load(&stream);
} }
World_SetNewMap(World_Blocks, World_BlocksSize, World_Width, World_Height, World_Length); }
result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "Loading map - close file");
World_SetNewMap(World_Blocks, World_BlocksSize, World_Width, World_Height, World_Length);
Event_RaiseVoid(&WorldEvents_MapLoaded); Event_RaiseVoid(&WorldEvents_MapLoaded);
if (Game_AllowServerTextures && World_TextureUrl.length > 0) { if (Game_AllowServerTextures && World_TextureUrl.length > 0) {
ServerConnection_RetrieveTexturePack(&World_TextureUrl); ServerConnection_RetrieveTexturePack(&World_TextureUrl);

View File

@ -47,10 +47,10 @@ int main(int argc, char* argv[]) {
} }
String title = String_FromConst(PROGRAM_APP_NAME); String title = String_FromConst(PROGRAM_APP_NAME);
argc = 5; //argc = 5;
char* default_argv[5] = { "path", "UnknownShadow200", "fff", "127.0.0.1", "25566" }; //char* default_argv[5] = { "path", "UnknownShadow200", "fff", "127.0.0.1", "25566" };
//argc = 2; argc = 2;
//char* default_argv[2] = { "path", "UnknownShadow200" }; char* default_argv[2] = { "path", "UnknownShadow200" };
argv = default_argv; argv = default_argv;
if (argc == 1 || argc == 2) { if (argc == 1 || argc == 2) {

View File

@ -192,8 +192,8 @@ void EntryList_Load(EntryList* list) {
if (result == ReturnCode_FileNotFound) return; if (result == ReturnCode_FileNotFound) return;
/* TODO: Should we just log failure to save? */ /* TODO: Should we just log failure to save? */
ErrorHandler_CheckOrFail(result, "EntryList_Load - open file"); ErrorHandler_CheckOrFail(result, "EntryList_Load - open file");
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
while (Stream_ReadLine(&stream, &path)) { while (Stream_ReadLine(&stream, &path)) {
String_UNSAFE_TrimStart(&path); String_UNSAFE_TrimStart(&path);
String_UNSAFE_TrimEnd(&path); String_UNSAFE_TrimEnd(&path);
@ -201,7 +201,7 @@ void EntryList_Load(EntryList* list) {
if (path.length == 0) continue; if (path.length == 0) continue;
StringsBuffer_Add(&list->Entries, &path); StringsBuffer_Add(&list->Entries, &path);
} }
}
result = stream.Close(&stream); result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "EntryList_Load - close file"); ErrorHandler_CheckOrFail(result, "EntryList_Load - close file");
} }
@ -222,14 +222,14 @@ void EntryList_Save(EntryList* list) {
ReturnCode result = Platform_FileCreate(&file, &path); ReturnCode result = Platform_FileCreate(&file, &path);
/* TODO: Should we just log failure to save? */ /* TODO: Should we just log failure to save? */
ErrorHandler_CheckOrFail(result, "EntryList_Save - open file"); ErrorHandler_CheckOrFail(result, "EntryList_Save - open file");
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
Int32 i; Int32 i;
for (i = 0; i < list->Entries.Count; i++) { for (i = 0; i < list->Entries.Count; i++) {
String entry = StringsBuffer_UNSAFE_Get(&list->Entries, i); String entry = StringsBuffer_UNSAFE_Get(&list->Entries, i);
Stream_WriteLine(&stream, &entry); Stream_WriteLine(&stream, &entry);
} }
}
result = stream.Close(&stream); result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "EntryList_Save - close file"); ErrorHandler_CheckOrFail(result, "EntryList_Save - close file");
} }
@ -363,8 +363,9 @@ void TextureCache_AddImage(STRING_PURE String* url, Bitmap* bmp) {
String path; TexCache_InitAndMakePath(url); String path; TexCache_InitAndMakePath(url);
void* file = TextureCache_CreateFile(&path); void* file = TextureCache_CreateFile(&path);
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
Bitmap_EncodePng(bmp, &stream); Bitmap_EncodePng(bmp, &stream);
}
ReturnCode result = stream.Close(&stream); ReturnCode result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "TextureCache_AddImage - close file"); ErrorHandler_CheckOrFail(result, "TextureCache_AddImage - close file");
} }
@ -373,8 +374,9 @@ void TextureCache_AddData(STRING_PURE String* url, UInt8* data, UInt32 length) {
String path; TexCache_InitAndMakePath(url); String path; TexCache_InitAndMakePath(url);
void* file = TextureCache_CreateFile(&path); void* file = TextureCache_CreateFile(&path);
Stream stream; Stream_FromFile(&stream, file, &path); Stream stream; Stream_FromFile(&stream, file, &path);
{
Stream_Write(&stream, data, length); Stream_Write(&stream, data, length);
}
ReturnCode result = stream.Close(&stream); ReturnCode result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - close file"); ErrorHandler_CheckOrFail(result, "TextureCache_AddData - close file");
} }
@ -448,11 +450,10 @@ void TexturePack_ExtractZip_File(STRING_PURE String* filename) {
void* file; void* file;
ReturnCode result = Platform_FileOpen(&file, &path); ReturnCode result = Platform_FileOpen(&file, &path);
ErrorHandler_CheckOrFail(result, "TexturePack_Extract - opening file"); ErrorHandler_CheckOrFail(result, "TexturePack_Extract - opening file");
Stream stream; Stream_FromFile(&stream, file, &path);
Stream stream; {
Stream_FromFile(&stream, file, &path);
TexturePack_ExtractZip(&stream); TexturePack_ExtractZip(&stream);
}
result = stream.Close(&stream); result = stream.Close(&stream);
ErrorHandler_CheckOrFail(result, "TexturePack_Extract - closing file"); ErrorHandler_CheckOrFail(result, "TexturePack_Extract - closing file");
} }