Home

A title this would be, had I the originality.

Dragonwars savegame format

Dewi

defaultShades

Advertisement

Dragonwars savegame format

Previous Entry Add to Memories Tell a Friend Next Entry
defaultShades
Been playing DragonWars a little lately. Nice enough game, but...

I think I'll give up on it. In order to play all 4 games I intended to (Dragon Wars, Bard's Tale 1-3) and enjoy the game plots and story arcs without being bored to tears, I'd have to:

1) hack the save files (done);

2) write a savegame-backup script (they have only one save slot!) (done);

3) hotkey the whole tedious combat experience (could do easily); because combat really gets old fast, two or three combats and I'm sick of them already. I've done hundreds. I spent 20 minutes clicking buttons for one combat - and got 4XP for the party at the end!

4) script an automap for the three that don't have one (feasible); DragonWars has a nice enough automap, the others don't, and I can't be bothered with graph paper nowadays.

5) script a paragraph-display for Dragonwars (tricky); this is because it occasionally pops up "read paragraph 287" or somesuch, and you have to flip through the manual to find it. I have both the manual and a PDF of it, but still... distracting, I just want to play the game!

... but I think I'll just go play something more interesting instead. There are limits to even my gamer-masochism.

But I thought I'd save what I'd done so far here, just in case anyone else was feeling masochistic.

First, the savegame format. For Bard's Tale 1-3 it's a matter of record and plenty of places have it. For DragonWars, nowhere seems to have it, so here is what I could find out.

Each character's info is 200Hex bytes long.

The characters are stored at 2E26, 3036, 3226, 3426, 3626 and I presume onwards if you have more than 5 characters in your party. The order they are displayed on screen is the order they are in the savegame.

Name Strings for items and characters are stored a little unusually. They are allocated 12 bytes, and the high byte of every byte except the last character of the name is set. So, the string ends after the first character that does not have the high bit set. If the name is less than the full 12 characters then generally the next character is a null, and the rest are random, but they don't need to be. If you put in the string "Sword" (no high bits set) then you will see the string "S" displayed, since it ends after the first character that has no high bit set, regardless of what follows.

All numbers are stored little-endian, so the least significant byte first. For example, 0x0201 (513dec) would be stored as "01 02" in your hex editor. I doubt any of these numbers are signed, but I generally never took them high enough to be sure.

The character information blocks are pretty obvious in a hex editor, but to make sure that they aren't in a slightly different place, find the name of your first character as a NameString, and work from there. At least one site reports the info at a different address, claiming to find the health info where I see the name. That site also has Bard's tale save file info).

Each character information block is split up as follows:
2E26 - 2E31 12 bytes. Character name as Name String (see above).
2E32 1 byte. Str - each of the next 4 stats is repeated, I guess for current and max values.
2E33 1 byte. Str
2E34 1 byte. Dex
2E35 1 byte. Dex
2E36 1 byte. Int
2E37 1 byte. Int
2E38 1 byte. Spr
2E39 1 byte. Spr
2E3A - 2E3B 2 bytes. Current health.
2E3C - 2E3D 2 bytes. Max health.
2E3E - 2E3F 2 bytes. Current stun.
2E40 - 2E41 2 bytes. Max stun.
2E42 - 2E43 2 bytes. Current pow.
2E44 - 2E45 2 bytes. Max pow.
2E46 - 2E60 27 bytes. Skills, see list below.
2E61 1 byte. Number of advancement points left to spend.
2E62 - 2E69 8 bytes. Bitfield for spells. See below.
(The following may all be arranged in a more complex bitfield, I dunno.)
2E6A - 2E71 8 bytes. [Unknown purpose, always seems to be 0?]
2E72 1 bytes. Status bitfield. 0=OK, 1=dead, 2=chained, 4=poisoned. (part of a larger bitfield? Setting other values seems to do nothing.)
2E73 1 byte. [Unknown purpose, always 0?]
2E74 1 byte. 0 if male, 1 if female. (part of a larger bitfield?  Setting other values seems to do nothing, though the manual does claim "Male, female, sometimes, never" as values for gender.)
2E75 - 2E76 2 bytes. Level.
2E77 - 2E7A 4 bytes. XP.
2E7B - 2E7E 4 bytes. Gold.
2E7F 1 byte. Armor Value.
2E80 1 byte. Defence Value.
2E81 1 byte. Armor Class.
2E82 1 byte. (unknown purpose, but not 0).
2E83 - 2F11 143 bytes. (unknown purpose, always 0, possibly padding?).
2F12 - 3025 276 bytes. The inventory, as 12 items * 23 bytes. See below.


