Frame Timing

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome.
Forum rules
Keep it classy!

  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!

Frame Timing

Postby Bart » Sun May 29, 2016 11:21 pm

Investigations related to frame set up and timing will be posted to this thread.

Obviously the register at 0x88000000 has something to do with triggering the rendering process. Here is the sequence of DMA transfers for two consecutive frames in dayto2pe. This is in the first tunnel of the medium-level track. In the second frame, the first of a series of texture uploads via VROM are performed (to prepare the haunted house scene). Note that in both cases, 0x88000000 is written twice and apart from the VROM texture upload, the two frames are indistinguishable:

Code: Select all
Frame 1:

Real3D DMA copy (PC=00002838, LR=000030A4): 001016A0 -> 980010C8, 4
Real3D DMA copy (PC=00002838, LR=000030A4): 001016A4 -> 980010CC, 4
Real3D DMA copy (PC=00002838, LR=000030A4): 001016A8 -> 980010D0, 4
Real3D DMA copy (PC=00002A3C, LR=000030A4): 001A88D4 -> 9802CC2C, 88D8 (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C2358 -> 98038738, 2614 (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C7BA0 -> 9803AD4C, 2F0 (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 0010502C -> 980017F8, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105030 -> 980017D4, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105034 -> 980017D8, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105028 -> 980017D0, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8180 -> 9803B03C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C81DC -> 9803B098, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8238 -> 9803B0F4, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8294 -> 9803B150, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C82F0 -> 9803B1AC, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C834C -> 9803B208, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C83A8 -> 9803B264, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8404 -> 9803B2C0, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8460 -> 9803B31C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C84BC -> 9803B378, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8518 -> 9803B3D4, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8574 -> 9803B430, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C85D0 -> 9803B48C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C862C -> 9803B4E8, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8688 -> 9803B544, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C86E4 -> 9803B5A0, 5C (byte reversed)
Real3D DMA copy (PC=00002A3C, LR=000030A4): 00660010 -> 8E000000, E80
Real3D DMA copy (PC=00002D00, LR=00001A60): 00661D10 -> 8E001D00, 1000
Real3D DMA copy (PC=00002D00, LR=00001A60): 0066AA10 -> 8E00AA00, 120
Real3D DMA copy (PC=00002D00, LR=00001A60): 0066B040 -> 8E00B030, 1260
Real3D DMA copy (PC=00002D00, LR=00001A60): 00662D10 -> 8E002D00, F78
Real3D DMA copy (PC=00002D00, LR=00001A60): 006736B0 -> 8E0136A0, 13C
Real3D DMA copy (PC=00002D00, LR=00001A60): 006742B0 -> 8E0142A0, 320
Real3D DMA copy (PC=00002838, LR=000030A4): 0073EF88 -> 88000000, 4 (byte reversed)
Real3D DMA copy (PC=00002838, LR=000030A4): 0073EF88 -> 88000000, 4 (byte reversed)

Frame 2:

Real3D DMA copy (PC=00002838, LR=000030A4): 001016A0 -> 980010C8, 4
Real3D DMA copy (PC=00002838, LR=000030A4): 001016A4 -> 980010CC, 4
Real3D DMA copy (PC=00002838, LR=000030A4): 001016A8 -> 980010D0, 4
Real3D DMA copy (PC=00002838, LR=000030A4): 0055F2D0 -> 90000000, C (byte reversed)
Real3D VROM texture upload
Real3D DMA copy (PC=00002A3C, LR=000030A4): 001C2358 -> 98038738, 2614 (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C7BA0 -> 9803AD4C, 2F0 (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 0010502C -> 980017F8, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105030 -> 980017D4, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105034 -> 980017D8, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 00105028 -> 980017D0, 4
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8180 -> 9803B03C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C81DC -> 9803B098, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8238 -> 9803B0F4, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8294 -> 9803B150, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C82F0 -> 9803B1AC, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C834C -> 9803B208, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C83A8 -> 9803B264, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8404 -> 9803B2C0, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8460 -> 9803B31C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C84BC -> 9803B378, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8518 -> 9803B3D4, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8574 -> 9803B430, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C85D0 -> 9803B48C, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C862C -> 9803B4E8, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C8688 -> 9803B544, 5C (byte reversed)
Real3D DMA copy (PC=00002D00, LR=00001A60): 001C86E4 -> 9803B5A0, 5C (byte reversed)
Real3D DMA copy (PC=00002A3C, LR=000030A4): 00660010 -> 8E000000, E80
Real3D DMA copy (PC=00002D00, LR=00001A60): 00661D10 -> 8E001D00, 1000
Real3D DMA copy (PC=00002D00, LR=00001A60): 0066AA10 -> 8E00AA00, 120
Real3D DMA copy (PC=00002D00, LR=00001A60): 0066B040 -> 8E00B030, 1260
Real3D DMA copy (PC=00002D00, LR=00001A60): 00662D10 -> 8E002D00, F78
Real3D DMA copy (PC=00002D00, LR=00001A60): 006736B0 -> 8E0136A0, 13C
Real3D DMA copy (PC=00002D00, LR=00001A60): 006742B0 -> 8E0142A0, 320
Real3D DMA copy (PC=00002838, LR=000030A4): 0073EF88 -> 88000000, 4 (byte reversed)
Real3D DMA copy (PC=00002838, LR=000030A4): 0073EF88 -> 88000000, 4 (byte reversed)


But why is it written twice? Hmm... Need to investigate.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Frame Timing

Postby Ian » Mon May 30, 2016 3:16 am

This is decompiled from lib

Code: Select all
signed int PRO_DisplayDatabase()
{
  signed int v0; // esi@1
  signed int v1; // edi@1
  int v2; // ebx@1
  int v3; // ecx@1
  int v4; // eax@3
  int v5; // eax@5
  PRO_Viewport *v6; // ecx@7
  PRO_Dynamic_Update *v7; // ecx@9
  int v8; // eax@12
  int v9; // edi@14
  int v10; // ebx@14
  __int32 v11; // ST00_4@15
  PRO_Vertex *v12; // eax@15

  v0 = 1;
  v1 = 1;
  v2 = *(_DWORD *)(*((_DWORD *)g_API_Data + 3) + 2316);
  v3 = *((_DWORD *)g_API_Data + 4859);
  if ( v3 )
  {
    v1 = *(_DWORD *)(v3 + 8);
    PRO_Dynamic_Update::DoUpdate((PRO_Dynamic_Update *)v3);
  }
  v4 = PRO_API_Data::FormatUserTextures(g_API_Data);
  if ( v4 != 1 )
    v0 = v4;
  v5 = PRO_API_Data::FormatUserMicroTextures(g_API_Data);
  if ( v5 != 1 )
    v0 = v5;
  PRO_SetScroll(0);
  PRO_ProcessAnimations();
  v6 = (PRO_Viewport *)*((_DWORD *)g_API_Data + 47);
  if ( v6 )
    PRO_Viewport::UpdateSiblingPointers(v6);
  PRO_Directional_Light_List::ProcessDirectionalLightList(*((PRO_Directional_Light_List **)g_API_Data + 323));
  PRO_Range_Node_List::ProcessRangeLodNodeList(*((PRO_Range_Node_List **)g_API_Data + 324));
  PRO_Memory_Manager::WriteDataToHardware(*((_DWORD *)g_API_Data + 2));
  PRO_Memory_Manager::WriteDataToHardware(*((_DWORD *)g_API_Data + 1));
  PRO_PingPong_Manager::WriteAllDataToHardware(*(_DWORD *)g_API_Data);
  v7 = (PRO_Dynamic_Update *)*((_DWORD *)g_API_Data + 4859);
  if ( v7 )
    PRO_Dynamic_Update::DoIO(v7);
  PRO_Flush();
  if ( *(_DWORD *)(*((_DWORD *)g_API_Data + 3) + 2316) - v2 > 1 )
  {
    v0 = 4;
    v8 = *((_DWORD *)g_API_Data + 4859);
    if ( v8 )
      ++*(_DWORD *)(v8 + 4 * v1 + 1048);
  }
  v9 = 0;
  v10 = *(_DWORD *)(*((_DWORD *)g_API_Data + 61) + 4);
  if ( v10 > 0 )
  {
    do
    {
      v11 = v9++;
      v12 = (PRO_Vertex *)PRO_Generic_List::GetEntryByIndex(*((PRO_Generic_List **)g_API_Data + 61), v11);
      PRO_Vertex::ResetChangeAttributes(v12);
    }
    while ( v10 > v9 );
  }
  *(_DWORD *)(*((_DWORD *)g_API_Data + 61) + 4) = 0;
  ++*((_DWORD *)g_API_Data + 329);
  ++*((_DWORD *)g_API_Data + 330);
  return v0;
}


Shorter maybe more useful example ..

Code: Select all
int PRO_ReloadLogo()
{
  int result; // eax@1
  int v1; // [sp+0h] [bp-4h]@1

  result = (int)g_API_Data;
  v1 = 0;
  if ( !(*((_BYTE *)g_API_Data + 2016) & 2) )
  {
    PRO_IO(&v1, 1, 536870917, -1, 0);
    result = PRO_Flush();
  }
  return result;
}


Code: Select all
int __fastcall PRO_Flush(int a1, int a2)
{
  int v2; // eax@1
  int result; // eax@2
  signed int i; // esi@9
  int v5; // ebx@10
  int v6; // eax@12
  int v7; // edi@14
  int v8; // eax@15

  v2 = *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1368);
  if ( v2 == 2 )
  {
    result = _g_API_Data__3PAVPRO_API_Data__A;
    if ( !(*(_BYTE *)(_g_API_Data__3PAVPRO_API_Data__A + 2016) & 2) )
      result = do_scsi_io();
  }
  else
  {
    if ( *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1952) < v2 )
      printf(___C__0FE_DNKA__5Too_5much_5data_5is_5being_5sent_5to_5_);
    g_current_update_word_count_S3571 = 12;
    g_number_of_available_scsi_words_S3572 = *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1952) - 4;
    *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1368) = 2;
    *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1312) = 0;
    if ( !(*(_BYTE *)(_g_API_Data__3PAVPRO_API_Data__A + 2016) & 2) )
      do_scsi_io();
    result = _g_API_Data__3PAVPRO_API_Data__A;
    if ( !(*(_BYTE *)(_g_API_Data__3PAVPRO_API_Data__A + 2016) & 2) )
    {
      for ( i = -1; *(_DWORD *)(_g_API_Data__3PAVPRO_API_Data__A + 1352) > i; ++i )
      {
        v5 = _GetDevice_PRO_API_Data__QAEPAVPRO_Device__J_Z(_g_API_Data__3PAVPRO_API_Data__A, a2);
        if ( v5 )
        {
          if ( i == -1 )
            v6 = ls_hw_stats(0);
          else
            v6 = ls_hw_stats(i);
          v7 = v6;
          *(_DWORD *)(v5 + 2312) = *(_DWORD *)v6 & 0x7FFFFF;
          *(_DWORD *)(v5 + 2316) = *(_DWORD *)(v6 + 36);
          *(_DWORD *)(v5 + 2296) = *(_DWORD *)(v6 + 20);
          *(_DWORD *)(v5 + 2300) = *(_DWORD *)(v6 + 24);
          *(_DWORD *)(v5 + 2304) = *(_DWORD *)(v6 + 28);
          a2 = *(_DWORD *)(v6 + 32);
          *(_DWORD *)(v5 + 2308) = a2;
          if ( !i )
          {
            v8 = _GetDevice_PRO_API_Data__QAEPAVPRO_Device__J_Z(_g_API_Data__3PAVPRO_API_Data__A, a2);
            if ( v8 )
            {
              *(_DWORD *)(v8 + 2312) = *(_DWORD *)v7 & 0x7FFFFF;
              *(_DWORD *)(v8 + 2316) = *(_DWORD *)(v7 + 36);
              *(_DWORD *)(v8 + 2296) = *(_DWORD *)(v7 + 20);
              *(_DWORD *)(v8 + 2300) = *(_DWORD *)(v7 + 24);
              a2 = *(_DWORD *)(v7 + 28);
              *(_DWORD *)(v8 + 2304) = a2;
              *(_DWORD *)(v8 + 2308) = *(_DWORD *)(v7 + 32);
            }
          }
        }
      }
      result = CsimClearLists();
    }
  }
  return result;
}
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Frame Timing

