Jump to content
IGNORED

Fuji's First Hack - Outlaw 100


FujiSkunk

Recommended Posts

I'll tell you a story...

 

We all know about frying, the dangerous art of jiggling an Atari 2600's power switch to make the games do things no one intended them to do. Funny, pointless things like Pitfall's Ninja Harry. Odd, surreal things, like Video Pinball's drug-trippy sound effects. Futile, depressing things like E.T. robbed of all ability to get home. And sometimes very useful or intriguing things...

 

Frying Outlaw usually gives a 17th game variation, #0, a 2-player game with a destructible wall and the "getaway" feature officially seen only in variation #2. "Getaway" was a nice twist on the game, letting you move as soon as your bullet left the gun. Why this feature was so underused in the official variations is a mystery. Anyway, once upon a time, I fried my Outlaw cartridge, and ended up not with game variation #0, but game variation #26! I then proceeded to explore variations #26 through #99 of a game that supposedly had only 16. There were some neat twists on the game, like target practice with a wall, or, for the dueling cowboys who've had a little too much tequila, a caravan of cactii. Some were completely unplayable, boasting "features" like walls that could not be shot, or targets with six-shooters, which of course they never fired.

 

Variation #99 gave way to #0, and then #1, and from then on I only got to select from the official 16. I tried frying the game many times afterward, but never again did I see anything beyond the official 16, and #0. Until now...

 

Now that I program for a living, I know what a "buffer overflow" is, and how it can make programs do things they're not supposed to... such as treating completely unrelated data as a set of game options. Good programs have protections in place to prevent buffers from being addressed beyond their intended sizes. "Bad" programs happily treat whatever you ask them to as buffer data, even data that isn't actually in that buffer. Outlaw is a good program. One particular buffer contains 16 sets of game options, and the game is programmed never to allow the game variation number to be anything less than 1 or greater than 16. But what if something causes the number to be beyond that range to begin with? Or, what if somebody comes along and says the number doesn't have to stay between 1 and 16? Suddenly 84 other pieces of data get turned game options, even while those bits of data are doing some other job (program instructions, graphic bitmaps, sound data, whatever might happen to be in that bit of space).

 

It took a few years, to say the least, but this morning it finally hit me that it should be possible to make the game show those other unofficial game variations again. All that was necessary was to learn how to hack. Thanks to the fine utilities and instructions here on AtariAge and elsewhere on the 'net, and especially thanks to a disassembly of Outlaw over on bjars.com, executing this hack took about one hour of reading, 10 seconds of editing, 2 seconds of compiling, and what will doubtless become several hours of reminiscing.

 

Now you can too. Presenting Outlaw 100 with "all" 100 game variations! More stagecoaches! Floating cactii! Impenetrable walls! Mysterious flying L's! Targets with six-shooters! And of course the "safe" 16 for those greenhorns too scared to venture beyond the ranch.

 

Enjoy!

outlaw100.bin

  • Like 1
Link to comment
Share on other sites

Many games handle variations as just bits toggled on or off in a given memory location. Contradictory variations aside...why Atari chose to allow all combinations for some and not for others is a mystery to me.

 

Maybe just a lack of room? At least in Outlaw's case, since there are contradictory variations, the code can't just read bits out of a counter variable, so each variation needs its own set of bits. Perhaps anything "legitmately" more than 16 would have pushed the game over 2K.

Link to comment
Share on other sites

the code can't just read bits out of a counter variable

 

