📄 dataprocess.c
字号:
/* analyze the replay file */
#include "crc32.h"
#include "srv.h"
#include <zlib.h>
#define WAR3 0x57415233
#define W3XP 0x57335850
struct replay_header rh;
struct replay_block_header *rbh;
WORD ver;
BYTE *data;
DWORD datasize, gametime, dindex[8];
struct slot_s slot[12];
int readdata()
/* return 0: OK *
* -3: data corrupted *
* -4: memory error *
* -6: zlib version error */
{
const char header_match[]="Warcraft III recorded game\x1A";
DWORD i;
int j, status;
DWORD hcrc32, offset = 0;
void freemem();
/* read the header */
if (fread(&rh, 1, 0x30, in) < 0x30) return -3;
for (i=0;i<28;i++) if (header_match[i] - rh.header[i]) return -3;
if (rh.offset == 0x40 && rh.header_ver == 0x00) {
if (fread(&rh.sub_0, 1, 0x10, in) < 0x10) return -3;
} else if (rh.offset == 0x44 && rh.header_ver == 0x01) {
if (fread(&rh.sub_1, 1, 0x14, in) < 0x14) return -3;
} else return -3;
if (rh.header_ver == 0x00) {
if (rh.sub_0.flags != 0x0000 && rh.sub_0.flags != 0x8000) return -3;
hcrc32 = rh.sub_0.checksum;
rh.sub_0.checksum = 0;
if (hcrc32 - chksum_crc32((BYTE *) &rh, 0x40)) return -3;
rh.sub_0.checksum = hcrc32;
ver = rh.sub_0.major_ver;
gametime = rh.sub_0.length_ms;
} else {
if (rh.sub_1.flags != 0x0000 && rh.sub_1.flags != 0x8000) return -3;
if (rh.sub_1.ver_str != WAR3 && rh.sub_1.ver_str != W3XP) return -3;
hcrc32 = rh.sub_1.checksum;
rh.sub_1.checksum = 0;
if (hcrc32 - chksum_crc32((BYTE *) &rh, 0x44)) return -3;
rh.sub_1.checksum = hcrc32;
ver = rh.sub_1.major_ver;
gametime = rh.sub_1.length_ms;
}
/* read data blocks */
rbh = (struct replay_block_header *)
calloc(rh.blocks, sizeof(struct replay_block_header));
if (rbh == NULL) return -4;
for (i=0;i<rh.blocks;i++) {
if (fread(rbh + i, 1, 0x08, in) < 0x08) {
for (j=0;j<i;j++) free(rbh[j].data);
free(rbh);
return -4;
}
rbh[i].data = malloc(rbh[i].size);
if (rbh[i].data == NULL) {
for (j=0;j<i-1;j++) free(rbh[j].data);
free(rbh);
return -4;
}
if (fread(rbh[i].data, 1, rbh[i].size, in) < rbh[i].size)
for (j=0;j<i;j++) {
free(rbh[j].data);
free(rbh);
return -3;
}
}
/* decompress */
z_stream str;
data = (BYTE *) malloc(datasize = 8192L * rh.blocks);
if (data == NULL) {
for (i=0;i<rh.blocks;i++) free(rbh[i].data);
free(rbh);
return -4;
}
offset = 0;
for (i=0;i<rh.blocks;i++) {
str.next_in = (Bytef *) rbh[i].data;
str.avail_in = rbh[i].size;
str.zalloc = str.zfree = Z_NULL;
status = inflateInit(&str);
if (status) {
freemem();
return status;
}
str.next_out = (Bytef *) data + offset;
str.avail_out = datasize - offset;
status = inflate(&str,Z_SYNC_FLUSH);
if ((status && status != 1) ||
offset + str.avail_out + rbh[i].uncomp_size - datasize) {
freemem();
return -3;
}
offset += rbh[i].uncomp_size;
inflateEnd(&str);
}
for (i=rh.uncomp_size;i<datasize;i++) if (data[i]) {
freemem();
return -3;
}
/* set indices & slots */
dindex[0] = 4; // player record index
offset = 6;
slot[0].name = data + offset;
while (*(data + (offset++))) ; // player name
offset += 1 + *(data + offset); // additional data
dindex[1] = offset; // game name index
while (*(data + (offset++))) ; // game name
dindex[2] = ++offset; // encoded strings index
while (*(data + (offset++))) ; // encoded strings
dindex[3] = offset; // player count index
offset += 4; // player count
dindex[4] = offset; // game type index
offset += 8; // game type & unknown
dindex[5] = offset; // player list index
while (*(data + (offset)) == 0x16) {
offset++;
slot[*(data + offset)-1].name = data + offset + 1;
while (*(data + (offset++))) ; // player name
offset += 5 + *(data + offset); // additional data
}
dindex[6] = offset; // game start record index
offset += 3;
int nr = *(data + (offset++));
for (i=0;i<nr;i++) {
offset += 2;
if (*(data + offset) < 0x02) // *(data + offset) == 0x00 or 0x01
slot[i] = ((struct slot_s) {*(data + offset), NULL});
else if (*(data + offset + 1)) // computer
slot[i] = ((struct slot_s) {2, ""});
else if (*(data + offset + 2) == 12) // observer
slot[i].status = 3;
else // player
slot[i].status = 4;
offset += (ver < 3) ? 5 : ((ver < 7) ? 6 : 7);
}
for (;i<12;i++) slot[i] = ((struct slot_s) {-1, NULL});
offset += 6;
dindex[7] = offset; // replay data index
return 0;
}
void freemem()
{
int i = 0;
for (;i<rh.blocks;i++) free(rbh[i].data);
free(rbh);
free(data);
}
void info()
{
DWORD offset;
char pid = 1;
BYTE c;
/* header infomation */
if (rh.header_ver) {
printf("Warcraft III: %s", rh.sub_1.ver_str == WAR3
? "Reign of Chaos"
: "Frozen Throne");
printf(" 1.%02u.%u\n", ver, rh.sub_1.build);
printf("Replay length %d min %d.%03d s\n", rh.sub_1.length_ms / 60000,
rh.sub_1.length_ms % 60000 / 1000, rh.sub_1.length_ms % 1000);
} else {
printf("Warcraft III: Reign of Chaos 1.%02u.%u\n", ver,
rh.sub_0.build);
printf("Replay length %d min %d.%03d s\n", rh.sub_0.length_ms / 60000,
rh.sub_0.length_ms % 60000 / 1000, rh.sub_1.length_ms % 1000);
}
/* game name */
offset = dindex[1];
printf("Game name ");
while (c = *((char *)data + (offset++))) putchar(c);
putchar('\n');
/* decode the encoded strings */
BYTE mask, decoded[dindex[3]-dindex[2]];
int pos = 0, dpos = 0;
offset = dindex[2];
while (c = *(data + offset + pos)) {
if (pos % 8)
decoded[dpos++] = c - !(mask & (0x1 << (pos % 8)));
else
mask = c;
pos++;
}
/* map & creator name */
printf("Map path ");
dpos = 13;
while (decoded[dpos]) putchar(decoded[dpos++]);
dpos++;
putchar('\n');
printf("Creator name %s\n", decoded + dpos);
/* game type */
offset = dindex[4];
printf("Game type ");
switch (*(data + offset)) {
case 0x00: case 0x01: case 0x09:
printf("Custom game\n");
break;
case 0x20:
printf("Ladder game\n");
break;
default:
printf("Unknown\n");
}
}
void player()
{
int i;
DWORD offset;
BYTE nr, racen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -