Gliden64: Toukon road 1 & 2, last legion UX: HLE implementation (extended turbo3D)?

Created on 26 Jul 2015  路  27Comments  路  Source: gonetz/GLideN64

Revesering customs microcode are of course a very difficult task however it would be wonderful to have one day of full HLE plugin supporting all games.

For Toukon road 1 & 2, last legion UX, i ran a ram analysis with Nemu debugger of this game and I detected something interesting.

Apparently the name of the microcode of those games is T3DUX (vers 0.83 for Toukon Road, 0.85 for Toukon Road 2 and Last Legion UX)

t3d

I guess T3D stands for Turbo3D and UX to show that this microcode was improved (as for F3DEX).

As the missing graphics are mostly 3D characters (as for Dark Rift) in those games,t it makes that the developer may have use such a microcode. Also the quality of the graphics seems likely to be the unprecised turbo3D microcode.

However I cannot understand why Rice debug plugin (and certainly others) is not able to "detect" the string in the memory when such a microcode is used. Is there something to dig in as a bug in this regard?

Most helpful comment

All 27 comments

Agreed!!

Glad to see there are others who want these games HLE'd :smile: . I do believe Last Legion uses Turbo3d, at least partially anyway. I did see some of the same code I saw in Turbo3d examples.

However I cannot understand why Rice debug plugin (and certainly others) is not able to "detect" the string in the memory when such a microcode is used. Is there something to dig in as a bug in this regard?

Good find! It's because glN64, GlideN64, and Rice Video assume that the string starts with "RSP". All you have to do is also check for "T3D" and it will be found. I can't seem to find the text for WDC unfortunately.

Last Legion UX works with Rice video, only the characters are missing
But GLideN64 in HLE shows nothing

There is 2 microcodes used for this game, the normal F3DEX for the background grahics and this T3DUX microcode. Rice has also implemented a hack to support 2D in games with unknown microcode.

GlideN64 can handle the background graphics easily as other plugins do.

After checking the ucode, it is clearly a modified turbo3d microcode that those games use.

Can you take a look at Goldeneye's microcode and compare to Last Legion? I thought some of the code looked very familiar tbh. It made me wonder why this microcode hasn't been HLE'd yet.

I gotta figure out how to HLE the RDP since that's the main bottleneck, usually.

There is 2 ucodes for this game: f3dex v1 and t3dux.

In your dump, f3dex v1 can be found in "Last Legion Gfx 02".

F3DEX is nearly the same than GE007.

GlideN64 can render the background of the game, it is not issue at all.

in your dump T3DUX can be found in "Last Legion Gfx 06"

It is similar but with some quite major differences with "Dark Rift Gfx 06".

it is mainly used for the characters.

It is where HLE fails.

My small idea of mine: this turbo3d microcode was extended to support the same format than F3DEX when it comes to manage the vertex. T3D = Turbo3D and UX = Unified eXtension. It is true that the manual says that the the turbo3d microcode uses the same format as the vertex format in gbi.h so if gbi.h changes in F3DEX, the turbo3d microcode had to change accordinlgy.

Many part of the code is the same but things related to the vertex in the code was changed. Sometimes it looks like double,as if it was treating two triangles in the same time as gSP2Triangles.

Is it just me, or does that blocks.turbo demo you sent not work in GLideN64 HLE?

Yes but nothing to do with T3DUX microcode. It is working with Glide64. Fifo issue that can be easily fixed if I do remember.

I couldn't get it working in Glide64. I figured maybe fixing this could help with implementing T3DUX.

I think it would be a good start to at least get the game booting, and display the backgrounds. Maybe I'll just use Rice though, for studying that game.

So I think more or less I understand what is going on.

Small explanation:

Here an example of a turbo display list in T3DUX:

image

As you can see there is two more 32 bits words than the standard turbo3d.

The global state works in the same way. The treatment of the RDP command list nearly the same, however the last F5 command processed in the list is send to the RDP but also saved in a place in memory, the second 32 bits word being ANDed by 0xFF0FFFFF. It will be used back when the textures are processed with the generation of the triangles.

