Code


Version 2 (modified by riklaunim@…, 8 years ago) (diff)

misc changes

Python has “batteries included” and as we all know Django is written in this language. Python has struct module (http://docs.python.org/lib/module-struct.html) which can do many interesting things.

If you played in Baldurs Gate, Icewind Dale or Planescape Torment then this mini tutorial may be quite interesting for you – we will read data from a binary file – Baldurs Gate II CHR file containing data abut players character. Before we continue check out:

pocketplane.net forums – How to read data from infinity engine files

IE File Formats list – specification of Infinity Engine files, we will use CHR v2

Requirements: you need a working django, can be development server. We will create one view and one template.

A example CHR file is attached to this page - look at the bottom.

  • Create a view and hook it up in the urls.py:
    from django.shortcuts import render_to_response
    import struct
    
    def view_char(request):
    	file = open('media/Mag.chr', 'rb')
    	try:
    		text = file.read()
    	finally:
    		file.close()
    	print text[0x0000:0x0000+4]
    	print text[0x0004:0x0004+4]
    	print text[0x0008:0x0008+32]
    	return render_to_response('char.html')
    

Where ('media/Mag.chr') is a path to the CHR file. Create char.html template with some pointless text and open the view in the browser. In the terminal where the development server is running you should see:

CHR
V2.0
Daria

We have just read the basic data, and reading more isn't any problem (only problem is to specify the locations). Looking at CHR V2 and CRE V1 specification we can read more data:

from django.shortcuts import render_to_response
import struct

def view_char(request):
	file = open('media/Mag.chr', 'rb')
	try:
		text = file.read()
	finally:
		file.close()
	char = {}
	if str(text[0x0000:0x0000+4]) == 'CHR ':
		char['name'] = str(text[0x0008:0x0008+32])
		a = struct.unpack('i', text[0x0028:0x0028+4]) # offset to CRE "file"
		a = 0x0000+a[0]
		if str(text[a:a+4]) == 'CRE ' and str(text[a+4:a+8]) == 'V1.0':
			char['xp'] = str(struct.unpack('i', text[a+0x0018:a+0x0018+4])[0])
			char['hp'] = str(struct.unpack('h', text[a+0x0024:a+0x0024+2])[0])
			char['pic'] = str(text[a+0x0034:a+0x0034+8])
			char['str'] = str(struct.unpack('b', text[a+0x0238:a+0x0238+1])[0]) #str
			char['int'] = str(struct.unpack('b', text[a+0x023a:a+0x023a+1])[0]) #int
			char['wis'] = str(struct.unpack('b', text[a+0x023b:a+0x023b+1])[0]) #wis
			char['dex'] = str(struct.unpack('b', text[a+0x023c:a+0x023c+1])[0]) #dex
			char['con'] = str(struct.unpack('b', text[a+0x023d:a+0x023d+1])[0]) #con
			char['char'] = str(struct.unpack('b', text[a+0x023e:a+0x023e+1])[0]) #char
	# better error checking/reporting would be nice
	return render_to_response('char.html', {'char': char})

And the template:

<h1>{{ char.name }}</h1>
<b>Hit Points</b>: {{ char.hp }}<br>
<b>Experience Points</b>: {{ char.xp }}<br>
<b>Strenght</b>: {{ char.str }}<br>
<b>Dexterity</b>: {{ char.dex }}<br>
<b>Constitution</b>: {{ char.com }}<br>
<b>Inteligence</b>: {{ char.int }}<br>
<b>Wisdom</b>: {{ char.wis }}<br>
<b>Charisma</b>: {{ char.char }}

The results:

You can read and write to any binary file with python – you just need the specification which shows where the data is located and what type it is :) Note that there aren't available specifications for most proprietary file formats.

Attachments (1)

Download all attachments as: .zip