Monday, February 25, 2013

Track Format Solved!

Following on from yesterday's post, I resolved OutRun's track format. This means we can press ahead with creating the level editor.

Firstly, I plotted the raw track data points as an x,y scatter graph in Excel. As you can see, the x,y co-ordinates that comprise the track data form a perfect circle. This is a pretty big clue.


The track is stored as a series of 2D co-ordinates on the perimeter of a circle (radius 4096). So to create the first left turn in Coconut Beach, you can start at 0, 4096 and iterate anti-clockwise from this point. For example, the start of the left turn is represented as follows. 


To sharpen the turn, you essentially step through the circle perimeter faster. To create a turn in the opposite direction, you iterate through the circle in the opposite direction. To create a straight you can simply stop wherever you are in the circle and continually output the current coordinate. 

I'm curious to know whether this technique for path generation is a common one, and whether it has a name. 

Sunday, February 24, 2013

Maths Assistance Required

The next stage of the Cannonball project is to build track editing tools. This will take the form of an independent track editor (a cross platform GUI based desktop program), that works in conjunction with the Cannonball engine (to provide the rendering). The editor will output level data for both Cannonball and the original arcade machine. This work is likely to take a good few months, but should be pretty exciting.

In terms of the level data, much of its format is fully understood: sprite/object placement, changing the road width and height, road colour setup and even changing the road texture.

Where I need assistance is with the road path or direction. Whilst I can interpret Outrun's road data into an x position or (obviously) a screen co-ordinate for Cannonball, I do not fully understand how to reverse the Maths used. I need the formula that will enable a user to plot a road path in a level editor, and then convert back to the original format stored in the program code.

Unfortunately, my Maths skills are limited but I'm hopeful there's someone out there who can look at this and outline how we can produce the path format stored in rom. Maybe it's trivial. Maybe I should have taken Maths class past the age of 16. ;)

To simplify the problem, I've created an Excel spreadsheet. The spreadsheet uses as input the raw level data stored in the program code (Columns A & B). It runs it through a series of calculations (tab 1), similar to the program code, and outputs the path of the road as a line graph (tab 2).

Excel: More fun when rendering OutRun tracks. 

Below you can see we've output the path for Stage 1, Coconut Beach. It's rough because the spreadsheet makes some simplifications with rendering, due to its top down 2D approach rather than the pseudo-3D approach of the original game. 

Coconut Beach Track Path. Note the chicane at the end. 

As mentioned, the level data does not contain width, height, objects or anything else. Nor should we care about that. It's simply the road path.

The input columns are A & B. I'm pretty sure A relates to the road direction, and B somehow relates to the length of the direction. But I might be completely wrong.

On the third tab of the spreadsheet, is the C++ code that handles this data, which you can also refer to if you're a coder.

You can download the Excel spreadsheet here. I've also uploaded it to Google Docs here, but the formatting isn't as good. So work with the original if you can.

Update: This problem has now been solved.

Saturday, February 23, 2013

Cannonball 0.181 - Force Feedback

Cannonball now supports Force Feedback on Windows. Here's what's new:

  • Force Feedback Support (Windows Only). More details below. 
  • Controllers: Added support for steering dead zone.
  • Controllers: Added rudimentary support for split axis controllers.
  • Controllers: Able to navigate menus by turning wheel.
  • Controllers: Ability to select analog steering with digital pedals.
  • Controllers: No longer display H/L on screen when gear mode is set to cabinet. 
  • Bug: Fixed Prototype level not clearing.
  • Bug: Fixed score on completing game. The final score was incorrect.
  • Bug: Fixed bonus counter on completing game. (v0.181)
  • Bug: Reversed gear for cabinet play.
  • Build System: Added some changes supplied by user sairuk. 
Firstly, some background; the original OutRun arcade machines provide feedback in three ways:
  • The mini-upright offers the most basic feedback. During a crash, or when driving off-road, the end of the steering column is struck repeatedly. This causes the wheel to vibrate outwards in a crude manner.
  • The deluxe upright is somewhat more sophisticated. The steering assembly is mounted on a moveable layer. This layer, and therefore the steering column, is shifted left and right at varying speeds by a motor.
  • The deluxe sitdown is different yet again. The steering wheel is not connected to a motor mechanism at all. Instead, the entire unit rolls left and right based on your cornering speed, driving off-road and crashing.
On all machines, the wheel is centred by a pair of strong springs.
Cannonball ports the deluxe sitdown motor code. Instead of connecting it to a giant moving seat, the forces are channelled directly to the wheel. This results in both appropriate cornering forces and vibrations on impact. The codebase was not intended to be used in this way, so the results may not be perfect. And the benefits of force feedback will vary depending on your hardware and configuration options. Still, it works quite nicely for me, so please report how you get on. 
Setting up force feedback will require you to follow the instructions in the Cannonball manual here. You should also delete old config.xml files you may have, as the configuration has changed somewhat. 
For the technically minded, you can see the ported motor code here. And the DirectX interface code is here.  The reason for using DirectX is SDL does not yet support force feedback out of the box. I did try a patched version of SDL, but it proved to be more hassle than it was worth. So I simply ensured the DirectX code is omitted on non-Windows compiles. 
Next up, I'll probably resume work on level editing tools. I expect this part of the project to take a while, so there may not be as many regular updates. Many of the easy and quick wins are now complete.

Update: Fixed a bug reported in the bonus counter.

Friday, February 22, 2013

Gear Gacha Technique

This is a great demonstration of the OutRun gear-gacha (gear rattling) technique on real hardware, as opposed to emulation.

This technique exploits a feature (or bug) in the gear changing code, allowing the player to maintain speeds of 294kph whilst driving off-road. This technique was well known in Japan, following detailed coverage in popular gaming magazine, Gamest.


There will also be a new version of Cannonball released this weekend. Look out for it!

Tuesday, February 19, 2013

Space Harrier Easter Egg (Dev Credits)

Whilst you're patiently waiting for me to finish force feedback support in Cannonball (it's going well), here's a Space Harrier Easter Egg for you to try.

It's similar to the OutRun egg, in that it provides a Yu Suzuki development credit, along with the development date. Interestingly November 1985 was around the date the AM2 team started OutRun, which probably explains why the team used the Space Harrier code as a framework to work from.


Like most AM2 titles, the egg is somewhat tricky to activate. You need to enter the code during the death / respawn sequence; therefore after the character collides and flips upwards or is flashing.

The code is:
  • Press button 3 (typically mapped to space on MAME) six times. 
  • Press the start button eight times. 
  • Then finally, press button 3 again. You should see the message.
You can enter the code over multiple iterations of this death sequence. So you can start after the first time you die, and complete it the second time you die. However, any error in input resets the code, so go carefully.