# 画面設計書 4-プレイ前処理画面

## 概要

本ドキュメントは、K-Shoot MANIA のプレイ前処理画面の設計仕様を記述する。コースモードの前処理を行う内部画面であり、コースファイル（.kco）の解析、チャート情報の読み込み、エラーハンドリングを実行する。ユーザーに表示されない内部処理画面である。

### 本画面の処理概要

プレイ前処理画面は、曲選択画面からゲームプレイ画面への遷移時に実行される中間処理画面であり、主にコースモード時のコースファイル解析を担当する。

**業務上の目的・背景**：コースモードでは複数の楽曲を連続してプレイする必要があり、コースファイル（.kco）に記述された曲リストを解析して順序通りにプレイ画面へ送り出す必要がある。本画面はその前処理を担い、コースファイルの構文解析・譜面ファイルの存在確認・エラーハンドリングを行う。通常楽曲プレイ時はそのままSCENE_PLAYへ通過する。

**画面へのアクセス方法**：曲選択画面でEnterキー（楽曲決定）を押下した際、scene=SCENE_BEFORE_PLAYが設定されることで自動的に遷移する。コマンドライン引数による直接起動時にも遷移する。

**主要な操作・処理内容**：
1. コース関連変数の初期化（courselist, courselistnum, coursenow等）
2. コースモード時（iscourse=1）のコースファイル読み込みと解析
3. UTF-8 BOM検出とエンコード自動判定
4. コースファイル内の曲リスト（[パス]形式）の抽出
5. 各曲の譜面ファイル存在確認
6. 解析結果に応じたSCENE_PLAYまたはSCENE_SELECTへの遷移
7. エラー時のダイアログ表示

**画面遷移**：
- 遷移先：ゲームプレイ画面（SCENE_PLAY、解析成功時、行1013）、曲選択画面（SCENE_SELECT、エラー時、行1017/1021/1025）
- 遷移元：曲選択画面（Enter決定時）、タイトル画面（コマンドライン引数時）

**権限による表示制御**：なし（内部処理画面のため画面表示なし）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | シーン遷移管理 | 主機能 | コースモード時の前処理としてコースファイル解析後にSCENE_PLAYまたはSCENE_SELECTへ遷移制御 |
| 14 | コースモード | 主機能 | コースファイル(.kco)のnoteload/notegetによる解析、courselist/courselistnumへの曲リスト展開 |
| 24 | 文字エンコード自動判定 | 補助機能 | UTF-8 BOM(0xBFBBEF)検出によるコースファイルのエンコード自動判定とDeleteUTF8BOM処理 |
| 117 | ファイルシステムユーティリティ | 補助機能 | ファイル存在確認(exist)による譜面ファイルの有効性検証 |
| 101 | 多言語テキスト管理 | 補助機能 | lang.2.11/lang.2.12/lang.2.13によるエラーダイアログの多言語メッセージ表示 |
| 3 | プレイ画面 | 遷移先機能 | コースファイル解析成功後にSCENE_PLAYへ遷移してゲームプレイを開始 |
| 2 | 選曲画面 | 遷移先機能 | コースファイル解析失敗時にSCENE_SELECTへ遷移して曲選択画面に戻る |

## 画面種別

内部処理画面（ユーザー表示なし）

## URL/ルーティング

