diff options
author | Damien Zammit <damien@zamaudio.com> | 2019-06-15 14:37:13 +1000 |
---|---|---|
committer | Damien Zammit <damien@zamaudio.com> | 2019-06-15 14:37:13 +1000 |
commit | fc57bfa3bd136c878627eda2088cf2fa915692ad (patch) | |
tree | b471740d1479475691d6ec20b2a04d336c0f41af | |
parent | 756ba0746af5ca054566e6fd3c5b91acf5cb24bf (diff) |
WIP block parsing support
-rw-r--r-- | ptfformat.cc | 99 | ||||
-rw-r--r-- | ptformat/ptfformat.h | 17 | ||||
-rwxr-xr-x | re/blocks.js | 2 |
3 files changed, 111 insertions, 7 deletions
diff --git a/ptfformat.cc b/ptfformat.cc index 4c35e3f..fcbe90c 100644 --- a/ptfformat.cc +++ b/ptfformat.cc @@ -55,16 +55,17 @@ static bool regname_compare(PTFFormat::region_t& r1, PTFFormat::region_t& r2) { } static void -hexdump(uint8_t *data, int len) +hexdump(uint8_t *data, int length, int level) { - int i,j,end,step=16; + int i,j,k,end,step=16; - for (i = 0; i < len; i += step) { - printf("0x%02X: ", i); + for (i = 0; i < length; i += step) { end = i + step; - if (end > len) end = len; + if (end > length) end = length; + for (k = 0; k < level; k++) + printf(" "); for (j = i; j < end; j++) { - printf("0x%02X ", data[j]); + printf("%02X ", data[j]); } for (j = i; j < end; j++) { if (data[j] < 128 && data[j] > 32) @@ -337,6 +338,10 @@ PTFFormat::parse_version() { uint8_t seg_type; bool success = false; + if (ptfunxored[0] != '\x03' && foundat(ptfunxored, 0x100, BITCODE) != 1) { + return false; + } + while( ((uintptr_t)data < data_end) && (success == false) ) { if (data[0] != 0x5a) { @@ -421,6 +426,7 @@ PTFFormat::gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative) { return 0; } +/* int PTFFormat::parse(void) { if (version == 5) { @@ -469,6 +475,7 @@ PTFFormat::parse(void) { } return 0; } +*/ void PTFFormat::setrates(void) { @@ -478,6 +485,86 @@ PTFFormat::setrates(void) { } } +bool +PTFFormat::parse_block_at(uint32_t pos, struct block_t *block, int level) { + struct block_t b; + int childjump; + int i; + + if (pos + 7 > len) + return false; + if (level > 10) + return false; + if (ptfunxored[pos] != ZMARK) + return false; + + b.zmark = ZMARK; + b.block_type = u_endian_read2(&ptfunxored[pos+1], is_bigendian); + b.block_size = u_endian_read4(&ptfunxored[pos+3], is_bigendian); + b.content_type = u_endian_read2(&ptfunxored[pos+7], is_bigendian); + b.offset = pos + 7; + + if (b.block_size + b.offset > len) + return false; + if (b.block_type & 0xff00) + return false; + + block->zmark = b.zmark; + block->block_type = b.block_type; + block->block_size = b.block_size; + block->content_type = b.content_type; + block->offset = b.offset; + + for (i = 1; (i < block->block_size) && (pos + i + childjump < len); i += childjump ? childjump : 1) { + int p = pos + i; + struct block_t bchild; + childjump = 0; + if (parse_block_at(p, &bchild, level+1)) { + block->child.push_back(bchild); + childjump = bchild.block_size + 7; + } + } + return true; +} + +void +PTFFormat::dump_block(struct block_t& b, int level) +{ + int i; + + for (i = 0; i < level; i++) { + printf(" "); + } + printf("Content type=0x%04x\n", b.content_type); + + hexdump(&ptfunxored[b.offset], b.block_size, level); + + for (vector<PTFFormat::block_t>::iterator c = b.child.begin(); + c != b.child.end(); ++c) { + dump_block(*c, level + 1); + } +} + +int +PTFFormat::parse(void) { + uint32_t i = 20; + + while (i < len) { + struct block_t b; + if (parse_block_at(i, &b, 0)) { + blocks.push_back(b); + } + i += b.block_size ? b.block_size + 7 : 1; + } + + for (vector<PTFFormat::block_t>::iterator b = blocks.begin(); + b != blocks.end(); ++b) { + dump_block(*b, 0); + } + return 0; +} + + void PTFFormat::parse5header(void) { uint32_t k; diff --git a/ptformat/ptfformat.h b/ptformat/ptfformat.h index 72dc64c..d98c37e 100644 --- a/ptformat/ptfformat.h +++ b/ptformat/ptfformat.h @@ -28,6 +28,9 @@ #include <stdint.h> #include "ptformat/visibility.h" +#define BITCODE "0010111100101011" +#define ZMARK '\x5a' + class LIBPTFORMAT_API PTFFormat { public: PTFFormat(); @@ -43,6 +46,17 @@ public: */ int unxor(std::string path); + struct block_t; + + struct block_t { + uint8_t zmark; // 'Z' + uint16_t block_type; // type of block + uint32_t block_size; // size of block + uint16_t content_type; // type of content + uint32_t offset; // offset in file + std::vector<block_t> child; // vector of child blocks + }; + struct wav_t { std::string filename; uint16_t index; @@ -108,6 +122,7 @@ public: } } track_t; + std::vector<block_t> blocks; std::vector<wav_t> audiofiles; std::vector<region_t> regions; std::vector<region_t> midiregions; @@ -166,6 +181,8 @@ private: uint64_t u_endian_read5(unsigned char *buf, bool); int parse(void); + bool parse_block_at(uint32_t pos, struct block_t *b, int level); + void dump_block(struct block_t& b, int level); bool parse_version(); uint8_t gen_xor_delta(uint8_t xor_value, uint8_t mul, bool negative); void setrates(void); diff --git a/re/blocks.js b/re/blocks.js index 9552945..08ccdb4 100755 --- a/re/blocks.js +++ b/re/blocks.js @@ -34,7 +34,7 @@ function readBlockAt (buffer, pos, parentBlock) { return; } const blockType = isBigEndian ? file.readUInt16BE(pos + 1) : file.readUInt16LE(pos + 1); - if (blockType > 0xf) { + if (blockType > 0xff) { console.log("Blocktype out of range, skipping"); return; } |