PlayStation的CD格式

来源:互联网 发布:环保工作有哪些 知乎 编辑:程序博客网 时间:2024/05/16 07:36

前言

本文的内容算是一个学习笔记,主要资料来源于张晓波(pinokio)翻译的《Everything You Have Always Wanted to Know about the Playstation But Were Afraid to Ask.》,这个资料Agemo的主页那边有下载,在【新手必读硬件资料】目录下面。里面有两个章节和CD有关,一个是CDROM,另一个是CD,其中CDROM主要讲PS中和CD相关的各种指令和设置。CD这章才描述CD格式,另外这一章并不存在于原版的《Everything》中,应该是pinokio自己整理的PS CD格式资料

 

关于CD格式,要分成三个部分来说,首先是扇区格式,然后是光盘结构,最后是文件系统。这些内容都在CD这一章节中,但是光盘结构这部分描述得不太清楚,本文会略做详解。实际上这三部分是由不同的标准制定的。比如扇区格式、光盘结构等来自于SonyPhilips等大公司制定的彩虹书(Rainbow Book),文件系统使用的是ISO9660,它们各有各的渊源。

 

扇区格式

首先来说一下扇区格式,PS使用的扇区格式包括Mode2 form1Mode2 form 2,这两个格式的大小都是0x930,区别在于form1包含ECC(纠错码),用来保存重要的数据,那么实际存放数据的大小只有0x800form2仅含有EDC(检错码),适合用来存放视频、音频之类的数据,相应的也多出了ECC276个字节。

 

下面具体的看一下这两个格式的构成:

类型 #2: Mode 2 (XA), form 1

-----------------------------------------------------

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0000h 00 FF FF FF FF FF FF FF FF FF FF 00 [-ADDR-] 02

0010h [--FLAGS--] [--FLAGS--] [---DATA...

...

0810h             ...DATA---] [---EDC---] [---ECC...

...

0920h                                      ...ECC---]

-----------------------------------------------------

 

类型 #3: Mode 2 (XA), form 2

-----------------------------------------------------

       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

0000h 00 FF FF FF FF FF FF FF FF FF FF 00 [-ADDR-] 02

0010h [--FLAGS--] [--FLAGS--] [---DATA...

...

0920h                         ...DATA---] [---EDC---]

-----------------------------------------------------

 

:

 

ADDR:  扇区地址,用BCD编码成 分::

FLAGS: Mode 2 (XA)扇区中用来描述扇区类型,冗余重复一次

DATA:  扇区里包含实际数据的区域

EDC:   Error Detection Code检错码

ECC:   Error Correction Code纠错码

 

上面这些内容来自pinokio的文档,值得注意的是ADDR的组成是分:秒:帧(原文是sector,扇区,而且这个单位一般称作分秒),具体的换算是1 minute = 60 seconds = 4500 sectors, 1 second = 75 sectors。光驱头一秒读取75个扇区叫做1倍速,有时候也称1倍速是150k/s,但这要看扇区格式是什么,所以这个说法并不准确。

 

这两个扇区格式来自于SonyPhilips制定的Yellow BookWhite BookMode1来自于Red Book,这些标准还有不少,统称Rainbow Book。不过这些标准并不是公开的(要花钱买),所以也没有参考文档。我所能知道也就是pinokio文章中所提到的那些,这里不再赘述了。

光盘结构

描述

额外信息

000000-000015

数据轨引导块

16个扇区

000016-024520

数据轨程序区

Mode2 Form12

024521-024670

数据轨后空隙

最少150扇区

024671-024820

1音轨前间隙

最少150扇区

024821-048326

音轨#1

 

048327-048476

2音轨前间隙

0150扇区

048477-072485

音轨#2

 

. .

 

 

191281-191430

9音轨前间隙

 

191431-214349

音轨9

 

214350-??????

导出轨

由刻录机写入,不可读

 