デスクトップアプリケーション（HSP3）のため、URLルーティングは存在しない。シーン管理はscene変数（SCENE_BEFORE_PLAY = 3）により制御される。

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| iscourse | 入力 | int | コースモードフラグ（1:コース、0:通常） |
| cnotesfile | 入力 | string | 選択された譜面/コースファイルパス |
| courselist | 出力 | string | 改行区切りのコース内曲リスト |
| courselistnum | 出力 | int | コース内の曲数 |
| coursenow | 出力 | int | 現在プレイ中のコース内曲番号（0初期化） |
| coursetotalscore | 出力 | int | コース累計スコア（0初期化） |
| coursecritical | 出力 | int | コース累計CRITICAL数（0初期化） |
| coursenear | 出力 | int | コース累計NEAR数（0初期化） |
| courseerrorn | 出力 | int | コース累計ERROR数（0初期化） |
| courseend | 出力 | int | コース終了フラグ（0初期化） |
| ccoursetitle | 出力 | string | コースタイトル（title=行から取得） |
| is_course_utf8 | 出力 | int | コースファイルがUTF-8かどうか |
| course_sc | 出力 | int配列 | 各曲のスコア格納用配列 |
| course_md | 出力 | int配列 | 各曲のメダル格納用配列 |
| course_gr | 出力 | int配列 | 各曲のグレード格納用配列（-1で初期化） |

## 表示項目

ユーザーに対する画面表示はなし（エラー時のダイアログのみ）。

## イベント仕様

### 1-コースファイル解析（iscourse=1時）

1. コースファイルの読み込み（notesel/noteload）（行970-971）
2. UTF-8 BOM検出（0xBFBBEF判定）とBOM除去（行972-975）
3. 行ごとの解析：
   - `title=`行：コースタイトルを取得（行978-980）
   - `--`行：曲リストセクション開始のマーカー（行981-982）
   - `[パス]`形式行：曲パスを抽出し、相対パス（./や.\）を検出した場合はエラー（行983-988）
   - 各曲パスに対してexist命令でファイル存在確認（行990-997）
   - 有効な曲はcourselistに追加、courselistnumをインクリメント（行998-999）
4. 結果変数fの値による遷移判定

### 2-遷移判定

解析結果のフラグ変数fの値に応じて遷移先を決定する：
- **f=1（解析成功）またはiscourse=0（通常楽曲）**：course_sc/course_md/course_gr配列を初期化し、scene=SCENE_PLAY（行1006-1013）
- **f=2（バージョン不一致）**：lang.2.12のエラーダイアログを表示し、scene=SCENE_SELECT（行1014-1017）
- **f=0（ファイル不存在）**：lang.2.13のエラーダイアログを表示し、scene=SCENE_SELECT（行1018-1021）
- **f=4（相対パス検出/ファイル不存在）**：lang.2.11のエラーダイアログを表示し、scene=SCENE_SELECT（行1022-1025）

## データベース更新仕様

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

