Page 1 of 1

The end of the frame

PostPosted: Mon Aug 14, 2023 7:26 am
by Ian
The real3d chip is not like a normal 3d card. Normal 3d cards literally just eat polygons usually in order. Real3d has a scene graph view of the entire frame. In order to start rendering the database must be complete.

But something that puzzled me for a long time is what marks the database as complete? For a long time people assumed (mame etc) that when 0x88 is written to this marks the end of the frame. But this can not be true. Some games write it multiple times per frame. Many games will write 0x88 after updating the culling ram, but then update the polygon ram without calling 0x88.

This is emergency call ambulance

Code: Select all
write reg 60 80000000 33
write reg 64 80000000 33
write reg 68 80000000 33
write reg 6c 80000000 33
write reg 10 2 33
write reg 10 4 33
write reg 10 8 33
WriteHighCullingRAM 62
flush 62
WritePolygonRAM 62
write reg c 3 62
swap buffers 100


So it updates the high culling ram, calls 0x88, then writes to poly ram.

It looks like the last thing that is written in every frame is a write to the tilegen register C. I'm pretty sure this register write says start rendering the 3d.

This is virtua fighter 3

Code: Select all
WritePolygonRAM 47
WriteHighCullingRAM 73
flush 73
write reg c 3 73
swap buffers 100


The last thing it writes is reg C. This is true for everything except the loading stages between games. Then this happens.

Code: Select all
write reg 40 0 33
write reg c 3 35
WriteLowCullingRAM 35
flush 35


It still writes C to the tilegen register. But at that point 0x88 has never been written so, so I assume it doesn't render anything. If it does try and render stuff. The attached image is what's going on in the background. There is a good chance this will crash the real3d board. It would crash us too but we put some hacks in the renderer to stop it happening.

What does this mean for emulation?
Well not a huge amount, because 99% of the time the scene database is updated every single frame. It's only in certain places like vf3 where this might be an issue.

But we could check if 0x88 had been written to when the tilegen register C is written it. If it has render that frame. That would stop all the garbage background problems and the hacks we need in the renderer.

It's not immediately clear what 0x88 actually does, but my best guess is it marks like a specific transfer as complete, that's why it can be called many times per frame. Without it, I don't think it'll try and draw a frame.

It would be interesting to know if there are any games this logic doesn't work for.

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 12:02 pm
by gm_matthew
I imagine that what happens is that when a DMA transfer takes place, Mercury stops processing viewpoints/culling nodes so it can receive the data and write it into the ping pong buffer or update buffer, and writing to 0x88000000 basically tells Mercury that it can go back to processing culling nodes again. If we don’t write to 0x88000000, then Mercury just sits there waiting for more data. At least, that’s my theory.

For what it’s worth, I reckon that it we were to not make any DMA transfers at all but still write to 0xF118000C, the video board would still render a new frame using the existing contents of the ping pong buffer (assuming that it is not cleared when starting a new frame).

Oddly enough, I searched the Real3D API library file and couldn’t find any evidence that it ever writes to 0x88000000; perhaps it is only required for internal DMA transfers.

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 4:16 pm
by Ian
I dug through some emails from bart from sometime ago

For sure, we know that writing 0x88000000 signals the end of data for a given frame.
Is there any way the following hypothesis works:

1. 0x88000000 <-- written to start rendering to current back buffer
2. 0xF118000C = 0x3 <-- written to flip the back buffer


A bit of bad news:

I ran my ping pong test with flushing removed (only the tilegen register written). No flip occurs and the game gets stuck at the first of my tests waiting forever. The board LED indicates test #1 is being run. Nothing on screen appears.


What about the other way around? Ie no write to the tilegen?


Tried that last time. For sure did not work. It seems both are required. My guess is one triggers rendering and one triggers some sort of flip and that ping pong occurs as the result of rendering happening after a flip.

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 4:40 pm
by Bart
I was going to say that I recall testing this. Couldn't figure out what they did individually but it did seem that both were required.

Matthew: Check out pro_io_structs.hh:141:

Code: Select all
#define PRO_RET_DAT_MAGIC   0xbeefbabe


Not sure where this is used but it looks like the sort of nonsense that the games write to 0x88000000. Does the SDK use it anywhere? It's also quite possible that the actual write to this register is performed in firmware. I believe that the SDK code just shuttles data along via SCSI and that some of the commands might be intercepted by the firmware (which is equivalent to a Model 3 game running on the board). Disassembling the firmware and getting it up and running in Supermodel might make things clear. I was hoping to find time this year to do this to add proper Pro-1000 support to Supermodel.

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 4:43 pm
by Ian
#beefbabe im pretty sure is what the real3d returns in the stat packet
I think it's just there to like validate the packet


Code: Select all
int __cdecl ls_ret_dat(int a1)
{
  int result; // eax@5

  if ( a1 >= 0 && a1 < num_of_pro_boxes_S410 && (1 << a1) & pro_lun_on_off_mask_S412 )
  {
    if ( *(_DWORD *)(pro_ret_data_S407[a1] + 64) == 0xBABEBEEF )
      result = pro_ret_data_S407[a1];
    else
      result = 0;
  }
  else
  {
    result = 0;
  }
  return result;
}

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 4:55 pm
by Bart
Ah. I wonder if the firmware constructs these packets and sends them back explicitly? Not on my PC with hex editor right now but could search the firmware binary for 0xBEEFBABE. Or 0xBEEF and 0xBABE in case they are encoded piece-wise in a load instruction pair.

There is a substantial amount of PowerPC logic in the firmware, so it likely isn't just sitting around idly.

Re: The end of the frame

PostPosted: Mon Aug 14, 2023 5:03 pm
by Ian
check the headers

typedef struct
{
Scsi_Head scsi_head;
Stat_Pckt stat_pckt; <---- model3 just returns this
unsigned long magic; <--- beefbabe
Sync_Info sync_info[LINE_RATES];
Misc_Info misc_info;
} Pro_Ret_Dat ;