Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLE BIOS improvements (based on nocash doc, pcsx4all, upstream pcsxr etc...) #137

Merged
merged 51 commits into from Jul 24, 2019

Conversation

@gameblabla
Copy link
Contributor

commented Jul 18, 2019

This is a bunch of patches to improve the HLE Bios in PCSX rearmed.
This should hopefully address some of the broken games listed in #6.

Some of the patches came from @dmitrysmagin & @senquack as part of PCSX4ALL.
Many thanks to them !
Some patches also came from upstream (notably some of the memory card changes) that were never merged.
As for mine, i made sure to test them against games and make sure it conforms to Nocash's PSX findings on the BIOS calls.

What games are fixed ?

Digimon World, Medievil 2
These games require a proper implementation of EnterCritical.
Setting 1 to v0 could fix these games but could also break other games assuming v0 is equal to 0 sometimes. This properly implements EnterCritical according to nocash documentation.

Once those fixes are merged, Digimon World could sometimes have broken controls, which is addressed by the checks in PAD_init.
The game would also have trouble saving, which is fixed by the memory card upstream fixes.

LEGO Racers, Parasite Eve 2
LEGO Racers is particular because it would fail when trying to create a save. The fix suggested by a forum user would fix LEGO racers but would then break games like Parasite Eve 2.
It's only after combining some other patches and some testing against Parasite Eve 2 did this game get properly fixed save wise.

(Note that Parasite Eve 2 is very finicky and you may have to turn on and off the parasite eve 2 hack on the fly for it to make it work.)

Crash Team Racing, R-types, Fade to black
These games would not get past the first logo screen.
After reading nocash's documentation, i found a small section called "Garbage Area at Address 00000000h" where it would describe some games like R-types reading from address 0 and would subsequently crash if the first bytes in memory are set to 0.

