/* itemcache.wdb parser by dfighter */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define NUMSTATFIELDS 20
#define HDR "id,recordlength,class,subclass,unk1,name1,name2,name3,name4,modelid,quality,flags,buyprice,sellprice,inventoryslot,allowableclass,allowablerace,itemlevel,requiredlevel,requiredskill,requiredskill_level,requiredspell,unknown,unknown,reqfaction,reqfactionstanding,isunique,stackamount,containerslots,itemstatcount,stat1,stat1value,stat2,stat2value,stat3,stat3value,stat4,stat4value,stat5,stat5value,stat6,stat6value,stat7,stat7value,stat8,stat8value,stat9,stat9value,stat10,stat10value,unknown,unknown,dmg1min,dmg1max,dmg1type,dmg2min,dmg2max,dmg2type,dmg3min,dmg3max,dmg3type,dmg4min,dmg4max,dmg4type,dmg5min,dmg5max,dmg5type,armor,holy_resistance,fire_resistance,nature,frost_resistance,shadow_resistance,arcane_resistance,delay,ammotype,range,spellid1,spelltrigger1,spellcharges1,spellcooldown1,spellcategory1,spellcategory1cooldown,spellid2,spelltrigger2,spellcharges2,spellcooldown2,spellcategory2,spellcategory2cooldown,spellid3,spelltrigger3,spellcharges3,spellcooldown3,spellcategory3,spellcategory3cooldown,spellid4,spelltrigger4,spellcharges4,spellcooldown4,spellcategory4,spellcategory4cooldown,spellid5,spelltrigger5,spellcharges5,spellcooldown5,spellcategory5,spellcategory5cooldown,bondid,Description,page_id,page_language,page_material,questid,unknown,lock_material,sheatid,randomprop,randomsuffix,block,itemset,durability,unknown,unknown,bagfamily,totemcategory,socket_color1,socket_content_1,socket_color2,socket_content_2,socket_color3,socket_content_3,socket_bonus,gemproperties,requireddisenchantingskill,armordmgmodifier,unknown,unknown"

typedef unsigned long uint32;
typedef long int32;

typedef struct WDBheader{
	char id[5];
	uint32 build;
	char locale[5];
	uint32 unk1;
	uint32 unk2;
}WDB_HEADER;

