PR
[PR]アフィリエイト広告を利用しています
[PR]アフィリエイト広告を利用しています

【中級】BizHawk LuaでゲームのHPバーを画面オーバーレイ表示する|取得したメモリアドレスをgui.textで常時表示(試行錯誤ログ)

BizHawk LuaでHPバーを画面オーバーレイ表示するイメージ Lua・自動化プログラミング

【PR】本記事にはアフィリエイトリンク(Amazonアソシエイト)を含みます。難易度:中級★★☆/対象環境:BizHawk 2.9〜2.10(Windows 10/11・EmuHawk・Lua Console)

【技術検証に関する法的注意事項・免責事項】
本記事にはは掲載されているメモリ解析、Luaスクリプト実行、およびAIコード生成に関する技術情報は、自らが所有するゲームソフトおよびオフライン環境における技術研究・教育目的の検証記です。著作権法第47条の3に配慮し、複製ROMの配布、コピーガードの回避(DRM解除)、オンライン環境での不正操作(BOT化)等に関する情報は一切取り扱いません。掲載情報の実行によって生じた損害について、当ブログは一切の責任を負いかねます。

BizHawkのLuaで、RAM Searchで特定したHPアドレスを読み取り、画面左上に「HPバー」として常時オーバーレイ表示する最小の手順をまとめます。使う関数はmemory.read_u16_le()(値の読み取り)とgui.drawRectangle()gui.text()(描画)の3つだけ。ポイントは、描画を毎フレーム呼び直すことと、座標のズレ・点꼅(チラつき)をemu.frameadvance()のループ設計で解消することです。コピペで動く最終コードと、Claudeに書かせてエラーを直していった試行錯誤ログを載せます。値の「特定」がまだの場合は、下の関連記事(RAM Search編)を先に読むとスムーズです。

完成形GIF(後日追記):HP値の増減に合わせて左上のバーが伸縮する様子を、オーナーによる実機検証後に掲載予定です。本記事は技術的に正しい概念版として先行公開しています。

前提環境と、この記事でやること

この記事は「RAM Searchでアドレスはもう特定した。あとはそれを画面に見やすく出したい」という段階の人向けです。まだアドレスを探せていない場合は、下の関連記事(RAM Search編)を先に済ませてから戻ってきてください。

項目 内容
エミュレータ BizHawk 2.9〜2.10(EmuHawk)
OS Windows 10 / 11
使う機能 Lua Console(Tools → Lua Console)
前提データ RAM Searchで特定済みのHPアドレス(本記事では仮に 0x00XXXX と表記)
難易度 中級★★☆(Luaの基本ループとメモリ読取が分かればOK)
使用ソフト 自分が所有するゲームソフトのみ(オフライン環境)

0x00XXXX はプレースホルダです。実際のアドレスはゲーム・リビジョンごとに異なるため、必ずご自身のRAM Searchで特定した値に置き換えてください。確定アドレスの実測例はオーナーの事後検証で追記します。

メモリ読取→Lua描画→画面オーバーレイの3ステップ概念図
図:HPバー オーバーレイ表示の3ステップ(メモリ読取→Lua描画→画面オーバーレイ)

試行錯誤プロセス:AIにHPバーのLuaを書かせて、詰まりを直していく

ステップ1:目的を決める

やりたいことを一文にします。「特定済みのHPアドレスの値を毎フレーム読み、画面左上に数値とバーで常時表示する」。これをそのままAI(Claude)へのプロンプトにします。曖昧なまま投げると汎用的なサンプルが返るので、アドレス・読み取りサイズ・表示位置・表示形式を具体で渡すのがコツです。

ステップ2:Claudeへの実プロンプト

BizHawk(EmuHawk)のLuaで、次の仕様のスクリプトを書いてください。
- アドレス 0x00XXXX から2バイト(リトルエンディアン)でHP値を読む
- HPの最大値は仮に 9999 とする
- 画面左上(x=8, y=8)に「HP: 現在値」をテキストで表示
- その下に、最大値に対する現在値の割合で横バーを描画する
- 毎フレーム更新し続ける
- BizHawk 2.9 の client/gui/memory/emu APIを使う

ステップ3:最初に返ってきたコード(未修正)

AIは、だいたい次のような素直なコードを返してきます。まずはこれをLua Consoleで動かして、何が起きるかを見ます。

-- v1: 最初の生成コード(このあと2箇所つまずく)
local addr = 0x00XXXX
local hpMax = 9999

