# 拡張ポイントと開発者リファレンス — auxcode・hexfile・デバッグ・help

> auxcode/auxcode.c の補助コードライブラリ拡張インタフェース (aux_statements / aux_int_functions 等)、hexfile.c の Intel HEX 直接実行機能 (runHex)、pcconnect.c の PC シリアルプロトコル、debug.c のデバッグユーティリティ、help.c の組み込みヘルプ辞書、開発者が新規ライブラリを追加する際の手順と注意点をまとめます。

- Repository: machikania/phyllosoma
- GitHub: https://github.com/machikania/phyllosoma
- Human wiki: https://grok-wiki.com/public/wiki/machikania-phyllosoma-fab169c4381c
- Complete Markdown: https://grok-wiki.com/public/wiki/machikania-phyllosoma-fab169c4381c/llms-full.txt

## Source Files

- `auxcode/auxcode.c`
- `auxcode/auxcode.cmake`
- `hexfile.c`
- `pcconnect/pcconnect.c`
- `debug.c`
- `help.c`

---

<details>
<summary>関連するソースファイル</summary>
このWikiページの生成に使用したファイル:
- [auxcode/auxcode.c](auxcode/auxcode.c)
- [auxcode/auxcode.cmake](auxcode/auxcode.cmake)
- [hexfile.c](hexfile.c)
- [pcconnect.c](pcconnect.c)
- [debug.c](debug.c)
- [help.c](help.c)
- [debug.h](debug.h)
- [compiler.h](compiler.h)
- [CMakeLists.txt](CMakeLists.txt)
- [statements.c](statements.c)
- [integer.c](integer.c)
- [string.c](string.c)
- [float.c](float.c)
- [library.c](library.c)
- [withoutkeyboard.c](withoutkeyboard.c)
- [main.c](main.c)
</details>

# 拡張ポイントと開発者リファレンス — auxcode・hexfile・デバッグ・help

このページは、Phyllosoma (KM-BASIC for ARM) の**コンパイラ拡張レイヤー**と**開発者向けユーティリティ**を解説します。対象は、新しい BASIC ステートメント／関数を追加したい組み込みライブラリ開発者、Intel HEX ファイルを直接実行する仕組みを理解したい方、PC との USB シリアルプロトコルを把握したい方、デバッグモードやヘルプ辞書を活用したい方です。

組み込み機能はすべて固定のディスパッチテーブルに列挙されていますが、`aux_statements` / `aux_int_functions` / `aux_str_functions` / `aux_float_functions` / `lib_aux` の 5 関数だけが**意図的な拡張スタブ**として `auxcode/auxcode.c` に切り出されています。これらを差し替えるだけで、ビルドシステムを最小限しか変更せずに新規機能を追加できます。

---

## 1. auxcode — 補助コードライブラリ拡張インタフェース

### 1.1 スタブ関数の概要

`auxcode/auxcode.c` は以下の 5 関数のデフォルト実装を提供します。

```c
// auxcode/auxcode.c (全体)
int aux_statements(void)      { return ERROR_STATEMENT_NOT_DETECTED; }
int aux_int_functions(void)   { return ERROR_STATEMENT_NOT_DETECTED; }
int aux_str_functions(void)   { return ERROR_STATEMENT_NOT_DETECTED; }
int aux_float_functions(void) { return ERROR_STATEMENT_NOT_DETECTED; }
int lib_aux(int r0, int r1, int r2) { return r0; }
```

`ERROR_STATEMENT_NOT_DETECTED`（値 `-17`）を返すと、コンパイラはその関数が「認識しなかった」と判断し、次の候補へ処理を移します。新規ステートメント・関数を実装する場合は、この返り値を使って「自分の担当ではない」ことを伝えます。

Sources: [auxcode/auxcode.c:8-21](), [compiler.h:27]()

### 1.2 コンパイラからの呼び出し位置

各スタブは、対応する型解析モジュールの末尾付近で呼ばれます。

