Thursday, May 16, 2013

LayOut: Preview Mode

Layout

Those of you who watched the previous LayOut video will have noticed one significant problem; whilst editing the track technically worked, the visualization of your actions leaved something to be desired.

As planned, I've moved on to editing sprite placement next. And in doing so, I incorporated a real-time preview of the changes you are making. If you create a new curve, hill or even change the placement of an object, this is updated in real-time. You can also change the camera angle by dragging in the preview window with the mouse.


In this screenshot, I've imported the Devil's Canyon track. The 2D path is shown in the lower panel, and the actual rendering in the top panel. The panels can be linked so as you scroll through a level, the placement remains in sync. The 2D window is in scenery editing mode. The large dots indicate the start of a 'segment' of scenery items. Scenery in OutRun is segmented like this, so that patterns can be reused multiple times to save on storage space. Each time you use a segment, its length is variable. Segments wrap if the length exceeds the number of items in the segment.


Switching to the scenery tab, you are immediately linked to the segment selected in the 2D view. There is a lot of complexity here, and I haven't even finished work on this part of the editor. The list on the left represents the segment and shows the list of items used in this section. Here you can see items including, rocks, road debris and so forth. The timing at which this list is rendered is affected by the pattern frequency. The engine can render two sprites per road position. Although it's possible to create the illusion of more. For example, on the Gateway stage the top beam is actually positioned behind the pillars. Or you can adjust the y values in some cases. 

Clicking an item in this list invokes object specific properties on the right hand side. In this case, you can edit the x and y position, select whether to horizontally flip the sprite, whether the object has a shadow and the custom draw routine used. Changing these properties only affects a single entry of the item in the segment. All of this is of course based on how the original OutRun engine works. 

Where we deviate from how the original engine works is with the new preview window. The preview window is cool because you can just say 'show me the track at position 704'. The original engine doesn't work like this; it must render the entire level from start to finish. If you were to hack the original game so that each level started at position 704, you would see something completely incorrect. Similarly, there is no easy way to reverse backwards through a track and this is now possible. The downside to this is that it adds complexity and possibly bugs where the rendering deviates. The upside in terms of previewing all changes in real-time is immense though. You can position the camera on the track, create a curve and watch the environment change in front of your eyes as you turn a dial. 

There's still a lot of work to do; it's a relatively complex project, which I guess is why no one has attempted it before. Additionally, I haven't done a lot of GUI based application development before, so I'm learning as I go.

CannonBall

Neil from the OutRun and Space Harrier Replicas project has kindly made this rather stunning logo for CannonBall. 


For now, it's only featured on the CannonBall page, but I will incorporate it into the build itself in future. I do plan to get back to CannonBall and add hardware rendering and other new features when LayOut is released.

I also moved the standard CannonBall download page to a new cleaner page on github. The old blog page was full of dated comments and somewhat messy. 

Tuesday, April 23, 2013

Sprite Outtakes

You might think that after years of pulling OutRun apart I would have exhausted the hidden extras. Not quite yet! Here are a few unused sprites that are in the game.

Firstly, here's a motorbike that didn't make the final cut. There is a preliminary data structure to hook the bike up in the game code, and that data structure is similar to the existing traffic entries so we can assume this was an early attempt to include other forms of traffic. However, the final higher level data structure is missing, which would include the palette information. So I've just used a random palette here.


Here's an extra frame from the end sequence with the genie. I guess there was originally concern that it wouldn't be clear who the genie was, so the extra frame on the left was made.


Finally here's another end sequence idea that was dropped. The existing sequence sees the guy kissed by the girl awarding the trophy, before flexing his muscles. It looks like the original plan was to also have him fall over. You can see the extra frames below:


You can use my quick and dirty sprite viewer to browse sprite data in other Sega titles. 

Monday, April 22, 2013

LayOut - WIP Video

