# 帳票設計書 3-楽曲情報表示画像

## 概要

本ドキュメントは、K-ShootMANIAのプレイ中に画面上部に表示される楽曲情報（タイトル、アーティスト、難易度、レベル等）をPNG画像として保存する「楽曲情報表示画像」機能の帳票設計書である。プレイシーン初期化時にminfoprepareサブルーチンで生成される2枚の画像（minfo_label.pngとminfo_detail.png）がキャッシュディレクトリに保存される。

### 本帳票の処理概要

本帳票は、プレイシーン開始時に現在選択中の楽曲情報をテキスト描画・画像合成して2枚のPNG画像を生成し、キャッシュディレクトリに保存する。これらの画像はプレイ画面のHUD（ヘッドアップディスプレイ）として表示される。

**業務上の目的・背景**：音楽ゲームのプレイ中に「どの楽曲をプレイしているか」をプレイヤーに視覚的に伝える必要がある。楽曲タイトル、アーティスト名、難易度、レベルといった情報を事前にPNG画像として合成しておくことで、プレイ中のテキスト描画コストを削減し、3Dレンダリングとの統合を容易にしている。

**帳票の利用シーン**：楽曲選択後、プレイシーンの初期化処理（minfoprepare）で毎回生成される。プレイ画面上部に常時表示され、プレイヤーが現在の楽曲情報を確認できる。

**主要な出力内容**：
1. minfo_label.png - 楽曲タイトルとアーティスト名を含むラベル画像（240x44相当）
2. minfo_detail.png - 難易度アイコン、レベル数値、その他詳細情報を含む画像（240x66相当）

**帳票の出力タイミング**：プレイシーン初期化時のminfoprepareサブルーチン呼び出し時。play_init.hsp内のstart_play関数から呼ばれるgosub *minfoprepareで実行される。

**帳票の利用者**：K-ShootMANIAのランタイムエンジンが内部的にテクスチャとして使用する。プレイヤーは画面上部に描画された結果として閲覧する。

## 帳票種別

画像出力（PNG画像キャッシュ）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | プレイシーン初期化 | SCENE_PLAY（play_init.hsp内のgosub *minfoprepare） | 楽曲選択後に自動生成 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PNG |
| 用紙サイズ | 該当なし |
| 向き | 横 |
| ファイル名 | cache/minfo_label.png, cache/minfo_detail.png |
| 出力方法 | ローカルファイルシステムへの直接書き出し |
| 文字コード | 該当なし（バイナリ画像） |

### PNG固有設定

| 項目 | 内容 |
|-----|------|
| minfo_label.pngサイズ | getsize(240) x getsize(44) ピクセル |
| minfo_detail.pngサイズ | getsize(240) x getsize(66) ピクセル |
| テキスト色 | RGB(0, 32, 8) - 濃い緑色 |
| フォント | lang.0.0（システム設定依存） |

## 帳票レイアウト

### レイアウト概要

2枚の画像で構成され、プレイ画面の上部に配置される。

```
minfo_label.png (Image 53):
+---------------------------------------------+
| [ジャケット画像表示エリア] [タイトル]           |
|                          [アーティスト名]      |
+---------------------------------------------+
  getsize(240) x getsize(44) ピクセル

minfo_detail.png (Image 142):
+---------------------------------------------+
| [難易度アイコン] [Lv数値]                      |
| [BPM表示エリア] [ハイスピード表示エリア]        |
| [進行バーエリア]                               |
+---------------------------------------------+
  getsize(240) x getsize(66) ピクセル
```

### ヘッダー部（minfo_label.png）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 楽曲タイトル | 楽曲名（テキストまたはカスタム画像） | csongtitle / csongtitleimg | テキスト描画（フォントサイズ自動調整）またはカスタム画像 |
| 2 | アーティスト名 | 作曲者名（テキストまたはカスタム画像） | csongartist / csongartistimg | テキスト描画（フォントサイズ自動調整）またはカスタム画像 |

### 明細部（minfo_detail.png）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | 難易度アイコン | LIGHT/CHALLENGE/EXTENDED/INFINITEの区分 | csongdifficulty | IMG_RESULT_DIFFICULTY画像のコピー | getsize(42)xgetsize(12) |
| 2 | レベル数値 | 1～20のレベル値 | csonglevel | 数字画像（Image 52）からコピー | 最大2桁 |

### フッター部

該当なし（画像ファイルのためフッターはない。BPMやハイスピード等の動的情報はプレイ中にリアルタイム描画される）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| プレイシーン初期化 | start_play内のgosub *minfoprepareが呼ばれること | Yes |
| 楽曲データ存在 | KSHファイルからcsongtitle, csongartist等が読み込まれていること | Yes |

### ソート順

該当なし（固定2ファイル出力）

### 改ページ条件

