Scph-1000 Bios

0 views
Skip to first unread message

Flocka Bilodeau

unread,
Aug 5, 2024, 7:33:43 AM8/5/24
to sleeperocstan
Themain purpose of the BIOS is to boot games from CDROM, unfortunately, beforedoing that, it displays the Sony intro. It's also doing some copy protectionand region checks, and refuses to boot unlicensed games, or illegal copies, orgames for other regions.

The BIOS contains a number of more or less useful, and probably more or lessinefficient functions that can be used by software.

No idea if it's easy to take full control of the CPU, ie. to do all hardwareaccess and interrupt handling by software, without using the BIOS at all?

Eventually the BIOS functions for accessing the CDROM drive are important, notsure how complicated/compatible it'd be to access the CDROM drive directly viaI/O ports... among others, there might be different drives used in differentversions of the Playstation, which aren't fully compatible with each other?




The BIOS occupies 512Kbyte ROM with 8bit address bus (so the BIOS ROM is ratherslow, for faster execution, portions of it are relocated to the first 64K ofRAM). For some very strange reason, the original PSX BIOS executes all ROMfunctions in uncached ROM, which is incredible slow (nocash BIOS uses cachedROM, which does work without problems).

The first 64Kbyte of the 2Mbyte Main RAM are reserved for the BIOS (containingexception handlers, jump tables, other data, and relocated code). That reservedregion does unfortunately include the "valuable" first 32Kbytes (valuablebecause that memory could be accessed directly via [R0+immediate], withoutneeding to use R1..R31 as base register).




The first some bytes of memory address 00000000h aren't actually used by theKernel, except for storing some garbage at that locations. However, thisgarbage is actually important for bugged games like R-Types and Fade to Black(ie. games that do read from address 00000000h due to using uninitializedpointers).

Initially, the garbage area is containing a copy of the 16-byte exceptionhandler at address 80h, but the first 4-bytes are typically smashed (set to00000003h from some useless dummy writes in some useless CDROM delays). Ie. the16-bytes should have these values:

[00000000h]=3C1A0000h ;


seektype 0 = from start of file (with positive offset) 1 = from current file pointer (with positive/negative offset) 2 = Bugs. Should be from end of file.Moves the file pointer the number of bytes in A1, relative to the locationspecified by A2. Movement from the eof is incorrect. Also, movement beyond theend of the file is not checked.




