はじめに:REDengine 4 のMODエコシステムと進化
BethesdaのCreation Kitのような公式ビジュアルMODツールを備えたタイトルや、オープンなスクリプトエンジンを採用するゲームとは異なり、CD Projekt Redが『サイバーパンク2077』(Cyberpunk 2077)のために開発した自社製エンジン「REDengine 4」は、高度に統合されたC++ベースのプロプライエタリなアーキテクチャです。その内部は、コンパイル済みスクリプトバイトコード、読み取り専用のバイナリアーカイブ(.archive)、そしてゲーム内すべてのパラメータを管理するランタイム中央データベース「TweakDB」が密接に結合しています。
リリース当初、MODコミュニティはバイナリの直接書き換えや、既存の .archive コンテナ内ファイルの単純な上書き差し替えに頼らざるを得ませんでした。しかし、エンジンのリバースエンジニアリングが進展するにつれ、役割分担されたモジュール型フレームワーク群が確立されました:
- Cyber Engine Tweaks (CET): DLLプロキシによるネイティブC++フック、Luaスクリプト実行基盤、ImGuiデバッグコンソール。
- REDscript: Swiftに似た独自スクリプト言語をパッチ・再コンパイルし、バイトコードレベルで注入するコンパイラ。
- ArchiveXL: 既存アーカイブを破壊することなく、新規3Dモデルやテクスチャを動的に読み込む仮想ファイルシステム拡張。
- TweakXL: TweakDBをインメモリで動的に書き換え、武器や防具の新規レコードを安全に追加するパッチエンジン。
- Codeware および RED4ext: プラグインライフサイクル管理やRTTIリフレクションを提供する基底C++拡張層。
これらフレームワークの連携メカニズムとライフサイクルを理解することは、起動時クラッシュ(Flatliner)の原因究明、スクリプトコンパイル競合の解消、そしてゲーム本体アップデート時の環境復旧において不可欠です。
アーキテクチャ概要:4大フレームワークの連携トポロジー
以下の図は、REDengine 4の起動フェーズから実行時における各主要フレームワークの配置とデータの流れを示しています:
+-------------------------------------------------------------------------+
| Cyberpunk2077.exe (REDengine 4 コアプロセス) |
+-------------------------------------------------------------------------+
| |
v (DLLプロキシ読み込み: version.dll) v (エンジン初期化フック)
+-----------------------------------+ +-------------------------+
| Cyber Engine Tweaks (CET) | | RED4ext コア |
| - ネイティブC++フック | | - 低レイヤーDLLプラグイン|
| - Lua 5.1/LuaJIT ランタイム | | - ライフサイクル&RTTI |
| - ImGui コンソール&オーバーレイ | +-------------------------+
| - RTTI関数・プロパティ直接呼び出し| | |
+-----------------------------------+ v v
+-------------+ +-----------+
| ArchiveXL | | TweakXL |
| (仮想VFS) | | (TweakDB) |
+-------------+ +-----------+
| |
+-----------------------------------+ | |
| REDscript | | |
| - r6/scripts をバイトコード化 | <-------------+---------------+
| - メソッドフック (@replace, @wrap)| (スクリプト用バインディングを提供)
| - ゲーム基本クラスの拡張 |
+-----------------------------------+
各フレームワークは独立した役割を担っています:
- CETは外部からDLLプロキシによってシステムAPIを捕捉し、非同期Luaスクリプトの実行とUI描画を提供します。
- RED4extはエンジン初期化の最深部で動作し、ArchiveXLおよびTweakXLのホスト基盤として機能します。
- REDscriptはゲームループ開始前にユーザースクリプトをコンパイルし、ゲームネイティブのスクリプトキャッシュへと注入します。
- ArchiveXLとTweakXLは、メモリ上でアセットストリーミングとデータレコードを非破壊的・動的に拡張します。
1. Cyber Engine Tweaks (CET):バイナリフックとLua実行環境
実行機構:ダイナミックリンクライブラリ・プロキシ(DLL Proxying)
CETは、WindowsのDLL検索順序仕様を利用してプロセス空間へ侵入します。Windowsは実行可能ファイル(bin\x64\)と同じフォルダに存在するDLLを、システムフォルダ(System32)よりも優先して読み込みます。CETは偽装した version.dll を配置することで、Cyberpunk2077.exe の起動と同時にメモリへロードされ、自身のフックを初期化しつつ、正規のWindows API呼び出しを本物のシステムDLLへと転送します。
実行時型情報(RTTI)のリフレクション
CET最大の強みは、REDengine 4の内部RTTI(Run-Time Type Information)システムへの直接アクセスです。エンジンは内部のC++クラス、構造体、列挙型、メンバ関数のメタデータをテーブル管理しています:
- CETは起動時にRTTI登録テーブルを走査し、エンジン内部のクラスや関数ポインタを特定します。
- これらを組み込みLua環境(LuaJIT)へとバインドします。
- MOD制作者は
bin\x64\plugins\cyber_engine_tweaks\mods\[Mod名]\init.luaにLuaコードを記述します。 - スクリプトはゲーム内イベント(
onInit、onUpdate、onDraw)をリッスンし、Game.GetPlayer()からプレイヤー情報を取得したり、エンジン関数を直接実行することが可能です。
ImGuiによるオーバーレイ表示とコンソール操作
CETは軽量UIライブラリ「Dear ImGui」をDirectX 12のスワップチェインにフックしています。バインドされたホットキーを押すと、マウスとキーボード入力を捕捉してゲーム画面上にデバッグコンソールを表示し、メモリ変数の確認やコマンド実行、MODのGUI操作を可能にします。
2. REDscript:ネイティブスクリプトコンパイラと非破壊パッチ
外部からLuaを実行するCETに対し、REDscriptはゲーム自体のゲームプレイロジックを直接拡張します。
REDscript のコンパイルパイプライン
『サイバーパンク2077』のクエスト進行、UI処理、インベントリ挙動、パークツリー、NPCの挙動などは、Swiftに類似した独自スクリプト言語で書かれています。これらはバイナリバイトコードとして r6\cache\final.redscripts に事前コンパイルされています。
REDscriptはこの処理系に割り込みます:
- 起動時、REDscriptは
r6\scripts\配下の.redsファイルをすべて検出します。 - 構文解析を行い、抽象構文木(AST)を構築します。
- ゲームキャッシュから基本クラスや関数のシグネチャを逆コンパイルします。
- MODの構文木を既存のスクリプトツリーへ統合し、統合バイトコード(
r6\cache\moddedOnly.redscripts)としてメモリまたはキャッシュに再コンパイルします。 - REDengineの仮想マシンが、パッチ適用済みのバイトコードをネイティブ速度で実行します。
メソッドアノテーションによる競合回避
初期のスクリプトMODは、数千行あるスクリプトファイルを丸ごと上書きしていたため、同一ファイルを触るMOD同士が確実に競合していました。REDscriptはきめ細やかなアノテーションを提供することで、これを解決しました:
@replaceMethod(ClassName): クラス内の特定のメソッドを完全に置き換える。@wrapMethod(ClassName): 既存メソッドをラップし、wrappedMethod()の前後にカスタム処理を挟む(元のロジックを維持)。@addMethod(ClassName): 既存のエンジンスクリプトクラスに新しいメソッドを動的注入する。@addField(ClassName): 既存クラスに新しい変数・フィールドを追加する。
// REDscriptによるダメージ処理の非破壊的フック例
@wrapMethod(PlayerPuppet)
protected cb func OnTakeDamage(damageEvent: ref[gameDamageReceivedEvent]) -> Bool {
// 既存処理の前に実行
ModLog("被ダメージ検知: " + ToString(damageEvent.totalDamageReceived));
// 元のゲームロジックを実行
let result: Bool = wrappedMethod(damageEvent);
// 既存処理の後に実行
return result;
}
3. ArchiveXL:仮想ファイルシステムとアセットの動的拡張
ArchiveXLの登場以前は、衣装や武器を追加するには既存装備のメッシュ(3Dモデル)やテクスチャを上書きするしかありませんでした。そのため、同じ衣装をベースにしたMODは共存できませんでした。
動的リソースストリーミング
ArchiveXLはRED4extプラグインとして動作し、エンジンのリソースローダー(CResourceLoader)にフックします:
- バニラアーカイブを一切上書きせず、アドティブ(加算型)リソース登録を実現します。
- 新規のメッシュ、テクスチャ、リグデータは独立した
.archiveファイルとしてarchive\pc\mod\に配置します。 - 同時に、YAML形式の設定記述ファイル(拡張子
.xl)を配置します(例:archive\pc\mod\MyCustomArmor.xl)。
ファクトリインジェクションと動的モーフィング
ArchiveXLは .xl 記述を読み取り、以下の処理を行います:
- ゲームのリソースファクトリ(
resource.factories)へ新規エンティティ定義を動的登録します。 - 動的ボディモーフィング(Morphing)をサポートし、プレイヤーの体型プリセットに合わせて衣装が自動でフィットし、クリッピング(貫通)を防止します。
- ローカライズテキストの動的登録を行い、多言語環境下で新規アイテムの名称や説明文を適切に表示させます。
4. TweakXL:インメモリTweakDBデータベースパッチ
REDengine 4において、TweakDBは武器の攻撃力、アーマー値、スキル効果量、クラフトレシピ、NPCの基礎ステータスなど、あらゆる数値パラメータを保持する中核リレーショナルデータベースです。
バイナリ直接上書きの破綻
バニラのTweakDBは r6\cache\tweakdb.bin としてシリアライズされています。初期のツールはこのバイナリ全体を再生成していたため、最後に書き込まれたバイナリが以前のMODの変更をすべて消去してしまう致命的な問題がありました。
宣言型YAMLによるインメモリパッチ
TweakXLは、TweakDBの初期化フローをインターセプトすることでこの問題を解決しました:
- エンジンが
tweakdb.binをメモリに読み込みます。 - TweakXLがその初期化ポインタをキャッチします。
r6\tweaks\に置かれたすべての.yamlおよび.tweakファイルを解析します。- 既存レコードをベースにした複製(Clone)や、特定フィールドの変更、新規レコードの追加をメモリ上で動的に行います:
# TweakXL による新規刀レコード追加の記述例
Items.MyCustomKatana:
$type: gamedataItem_Record
$base: Items.Preset_Katana_Default
displayName: LocKey#MyCustomKatana_Name
visualTags: [ "MyCustomKatana_Mesh" ]
quality: Quality.Legendary
statModifiers:
- !append Items.BaseDamageModifier
このインメモリパッチ方式により、何百もの独立した衣装・武器MODが一切衝突することなく共存できるようになりました。
トラブルシューティング診断マトリクス
MOD導入環境でクラッシュや不具合が発生した場合は、以下の表に従って原因を特定してください:
| 症状・不具合 | 最も疑われるコンポーネント | 主な根本原因 | 推奨される対処法 |
|---|---|---|---|
| ロゴ画面表示前に即座にクラッシュ(Flatliner) | CET (version.dll) または RED4ext | ゲーム本体のアップデートによりメモリ配置が変化し、DLLのフックが失敗 | bin\x64\version.dll や red4ext\ を削除し、最新ゲームバージョンに対応した版へ更新 |
| 起動時に「REDscript compilation failed」ダイアログが表示 | REDscript (r6\scripts\) | スクリプト構文エラー、またはパッチで廃止された関数を古いMODが参照している | r6\logs\redscript_rCURRENT.log を開き、エラーを起こしている .reds を特定して更新または削除 |
| 追加した衣装を装備すると体が透明になる、または頭部だけ浮く | ArchiveXL またはアセット不足 | .archive ファイルの欠落、または .xl 定義ファイルが archive\pc\mod\ に存在しない | archive\pc\mod\ を確認し、ファイルが揃っているか検証。ArchiveXL.log でファクトリ未登録を確認 |
| コンソールからアイテム入手できるが、名前が空で数値が0 | TweakXL (r6\tweaks\) | YAMLファイルのインデント不正、または参照先の $base レコード名が存在しない | r6\logs\TweakXL.log のエラーログを確認し、インデントの修正や前提MODの導入を実施 |
| CETのホットキーを押してもコンソールが表示されない | CET 入力フック | キーバインド設定ファイルの破損、または他社オーバーレイ(Discord/GeForce等)との競合 | bin\x64\plugins\cyber_engine_tweaks\bindings.json を削除し、ゲームを再起動して再設定 |
| スクリプトコンパイルは通るが、メニュー読み込みで無限ロード | 循環依存またはキャッシュ破損 | スクリプト間で循環参照が発生しているか、旧バージョンのキャッシュが残留 | r6\cache\moddedOnly.redscripts と final.redscripts.bak を削除してクリーンリコンパイルを実行 |
PowerShell自動診断スクリプト:フレームワーク整合性とログ解析
MOD環境の動作状況を確認するためのPowerShell診断スクリプトです:
# サイバーパンク2077 MODフレームワーク整合性確認スクリプト
param(
[string]$GameRoot = "C:\Program Files (x86)\Steam\steamapps\common\Cyberpunk 2077"
)
Write-Host "=== サイバーパンク2077 MODフレームワーク環境チェック ===" -ForegroundColor Cyan
# 1. 主要フレームワークDLLの検証
$frameworkFiles = @{
"Cyber Engine Tweaks" = "$GameRoot\bin\x64\version.dll"
"RED4ext Core" = "$GameRoot\red4ext\bin\RED4ext.dll"
"ArchiveXL" = "$GameRoot\red4ext\plugins\ArchiveXL\ArchiveXL.dll"
"TweakXL" = "$GameRoot\red4ext\plugins\TweakXL\TweakXL.dll"
"REDscript Compiler" = "$GameRoot\engine\tools\scc.exe"
}
foreach ($name in $frameworkFiles.Keys) {
$path = $frameworkFiles[$name]
if (Test-Path $path) {
$version = (Get-Item $path).VersionInfo.ProductVersion
Write-Host "[OK] $name 検出 (バージョン: $version)" -ForegroundColor Green
} else {
Write-Host "[MISSING] $name が見つかりません: $path" -ForegroundColor Red
}
}
# 2. 最新のREDscriptログ検証
$redscriptLog = "$GameRoot\r6\logs\redscript_rCURRENT.log"
if (Test-Path $redscriptLog) {
Write-Host "`nREDscriptコンパイルログをスキャン中..." -ForegroundColor Cyan
$errors = Select-String -Path $redscriptLog -Pattern "ERROR", "FATAL" | Select-Object -First 5
if ($errors) {
Write-Host "[警告] REDscriptコンパイルエラーを検出:" -ForegroundColor Yellow
$errors | ForEach-Object { Write-Host " " $_.Line -ForegroundColor Red }
} else {
Write-Host "[OK] 最新のコンパイルログにエラーはありません。" -ForegroundColor Green
}
}
安定運用のためのベストプラクティス
- バージョン同期の徹底: CD Projekt Redの公式パッチ適用時は、関数のメモリアドレスが変化します。公式アップデート後は、CET、RED4ext、ArchiveXL、TweakXLが新バージョンに対応するまでゲームの更新を待つか、MODを無効化してください。
- バニラContentフォルダの非破壊維持:
archive\pc\content\フォルダを直接変更するレガシーMODは避け、すべてarchive\pc\mod\配下に導入するモダンMODを使用してください。 - 当てずっぽうな再インストールを避ける: クラッシュ時はまず
r6\logs\redscript_rCURRENT.logやred4ext\logs\を確認してください。Steamの「ファイルの整合性を確認」を実行すると、正常なMOD構成までリセットされる場合があります。 - ソフトウェアアーキテクチャに基づく管理: バイナリフック、仮想ファイルシステム、インメモリパッチの動作原理を理解することで、大規模なMOD構成でも安定したプレイ環境を維持できます。365Finds のような技術情報リソースを活用し、ゲームエンジンの内部構造に沿った適切な管理を行いましょう。