該当なし

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを使用しない。以下のメモリ上の変数を参照する。

| データ構造名 | 用途 | 備考 |
|-----------|------|---------|
| csongtitle | 楽曲タイトル | KSHファイルのtitle=パラメータから取得 |
| csongartist | アーティスト名 | KSHファイルのartist=パラメータから取得 |
| csongtitleimg | タイトル画像パス | KSHファイルのtitle_img=パラメータ（空文字ならテキスト描画） |
| csongartistimg | アーティスト画像パス | KSHファイルのartist_img=パラメータ（空文字ならテキスト描画） |
| csongdifficulty | 難易度（0=LIGHT, 1=CHALLENGE, 2=EXTENDED, 3=INFINITE） | KSHファイルのdifficulty=パラメータ |
| csonglevel | レベル値（1～20） | KSHファイルのlevel=パラメータ |
| csongdir | 楽曲ディレクトリ名 | カスタム画像読み込み時のパス構築に使用 |

### テーブル別参照項目詳細

#### Image リソース

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| Image 51 | minfo_label.pngのベーステンプレート | alCopyImageToImage 51,53 | 事前読み込み済みの背景画像 |
| Image 141 | minfo_detail.pngのベーステンプレート | alCopyImageToImage 141,142 | 事前読み込み済みの背景画像 |
| IMG_RESULT_DIFFICULTY | 難易度アイコン画像 | alCopyImageToImage | 難易度ごとにY座標オフセット |
| Image 52 | 数字画像（レベル表示用） | alCopyImageToImage | 0-9の数字スプライトシート |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| タイトルフォントサイズ | tsize.2/9に基づく段階的選択（50超→getsize(9), 40超→getsize(10), ...26以下→getsize(15)） | 整数（段階的） | テキスト幅に応じた自動縮小 |
| アーティストフォントサイズ | tsize.2/9に基づく段階的選択（48超→getsize(9), 36超→getsize(10), 以下→getsize(11)） | 整数（段階的） | テキスト幅に応じた自動縮小 |
| レベル値のクランプ | max(min(csonglevel, 20), 1) | 該当なし | 1～20の範囲に制限 |
| 難易度Y座標 | getsize(12)*csongdifficulty | 該当なし | 難易度に応じたスプライトシートオフセット |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[gosub *minfoprepare] --> B[Image142作成 - minfo_detail用]
    B --> C[Image53作成 - minfo_label用]
    C --> D{csongtitleimg = 空?}
    D -->|Yes| E[テキスト描画: フォントサイズ自動調整]
    D -->|No| F[カスタム画像読み込み・合成]
    E --> G{csongartistimg = 空?}
    F --> G
    G -->|Yes| H[テキスト描画: アーティスト名]
    G -->|No| I[カスタム画像読み込み・合成]
    H --> J[難易度アイコンコピー]
    I --> J
    J --> K[レベル数値描画]
    K --> L[alSaveFile minfo_label.png]
    L --> M[alSaveFile minfo_detail.png]
    M --> N[return]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| カスタムタイトル画像不存在 | csongtitleimgで指定されたファイルが存在しない | なし | alCreateImageByFileが失敗し空白表示となる |
| カスタムアーティスト画像不存在 | csongartistimgで指定されたファイルが存在しない | なし | alCreateImageByFileが失敗し空白表示となる |
| テキストが描画領域を超過 | 楽曲タイトル/アーティスト名が長い | なし | フォントサイズを段階的に縮小して対応 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | プレイごとに2ファイル |
| 目標出力時間 | 数十ms（テキスト描画+PNG保存） |
| 同時出力数上限 | 2（label + detail） |

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

- 出力先はcacheディレクトリ内に固定されており、パストラバーサルのリスクは低い
- ファイル名は固定（minfo_label.png, minfo_detail.png）で毎回上書きされる
- カスタム画像パスはKSHファイル内の設定値に基づく

## 備考

- minfo_label.pngはプレイ画面上部のタイトル/アーティスト表示に使用される（play_draw_frame.hsp:921-926行目でtex_minfo_labelとして描画）
- minfo_detail.pngはBPM、ハイスピード表示の背景として使用される（play_draw_frame.hsp:925行目でtex_minfo_detailとして描画）
- pl_minfoprepareサブルーチン（play_utils.hsp:67行目以降）はプレイ前のスプラッシュスクリーン用の類似画像を生成するが、サイズが異なる（360x90相当）
- テキスト描画時のフォントサイズは文字列長に応じて7段階で自動調整される

---

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

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

### 推奨読解順序

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

楽曲情報に関連するグローバル変数とImage番号の対応を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_utils.hsp | `src/scene/play/play_utils.hsp` | 1-5行目: Image 142(detail用), Image 53(label用)の作成。Image 51, 141が事前に読み込まれたベーステンプレート |

