DeSmuMEで組み込まれているLua用API　非公式リファレンス　～memoryライブラリ～

この記事はニンテンドーDS向けエミュレータの一つである「DeSmuME」（以降Desmume）のLua用APIの非公式日本語リファレンスです。今回はmemoryライブラリについてのリファレンスです。

:::note warn
このリファレンスは非公式の日本語リファレンスです。そもそも英語のリファレンスも公式のリファレンスもありません。
さらに詳細の仕様を確認したい場合はDesmumeのソースコードを参照することを推奨します。
→https://github.com/TASEmulators/desmume/blob/master/desmume/src/lua-engine.cpp
:::

---
`memory.readbyte()`

特定メモリ番地の1byte長のメモリ値を読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800
</details>

<details><summary>戻り値</summary>

`unsigned char`型
0~255の整数が戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::

</details>

``` lua: example.lua
function fn()
local X,Y
X = memory.readbyte(0x0208AD20)
Y = memory.readbyte(0x0208AD24)

gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)

end
gui.register(fn)
```

---

`memory.readbytesigned()`
特定メモリ番地の1byte長のメモリ値を符号付で読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`signed char`型
-128～127の0を含む整数が戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::

</details>

``` lua: example.lua
function fn()
local X,Y
X = memory.readbytesigned(0x0208AD20)
Y = memory.readbytesigned(0x0208AD24)

gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)

end
gui.register(fn)

```

---

`memory.readword()`
特定メモリ番地の2byte長のメモリ値を読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`unsigned short` 型
0～65535の整数が戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::


</details>

``` lua: example.lua
function fn()
local X,Y
X = memory.readword(0x0208AD20)
Y = memory.readword(0x0208AD24)

gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)

end
gui.register(fn)
```

---

`memory.readwordsigned()`
特定メモリ番地の2byte長のメモリ値を符号付で読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`signed short`型
-32768～32767の0を含む整数が戻ってきます。


:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::


</details>

``` lua: example.lua
function fn()
local X,Y
X = memory.readwordsigned(0x0208AD20)
Y = memory.readwordsigned(0x0208AD24)

gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)

end
gui.register(fn)
```

---

`memory.readdword()`
特定メモリ番地の4byte長のメモリ値を読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`unsigned long` 型
0～4,294,967,295の整数が戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::

</details>

``` lua: example.lua
function fn()
local X,Y
X = memory.readdword(0x0208AD20)
Y = memory.readdword(0x0208AD24)

gui.text(0,10,"X: "..X)
gui.text(0,20,"Y: "..Y)

end
gui.register(fn)
```

---

`memory.readdwordsigned()`
特定メモリ番地の4byte長のメモリ値を符号付で読み込む

<details><summary>引数</summary>

読み込みたいメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`signed long` 型
-2,147,483,648~2,147,483,647の0を含む整数が戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::

</details>

``` lua: example.lua
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)
```

---
`memory.readbyterange()`

特定メモリ番地から第二引数分のメモリを1byteずつ読みこむ

<details><summary>引数</summary>

第一引数　オフセット（開始メモリ番地）
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

第二引数　読み込む長さ　（テーブルの長さにも相当する）
範囲： `int` 型
NDSのメモリマップ的に-0xFFFF800～0xFFFF800

</details>

<details><summary>戻り値</summary>

長さが第二引数のテーブルが返ってきます。
各インデックスには第一引数から第二引数分まで1byteずつ読み込んだ値を`unsigned char`型の整数で戻ってきます。

:::note warn
ゲームで実装されている型が小数型や文字型など、整数型以外でも整数として戻ってきます。
:::

:::note info
変数の宣言時の初期化で={}と書いてテーブル型に指定しておくとコードが読みやすくなると思います。もちろんLuaなので宣言しなくても問題なく動きます。　
:::


</details>

``` lua: example.lua
function fn()
local X = {}

X = memory.readbyterange(0x0208AD20,4)

gui.text(0,10,"X: "..X[1])

end
gui.register(fn)
```

---

`memory.writebyte()`

特定のメモリ番地の1byte長のメモリ値を第二引数に上書きする

<details><summary>引数</summary>

第一引数　上書きするメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

第二引数
範囲：`unsigned char`型
0~255

</details>

<details><summary>戻り値</summary>

無し　nil

</details>

``` lua: example.lua
function fn()
local X 

X = memory.writebyte(0x0208AD20,10)

end
gui.register(fn)
```

:::note info
Desmumeではメモリの上書きとしてLuaスクリプト,チート,メモリビュアー上での直接的な書き込みがサポートされています。膨大な量の書き換えや何かをトリガーとして上書きをする時にLuaスクリプトが便利です。
:::