Yes, it could. This game (like Berzerk) sets the bits from a data table which does just that. In an attempt to save romspace in the display code (I gather, since there's no other reason for it), the game variation counter is handled in BCD mode which makes a data table necessary. Solely so that the game variation does not need long conversion later to display the variation #. So in saving what would have been only a few lines of code and maybe a couple dozen cycles of time (tops) to handle displaying the game variation #, the program ends up wasting more romspace due to the data table and BCD setup. "Potential" contradictory variations are no problem to deal with (as you could see from games like Space Invaders or Maze Craze)...use multiple bits instead of 1 - an established method going back as far as their earliest games.

 

Particularly odd for Atari to do, since marketing translated the number of variations as the number of "games" available - and stuck it right on the box to attract buyers.

Link to comment
Share on other sites

Yes, it could. This game (like Berzerk) sets the bits from a data table which does just that.

 

Maybe I didn't word that correctly. I meant that the bits "have" to be read from a table, because simply translating the game variation number itself into a set of bits (e.g. #14 -> enable features defined by the second, third and fourth bits) wouldn't work because of the potential for unplayable variations. I believe that's true even if the variation counter isn't BCD.

 

But if there are ways around the conflicting combinations that don't require a look-up table and don't make the ROM size bigger, then I stand corrected.

 

"Potential" contradictory variations are no problem to deal with (as you could see from games like Space Invaders or Maze Craze)...use multiple bits instead of 1

 

I wonder if the multiple-bits solution would still allow all features to be crammed into an 8-bit value...

 

Yes, it could. It looks like there are eight "sensible" playfields, which fit perfectly into three bits. That leaves five bits, which is more than enough even if every other feature gets its own bit. If getaway, six-shooters and the number of players each get their own bit, then the only combination to avoid is having one player and six-shooters toggled. A jump back to variation #1 at the right count will work around that effectlvely enough.

 

So if I'm doing my math right, there are 48 possible "good" combinations. But, I'm afraid the logic to create them is a little beyond my current hacking ablity.

Edited by FujiSkunk
Link to comment
Share on other sites

One player and six-shooter are mutually-exclusive, yes. So is a wall playfield object and a non-shootable playfield - that would be an impossible game. Cactus and moving playfield doesn't make much sense logically, so that too could be considered to be mutually-exclusive. The trick is to end the game variation increments (via rollover) before those bitpattern combinations are reached, or use those same bits to control differing things in alternate sections of game variations.

 

I don't see how you got eight playfields, tho. There's really only 3 (cactus, coach, or wall). This could be expanded to have no obstacle as a fourth...which fits into 2 bits (i.e. a non-shootable wall variation should be replaced by no playfield). Getaway uses a bit. # of players uses a bit. You could use the leftovers for other Atari-like variations (such as Pong - allow missiles to rebound).

Link to comment
Share on other sites

Here's an example of how this could be done. By moving the target and 6gun selections to use higher bits, an additional option can be added to bit5 (let's call it "pong" for the sake of description). Adding rollover code to happen at variation 193, target+6gun game selections never happen. So the remaining problems would be a solid wall (impossible), and moving and/or shootable coupled with noPF (identical gameplay as nonmoving+solid+noPF). The first problem is solved by blinking the wall on and off during gameplay...so the gameplay selection chart would look like this:

