Swords of Glass people format
Jump to navigation
Jump to search
Swords of Glass people format
Format type | Saved game |
---|---|
Save locations | Unrestricted |
Elements saved | Character stats, items |
Games |
The character data in Swords of Glass is stored in the People.dat file. The file is fixed-width and stores 20 characters. Only those characters with an Unused flag set to false (0) are active.
Characters
Data type | Description |
---|---|
UINT8 X position | The X position of the character in the dungeon. |
UINT8 Y position | The Y position of the character in the dungeon. |
UINT8 Z position | The Z position (floor) of the character in the dungeon. |
UINT8 Strength | Character's strength. |
UINT8 Dexterity | Character's dexterity. |
UINT8 IQ | Character's IQ. |
UINT8 Class | 1 - Warrior, 2 - Magician. |
1 Byte Unknown | ? |
UINT8 Level | Character's level. |
INT16LE Max HP | Maximum hit points. Game caps at 255. |
INT16LE HP | Current hit points. Game caps at 255. |
INT16LE Dead flag | 0 - Alive, -1 - Dead. When a character dies, this flag is set to true (-1). |
4 Bytes Unknown | ? |
INT16LE Unused flag | 0 - Used, -1 - Unused. If this flag is true (-1), this character slot is unused. |
Real Experience | The character's experience. |
Real Gold | The character's gold. |
1 Byte Unknown | ? |
12 Items | See the Item structure. |
UINT8[10] Max MP | Maximum magic power for each level. Game caps at 99. |
UINT8[10] MP | Current magic power for each level. Game caps at 99. |
UINT8[30] Spell flag | 0 - No, 1 - Yes. Flags for which spells this character knows. |
7 Bytes Unknown | ? |
UINT8 Name length | Length of this character's name. |
char[7] Name | The character's name. Names are always 7 bytes, but you should only display the length of bytes read from the previous value. |
Items
Each player has 12 item slots. If the item id is zero, the slot is empty. Both empty and occupied slots are 15 bytes.
Data type | Description |
---|---|
UINT8 Item id | The id of the item found in the CNames.dat file. If zero, this slot is empty. |
UINT8 Bonus | The bonus to the item (like Sword +1). The game never goes above +9, but it accepts over-buffed items. |
INT16LE Quantity/Durability | For items like arrows, this holds the quantity, but for non-stackable items like a sword or armor, this is the durability of the item. It will break at 0. The game never has quantities greater than 9, but accepts them. |
UINT8 Name length | The length of the item's name. Always 0x0A. |
char[10] Name | The name of the item. You can create custom names since the game uses id for everything. |
Source Code
Exporter
This FreeBASIC program will export each player slot into a text file.
Declare Function RealToDouble(Real48() As UByte) As Double
Dim As Integer PlayerNo, ByteNo, ItemNo, SpellLevel, SpellNo
Dim As UByte PositionX, PositionY, PositionZ, Strength, Dexterity, IQ, ClassId, Unknown1, Level
Dim As UByte Unknown2, Unknown3, Unknown4, Unknown5, Unknown6, Unknown7, Experience(0 To 5)
Dim As UByte Gold(0 To 5), MaxMagicPower(0 To 9), MagicPower(0 To 9)
Dim As UByte SpellFlag(0 To 29), ItemId(0 To 11), Bonus(0 To 11), ItemNameLength(0 To 11), Unknown8
Dim As UByte Unknown9, Unknown10, Unknown11, Unknown12, Unknown13, PlayerNameLength
Dim As String ItemName(0 To 11), PlayerName
Dim As Short MaxHitPoints, CurrentHitPoints, Deceased, Unused, QuantityOrDurability(0 To 11)
Open "People.dat" For Binary As #1
Open "People.txt" For Binary As #2
For PlayerNo = 0 To 19
Get #1, , PositionX
Get #1, , PositionY
Get #1, , PositionZ
Get #1, , Strength
Get #1, , Dexterity
Get #1, , IQ
Get #1, , ClassId
Get #1, , Unknown1
Get #1, , Level
Get #1, , MaxHitPoints
Get #1, , CurrentHitPoints
Get #1, , Deceased
Get #1, , Unknown2
Get #1, , Unknown3
Get #1, , Unknown4
Get #1, , Unknown5
Get #1, , Unused
For ByteNo = 0 To 5
Get #1, , Experience(ByteNo)
Next ByteNo
For ByteNo = 0 To 5
Get #1, , Gold(ByteNo)
Next ByteNo
Get #1, , Unknown6
For ItemNo = 0 To 11
ItemName(ItemNo) = Space(10)
Get #1, , ItemId(ItemNo)
Get #1, , Bonus(ItemNo)
Get #1, , QuantityOrDurability(ItemNo)
Get #1, , ItemNameLength(ItemNo)
Get #1, , ItemName(ItemNo)
Next ItemNo
For SpellLevel = 0 To 9
Get #1, , MaxMagicPower(SpellLevel)
Next SpellLevel
For SpellLevel = 0 To 9
Get #1, , MagicPower(SpellLevel)
Next SpellLevel
For SpellNo = 0 To 29
Get #1, , SpellFlag(SpellNo)
Next SpellNo
Get #1, , Unknown7
Get #1, , Unknown8
Get #1, , Unknown9
Get #1, , Unknown10
Get #1, , Unknown11
Get #1, , Unknown12
Get #1, , Unknown13
PlayerName = Space(7)
Get #1, , PlayerNameLength
Get #1, , PlayerName
Put #2, , "Player Id: " + Str(PlayerNo) + Chr(13) + Chr(10)
Put #2, , "Player Is Active?: " + IIf(Unused = True, "No", "Yes") + Chr(13) + Chr(10)
If Unused = False Then
Put #2, , "Player Is Alive?: " + IIf(Deceased = True, "No", "Yes") + Chr(13) + Chr(10)
Put #2, , "Player Name: " + Left(PlayerName, PlayerNameLength) + Chr(13) + Chr(10)
Put #2, , "Dungeon Coordinates: X(" + Str(PositionX) + "), Y(" + Str(PositionY) + "), Z(" + Str(PositionZ) + ")" + Chr(13) + Chr(10)
Put #2, , Chr(13) + Chr(10)
Put #2, , "Class: " + IIf(ClassId = 1, "Warrior", "Magician") + Chr(13) + Chr(10)
Put #2, , "Level: " + Str(Level) + Chr(13) + Chr(10)
Put #2, , "Experience: " + Str(RealToDouble(Experience())) + Chr(13) + Chr(10)
Put #2, , "Stats: Str(" + Str(Strength) + "), Dex(" + Str(Dexterity) + "), IQ(" + Str(IQ) + ")" + Chr(13) + Chr(10)
Put #2, , "Hit Points: " + Str(MaxHitPoints) + "/" + Str(CurrentHitPoints) + Chr(13) + Chr(10)
Put #2, , "Gold: " + Str(RealToDouble(Gold())) + Chr(13) + Chr(10)
Put #2, , Chr(13) + Chr(10)
Put #2, , "Magic Power: "
For SpellLevel = 0 To 9
Put #2, , Str(MaxMagicPower(SpellLevel)) + "/" + Str(MagicPower(SpellLevel)) + ", "
Next SpellLevel
Put #2, , Chr(13) + Chr(10)
Put #2, , "Spells: "
For SpellNo = 0 To 29
Put #2, , Str(SpellNo) + ":" + IIf(SpellFlag(SpellNo) = 1, "Y", "N") + ","
Next SpellNo
Put #2, , Chr(13) + Chr(10)
Put #2, , "Items: " + Chr(13) + Chr(10)
For ItemNo = 0 To 11
If ItemId(ItemNo) > 0 Then
Put #2, , "Id: " + Str(ItemId(ItemNo)) + " - " + Left(ItemName(ItemNo), ItemNameLength(ItemNo))
Put #2, , IIf(Bonus(ItemNo) > 0, " +" + Str(Bonus(ItemNo)), "") + " - "
Put #2, , "Qty/Durability: " + Str(QuantityOrDurability(ItemNo)) + Chr(13) + Chr(10)
End If
Next ItemNo
Put #2, , Chr(13) + Chr(10)
Put #2, , "Unknown Bytes: " + Str(Unknown1) + ", " + Str(Unknown2) + ", " + Str(Unknown3) + ", "
Put #2, , Str(Unknown4) + ", " + Str(Unknown5) + ", " + Str(Unknown6) + ", " + Str(Unknown7) + ", "
Put #2, , Str(Unknown8) + ", " + Str(Unknown9) + ", " + Str(Unknown10) + ", " + Str(Unknown11) + ", "
Put #2, , Str(Unknown12) + ", " + Str(Unknown13)
End If
Put #2, , Chr(13) + Chr(10)
Put #2, , Chr(13) + Chr(10)
Put #2, , Chr(13) + Chr(10)
Next PlayerNo
' Convert a Pascal 48-bit Real into a standard Double.
Function RealToDouble(Real48() As UByte) As Double
Dim Exponent As Double
Exponent = Real48(0) - 129.0
Dim Mantissa As Double
Dim Value As Double
Value = 1
Dim ByteNo As Byte
For ByteNo = 5 To 1 Step -1
Dim StartBit As Byte
StartBit = 7
If ByteNo = 5 Then StartBit = 6
Dim BitNo As Byte
For BitNo = StartBit To 0 Step -1
Value = Value / 2
If ((Real48(ByteNo) ShR BitNo) And 1) = 1 Then
Mantissa = Mantissa + Value
End If
Next BitNo
Next ByteNo
If Mantissa = 1.0 And Real48(0) = 0 Then
Return 0.0
End If
If Real48(5) And &H80 = -1 Then
Mantissa = -Mantissa
End If
Dim Result As Double
Mantissa = Mantissa + 1
Result = Mantissa * (2 ^ Exponent)
Return (Result)
End Function
Credits
This save game format was reverse engineered by TheAlmightyGuru. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)