logo
ja
日本語

SKSE プラグインのアドレスライブラリ

クリエイター: meh321
更新済み:2020-02-24 19:31:54
2.8MB
mcafee
認証
200,000,000+ ユーザーに信頼されています

このモッドについて

SKSE DLL プラグインのバージョンを簡単に独立させるためのヘッダーファイルとデータベースが含まれています.
重要!現在、Special Edition (1.5.x) と Anniversary Edition (1.6.x) の2つのバージョンに分割されています。これらの2つのバージョン間では、アドレスを指すIDは一致しません(ゲームの実行ファイルがあまりにも異なるため一致しませんし、一致したとしても関数内のコードはいずれにしても異なります)。

説明

通常の MOD ユーザーの場合:ファイルセクションから「オールインワン」パッケージをダウンロードしてインストールしてください。modマネージャーを使用するか、手動でインストールできます。.binファイルはここに配置してください。
データ/SKSE/プラグイン/
残りの部分を読む必要はありません。

SKSE DLLプラグイン作成者向け:
これはモッダーリソース(ヘッダーファイル)です。オフセットを格納するデータベースをロードすることで、DLLプラグインを再コンパイルすることなくバージョンに依存しない状態にすることができます。ヘッダーファイルはファイルのオプションセクションからダウンロードできます。Anniversary Editionの場合、ヘッダーファイルはversiondb.hではなくversionlibdb.hです。CommonLibを使用している場合は、これらはすべて既に組み込まれているため、ここから追加する必要はありません。


使い方

最も早い方法:
ネタバレ:
見せる


#include "versiondb.h"

void * MyAddress = NULL;
符号なしlong long MyOffset = 0;

ブール型InitializeOffsets()
{
// スタックに割り当てて、この関数を終了するときにアンロードされるようにします。
// データベース全体をロードして、理由もなくメモリを消費する必要はありません。
バージョンデータベースdb;

// 現在の実行可能バージョンでデータベースを読み込みます。
if (!db.Load())
{
_FATALERROR("現在の実行可能ファイルのバージョンデータベースの読み込みに失敗しました!");
false を返します。
}
それ以外
{
// "SkyrimSE.exe", "1.5.97.0"
_MESSAGE("%s バージョン %s のデータベースをロードしました。", db.GetModuleName().c_str(), db.GetLoadedVersionString().c_str());
}

// このアドレスにはモジュールのベース アドレスがすでに含まれているため、アドレスを直接使用できます。
私の住所 = db.FindAddressById(123);
(MyAddress == NULL)の場合
{
_FATALERROR("アドレスが見つかりませんでした!");
false を返します。
}

// このオフセットにはベースアドレスは含まれません。実際のアドレスはModuleBase + MyOffsetになります。
if (!db.FindOffsetById(123, MyOffset))
{
_FATALERROR("私のもののオフセットが見つかりませんでした!");
false を返します。
}

// すべて成功しました。
true を返します。
}



さて、この「123」という値は一体何なのか、と疑問に思われるかもしれません。これは住所のIDです。異なるバージョンのデータベースでは、同じ住所のIDは同じでも、異なる値を指す場合があります。特定のバージョンのIDと値のペアのリストを取得するには、以下のコマンドを実行してください。

ネタバレ:
見せる


#include "versiondb.h"

ブールダンプ特定バージョン()
{
バージョンデータベースdb;

// 実行中の実行可能ファイルのバージョンに関係なく、バージョン 1.5.62.0 のデータベースをロードしようとします。
if (!db.Load(1, 5, 62, 0))
{
_FATALERROR("1.5.62.0 のデータベースの読み込みに失敗しました!");
false を返します。
}

// offsets-1.5.62.0.txt というファイルを書き出します。各行は ID とオフセットです。
db.Dump("offsets-1.5.62.0.txt");
_MESSAGE("1.5.62.0 のオフセットをダンプしました");
true を返します。
}



1, 5, 62, 0 の代わりに、リバース対象のSKSEのバージョン番号を入力してください。対応するデータベースファイルが/Data/SKSE/Pluginsディレクトリにある必要があります。

