User:Haxar/NV2A

From xboxdevwiki
< User:Haxar
Revision as of 09:48, 4 June 2017 by Haxar (talk | contribs) (Created page with "I wanted to know how NV2A registers were being accessed from Xbox executables. So, I loaded IDA with Turok with the applied Xbox Flirt Signatures v.2 and took references from...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

I wanted to know how NV2A registers were being accessed from Xbox executables. So, I loaded IDA with Turok with the applied Xbox Flirt Signatures v.2 and took references from pbkit to help me out with this.

D3D::CMiniport::MapRegisters is where it all begins. This is just a handful of subroutines from the D3D::CMiniport namespace.

Every single access is annotated from pbkit. It has been very useful.

// turok
// using pbkit/outer.h
// gpu == 0xfd000000
signed int __thiscall D3D::CMiniport::MapRegisters(void *this)
{
  *(_DWORD *)this = 0xFD000000u;                // VIDEO_BASE
  vFD001804 |= 4u;                              // NV_PBUS_PCI_NV_1_BUS_MASTER_ENABLED
  vFD600140 = 0;                                // PCRTC_INTR_EN_VBLANK_DISABLED
  vFD009140 = 0;                                // NV_PTIMER_INTR_EN_0_ALARM_DISABLED
  return 1;
}
signed int __thiscall D3D::CMiniport::LoadEngines(void *this)
{
  void *v1; // edi@1
  int gpu; // esi@1
  int v3; // eax@1
  int v4; // ecx@1

  v1 = this;
  gpu = *(_DWORD *)this;
  v3 = *(_DWORD *)this + 6220;
  v4 = *(_DWORD *)v3;
  *(_DWORD *)v3 &= 0xFFFFFCFFu;
  *(_DWORD *)v3 = v4;
  *(_DWORD *)(gpu + 0x200) = 0xFFFFFFFFu;       // NV_PMC_ENABLE_ALL_ENABLE
  *(_DWORD *)(gpu + 0x140) = *((_DWORD *)v1 + 45);// NV_PMC_INTR_EN_0
  D3D::CMiniport::HalDacLoad(v1);               // PCRTC_INTR_EN_VBLANK_ENABLED
  *(_DWORD *)(gpu + 0x9400) = 0;                // NV_PTIMER_TIME_0
  *(_DWORD *)(gpu + 0x9410) = 0;                // NV_PTIMER_TIME_1
  *(_DWORD *)(gpu + 0x400720) = 0;              // NV_PGRAPH_FIFO_ACCESS_DISABLE
  D3D::CMiniport::HalGrControlLoad(v1);
  *(_DWORD *)(gpu + 0x400100) = 0xFFFFFFFFu;    // NV_PGRAPH_INTR_ALL_ENABLE
  *(_DWORD *)(gpu + 0x400140) = 0xFFFFFFFFu;    // NV_PGRAPH_INTR_EN_ALL_ENABLE
  D3D::CMiniport::HalFifoControlLoad(v1);
  *(_DWORD *)(gpu + 0x2100) = 0xFFFFFFFFu;      // NV_PFIFO_INTR_0_ALL_RESET
  *(_DWORD *)(gpu + 0x2140) = *((_DWORD *)v1 + 71);// NV_PFIFO_INTR_EN_0
  *((_DWORD *)v1 + 528) = 0xFFFFFFFFu;
  *((_DWORD *)v1 + 529) = 0xFFFFFFFFu;
  *((_DWORD *)v1 + 520) = 0;
  *((_DWORD *)v1 + 521) = 0;
  return 1;
}
int __thiscall D3D::CMiniport::HalDacLoad(void *this)
{
  int gpu; // eax@1

  gpu = *(_DWORD *)this;
  *(_DWORD *)(*(_DWORD *)this + 6291712) = 1;
  *(_DWORD *)(gpu + 0x600140) = 1;              // PCRTC_INTR_EN_VBLANK_ENABLED
  return gpu;
}
int __thiscall D3D::CMiniport::HalGrControlLoad(int this)
{
  int v1; // edi@1
  int gpu; // esi@1
  int v3; // eax@1
  signed int v4; // edx@1
  int v5; // eax@1
  int v6; // ebp@2
  int v7; // ebp@2
  int v8; // ebp@2
  int v9; // eax@3
  int v10; // edx@4
  int v11; // ebp@4
  char v12; // zf@4
  int v13; // eax@5
  int v14; // eax@5
  int v15; // eax@5
  signed int v17; // [sp+14h] [bp-4h]@3

  v1 = this;
  gpu = *(_DWORD *)this;
  v3 = *(_DWORD *)this + 512;
  *(_DWORD *)v3 &= 0xFFFFEFFFu;
  *(_DWORD *)v3 |= 0x1000u;
  *(_DWORD *)(this + 2028) = 0;
  *(_DWORD *)(this + 2044) = 0;                 // NV_PGRAPH_DEBUG_4
  *(_DWORD *)(this + 2056) = 0;                 // NV_PGRAPH_UNKNOWN_400B84
  *(_DWORD *)(this + 2068) = 0;                 // NV_PGRAPH_UNKNOWN_400B88
  *(_DWORD *)(this + 2032) = 0x118700u;         // NV_PGRAPH_DEBUG_1
  *(_DWORD *)(this + 2036) = 0x28C3FFu;         // NV_PGRAPH_DEBUG_7
  *(_DWORD *)(this + 2040) = 0xF3DE0479u;       // NV_PGRAPH_DEBUG_3
  *(_DWORD *)(this + 2048) = 4;                 // NV_PGRAPH_DEBUG_5
  *(_DWORD *)(this + 2052) = 0x45EAD10Eu;       // NV_PGRAPH_UNKNOWN_400B80
  *(_DWORD *)(this + 2060) = 0x78u;             // NV_PGRAPH_UNKNOWN_400098
  *(_DWORD *)(this + 2064) = 0x40u;             // NV_PGRAPH_UNKNOWN_40009C
  *(_DWORD *)(gpu + 0x400080) = 0;              // NV_PGRAPH_DEBUG_0_NO_RESET
  *(_DWORD *)(gpu + 0x400084) = *(_DWORD *)(this + 2032);// NV_PGRAPH_DEBUG_1
  *(_DWORD *)(gpu + 0x400880) = *(_DWORD *)(this + 2036);// NV_PGRAPH_DEBUG_7
  *(_DWORD *)(gpu + 0x40008C) = *(_DWORD *)(this + 2040);// NV_PGRAPH_DEBUG_3
  *(_DWORD *)(gpu + 0x400090) = *(_DWORD *)(this + 2044);// NV_PGRAPH_DEBUG_4
  *(_DWORD *)(gpu + 0x400094) = *(_DWORD *)(this + 2048);// NV_PGRAPH_DEBUG_5
  *(_DWORD *)(gpu + 0x400B80) = *(_DWORD *)(this + 2052);// NV_PGRAPH_UNKNOWN_400B80
  *(_DWORD *)(gpu + 0x400B84) = *(_DWORD *)(this + 2056);// NV_PGRAPH_UNKNOWN_400B84
  *(_DWORD *)(gpu + 0x400098) = *(_DWORD *)(this + 2060);// NV_PGRAPH_UNKNOWN_400098
  *(_DWORD *)(gpu + 0x40009C) = *(_DWORD *)(this + 2064);// NV_PGRAPH_UNKNOWN_40009C
  *(_DWORD *)(gpu + 0x400B88) = *(_DWORD *)(this + 2068);// NV_PGRAPH_UNKNOWN_400B88
  *(_DWORD *)(gpu + 0x400780) = *(_DWORD *)(this + 320) & 0xFFFF;// NV_PGRAPH_CHANNEL_CTX_TABLE
  D3D::CMiniport::HalGrIdle((void *)this);
  v4 = 80;
  v5 = gpu + 0x400904;                          // NV_PGRAPH_TLIMIT_XBOX
  do
  {
    v6 = *(_DWORD *)(v5 - 0x3006C0);            // NV_PFB_TLIMIT
    *(_DWORD *)v5 = v6;                         // NV_PGRAPH_TLIMIT_XBOX
    *(_DWORD *)(gpu + 0x400750) = (v4 - 32) & 0x1FFC | 0xEA0000;// NV_PGRAPH_RDI_INDEX
    *(_DWORD *)(gpu + 0x400754) = v6;           // NV_PGRAPH_RDI_DATA
    v7 = *(_DWORD *)(v5 - 0x3006BC);            // NV_PFB_TSIZE
    *(_DWORD *)(v5 + 4) = v7;                   // NV_PGRAPH_TSIZE_XBOX
    *(_DWORD *)(gpu + 0x400750) = v4 & 0x1FFC | 0xEA0000;// NV_PGRAPH_RDI_INDEX
    *(_DWORD *)(gpu + 0x400754) = v7;           // NV_PGRAPH_RDI_DATA
    v8 = *(_DWORD *)(v5 - 0x3006C4);            // NV_PFB_TILE
    *(_DWORD *)(v5 - 4) = v8;                   // NV_PGRAPH_TILE_XBOX
    *(_DWORD *)(gpu + 0x400750) = (v4 - 64) & 0x1FFC | 0xEA0000;// NV_PGRAPH_RDI_INDEX
    v4 += 4;
    v5 += 0x10u;
    *(_DWORD *)(gpu + 0x400754) = v8;           // NV_PGRAPH_RDI_DATA
  }
  while ( v4 < 112 );
  v9 = gpu + 0x400980;                          // NV_PGRAPH_ZCOMP_XBOX
  v17 = 8;
  do
  {
    v10 = *(_DWORD *)(v9 - 0x300680);           // NV_PFB_ZCOMP
    *(_DWORD *)v9 = v10;                        // NV_PGRAPH_ZCOMP_XBOX
    v11 = (v9 + 0xFFBFF710 - gpu) & 0x1FFC | 0xEA0000;// (0x90) & 0x1FFC | 0xEA0000
    v9 += 4;
    v12 = v17-- == 1;
    *(_DWORD *)(gpu + 0x400750) = v11;          // NV_PGRAPH_RDI_INDEX
    *(_DWORD *)(gpu + 0x400754) = v10;          // NV_PGRAPH_RDI_DATA
  }
  while ( !v12 );
  v13 = *(_DWORD *)(gpu + 0x100324);            // NV_PFB_ZCOMP_OFFSET
  *(_DWORD *)(gpu + 0x4009A0) = v13;            // NV_PGRAPH_ZCOMP_OFFSET_XBOX
  *(_DWORD *)(gpu + 0x400750) = 0xEA000Cu;      // NV_PGRAPH_RDI_INDEX
  *(_DWORD *)(gpu + 0x400754) = v13;            // NV_PGRAPH_RDI_DATA
  v14 = *(_DWORD *)(gpu + 0x100200);            // NV_PFB_CFG0
  *(_DWORD *)(gpu + 0x4009A4) = v14;            // NV_PGRAPH_CFG0_XBOX
  *(_DWORD *)(gpu + 0x400750) = 0xEA0000u;      // NV_PGRAPH_RDI_INDEX
  *(_DWORD *)(gpu + 0x400754) = v14;            // NV_PGRAPH_RDI_DATA
  v15 = *(_DWORD *)(gpu + 0x100204);            // NV_PFB_CFG1
  *(_DWORD *)(gpu + 0x4009A8) = v15;            // NV_PGRAPH_CFG1_XBOX
  *(_DWORD *)(gpu + 0x400750) = 0xEA0004u;      // NV_PGRAPH_RDI_INDEX
  *(_DWORD *)(gpu + 0x400754) = v15;            // NV_PGRAPH_RDI_DATA
  *(_DWORD *)(gpu + 0x40014C) = 0;              // NV_PGRAPH_CTX_SWITCH1_ALL_DISABLE
  *(_DWORD *)(gpu + 0x400150) = 0;              // NV_PGRAPH_CTX_SWITCH2_ALL_DISABLE
  *(_DWORD *)(gpu + 0x400154) = 0;              // NV_PGRAPH_CTX_SWITCH3_ALL_DISABLE
  *(_DWORD *)(gpu + 0x400158) = 0;              // NV_PGRAPH_CTX_SWITCH4_ALL_DISABLE
  *(_DWORD *)(gpu + 0x400144) = 0x10000000u;    // NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED
  *(_DWORD *)(gpu + 0x400764) = 0x8000000u;     // NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_VALID
  return D3D::CMiniport::HalGrLoadChannelContext((void *)v1, *(_DWORD *)(v1 + 308));
}

int __thiscall D3D::CMiniport::HalGrIdle(void *this)
{
  void *v1; // edi@1
  int gpu; // esi@1
  int result; // eax@1
  int v4; // ebx@2

  v1 = this;
  gpu = *(_DWORD *)this;
  result = *(_DWORD *)(*(_DWORD *)this + 4196096);
  if ( result )
  {
    do
    {
      v4 = *(_DWORD *)(gpu + 0x100);            // NV_PBUS_ROM_VERSION_MASK
      if ( BYTE1(v4) & 0x10 )
        result = unknown_libname_835(v1);
      if ( v4 & 0x1000000 )
        result = D3D::CMiniport::VBlank(v1);
    }
    while ( *(_DWORD *)(gpu + 0x400700) );      // NV_PGRAPH_STATUS_NOT_BUSY (while BUSY)
  }
  return result;
}

int __thiscall unknown_libname_835(void *this)
{
  int gpu; // esi@1
  int v2; // eax@1
  int v3; // ebx@1
  int v4; // edi@1
  void *v6; // [sp+0h] [bp-4h]@1

  v6 = this;
  gpu = *(_DWORD *)this;
  *(_DWORD *)(*(_DWORD *)this + 0x400720) = 0;  // NV_PGRAPH_FIFO_ACCESS_DISABLE
  v2 = *(_DWORD *)(gpu + 0x400100);             // NV_PGRAPH_INTR
  v3 = *(_DWORD *)(gpu + 0x400108);             // NV_PGRAPH_NSOURCE
  v4 = *(_DWORD *)(gpu + 0x400704) & 0x1FFC;    // NV_PGRAPH_TRAPPED_ADDR_MTHD
  if ( !(BYTE1(v2) & 0x10) )                    // NV_PGRAPH_INTR_MISSING_HW_PENDING
    goto LABEL_14;
  *(_DWORD *)(gpu + 0x400100) = 0x1000u;        // NV_PGRAPH_INTR_CONTEXT_SWITCH_PENDING
  while ( *(_DWORD *)(*(_DWORD *)this + 0x400700) )// NV_PGRAPH_STATUS_NOT_BUSY (while BUSY)
    ;
  D3D::CMiniport::HalGrLoadChannelContext(this, ((unsigned int)v4 >> 20) & 0x1F);
  v2 = *(_DWORD *)(gpu + 0x400100);             // NV_PGRAPH_INTR
  if ( v2 )
  {
LABEL_14:
    *(_DWORD *)(gpu + 0x400100) = v2;           // NV_PGRAPH_INTR
    if ( v3 && v2 & 0x100001 && !(v3 & 0x40) )  // NV_PGRAPH_NSOURCE && NV_PGRAPH_INTR & NV_PGRAPH_INTR_NOTIFY_PENDING|NV_PGRAPH_INTR_ERROR_PENDING && !(NV_PGRAPH_NSOURCE & NV_PGRAPH_NSOURCE_ILLEGAL_MTHD_PENDING)
    {
      if ( v4 == 0x100 )                        // NV_PGRAPH_TRAPPED_ADDR_MTHD
      {
        D3D::CMiniport::SoftwareMethod(v6, *(_DWORD *)(gpu + 0x400708));// NV_PGRAPH_TRAPPED_DATA_LOW
      }
      else
      {
        unknown_libname_837(
          "Graphics hardware error information:\n Source: %08x\n   ChID: %d\n  Class: %x\n Method: %08x\n   Data: %08x\n    Get: %08x\n",
          v3,                                   // NV_PGRAPH_NSOURCE
          ((unsigned int)v4 >> 20) & 0x1F,      // NV_PGRAPH_TRAPPED_ADDR_CHID
          *(_DWORD *)(gpu + 0x40014C) & 0xFF,   // NV_PGRAPH_CTX_SWITCH1_GRCLASS
          v4,                                   // NV_PGRAPH_TRAPPED_ADDR_MTHD
          *(_DWORD *)(gpu + 0x400708),          // NV_PGRAPH_TRAPPED_DATA_LOW
          vFD003244 | 0x80000000);              // NV_PFIFO_CACHE1_DMA_GET
        __debugbreak();
      }
    }
  }
  *(_DWORD *)(gpu + 0x400720) = 1;              // NV_PGRAPH_FIFO_ACCESS_ENABLE
  return *(_DWORD *)(gpu + 0x400100);           // NV_PGRAPH_INTR
}

//TODO D3D::CMiniport::VBlank

int __thiscall D3D::CMiniport::HalGrLoadChannelContext(void *this, int a2)
{
  void *v2; // ebx@1
  int gpu; // esi@1
  int v4; // edx@3
  int result; // eax@6
  signed int v6; // eax@8
  int v7; // edi@10
  int v8; // esi@10
  int v9; // [sp+Ch] [bp-4h]@3

  v2 = this;
  gpu = *(_DWORD *)this;
  if ( *(_DWORD *)(*(_DWORD *)this + 4194560) )
    unknown_libname_835(this);
  v9 = *(_DWORD *)(gpu + 0x400720);             // NV_PGRAPH_FIFO
  *(_DWORD *)(gpu + 0x400720) = 0;              // NV_PGRAPH_FIFO_ACCESS_DISABLE
  D3D::CMiniport::HalGrIdle(v2);
  v4 = a2;
  if ( *((_DWORD *)v2 + 77) != a2 )
  {
    D3D::CMiniport::HalGrUnloadChannelContext(v2, *((_DWORD *)v2 + 77));
    v4 = a2;
  }
  *((_DWORD *)v2 + 77) = v4;
  if ( v4 == 2 )
  {
    *(_DWORD *)(gpu + 0x400144) = 0x10000100u;  // NV_PGRAPH_CTX_CONTROL_TIME_NOT_EXPIRED|NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED
    result = v9 | 1;
    *(_DWORD *)(gpu + 0x400764) = 0x8000000u;   // NV_PGRAPH_FFINTFC_ST2_CHID_STATUS_VALID
    *(_DWORD *)(gpu + 0x400720) = v9 | 1;       // NV_PGRAPH_FIFO_ACCESS_ENABLE
  }
  else
  {
    if ( *((_DWORD *)v2 + v4 + 81) )
    {
      *(_DWORD *)(gpu + 0x400080) = 0x70000u;   // NV_PGRAPH_DEBUG_0_IDX_STATE_RESET|NV_PGRAPH_DEBUG_0_VTX_STATE_RESET|NV_PGRAPH_DEBUG_0_CAS_STATE_RESET
      *(_DWORD *)(gpu + 0x400080) = 0;          // NV_PGRAPH_DEBUG_0_NO_RESET
      *(_DWORD *)(gpu + 0x400750) = 0x3D0000u;  // NV_PGRAPH_RDI_INDEX_SELECT
      v6 = 15;
      do
      {
        --v6;
        *(_DWORD *)(gpu + 0x400754) = 0;        // NV_PGRAPH_RDI_DATA
      }
      while ( v6 );
    }
    *(_DWORD *)(gpu + 0x400084) |= 0x1000000u;  // NV_PGRAPH_DEBUG_1_CACHE_INVALIDATE
    v7 = (v4 & 0x1F) << 24;
    *(_DWORD *)(gpu + 0x400148) = v7;           // NV_PGRAPH_CTX_USER
    *(_DWORD *)(gpu + 0x400784) = *((_DWORD *)v2 + a2 + 78) & 0xFFFF;// NV_PGRAPH_CHANNEL_CTX_POINTER_INST
    *(_DWORD *)(gpu + 0x400788) = 1;            // NV_PGRAPH_CHANNEL_CTX_STATUS_LOADED
    D3D::CMiniport::HalGrIdle(v2);
    *(_DWORD *)(gpu + 0x400148) = v7 | *(_DWORD *)(gpu + 0x400148) & 0xE0FFFFFF;// NV_PGRAPH_CTX_USER_CHID (inverted mask)
    *(_DWORD *)(gpu + 0x400144) = 0x10010100u;  // NV_PGRAPH_CTX_CONTROL_TIME_NOT_EXPIRED|NV_PGRAPH_CTX_CONTROL_CHID_VALID|NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED
    v8 = gpu + 0x400764;                        // NV_PGRAPH_FFINTFC_ST2
    result = *(_DWORD *)v8 & 0xCFFFFFFF;        // NV_PGRAPH_FFINTFC_ST2_CHSWITCH_CLEAR&NV_PGRAPH_FFINTFC_ST2_FIFOHOLD_CLEAR
    *(_DWORD *)v8 = result;                     // NV_PGRAPH_FFINTFC_ST2
  }
  return result;
}

int __thiscall D3D::CMiniport::HalGrUnloadChannelContext(void *this, int a2)
{
  int result; // eax@1
  int gpu; // esi@1

  result = a2;
  gpu = *(_DWORD *)this;
  if ( a2 != 2 )
  {
    *(_DWORD *)(gpu + 0x400784) = *((_DWORD *)this + a2 + 78) & 0xFFFF;// NV_PGRAPH_CHANNEL_CTX_POINTER_INST
    *(_DWORD *)(gpu + 0x400788) = 2;            // NV_PGRAPH_CHANNEL_CTX_STATUS_UNLOADED
    result = D3D::CMiniport::HalGrIdle(this);
    *(_DWORD *)(gpu + 0x400144) = 0x10000000u;  // NV_PGRAPH_CTX_CONTROL_DEVICE_ENABLED
  }
  return result;
}
int __thiscall D3D::CMiniport::HalFifoControlLoad(void *this)
{
  int gpu; // esi@1
  int result; // eax@1

  gpu = *(_DWORD *)this;
  *(_DWORD *)(*(_DWORD *)this + 12836) = 0xF0078u;
  *(_DWORD *)(gpu + 0x2044) = 0x101FFFFu;       // NV_PFIFO_DMA_TIMESLICE_SELECT_128K|NV_PFIFO_DMA_TIMESLICE_TIMEOUT_ENABLED
  *(_DWORD *)(gpu + 0x2040) = *((_DWORD *)this + 72) & 0x3FF;// NV_PFIFO_DELAY_0_WAIT_RETRY
  *(_DWORD *)(gpu + 0x2500) = 0;                // NV_PFIFO_CACHES_ALL_DISABLE
  *(_DWORD *)(gpu + 0x3000) = 0;                // NV_PFIFO_CACHE0_PUSH0_ACCESS_DISABLE
  *(_DWORD *)(gpu + 0x3050) = 0;                // NV_PFIFO_CACHE0_PULL0_ACCESS_DISABLE
  *(_DWORD *)(gpu + 0x3200) = 0;                // NV_PFIFO_CACHE1_PUSH0_ACCESS_DISABLE
  *(_DWORD *)(gpu + 0x3250) = 0;                // NV_PFIFO_CACHE1_PULL0_ACCESS_DISABLE
  *(_DWORD *)(gpu + 0x3220) = 0;                // NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_DISABLE
  result = D3D::CMiniport::HalFifoContextSwitch(this, 1);
  *(_DWORD *)(gpu + 0x3210) = 0;                // NV_PFIFO_CACHE1_PUT_ADDRESS
  *(_DWORD *)(gpu + 0x3270) = 0;                // NV_PFIFO_CACHE1_GET_ADDRESS
  *(_DWORD *)(gpu + 0x3250) = 1;                // NV_PFIFO_CACHE1_PULL0_ACCESS_ENABLE
  *(_DWORD *)(gpu + 0x3200) = 1;                // NV_PFIFO_CACHE1_PUSH0_ACCESS_ENABLE
  *(_DWORD *)(gpu + 0x2500) = 1;                // NV_PFIFO_CACHES_REASSIGN_ENABLED
  *(_DWORD *)(gpu + 0x2500) = 0;                // NV_PFIFO_CACHES_ALL_DISABLE
  return result;
}

int __thiscall D3D::CMiniport::HalFifoContextSwitch(void *this, int a2_switch)
{
  void *v2; // esi@1
  int gpu; // eax@1
  int v4; // ebx@1
  int v5; // ecx@1
  int v6; // edx@1
  int v7; // ecx@2
  int v8; // edx@8
  int v9; // [sp+Ch] [bp-14h]@1
  int v10; // [sp+10h] [bp-10h]@1
  int v11; // [sp+14h] [bp-Ch]@1
  signed int v12; // [sp+1Ch] [bp-4h]@2

  v2 = this;
  gpu = *(_DWORD *)this;
  v4 = *((_DWORD *)this + 74);                  // unknown1
  v9 = *(_DWORD *)(*(_DWORD *)this + 9472);
  v10 = *(_DWORD *)(*(_DWORD *)this + 12800);
  v11 = *(_DWORD *)(*(_DWORD *)this + 12880);
  *(_DWORD *)(*(_DWORD *)this + 9472) = 0;
  *(_DWORD *)(gpu + 0x3200) = 0;                // NV_PFIFO_CACHE1_PUSH0_ACCESS_DISABLE
  *(_DWORD *)(gpu + 0x3250) = 0;                // NV_PFIFO_CACHE1_PULL0_ACCESS_DISABLE
  v5 = *(_DWORD *)(gpu + 0x3204) & 0x1F;        // NV_PFIFO_CACHE1_PUSH1_CHID
  v6 = gpu + v4 + ((*(_DWORD *)(gpu + 0x3204) & 0x1F) << 6);// unknown2
  *(_DWORD *)v6 = *(_DWORD *)(gpu + 0x3240);    // NV_PFIFO_CACHE1_DMA_PUT
  *(_DWORD *)(v6 + 4) = *(_DWORD *)(gpu + 0x3244);// NV_PFIFO_CACHE1_DMA_GET
  *(_DWORD *)(v6 + 8) = *(_DWORD *)(gpu + 0x3248);// NV_PFIFO_CACHE1_REF
  *(_DWORD *)(v6 + 12) = *(_DWORD *)(gpu + 0x322C);// NV_PFIFO_CACHE1_DMA_INSTANCE
  *(_DWORD *)(v6 + 16) = *(_DWORD *)(gpu + 0x3228);// NV_PFIFO_CACHE1_DMA_STATE
  *(_DWORD *)(v6 + 20) = *(_DWORD *)(gpu + 0x3224);// NV_PFIFO_CACHE1_DMA_FETCH
  *(_DWORD *)(v6 + 24) = *(_DWORD *)(gpu + 0x3280);// NV_PFIFO_CACHE1_ENGINE
  *(_DWORD *)(v6 + 28) = *(_DWORD *)(gpu + 0x3254);// NV_PFIFO_CACHE1_PULL1
  *(_DWORD *)(v6 + 32) = *(_DWORD *)(gpu + 0x3268);// NV_PFIFO_CACHE1_ACQUIRE_2
  *(_DWORD *)(v6 + 36) = *(_DWORD *)(gpu + 0x3264);// NV_PFIFO_CACHE1_ACQUIRE_1
  *(_DWORD *)(v6 + 40) = *(_DWORD *)(gpu + 0x3260);// NV_PFIFO_CACHE1_ACQUIRE_0
  *(_DWORD *)(v6 + 44) = *(_DWORD *)(gpu + 0x326C);// NV_PFIFO_CACHE1_SEMAPHORE
  *(_DWORD *)(v6 + 48) = *(_DWORD *)(gpu + 0x324C);// NV_PFIFO_CACHE1_DMA_SUBROUTINE
  if ( *(_DWORD *)(gpu + 0x3204) & 0x100 )      // NV_PFIFO_CACHE1_PUSH1_MODE_DMA
  {
    v12 = 1 << v5;
    v7 = *(_DWORD *)(gpu + 0x2508) & ~(1 << v5);// NV_PFIFO_DMA
    if ( *(_DWORD *)(gpu + 0x3240) != *(_DWORD *)(gpu + 0x3244) )// NV_PFIFO_CACHE1_DMA_PUT != NV_PFIFO_CACHE1_DMA_GET
      v7 |= v12;
    *(_DWORD *)(gpu + 0x2508) = v7;             // NV_PFIFO_DMA
  }
  *(_DWORD *)(gpu + 0x3204) = a2_switch & 0x1F; // NV_PFIFO_CACHE1_PUSH1_CHID
  if ( (1 << a2_switch) & *((_DWORD *)v2 + 65) && a2_switch != 1 )
    *(_DWORD *)(gpu + 0x3204) |= 0x100u;        // NV_PFIFO_CACHE1_PUSH1_MODE_DMA
  v8 = v4 + (a2_switch << 6) + gpu;             // unknown3
  *(_DWORD *)(gpu + 0x3240) = *(_DWORD *)v8;    // NV_PFIFO_CACHE1_DMA_PUT
  *(_DWORD *)(gpu + 0x3244) = *(_DWORD *)(v8 + 4);// NV_PFIFO_CACHE1_DMA_GET
  *(_DWORD *)(gpu + 0x3248) = *(_DWORD *)(v8 + 8);// NV_PFIFO_CACHE1_REF
  *(_DWORD *)(gpu + 0x322C) = *(_DWORD *)(v8 + 12);// NV_PFIFO_CACHE1_DMA_INSTANCE
  *(_DWORD *)(gpu + 0x3228) = *(_DWORD *)(v8 + 16);// NV_PFIFO_CACHE1_DMA_STATE
  *(_DWORD *)(gpu + 0x3224) = *(_DWORD *)(v8 + 20);// NV_PFIFO_CACHE1_DMA_FETCH
  *(_DWORD *)(gpu + 0x3280) = *(_DWORD *)(v8 + 24);// NV_PFIFO_CACHE1_ENGINE
  *(_DWORD *)(gpu + 0x3254) = *(_DWORD *)(v8 + 28);// NV_PFIFO_CACHE1_PULL1
  *(_DWORD *)(gpu + 0x3268) = *(_DWORD *)(v8 + 32);// NV_PFIFO_CACHE1_ACQUIRE_2
  *(_DWORD *)(gpu + 0x3264) = *(_DWORD *)(v8 + 36);// NV_PFIFO_CACHE1_ACQUIRE_1
  *(_DWORD *)(gpu + 0x3260) = *(_DWORD *)(v8 + 40);// NV_PFIFO_CACHE1_ACQUIRE_0
  *(_DWORD *)(gpu + 0x326C) = *(_DWORD *)(v8 + 44);// NV_PFIFO_CACHE1_SEMAPHORE
  *(_DWORD *)(gpu + 0x324C) = *(_DWORD *)(v8 + 48);// NV_PFIFO_CACHE1_DMA_SUBROUTINE
  if ( (1 << a2_switch) & *((_DWORD *)v2 + 65) && a2_switch != 1 )
    *(_DWORD *)(gpu + 0x3220) = 1;              // NV_PFIFO_CACHE1_DMA_PUSH_ACCESS_ENABLE
  *(_DWORD *)(gpu + 0x204C) = 0x1FFFFFu;        // NV_PFIFO_TIMESLICE_TIMER_EXPIRED
  *(_DWORD *)(gpu + 0x3250) = v11;              // NV_PFIFO_CACHE1_PULL0
  *(_DWORD *)(gpu + 0x3200) = v10;              // NV_PFIFO_CACHE1_PUSH0
  *(_DWORD *)(gpu + 0x2500) = v9;               // NV_PFIFO_CACHES
  return gpu;
}