CD-ROM

PSX使用一个特殊的倍速CD-ROM,最大速率是352K/秒,它使用下面这些寄存器来控制。
CDREG0 0x1F80_1800
CDREG1 0x1F80_1801
CDREG2 0x1F80_1802
CDREG3 0x1F80_1803

寄存器格式
CDREG0 0 发送命令
1 读取结果
IO状态
0位 0 REG1发送命令
    1 REG2读取结果
1位 0 数据传输结束
    1 数据传输忙/进行中
7位 1 命令处理中
CDREG1 命令
结果
CDREG2 发送参数
7=清空参数缓存
CDREG3 7=清空IRQ
高位:未知
地位:中断状态
模式设置
模式 功能
0 1
M_Speed 7 正常速度 倍速
M_Strsnd 6 ADPCM关 ADPCM开
M_Size 5 2048字节 2340字节
M_Size2 4 2328字节
M_SF 3 通道关 通道开
M_Report 2 报告关 报告开
M_AutoPause 1 自动暂停关 自动暂停开
M_CDDA 0 CD-DA关 CD-DA开

可以通过设置模式命令来设置模式。下面是从CD命令接收到的状态位:

状态位
Play 位7 播放CD-DA
Seek 位6 寻道
Read 位5 读取数据扇区
ShellOpen 位4 壳门打开一次
SeekError 位3 检测到寻道错误
Standby 位2 转轴马达旋转
Error 位1 检测到命令错误
中断
NoIntr 0x00 没有中断
DataReady 0x01 数据准备好
Acknowledge 0x02 命令完成
Complete 0x03 应答
DataEnd 0x04 检测到数据结束
DiskError 0x05 检测到错误

这些是CDREG3返回的低位。读取CDREG3前先向CDREG0写1。当一个命令完成,它返回3。在处理完IRQ后,向CDREG写1,然后向CDREG2和CDREG3些7作为应答。其他的中断可能在排队,所以应该检查CDREG3是0,或者有其他中断等待处理。

 

命令
名称 命令 需等待的 参数 返回
Sync 0x00   - 状态
Nop 0x01   - 状态
Setloc 0x02   min,sec,sector 状态
Play 0x03 B - 状态
Forward 0x04 B - 状态
Backward 0x05 B - 状态
ReadN 0x06 B - 状态
Standby 0x07 B - 状态
Stop 0x08 B - 状态
Pause 0x09 B - 状态
Init 0x0a   - 状态
Mute 0x0b   - 状态
Demute 0x0c   - 状态
Setfilter 0x0d   file,channel 状态
Setmode 0x0e   mode 状态
Getparam 0x0f   - 状态,模式,文件?,通道?,?,?
GetlocL 0x10   - 分,秒,扇区,模式,文件,通道
GetlocP 0x11   - 轨道,索引,分,秒,帧,amin, asec,aframe
GetTN 0x13   - 状态,第一,全部(BCD)
GetTD 0x14   rack(BCD) 状态,分,秒(BCD)
SeekL 0x15 B * 状态(命令目标用Setloc设置)
SeekP 0x16 B * 状态(命令目标用Setloc设置)
Test 0x19 B # 依赖于参数(事实是另一个命令集的入口)
ID 0x1A B - 成功,标志1,标志2,00 4个字母ID(SCEx)
ReadS 0x1B B - 状态
Reset 0x1C   - 状态
ReadTOC 0x1E B - 状态

B表示阻塞,这些命令立即返回一个结果表明命令开始了,但是必须等待IRQ去获取真正的结果。

命令描述
命令序号 命令名称 描述
0x00 Sync

其他命令都完成了此命令才成功,用来同步。

0x01 Nop

什么也不做,用来返回状态

0x02 Setloc

用这个命令和它的参数,设置参数列表带*号的命令的目标

0x03 Play

从最后寻道点播放音频扇区,几乎和CdlReadS一样,主要的不同是这个命令没有触发一个读取完成IRQ.CdlPlay可以用于数据扇区,但是,所有数据轨的扇区都被当作00,所以没有声音。当CdlPlay被读,音频数据出现在扇区缓存中,但是是不可信的。有些游戏的增强CD用这个来进行PSX版权保护

0x04 Forward

寻道下一轨

0x05 Backward

寻道当前轨开始,或者前一轨(如果处于当前轨刚开始的地方,和CD播放器的按钮一样)

0x06 ReadN

带重试读取。如果ModeRept打开了,每个扇区引发一个IRQ(类型1)。如果尝试读取非PSX CD或者音频CD(没有mod芯片),ReadN和ReadS会引发错误。

0x07 Standby

CD-ROM放弃所有读取和播放,但是继续旋转,CD-ROM不保持当前位置。

0x08 Stop

停止马达,标准的重启方法是0A,但是几乎所有命令都重启它。

0x09 Pause