Changes the current directory on the specified device, which should be "cdrom:"(memory cards don't support directories). The PSX supports only a currentdirectory, but NOT a current device (ie. after cd, the directory name may beommited from filenames, but the device name must be still included in allfilenames).

in: A0 Pointer to new directory path (eg. "cdrom:\path")Returns 1=okay, or 0=failed.

The function doesn't verify if the directory exists. Caution: For cdrom, thefunction does always load the path table from the disk (even if it was alreadystored in RAM, so cd is causing useless SLOW read/seek delays).




Returns r2=direntry (or r2=0 if no matching files).

Searches for the first file to match the specified filename; the filename maycontain "?" and "*" wildcards. "*" means to ignore ALL following characters;accordingly one cannot specify any further characters after the "*" (eg."DATA*" would work, but "*.DAT" won't work). "?" is meant to ignore a singlecharacter cell. Note: The "?" wildcards (but not "*") can be used also in allother file functions; causing the function to use the first matching name (eg.erase "????" would erase the first matching file, not all matching files).

Start the name with the device you want to address. (ie. pcdrv:) Differentdrives can be accessed as normally by their drive names (a:, c:, huh?) if pathis omitted after the device, the current directory will be used.

A direntry structure looks like this:

00h 14h Filename, terminated with 00h 14h 4 File attribute (always 0 for cdrom) (50h=norm or A0h=del for card) 18h 4 File size 1Ch 4 Pointer to next direntry? (not used?) 20h 4 First Sector Number 24h 4 Reserved (not used)BUG: If "?" matches the ending 00h byte of a name, then any further charactersin the search expression are ignored (eg. "FILE?.DAT" would match to"FILE2.DAT", but accidently also to "FILE").

BUG: For CDROM, the BIOS includes some code that is intended to realize diskchanges during firstfile2/nextfile operations, however, that code is so buggedthat it does rather ensure that the BIOS does NOT realize new disks beinginserted during firstfile2/nextfile.

BUG: firstfile2/nextfile is internally using a FCB. On the first call tofirstfile2, the BIOS is searching a free FCB, and does apply that as "searchfcb", but it doesn't mark that FCB as allocated, so other file functions mayaccidently use the same FCB. Moreover, the BIOS does memorize that "searchfcb", and, even when starting a new search via another call to firstfile2, itkeeps using that FCB for search (without checking if the FCB is still free). Apossible workaround is not to have any files opened during firstfile2/nextfileoperations.




Basically same as B(54h), but allowing to specify a file handle for which errorinformation is to be received; accordingly it doesn't work for functions thatdo use 'hidden' internal file handles (eg. erase, or unsuccessfulopen). Returns FCB[18h], or FFFFFFFFh if the handle is invalid/unused.




Whatever. Checks the devicename, and if it's accepted, calls a device specificfunction. For the existing devices (cdrom,bu,tty) that specific function simplyreturns without doing anything. Maybe other devices (like printers or modems)would do something more interesting.




Same as LoadTest (see there for details), but additionally loads the bodyof the executable (using the size and destination address in the file header),and does call FlushCache. The exe can be then started via Exec (this isn'tdone automatically by LoadTest). Unlike "LoadExec", the"LoadTest/Exec" combination allows to return the new exe file to returnto the old exe file (instead of restarting the boot executable).

BUG: Uses the unstable FlushCache function (see there for details).




This is a rather bizarre function. In short, it does load and execute thespecified file, and thereafter, it (tries to) reload and restart to bootexecutable.

Part1: Takes a copy of the filename, with some adjustments: Everything up tothe first ":" or 00h byte is copied as is (ie. the device name, if it doesexist, or otherwise the whole path\filename.ext;ver), the remaining charactersare copied and converted to uppercase (ie. the path\filename.ext;ver part, ornone if the device name didn't exist), finally, checks if a ";" exists (ie. theversion suffix), if there's none, then it appends ";1" as default version.CAUTION: The BIOS allocates ONLY 28 bytes on stack for the copy of thefilename, that region is followed by 4 unused bytes, so the maximum lengthwould be 32 bytes (31 characters plus EOL) (eg."device:\pathname\filename.ext;1",00h).

Part2: Enables IRQs via ExitCriticalSection, memorizes the stack base/offsetvalues from the previously loaded executable (which should have been the bootexecutable, unless LoadExec should have been used in nested fashion),does then use LoadTest to load the desired file, replaces the stackbase/offset values in its headerbuf by the LoadExec parameter values, anddoes then execute it via Exec(headerbuf,1,0).

Part3: If the exefile returns, or if it couldn't be loaded, then the boot fileis (unsuccessfully) attempted to be reloaded: Enables IRQs viaExitCriticalSection, loads the boot file via LoadTest, replaces the stackbase/offset values in its headerbuf by the values memorized in Part2 (which\ be the boot executable's values from SYSTEM.CNF, unless thenesting stuff occurred), and does then execute the boot file viaExec(headerbuf,1,0).

Part4: If the boot file returns, or if it couldn't be loaded, then the functionlooks up in a "JMP $" endless loop (normally, returning from the boot execauses SystemError("B",38Ch), however, after usingLoadExec, this functionality is replaced by the "JMP $" lockup.

BUG: Uses the unstable FlushCache function (see there for details).

BUG: Part3 accidently treats the first 4 characters of the exename as memoryaddress (causing an invalid memory address exception on address 6F726463h, for"cdrom:filename.exe").




Changes the number of EvCBs and TCBs, and the stacktop. These values are usuallyinitialized from the settings in the SYSTEM.CNF file, so using this functionusually shouldn't ever be required.

The function deallocates all old ExCBs, EvCBs, TCBs (so all Exception handlers,Events, and Threads (except the current one) are lost, and all other memorythat may have been allocated via alloc_kernel_memory(size) is deallocated, too.It does then allocate the new control blocks, and enqueue the default handlers.Despite of the changed stacktop, the current stack pointer is kept intact, andthe function returns to the caller.




Flushes the Code Cache, so opcodes are ensured to be loaded from RAM. This isrequired when loading program code via DMA (ie. from CDROM) (the cachecontroller apparently doesn't realize changes to RAM that are caused by DMA).The LoadTest and LoadExec functions are automatically callingFlushCache (so FlushCache is required only when loading program code via"read" or via "CdReadSector").

FlushCache may be also required when relocating or modifying program code bysoftware (the cache controller doesn't seem to realize modifications to memorymirrors, eg. patching the exception handler at 80000080h seems to be workwithout FlushCache, but patching the same bytes at 00000080h doesn't).

Note: The PSX doesn't have a Data Cache (or actually, it has, but it's misusedas Fast RAM, mapped to a fixed memory region, and which isn't accessable byDMA), so FlushCache isn't required for regions that contain data.

BUG: The FlushCache function contains a handful of opcodes that do use the k0register without having IRQs disabled at that time, if an IRQ occurs duringthose opcodes, then the k0 value gets destroyed by the exception handler,causing FlushCache to get trapped in an endless loop.

One workaround would be to disable all IRQs before calling FlushCache, however,the BIOS does internally call the function without IRQs disabled, that appliesto:

load_file A(42h) load_exec A(51h) add_device B(47h) (and all "add_xxx_device" functions) init_card B(4Ah) and by intro/boot codefor load_file/load_exec, IRQ2 (cdrom) and IRQ3 (dma) need to be enabled, so the"disable all IRQs" workaround cannot be used for that functions, however, onecan/should disable as many IRQs as possible, ie. everything except IRQ2/IRQ3,and all DMA interrupts except DMA3 (cdrom).



3a8082e126
Reply all
Reply to author
Forward
0 new messages