TourVision – busting open the BIOS data

This is a followup to my previous article on the TourVision system here:

http://blog.system11.org/?p=1785

I was playing around with the system recently, and I noticed that Dragon Spirit wouldn’t run.  It would boot, but just sat there on the title screen.  Dragon Spirit is one of four V1 carts I recevied which had either a missing adapter or one with an incorrect sticker on so I’d paired it with a spare Daisenpu adapter.  Honestly at the time I didn’t know about V1/V4 carts and I thought the hand written stickers were just an operator convenience, but as I was looking at a couple of adapters I noticed the extra pins were actually a series of 8 jumpers, and the adapters were different.  Dragon Spirit ran fine on a Final Blaster one.

tv_cartadapter

The MAME pinout for these carts is currently wrong, the 4×2 pins on the right side of the connector are actually pins 1 to 8, starting from the right hand underside – meaning those 8 small pads you can see are from right to left, pins 1 to 8.  These are connected to a 74LS244 near each cart slot and are actually just being read as an IO port just like any other input.  They form an 8 bit number which is the game ID, for example Override is:

00110101 – 53

It turns out this really matters.

It’s worth taking a moment to discuss what the V4 TourVision system actually is – as mentioned in the previous article it’s a cart switching pay-for-time based system which uses an actual PC engine to run the games.  Single cart ‘adapter’ systems for JAMMA cabinets with simple pay-for-time mechanics are fairly widespread but the later model TourVision is actually more advanced and almost akin to an automation platform.

tv_assembled

Due to the fact that it really IS just a PC Engine playing the games, the system is almost like an arcade operator with a room containing a PC engine – you give him money and tell him which game you want to play, and he stands there having plugged the game in and starting it for you, then stands there with a stopwatch, taking the controller from you and asking for more money.  That’s exactly what it’s doing.

And this brings us to why the game ID matters.  If you have a cart system capable of playing 200+ different games which were produced by different companies for home consumers, they all have a different way of getting into the game, you can’t really start charging people for time spent in menus, and you don’t really want them playing around with option menus and music tests for half an hour.

The solution is to start the game for them, but to do that you need to know how to start the game.  The TourVision knows how, the BIOS contains tables of data for various functions all of which are looked up using that game ID.

The game ID also gives us an interesting insight into how many games may have existed for the platform.  Currently there are 210 defined data blocks, this actually increased with each BIOS revision, and we now know which versions support up to which games:

2.0 - No ID support, V1 carts only
4.0 - 0 to 91
4.3 - 0 to 175
5.2 - 0 to 191
5.3 - 0 to 197
5.5 - 0 to 203
6.0 - 0 to 209

The majority of games dumped so far will run on bios 5.2, with only a few needing anything higher.  There appear to be minor data corrections in some versions though so it would be worth upgrading any V4 TourVision system to the 6.0 bios.  Just burn it to a 27256 and you’re done.  Given that some games share IDs (I’ve found at least 5 so far) it’s quite possible more than 256 games are supported by the system, that’s just 210 combinations of handling and option data.

There are actually 8 tables of data stored in the BIOS, data is retrieved by multiplying the data block size for the table by the game ID, and adding it to the table offset.  This offset varies in the BIOS revisions, the following information is correct for the 6.0 BIOS.

 

Table 1 – Players

The first table contains number of players supported.  Where 2 players are supported the player 1 and 2 start buttons will be enabled.  The only difference I can see in end results between the two player options is that the timer reduces twice as quickly in dual.  I suppose the rationale was that twice as much player time was being consumed, but it seems a bit unreasonable.

Offset: 0x1184
Block size: 1 byte
Values:
00 - single player
55 - two player, alternating
ff - two player, simultaneous

 

Table 2 – Start button reset

I’m not sure why this option exists and is set for so many games (potentially difficulty handling them), but this table controls whether or not the game will simply reset to the title screen when start is pressed.  It’s worth mentioning here and we’ll come to it again, that the start/run button is actually special cased.  Strangely this option has been set incorrectly in some games, like Formation Soccer which should use the Run button to change the active footballer.

