Thursday, October 18, 2012

Z80 Program Code - Part 1

I've almost finished decompiling OutRun's Z80 program code, so I'll be providing high level information regarding its workings over a series of posts.

The Z80 processor controls two pieces of sound hardware; a custom Sega PCM controller and a Yamaha YM2151 FM sound chip. This was a fairly standard configuration for Sega boardsets at the time. As you'd expect, some of the Z80 program code is in fact shared with other games of the era. However, most of the code is unique and written solely with OutRun in mind.

Commands are sent to the Z80 from the master 68000 program code. The Z80's interrupt routine reads from port 0x40 and places the values received into a sequential set of locations in RAM. Commands are high level and consist of a byte corresponding to a Z80 routine. So sending 0x81 plays the 'Passing Breeze' music, whereas 0x9d triggers the 'Checkpoint' PCM sample. From the 68000's point of view, playing a sound is simple and the complexity is nicely masked.

In addition to these commands, the 68000 sends data relating to the volume and pitch of the Ferrari's engine tone. It also sends volume and panning information relating to the passing traffic. This ensures that when you drive past a vehicle, the volume of its engine is proportional to the y distance from your Ferrari and the stereo panning corresponds to the x difference.

The core loop to achieve everything is as follows:

ROM:0039 main_loop:
ROM:0039   call    DoFMTimerA      ; Wait for timer on YM2151 chip 
ROM:003C   call    ProcessCommand  ; Process Command sent by 68000
ROM:003F   call    ProcessChannels ; Run logic on individual sound channel (both YM & PCM channels)
ROM:0042   call    ProcessEngines  ; Ferrari Engine Tone & Traffic Noise
ROM:0045   call    ProcessTraffic  ; Traffic Volume, Panning, Pitch
ROM:0048   jp      main_loop

The Z80 maps the 16 channels of the PCM chip to various uses. 6 are reserved for the music's drum samples, 4 are used for sampled sound effects and the remainder are used for the Ferrari's engine sound and passing traffic. Each channel is allocated a 32 byte area of RAM by the Z80 program code, which stores its current state. This concept is extended to include the channels from the YM chip which are also allocated to these areas of RAM.

The usage of the 32 byte area of RAM differs dependent on whether it represents a YM or PCM channel. The area contains everything from basics including volume and pitch for PCM samples through to complex YM configuration including positional information within the current block of audio commands, section loop counters and the address of the next data block. This 32 byte block is used as a starting point to configure the separate PCM RAM area, which has a different format and to program the YM's registers.

Next time, I'll explain the interpreted language stored within the Z80 code. This is used by the Z80 to program the sound hardware. And you'll see how the music and sound effects are actually stored as an interpreted sequence of commands that call functions within the code.

Monday, September 24, 2012

Raspberry Pi Progress

Here's a screenshot of the OutRun engine running on a Raspberry Pi. The display is being output on X11 via SSH. It hasn't been tried on the native Pi display yet. 


I've decided to name the OutRun engine Cannonball, after the 1981 Cannonball Run film that Yu Suzuki was inspired by. 

Friday, September 07, 2012

Cross Platform Support

Thanks to everyone who tried the recent Visual Studio based build for Windows. The plan is to ensure this becomes a true cross platform project, not tied to a particular operating system or architecture. I like to think of it as "OutRun Everywhere", making the world a better place ;) Thanks to some work from a friend, who knows far more about this sort of thing than me, this is close to becoming a reality.

The code now successfully compiles and runs on both a Mac with XCode IDE support and the Windows MinGW compiler. Other platforms will shortly follow, including Linux and the Raspberry PI if performance allows.

We're using CMake, the cross platform, open-source build system. This automates the creation of build files for a whole range of target platforms. We're able to generate builds for a whole host of platforms and configurations.

The C++ libraries have been switched to Boost. This provides an open-source cross platform alternative to facilitate portability.

I can't take credit for the above, but I have started decompilation work on the Z80 code that controls the sound hardware (both the custom Sega PCM sample player and the Yamaha YM2151). This is my main area of focus and will take some time. So far, I've commented the code that triggers the PCM samples. Ultimately, I'd love to give players the choice of emulating the original sound hardware or streaming audio from disk, similar to the approach used by the Sega Saturn conversion.

Monday, August 27, 2012

OutRun C++ Engine Tech Demo 2

At last, here's a new demo of the OutRun engine. The entire game is ported, aside from sound and the service mode.

In terms of functionality, this release is bare bones. There is no menu system yet, all options are hardcoded and you have to play the game windowed.

