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.

Tuesday, October 20, 2009

OutRun Gameplay Laserdisc & VHS

I'm still beavering away, reverse engineering the OutRun source. I'm focusing on the sprite routines and level data at the moment. Both of which are quite complex. I've uncovered some pretty intriguing stuff, and understand why OutRun uses the convoluted jump table I mentioned in an earlier post. It's related to rendering the level data, and many of the repeated routines handle sprites.

But I'm not going to talk about that right now, as there's still further work to be done. Instead let's take a look at some curiosities I've found on ebay over the years.

First up is a rare Japanese video laser disc (i.e. not a game), manufactured by Pony Canyon in 1988. Pony Canyon are a Japanese publisher, who also published the MSX 2 version of Outrun. 


The laserdisc is a small 20cm disc, so requires an adapter to work in certain players. The content of the laserdisc is a short 18 min video showing the optimal way of completing each of OutRun's 15 stages. The gameplay makes use of the Geargacha technique, popularised by Japanese games magazine Gamest in 1987. This technique allows the player to drive off-road without loss of speed by carefully timed rapid gear shifting. It also allows the player to achieve a rocket start, flying off the line to top speed in seconds. 

The accompanying booklet contains information on the stages in the game. I would love to get this translated if anyone can speak Japanese?



Pony Cannon also released the "Game Simulation Video" shown below in the same year. The video contains footage from Galaxy Force and Thunder Blade in addition to the same video of Outrun.


The booklet that accompanies the video, shows a range of these videos was available. Other titles included After Burner, Hang-On, R-Type, Street Fighter and more. Incidentally, at the time I purchased the Outrun LD, the same seller also had a Turbo Outrun disc. But I'm not a huge fan of Turbo Outrun, so I passed on that option.

 


This was also released on Laserdisc:





The OutRun movie makes a further reappearance on this rare DVD, included in early editions of the OutRun 20th anniversary soundtrack box set. I've partially scanned the inlay here


In 1987, Sony released a separate gameplay laserdisc produced by the Tyrell Corporation. Unlike the Pony Canyon edition, this is a full-size 12 inch disc. It contains a wonderful colour inlay of the OutRun stages, lifted from the original Japanese arcade flyer. 




And here's the VHS version:


The contents of this release are different and somewhat strange. For example, it contains a section which shows a series of crashes in succession, as well as the Ferrari being driven deliberately off-road. However, it doesn't demonstrate the gia-gacha (gear rattling) technique during gameplay sequences like the Pony Canyon release.

Article from Game Machine July 1987

Tuesday, September 29, 2009

Tools and Tiles

Wrote a quick tool, which takes an Outrun CPU 0 memory dump from the MAME debugger as input. As output it prints the jump table from that stage of the game that has been built and stored in RAM.

This is handy, because it formats the data and only shows the addresses which are currently enabled, and doesn't repeat addresses when they're called in succession. The table in RAM itself is 124 entries long, and updated at various points during runtime.

So here's the in-game output:

0. 0xB15E
1. 0x74E2
2. 0x3BEE
3. 0x4048 (16 times)
21. 0x4828 (15 times)
82. 0x4ADC
83. 0x5248 (5 times)
91. 0x9862
92. 0x9C84
93. 0xA568 (2 times)
95. 0x5EA8
103. 0xA816
104. 0xA7D2
105. 0xA816
106. 0xC5A4
123. 0x78B0
124. 0xE644


This has made it easier to figure out exactly where in code the program is updating this table.

What else? I've been looking into the tile handling code. Tilemaps are used in OutRun for the horizon graphics (two layers) , the text layer is a tilemap and obvious things like the music selection screen are a tilemap. Each tile entry in the map is a word. The compression format for the first tilemap I've analysed in ROM is as follows:

1/ If a word is not '0x0000', copy immediate word directly to tileram
2/ If a word is '0x0000' a long follows which details the compression.
The upper word of the long is the tilemap value to copy.
The lower word of the long is the number of times to copy that value.

And here's how OutRun manages to store your exact route history through the levels in just a byte.

1/ There are 5 stages, and a memory location increases by 0x10 for each stage you progress.
2/ Each stage forks twice, giving 15 stages in total. At each stage, this same memory location increments as follows when the left hand route is selected:

Stage 1 = +8 (1 << 3 - 0)
Stage 2 = +4 (1 << 3 - 1)
Stage 3 = +2 (1 << 3 - 2)
Stage 4 = +1 (1 << 3 - 3)
Stage 5 = Road doesn't split on this stage

3/ Later this indexes into a lookup table, which then makes it easy to update things like the stage map at the bottom right hand corner of the screen during gameplay.

Other than that, I'm thinking about how to represent the graphics once I convert the engine to C. Do I keep them in a similar format, and just render a final array of pixel data (similar to how an emulator would render it's display), or do I convert them to a native PNG or similar? This would make it easier for someone to replace them and change the game, but could run into problems with palette changes and so forth. Thoughts...

Anyway, this post might give you some idea of some of the things I'm doing at the moment. There's still a long way to go.

Thursday, September 17, 2009

Quick progress report: Commented all the code relating to detecting when the car is off-road. Figured out the memory location that determined which wheel was off. Established the memory location that determined the width of the road, and handles splitting the road between number of lanes and individual roads. Commented some slightly less interesting code relating to lap times, output lamps and various other areas.