| 関数 | 呼び出し元ファイル | タイミング |
|---|---|---|
| `aux_statements()` | `statements.c:1578` | 全組み込みステートメント判定の後 |
| `aux_int_functions()` | `integer.c:231` | 全組み込み整数関数判定の後 |
| `aux_str_functions()` | `string.c:70` | 全組み込み文字列関数判定の後 |
| `aux_float_functions()` | `float.c:74` | 全組み込み浮動小数点関数判定の後 |

```c
// statements.c — コンパイル時のステートメント検索末尾 (抜粋)
e = wifi_statements();
if (e != ERROR_STATEMENT_NOT_DETECTED) return e;
// Aux statements
e = aux_statements();
if (e != ERROR_STATEMENT_NOT_DETECTED) return e;
// Try call statement …
```

Sources: [statements.c:1574-1581](), [integer.c:229-233](), [string.c:68-72](), [float.c:72-76]()

### 1.3 ランタイムライブラリテーブルと `lib_aux`

コンパイル時に `call_lib_code(LIB_AUXCODE)` を生成すると、実行時に `kmbasic_library()` が `lib_aux(r0, r1, r2)` を呼び出します。`LIB_AUXCODE` の番号は **157**、ライブラリテーブルの最後のエントリです。

```c
// library.c — lib_list2[] テーブル (抜粋)
lib_wifi,       // #define LIB_WIFI 156
lib_aux,        // #define LIB_AUXCODE 157
```

Sources: [library.c:864-865](), [compiler.h:133]()

### 1.4 ビルドシステムへの統合 — `auxcode/auxcode.cmake`

デフォルトの CMake 定義は以下の通りです。

```cmake
# auxcode/auxcode.cmake
add_library(aux_files
    auxcode/auxcode.c
)
target_link_libraries(aux_files
    pico_stdlib
)
```

`CMakeLists.txt` はこのファイルを `include(auxcode/auxcode.cmake)` で読み込み、生成される両バイナリ（`_kb` / 無印）に `aux_files` をリンクします。

Sources: [auxcode/auxcode.cmake:1-8](), [CMakeLists.txt:100-115]()

### 1.5 新規ライブラリを追加する手順

```text
1. auxcode/ 以下に新しい .c / .h を作成する
2. auxcode/auxcode.cmake の add_library(aux_files ...) にソースを追記する
3. auxcode/auxcode.c の各スタブ関数内で instruction_is() などを使い、
   自分のキーワードを判定・処理する
4. ランタイム動作が必要な場合は lib_aux() 内に実装し、
   コンパイル側では call_lib_code(LIB_AUXCODE) を emit する
5. ERROR_STATEMENT_NOT_DETECTED を返す前にすべての自担当キーワードを
   確認し終えること（落ちたら組み込み処理に制御が戻る）
```

---

## 2. hexfile.c — Intel HEX ファイル直接実行

### 2.1 機能概要

`runHex(char* fname)` は SD カード上の Intel HEX ファイルをパースし、`kmbasic_object[]` 配列へ書き込んだ後、ウォッチドッグリブートで指定アドレスへジャンプします。メインループでは `.HEX` 拡張子が検出されたときにこの関数を呼び出します。

```c
// main.c:175
if (!strncmp(&str[i-4], ".HEX", 4)) runHex(str);
```

Sources: [main.c:175](), [editor.c:1551]()

### 2.2 Intel HEX レコード処理

`hexfile.c` 先頭のコメントに示されているフォーマット仕様に従い、4 種類のレコードタイプを処理します。

| タイプ定数 | 値 | 意味 | 処理 |
|---|---|---|---|
| `HEX_DATA` | `0x00` | データ | `addr[laddr + i]` へコピー（`kmbasic_object` 範囲チェック付き） |
| `HEX_EOF` | `0x01` | 終端 | ループ終了 |
| `HEX_EXTENDED_ADDRESS` | `0x04` | 上位 16 ビットアドレス | `addr = (char*)(data<<16)` |
| `HEX_START_ADDRESS` | `0x05` | 開始アドレス | `start_address` に記録 |

```c
// hexfile.c:98-107
case HEX_DATA:
    if (&addr[hexdata->laddr] < (char*)&kmbasic_object[0] ||
        fbuff <= &addr[hexdata->laddr + hexdata->bytes]) return "HEX region doesn't fit";
    for(i = 0; i < hexdata->bytes; i++)
        addr[hexdata->laddr + i] = hexdata->data[i];
    break;
```

