CISO / CSO を読む

# CISO / CSO を読む

CISO ファイルは CD/DVD イメージファイルのひとつ。CSO ファイルとも呼ばれるが、この文書の中においては CISO と統一している。

機能が同じものとしては ISZ ファイルがある。

当文書は、引用されたものを除いて [![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)](http://creativecommons.org/publicdomain/zero/1.0/) とする。

## CISO ファイルの特徴

- 圧縮される (圧縮単位はセクタ = 通常 2048 バイト)
- 単一データトラックのみ
- バイトオーダーはリトルエンディアン (明確に仕様化されているわけではないようだが、作成は i386、利用は PSP なんだろ?)

## CISO ファイル構造

```
     +----------------------+
+00h |  ファイルヘッダ      |
     +----------------------+
+18h |  セクタインデックス  |
     +----------------------+
+... |  圧縮セクタデータ列  |
     +----------------------+
```

## CISO ファイル識別部

CISO ファイルの認識情報と諸情報が記述される。ファイル位置0から始まる。

(ciso-1.0.0/ciso.h から引用)

> ```c:ciso-1.0.0/ciso.h
typedef struct ciso_header
{
        unsigned char magic[4];                 /* +00 : 'C','I','S','O'                 */
        unsigned long header_size;              /* +04 : header size (==0x18)            */
        unsigned long long total_bytes;         /* +08 : number of original data size    */
        unsigned long block_size;               /* +10 : number of compressed block size */
        unsigned char ver;                      /* +14 : version 01                      */
        unsigned char align;                    /* +15 : align of index value            */
        unsigned char rsv_06[2];                /* +16 : reserved                        */
#if 0
// INDEX BLOCK
        unsigned int index[0];                  /* +18 : block[0] index                  */
        unsigned int index[1];                  /* +1C : block[1] index                  */
             :
             :
        unsigned int index[last];               /* +?? : block[last]                     */
        unsigned int index[last+1];             /* +?? : end of last data point          */
// DATA BLOCK
        unsigned char data[];                   /* +?? : compressed or plain sector data */
#endif
}CISO_H;
> ```

### メモリレイアウト

```
      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
      | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 +00h | magic         | header_size   | total_bytes                   |
      +---------------+---+---+-------+-------------------------------+
 +10h | block_size    |ver|ali|reserve|
      +---------------+---+---+-------+
```

## セクタインデックス

これは `struct ciso_header` 内のコメントを見てわかるように、無符号32ビット整数値の羅列でセクタ数 + 1となっている。ただし、下位31ビットがインデックスに対応するセクタデータのオフセット、最上位の1ビットが圧縮されているかいないかを表している。

気をつけることはこの31ビット整数値はそのまま利用しないこと。一度64ビット整数値 (`uint64_t` あたり) に変換し、`ciso_header.align` の分だけ調整する必要がある。具体的には次のとおり:

```c:c
(uint64_t)(index[n] & 0x7fffffff) << ciso_header.align;
```

もっともたいていの場合は `ciso_header.align` は `0` になっている。

この仕組みは、元となる ISO ファイルが 2 GiB 以上の場合にも対応可能とするためである。DVD イメージや BD イメージなどでは必要になるだろう。PSP 上で利用するのかは疑問ではあるが。

セクタ数 + 1となっているのは、インデックスの値は対応するセクタの開始位置を表しているからである。セクタデータは羅列になっているため、セクタデータの終端位置はひとつ後ろのインデックスを見れば得ることが出来る。最終セクタの終端位置を得るために、インデックスがひとつ余計に用意されているわけだ。

```
+-----------+ <-- インデックス[0] (これはセクタインデックスの終わりと同じ)
| セクタ[0] |
+-----------+ <-- インデックス[1]
| セクタ[1] |
+-----------+ <-- インデックス[2]
    :
+-----------+ <-- インデックス[n]
| セクタ[n] |
+-----------+ <-- インデックス[n + 1]
```

## 圧縮セクタデータ列

インデックスの圧縮フラグが0であれば無圧縮、1であれば deflate によって圧縮されている。データの位置も読み込み量もインデックスを見ればわかるので、後は示す位置から必要な量を読み込んで処理すれば読み込みが出来る。

## 参考資料

- ciso-1.0.0.tar.gz  
  \<http://sourceforge&#x2e;net/projects/ciso/\>

---

<p xmlns:dct="http://purl.org/dc/terms/">
  <a rel="license"
     href="http://creativecommons.org/publicdomain/zero/1.0/">
    <img src="http://i.creativecommons.org/p/zero/1.0/88x31.png" style="border-style: none;" alt="CC0" />
  </a>
  <br />
  To the extent possible under law,
  <span resource="[_:publisher]" rel="dct:publisher">
    <span property="dct:title">dearblue</span></span>
  has waived all copyright and related or neighboring rights to
  this work.
</p>