这段内容是CD章节的第一部分,原文应该来自PSX CD-Info,也可以参考。

 

但我觉得解释并不太明确,不能解释我的一些疑问,所以从网上找了一些资料。

首先打开一个PS光盘镜像,你可以看到第一个扇区的时间是0:2:0,而看pscx的源代码,也能看到他直接读取0:2:16来获取root的信息。那么为什么从0:2:0开始?其实文章也提到“有的raw镜像在最前面还包含有光盘导入轨,是一片连续的空白扇区,忽略它”。我很怀疑这个说法,前面的2秒(150扇区)应该是pre-gap。一个光盘一般包括一个导入轨,若干个数据轨和一个导出轨,数据轨编号从1开始,最多可以有99个。每个数据轨的前后可以有pre-gappost-gapgap的大小一般是150扇区,也就是2秒。这些间隙的功能其实是提示系统扇区模式发生变化,也是为了给系统转模式提供缓冲时间(同一个轨道内的扇区模式必须一样,似乎form可以不一样(?))。那么如果扇区模式没有变化,其实并不需要gap,这就是为什么上表中音轨之间的gap0或者150扇区。另外,数据轨的post-gap和音轨的pre-gap虽然都是空白,但是它们的mode其实不一样。

 

上表还有一个容易混淆的地方,首先它将数据轨分成了3块,boot blockprogram areapost-gap,其实16扇区的boot blockISO 9660的标准,这个见下节,并不需要写在这里。这种分法容易和光盘的结构搞混。光盘其实分成leadinprogramleadout(导入区,节目区和导出区,其实也就对应一个导入轨,若干个数据轨和一个导出轨,这个说法也不够准确,应该是一个session包含这3部分,一般光盘都是单session的,也有多session的光盘),这里故意写英文是因为boot(引导区)和leadin(导入区)中文看起来十分的相像。另外program其实是节目的意思,因为CD一开始就是放歌曲的。一首歌一轨道,轨道的概念也是源自于此。数据CD往往就一轨了事了,我看到的PS光盘大多如此。

 

关于音轨我也有点疑惑,首先音轨其实是一个特殊的概念,“每个扇区各存放588个立体声取样数据,无模式之分”,而且必须放在最后。PS光盘的扇区格式必须是mode 2 form 1/2,可能是有些特殊的游戏光盘使用了音轨。

 

下面说一下导入轨,导入轨包含TOCTable Of Content,内容表),指出每个数据轨的起点。所以不可能是连续空白的扇区。但是一般的ISO镜像并没有导入轨,ccd文件中内容也许就是导入轨的内容。

 

这里总结一下,首先CD可以由多个Session组成,每个Session包括三个部分:导入区,节目区和导出区。导入区只包含一条导入轨,里面有TOC,包含该Session中的每个数据轨的信息。节目区中则可以有多条数据轨,数据轨前后可以有间隙,一般原则是前后模式不同则加间隙给读取设备缓冲。导出区只包含一条导出轨,里面没有内容,只是标明结束。

文件系统:ISO 9660

接着说一下文件系统,ISO 9660是为CD制定的标准,Yellow BookWhite Book等与之兼容。PS使用的是ISO 9660 level 1。和level 23相比,要求限制更加多一些,比如文件名、目录名使用字符和长度限制。

 

ISO 9660来源于High Sierra1986年被ECMA采用并修改成为Ecma-119,提交到ISO后成为了ISO 9660:1988,目前最新的版本是ISO 9660:1999

 

所以本章的参考文档是Ecma-199。不过下面还是称呼为ISO 9660

 

ISO 9660分成两部分,系统区数据区

 

1.         系统区

0-1516个扇区,叫做系统区是因为这部分是给系统使用的,比如VCD,就是给VCD机使用,是PS就是给PS机用,里面存放什么东西,什么格式,都是由各个系统决定的。

 