Offset: 0x1284
Block size: 1 byte
Values:
00 - reset when start is pressed
ff - no reset when start is pressed

 

Table 3 – Select (button 3) lockout

This table can optionally block the use of the Select button by ignoring JAMMA button 3 (although the TourVision can still send it through itself).  This is probably again for handling interesting cases where select had undesirable functions.

Offset: 0x1384
Block size: 1 byte
Values:
00 - block use of JAMMA button 3 for Select
ff - allow use of JAMMA button 3 for Select

 

Table 4 – Timer expiry function

This table defines what the TourVision will do to prevent gameplay after the timer grace period has expired.  I found several instances of games which could have had better options here.

Offset: 0x1484
Block size: 1 byte
Values:
00 - use Select button to pause while locking inputs
55 - just lock inputs
ff - use Run button to pause while locking inputs

 

Table 5 – One player startup inputs

This is one of the most interesting tables, and it defines a simple series of codes needed to start the game – it is referenced whenever a game is started in single player mode.  Some things to note here are that player input is completely locked out and the timer will remain paused and flashing until the input string has finished.  This sequence only runs after game resets – these happen when you’ve selected a game to play, or when the start button has been configured to reset the game.  Other than that if you die and go back to the title screen you’ll be free to start manually or enter menus.

The automated input system appears to run on a 1/10th of a second timer interval – the button will appear to be held for that long, tested by tricking the system into moving a player ship around in Aero Blasters.  Delay codes are often used to avoid charging players for intro sequences – for example Daisenpu has several delay elements before turning over control to the player – but because these are not an exact science and measured in 1/10ths of a second, player control of the ship happens slightly later than it would on a normal PC Engine.

Offset: 0x1584
Block size: 32 bytes
Values:
10 = P1 Run
11 = P1 II
12 = P1 I
13 = P1 Select
14 = P1 Up
15 = P1 Right
16 = P1 Down
17 = P1 Left
28 - P2 Run
29 - P2 II
2A - P2 I
2B - P2 Select
2C - P2 Up
2D - P2 Right
2E - P2 Down
2F - P2 Left
76 -> FE - '0xN - 0x76' delay in 10ths of a second
FF = null (releases inputs)

 

Table 6 – Two player startup inputs

This works exactly like table 5, except this is the sequence followed if a 2 player game is started.  This is required for games where 2 player mode is selected from a menu, for example Legend Of Hero Tonma.  The data block size has been increased since the strings are longer.

Offset: 0x3584
Block size: 40 bytes
Values:
(all as per table 5)

 

Table 7 – P1 start inputs

As mentioned in the description of table 2 (start/reset), the start button is a special case which doesn’t directly map to the Run button.  If the game is not configured to reset when start is pressed, instead it will do whatever is defined in this table.  Again it’s an input string table supporting all the same features as tables 5 and 6, and this is what will actually happen when the player presses start and the inputs are unlocked.  The TourVision will temporarily take over and run through this input string.  In the vast majority of cases it’s just a ’10’ which makes start trigger the Run button, or an empty string for the reset games.

Offset: 0x5d84
Block size: 8 bytes
Values:
(all as per table 5)

 

Table 8 – P2 start inputs

Exactly the same as table 7, where games don’t reset this is what the player 2 start button press will do.  Far fewer entries in this table due to the number of single player games.

Offset: 0x6584
Block size: 8 bytes
Values:
(all as per table 5)

 

Got all that? 😉

Let’s look at a small example and make life a bit easier.  This is how all the data appears in the BIOS file in my favourite hex/binary/text editor, “010 Editor”.  It’s not very expensive and worth every penny, I’ve been using it for years and you can get it here:

010 Editor from Sweetscape

tourvis_inputhex