Postby Ian » Tue Jun 07, 2016 1:41 am

I had a brief thought about frame timing
Bart, have you tested the version of scud with the video? The video runs at like half the proper frame rate, and there is visible tearing between the top and bottom images.

Might this be useful for debugging? It's basically only doing texture updates + swapbuffers. There is almost no geometry being drawn, other than maybe 2 textured quads? The swap buffers should be called after the 2nd texture is updated, but it seems to be getting called after the first.

I just did a quick debug, it really is just 2 quads being drawn.
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Frame Timing

Postby Bart » Tue Jun 07, 2016 6:44 am

That's actually a very good idea. I completely forgot about this. And I had assumed it was done with tiles, not textured quads. It's really using textures to display this? I guess there is some sense to it: they probably store the textures in VROM.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Frame Timing

Postby Ian » Tue Jun 07, 2016 12:54 pm

I had a proper look
It's actually a single textured quad, with 1 texture.
The tearing happens within the same texture .. which is kinda weird :p

Image

I think it's switching between texture 3/4 every other frame.

Here is a closeup of the single texture (the top half is presumably padding).

Image
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Frame Timing

Postby Jiterdomer » Tue Jun 07, 2016 1:13 pm

Wait, are these "FMV"s in Scud Race Plus rendered in 2D using frame-by-frame methods like a GIF image, or is it in 3D?
Feel the heartbeat of my machine through this tight seat. I feel every motion of my machine
Image
User avatar
Jiterdomer
 
