NeoGeo CD updates (#787)

- Add Unibios and CDZ support
- Ask FPGA before sending sector
- 1-4x CD speed
This commit is contained in:
paulb-nl
2023-07-01 10:53:18 +02:00
committed by GitHub
parent 3547099b7f
commit 71a8caacde
8 changed files with 106 additions and 27 deletions

View File

@@ -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
{

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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