这里说的0-15,指的是0:2:0开始的数据,应该是以第一条数据轨作为起点,之后的extent都是以此为起点。

 

PS的系统区前5个扇区包含区域信息,有JAPEURUSA三种。

 

2.         数据区

从扇区16开始,之后有4种描述符来描述数据区存放的数据:

l         卷描述符

l         文件描述符

l         目录描述符

l         路径表

 

1.         卷描述符 Volume Descriptor

卷描述符分成5种,但是我只看到过主卷描述符(Primary Volume Descriptor)和卷描述集终止符(Volume Descriptor Set Terminator)。

 

下面主要说一下主卷描述符,我找一下相关的代码,在各种linux源码中基本上都有iso_fs.h之类的文件,里面就有相关的定义。一般如下:

 

typedef struct iso_primary_descriptor {
    U8 type                     [ISODCL (  1,   1)]; /* 711 */
    U8 id                       [ISODCL (  2,   6)];
    U8 version                  [ISODCL (  7,   7)]; /* 711 */
    U8 unused1                  [ISODCL (  8,   8)];
    U8 system_id                [ISODCL (  9,  40)]; /* achars */
    U8 volume_id                [ISODCL ( 41,  72)]; /* dchars */
    U8 unused2                  [ISODCL ( 73,  80)];
    U8 volume_space_size        [ISODCL ( 81,  88)]; /* 733 */
    U8 unused3                  [ISODCL ( 89, 120)];
    U8 volume_set_size          [ISODCL (121, 124)]; /* 723 */
    U8 volume_sequence_number   [ISODCL (125, 128)]; /* 723 */
    U8 logical_block_size       [ISODCL (129, 132)]; /* 723 */
    U8 path_table_size          [ISODCL (133, 140)]; /* 733 */
    U8 type_l_path_table        [ISODCL (141, 144)]; /* 731 */
    U8 opt_type_l_path_table    [ISODCL (145, 148)]; /* 731 */
    U8 type_m_path_table        [ISODCL (149, 152)]; /* 732 */
    U8 opt_type_m_path_table    [ISODCL (153, 156)]; /* 732 */
    U8 root_directory_record    [ISODCL (157, 190)]; /* 9.1 */
    U8 volume_set_id            [ISODCL (191, 318)]; /* dchars */
    U8 publisher_id             [ISODCL (319, 446)]; /* achars */
    U8 preparer_id              [ISODCL (447, 574)]; /* achars */
    U8 application_id           [ISODCL (575, 702)]; /* achars */
    U8 copyright_file_id        [ISODCL (703, 739)]; /* 7.5 dchars */
    U8 abstract_file_id         [ISODCL (740, 776)]; /* 7.5 dchars */
    U8 bibliographic_file_id    [ISODCL (777, 813)]; /* 7.5 dchars */
    U8 creation_date            [ISODCL (814, 830)]; /* 8.4.26.1 */
    U8 modification_date        [ISODCL (831, 847)]; /* 8.4.26.1 */
    U8 expiration_date          [ISODCL (848, 864)]; /* 8.4.26.1 */
    U8 effective_date           [ISODCL (865, 881)]; /* 8.4.26.1 */
    U8 file_structure_version   [ISODCL (882, 882)]; /* 711 */
    U8 unused4                  [ISODCL (883, 883)];
    U8 application_data         [ISODCL (884, 1395)];
    U8 unused5                  [ISODCL (1396, 2048)];
}ISO_PVD;

 

解释一下后面的注释,如711,指的是ecma-119中的7.1.1所描述的数据类型,dchar等也在第7章有说明,请自行查找。

 

其中比较重要的两个字段是type_l_path_tableroot_directory_record,其中前者指向path table,这张表共有4份,区别在于大尾小尾的不同。root_directory_record则直接存放了根目录的信息,注意并不是一个指向directory_record的指针。

 

2.         文件和目录描述符

这两个描述符都统一在directory record结构中。

