flyinghead / flycast

Flycast is a multiplatform Sega Dreamcast, Naomi, Naomi 2 and Atomiswave emulator
GNU General Public License v2.0
1.29k stars 162 forks source link

Kaen Seibo - Disk swap not working with real BIOS #1046

Open kihato opened 1 year ago

kihato commented 1 year ago

Platform / OS / Hardware: Windows11 / i7-10700F / GTX 1660 SUPER

Github hash: 5f161df

SaveState It also blacks out after the Sega logo when booting with HLE BIOS.

In addition, disk swap does not work with both real BIOS and HLE BIOS in the following games.

Shenmue II (the game can progress) Dancing Blade - Katteni Momo Tenshi II (the game can't progress)

Related issues #189

flyinghead commented 1 year ago

The black screen after the Sega IP.BIN logo is due to missing Japanese characters in HLE BIOS on the master branch. JP characters for HLE BIOS are on the dev branch only.

kihato commented 1 year ago

Dancing Blade - Katteni Momo Tenshi II , Shenmue II, and First Kiss Story II were able to exchange disks with real BIOS. Unfortunately Kaen Seibo cannot exchange discs.

common.cpp (Line 116)

libCore_gdrom_disc_change();
sns_key = 0x2;
sns_asc = 0x04;
sns_ascq = 0x01;
_sleep(200);
return disc != NULL;

gdromv3.cpp (Line 822)

gd_spi_pio_end(resp,packet_cmd.data_8[4]);
if (sns_key == 0x2)
{
    SecNumber.Status = GD_BUSY;
    sns_key = 0x6;
    sns_asc = 0x28;
    sns_ascq = 0x00;
}
else if (sns_key == 0x6)
{
    SecNumber.Status = GD_PAUSE;
    sns_key = 0;
    sns_asc = 0;
    sns_ascq = 0;
}
GDStatus.CHECK = 0;

Here are the steps I tested.

  1. Select Disc 2 of any of the 3 games.
  2. Insert disk 1 on the exchange message screen.
  3. After booting, eject and go to the BIOS screen.
  4. Return to step 1.

Since it is the result of trial and error by an amateur, I think that it is wrong as an emulation. Is it worth using?

flyinghead commented 1 year ago

This is interesting. Note that the _sleep(200) likely has no effect since the emulator doesn't use real time. I bet it still works if you remove it. The correct way to introduce delays is to use the sh4 scheduler: either manually using the current cycle count (sh4_sched_now64()) or with a scheduler callback (sh4_sched_request())

Also note that there is at least one game that requires the disk swapping to work (D2 iirc but there may be others.) So it's important verify that no regression is introduced by these changes. Let me know if you know of other games in this situation.

kihato commented 5 months ago

After testing the following code, I found that it works for games that currently cannot do disk swaps. (real BIOS only. Stupid invaders are excluded because they cannot be tested. )

Memorize the mainframe count at the time of disk swap and execute gd_setdisc() after 10 frames have passed.

There is a glitch in "Alone in the Dark" where the frame count stops when "Now checking..." is displayed, so you have to resume after the flycast pause menu, but other games seem to work fine.

This code is incomplete, but I hope it will be helpful.

common.cpp

static bool loadDisk(const std::string& path)
{
...
        //libCore_gdrom_disc_change();
...
}

bool InitDrive(const std::string& path)
{
    bool rc = DiscSwap(path);
        gd_setdisc();
...
}

bool DiscSwap(const std::string& path)
{
    // These Additional Sense Codes mean "The lid was closed"
    //sns_asc = 0x28;
    //sns_ascq = 0x00;
    //sns_key = 0x6;
    sns_key = 0x2;
    sns_asc = 0x04;
    sns_ascq = 0x01;
    SecNumber.Status = GD_BUSY;
...
}

void DiscSwapFinish()
{
    gd_setdisc();
    sns_key = 0x6;
}

gui.h

struct DiscSwapFrame
{
    u32 count;
    bool swapped;
};

extern DiscSwapFrame SwapFrameCount;

gui.cpp


DiscSwapFrame SwapFrameCount;
...
if (gui_state == GuiState::SelectDisk)
{
                settings.content.path = game.path;
                try {
                    DiscSwap(game.path);
                    SwapFrameCount.count = MainFrameCount;
                    SwapFrameCount.swapped = true;
                    gui_setState(GuiState::Closed);
                                }
...
}

mainui.cpp

bool mainui_rend_frame()
{
    FC_PROFILE_SCOPE;

    os_DoEvents();
    UpdateInputState();
    if (MainFrameCount - SwapFrameCount.count >= 10 && SwapFrameCount.swapped)
    {
        DiscSwapFinish();
        SwapFrameCount.swapped = false;
    }
    if (gui_is_open() || gui_state == GuiState::VJoyEdit)
...
}
flyinghead commented 5 months ago

Thank you for this code. I'm working on an implementation based on it and it works fine with the following games (real BIOS):

Every time I try with Shenmue II however, it reboots to BIOS as soon as the disk is ejected. Shenmue I acts the same way and I believe this is what happens on real hardware too. (See https://github.com/flyinghead/flycast/issues/189#issuecomment-787041301) Can you confirm that Shenmue II disc switching does not exit to bios in your case?

I cannot test Alone in the Dark since it doesn't allow to start a game from disc 2. If you have a savestate available I'd be interested.

Finally, my changes break HLE disc switching (at least for Eternal Arcadia) so I need to fix this before I can push the changes.

kihato commented 5 months ago

Shenmue 1 returns to BIOS due to specifications, but Shenmue 2 does not return to BIOS as shown in the video. https://youtu.be/MXt7KR9Dfyg?list=PLoy7DNb4x38KNePo-huM37G5-IATL_GM_&t=2386

Actually run the above code. (Disc 2 -> Disc 1) (The PAL version is also successful.) In my testing, Dancing Blade 2 and Shenmue 2 work exactly the same and require the same code.

https://github.com/flyinghead/flycast/assets/14366233/4d43e844-4866-4c99-85c1-23eae6990bb6

Regarding Alone in the Dark: First, start from disk 1 and create a save file when the game starts. You will then be able to load from disk 2.

Alone

flyinghead commented 5 months ago

Thanks for the confirmation and the Alone in the Dark tip. Both Shenmue II and Alone in the Dark disk switching work with real BIOS. However they fail with HLE.

flyinghead commented 5 months ago

This should be fixed in the latest dev build. Disk swapping now works fine for the following games:

No regression for D2 and Alone in the Dark. Shenmue II disk swapping still not working with HLE BIOS. Disk insertion is now possible in the BIOS menu.

flyinghead commented 5 months ago

A last minute change broke a few things so best to wait until the next build.

flyinghead commented 5 months ago

It should now be fixed by https://github.com/flyinghead/flycast/commit/116dc0e1ed9313a4cba19d63cf68b4a12bcd5237

flyinghead commented 5 months ago

There is a regression with Alone in the Dark and Resident Evil Code Veronica. (I was testing Alone in the Dark with HLE BIOS instead of real)

flyinghead commented 5 months ago

The Alone in the Dark and RE Code Veronica regressions should be fixed

kihato commented 5 months ago

When booted with real BIOS, I've tested all gd-rom games with swappable disks and they all work fine. (Except for "Stupid Invaders".) However, the following games do not work with HLE BIOS.

Github hash: 4c7e57e

Stuck when replacing disk

flycast has stopped. Reboot to BIOS ("MyMerryMaybe" and "Suigetsu" have a problem where the title screen is not displayed, but when the BGM starts playing, press the start button and then the A button.) ("Golf Shiyouyo Course Data Syuu" can do disk swapping, but the message displayed on the screen is incorrect.)

About Golf Shiyouyo Course Data Syuu

In this game, after starting "Golf Shiyouyo Course Data Syuu", you can increase the number of selectable characters to 16 by replacing the disk with "Golf Shiyouyo" and loading the character data. After loading, you need to return the disc to "Golf Shiyouyo Course Data Syuu" again.

Booting with real BIOS (correct message)

https://github.com/flyinghead/flycast/assets/14366233/896347fb-2808-4166-bcc6-716d170c1291

HLE_BIOS_Golf Shiyouyo Course Data Syuu.zip real_BIOS_Golf Shiyouyo Course Data Syuu.zip

bslenul commented 5 months ago

The Alone in the Dark and RE Code Veronica regressions should be fixed

Working like a charm now, thank you! ❤️

There's a minor annoyance with the Libretro core, you have to resume the game for a few frames after ejecting the disc or else it doesn't register that the tray was opened, similar to the Beetle PSX core (https://github.com/libretro/beetle-psx-libretro/issues/793), basically instead of doing quick menu > disc control > eject > change disc > insert, you have to do quick menu > disc control > eject > resume > re-open menu > change disc > insert.

No resume required with HLE BIOS. Not a big deal but it can be very confusing for users not aware of this, thinking it's not working at all.

edit: Checked the core from master and it seems to behave the same, so this is not a regression. With HLE BIOS it didn't register the tray being open either in master, so this is actually an improvement :D

flyinghead commented 5 months ago

Can you give me a test procedure to reproduce the issue with Dancing Blade - Katteni Momo Tenshi II? I currently start disk 2 then start the game from the beginning and swap to disk 1 when asked and it works fine with HLE bios for me.

Kaen Seibo and Shenmue II do get stuck when swapping disks with HLE bios.

kihato commented 5 months ago

The test procedure is exactly the same. Is it because of the difference in environment? It works fine when booting with real BIOS, but gets stuck when booting with HLE BIOS.

I don't know if it's useful, but this is the savestate when booting with each BIOS. real_BIOS_Dancing Blade - Katteni Momo Tenshi II (Disc2).zip HLE_BIOS_Dancing Blade - Katteni Momo Tenshi II (Disc2).zip

It seems to get stuck even when I test it using the following save file: (Disc1 -> Disc2) vmu_save_A1.zip

https://github.com/flyinghead/flycast/assets/14366233/600ed1a8-644f-4285-a5a0-0c09510eb99a

flyinghead commented 5 months ago

I was testing with Dancing Blade - Katteni Momo Tenshi! Kanzen Ban instead of Dancing Blade - Katteni Momo Tenshi II Sorry about that

kihato commented 5 months ago

I see, no problem. Here is a table of the types of games I test.

Type1: no check

|Title|real BIOS|HLE BIOS| |---|---|---| |MyMerryMaybe|OK|Not OK[^1]| |Web Mystery|OK|OK| |Ohgami Ichirou Funtouki|OK|Not OK[^1]| |Suigetsu|OK|Not OK[^1]|

[^1]: Error Flycast has stopped. Reboot to BIOS

Type2: sns_key=6

|Title|real BIOS|HLE BIOS| |---|---|---| |Comic Party|OK|OK| |Golf Shiyouyo Course Data Syuu|OK|Not OK[^1]| |Golf Shiyouyo|OK|Not OK[^1]| |Pop'n Music 2|OK|OK| |Pop'n Music 3 - Append Disc|OK|OK| |Pop'n Music 4 - Append Disc|OK|OK| |Deep Fighter|OK|OK| |D2|OK|OK| |Dancing Blade 1|OK|OK| |Sakura Taisen 2|OK|OK|

Type3: Requires Open

|Title|real BIOS|HLE BIOS| |---|---|---| |Biohazard - Code Veronica - Kanzenban|OK|OK| |Black Matrix A-D|OK|OK| |EVE ZERO Kanzenban|OK|OK| |es|OK|OK| |First Kiss Story|OK|OK| |Grauen no Torikago|OK|OK| |Real Sound - Kaze no Regret|OK|OK| |Sakura Taisen|OK|OK| |Sakura Taisen 3|OK|OK| |Sister PrincessS Premium Edition|OK|OK| |Alone in the dark|OK|OK|

Type4: Busy

|Title|real BIOS|HLE BIOS| |---|---|---| |First Kiss Story II|OK|OK| |Eternal Arcadia|OK|OK| |Kaen Seibo|OK|Not OK[^2]|

Type5: sns_key=2

|Title|real BIOS|HLE BIOS| |---|---|---| |Dancing Blade - Katteni Momo Tenshi II|OK|Not OK[^2]| |Shenmue II|OK|Not OK[^2]|

flyinghead commented 5 months ago

The latest dev build has some changes to HLE BIOS. Shenmue II, Kaen Seibo and Dancing Blade II disk swapping should now work fine. It also fixes the wrong visual in Golf Shiyouyo Course Data Syuu.

kihato commented 5 months ago

It does works very well. Thanks for your great work!

I don't know why these three games don't work, but it seems to occur when gd_hle_state.result[0] = sns_key(=6) is held in if (sns_asc != 0).

Also, I found a new bug in "Comic Party" where if you insert a different disc when changing discs, a message will be displayed multiple times. However, since the disk exchange itself works, there is no particular problem.