;----------    S
;----------    H
;----------    OG
;----------T  MOE
;----------A  OTT C
;----------R6PVAAWO
;----------GGOIBWAA
;----------EUNNLALC
;----------TNGGEYLH
   .byte %00000000 ; Variant 001 cactus
   .byte %00000001 ; Variant 002 coach
   .byte %00000010 ; Variant 003 blinkwall
   .byte %00000011 ; Variant 004 noPF
   .byte %00000100 ; Variant 005 getaway,cactus
   .byte %00000101 ; Variant 006 getaway,coach
   .byte %00000110 ; Variant 007 getaway,blinkwall
   .byte %00000111 ; Variant 008 getaway,noPF
   .byte %00001000 ; Variant 009 shootable,cactus
   .byte %00001001 ; Variant 010 shootable,coach
   .byte %00001010 ; Variant 011 shootable,wall
   .byte %00001011 ; Variant 012 shootable,noPF
   .byte %00001100 ; Variant 013 shootable,getaway,cactus
   .byte %00001101 ; Variant 014 shootable,getaway,coach
   .byte %00001110 ; Variant 015 shootable,getaway,wall
   .byte %00001111 ; Variant 016 shootable,getaway,noPF
   .byte %00010000 ; Variant 017 moving,cactus
   .byte %00010001 ; Variant 018 moving,coach
   .byte %00010010 ; Variant 019 moving,blinkwall
   .byte %00010011 ; Variant 020 moving,noPF
   .byte %00010100 ; Variant 021 moving,getaway,cactus
   .byte %00010101 ; Variant 022 moving,getaway,coach
   .byte %00010110 ; Variant 023 moving,getaway,blinkwall
   .byte %00010111 ; Variant 024 moving,getaway,noPF
   .byte %00011000 ; Variant 025 moving,shootable,cactus
   .byte %00011001 ; Variant 026 moving,shootable,coach
   .byte %00011010 ; Variant 027 moving,shootable,wall
   .byte %00011011 ; Variant 028 moving,shootable,noPF
   .byte %00011100 ; Variant 029 moving,shootable,getaway,cactus
   .byte %00011101 ; Variant 030 moving,shootable,getaway,coach
   .byte %00011110 ; Variant 031 moving,shootable,getaway,wall
   .byte %00011111 ; Variant 032 moving,shootable,getaway,noPF
   .byte %00100000 ; Variant 033 pong,cactus
   .byte %00100001 ; Variant 034 pong,coach
   .byte %00100010 ; Variant 035 pong,blinkwall
   .byte %00100011 ; Variant 036 pong,noPF
   .byte %00100100 ; Variant 037 pong,getaway,cactus
   .byte %00100101 ; Variant 038 pong,getaway,coach
   .byte %00100110 ; Variant 039 pong,getaway,blinkwall
   .byte %00100111 ; Variant 040 pong,getaway,noPF
   .byte %00101000 ; Variant 041 pong,shootable,cactus
   .byte %00101001 ; Variant 042 pong,shootable,coach
   .byte %00101010 ; Variant 043 pong,shootable,wall
   .byte %00101011 ; Variant 044 pong,shootable,noPF
   .byte %00101100 ; Variant 045 pong,shootable,getaway,cactus
   .byte %00101101 ; Variant 046 pong,shootable,getaway,coach
   .byte %00101110 ; Variant 047 pong,shootable,getaway,wall
   .byte %00101111 ; Variant 048 pong,shootable,getaway,noPF
   .byte %00110000 ; Variant 049 pong,moving,cactus
   .byte %00110001 ; Variant 050 pong,moving,coach
   .byte %00110010 ; Variant 051 pong,moving,blinkwall
   .byte %00110011 ; Variant 052 pong,moving,noPF
   .byte %00110100 ; Variant 053 pong,moving,getaway,cactus
   .byte %00110101 ; Variant 054 pong,moving,getaway,coach
   .byte %00110110 ; Variant 055 pong,moving,getaway,blinkwall
   .byte %00110111 ; Variant 056 pong,moving,getaway,noPF
   .byte %00111000 ; Variant 057 pong,moving,shootable,cactus
   .byte %00111001 ; Variant 058 pong,moving,shootable,coach
   .byte %00111010 ; Variant 059 pong,moving,shootable,wall
   .byte %00111011 ; Variant 060 pong,moving,shootable,noPF
   .byte %00111100 ; Variant 061 pong,moving,shootable,getaway,cactus
   .byte %00111101 ; Variant 062 pong,moving,shootable,getaway,coach
   .byte %00111110 ; Variant 063 pong,moving,shootable,getaway,wall
   .byte %00111111 ; Variant 064 pong,moving,shootable,getaway,noPF
   .byte %01000000 ; Variant 065 6gun,cactus
   .byte %01000001 ; Variant 066 6gun,coach
   .byte %01000010 ; Variant 067 6gun,blinkwall
   .byte %01000011 ; Variant 068 6gun,noPF
   .byte %01000100 ; Variant 069 6gun,getaway,cactus
   .byte %01000101 ; Variant 070 6gun,getaway,coach
   .byte %01000110 ; Variant 071 6gun,getaway,blinkwall
   .byte %01000111 ; Variant 072 6gun,getaway,noPF
   .byte %01001000 ; Variant 073 6gun,shootable,cactus
   .byte %01001001 ; Variant 074 6gun,shootable,coach
   .byte %01001010 ; Variant 075 6gun,shootable,wall
   .byte %01001011 ; Variant 076 6gun,shootable,noPF
   .byte %01001100 ; Variant 077 6gun,shootable,getaway,cactus
   .byte %01001101 ; Variant 078 6gun,shootable,getaway,coach
   .byte %01001110 ; Variant 079 6gun,shootable,getaway,wall
   .byte %01001111 ; Variant 080 6gun,shootable,getaway,noPF
   .byte %01010000 ; Variant 081 6gun,moving,cactus
   .byte %01010001 ; Variant 082 6gun,moving,coach
   .byte %01010010 ; Variant 083 6gun,moving,blinkwall
   .byte %01010011 ; Variant 084 6gun,moving,noPF
   .byte %01010100 ; Variant 085 6gun,moving,getaway,cactus
   .byte %01010101 ; Variant 086 6gun,moving,getaway,coach
   .byte %01010110 ; Variant 087 6gun,moving,getaway,blinkwall
   .byte %01010111 ; Variant 088 6gun,moving,getaway,noPF
   .byte %01011000 ; Variant 089 6gun,moving,shootable,cactus
   .byte %01011001 ; Variant 090 6gun,moving,shootable,coach
   .byte %01011010 ; Variant 091 6gun,moving,shootable,wall
   .byte %01011011 ; Variant 092 6gun,moving,shootable,noPF
   .byte %01011100 ; Variant 093 6gun,moving,shootable,getaway,cactus
   .byte %01011101 ; Variant 094 6gun,moving,shootable,getaway,coach
   .byte %01011110 ; Variant 095 6gun,moving,shootable,getaway,wall
   .byte %01011111 ; Variant 096 6gun,moving,shootable,getaway,noPF
   .byte %01100000 ; Variant 097 6gun,pong,cactus
   .byte %01100001 ; Variant 098 6gun,pong,coach
   .byte %01100010 ; Variant 099 6gun,pong,blinkwall
   .byte %01100011 ; Variant 100 6gun,pong,noPF
   .byte %01100100 ; Variant 101 6gun,pong,getaway,cactus
   .byte %01100101 ; Variant 102 6gun,pong,getaway,coach
   .byte %01100110 ; Variant 103 6gun,pong,getaway,blinkwall
   .byte %01100111 ; Variant 104 6gun,pong,getaway,noPF
   .byte %01101000 ; Variant 105 6gun,pong,shootable,cactus
   .byte %01101001 ; Variant 106 6gun,pong,shootable,coach
   .byte %01101010 ; Variant 107 6gun,pong,shootable,wall
   .byte %01101011 ; Variant 108 6gun,pong,shootable,noPF
   .byte %01101100 ; Variant 109 6gun,pong,shootable,getaway,cactus
   .byte %01101101 ; Variant 110 6gun,pong,shootable,getaway,coach
   .byte %01101110 ; Variant 111 6gun,pong,shootable,getaway,wall
   .byte %01101111 ; Variant 112 6gun,pong,shootable,getaway,noPF
   .byte %01110000 ; Variant 113 6gun,pong,moving,cactus
   .byte %01110001 ; Variant 114 6gun,pong,moving,coach
   .byte %01110010 ; Variant 115 6gun,pong,moving,blinkwall
   .byte %01110011 ; Variant 116 6gun,pong,moving,noPF
   .byte %01110100 ; Variant 117 6gun,pong,moving,getaway,cactus
   .byte %01110101 ; Variant 118 6gun,pong,moving,getaway,coach
   .byte %01110110 ; Variant 119 6gun,pong,moving,getaway,blinkwall
   .byte %01110111 ; Variant 120 6gun,pong,moving,getaway,noPF
   .byte %01111000 ; Variant 121 6gun,pong,moving,shootable,cactus
   .byte %01111001 ; Variant 122 6gun,pong,moving,shootable,coach
   .byte %01111010 ; Variant 123 6gun,pong,moving,shootable,wall
   .byte %01111011 ; Variant 124 6gun,pong,moving,shootable,noPF
   .byte %01111100 ; Variant 125 6gun,pong,moving,shootable,getaway,cactus
   .byte %01111101 ; Variant 126 6gun,pong,moving,shootable,getaway,coach
   .byte %01111110 ; Variant 127 6gun,pong,moving,shootable,getaway,wall
   .byte %01111111 ; Variant 128 6gun,pong,moving,shootable,getaway,noPF
   .byte %10000000 ; Variant 129 target,cactus
   .byte %10000001 ; Variant 130 target,coach
   .byte %10000010 ; Variant 131 target,blinkwall
   .byte %10000011 ; Variant 132 target,noPF
   .byte %10000100 ; Variant 133 target,getaway,cactus
   .byte %10000101 ; Variant 134 target,getaway,coach
   .byte %10000110 ; Variant 135 target,getaway,blinkwall
   .byte %10000111 ; Variant 136 target,getaway,noPF
   .byte %10001000 ; Variant 137 target,shootable,cactus
   .byte %10001001 ; Variant 138 target,shootable,coach
   .byte %10001010 ; Variant 139 target,shootable,wall
   .byte %10001011 ; Variant 140 target,shootable,noPF
   .byte %10001100 ; Variant 141 target,shootable,getaway,cactus
   .byte %10001101 ; Variant 142 target,shootable,getaway,coach
   .byte %10001110 ; Variant 143 target,shootable,getaway,wall
   .byte %10001111 ; Variant 144 target,shootable,getaway,noPF
   .byte %10010000 ; Variant 145 target,moving,cactus
   .byte %10010001 ; Variant 146 target,moving,coach
   .byte %10010010 ; Variant 147 target,moving,blinkwall
   .byte %10010011 ; Variant 148 target,moving,noPF
   .byte %10010100 ; Variant 149 target,moving,getaway,cactus
   .byte %10010101 ; Variant 150 target,moving,getaway,coach
   .byte %10010110 ; Variant 151 target,moving,getaway,blinkwall
   .byte %10010111 ; Variant 152 target,moving,getaway,noPF
   .byte %10011000 ; Variant 153 target,moving,shootable,cactus
   .byte %10011001 ; Variant 154 target,moving,shootable,coach
   .byte %10011010 ; Variant 155 target,moving,shootable,wall
   .byte %10011011 ; Variant 156 target,moving,shootable,noPF
   .byte %10011100 ; Variant 157 target,moving,shootable,getaway,cactus
   .byte %10011101 ; Variant 158 target,moving,shootable,getaway,coach
   .byte %10011110 ; Variant 159 target,moving,shootable,getaway,wall
   .byte %10011111 ; Variant 160 target,moving,shootable,getaway,noPF
   .byte %10100000 ; Variant 161 target,pong,cactus
   .byte %10100001 ; Variant 162 target,pong,coach
   .byte %10100010 ; Variant 163 target,pong,blinkwall
   .byte %10100011 ; Variant 164 target,pong,noPF
   .byte %10100100 ; Variant 165 target,pong,getaway,cactus
   .byte %10100101 ; Variant 166 target,pong,getaway,coach
   .byte %10100110 ; Variant 167 target,pong,getaway,blinkwall
   .byte %10100111 ; Variant 168 target,pong,getaway,noPF
   .byte %10101000 ; Variant 169 target,pong,shootable,cactus
   .byte %10101001 ; Variant 170 target,pong,shootable,coach
   .byte %10101010 ; Variant 171 target,pong,shootable,wall
   .byte %10101011 ; Variant 172 target,pong,shootable,noPF
   .byte %10101100 ; Variant 173 target,pong,shootable,getaway,cactus
   .byte %10101101 ; Variant 174 target,pong,shootable,getaway,coach
   .byte %10101110 ; Variant 175 target,pong,shootable,getaway,wall
   .byte %10101111 ; Variant 176 target,pong,shootable,getaway,noPF
   .byte %10110000 ; Variant 177 target,pong,moving,cactus
   .byte %10110001 ; Variant 178 target,pong,moving,coach
   .byte %10110010 ; Variant 179 target,pong,moving,blinkwall
   .byte %10110011 ; Variant 180 target,pong,moving,noPF
   .byte %10110100 ; Variant 181 target,pong,moving,getaway,cactus
   .byte %10110101 ; Variant 182 target,pong,moving,getaway,coach
   .byte %10110110 ; Variant 183 target,pong,moving,getaway,blinkwall
   .byte %10110111 ; Variant 184 target,pong,moving,getaway,noPF
   .byte %10111000 ; Variant 185 target,pong,moving,shootable,cactus
   .byte %10111001 ; Variant 186 target,pong,moving,shootable,coach
   .byte %10111010 ; Variant 187 target,pong,moving,shootable,wall
   .byte %10111011 ; Variant 188 target,pong,moving,shootable,noPF
   .byte %10111100 ; Variant 189 target,pong,moving,shootable,getaway,cactus
   .byte %10111101 ; Variant 190 target,pong,moving,shootable,getaway,coach
   .byte %10111110 ; Variant 191 target,pong,moving,shootable,getaway,wall
   .byte %10111111 ; Variant 192 target,pong,moving,shootable,getaway,noPF

 