Posts: 627
Joined: Mon Sep 26, 2011 6:37 pm
Location: Los Angeles, California

Re: Frame Timing

Postby Bart » Tue Jun 07, 2016 1:15 pm

Is it performing multiple texture uploads per frame? That could explain tearing.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Frame Timing

Postby Bart » Tue Jun 07, 2016 1:15 pm

Jiterdomer wrote:Wait, are these "FMV"s in Scud Race Plus rendered in 2D using frame-by-frame methods like a GIF image, or is it in 3D?


It's a 2D image.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Re: Frame Timing

Postby Ian » Tue Jun 07, 2016 1:53 pm

Bart wrote:Is it performing multiple texture uploads per frame? That could explain tearing.


It's just performing 1 update per frame. Actually less than one update, since the video is maybe 24~ fps but the frame rate is 60
Ian
 
Posts: 2044
Joined: Tue Feb 23, 2016 9:23 am

Re: Frame Timing

Postby Bart » Tue Jun 07, 2016 2:57 pm

I'll have to look at it. What I mean is, how many textures are being uploaded? Even if one texture is being specified for the quad, it might be uploaded as more than one single block. That would explain intra-polygon tearing.
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada

Next

Return to The Dark Room

Who is online

Users browsing this forum: No registered users and 1 guest

cron