mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
More WIP towards sound zip creation
This commit is contained in:
parent
4b9ab4de5f
commit
f600f84cbf
449
src/Resources.c
449
src/Resources.c
@ -28,6 +28,8 @@ struct AssetSet {
|
|||||||
const char* (*GetRequestName)(int reqID);
|
const char* (*GetRequestName)(int reqID);
|
||||||
/* Checks if any assets have been downloaded, and processes them if so */
|
/* Checks if any assets have been downloaded, and processes them if so */
|
||||||
void (*CheckStatus)(void);
|
void (*CheckStatus)(void);
|
||||||
|
/* Resets state and frees and allocated memory */
|
||||||
|
void (*ResetState)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
int Resources_Count, Resources_Size;
|
int Resources_Count, Resources_Size;
|
||||||
@ -47,12 +49,196 @@ struct ResourceZipEntry {
|
|||||||
#define RESOURCE_TYPE_DATA 1
|
#define RESOURCE_TYPE_DATA 1
|
||||||
#define RESOURCE_TYPE_PNG 2
|
#define RESOURCE_TYPE_PNG 2
|
||||||
#define RESOURCE_TYPE_CONST 3
|
#define RESOURCE_TYPE_CONST 3
|
||||||
|
#define RESOURCE_TYPE_SOUND 4
|
||||||
|
|
||||||
static CC_NOINLINE cc_bool Fetcher_Get(int reqID, struct HttpRequest* item);
|
static CC_NOINLINE cc_bool Fetcher_Get(int reqID, struct HttpRequest* item);
|
||||||
CC_NOINLINE static struct ResourceZipEntry* ZipEntries_Find(const cc_string* name);
|
CC_NOINLINE static struct ResourceZipEntry* ZipEntries_Find(const cc_string* name);
|
||||||
static cc_result ZipEntry_ExtractData(struct ResourceZipEntry* e, struct Stream* data, struct ZipEntry* source);
|
static cc_result ZipEntry_ExtractData(struct ResourceZipEntry* e, struct Stream* data, struct ZipEntry* source);
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------Zip entry writer---------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
static void GetCurrentZipDate(int* modTime, int* modDate) {
|
||||||
|
struct DateTime now;
|
||||||
|
DateTime_CurrentLocal(&now);
|
||||||
|
|
||||||
|
*modTime = (now.second / 2) | (now.minute << 5) | (now.hour << 11);
|
||||||
|
*modDate = (now.day) | (now.month << 5) | ((now.year - 1980) << 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_LocalFile(struct Stream* s, struct ResourceZipEntry* e) {
|
||||||
|
int filenameLen = String_Length(e->filename);
|
||||||
|
cc_uint8 header[30 + STRING_SIZE];
|
||||||
|
cc_result res;
|
||||||
|
int modTime, modDate;
|
||||||
|
|
||||||
|
GetCurrentZipDate(&modTime, &modDate);
|
||||||
|
if ((res = s->Position(s, &e->offset))) return res;
|
||||||
|
|
||||||
|
Stream_SetU32_LE(header + 0, 0x04034b50); /* signature */
|
||||||
|
Stream_SetU16_LE(header + 4, 20); /* version needed */
|
||||||
|
Stream_SetU16_LE(header + 6, 0); /* bitflags */
|
||||||
|
Stream_SetU16_LE(header + 8, 0); /* compression method */
|
||||||
|
Stream_SetU16_LE(header + 10, modTime); /* last modified */
|
||||||
|
Stream_SetU16_LE(header + 12, modDate); /* last modified */
|
||||||
|
|
||||||
|
Stream_SetU32_LE(header + 14, e->crc32); /* CRC32 */
|
||||||
|
Stream_SetU32_LE(header + 18, e->size); /* Compressed size */
|
||||||
|
Stream_SetU32_LE(header + 22, e->size); /* Uncompressed size */
|
||||||
|
|
||||||
|
Stream_SetU16_LE(header + 26, filenameLen); /* name length */
|
||||||
|
Stream_SetU16_LE(header + 28, 0); /* extra field length */
|
||||||
|
|
||||||
|
Mem_Copy(header + 30, e->filename, filenameLen);
|
||||||
|
return Stream_Write(s, header, 30 + filenameLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_CentralDir(struct Stream* s, struct ResourceZipEntry* e) {
|
||||||
|
int filenameLen = String_Length(e->filename);
|
||||||
|
cc_uint8 header[46 + STRING_SIZE];
|
||||||
|
int modTime, modDate;
|
||||||
|
GetCurrentZipDate(&modTime, &modDate);
|
||||||
|
|
||||||
|
Stream_SetU32_LE(header + 0, 0x02014b50); /* signature */
|
||||||
|
Stream_SetU16_LE(header + 4, 20); /* version */
|
||||||
|
Stream_SetU16_LE(header + 6, 20); /* version needed */
|
||||||
|
Stream_SetU16_LE(header + 8, 0); /* bitflags */
|
||||||
|
Stream_SetU16_LE(header + 10, 0); /* compression method */
|
||||||
|
Stream_SetU16_LE(header + 12, modTime); /* last modified */
|
||||||
|
Stream_SetU16_LE(header + 14, modDate); /* last modified */
|
||||||
|
|
||||||
|
Stream_SetU32_LE(header + 16, e->crc32); /* CRC32 */
|
||||||
|
Stream_SetU32_LE(header + 20, e->size); /* compressed size */
|
||||||
|
Stream_SetU32_LE(header + 24, e->size); /* uncompressed size */
|
||||||
|
|
||||||
|
Stream_SetU16_LE(header + 28, filenameLen); /* name length */
|
||||||
|
Stream_SetU16_LE(header + 30, 0); /* extra field length */
|
||||||
|
Stream_SetU16_LE(header + 32, 0); /* file comment length */
|
||||||
|
Stream_SetU16_LE(header + 34, 0); /* disk number */
|
||||||
|
Stream_SetU16_LE(header + 36, 0); /* internal attributes */
|
||||||
|
Stream_SetU32_LE(header + 38, 0); /* external attributes */
|
||||||
|
Stream_SetU32_LE(header + 42, e->offset); /* local header offset */
|
||||||
|
|
||||||
|
Mem_Copy(header + 46, e->filename, filenameLen);
|
||||||
|
return Stream_Write(s, header, 46 + filenameLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_EndOfCentralDir(struct Stream* s, int numEntries,
|
||||||
|
cc_uint32 centralDirBeg, cc_uint32 centralDirEnd) {
|
||||||
|
cc_uint8 header[22];
|
||||||
|
|
||||||
|
Stream_SetU32_LE(header + 0, 0x06054b50); /* signature */
|
||||||
|
Stream_SetU16_LE(header + 4, 0); /* disk number */
|
||||||
|
Stream_SetU16_LE(header + 6, 0); /* disk number of start */
|
||||||
|
Stream_SetU16_LE(header + 8, numEntries); /* disk entries */
|
||||||
|
Stream_SetU16_LE(header + 10, numEntries); /* total entries */
|
||||||
|
Stream_SetU32_LE(header + 12, centralDirEnd - centralDirBeg); /* central dir size */
|
||||||
|
Stream_SetU32_LE(header + 16, centralDirBeg); /* central dir start */
|
||||||
|
Stream_SetU16_LE(header + 20, 0); /* comment length */
|
||||||
|
return Stream_Write(s, header, 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_FixupLocalFile(struct Stream* s, struct ResourceZipEntry* e) {
|
||||||
|
int filenameLen = String_Length(e->filename);
|
||||||
|
cc_uint8 tmp[2048];
|
||||||
|
cc_uint32 dataBeg, dataEnd;
|
||||||
|
cc_uint32 i, crc, toRead, read;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
|
dataBeg = e->offset + 30 + filenameLen;
|
||||||
|
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 = ZipWriter_LocalFile(s, e))) return res;
|
||||||
|
return s->Seek(s, dataEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_WriteData(struct Stream* dst, struct ResourceZipEntry* e) {
|
||||||
|
cc_uint8* data = e->value.data;
|
||||||
|
cc_result res;
|
||||||
|
e->crc32 = Utils_CRC32(data, e->size);
|
||||||
|
|
||||||
|
if ((res = ZipWriter_LocalFile(dst, e))) return res;
|
||||||
|
return Stream_Write(dst, data, e->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result ZipWriter_WritePng(struct Stream* dst, struct ResourceZipEntry* e) {
|
||||||
|
struct Bitmap* src = &e->value.bmp;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
|
if ((res = ZipWriter_LocalFile(dst, e))) return res;
|
||||||
|
if ((res = Png_Encode(src, dst, NULL, true, NULL))) return res;
|
||||||
|
return ZipWriter_FixupLocalFile(dst, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*------------------------------------------------------Zip file writer----------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
static cc_result ZipFile_WriteEntries(struct Stream* s, struct ResourceZipEntry* entries, int numEntries) {
|
||||||
|
struct ResourceZipEntry* e;
|
||||||
|
cc_uint32 beg, end;
|
||||||
|
int i;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
|
for (i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
e = &entries[i];
|
||||||
|
|
||||||
|
if (e->type == RESOURCE_TYPE_PNG) {
|
||||||
|
if ((res = ZipWriter_WritePng(s, e))) return res;
|
||||||
|
} else {
|
||||||
|
if ((res = ZipWriter_WriteData(s, e))) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = s->Position(s, &beg))) return res;
|
||||||
|
for (i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
if ((res = ZipWriter_CentralDir(s, &entries[i]))) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = s->Position(s, &end))) return res;
|
||||||
|
return ZipWriter_EndOfCentralDir(s, numEntries, beg, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ZipFile_Create(cc_string* path, struct ResourceZipEntry* entries, int numEntries) {
|
||||||
|
struct Stream s;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
|
res = Stream_CreateFile(&s, path);
|
||||||
|
if (res) {
|
||||||
|
Logger_SysWarn2(res, "creating", path); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = ZipFile_WriteEntries(&s, entries, numEntries);
|
||||||
|
if (res) Logger_SysWarn2(res, "making", path);
|
||||||
|
|
||||||
|
res = s.Close(&s);
|
||||||
|
if (res) Logger_SysWarn2(res, "closing", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*---------------------------------------------------------Music assets----------------------------------------------------*
|
*---------------------------------------------------------Music assets----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
@ -161,12 +347,16 @@ static void MusicAssets_CheckStatus(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MusicAssets_ResetState(void) {
|
||||||
|
}
|
||||||
|
|
||||||
static const struct AssetSet mccMusicAssetSet = {
|
static const struct AssetSet mccMusicAssetSet = {
|
||||||
MusicAssets_CheckExistence,
|
MusicAssets_CheckExistence,
|
||||||
MusicAssets_CountMissing,
|
MusicAssets_CountMissing,
|
||||||
MusicAssets_DownloadAssets,
|
MusicAssets_DownloadAssets,
|
||||||
MusicAssets_GetRequestName,
|
MusicAssets_GetRequestName,
|
||||||
MusicAssets_CheckStatus
|
MusicAssets_CheckStatus,
|
||||||
|
MusicAssets_ResetState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -176,7 +366,8 @@ static const struct AssetSet mccMusicAssetSet = {
|
|||||||
static struct SoundAsset {
|
static struct SoundAsset {
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* hash;
|
const char* hash;
|
||||||
int reqID;
|
int reqID, size;
|
||||||
|
void* data;
|
||||||
} soundAssets[] = {
|
} soundAssets[] = {
|
||||||
{ "dig_cloth1", "5fd568d724ba7d53911b6cccf5636f859d2662e8" }, { "dig_cloth2", "56c1d0ac0de2265018b2c41cb571cc6631101484" },
|
{ "dig_cloth1", "5fd568d724ba7d53911b6cccf5636f859d2662e8" }, { "dig_cloth2", "56c1d0ac0de2265018b2c41cb571cc6631101484" },
|
||||||
{ "dig_cloth3", "9c63f2a3681832dc32d206f6830360bfe94b5bfc" }, { "dig_cloth4", "55da1856e77cfd31a7e8c3d358e1f856c5583198" },
|
{ "dig_cloth3", "9c63f2a3681832dc32d206f6830360bfe94b5bfc" }, { "dig_cloth4", "55da1856e77cfd31a7e8c3d358e1f856c5583198" },
|
||||||
@ -361,11 +552,15 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void SoundAsset_Check(const struct SoundAsset* sound) {
|
static void SoundAsset_Check(struct SoundAsset* sound) {
|
||||||
struct HttpRequest item;
|
struct HttpRequest item;
|
||||||
if (!Fetcher_Get(sound->reqID, &item)) return;
|
if (!Fetcher_Get(sound->reqID, &item)) return;
|
||||||
|
|
||||||
SoundPatcher_Save(sound->name, &item);
|
SoundPatcher_Save(sound->name, &item);
|
||||||
|
|
||||||
|
sound->data = item.data;
|
||||||
|
sound->size = item.size;
|
||||||
|
item.data = NULL;
|
||||||
HttpRequest_Free(&item);
|
HttpRequest_Free(&item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,12 +572,24 @@ static void SoundAssets_CheckStatus(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SoundAssets_ResetState(void) {
|
||||||
|
int i;
|
||||||
|
allSoundsExist = false;
|
||||||
|
|
||||||
|
for (i = 0; i < Array_Elems(soundAssets); i++)
|
||||||
|
{
|
||||||
|
Mem_Free(soundAssets[i].data);
|
||||||
|
soundAssets[i].data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct AssetSet mccSoundAssetSet = {
|
static const struct AssetSet mccSoundAssetSet = {
|
||||||
SoundAssets_CheckExistence,
|
SoundAssets_CheckExistence,
|
||||||
SoundAssets_CountMissing,
|
SoundAssets_CountMissing,
|
||||||
SoundAssets_DownloadAssets,
|
SoundAssets_DownloadAssets,
|
||||||
SoundAssets_GetRequestName,
|
SoundAssets_GetRequestName,
|
||||||
SoundAssets_CheckStatus
|
SoundAssets_CheckStatus,
|
||||||
|
SoundAssets_ResetState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -462,198 +669,21 @@ static void CCTextures_CheckStatus(void) {
|
|||||||
HttpRequest_Free(&item);
|
HttpRequest_Free(&item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CCTextures_ResetState(void) {
|
||||||
|
ccTexturesExist = false;
|
||||||
|
ccTexturesDownloaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct AssetSet ccTexsAssetSet = {
|
static const struct AssetSet ccTexsAssetSet = {
|
||||||
CCTextures_CheckExistence,
|
CCTextures_CheckExistence,
|
||||||
CCTextures_CountMissing,
|
CCTextures_CountMissing,
|
||||||
CCTextures_DownloadAssets,
|
CCTextures_DownloadAssets,
|
||||||
CCTextures_GetRequestName,
|
CCTextures_GetRequestName,
|
||||||
CCTextures_CheckStatus
|
CCTextures_CheckStatus,
|
||||||
|
CCTextures_ResetState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*------------------------------------------------------Zip entry writer---------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
static void GetCurrentZipDate(int* modTime, int* modDate) {
|
|
||||||
struct DateTime now;
|
|
||||||
DateTime_CurrentLocal(&now);
|
|
||||||
|
|
||||||
*modTime = (now.second / 2) | (now.minute << 5) | (now.hour << 11);
|
|
||||||
*modDate = (now.day) | (now.month << 5) | ((now.year - 1980) << 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_LocalFile(struct Stream* s, struct ResourceZipEntry* e) {
|
|
||||||
int filenameLen = String_Length(e->filename);
|
|
||||||
cc_uint8 header[30 + STRING_SIZE];
|
|
||||||
cc_result res;
|
|
||||||
int modTime, modDate;
|
|
||||||
|
|
||||||
GetCurrentZipDate(&modTime, &modDate);
|
|
||||||
if ((res = s->Position(s, &e->offset))) return res;
|
|
||||||
|
|
||||||
Stream_SetU32_LE(header + 0, 0x04034b50); /* signature */
|
|
||||||
Stream_SetU16_LE(header + 4, 20); /* version needed */
|
|
||||||
Stream_SetU16_LE(header + 6, 0); /* bitflags */
|
|
||||||
Stream_SetU16_LE(header + 8, 0); /* compression method */
|
|
||||||
Stream_SetU16_LE(header + 10, modTime); /* last modified */
|
|
||||||
Stream_SetU16_LE(header + 12, modDate); /* last modified */
|
|
||||||
|
|
||||||
Stream_SetU32_LE(header + 14, e->crc32); /* CRC32 */
|
|
||||||
Stream_SetU32_LE(header + 18, e->size); /* Compressed size */
|
|
||||||
Stream_SetU32_LE(header + 22, e->size); /* Uncompressed size */
|
|
||||||
|
|
||||||
Stream_SetU16_LE(header + 26, filenameLen); /* name length */
|
|
||||||
Stream_SetU16_LE(header + 28, 0); /* extra field length */
|
|
||||||
|
|
||||||
Mem_Copy(header + 30, e->filename, filenameLen);
|
|
||||||
return Stream_Write(s, header, 30 + filenameLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_CentralDir(struct Stream* s, struct ResourceZipEntry* e) {
|
|
||||||
int filenameLen = String_Length(e->filename);
|
|
||||||
cc_uint8 header[46 + STRING_SIZE];
|
|
||||||
int modTime, modDate;
|
|
||||||
GetCurrentZipDate(&modTime, &modDate);
|
|
||||||
|
|
||||||
Stream_SetU32_LE(header + 0, 0x02014b50); /* signature */
|
|
||||||
Stream_SetU16_LE(header + 4, 20); /* version */
|
|
||||||
Stream_SetU16_LE(header + 6, 20); /* version needed */
|
|
||||||
Stream_SetU16_LE(header + 8, 0); /* bitflags */
|
|
||||||
Stream_SetU16_LE(header + 10, 0); /* compression method */
|
|
||||||
Stream_SetU16_LE(header + 12, modTime); /* last modified */
|
|
||||||
Stream_SetU16_LE(header + 14, modDate); /* last modified */
|
|
||||||
|
|
||||||
Stream_SetU32_LE(header + 16, e->crc32); /* CRC32 */
|
|
||||||
Stream_SetU32_LE(header + 20, e->size); /* compressed size */
|
|
||||||
Stream_SetU32_LE(header + 24, e->size); /* uncompressed size */
|
|
||||||
|
|
||||||
Stream_SetU16_LE(header + 28, filenameLen); /* name length */
|
|
||||||
Stream_SetU16_LE(header + 30, 0); /* extra field length */
|
|
||||||
Stream_SetU16_LE(header + 32, 0); /* file comment length */
|
|
||||||
Stream_SetU16_LE(header + 34, 0); /* disk number */
|
|
||||||
Stream_SetU16_LE(header + 36, 0); /* internal attributes */
|
|
||||||
Stream_SetU32_LE(header + 38, 0); /* external attributes */
|
|
||||||
Stream_SetU32_LE(header + 42, e->offset); /* local header offset */
|
|
||||||
|
|
||||||
Mem_Copy(header + 46, e->filename, filenameLen);
|
|
||||||
return Stream_Write(s, header, 46 + filenameLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_EndOfCentralDir(struct Stream* s, int numEntries,
|
|
||||||
cc_uint32 centralDirBeg, cc_uint32 centralDirEnd) {
|
|
||||||
cc_uint8 header[22];
|
|
||||||
|
|
||||||
Stream_SetU32_LE(header + 0, 0x06054b50); /* signature */
|
|
||||||
Stream_SetU16_LE(header + 4, 0); /* disk number */
|
|
||||||
Stream_SetU16_LE(header + 6, 0); /* disk number of start */
|
|
||||||
Stream_SetU16_LE(header + 8, numEntries); /* disk entries */
|
|
||||||
Stream_SetU16_LE(header + 10, numEntries); /* total entries */
|
|
||||||
Stream_SetU32_LE(header + 12, centralDirEnd - centralDirBeg); /* central dir size */
|
|
||||||
Stream_SetU32_LE(header + 16, centralDirBeg); /* central dir start */
|
|
||||||
Stream_SetU16_LE(header + 20, 0); /* comment length */
|
|
||||||
return Stream_Write(s, header, 22);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_FixupLocalFile(struct Stream* s, struct ResourceZipEntry* e) {
|
|
||||||
int filenameLen = String_Length(e->filename);
|
|
||||||
cc_uint8 tmp[2048];
|
|
||||||
cc_uint32 dataBeg, dataEnd;
|
|
||||||
cc_uint32 i, crc, toRead, read;
|
|
||||||
cc_result res;
|
|
||||||
|
|
||||||
dataBeg = e->offset + 30 + filenameLen;
|
|
||||||
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 = ZipWriter_LocalFile(s, e))) return res;
|
|
||||||
return s->Seek(s, dataEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_WriteData(struct Stream* dst, struct ResourceZipEntry* e) {
|
|
||||||
cc_uint8* data = e->value.data;
|
|
||||||
cc_result res;
|
|
||||||
e->crc32 = Utils_CRC32(data, e->size);
|
|
||||||
|
|
||||||
if ((res = ZipWriter_LocalFile(dst, e))) return res;
|
|
||||||
return Stream_Write(dst, data, e->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cc_result ZipWriter_WritePng(struct Stream* dst, struct ResourceZipEntry* e) {
|
|
||||||
struct Bitmap* src = &e->value.bmp;
|
|
||||||
cc_result res;
|
|
||||||
|
|
||||||
if ((res = ZipWriter_LocalFile(dst, e))) return res;
|
|
||||||
if ((res = Png_Encode(src, dst, NULL, true, NULL))) return res;
|
|
||||||
return ZipWriter_FixupLocalFile(dst, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
|
||||||
*------------------------------------------------------Zip file writer----------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
static cc_result ZipFile_WriteEntries(struct Stream* s, struct ResourceZipEntry* entries, int numEntries) {
|
|
||||||
struct ResourceZipEntry* e;
|
|
||||||
cc_uint32 beg, end;
|
|
||||||
int i;
|
|
||||||
cc_result res;
|
|
||||||
|
|
||||||
for (i = 0; i < numEntries; i++)
|
|
||||||
{
|
|
||||||
e = &entries[i];
|
|
||||||
|
|
||||||
if (e->type == RESOURCE_TYPE_PNG) {
|
|
||||||
if ((res = ZipWriter_WritePng(s, e))) return res;
|
|
||||||
} else {
|
|
||||||
if ((res = ZipWriter_WriteData(s, e))) return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res = s->Position(s, &beg))) return res;
|
|
||||||
for (i = 0; i < numEntries; i++)
|
|
||||||
{
|
|
||||||
if ((res = ZipWriter_CentralDir(s, &entries[i]))) return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res = s->Position(s, &end))) return res;
|
|
||||||
return ZipWriter_EndOfCentralDir(s, numEntries, beg, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ZipFile_Create(cc_string* path, struct ResourceZipEntry* entries, int numEntries) {
|
|
||||||
struct Stream s;
|
|
||||||
cc_result res;
|
|
||||||
|
|
||||||
res = Stream_CreateFile(&s, path);
|
|
||||||
if (res) {
|
|
||||||
Logger_SysWarn2(res, "creating", path); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = ZipFile_WriteEntries(&s, entries, numEntries);
|
|
||||||
if (res) Logger_SysWarn2(res, "making", path);
|
|
||||||
|
|
||||||
res = s.Close(&s);
|
|
||||||
if (res) Logger_SysWarn2(res, "closing", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*----------------------------------------------------default.zip resources------------------------------------------------*
|
*----------------------------------------------------default.zip resources------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
@ -998,6 +1028,7 @@ static void MCCTextures_DownloadAssets(void) {
|
|||||||
{
|
{
|
||||||
url = String_FromReadonly(defaultZipSources[i].url);
|
url = String_FromReadonly(defaultZipSources[i].url);
|
||||||
defaultZipSources[i].reqID = Http_AsyncGetData(&url, 0);
|
defaultZipSources[i].reqID = Http_AsyncGetData(&url, 0);
|
||||||
|
defaultZipSources[i].downloaded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1046,12 +1077,29 @@ static void MCCTextures_CheckStatus(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MCCTextures_ResetState(void) {
|
||||||
|
int i;
|
||||||
|
allZipEntriesExist = false;
|
||||||
|
zipEntriesFound = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < Array_Elems(defaultZipEntries); i++)
|
||||||
|
{
|
||||||
|
if (defaultZipEntries[i].type == RESOURCE_TYPE_CONST) continue;
|
||||||
|
|
||||||
|
/* can reuse value.data for value.bmp case too */
|
||||||
|
Mem_Free(defaultZipEntries[i].value.data);
|
||||||
|
defaultZipEntries[i].value.data = NULL;
|
||||||
|
defaultZipEntries[i].size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct AssetSet mccTexsAssetSet = {
|
static const struct AssetSet mccTexsAssetSet = {
|
||||||
MCCTextures_CheckExistence,
|
MCCTextures_CheckExistence,
|
||||||
MCCTextures_CountMissing,
|
MCCTextures_CountMissing,
|
||||||
MCCTextures_DownloadAssets,
|
MCCTextures_DownloadAssets,
|
||||||
MCCTextures_GetRequestName,
|
MCCTextures_GetRequestName,
|
||||||
MCCTextures_CheckStatus
|
MCCTextures_CheckStatus,
|
||||||
|
MCCTextures_ResetState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1069,11 +1117,21 @@ static const struct AssetSet* const asset_sets[] = {
|
|||||||
&mccSoundAssetSet
|
&mccSoundAssetSet
|
||||||
};
|
};
|
||||||
|
|
||||||
void Resources_CheckExistence(void) {
|
static void ResetState() {
|
||||||
int i;
|
int i;
|
||||||
Resources_Count = 0;
|
Resources_Count = 0;
|
||||||
Resources_Size = 0;
|
Resources_Size = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < Array_Elems(asset_sets); i++)
|
||||||
|
{
|
||||||
|
asset_sets[i]->ResetState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resources_CheckExistence(void) {
|
||||||
|
int i;
|
||||||
|
ResetState();
|
||||||
|
|
||||||
for (i = 0; i < Array_Elems(asset_sets); i++)
|
for (i = 0; i < Array_Elems(asset_sets); i++)
|
||||||
{
|
{
|
||||||
asset_sets[i]->CheckExistence();
|
asset_sets[i]->CheckExistence();
|
||||||
@ -1111,18 +1169,9 @@ void Fetcher_Run(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Fetcher_Finish(void) {
|
static void Fetcher_Finish(void) {
|
||||||
int i;
|
|
||||||
Fetcher_Completed = true;
|
Fetcher_Completed = true;
|
||||||
Fetcher_Working = false;
|
Fetcher_Working = false;
|
||||||
|
ResetState();
|
||||||
for (i = 0; i < Array_Elems(defaultZipEntries); i++) {
|
|
||||||
if (defaultZipEntries[i].type == RESOURCE_TYPE_CONST) continue;
|
|
||||||
|
|
||||||
/* can reuse value.data for value.bmp case too */
|
|
||||||
Mem_Free(defaultZipEntries[i].value.data);
|
|
||||||
defaultZipEntries[i].value.data = NULL;
|
|
||||||
defaultZipEntries[i].size = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Fetcher_Fail(struct HttpRequest* item) {
|
static void Fetcher_Fail(struct HttpRequest* item) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user