hsp3dx 仕様書 Phase 0 ドラフト

最終更新: 2026-04-20

hsp3dx は HSP3 言語を DxLib ベースのランタイムで動かすクロスプラットフォーム実行環境。 Windows / iOS / Android の 3 プラットフォームで 同一の .ax バイト列 を実行できることを目指す。

目次
  1. 設計コンセプト
  2. HSP コマンド分類 (採用 / 除外 / DxLib 置換)
  3. 型システムの進化計画 (float / 構造体 / NSTRUCT)
  4. プラグイン方針
  5. 文字コード規則
  6. ビルド / 配布フロー
  7. Phase 計画
  8. ディレクトリ構成
  9. 未確定事項

1. 設計コンセプト

項目方針
VM ベースhsp3/ コア (Hsp3 クラス) を fork (Hsp3::Reset() が runtime で .ax を読み込み、HSPHED 解析まで自己完結。標準の hsp3cl.exe が採用している方式)
描画 / 音声 / 入力hgio 層を DxLib バックエンドに差し替え (hgio_dx.cpp)
DxLib 全 API 公開dxlib_core プラグインを静的リンク (dx_* 命令として HSP 側に公開)
.ax バイト列3 プラットフォーム共通、すべて VM インタプリトで実行
.ax 配布経路Win = ファイル直読み / iOS = bundle 内バイト配列 / Android = assets 内バイト配列
JITなし (インタプリト実行、iOS 禁止のため)
ポインタ幅64bit 固定 (#bootopt hsp64 1 既定)
文字コードUTF-8 固定 (3 プラットフォーム共通)

HSP3Dish との差別化ポイント (4 点)

  1. 真の "同一 .ax が 3 プラットフォームで同じ VM で走る"
    HSP3Dish mobile は hsp3cnv.ax → C++ AOT 翻訳して native ビルドするため、Win (interpret) と mobile (AOT native) で実行コードパスが違う。hsp3dx は全プラットフォームで VM インタプリタ統一のため、挙動再現性が高い (Win で出たバグは mobile でも同じ VM で再現)。
  2. DxLib の豊富な API をそのまま呼べる (3D / エフェクト / 動画再生 / ネットワークなど 2000 関数超、HSP3Dish は 2D + 簡易 3D のみ)
  3. DxLib 既存ユーザーの資産移行パス
  4. 新命令追加時に翻訳ルール不要 (hsp3cnv に HSP→C++ 翻訳ルール追加が要らない、プラグイン側の命令表だけでよい)

Route B を採用した理由 (Route A との比較)

項目Route A (hsp3dish AOT 方式)Route B (全 VM interpret) 採用
Win 実行インタプリタインタプリタ
Mobile 実行hsp3cnv で AOT、native 実行VM がインタプリト
挙動一致性翻訳バグの可能性完全一致
Mobile 性能★★★ (native)★★ (interpret)
新命令追加コスト翻訳ルール + plugin 両方plugin のみ
実装ベースhsp3dish forkhsp3/ コア fork (Hsp3 クラス、Hsp3::Reset() が runtime ロード担当)
hsp3dish との差別化薄い明確

ランタイム構成と hgio 差し替え戦略

hgio = HSP Graphics I/O。HSP3Dish が導入した描画/音声/入力の抽象層で、VM からは統一 C++ 関数群 (hgio_init / hgio_render_start / hgio_gsel など) だけが見える。プラットフォーム別実装を差し替えることでマルチプラットフォーム化する設計。

hsp3dx ランタイム (libhsp3dx / hsp3dx.exe) の内部構成 ════════════════════════════════════════════════════════ HSP ユーザーコード (.hsp) → hspcmp → .ax バイト列 │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ hsp3embed VM (HSP3 インタプリタ) │ │ ※ Win / iOS / Android 共通 │ └─────────────┬───────────────────────────────┬───────────────┘ │ │ HSP 標準命令 (mes/pset/redraw/getkey) dx_* プラグイン命令 │ │ ▼ ▼ ┌─────────────────────────┐ ┌─────────────────────────────┐ │ hgio_dx.cpp │ │ dxlib_core プラグイン │ │ (HSP stdlib → DxLib) │ │ (dx_drawmodel など 2000) │ │ 約 30 関数 │ │ DxLib 全 API を直接公開 │ └──────────┬──────────────┘ └──────────┬──────────────────┘ │ │ └──────────────┬──────────────┘ ▼ ┌──────────────────────┐ │ DxLib API │ │ (Win/iOS/Android) │ └──────────────────────┘

hsp3dx では hgio_dx.cpp を新規に書いて hgio_initDxLib_Inithgio_render_startClearDrawScreen、のように DxLib API に転送する。VM 側 (hsp3embed) は一切触らない

さらに DxLib の 2000 関数を dx_* 命令として HSP 側に公開する dxlib_core プラグイン を別途静的リンクする。これにより (a) 既存 HSP コード (mes など) の互換性 と (b) DxLib 全 API フルアクセス の両立。

2. HSP コマンド分類

2.1 採用する (pure HSP / 言語コア)

分類コマンド
制御if / else / repeat / loop / break / continue / foreach / return / gosub / goto / on / switch / case / default / swbreak / swend
変数宣言dim / ddim / sdim / ldim / alloc / dimtype
配列・メモリlength / length2 / length3 / length4 / memcpy / memset / dup / dupptr / mref / vartype / varuse / varsize
文字列strmid / instr / strf / split / getstr / strtrim / strrep / cnvstow / cnvwtos
数学 (整数)int / abs / limit / rnd / srand
数学 (浮動小数)double / sin / cos / tan / atan / sqrt / pow / exp / log / absf
型変換str / int / double / char / cnvint / cnvwide
ファイルexist / bsave / bload / fileopen / fileclose / fileread / filewrite
プロセス制御wait / await / stop / end / exgoto
デバッグmes (DxLib の DrawString にリダイレクト) / logmes / title (SetMainWindowText) / assert

2.2 除外する (Win32 依存で iOS/Android に持っていけない)

分類除外コマンド理由
GUI ウィジェットbutton / mesbox / chkbox / combox / listbox / input / objprm / objsel / objmode / clrobj / objsizeWin32 Common Controls 前提
HSP 標準描画color / palette / palcolor / palfade / pset / line / boxf / circle / pget / gcopy / gzoom / gmode / gsquare / grotate / celput / celload / celdiv / redraw / screen / bgscr / gsel / buffer / picload / bmpsaveDxLib に置換
HSP 標準音声mmload / mmplay / mmstop / mmvol / mmpan / mciDxLib に置換
HSP 標準入力getkey / mousex / mousey / mousew / mouse / stick / onkey / onclickDxLib に置換
ダイアログdialogDxLib で簡易代替
COMnewcom / delcom / comobj / comres / comevent / comevarg / comevdisp / axobjWin32 COM 前提
レジストリregread / regwrite / regdelWin 固有
Win32 API 直叩き#uselib (任意 DLL) / dllproc / dllfunc / dllctrl / winobjiOS 禁止 / Android NDK 面倒
イベントonerror / oncmdWin32 メッセージ依存

2.3 DxLib 経由で置換提供する命令

詳細は Phase 1 以降で 40 関数から順次拡張。分類は以下:

分類命令 (一部)Phase
描画dx_drawgraph / dx_drawbox / dx_drawline / dx_drawcircle / dx_drawstring / dx_loadgraph / dx_screenflip / dx_cleardrawscreen1
音声dx_loadsoundmem / dx_playsoundmem / dx_stopsoundmem / dx_setvolumesoundmem1
入力dx_getmouseinput / dx_getmousepoint / dx_getjoypadinputstate / dx_checkhitkey / dx_getinputstring1
ウィンドウdx_setwindowtext / dx_setgraphmode / dx_setwindowstyle / dx_changewindowmode1
タイマdx_gettickcount / dx_getnowcount1
3Ddx_loadmodel / dx_drawmodel / dx_setcameraposeye4+
動画dx_playmovie / dx_pausemovie4+
ネットワークdx_connectnetwork / dx_netsend / dx_netrecv4+

3. 型システムの進化計画

DxLib は float / 構造体 / 構造体配列 を多用するため、段階的に HSP の型システムを拡張する必要がある。本章で 段階的移植計画 を明記する。

3.1 DxLib が使う型 / 機構

カテゴリ具体例
float 引数 / 戻り値VECTOR = {float x,y,z;} / DrawCircle(x,y,r,color,fill,thickness) の半径 / 音量・ピッチ
構造体VECTOR / VECTOR_D / VERTEX3D / MATRIX / RECT / COLOR_F / MV1_COLL_RESULT_POLY 他多数
構造体の出力 (pointer)GetCameraPosition(&pos) で VECTOR を返す
構造体配列頂点バッファ、当たり判定ポリゴン群
コールバックSetMovieSurfaceCallback 等 (少数)

3.2 hsp3net にあって hsp3embed に無い型機構

ベースとする hsp3embed は HSP3 素の型セット (int / double / str / 配列) しか持たない。対して hsp3net には以下が実装済:

機能hsp3nethsp3embed (fork 元)用途例
#cfunc (int 返し)ハンドル / カウント
#cfuncd (double 返し)一般数値
#cfuncf (float 返し)DxLib float 戻り値
#cfuncst (struct 返し)VECTOR 取得など
NSTRUCT (構造体型)pos.x で触れる
#defcbcom (COM callback)DxLib では概ね不要

3.3 取れる 3 方針

方針 1: プラグイン側ですべて吸収

方針 2: 最小限の型拡張 (float + cfuncf だけ移植)

方針 3: hsp3net の型機構フル移植

3.4 Phase と方針の対応

Phase型方針理由
Phase 1 (MVP 40 関数)方針 1スカラ分解で DrawGraph / DrawCircle / GetMousePoint など動かす
Phase 2-3 (cnv + mobile)方針 1 継続VM 側は触らず、安定化優先
Phase 4-5 (API 40 → 500)方針 2#cfuncf 追加、float 精度必要な API が増える
Phase 6 (3D / 動画)方針 3NSTRUCT / cfuncst 移植、MATRIX / VERTEX3D を touch する段階

3.5 長期ベース判断 (Phase 1.1 で前倒し確定 / Phase 6 で再々考)

Phase 1.1 着手時点で、当初予定の hsp3embed fork は不適と判明: Phase 1.1 確定: VM ベースは hsp3/ コア (Hsp3 クラス)。hsp3embed は採用しない。
Phase 6 (NSTRUCT / cfuncst 必要) 到達時に再々考する項目:

3.6 自動コード生成の指針

DxLib の 2000 関数を手書きで #deffunc / #cfunc 定義するのは非現実的 → DxLib.h をパースして機械生成するスクリプトを Phase 5 で整備予定。

3.7 コールバック方針 (iOS / Android 制約への対処)

DxLib には SetMovieSurfaceCallback / サウンドストリーム / ネットワーク受信 / MV1 当たり判定など C 関数ポインタを受ける API が 10〜20 個存在する。これを HSP 側から扱う方針。

3.7.1 プラットフォーム制約

プラットフォーム動的コード生成 (JIT / trampoline 実行時生成)静的 C 関数ポインタ渡し
Windows 自由
Android△ NDK で mprotect 使えば可、ただし Android 10+ で制限強化
iOS 原則禁止 (W^X、executable page を write できない)

3.7.2 コールバック 3 技法と対応

技法仕組みiOSAndroidWin
(a) 静的スロット trampolineビルド時に N 個の C 関数 (cb_slot_0, cb_slot_1, …) を用意、スロット ID から HSP 側ハンドラへ dispatch
(b) 動的 trampoline 生成実行時に機械語を書き出して関数ポインタ化 (HSP3 classic の callback 命令、libffi closure)
(c) .NET CLR thunkCLR が JIT で生成 (hsp3net の #defcbcom) (iOS Mono は AOT 必須、JIT 不可)
hsp3dx は (a) 静的スロット方式を採用。HSP3 classic の callback / hsp3net の #defcbcom はそのままでは iOS 動作不可。

3.7.3 静的スロット方式の具体像

// ビルド時に signature family ごとに N 個事前生成 (DxLib.h パース時に自動)
static int g_hsp_label[256];
static void cb_slot_0(int arg0, int arg1) {
    VM_CallHspLabel(g_hsp_label[0], arg0, arg1);
}
static void cb_slot_1(int arg0, int arg1) { ... }
/* ... cb_slot_255 まで ... */

static void (*trampolines[256])(int,int) = {
    cb_slot_0, cb_slot_1, /* ... */, cb_slot_255
};

HSP 側:

dx_set_callback_xxx *my_handler     ; プラグインが空きスロットを確保、ラベル ID を記録
...
*my_handler
    ; DxLib からコールバックされたときここに来る
    return

3.7.4 制約と運用

3.7.5 Phase 対応

Phaseコールバック対応
Phase 1 (MVP 40 関数)コールバック不使用、スキップ
Phase 5 (API 拡張)静的スロット trampoline 導入、5 シグネチャ × 256 スロット程度で初期実装
Phase 6 (3D / 動画)SetMovieSurfaceCallback など本命コールバック対応

3.7.6 §3.2 の #defcbcom 記述の補足

§3.2 の型機構比較表では「#defcbcom は DxLib では概ね不要」と書いたが、これは CLR thunk 方式の #defcbcom そのものは mobile で動かないので流用できない 意味であり、コールバック機能自体が不要ではない。hsp3dx では代わりに #defcallback (仮称) + 静的スロット方式 を自前で用意する。

4. プラグイン方針

#uselib での任意 DLL ロードは禁止
iOS はダイナミックロードが原則禁止、Android も外部 .so 配布が面倒なため。

同梱プラグインは 事前承認制 (ランタイムビルド時に静的リンク) となる。

4.1 OK プラグイン pure HSP / cross-platform 可

4.2 NG プラグイン 使えない

5. 文字コード規則

5.1 統一ルール

エンコーディング
.hsp ソースファイルUTF-8 (BOM なし) 必須
hspcmp オプション#cmpopt utf8 1 相当を既定
.ax 内文字列テーブルUTF-8 バイト列
ランタイム内部文字列UTF-8
DxLib 呼び出しSetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8) を起動時固定
ファイルパスUTF-8 (Win は _wfopen 経由で UTF-16 変換、iOS/Android はネイティブ UTF-8)
フォントファイル (.ttf / .otf)バイナリなので非依存

5.2 DxLib 公式ドキュメント準拠

5.3 移行時の既知の落とし穴

  1. Shift-JIS の 2 バイト目 0x5C 問題: (0x95 0x5C) などの文字がリテラル中に出ると 0x5C がエスケープ扱いされてリテラルが破壊される → UTF-8 化で自動解消
  2. sdim のサイズ指定: UTF-8 では 1 文字 1〜4 バイト。Shift-JIS で 2 バイトだった文字が UTF-8 で 3 バイトになる例が多数 → バッファサイズを 1.5 倍程度で見積もる
  3. strlen は文字数ではなくバイト数 (既存 HSP と同じだが UTF-8 では差が顕著)
  4. poke / peek でバイト単位に触っている既存コード: 非互換、書き換え必須
  5. DxLib API 引数: SetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8) 呼び出し後は UTF-8 で渡せばよく、特別な変換は不要

