Comparisons to first Pitfall game

When I first learned about this game, I was still using an Atari 2600 console before I even had the experience of owning my very first personal computer. I was already used to the joystick controller and style of the Atari VCS games in that era. I was blown away by how much more they added to the game, including some scrolling screens when Pitfall Harry descended further below into the caverns.

Some of the same game enemies remained the same such as the scorpion. Newer adversaries such as a bat, vulture, frogs, and electric eel added to the fun and gameplay.

It also remained true to the original version and the rewards were still gold bars. However, there was also a stolen Raj diamond in this episode that would kept you on your toes as you searched deeper into the caverns, swimming in rivers, and climbing to extreme heights with the end in sight. You were also supposed to capture the rat (seen at the game’s beginning) . A perfect score is reached at 199,000. This is taken into account that you don’t lose any points along the way with enemy conflicts.

I also decided to include the full source code for Pitfall II in this section. It can be found in the PDFs menu at the top, but I wanted to be sure that my visitors would have immediate access to the decompiled assembly listing below.  Just click on the image in this section and you will get access to. It will open up in a separate menu a PDF document that can be viewed from top to bottom. I hope this encourages many readers to start their own series on reverse engineering. I have found few websites out here that even attempt to tackle this.

Feel free to use the VICE C64 Emulator below to load up Basic programs or files that were downloaded on this page.

To load a file, click on the menu C64/Attach D64 or you can also drop and drag a .D64 image onto the VICE window and it will load.

Learning how the game works

One of the most important things you can do before you start to reverse engineer any game is play it. Learn how it works, who are the game characters, goal of the game, etc. This will help you keep a perspective as you begin to explore the strange code known as assembly language. Also it wouldn’t hurt to have some skills in programming already.

Please understand this is no perfect solution to the game, will obviously contain errors since I do not own the original source code. Rather I am deriving my facts on what I know about the game, my experience with assembly language, and just learning what the code may be doing.

There are also going to be a lot of unanswered questions, since once again I am no master at this. Rather it has always been my curiosity that drives me deeper into code to explore strange worlds where no man has gone before. Sorry I couldn’t resist that statement. Seriously though, it will be fun as we start to unravel mysteries that went down in a sinking ship after the game designers pitched most of their code to the trash. This was common for many game companies, usually after a liquidation to prevent anyone from reproducing their work.

The Pitfall II C64 Source Code

For this series since my website is centered on the Commodore 64, we are going to be analyzing the assembly language code on this machine. The Commodore 64 version was not bad, compared to the Atari 2600 predecessor. This one obviously could take better advantage of multi-color graphics due to the VIC chip that managed 4 colors per square.

So what I’d like to do first is present my discovery finding when I disassembled this code. A lot of things I arrived at by tweaking values and then running the game afterward. Some of this logic is based on my experience with how the Commodore 64 works, such as the loading of the game sprites, and other cool things.

Reviewing the disassembly

So exploring the code from top to bottom, I was able to pinpoint where the interrupts existed, the sprite colors, the sprite loader, the screen drawings, and some other game evaluations as listed below:

Memory and code review

This game appears be using Bank 1 to relocate an empty area for sprites, the game screens, and program code. A bank is required since the Commodore 64 can only access 16K of memory for its graphics. By moving memory to start at register $4000 through $7FFF (decimal 16384 – 32767), there is plenty of room for design and the map graphics. Many commercial video games for the Commodore 64 followed this same style.

The following code below breaks the game down into the memory registers and assumed functionality of the game segments. The complete disassembly is still under construction, so your patience is appreciated as this extraction continues forward. Also taking tips from the YouTube spotlight at the GameSpot channel for David Crane is helping me learn how he created the original Pitfall.

C64 Sprites defined