| 操作（イベント） | 対象ファイル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| コースファイル解析 | songs/ディレクトリ/*.kco | SELECT | コースファイルの読み込みと解析 |
| 譜面存在確認 | songs/ディレクトリ/*.ksh | SELECT | exist命令による譜面ファイルの存在確認 |

### テーブル別更新項目詳細

該当なし（ファイルベースアーキテクチャ）。

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|----------|--------------|
| lang.2.11 | エラー | コースファイルの譜面パスが不正（相対パスまたはファイル不存在） | 「指定された譜面ファイルが見つかりません。」 |
| lang.2.12 | エラー | コースファイルのバージョンが非対応 | 「このコースをプレイするには、最新バージョンのK-Shoot MANIAが必要です。」 |
| lang.2.13 | エラー | コースファイル自体が見つからない | 「指定された譜面ファイルが見つかりません。」 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| コースファイルが存在しない | f=0となり、エラーダイアログ表示後SCENE_SELECTへ遷移 |
| コースファイル内の譜面パスが無効 | f=4となり、エラーダイアログ表示後SCENE_SELECTへ遷移 |
| コースファイルのバージョン非対応 | f=2となり、エラーダイアログ表示後SCENE_SELECTへ遷移 |
| 相対パス（./や.\）の検出 | 安全性の観点からf=4としてエラー処理 |

## 備考

- 本画面はフレーム描画を行わない内部処理シーンであり、TODOコメント（行14）にも「フレーム描画がないのでシーンから除外」と記載されている。
- 通常楽曲プレイ時（iscourse=0）はコースファイル解析をスキップし、直接SCENE_PLAYへ遷移する。
- コースファイル形式は独自フォーマットで、title=行でタイトル、--行で曲リスト開始、[パス]形式で各曲を指定する。
- UTF-8とShift-JISの両方に対応しており、BOM検出による自動判定を行う。

---

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

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

### 推奨読解順序

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

コースモード関連のデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshootmania.hsp | `kshootmania.hsp` | 行13: SCENE_BEFORE_PLAY = 3の定義。コメントに「フレーム描画がないのでシーンから除外」とある |
| 1-2 | kshootmania.hsp | `kshootmania.hsp` | courselist(string), courselistnum(int), coursenow(int)等のコース管理変数 |

**読解のコツ**: iscourse変数が1の場合のみコースファイル解析が実行される。iscourse=0の場合は初期化のみでSCENE_PLAYへ直通する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshootmania.hsp | `kshootmania.hsp` | 行955: `case SCENE_BEFORE_PLAY`がエントリーポイント |

**主要処理フロー**:
1. **行956-964**: コース関連変数の初期化（courselist, courselistnum, coursenow等を0/空で初期化）
2. **行966**: iscourse=1の判定
3. **行967-1004**: コースファイル解析ループ
4. **行1006-1026**: 解析結果に基づく遷移判定

#### Step 3: コースファイル解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kshootmania.hsp | `kshootmania.hsp` | 行970-971: notesel/noteloadによるコースファイル読み込み |
| 3-2 | kshootmania.hsp | `kshootmania.hsp` | 行972-975: UTF-8 BOM検出と除去 |
| 3-3 | kshootmania.hsp | `kshootmania.hsp` | 行976-1004: 行ごとの解析ループ（title=、--、[パス]形式の判定） |

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

```
kshootmania.hsp メインループ
    |
    +-- case SCENE_BEFORE_PLAY (行955)
            |
            +-- 変数初期化 (行956-965)
            +-- iscourse判定 (行966)
            |       |
            |       +-- [iscourse=1] コースファイル解析
            |       |       +-- notesel/noteload (行970-971)
            |       |       +-- UTF-8 BOM判定 (行972-975)
            |       |       +-- 行解析ループ (行976-1004)
            |       |               +-- title= ... ccoursetitle設定
            |       |               +-- -- ... 曲リスト開始マーカー
            |       |               +-- [パス] ... courselist追加
            |       |               +-- exist ... ファイル存在確認
            |       |
            |       +-- [iscourse=0] スキップ
            |
            +-- f値判定 (行1006-1026)
                    +-- [f=1 or iscourse=0] scene=SCENE_PLAY
                    +-- [f=2] dialog(lang.2.12), scene=SCENE_SELECT
                    +-- [f=0] dialog(lang.2.13), scene=SCENE_SELECT
                    +-- [f=4] dialog(lang.2.11), scene=SCENE_SELECT
```

### データフロー図

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

cnotesfile (.kco) -------> notesel/noteload -----+
                                                  |
                           UTF-8 BOM判定 <--------+
                                |
                                v
                           行解析ループ
                                |
                    +-----------+-----------+
                    |           |           |
                    v           v           v
              title=行     --マーカー   [パス]行
              ccoursetitle  f=1設定    courselist追加
                                      courselistnum++
                                      exist確認
                                |
                                v
                           f値による遷移
                                |
                    +-----------+-----------+
                    |                       |
                    v                       v
              scene=SCENE_PLAY       scene=SCENE_SELECT
              (成功)                 (エラー + dialog)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshootmania.hsp | `kshootmania.hsp` | ソース | プレイ前処理の全処理（行955-1027）。メインループ内にインライン記述 |
| *.kco | `songs/*/**.kco` | データ | コースファイル。title=、--、[パス]形式で曲リストを定義 |
| *.ksh | `songs/*/**.ksh` | データ | 譜面ファイル。exist命令による存在確認の対象 |