Amusing OutRun link: Unbelievable. I have found someone with a more insane project than my own. A real world OutRun cabinet containing a golf-cart... The mind boggles?

Thursday, September 10, 2009

Debugging

I reached a point where it was time to switch to a competent interactive debugger, instead of working out of a series of text files that were becoming increasingly difficult to manage.

It took me a good few days to transfer my comments and knowledge to the new system. But the payoff is massive - I've immediately spotted mistakes, and identifying blocks of code has become a lot less painful.



In the screenshot you can see the commented block of code that transfers the in-game timer to the on-screen HUD.

Yesterday I also documented how the main branch table works in memory. In fact, I'm not even sure if branch table is the correct terminology. Figuring this out was important because actually determining the program flow in Outrun is tricky. The list of functions that are finally called is generated at runtime, and differs at different points of the game.

Firstly, there's a portion of ROM that contains a series of long addresses. Each of these addresses is a pointer to another portion of ROM. This second portion of ROM contains a set of properties related to the function, and the final address of the function itself. The final step is to compile these to a table within RAM. This table contains bits so that the functions can be enabled or disabled.

I presume this is some kind of optimisation, but it seems to add a lot of indirection and makes following the flow of code rather tough from the onset. Maybe some level of obfuscation was the idea? Perhaps someone reading who is a 68000 wiz will know.

Update: Figured this out. Some useful information in the comments regarding this from one of the blog readers and myself :)

Thursday, August 27, 2009

Decompilation Update

As predicted, progress is slow and steady.

The most satisfying way of working is attempting to solve as many unknowns in a particular area, and then moving on when the going gets tough. Going back to a set of routines with a fresh pair of eyes really helps.

Some areas that I've worked on:

1/ Car control (X Position, Acceleration, Gear Changes)
2/ Road splitting code (High level areas including the 'road splitting state')
3/ Elements relating to the current track segment
4/ Sprite rendering code (Very complex, so moved on temporarily from there)

I've successfully understood various memory locations, and slowly routines become understandable from the meaningless muddle they originally were.

Tuesday, August 11, 2009

Outrun Decompilation Oddities

The decompilation is moving along reasonably nicely. I've slowly picking up a decent understanding of the game code.

One interesting thing with the decompilation is that it uncovers code routines and text that don't appear to be in the final game.

For example, check the strings in the following screenshot:



BIN CHAN E
COLOR BANK GA TARINA NOYO !
1 STAGE 127 KO INAINI SHITENE

If you set the program counter to 0x7644 (by typing pc=0x7644) in the mame debugger, and resume execution you will see for yourself.

The text can be translated roughly as follows:

To BIN CHAN
Color bank is lacking.
Make it less than 127 for one stage. 


Bin Chan (aka Satoshi Mifune) is a developer who worked on OutRun, Space Harrier and Afterburner. He is listed as BIN in the hi-score table.




It's suggested that this is some kind of protection. "Sega use the MCU to copy tilebank values on most of the system16 games, maybe they use it to copy a colour bank value on space harrier too, but it's not obvious until you get to that stage". 

Monday, August 10, 2009

OutRun Decompilation Project

I'm something of an OutRun obsessive. I've got the arcade machine in my parent's garage (they keep requesting that I remove it) and I coded the OutRun driver for Jemu2. The game has so many memories attached to it, and it will always hold a lofty place in my heart beyond what it probably deserves.


One coding project that I've dabbled with on rainy days, is a full decompilation and reverse engineering of the original arcade ROMs. This is a massive undertaking, and one that I suspect I will never truly complete. But it is intriguing to pull apart the game I loved so much as a kid, to find out exactly how it works.

The ultimate goals of this project are:

1/ Reimplement OutRun in portable C, so that it can be compiled to pretty much any modern handheld/computer. And the code can be easily extended/modified.

2/ Create a level editor for the game. Potentially for the original arcade version and the version created in step 1.

Realistically, it will probably just be a bit of fun. If you can call pouring through thousands of lines of unlabelled, uncommented, decompiled 68000 assembler fun that is.

So far, my steps have been as follows:

1/ Wrote a program to de-interleave the arcade ROMs and spit them back out. I've then decompiled them to text files.

2/ Made some notes on the OutRun hardware via reference to the Mame source code.

3/ Begun commenting the decompiled assembler, using the Mame debugger for assistance.

Progress is promising. I started by figuring out all the routines for the text layer of the hardware. As the name suggests, this is essentially a layer of 8x8 tiles that is used to print things like "INSERT COIN" to the screen, and some other static graphics like the HUD elements.

It's been quick to rattle through the code and comment exactly when and where the graphics are blitted. So I quickly have an understanding of the general code structure, from the service tests through to high score tables and even the OutRun easter egg, which prints Yu Suzuki's name.

I've also figured out a lot of other important information, including the memory address used to store the games internal state (e.g. attract mode / music selection / high score entry / in-game / clock countdown / map screen), which makes identifying roughly what individual areas of code are performing far simpler.

There's a lot more I've managed to achieve, although this is a project whereby progress is slow until you reach a tipping point. The most similar project I've worked on previously was converting Speedball 2 to J2ME phones. But as this was an official port, I had access to nicely commented and labelled 68000 assembler - much easier.

In other news, I haven't forgotten about FlashGear, just put it on hold for the time being, until I get the motivation to polish it up for a release.