試行番号0。設定をひねります
最初に、私は最も抵抗の少ない道を取りました。ゲーム自体を調整してみてください。 私は部分的に成功しました。 開始するには、TRUCK.INIファイル、つまりDRVセクションを編集し、その中にビデオアダプターの正しい設定を書き込む必要があります。 正しい設定でTRUCK.INIファイルを見つけてゲームを開始したことがありましたが、この記事を書き始めたとき、パッチを当てていないワインで「正しい」TRUCK.INIを使用してゲームの起動を再現できませんでした。 この方法は信頼できないと考えています。
試行番号1.ワインバージョンを選択します
手元にあるいくつかのバージョン(最新のgitを含む)を試しました。 それらのどれも「クリーンな設定」でゲームを実行しませんでした。 したがって、最新の安定バージョンのソースを取得することが決定されました。 この記事の執筆時点では、バージョンwine-1.2.3でした。 さらに、この特定のバージョンのワインで行ったすべての実験。
ゲームログ分析
「純粋な」ワインでゲームを開始すると、起動スプラッシュ画面が表示され、その後数回ウィンドウが開き、メッセージなしでオフになります。 このような起動後、ゲームフォルダーを調べて、次の内容のwarn.logファイルを確認しました。
warning : fail in SetCoop... One or more of the parameters passed to the method are incorrect. (unknown) 0
warning : DirectDraw4/7 not found 0
warning :
(09-03-12 11:09)
,
(fail in SetCoop... One or more of the parameters passed to the method are incorrect. (unknown)(null))
0
このログから最初の手がかりが得られました。DirectDrawサブシステムが正しく初期化されていません。 以前はダイレクトドローのビジネスがなかったので、この記録は少し助けになりましたが、それが最初の手がかりになりました。 Googleからのリクエスト「directdraw SetCoop」により、SetCooperativeLevel関数に関する情報が提供されました。 この関数の説明には深く入りませんでしたが、代わりに他の方法に進むことにしました(ただし、この関数に戻ります)。
理論を掘り下げます。 wineのロギング機能
オフィスに行きました。 サイトのワインを探し、ワインの入手方法に関する情報を探し始め、アプリケーションの起動時に発生するすべてのエラーに関するメッセージを提供します。 すべての情報はwww.winehq.org/developer-cheatsheetにあります。 wineのロギング機能は非常に豊富であり、起動中のプログラムに関するさまざまな情報を取得できます(すべての入力および出力パラメーターを使用して、すべてのWinAPI関数の呼び出しのチェーンをトレースすることもできます)。
したがって、wineを実行してログを削除します。
最初に、パラメーターなしで実行しました:
wine king > wine.dbg 2>&1
。 受信した出力で
fixme:win:EnumDisplayDevicesW ((null),0,0x32f110,0x00000000), stub!
fixme:win:EnumDisplayDevicesW ((null),0,0x32f424,0x00000000), stub!
ここには興味深いものは何もありません。
小さな余談:wineのロギングサブシステムの説明
- ワインにはいくつかのクラスがあります(ただし、私は単語レベルに精通していますが)。これらはFIXME、ERR、WARN、TRACE、MESSAGEです。 彼らはメッセージとそのタイプの重要性に責任があります。
- また、wineにはデバッグチャネルがあり、wine内の特定のサブシステムを担当します。 たとえば、 regはレジストリサブシステムなどを担当します。
- ロギングは、WINEDEBUG環境変数を使用して制御されます。 たとえば、次の引数で実行しました: WINEDEBUG = warn + all、trace + all
それでは、タスクに戻りましょう。 ロギングの可能性を調査した後、私はさまざまなロギングパラメーターを使用してゲームを実行し始めました。
開始後、40メガバイトのログを取得しました。 手動で何かを見つけることは不可能であることは明らかです。 最初はERRクラスに従ってフィルタリングしましたが、そこでは何も興味深いものは見つかりませんでした。 次に、warn.logからのメッセージに戻り、SetCoopでフィルター処理することにしました 。
cat wine.dbg | grep SetCoop
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x15ae78)->(0x40066,0000105b)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x15ae78) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x15ae78)->(0x40066,00000008)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel SetCooperativeLevel retuning DD_OK
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x15ae78)->(0x40066,00000008)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel SetCooperativeLevel retuning DD_OK
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x15ae78)->((nil),00000008)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel SetCooperativeLevel retuning DD_OK
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x160420)->(0x40066,0000105b)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x160420) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x160420)->(0x40066,00000008)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel SetCooperativeLevel retuning DD_OK
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel (0x160420)->((nil),00000008)
0009:trace:ddraw:IDirectDrawImpl_SetCooperativeLevel SetCooperativeLevel retuning DD_OK
ここにもっと興味深いデータがあります。 互換性のないパラメーターがSetCooperativeLevel関数に渡されたことがわかります。これは既に何かです。 ログの前の行を見ると、関数に渡されるすべてのパラメーターが表示されます
0009:trace:ddraw:DDRAW_dump_cooperativelevel - DDSCL_FULLSCREEN DDSCL_ALLOWREBOOT DDSCL_NORMAL DDSCL_ALLOWMODEX DDSCL_EXCLUSIVE
0009:trace:ddraw:DDRAW_dump_cooperativelevel - DDSCL_FULLSCREEN DDSCL_ALLOWREBOOT DDSCL_NORMAL DDSCL_ALLOWMODEX DDSCL_EXCLUSIVE
すべてのパラメーターの説明は、MSDNで見つけることができます。
ソースコード分析
次に、SetCooperativeLevel関数のソースコードとドキュメントを分析しました。
wineで適切な関数を見つけるのは簡単です。%SRC_ROOT%/ dlls / ddraw / ddraw.cにあります。 この関数はIDirectDrawImpl_SetCooperativeLevelと呼ばれます 。
MSDNを開き、 SetCooperativeLevel関数の説明を見つけて、以下を参照してください。
DDSCL_NORMAL
The application functions as a typical Windows application. This flag cannot be used with the DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, or DDSCL_FULLSCREEN flags
つまり、これは、これらのフラグを一緒にすることはできないことを意味します。
wineの実装はドキュメントと完全に一致しており、この場合はエラーコードDDERR_INVALIDPARAMSが表示されることに注意してください。 テストでは、フラグの特定の組み合わせのチェックを削除しようとすることにしました。
/* DDSCL_NORMAL or DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE */ if(cooplevel & DDSCL_NORMAL) { /* Can't coexist with fullscreen or exclusive */ /** @note commented for test only if(cooplevel & (DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) ) { TRACE("(%p) DDSCL_NORMAL is not compative with DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE\n", This); LeaveCriticalSection(&ddraw_cs); return DDERR_INVALIDPARAMS; } */
wineをコンパイルしてインストールし、Truckersを実行して...
おなじみのゲームメニューが読み込まれ、勝利です! 私たちはゲームを作成しようとしています。ゲームは作成中です。お気に入りのZilトラックに乗れます!
研究の改善
仮想マップ上で動き回った後、ゲームが非常に安定して動作していると判断しました。つまり、パッチの形で結果を記入し、ワインバグトラッカーでアプリケーションを作成するときです。
この関数を完全に理解するために、フラグDDSCL_ *の組み合わせに応じてエラーコードを生成するwin32のテストプログラムを作成することにしました。成功があります。 また、この関数は、MSDNで説明されているよりもはるかに頻繁にDD_OKを返すことに注意してください 。 ゲーム開発者は、この関数の説明と実装の違いを考慮せず、ドキュメントで禁止されているフラグを使用しなかった可能性があります。
リクエストを作成し、ログとパッチを添付しました。
実際、パッチは非常に単純です。禁止フラグのチェックをコメントアウトしました(上記の例のように)が、この関数は多くのアプリケーションで使用されるため、より詳細な分析を行う必要があります。 これを行うために、win32プログラムをアプリケーションに添付しました。これは、フラグの可能なすべての組み合わせを反復処理し、対応するエラーコードを提供します。
PS私はすべてがwine-1.4でうまく動くことを確認しました。
このバージョンでは、SetCooperativeLevelが大幅に再設計され、この関数の動作はwin32の実際の実装に近くなりました。 ワインの対応するアプリケーションを閉じました。 ご意見ありがとうございます。