From 71a8caacde94dd4ba31eea4a91b776f7f5a0a25a Mon Sep 17 00:00:00 2001 From: paulb-nl Date: Sat, 1 Jul 2023 10:53:18 +0200 Subject: [PATCH] NeoGeo CD updates (#787) - Add Unibios and CDZ support - Ask FPGA before sending sector - 1-4x CD speed --- menu.cpp | 2 +- support/megacd/megacd.cpp | 1 + support/megacd/megacd.h | 3 +- support/megacd/megacdd.cpp | 30 ++++++++++++++--- support/neogeo/neogeo_loader.cpp | 38 ++++++++++++++-------- support/neogeo/neogeo_loader.h | 2 +- support/neogeo/neogeocd.cpp | 55 +++++++++++++++++++++++++++++--- support/neogeo/neogeocd.h | 2 ++ 8 files changed, 106 insertions(+), 27 deletions(-) diff --git a/menu.cpp b/menu.cpp index 04b088d..c6d506d 100644 --- a/menu.cpp +++ b/menu.cpp @@ -2269,7 +2269,7 @@ void HandleUI(void) if (fs_Options & SCANO_NEOGEO) { neocd_set_en(0); - neogeo_romset_tx(selPath); + neogeo_romset_tx(selPath, 0); } else { diff --git a/support/megacd/megacd.cpp b/support/megacd/megacd.cpp index 42655c2..70b2135 100644 --- a/support/megacd/megacd.cpp +++ b/support/megacd/megacd.cpp @@ -153,6 +153,7 @@ void mcd_set_image(int num, const char *filename) cdd.status = cdd.loaded ? CD_STAT_STOP : CD_STAT_NO_DISC; cdd.latency = 10; cdd.SendData = mcd_send_data; + cdd.CanSendData = NULL; if (!same_game) { diff --git a/support/megacd/megacd.h b/support/megacd/megacd.h index 36e097b..8475b65 100644 --- a/support/megacd/megacd.h +++ b/support/megacd/megacd.h @@ -49,6 +49,7 @@ public: uint8_t isData; int loaded; SendDataFunc SendData; + int (*CanSendData)(uint8_t type); cdd_t(); int Load(const char *filename); @@ -79,7 +80,7 @@ private: int SubcodeSend(); void ReadData(uint8_t *buf); int ReadCDDA(uint8_t *buf); - void ReadSubcode(uint16_t* buf); + int ReadSubcode(uint16_t* buf); void LBAToMSF(int lba, msf_t* msf); void MSFToLBA(int* lba, msf_t* msf); void MSFToLBA(int* lba, uint8_t m, uint8_t s, uint8_t f); diff --git a/support/megacd/megacdd.cpp b/support/megacd/megacdd.cpp index 2fc48bc..f9eda47 100644 --- a/support/megacd/megacdd.cpp +++ b/support/megacd/megacdd.cpp @@ -23,6 +23,7 @@ cdd_t::cdd_t() { chd_hunkbuf = NULL; chd_hunknum = -1; SendData = NULL; + CanSendData = NULL; stat[0] = 0xB; stat[1] = 0x0; @@ -371,7 +372,12 @@ void cdd_t::Update() { this->latency--; return; } - this->status = this->loaded ? CD_STAT_TOC : CD_STAT_NO_DISC; + // Neo Geo CDZ does not like the status changing to TOC here. + //this->status = this->loaded ? CD_STAT_TOC : CD_STAT_NO_DISC; + if (!this->loaded) + { + this->status = CD_STAT_NO_DISC; + } } else if (this->status == CD_STAT_SEEK) { @@ -396,6 +402,11 @@ void cdd_t::Update() { return; } + if (CanSendData && !CanSendData(this->toc.tracks[this->index].type)) + { + // Not ready yet to receive sector + return; + } if (this->toc.tracks[this->index].type) { @@ -409,7 +420,6 @@ void cdd_t::Update() { header[3] = 0x01; SectorSend(header); - } else { @@ -551,6 +561,9 @@ void cdd_t::CommandExec() { break; case CD_COMM_TOC: + if (this->status == CD_STAT_STOP) { + this->status = CD_STAT_TOC; + } switch (comm[3]) { case 0: { int lba_ = this->lba + 150; @@ -980,8 +993,9 @@ void InterleaveSubcode(uint8_t *subc_data, uint16_t *buf) } } -void cdd_t::ReadSubcode(uint16_t* buf) +int cdd_t::ReadSubcode(uint16_t* buf) { + int err = 0; uint8_t subc[96]; if (this->toc.chd_f) { @@ -991,11 +1005,17 @@ void cdd_t::ReadSubcode(uint16_t* buf) } else if (this->toc.tracks[this->index].sbc_type == SUBCODE_RW) { mister_chd_read_sector(this->toc.chd_f, this->chd_audio_read_lba + this->toc.tracks[this->index].offset, 0, CD_MAX_SECTOR_DATA, 96, subc, this->chd_hunkbuf, &this->chd_hunknum); InterleaveSubcode(subc, buf); + } else { + err = -1; } } else if (this->toc.sub.opened()) { FileReadAdv(&this->toc.sub, subc, 96); InterleaveSubcode(subc, buf); + } else { + err = -1; } + + return err; } @@ -1024,9 +1044,9 @@ int cdd_t::SubcodeSend() { uint16_t buf[98 / 2]; - ReadSubcode(buf); + int err = ReadSubcode(buf); - if (SendData) + if (!err && SendData) return SendData((uint8_t*)buf, 98, MCD_SUB_IO_INDEX); return 0; diff --git a/support/neogeo/neogeo_loader.cpp b/support/neogeo/neogeo_loader.cpp index 109b9ac..d584fc6 100644 --- a/support/neogeo/neogeo_loader.cpp +++ b/support/neogeo/neogeo_loader.cpp @@ -1053,17 +1053,18 @@ void load_neo(char *path) } } -int neogeo_romset_tx(char* name) +int neogeo_romset_tx(char* name, int cd_en) { char *romset = strrchr(name, '/'); if (!romset) return 0; romset++; - int system_type; + int system_mvs, system_cdz; static char full_path[1024]; - system_type = user_io_status_get("[2:1]") & 3; - printf("System type: %u\n", system_type); + system_mvs = user_io_status_get("[1]") & 1; + system_cdz = user_io_status_get("[2]") & 1; + printf("System MVS: %u, CDZ: %u, CD: %u\n", system_mvs, system_cdz, cd_en); spi_uio_cmd_cont(UIO_GET_OSDMASK); uint16_t mask = spi_w(0); @@ -1078,8 +1079,12 @@ int neogeo_romset_tx(char* name) const char* home = HomeDir(); + // Send cd_en to the FPGA before loading files + set_config((cd_en & 1) << 31, 1 << 31); + notify_conf(); + // Look for the romset's file list in romsets.xml - if (!(system_type & 2)) + if (!cd_en) { char *p = strrchr(name, '.'); if (p && !strcasecmp(p, ".neo")) @@ -1118,31 +1123,36 @@ int neogeo_romset_tx(char* name) // Load system ROMs if (strcmp(romset, "debug")) { // Not loading the special 'debug' romset - if (!(system_type & 2)) { + if (!cd_en) { sprintf(full_path, "%s/uni-bios.rom", home); if (!(mask & 0x8000) && FileExists(full_path)) { // Autoload Unibios for cart systems if present neogeo_tx(home, "uni-bios.rom", NEO_FILE_RAW, 0, 0, 0x20000); } else { // Otherwise load normal system roms - if (system_type == 0) + if (!system_mvs) neogeo_tx(home, "neo-epo.sp1", NEO_FILE_RAW, 0, 0, 0x20000); else neogeo_tx(home, "sp-s2.sp1", NEO_FILE_RAW, 0, 0, 0x20000); } - } else if (system_type == 2) { - // NeoGeo CD - neogeo_tx(home, "top-sp1.bin", NEO_FILE_RAW, 0, 0, 0x80000); } else { - // NeoGeo CDZ - neogeo_tx(home, "neocd.bin", NEO_FILE_RAW, 0, 0, 0x80000); + sprintf(full_path, "%s/uni-bioscd.rom", home); + if (!(mask & 0x8000) && FileExists(full_path)) { + neogeo_tx(home, "uni-bioscd.rom", NEO_FILE_RAW, 0, 0, 0x80000); + } else if (!system_cdz) { + // NeoGeo CD + neogeo_tx(home, "top-sp1.bin", NEO_FILE_RAW, 0, 0, 0x80000); + } else { + // NeoGeo CDZ + neogeo_tx(home, "neocd.bin", NEO_FILE_RAW, 0, 0, 0x80000); + } } } //flush CROM if any. neogeo_tx(NULL, NULL, 0, -1, 0, 0); - if (!(system_type & 2)) neogeo_tx(home, "sfix.sfix", NEO_FILE_FIX, 2, 0, 0); + if (!cd_en) neogeo_tx(home, "sfix.sfix", NEO_FILE_FIX, 2, 0, 0); neogeo_file_tx(home, "000-lo.lo", NEO_FILE_8BIT, 1, 0, 0x10000); if (crom_start < 0x300000) crom_start = 0x300000; @@ -1156,7 +1166,7 @@ int neogeo_romset_tx(char* name) notify_conf(); - FileGenerateSavePath((system_type & 2) ? "ngcd" : name, (char*)full_path); + FileGenerateSavePath(cd_en ? "ngcd" : name, (char*)full_path); user_io_file_mount((char*)full_path, 0, 1); user_io_status_set("[0]", 0); // Release reset diff --git a/support/neogeo/neogeo_loader.h b/support/neogeo/neogeo_loader.h index 4c87a24..105d050 100644 --- a/support/neogeo/neogeo_loader.h +++ b/support/neogeo/neogeo_loader.h @@ -5,6 +5,6 @@ #define NEO_FILE_FIX 2 #define NEO_FILE_SPR 3 -int neogeo_romset_tx(char* name); +int neogeo_romset_tx(char* name, int cd_en); int neogeo_scan_xml(char *path); char *neogeo_get_altname(char *path, char *name, char *altname); diff --git a/support/neogeo/neogeocd.cpp b/support/neogeo/neogeocd.cpp index 8f55d74..fd68963 100644 --- a/support/neogeo/neogeocd.cpp +++ b/support/neogeo/neogeocd.cpp @@ -17,21 +17,24 @@ static int need_reset=0; static uint8_t has_command = 0; static uint8_t neo_cd_en = 0; +static uint32_t poll_timer = 0; +static uint8_t cd_speed = 0; #define CRC_START 5 #define NEOCD_AUDIO_IO_INDEX 4 +#define NEOCD_GET_CMD 0 +#define NEOCD_GET_SEND_DATA 1 + void neocd_poll() { - static uint32_t poll_timer = 0; static uint8_t last_req = 255; - static uint8_t adj = 0; if (!poll_timer || CheckTimer(poll_timer)) { - poll_timer = GetTimer(13 + (!adj ? 1 : 0)); - if (++adj >= 3) adj = 0; + + set_poll_timer(); if (has_command) { spi_uio_cmd_cont(UIO_CD_SET); @@ -56,6 +59,8 @@ void neocd_poll() { last_req = req; + spi_w(NEOCD_GET_CMD); + uint16_t data_in[4]; data_in[0] = spi_w(0); data_in[1] = spi_w(0); @@ -68,6 +73,8 @@ void neocd_poll() cdd.Reset(); } + cd_speed = (data_in[2] >> 8) & 3; + uint64_t c = *((uint64_t*)(data_in)); cdd.SetCommand(c, CRC_START); cdd.CommandExec(); @@ -79,6 +86,32 @@ void neocd_poll() DisableIO(); } +void set_poll_timer() +{ + int speed = cd_speed; + int interval = 10; // Slightly faster so the buffers stay filled when playing + + if (!cdd.isData || cdd.status != CD_STAT_PLAY || cdd.latency != 0) + { + speed = 0; + } + + if (speed == 1) + { + interval = 5; + } + else if (speed == 2) + { + interval = 4; + } + else if (speed == 3) + { + interval = 2; + } + + poll_timer = GetTimer(interval); +} + void neocd_set_image(char *filename) { cdd.Unload(); @@ -86,13 +119,14 @@ void neocd_set_image(char *filename) if (*filename) { - neogeo_romset_tx(filename); + neogeo_romset_tx(filename, 1); if (cdd.Load(filename) > 0) { cdd.status = cdd.loaded ? CD_STAT_STOP : CD_STAT_NO_DISC; cdd.latency = 10; cdd.SendData = neocd_send_data; + cdd.CanSendData = neocd_can_send_data; } else { @@ -133,3 +167,14 @@ int neocd_is_en() { void neocd_set_en(int enable) { neo_cd_en = enable; } + +int neocd_can_send_data(uint8_t type) { + // Ask the FPGA if it is ready to receive a sector + spi_uio_cmd_cont(UIO_CD_GET); + spi_w(NEOCD_GET_SEND_DATA | (type << 2)); + + uint16_t data = spi_w(0); + DisableIO(); + + return (data == 1); +} diff --git a/support/neogeo/neogeocd.h b/support/neogeo/neogeocd.h index 06bee1f..c4cb799 100644 --- a/support/neogeo/neogeocd.h +++ b/support/neogeo/neogeocd.h @@ -6,6 +6,8 @@ void neocd_poll(); void neocd_set_image(char *filename); void neocd_reset(); int neocd_send_data(uint8_t* buf, int len, uint8_t index); +int neocd_can_send_data(uint8_t type); int neocd_is_en(); void neocd_set_en(int enable); +void set_poll_timer(); #endif