Advertisement
Guest User

Microsoft Comic Chat AVB/BGB extractor

a guest
Jan 11th, 2014
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.73 KB | None | 0 0
  1. // AVBuster.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include "zlib.h"
  8.  
  9. #pragma pack(push, 1)
  10.  
  11. // type 0x8181 = avb header
  12. typedef struct _AVB_HEADER
  13. {
  14. short type;
  15. short unk;
  16. } AVB_HEADER, *PAVB_HEADER;
  17.  
  18. // type 1 = null-terminated string
  19.  
  20. // type 2 = unknown, 2 bytes
  21. typedef struct _AVB_UNK_HEADER_2
  22. {
  23. short unk;
  24. } AVB_UNK_HEADER_2, *PAVB_UNK_HEADER_2;
  25.  
  26. // type 6 = zlib compressed bmp
  27. typedef struct _AVB_ZLIB_BMP_HEADER
  28. {
  29. BITMAPINFOHEADER header;
  30. int len_decomp;
  31. int len_comp;
  32. } AVB_ZLIB_BMP_HEADER, *PAVB_ZLIB_BMP_HEADER;
  33.  
  34. typedef struct _AVB_ZLIB_GESTURE_HEADER
  35. {
  36. short colors_magic;
  37. short colors_length;
  38. short num_colors;
  39. } AVB_ZLIB_GESTURE_HEADER, *PAVB_ZLIB_GESTURE_HEADER;
  40.  
  41. // type 8 = unknown, 2 bytes
  42. typedef struct _AVB_UNK_HEADER_8
  43. {
  44. short unk;
  45. } AVB_UNK_HEADER_8, *PAVB_UNK_HEADER_8;
  46.  
  47.  
  48. // gesture list entry
  49. typedef struct _AVB_GESTURE_ENTRY
  50. {
  51. int gestureOffset; // 4
  52. int unknownOffset; // 8
  53. int poseOffset; // 12
  54. short unk1; // 14
  55. int facePosition; // 16
  56. short unk2; // 20
  57. short unk3; // 22
  58. short unk4; // 24
  59. char unk5; // 25
  60. } AVB_GESTURE_ENTRY, *PAVB_GESTURE_ENTRY;
  61.  
  62. // type 0xA = unknown list
  63. typedef struct _AVB_UNK_HEADER_A
  64. {
  65. short count;
  66. } AVB_UNK_HEADER_A, *PAVB_UNK_HEADER_A;
  67.  
  68. typedef struct _AVB_UNK_HEADER_A_ENTRY
  69. {
  70. AVB_GESTURE_ENTRY ent;
  71. char unk[8];
  72. } AVB_UNK_HEADER_A_ENTRY, *PAVB_UNK_HEADER_A_ENTRY;
  73.  
  74. // type 0xB/0xC = gesture list
  75. typedef struct _AVB_GESTURE_LIST
  76. {
  77. short count;
  78. } AVB_GESTURE_LIST, *PAVB_GESTURE_LIST;
  79.  
  80. // type 0x100 = unknown
  81. typedef struct _AVB_UNK_HEADER_100
  82. {
  83. short size;
  84. short unk1;
  85. short unk2;
  86. short unk3;
  87. } AVB_UNK_HEADER_100, *PAVB_UNK_HEADER_100;
  88.  
  89. // type 0x103 & 0x104 = string entry
  90. typedef struct _AVB_STRING_HEADER
  91. {
  92. short size;
  93. } AVB_STRING_HEADER, *PAVB_STRING_HEADER;
  94.  
  95. // type 0x106 = url protection header
  96. typedef struct _AVB_PROTECT_HEADER
  97. {
  98. short size;
  99. bool download_protected;
  100. } AVB_PROTECT_HEADER, *PAVB_PROTECT_HEADER;
  101.  
  102. #pragma pack(pop)
  103.  
  104.  
  105. int _tmain(int argc, _TCHAR* argv[])
  106. {
  107. printf("AVBuster, extractor for MS Comic Chat AVB and BGB files\nnote: official MS chars are unsupported due to them using a different compression method\n");
  108. if(argc <= 1)
  109. {
  110. printf("usage: avbuster.exe character.avb\n");
  111. return 0;
  112. }
  113.  
  114. FILE* fp;
  115. if(_wfopen_s(&fp, argv[1], L"rb") != 0)
  116. {
  117. printf("failed to open file!\n");
  118. return 0;
  119. }
  120.  
  121. fseek(fp, 0L, SEEK_SET);
  122.  
  123. bool headerRead = false;
  124. AVB_HEADER header;
  125. bool nameRead = false;
  126. char name[256];
  127. bool header8Read = false;
  128. AVB_UNK_HEADER_8 header8;
  129. bool header2Read = false;
  130. AVB_UNK_HEADER_2 header2;
  131. bool header100Read = false;
  132. AVB_UNK_HEADER_100 header100;
  133. bool header103Read = false;
  134. AVB_STRING_HEADER header103;
  135. char author[256];
  136.  
  137. bool header104Read = false;
  138. AVB_STRING_HEADER header104;
  139. char download[256];
  140. bool header105Read = false;
  141. AVB_STRING_HEADER header105;
  142. char download2[256];
  143. bool header106Read = false;
  144. AVB_PROTECT_HEADER header106;
  145. bool header107Read = false;
  146. AVB_STRING_HEADER header107;
  147.  
  148. bool hasGestures = false;
  149. AVB_UNK_HEADER_A headerA;
  150. AVB_UNK_HEADER_A_ENTRY headerAEntries[256];
  151. bool headerCisB = false;
  152. AVB_GESTURE_LIST headerC;
  153. AVB_GESTURE_ENTRY headerPoses[256];
  154. AVB_ZLIB_GESTURE_HEADER gestureHdr[256];
  155. memset(&gestureHdr, 0, sizeof(AVB_ZLIB_GESTURE_HEADER) * 256);
  156.  
  157. AVB_ZLIB_BMP_HEADER gestureBmpHdr[256];
  158. AVB_ZLIB_BMP_HEADER poseBmp[256];
  159.  
  160. int zlibOffset = 0;
  161.  
  162. memset(&header, 0, sizeof(AVB_HEADER));
  163. int current = 0;
  164. int ni = 0;
  165. while(true)
  166. {
  167. if(current > 0 && header.type == 0)
  168. {
  169. printf("invalid file?\n");
  170. return 0;
  171. }
  172. unsigned short type;
  173. fread(&type, sizeof(short), 1, fp);
  174. printf("Type %x\n", type);
  175. if(type == 6)
  176. break;
  177. switch(type)
  178. {
  179. case 0x8181:
  180. fread(&header, sizeof(AVB_HEADER), 1, fp);
  181. if(header.type != 1)
  182. printf("** new header type 0x%x\n", header.type);
  183. if(header.unk != 2)
  184. printf("** new header unk 0x%x\n", header.unk);
  185.  
  186. if(header.type == 2)
  187. {
  188. printf("** unsupported type 2 (OEM/Microsoft?)\n");
  189. return 0;
  190. }
  191. headerRead = true;
  192. break;
  193. case 1:
  194. while(true)
  195. {
  196. fread(&name[ni], 1, 1, fp);
  197. if(name[ni] == 0) break;
  198. ni++;
  199. }
  200. nameRead = true;
  201. ni = 0;
  202. break;
  203. case 2:
  204. fread(&header2, sizeof(AVB_UNK_HEADER_2), 1, fp);
  205. if(header2.unk != 5)
  206. {
  207. printf("** new header2: unk 0x%x\n", header2.unk);
  208. }
  209. header2 = header2;
  210. header2Read = true;
  211. break;
  212. case 8:
  213. fread(&header8, sizeof(AVB_UNK_HEADER_8), 1, fp);
  214. if(header8.unk != 1)
  215. {
  216. printf("** new header8: unk 0x%x\n", header8.unk);
  217. }
  218. header8 = header8;
  219. header8Read = true;
  220. break;
  221. case 0xA:
  222. fread(&headerA, sizeof(AVB_UNK_HEADER_A), 1, fp);
  223. for(int i = 0; i < headerA.count; i++)
  224. fread(&headerAEntries[i], sizeof(AVB_UNK_HEADER_A_ENTRY), 1, fp);
  225. break;
  226. case 0xB:
  227. headerCisB = true;
  228. case 0xC:
  229. hasGestures = true;
  230. fread(&headerC, sizeof(AVB_GESTURE_LIST), 1, fp);
  231. for(int i = 0; i < headerC.count; i++)
  232. {
  233. fread(&headerPoses[i], sizeof(AVB_GESTURE_ENTRY), 1, fp);
  234. }
  235. break;
  236. case 0x100:
  237. fread(&header100, sizeof(AVB_UNK_HEADER_100), 1, fp);
  238. if(header100.size != 6)
  239. printf("** new header100 size: 0x%x\n", header100.size);
  240. if(header100.unk1 != 0x60)
  241. printf("** new header100 unk1: 0x%x\n", header100.unk1);
  242. if(header100.unk2 != 0)
  243. printf("** new header100 unk2: 0x%x\n", header100.unk2);
  244. if(header100.unk3 != 0x201)
  245. printf("** new header100 unk3: 0x%x\n", header100.unk3);
  246. header100 = header100;
  247. header100Read = true;
  248. break;
  249. case 0x103:
  250. fread(&header103, sizeof(AVB_STRING_HEADER), 1, fp);
  251. fread(&author, header103.size, 1, fp);
  252. header103Read = true;
  253. break;
  254. case 0x104:
  255. fread(&header104, sizeof(AVB_STRING_HEADER), 1, fp);
  256. fread(&download, header104.size, 1, fp);
  257. header104Read = true;
  258. break;
  259. case 0x105:
  260. fread(&header105, sizeof(AVB_STRING_HEADER), 1, fp);
  261. fread(&download2, header105.size, 1, fp);
  262. header105Read = true;
  263. break;
  264. case 0x106:
  265. fread(&header106, sizeof(AVB_PROTECT_HEADER), 1, fp);
  266. if(header106.size != 1)
  267. printf("** new header106 size: 0x%x\n", header106.size);
  268. if(header106.download_protected != 1)
  269. printf("** new header106 download_protected: 0x%x\n", header106.download_protected);
  270. header106 = header106;
  271. header106Read = true;
  272. break;
  273. case 0x107:
  274. fread(&header104, sizeof(AVB_STRING_HEADER), 1, fp);
  275. fread(&zlibOffset, 4, 1, fp);
  276. header107Read = true;
  277. break;
  278.  
  279.  
  280. case 0x81:
  281. if(!headerRead)
  282. {
  283. printf("** older header detected, use avbcvt / bmpbgb to convert to 2.5 first\n");
  284. return 0;
  285. }
  286. default:
  287. printf("** new header # 0x%x\n", type);
  288. if(type >= 0x100)
  289. {
  290. unsigned short size = 0;
  291. fread(&size, 2, 1, fp);
  292. printf("** header has size field, skipping 0x%x bytes...\n", size);
  293. fseek(fp, size, SEEK_CUR);
  294. }
  295.  
  296. break;
  297. }
  298. current++;
  299. }
  300.  
  301. if(nameRead)
  302. printf("name: %s\n", name);
  303. if(header103Read)
  304. printf("author: %s\n", author);
  305. if(header104Read)
  306. printf("download: %s\n", download);
  307. if(header105Read)
  308. printf("download2: %s\n", download2);
  309. if(headerRead)
  310. printf("header type: 0x%x unk: 0x%x\n", header.type, header.unk);
  311. if(header2Read)
  312. printf("header2 unk: 0x%x\n", header2.unk);
  313. if(header8Read)
  314. printf("header8 unk: 0x%x\n", header8.unk);
  315. if(header100Read)
  316. printf("header100 size: 0x%x unk1: 0x%x unk2: 0x%x unk3: 0x%x\n", header100.size, header100.unk1, header100.unk2, header100.unk3);
  317. if(header106Read)
  318. printf("header106 size: 0x%x download_protected: 0x%x\n", header106.size, header106.download_protected);
  319. if(header107Read)
  320. printf("header107 zlib offset: 0x%x\n", zlibOffset);
  321. if(hasGestures)
  322. {
  323. printf("gesture count: 0x%x\n", headerC.count);
  324. for(int i = 0; i < headerC.count; i++)
  325. {
  326. printf("== Gesture %d\n", i);
  327. printf(" gestureOffset: 0x%x unknownOffset: 0x%x poseOffset: 0x%x\n unk1: 0x%x facePosition: 0x%x unk2: 0x%x\n unk3: 0x%x unk4: 0x%x unk5: 0x%x\n", headerPoses[i].gestureOffset, headerPoses[i].unknownOffset, headerPoses[i].poseOffset, headerPoses[i].unk1, headerPoses[i].facePosition, headerPoses[i].unk2, headerPoses[i].unk3, headerPoses[i].unk4, headerPoses[i].unk5);
  328. }
  329.  
  330. }
  331.  
  332.  
  333. unsigned char check = 0;
  334. unsigned char chk2 = 0;
  335. if(!hasGestures)
  336. {
  337. AVB_ZLIB_GESTURE_HEADER hdr;
  338. AVB_ZLIB_BMP_HEADER bmpHdr;
  339. fread(&hdr, sizeof(AVB_ZLIB_GESTURE_HEADER), 1, fp);
  340. void* colors = 0;
  341. if(hdr.num_colors > 0)
  342. {
  343. colors = malloc(hdr.num_colors * 4);
  344. memset(colors, 0, hdr.num_colors * 4);
  345. for(int y = 0; y < hdr.num_colors; y++)
  346. fread((BYTE*)colors + (y * 4), 3, 1, fp);
  347. }
  348.  
  349. fread(&bmpHdr, sizeof(AVB_ZLIB_BMP_HEADER), 1, fp);
  350.  
  351. void* compressed = malloc(bmpHdr.len_comp);
  352. fread(compressed, bmpHdr.len_comp, 1, fp);
  353.  
  354. // create bmp and decompress
  355. BITMAPFILEHEADER bmp;
  356. memset(&bmp, 0, sizeof(BITMAPFILEHEADER));
  357. bmp.bfType = 0x4D42;
  358. bmp.bfOffBits = 0x36 + (hdr.num_colors * 4);
  359. bmp.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (hdr.num_colors * 4) + bmpHdr.len_decomp;
  360.  
  361. void* dest = malloc(bmpHdr.len_decomp);
  362. int size = bmpHdr.len_decomp;
  363.  
  364. int ret = uncompress((Bytef*)dest, (uLongf*)&size, (Bytef*)compressed, bmpHdr.len_comp);
  365. if(ret != 0) return 0;
  366.  
  367. TCHAR fname[256];
  368. swprintf(fname, L"%ws_data\\", argv[1]);
  369. _tmkdir(fname);
  370. swprintf(fname, L"%ws_data\\bg.bmp", argv[1]);
  371. FILE* file = _wfopen(fname, L"wb");
  372. fwrite(&bmp, sizeof(BITMAPFILEHEADER), 1, file);
  373. fwrite(&bmpHdr.header, sizeof(BITMAPINFOHEADER), 1, file);
  374. if(colors)
  375. fwrite(colors, hdr.num_colors * 4, 1, file);
  376. fwrite(dest, size, 1, file);
  377. fclose(file);
  378.  
  379. if(colors) free(colors);
  380.  
  381. dest = dest;
  382.  
  383. }
  384. else
  385. for(int i = 0; i < headerC.count; i++)
  386. {
  387. void* colors = 0;
  388. //fseek(fp, headerAEntries[i].ent.gestureOffset + zlibOffset, SEEK_SET);
  389. fseek(fp, headerPoses[i].gestureOffset + zlibOffset, SEEK_SET);
  390.  
  391. if(!headerCisB)
  392. {
  393. fread(&gestureHdr[i], sizeof(AVB_ZLIB_GESTURE_HEADER), 1, fp);
  394. if(gestureHdr[i].num_colors > 0)
  395. {
  396. colors = malloc(gestureHdr[i].num_colors * 4);
  397. memset(colors, 0, gestureHdr[i].num_colors * 4);
  398. for(int y = 0; y < gestureHdr[i].num_colors; y++)
  399. fread(((BYTE*)colors + (y * 4)), 3, 1, fp);
  400. }
  401. }
  402.  
  403. fread(&gestureBmpHdr[i], sizeof(AVB_ZLIB_BMP_HEADER), 1, fp);
  404.  
  405. fread(&check, 1, 1, fp);
  406. fread(&chk2, 1, 1, fp);
  407. fseek(fp, -2, SEEK_CUR);
  408. if(check != 0x78 || chk2 != 0xDA)
  409. {
  410. /*printf("** scanning for zlib data...\n");
  411. int offset = 0;
  412. while(true)
  413. {
  414. offset++;
  415. fread(&check, 1, 1, fp);
  416. if(check != 0x78) continue;
  417. fread(&chk2, 1, 1, fp);
  418. if(chk2 != 0xDA)
  419. {
  420. fseek(fp, -1, SEEK_CUR);
  421. continue;
  422. }
  423. break;
  424. }
  425. offset -= 1;
  426. printf("found at %x\n", offset);
  427. fseek(fp, headerPoses[i].gestureOffset + zlibOffset + offset, SEEK_SET);
  428. fread(&gestureHdr[i], sizeof(AVB_ZLIB_GESTURE_HEADER), 1, fp);
  429. if(gestureHdr[i].num_colors > 0)
  430. {
  431. if(colors) free(colors);
  432. colors = malloc(gestureHdr[i].num_colors * 4);
  433. for(int y = 0; y < gestureHdr[i].num_colors; y++)
  434. fread(&colors + (y * 4), 3, 1, fp);
  435. }
  436. fread(&gestureBmpHdr[i], sizeof(AVB_ZLIB_BMP_HEADER), 1, fp);
  437. //return 0;*/
  438. printf("** zlib data not found and searching is deprecated, exiting\n");
  439. return 0;
  440. }
  441.  
  442. void* compressed = malloc(gestureBmpHdr[i].len_comp);
  443. fread(compressed, gestureBmpHdr[i].len_comp, 1, fp);
  444.  
  445. // create bmp and decompress
  446. BITMAPFILEHEADER bmp;
  447. memset(&bmp, 0, sizeof(BITMAPFILEHEADER));
  448. bmp.bfType = 0x4D42;
  449. bmp.bfOffBits = 36 + (gestureHdr[i].num_colors * 4);
  450. bmp.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (gestureHdr[i].num_colors * 4) + gestureBmpHdr[i].len_decomp;
  451.  
  452. void* dest = malloc(gestureBmpHdr[i].len_decomp);
  453. int size = gestureBmpHdr[i].len_decomp;
  454.  
  455. int ret = uncompress((Bytef*)dest, (uLongf*)&size, (Bytef*)compressed, gestureBmpHdr[i].len_comp);
  456. if(ret != 0) continue;
  457.  
  458. TCHAR fname[256];
  459. swprintf(fname, L"%ws_data\\", argv[1]);
  460. _tmkdir(fname);
  461. swprintf(fname, L"%ws_data\\%d.bmp", argv[1], i);
  462. FILE* file = _wfopen(fname, L"wb");
  463. fwrite(&bmp, sizeof(BITMAPFILEHEADER), 1, file);
  464. fwrite(&gestureBmpHdr[i].header, sizeof(BITMAPINFOHEADER), 1, file);
  465. if(colors)
  466. fwrite(colors, gestureHdr[i].num_colors * 4, 1, file);
  467. fwrite(dest, size, 1, file);
  468. fclose(file);
  469. if(colors) free(colors);
  470.  
  471. dest = dest;
  472.  
  473. }
  474.  
  475. return 0;
  476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement