How to properly send commands to the CD controller (low-level)
Posted: February 16th, 2019, 4:33 pm
I've been trying to figure this one out in awhile but was unable to figure it out. I'm working on some low level CD routines that allow me to send any command to the CD controller but it would often miss commands when I send a string of them to the controller judging by observing the CD-ROM command log in no$psx.
Here's the assembly code of my CD command function written in GNU assembler syntax:
It'll successfully send a command to the CD controller at first but any further commands won't register. I think I'm missing something that I haven't figured out yet.
Here's the assembly code of my CD command function written in GNU assembler syntax:
Code: Select all
.set IOBASE, 0x1f80
.set CD_REG0, 0x1800
.set CD_REG1, 0x1801
.set CD_REG2, 0x1802
.set CD_REG3, 0x1803
StupidCdControl:
# a0 - Command value
# a1 - Arguments
# a2 - Pointer to result buffer
lui $v1, IOBASE
li $v0, 1 # Clear parameter FIFO
sb $v0, CD_REG0($v1)
li $v0, 0x40
sb $v0, CD_REG3($v1)
.cmd_wait: # Wait for CD to become ready to take commands
lbu $v0, CD_REG0($a1)
nop
andi $v0, 0x80
bnez $v0, .cmd_wait
nop
la $v0, _cd_busy # Set internal values
sw $a0, 0($v0)
la $v0, _cd_result_dest
sw $a2, 0($v0)
beqz $a1, .no_params
nop
beq $a0, 0x02, .setLoc_param
nop
beq $a0, 0x03, .play_param
nop
beq $a0, 0x0e, .setMode_param
nop
beq $a0, 0x14, .getTD_param
nop
b .no_params
nop
.setLoc_param:
b .do_params
li $a3, 0x03
.play_param:
b .do_params
li $a3, 0x01
.setMode_param:
b .do_params
li $a3, 0x02
.getTD_param:
li $a3, 0x01
sb $0 , CD_REG0($v1)
.do_params:
lbu $v0, 0($a1)
addi $a3, -1
sb $v0, CD_REG1($v1)
bgtz $a3, .do_params
addiu $a1, 1
.no_params:
sb $0 , CD_REG0($v1)
sb $a0, CD_REG1($v1)
.param_wait:
lbu $v0, CD_REG0($v1)
nop
and $v0, 0x8
beqz $v0, .param_wait
nop
jr $ra
nop
# Related to IRQ handler but that isn't really relevant to this issue
.comm _cd_busy,4,4
.comm _cd_result_dest,4,4