⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dataprocess.c

📁 3号作品是分析WarCraft III游戏的replay文件的命令行工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -