diff --git a/core/emulator.cpp b/core/emulator.cpp index 3c97615d4..fe1d3a2de 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -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; } diff --git a/core/hw/gdrom/gdrom_if.h b/core/hw/gdrom/gdrom_if.h index b71180429..213084c77 100644 --- a/core/hw/gdrom/gdrom_if.h +++ b/core/hw/gdrom/gdrom_if.h @@ -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(); diff --git a/core/hw/gdrom/gdromv3.cpp b/core/hw/gdrom/gdromv3.cpp index 4cc1cc88f..86758ee37 100644 --- a/core/hw/gdrom/gdromv3.cpp +++ b/core/hw/gdrom/gdromv3.cpp @@ -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 diff --git a/core/imgread/common.cpp b/core/imgread/common.cpp index 611bff5d1..bdbb8a72b 100644 --- a/core/imgread/common.cpp +++ b/core/imgread/common.cpp @@ -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 *digest); Disc* gdi_parse(const char* file, std::vector *digest); @@ -9,8 +11,9 @@ Disc* cdi_parse(const char* file, std::vector *digest); Disc* cue_parse(const char* file, std::vector *digest); Disc* ioctl_parse(const char* file, std::vector *digest); -u32 NullDriveDiscType; +static u32 NullDriveDiscType; Disc* disc; +static int schedId = -1; constexpr Disc* (*drivers[])(const char* path, std::vector *digest) { @@ -23,7 +26,7 @@ constexpr Disc* (*drivers[])(const char* path, std::vector *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); +} diff --git a/core/imgread/common.h b/core/imgread/common.h index 0e1ab86d5..8da24bf51 100644 --- a/core/imgread/common.h +++ b/core/imgread/common.h @@ -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 { diff --git a/core/reios/reios.cpp b/core/reios/reios.cpp index 7389b32c7..42c2127b3 100644 --- a/core/reios/reios.cpp +++ b/core/reios/reios.cpp @@ -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 diff --git a/core/serialize.cpp b/core/serialize.cpp index 610dd5f32..4c6b5735d 100644 --- a/core/serialize.cpp +++ b/core/serialize.cpp @@ -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(); // FLASH_SIZE deser.skip(); // 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); diff --git a/core/serialize.h b/core/serialize.h index 9295f36d1..81405cfef 100644 --- a/core/serialize.h +++ b/core/serialize.h @@ -71,7 +71,8 @@ public: V43, V44, V45, - Current = V45, + V46, + Current = V46, Next = Current + 1, }; diff --git a/tests/src/serialize_test.cpp b/tests/src/serialize_test.cpp index 1415b19eb..0e197a516 100644 --- a/tests/src/serialize_test.cpp +++ b/tests/src/serialize_test.cpp @@ -32,7 +32,7 @@ TEST_F(SerializeTest, SizeTest) std::vector data(30000000); Serializer ser(data.data(), data.size()); dc_serialize(ser); - ASSERT_EQ(28191425u, ser.size()); + ASSERT_EQ(28191437u, ser.size()); }