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 |
这个命令有很多完全不同的子命令,见注释末尾。 |
| 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相似。 |