Skip to content

The Joy of Game Hacking – Part 2

October 5, 2012

The Joy of Game Hacking – Part 2

WARNING!! Before proceeding with these procedures, you should make a backup copy your Wiz1.dsk file to a safe location.  Mine was located in C:\users\tom\D-Fend Reloaded\VirtualHD\wizardry-proving-grounds-of-the-mad-overloard.  Yours may be in a different location depending upon your installation.  You can search for it in Windows.

NOTE:  I created the images for this tutorial over a period of time.  There may be some changes between one image and the next as far as the addresses that are being examined.  If you do this in one session, your addresses will be consistent.

You WILL need to understand a little computer mathematics in order for you to intelligently perform the procedures that will follow.  You will need to understand how to work with Decimal, Hexadecimal, and Binary based numbers.  When it is not clear what base a number is in, I will use a “b” after a binary number, a “0x” in FRONT of a hexadecimal number and a “d” after a decimal number.  So, 1111d is a decimal number, 1111b is a binary number, and 0x1111 is a hexadecimal number.  Because we normally think in decimal, I will consider “values” to be in decimal unless otherwise specified.

First, consider decimal or base 10 numbers.  The possible digits are 0,1,2,3,4,5,6,7,8, and 9.  It has a total of 10 possible values for each “place” in the number.  If you have a number that cannot be represented with a single decimal digit, then you add a second digit to the left that has 10 times more value.  The digit on the far right is always in the “units” place.  Consider the number 22.  Each of the digits is the same, but they do not have the same numeric value.  The 2 on the right is in the units or  1’s place and it’s value is just 1×2=2.  The 2 on the left is in the tens place and it’s value is 10×2=20.  To get the value of the full number, you add the value of the digits in their “place” and in this case you get (10×2)+(1×2) for a value of 22.  The REASON that the digit on the left is 10x more value is because there are 10 possible digits.

Now think of the decimal number 5432 and what each digit represents.  The 2 is in the “units” place, or it represents 1×2.  The 3 is in the “tens” place, or it represents 10×3.  The 4 is in the “hundreds” place and represents 100×4.  Last, the 5 is in the “thousands” place and represents 1000×5.  As you move left in the number, each place is 10 times more value.  To get the full value of the number we add them up (1×2)+(10×3)+(100×4)+(1000×5).

Second, consider binary or base 2 numbers.  The possible binary digits (bits) are 0 and 1 for a total of 2 possible values for each place in the number.  As you move left in a binary number, the places have twice the value of the previous place.  Consider the binary number 11.  The 1 on the right is in the “units” place. So it’s value is 1×1.  The 1 on the left is in the 2’s place so it’s value is 2×1.  To get the value of the number, we add them up, (2×1)+(1×1) for a value of 3 in decimal.  For now, the largest binary number we will work with contains 8 digits to represent a Byte.  I will normally write binary Bytes with a space between the first 4 bits and the last 4 bits because it is easier for me to think in terms of only 4 bits at a time.

Third, consider hexadecimal or base 16 numbers. The possible hexadecimal digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F for a total of 16 possible values for each place in the number.  As you move left in a hexadecimal number the places have 16 times the value of the previous place.  Consider the number 0x1111.  Starting from the right, the 1 in the units place has a value of 1×1.  The second digit from the right, in the 16’s place has a value of 16×1.  The third digit has a value of 256×1.  The last digit has a value of 4096×1.  So, the value of 0x1111 is (1×1)+(16×1)+(256×1)+(4096×1) or 4369d.  As you can see, the value of a hexadecimal number can be very large for a few digits.  The largest hexadecimal number we are likely to work with is 0xFFFF or 65535d because it is two bytes in length.

Computers work in binary.  A circuit is either on or it is off.  We work in hexadecimal because binary is too cumbersome.  Converting from decimal to hexadecimal or binary is much more difficult than converting from binary to hexadecimal or from hexadecimal to binary.

Here is a small conversion chart for all 16 possible combinations in a 4 bit number:

Decimal         Hex                Binary

0                      0                     0000

1                      1                      0001

2                      2                     0010

3                      3                     0011

4                      4                     0100

5                      5                     0101

