How to properly send commands to the CD controller (low-level)

General Programming help in C, C++ or ASM, Compiling / Debugging, and R3000A Central Processing Unit (CPU) information
Post Reply
User avatar
LameGuy64
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 381
Joined: April 10th, 2013, 3:47 pm
I am a: Hobbyist Game Developer
Motto: Commercial or not, play it!
PlayStation Model: H2000/7000
Location: Philippines
Contact:

How to properly send commands to the CD controller (low-level)

Post by LameGuy64 » 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:

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
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.
Please don't forget to include my name if you share my work around. Credit where it is due.

Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.

DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.

User avatar
TriMesh
PSX Aptitude
PSX Aptitude
Posts: 193
Joined: December 20th, 2013, 2:25 pm
PlayStation Model: DTL-H1202
Location: Hong Kong

Re: How to properly send commands to the CD controller (low-level)

Post by TriMesh » April 1st, 2019, 2:05 pm

You always have to wait for the int before sending another command or it just gets dropped on the floor. If the last int hasn't been cleared, the HC05 just throws the command away.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest