吉里吉里Zの解析 その 1

ゲームエンジンとして、比較的多く採用されている吉里吉里2の後継版
吉里吉里Zが Windows 2000で動作させると、バグるって話だったので、とりあえず、
デバッグできる環境を作るために、 GitHub からダウンロードして、VC++2005 環境でコンパイルしてみることにした

kkz

BasicDrawDevice.cpp

void TJS_INTF_METHOD tTVPBasicDrawDevice::StartBitmapCompletion(iTVPLayerManager * manager)
{
    EnsureDevice();

    if( Texture && TargetWindow ) {
        if(TextureBuffer) {
            TVPAddImportantLog( (const tjs_char*)TVPBasicDrawDeviceTextureHasAlreadyBeenLocked );
            Texture->UnlockRect(0), TextureBuffer = NULL;
        }

        D3DLOCKED_RECT rt;
        HRESULT hr = Texture->LockRect( 0, &rt, NULL, D3DLOCK_NO_DIRTY_UPDATE );

        if(hr == D3DERR_INVALIDCALL && IsTargetWindowActive() ) {
            TVPThrowExceptionMessage( TVPInternalErrorResult, TJSInt32ToHex(hr, 8));
        }

        if(hr != D3D_OK) {
            ErrorToLog( hr );
            TextureBuffer = NULL;
            TryRecreateWhenDeviceLost();
        } else /*if(hr == DD_OK) */ {
            TextureBuffer = rt.pBits;
            TexturePitch = rt.Pitch;
        }
    }
}

トレースしてみた所
LockRect で D3DERR_DRIVERINTERNALERROR が発生してることが分かった。
|。・ω・) 。o ( でも原因が分からん )

D3DLOCK_NO_DIRTY_UPDATE(0x00008000) をやめて NULL にしたら、動いた・・・訳が分からん
D3DLOCK_READONLY(0x0010)、D3DLOCK_NOSYSLOCK (0x800)は指定しても動いた

kkz2

 L00405E92:
          mov    eax,[edi+4Ch]
          mov    ecx,[eax]
          mov    edx,[ecx+50h]
          push    00000000h
          push    eax
          call    edx
          mov    dword ptr [edi+0000009Ch],00000000h
 L00405EA9:
          mov    eax,[edi+4Ch]
          mov    ecx,[eax]
          push    00008000h
          push    00000000h
          lea    edx,[esp+1Ch]
          push    edx
          push    00000000h
          push    eax
          mov    eax,[ecx+4Ch]
          call    eax
          mov    esi,eax
          cmp    esi,8876086Ch
          jnz    L00405F11
          cmp    dword ptr [edi+3Ch],00000000h
          jz     L00405F15
          call    [USER32.dll!GetForegroundWindow]
          cmp    eax,[edi+3Ch]
          setz     al
          test    al,al
          jz     L00405F15
          mov    edx,00000008h
          mov    ecx,esi
          lea    edi,[esp+10h]
          call    SUB_L004F2DD0
          mov    dword ptr [esp+28h],00000001h
          mov    ecx,[L0070B954]
          test    ecx,ecx
          jnz    L00405F0A
          mov    ecx,[L0070B950]
void TJS_INTF_METHOD tTVPBasicDrawDevice::StartBitmapCompletion(iTVPLayerManager * manager)
{
    EnsureDevice();

    if( Texture && TargetWindow ) {
        if(TextureBuffer) {
            TVPAddImportantLog( (const tjs_char*)TVPBasicDrawDeviceTextureHasAlreadyBeenLocked );
            Texture->UnlockRect(0), TextureBuffer = NULL;
        }

        D3DLOCKED_RECT rt;
        HRESULT hr = Texture->LockRect( 0, &rt, NULL, D3DLOCK_NO_DIRTY_UPDATE );
        if(hr != D3D_OK){
            hr = Texture->LockRect( 0, &rt, NULL, NULL );
        }

        if(hr == D3DERR_INVALIDCALL && IsTargetWindowActive() ) {
            TVPThrowExceptionMessage( TVPInternalErrorResult, TJSInt32ToHex(hr, 8));
        }

        if(hr != D3D_OK) {
            ErrorToLog( hr );
            TextureBuffer = NULL;
            TryRecreateWhenDeviceLost();
        } else /*if(hr == DD_OK) */ {
            TextureBuffer = rt.pBits;
            TexturePitch = rt.Pitch;
        }
    }
}

つまり、こうすれば動くはず

Win2000/XPは5コア以上のCPUをDirectXで扱うとクラッシュするバグがある
(副題 吉里吉里Zの解析 その2)

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です