---

`memory.writeword()`
特定のメモリ番地の2byte長のメモリ値を第二引数に上書きする

<details><summary>引数</summary>

第一引数　上書きするメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

第二引数
範囲：`unsigned short`型
0～65535

</details>

<details><summary>戻り値</summary>

無し　nil

</details>

``` lua: example.lua
function fn()
local X 

X = memory.writeword(0x0208AD20,10000)

end
gui.register(fn)
```

:::note info
Desmumeではメモリの上書きとしてLuaスクリプト,チート,メモリビュアー上での直接的な書き込みがサポートされています。膨大な量の書き換えや何かをトリガーとして上書きをする時にLuaスクリプトが便利です。
:::

---

`memory.writedword()`
特定のメモリ番地の4byte長のメモリ値を第二引数に上書きする

<details><summary>引数</summary>

第一引数　上書きするメモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

第二引数
範囲：`unsigned long`型
0~4,294,967,295

</details>

<details><summary>戻り値</summary>

無し　nil

</details>

``` lua: example.lua
function fn()
local X 

X = memory.writedword(0x0208AD20,1000000)

end
gui.register(fn)
```

:::note info
Desmumeではメモリの上書きとしてLuaスクリプト,チート,メモリビュアー上での直接的な書き込みがサポートされています。膨大な量の書き換えや何かをトリガーとして上書きをする時にLuaスクリプトが便利です。
:::

---

`memory.isvalid()`

特定メモリ番地のブール型を読み込む

<details><summary>引数</summary>

範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

</details>

<details><summary>戻り値</summary>

`boolean`型
true or falseで戻ってきます。

</details>

``` lua: example.lua
function fn()
local X

X = memory.isvalid(0x0208AD20)

if x then

gui.text(0,10,string.format("True"))

else

gui.text(0,10,string.format("False"))

end

end
gui.register(fn) 
```

---

`memory.getregister()`
任意のレジストリの値を取得する

<details><summary>引数</summary>

CPU名.レジストリ名で指定します。
CPU名は`arm9` `arm7`で指定します。`main` `sub`でも指定できます。
CPU名は省略可能で省略した場合はARM9が指定されます。
レジストリ名は
`r0` `r1` `r2` `r3` `r4` `r5` `r6` `r7` `r8` `r9`
`r10` `r11` `r12` `r13` `r14` `r15` `cpsr` `spsr`
が指定できます。

</details>

<details><summary>戻り値</summary>

レジストリ名が正しくない場合　nilが戻ってきます。
1byteのレジストリ　`unsigned char`型　0~225の整数が戻ってきます。
2byteのレジストリ　`u16`型  0~65535の整数が戻ってきます。
4byteのレジストリ　`u32`型　0~4,294,967,295の整数が戻ってきます。

</details>

``` lua: example.lua
function fn()
local reg

reg = memory.getregister("main.r0")

gui.text(0,10,"r0: "..reg)

end
gui.register(fn) 
```

---

`memory.setregister()`
第一引数のレジスタの値を第二引数の値に上書きする

<details><summary>引数</summary>

第一引数
CPU名.レジストリ名で指定します。
CPU名は`arm9` `arm7`で指定します。`main` `sub`でも指定できます。
CPU名は省略可能で省略した場合はARM9が指定されます。
レジストリ名は
`r0` `r1` `r2` `r3` `r4` `r5` `r6` `r7` `r8` `r9`
`r10` `r11` `r12` `r13` `r14` `r15` `cpsr` `spsr`
が指定できます。

第二引数
範囲：`unsigned long`型
0~4,294,967,295

</details>

<details><summary>戻り値</summary>

無し　nil

</details>

``` lua: example.lua
function fn()
local reg

reg = memory.setregister("main.r0",10)

end
gui.register(fn) 
```

:::note warn
このサンプルコードそのままではフリーズします。条件に応じて書き込むようにすべきです。
:::


---

`vram.readword()`
特定のVRAM範囲のメモリ番地の2byte長のメモリ値を読み込む

<details><summary>引数</summary>

範囲：`int`型
VRAMの範囲は0x06000000~0x068A0000のはずだがnilが返ってくるため調査中

</details>

<details><summary>戻り値</summary>

`u16`型
0~65535の整数が戻ってきます。

</details>

``` lua: example.lua
--すみません調査中です。(引数に詳細)
```
:::note alert
追記が必要な個所です。　分かる人いれば編集権限リクエストしてください

:::

---