データ書き込みは `kmbasic_object` の範囲内に限定されており、範囲外へのアクセスはエラー文字列を返して停止します。

### 2.3 リブートシーケンス

```c
// hexfile.c:119-124
if (KMBASIC_RP2350) {
    watchdog_reboot(start_address, 0x20080000, 1000);
} else {
    watchdog_reboot(start_address, 0x20040000, 1000);
}
sleep_ms(2000);
```

RP2350 と RP2040 でスクラッチパッドアドレスを切り替えています。呼び出し後は `sleep_ms(2000)` で待機し、ウォッチドッグタイムアウトにより新しいファームウェアが起動します。

Sources: [hexfile.c:78-143]()

---

## 3. pcconnect.c — PC シリアルプロトコル

### 3.1 呼び出しタイミング

`withoutkeyboard.c` (USB シリアルモードの起動設定) の `post_inifile()` から `connect2pc()` が呼ばれます。USB キーボードモード (`withkeyboard.c`) では呼ばれません。

```c
// withoutkeyboard.c:39
void post_inifile(void) {
    connect2pc();
}
```

Sources: [withoutkeyboard.c:37-41]()

### 3.2 ハンドシェイクとコマンドループ

通信シーケンスは以下の通りです。

```mermaid
sequenceDiagram
    participant D as MachiKania デバイス
    participant P as PC アプリ

    D->>P: "MACHIKAP" + BS×8
    P->>D: "OK\x08\x08OK\x08\x08OK\x08\x08OK\x08\x08" (16 bytes)
    D->>P: "SENDCMDS" + BS×8
    loop コマンドループ
        P->>D: 16 byte コマンド (CD: / SIZE: / CP: / DONEDONE)
        alt CD:path
            D->>P: "OK\x08\x08OK\x08\x08OK\x08\x08OK\x08\x08"
        else SIZE:nnnn
            D->>P: "OK\x08\x08OK\x08\x08OK\x08\x08OK\x08\x08"
        else CP:filename
            D->>P: "SENDFILE" + BS×8
            P->>D: ファイルデータ (バイト列)
            D->>P: "DONEDONE" + BS×8
        else DONEDONE
            D->>P: "ALL DONE" + BS×8
        end
    end
```

各コマンドは固定 16 バイトで受信します (`receive_command()`)。タイムアウトは **2 秒**で、超過すると `communication_error()` が呼ばれ無限ループに入ります。

### 3.3 ファイル転送の詳細

`CP:` コマンド受信後、デバイスはファイルを FA_WRITE | FA_CREATE_ALWAYS で開き、バイトを逐次受信します。内部バッファは `PC_CONNECT_BUFFER_SIZE = 256` バイトで、256 バイト毎にフラッシュします。

```c
// pcconnect.c:78-97
printf("SENDFILE\x08\x08\x08\x08\x08\x08\x08\x08");
for(i = 0; i < g_connect_file_size; i++) {
    c = getchar_timeout_us(2000000);
    g_connect_buffer[(PC_CONNECT_BUFFER_SIZE-1) & i] = c;
    if ((PC_CONNECT_BUFFER_SIZE-1) == ((PC_CONNECT_BUFFER_SIZE-1) & i)) {
        printf("OK\x08\x08OK\x08\x08OK\x08\x08OK\x08\x08");
        f_write(&fh, g_connect_buffer, PC_CONNECT_BUFFER_SIZE, NULL);
    }
    …
}
```

Sources: [pcconnect.c:1-120]()

---

## 4. debug.c / debug.h — デバッグユーティリティ

### 4.1 通常モード（`MACHIKANIA_DEBUG_MODE` 未定義）

デバッグモードが無効な場合、`debug.c` は 2 つの関数のみ有効です。

| 関数 | 説明 |
|---|---|
| `memdump()` | `kmbasic_object[]` 全体 (256 KiB) を `MEMDUMP.BIN` へダンプ |
| `blink_led(int num)` | 指定回数 LED を点滅する無限ループ（クラッシュ時のデバッグ用） |