Fade to Black is a bit more extreme in that it can crash upon memory card access if byte 5 is not set properly. (though saving still doesn't work properly)
Crash Team Racing actually is a bit different, because the HLE bios will set the 3rd and 4th byte to a non zero value (reasons unknown...) and would crash as a result. I have commented that out because no explanation is given and it breaks more stuff than it fixes, if anything.

Other games
Other games being fixed (either booting or saves) include Yu-gi-oh Forbidden Memories, Metal Slug X (should be fixed), GTA 2, Burning Road (addressed by the malloc & free fixes by dmitrysmagin), Ridge Racer Revolution controls being fixed and probably more...

(Still) Broken games

  • Digimon Rumble Arena (refuses to boot, switches threads then is seemingly stuck.)
  • Nuclear Strike, Ape Escape (Crashes upon memory card access gameblabla/pcsx4all#8)
  • Roswell Conspiracies - Aliens, Myths & Legends (Black screen with GUI upon starting new game, no cutscene, unplayable.)
  • Final Fantasy 8 (memcards broken, freezes before trying to enter a battle)
  • Fade to Black (unable to load a save, seems to suffer from the same issue as FF8)
  • Sound issues in games like Digimon World
  • Jumping Flash (been told this game would crash on HLE but i need to try it myself)
  • Formula One 2001. (Crashes during loading screen. Works on my PCSX4ALL fork over HLE. Reason unknown)

I haven't noticed any regressions but it would be nice if someone could look over the patches.
This has been somewhat tested over a bunch of games so i believe i haven't introduced any regressions (in fact it's more likely to fix than to break games).

gameblabla added some commits Jul 17, 2019

psxbios: Add checks to strcat
Nocash documentation says that function fails if src or dst is 0.
If so, then it must return 0.

This fix is required for fixing crash on bootup in Digimon World.
psxbios: Add checks to PAD_init
Nocash documentation says that function fails if type is not 0x20000000
or 0x20000001. In case of failure, it should return 0.
If not, then it should return 2.

This fixes input in Digimon World.
psxbios: Merging fixes from upstream.
DeliverEvent functions are executed right after writing/reading instead of after setting v0.
This fixes saving in games like LEGO Racers.
psxbios: Merging improved card_info function from upstream
It should be closer to the real thing, and this commit and the previous one
definitely fixes the save issues in Digimon World.
psxbios: Add checks for card_write, card_read
This also implements a bug which allows writes to 0x400
(Is supposed to only accept sector number between 0..3FFh).
Function should return 0 if sector is invalid.
psxbios: Better EnterCiritcal implementation
Nocash documentation says it should return 0 if one or
none of the bits were changed and return 1 of both bits were set.

This fixes Medievil 2, which would freeze upon starting up a game
and this properly fixes Digimon World crashing (with fixed strcat implementation).
It also possibly fix other games.
psxbios: Return 0x1f801814 for gpu_abort_dma
Nocash documentation says that it returns the I/O address.
I doubt any games use it so but it doesn't hurt to have it.
psxbios: Adds putc and getc implementation
getc will need to be fixed later but this should do as it is.
No issues with putc. Both are similar to psxBios_read and psxBios_write,
except size is 1.
psxbios: Add todigit implementation
Based on CTRX's code : https://github.com/machinamentum/CTRX/blob/master/bios/source/libc.c#L152

I'm not aware of any games using it but it doesn't hurt to have it
and it should work fine.
psxbios : Add checks for strncat
Returns 0 if src or dst is 0x00.
psxbios: Better realloc implementation
This should be closer to the real behaviour as described by nocash.
It doesn't do any bcopy though but it shouldn't be too much different
other than that.
psxbios: Improve WaitEvent behaviour according to documentation
Nocash says it should return 0 if Event is unused, which it already does so it might be safe to remove the warning about it.
(see why below)

Then, it says that it should return 1 if event is ready (EvStALREADY). When that happens, it should also set it to ready (EvStACTIVE),
unless event mode is EvMdINTR. (aka Callback Events)
If it is a callback event, then documentation says it should be stuck in a loop forever.

It also says that it can sometime return 0 (a BUG according to nocash),
especially if it switched from EvStALREADY to EvStACTIVE.

Said return value was previously set to 1, for some reasons. Now that we are covering all the corner cases,
we should be returning 0 instead by default to cover the BUG.

This should cover how most games expects it to behave now and should make it more robust.
psxbios: Fix out-of-bounds issue.
Make sure to return 0xff is no TCBs are available.
Thanks senquack for the proper fix.
psxbios: Should fix input issues in some games.
Someone reported that this fixed Negcon controls in Ridge Racer Revolution
and Grand Tour Racing.
I doubt this will suffer from regressions ?
psxbios: Merge upstream fix for Deliverevent in firstfile
Looks like it is only executed for memory cards, that makes sense i guess.
psxbios : Add checks to index and rindex calls
Return 0 for index/rindex if src is 0x00.
psxbios: Add checks for bcopy
Nocash documentation say that function refuses to copy any data
if dst is NULL or len greater than 0x7FFFFFFF.
(In any cases, return value is always dst)
psxbios: Add checks for bzero.
Only return 0 if size is invalid. (0 or 0x7FFFFFFF), return dst if not.
psxbios: Add checks to memcpy.
Always returns dst
psxbios : Add checks to memset.
This now can be a tricky pony and an improper memset implementation means that
you can't play Tomb Raider 4 properly.
(Trying to put in the eye of horus will just result in Lara sidestepping)

This should hopefully be fixed (and follows nocash doc).
psxbios: Add checks for memmove.
Always returns dst per documentation.
psxbios : Several fixes to malloc.
- Don't allow malloc to init memory if heap is invalid
According to nocash documentation, malloc will not allocate if heap size
is too small or invalid.

- Also merge some fixes from PCSX4ALL fork by senquack in order to allow
Burning Road to run.
psxbios: Stub for get_error
According to a user on PCSX-Reloaded codeplex (now dead), this fixed loading/saving
in Final Fantasy Tactics.
psxbios: Add checks for strcmp & strncmp.
Yes, it's supposed to have a lot of checks like these.
Also merge some more fixes from PCSX4ALL. (upstream did not have
these as far as i know)
psxbios: Fixup free.
This is needed for Burning Road. Fix comes from PCSX4ALL by dmitryssmagin.
psxbios: Add checks for strcpy & strncpy.
This should be closer to documentation.
psxbios: Add checks for strlen.
Per what Nocash documentation says.
psxbios: Support other syscalls
Since they don't do anything however, let's just add a default and break;
instead. Interestingly, trying to implement SYS(04h+ can actually crash
the HLE bios. Nocash documentation said that it should crash it
but due to other reasons, it doesn't and returns to main program instead.

gameblabla added some commits Jul 18, 2019

psxbios: Callback Events should not set event status to busy in TestE…
…vent.

We are already doing that in WaitEvent. According to nocash documentation,
this also applies to TestEvent as well so let's implement it.
psxbios: Fixes save issues on Parasite Eve II, Parasite Eve I and others
Merging never-merged fix by Solus for Parasite Eve. I also fixed some GCC warnings
about dir->name going out of bounds too.
We also make sure to only add '/0' if string is not full and right after the last character in the dir array.

This fixes saving/loading in Parasite Eve II, Parasite Eve.
It also fixed regressions for the LEGO Racers where other games would break,
meaning this should be the proper fix for saves.

We're also using our own strlen implementation to avoid any issues or
relying on the libc's own strlen.

@gameblabla gameblabla changed the title BIOS HLE improvements (based on nocash doc, pcsx4all, upstream pcsxr etc...) HLE BIOS improvements (based on nocash doc, pcsx4all, upstream pcsxr etc...) Jul 18, 2019

@notaz
Copy link
Owner

left a comment

I've left some comments, you can adjust some things if you like.
If not I can merge this as-is as it's definitely and improvement.

} \
} \
char ffile[64], *pfile;
int nfile;