At 0x16c4 (16C4h) you can see the input string definition for Ninja Ryukenden and Liquid Kids, since they share ID 10.  10 x 32 = 320, or 0x140 and 0x1584 + 0x140 =  0x16c4.

I had to reverse engineer all the data tables by using a test/observation approach, this involved a lot of tests and a lot of burning 27256s to verify changes did as expected.  It also meant I spent a lot of time digging through the data to find out what game ‘x’ would do.  I got fed up enough to write a small and very basic Perl script which you can use on any Linux machine with Perl and hexdump installed.  Here’s the zip file with the script, the current latest CSV list of IDs and game names, and the 6.0 revision of the BIOS:

tourvision_decoder

Let’s pick a couple of interesting games to demonstrate – Legend Of Hero Tonma and Afterburner.  Here’s LOHT (game ID 56):

[foo@bar ~]$ ./tvdata.pl 56
56,Legend Of Hero Tonma
Players:
0x11bc 55
Start button reset:
0x12bc ff
Select (button 3) lockout:
0x13bc ff
Timer expiry function:
0x14bc ff
One player startup inputs:
0x1c84 b2 10 8a 10 8a 10 9e ff ff ff ff ff ff ff ff ff
0x1c94 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
Two player startup inputs:
0x3e44 b2 10 8a 16 11 14 10 8a 10 9e ff ff ff ff ff ff
0x3e54 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3e64 ff ff ff ff ff ff ff ff
P1 start inputs:
0x5f44 10 ff ff ff ff ff ff ff
P2 start inputs:
0x6744 28 ff ff ff ff ff ff ff

Here we can see this is a 2 player alternating game, with standard Run button behaviour and Run used to pause when the time runs out.  After the game reset it waits 6 seconds, presses Run, waits 2 seconds, Run, 2 seconds, Run and finally waits 4 seconds before letting the player take over.

However if we start a 2 player game, it waits 6 seconds, presses Run, waits 2 seconds, P1 down, P1 button II, P1 up, Run, 2 seconds, Run, 4 seconds.  These extra inputs 16 11 14 are moving the title screen menu down, selecting 2 player mode and then back up again.

Another interesting example is Afterburner – this game actually has a pause feature on the select button, but select is disabled and the timer expiry mode is set to just lock the inputs out.

46,After Burner
Players:
0x11b2 00
Start button reset:
0x12b2 ff
Select (button 3) lockout:
0x13b2 00
Timer expiry function:
0x14b2 55
One player startup inputs:
0x1b44 8a 10 8a 10 d0 ff ff ff ff ff ff ff ff ff ff ff
0x1b54 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
Two player startup inputs:
0x3cb4 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3cc4 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3cd4 ff ff ff ff ff ff ff ff
P1 start inputs:
0x5ef4 10 ff ff ff ff ff ff ff
P2 start inputs:
0x66f4 ff ff ff ff ff ff ff ff

For fun and to prove some theory I changed the P1 start input to 13, which took away my ability to use the afterburners and made the game pause instead.

Finally let’s have an example in motion.  Gunhed has a secret music test menu available from an input sequence on the title screen.  This is the normal startup input string for Gunhed:

9E 10 94 10 9E 11 FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

Here’s what I changed them to:

9E 17 15 17 15 17 15 17 15 17 15 17 15 17 15 17
15 17 15 17 15 B2 15 15 15 11 FF FF FF FF FF FF

And here’s a TourVision system playing Gunhed music test for your enjoyment:

I want to thank Haze for pointing me in the right direction with this – when I mentioned finding the ID to him, he mentioned there were data blocks in the BIOS which might be accessed based on ID and offset.

And finally, here’s where you can help out.  I need access to more TourVision carts.  I’ll pay good prices for them or if you don’t want to sell, just loaning them to me for dumping would be extremely helpful.  For games which have already been dumped but we don’t have the game ID because the pins weren’t checked, it’s easy and non invasive to check them with any cheap multimeter.  Without this information some games will have to be hand crafted to work instead of using the correct startup data, and I might get something wrong.