SEGA Model 1 TGP Observations
I've been looking at /machine/model1.c a bit lately. Mostly with Virtua Racing (VR). Turns out if you log all of the unknown TGP functions in the game, you get some pretty regular patterns. The following is what I've gathered by staring at log files for a few hours.
It's possible the MAMEdevs who have done so much amazing work on this hardware already know everything I'm writing here, and it's possible they don't. My experiments may advance the state of the emulation or they may not. Only time will tell.
OBSERVATION 1 : F71
F71 pops up in VR once a race is started. It pops four parameters out of the FIFO queue. Currently MAME believes all 4 of these parameters to be floats. This, I am nearly positive, is not correct, as I believe the first parameter is an UINT32, as is (probably) the third.
F71 appears to be some sort of velocity and heading function, as the four parameters are directly related to pressing the gas and turning the wheel in the game.
The first parameter (the UINT32) ranges from (-32k - 32k), and denotes the angle the car is facing around the up-axis - 0 is pointing straight up in global space (0 degrees) and -32k/32k is pointing straight down (-180/180 degrees). The functions tcos and tsin can be used with this value to recover a 2 dimensional vector of the car's heading.
The second parameter (the float), is the velocity the car believes it is traveling. This varies in direct proportion with the km/h reading in the lower-left corner of the in-game. 0.0 is no velocity, and ~2.8 is ~325 km/h.
The third and fourth parameters are unknown, as they seem to almost always be 0. I'm pretty sure they're similar to the first two parameters, and are probably just rotation around a horizontal axis and velocity in that direction. These values do actually show something when the car 'drops' off its pit blocks at the beginning of the Big Forest race, so it seems like that theory may be sound.
The function stuffs 4 numbers back into the FIFO queue. These four numbers may be a direction vector scaled by velocity or something of the sort (I would say, X, Y, Z, W - where W is scale), but right now any value you put into them does nothing. Probably because the car knows it's not on the road - more on this in the F54 section.
OBSERVATION 2 : Call-order and parameters of other unknowns
For now, I will describe what happens once the action has started in the game. Later I will describe some finer details of these functions, and other observations I've gleaned from the demo-mode and what happens when a race is 'initialized'.
Every frame of the race has the following function call order :
(1x) - F71
(16x) - f54,f42,f48
(sometimes there is are a few f24's mixed in here as well)
(1x) - f64
(15x) - f65
(1x) - f49
(1-2x) - f14
First, the velocity function (as described above - F71) is called. Then a series of 16 sets of f54, f42, and f48 are called. The key thing to note here is that there are 16 cars on the track at all times. So I believe every time we see a set of 16 function calls, we're referring to each individual car...
Before I explain much else, let me further justify my belief that each of these sixteen values represent a car. F54 has at least 2 floating-point parameters, as does F42, as does F64/F65. For each frame, these two floating point parameters are exactly the same values as their counterparts. What I mean by this is the following :
If F54 is called with 110.0 and 220.0 as parameters 3 and 4
the next F42 will have 110.0 and 220.0 as parameters 2 and 3
and the matching F64/65 (called after all of the f54,f42,f48 combos) will have 110.0 and 220.0 as its parameters 1 and 2
If you plot these parameters on a per-frame basis, you get the following two images : COMPARISON and EXPLANATION.
So on that webpage, the last thing I said was : "but it should be apparent that the parameters for f54, f42, and f64/65 are the locations of all of the cars on a 2-dimensional plane (height = 0) in relation to global 0,0!"
Each of these functions therefore have something to do with the locations of the game's cars in global space. Furthermore, I believe these functions are always called in the same order, and the first set always refers to the player's car. I will explain this observation and numerous others in greater detail below.
F54
F54 seems to do a lot of the work here. A few things stand out immediately.
Parameter 1 seems to be a height value - or maybe a ground-level offset. I've noticed when the game switches to a new map that has a different ground-level, this value is changed in F54(). This is reflected in F54()'s current write to RAM based on the value of this first parameter. Controlling this value is a little strange, and I wasn't able to find out anything by doing so, so I can't comment much more on this part.
Parameter 2 seems to be a value relating to the race track. Every car which is on the track has a valid non-zero hex value here. The first car of each frame (the first time f54 is called), however, has a value of 0x00 here. This correlation between being off the track and having a value of 0x00 is made stronger by observing that every time a car drives off the track (such as in the images here), its' second f54 parameter changes to 0x00 as well. Maybe this is an index into a collision-object hash? Maybe it's an index as to what type of surface the vehicle is on? Either way, it is 0x00 when the car is off the track and something else when the car is on...
Parameter 3 and 4 are the 2d values of the car on a plane. Sometimes, however, f54 is called more than once in a row. At the beginning of each frame (the first set of f54's) it's called like this :
TGP f54 30.100000 (41f0cccd), 0x0, 0.000000, 0.000000 (fed580)
TGP f54 0.000000 (00000000), 0x0, -0.906207, 1.796883 (fed580)
TGP f54 0.000000 (00000000), 0x0, 0.893782, 1.803096 (fed580)
TGP f54 0.000000 (00000000), 0x0, -0.893782, -1.803096 (fed580)
TGP f54 0.000000 (00000000), 0x0, 0.906207, -1.796883 (fed580)
I believe these f54 calls refer to the car you are driving (your car is stuck at 0,0 - which is reflected in the first f54 call). I also believe the next 4 f54 calls reference the wheels of the car - or the bounding-box of the car - in a relative coordinate system to the first f54 call. The only time there is a series of 5 f54's is the first time it is called per-frame. I think the car you are driving, therefore, has more information stored about it than the rest of the cars.
There is a good chance there is a collision-point hierarchy in those numbers - the first one could be called with global coordinates, and the next four with local coordinates (this would explain the 0's in the next four calls' parameter 1). But since the car is at 0,0 in global coordinates, it is unknown whether or not the next four calls' parameters 3 and 4 are relative to the coordinate system of the first call or not, so this hierarchical theory is not provable.
F54 doesn't push any info back into the FIFO queue. I'm sure the previous 'guess' that it affects RAM directly is a very good one (for a number of reasons - one being I'm sure the people who worked on this before me are a lot better at this stuff :) ). Maybe it 'registers' where each car is on a per-frame basis? Or possibly there's a collision portion of the TGP with its own RAM that logs car locations and checks them against each other internally? Kind of like a collision stack with heirarchical storage. Maybe some of these other functions 'pop' this stack after f54 pushes it... Far-fetched, i know, but it's always fun to guess.
F42
I have only seen the value of f42's parameter 1 to be 0. Parameters 2 and 3 are identical to parameters 3 and 4 of the 'parent' f54 that was just called (in the above example, the one where there were 5 f54's called in a row, it would have 0,0 since the 'parent' f54, or the first one that was called, has 0,0 as its params 3 and 4).
It pushes 6 values into the FIFO queue. I have not tried applying miscellaneous numbers here to see what happens, so I really don't know much about f42.
F48
f48 is always, without fail, called with a 0. No idea why. It does push one number back onto the queue, but I haven't tried playing with putting random stuff in here either.
F64/f65
There is always 1 f64 and 15 f65's. This totals 16 - but why is one 64 and the rest 65? I'd say they're both very similar functions. And I'd say the 64 deals with the driver's car (you), and the 65's deal with the opponents' cars. One may surmise that the 64 deals with the fact that there are 5 f54 calls for the first car (as described above), but there is one part of the game (the introduction), where even though the first car only has 1 f54, it still uses a f64 at the beginning of this section.
f64's two first parameters match the first f54's parameters exactly (0,0). f64's third parameter, however, always seems to be 4.5f. I thought this might be the height of the car, but according to the f54's that were called earlier (the ones that set up the bounding box of the driver's car), the car's length is about 4.0 long, so this doesn't seem to be right - the car isn't taller than it is long. No idea what the third parameter means...
the f65's that are called all have 2 parameters identically matching the f54's from above.
Strangely, f64 pushes nothing into the queue, and f65 pushes one 32-bit value. Maybe the functions aren't as closely related as i would think, but the way they are called in a group (with the same PC) is really suspicious.
f49
f49 is always the last unknown function to be called per-frame. It is a 12-parameter function that takes the values from the extra 4 f54's called at the beginning of the frame (the ones i believe are related to the 'bounding box' of the player-car), puts them next to eachother, and sticks some values very similar to f54's first parameter alongside them. Maybe this function takes the bounding-box setup by the first series of f54's and compares it to the neighboring cars whose values were set up in the groups of functions following the initial call. Maybe...
f14
Most of the time the following is true :
Parameter 1 = parameter 3 of f54.
Parameter 2 = parameter 1 of f54.
Parameter 3 = parameter 4 of f54.
I haven't looked into f14 much at all, but it looks like someone else believes it effects the TGP's current matrix. Could be a push or a pop with collision thrown in. It seems like VR needs another push matrix in its drawing loop, because things like the track on the right side of the screen rotate instead of the car rotating on it...
f24
F24 is called just before a f54 with one parameter each time - and this parameter always seems to be within a limited range. Sometimes this range is from 3 to 17, and sometimes the range is from 1046 to 1092. It is never called before the first f54 (the one I believe relates to the player's car), and when the race starts, it's called for each subsequent car with an increasing number...
It is called occasionally throughout the race for particular cars that are moving or 'go astray'. For example, when those two blue cars drive off the road above, it is called repeatedly with the values 11 and 12 every frame the car is off the road (every time parameter 2 of f54 is 0x00, it is called just before said f54).
f24 pushes 12 values to the FIFO queue, and even though it seems like it may be a transformation matrix, I don't think it is. The values affect the behaviour of the cars directly (putting mame_rand() for a return value gives you different car paths each race). Maybe it takes information about the other cars, calculates some distances, and the AI reacts to what happens?
Miscellaneous tidbits with demo mode versus gameplay mode, etc.
When the demo is running, the first f54 isn't called with 0,0 and there aren't 4 accompanying f54's alongside it. It appears as though the car is treated just like any of the other cars on the track - it has a value that changes/animates in global space just like the rest of them.
At the beginning of the demo mode as well as at the beginning of each race, an large set of f54's is called on the very first frame. This large set of f54's contains numerous values for parameter 1 (unlike the rest of the time where parameter 1 stays the same), never has 0x00 for parameter 2, and has 2d coordinates all over the place. Graphing these 2d coordinates when in demo mode looks like the following : link - which looks a lot like the race track's corners! When the demo mode first runs, it runs on the Bay Bridge stage - it turns out if you play the bay bridge stage, an identical set of calls appears in the beginning of the race. The calls for the other two tracks are quite different. This set of f54's may the engine registering the corners as collision objects in the beginning of the race...
Oh, and last but not least, if you would like to look at a sample log file I've been playing around with, you can download a zipped copy of one here : output.zip. It is a log which starts out in demo mode, quickly switches to the course-select screen (I inserted a coin), selects the Bay Bridge map, and 'plays' the map until the two cars drive toward the center and collide with your car.