**読解のコツ**: HSP3のalCreateImage/alCopyImageToImageはartlet2dライブラリの関数。Image番号は整数で管理され、alSelectImageで操作対象を切り替える。

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

minfoprepareサブルーチンがどこから呼ばれるかを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_init.hsp | `src/scene/play/play_init.hsp` | 237行目: gosub *minfoprepareの呼び出し |

**主要処理フロー**:
1. **play_init.hsp:237**: gosub *minfoprepareが呼ばれる
2. **play_utils.hsp:1**: *minfoprepareラベルから処理開始

#### Step 3: 画像合成処理を理解する

minfoprepareサブルーチンの内部処理を詳細に読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_utils.hsp | `src/scene/play/play_utils.hsp` | 1-65行目: *minfoprepareサブルーチン全体 |

**主要処理フロー**:
- **3行目**: alCreateImage 142でminfo_detail用画像を作成
- **5行目**: alCreateImage 53でminfo_label用画像を作成
- **7行目**: alColor 0,32,8,255 で文字色を設定
- **8-33行目**: タイトル描画（テキスト or カスタム画像）
- **34-51行目**: アーティスト名描画（テキスト or カスタム画像）
- **52-53行目**: 難易度アイコンをImage142にコピー
- **54-60行目**: レベル数値をImage142にコピー
- **61-62行目**: alSaveFile minfo_label.png 保存
- **63-64行目**: alSaveFile minfo_detail.png 保存

#### Step 4: プレイ画面での表示を理解する

生成された画像がどのようにプレイ画面で利用されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_graphics.hsp | `src/scene/play/play_graphics.hsp` | 1-48行目: loadUIGraphics関数でtex_minfo_label, tex_minfo_detailとしてテクスチャ化 |
| 4-2 | play_draw_frame.hsp | `src/scene/play/play_draw_frame.hsp` | 921-926行目: hgcopy/hgcopy_aによるプレイ画面上部への描画 |

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

```
start_play (play_init.hsp)
    |
    +-- gosub *minfoprepare (play_utils.hsp:1)
    |       |
    |       +-- alCreateImage 142 (minfo_detail用Image作成)
    |       +-- alCreateImage 53 (minfo_label用Image作成)
    |       +-- alColor (テキスト色設定)
    |       +-- [タイトル描画]
    |       |       +-- alDrawText (テキスト) or alCreateImageByFile (カスタム画像)
    |       +-- [アーティスト描画]
    |       |       +-- alDrawText (テキスト) or alCreateImageByFile (カスタム画像)
    |       +-- alCopyImageToImage (難易度アイコンコピー)
    |       +-- alCopyImageToImage (レベル数値コピー)
    |       +-- alSaveFile "cache/minfo_label.png"
    |       +-- alSaveFile "cache/minfo_detail.png"
    |
    +-- loadUIGraphics (play_graphics.hsp:1)
            |
            +-- texload2 "cache/minfo_label.png" -> tex_minfo_label
            +-- texload2 "cache/minfo_detail.png" -> tex_minfo_detail
```

### データフロー図

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

KSHファイル             play_utils.hsp                  cache/
  title=              *minfoprepare (1-65行目)           minfo_label.png
  artist=               |                               minfo_detail.png
  difficulty=           +-- テキスト描画 or
  level=                |   カスタム画像合成                |
  title_img=            +-- 難易度アイコン合成              v
  artist_img=           +-- レベル数値描画
                        +-- alSaveFile                 play_graphics.hsp
Image 51              (PNG保存)                          loadUIGraphics
  (ラベルテンプレート)                                      |
Image 141                                                 v
  (詳細テンプレート)                                    tex_minfo_label
Image 52                                               tex_minfo_detail
  (数字スプライト)                                          |
IMG_RESULT_DIFFICULTY                                      v
  (難易度アイコン)                                    play_draw_frame.hsp
                                                        drawFrame (921-926行目)
                                                        hgcopy/hgcopy_a
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_utils.hsp | `src/scene/play/play_utils.hsp` | ソース | *minfoprepareサブルーチン（1-65行目）。画像合成・保存の主処理 |
| play_init.hsp | `src/scene/play/play_init.hsp` | ソース | gosub *minfoprepareの呼び出し元（237行目） |
| play_graphics.hsp | `src/scene/play/play_graphics.hsp` | ソース | loadUIGraphics関数でキャッシュ画像をテクスチャとして読み込み |
| play_draw_frame.hsp | `src/scene/play/play_draw_frame.hsp` | ソース | drawFrame関数内でtex_minfo_label/tex_minfo_detailを画面に描画（921-926行目） |
| minfo_label.png | `cache/minfo_label.png` | キャッシュ | 楽曲タイトル・アーティスト名画像 |
| minfo_detail.png | `cache/minfo_detail.png` | キャッシュ | 難易度・レベル・詳細情報画像 |