これを実行すると、Skyrimのメインディレクトリに「offsets-1.5.62.0.txt」または任意のファイル名の新しいファイルが作成されます。各行は以下の形式になります。
10進数ID六角オフセット

たとえば、1.5.62.0 にアドレス 142F4DEF8 (プレイヤー キャラクターの静的ポインター) があり、これをバージョン非依存にしたい場合は、次のようにします。
1. オフセットファイルで2F4DEF8を検索します。これはベース140000000を除いたオフセットです。
2. ID が 517014 (10 進数) であることを確認します。
3. 実行時にこのアドレスを DLL に含める場合は、次のようにします。


void* addressOf142F4DEF8 = db.FindAddressById(517014);


これで完了です。

VersionDb 構造体には次の機能があります。
ネタバレ:
見せる


bool Dump(const std::string& path); // 現在ロードされているデータベースをファイルにダンプする
bool Load(int major, int minor, int revision, int build); // Data/SKSE/Plugins ディレクトリに db-major-minor-revision-build.bin が存在する場合は特定のバージョンをロードします
bool Load(); // 現在のアプリケーションのバージョンをロードする
void Clear(); // 現在ロードされているデータベースをクリアする
void GetLoadedVersion(int& major, int& minor, int& revision, int& build) const; // 現在ロードされているデータベースファイルのバージョンを取得します
bool GetExecutableVersion(int& major, int& minor, int& revision, int& build) const; // 現在実行中のアプリケーションのバージョンを取得します
const std::string& GetModuleName() const; // 現在ロードされているデータベースモジュールの名前を取得します。「SkyrimSE.exe」と表示されます。
const std::string& GetLoadedVersionString() const; // 現在ロードされているバージョンを文字列として取得します。例: "1.5.62.0"
定数std::map& GetOffsetMap() const; // 手動で反復処理する必要がある場合は、ID とオフセットのマップを取得します。
void* FindAddressById(unsigned long long id) const; // IDでアドレスを検索します。ベースアドレスが既に含まれており、正しいアドレスです。見つからない場合はNULLを返します。
bool FindOffsetById(unsigned long long id, unsigned long long& result) const; // ID でオフセットを検索します。これはベースを含まないオフセットのみになります。
bool FindIdByAddress(void* ptr, unsigned long long& result) const; // アドレスからIDを検索します。これにより、アドレスをIDに変換するための逆引き検索が試行されます。
bool FindIdByOffset(unsigned long long offset, unsigned long long& result) const; // オフセットでIDを検索します。これにより、オフセットをIDに変換するための逆引き検索が試行されます。



知っておくべきこと、心に留めておくべきこと:

1. データベースファイルのいずれか(またはすべて)をプラグインに含めることは可能ですが、ファイルサイズが大幅に増加する可能性があります(約2.5MB)。これまでは、このモジュールを依存関係としてマークすることが一般的でした。

2. データベースは起動時に必ず一度だけ読み込み、必要なアドレスを初期化/キャッシュしてアンロードしてください。アンロードとは、VersionDb構造体が削除または失われることを意味します(スタック上に割り当てた場合)。これにより、ゲーム実行中に不要なメモリ使用量が削減されます。ゲームプレイ中はデータベースをロードしたままにする必要はありません。CommonLibを使用する場合、これは問題になりません。CommonLibはDLLごとにデータベースを読み込むのではなく、一度だけ読み込むからです。

3. データベースには、関数、グローバル変数、RTTI、vtable、その他参照される可能性のあるすべてのアドレスが含まれます。関数の途中やグローバル変数の途中にあるアドレスは含まれません。関数の途中にあるアドレスが必要な場合は、関数のベースアドレスを参照し、オフセットを自分で追加する必要があります。また、関数のアライメント(rdataで参照される)などの不要な情報も含まれません。pdataセクションは破棄され、rdataからコンパイラによって生成されたSEH情報も破棄されます。