想Standby,但是会保持当前位置。

0x0A Init

一次执行多种效果。 Setmode = 00,Standby,放弃所有命令

0x0B Mute

关闭到SPU的CDDA流。

0x0C Demute

打开到SPU的CDDA流。

0x0D Setfilter

自动ADPCM(CD-ROM XA)过滤器忽略副头部区域中不同通道和文件(参数)的扇区。这个是在单个XA中包含多首歌时的选歌方法。Setfilter不会影响实际的读取(所有扇区都被读取)。

0x0E Setmode

设置参数,例如读取模式,旋转速度等。

0x0F Getparam

返回状态,模式,文件,通道,?,?

0x10 GetlocL

返回最后读取扇区(头部)的前6(8?)个字节。用来知道扇区来源,但是通常在2340字节读取模式中没有意义。所有的结果都是BCD码(0x12表示12,而不是18),命令可以和读取或者播放同时执行(GetlocL立刻返回结果)。

0x11 GetlocP

返回最后读取扇区的12字节sub-Q数据的8个。和GetlocL的目的相同,但是更强大,返回BCD码。见注释。

0x13 GetTN

取TOC中第一个轨道号码和轨道总数。

0x14 GetTD

取指定轨道的开始(返回扇区?)

0x15 SeekL

在数据模式寻道到Setloc的位置,只能寻道数据扇区,精确到扇区。

0x16 SeekP

在音频模式寻道到Setloc的位置,可以寻道任何扇区,但只精确到秒。

0x19 Test

这个命令有很多完全不同的子命令,见注释末尾。

 

sub-Q格式
track 轨道号(0xAA是导出区)
index 索引号(CUE表的INDEX行)
min 轨道的分
sec 轨道的秒
frame 相对于ses的扇区号(0-74)
amin 整盘的分
asec 整盘的秒
aframe 相对于asec的扇区号(0-74)

 

测试子命令
1A ID 返回版权保护状态,对无效的数据CD返回StatError,对有效的PSX CD或者音频CD返回StatStandby。下面的位不太肯定,估计是第3字节0x80位表示CD拒绝,0x10位表示输入。0x080=拷贝,0x90=输入拒绝,0x10=输入接受(只用于Yaroze)。第5到第8字节是从CD得到的SCEx ASCII字符串。
1B ReadS 不重试读取。
1C Reset 和打开、关闭驱动器门一样
1E ReadTOC 不复位重读内容表。

要发送一个命令:先向CDREG0写0,然后向CDREG2顺序写全部的参数,再写0到CDREG0,最后写命令到CDREG1。

要等待一个命令完成:等待一个CDROM IRQ发生(中断寄存器第3位),引起CDROM IRQ的原因在CDREG3的低位中。通常成功完成是3,不能完成是5。如果不想用IRQ,也可以只检查CDREG3的低位变成不是0的数,但是要注意它不会因任何IRQ的建立而清空。

要获取结果:写1到CDREG0,然后读CDREG0,如果第5位被设置,读CDREG1的返回值,然后再读CDREG0,直到第5位变成0。

要清除IRQ:命令完成后,引起的IRQ要被清除,可以向CDREG0写1,然后向CDREG2和CDREG3写7来完产。写CDREG2应该是清除先前从一些缓存设置的参数。注意IRQ是队列的,清除了当前的,其它的可能直接跳出来...

要初始化CD:清除所有IRQ,CDREG0=0,CDREG3=0,Com_Delay=4901(0x1F801020),发送2个NOP,命令0x0A(无参数),消除静音。

要开始CD音频回放:CDREG0=2,CDREG2=0x80,CDREG3=0,CDREG0=3,CDREG1=0x80,CDREG2=0,CDREG3=0x20。也不要忘记初始化SPU,尤其是CDvol和CD使能)

注意不应该在CD寻道时发送命令(例如设置第6位返回状态),事实是只有在新命令之后才会更新状态。除了可以一直重复执行播放命令(0x03)和检查它的状态是否第6位变低(这时第7位变高)。如果你不这样,而在播放命令完成后直接尝试执行GetLoc命令,CD会停止(可能是CD不能在寻道时获取当前位置,所以逻辑器停止寻道和获取额外的定位,但是不再重启动...)

19个子命令。

为了某些原因,有一个计数器计算SCEx从CD-ROM控制器接收到的字符串长度。

下面这些命令的结果超过了8个字节:
0x04

读SCEx计数器(在第一个字节返回?)

0x05

复位SCEx计数器。同时设置1A的SCEx响应为 00 00 00 00,但是似乎不会迫使保护失效。

0x20

返回一个指明了CD-ROM固件意图使用区域的ASCII字符串("for Japan","for U/C")

0x22

返回一个PSX内部芯片号码

0x23

返回另一个芯片号码

0x24

返回另一个芯片号码,在某些PSX上和0x22相似。