# 機能設計書 102-ファイル操作

## 概要

本ドキュメントは、K-Shoot Editor(譜面エディタ)における新規作成/開く/保存/名前を付けて保存/エクスポートの各ファイル操作機能の設計を記述する。

### 本機能の処理概要

本機能は、KSH形式の譜面ファイルに対する基本的なファイル操作(CRUD)を提供する。新規作成(CMD_NEW)、ファイルを開く(CMD_OPEN)、上書き保存(CMD_SAVE)、名前を付けて保存(CMD_SAVEAS)、終了(CMD_QUIT)の5つのコマンドから構成される。KSH形式に加えて、SMファイル(StepMania形式)やKSON形式のインポートにも対応する。

**業務上の目的・背景**: 譜面エディタの最も基本的な機能として、譜面データの永続化とファイル管理を行う。ユーザーが作成・編集した譜面データを安全に保存し、再読み込みできるようにすることが目的である。

**機能の利用シーン**: エディタ起動時のファイル読み込み、編集中の保存操作、新規譜面の作成、エディタ終了前の保存確認など、エディタの全ライフサイクルで使用される。ファイルメニュー(Ctrl+N/O/S/Shift+S)またはツールバーからアクセスする。

**主要な処理内容**:
1. CMD_NEW: 全配列(note/analog/spin/bpml等)をリセットし、初期値で新規譜面を作成
2. CMD_OPEN: ダイアログでファイル選択し、KSH/KSON/SM形式を自動判定して読み込み。UTF-8 BOM検出も実施
3. CMD_SAVE: `*command_save`サブルーチンで現在のファイル名に上書き保存。ファイル名未設定時はCMD_SAVEASに遷移
4. CMD_SAVEAS: 保存ダイアログを表示し、タイトル未設定時の警告後にファイル名を指定して保存
5. CMD_QUIT: `*exit`サブルーチンで未保存確認後に終了

**関連システム・外部連携**: KSON形式のインポートには `kson.dll` (KSON_ToKSH関数)を使用。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 譜面エディタ | 主画面 | ファイルメニューからの各ファイル操作コマンド実行 |

## 機能種別

CRUD操作(ファイルI/O)

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cmd | 整数(enum) | Yes | コマンドID(CMD_NEW=1, CMD_OPEN=2, CMD_SAVE=3, CMD_SAVEAS=4, CMD_QUIT=5) | 有効なコマンド値であること |
| afname | 文字列 | No | 外部指定のファイル名(ドラッグ&ドロップ等) | ファイルが存在すること |

### 入力データソース

- ファイルダイアログからのユーザー選択(CMD_OPEN/CMD_SAVEAS)
- コマンドライン引数 / ドラッグ&ドロップによるファイルパス
- KSH/KSON/SM形式の譜面ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| note配列 | 整数配列[131072][6] | ノートデータ(レーン/位置/長さ/エフェクト等) |
| analog配列 | 整数配列[131072][6] | アナログ(レーザー)データ |
| spin配列 | 整数配列[131072][6] | スピンエフェクトデータ |
| bpml配列 | 整数配列[131072][2] | BPM変更リスト |
| fname | 文字列 | 現在編集中のファイルパス |

### 出力先

- KSH形式テキストファイル(保存時)
- メモリ上の各種配列(読み込み時)

## 処理フロー

### 処理シーケンス