6                      6                     0110

7                      7                      0111

8                      8                     1000

9                      9                     1001

10                    A                     1010

11                    B                     1011

12                    C                     1100

13                    D                     1101

14                    E                     1110

15                    F                     1111

Notice that 4 bit binary matches up nicely with single digit hexadecimal numbers.  This extends into a full Byte with 2 hex digits.

0xFF  =  11111111b (or more commonly 1111 1111 because it is obviously binary representing 2 hex digits).

At the end of Part 1, Superman’s STR, IQ, PIE, VIT, AGI, and LUK were all at 18.  In this part we will modify those stats to higher values.  Use your character’s name in ALL CAPITAL LETTERS when I use SUPERMAN.  Here is SUPERMAN with all 18’s:

Illustration 01

If you haven’t already made a few more Wizardry characters, do that now.  NOTE: DO NOT take a lone character into the dungeon unless you want to leave him/her there.  If he/she gets paralyzed then they will be lost and you will need to go after him/her with another group of 5 or less characters.  It will be much easier to locate the proper place to modify if you have a full party of characters in your game.  Here is my *Roster of characters:

Illustration 02

Go to Gilgamesh’s Tavern and form a group with at least 3 characters as follows: Make sure SUPERMAN is the first character and the other characters are in a different order than listed in the *Roster.  Here is my group of 6 characters:

Illustration 03

Notice that BRUCE LEE and CHUCK NORRIS are in a different order in the group than they were in my *Roster.  I did this so that I can tell the difference in memory between the *Roster and my “Active Group”.

All of my characters were made as described in Part 1 and they have 18 for each of STR/IQ/PIE/VIT/AGI/LUK.

Leave Wizardry with Alt-Tab (do not quit the game) and start up Cheat Engine.  Link it to DosBox.exe as in Part 1.  The characters are in memory at several locations.  We need to find the location that has them in the group because this location will overwrite all of the others when you quit Wizardry.  So, if you modify the wrong location, your changes will be lost whenever the game writes to that location.  Click on New Scan and set the Value Type to Text.  Now type SUPERMAN in the Text box.  It MUST be in all capitals unless you uncheck the “Case sensitive”.  And, I prefer to have it case sensitive for my searches.  Click on First Scan.  Hopefully, you will be presented with one or more addresses (they will not likely be the same addresses that I get) where you can find “SUPERMAN”.  Here are my results:

Illustration 04

Only one of the addresses will point into the area of my active group.  In order to find out which of them is my active group in memory I need to examine each one. I need to narrow down the choices to just one for modifications.  So I double-click on each address to add it to my list at the bottom.  I will not put in a description yet, so here is what I get in my list:

Illustration 05

In order to check out the area of memory, right-click on the first address and select “Browse this memory region” from the list.  The Memory Viewer will come up and SUPERMAN will be at the top.  A second character name should be just underneath the data for SUPERMAN.  Here are my results for the first address:

Illustration 06

I can readily see that the next character after SUPERMAN is not my second character in the group (BRUCE LEE), so this is not the memory location of my group.  I remove this address from my list and examine the memory location of the next address:

Illustration 07

Once again, this is not the right location so I remove this address from the list and browse the next address:

Illustration 08

This is where having a different character order in my group from the character order in the *Roster helps in the process.  My group has SUPERMAN first, then BRUCE LEE, and CHUCK NORRIS third.  I note that this address MIGHT be the location of the *Roster but it is not the location of my group.  I remove this address from the list and browse the last address on my list:

Illustration 09

This looks like it IS the correct location to modify the characters of my group.  (Good thing, since it was my LAST address!)  As I scroll down in memory I see each of the characters in my active group in the correct order.

NOTE: The information you see may vary in address and content from mine if you have run SUPERMAN into the dungeon to test him.  Don’t worry, this procedure will still work.  Scroll the Memory Viewer up by a line or two so you can see the line above SUPERMAN.  From the ORIGINAL Wizardry Player’s Guide, I know that the game was written in the Pascal language.  I also know that Pascal stores strings (like the names) with a character count before the letters.  The character count is the number of letters in the name.  With “SUPERMAN” there should be a character count of 8.  What we are interested in seeing, is the value 08 at the far right in the line directly above SUPERMAN.  I may be wrong at this point, but I believe that this is the starting point in memory for data affecting Superman.  The 08 is the number of letters in “SUPERMAN”.