It would be great if you could report bugs (and I'm sure there will be plenty) in the comments below. Please verify any subtleties against MAME for reference.


Stats:

  • Conversion time from decompiled code: 1 year 10 months.
  • Estimated ratio of time spent coding vs. debugging: 1:5
  • Road rendering code: 1500 lines
  • Ferrari handling & rendering: 1680 lines
  • Code to render level objects: 1050 lines
  • General sprite handling code: 890 lines
  • Traffic handling code: 675 lines
  • Code to handle crash routines: 1450 lines

Keys:

  • Cursors: Steering
  • Z: Accelerate
  • X: Brake
  • Space: Gear Change
  • 5: Insert Coin
  • 1: Start
  • F1: Pause
  • F2: Advance a frame when paused (useful for observing visual problems)
  • F3: Toggle/Freeze timers. (i.e. infinite time)
In a future revision, there will be options to custom the controls and the analogue sensitivity. I find MAME's default setup too twitchy, so you'll find the steering a little more heavy in comparison. 


Enhancements over original:

In a future revision, enhancements will be optional and there will be a menu toggle to enable/disable them.


Requirements:


Download:

Thursday, August 23, 2012

End Sequence Bugs

Here's another bug in the original game; the leftmost two end sequences have a palette issue which causes the male sprite to suddenly change in appearance. In the screenshot below, we're approaching the goal banner.


Then, as if by magic, the colour of the man's top changes to light blue!


But don't worry, on reaching the finish line it's back to dark blue again. 


The game code swaps to an animation playing routine at the point of the colour change. It should be seamless. But it seems as if 2 of the 5 end routines are configured incorrectly. 

Why am I noticing such trivial details? Because the engine is now complete (minus sound and test mode). Expect a test release in the next week! 

In other news, I updated the Philko bootleg page with some new pictures. 

Thursday, August 02, 2012

Light at the end of the tunnel...

It's been nearly two years since I started rewriting OutRun, and three years since I begun decompilation work. This is, and feels like, a long time. According to Yu Suzuki, the original game took four programmers between eight and ten months to complete, so I'll take some reconciliation from the fact this was only a part-time project.

Following the success of the decompilation work, I expected the rewrite to be plain sailing. In fact, the rewrite proved tough - really tough! The size and complexity of the codebase meant I spent an inordinate length of time debugging. Writing your own code from scratch is comparitively easy; your intentions are clear and tracking errors is straight forward. Finding the source of a bug in thousands of lines of ported assembler can be a nightmare.

Debugging ultimately became a case of stepping through the suspected area of code line-by-line and comparing results with the MAME debugger. I invoked crazy tactics along the way; I coded routines to utilise MAME memory dumps for the road layer to quickly determine whether bugs were caused by erroneous code or if data in memory was at fault. This also enabled me to compare the original with my port from an identical starting point.

The other complication was the way in which the original codebase was designed and structured. The style of code varies dependent on who was working on it and by god, they produced a lot of it. The hardware specifications were insane by 1986 standards, and the coding team appear to have approached the project with the view that space and clarity were not a primary concern. There is a huge amount of code duplication and multiple routines that perform similar tasks with minor modifications. Despite evidence of code reuse at Sega, there should be no doubt that this is disposable code, not a reusable game engine. In fairness, the programming team would have been under considerable time pressure.

So what's next? I'm going to port the final chunk of code to handle the game completion sequence. This consists of a big switch table to manually send commands to the sub CPU handling the road layer (similar to the road split, but not quite the same), code to control the Ferrari AI during this period (similar to attract mode, but not quite the same), code to blit the timing information to the screen (similar to other digit blitting routines but not quite the same) and code to handle the animation sequences (similar to the start line intro sequence but not quite the same). Now, you're beginning to understand the OutRun codebase!

Once this is complete, I will release a new build for testing purposes. I was going to release sooner, but I'm so close in terms of porting the entire core engine I'm going to hold back. This build will run at 60fps and feature a selection of other minor improvements not in the original game. From this point onwards, the fun begins and we can start to include extra functionality and enhancements. It will also be a good point to port the code to a variety of platforms. I will be looking for help once I tidy up the codebase a little further.

I hope that explains where the project is, feel free to comment below if you have questions.

UPDATE: Tantalisingly close... bonus points code done, bonus sequence AI done, bonus track control done. Just the animation sequences now.


Monday, July 23, 2012

Odds & Ends

Nothing interesting to report. Since returning from holiday I've converted the high-score entry code and course map screen. When I used to develop games professionally, I didn't enjoy working on these elements and I can't say the feeling has changed much!



Next I'll move onto some of the remaining attract mode code. Once I've tied up some loose ends, I'll release a playable tech demo in order to gather bug reports. And that will be a little more interesting. 

Update:
The core game engine is now ported, apart from the end sequences, test mode and sound code. We're getting close...