# 機能設計書 98-config.ini管理

## 概要

本ドキュメントは、K-Shoot MANIAのゲーム設定（キーバインド、HiSpeed、画面設定、言語等）をconfig.iniファイルに読み込み・保存する設定管理機能の設計を記述する。

### 本機能の処理概要

本機能は、アプリケーション起動時にconfig.iniファイルから各種設定値を読み込み、オプション設定画面やゲームプレイの変更を反映してconfig.iniに保存する設定永続化機能である。

**業務上の目的・背景**：プレイヤーの設定（キーバインド、HiSpeed、画面解像度、言語、ノートモード等）を永続的に保存し、次回起動時に復元するための仕組みが必要である。INIファイル形式(key=value)の独自実装で設定を管理する。

**機能の利用シーン**：
- アプリケーション起動時: config.iniの読み込みと変数への反映
- オプション設定画面終了時: *saveconfigサブルーチンでの設定保存
- 選曲画面での状態変更時: currentdir/currentitem等の保存

**主要な処理内容**：
1. アプリケーション起動時にconfig.iniを行単位で解析
2. 各行のプレフィックス(key=, fullscr=等)を判定して対応変数に値を設定
3. オプション設定画面終了時に*saveconfigサブルーチンで全設定値をconfig.iniに書き戻し
4. 既存設定の上書きと新規設定の追加を両方サポート

**関連システム・外部連携**：ファイルシステム(config.ini)、ksmcore.dllのStartsWith関数。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | タイトル画面 | 参照画面 | 初回起動時のconfig.ini設定値の読み込みと反映 |
| 3 | 曲選択画面 | 参照画面 | 選曲状態(currentdir/currentitem/currentlevel等)の保持と次回起動時復元 |
| 8 | オプション設定画面 | 主画面 | オプション変更値のconfig.iniへの保存処理(設定画面終了時) |

## 機能種別

設定管理 / データ永続化

## 入力仕様

### 入力パラメータ

config.iniの設定項目（47種類の設定キー）:

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | str(カンマ区切り14整数) | No | キーボード1のキーバインド | 11要素以上必要 |
| key2 | str(カンマ区切り14整数) | No | キーボード2のキーバインド | 11要素以上必要 |
| joy | str(カンマ区切り14整数) | No | ジョイスティック1のバインド | 11要素以上必要 |
| joy2 | str(カンマ区切り14整数) | No | ジョイスティック2のバインド | 11要素以上必要 |
| hispeedtype | str(カンマ区切り) | No | x/C/m/a/OのHiSpeed方式 | なし |
| hispeed | str | No | HiSpeed値(x10, C300等) | なし |
| laserinput | int | No | レーザー入力方式(0-5) | なし |
| fullscr | int | No | フルスクリーン(0/1) | なし |
| windowsize | str(カンマ区切り2整数) | No | ウィンドウサイズ(幅,高さ) | なし |
| fullscrsize | str(カンマ区切り2整数) | No | フルスクリーン解像度 | なし |
| lowquality | int | No | 描画品質(0-2) | なし |
| mastervol | int | No | マスターボリューム(0-100) | なし |
| vsync | int | No | Vsync(0/1) | なし |
| bt_mode | int | No | BTノートモード(0-3) | なし |
| fx_mode | int | No | FXノートモード(0-3) | なし |
| laser_mode | int | No | レーザーモード(0-3) | なし |
| currentplayer | str | No | 現在のプレイヤー名 | players配列から検索 |
| currentlang | str | No | 現在の言語名 | なし |
| currentdir | str | No | 選曲中のディレクトリ | なし |
| currentitem | int | No | 選曲中のアイテム番号 | なし |
| currentlevel | int | No | 選択中の難易度 | なし |
| inputdelay | int | No | 入力遅延(ms) | なし |
| laserdelay | int | No | レーザー遅延(ms) | なし |

### 入力データソース

- config.iniファイル(テキストファイル、key=value形式)

## 出力仕様

### 出力データ

各種グローバル変数(key, key2, joykey, fullscr, windowsize, lowquality等)

### 出力先

- メモリ上の各グローバル変数(読み込み時)
- config.iniファイル(保存時)

## 処理フロー

### 処理シーケンス

```
1. 起動時: config.ini読み込み
   └─ noteload "config.ini" で全内容を読み込み
   └─ split で改行区切りのconfstr配列に展開
   └─ 各行についてStartsWith()でキーを判定し、対応変数に値を設定
   └─ デフォルト値の適用(config.iniに存在しない設定)

2. 保存時: *saveconfig サブルーチン
   └─ confex配列で各設定キーの存在を事前チェック
   └─ 既存の行は更新値で置換
   └─ 存在しない設定は末尾に追加
   └─ notesave "config.ini" で保存
```

### フローチャート