Here's a quick video showing the latest progress with LayOut. You will want to view this full-screen to see the detail and turn the quality level up. As a bonus, there's some dodgy narration from myself, so turn the sound on. 

Current Features:
  • Edit Road path, width and height.
  • Import existing OutRun levels for editing and refinement. 
  • Export to Cannonball. Levels are fully playable.

I'm quite pleased with the ability to import existing levels. The import function generates the entire track path using nothing but the Curve Info value and direction that was discussed in a previous blogpost. So the large amount of data specifying the x,y of each road segment is completely redundant.

As you can see from the video, creating a playable level literally takes minutes. However, for the final release it will be important to quickly edit/preview sections of each level. I will be making additional changes to Cannonball to support that.

I must stress this is very much a work in progress; it's ugly, but it works!

Friday, April 12, 2013

Height Map Hell

One of the more complex areas of road data is the way in which setting the road height is handled. Each OutRun stage has 1948 positions that correspond to the path the level takes. We previously saw how a series of tables reference these positions to control aspects like the road width. This same table is also used to configure the height.

One of the entries in the table denotes whether the entry relates to a width change or a height change. Height changes are more complex than width changes. Each height change points to an entry in a separate table of 225 height maps.

So for example, on Coconut Beach at road position 1 the table references height map 211. In the diagram below, taken from my recent work on LayOut, you can see the data contained in this segment and a crude visualisation of the height map on the right.


The interesting thing is exactly how these maps correspond to a position in the level. We know when they are applied and therefore the start position of each height section, but how long do they last for? If the above map starts at road position 1, where does it end? 

The answer is relatively complex, as the height data you can see in the above table varies in length depending on the step adjust and multiplier values. Changing these values can either compress or expand the duration of the same height map. The road data isn't fixed to a particular road position increment. In fact in this example, changes in height are parsed through different multipliers to the straight sections and the end result would look something like this, presuming a start of road position 0. 


So here you can see the length of each data section in this single map and the road position it corresponds to at the bottom. I won't delve into the algorithms that map this data here, as it will probably confuse matters. I haven't yet visualized this in the editor itself. But we're starting to understand how these values correspond to a particular road position. 

Think of the actual values (0, 576 and -576) as the angle or steepness of the height section. And then the length pretty much specifies how high or how long that section of slope lasts for. 

To make things more complex there are four distinct types of height map in OutRun. Each type is rendered with a completely separate customized routine executed by the sub CPU that handles the road layer. Type 1 is the most common and shown above. 

Type 2 is more simple and used to create very long hills. It pretty much sets an angle and specifies a length or delay value. This is used at the point of the sharp chicane in Coconut Beach.


Now with Type 2, actually mapping this accurately to the road position gets interesting. Due to some quirks in the game code, the length of these sections actually depend on how fast you're driving. OK, you're not really going to notice this at normal speeds. But if you drive slowly, you can exploit a bug that pretty much elongates these sections way beyond where they should be. 


Here we are elongating the climb at the end of the Chicane. I'm driving slowly, and admittedly I've frozen the game timer. If we drive slow enough the hill can pretty much last right through to the end of the level:


OK, this is slightly silly stuff. But the point is that there is not a direct mapping between level position and the height map data. It's rather loose. So creating an editor where we can definitely say "the hill definitely ends here" or "this peak is exactly in line with this sign" simply isn't possible. The game code doesn't work in that way and there will always be ambiguity in some cases.  

Type 3 is a combination of Type 1 and Type 2. It's essentially some normal height data with a delayed section in the middle. The length of the section is handled differently again but is hard coded this time. Quite why, I don't really know. Typically a height entry will correspond to 8 road positions. This section isn't commonly used. 

Type 4 performs horizon y position changes. This can be seen at the start of Gateway, when the horizons level is raised. The only data attached to these entries is the new horizon position and the speed at which the change should happen.