An actual game selection chart within the program can then be done away with entirely...but the kernel would need a slight modification to convert the game selection # into decimal, and display 3 digits instead of only 2.

Link to comment
Share on other sites

I don't see how you got eight playfields, tho.

 

1. Cactus

2. Blowaway Cactus

3. Stagecoach

4. Blowaway Stagecoach

5. Moving Stagecoach

6. Moving, Blowaway Stagecoach

7. Blowaway Wall

8. Moving, Blowaway Wall

 

Here's an example of how this could be done. By moving the target and 6gun selections to use higher bits, an additional option can be added to bit5 (let's call it "pong" for the sake of description)...

 

I've been pondering on this, and come up with something similar to what you have, but focusing on the features Outlaw currently offers.

 

First three bits: playfield selection, based on the list above

Fourth bit: 0 = no getaway, 1 = getaway

Fifth bit: 0 = no six-shooter, 1 = six-shooter

Sixth bit: 0 = two-payer, 1 = one-player

Seventh and eighth bits: not used

 

Then, cap the game-select at 48 (actually 47 internally) and you have every sensible combination offered by the original features.

 

An actual game selection chart within the program can then be done away with entirely...but the kernel would need a slight modification to convert the game selection # into decimal, and display 3 digits instead of only 2.

 

I'm reading through and playing with Andrew Davies's 2600 programming tutorials now...