local hp = memory.read_u16_le(addr)
local ratio = hp / hpMax
gui.text(8, 8, "HP: " .. hp)
gui.drawRectangle(8, 26, 120, 10, 0xFF000000, 0xFF33D0FF)
gui.drawRectangle(8, 26, math.floor(120 * ratio), 10, 0xFF000000, 0xFF9BE15D)

ステップ4:動かした結果と、2つのエラー

このv1を実行すると、次の症状が出ました。

  • 症状A:一瞬しか表示されない/すぐ消える。 描画はしているのに、1フレーム分で終わってしまう。
  • 症状B:ゲームを進めてもバーが動かない。 HP値が変わっても表示が更新されない。

原因はどちらも同じで、「1回だけ描いて終わっているから」です。BizHawkのgui.textgui.drawRectangleは「そのフレームに1回描く」命令なので、毎フレーム描き直すループが必要です。ここをAIに追加で直してもらいます。

ステップ5:修正プロンプトと、直ったコード

今のコードは一瞬で消えます。while true と emu.frameadvance() で
毎フレーム描画し続けるループにしてください。値の読み取りもループ内で行い、
HPが最大値を超えたり0未満になっても割合が0〜1に収まるようにしてください。

この指示で、ループと値のクランプ(0〜1に丸める処理)が入り、症状A・Bが両方解消しました。

ステップ6:座標ズレ・点滅(チラつき)の微調整

ループ化で常時表示にはなったものの、環境によっては次の細かい詰まりが残ります。ここは「AIの一発回答」より、自分で数値を触って合わせるのが速い部分です。

症状 原因 直し方
バーが画面外/位置が微妙 解像度・表示倍率で原点感覚がズレる x, y を8刻みで調整。まず左上(8,8)基準で合わせる
文字とバーが重なる 行間が足りない バーのyをテキストより18px以上下げる
たまにチラつく 描画順とフレーム更新の噛み合わせぬアループ 読み取り→描画→emu.frameadvance()の順を固定する

色は0xAARRGGBB(先頭2桁が不透明度)で指定します。当ブログの配色に寄せるなら、枠は不透明の黒0xFF000000、背景バーはシアン0xFF33D0FF、HPバー本体はライムグリーン0xFF9BE15Dあたりが視認性が高くおすすめです。

コピペで動く最終スクリプト

下記が最終形です。addrhpMaxだけ自分の値に書き換えれば、そのまま常時オーバーレイ表示になります。BizHawkの Tools → Lua Console → 新規スクリプトに貼り付けて実行してください。

-- BizHawk Lua: HPバー 常時オーバーレイ表示(最小テンプレ)
-- 使い方: addr と hpMax を自分の値に置き換えて実行
local addr  = 0x00XXXX   -- RAM Searchで特定したHPアドレスに置換
local hpMax = 9999       -- そのゲームのHP最大値に置換

local X, Y = 8, 8        -- 左上の表示基準
local BAR_W, BAR_H = 120, 10

while true do
  -- 1) 値を読む(2バイト・リトルエンディアン)
  local hp = memory.read_u16_le(addr)

  -- 2) 割合を0〜1にクランプ
  local ratio = hp / hpMax
  if ratio < 0 then ratio = 0 end
  if ratio > 1 then ratio = 1 end

  -- 3) 描画(テキスト → バー枠 → バー本体)
  gui.text(X, Y, string.format("HP: %d / %d", hp, hpMax))
  gui.drawRectangle(X, Y + 18, BAR_W, BAR_H, 0xFF000000, 0xFF33D0FF)
  gui.drawRectangle(X, Y + 18, math.floor(BAR_W * ratio), BAR_H, 0xFF000000, 0xFF9BE15D)

  -- 4) 1フレーム進める(このループが常時表示の肝)
  emu.frameadvance()
end

memory.read_u16_leは「2バイト値」を読む例です。HPが1バイトのゲームならmemory.read_u8、4バイトならmemory.read_u32_leに変えてください。読み取りサイズはRAM Search時に判明しているはずです。

よくあるエラーと対処

Q. 実行した瞬間にエミュが固まる/操作できない

while true do ... end の中にemu.frameadvance()(またはemu.yield())が入っていないと、無限ループでフレームが進まず固まります。ループ内に必ず1回だけemu.frameadvance()を入れてください。

Q. 値がいつも0、または明らかに変な数字になる

