gdrom: fix disk swapping for some games
Add a 1 s delay when inserting a disk before the drive is ready. Fixes disk swapping for Skies of Arcadia, Shenmue II (except HLE), Alone in the Dark, Dancing Blade, First Kiss Story II and Kaen Seibo. Issue #1046 Issue #189 Fixes BIOS menu disk swapping.
This commit is contained in:
parent
88fd2641d9
commit
cbd01fba38
|
@ -412,6 +412,7 @@ void Emulator::init()
|
|||
// Default platform
|
||||
setPlatform(DC_PLATFORM_DREAMCAST);
|
||||
|
||||
libGDR_init();
|
||||
pvr::init();
|
||||
aica::init();
|
||||
mem_Init();
|
||||
|
@ -654,6 +655,7 @@ void Emulator::term()
|
|||
aica::term();
|
||||
pvr::term();
|
||||
mem_Term();
|
||||
libGDR_term();
|
||||
|
||||
state = Terminated;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ void gdrom_reg_Reset(bool hard);
|
|||
u32 ReadMem_gdrom(u32 Addr, u32 sz);
|
||||
void WriteMem_gdrom(u32 Addr, u32 data, u32 sz);
|
||||
void libCore_CDDA_Sector(s16* sector);
|
||||
void libCore_gdrom_disc_change();
|
||||
u32 gd_get_subcode(u32 format, u32 fad, u8 *subc_info);
|
||||
void gd_setdisc();
|
||||
|
||||
|
|
|
@ -23,16 +23,16 @@ int sns_asc;
|
|||
int sns_ascq;
|
||||
int sns_key;
|
||||
|
||||
u32 set_mode_offset;
|
||||
read_params_t read_params ;
|
||||
packet_cmd_t packet_cmd ;
|
||||
read_buff_t read_buff ;
|
||||
pio_buff_t pio_buff ;
|
||||
ata_cmd_t ata_cmd ;
|
||||
cdda_t cdda ;
|
||||
static u32 set_mode_offset;
|
||||
static read_params_t read_params;
|
||||
static packet_cmd_t packet_cmd;
|
||||
static read_buff_t read_buff;
|
||||
static pio_buff_t pio_buff;
|
||||
static ata_cmd_t ata_cmd;
|
||||
cdda_t cdda;
|
||||
|
||||
gd_states gd_state;
|
||||
DiscType gd_disk_type;
|
||||
static gd_states gd_state;
|
||||
static DiscType gd_disk_type;
|
||||
/*
|
||||
GD rom reset -> GDS_WAITCMD
|
||||
|
||||
|
@ -41,19 +41,19 @@ DiscType gd_disk_type;
|
|||
|
||||
GDS_SPI_READSECTOR -> Depending on features , it can do quite a few things
|
||||
*/
|
||||
u32 data_write_mode=0;
|
||||
static u32 data_write_mode=0;
|
||||
|
||||
//Registers
|
||||
u32 DriveSel;
|
||||
GD_ErrRegT Error;
|
||||
GD_InterruptReasonT IntReason;
|
||||
GD_FeaturesT Features;
|
||||
GD_SecCountT SecCount;
|
||||
GD_SecNumbT SecNumber;
|
||||
static u32 DriveSel;
|
||||
static GD_ErrRegT Error;
|
||||
static GD_InterruptReasonT IntReason;
|
||||
static GD_FeaturesT Features;
|
||||
static GD_SecCountT SecCount;
|
||||
GD_SecNumbT SecNumber;
|
||||
|
||||
GD_StatusT GDStatus;
|
||||
static GD_StatusT GDStatus;
|
||||
|
||||
ByteCount_t ByteCount;
|
||||
static ByteCount_t ByteCount;
|
||||
|
||||
//end
|
||||
GD_HardwareInfo_t GD_HardwareInfo;
|
||||
|
@ -94,9 +94,10 @@ void libCore_CDDA_Sector(s16* sector)
|
|||
memset(sector,0,2352);
|
||||
}
|
||||
}
|
||||
void gd_spi_pio_end(const u8* buffer, u32 len, gd_states next_state = gds_pio_end);
|
||||
void gd_process_spi_cmd();
|
||||
void gd_process_ata_cmd();
|
||||
|
||||
static void gd_spi_pio_end(const u8* buffer, u32 len, gd_states next_state = gds_pio_end);
|
||||
static void gd_process_spi_cmd();
|
||||
static void gd_process_ata_cmd();
|
||||
|
||||
static void FillReadBuffer()
|
||||
{
|
||||
|
@ -114,7 +115,7 @@ static void FillReadBuffer()
|
|||
}
|
||||
|
||||
|
||||
void gd_set_state(gd_states state)
|
||||
static void gd_set_state(gd_states state)
|
||||
{
|
||||
gd_states prev=gd_state;
|
||||
gd_state=state;
|
||||
|
@ -282,7 +283,7 @@ void gd_setdisc()
|
|||
SecNumber.DiscFormat = gd_disk_type >> 4;
|
||||
}
|
||||
|
||||
void gd_reset()
|
||||
static void gd_reset()
|
||||
{
|
||||
//Reset the drive
|
||||
gd_setdisc();
|
||||
|
@ -298,7 +299,7 @@ static u32 GetFAD(u8* data, bool msf)
|
|||
}
|
||||
|
||||
//disk changes etc
|
||||
void libCore_gdrom_disc_change()
|
||||
static void gd_disc_change()
|
||||
{
|
||||
gd_setdisc();
|
||||
read_params = { 0 };
|
||||
|
@ -311,7 +312,7 @@ void libCore_gdrom_disc_change()
|
|||
}
|
||||
|
||||
//This handles the work of setting up the pio regs/state :)
|
||||
void gd_spi_pio_end(const u8* buffer, u32 len, gd_states next_state)
|
||||
static void gd_spi_pio_end(const u8* buffer, u32 len, gd_states next_state)
|
||||
{
|
||||
verify(len<0xFFFF);
|
||||
pio_buff.index=0;
|
||||
|
@ -326,7 +327,7 @@ void gd_spi_pio_end(const u8* buffer, u32 len, gd_states next_state)
|
|||
else
|
||||
gd_set_state(gds_pio_send_data);
|
||||
}
|
||||
void gd_spi_pio_read_end(u32 len, gd_states next_state)
|
||||
static void gd_spi_pio_read_end(u32 len, gd_states next_state)
|
||||
{
|
||||
verify(len<0xFFFF);
|
||||
pio_buff.index=0;
|
||||
|
@ -338,7 +339,7 @@ void gd_spi_pio_read_end(u32 len, gd_states next_state)
|
|||
else
|
||||
gd_set_state(gds_pio_get_data);
|
||||
}
|
||||
void gd_process_ata_cmd()
|
||||
static void gd_process_ata_cmd()
|
||||
{
|
||||
//Any ATA command clears these bits, unless aborted/error :p
|
||||
Error.ABRT=0;
|
||||
|
@ -644,7 +645,7 @@ u32 gd_get_subcode(u32 format, u32 fad, u8 *subc_info)
|
|||
return subc_info[3];
|
||||
}
|
||||
|
||||
void gd_process_spi_cmd()
|
||||
static void gd_process_spi_cmd()
|
||||
{
|
||||
|
||||
printf_spi("Sense: %02x %02x %02x", sns_asc, sns_ascq, sns_key);
|
||||
|
@ -664,9 +665,7 @@ void gd_process_spi_cmd()
|
|||
{
|
||||
case SPI_TEST_UNIT:
|
||||
printf_spicmd("SPI_TEST_UNIT");
|
||||
|
||||
GDStatus.CHECK=SecNumber.Status==GD_BUSY; // Drive is ready ;)
|
||||
|
||||
// This device does not report the check condition status.
|
||||
gd_set_state(gds_procpacketdone);
|
||||
break;
|
||||
|
||||
|
@ -776,8 +775,8 @@ void gd_process_spi_cmd()
|
|||
|
||||
case SPI_REQ_STAT:
|
||||
{
|
||||
printf_spicmd("SPI_REQ_STAT");
|
||||
u32 curFad = cdda.status == cdda_t::Playing || cdda.status == cdda_t::Paused ? cdda.CurrAddr.FAD : read_params.start_sector - 1;
|
||||
printf_spicmd("SPI_REQ_STAT: status %d fmt %d fad %d", SecNumber.Status, SecNumber.DiscFormat, curFad);
|
||||
u32 elapsed;
|
||||
u32 tracknum = libGDR_GetTrackNumber(curFad, elapsed);
|
||||
u8 stat[10];
|
||||
|
@ -833,7 +832,7 @@ void gd_process_spi_cmd()
|
|||
|
||||
case SPI_REQ_SES:
|
||||
{
|
||||
printf_spicmd("SPI_REQ_SES");
|
||||
printf_spicmd("SPI_REQ_SES: status %d", SecNumber.Status);
|
||||
|
||||
u8 ses_inf[6];
|
||||
libGDR_GetSessionInfo(ses_inf,packet_cmd.data_8[2]);
|
||||
|
@ -1301,7 +1300,7 @@ static void GDROM_DmaEnable(u32 addr, u32 data)
|
|||
void gdrom_reg_Init()
|
||||
{
|
||||
gdrom_schid = sh4_sched_register(0, &GDRomschd);
|
||||
libCore_gdrom_disc_change();
|
||||
gd_disc_change();
|
||||
}
|
||||
|
||||
void gdrom_reg_Term()
|
||||
|
@ -1327,6 +1326,7 @@ void gdrom_reg_Reset(bool hard)
|
|||
memcpy(GD_HardwareInfo.drive_info, "SE ", sizeof(GD_HardwareInfo.drive_info));
|
||||
memcpy(GD_HardwareInfo.system_version, "Rev 6.43", sizeof(GD_HardwareInfo.system_version));
|
||||
memcpy(GD_HardwareInfo.system_date, "990408", sizeof(GD_HardwareInfo.system_date));
|
||||
TermDrive();
|
||||
}
|
||||
SB_GDST = 0;
|
||||
SB_GDEN = 0;
|
||||
|
@ -1354,7 +1354,7 @@ void gdrom_reg_Reset(bool hard)
|
|||
GDStatus = {};
|
||||
ByteCount = {};
|
||||
|
||||
libCore_gdrom_disc_change();
|
||||
gd_disc_change();
|
||||
}
|
||||
|
||||
namespace gdrom
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "hw/gdrom/gdromv3.h"
|
||||
#include "cfg/option.h"
|
||||
#include "stdclass.h"
|
||||
#include "hw/sh4/sh4_sched.h"
|
||||
#include "serialize.h"
|
||||
|
||||
Disc* chd_parse(const char* file, std::vector<u8> *digest);
|
||||
Disc* gdi_parse(const char* file, std::vector<u8> *digest);
|
||||
|
@ -9,8 +11,9 @@ Disc* cdi_parse(const char* file, std::vector<u8> *digest);
|
|||
Disc* cue_parse(const char* file, std::vector<u8> *digest);
|
||||
Disc* ioctl_parse(const char* file, std::vector<u8> *digest);
|
||||
|
||||
u32 NullDriveDiscType;
|
||||
static u32 NullDriveDiscType;
|
||||
Disc* disc;
|
||||
static int schedId = -1;
|
||||
|
||||
constexpr Disc* (*drivers[])(const char* path, std::vector<u8> *digest)
|
||||
{
|
||||
|
@ -23,7 +26,7 @@ constexpr Disc* (*drivers[])(const char* path, std::vector<u8> *digest)
|
|||
#endif
|
||||
};
|
||||
|
||||
u8 q_subchannel[96];
|
||||
static u8 q_subchannel[96];
|
||||
|
||||
static bool convertSector(u8* in_buff , u8* out_buff , int from , int to,int sector)
|
||||
{
|
||||
|
@ -113,18 +116,16 @@ static bool loadDisk(const std::string& path)
|
|||
INFO_LOG(GDROM, "gdrom: Failed to open image \"%s\"", path.c_str());
|
||||
NullDriveDiscType = NoDisk;
|
||||
}
|
||||
libCore_gdrom_disc_change();
|
||||
|
||||
return disc != NULL;
|
||||
}
|
||||
|
||||
static bool doDiscSwap(const std::string& path);
|
||||
|
||||
bool InitDrive(const std::string& path)
|
||||
{
|
||||
bool rc = DiscSwap(path);
|
||||
// not needed at startup and confuses some games
|
||||
sns_asc = 0;
|
||||
sns_ascq = 0;
|
||||
sns_key = 0;
|
||||
bool rc = doDiscSwap(path);
|
||||
gd_setdisc();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -139,18 +140,12 @@ void DiscOpenLid()
|
|||
sns_key = 0x6;
|
||||
}
|
||||
|
||||
bool DiscSwap(const std::string& path)
|
||||
static bool doDiscSwap(const std::string& path)
|
||||
{
|
||||
// These Additional Sense Codes mean "The lid was closed"
|
||||
sns_asc = 0x28;
|
||||
sns_ascq = 0x00;
|
||||
sns_key = 0x6;
|
||||
|
||||
if (path.empty())
|
||||
{
|
||||
TermDrive();
|
||||
NullDriveDiscType = NoDisk;
|
||||
gd_setdisc();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -158,15 +153,14 @@ bool DiscSwap(const std::string& path)
|
|||
return true;
|
||||
|
||||
NullDriveDiscType = NoDisk;
|
||||
gd_setdisc();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TermDrive()
|
||||
{
|
||||
sh4_sched_request(schedId, -1);
|
||||
delete disc;
|
||||
disc = NULL;
|
||||
disc = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -311,8 +305,64 @@ void libGDR_ReadSubChannel(u8 * buff, u32 len)
|
|||
|
||||
u32 libGDR_GetDiscType()
|
||||
{
|
||||
if (disc)
|
||||
if (SecNumber.Status != GD_BUSY && disc != nullptr)
|
||||
return disc->type;
|
||||
else
|
||||
return NullDriveDiscType;
|
||||
}
|
||||
|
||||
static int discSwapCallback(int tag, int sch_cycl, int jitter, void *arg)
|
||||
{
|
||||
if (disc != nullptr)
|
||||
// The lid was closed
|
||||
sns_asc = 0x28;
|
||||
else
|
||||
// No disc inserted at the time of power-on, reset or hard reset, or TOC cannot be read.
|
||||
sns_asc = 0x29;
|
||||
sns_ascq = 0x00;
|
||||
sns_key = 0x6;
|
||||
gd_setdisc();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DiscSwap(const std::string& path)
|
||||
{
|
||||
if (!doDiscSwap(path))
|
||||
throw FlycastException("This media cannot be loaded");
|
||||
// Drive is busy after the lid was closed
|
||||
sns_asc = 4;
|
||||
sns_ascq = 1;
|
||||
sns_key = 2;
|
||||
SecNumber.Status = GD_BUSY;
|
||||
sh4_sched_request(schedId, SH4_MAIN_CLOCK); // 1 s
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void libGDR_init()
|
||||
{
|
||||
schedId = sh4_sched_register(0, discSwapCallback);
|
||||
}
|
||||
void libGDR_term()
|
||||
{
|
||||
TermDrive();
|
||||
sh4_sched_unregister(schedId);
|
||||
schedId = -1;
|
||||
}
|
||||
|
||||
void libGDR_serialize(Serializer& ser)
|
||||
{
|
||||
ser << NullDriveDiscType;
|
||||
ser << q_subchannel;
|
||||
sh4_sched_serialize(ser, schedId);
|
||||
}
|
||||
void libGDR_deserialize(Deserializer& deser)
|
||||
{
|
||||
deser >> NullDriveDiscType;
|
||||
deser >> q_subchannel;
|
||||
if (deser.version() >= Deserializer::V46)
|
||||
sh4_sched_deserialize(deser, schedId);
|
||||
else
|
||||
sh4_sched_request(schedId, -1);
|
||||
}
|
||||
|
|
|
@ -273,6 +273,10 @@ bool libGDR_GetTrack(u32 track_num, u32& start_fad, u32& end_fad);
|
|||
std::string libGDR_GetDiskCatalog();
|
||||
std::string libGDR_GetTrackIsrc(u32 trackNum);
|
||||
void libGDR_GetTrackAdrAndControl(u32 trackNum, u8& adr, u8& ctrl);
|
||||
void libGDR_init();
|
||||
void libGDR_term();
|
||||
void libGDR_serialize(Serializer& ser);
|
||||
void libGDR_deserialize(Deserializer& deser);
|
||||
|
||||
namespace flycast
|
||||
{
|
||||
|
|
|
@ -357,9 +357,17 @@ static void reios_sys_misc()
|
|||
break;
|
||||
|
||||
case 2: // check disk
|
||||
p_sh4rcb->cntx.r[0] = 0;
|
||||
// Reload part of IP.BIN bootstrap
|
||||
libGDR_ReadSector(GetMemPtr(0x8c008100, 0), base_fad, 7, 2048);
|
||||
{
|
||||
u32 diskType = libGDR_GetDiscType();
|
||||
if (diskType == NoDisk || diskType == Open) {
|
||||
p_sh4rcb->cntx.r[0] = -1;
|
||||
}
|
||||
else {
|
||||
p_sh4rcb->cntx.r[0] = 0;
|
||||
// Reload part of IP.BIN bootstrap
|
||||
libGDR_ReadSector(GetMemPtr(0x8c008100, 0), base_fad, 7, 2048);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Exit to CD menu
|
||||
|
|
|
@ -15,10 +15,7 @@
|
|||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "hw/bba/bba.h"
|
||||
#include "cfg/option.h"
|
||||
|
||||
//./core/imgread/common.o
|
||||
extern u32 NullDriveDiscType;
|
||||
extern u8 q_subchannel[96];
|
||||
#include "imgread/common.h"
|
||||
|
||||
void dc_serialize(Serializer& ser)
|
||||
{
|
||||
|
@ -43,8 +40,7 @@ void dc_serialize(Serializer& ser)
|
|||
|
||||
sh4::serialize2(ser);
|
||||
|
||||
ser << NullDriveDiscType;
|
||||
ser << q_subchannel;
|
||||
libGDR_serialize(ser);
|
||||
|
||||
naomi_Serialize(ser);
|
||||
|
||||
|
@ -82,8 +78,7 @@ static void dc_deserialize_libretro(Deserializer& deser)
|
|||
|
||||
sh4::deserialize2(deser);
|
||||
|
||||
deser >> NullDriveDiscType;
|
||||
deser >> q_subchannel;
|
||||
libGDR_deserialize(deser);
|
||||
|
||||
deser.skip<u32>(); // FLASH_SIZE
|
||||
deser.skip<u32>(); // BBSRAM_SIZE
|
||||
|
@ -141,8 +136,7 @@ void dc_deserialize(Deserializer& deser)
|
|||
|
||||
sh4::deserialize2(deser);
|
||||
|
||||
deser >> NullDriveDiscType;
|
||||
deser >> q_subchannel;
|
||||
libGDR_deserialize(deser);
|
||||
|
||||
naomi_Deserialize(deser);
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ public:
|
|||
V43,
|
||||
V44,
|
||||
V45,
|
||||
Current = V45,
|
||||
V46,
|
||||
Current = V46,
|
||||
|
||||
Next = Current + 1,
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST_F(SerializeTest, SizeTest)
|
|||
std::vector<char> data(30000000);
|
||||
Serializer ser(data.data(), data.size());
|
||||
dc_serialize(ser);
|
||||
ASSERT_EQ(28191425u, ser.size());
|
||||
ASSERT_EQ(28191437u, ser.size());
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue