void decode_protobuf(char *buf, char *buf_end, yield_t yield) { while(buf < buf_end) { uint64_t key = decode_varint(buf, &buf); struct key_value_pair pair = { .field_number = key >> 3, .wire_type = key & 0x07 }; switch(pair.wire_type) { case WT_VARINT: /* varint */ pair.value.varint = decode_varint(buf, &buf); break; case WT_64BIT: /* 64 bit */ pair.value._64_bit = get_32_le(buf, &buf); buf += 4; pair.value._64_bit |= (uint64_t)get_32_le(buf, &buf) << 32; buf += 4; break; case WT_STRING: /* string */ pair.value.string.len = decode_varint(buf, &buf); pair.value.string.start = buf; buf += pair.value.string.len; break; case WT_32BIT: /* 32 bit */ pair.value._32_bit = get_32_le(buf, &buf); buf += 4; break; } yield(&pair); } } void yield_cb(struct key_value_pair *pair) { printf("Field number: %d, Wire type: %d\n", pair->field_number, pair->wire_type); }
int main(int argc, char **argv) { /* input file name */ const char *infile_name = NULL; CHECK_ERROR(argc != 2, "needs one argument: file to work on"); infile_name = argv[1]; /* input file */ FILE *infile = fopen(infile_name, "rb"); CHECK_ERRNO(NULL == infile, "input file open failed"); CHECK_ERROR(get_32_le(infile) != 3 || get_32_le(infile) != 0 || get_32_le(infile) != 3 || get_32_le(infile) != 1 || get_32_le(infile) != 0,"whither 30310?!?"); const uint32_t data_size = get_32_le(infile); printf("data size = 0x08%" PRIx32 "\n", data_size); const uint32_t header_size = get_32_le(infile); printf("header size = 0x%08" PRIx32 "\n", header_size); process_dir_list(0x1C, header_size, data_size, infile); }
int main(int argc, char ** argv) { if (argc != 3) { fprintf(stderr, "usage: %s infile.WwiseBank outfile_prefix\n", argv[0]); return 1; } FILE *infile = fopen(argv[1], "rb"); CHECK_ERRNO(!infile, "failed opening input"); const char * outfile_prefix = argv[2]; CHECK_ERROR(UINT32_C(-1) != get_32_be(infile), "missing magic -1"); long DATA_offset = -1; uint32_t DATA_size = 0; { int done = 0; long chunk_start = 0x80; // top level wwise chunks loop while (!done) { CHECK_ERRNO(-1 == fseek(infile, chunk_start, SEEK_SET), "fseek to BKHD chunk failed"); const uint32_t chunk_id = get_32_be(infile); const uint32_t chunk_size = get_32_be(infile); switch (chunk_id) { case UINT32_C(0x424B4844): // BKHD: Bank Header? case UINT32_C(0x44494458): // DIDX: Data Index? case UINT32_C(0x48495243): // HIRC case UINT32_C(0x53544944): // STID: Stream Identifier? break; case UINT32_C(0): // 16 bytes padding at end, starting with 0s done = 1; break; case UINT32_C(0x44415441): // DATA: body DATA_offset = chunk_start + 8; DATA_size = chunk_size; break; default: CHECK_ERROR(1, "unknown chunk id"); break; } chunk_start += 8 + chunk_size; } CHECK_ERROR(DATA_offset == -1, "no DATA chunk found in BKHD"); } { int file_idx = 0; long subfile_offset = DATA_offset; // subfile loop while (subfile_offset < DATA_offset + DATA_size) { CHECK_ERRNO(-1 == fseek(infile, subfile_offset, SEEK_SET), "fseek to subfile failed"); const uint32_t subfile_id = get_32_be(infile); const uint32_t subfile_size = get_32_le(infile); // SAY WHAT?!? switch (subfile_id) { case UINT32_C(0x52494658): // RIFX break; default: CHECK_ERROR(1, "unexpected subfile type"); break; } handle_RIFX(subfile_size, infile, outfile_prefix, file_idx); subfile_offset += subfile_size; file_idx ++; } } return 0; }
uint32_t get_32_le_seek(long offset, FILE *infile) { CHECK_ERRNO(fseek(infile, offset, SEEK_SET) != 0, "fseek"); return get_32_le(infile); }
int main(int argc, char **argv) { const char *infile_name = NULL; const char *outfile_name = NULL; if (argc != 3) { fprintf(stderr, "build GENH from Taiko no Tatsukin Atsumete Tomodachi Daisakusen .nus3bank\n"); fprintf(stderr, "usage: ttatd SONG_YUGEN.nus3bank SONG_YUGEN.genh\n"); return -1; } infile_name = argv[1]; outfile_name = argv[2]; FILE *infile = fopen(infile_name, "rb"); CHECK_ERRNO(NULL == infile, "input file open failed"); const long nus3_offset = 0; EXPECT_32_BE(nus3_offset, infile, 0x4E555333, "NUS3"); const long nus3_size = get_32_le_seek(nus3_offset + 4, infile) + 8; const long nus3_end = nus3_offset + nus3_size; EXPECT_32_BE(nus3_offset + 8, infile, 0x42414E4B, "BANK"); long chunk_offset = nus3_offset + 12; long PACK_offset = -1; uint32_t PACK_size = 0; /* scan to find PACK */ while (chunk_offset < nus3_end) { uint32_t chunk_type = get_32_be_seek(chunk_offset, infile); long chunk_size = get_32_le(infile); //printf("offset: %"PRIx32" type: %"PRIx32" size: %"PRIx32"\n", (uint32_t)chunk_offset, chunk_type, (uint32_t)chunk_size); switch (chunk_type) { case UINT32_C(0x544F4320): /* TOC */ case UINT32_C(0x50524F50): /* PROP */ case UINT32_C(0x42494E46): /* BINF */ case UINT32_C(0x47525020): /* GRP */ case UINT32_C(0x44544F4E): /* DTON */ case UINT32_C(0x544F4E45): /* TONE */ case UINT32_C(0x4A554E4B): /* JUNK */ break; case UINT32_C(0x5041434B): /* PACK */ CHECK_ERROR(PACK_offset != -1, "expected only one PACK"); PACK_offset = chunk_offset + 8; PACK_size = chunk_size; break; default: fprintf(stderr, "unexpected chunk %"PRIx32" at 0x%lx\n", chunk_type, chunk_offset); CHECK_ERROR(1, "who knows?"); break; } chunk_offset += 8 + chunk_size; CHECK_ERROR(chunk_offset > nus3_end, "truncated chunk"); } CHECK_ERROR(PACK_offset == -1, "missing PACK"); const long IDSP_offset = PACK_offset; EXPECT_32_BE(IDSP_offset, infile, 0x49445350, "IDSP"); EXPECT_32_BE(IDSP_offset + 4, infile, 0, "0 at IDSP+4"); const uint32_t channels = get_32_be_seek(IDSP_offset + 0x08, infile); CHECK_ERROR(channels != 1 && channels != 2, "only mono and stereo supported in GENH"); const uint32_t sample_rate = get_32_be_seek(IDSP_offset + 0x0c, infile); const uint32_t sample_count= get_32_be_seek(IDSP_offset + 0x10, infile); EXPECT_32_BE(IDSP_offset + 0x14, infile, 0, "0 at IDSP+0x14"); EXPECT_32_BE(IDSP_offset + 0x18, infile, 0, "0 at IDSP+0x18"); EXPECT_32_BE(IDSP_offset + 0x1c, infile, 0, "0 at IDSP+0x1c"); const uint32_t ch_head_offset = get_32_be_seek(IDSP_offset + 0x20, infile); const uint32_t ch_head_size = get_32_be_seek(IDSP_offset + 0x24, infile); const uint32_t ch_body_offset = get_32_be_seek(IDSP_offset + 0x28, infile); const uint32_t ch_body_size = get_32_be_seek(IDSP_offset + 0x2c, infile); CHECK_ERROR(ch_head_size != 0x60, "expected 0x60 header per channel"); int loop_flag = 0; int loop_start = 0; int loop_end = 0; /* read header for checking and loop info */ for (unsigned int c = 0; c < channels; c++) { struct dsp_header h; read_dsp_header(&h, infile, IDSP_offset + ch_head_offset + ch_head_size * c); CHECK_ERROR(h.sample_count != sample_count, "sample count mismatch"); CHECK_ERROR(dsp_nibbles_to_samples(h.nibble_count) != sample_count, "nibble count mismatch"); CHECK_ERROR(h.sample_rate != sample_rate, "sample rate mismatch"); CHECK_ERROR(h.format != 0, "not DSP format?"); CHECK_ERROR(c > 0 && ((h.loop_flag && !loop_flag) || (!h.loop_flag && loop_flag)), "loop flag mismatch"); if (h.loop_flag) { loop_flag = 1; uint32_t new_loop_start = dsp_nibbles_to_samples(h.loop_start_offset); uint32_t new_loop_end = dsp_nibbles_to_samples(h.loop_end_offset); if (c > 0) { CHECK_ERROR(loop_start != new_loop_start || loop_end != new_loop_end, "loop point mismatch"); } loop_start = new_loop_start; loop_end = new_loop_end; } } long IDSP_size = ch_head_offset + (ch_head_size + ch_body_size) * channels; CHECK_ERROR(IDSP_size != PACK_size, "IDSP size does not match PACK size"); /* build GENH */ unsigned char genh_head[0x38]; memset(genh_head, 0, sizeof(genh_head)); /* header magic */ memcpy(&genh_head[0x00], "GENH", 4); /* channel count */ write_32_le(channels, &genh_head[0x04]); /* interleave */ if (channels == 1) { write_32_le(0, &genh_head[0x08]); } else if (channels == 2) { // no interleave, but GENH does split data like this write_32_le(ch_body_size, &genh_head[0x08]); } /* sample rate */ write_32_le(sample_rate, &genh_head[0x0c]); /* loop start */ if (loop_flag) { write_32_le(loop_start, &genh_head[0x10]); } else { write_32_le(~UINT32_C(0), &genh_head[0x10]); } /* loop end */ if (loop_flag) { write_32_le(loop_end, &genh_head[0x14]); } else { write_32_le(sample_count, &genh_head[0x14]); } /* coding type, coding_NGC_DSP */ write_32_le(12, &genh_head[0x18]); /* start_offset */ write_32_le(0x38 + IDSP_offset + ch_body_offset, &genh_head[0x1c]); /* header_size */ write_32_le(0x38, &genh_head[0x20]); /* dsp coefs */ write_32_le(0x38 + IDSP_offset + ch_head_offset + 0x1c, &genh_head[0x24]); if (channels == 2) { write_32_le(0x38 + IDSP_offset + ch_head_offset + ch_head_size + 0x1c, &genh_head[0x28]); } /* dsp interleave type */ if (channels == 1) { /* no interleave */ write_32_le(2, &genh_head[0x2c]); } /* normal coefs */ //write_32_le(0, &genh_head[0x30]); FILE *outfile = fopen(outfile_name, "wb"); CHECK_ERRNO(NULL == outfile, "output file open failed"); put_bytes(outfile, genh_head, sizeof(genh_head)); dump(infile, outfile, nus3_offset, nus3_size); CHECK_ERRNO(EOF == fclose(outfile), "fclose of output file"); }
void analyze_Huf8(FILE *infile, FILE *outfile, long file_length) { unsigned char *decode_table = NULL; int decode_table_size; long decoded_length; int symbol_count; /* read header */ { unsigned char buf[5]; get_bytes_seek(0, infile, buf, 5); CHECK_ERROR (buf[0] != 0x28, "not 8-bit Huffman"); decoded_length = read_24_le(&buf[1]); symbol_count = buf[4] + 1; } /* allocate decode table */ decode_table_size = symbol_count * 2 - 1; decode_table = malloc(decode_table_size); CHECK_ERRNO(decode_table == NULL, "malloc"); /* read decode table */ get_bytes(infile, decode_table, decode_table_size); #if 0 printf("encoded size = %ld bytes (%d header + %ld body)\n", file_length, 5 + decode_table_size, file_length - (5 + decode_table_size)); printf("decoded size = %ld bytes\n", decoded_length); #endif /* decode */ { uint32_t bits; int bits_left = 0; int table_offset = 0; long bytes_decoded = 0; while ( bytes_decoded < decoded_length ) { if (bits_left == 0) { bits = get_32_le(infile); bits_left = 32; } int current_bit = ((bits & 0x80000000) != 0); int next_offset = ((table_offset + 1) / 2 * 2) + 1 + (decode_table[table_offset] & 0x3f) * 2 + (current_bit ? 1 : 0); #if 0 printf("%d %02x %lx => %lx\n", current_bit, decode_table[table_offset], (unsigned long)table_offset, (unsigned long)next_offset); #endif CHECK_ERROR (next_offset >= decode_table_size, "reading past end of decode table"); if ((!current_bit && (decode_table[table_offset] & 0x80)) || ( current_bit && (decode_table[table_offset] & 0x40))) { CHECK_FILE( fwrite(&decode_table[next_offset], 1, 1, outfile) != 1, outfile, "fwrite"); bytes_decoded++; #if 0 printf("%02x\n", decode_table[next_offset]); return; #endif next_offset = 0; } CHECK_ERROR (next_offset == table_offset, "stuck in a loop somehow"); table_offset = next_offset; bits_left--; bits <<= 1; } } #if 0 printf("done\n"); #endif }