Inventory
I haven't done a whole lot of work on the inventory. It's clearly a bitfield and there are bits that I haven't figured out the meaning of yet.

Byte addresses are for the first item in the first character's inventory.

2F12 - 8 if wielded, 0 if not.
2F13 - Bits 2 & 3 are the stat required to use the weapon. 0x02=Dex, 0x04=Int, 0x06=Spi. Bit 0 seems to do nothing, and using any higher bits in the byte gives garbage skillnames when taking the item to be evaluated at a trader.
2F14 - Bits 1-5 are how many points are required for the above skill, 0 to 31. Don't know what the top 3 bits are for, but setting them does not affect the displayed skill requirement when evaluating.
2F15 - Unknown. Seen as 0x00 (hand axe) and 0x10 (battle axe, dagger, shortsword).
2F16 - Type, see below.
2F17 - Unknown. Only seen as 0x80.
2F18 - Unknown. Only seen as 0x00.
2F18 - Unknown. Seen as 0x40 (hand axe), 0x80 (battle axe), 0x00 (dagger), 0x20 (shortsword).
2F19 - Unknown. Only seen as 0x00.
2F1A - Unknown. Only seen as 0x01.
2F1B - 2F26 (12 bytes) Name string for the item. See above for explanation of name strings.

Item types
0x00 - General Item
0x01 - Shield
0x02 - Full Shield
0x03 - Axe
0x04 - Flail
0x05 - Sword
0x06 - Two-handed sword
0x07 - Mace
0x08 - Bow
0x09 - Crossbow
0x0A - Gun
0x0B - Thrown weapon
0x0C - Ammunition
0x0D - Gloves
0x0E - Mage Gloves
0x0F - Ammo Clip
0x10 - Cloth Armor
0x11 - Leather Armor
0x12 - Cuir Bouilli Armor
0x13 - Brigandine Armor
0x14 - Scale Armor
0x15 - Chain Armor
0x16 - Plate And Chain Armor
0x17 - Full plate Armor
0x18 - Helmet
0x19 - Scroll
0x1A - Pair of Boots
0x1B and above - blank (no text).


Skills list
Each of these skills has 1 byte each.

What "Merchant" does, I don't know - it does not appear on the "X" experience point list, but will appear under your character's general skills list if you hack some points into it. An unimplemented or hidden stat?

2E46 - Arcane Lore
2E47 - Cave Lore
2E48 - Forest Lore
2E49 - Mountain Lore
2E4A - Town Lore
2E4B - Bandage
2E4C - Climb
2E4D - Fistfighting
2E4E - Hide
2E4F - Lockpick
2E50 - Pickpocket
2E51 - Swim
2E52 - Tracking
2E53 - Bureaucracy
2E54 - Druid Magic
2E55 - High Magic
2E56 - Low Magic
2E57 - Merchant
2E58 - Sun Magic
2E59 - Axe
2E5A - Flail
2E5B - Mace
2E5C - Sword
2E5D - 2-Handed Sword
2E5E - Bow
2E5F - Crossbow
2E60 - Thrown Weaponry



