C64 Pitfall II Hack and History
On this page you will learn about my Commodore 64 background, how to use the MON (monitor) that came packaged with the Final Cartridge III, and how to hack Pitfall II:The Lost Caverns by modifying assembly language instructions.
Pitfall II for Commodore 64
Here is a video of a user playing Pitfall 2 on the Commodore 64. The many screens and musical fanfares that made up this game were made possible by a special chip embedded into the cartridge.
Atari 2600 Pitfall II The Lost Caverns
This one shows a user playing it on the Atari 2600. The Atari 2600 was a console cartridge invented by Nolan Busnell in the early 70's. He is known as the pioneer of the gaming industry and launched the video game craze. This game started with the original Pitfall and later expanded into Pitfall II: The Lost Caverns. I used to play this things for hours. It also has a nice sound track.
Learning to use my Commodore 64
Back in 1991, I had purchased my first Commodore 64 system for about $400. At the time this single purchase cost me over a week's worth of pay. My ultimate goal was to master both Basic and Assembly language just like I was doing on my Atari 800 personal computer on various weekends.
At first my journey had led me to writing simple Basic games mixed with Assembly language. However there was still a desire within me to push my limits with the 6510 processor that handled the lightning fast instructions in assembly language. So I began developing a few simple assembly routines in Basic that used the SYS command as practice.
At the same time however I was curious about how commercial games worked. My friends were all playing the Commodore 64 games and having a blast. So was I. Yet the difference here is I wanted to learn where stuff was concealed like the lives counter, sprite collision, and other things.
My first hacking experience
This eventually led me to my first game hack. It was a game called Mission Elevator. This game had often frustrated me because of the gameplay, which resulted in dying a lot. However I knew if I could break inside the code then I could search for the life counter. This little adventure did not happen overnight.
Final Cartridge III
So in my conquest to hack into this game, I needed a tool that had a built in assembly language monitor. One day I was reviewing a magazine I bought that advertised a catalog within. It was there that I first saw the Final Cartridge III. My eyes kept getting bigger as I read about all the options contained in this amazing cartridge. Below is a screenshot of my cartridge.
So I ordered it and it arrived in about a week. The advantage here was having access to the built in monitor and the ability to perform a soft reset on a game.
Discovering the assembly language monitor
The monitor served as an entry point so I could disassemble the game code. There is also a built in command known as hunt. The hunt command allows searching through memory addresses. This came in handy later when I finally gave myself infinite lives for Mission Elevator.
Here are some screenshots of that game.
Activating the Freeze mode
To break into the game, there is a freezer switch located on the rear of the cartridge to the right. Pressing the small black button on the left activates the Freezer Mode. In the Freezer Mode there is a list of pull down menus that control various aspects of the cartridge. Using a joystick I navigated to the Exit menu and selected the text called Monitor. Clicking the joystick then transferred the system back into Basic with a soft reset, keeping the assembly language program intact.
Using the assembly language monitor
Once you are inside the monitor, it is necessary to understand how to use it. Before I speak about that there is one important thing you must know, which is how to program in Assembly Language. This website is not setup to teach a user how to do that, so my recommendation is to take advantage of Google's massive search queries where I am confident you will find great teaching guides. Now I do have my own google website that teaches basic assembly instructions, but it was programmed for the Atari 800.
Your first instruction
This example is setup to disassemble the game Pitfall II as my latest attempt. I was never successful at dissecting David Crane's masterpiece until recently. However please do understand this is a work in progress and not everything is immediately known yet. So the example will work through what I learned about it so far.
First type the word MON. That will instantly take you to the assembly language editor. To see the listing for Pitfall II just type D 8009 8033 as an example. This will examine the memory at the address 32777 through 32819 (hexadecimal:8009 to 8033), which is the starting address where the Pitfall II code begins. The screenshot verifies this.
Commodore 64 Pitfall II Hack video: Part 1
For those who haven't visited my Youtube channel and want to see the Pitfall II hacking examples and other programs, you can view it here
Commodore 64 Pitfall II Hack video: Part 2
Here is the second part of those hacks.
Hacking the game
The first important thing before you begin hacking any game is to know where the starting address is. Often this can be difficult to find and takes work. With an assembly language editor though, you can scroll through memory until you see something that this could be the correct starting point. Usually an SEI followed by LDA #(some value) STA $0318 is a good sign you found the entry to the raster routine. The raster routine allows multitasking to occur in the background. Most commercial games back in the days used interrupts.
Larger screenshot of source
For your convenience, I have expanded the code shot image for easier clarity.
Before we begin this hacking journey, it is necesary to know how to translate hexadecimal to decimal in case you're like me and never really learned the math.
Type $8009 and hit enter inside the monitor. You should get something like $8009 = #32777. That is the decimal equivalent for the hex code.
Next type #32777. You will see something like #32777 = $8009. Hopefully this is pretty straight forward.
Now we are going to change an address in memory. It is necessary to make sure you know what you are doing at this point as it is very easy to lock up the program with an improper instruction.
Type A B01D LDA #$02 and press the Return key (enter if using an emulator).
You just told the accumulator to change address location B01D to "Load the accumulator with the immediate value of two. Now if you look at the code again with D 8009 802A you will see the change. This was safe to do as all it did was record a two into sprite 53248 ($D000), a two into location 54272 ($D400) and another two into location 56320 ($DC00).So basically you positioned the starting sprite at location two, changed the sound register (known as the VIC II Chip Memory Control Register) and finally a two was stored in the joystick location.
Screenshot of memory change
The raster interrupt is stored in a low/hi byte style. The location $0318 (792) is the low byte and location $0319 (793) is the high byte. If you take the value in the LDA immediate address before each instruction here you can find where the raster interrupt begins at. Example: 226 + 252 * 256 = 64738.
A raster will stop (interrupt) and set the interrupt disable flag to insert the code between SEI (set interrupt) and CLI (clear interrupt). If you have ever seen games that were hacked with a startup demo then you have most likely witnessed an embedded interrupt.
Probably the easiest way to understand this is to know that your Commodore 64 system is constantly checking interrupts all the time. When you type something on the keyboard, the keyboard interrupt vector is invoked. If you press the Run/Stop key it is activated again. If you load something from the disk drive, again it handles an interrupt. This is happening at all times usually unknown to the user.
I decided to keep this tutorial consistent with the Youtube video above for easier reference. However in later sections, I may reveal some of the other secrets I learned about this game.
Changing the bits within a sprite
According to the video at 12:28 (part) I changed the Sprite Data Pointer left image by altering the AND instruction. This was originally using an AND #3 to mask off every 3 bits. In the example it was changed to AND #212.
Then it uses an ORA to set those bits into the value found in memory location 23 ($17). This seemed to change Pitfall Harry and also parts of the condor.
After more discovery later I realized that when I changed the code seen in the screenshot that it uses the low/hi byte of memory locations 13 and 14 to store the area where the sprite data is found out.
View sprite memory
Here is how I found this out. When the command ES 4000 is issued you can scroll through memory using the arrow keys. That area contains the starting sprite data (such as the scorpion, player, etc). I will first show you a screenshot and then explain where the program saved data to locations 13 and 14.
Screenshots of the scorpion, frog, QuickClaw (scared cat) and Rhoda (girl). You can also see the sprite for the gold bar and the ring.
All Sprite Data locations
Finally here is a list of all of the sprite data found to date. I would have normally defined everything, but it would take up a lot of space here. Rather you will see the basic sprites instead.
Deactivating sprite collisions
Toward the end of the video I showed how to turn off sprite to sprite collision. Memory location 53278 contains the masking capability for sprites to detect an overlap. When two sprite bits overlap then this register is set for the current sprite.
Using the Hunt (H) command
So according to the video this sprite detection was found by using the hunt command. For example to search for location 53278 in memory just type H 0801 CFFF 1E DO. The two hexadecimal values are 30 ($1E) and 208 ($D0). This translates to H 2049 53247 30 208. A calculation of the last two bytes is necessary to see which memory location the Hunt is searching for. Just type in 30+208*256=53278. Therefore the editor is searching through those memory addresses for every detection of 53278. The system will find all occurances of that register. You can see this in the video above at 25:10
Therefore memory location address 9915 revealed the sprite collision detection. I found out that the sprite collision values were being saved in memory location 147 for storage. So I forced the computer to look in another location by storing a 251 in the zero page address. Here is the final screenshot of the before and after view of the change.