`vram.writeword()`
特定のVRAM範囲のメモリ番地の2byte長のメモリ値を第二引数に上書きする

<details><summary>引数</summary>

第一引数　上書きするメモリ番地
範囲： `int` 型　
VRAMの範囲は0x06000000~0x068A0000のはずだが動作しているのか分からない（`vram.readword`で確認できない）ので調査中

第二引数
範囲：`u16`型
0～65535

</details>

<details><summary>戻り値</summary>

無し　nil

</details>

``` lua: example.lua
--すみません調査中です。(引数に詳細)
```

:::note alert
追記が必要な個所です。　分かる人いれば編集権限リクエストしてください
:::

---

`memory.registerwrite()`
任意のメモリでの書き込みが発生した時に第四引数(第二引数)の関数を実行する。


<details><summary>引数</summary>

第一引数　メモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

[第二引数:オプション]　メモリサイズ
デフォルト:1

[第三引数：オプション]　CPU名
デフォルト:main
`main` `sub` `arm9` `arm7`が指定可能

第四引数　実行する関数


</details>

<details><summary>戻り値</summary>

第4引数の関数の実行

</details>

``` lua: example.lua
function fn()

memory.registerwrite(0x0208AD20,print)

end

function print()

gui.text(0,10,string.format("Hello World!"))

end

gui.register(fn) 
```


:::note warn
必ず元の関数に戻るように書いてください。　実行先の関数で無限ループをしないように注意すべきです。
:::


:::note alert
`memory.registerwrite failed: function is not available in this build.`が出た場合はそのバージョンでは使えないので他のバージョンのビルドを使用してください。例えば0.9.11を使用しているなら0.9.13を使用してください。
:::

---

`memory.registerread()`
任意のメモリでの読み込みが発生した時に第四引数(第二引数)の関数を実行する。

<details><summary>引数</summary>

第一引数　メモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

[第二引数:オプション]　メモリサイズ
デフォルト:1

[第三引数：オプション]　CPU名
デフォルト:main
`main` `sub` `arm9` `arm7`が指定可能

第四引数　実行する関数


</details>

<details><summary>戻り値</summary>

第4引数の関数の実行

</details>

``` lua: example.lua
function fn()

memory.registerread(0x0208AD20,print)

end

function print()

gui.text(0,10,string.format("Hello World!"))

end

gui.register(fn) 


```
:::note warn
必ず元の関数に戻るように書いてください。　実行先の関数で無限ループをしないように注意すべきです。
:::


:::note alert
`memory.registerwrite failed: function is not available in this build.`が出た場合はそのバージョンでは使えないので他のバージョンのビルドを使用してください。例えば0.9.11を使用しているなら0.9.13を使用してください。
:::


---


`memory.registerexec()`
任意のメモリでの実行が発生した時に第四引数(第二引数)の関数を実行する。



<details><summary>引数</summary>

第一引数　メモリ番地
範囲： `int` 型　
NDSのメモリマップ的に0x00000000～0xFFFF800

[第二引数:オプション]　メモリサイズ
デフォルト:2

[第三引数：オプション]　CPU名
デフォルト:main
`main` `sub` `arm9` `arm7`が指定可能

第四引数　実行する関数


</details>

<details><summary>戻り値</summary>

第4引数の関数の実行

</details>

``` lua: example.lua
function fn()

memory.registerexec(0x0208AD20,print)

end

function print()

gui.text(0,10,string.format("Hello World!"))

end

gui.register(fn) 


```

:::note warn
必ず元の関数に戻るように書いてください。　実行先の関数で無限ループをしないように注意すべきです。
:::


:::note alert
`memory.registerwrite failed: function is not available in this build.`が出た場合はそのバージョンでは使えないので他のバージョンのビルドを使用してください。例えば0.9.11を使用しているなら0.9.13を使用してください。
:::

---
代替名一覧
以下の関数でコードを書いても右側の関数として認識されます。
`readbyteunsigned()`→`memory_readbyte()`
`readwordunsigned()`→`memory_readword()`
`readdwordunsigned()`→`memory_readdword()`
`readshort()`→`memory_readword()`
`readshortunsigned()`→`memory_readword()`
`readshortsigned()`→`memory_readwordsigned()`
`readlong()`→`memory_readdword()`
`readlongunsigned()`→`memory_readdword()`
`readlongsigned()`→`memory_readdwordsigned()`
`writeshort()`→`memory_writeword()`
`writelong()`→`memory_writedword()`
`register()`→`memory_registerwrite()`
`registerrun()`→`memory_registerexec()`
`registerexecute()`→`memory_registerexec()`