5.4 既存資産の移行サポート

tools/hsp3dx_sjis2utf8/.hsp ソースを Shift-JIS → UTF-8 に一括変換するツールを同梱。

hsp3dx_sjis2utf8 --in path\to\src.hsp [--out path\to\dst.hsp]
hsp3dx_sjis2utf8 --dir path\to\project [--recursive]
hsp3dx_sjis2utf8 --dir path\to\project --dry-run

6. ビルド / 配布フロー

6.1 Windows

your_game.hsp → hspcmp (#cmpopt utf8 1, #bootopt hsp64 1) → start.ax ↓ hsp3dx.exe ← start.ax を読んで実行

6.2 iOS

your_game.hsp → hspcmp → start.ax ↓ Xcode project に start.ax + 画像/音声を Resources/ にドロップ ↓ Xcode build: libhsp3dx.a (hsp3 VM + hgio_dx + dxlib_core) + DxLib iOS lib ↓ .ipa (bundle 内に start.ax / PNG / WAV が同梱)

起動時にランタイムが [NSBundle pathForResource:@"start"] 経由で start.ax のパスを得て、通常の fopen で読み込んで VM にロード → interpret 実行。画像や音声と同じ扱いで bundle resource としてアクセスするシンプル構成。

6.3 Android

your_game.hsp → hspcmp → start.ax ↓ Studio project の app/src/main/assets/ に start.ax + 画像/音声を配置 ↓ Studio build: libhsp3dx.so (hsp3 VM + hgio_dx + dxlib_core) + DxLib Android lib ↓ .apk / .aab (assets/ 内に同梱)

ランタイムは AAssetManager_open() 経由で start.ax を読み込み、通常通り VM interpret。画像/音声も同じ AAssetManager 経由。

6.4 配布経路が統一されている点

Win / iOS / Android で .ax も画像/音声も同じ土俵の通常ファイルとして扱う。 VM の .ax ローダと、プラグインのアセットローダ (picload / mmload) は プラットフォーム抽象を挟んだ共通 I/O 経由で動作する。 Win 用の fopen、iOS 用の [NSBundle pathForResource:]、Android 用の AAssetManager_openhsp3dx_platform_fopen() みたいな薄いラッパで束ねる 設計 (Phase 3/4 で実装)。

.ax の C バイト配列化 (hsp3dx_cnv) は必須ではない (旧 Phase 2 見送り)。 どうしても .ax を隠蔽したい・ファイルにしたくないケース向けの オプションツールとして Phase 6 以降に整備する位置づけ。

6.4 共通アセットパッケージング

.ax 以外の素材 (画像 / 音声 / フォント) は hsp3dx_pack ツール (Phase 2) で仮想 FS に固める。ランタイムはプラットフォーム問わず同じ API で素材にアクセス可能。

7. Phase 計画

Phase内容型方針 (§3)状態
Phase 0仕様書 + SJIS→UTF-8 移行ツール + ディレクトリ雛形完了 (2026-04-20)
Phase 1Windows 版 hsp3dx.exe MVP (extcmd 27 + reffunc 8 + 7 サンプル)方針 1完了 (2026-04-21)
Phase 2 (旧)hsp3dx_cnv / hsp3dx_pack ツール見送り (下記参照)
Phase 2 (新)iOS/Android 向け platform abstraction I/O 層 (hsp3dx_platform_fopen 等)方針 1未着手
Phase 3iOS 版 libhsp3dx.a + Xcode テンプレ (.ax/アセットは bundle resource)方針 1未着手
Phase 4Android 版 libhsp3dx.so + Android Studio テンプレ (.ax/アセットは assets/)方針 1未着手
Phase 5DxLib API を 40 → 500 関数に拡張 + dx_* 命令群方針 2 (float + #cfuncf)未着手
Phase 63D / 動画 / ネットワーク機能追加方針 3 (NSTRUCT / cfuncst 移植)未着手

7.1 Phase 2 (旧) 見送りの経緯

初期設計では .axconst uint8_t[] の C ソースに変換して mobile アプリに 静的リンクする hsp3dx_cnv ツールを Phase 2 に置いていた。しかし: 新方針: .ax も画像/音声と同じく bundle / assets に通常ファイル配置。 ランタイムがプラットフォーム抽象 I/O で同一経路から読み込む。 hsp3dx_cnv は「.ax 隠蔽したい / ファイル出したくない」ケース向けの オプションツールとして Phase 6 以降に譲る。

8. ディレクトリ構成 (Phase 0 時点)

hsp3dx/
  README.md                    このドキュメントへのリンク
  samples/
    sample_drawgraph.hsp       Phase 1 検証用サンプル (雛形)
    sample_sound.hsp           Phase 1 検証用サンプル (雛形)
    sample_mouse.hsp           Phase 1 検証用サンプル (雛形)
  win32/                       Phase 1 で hsp3dx.exe のソース/vcxproj を配置
    README.md
  ios/                         Phase 3 で Xcode プロジェクトを配置
    README.md
  ndk/                         Phase 4 で Android Studio プロジェクトを配置
    README.md

docs/
  hsp3dx_spec.md               Markdown 版仕様書
  hsp3dx_spec.html             本ドキュメント

tools/
  hsp3dx_sjis2utf8/            SJIS → UTF-8 一括変換ツール (.NET)
    hsp3dx_sjis2utf8.csproj
    Program.cs
    README.md

9. 未確定事項 (Phase 1 着手時に決める)

Markdown 版: hsp3dx_spec.md / リポジトリ: hsp3dx/