Closed i30817 closed 6 years ago
How do you define and identify a "successful read"?
The system call open returns success/file descriptor (>0 if i recall my C-ishms). As long as that file descriptor is from the cd drive, not the memory card - which i suppose can be checked by decorating the arguments in addition to the return (unless there is a way to tell from the FD anyway).
This might even work but be too slow anyway because the game introduces delays/takes too long to spin up the disk/insists in changing the 'insert cd' message; or have false positives from games that use 'actual parsing' of the same named file, so it's not like it's something i think will work perfectly, but it should be worth experimenting.
Maybe it's even possible to trick the game with save/loadstates to fix any wasted time before trying each cd (save after the shortcut is pressed and after the medium is removed, but before a new medium is inserted, reload on failure, or something like that).
BTW,,, I think this approach might even work for some floppy or multi floppy emulators like the ones for the X68000. As long as the required file is not open for 'writing' i guess.
The one thing i don't know if it's possible is to get at the system call parameters and return in psx memory. It's part of the bios i suppose right?
The first of these: http://problemkaputt.de/psx-spx.htm#biosfilefunctions
It will probably be problematic to extend the idea to other platforms even if it works though, since it requires wrapping a bios function. I'd love it in amiga, pc-98 and x68k cores though, those are annoying. Wouldn't say no to dosbox either (if i used RA dosbox) but it's not so bad in DOS since most games have a full install hack.
I guess to be sure one would have to look at how games usually handle this and if a generic method can be devised. I'm not sure if having a successful FileOpen
is enough for most game, what if it then looks for a certain identifier within the game? What if it executes a program on the disc instead? What if it uses a raw sector read?
Hooking the PSX BIOS functions would be the easy part, you just have to check for jumps to fixed addresses in memory.
If the method fails nothing happens. I think it's worth trying.
And, what's the problem with it searching another file or executing a exec? Even if it does that, the beauty of this method is that it doesn't need to be the first thing that the game does, but that it happens. In this case, when it finds the executable and execs it, 'a' game file will eventually be opened and success can be called that way.
But your observation reminded me that SYSTEM.CNF;1 should be blacklisted from this process. It contains the path and name to the executable in most ps1 games (and ps2), so it being opened for reading on disc change is not indicative, and indeed may be used for 'manual ID parsing'.
There should be a timeout if this file is skipped on the blacklist too to make sure the running code isn't just parsing the exec name and doing nothing if it doesn't match.
I've got nothing on raw sectors. Hoping it's rare.
edit: just figured out the timeout should apply generally, because non-matching file-search (eg: from B(42h) - firstfile(filename,direntry)
and B(43h) - nextfile(direntry)
can also 'do nothing' if it doesn't match. Or you can wrap these ones too with the same 'failure/success' idea but i'm unsure if that would work well from these functions descriptions.
no$cash specs have this warning on them, so it may end up unnecessary?:
BUG: For CDROM, the BIOS includes some code that is intended to realize disk changes during firstfile/nextfile operations, however, that code is so bugged that it does rather ensure that the BIOS does NOT realize new disks being inserted during firstfile/nextfile.
I think you should formalize exactly the procedure you have in mind (and how you ended up with it). I know fairly well how the CD code works and I have some trouble understanding what you want to do exactly. Are you guessing how games are working or did you actually check to make sure that it's what's happening? It wouldn't surprise me if different games handled disc switching differently.
What I'd like to see is 1/ a factual technical explanation of how disc swaps works in your average PSX game 2/ how you propose to hook emulator code into that to automate it.
I realize that you've already done some of that but I have some trouble discriminating what's fact and what's guesswork. I can help with the low level stuff but I can't be bothered to reverse engineer a bunch of games to figure out how they implement disc swapping.
It's honestly all guess work. My intention is as was stated: ps1 disc change success needs to open a first file. This is obvious because regardless of the method the game used to change cds, the game needs to continue, and opening a file with success to access new data.
The main problem comes from some failure cases which may leave the process in a limbo or wrongly assume success:
The game opens a 'first' file, but it's a for parsing a ID that is different on each disk (many pc games did this). Success opening here is not indicative the game recognized a new file.
The game doesn't open a file but uses firstfile
and friends to find a file, but fails, so it won't ever get to use FileOpen
The second has a workaround by using a timeout. The first not so much. I'd honestly suggest just to try it to see how common it is, and blacklist opening SYSTEM.CNF counting towards success because it seems the 'obvious' way to implement this if you're lazy. Even if it fails like this the system will just assume that the change is complete and stop trying, ie: it's a false positive, the user just needs to change manually and there is no lockup or anything like that.
It's also possible i suppose that a game opens a executable to do the work of checking instead of using code in memory. I'd suggest blacklisting open files opened with +x too. I dunno how the playstation executes execs, but my guess is that bios open is involved? edit: this is unnecessary, this uses LoadExeFile
and DoExecute
, not FileOpen
.
Maybe there is a even better method of recognizing that the game is doing 'useful work' instead of that doesn't have so many gotchas.
Maybe it's possible to recognize the moment a new executable 'takes over'? Probably not since i'd make them all the same, except for name (which is a sony requirement). edit: Confirmed with FF7.
Ok, you know what? This idea actually has further holes in it because even the failure case may open files (think of the loading screens in FFVII disc changes, only if the game assumed the new disc was a game disc and tried to open some file for a new one). And in the end it's not very much better than a manual disc change cycle shortcut, because games often require 'input' to detect the closed tray. I'll close this as a idea, sadly (because the situation is even worse than the ps1 in many other cores like x68000, where a way to detect 'which' diskettes the game wants in what drive would be very useful).
I think making disc switching simpler is a noble cause, but I wonder if the first step wouldn't be to make the UI for disc switching a little simpler and more accessible. I haven't played a lot with disc-swapping so far but as far as I've heard it's a bit tricky to make it work in RA.
Well, it's not terrible if you have:
if cd or disc
on the script). It's simple enough to find files of certain extensions in a dir, sorting them, and grouping filenames with maximally common substrings starting from index 0 and stuffing those files in a m3uProblems occur when:
I had already suggested - a year ago - creating the groups of cds without forcing the user to create m3u files. It's actually rather simple to create such a thing (as 1. shows) and it could possibly be in-built in the filechooser and scanner/playlists as a 'optional runtime preprocessing step'. More complicated for the scanner though. I suppose it could be done by indexing a 'gamedir/filenamesubstring.m3u' file for the playlist and just build it at runtime as a 'artificial' in-memory file if it doesn't actually exist.
cmd files serve a similar purpose to m3u files on the x68000 core but just for setting up the 'initial' two diskettes the game needs... initial because the game almost certainly will ask for a changed disk if it has more than 2 eventually, and the cmd file doesn't support that.
A extension where the m3u supports '2' files on the same line for these, to work as a 'group of mounted' disks for the x68000 would probably solve this corner case, but you really can't tell ahead of time what combinations of disks a game actually requires.
@simias , i created https://github.com/libretro/RetroArch/issues/6324 for my 'VFS m3u' idea if you're interested on it or working on it.
I've requested a closed issue to 'automatic' disk change before, that wouldn't work because it expected a push api where the volume identifier of the psx game was a argument for a library function to check it (this function apparently doesn't exist).
I had another idea now. How about if a user shortcut was created that when pressed:
It's only a minor ergonomic gain but do you think it could work and it's possible to hook into the 'read' function of the ps1 like this?