The game sprites locations were revealed when I loaded the Vice snapshot file into a Windows tool called Infiltrator. This also helped me understand much later that it was necessary to move memory to accommodate so many sprites and graphics. You will notice that these sprites are seen in black and white. This is a default setting for the tool when the multi-color is not turned on. Besides I figured it would be easier to make out some of the pixels this way. I will later convert this to PDF to save scrolling through long pages. 🙂

Game Maps and Screens

When I loaded up the Pitfall II game in the tool Infiltrator for the Commodore 64, after some time searching through memory locations, I finally came across screens that fit together. Therefore I was able to see that a specific map that starts the game (likely replicated throughout the game) started at $7C00 – $7fE7 (31744 – 32743) and the character set read from $7000 – $77FF (28672 – 30719). Seen here is a screenshot of that starting map. This is helping to know when you are beginning to disassemble a game at the machine level.

Another thing I found interesting upon close observation when looking at this in memory here was to see the screen that controls the levels that scroll down. When Pitfall Harry begins to descend down a screen a similar screenshot is seen like in this example. I’m not completely convinced yet, but I believe David Crane (Tim Shotter for the C64 version), may be reusing a screen over and over to save RAM. Also being under tight timeframes and restrictions they had to churn out games pretty fast while staying as accurate as possible. The memory locations here read the screen between $7800 – $7BE7 (30720 – 31719) and the character set range is $7000 – $77FF (28672 – 30719).

Game Source Disassembly

  • Perceived labels:
    SPRITE_X_POS = 25
    SPRITE_Y_POS = 26
    GAME_DEMO_TIMER = 7
    JOYSTICK_STORED = $48
    SPRITE4_SPEED = $68 ; Pitfall Harry
    SPRITE4_ANIM_FRAME_SPEED = $0A
  • SPRITE4_ANIM_FRAME_INWATER_LEFT = $a7
    SPRITE4_ANIM_FRAME_INWATER_RIGHT = $a8

