Wednesday, March 21, 2012

Vroom Vroom

Some good news - the main Ferrari is implemented. Controls are also complete, which means you can drive through all the levels of the game, albeit without collisions or crash sequences yet. The handling feels right though. Here are some screenshots:

 

The code, as usual, is rather comical. The original assembler manages to combine sound effect triggering logic, score updates and logic to trigger tyre smoke when turning into sharp bends into one almighty routine. I guess coding practices have come on somewhat since 1986. It's kind of funny to be the first person to delve into this code in over 25 years. 

I continue to find bugs in the original codebase, which I'm optionally fixing in my conversion. There will probably be a menu option to toggle my fixes. The latest can be reproduced as follows:
  • Drive into the level a bit.
  • Come to a standstill.
  • Turn the wheel leftmost, then let it centre itself
  • Accelerate and notice the car veers off to the left, even though the wheel is now centered
I can patch this bug on the anniversary edition the next time I do a release, if there's demand. I suspect no-one ever noticed it though. Can it be reproduced easily on hardware?

Update: Yes, it's been reproduced on hardware. Interestingly, it can't be reproduced on the Sega Saturn port.

Saturday, March 10, 2012

Splitting Roads

At last, the core level engine that handles rendering of levels can be deemed complete:
  • Every stage renders correctly and the corresponding level object routines are complete.
  • The code to handle the road split is complete.
  • The code to transition tilemaps between levels is complete.
  • The code to fade the road and sky palettes is complete.
  • You can move through each level and seamlessly load the next one.
Being OutRun, there was an unbelievably large amount of code to handle the level transitions. For example, the road split works via a giant 15-way switch statement that looks at your position and sends commands to the sub CPU to alter the road. 

So now it's onto gameplay. I've been coding the routines to render and control the Ferrari. This higher level code is far easier to work with than the core level engine code. Debugging an error in this area of code now thankfully  involves a few minutes investigation, as opposed to the days some of the core rendering bugs took.  

The code is atrociously messy in places. For example, the logic to handle smoke under the Ferrari's tyres seems to have been inserted pretty much everywhere: in the road splitting code, gear changing code, level object rendering code etc. There is nothing modular about this game! 

To compensate for this, I allow my ported C++ classes to all access each other. They still have private members of course, but there's a global public reference to the class itself. The code could potentially be refactored at a later stage, but for now the focus is getting it ported and working. 


Tuesday, January 31, 2012

Gateway's Broken Arches

Have you noticed that Gateway's arches are randomly broken in the original OutRun? At times arches don't join, sometimes they float in the air and occasionally complete pillars are missing. 

It's not very noticeable at high speed, and the precise nature of the breakage isn't consistent. Overall though, it spoils the illusion of what would otherwise be a cool level. 


For my rewrite, there's a simple solution to this problem; but not for the original game sadly. OutRun's software engine can display 76 scenery sprites at any one time, which are initialized dynamically as the level progresses. Further sprites are reserved for traffic and other essential objects. 

Each Gateway arch comprises 4 sprites (two pillars and two joining sections). So we can display 19 complete arches at any one time. Therefore, on complex stretches of road where no free slots can be allocated, some of the pillar components are simply skipped.

Thankfully, we don't have memory or speed restrictions on a modern PC and can allocate additional slots to dynamically spawn sprites. In fact, it's as easy as changing a single number. And here's a screenshot to (somewhat) prove it. 


The illusion when moving through the level is greatly improved, and when I eventually increase the frame rate beyond the original 30fps, this level will be awesome! 

Sunday, January 29, 2012

OutRun C++ Engine Tech Demo

Finally, after years of hard labour, here's a technical demo of the OutRun C++ port. The demo showcases recent work porting the core level rendering engine. The benefit of rewriting the engine, is that it will facilitate modifications and enhancements to the original game that Yu Suzuki only dreamed of.

Now, let's get arty and check out some stills from the demo. I've implemented the ability to change the horizon y coordinate, so we can experience viewpoints never seen in the original game. How about a bird's eye view of the start line?


We can also straddle left and right, so it's possible to find further interesting camera angles. Although this one reveals that our surf-boarding friend isn't actually in the water! Messing with the original engine can highlight its limitations of course. This demo allows you to scroll further left and right than the original engine, which can cause glitches. 


It's fun to be able to browse the scenery in detail: 


Here's a beach-side postcard scene for you:


And finally a view down the final straight of Coconut Beach before the road fork. Alas, the road fork code hasn't been ported yet, so this is the road to nowhere at the moment. 


The keys for the demo are:
  • Space: Toggle automatic movement through level
  • Cursor Up: Advance slowly
  • Cursor Left/Right: Move camera left/right
  • A/Z: Adjust horizon
  • Escape: Quit