```
1. CMD_NEW: 新規作成
   ├─ *confirmsave で未保存確認ダイアログ表示
   ├─ 全配列(note/analog/spin/bpml/tilt/ztop/zbot等)をdim/sdimで再初期化
   ├─ メタデータ(csongtitle/csongartist等)を空文字に初期化
   ├─ Undo履歴をリセット(ud_cnt=0, ud_cur=0, ud_redomax=0)
   └─ *refreshtitle でタイトルバー更新

2. CMD_OPEN: ファイルを開く
   ├─ *confirmsave で未保存確認
   ├─ ダイアログでファイル選択(afnameが空の場合)
   ├─ 全配列を再初期化
   ├─ ファイル拡張子判定(.kson / .sm / .ksh)
   │   ├─ .kson: KSON_ToKSHでKSH形式に変換後読み込み
   │   ├─ .sm: *smlabelでStepMania形式を解析
   │   └─ .ksh: notesel/noteloadで直接読み込み
   ├─ UTF-8 BOM検出(0xBFBBEF)とDeleteUTF8BOM処理
   ├─ 譜面データの行単位解析ループ
   └─ Undo履歴リセット

3. CMD_SAVE: 上書き保存
   └─ *command_save サブルーチン呼び出し

4. CMD_SAVEAS: 名前を付けて保存
   ├─ タイトル未設定時の警告ダイアログ
   ├─ 保存ダイアログ表示(ksh形式)
   ├─ ファイル名をfnameに設定
   └─ CMD_SAVEを呼び出し

5. CMD_QUIT: 終了
   └─ *exit サブルーチン(未保存確認含む)
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド受信] --> B{コマンド種別?}
    B -->|CMD_NEW| C[未保存確認]
    B -->|CMD_OPEN| D[未保存確認]
    B -->|CMD_SAVE| E[*command_save]
    B -->|CMD_SAVEAS| F[タイトル確認]
    B -->|CMD_QUIT| G[*exit]
    C --> C1[全配列初期化]
    C1 --> C2[メタデータ初期化]
    C2 --> C3[Undo履歴リセット]
    D --> D1[ファイル選択ダイアログ]
    D1 --> D2{拡張子?}
    D2 -->|.kson| D3[KSON_ToKSH変換]
    D2 -->|.sm| D4[StepMania解析]
    D2 -->|.ksh等| D5[直接読み込み]
    D3 --> D6[BOM検出・データ解析]
    D4 --> D6
    D5 --> D6
    F --> F1[保存ダイアログ]
    F1 --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-102-01 | 未保存確認 | 編集済み(e=1)の場合、ファイル操作前に保存確認ダイアログを表示する | CMD_NEW, CMD_OPEN, CMD_QUIT実行時 |
| BR-102-02 | 拡張子判定 | ファイル拡張子(.ksh/.kson/.sm/.mp3/.ogg/.wav)に応じて読み込み方法を切り替える | CMD_OPEN実行時 |
| BR-102-03 | KSON変換 | .ksonファイルはKSON_ToKSH関数でKSH形式に変換してインポートする。上書き保存不可(fnameを空にする) | .ksonファイル読み込み時 |
| BR-102-04 | 音楽ファイルドロップ | .mp3/.ogg/.wavファイルがドロップされた場合、新規作成してcsongfileに設定する | CMD_OPEN時に音楽ファイルが指定された場合 |
| BR-102-05 | 異常譜面警告 | 特殊な譜面配置が存在する場合(caution=1)、上書き保存でデータが破壊される可能性を警告する | ファイル読み込み完了後 |

### 計算ロジック

該当なし。

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

該当なし(ファイルベースI/O)

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル不存在 | 指定されたファイルが存在しない | ダイアログ通知後、処理を中断 |
| - | KSON変換失敗 | KSON_ToKSHが負の値を返した場合 | lang.0.76エラーダイアログを表示し処理中断 |
| - | KSON変換警告 | KSON_GetLastEditorDiagWarningが警告を返した場合 | lang.0.77警告ダイアログを表示して続行 |
| - | タイトル未設定 | csongtitleが空の状態でCMD_SAVEAS実行 | 警告ダイアログ表示。キャンセルでCMD_EDIT_SONGSETTINGSを案内 |

### リトライ仕様

リトライ処理はなし。

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

該当なし。ファイル保存は一括書き込み。

## パフォーマンス要件

大規模譜面(131072要素)の読み込み・保存に対応。配列サイズは固定で事前確保済み。

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

外部ファイルの読み込みにおいて、不正なKSH/KSONデータによるバッファオーバーフローのリスクがある。配列サイズ(131072)の上限チェックにより緩和されている。

## 備考

- CMD_OPEN実行時、ファイル選択ダイアログのフィルタは `ksh;*.kson|sm` (KSHファイルとKSONファイル、SMファイル)
- KSONファイルを開いた場合、fname変数は空文字に設定され、上書き保存(CMD_SAVE)ができない設計になっている
- Undo/Redo履歴はファイル操作時にリセットされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshooteditor.hsp | `kshooteditor.hsp` | 266-310行目: 主要配列の宣言(note[131072][6], analog[131072][6], spin[131072][6]等) |
| 1-2 | kshooteditor.hsp | `kshooteditor.hsp` | 404-447行目: メタデータ変数の初期値(fname, csongtitle, csongartist, bpm等) |

**読解のコツ**: HSP3では `dim` は整数配列、`sdim` は文字列配列、`ddim` は浮動小数点配列の宣言命令である。配列サイズ131072は十分な余裕を持った固定サイズ。

#### Step 2: コマンドディスパッチャを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshooteditor.hsp | `kshooteditor.hsp` | 2191-2198行目: `*OnCommand` サブルーチンのコマンド振り分け処理 |

**主要処理フロー**:
1. **2192行目**: `if(acmd=-1)` で外部コマンド(メニュー)とアクセラレータキーの判定
2. **2193行目**: `cmd=wparam&0xFFFF` でWindows メッセージからコマンドIDを取得
3. **2199行目**: `if(cmd=CMD_NEW)` で新規作成コマンドの処理開始

#### Step 3: CMD_OPEN(ファイルを開く)の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kshooteditor.hsp | `kshooteditor.hsp` | 2203-2489行目: CMD_OPEN処理全体 |

**主要処理フロー**:
- **2204行目**: `gosub *confirmsave` で未保存確認
- **2214-2221行目**: ファイル選択(afnameが空の場合はダイアログ表示)
- **2223-2291行目**: 全配列の再初期化
- **2335-2382行目**: 拡張子判定(.sm / .kson / 音楽ファイル / .ksh)
- **2337-2362行目**: KSON形式の変換処理(KSON_ToKSH)
- **2373-2381行目**: KSH形式の直接読み込み(notesel/noteload)
- **2376-2378行目**: UTF-8 BOM検出

#### Step 4: CMD_SAVE/CMD_SAVEAS(保存)の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | kshooteditor.hsp | `kshooteditor.hsp` | 3889-3930行目: CMD_SAVE/CMD_SAVEAS処理 |

**主要処理フロー**:
- **3889行目**: CMD_SAVE → `*command_save` サブルーチン呼び出し
- **3892-3930行目**: CMD_SAVEAS → タイトル確認 → 保存ダイアログ → CMD_SAVE呼び出し
- **3913-3919行目**: `csongtitle=""` の場合の警告ダイアログ
- **3921行目**: `dialog "ksh",17,lang.0.30` で保存ダイアログ表示

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

```
*OnCommand (コマンドディスパッチャ)
    │
    ├─ CMD_NEW
    │   ├─ *confirmsave (未保存確認)
    │   ├─ *new (配列初期化)
    │   └─ *refreshtitle (タイトルバー更新)
    │
    ├─ CMD_OPEN
    │   ├─ *confirmsave (未保存確認)
    │   ├─ *selinit (選択状態初期化)
    │   ├─ dialog (ファイル選択ダイアログ)
    │   ├─ KSON_ToKSH (KSON変換, .kson時)
    │   ├─ *smlabel (SM解析, .sm時)
    │   ├─ notesel/noteload (KSH読み込み)
    │   └─ *refreshtitle (タイトルバー更新)
    │
    ├─ CMD_SAVE
    │   └─ *command_save (保存処理)
    │
    ├─ CMD_SAVEAS
    │   ├─ dialog (保存ダイアログ)
    │   └─ CMD_SAVE → *command_save
    │
    └─ CMD_QUIT
        └─ *exit (終了処理)
```

### データフロー図

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

KSH/KSON/SMファイル ───────▶  CMD_OPEN                       ───▶  メモリ上の配列群
                              (ファイル解析・配列格納)                (note/analog/spin等)

メモリ上の配列群    ───────▶  CMD_SAVE / CMD_SAVEAS          ───▶  KSHファイル
                              (配列→KSH形式テキスト変換)

ユーザー操作        ───────▶  CMD_NEW                        ───▶  初期化された配列群
(メニュー/ショートカット)     (全配列リセット)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshooteditor.hsp | `kshooteditor.hsp` | ソース | ファイル操作コマンド処理(CMD_NEW/OPEN/SAVE/SAVEAS/QUIT) |
| kson.as | `src/kson.as` | ソース | KSON_ToKSH等のKSON DLL関数バインディング |
| kson.dll | `kson.dll` | DLL | KSONフォーマットの変換処理 |