* = $8009 (32777 – program counter start)

  • $800A – Interrupt 1: Reset Vector LDA #$<318, LDA #$>319
    $801F – Sprites X Position cleared (starting address), $D000,X
    $8028 – Joystick bit values cleared, $DC00
    $802E – Setup the VIC bank, $DD02
    $803D – Appears to be capturing joystick bits, $D011
    $8048 – Raster scan line interrupts, $D011
    $8057 – Raster Position (current raster line), $D012
    $808A – Background colors 0 – 2, $D021 – $D023
    $8099 – Begin loading the sprite designs and shape data, LDA #<$4000, LDA #>$4000
    $8172 – Game title screen – Activision presents… Adapated by Tim Shotter
    $81C0 – Points to hi/lo bytes of screen memory at 1798 – likely to store screen data for use in the game, <$0706, >$0706
    $8206 – Sprite data for walls at the left/right far edges
    $83F1 – Sprite 0 and 2 X position, $D000,$D004
    $83FE – Sprite 1 Color, $D028
    $8403 – Sprite 7 Horizontal Expansion, $D01D
    $8415 – Sprite Multicolor Color Registers 0-1, $D025 – $D026
    $8421 – Sprite Multicolor Mode (activation), $D01C
    $8426 – Sprites 3, 4-5 Colors, $D02B – $D02C
    $8430 – Sprite 3 X position, $D006
    $8435 – Sprite 3 Color, $D02A
    $843F – Set Voice 1-3 Attack / Decay Cycle Control, $D405, $D40C, $D413
    $844A – Set Voice 1-3 Sustain / Release Cycle Control, $D406,$D40D,$D414
    $8453 – Select Filter Mode and Volume, $D418
    $8458 – Interrupt 2: Unknown, LDA #<$9CBF, LDA #>$9CBF
    $8464 – Raster scan line interrupts, $D012
    $8469 – Turn off Interrupts (Interrupt Mask Register), $D01A
    $846C – Interrupt Request Register, $D019
    $8475 – Current raster position, $D012
    $8482 – JSR $9448 (Subroutine)
    $848E – JSR $943D (Subroutine)
    $8491 – JSR $92EO (Subroutine) – Screen pixel shifting (scrolling)
    $8494 – JSR $9300 (Subroutine) – Screen pixel shifting (scrolling)
    $84A6 – JSR $9300 (Subroutine)
    $84BC – JSR $9448 (Subroutine)
    $84C1 – JSR $9448 (Subroutine)
    $84CB – JSR $9448 (Subroutine)
    $84D0 – JSR $9448 (Subroutine)
    $84DE – Data for “Designed by David Crane” (title screen)
    $851B – Data for “Adapted by” (title screen)
    $8523 – CIA1: Data Direction Register A, $DC02
    $8528 – CIA1: Data Port Register A, $DC00 (keyboard/joystick 2)
    $852C – CIA1: Data Direction Register B, $DC03
    $852F – CIA1: Data Port Register B, $DC01 (read joystick 1)
    $8534 – Store Joystick 1 in register $0A (10)
    $853A – Store other joystick values $48 (72)
    $8585 – CIA1: Data Direction Register B, $DC03
    $8589 – CIA1: Data Direction Register A, $DC02
    $858E – CIA1: Data Port Register B, $DC01 (save joystick 1 value)
    $8591 – CIA1: Data Port Register A, $DC00 (keyboard/joystick 2) – Beginning routine to read keyboard (CMP #$FE) – Reads keyboard column 1
    $85AF – Game demo timer (counts down time until Pitfall Harry moves during the game demo). Set to mask to 0 to start with no delay (otherwise it is 7 cycles to launch the demo).
    $85BF – JSR $87F9 (Subroutine)
    $85C2 – JSR $9C6E (Subroutine)
    $85DE – CIA1: Data Port Register B, $DC01 (save joystick 1 value)
    $85E1 – CIA1: Data Port Register A, $DC00 (Read keyboard/joystick 2). Here the keyboard/joystick 2 is idle (not moving).
    $85E8 – Joystick 2 is pushed DOWN
    $8608 JSR $9B9D (Subroutine)
    $860B JSR $94D5 (Subroutine)
    $860E JSR $87F9 (Subroutine)
    $8611 JSR $99BA (Subroutine)
    $861E JSR $8800 (Subroutine)
    $8621 JSR $9ACD (Subroutine)
    $8626 Sprite 4 Y Position
    $8629 Position of Player X when entering a new room. Try LDX #32 as an example.
    $865C JSR $981E (Subroutine)
    $865F JSR $989D (Subroutine)
    $8662 JSR $86F8 (Subroutine)
    $8668 Sprite 4 X Position, $D008
    $866F Sprites 0-7 MSB of X coordinate (cross over 256th position), $D010
    $8677 Sprites 0-7 MSB of X coordinate (set bit), $D010
    $867A Sprites 0-7 MSB of X coordinate (save value), $D010
    $8684 Clear balloon when it breaks
    $868F Sprite 4 Y Position, $D009
    $8695 Sprite 5 Y Position (saved), $D00B
    $8698 Sprite 4 X Position (read), $D008 – Pitfall Harry character
    $869B Sprite 5 X Position (saved), $D00A – Balloon
    $869E Sprites 0-7 MSB of X coordinate (read), $D010
    $86AE Sprites 0-7 MSB of X coordinate (saved), $D010
    $86DB Read low byte ($FB – 251), ZEROPAGE_POINTER_1
    $86DF Store in high byte ($FD – 253), ZEROPAGE_POINTER_3
    $86E4 Read low/hi bytes, LDA #<$9000, LDA #>$9000 (36864)
    $86F4 JSR $0FE8 (Subroutine), RTS ($86F7)
    $87D2 Starting address for a subroutine call. Ends with RTS.
    $87F9 Starting address for timer routine. Can change the INC 127 to slow the game demo start or set INC 00 to speed it up.
    $8824 JSR $9B2D (Subroutine)
    $8827 JSR $9B49 (Subroutine)
    $8833 JSR $87CB (Subroutine)
    $8872 JSR $959A (Subroutine)
    $8897 JSR $9B49 (Subroutine)
    $88A3 JSR $87CB (Subroutine)
    $8911 JSR $87CB (Subroutine)
    $8914 JSR $9B70 (Subroutine)
    $8934 JSR $9B7A (Subroutine)
    $8983 JSR $87CB (Subroutine)
    $8986 JSR $9B70 (Subroutine)
    $89A6 JSR $9B7A (Subroutine)
    $89EE JSR $87CB (Subroutine)
    $8A2A Controls Pitfall Harry’s timed movement speed to the right. Change to AND #$7f to slow down the character timing movement. Interesting tweak on the game mechanics. Set to AND #$00 to speed up the movement.
    $8A32 JSR $9B2D (Subroutine)
    $8A35 JSR $9B49 (Subroutine)
    $8A4D JSR $940F (Subroutine)
    $8A5F JSR $959A (Subroutine)
    $8A6F Controls animation speed of Pitfall Harry’s left movement. Changed to LDA $01 to bypass the read from LDA $44
    $8A79 JSR $87CB (Subroutine)
    $8AA6 Controls movement to the left. Set AND #$7f to slow down the left animation frames, which produces the smooth animation.
    $8AB5 Controls Pitfall Harry’s timed movement speed to the left. Change to AND #$7f to slow down the character timing movement. Set to AND #$00 to speed up the movement.
    $8ABD JSR $9B2D (Subroutine)
    $8AC0 JSR $9B49 (Subroutine)
    $8AD8 JSR $9423 (Subroutine)
    $8AEA JSR $959A (Subroutine)
    $8AFC JSR $87CB (Subroutine)
    $8AFF JSR $9B70 (Subroutine)
    $8B04 Load lo/hi bytes, LDA #<$000F, LDA #>$000F
    $8B0C Jumping speed for Pitfall Harry when moving to the right. Change to AND #$00 to get a bigger jump.
    $8B29 JSR $940F (Subroutine)
    $8B40 JSR $982D (Subroutine)
    $8B43 JSR $9B49 (Subroutine)
    $8B64 JSR $87CB (Subroutine)
    $8B67 JSR $9B70 (Subroutine)
    $8B6C Load lo/hi bytes, LDA #<$000F, LDA #>$000F
    $8B74 Jumping speed for Pitfall Harry when moving to the left. Change to AND #$00 to get a bigger jump.
    $8B91 JSR $9423 (Subroutine)
    $8B9D JSR $9B7A (Subroutine)
    $8BA4 Controls the up movement when Pitfall Harry dies. Changing to a different register forces Harry back to the previous saved (cross object) position. Funny things happen here.
    $8BA8 JSR $9B2D (Subroutine)
    $8BAB JSR $9B49 (Subroutine)
    $8BD7 Controls animation when swimming in the water to the right. If you change the line to ADC #$01 the scorpion and bat frames alternate. This could be used to switch a character’s animation frames.
    $8BDF JSR $87CB (Subroutine)
    $8BF1 Controls Pitfall Harry’s swimming movement to the right. Use AND #$00 to speed up the swimming movement.
    $8CB9 Controls Pitfall Harry’s swimming movement to the left Use AND #$00 to speed up the swimming movement.
    $8CF2 JSR $9423 (Subroutine)
    $8D33 JSR $9B2D (Subroutine)
    $8D41 JSR $9B7A (Subroutine)
    $8D51 JSR $9B2D (Subroutine)
    $8D54 JSR $9B49 (Subroutine)
    $8D59 Controls the swimming height that Pitfall Harry can ascend to. Set to LDA #$01 to turn off the height of his swimming. Does strange things though since moving to the right makes him fall again.
    $8D5B JSR $9B7A (Subroutine)
    $8D63 JSR $87CB (Subroutine)
    $8D66 JSR $9B70 (Subroutine)
    $8D71 JSR $9B7A (Subroutine)
    $8D95 JSR $87CB (Subroutine)
    $8D98 JSR $9B70 (Subroutine)
    $8DA3 JSR $9B7A (Subroutine) *
    $8DC7 JSR $87CB (Subroutine)
    $8DCC JSR $9B7A (Subroutine)
    $8DDA JSR $87CB (Subroutine)
    $8DDF JSR $9B7A (Subroutine)
    $8DF5 JSR $87CB (Subroutine)
    $8DFE JSR $87CB (Subroutine)
    $8E03 Change to INC $1A to slow down the fall movement. Likely this register controls the rate of descent.
    $8E1A JSR $9B2D (Subroutine)
    $8E1D JSR $9B49 (Subroutine)
    $8E22 Sets limits a specific height Pitfall Harry can swim when in the water. Set to DEC $1A increased his swim height (above water).
    $8E30 JSR $959A (Subroutine)
    $8E33 JSR $9C1C (Subroutine)
    $8E6B JSR $87CB (Subroutine)
    $8E74 JSR $87CB (Subroutine)
    $8E90 JSR $9B2D (Subroutine)
    $8E93 JSR $9B49 (Subroutine)
    $8EA6 JSR $959A (Subroutine)
    $8EA9 JSR $9C1C (Subroutine)

Using the Hack Tools

Now that you have been provided with an overview of the disassembly of Pitfall II for the Commodore 64, it is your turn to go forward and try some hacking on your own. If you get lost, refer to the Disassembly above. I will also provide a few hack examples below that you can use on your own to learn from the game source code. This is a great way to enhance your skills and help you on the path to designing your own game and adapting your preferred style.

Using Regenerator

This is not a complete guide to Regenerator, but will provide some of the basic essentials to get you started. First you will want to load the VICE snapshot. For simplicity I have provided a download link below so download it now.

After Regenerator starts, click on the Load button (on the right). A dialog window appears. Search for the area where you downloaded the zip file. You will need to extract it into a folder using Winzip, Jzip, or a similar tool to used to unzip the file. The file is called Pitfall2.vsf (VICE screen snapshot).

Once the code loads into the window, you have many options available for disassembling the program. To keep this simple, click on the JumpTo button and type in 8009. Then press the Jump To button on the pop up window. This will immediately redirect Regenerator to the correct starting address you specified. It is also a great way to jump from one area to another. You can also use the Page Up and Page Down keys to scroll forward and backward through the source code.

Game Source Comments

When you are scrolling or jumping to specific address, you will notice messages embedded to the right of individual assembly instructions. These are the comments to make it easier to understand what that particular area is executing. So in the default load, the comments are actually pointing to memory address in the Commodore 64. These can also be changed within Regenerator. It can be completely customized.

Running the Game

I am also including a download link for the Pitfall II game for the Commodore 64. Although you can also get this online, I wanted to make this tutorial easy enough for any beginner. Click on the button below to obtain the tape image. Once it has been downloaded, load up VICE and click on the File menu and then on Attachc tape image. You can also learn more about VICE, but watching the VICE C64 video.

This opens a file window where you can search for and select the game. The game file name is Pitfall2.T64. When you click on it you will see the file contents in the window below called Image Contents. You can then double click in that window on the file to run it. For example, click on the file name called PITFALL II+ and it will execute in VICE.

Since this is a hacked version you will see the Cracked Title ‘remember’. Click on the space bar to move forward. Then press the escape key and the game will show the title screen. Next click on the space bar and you will see the message ‘DO YOU WANT TO BE INVINCIBLE (Y/N) ? Since we are already hacking the game, choose N and the game will finally appear. Now we finally get to the good stuff.

The section below provides hacks to change the game to be more playable and hopefully easier to win. The goal here is to learn from these examples, so again you can recreate your own masterpiece(s) much later. As always please refer to the Game Source Disassembly section to learn more tips. Have fun! 🙂

Using the VICE C64 monitor

Now in order to enter the hack examples below or your own edits, you will need to become familiar with the VICE monitor. Since it is already built in, within VICE, click on the File menu and select Monitor. This opens up the VICE monitor window and freezes the game. You will see a starting address with a flashing cursor. I don’t intend to make this a complete tutorial, but may provide one later. For now we are going to utilize a few instructions to get you up and running.

Next to the flashing cursor, type the instruction:
d 8ab5

Then press the enter key. The d stands for ‘disassemble’ and is used to look at sections of code. You will now be looking a small segment. Usually it is enough to see a path to the logic.

Our First Hack

For learning purposes, our first hack to this game will be to increase the running speed of Pitfall Harry to the right. In the original game he runs at a moderate speed. However we want to make the game more exciting, so we will be altering the timer. Observe memory address $8ab7. It should show .C:8ab7 29 01 AND #$01. For a quick assembly guide this is showing the starting address (8ab7), the bytes (29, 01), and the instruction (AND #$01).

Speeding up Harry to the Right

Now let’s change the code to our leisure. Next to the flashing cursor, type the instruction:

a 8ab7 and #$00

You will then see .8ab9 appear. Press enter again to ensure that the instruction has been saved. Now type in the instruction:

d 8ab5

Examine the instruction for 8ab7. You will see it has been been changed to AND #$00.

Finally let’s see this live in the game. Click the X to close the window. The game screen displays again. Press the F1 key to start the game. You will now notice Pitfall Harry speeds up when running to the left. To even the slope, let’s also change his speed to the right as well.

Speeding up Harry to the Left

Open up the VICE monitor again. This time let’s view the section to change his running speed to the left. At the flashing cursor type:

d 8a2a

Then after the code section appears, type:

a 8a2c and #$00

Then press the enter key to ensure it is saved. If you want you can view the changes by typing d 8a2a again or you can close the window and see the new hack.

If you followed everything correctly, Pitfall Harry should now be running at a pretty fast pace in both directions. As explained earlier, this is because we altered the timing cycle to 0 so there is no delay. The AND instruction is masking out bits to track timed movement. So if for example you change the instruction to AND #$48 he will definitely slow down when running in the appropriate direction.

Listed below I have provided complete examples to show the code examples we just reviewed and others you can try out later. My favorite is increasing the jumping speed. I always grimaced when I had to scale the scorpion in the game. However if you tweak the setting to AND #$00 it will speed up his jumping movement in that direction.

C64 Game Hack Examples

Increase Left Movement Speed

Memory starting address: $8ab5

LDA $44
AND #$00
BNE $8AE2
DEC $19

Increase Right Movement Speed

Memory Starting Address: $8a2a

LDA $44
AND #$00
BNE $8A57
INC $19

Increase Left Jumping Speed

Memory Starting Address: $8b74

LDA $44
AND #$00
BNE $8B94
DEC $19

Increase Right Jumping Speed

Memory Starting Address: $8b0c

LDA $44
AND #$00
BNE $8B2C
INC $19

Increase Swimming Speed to the Right

Memory Starting Address: $8BF1

LDA $44
AND #$00
BNE $8C33
INC $19

Increase Swimming Speed to the Left

Memory Starting Address: $8CB9

LDA $44
AND #$00
BNE $8CF5
DEC $19

Remove Delay Demo at Start

Memory Starting Address: $85B1

LDA $03
AND #$00
STA $03
BNE $85C8

Increase Swim Height Limit (to Left)

Memory Starting Address: $8D59

LDA #$01
JSR $9B7A
JMP $8D44

Keep pressing forward and try learning your own hacks. Also for beginners if you wander out of this tutorial and try your own tweaks without understanding what that section of code is doing, you can easily crash the game. It is best to refer to my Assembly Guide to learn more. I hope this has been helpful and interesting.