# 機能設計書 8-曲リスト表示

## 概要

K-Shoot MANIAの選曲画面において、通常曲・フォルダ・コースモードに対応した曲リストをスクロール可能に表示する機能の設計書である。

### 本機能の処理概要

曲リスト表示機能は、songs/ディレクトリ配下の楽曲ファイル群をスキャンし、通常楽曲・フォルダ・サブフォルダ・コースファイルを統合的に一覧表示する。スクロール、循環ナビゲーション、ジャケット画像表示、スコア・メダル表示を含む。

**業務上の目的・背景**：大量の楽曲コレクションから効率的に楽曲を探索するため、フォルダ構造対応のスクロール可能リストが必要である。通常曲だけでなく、サブフォルダやコースモードの.kcoファイルも同一リスト内に表示する。

**機能の利用シーン**：選曲画面（start_select）のメインループ内で常時動作する。曲リストの生成は画面初期化時（*refreshfilelist）に行われ、スクロールや選択変更のたびにジャケット・スコア・楽曲情報がリフレッシュされる。

**主要な処理内容**：
1. songsディレクトリのスキャンと.kshファイル列挙
2. フォルダ構造の認識とネスト表示対応
3. コースファイル（.kco）の認識とリスト統合
4. リスト項目のカテゴリ分類（通常曲/フォルダ/レベルフォルダ/サブフォルダ/コース）
5. スクロール可能なリスト描画（上下キー/アナログ入力対応）
6. 循環ナビゲーション（リスト末尾→先頭、先頭→末尾）
7. Home/End/PageUp/PageDown対応
8. 選択変更時のジャケット・スコア・楽曲情報リフレッシュ

**関連システム・外部連携**：ファイルシステム（楽曲ディレクトリスキャン）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | refreshfilelistサブルーチンで楽曲一覧を生成し、スクロール可能なリストとして描画 |

## 機能種別

データ検索・画面表示・ナビゲーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| dir | str | No | 現在のディレクトリパス | 相対パス |
| sorttype | int | No | ソート方式 | 0(通常) / 1(レベル順) |
| selnow | int | No | 現在の選択位置 | 0 - mnum-1 |
| levnow | int | No | 現在の難易度 | 0-3 |

### 入力データソース

- songs/ディレクトリ配下の.ksh/.kcoファイル群
- ディレクトリ構造（フォルダ・サブフォルダ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| minfo | int[SONG_MAX][4][n] | 曲リストの整数情報配列 |
| minfostr | str[SONG_MAX][4][n] | 曲リストの文字列情報配列 |
| mnum | int | リスト内のアイテム総数 |
| footerdirnum | int | フッターディレクトリ数 |
| levcnt | int[20] | レベル順ソート時の各レベル開始位置 |

### 出力先

- グローバル変数（minfo, minfostr, mnum等）
- 画面表示（曲リスト描画）

## 処理フロー

### 処理シーケンス

```
1. 曲リスト生成（*refreshfilelist）
   ├─ ディレクトリ内ファイル列挙（dirlist）
   ├─ .kshファイルのメタデータ読み込み（title, level等）
   ├─ フォルダ/サブフォルダの認識
   ├─ コースファイル(.kco)の認識
   ├─ ソート方式に応じた並べ替え
   │   ├─ sorttype=0: 通常順（ディレクトリ構造準拠）
   │   └─ sorttype=1: レベル順（難易度値でソート）
   └─ minfo/minfostr配列への格納
2. リスト表示
   ├─ 選択位置周辺のリスト項目描画
   ├─ フォルダ/楽曲/コースのアイコン区別表示
   └─ 選択カーソルアニメーション
3. スクロール制御
   ├─ 上下キー: 1曲単位スクロール
   ├─ PageUp/Down: 8曲単位スクロール
   ├─ Home/End: 先頭/末尾移動
   └─ アナログ入力: 連続スクロール
```

### フローチャート