typedef struct itemsWDBstruct{
	int32 id;
	int32 recordlength;
	int32 class;
	int32 subclass;
	int32 unknown;
	char name1[100];
	char name2[100];
	char name3[100];
	char name4[100];
	int32 modelid;
	int32 quality;
	int32 unknown3; /* some item flag */
	int32 buyprice;
	int32 sellprice;
	int32 inventoryslot;
	int32 unknown4; /* allowableclass? */
	int32 unknown5; /* allowablerace? */
	int32 itemlevel;
	int32 requiredlevel;
	int32 unknown6;
	int32 unknown7;
	int32 unknown8;
	int32 unknown9;
	int32 unknown10;
	int32 unknown11;
	int32 unknown12;
	int32 unknown13;
	int32 maxcount;
	int32 unknown14; /* containerslots?*/
	int32 unknown15; /* number of stat fields / 2 (because of stat,statval)*/
	int32 stat[NUMSTATFIELDS];
	int32 unknown18; 
	int32 unknown19;  
	float unknown20; /* dmgmin */
	float unknown21; /* dmgmax */
	int32 unknown22;
	float unknown23; /* */
	float unknown24; /*damage*/
	int32 unknown25;
	float unknown26; /**/
	float unknown27; /**/
	int32 unknown28;
	float unknown29; /**/
	float unknown30; /**/
	int32 unknown31;
	float unknown32; /**/
	float unknown33; /**/
	int32 unknown34;
	int32 armor;
	int32 unknown35;
	int32 unknown36;
	int32 unknown37;
	int32 unknown38;
	int32 unknown39;
	int32 unknown40;
	int32 unknown41; /* ammotype */
	int32 unknown42;
	float unknown43; /*range */
	int32 unknown44;
	int32 unknown45;
	int32 unknown46;
	int32 unknown47;
	int32 unknown48;
	int32 unknown49;
	int32 unknown50;
	int32 unknown51;
	int32 unknown52;
	int32 unknown53;
	int32 unknown54;
	int32 unknown55;
	int32 unknown56;
	int32 unknown57;
	int32 unknown58;
	int32 unknown59;
	int32 unknown60;
	int32 unknown61;
	int32 unknown62;
	int32 unknown63;
	int32 unknown64;
	int32 unknown65;
	int32 unknown66;
	int32 unknown67;
	int32 unknown68;
	int32 unknown69;
	int32 unknown70;
	int32 unknown71;
	int32 unknown72;
	int32 unknown73;
	int32 bondid;
	char   description[500];
	int32 unknown74;
	int32 unknown75;
	int32 unknown76;
	int32 unknown77;
	int32 unknown78;
	int32 unknown79;
	int32 unknown80;
	int32 unknown81;
	int32 unknown82;
	int32 unknown83;
	int32 unknown84;
	int32 unknown85;
	int32 unknown86;
	int32 unknown87;
	int32 unknown88;
	int32 unknown89;
	int32 unknown90;
	int32 unknown91;
	int32 unknown92;
	int32 unknown93;
	int32 unknown94;
	int32 unknown95;
	int32 unknown96;
	int32 unknown97;
	int32 unknown98;
	float unknown99; /* armordmg mod*/
	int32 unknown100;
	int32 unknown101;

}WDB_ITEM;

FILE* readstr(FILE* fp, char* str){
	int i = 0;
	char ch = 255;
	
	while(ch != 0){
		fread(&ch,sizeof(char),1,fp);
		str[i++] = ch;
	}
	return fp;
}

