|
Post by elmer on Jan 20, 2022 19:26:44 GMT
Since both systems predate much of the later standards for CD-ROM implementations, it can be tough to find out what SCSI commands they support, and diving into the Mednafen source code or a disassembly of the System Card seems to be the only way to really understand what is going on. Here are a couple of old documents that can help to provide some context for similar SCSI CD-ROM drives from the time ... NEC CDR75 SCSI Command Set (198?)Pioneer CD-ROM SCSI-2 Command Set (1997)
|
|
|
Post by gameblabla on Jan 21, 2022 17:08:24 GMT
Hey elmer ! We had a discussion about it when it came to CD-DA here : github.com/jbrandwood/liberis/pull/2#issuecomment-1017837800I looked at the Pioneer PDF and this is what it should look like according to them : scsicmd10[0] = 0xD8; scsicmd10[1] = 0; scsicmd10[2] = /* MSB */ scsicmd10[3] = 0; /* reserved */ scsicmd10[4] = /* Starting Logical Block address*/ scsicmd10[5] = 0; /* LSB */ scsicmd10[6] = 0; /* reserved */ scsicmd10[7] = 0; /* MSB */ scsicmd10[8] = /* Transfer length */ scsicmd10[9] = 0; /* lsb */ scsicmd10[10] = /* subcode */ scsicmd10[11] = 0; /* reserved */
However, the LSB & MSB is a bit over my head (this reminds me of when i tried to improve the cdrom emulation in PCSX-Rearmed, it is a big mess lol). Even if i could get this to work somehow, would i even tell it to infinitely loop a track ? I suppose i could use my former code and then do a bunch of printfs in Mednafen but not even sure that would work to be honest. For the other peeps, this is how using 0x48 mode looked like (according to elmer, the mode parameter is not supported on PC-FX/PCE) : void cd_playtrk(u8 start, u8 end, u8 mode) { u8 scsicmd10[10]; scsicmd10[0] = 0x48; scsicmd10[1] = 0; scsicmd10[2] = 0; /* reserved */ scsicmd10[3] = 0; /* reserved */ scsicmd10[4] = start; scsicmd10[5] = 1; scsicmd10[6] = 0; /* reserved */ scsicmd10[7] = end; scsicmd10[8] = 1; scsicmd10[9] = mode; eris_low_scsi_command(scsicmd10,10); }
0x48 takes a track number but 0xD8 doesn't... or maybe it does and it's 0xD9 that doesn't. IDK In fact, i'm not even sure the difference between 0xD8 and 0xD9.
EDIT: Actually there's a difference and it seems that 0xD9 might be easier to setup. However when i did try it, still no dice. I was setting the M to 2 and the rest to 0. This makes me wonder how HuC does it ? Took a look at it and i was not able to figure it out, it's all assembly.
|
|
|
Post by elmer on Jan 21, 2022 18:44:51 GMT
Hi! As mentioned in my comments to your pull-request ... what you need to look at are the vendor-specific SCSI commands ... which means that those commands are different between different vendors (i.e. manufacturers), so looking at Pioneer's document and trying to apply Pioneer's vendor-specific SCSI commands to NEC's CD-ROM drive on the PC-FX isn't going to get you very far. You are a C programmer ... so I suggest that you take a look at mednafen's C source code to see how mednafen processes the 0xD8 and 0xD9 SCSI commands on the PC-FX, and then take a look at NEC's CDR75 document for hints on things that mednafen's source leaves unclear (while understanding that it is a different CD-ROM drive to the one in the PC-FX). That should give you some clues of what the 0xD8 (Audio Track Search) and 0xD9 (Play) SCSI commands are *supposed* to do ... then, in exactly the same way that I would have to do, the only way to actually be *sure* that things work in the way that you have figured-out, is to write some test code and experiment to see if you can get it working. Good hunting!
|
|
|
Post by dshadoff on Jan 21, 2022 19:56:27 GMT
If you have a MiSTer, you can just watch the log on the serial port too. I'll take a look at some point over the weekend, but the 0xd8 / 0xd9 generally appear as a pair (d8 has start info, d9 has end), and there is a pause and a status also inthe 0xd(x) range. 0x06 seems to be data read...
|
|
|
Post by elmer on Jan 21, 2022 20:07:11 GMT
If you have a MiSTer, you can just watch the log on the serial port too. Does MiSTer do PC-FX now? If so, cool! From looking at mednafen, it suggests that 0xD8 and 0xD9 are *slightly* different between the PCE and PC-FX. We've either got to trust mednafen on that, or write some tests and run them on real PC-FX hardware.
|
|
|
Post by dshadoff on Jan 21, 2022 21:13:08 GMT
Ah, sorry, I thought the thread was about both units. No PC-FX yet.
|
|
|
Post by gameblabla on Jan 21, 2022 23:38:38 GMT
So i figured it out thanks to mednafen by running a game like Team innocent and watching the calls it makes to 0xD8/0xD8 void cd_playtrk(u8 start, u8 end, u8 mode) {
u8 scsicmd10[10]; memset(scsicmd10, 0, sizeof(scsicmd10)); scsicmd10[0] = 0xD8; scsicmd10[1] = 0x01; /* 0 : Silent, 1: Loop, 2: Interrupt, 3: Normal s*/ scsicmd10[2] = start; scsicmd10[9] = 0x80; eris_low_scsi_command(scsicmd10,10); memset(scsicmd10, 0, sizeof(scsicmd10)); scsicmd10[0] = 0xD9; scsicmd10[1] = 0x4; scsicmd10[2] = end; scsicmd10[9] = 0x80; eris_low_scsi_command(scsicmd10,10);
}
It expects two SCSI commands : One for the starting position, the other one for the end position. Unfortunately... liberis SCSI commands suffer from a nasty bug : issuing a second SCSI command will totally freeze the software unless you reset the whole SCSI subsystem.. which would also cancel the first command you issued ! Effectively, i was able to get looping working but because i can't set the end position, this means that it tries to play all tracks ahead.
That's balls.
Oldrover said this previously :
Not sure where to go from this... xox
|
|
|
Post by dshadoff on Jan 21, 2022 23:50:31 GMT
So, if I understand correctly, you are trying to write code running on PC-FX which plays audio with repeat, by issuing the low-level SCSI commands.
Don't the official games just call BIOS functions to do this ? I would expect this to be something which would be more accessible (via API) - and possibly understandable via disassembly...
|
|
|
Post by elmer on Jan 22, 2022 0:13:22 GMT
Don't the official games just call BIOS functions to do this ? I would expect this to be something which would be more accessible (via API) - and possibly understandable via disassembly... Nope, the 5th generation consoles were the first generation designed to be programmed in C, specifically avoiding direct-hardware-access as much as possible, and using manufacturer-supplied libraries instead, which would theoretically allow the manufacturers to make hardware changes and revisions without breaking existing software. It also allowed them to release bug-fixed libraries whenever they found a problem, and not be limited to whatever bugs were in the original shipped-firmware. Heck, Sony wouldn't even *let* you access the hardware directly for many years (ever?) and would fail a game if it tried; and Sega were notorious for shipping monsterously-buggy libraries that would need many updates while any early game was in development. So ... while the PC-FX may not have been as strict (I don't know), all the main access functions (except for the Backup RAM) are based in C libraries, and not in firmware. Since liberis avoids using those libraries (for copyright), it tries to recreate the low level functionality. It just isn't either full-featured or fully-debugged since Alex (trap15) lost interest part way through the Sisyphean task of trying to do all of the work by himself. I burned through most of my personal enthusiasm spending months getting the compiler working, and still haven't had the time or passion to go back to working on fixing the things that are broken in liberis.
|
|
|
Post by elmer on Jan 22, 2022 0:41:54 GMT
It expects two SCSI commands : One for the starting position, the other one for the end position. That matches what I saw from taking a quick look at mednafen's source, although I *think* that you may still be wrong about some of the bits in the commands (for instance, "loop" seems to be part of 0xD9 and not 0xD8). ...and if I sent a REQUEST_SENSE before I send the audio play command, it *also* jams up the system. What. The. Fuck. Welcome to low-level library/firmware/hardware debugging ... darned frustrating, isn't it! Not sure where to go from this... xox I wish that I had an easy answer for you, but I don't. It needs someone with low-level SCSI knowledge to take a look at liberis's code and figure out what Alex got wrong. I certainly didn't have that back in 2016 when I was last working on the PC-FX toolchain, but I *may* be a little better-off these days after spending so much time looking at the PCE's SCSI subsystem. Unfortunately, I'm also extremely busy on other things, and so I don't know when I'll have either the time, or the passion, to get back to fighting with the PC-FX hardware.
|
|
|
Post by dshadoff on Jan 22, 2022 1:26:49 GMT
Don't the official games just call BIOS functions to do this ? I would expect this to be something which would be more accessible (via API) - and possibly understandable via disassembly... Nope, the 5th generation consoles were the first generation designed to be programmed in C, specifically avoiding direct-hardware-access as much as possible, and using manufacturer-supplied libraries instead, which would theoretically allow the manufacturers to make hardware changes and revisions without breaking existing software. It also allowed them to release bug-fixed libraries whenever they found a problem, and not be limited to whatever bugs were in the original shipped-firmware. But... that doesn't really make sense. If the hardware can possibly change, you *really* don't want your hardware access (i.e. direct SCSI commands) to be in the pressed CD-ROM game. You want it to be in the BIOS on the actual device, so that it can translate to whatever the flavour-of-the-week hardware is. And in any case, the BIOS *does* implement these SCSI bits, even if they're not in an exposed API; the device is designed to play CDs and boot PC-FX discs after all.
|
|
|
Post by elmer on Jan 22, 2022 2:27:47 GMT
If the hardware can possibly change, you *really* don't want your hardware access (i.e. direct SCSI commands) to be in the pressed CD-ROM game. You want it to be in the BIOS on the actual device, so that it can translate to whatever the flavour-of-the-week hardware is. You've got the right idea, but at the wrong layer. Nope, it's not in the BIOS, it's in the C library ... but it isn't a low-level SCSI call, it's a high-level "Play Audio Track" with a "Do you want to loop?" parameter. Then the game doesn't care if you're using SCSI, IDE, Network, or whatever-the-manufacturer comes up with. The fact that liberis has implemented the low-level SCSI calls doesn't mean that that is how either NEC or Hudson wanted people to use the system ... and even if they did, despite not including *any* SCSI command documentation in the PC-FXGA SDK, then they would have been unique at the time because the concept is still valid. And in any case, the BIOS *does* implement these SCSI bits, even if they're not in an exposed API; the device is designed to play CDs and boot PC-FX discs after all. That isn't relevent, because those functions are internal to the firmware within a specific console, and thus tied to a particular revision of the hardware, and they are not publicly exported to external games that use libraries, although there may be *undocumented* firmware calls that were never meant for developer use, kinda like Microsoft hid a lot of "undocumented" call in Windows for many years.
|
|
|
Post by dshadoff on Jan 22, 2022 2:53:23 GMT
Hmm... not sure if I'm adequately making my point.
I agree that the game programmer should not be concerned with underlying implementation. But the library which is linked into the game, also shouldn't be concerned with specific implementation... it should be a translation layer from "high level for game programmer" to "lower-level hardware-independent layer"... with the hardware-dependent stuff being on the hardware itself.
...But if we are, for some reason, concerned with specific SCSI codes so that they can be inserted into the linked-library layer... then a perfectly-working example is in the BIOS, and it may be the most straightforward implementation due to its simple hardware accesses. (So disassembly might be relatively straightforward)
|
|
|
Post by gameblabla on Jan 22, 2022 5:03:16 GMT
So sadly my only recourse was to try to trim down liberis's scsi command call and hopefully find the culprit lol. I found the instruction that could cause the freeze on mednafen at least (not yet tested on real hardware, my PC-FX is currently stuck in Japan). So if you disable this instruction : bne 1b at line 360 (which is after cmp 4, r10 # command), then it will no longer freeze. it's in there : 1: jal _eris_low_scsi_get_phase cmp 4, r10 # command bne 1b
mov 3, r11 mov 2, r10 out.h r11, 0x600[r0] out.h r10, 0x604[r0][/div][div]
I wonder what this is supposed to do exactly ? Now i still couldn't get my end command (0xD9) to be detected by Mednafen but it wasn't working on its own anyway so perhaps i'm misunderstanding it.
EDIT: Lol... so now i'm not getting the freeze anymore but instead, it simply refuses to recognize/detect whenever i do anything with 0xD9...
I also looked into the status function and this is what i found so far : mov lp, r15 jal _eris_low_scsi_get_phase shl 2, r10 # Causes freeze movea lo(scsi_phase_status_tbl), r0, r12 movhi hi(scsi_phase_status_tbl), r12, r12 add r10, r12 ld.w 0[r12], r10 # Causes freeze cmp 0, r10 be 1f blt 2f So disabling shl 2, r10 or ld.w 0[r12], r10 does not freeze anymore but if done then it reports nothing, making it kind of useless. I've tried disabling the other stuff down the chain but it does not unfreeze it, only this part.
EDIT2:
Also, you were right about the looping part, it's only for 0xD9.
void cd_playtrk(u8 start, u8 end, u8 mode) { u8 scsicmd10[10]; memset(scsicmd10, 0, sizeof(scsicmd10)); scsicmd10[0] = 0xD8; scsicmd10[1] = 0x01; scsicmd10[2] = start; scsicmd10[9] = 0x80; // 0x80, 0x40 LBA, 0x00 MSB, Other : Illegal eris_low_scsi_command(scsicmd10,10); memset(scsicmd10, 0, sizeof(scsicmd10)); scsicmd10[0] = 0xD9; scsicmd10[1] = 0x4; // 0 : Silent, 4: Loop, Other: Normal scsicmd10[2] = end; scsicmd10[9] = 0x80; // 0x80, 0x40 LBA, 0x00 MSB, Other : Illegal eris_low_scsi_command(scsicmd10,10); }
For whatever reason, it still ignores any commands issued after the first one even after my fix.
|
|
|
Post by elmer on Jan 22, 2022 5:23:50 GMT
So disabling shl 2, r10 or ld.w 0[r12], r10 does not freeze anymore but if done then it reports nothing, making it kind of useless. Alright, thanks! You've narrowed the problem down to a very specific narrow point ... and that's small enough that I feel that I should take a look and see if it's a simple fix. But, just to warn you ... it probably isn't, and I'll give up (sorry, but there's far too much to do to get distracted right now).
|
|