diff --git a/src/Bitmap.c b/src/Bitmap.c index 496a405b5..9c417949b 100644 --- a/src/Bitmap.c +++ b/src/Bitmap.c @@ -617,10 +617,13 @@ ReturnCode Png_Encode(Bitmap* bmp, struct Stream* stream, Png_RowSelector select struct ZLibState zlState; struct Stream chunk, zlStream; - uint32_t stream_len; + uint32_t stream_end, stream_beg; int y, lineSize; ReturnCode res; + /* stream may not start at 0 (e.g. when making default.zip) */ + if ((res = stream->Position(stream, &stream_beg))) return res; + if (!selectRow) selectRow = Png_SelectRow; if ((res = Stream_Write(stream, png_sig, PNG_SIG_SIZE))) return res; Stream_WriteonlyCrc32(&chunk, stream); @@ -666,13 +669,14 @@ ReturnCode Png_Encode(Bitmap* bmp, struct Stream* stream, Png_RowSelector select /* Write end chunk */ Stream_SetU32_BE(&tmp[4], 0); Stream_SetU32_BE(&tmp[8], PNG_FourCC('I','E','N','D')); - Stream_SetU32_BE(&tmp[12], 0xAE426082UL); /* CRC32 of iend */ + Stream_SetU32_BE(&tmp[12], 0xAE426082UL); /* CRC32 of IEND */ if ((res = Stream_Write(stream, tmp, 16))) return res; - /* Come back to write size of data chunk */ - if ((res = stream->Length(stream, &stream_len))) return res; - if ((res = stream->Seek(stream, 33))) return res; + /* Come back to fixup size of data in data chunk */ + if ((res = stream->Length(stream, &stream_end))) return res; + if ((res = stream->Seek(stream, stream_beg + 33))) return res; - Stream_SetU32_BE(&tmp[0], stream_len - 57); - return Stream_Write(stream, tmp, 4); + Stream_SetU32_BE(&tmp[0], (stream_end - stream_beg) - 57); + if ((res = Stream_Write(stream, tmp, 4))) return res; + return stream->Seek(stream, stream_end); } diff --git a/src/Platform.c b/src/Platform.c index cd6bd9a18..fae5d2b21 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -473,10 +473,10 @@ ReturnCode File_Open(FileHandle* file, const String* path) { return File_Do(file, path, GENERIC_READ, OPEN_EXISTING); } ReturnCode File_Create(FileHandle* file, const String* path) { - return File_Do(file, path, GENERIC_WRITE, CREATE_ALWAYS); + return File_Do(file, path, GENERIC_WRITE | GENERIC_READ, CREATE_ALWAYS); } ReturnCode File_Append(FileHandle* file, const String* path) { - ReturnCode res = File_Do(file, path, GENERIC_WRITE, OPEN_ALWAYS); + ReturnCode res = File_Do(file, path, GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS); if (res) return res; return File_Seek(*file, 0, FILE_SEEKFROM_END); } @@ -608,10 +608,10 @@ ReturnCode File_Open(FileHandle* file, const String* path) { return File_Do(file, path, O_RDONLY); } ReturnCode File_Create(FileHandle* file, const String* path) { - return File_Do(file, path, O_WRONLY | O_CREAT | O_TRUNC); + return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC); } ReturnCode File_Append(FileHandle* file, const String* path) { - ReturnCode res = File_Do(file, path, O_WRONLY | O_CREAT); + ReturnCode res = File_Do(file, path, O_RDWR | O_CREAT); if (res) return res; return File_Seek(*file, 0, FILE_SEEKFROM_END); } diff --git a/src/Platform.h b/src/Platform.h index 3eccafc5e..fd6fc1c78 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -132,6 +132,7 @@ ReturnCode File_GetModifiedTime(const String* path, TimeMS* ms); ReturnCode File_SetModifiedTime(const String* path, TimeMS ms); /* Attempts to create a new (or overwrite) file for writing. */ +/* NOTE: If the file already exists, its contents are discarded. */ ReturnCode File_Create(FileHandle* file, const String* path); /* Attempts to open an existing file for reading. */ ReturnCode File_Open(FileHandle* file, const String* path); diff --git a/src/Resources.c b/src/Resources.c index aa9000149..82bcd31f3 100644 --- a/src/Resources.c +++ b/src/Resources.c @@ -244,6 +244,40 @@ static ReturnCode ZipPatcher_EndOfCentralDir(struct Stream* s, uint32_t centralD return Stream_Write(s, header, 22); } +static ReturnCode ZipPatcher_FixupLocalFile(struct Stream* s, struct ResourceTexture* e) { + String name = String_FromReadonly(e->Filename); + uint8_t tmp[2048]; + uint32_t dataBeg, dataEnd; + uint32_t i, crc, toRead, read; + ReturnCode res; + + dataBeg = e->Offset + 30 + name.length; + if ((res = s->Position(s, &dataEnd))) return res; + e->Size = dataEnd - dataBeg; + + /* work out the CRC 32 */ + crc = 0xffffffffUL; + if ((res = s->Seek(s, dataBeg))) return res; + + for (; dataBeg < dataEnd; dataBeg += read) { + toRead = dataEnd - dataBeg; + toRead = min(toRead, sizeof(tmp)); + + if ((res = s->Read(s, tmp, toRead, &read))) return res; + if (!read) return ERR_END_OF_STREAM; + + for (i = 0; i < read; i++) { + crc = Utils_Crc32Table[(crc ^ tmp[i]) & 0xFF] ^ (crc >> 8); + } + } + e->Crc32 = crc ^ 0xffffffffUL; + + /* then fixup the header */ + if ((res = s->Seek(s, e->Offset))) return res; + if ((res = ZipPatcher_LocalFile(s, e))) return res; + return s->Seek(s, dataEnd); +} + static ReturnCode ZipPatcher_WriteData(struct Stream* s, struct ResourceTexture* tex, const uint8_t* data, uint32_t len) { ReturnCode res; tex->Size = len; @@ -254,6 +288,21 @@ static ReturnCode ZipPatcher_WriteData(struct Stream* s, struct ResourceTexture* return Stream_Write(s, data, len); } +/*static ReturnCode ZipPatcher_WriteStream(struct Stream* s, struct ResourceTexture* tex, struct Stream* src) { + uint8_t tmp[2048]; + uint32_t read; + ReturnCode res; + if ((res = ZipPatcher_LocalFile(s, tex))) return res; + + for (;;) { + res = src->Read(src, tmp, sizeof(tmp), &read); + if (res) return res; + if (!read) break; + + if ((res = Stream_Write(s, tmp, read))) return res; + } + return ZipPatcher_FixupLocalFile(s, tex); +}*/ static ReturnCode ZipPatcher_WriteStream(struct Stream* s, struct ResourceTexture* tex, struct Stream* src) { uint8_t tmp[2048]; uint32_t read; @@ -274,23 +323,15 @@ static ReturnCode ZipPatcher_WriteStream(struct Stream* s, struct ResourceTextur } tex->Crc32 = crc32.Meta.CRC32.CRC32 ^ 0xFFFFFFFFUL; - return 0; + return ZipPatcher_FixupLocalFile(s, tex); } static ReturnCode ZipPatcher_WritePng(struct Stream* s, struct ResourceTexture* tex, Bitmap* src) { - struct Stream crc32; ReturnCode res; - res = ZipPatcher_LocalFile(s, tex); - if (res) return res; - //Stream_WriteonlyCrc32(&crc32, s); - - //res = Png_Encode(src, &crc32, NULL, true); - res = Png_Encode(src, s, NULL, true); - if (res) return res; - - //tex->Crc32 = crc32.Meta.CRC32.CRC32 ^ 0xFFFFFFFFUL; - return 0; + if ((res = ZipPatcher_LocalFile(s, tex))) return res; + if ((res = Png_Encode(src, s, NULL, true))) return res; + return ZipPatcher_FixupLocalFile(s, tex); }