The object state is a slightly different:

image

The simple matrix is downloaded from the object state memory address + 0x0018 (if the flag is 0x00).

The colors and textures coordinates state are downloaded from the memory with this 5th 32 bits words of the display list ( in our example 0x802FB148). Such a list has a number of bytes as follow: ("number as per the object state" shift left by 2) -1.

The treatment of the RDP command list nearly the same, however the last F5 command processed in the list is send to the RDP but also saved in a place in memory, the second word being ANDed by 0xFF0FFFFF. It will be used back when the textures are processed with the generation of the triangles (Note: it will be the very last F5 amongst the global state and the object state that will be used, so usually the one from the object state except if there is no F5 in its object state RDP command list or if there is no RDP command list address).

The vertex in this ucode is very very simple: it does have only x, y and z information (2 32 bit words only!).

The colors and textures coordinates are processed when running the "tri, colors and textures coordinates pointer list."

here what you do have in this list as an example (the list contains many of those):

image

the first line ( 0x740) from this list are, as for turbo3d, are the pointers to 3 vertex of the triangles (so here v0 = 00, v1 = 01, v2 = 02, flag = 00) as you can find in the the vertex state but also the pointer to the 3 colors of those triangles in the textures coordinates and colors state. If you have vertex 00, you pick up the very first color in textures coordinates and colors state.

the second line ( 0x744) provides 3 pointers to the textures coordinates for each vertex. You need to shift left them by 2 to get the right place in memory of the textures coordinates and colors state. So for instance you have 4a, you shift left by 2, you get 296 in decimal (0x128 in hex), this is the number of bytes you need to calculate to reach the right place in memory.

The last byte is a bit less clear for the time being. It is done only when the last byte is different than zero. Currently what I understand is that this byte is shifted left by 20 (0x14) and then the results is ORed to the second 32 bits word of F5 command that we saved earlier. So for instance if it would be 0x80 (being a negative byte), then it would be 0xF8. We would have then for instance:

F5400800 F8000000

Is F8 a valid parameter for F5 at this place? F8 should be in padding no? However with the ORed, you may have F5000000 F8100000. Here i think it would mean tile 1.

The result is sent to the RDP.

Note that usually this last byte in this second line is not nil at the very beginning of the list, the rest being nil. It would mean that the same tile is used for the entire list.

Voila :)

PS: the ucode is written in a poor manner, it is quite a mess.

I think that my explanation should be sufficient to have a HLE implemention of this ucode.

wiki created for for posterity :)

https://github.com/gonetz/GLideN64/wiki/T3DUX-ucode

PS: the ucode is written in a poor manner, it is quite a mess.

Out of curiosity, why do you say it's written in a poor manner?

actually the modifications are written with poor quality, the original code of turb3d being all right.

Why?

For instance the code does not implement necessary checks to avoid sending to RDP meaningless information for instance.

For instance a part of the code sends to RDP 0x08000000 00000000 each time a triangle does not have a texture. It is a waste of resource.

@olivieryuyu Thanks for the wiki page!
It would be great to create such pages for other custom ucodes decoded by you and other devs - for posterity.
For example: F3DTEXA, F3DSETA, F3DBETA

I could do one for F3DTEXA indeed :)

Great work. Just beware that PJ64 is likely set to override HLE for some of those games, so you may have to make some changes.

Use RSP plugin from older PJ64 version to be sure that you run HLE.

Toukon Road 1+2, and Last Legion UX, all work with latest PJ64 in HLE. Just select Use HLE in plugin selection for those games.

@gonetz

just a short question about your code: why not detecting the microcode by its string, meaning "T3DUX"?

Ucode name not started from "RSP". A bit more additional code needed to parse that case.

I see :)

No bug found, let's close the ticket then!

It took almost to years to solve. A hard one.

Impressive work btw!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andrea-petrucci-1975 picture andrea-petrucci-1975  路  8Comments

maximemoring picture maximemoring  路  17Comments

gonetz picture gonetz  路  10Comments

olivieryuyu picture olivieryuyu  路  20Comments

Dorzalty picture Dorzalty  路  20Comments