Arena Mod:Technical Reference
The purpose of this reference material is for support of the information listed on UESP. Changing the game file could have unintended consequences for your game and could potentially pose a risk to other files on your computer. |
Contents
Game Executable[edit]
Hex Editor Basics[edit]
When you open a file in a HEX editor you are often presented with three windows. One window appears as a basic TEXT editor. A second window shows the lower level code presented in hexadecimal format. This is often organized in sections of eight characters each, while some editors show groups of two or four characters. A third window displays the location of the first byte (two characters) in the hexadecimal window which is also the first character in the text window. This location marker is often displayed in hexadecimal format. Opening the decompressed A.EXE file in a very narrow windowed hex editor you may be presented with the following:
00000 | 4D5A2001 7202440F | "MZ r D "
The first character in the text window is "M". This is a representation of the first byte in the hexadecimal window "4D" and it is located at "00000" The seventh character in the text window is "D". This is a representation of the seventh byte in the hexadecimal window "44" and is at location "00006". If you enter "Hex to Ascii" in your search engine, you can find a converter to enter "44" which can be converted to ASCII (text) as "D". It should be noted that what is presented in the text window depends on the font being used and some of the hexadecimal bytes will not represent any text character. The first example includes four spaces; however, only the first space was an original ascii text character. The remaining three were converted into standard spaces for the example.
While hexadecimal characters can represent text, they are actually numbers. The decimal system is based on ten characters. (0,1,2,3,4,5,6,7,8,9) The hexadecimal system is based on sixteen characters. (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) One value higher than nine is represented in the decimal system by combining "1" and "0" to make "10", while incrementing one number higher than nine in the hexadecimal system is represented by the character "A". The number fifteen is represented by "F" and incrementing one more to sixteen is represented by combining as in the decimal system. Hexadecimal "10" represents sixteen. This is important for understanding the locations, because you will often have to count, but you must remember to count in hexadecimal. Hex values are often listed with the hash or 0x prefix such as #4D or 0x4D and can be listed with lower-case letters as in 0x4d. The listing of the byte location for the character "D" was location "00006". A location reference is sometimes called an offset. Offsets are sometimes listed with an additional "@" prefix such as @06 or @0x06 and any preceding 0's may be left off. A location in the hex editor as "00FD8" may be listed as @fd8.
Bytes, Words, and Dwords[edit]
Generally the hexadecimal code is organized in sections of eight characters. In the previous example the first section was "4D5A2001".
- A BYTE consists of two characters. So the first section contains four bytes (4D, 5A, 20, 01). Bytes can be converted using a hex to ascii converter, (M, Z, (space), (non-character)), or using a hex to decimal converter (77, 90, 32, 1). Only convert one byte at a time. Just as combining decimals "10" and "10" are no longer two tens, but 1,010, combining "4D" and "5A" are no longer 77 and 90, but 19,802.
- A WORD is two bytes or four characters. The example contains two words. (4D5A, 2001). You can convert words using a hex to dec converter, but you have to enter the bytes from right to left. The first word "4D5A" is entered into the hex converter as "5A4D" and is converted to 23,117. The second word "2001" is entered into the hex converter as "0120" and converted to 288.
- A DWORD is two "words" (literally double-word), four bytes, or eight characters. The example is a single dword (4D5A2001). Dwords can be converted using a hex to dec converter, but as with words, you must enter the bytes from right to left. The dword "4D5A2001" is entered as "01205A4D" and converted to 18,897,485.
When using converters, enter the values without punctuation such as commas or parentheses.
2.56 Divisor[edit]
Often, after converting a hexadecimal byte to a decimal value, you must divide the decimal by 2.56 to arrive at the intended value. This is primarily used in the values for stats. This is used to take the full range of values possible in a single byte (0x00..0xFF / 0-255) and convert it to a range of 0..100. In some places in the code where these values were hand entered, like the monster stats, you will find a mix between calculating using 2.55 as well as 2.56. However, in the case with those entries, the internal values round up to the same whole numbers.
Sort Order[edit]
Values in the code will often be stored in an array with specific sort orders. For example the Hit Die for each class is stored one after the other but sorted by the Class order; Mage, Spellsword, etc. The base stat values are sorted first by Race, followed by Gender, and finally by Stat order. The first eight values are stats for a Breton male. The second set of eight are values for a Breton Female. The third set is for a Redguard male. The offset location only lists the first byte in the array. The offset for Character Stats is 0x39CF3 which is the location of the first byte in the array which represents the Strength stat for a Breton male.
- CLASS:
- Mage, Spellsword, Battlemage, Sorceror, Healer, Nightblade, Bard, Burglar, Rogue, Acrobat, Thief, Assassin, Monk, Archer, Ranger, Barbarian, Warrior, Knight
- RACE:
- Bretons, Redguards, Nords, Dark Elves, High Elves, Wood Elves, Khajiit, Argonians
- GENDER:
- Male, Female
- STAT:
- STR, INT, WIL, AGI, SPD, END, PER, LUC
- MONSTER:
- Rat, Goblin, Lizard Man, Wolf, Snow Wolf, Orc, Skeleton, Minotaur, Spider, Ghoul, Hell Hound, Ghost, Zombie, Troll, Wraith, Homonculus, Ice Golem, Stone Golem, Iron Golem, Fire Daemon, Medusa, Vampire, Lich
- MONSTER LOOT TYPE:
- Gold, Magic Item or Potion, Base Weapon or Armor, Magic Weapon or Armor
Game Code[edit]
Description | Offset | Data Structure | Sort Order/Value |
---|---|---|---|
Initial Health Modifier | 0x1655B | BYTE | +(25) |
Initial Gold (min) | 0x165B2 | BYTE | min(50) |
Initial Gold (max) | 0x165B5 | BYTE | max(200) |
Initial Bonus Point Die | 0x165CF | BYTE | d(25) |
Initial Stat Die | 0x1715D | BYTE | d(20) |
Initial Health "if <1" | 0x17191 | BYTE | <(1) |
Initial Health "+1" if 0 | 0x17196 | BYTE | +(1) |
Drink Limit Divisor (Default) | 0x1F63D | BYTE
Divide decimal result by 2.56 |
25
(END ÷ 9.804) |
Drink Limit Divisor (Breton) | 0x1F642 | BYTE
Divide decimal result by 2.56 |
12
(END ÷ 4.706) |
Drink List Range Limit | 0x1F93F | BYTE | 15 |
Ria Vision Limiter | 0x20D40 | BYTE | 8 |
Base Player Stats | 0x39CF3 | BYTE (array)
First 8 bytes are Breton male stats Divide decimal result by 2.56 |
Race / Gender / Stat |
Monster Stats | 0x39DBB | BYTE (array)
First 8 bytes are Rat stats Divide decimal result by 2.56 |
Monster / Stat |
Monster Loot Chance | 0x3B139 | BYTE (array)
First 4 bytes are for Rat |
Monster / Loot Type |
Class Hit Die | 0x42001 | BYTE (array) | Class |
Monster No Corpse | 0x4204E | BYTE (array) | Monster |
Monster Level | 0x42096 | BYTE (array) | Monster |
Monster Hit Point Range (HP) | 0x420DE | WORD (array)
1st Word is Rat min HP 2nd Word is Rat max HP |
Monster |
Monster Experience Points | 0x4213E | DWORD (array) | Monster |
Monster Exp/HP | 0x4219E | BYTE (array) | Monster |
Monster Damage Range | 0x421B6 | BYTE (array)
1st Byte is Rat min Damage 2nd Byte is Rat max Damage |
Monster |
Wilderness Block (List A) | 0x42D5C | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Wilderness Block (List B) | 0x42D75 | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Wilderness Block (List C) | 0x42D82 | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Wilderness Block (List D) | 0x42D8F | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Wilderness Block (List E) | 0x42D9A | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Wilderness Block (List F)
Not Used |
0x42DA6 | BYTE (array)
1st Byte represents the number of Blocks in the list |
Numerical Order |
Notes[edit]
- The information provided is basic and specific to Arena and may not apply to other areas.
- All information on this page is specific to version 1.06 but also applies to version 1.07 except where noted.
- All location markers (offsets) were obtained using A.EXE version 1.06 and decompressed using UNP version 4.11 with default parameters. The information is the same as ver 1.07 but the offsets are different.
- Initial Health modifiers at offset 0x17191 and 0x17196 work together for a +1 bonus if your Health modifier from your END stat is +0 and your initial Health die roll is also 0. Testing shows that if your Health die roll plus the END stat bonus is less than the value at 0x17191, then your Health value will be the value located at 0x17196 + 25. An unexpected exception occurs if the scenario has the same values but the END bonus is -1. If the Health die and END bonus equal -1 it will remain unchanged and your final starting Health will be 24. This has a very low probability of occurring, but is possible.
- The Ria Vision Limiter byte controls when to stop showing Visions. This is set to 08 and if the player has eight staff pieces in their inventory, then no Visions from Ria Silmane will show. If a new game is modified to start the player with eight staff pieces in their inventory, and the Limiter byte is changed to 09 then the final Ria Vision will be displayed when sleeping after reaching level two. In version 1.07 the byte is located at 0x22BEC.
- When saving a game, dungeon maps will be fuzzy or distorted when reloading from the save. This is apparently caused by the game unpacking the map in a different order from the method used to store it. It's possible to modify the game so that this does not occur. For 1.06, beginning at offset 0x2674C; the fourteen bytes (8A DC 83 E3 03 64 8A 87 F6 45 AA C0 EC 02) should be changed to (C0 C4 02 8A DC 83 E3 03 64 8A 87 F6 45 AA). For 1.07, beginning at offset 0x281E9; the fourteen bytes (8A DC 83 E3 03 64 8A 87 30 47 AA C0 EC 02) should be changed to (C0 C4 02 8A DC 83 E3 03 64 8A 87 30 47 AA).
- The drink list is located at 0x4153E and contains 21 drinks, although the Drink List Range Limit is set to only use the first 15. (Drink prices is a BYTE array starting at 0x41614.)
LOG.0x[edit]
This file is created as part of a game save. The "x" in the file extension represents the number assigned to the game slot you chose, with the top box being 0 and the bottom box being 9.
In version 1.07, this file will contain all the quests you accept during your game. For previous versions, the file has a limit in order to conserve disk space. Whenever the file becomes two thousand bytes or larger, the game will remove the oldest entry when it adds a new entry. This results in the file containing approximately the last ten to sixteen quests depending on the amount of text in each quest.
Each entry begins with the "&" symbol and ends with " *". The space before the asterisk is important because without it, the previous character will not appear in the log. The text immediately following the ampersand is the game date the quest was accepted and will be displayed as a title and highlighted in red. This title is ended with two bytes represented in hex as 0D and 0A. The 0A byte is used to start a new line and used throughout the rest of the text as the logbook does not automatically wrap the text if a sentence is too long. Without the 0A byte, the text will eventually return to the left side of the screen and begin writing over the same line and may cause the game to lock after opening the file.
SAVEENGN.0x[edit]
This file is created as part of a game save. The "x" in the file extension represents the number assigned to the game slot you chose, with the top box being 0 and the bottom box being 9.
Encryption[edit]
Certain sections of this file are encrypted and must be converted before being used. While a single formula is used to encrypt the entire section, it can sometimes be simplified by understanding that each byte in an encrypted area has it's own encryption key. A byte is two characters such as 9D and each character is called a NIBBLE. The left nibble is 9 and the right nibble is D. If this were a player's level, you could use the key to determine that the left nibble 9 is unscrambled to 1, and the right nibble D is unscrambled to A. If you enter 1A into a Hex to Decimal converter, you will find that the player's level is twenty six.
Level[edit]
Offset | Data Structure | Sort Order/Value |
---|---|---|
0x06 | BYTE(encrypted) | {1..256} |
The smallest amount a player can have is represented by hex value 87. One is added to this value making the lowest level "1" instead of "0". This value can be edited to 78 making the player level 256 when the game is started. However, this does not occur naturally and will be adjusted the next time experience is gained. Also, moving from level 27 to 28 requires the standard amount of experience; however, it no longer operates as expected and will be a value different than 28.
The following table shows the encryption values for the byte used for player level.
Offset | NIBBLE | Values | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Unscrambled | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x06 | Left | 8 | 9 | A | B | C | D | E | F | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Right | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | F | E | D | C | B | A | 9 | 8 |
Experience[edit]
Offset | Data Structure | Sort Order/Value |
---|---|---|
0x0409 | DWORD(encrypted) | {0..4294967295} |
The smallest amount a player can have is represented by 2952A448 and the largest by D6AD5BB7. If this value is increased, the next time "experience" is gained in the game, your character's level will be raised to the appropriate level matching the experience. You will also receive the standard three to six bonus points, but multiplied by the number of levels you increased. (See the Level section for exceptions.)
The following table shows the encryption values for each byte of the dword used for player experience.
Offset | NIBBLE | Values | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Unscrambled | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x0409 | Left | 2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 | A | B | 8 | 9 | E | F | C | D |
Right | 9 | 8 | B | A | D | C | F | E | 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 | |
0x040A | Left | 5 | 4 | 7 | 6 | 1 | 0 | 3 | 2 | D | C | F | E | 9 | 8 | B | A |
Right | 2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 | A | B | 8 | 9 | E | F | C | D | |
0x040B | Left | A | B | 8 | 9 | E | F | C | D | 2 | 3 | 0 | 1 | 6 | 7 | 4 | 5 |
Right | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | C | D | E | F | 8 | 9 | A | B | |
0x040C | Left | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | C | D | E | F | 8 | 9 | A | B |
Right | 8 | 9 | A | B | C | D | E | F | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Gold in Inventory[edit]
Offset | Data Structure | Sort Order/Value |
---|---|---|
0x041E | DWORD(encrypted) | {0..4294967295} |
The smallest amount a player can have is represented by 18305EB8 and the largest by E7CFA147. The hex value 18FAC483 will give a player one million gold and changing just the single byte at 0x41F to CC, will give approximately sixty-five thousand gold. If you happened to have the maximum amount of gold, the next amount you gain will cause the value to roll over and you will loose the previous amount.
The following table shows the encryption values for each byte of the dword used for gold.
Offset | NIBBLE | Values | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Unscrambled | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x041E | Left | 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 | 9 | 8 | B | A | D | C | F | E |
Right | 8 | 9 | A | B | C | D | E | F | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
0x041F | Left | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | B | A | 9 | 8 | F | E | D | C |
Right | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x0420 | Left | 5 | 4 | 7 | 6 | 1 | 0 | 3 | 2 | D | C | F | E | 9 | 8 | B | A |
Right | E | F | C | D | A | B | 8 | 9 | 6 | 7 | 4 | 5 | 2 | 3 | 0 | 1 | |
0x0421 | Left | B | A | 9 | 8 | F | E | D | C | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 |
Right | 8 | 9 | A | B | C | D | E | F | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Blessing[edit]
Offset | Data Structure | Sort Order/Value |
---|---|---|
0x0422 | WORD(encrypted)
Divide decimal result by 2.56 |
{0..25600}
Practical ver. 1.06 {0..1953} Practical ver. 1.07 {0..781} |
There is a max limit of 9999 for donation at a temple, so only a small portion of the full range of values are used. The half-price for blessings during the Mid Year Celebration doesn't work in version 1.07 making the practical range smaller.
The following table shows the encryption values for each byte of the word used for blessings.
Offset | NIBBLE | Values | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Unscrambled | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x0422 | Left | 6 | 7 | 4 | 5 | 2 | 3 | 0 | 1 | E | F | C | D | A | B | 8 | 9 |
Right | 8 | 9 | A | B | C | D | E | F | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
0x0423 | Left | C | D | E | F | (remaining values are not possible in-game) | |||||||||||
Right | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
Detail (View Distance)[edit]
Offset | Data Structure | Default Value |
---|---|---|
0x0B90 | DWORD | 7EF8 E8C6 |
The "Detail" setting in the in-game menu ranges from 0-19 notches in the game, with 0 being "7EF8 E8C6". This value can be increased well beyond the max. An arbitrarily high value to set it to is "CF90 36FA" which will render more than the maximum normally allowed by the game and is still resolved by the 320x200 resolution.
Main Quest Flags[edit]
These are in the encrypted section, yet because most of them are simply on/off indicators, it isn't necessary to convert them. The following table shows how the values change after specific actions. Bold values indicate a change from the previous step.
STEP# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 |
---|---|---|---|---|---|---|---|---|
Offset | New | 1st Vision | Exit Dungeon | Talk to Quest Giver (refuse) | Talk to Quest Giver (accept) | Pick up Quest Item | Give Item to Quest Giver | Pick Up 1st Staff Piece |
0x0DD2 | E8 | E9 | E9 | E9 | E9 | E9 | E9 | E8 |
0x0DD3 | C0 | C0 | C0 | C0 | C0 | C0 | C0 | C1 |
0x0DD4 | 60 | 60 | 60 | 60 | 61 | 61 | 61 | 60 |
0x0DD5 | 80 | 80 | 80 | 80 | 81 | 81 | 81 | 80 |
0x0DD6 | 80 | 81 | 81 | 81 | 81 | 81 | 81 | 80 |
0x0DD7 | 00 | 00 | 00 | 01 | 01 | 00 | 01 | 00 |
0x0DD8 | 00 | 00 | 00 | 00 | 01 | 01 | 01 | 00 |
0x0DD9 | 01 | 01 | 01 | 01 | 01 | 00 | 00 | 01 |
0x0DDA | 03 | 03 | 02 | 02 | 02 | 02 | 02 | 03 |
0x0DDB | 07 | 07 | 07 | 07 | 07 | 06 | 07 | 07 |
- 0x0DD2 - "E8" allows a Ria vision to trigger during camping. Which vision is displayed depends on the value at 0x0DD3. The quest giver will not offer a quest until this flag is set to "E9".
- 0x0DD3 - The value at this location represents the number of staff pieces as a range {C0..C8}. It controls the number staff pieces listed in the inventory, which vision is shown (Ria and Jagar "enemy" encounters), the main quest location in an NPC's "Where is" dialogue, and which death scene is displayed (Ria or Jagar). If this value is changed to {C1..C7} before starting a game, after reaching level two, camping will result in two visions. The first is an introduction to the Staff of Chaos and the second is a message indicating the location of the next staff piece, based on the value entered. If this value is changed to C8, no Ria vision occurs.
- 0x0DD4 - When this value is "61", NPCs do not offer the main quest location option in the "Where is" dialogue.
- 0x0DDA - If you exit the dungeon before receiving a Ria vision, the value will remain "03", until you exit some other interior such as a dungeon or an inn.
- 0x0DDB - When this value is "06" the initial quest item (e.g. parchment) is displayed in your inventory. The specific item displayed depends on the value at 0x0DD3. The item names are from a list in the executable file at 0x44008.
The dungeon locations are only added to the continental map during a conversation with a quest giver and are not contained in this file.
The information below this notice is copied from the 1994 Unofficial FAQ. This information should be tested, updated, and then incorporated above this notice until fully incorporated. |
How do you make spells more powerful and cost less?[edit]
It's much easier to edit the spells, since they're kept in clear hex. Use Spellmaker to create a spell that does 1-1 pts of damage, +1-1/level, then look the spell up in the SPELLS.xx file (where xx is the savegame #), and change it to 99-99, + 99-99/level, etc, etc. [see 17 below for details.]
You can also edit the % chance, plus the duration, etc.... You'll also find a couple of new spell effects in here, that probably never got implemented, CAGE and DEATH SPELL. Attempting to use them generally results in disharmonious outcomes... [Advice - Do not try them].
The following is extracted from a spellbook to demonstrate the method used to change the value of a purchased spell. [Each line below starts with its offset from the beginning of the file (in hex) and then the 16 hex bytes, followed on the right with the ASCII equivalents.] The values to change all precede the name of the spell. Multiple spells follow on each other and follow the same pattern.
PCTools DiskEdit Version 9.0 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0 4 8 C 000 63 00 63 00 63 00 01 00 01 00 63 00 00 00 00 00 c.c.c...c..... ^^ ^^ ^^ ** ** ** 010 01 00 00 00 00 00 01 00 1E 00 01 00 01 00 00 00 ........... && && && 020 00 00 00 00 00 00 05 00 00 14 0F 0C 00 00 01 00 ............. 030 00 FF 01 00 72 65 67 65 6E 2F 69 6E 76 2F 68 65 ...regen/inv/he ++ ++ 040 61 6C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 al.............. 050 00 00 00 00 00 .....
Patching spells..... You must use a hexadecimal editor. Examples include the DiskEdit from both Central Point's PCTools and Norton/Symantec's Norton Utilities.
The 63 over each ^^ in the first line above changes the original 01 points to 99 points.
Where the spell has wording such as 1 to 1 points, as heal does, the 63 over the ** in the first line changes it to 99 to 99 points
The values over the &&s is the number of turns between repeats. 1E is equivalent to 30 turns. Change as desired.
The 01 00 over the ++ changes the cost of the spell to 0 spell points.
This pattern using 85 bytes repeats for each spell in a spell book.
32 spells can be added to the spells book, requiring 2720 bytes, which is the size of the SPELLS.xx file, where xx is a value of between 00 and 09, and depends on the saved character's position in the list of saved games.