```mermaid
flowchart TD
    A[refreshfilelist] --> B[ディレクトリスキャン]
    B --> C[.kshファイル列挙]
    C --> D[メタデータ読み込み]
    D --> E{sorttype}
    E -->|0| F[通常順ソート]
    E -->|1| G[レベル順ソート]
    F --> H[minfo/minfostr配列格納]
    G --> H
    H --> I[リスト描画]
    I --> J[入力待ち]
    J --> K{入力種別}
    K -->|上下キー| L[1曲スクロール]
    K -->|PageUp/Down| M[8曲スクロール]
    K -->|Home/End| N[先頭/末尾]
    L --> O[リフレッシュ]
    M --> O
    N --> O
    O --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | アイテム種別 | minfo.i.0.0の値: 0=通常曲, -1=フォルダ, -3=レベルフォルダ, -5=サブフォルダ, -6=サブフォルダ, -8=コースフォルダ, 4=コース | 常時 |
| BR-02 | SONG_MAX制限 | 楽曲数上限は8192 | *refreshfilelist |
| BR-03 | 循環ナビゲーション | リスト末尾→先頭、先頭→末尾に循環 | selnow範囲超過時 |
| BR-04 | 難易度フォールバック | 選択難易度のデータ未存在時は隣接難易度に自動切替 | 曲選択変更時 |
| BR-05 | フッターディレクトリ | リスト末尾の親ディレクトリ戻りアイテムはfooterdirnum変数で管理 | dir!=""時 |

### 計算ロジック

- PageUp/Down: `repeat 8: selnow++/--: loop`（select.hsp 1095-1100行目, 1161-1166行目）
- アナログスクロール: `selslider / SELSLIDER_MAX` で移動量決定

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

本機能ではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ディレクトリ不在 | dirが存在しない | dir=""にリセット |

### リトライ仕様

リトライ処理は実装されていない。

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

トランザクション処理は適用されない。

## パフォーマンス要件

- 楽曲数上限: SONG_MAX=8192
- ディレクトリスキャン時間は楽曲数に比例

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

特になし。

## 備考

- select.hsp内の*refreshfilelistサブルーチンとして実装
- ソート方式はFXキー同時押しで動的に切替可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshootmania.hsp | `kshootmania.hsp` | SONG_MAX=8192定数、minfo/minfostr配列構造 |

**読解のコツ**: minfo配列は4次元で使用される。`minfo.曲インデックス.難易度.プロパティ` の形式。minfo.i.0.0 < 0 の場合はフォルダやレベルフォルダ等の特殊アイテム。

- **25行目**: `#define SONG_MAX 8192`

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | *refreshfilelistサブルーチン |
| 2-2 | select.hsp | `src/scene/select.hsp` | スクロール入力処理（827-1216行目） |

**主要処理フロー**:
- **42行目**: `gosub *refreshfilelist` - 初期化時の曲リスト生成呼び出し
- **836-838行目**: 下キースクロール `selnow++; if(selnow>=mnum):selnow=0`
- **911-913行目**: 上キースクロール `selnow--; if(selnow<0):selnow=mnum-1`
- **1095-1100行目**: PageDown `repeat 8: selnow++: loop`
- **1161-1166行目**: PageUp `repeat 8: selnow--: loop`

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

```
start_select (src/scene/select.hsp)
    │
    ├─ *refreshfilelist (曲リスト生成)
    │      ├─ dirlist (ディレクトリ列挙)
    │      ├─ .kshファイルメタデータ読み込み
    │      ├─ ソート処理
    │      └─ minfo/minfostr配列格納
    │
    ├─ 上下キー入力 → selnow++/--
    ├─ Home/End → selnow=0 / selnow=mnum-1
    ├─ PageUp/Down → selnow+=/-=8
    ├─ アナログ入力 → selslider → selnow
    │
    ├─ *refreshjacket (ジャケット更新)
    ├─ *refreshscore (スコア更新)
    └─ *refreshsonginfo (楽曲情報更新)
```

### データフロー図

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

songs/**/*.ksh ──────────────▶ *refreshfilelist ───────────────▶ minfo/minfostr配列
songs/**/*.kco ──────────────▶     │                               mnum（総数）
ディレクトリ構造 ────────────▶     └── ソート処理 ────────────▶ levcnt（レベル位置）
                                                                    footerdirnum
キーボード/アナログ ─────────▶ スクロール制御 ────────────────▶ selnow（選択位置）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | 曲リスト生成・スクロール制御・描画 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | SONG_MAX定数・minfo/minfostr配列定義 |
| msel_0.png | `imgs/msel_0.png` | 画像 | 通常曲リスト項目背景 |
| msel_dir0.png | `imgs/msel_dir0.png` | 画像 | フォルダリスト項目背景 |
| msel_lev0.png | `imgs/msel_lev0.png` | 画像 | レベルフォルダリスト項目背景 |
| msel_sub0.png | `imgs/msel_sub0.png` | 画像 | サブフォルダリスト項目背景 |
| msel_course0.png | `imgs/msel_course0.png` | 画像 | コースリスト項目背景 |
| msel_bar.png | `imgs/msel_bar.png` | 画像 | スクロールバー |
| msel_barcur.png | `imgs/msel_barcur.png` | 画像 | スクロールバーカーソル |