This comment has been minimized.

Copy link
@notaz

notaz Jul 20, 2019

Owner

These are already declared below, why add again?

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 20, 2019

Author Contributor

A mistake on my part :P. Nice catch

@@ -2146,7 +2146,13 @@ void psxBios__card_write() { // 0x4e
#ifdef PSXBIOS_LOG
PSXBIOS_LOG("psxBios_%s: %x,%x,%x\n", biosB0n[0x4e], a0, a1, a2);
#endif

/* Function also accepts sector 400h (a bug) */
if (!(a1 <= 0x400))

This comment has been minimized.

Copy link
@notaz

notaz Jul 20, 2019

Owner

Hmm this 0x400 will still allow to corrupt memory of the emulator. I wonder what the real thing does with that.

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 20, 2019

Author Contributor

"The sector number should be in range of 0..3FFh, for some strange reason, probably a BUG, the function also accepts sector 400h. The function returns 1=okay, or 0=failed (on invalid sector numbers)." This is for both card_write & card_read. Not sure why Sony did this but nocash said this is how they implemented it.

This comment has been minimized.

Copy link
@notaz

notaz Jul 22, 2019

Owner

Yeah I believe the return part might be like that, what I meant is that the emulator itself should maybe avoid doing memcpy for 0x400 case as it will be out of bounds. Although that can be ignored for now as there are plenty of other places where the game could crash (or maybe even exploit) the emulator if it wanted.

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 22, 2019

Author Contributor

Well decided to not allow 0x400 given that it could corrupt it... still left a note in case it does get addressed in the future.

pad_buf1 = NULL;
pad_buf2 = NULL;
}

This comment has been minimized.

Copy link
@notaz

notaz Jul 20, 2019

Owner

Doesn't seem to make any sense though...

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 20, 2019

Author Contributor

You're right, pad_stopped already takes care of this.

return;
}
while ((s32)a2-- > 0) {
n++;

This comment has been minimized.

Copy link
@notaz

notaz Jul 20, 2019

Owner

What is this 'n' for?

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 20, 2019

Author Contributor

Hmm i took it directly from pcsx4all (dmitrysmagin did some work on the HLE after all) and i'm not sure why he did this. In fact, nothing in the doc says that this should be done this way. (it's mostly straightforward). So i removed it since it's not being used anyway.

@@ -3271,6 +3275,7 @@ void psxBiosException() {
void psxBiosFreeze(int Mode) {
u32 base = 0x40000;

pad_stopped = 0;

This comment has been minimized.

Copy link
@notaz

notaz Jul 20, 2019

Owner

Saving or loading a savestate now makes the BIOS act as if psxBios_StartPAD() was called. Should at least only do it on state load and set it according to pad_buf1 being set to NULL perhaps.

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 20, 2019

Author Contributor

Would it be okay if i do bfreezel(&pad_stopped); instead ? Should i also do this for heap_size too ?

psxbios : Fix a few mistakes :
- Remove extra ffile, pfile.. as it is declared elsewhere.
- Remove extra condition as it's already being handled by pad_stopped.
- Remove n variable from function (pcsx4all did this) as it's useless
and documentation doesn't seem to specify it's needed.

@gameblabla gameblabla force-pushed the gameblabla:hle branch from 4edfc74 to 44e9fa8 Jul 20, 2019

gameblabla added some commits Jul 20, 2019

psxbios : Implement stub for wait_card.
Pretty much identical to get_card_status except it's supposed
to wait until a non-busy state occurs.
psxbios: Merge interrupt_r26 fix from PCSX4ALL.
Thanks DmitrySmagin for the fix.
psxbios: Make HLE bios start from block 1, not 2.
I already fixed this for bufile :
ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
instead of
ptr = Mcd##mcd##Data + 128 * nfile; \

But i forgot to also fix psxBios_firstfile accordingly.
So nfile would still start from block 2 and it would
cause all kinds of issues.

This was the original comment on pcsxr codeplex
as my patch was based on it :
"The HLE-Bios start to read memory card blocks at block 2. You need to change
ptr = Mcd##mcd##Data + 128 * nfile; \ to
ptr = Mcd##mcd##Data + 128 * (nfile + 1); \
for #define bufile(mcd) { \ and changing nfile = 1; to nfile = 0; for psxBios_firstfile() { // 42 Starts numbering slots in the right position."
@gameblabla

This comment has been minimized.

Copy link
Contributor Author

commented Jul 21, 2019

Alright, i'm glad you did not merge this asap because i forgot some patches and i found some issues with them too lol...
What i've changed since then ?

  • Fixed the issues you pointed out above. (Also save pad_stopped & heap_size variables since they are important)
  • Merged the interrupt_r26 fix from PCSX4ALL. Not sure what game relies on this but doesn't hurt to try it.
  • Fixed card_status as to make use of card_active_chan instead.
  • Fixed a mistake with firstfile when i merged my patches. Since HLE bios should start from block 1, i forgot to fix firstfile accordingly.
  • Implement the get_cd_status stub.
  • Fixed a mistake i made in card_info. (I did not properly merge my patch oops) Fixes Looney Tunes Sheep Raiders.
  • Some games like R-types, Crash Team Racing read from address 0. (More details above) Fixed that.

Cheers, let me know if you spot more issues.

gameblabla added some commits Jul 21, 2019

psxbios: Some games read from address 0, fix that.
See Garbage Area at Address 00000000h in Nocash PSX Specifications for more inf>

R-types will refuse to boot if psxM[0] is zero.
Fade to Black can crash upon memory card access if psxM[5] is set to the wrong >
Crash Team Racing will refuse to boot if psxM[2] and psxM[3] are not zero.
(Previously, that region of memory would be overwritten above. No explanation why.)

It's set as such according to nocash :
[00000000h]=3C1A0000h  ;<-- but overwritten by 00000003h after soon
[00000004h]=275A0C80h  ;<-- or 275A0C50h (in older BIOS)
[00000008h]=03400008h
[0000000Ch]=00000000h

Note that setting 00000000h to 00000003h doesn't work for R-types.
psxbios: Return value is always 1 for CloseTh and ChangeTh.
According to nocash PSX doc, ChangeThread and CloseThread should
always return 1. Fix it accordingly.
psxbios: Fixup mistake in card_info function.
This fixes Looney Tunes Sheep Raiders.
psxM[4] = SWAPu32(0x27);
psxM[5] = SWAPu32(0x5A);
psxM[6] = SWAPu32(0x0C);
psxM[7] = SWAPu32(0x80);

This comment has been minimized.

Copy link
@notaz

notaz Jul 22, 2019

Owner

You are writing bytes here, not u32, SWAPu32 is wrong and unneeded.
(not that we support big endian, but still)...

This comment has been minimized.

Copy link
@gameblabla

gameblabla Jul 22, 2019

Author Contributor

Thanks, i've fixed this properly now.

gameblabla added some commits Jul 22, 2019

psxbios: Properly fix garbage area code.
This should work as intended now.
psxbios: Don't accept 400h as a valid sector.
Notaz said this could corrupt the emulator (even though
the console allowed this and it was a bug) so limit it to 0x3FF.

@notaz notaz merged commit 39ecfba into notaz:master Jul 24, 2019

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.