wad_writer.c (3136B)
1 #include "libriot/wad.h" 2 3 static b32 4 riot_wad_chunk_write(struct riot_wad_ctx *ctx, struct riot_wad_chunk *chunk, struct mem_stream *stream); 5 6 b32 7 riot_wad_write(struct riot_wad_ctx *ctx, void *data, u64 len, struct mem_stream stream) { 8 assert(ctx); 9 10 char magic[2] = { 'R', 'W', }; 11 if (!mem_stream_push(&stream, magic, sizeof magic)) { 12 errlog("Failed to write WAD magic"); 13 return false; 14 } 15 16 if (!riot_mem_stream_write_u8(&stream, 3)) { 17 errlog("Failed to write WAD version major"); 18 return false; 19 } 20 21 if (!riot_mem_stream_write_u8(&stream, 1)) { 22 errlog("Failed to write WAD version minor"); 23 return false; 24 } 25 26 u32 ecdsa_signature_length = 256; 27 u8 signature[ecdsa_signature_length]; 28 memset(signature, 0, ecdsa_signature_length); 29 if (!mem_stream_push(&stream, signature, ecdsa_signature_length)) { 30 errlog("Failed to write v3 signature (%u bytes)", ecdsa_signature_length); 31 return false; 32 } 33 34 u64 checksum = 0; 35 if (!riot_mem_stream_write_u64(&stream, checksum)) { 36 errlog("Failed to write v3 signature checksum"); 37 return false; 38 } 39 40 if (!riot_mem_stream_write_u32(&stream, ctx->wad.chunk_count)) { 41 errlog("Failed to write WAD chunk count"); 42 return false; 43 } 44 45 for (u32 i = 0; i < ctx->wad.chunk_count; i++) { 46 struct riot_wad_chunk *chunk = (struct riot_wad_chunk *)ctx->chunk_pool.ptr + i; 47 if (!riot_wad_chunk_write(ctx, chunk, &stream)) { 48 errlog("Failed to write WAD chunk %u/%u", i + 1, ctx->wad.chunk_count); 49 return false; 50 } 51 } 52 53 if (!mem_stream_push(&stream, data, len)) { 54 errlog("Failed to write WAD data segment"); 55 return false; 56 } 57 58 return true; 59 } 60 61 static b32 62 riot_wad_chunk_write(struct riot_wad_ctx *ctx, struct riot_wad_chunk *chunk, struct mem_stream *stream) { 63 assert(ctx); 64 assert(chunk); 65 assert(stream); 66 67 if (!riot_mem_stream_write_xxh64_u64(stream, chunk->path_hash)) { 68 errlog("Failed to write WAD chunk path hash"); 69 return false; 70 } 71 72 if (!riot_mem_stream_write_u32(stream, chunk->data_offset)) { 73 errlog("Failed to write WAD chunk data offset"); 74 return false; 75 } 76 77 if (!riot_mem_stream_write_u32(stream, chunk->compressed_size)) { 78 errlog("Failed to write WAD chunk compressed data size"); 79 return false; 80 } 81 82 if (!riot_mem_stream_write_u32(stream, chunk->decompressed_size)) { 83 errlog("Failed to write WAD chunk decompressed data size"); 84 return false; 85 } 86 87 u8 sub_chunk_count_and_compression_type = 0; 88 sub_chunk_count_and_compression_type |= (chunk->sub_chunk_count << 4); 89 sub_chunk_count_and_compression_type |= (u8)chunk->compression & 0xf; 90 if (!riot_mem_stream_write_u8(stream, sub_chunk_count_and_compression_type)) { 91 errlog("Failed to write WAD chunk sub-chunk count and compression type byte"); 92 return false; 93 } 94 95 if (!riot_mem_stream_write_b8(stream, chunk->duplicated)) { 96 errlog("Failed to write WAD chunk duplicated flag"); 97 return false; 98 } 99 100 if (!riot_mem_stream_write_u16(stream, chunk->sub_chunk_start)) { 101 errlog("Failed to write WAD chunk sub-chunk start"); 102 return false; 103 } 104 105 u64 checksum = 0; 106 if (!riot_mem_stream_write_u64(stream, checksum)) { 107 errlog("Failed to write WAD chunk checksum"); 108 return false; 109 } 110 111 return true; 112 }