Spells bitfield
I'm giving the bytes in the "reverse" order here, as it is little endian and this makes the spells group more logically. One of the things I always worry about spells is that spells are often used for "quest gates" - you can't complete the quest until you have the spell to unlock the gates, or turn the statue to a living person or whatever. I don't know if this is done in this game, but if you want to follow the plot, it might be worth just going with hacking the purely offensive, defensive, and healing ones, rather than the world changing ones like summons, wall creation/removal, etc.

2E4E
0x01 - [Not used]
0x02 - [Not used]
0x04 - [Not used]
(Misc spells)
0x08 - Poison
0x10 - Kill Ray
0x20 - Zak's Speed
0x40 - Charger
0x80 - Summon Salamander

2E4D
0x01 - Radiance
0x02 - Guidance
0x04 - Disarm Trap
(Sun Spells)
0x08 - Major Heal
0x10 - Heal
0x20 - Sun Light
0x40 - Armor of Light
0x80 - Light Flash

2E4C
0x01 - Mithras' Bless
0x02 - Column of Fire
0x04 - Battle Power
0x08 - Holy Aim
0x10 - Inferno
0x20 - Fire Storm
0x40 - Wrath of Mithras
0x80 - Rage of Mithras

2E4B
0x01 - Exorcism
0x02 - Sunstroke
0x04 - Wood Spirit
0x08 - Beast Call
0x10 - Invoke Spirit
0x20 - Soften Stone
0x40 - Create Wall
0x80 - Cure All

2E4A
0x01 - Exorcism
0x02 - Sunstroke
 (Druid magic)
0x04 - Wood Spirit
0x08 - Beast Call
0x10 - Invoke Spirit
0x20 - Soften Stone
0x40 - Create Wall
0x80 - Cure All

2E49
0x01 - Greater Healing
0x02 - Brambles
0x04 - Scare
0x08 - Whirlwind
0x10 - Insect Plague
0x20 - Fire Blast
0x40 - Death Curse
 (High magic)
0x80 - Fire Summon

2E48
0x01 - Water Summon
0x02 - Earth Summon
0x04 - Air Summon
0x08 - Sense Traps
0x10 - Cloak Arcane
0x20 - Group Heal
0x40 - Healing
0x80 - Cowardice

2E47
0x01 - Vorn's Guard
0x02 - Sala's Swift
0x04 - Reveal Glamor
0x08 - Mystic Might
0x10 - Dazzle
0x20 - Big Chill
0x40 - Ice Chill
0x80 - Poog's Vortex

2E46
0x01 - Elvar's Fire
0x02 - Fire Light
 (Low magic)
0x04 - Mage Light
0x08 - Lesser Heal
0x10 - Luck
0x20 - Charm
0x40 - Disarm
0x80 - Mage Fire


Batch file for backing up saves
This is pretty sucky - it doesn't diff the files and only save if it's different, for instance, so you'll get way more saves than you need if you save rarely... and if you want to restore from backup, you'll need to copy it yourself.

It's modified from a similar but more complex version I did for Falcon's Eye, which worked better.

Anyway, for what it's worth... (obviously this is public domain code, use it all you want!)

@echo off

:loop
echo Hit enter to restore from your latest save.
echo Or anything else to quit.
set /P in=Your call: 

if X%in%==X goto play
goto end

:play
dragon.com
if exist data1 goto save
goto loop

:save
REM Yes, this does check for the existence of 500 files. Yes, it is faster than you'd think: the dir info gets cached.
set b=test
for /L %%a in (1,1,500) do if exist saves\save.%%a set b=%%a
set /A b=%b% + 1
echo Saving to saves\save.%b%
copy data1 saves\save.%b%
goto loop

:end
echo Quitting at user request.
set /P a=Hit enter
pause
  • Dude - too much spare time!

    I loves Bards Tale on the Amiga. I remember mapping loads of the levels on graph paper, and then getting pissed off when I realised there were areas that "looped". Grr.
Powered by LiveJournal.com