Friday, November 27, 2009

Game Objects and Level Format

I've made a lot of progress. After a lot of hard work I've figured out the internal object format used by OutRun for most sprites and game objects which is a big breakthrough. I understand the complete format, with the exception of a single bit that eludes me right now. The internal format is a lot more complex than the values finally written directly to the sprite hardware, as it includes aspects like:
  • Both Screen Co-ordinates & World co-ordinates
  • Sprite Z Values
  • Independent priority settings in relation to the road layer and other sprites
  • Specific Sprite routines to use
  • X/Y Draw anchors
  • Sprite Type
  • Frame Number
  • The way in which the sprites utilise a series of lookup tables to extract more properties
  • All the usual things you'd expect: h-flip values, palette settings and so forth.
The traffic sprite format uses a version of this, but adds additional properties:
  • Bits to denote the traffic's position in relation to other traffic. This is used to control its speed and lane changing behaviour. 
  • Speed
  • Information regarding the side of the road the traffic has spawned on
Even after establishing the above, and also a lot of related code - one thing is pretty clear: the codebase to this game is advanced and complex.

I also understand the internal format used to store the scenery data for the entire set of levels. Writing a quick utility to spit this out in some kind of visual form would be an interesting exercise and a way of verifying this. Whilst all the code is documented and commented, looking at it actually hurts by brain. I'll follow up on this later.

Wednesday, November 11, 2009

Look Both Ways!

One interesting aspect of disassembling games you're fond of, is that you might uncover hidden code that was unused in the final build. This can give an insight into some of the features that were planned that didn't make the final cut, either because of time, technical problems or maybe they simply didn't prove fun during playtesting.

Lately I've been disassembling the traffic handling code, and in doing so I stumbled upon an interesting memory address that controlled a block of code related to spawning traffic. I was unable to figure out exactly what it did from the code and couldn't find any references where the address was written to. So I fired up the MAME debugger and wrote to the memory address manually so that the block of code would always execute.

In Outrun, all traffic drives into the horizon before disappearing. To my surprise, setting this flag caused the traffic to drive away from the horizon in the opposite direction towards the player's Ferrari. I imagine that the original idea was to have two-way traffic. The fact that Outrun's hardware supports two separate road layers means that the final effect could have been quite impressive with independent flows of traffic on each road!

As it is, the code is clearly unfinished, and no graphics exist for traffic travelling in the opposite direction. But it demonstrates what the development team originally planned. It certainly would have been impressive back in 1986 if they'd pulled it off. 

You can see for yourself in the MAME debugger by changing the address with: b@60b6b = 1 once the game has booted.

Tuesday, November 10, 2009

Extend Time!

One of the aspects of OutRun that somewhat puzzled me as a player, was exactly how the "Extend Time!" feature at the end of each level worked.

This is the additional time that is added to the countdown timer on passing a checkpoint. I've never seen details published - until now....

Here's a table that shows the time, in seconds, that is added to your overall counter per stage. The rightmost route is show first. The DIP switches of the arcade cabinet can be set to four difficulty settings for timing, and each respective setting has its own column. If you are lucky enough to find a working cabinet in the wild, it's easy to determine the setting by looking at how much time you start the game with.

         | Easy | Norm | Hard | VHar |
Stage 1  |  80     75     72     70  |
Stage 2a |  65     65     65     65  |
Stage 2b |  62     62     62     62  |
Stage 3a |  57     55     57     57  |
Stage 3b |  62     60     60     60  |
Stage 3c |  60     60     59     58  |
Stage 4a |  66     65     64     62  |
Stage 4b |  63     62     60     60  |
Stage 4c |  61     60     58     58  |
Stage 4d |  65     65     63     63  |
Stage 5a |  58     56     54     54  |
Stage 5b |  55     56     54     54  |
Stage 5c |  56     56     54     54  |
Stage 5d |  58     56     54     54  |
Stage 5e |  56     56     56     56  |

To be honest, some of the entries are a little strange. For example, why is Stage 3a (Cloudy Mountain) more difficult on Normal than Very Hard? Is this an error in the table?

I'm working from the Overseas version of Outrun. I'm not sure yet whether the table differs for the Japanese version where Gateway has been moved to Stage 4.

It should also be pointed out that all the tracks in Outrun are the same length from a technical point of view. Obviously some will be tougher in terms of sharp bends and thinner stretches of road. The road split at the end of each level is hard coded and not read from the level data.

Moving onto the traffic in the game. Once again, this can be set by the DIP switches to four independent settings. I haven't reverse engineered the traffic code in detail yet, but I can provide some rough guidance as to how the settings affect each level in the game. It's my understanding that the following table represents the maximum number of vehicles that can be spawned simultaneously on each level.

         | Easy | Norm | Hard | VHar |
Stage 1  |   2      3      4      5  |
Stage 2  |   2      4      5      6  |
Stage 3  |   3      5      6      7  |
Stage 4  |   4      6      7      8  |
Stage 5  |   5      7      8      8  |

Looking at the code which spawns the traffic, hacking the game to support more traffic wouldn't be trivial because there are only 8 slots in the jump table reserved for traffic sprite routines.