4. 結果は常にチェックし、データベースが正常にロードされたか(bool Load が true を返したか)、クエリしたアドレスが実際に有効な結果(NULL ではない)を返したかを確認する必要があります。ロードに失敗した場合は、ファイルが見つからないか、バージョンが間違っている可能性があります(例:AE で SE ヘッダーを使用しようとしている)。クエリが失敗した場合は、そのバージョンでアドレスが見つからなかったことを意味します。これは、ゲームコードが変更されたためにアドレスがそのバージョンで有効でなくなったか、データベース自体が正しいアドレスを検出できなかったことを意味します。これらのどちらかが発生した場合は、プラグインの初期化を失敗させて、SKSE に正しくロードされなかったことを通知する必要があります。または、手動でエラーメッセージを表示してください。

5. DLLプラグインを公開する前に、ゲームの全バージョンにアドレスが存在することを確認することをお勧めします。そのためには、データベースファイルの各バージョンを読み込み、各バージョンで同じアドレスIDをクエリして、存在するかどうかを確認してください。
ネタバレ:
見せる


ブールLoadAll(std::vector& 全て)
{
静的intバージョン[] = { 3, 16, 23, 39, 50, 53, 62, 73, 80, 97, -1 };
(int i = 0; バージョン[i] >= 0; i++)
{
バージョンデータベース * db = 新しいバージョンデータベース();
if (!db->Load(1, 5, バージョン[i], 0))
{
dbを削除します。
false を返します。
}
all.push_back(db);
}
true を返します。
}

ブール型 ExistsInAll(std::vector& すべて、unsigned long long id)
{
unsigned long long 結果 = 0;
(自動データベース: すべて)
{
if (!db->FindOffsetById(id, result))
false を返します。
}
true を返します。
}

void FreeAll(std::vector& 全て)
{
(自動データベース: すべて)
dbを削除します。
すべてクリア();
}

ブール型IsOk()
{
std::vector全て;
if (!LoadAll(すべて))
{
_FATALERROR("現在の実行可能ファイルの 1 つ以上のバージョン データベースの読み込みに失敗しました!");
FreeAll(すべて);
false を返します。
}

if (!ExistsInAll(すべて、517014))
{
_FATALERROR("517014 はデータベースのすべてのバージョンに存在しません!");
FreeAll(すべて);
false を返します。
}

FreeAll(すべて);
// わかりました!
true を返します。
}



この方法により、DLL モッドがすべてのバージョンで動作することを確認できます。また、一部のバージョンで動作しない場合は、その旨をモッド ページに書き込むことができます。

6. 実行中のゲームのバージョンに応じて異なる処理を実行する必要がある場合があります。その場合は、次のコードスニペットを使用します。
ネタバレ:
見せる


int メジャー = 0、マイナー = 0、リビジョン = 0、ビルド = 0;
if (!db.GetExecutableVersion(メジャー、マイナー、リビジョン、ビルド))
{
_FATALERROR("問題が発生しました!");
false を返します。
}

// 実行中のゲームは 1.5.x であり、少なくともバージョン 1.5.39.0 です
if (メジャー == 1 && マイナー == 5 && リビジョン >= 39)
{
// もの ... ?
}



7. SKSE DLLをデバッグモードでコンパイルすると、データベースの読み込み時間は約14秒かかる場合があります。リリースモードでは約0.2秒です。これは、標準ライブラリコンテナ(std map)の読み込み速度が非常に遅いためです。


権限

何でも好きなようにしてください。

Multiverse Loot Hunter向けトップモッド

Multiverse Loot Hunter向けの最高のモッドを探検しよう。新しい機能、向上したグラフィック、そしてゲームプレイ体験を変える刺激的な方法を提供します。

XmodでMultiverse Loot Hunterの可能性を最大限に引き出そう — これらのトップモッドを今日チェック!

mcafee
認証
200,000,000+ ユーザーに信頼されています

ダウンロードやインストールでお困りですか?サポートのためにDiscord コミュニティに参加してください!

logo
言語

ゲームソリューション

リソース

パートナー

フォローしてください

discordfacebooktwitteryoutube
dc@xmodhub.com or cathy@business.xmodhub.com
Discord: catherine_79237
利用規約
プライバシーポリシー
サポート

Larvas Limited

Room 1201, 12/F Tai Sang Bank Building 130-132 Des Voeux Road Central HK