Link to comment
Share on other sites

D'oH! Thanks for the breakdown.

 

Since you are only using 6 of the bits then, it becomes even simpler. The program just needs to convert to BCD using a little loop where cycle time is inconsequential. As a test, I did the changes below to Manuel's disassembly (without altering anything else but your suggestions, the program ultimately saves 7 bytes and 1 byte of ram). And there's much more that could be saved.

 

Look for the ";edit" lines

 

EDIT: score wasn't being shown. Stupid BIT instruction sometimes fails me.

outlaw48.asm

Edited by Nukey Shay
Link to comment
Share on other sites

Ah, cool!

 

I've read enough of the tutorials to follow along with the changes. It's definitely going to be a while before I'm good at reading between the lines to know what's going on with the flags.

 

I have at least one idea about an addition I could make. I'll make that my next (or first "real") hack project.

 

Thanks!

Link to comment
Share on other sites

It's definitely going to be a while before I'm good at reading between the lines to know what's going on with the flags.
Not at all. You already correctly noticed that flag values are set via lookup table in the original game. The rest can be done through trial-and-error... force a flag to be set and see what effect it has. The Stella debugger is invaluable here instead of continually creating test bins.

 

For increasing the number of options, you can use the 2 remaining bits of gameSettingBits (but this would require kernel mod to display > 2 digits). An alternate approach would be to use bcdScore02 to show them (i.e. Breakout uses p2's score for the number of players selection). The above assembly has an unused byte of ram (bcdGameVariant)... and bcdScore01Backup isn't really used at all either (if you take out those 4 lines that reference it) for an additional byte of ram.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...