It should be pointed out that the original assembler for this area of the game is horrendous and mildy terrifying.Therefore nailing all this detail down took a while, and unfortunately came at a time when things have been pretty busy for me. So apologies for the lack of exciting updates lately. 

In addition to this, I needed to expand my QT knowledge significantly to visualize this effectively in the LayOut editor. I implemented the ability to import the existing OutRun height map into the editor and display it in a logical tree format. 

There is still more work to be done, including basics like editing and creating new height map entries, although for a casual user, the existing maps should suffice. Once this is done, it will be time to move onto the fun stuff - adding level objects!

On Cannonball, a couple of people have kindly submitted changes that I will look into including in the future. The first is some control improvements from James and there is also some initial OpenGL rendering work from Legooolas, which will enable faster screen stretching/resizing than the current software approach. I'm holding off on Cannonball work for now and the next release is likely to be in conjunction with LayOut. 

Monday, March 18, 2013

More Data Hacking...

Although LayOut will handle the obvious visual mechanics of creating an OutRun track, things don't and can't stop there. In fact, OutRun's engine utilises an additional lookup table of pre-calculated values, required by the car physics and attract mode AI code.

This table, stored in the master CPU code, corresponds to the road path data, stored in the slave CPU code. Here is how three typical segments of road might be represented:


This means that at position 161, there's a left bend with property '121', until we reach the straight at position 277. This straight lasts until we reach the right curve at road position 359. This data is stored for every single curve and straight in every track in the game. 

Note, that this table does not define the path of the track at all from a visual point of view; this is purely used by the game's logic. If we get this stuff wrong, the car behaviour won't feel right when cornering. The value is used to adjust both the x position of the Ferrari as it enters a bend and to adjust your speed when you move through the corner. Without this, it would feel as if you drifted around corners too quickly. 

Understanding this table is all very well, but the problem is how to reverse engineer a curve back into this magical 'curve info' value required by the engine. Without knowing this formula, the editor project would be doomed!

I spent a long time experimenting with different ideas, largely aided by Excel and a bit of trial and error. In the end the solution was this:

For each curve in the game, calculate the average of the distances between the points on that curve. Therefore, you can use the standard distance formula for every pair of points:

Once you have the average distance between the points on a curve, you can do:

Curve Info = (1 / AverageDistance) * 4096

Where 4096 represents a 'one' in fixed point format. And finally we can spit out a curve info value in the format required by the game engine. 

Hopefully this gives you an idea of some of the less visually interesting work that I'm doing. 

Saturday, March 16, 2013

Road Width Editing

Road width editing is complete and working. Technically what you edit is the degree of separation between the two roads. The hardware overlaps the two roads, creating the illusion of one wide road. 

Therefore, it's nice and easy to split and rejoin the road into two lanes. 


Not the most exciting thing to look at, at the moment. But you see where this is going. Next on the list is height editing I reckon... 

Saturday, March 09, 2013

Road Path Implementation Complete

Following those exciting Excel spreadsheets and a little ranting, I'm pleased to say road path editing is implemented and working.

Here's an initial screenshot showing the progress of LayOut, the OutRun level editor.


This is just the first small stage; changing the path of the road. It's really easy to layout a complete track; you can produce something usable in under a minute. You define a series of control points and LayOut produces the curves and straights for you. Internally, the editor uses its own format and then exports to the format required by OutRun. This makes it easier to manipulate the track than dealing with the raw data.

Cannonball will have a debug mode to render the output in conjunction with Layout, so you can use both tools together. For now, a lot of this is somewhat hard coded, but the concept is proven.


For now, the road width and objects are still read from the original level data. This will obviously change as we add these options to LayOut. Here you can see we've inserted a curve at the start of Coconut Beach.

Well done to Shawn LeBlanc for naming the editor. I was originally going to call it 'Last Wave', but this sounds more like a sound editing tool and if I ever get round to creating sound editing tools it might cause confusion.

The next step will be to add the ability to define the road width, which encompasses single and dual road support.