アドレスか読み取りサイズが合っていません。0x00XXXXを自分のRAM Searchで確定した値に置き換え、1バイト/2バイト/4バイトの読み取り関数を実際のサイズに合わせてください。メインメモリ以外のドメインを読む場合はmemory.usememorydomain()でドメイン指定が要ることもあります。

Q. バーの色が思った通りにならない

色は0xAARRGGBB形式です。先頭のAA(不透明度)を00にすると透明で見えません。まずは0xFF始まりで指定してください。

Q. スクリプトを止めたい

Lua Consoleの「Stop」ボタン(または該当スクリプトのチェックを外す)で停止します。閉じても残る場合はConsoleを一度閉じてください。

まとめ

HPバーのオーバーレイ表示は、①memory.read_*で値を読む、②gui.textgui.drawRectangleで描く、③emu.frameadvance()のループで毎フレーム描き直す——この3点が骨格です。詰まりどころは「1回しか描いていない(=ループ化)」と「座標・色の微調整」に集約されます。AIには仕様を具体で渡し、返ってきたコードを実際に動かして症状ベースで直していくのが、結局いちばん速い進め方でした。

次に読む(関連記事)

まだHP・座標のアドレスを特定していない人は、まずこちら(値の「特定」編)。本記事はその続き(特定した値の「表示」編)です。

【中級】BizHawk RAM SearchでゲームのHP・座標アドレスを特定する手順|AIにアドレス候補を絞らせる試行錯誤ログ付き
BizHawkのRAM Searchで、ゲーム内のHPやキャラの座標が入っているメモリアドレスを自分で特定する手順を解説。AIに絞り込み条件を設計させ、候補がヒットしない失敗の立て直しまで記録した中級向けのメモリ解析・状態検証ガイドです。

メモリ値の読み取り・画面表示の基礎から確認したい人はこちら。

【入門】BizHawk×Lua×AI(Claude)でゲームのメモリ値を画面表示する最小テンプレ|RAM Searchで所持金アドレスを特定する手順
BizHawkのRAM Searchで所持金アドレスを特定し、Claudeに書かせたLuaで値を画面に常時表示する最小テンプレを解説。改造ではなくメモリ解析・状態検証の入門です。

エミュレータ側の基本操作・メニューの使い方はこちら。

Mesen2 メニューの使い方【Windows 10/11・Mesen 2.x】|Fileメニューの開き方・セーブステート保存/読込・前回セッション復元まで完全ガイド
Mesen2のメニューはウィンドウ最上部にあり、まず覚えるのはFileだけで十分です。Open・Save State・Load State・Load Last Session・Recent Files・Exitの全項目を日本語対訳つきで解説し、上書き事故を防ぐスロット運用、日本語UIの有無、セーブステートが読めなくなる原因までまとめました。

実験環境・学習用の道具(PR)

Amazonのアソシエイトとして、当ブログは適格販売により収入を得ています。

Lua+メモリ解析の実験を快適にするなら、処理落ちしないゲーミングPCや、検証画面をきれいに記録するキャプチャボードがあると捗ります。

教材

「コピペで動く最小Lua集(メモリ監視・オーバーレイ・入力自動化)」を教材としてのnoteにまとめています(準備中・公開後にリンク追加)。本記事のコードもこのキットに収録予定です。

この記事の親ガイド

【初級★☆☆】PCでレトロゲームを遊ぶ 完全ガイド|何から始めるか5ステップ
PCで昔のゲームを遊びたいけれど何から始めればいいか分からない方へ。①前提の確認→②何で遊ぶか決める→③PCとコントローラー→④画面に映す→⑤AIで解析・制御する、の5ステップで全体像を整理しました。各ステップの詳しい手順記事へ案内する地図として使えます。自己所有ソフト・オフライン環境での技術検証を前提としています。

【予告】この5工程で使うスクリプトをまとめた「コピペで動くLua集+環境構築キット」を配布予定です。価格・配布日は未定で、決まり次第この記事に追記します。

【中級★★☆】ゲームのメモリ解析は5ステップで内部の数値が読める|BizHawk×Lua×AI 手順の全体像
ゲームのメモリ解析は5工程しかありません。①読み出せる状態をつくる ②目的の数値がどこにあるかを絞り込む ③読んだ数値を画面に出し続ける ④AIにコードを書かせて往復を削る ⑤自動化して実験する。この記事は手順そのものではなく「いまどの工程にいるか」「次にどの記事を開くか」を示す地図です。開始地点を事実だけで判定する4問チャート付き。自己所有ソフト・オフライン環境が前提です。

コメント