DeSmuMEでLuaスクリプトやmemory searchを使用しメモリ値を監視している際、挙動はそれっぽいのに中身の値が大きな値が出てしまうことがあります。 それはおそらく型の問題である場合がほとんどです。 この記事では2種類の対処法を記します。
まずは以下のLuaスクリプトを咲かせて!ちびロボ!を起動した状態で動かしてください。
無い場合は画像をご覧ください。
local function fn()
local W
W = memory.readdword(0x02383CD4)
gui.text(0,0,"W: "..W)
end
gui.register(fn)
ある程度ゲームを進め、パーク内に入ってエミュレーターを一時停止させてください。(画像の例はまあまあ進んでいる状態ですが、チュートリアルの状態でも大丈夫です。)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3673555%2F0434e774-3e62-3c3d-c8f4-093cd519c439.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=85e18c3d75c0be7469cd29c864d1583f)
なんだかバカでかい数字が出てきました。その挙動からちびロボ!のワッツ数(右上に表示されているやつ)であることは明らかですがそれにしても大きな数字です。
float型で対応
非公式リファレンスのmemoryライブラリ
を確認すると、memory.readword()は数値型で受け取っていることが分かります。そこで以下のコードを使ってfloat型に変換をして表示をしてみます。float型の変換は以下の関数を用意して毎回呼び出すのがいいでしょう。
local function convf(addr)
local n,s,e,f = 0
n = memory.readdword(addr)
s = (-1)^bit.arshift(n,31)
e = bit.band(bit.arshift(n,23),0xFF) - 127
f = 1 + bit.band(n, 0x7FFFFF) / 0x800000
return s*f*2^e
end
function fn()
local W
W = convf(0x02383CD4)
gui.text(0,10,"W: "..W)
end
gui.register(fn)
出力結果として以下の図のようになりました。綺麗な数値になりました。
有効桁数が多すぎて見にくい場合は、gui.text(0,10,string.format("W:%07.3f",W))
などstring.format()
で文字列出力フォーマットを揃えるといいと思います。
decimal型で対応
ニンテンドーDSではfloat型以外にも固定小数点型(整数部:20bit 小数部:12bit)に対応しており、ゲームの変数によってはそちらで計算されていることがあります。例えばNewスーパーマリオブラザーズを起動し、コースにいる時以下のコードを実行してください。
function fn()
local X,Y
X = memory.readdwordsigned(0x0208AD20)
Y = memory.readdwordsigned(0x0208AD24)
gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)
end
gui.register(fn)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3673555%2F173ebac0-63ed-9300-72bb-7e28f9d6c38b.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=844ac2e51f207c7bb96735e7f46a5f13)
それっぽい数値が表示されました。ここでゲームを再開しマリオを動かしてみてください。XY座標どちらもマリオの動きに合わせて増減しており、カメラもしくはマリオの座標が格納されていることが確信できます。それにしても値が大きいです。
選択しているものはY座標ですが、この時の下部フロート{20.12}:
を確認するとなんだかそれっぽい数値が書いてあります。おそらくこの変数は固定小数点型で宣言されていると思われます。
この場合スケールを合わせればいいので0x1000で割ります。以下のコードがコード例です。
function fn()
local X,Y
X = memory.readdwordsigned(0x0208AD20)
Y = memory.readdwordsigned(0x0208AD24)
gui.text(0,10,"X: "..X/0x1000)
gui.text(0,20,"Y: "..Y/0x1000)
end
gui.register(fn)
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3673555%2Ff493e7b3-ca19-e7b6-bd96-5368d850007a.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=b344f22ea36903ccd3d1dee6fbd1c13d)
とてもそれっぽくなりました。有効桁数が多すぎて見にくい場合は、gui.text(0,10,string.format("X: %07.3f",X/0x1000))
などstring.format()
で文字列出力フォーマットを揃えるといいと思います。