Skip to content

Latest commit

 

History

History
 
 

dupescan

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
dupescan109 - Diablo II 1.09d Dupe Scanner
==========================================

How do I compile it?
	Just type "make".

How do I set the default directory?
	There is a macro defined which is called "DEFAULT_DIRECTORY" in the
	dupescan109.c file.


How to use it?
	The usage is quite easy. You have two main modes, first, the scan mode (-s)
	which scans all files in a given (or the default) directory for duplicate
	items. The second mode is the character mode (-c) which prints the itemlist,
	including base address in file, length, fingerprint and itemtype of a given
	character.

	For the first mode, there are three additional options. Verbose (-v),
	debug (-d) and quiet (-q). Verbose adds the info stuff from character
	mode for every character in the directory, debug mode prints additional
	debugging information and quiet (-q) suppresses all information except
	the final ones. The second mode only has the debug flag.

	Ok, examples:

	Scan a directory for dupes:
		./dupescan109 -s/home/diablo/var/charsave
	
	Print characters items:
		./dupescal109 -c/home/diablo/var/charsave/mychar

	NOTE: There is no space between the option and the parameter!


How does it work?
	Well, first of all, I have to give you a quick introduction to the d2s file
	format of 1.09. The files are binary coded and not human readable. Stuff that
	is important for a dupescanner is:

	File version (offset 4, size long)
	Character name (offset 20, size 16 chars)
	Character status (offset 36, size 1 byte)

	Ok, so far with the character info. Now lets get into the item info. The data
	before the item list has variable length, so there is no fixed offset for the
	beginning of the item list. But it has the magic prefix "JM" at the beginning
	and "JM", followed by two nullbytes, at the end. So everything between our
	first "JM" and our first "JM\0\0" is our (first) item list. Note: a character
	can have multiple item lists, for example for the merc (only in LoD) or the
	corpse (only in SC mode) or one item for the golem if you are a Nec.

	However, the game server I wrote this dupescanner for only allows hardcore
	mode players for D2 Classic, so the only items it will check are the main
	ones (no corpse, no merc, dont care about golem).

	From now on, I will refer to the offset of "J" (of "JM") as zero, so offset
	1 is "M", etc.. After the JM, there is a 16 bit number (short) which holds
	the number of items that follow. Each following item also starts with "JM"
	(but it does not end with anything, you know that you are at its end when
	you read the "JM" of the next item).

	Now, there are two main types of items. Standard items and extended items.
	All standard items have a fixed length of 14 bytes, everything that is longer
	than 14 bytes is extended. Extended items have a variable length, but thats
	not an issue because we only care about the item fingerprint. Only extended
	items have fingerprints.

	The fingerprint is a 32 bit unique identifier which is random-generated by
	the server on item drop. The chance of generating two 32 bit random numbers
	which are the same is 1 to 2^32, so dont bother about collisions. However,
	this is the main point of dupe detecting. If there are two items with the
	same fingerprints, this means that the items are the same and therefore are
	duped. So all we have to do is read all fingerprints and compare them.

	The fingerprints starts at bit 111 and is, as I said, 32 bit long. Those of
	you who did pass math will notice that 111 is not dividable by 8, which means
	that the fingerprint data is not byte aligned. It looks like this:
	
	byte 13  byte 14  byte 15  byte 16  byte 17
	xxxxxxxA|AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAy

	We dont care about the x and y, we just want A. I solved this with a packed
	bitfield structure.

	There is one other value that I use, the item type. A 32 bit value (4 chars) at
	bit offset 76. Same shit, different data. Not byte aligned :-) It starts in the
	middle of byte 9 and ends at the middle of byte 13.
	
	
How did you know how the file format looks like?
	http://www.ladderhall.com/ericjwin/109/trevin/trevinitemformat.html
	http://www.ladderhall.com/ericjwin/109/trevin/trevinfileformat.html
	http://home.stx.rr.com/svr/formats/d2s.htm


Why only 1.09d??
	Well, actually, it should work with every 1.09 version, but I only tested it
	with 1.09d. But it will definitely not work with a non-1.09 version. The
	reason for this is simple. Blizzard changes the d2s file format with every
	version and this software was written with 1.09 in mind.


I am using 1.09d, but the scanner gives me errors!
	You may notice an error like:
	
	 Error: myTestChar is not a valid v1.09 character file or he has never been in a game
	        (File version is 89, should be 92)

	I am not completely sure, but it happened to me some times when I created a
	char and never played it. Looks like an "empty" char which never has been in
	a real game does not necessarily have the "92" file version set (which stands
	for 1.09).


Your code sucks!
	Hehe, well, maybe it does, I dont really know, because I am not a very experienced C coder, but
	it works for me. If you dont like it, dont use it. But I would appreciate it if you send me bug
	reports.


Who did this?
	Florian 'fw' Weingarten
	http://hackvalue.de/


Thanks to	
	Trevin Beattie for his great file format description and his email support