typedef struct iso_directory_record {
    U8 length                   [ISODCL ( 1,  1)]; /* 711 */
    U8 ext_attr_length          [ISODCL ( 2,  2)]; /* 711 */
    U8 extent                   [ISODCL ( 3, 10)]; /* 733 */
    U8 size                     [ISODCL (11, 18)]; /* 733 */
    U8 date                     [ISODCL (19, 25)]; /* 7 by 711 */
    U8 flags                    [ISODCL (26, 26)];
    U8 file_unit_size           [ISODCL (27, 27)]; /* 711 */
    U8 interleave               [ISODCL (28, 28)]; /* 711 */
    U8 volume_sequence_number   [ISODCL (29, 32)]; /* 723 */
    U8 name_len                 [ISODCL (33, 33)]; /* 711 */
    U8 name                     [0];
} __attribute__((packed)) ISO_DR;

 

文件的入口和大小分别定义在extentsize中。ISO 9660中所有文件都是连续的,所以只要起始扇区和扇区数量就可以确定一个文件。要注意的是extent的单位是扇区,如果要转成时间的话需要额外加上2秒,size的单位则是字节。目录也被当成一个特殊的文件来看待,目录中保存的信息就是directory record列表,所以这种结构是树状的,只要给出root,就能一层层遍历所有的目录和文件。

 

3.         路径表

路径表的表项定义如下

typedef struct iso_path_table{
    U8 name_len                 [ISODCL ( 1,  1)]; /* 721 */
    U8 ext_attr_length          [ISODCL ( 2,  2)]; /* 711 */
    U8 extent                   [ISODCL ( 3,  6)]; /* 731 */
    U8 parent                   [ISODCL ( 7,  8)]; /* 721 */
    U8 name                     [0];
} __attribute__((packed)) ISO_PTR;

 

这张表只保存目录,而且各级目录都放在这张表中,只用一个parent加以区别。用这张表应该可以更快捷的定位。

 

实用

上面这些内容看起来有些枯燥,那么下面举一些具体实用的例子,帮助巩固一下。

 

1.         Agemoiso patch

这个软件叫做iso patch,但实际是对Yellow Book的扇区标准进行支持。主要功能是给定地址,文件后,可以将目标文件写入到iso镜像中,并且自动重算ECCEDC。对Mode1也支持,但是PS不使用这个标准,Mode 2 Form 2则未经测试。所以基本上有用的就是默认的Mode 2 Form 1了。

 

要使用这个软件,首先要给出文件在光盘中的地址。有两种方法可以使用,一个是从root directory record开始,遍历所有文件,然后找到extent字段,把这个字段乘上0x930(2352),再加上0x18Header部分),才是这个文件真正开始的地方。另一种方法也类似,就是遍历path table,也可以找到所有的文件。

 

程序pscd的算法就是遍历path table,里面略微麻烦一些的地方是path table可能跨多个扇区,需要进行一些操作。所以编写这个程序要对扇区格式,Primary Volume Descriptorpath table有一些了解。

 

Agemo专门写过一篇文章PS光盘格式简介,也可供参考。

 

2.         debuggerfilelist

Agemo_debuggercdrom read monitor功能,显示如下:

cdrom $80045800 <- 64:53:06($473f7), 2048 bytes

其实这个显示的可读性还是很差,我略微修改了一下,程序可以读取filelist目录下的文件列表,在显示的时候,可以直接显示文件名。文件列表格式如下:

// 文件名,起始扇区,大小(扇区数),大小(字节数)

INIT.BS,00ce,0010,7e64

暂时只有前3个数据有效,这个文件的构造方法和上面几乎一致,唯一的区别就是要通过size来计算占用的扇区数。另外有些游戏将很多文件都打包在一个大文件中,如果找到入口表就能写代码生成各个子文件的地址,方便调试。

 

历史:

第一版:2010年9月25日9:29:38

原创粉丝点击