Right click on the value 08 and select “Add this address to the list” from the selection box that appears.

Illustration 10

The address will be highlighted, just <tab> to the Description and enter something like “Number of Letters in Char 1 Name”.  Since this is a small number, change the Type to Byte and click OK.

Illustration 11

The address will appear in your list with the label given.

Illustration 12

Since the value 08 is the start of data that want to investigate, I prefer to have it on the left of the Memory Viewer table.  If you right click on the value 8 in your List, you will see the option of “Browse this memory region”.  Select this and your Memory Viewer will change:

Illustration 13

By experimentation, I know that the full line starting with 08 53 55 50…is for the letter count and letters of the Name of the character.  The next line is for the letter count and letters of the password.  For each Character there are 13 rows of data.  If you have more than one character, then the data for the second one should start at row 14.  In casual browsing of memory I have seen other information between characters but this may have been at one of the addresses that we did not use here.  Here is what I believe is the block of data for SUPERMAN (the image was made before I made more characters so there is no character after SUPERMAN):

Illustration 14

We are here to modify the stats of our characters.  As a refresher, here is the small conversion chart for all 16 possible combinations in a 4 digit binary number:

Decimal           Hexadecimal   Binary

0                      0                      0000

1                      1                      0001

2                      2                      0010

3                      3                      0011

4                      4                      0100

5                      5                      0101

6                      6                      0110

7                      7                      0111

8                      8                      1000

9                      9                      1001

10                    A                     1010

11                    B                     1011

12                    C                     1100

13                    D                     1101

14                    E                      1110

15                    F                      1111

And, for a couple more numbers of interest, using 8 binary digits:

18                    12                    0001 0010

19                    13                    0001 0011

20                    14                    0001 0100

21                    15                    0001 0101

22                    16                    0001 0110

23                    17                    0001 0111

24                    18                    0001 1000

25                    19                    0001 1001

26                    1A                   0001 1010

27                    1B                   0001 1011

28                    1C                   0001 1100

29                    1D                   0001 1101

30                    1E                    0001 1110

31                    1F                    0001 1111

The maximum normal value of Strength/IQ/Piety/Vitality/Agility/Luck is 18.  It actually only requires 5 bits to hold that value: 10010

If we put 3 of these together and fit them into two bytes we get:

10010 10010 10010

Change this to 2 8-bit numbers

1001010  01010010

Since this is one digit short of two full bytes, we then add a leading 0 to get

01001010 01010010

Change this to groups of 4 for easy conversion to hexadecimal

0100    1010    0101    0010

And the Hexadecimal notation

4          A         5          2

Now, looking at the data for SUPERMAN, we see something similar two lines down from the name and the last 4 bytes.  Only, they are out of order.  This is because the computer saves the value as low-high bytes instead of high-low.  The first 52 4A is for the STR/IQ/PIE, the second 52 4A is for the VIT/AGI/LUK.

We can now add these two memory locations to our Cheat Engine list.  Right click on the first “52” and select “Add address to the list” and set it for 2-bytes with a label. Repeat for the second “52”.  Your list should now look something like this:

Illustration 15

Repeat for the second “52”

But WAIT!!! We don’t have 52 4A in out list, it says 19026 instead!  This is because the number we see in the list is in decimal.  4A52 hexadecimal is 19026 decimal.  It is more convenient to view it in the same form (hexadecimal) as we see in the Memory Viewer.  Right click on the 19026 and select “Show as hexadecimal” then repeat for the other 19026.  Notice that the number appears in correct order of 4A52 in the list.

Illustration 16

Now it is time to decide what values you want for each of your character’s stats.  The maximum you can make with 5 bits is 31.  I know by experience that 31 is not a good value because it changes to Zero if the character GAINS one of that stat, so I will put in several different values to see if any are stable (meaning they won’t go to zero if my character advances enough times).  I know that 18 is stable, so I will try 20, 22, 24,26, 28,30 just to pick 6 numbers between 18 and 31.

