diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/demo.c | 186 | ||||
| -rw-r--r-- | src/main.c | 40 | ||||
| -rw-r--r-- | src/pack.c | 35 |
3 files changed, 257 insertions, 4 deletions
@@ -1,15 +1,29 @@ #include "../inc/demo.h" +#include "../inc/huffman.h" +#include "../inc/pack.h" #include <stdio.h> +#include <stdlib.h> +#include <string.h> + +const unsigned char CHUNK_TICK_MASK = 0b10000000; +const unsigned char CHUNK_TICK_KEYFRAME_MASK = 0b01000000; +const unsigned char CHUNK_TICK_INLINE_MASK = 0b00100000; +const unsigned char CHUNK_TYPE_MASK = 0b01100000; // TODO add NORMAL_ +const unsigned char CHUNK_SIZE_MASK = 0b00011111; + +const unsigned char mapmagic[] = {0x6b, 0xe6, 0xda, 0x4a, 0xce, 0xbd, 0x38, 0x0c, + 0x9b, 0x5b, 0x12, 0x89, 0xc8, 0x42, 0xd7, 0x80}; int reverseint(const unsigned char in[4]) { return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3]; } +// TODO make version sensitive int readdemoheader(FILE *fp, demoheader *dh) { - if (fscanf(fp,"TWDEMO%*c%c", &dh->version) != 1) + if (fscanf(fp, "TWDEMO%*c%c", &dh->version) != 1) return -1; if (fscanf(fp, "%64c", dh->netversion) != 1) return -2; @@ -41,4 +55,172 @@ int readdemotimeline(FILE *fp, demotimeline *dt) if (fscanf(fp, "%260c", dt->data) != 1) return -1; return 1; -}
\ No newline at end of file +} + +// TODO make version sensitive +int readdemomap(FILE *fp, demomap *dm, int mapsize) +{ + char magicbuf[sizeof(mapmagic)]; + fread(magicbuf, 1, sizeof(mapmagic), fp); + + if (memcmp(magicbuf, mapmagic, sizeof(mapmagic)) != 0) + return -1; + + if (fread(dm->sha256, 1, 32, fp) != 32) + return -2; + + if (fread(dm->data, 1, mapsize, fp) != mapsize) + return -3; + + return 1; +} + +int readdemotick(FILE *fp, char chunkhead, demotick *tick, unsigned char ver) +{ + tick->keyframe = (chunkhead & CHUNK_TICK_KEYFRAME_MASK); + + if (ver >= 5) + { + if (chunkhead & CHUNK_TICK_INLINE_MASK) + { + tick->innline = 1; + tick->delta = (chunkhead & 0x1f); // TODO name this mask? + } + else + { + tick->innline = 0; + unsigned char tickdelta[4]; + fread(tickdelta, 1, 4, fp); + tick->delta = reverseint(tickdelta); + } + } + else + { + if ((chunkhead & 0x3f) != 0) // TODO name this mask? + tick->delta = (chunkhead & 0x3f); + else + { + unsigned char tickdelta[4]; + fread(tickdelta, 1, 4, fp); + } + } + return 1; +} + +int readdemosnap(FILE *fp, demosnap *snap, int size) +{ + unsigned char data[size]; + unsigned char unpacked[1024 * 8]; + + fread(data, sizeof(unsigned char), size, fp); + + int r = decompresshuff((char *)data, size, (char *)unpacked, 1034 * 8); + + unsigned char *cp = unpacked; + + snap->datasize = readint(&cp); + snap->numitems = readint(&cp); + + snap->offsets = (int *)malloc(snap->numitems * sizeof(int)); + snap->items = (demosnapitem *)malloc(snap->numitems * sizeof(int)); + + for (int i = 0; i < snap->numitems; i++) + snap->offsets[i] = readint(&cp); + + for (int i = 0; i < snap->numitems; i++) + { + unsigned int item_key = (unsigned int)readint(&cp); + + snap->items[i].type = (item_key >> 16) & 0xffff; + snap->items[i].id = (item_key & 0xffff); + + if (i == (snap->numitems - 1)) + snap->items[i].numdata = (snap->datasize - snap->offsets[i]) / 4 - 1; + else + snap->items[i].numdata = (snap->offsets[i + 1] - snap->offsets[i]) / 4 - 1; + + snap->items[i].data = (int *)malloc(size * sizeof(int)); + + for (int y = 0; y < snap->items[i].numdata; y++) + snap->items[i].data[y] = readint(&cp); + } + + return 1; +} + +int readdemochunk(FILE *fp, demochunk *chunk, unsigned char ver) +{ + char chunkhead; + chunkhead = (char)fgetc(fp); + + if (chunkhead == EOF) + return 0; + + if (chunkhead & CHUNK_TICK_MASK) + { + demotick *tick = (demotick *)malloc(sizeof(demotick)); + if (readdemotick(fp, chunkhead, tick, ver)) + { + chunk->type = 4; + chunk->data.tick = tick; + printf("TICK={keyframe: %d, innline: %d, delta: %d}\n", tick->keyframe, tick->innline, tick->delta); + } + else + { + printf("[ ERROR ] error while reading tick!\n"); + return -1; + } + } + else + { + unsigned char type = (chunkhead & CHUNK_TYPE_MASK) >> 5; + short size = (chunkhead & CHUNK_SIZE_MASK); + + if (size == 30) + size = (short)fgetc(fp); + else if (size == 31) + fread(&size, sizeof(short), 1, fp); + + if (type == 1) + { + demosnap *snap = (demosnap *)malloc(sizeof(demosnap)); + if (readdemosnap(fp, snap, size)) + { + chunk->type = 1; // TODO make a chunk-type enum + chunk->data.snap = snap; + + printf("SNAPSHOT={datasize: %d, numitems: %d, offsets: [ ", snap->datasize, snap->numitems); + for (int i = 0; i < snap->numitems; i++) + printf("%d, ", snap->offsets[i]); + + printf("], items: [ "); + for (int i = 0; i < snap->numitems; i++) + { + printf("(type: %d, id: %d) { ", snap->items[i].type, snap->items[i].id); + for (int y = 0; y < snap->items[i].numdata; y++) + printf("%d, ", snap->items[i].data[y]); + printf("} "); + } + printf("]\n"); + } + else + { + printf("[ ERROR ] error while reading snapshot!\n"); + return -1; + } + } + else if (type == 2) + { + printf("MESSAGE={"); + fseek(fp, size, SEEK_CUR); + } + else if (type == 3) + { + printf("SNAPSHOT_DELTA={"); + fseek(fp, size, SEEK_CUR); + } + + printf("size: %d}\n", size); + } + return 1; +} @@ -1,9 +1,12 @@ #include "../inc/huffman.h" #include "../inc/demo.h" +#include "../inc/pack.h" #include <stdio.h> #include <stdlib.h> +#include <unistd.h> + int testcompress(char *line) { char inputbuff[4096]; @@ -109,16 +112,49 @@ int testdecompress(char *line) int main() { + inithuff(NULL); + FILE *fp = fopen("data/test.demo", "r"); + FILE *op = fopen("data/out.demo", "w"); + demoheader dh; demotimeline dt; + demomap dm; + int ret = readdemoheader(fp, &dh); - printf("\nheader: %i\n", ret); + dm.data = (unsigned char*) malloc(reverseint(dh.mapsize)); - ret = readdemotimeline(fp, &dt); + printf("\nheader: %i\n", ret); + + if (dh.version >= 4) + ret = readdemotimeline(fp, &dt); printf("\ntimeline: %i\n", ret); + + // TODO should be able to read 5 aswell, change readdemomap to fit + if (dh.version >= 6) + ret = readdemomap(fp, &dm, reverseint(dh.mapsize)); + printf("readdemomap ret: %d\n\n", ret); + + demochunk dc; + int i = 0; + while (readdemochunk(fp, &dc, dh.version) > 0) + { + i++; + } + printf("i: %d\n", i); + char c; + do + { + c = getc(fp); + // printf("%x\n", c & 0xff); + if (c != EOF) + { + putc(c, op); + } + } + while(c != EOF); return EXIT_SUCCESS; diff --git a/src/pack.c b/src/pack.c new file mode 100644 index 0000000..f7be2c8 --- /dev/null +++ b/src/pack.c @@ -0,0 +1,35 @@ +#include <stdio.h> + +int readint(unsigned char **cp) +{ + int result = 0; + int len = 1; + + unsigned char src = **cp; + + (*cp)++; + int sign = (src >> 6) & 1; + + result |= (src & 0b00111111); + for (int i = 0; i < 4; i++) + { + // printf("(%d, ", src); + if ((src & 0b10000000) == 0) + break; + + src = **cp; + (*cp)++; + len++; + + if (i == 3 && (src & 0b11110000) != 0) + printf("[ WARNING ] Non zero int padding!\n"); + + result |= (src & 0b01111111) << (6 + 7 * i); + } + if (len > 1 && src == 0b00000000) + printf("[ WARNING ] Overlong int encoding!\n"); + + result ^= -sign; + + return result; +} |