`dump()` / `dump_cmpdata()` / `dump_variables()` はすべて `debug_dummy()` (何もしない関数) に `#define` されます。

Sources: [debug.c:10-36](), [debug.h:75-86]()

### 4.2 デバッグモード（`MACHIKANIA_DEBUG_MODE` 定義時）

`config.cmake` の `set(MACHIKANIA_DEBUG_MODE 1)` のコメントを外すか、CMake 変数を設定すると有効になります。

**主な機能:**

1. **FatFS 置換マクロ** — `debug.h` が `f_open`、`f_close`、`f_gets` などを `debug_f_*` 関数へ `#define` で差し替えます。SD カードなしでコンパイル・実行できます。

2. **インメモリファイルシステム** — `debug_files[]` 配列がファイル名とその内容を交互に格納します。`MACHIKAP.BAS` には `rem_repeat64k` マクロで生成された膨大な `REM` 文が含まれており、大規模コンパイルのストレステストを SD カード不要で実施できます。

3. **`debug_fileselect()`** — 2500 ms 待機後（`g_disable_debugwait2500` フラグが未設定の場合）`"MACHIKAP.BAS"` を返します。

4. **ダンプ関数群:**

| 関数 | 出力内容 |
|---|---|
| `dump()` | `kmbasic_object` の先頭 256 ワード、クラスリスト、フィールド名 |
| `dump_class_list()` | クラス ID・アドレス・構造体フィールド |
| `dump_fieldnames()` | `CMPDATA_FIELDNAME` レコードの ID と名前 |
| `dump_cmpdata()` | 全コンパイルデータ (`CMPDATA_ALL`) の生 dump |
| `dump_variables()` | 変数番号・値・サイズ (A〜Z の 26+4 変数) |

5. **エラー追跡** — `MACHIKANIA_DEBUG_MODE` 時、`_throw_error(e)` は `throw_error(e, __LINE__, __FILE__)` に展開され、エラー発生箇所のファイル名と行番号を表示します。通常モードでは単に `(e)` に展開されます。

```c
// compiler.h:27-30
#ifdef MACHIKANIA_DEBUG_MODE
    int throw_error(int e, int line, char* file);
    #define _throw_error(e) throw_error(e, __LINE__, __FILE__)
#else
    #define _throw_error(e) (e)
#endif
```

Sources: [debug.c:34-363](), [debug.h:18-86](), [compiler.h:27-30]()

---

## 5. help.c — 組み込みヘルプ辞書

### 5.1 ヘルプファイルの設定

```c
// help.c:13
char g_help_file[64] = "/docs/help-e.txt";
```

デフォルトは SD カード上の `/docs/help-e.txt`（英語版）です。`MACHIKAP.INI` に `HELPFILE=` を記載すると `ini_file_help()` が上書きします。

```ini
# MACHIKAP.INI (抜粋)
HELPFILE=/docs/help-e.txt
#HELPFILE=/docs/help-k.txt   ← カタカナ日本語版
```

Sources: [help.c:13-22](), [scripts/MACHIKAP.INI:208-209]()

### 5.2 `get_help()` の動作

1. 検索ワードのハッシュを `cmpdata_nhash()` で計算する
2. ハッシュに基づいてグループキーワードを解決する（例: `TO` / `STEP` / `NEXT` はすべて `FOR` へ）
3. `num_lines` でそのエントリの継続行数、`num_funcs` で同一名前で複数記述がある場合の数を設定する
4. ヘルプファイルをシーケンシャルに読み込み、先頭 12 文字をキーワードと照合する
5. 一致したエントリとそれに続くタブインデント行を `g_file_buffer`（最大 1024 バイト）に格納して返す

**グループキーワードの例:**

```c
// help.c:41-58
case 0x00047392: //FOR
case 0x0000154f: //TO
case 0x01495110: //STEP
case 0x013c4654: //NEXT
    word = "FOR";
    num_lines = 2;
    break;
case 0x0000114f: //DO
case 0x0134e390: //LOOP
case 0x543d520c: //UNTIL
    word = "DO";
    num_lines = 8;
    break;
```