Decimal           Hex                 Binary             5-bit

20                    14                    0001 0100       10100

22                    16                    0001 0110       10110

24                    18                    0001 1000       11000

26                    1A                   0001 1010       11010

28                    1C                   0001 1100       11100

30                    1E                    0001 1110       11110

Arrange my 6 numbers into groups of 3 and insert the leading 0:

0101001011011000    0110101110011110

Split it up into 4 bits for conversion to Hex

0101    0010    1101    1000    0110    1011    1001    1110

Convert to Hex

5          2          D         8          6          B         9          E

Form this into 2-byte combinations

52D8  6B9E

This is the values I need to put into my character.  Double-click on the first 4A52 and type in 52D8, then click on the second 4A52 and type in 6B9E.  The list now looks like this:

Illustration 17

And, the Memory View looks like this:

Illustration 18

Check my character:

Illustration 19

Looking at my character stats now, I find out that the order of the stats is NOT STR/IQ/PIE, VIT/AGI/LUK but rather PIE/IQ/STR, LUK/AGI/VIT.

You should have enough information now to change your character’s stats to any desired value between 0 and 31.  Why would you want to change it to 0?  To make the game harder of course!  Give yourself a challenge!  How does a character with 0 luck perform?  Does he/she get any loot?

OK, now I will throw in a quick bonus.  I notice that my character has 103 gold and 8/8 HP.  Change 103 to Hexadecimal and it is 0x67, 8 remains as 8.  Looking in the memory locations I find the 0x67:

Illustration 20

I’m not sure what the maximum amount of gold can be, but it has to be at least 6000 since the Gloves of Copper in the Trading Post cost that much.  So, it must be at least 2 bytes.  Add this address, 2-bytes as my Character’s gold to the list.

Illustration 21

Illustration 22

Since I don’t see any other values that might contain my 8’s for the Hit Points, I will now take a chance that the two 8’s about 5 rows further down are for the Current and Maximum HP’s for my character so I will add them to my list (the order may be wrong but I will find that out by putting different values in them).  Because they are spaced apart like 2-byte values, I will also make them 2-bytes each (after all, I have a backup of my file if it crashes the game).

Illustration 23

Now modify the values and give my character more HP with the current value smaller than the Max just to test.

Illustration 24

Check my character to see if I was correct:

Illustration 25

OK, that should keep you busy for some time now.  I will leave it up to you to modify your other characters if you want.  With Cheat Engine you can save your list.  When you start Wizardry again, you can find the start of your character data, then load your saved list file.  You then right click on the first data address (the one that hold the length of the name for your first character and select recalculate the addresses.  You can then select “from address” and type in the current matching address for the data.  Also, after making many changes, it is a good idea to “Leave the Game” (you don’t need to fully exit back to windows by pressing Ctrl-F9 if you want to continue playing) so the information is saved to your Hard Drive.  You can then immediately press “return for more Wizardry” and re-form your group.

Illustration 26

So far, everything we have changed has been a number that is easy to find in memory.  They are also things that are somewhat permanent while the group is in camp or at Gilgamesh’s Tavern.  There are other things that you may want to find, such as if a character is POISONED, or which goes away when you leave the dungeon.  But you may want to change it WHILE your group is still in the dungeon.  Or maybe you don’t like the name of Gilgamesh’s Tavern and would like to change it to something else, like “Workforce Office”.

Some things are harder to find.  Your character has equipment in his inventory (or it is empty). But, that equipment may affect several things in the program memory.  An item may be magical or not.  It may be equipped or not.  If equipped, it may affect Armor Class (AC) or some other stat.  If you buy one item for a character, you may see it in his/her memory location, then trade it to another character to see it move around.  Finally, equip the item to see how it changes in memory.  There are several status’ for an item, is it usable? Not-usable?  Cursed?  Magical?  I’ll investigate some of these in later tutorials.

In the next part I will show you how to find and modify the spells your magic user knows and how many of each level he/she can cast.  I may also show you how to change the age of your character (so your character will not grow old an die).

Other things to consider are the status, E.P., alignment, class, race, level, and very importantly… IN/OUT.  But these will be in later Parts.


From → Computer Gaming

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: