# アーキテクチャ設計書

## 概要

本ドキュメントは、K-Shoot MANIA (KSM) v1.75b のアプリケーションアーキテクチャを記述する。KSMはHot Soup Processor (HSP) 3.51で開発されたWindows向け音楽ゲームであり、ゲーム本体（kshootmania.hsp）と譜面エディタ（kshooteditor.hsp）の2つの独立したアプリケーションから構成される。コア機能の一部はC++で実装されたDLLに委譲されており、音声処理にはBASSライブラリ群を使用する。全変数がグローバルスコープで管理され、シーン遷移ベースのメインループにより動作する手続き型アーキテクチャである。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図.md](./アーキテクチャ構成図.md) を参照。

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| BASS Audio Library (bass.dll) | DLL呼び出し (#uselib) | 音声再生・ストリーミング・エフェクト処理 |
| BASS FX (bass_fx.dll) | DLL呼び出し (#uselib) | テンポ変更等の音声エフェクト |
| BASS VST (bass_vst.dll) | DLL呼び出し (#uselib) | VSTプラグインによるDSP音声エフェクト |
| bassconv.dll | DLL呼び出し (#uselib) | 音声位置のms単位変換 |
| kshlib.dll (C++) | DLL呼び出し (#uselib) | 譜面メタデータ読込、ハッシュ計算、ディレクトリ監視、SwitchAudio管理 |
| ksmcore.dll (C++) | DLL呼び出し (#uselib) | ゲームシステム（カメラ値計算）、キー音再生管理 |
| kson.dll (C++) | DLL呼び出し (#uselib) | KSH/KSONフォーマット変換 |
| Win32 API (user32, kernel32, gdi32, msvcrt, comctl32) | DLL呼び出し (#uselib) | ウィンドウ操作、ファイル操作、GDI描画、フォント管理 |
| HGIMG3 (HSP標準拡張) | HSP拡張命令 (#include) | 3D描画・テクスチャ管理 |
| hspinet (HSP標準拡張) | HSP拡張命令 (#include) | ネットワーク通信（IR接続、プロキシ対応） |
| MCI (Windows Multimedia) | mci命令 | 動画再生（MPEGVideo） |
| VSTプラグインDLL群 (regawo.dll, flan.dll, pitc.dll, bitc.dll, phas.dll, tstp.dll, sich.dll) | BASS_VST経由 | 各種音声エフェクト（リトリガ、ゲート、フランジャー、ピッチシフト、ビットクラッシャー、フェイザー、ウォブル、テープストップ、エコー、サイドチェイン） |

## レイヤー構成

### アーキテクチャスタイル

**手続き型・シーン遷移ベースアーキテクチャ**

HSP言語の特性（インタプリタ、モジュール機能が限定的、コンパイル時最適化なし）により、伝統的なレイヤードアーキテクチャやオブジェクト指向アーキテクチャは採用されていない。代わりに以下の特徴を持つ:

- **グローバル変数による状態管理**: `#module`〜`#global`がほぼ使用されておらず、全変数がグローバルスコープ
- **シーン遷移ベースのメインループ**: `scene`変数によるswitch-caseでシーンを切り替え
- **#include指令による物理的なファイル分割**: 論理的モジュール分割ではなく、ファイル結合による構成
- **DLL委譲パターン**: パフォーマンスが要求される処理やC++での実装が適する処理をDLLに委譲

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| エントリポイント/メインループ | アプリケーション初期化、シーン遷移制御、メインループ管理 | kshootmania.hsp, kshooteditor.hsp |
| シーン層 | 各画面固有のロジック・描画・入力処理 | src/scene/title.hsp, select.hsp, play.hsp, result.hsp, course_result.hsp, option.hsp, gate.hsp |
| ゲームプレイサブモジュール層 | プレイ画面の細分化された機能 | src/scene/play/play_*.hsp (14ファイル) |
| オーディオ層 | 音声エフェクト定義、キー音管理、レーザースラム音管理 | src/audio/fxdef.hsp, key_sound.as, laser_slam_sound.as |
| ライブラリ/ユーティリティ層 | 外部DLLバインディング、Win32 API宣言、ファイルシステムユーティリティ | src/bass.as, bass_fx.as, bass_vst.as, bassconv.as, winapi.as, kshlib.as, ksmcore.as, kson.as, filesystem_utils.as |
| ネットワーク/IR層 | インターネットランキング接続（現在は無効化） | src/ir.hsp |

### レイヤー間の依存関係ルール

- エントリポイントは全レイヤーを`#include`により参照する
- シーン層はオーディオ層・ライブラリ層をグローバル変数・関数を介して間接的に参照する
- ゲームプレイサブモジュール層はplay.hspから`#include`され、相互にグローバル変数を共有する
- オーディオ層（key_sound.as, laser_slam_sound.as）は`#module`を使用しローカルスコープを持つ数少ないコンポーネントである
- ライブラリ層は他レイヤーへの依存を持たない（DLL宣言のみ）
- **依存方向は明示的に制御されておらず**、全グローバル変数が全コンポーネントから参照可能である

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| ゲーム本体 | 音楽ゲームとしてのプレイ体験の提供 | kshootmania.hsp, src/scene/*.hsp, src/scene/play/*.hsp |
| 譜面エディタ | 譜面ファイル(.ksh)の作成・編集 | kshooteditor.hsp |
| 音声システム | 楽曲再生、効果音、VSTエフェクト、キー音管理 | src/bass.as, src/bass_fx.as, src/bass_vst.as, src/bassconv.as, src/audio/*.hsp |
| 譜面データ管理 | 譜面ファイルの読込・解析・変換 | src/kshlib.as, src/kson.as, src/scene/play/play_chart_load.hsp |
| ゲームシステム | カメラ制御、判定ロジック、スコア計算 | src/ksmcore.as, src/scene/play/play_game_logic.hsp, play_button_note.hsp, play_laser_note.hsp |
| 入力処理 | キーボード、ジョイスティック、マウス、アナログデバイス入力 | src/scene/play/play_key_input.hsp |
| 描画 | 2D/3Dグラフィックス、UI描画、テクスチャ管理 | src/scene/play/play_draw_frame.hsp, play_graphics.hsp, play_splash_screen.hsp |
| ネットワーク | IR（インターネットランキング）通信 | src/ir.hsp |
| 設定管理 | config.ini読み書き、キー設定、表示設定 | kshootmania.hsp内の設定読込・保存処理 |

### パッケージ構造

```
ksm-v1-develop/
├── kshootmania.hsp              # ゲーム本体エントリポイント
├── kshooteditor.hsp             # 譜面エディタエントリポイント
├── config.ini                   # ユーザー設定ファイル
├── src/
│   ├── winapi.as                # Win32 API宣言
│   ├── kshlib.as                # kshlib.dllバインディング
│   ├── ksmcore.as               # ksmcore.dllバインディング
│   ├── kson.as                  # kson.dllバインディング
│   ├── bass.as                  # BASS音声ライブラリバインディング
│   ├── bass_fx.as               # BASS FXバインディング
│   ├── bass_vst.as              # BASS VSTバインディング
│   ├── bassconv.as              # BASS位置変換バインディング
│   ├── filesystem_utils.as      # ファイルシステムユーティリティ
│   ├── ir.hsp                   # インターネットランキングモジュール
│   ├── audio/
│   │   ├── fxdef.hsp            # 音声エフェクト定義（10種類）
│   │   ├── key_sound.as         # キー音管理モジュール
│   │   └── laser_slam_sound.as  # レーザースラム音管理モジュール
│   └── scene/
│       ├── title.hsp            # タイトル画面
│       ├── select.hsp           # 選曲画面
│       ├── play.hsp             # プレイ画面（サブモジュール集約）
│       ├── result.hsp           # リザルト画面
│       ├── course_result.hsp    # コースモードリザルト画面
│       ├── option.hsp           # オプション画面
│       ├── gate.hsp             # INPUT GATE画面（無効化済み）
│       └── play/
│           ├── play_init.hsp         # プレイ初期化
│           ├── play_update.hsp       # プレイ更新ループ
│           ├── play_key_input.hsp    # プレイ中キー入力処理
│           ├── play_button_note.hsp  # ボタンノート判定
│           ├── play_laser_note.hsp   # レーザーノート判定
│           ├── play_draw_frame.hsp   # フレーム描画
│           ├── play_chart_load.hsp   # 譜面読込・解析
│           ├── play_game_logic.hsp   # ゲームロジック
│           ├── play_graphics.hsp     # グラフィックスロード
│           ├── play_audio.hsp        # 音声タイミング制御
│           ├── play_audio_effects.hsp # カスタム音声エフェクト
│           ├── play_video.hsp        # 動画再生
│           ├── play_utils.hsp        # ユーティリティ（曲情報表示等）
│           └── play_splash_screen.hsp # プレイ前スプラッシュ画面
├── third_party/                  # サードパーティHSPモジュール
│   ├── mod_encode.hsp           # エンコーディング変換
│   ├── mod_csv.hsp              # CSV処理
│   ├── mod_d3d9vsync.hsp        # VSync制御
│   ├── mod_hgcapture2.hsp       # 画面キャプチャ
│   ├── mod_strlu.as             # 文字列処理
│   ├── gm_crlf.hsp             # 改行コード変換
│   ├── rc4_crypt.hsp            # RC4暗号化
│   ├── FileInfoModule.hsp       # ファイル情報取得
│   ├── a2d.hsp                  # AlphaBlend 2D描画
│   ├── jstick.as                # ジョイスティック入力
│   ├── alib_hash.as             # ハッシュテーブル
│   ├── clipboard.as             # クリップボード操作
│   ├── bitmap.as                # ビットマップ操作（エディタ用）
│   ├── mod_string.hsp           # 文字列操作（エディタ用）
│   └── ...
├── lang/                         # 多言語対応ファイル
├── imgs/                         # 画像リソース
├── se/                           # 効果音リソース
│   └── note/                    # キー音ファイル
├── songs/                        # 楽曲・譜面データ
├── courses/                      # コースモードデータ
├── cache/                        # キャッシュデータ
├── data/                         # データファイル
└── score/                        # スコアデータ
    └── {PLAYER}/                # プレイヤー別スコア
```

### コンポーネント依存関係

**ゲーム本体 (kshootmania.hsp) の依存関係:**

1. **ライブラリ層**: winapi.as → kshlib.as → ksmcore.as → kson.as
2. **オーディオ層**: key_sound.as → laser_slam_sound.as → fxdef.hsp
3. **ファイルシステム**: filesystem_utils.as
4. **音声ライブラリ**: bass.as → bassconv.as → bass_fx.as → bass_vst.as
5. **HSP標準拡張**: d3m.hsp, hgimg3.as, hspinet.as, hspmath.as, hspda.as, hspext.as, mod_regexp.as, mod_joystick.as, encode.as
6. **サードパーティ**: mod_encode.hsp, mod_csv.hsp, mod_d3d9vsync.hsp, mod_hgcapture2.hsp等
7. **IR**: ir.hsp
8. **シーン**: title.hsp, select.hsp, play.hsp, result.hsp, course_result.hsp, option.hsp, gate.hsp

**譜面エディタ (kshooteditor.hsp) の依存関係:**

1. **音声ライブラリ**: bass.as → bassconv.as → bass_fx.as → bass_vst.as
2. **ライブラリ層**: winapi.as → ksmcore.as → kson.as
3. **オーディオ層**: key_sound.as → laser_slam_sound.as → fxdef.hsp
4. **ファイルシステム**: filesystem_utils.as
5. **HSP標準拡張**: d3m.hsp, hspmath.as, hspext.as, mod_regexp.as, encode.as
6. **エディタ専用**: llmod3/*, mod_menu.as, third_party/bitmap.as, mod_string.hsp

## ミドルウェア構成

### データベース

本システムではRDBMS/NoSQLデータベースは使用されていない。データ永続化はファイルシステムベースで行われる。

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| ファイルベース | config.ini | - | アプリケーション設定の保存 |
| ファイルベース | score/{PLAYER}/ | - | プレイヤー別スコアデータの保存 |
| ファイルベース | cache/ | - | 描画キャッシュ・変換済みデータ |
| ファイルベース | .ksh/.kson | - | 譜面データ（テキスト形式） |

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| ファイルシステムキャッシュ (cache/) | - | 画像テクスチャ、背景画像、UI要素のリサイズ済み画像 | バージョン更新時に削除 |
| HSP buffer (インメモリ) | - | 描画用画像バッファ（最大187バッファ使用） | アプリケーション終了時まで |

### メッセージキュー

該当なし。

### 検索エンジン

該当なし。

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| BASS Audio Library | 不明 | 音声再生エンジン（44100Hz初期化） |
| BASS FX | 不明 | テンポ変更エフェクト |
| BASS VST | 不明 (LGPL v3) | VSTプラグインホスティング |
| HGIMG3 | HSP 3.51同梱 | 3Dグラフィックスエンジン・テクスチャ管理 |
| MCI (Windows) | OS同梱 | MPEG動画再生 |

## データフロー

### リクエスト処理の流れ（メインループ）

1. **メインループ開始**: `repeat`〜`loop`による無限ループで`scene`変数を参照
2. **シーンディスパッチ**: `switch scene`により対応するシーン関数（`start_title`, `start_select`, `start_play`, `on_update_result`等）を呼び出し
3. **シーン内処理**: 各シーンが独自の`repeat`〜`loop`で内部ループを持ち、入力処理→ロジック更新→描画の順で実行
4. **シーン遷移**: シーン内ループを`break`で抜け、`scene`変数を次のシーン値に設定
5. **フレーム同期**: `redraw 0`→描画処理→`redraw 1`→`await 7`（約7ms待機）のダブルバッファリング
6. **音声同期**: BASS_ChannelGetPosition_msで楽曲再生位置を取得し、ゲームタイマーと同期

### 非同期処理の流れ

1. **音声再生**: BASSライブラリが独立スレッドで音声バッファリング・再生を管理（`updateperiod`=100ms、`bufferlength`=200ms）
2. **キー入力コールバック**: `onkey gosub *keshu`によりキー入力イベントをHSPのイベントハンドラで処理
3. **ウィンドウメッセージ**: `oncmd gosub *alt`によりAlt+Tab等のシステムメッセージを処理
4. **VSTプラグイン処理**: BASS_VST経由でDSP処理が音声スレッド上で実行
5. **動画再生**: MCI命令による動画再生はOSのメディアサブシステムが管理

### データ永続化の流れ

1. **設定保存**: `*saveconfig`ルーチンにより`config.ini`をテキスト形式で保存。各設定項目を`key=value`形式で出力
2. **スコア保存**: リザルト画面でスコアデータを`score/{PLAYER}/`ディレクトリにファイルとして保存
3. **キャッシュ生成**: タイトル画面で画像テクスチャをリサイズし`cache/`ディレクトリに保存。バージョン更新時にキャッシュを全削除して再生成
4. **譜面読込**: KSHフォーマットの譜面ファイルをテキストとして読込、行ごとにパース。UTF-8 BOMの検出・変換を行い、メタデータとノートデータに分離

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| IR（インターネットランキング）ログイン | src/ir.hsp | オンラインスコア送信（ソースコード公開版では無効化） |

注: ソースコード公開に伴い、IR認証関連のコードは削除されている（`ir_is_logged_in`は常に0を返す）。

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| エラーダイアログ | `dialog`命令による即座のユーザー通知 | 画面表示のみ（ファイル保存なし） |
| IR通知 | `ir_popup_set_text`によるポップアップ表示 | 画面表示のみ |

注: アプリケーションログ、監査ログ、アクセスログの仕組みは実装されていない。

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| DLL不在 | `exist`命令でファイル存在確認後`dialog`表示→`end` | アプリケーション終了 |
| DLLバージョン不一致 | バージョン番号チェック（例: `KSHLib_GetVersion()<1663`）→`dialog`表示→`end` | アプリケーション終了 |
| BASS初期化失敗 | `BASS_Init`の戻り値チェック→`dialog`表示→`end` | アプリケーション終了 |
| 画像ファイル不在 | カスタム`picload`命令内で`exist`チェック→`dialog`表示 | 警告表示・処理継続 |
| 譜面ファイル不在 | `exist`チェック→`dialog`表示→シーン遷移（選曲画面へ） | シーン遷移で回復 |
| ディレクトリ不在 | `filesystem_utils.as`の`safeChdir`で存在確認→`dialog`表示 | 警告表示・処理継続 |
| VSTパラメータ設定失敗 | `BASS_VST_SetParam_R`内で最大5回リトライ | リトライによる自動回復 |
| `instr`関数のバグ | カスタム`instr`関数でマルチバイト文字のバッファオーバーラン防止 | 修正済み関数で置換 |

### トランザクション管理

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| 設定ファイル保存 | notesel/notesave による一括書き出し | ファイル単位（アトミック性なし） |
| スコアデータ保存 | ファイル書き込み | ファイル単位（アトミック性なし） |

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| DLL委譲パターン | パフォーマンスクリティカルな処理 | ksmcore.dll（カメラ値計算、キー音管理）、kshlib.dll（譜面メタデータ）、kson.dll（フォーマット変換） |
| シーンベース状態管理 | メインループ | `#enum SCENE_TITLE = 0` 〜 `SCENE_GATE`の列挙子でシーンを管理 |
| 物理的ファイル分割 | プレイ画面 | play.hspが14個のサブモジュールを`#include`で集約 |
| インクルードガード | ライブラリファイル | `#ifndef BASS_AS` / `#define BASS_AS` / `#endif`パターン |
| カスタム命令による組み込み関数修正 | 標準関数のバグ修正 | `picload`のファイル不在時エラー表示追加、`instr`のマルチバイト文字バグ修正 |
| モジュールによるカプセル化（限定的） | 音声サブシステム | `key_sound.as`と`laser_slam_sound.as`が`#module`〜`#global`を使用し、ローカル変数でカプセル化 |

### コーディング規約

- **変数命名**: 一貫した規約はなく、省略形が多用される（例: `stat1`, `stat2`は一時変数、`cnt`はカウンタ）
- **マジックナンバー**: 座標値・タイミング値等が直接ハードコードされている。パフォーマンス上の理由で計算済みの値がそのまま記述されている場合がある
- **コメント**: 日本語で記述。処理の意図を説明するコメントが適宜付与されている
- **ファイルエンコーディング**: Shift-JIS（HSP 3.51はANSI版であり、UTF-8版は使用不可）
- **定数定義**: `#define`および`#const`による定数定義が使用されているが、一部はマジックナンバーのまま残存
- **#enum**: シーンID、コマンドID等の列挙にはHSPの`#enum`が使用されている

## 備考

### シーン遷移メカニズム

メインループは`kshootmania.hsp`の末尾付近（946行〜1236行付近）に実装されている。`scene`変数の値に基づき`switch`〜`case`で各シーンの処理関数を呼び出す。シーン遷移は各シーン内で`scene`変数を書き換え、内部ループを`break`で抜けることで実現される。

- SCENE_TITLE (0): タイトル画面
- SCENE_IR_SIGN_IN (1): IRログイン画面
- SCENE_SELECT (2): 選曲画面
- SCENE_BEFORE_PLAY (3): プレイ前準備（コースモード用）
- SCENE_PLAY (4): プレイ画面
- SCENE_RESULT (5): リザルト画面
- SCENE_COURSE_RESULT (6): コースモードリザルト画面
- SCENE_OPTION (7): オプション画面
- SCENE_GATE (8): INPUT GATE画面（ソースコード公開版では無効化）

### 入力システム

入力は以下の4種類をサポートする:

1. **キーボード入力**: `getkey`命令で直接ポーリング。キーマッピングは`config.ini`の`key=`/`key2=`で設定
2. **ジョイスティック入力**: `mod_joystick.as`および`third_party/jstick.as`経由。`joy=`/`joy2=`で設定
3. **マウス入力**: `ginfo_mx`/`ginfo_my`でアナログデバイスとして使用（`analoginput=2`時）
4. **アナログスライダー**: ジョイスティックの軸をレーザー入力として使用（`analoginput=4`時）

### 音声エフェクトシステム

音声エフェクトは`fxdef.hsp`で10種類が定義されており、各エフェクトは対応するVSTプラグインDLLを通じて適用される:

1. Retrigger (regawo.dll)
2. Gate (regawo.dll)
3. Flanger (flan.dll)
4. PitchShift (pitc.dll)
5. BitCrusher (bitc.dll)
6. Phaser (phas.dll)
7. Wobble (regawo.dll)
8. TapeStop (tstp.dll)
9. Echo (regawo.dll)
10. SideChain (sich.dll)
11. SwitchAudio（エフェクトではなく代替音声への切替）

ユーザー定義エフェクトは譜面ファイル内の`#define_fx`/`#define_filter`行で定義でき、`play_audio_effects.hsp`内の`initCustomAudioEffects`で解析・初期化される。

### ソースコード公開版での制限事項

以下の機能はソースコード公開に伴い削除されている:

- INPUT GATE（ゲーム内譜面ダウンローダ）: `gate.hsp`はスタブのみ
- Twitter連携機能: 関連コード削除
- インターネットランキング: `ir.hsp`内の通信コードが削除（`ir_is_logged_in`は常に0を返す）
- `hosts`変数は空文字列に設定（開発版表記となる）