`num_funcs > 1` の場合（例: `GOSUB` は 4）、ファイル内で同じキーワードが複数回現れる分をすべて連結して返します。

**無効キーワード（`A`、`AND`、`OR`、`XOR`、`BASIC` など）は `return 0`** でヘルプなし扱いになります。

Sources: [help.c:27-130]()

### 5.3 エディタからの呼び出し

```c
// editor.c:2515
unsigned char *helptext = get_help(searchtext);
```

F3 キー押下時にカーソル位置のキーワードが `get_help()` に渡され、戻り値が画面に表示されます。

---

## 6. バイナリターゲットとモジュール配置

CMakeLists.txt は 2 つのバイナリを生成します。

```text
┌────────────────────────────────────┬─────────────────────────────────────┐
│  ${CODE_NAME}_kb.uf2               │  ${CODE_NAME}.uf2                   │
│  (USB キーボードモード)            │  (USB シリアル / PC 接続モード)     │
├────────────────────────────────────┼─────────────────────────────────────┤
│  withkeyboard.c                    │  withoutkeyboard.c                  │
│  interface/${KEYBOARD}.c           │  pcconnect.c                        │
│  interface/hid_virtual_keytable.c  │                                     │
│  interface/keyinput.c              │                                     │
│  tinyusb_host (USB HID ホスト)     │  stdio_usb 有効                     │
├────────────────────────────────────┴─────────────────────────────────────┤
│  共通: shared_files / video_files / wifi_files / aux_files               │
└──────────────────────────────────────────────────────────────────────────┘
```

`_kb` バイナリは `pico_enable_stdio_usb = 0`（USB シリアル無効）、無印バイナリは `pico_enable_stdio_usb = 1`（USB シリアル有効）です。`pcconnect.c` は無印バイナリにのみリンクされます。

Sources: [CMakeLists.txt:120-160]()

---

## 7. 新規ライブラリ追加 — 開発者向けチェックリスト

```text
[ ] auxcode/auxcode.c の適切なスタブ関数にキーワード判定を追加する
    - BASIC ステートメント    → aux_statements()
    - 整数返し関数           → aux_int_functions()
    - 文字列返し関数         → aux_str_functions()
    - 浮動小数点返し関数     → aux_float_functions()
    - ランタイム処理         → lib_aux()

[ ] 認識できなかったキーワードは必ず ERROR_STATEMENT_NOT_DETECTED を返す

[ ] ランタイム用コードを call_lib_code(LIB_AUXCODE) で emit する場合、
    r0/r1/r2 に渡す引数の規約を組み込みライブラリ (library.c) に合わせる

[ ] auxcode/auxcode.cmake に新しいソースファイルを追記する

[ ] MACHIKANIA_DEBUG_MODE でのテストでは SD カードが不要。
    debug_files[] にテスト用コードを追加して動作確認できる

[ ] ヘルプ辞書への対応: /docs/help-e.txt (または help-k.txt) に
    新キーワードとそのタブインデント説明行を追記する
```

---

## まとめ

Phyllosoma の拡張ポイントは**コンパイラレイヤー**と**ランタイムレイヤー**の 2 段構えになっています。コンパイラ側の `aux_statements` / `aux_*_functions` 群はすべての組み込み処理の後に呼ばれるフォールバックフックであり、`auxcode/auxcode.cmake` を差し替えることで独立した CMake ライブラリとして管理できます。`hexfile.c` はファームウェア更新を BASIC エディタと統合する仕組みを提供し、`pcconnect.c` は 16 バイト固定長コマンドによるシンプルな PC ↔ デバイス間ファイル転送プロトコルを実装しています。`debug.c` の `MACHIKANIA_DEBUG_MODE` は FatFS を完全にインメモリ実装へ差し替えることで、SD カードなしの CI テストを可能にします。`help.c` はハッシュベースのキーワード照合とグループ展開により、外部テキストファイルから柔軟なヘルプ表示を実現しています。

Sources: [auxcode/auxcode.c:8-21](), [CMakeLists.txt:98-115](), [hexfile.c:135-143](), [pcconnect.c:107-120](), [debug.h:28-68](), [help.c:13-22]()