int main(void){
	WDB_HEADER itemshdr;
	WDB_ITEM itemswdb;
	FILE* fp = NULL;
	FILE* fpout = NULL;
	uint32 i = 0;

	fp = fopen("itemcache.wdb","rb");
	if(fp == NULL){
		printf("ERROR: cannot open input file.\n");
		return -1;
	}

	fpout = fopen("itemcache.csv","wt");
	if(fpout == NULL){
		printf("ERROR: cannot open output file.\n");
		return -1;
	}

	/* Reading header and checking for correct signature + build */
	fread(&(itemshdr.id),sizeof(char)*4,1,fp);
	itemshdr.id[4] = '\0';
	fread(&(itemshdr.build),sizeof(uint32),1,fp);
	fread(&(itemshdr.locale),sizeof(char)*4,1,fp);
	itemshdr.locale[4] = '\0';
	fread(&(itemshdr.unk1),sizeof(uint32),1,fp);
	fread(&(itemshdr.unk2),sizeof(uint32),1,fp);

	if(strcmp(itemshdr.id,"BDIW")!=0){
		printf("ERROR: input file is not a itemcache file.\n");
		fclose(fp);
		return -1;
	}
	/* if(itemshdr.build != 8714){
		printf("ERROR: input file is not a build 8714 itemcache file.\n");
		fclose(fp);
		return -1;
	}
	*/


	/* Reading the records and dumping them into a csv format */

	fprintf(fpout,"%s\n",HDR);

	while(feof(fp)==0){
		for(i = 0; i < NUMSTATFIELDS; i++)
			itemswdb.stat[i] = 0;
		fread(&(itemswdb.id),sizeof(uint32),1,fp);
		fread(&(itemswdb.recordlength),sizeof(uint32),1,fp);
		fread(&(itemswdb.class),sizeof(uint32),1,fp);
		fread(&(itemswdb.subclass),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown),sizeof(uint32),1,fp);
		
		fp = readstr(fp,itemswdb.name1);
		fp = readstr(fp,itemswdb.name2);
		fp = readstr(fp,itemswdb.name3);
		fp = readstr(fp,itemswdb.name4);

		fread(&(itemswdb.modelid),sizeof(uint32),1,fp);
		fread(&(itemswdb.quality),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown3),sizeof(uint32),1,fp);
		fread(&(itemswdb.buyprice),sizeof(uint32),1,fp);
		fread(&(itemswdb.sellprice),sizeof(uint32),1,fp);
		fread(&(itemswdb.inventoryslot),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown4),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown5),sizeof(uint32),1,fp);
		fread(&(itemswdb.itemlevel),sizeof(uint32),1,fp);
		fread(&(itemswdb.requiredlevel),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown6),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown7),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown8),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown9),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown10),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown11),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown12),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown13),sizeof(uint32),1,fp);
		fread(&(itemswdb.maxcount),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown14),sizeof(uint32),1,fp); /* containerslots */
		fread(&(itemswdb.unknown15),sizeof(uint32),1,fp); /* number of stat fields / 2 */
		for(i = 0; i < itemswdb.unknown15*2; i++)
			fread(&(itemswdb.stat[i]),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown18),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown19),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown20),sizeof(float),1,fp);
		fread(&(itemswdb.unknown21),sizeof(float),1,fp);
		fread(&(itemswdb.unknown22),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown23),sizeof(float),1,fp);
		fread(&(itemswdb.unknown24),sizeof(float),1,fp);
		fread(&(itemswdb.unknown25),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown26),sizeof(float),1,fp);
		fread(&(itemswdb.unknown27),sizeof(float),1,fp);
		fread(&(itemswdb.unknown28),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown29),sizeof(float),1,fp);
		fread(&(itemswdb.unknown30),sizeof(float),1,fp);
		fread(&(itemswdb.unknown31),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown32),sizeof(float),1,fp);
		fread(&(itemswdb.unknown33),sizeof(float),1,fp);
		fread(&(itemswdb.unknown34),sizeof(uint32),1,fp);
		fread(&(itemswdb.armor),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown35),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown36),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown37),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown38),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown39),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown40),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown41),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown42),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown43),sizeof(float),1,fp);
		fread(&(itemswdb.unknown44),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown45),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown46),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown47),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown48),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown49),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown50),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown51),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown52),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown53),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown54),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown55),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown56),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown57),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown58),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown59),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown60),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown61),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown62),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown63),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown64),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown65),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown66),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown67),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown68),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown69),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown70),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown71),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown72),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown73),sizeof(uint32),1,fp);
		fread(&(itemswdb.bondid),sizeof(uint32),1,fp);
		fp = readstr(fp,itemswdb.description);
		fread(&(itemswdb.unknown74),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown75),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown76),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown77),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown78),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown79),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown80),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown81),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown82),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown83),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown84),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown85),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown86),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown87),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown88),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown89),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown90),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown91),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown92),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown93),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown94),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown95),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown96),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown97),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown98),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown99),sizeof(float),1,fp);
		fread(&(itemswdb.unknown100),sizeof(uint32),1,fp);
		fread(&(itemswdb.unknown101),sizeof(uint32),1,fp);

		fprintf(fpout,"%lu,",itemswdb.id);
		fprintf(fpout,"%lu,",itemswdb.recordlength);
		fprintf(fpout,"%lu,",itemswdb.class);
		fprintf(fpout,"%lu,",itemswdb.subclass);
		fprintf(fpout,"%lu,",itemswdb.unknown);
		fprintf(fpout,"\"%s\",",itemswdb.name1);
		fprintf(fpout,"\"%s\",",itemswdb.name2);
		fprintf(fpout,"\"%s\",",itemswdb.name3);
		fprintf(fpout,"\"%s\",",itemswdb.name4);
		fprintf(fpout,"%lu,",itemswdb.modelid);
		fprintf(fpout,"%lu,",itemswdb.quality);
		fprintf(fpout,"%lu,",itemswdb.unknown3);
		fprintf(fpout,"%lu,",itemswdb.buyprice);
		fprintf(fpout,"%lu,",itemswdb.sellprice);
		fprintf(fpout,"%lu,",itemswdb.inventoryslot);
		fprintf(fpout,"%lu,",itemswdb.unknown4);
		fprintf(fpout,"%lu,",itemswdb.unknown5);
		fprintf(fpout,"%lu,",itemswdb.itemlevel);
		fprintf(fpout,"%lu,",itemswdb.requiredlevel);
		fprintf(fpout,"%lu,",itemswdb.unknown6);
		fprintf(fpout,"%lu,",itemswdb.unknown7);
		fprintf(fpout,"%lu,",itemswdb.unknown8);
		fprintf(fpout,"%lu,",itemswdb.unknown9);
		fprintf(fpout,"%lu,",itemswdb.unknown10);
		fprintf(fpout,"%lu,",itemswdb.unknown11);
		fprintf(fpout,"%lu,",itemswdb.unknown12);
		fprintf(fpout,"%lu,",itemswdb.unknown13);
		fprintf(fpout,"%lu,",itemswdb.maxcount);
		fprintf(fpout,"%lu,",itemswdb.unknown14);
		fprintf(fpout,"%lu,",itemswdb.unknown15);
		for(i = 0; i < NUMSTATFIELDS; i++)
			fprintf(fpout,"%lu,",itemswdb.stat[i]);
		
		fprintf(fpout,"%lu,",itemswdb.unknown18);
		fprintf(fpout,"%lu,",itemswdb.unknown19);
		fprintf(fpout,"%f,",itemswdb.unknown20);
		fprintf(fpout,"%f,",itemswdb.unknown21);
		fprintf(fpout,"%lu,",itemswdb.unknown22);
		fprintf(fpout,"%f,",itemswdb.unknown23);
		fprintf(fpout,"%f,",itemswdb.unknown24);
		fprintf(fpout,"%lu,",itemswdb.unknown25);
		fprintf(fpout,"%f,",itemswdb.unknown26);
		fprintf(fpout,"%f,",itemswdb.unknown27);
		fprintf(fpout,"%lu,",itemswdb.unknown28);
		fprintf(fpout,"%f,",itemswdb.unknown29);
		fprintf(fpout,"%f,",itemswdb.unknown30);
		fprintf(fpout,"%lu,",itemswdb.unknown31);
		fprintf(fpout,"%f,",itemswdb.unknown32);
		fprintf(fpout,"%f,",itemswdb.unknown33);
		fprintf(fpout,"%lu,",itemswdb.unknown34);
		fprintf(fpout,"%lu,",itemswdb.armor);
		fprintf(fpout,"%lu,",itemswdb.unknown35);
		fprintf(fpout,"%lu,",itemswdb.unknown36);
		fprintf(fpout,"%lu,",itemswdb.unknown37);
		fprintf(fpout,"%lu,",itemswdb.unknown38);
		fprintf(fpout,"%lu,",itemswdb.unknown39);
		fprintf(fpout,"%lu,",itemswdb.unknown40);
		fprintf(fpout,"%lu,",itemswdb.unknown41);
		fprintf(fpout,"%lu,",itemswdb.unknown42);
		fprintf(fpout,"%f,",itemswdb.unknown43);
		fprintf(fpout,"%lu,",itemswdb.unknown44);
		fprintf(fpout,"%lu,",itemswdb.unknown45);
		fprintf(fpout,"%lu,",itemswdb.unknown46);
		fprintf(fpout,"%lu,",itemswdb.unknown47);
		fprintf(fpout,"%lu,",itemswdb.unknown48);
		fprintf(fpout,"%lu,",itemswdb.unknown49);
		fprintf(fpout,"%lu,",itemswdb.unknown50);
		fprintf(fpout,"%lu,",itemswdb.unknown51);
		fprintf(fpout,"%lu,",itemswdb.unknown52);
		fprintf(fpout,"%lu,",itemswdb.unknown53);
		fprintf(fpout,"%lu,",itemswdb.unknown54);
		fprintf(fpout,"%lu,",itemswdb.unknown55);
		fprintf(fpout,"%lu,",itemswdb.unknown56);
		fprintf(fpout,"%lu,",itemswdb.unknown57);
		fprintf(fpout,"%lu,",itemswdb.unknown58);
		fprintf(fpout,"%lu,",itemswdb.unknown59);
		fprintf(fpout,"%lu,",itemswdb.unknown60);
		fprintf(fpout,"%lu,",itemswdb.unknown61);
		fprintf(fpout,"%lu,",itemswdb.unknown62);
		fprintf(fpout,"%lu,",itemswdb.unknown63);
		fprintf(fpout,"%lu,",itemswdb.unknown64);
		fprintf(fpout,"%lu,",itemswdb.unknown65);
		fprintf(fpout,"%lu,",itemswdb.unknown66);
		fprintf(fpout,"%lu,",itemswdb.unknown67);
		fprintf(fpout,"%lu,",itemswdb.unknown68);
		fprintf(fpout,"%lu,",itemswdb.unknown69);
		fprintf(fpout,"%lu,",itemswdb.unknown70);
		fprintf(fpout,"%lu,",itemswdb.unknown71);
		fprintf(fpout,"%lu,",itemswdb.unknown72);
		fprintf(fpout,"%lu,",itemswdb.unknown73);
		fprintf(fpout,"%lu,",itemswdb.bondid);
		fprintf(fpout,"\"%s\",",itemswdb.description);
		fprintf(fpout,"%lu,",itemswdb.unknown74);
		fprintf(fpout,"%lu,",itemswdb.unknown75);
		fprintf(fpout,"%lu,",itemswdb.unknown76);
		fprintf(fpout,"%lu,",itemswdb.unknown77);
		fprintf(fpout,"%lu,",itemswdb.unknown78);
		fprintf(fpout,"%lu,",itemswdb.unknown79);
		fprintf(fpout,"%lu,",itemswdb.unknown80);
		fprintf(fpout,"%lu,",itemswdb.unknown81);
		fprintf(fpout,"%lu,",itemswdb.unknown82);
		fprintf(fpout,"%lu,",itemswdb.unknown83);
		fprintf(fpout,"%lu,",itemswdb.unknown84);
		fprintf(fpout,"%lu,",itemswdb.unknown85);
		fprintf(fpout,"%lu,",itemswdb.unknown86);
		fprintf(fpout,"%lu,",itemswdb.unknown87);
		fprintf(fpout,"%lu,",itemswdb.unknown88);
		fprintf(fpout,"%lu,",itemswdb.unknown89);
		fprintf(fpout,"%lu,",itemswdb.unknown90);
		fprintf(fpout,"%lu,",itemswdb.unknown91);
		fprintf(fpout,"%lu,",itemswdb.unknown92);
		fprintf(fpout,"%lu,",itemswdb.unknown93);
		fprintf(fpout,"%lu,",itemswdb.unknown94);
		fprintf(fpout,"%lu,",itemswdb.unknown95);
		fprintf(fpout,"%lu,",itemswdb.unknown96);
		fprintf(fpout,"%lu,",itemswdb.unknown97);
		fprintf(fpout,"%lu,",itemswdb.unknown98);
		fprintf(fpout,"%f,",itemswdb.unknown99);

		fprintf(fpout,"%lu,",itemswdb.unknown100);
		fprintf(fpout,"%lu,",itemswdb.unknown101);

		fprintf(fpout,"\n");
	}

	fclose(fp);
	fclose(fpout);
	return 0;
}