```mermaid
flowchart TD
    A[アプリ起動] --> B{config.ini存在?}
    B -->|No| C[空ファイルを作成]
    B -->|Yes| D[noteload config.ini]
    C --> D
    D --> E[split → confstr配列]
    E --> F[行ループ: StartsWith判定]
    F --> G[対応変数に値を設定]
    G --> H[デフォルト値適用]
    H --> I[ゲーム起動]
    I --> J[オプション画面等で設定変更]
    J --> K[*saveconfig呼び出し]
    K --> L[confex配列で存在チェック]
    L --> M[既存行更新 + 新規行追加]
    M --> N[notesave config.ini]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-98-01 | 初回起動対応 | config.iniが存在しない場合は空ファイルを作成 | 起動時(390-395行目) |
| BR-98-02 | デフォルトキーバインド | keyが11要素未満の場合はデフォルト値を適用 | key解析時(686-698行目) |
| BR-98-03 | 固定キー | key.11=Enter(13), key.12=Esc(27), key.13=F11(122)は常に上書き | key解析後(710-712行目) |
| BR-98-04 | 設定追加 | config.iniに存在しない設定は保存時に末尾に追加 | *saveconfig(1351-1366行目) |
| BR-98-05 | 連続改行除去 | 保存時に3連続以上の改行を除去 | *saveconfig(1494行目) |
| BR-98-06 | 隠し設定 | #peakingfilter:on, #fxeffects:on, #bufferlength:等は#プレフィックスの隠し設定 | config.ini解析時(657-674行目) |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定読み込み | config.ini | READ | 起動時に全行を解析 |
| 設定保存 | config.ini | WRITE | オプション画面終了時に全設定を書き戻し |

### テーブル別操作詳細

#### config.ini

47種類の設定キーの読み書き。key=value形式。各キーの読み込みはStartsWith関数でプレフィックス一致、値はstrmid関数で文字列切り出し後にint()やsplit()で変換。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ファイル未発見 | config.iniが存在しない場合 | 空ファイルを新規作成(390-394行目) |
| N/A | 不正形式 | keyの要素数が不足(11未満) | デフォルト値を適用(696-698行目) |

### リトライ仕様

特になし。

## トランザクション仕様

ファイルベースの設定保存であり、トランザクション管理は行われない。notesave命令で一括書き込みを行う。

## パフォーマンス要件

起動時の1回読み込みと保存時の1回書き込みのため、パフォーマンス要件は特になし。

## セキュリティ考慮事項

- config.iniはプレーンテキストであり、暗号化は行われない
- proxy_host/proxy_port等のネットワーク設定を含む

## 備考

- config.iniの設定キーは47種類(confex配列のサイズ)
- 隠し設定(#プレフィックス)はUIからは変更できず、テキストエディタで直接編集する必要がある
- analoginputの旧キー名「analoginput=」は「laserinput=」に読み替えて保存される(1418-1419行目)

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshootmania.hsp | `kshootmania.hsp` | confstr配列: config.iniの各行を格納する文字列配列(417行目) |
| 1-2 | kshootmania.hsp | `kshootmania.hsp` | confex配列: 47要素の設定キー存在フラグ配列(1302行目) |

**読解のコツ**: HSP3のnotesel/noteload/notesave命令は、変数をテキストファイルとして操作する。split命令で改行区切りの文字列を配列に変換する。

#### Step 2: 読み込み処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshootmania.hsp | `kshootmania.hsp` | config.ini存在チェックと空ファイル作成(390-395行目) |
| 2-2 | kshootmania.hsp | `kshootmania.hsp` | noteload/split処理(416-417行目) |
| 2-3 | kshootmania.hsp | `kshootmania.hsp` | 各設定キーの解析ループ(418-681行目) |

**主要処理フロー**:
1. **390-395行目**: config.iniの存在チェック、存在しない場合は空ファイル作成
2. **416行目**: noteload "config.ini" で全内容読み込み
3. **417行目**: split confs,"\n",confstr で行配列に変換
4. **418-681行目**: 各行のStartsWithチェックと変数設定
5. **684-712行目**: key/key2/joykeyのデフォルト値適用と固定キー設定

#### Step 3: 保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kshootmania.hsp | `kshootmania.hsp` | *saveconfig サブルーチン(1299-1500行目) |

**主要処理フロー**:
- **1302-1350行目**: confex配列で各設定キーの存在をチェック
- **1351-1366行目**: 存在しない設定キーのインデックスを計算
- **1368-1492行目**: 既存行の更新と新規行の追加
- **1494行目**: 3連続改行の除去
- **1497-1498行目**: notesaveでconfig.iniに書き込み

### プログラム呼び出し階層図

```
kshootmania.hsp (起動時)
    |
    +-- exist "config.ini" → 存在チェック
    +-- noteload "config.ini" → 読み込み
    +-- split → confstr配列
    +-- 解析ループ(418-681行目)
    |       +-- StartsWith(confstr.cnt, "key=") → key配列
    |       +-- StartsWith(confstr.cnt, "fullscr=") → fullscr変数
    |       +-- StartsWith(confstr.cnt, "hispeed=") → hsr/hsc/hsm/hsa/hso変数
    |       +-- ... (47種類)
    |       └── 隠し設定(#prefix) → peffecta/feffecta/bufferlength等
    |
    +-- デフォルト値適用(684-712行目)

option.hsp → Escキー
    |
    +-- *saveconfig (kshootmania.hsp 1299行目)
            +-- confex配列の構築(1302-1350行目)
            +-- 行更新/追加ループ(1356-1492行目)
            └── notesave "config.ini"(1498行目)
```

### データフロー図

```
[入力]                    [処理]                           [出力]

config.ini ──────────> noteload → split → 解析ループ ──> グローバル変数群
                                                          (key, fullscr, etc.)

グローバル変数群 ──────> *saveconfig ──────────────────> config.ini
(設定変更後)              (行更新/追加)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshootmania.hsp | `kshootmania.hsp` | ソース | config.ini読み込み(390-681行目)・保存(1299-1500行目) |
| option.hsp | `src/scene/option.hsp` | ソース | *saveconfig呼び出し(1081行目)、設定変更UI |
| ksmcore.as | `src/ksmcore.as` | ソース | StartsWith関数の定義 |
| config.ini | `config.ini` | 設定ファイル | 設定値の永続化先 |