Requirements:
Other Notes:
  • Having control over the rendering engine surfaces glitches and limitations present in the original code. Using unpatched roms, the sprite zoom bug mentioned in this post is evident. You can use patched roms to eliminate this. 
  • There is a bug where a random shadow pops into view dependent on the camera x coordinate. This is present in MAME as well, but is hard to reproduce when you're actually racing through the level. I need to get this verified on hardware to help track down a solution and determine whether it's a video emulation issue or a bug in the original codebase. 
Download here: outrun_tech_demo1.zip

Let me know what you think by leaving a comment below.

Monday, January 16, 2012

OutRun Sprite Zoom Bug

OutRun uses a lookup table to set the horizontal and vertical zoom values of sprites based on their z co-ordinate.

Unfortunately, one of the vertical zoom entries in this table is incorrect. If you drive as slowly as possibly by gently tapping the accelerator, there is a single position where sprites snap to an erroneous vertical zoom value. This causes the sprite to clip incorrectly and jolt to a different offset.

You can see an example of this behaviour in the animation below. Note the third palm tree from the left suddenly snaps and zooms to an incorrect position.


Unbelievably, this applies to all sprites in the game. Although it's only noticeable when driving at low speeds. However, once spotted it's hard to ignore.

I've updated OutRun: Enhanced Edition with a patch for the bug.

In other news, expect an early tech demo of my C++ port very shortly. It was in coding the port that I spotted this bug.

Update: The Sega Saturn port does not suffer from this issue. Looking through the Saturn binary, I can't find the lookup table used by the arcade version, so this area was probably rewritten for hardware purposes.

The Xbox port (part of OutRun 2) does have the bug.

Wednesday, November 23, 2011

OutRun Conversion Update

I haven't written about the OutRun conversion to C++ for some time. That's because I put it on hold whilst I focused on the anniversary edition, amongst other projects. Having a break was sensible and necessary, as it's such intense work.

Compared with other 68k conversions I've worked on professionally, this is much tougher, due to the sheer complexity and in some cases poor quality of the original code. Even after a first draft, a huge amount of refactoring will be needed so that the codebase can be extended.


Things are slowly coming together. Don't hold your breath whilst waiting for this; I'm doing it at a very steady pace. I've taken a screenshot of my desktop, which shows that much of the level data is now being parsed. Underlying this, many of the sprite rendering routines are ported. I've included a MAME screenshot for comparison so you can see what's currently missing. 

Sunday, November 13, 2011

OutRun Original Japanese Version

Japanese only static sit-down cabinet design with roof

Interior shot from a more beat-up cabinet. Note the unique bezel design

Following my comparison of Rev A and Rev B of the OutRun ROMs, I've turned my attention to the original Japanese release of the ROMs. There are a number of differences and bug fixes which are detailed below.

1. There is no backup RAM. Therefore, the code doesn't contain the routines to handle backup RAM found in later revisions. For example, the code to calculate backup RAM checksums.

2. The mini upright and standard upright cabinets are not supported. The revision only includes motor code for the deluxe sitdown. As a result, Dip switch bank B functions differently. Dip switch #1 toggles the motor hardware. Dip switch #2 toggles advertise sound. MAME currently emulates this dip switch incorrectly, assuming it to be the same as later revisions.

3. The default scores are different. For example, in the original version YU has 1,000,000 points. In later revisions this became 5,000,000.

4. The code to initialise default scores is called from a different routine.

5. The music selection screen is set to a 15 second timeout, rather than 30. SELECT MUSIC BY STEERING text is omitted.

6. The code to set the y position of the backdrop tilemap is different (e.g. the position of the cloud backdrop on coconut beach). In the original version, the tilemap immediately snaps to the horizon y coordinate. In later revisions, the tilemap will smoothly scroll to a new position.

7. Traffic logic changes. The code that determines when to flag other cars on the road as being near the player's Ferrari is different. This will presumably cause different behaviour when approaching packs of traffic. I'm unsure why the code has been changed or what situation the coders were trying to mitigate.

8. The code to set the speed of other cars when bunched in traffic has been changed. In later revisions, the speed is capped but in the original version a higher speed can be obtained by the traffic. This is noticeable at the start of the game. In later revisions the truck on the right hand side initially speeds off, but then the other cars catch up and bunch together around it. In the original, the truck accelerates away and the other cars never catch it. Without observing the presumably rare bug the coders were attempting to fix, it's tough to say why this change was made.

9. Later versions of the game contain an optimization to not add sprites that are off screen to the display list. This version does not contain this optimization.

10. As most players know, the stages are in a different order and there are layout differences in places in the original version. As such, certain routines differ to compensate for this when setting up stage palettes and sprite effects when driving offroad.

11. In later revisions, a safety counter was added to bonus mode in the main game's switch. (Bonus mode is the section of the game that increments your bonus score after completing stage 5.) This ensures that bonus mode exits eventually and presumably fixes a rare hang that can take place in this version.

12. This version does not attempt to terminate the crash animation sequence when entering bonus mode. Video of this bug on hardware here.

13. There are minor changes to ensure the y placement of some sprite objects (including those on the intro sequence and some in completion screens) more accurately reflect the y position of the blitted road layer.