summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2026-01-15 16:38:35 +0100
committer angelosa <lordkale4@gmail.com>2026-01-15 16:38:43 +0100
commit22664673d449f1bea33c6d60015b276e6e2118bd (patch)
tree4491783b1c90627839855035244c5ed7b28b669e
parentb8b6c5967e1e769c394916f0c9a4383a4eedf9a9 (diff)
misc/3do_clio.cpp: initial hookup of a CR-560-B CDROM drive
-rw-r--r--scripts/src/machine.lua13
-rw-r--r--src/devices/machine/cr560b.cpp653
-rw-r--r--src/devices/machine/cr560b.h146
-rw-r--r--src/mame/misc/3do.cpp111
-rw-r--r--src/mame/misc/3do.h6
-rw-r--r--src/mame/misc/3do_clio.cpp65
-rw-r--r--src/mame/misc/3do_clio.h8
-rw-r--r--src/mame/misc/3do_madam.cpp3
8 files changed, 952 insertions, 53 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 7bb8fe73fa9..69387220282 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -205,6 +205,19 @@ end
---------------------------------------------------
--
+--@src/devices/machine/cr560b.h,MACHINES["CR560B"] = true
+---------------------------------------------------
+
+if MACHINES["CR560B"] then
+ files {
+ MAME_DIR .. "src/devices/machine/cr560b.cpp",
+ MAME_DIR .. "src/devices/machine/cr560b.h",
+ }
+end
+
+
+---------------------------------------------------
+--
--@src/devices/machine/dmac.h,MACHINES["DMAC"] = true
---------------------------------------------------
diff --git a/src/devices/machine/cr560b.cpp b/src/devices/machine/cr560b.cpp
new file mode 100644
index 00000000000..0738a787de1
--- /dev/null
+++ b/src/devices/machine/cr560b.cpp
@@ -0,0 +1,653 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+CR-560-B CD-ROM drive
+
+Panasonic pre-IDE MKE interface, akin to CR-511-B (which this is based off) and Creative
+Soundblaster.
+
+TODO:
+- stub;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "cr560b.h"
+
+#define LOG_CMD (1 << 1)
+#define LOG_PARAM (1 << 2)
+#define LOG_DATA (1 << 3)
+#define LOG_SUBQ (1 << 4)
+#define LOG_SUBQ2 (1 << 5) // log subq data to popmessage
+
+#define VERBOSE (LOG_GENERAL | LOG_CMD | LOG_PARAM)
+//#define LOG_OUTPUT_FUNC osd_printf_warning
+
+#define LOGPARAM LOGMASKED(LOG_PARAM, "-> Param: %02x %02x %02x %02x %02x %02x\n", \
+ m_input_fifo[1], m_input_fifo[2], m_input_fifo[3], \
+ m_input_fifo[4], m_input_fifo[5], m_input_fifo[6])
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(CR560B, cr560b_device, "cr560b", "CR-560-B CD-ROM drive")
+
+cr560b_device::cr560b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ cdrom_image_device(mconfig, CR560B, tag, owner, clock),
+ device_mixer_interface(mconfig, *this),
+ m_cdda(*this, "cdda"),
+ m_stch_cb(*this),
+ m_sten_cb(*this),
+ m_drq_cb(*this),
+ m_dten_cb(*this),
+ m_scor_cb(*this),
+ m_input_fifo_pos(0),
+ m_output_fifo_pos(0),
+ m_output_fifo_length(0),
+ m_status(0),
+ m_enabled(false),
+ m_cmd(false),
+ m_status_ready(false),
+ m_data_ready(false)
+{
+ set_interface("cdrom");
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void cr560b_device::device_add_mconfig(machine_config &config)
+{
+ CDDA(config, m_cdda);
+ m_cdda->add_route(0, DEVICE_SELF, 1.0, 0);
+ m_cdda->add_route(1, DEVICE_SELF, 1.0, 1);
+ m_cdda->set_cdrom_tag(*this);
+ m_cdda->audio_end_cb().set(FUNC(cr560b_device::audio_end_cb));
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void cr560b_device::device_start()
+{
+ cdrom_image_device::device_start();
+
+ m_frame_timer = timer_alloc(FUNC(cr560b_device::frame_cb), this);
+ m_stch_timer = timer_alloc(FUNC(cr560b_device::stch), this);
+ m_sten_timer = timer_alloc(FUNC(cr560b_device::sten), this);
+
+ std::fill(std::begin(m_input_fifo), std::end(m_input_fifo), 0x00);
+ std::fill(std::begin(m_output_fifo), std::end(m_output_fifo), 0x00);
+
+ // register for save states
+ save_item(NAME(m_input_fifo));
+ save_item(NAME(m_input_fifo_pos));
+ save_item(NAME(m_output_fifo));
+ save_item(NAME(m_output_fifo_pos));
+ save_item(NAME(m_output_fifo_length));
+ save_item(NAME(m_status));
+ save_item(NAME(m_sector_size));
+ save_item(NAME(m_transfer_lba));
+ save_item(NAME(m_transfer_sectors));
+ save_item(NAME(m_transfer_length));
+ save_item(NAME(m_transfer_buffer));
+ save_item(NAME(m_transfer_buffer_pos));
+ save_item(NAME(m_enabled));
+ save_item(NAME(m_cmd));
+ save_item(NAME(m_status_ready));
+ save_item(NAME(m_data_ready));
+}
+
+void cr560b_device::device_reset()
+{
+ cdrom_image_device::device_reset();
+
+ m_input_fifo_pos = 0;
+ m_output_fifo_pos = 0;
+ m_output_fifo_length = 0;
+
+ m_status_ready = false;
+ m_data_ready = false;
+
+ m_status = STATUS_READY;
+
+ if (exists())
+ m_status |= STATUS_MEDIA;
+
+ m_sten_cb(1);
+ m_stch_cb(0);
+}
+
+std::pair<std::error_condition, std::string> cr560b_device::call_load()
+{
+ auto ret = cdrom_image_device::call_load();
+
+ if (!ret.first)
+ status_change(m_status | STATUS_MEDIA);
+
+ return ret;
+}
+
+void cr560b_device::call_unload()
+{
+ status_change(STATUS_READY);
+
+ cdrom_image_device::call_unload();
+}
+
+uint32_t cr560b_device::lba_to_msf(int32_t lba)
+{
+ uint32_t msf = 0;
+
+ lba += 2 * 75; // lba 0 is equivalent to msf 00:02:00
+
+ msf |= ((lba / (60 * 75)) & 0xff) << 16;
+ msf |= (((lba / 75) % 60) & 0xff) << 8;
+ msf |= ((lba % 75) & 0xff) << 0;
+
+ return msf;
+}
+
+int32_t cr560b_device::msf_to_lba(uint32_t msf)
+{
+ uint32_t lba = 0;
+
+ lba += ((msf >> 16) & 0xff) * 60 * 75;
+ lba += ((msf >> 8) & 0xff) * 75;
+ lba += ((msf >> 0) & 0xff);
+
+ lba -= 2 * 75; // msf 00:02:00 is equivalent to lba 0
+
+ return lba;
+}
+
+int cr560b_device::size_to_track_type()
+{
+ switch (m_sector_size)
+ {
+ case 2048: return cdrom_file::CD_TRACK_MODE1;
+ }
+
+ // TODO: 3do definitely supports other formats
+ throw emu_fatalerror("Unknown sector mode: %d\n", m_sector_size);
+}
+
+TIMER_CALLBACK_MEMBER(cr560b_device::frame_cb)
+{
+ if (m_transfer_sectors > 0)
+ {
+ // old data hasn't been read completely yet
+ if (m_data_ready)
+ return;
+
+ LOGMASKED(LOG_DATA, "Reading sector: %d\n", m_transfer_lba);
+
+ read_data(m_transfer_lba, m_transfer_buffer, size_to_track_type());
+
+ // prepare for next sector
+ m_transfer_lba++;
+ m_transfer_sectors--;
+ m_transfer_buffer_pos = 0;
+
+ // signal that we have data
+ m_data_ready = true;
+ m_drq_cb(1);
+ }
+ else if (m_status & STATUS_PLAYING)
+ {
+ // TODO: subcode handling
+ m_scor_cb(0);
+ m_scor_cb(1);
+ }
+}
+
+TIMER_CALLBACK_MEMBER(cr560b_device::stch)
+{
+ m_stch_cb(1);
+ m_stch_cb(0);
+}
+
+void cr560b_device::status_change(uint8_t status)
+{
+ if (m_status != status)
+ {
+ m_status = status;
+
+ if (m_status & STATUS_MOTOR)
+ m_frame_timer->adjust(attotime::from_hz(75), 0, attotime::from_hz(75));
+ else
+ m_frame_timer->adjust(attotime::never);
+
+ m_stch_timer->adjust(attotime::from_usec(64 * 3)); // TODO
+ }
+}
+
+TIMER_CALLBACK_MEMBER(cr560b_device::sten)
+{
+ m_status_ready = true;
+
+ m_sten_cb(0);
+ m_sten_cb(1);
+}
+
+void cr560b_device::status_enable(uint8_t output_length)
+{
+ m_input_fifo_pos = 0;
+ m_output_fifo_pos = 0;
+ m_output_fifo_length = output_length;
+
+ // do we have status data to send?
+ if (m_output_fifo_length > 0)
+ {
+ if (m_input_fifo[0] != 0x87 || (VERBOSE & LOG_SUBQ))
+ LOGMASKED(LOG_CMD, "-> Output: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", m_output_fifo[0], m_output_fifo[1], m_output_fifo[2], m_output_fifo[3], m_output_fifo[4], m_output_fifo[5], m_output_fifo[6], m_output_fifo[7], m_output_fifo[8], m_output_fifo[9], m_output_fifo[10], m_output_fifo[11]);
+
+ //m_sten_timer->adjust(attotime::from_usec(64 * 4)); // TODO
+ m_sten_timer->adjust(attotime::zero);
+ }
+}
+
+void cr560b_device::audio_end_cb(int state)
+{
+ if (!state)
+ return;
+
+ LOGMASKED(LOG_CMD, "Playing audio finished\n", state);
+
+ status_change(m_status & ~STATUS_PLAYING);
+}
+
+uint8_t cr560b_device::read()
+{
+ uint8_t data = 0xff;
+
+ if (!m_enabled)
+ {
+ LOG("Read while not enabled!\n");
+ return data;
+ }
+
+ if (m_cmd)
+ {
+ // command mode
+ if (m_status_ready)
+ {
+ data = m_output_fifo[m_output_fifo_pos];
+
+ // clear old data once read
+ m_output_fifo[m_output_fifo_pos++] = 0x00;
+
+ LOGMASKED(LOG_DATA, "Data from drive: %02x (%d of %d)\n", data, m_output_fifo_pos, m_output_fifo_length);
+
+ // more data?
+ if (m_output_fifo_pos < m_output_fifo_length)
+ {
+ m_sten_cb(0);
+ m_sten_cb(1);
+ }
+ else
+ {
+ m_status_ready = false;
+ }
+ }
+ }
+ else
+ {
+ // data mode
+ if (m_data_ready)
+ {
+ data = m_transfer_buffer[m_transfer_buffer_pos];
+ m_transfer_length--;
+
+ LOGMASKED(LOG_DATA, "Data = %02x, pos %d, length %d\n", data, m_transfer_buffer_pos, m_transfer_length);
+
+ // finished transferring this sector?
+ if (++m_transfer_buffer_pos == m_sector_size)
+ {
+ m_data_ready = false;
+ m_drq_cb(0);
+
+ if (m_transfer_sectors == 0)
+ {
+ LOGMASKED(LOG_DATA, "Read done\n");
+ status_change(m_status | STATUS_SUCCESS);
+ }
+ }
+ }
+ }
+
+ return data;
+}
+
+void cr560b_device::write(uint8_t data)
+{
+ // verify that we're enabled and are in command mode
+ if (!m_enabled || !m_cmd)
+ {
+ LOG("Invalid write: %02x (enabled: %d, cmd: %d)\n", data, m_enabled, m_cmd);
+ return;
+ }
+
+ m_input_fifo[m_input_fifo_pos++] = data;
+
+ // all commands except for abort takes 7 input bytes
+ if (m_input_fifo_pos == 1 && m_input_fifo[0] == 0x08)
+ {
+ LOG("Abort command %08x (tbd)\n", m_input_fifo[0]);
+ //cmd_abort();
+ status_enable(0);
+ return;
+ }
+
+ if (m_input_fifo_pos != 7)
+ return;
+
+ switch (m_input_fifo[0])
+ {
+ case 0x01: cmd_seek(); break;
+ case 0x02: cmd_motor_on(); break;
+ case 0x03: cmd_motor_off(); break;
+ //case 0x04: cmd_diag(); break;
+ case 0x05: cmd_read_status(); break;
+ //case 0x06: cmd_drawer_open(); break;
+ //case 0x07: cmd_drawer_close(); break;
+ //case 0x09: cmd_set_mode(); break;
+ //case 0x0a: cmd_reset(); break;
+ //case 0x0b: cmd_flush(); break;
+
+ // these two are unconfirmed
+ //case 0x0c: cmd_lock(); break;
+ //case 0x0d: cmd_pause_resume(); break;
+
+ case 0x0e: cmd_play_msf(); break;
+ case 0x0f: cmd_play_track(); break;
+ case 0x10: cmd_read(); break;
+ //case 0x11: cmd_read_subq(); break;
+
+ case 0x80: cmd_data_path_check(); break;
+ //case 0x81: cmd_read_status(); break;
+ case 0x82: cmd_read_error(); break;
+ case 0x83: cmd_version(); break;
+ //case 0x84: cmd_mode_sense(); break;
+ //case 0x85: cmd_read_capacity(); break;
+ //case 0x86: cmd_read_header(); break;
+ //case 0x87: cmd_read_subq(); break;
+ //case 0x88: cmd_read_upc(); break;
+ //case 0x89: cmd_read_isrc(); break;
+ //case 0x8a: cmd_read_disc_code(); break;
+ //case 0x8b: cmd_read_disc_info(); break;
+ //case 0x8c: cmd_read_toc(); break;
+ //case 0x8d: cmd_read_session_info(); break;
+ //case 0x8e: cmd_read_device_driver(); break;
+
+ default:
+ LOG("Unknown command: %02x\n", m_input_fifo[0]);
+ status_enable(0);
+ break;
+ }
+}
+
+void cr560b_device::cmd_w(int state)
+{
+ m_cmd = !bool(state); // active low
+}
+
+void cr560b_device::enable_w(int state)
+{
+ m_enabled = !bool(state); // active low
+}
+
+// TODO: unverified
+void cr560b_device::cmd_seek()
+{
+ LOGMASKED(LOG_CMD, "Command: Seek\n");
+ LOGPARAM;
+
+ // TODO: Does this enable STATUS_SUCCESS?
+ u8 status = m_status;
+ status |= STATUS_MOTOR;
+ m_output_fifo[0] = status;
+
+ status_change(status);
+ status_enable(1);
+}
+
+// TODO: unverified
+// labeled as "No Operation" in 3do Technical Manual
+void cr560b_device::cmd_read_status()
+{
+ LOGMASKED(LOG_CMD, "Command: Read Status\n");
+
+ u8 status = m_status;
+ status &= ~STATUS_SUCCESS;
+ m_output_fifo[0] = status;
+
+ status_change(status);
+ status_enable(1);
+}
+
+// TODO: unverified
+// Spinup
+void cr560b_device::cmd_motor_on()
+{
+ LOGMASKED(LOG_CMD, "Command: Motor On\n");
+ LOGPARAM;
+
+ // TODO: Does this enable STATUS_SUCCESS?
+ u8 status = m_status;
+ status |= STATUS_SUCCESS;
+ m_output_fifo[0] = status;
+
+ status_change(status);
+ status_enable(1);
+}
+
+// TODO: unverifed
+// Spindown
+void cr560b_device::cmd_motor_off()
+{
+ LOGMASKED(LOG_CMD, "Command: Motor Off\n");
+ LOGPARAM;
+
+ // TODO: Does this enable STATUS_SUCCESS?
+ u8 status = m_status;
+ status &= ~STATUS_MOTOR;
+ m_output_fifo[0] = status;
+
+ status_change(status);
+ status_enable(1);
+}
+
+
+// TODO: unverified
+void cr560b_device::cmd_play_msf()
+{
+ LOGMASKED(LOG_CMD, "Command: Play MSF\n");
+ LOGPARAM;
+
+ uint8_t status = m_status;
+
+ uint32_t start = (m_input_fifo[1] << 16) | (m_input_fifo[2] << 8) | (m_input_fifo[3] << 0);
+ uint32_t end = (m_input_fifo[4] << 16) | (m_input_fifo[5] << 8) | (m_input_fifo[6] << 0);
+
+ int32_t start_lba = msf_to_lba(start);
+ int32_t end_lba = msf_to_lba(end);
+
+ // play to the end of the disc?
+ if (end == 0xffffff)
+ end_lba = get_track_start(0xaa) - 1;
+
+ if (start == 0 && end == 0)
+ {
+ LOGMASKED(LOG_CMD, "Stop audio\n");
+
+
+ if (m_cdda->audio_active())
+ status |= STATUS_SUCCESS;
+
+ m_cdda->stop_audio();
+
+ status &= ~STATUS_PLAYING;
+ status &= ~STATUS_MOTOR;
+
+ status_change(status);
+ }
+ else if (start_lba < end_lba)
+ {
+ LOGMASKED(LOG_CMD, "Playing audio %02d:%02d.%02d to %02d:%02d.%02d (LBA %d to %d)\n",
+ m_input_fifo[1], m_input_fifo[2], m_input_fifo[3],
+ m_input_fifo[4], m_input_fifo[5], m_input_fifo[6], start_lba, end_lba);
+
+ m_cdda->start_audio(start_lba, end_lba - start_lba);
+
+ status |= STATUS_PLAYING;
+ status |= STATUS_MOTOR;
+
+ status_change(status);
+ }
+ else
+ {
+ LOGMASKED(LOG_CMD, "Invalid range %d to %d!\n", start_lba, end_lba);
+
+ status |= STATUS_ERROR;
+ status_change(status);
+ }
+
+ m_output_fifo[0] = status;
+ status_enable(1);
+}
+
+// TODO: unverified
+void cr560b_device::cmd_play_track()
+{
+ LOGMASKED(LOG_CMD, "Command: Play Track\n");
+ LOGPARAM;
+
+ uint8_t start_track = m_input_fifo[1];
+ uint8_t start_index = m_input_fifo[2]; // TODO
+ uint8_t end_track = m_input_fifo[3];
+ uint8_t end_index = m_input_fifo[4]; // TODO
+
+ uint32_t start_lba = get_track_start(start_track - 1);
+ uint32_t end_lba = get_track_start(end_track - 1) - 1;
+
+ LOGMASKED(LOG_CMD, "Playing audio track %d-%d to %d-%d (LBA %d to %d)\n", start_track, start_index, end_track, end_index, start_lba, end_lba);
+
+ m_cdda->start_audio(start_lba, end_lba - start_lba);
+
+ u8 status = m_status;
+ status |= STATUS_PLAYING;
+ status |= STATUS_MOTOR;
+
+ m_output_fifo[0] = status;
+
+ status_change(status);
+ status_enable(1);
+}
+
+// TODO: unverified
+void cr560b_device::cmd_read()
+{
+ LOGMASKED(LOG_CMD, "Command: Read\n");
+ LOGPARAM;
+
+ u8 read_mode = m_input_fifo[4];
+
+ switch(read_mode)
+ {
+ case 0x00:
+ LOG("Warning: Unsupported MSF mode\n");
+ break;
+ case 0x01:
+ // compared to CR-511 this is shuffled around to accomodate the transfer mode
+ m_transfer_lba = (m_input_fifo[1] << 16) | (m_input_fifo[2] << 8) | (m_input_fifo[3] << 0);
+ m_transfer_sectors = (m_input_fifo[5] << 8) | (m_input_fifo[6] << 0);
+ m_transfer_length = m_transfer_sectors * m_sector_size;
+
+ LOGMASKED(LOG_CMD, "-> LBA %d, sectors %d\n", m_transfer_lba, m_transfer_sectors);
+ break;
+ default:
+ throw emu_fatalerror("Unknown read mode %02x", read_mode);
+ }
+
+
+ m_cdda->stop_audio();
+
+ uint8_t status = m_status;
+
+ status &= ~STATUS_PLAYING;
+ status |= STATUS_MOTOR;
+
+ status_change(status);
+ status_enable(1);
+}
+
+// checked in BIOS if a CD is inserted
+void cr560b_device::cmd_data_path_check()
+{
+ LOGMASKED(LOG_CMD, "Command: Data path check\n");
+ LOGPARAM;
+
+ m_output_fifo[0] = 0x80;
+ m_output_fifo[1] = 0xaa;
+ m_output_fifo[2] = 0x55;
+ m_output_fifo[3] = m_status;
+
+ status_enable(4);
+}
+
+// TODO: most unknowns, just checked by BIOS at startup
+void cr560b_device::cmd_read_error()
+{
+ LOGMASKED(LOG_CMD, "Command: Read error\n");
+ LOGPARAM;
+
+ uint8_t status = m_status;
+ status |= STATUS_READY;
+
+ m_output_fifo[0] = 0x82;
+ m_output_fifo[1] = 0x00;
+ m_output_fifo[2] = 0x00;
+ m_output_fifo[3] = 0x00;
+ m_output_fifo[4] = 0x00;
+ m_output_fifo[5] = 0x00;
+ m_output_fifo[6] = 0x00;
+ m_output_fifo[7] = 0x00;
+ m_output_fifo[8] = 0x00;
+ m_output_fifo[9] = exists() ? 1 : 0;
+
+ status_change(status);
+ status_enable(10);
+}
+
+void cr560b_device::cmd_version()
+{
+ LOGMASKED(LOG_CMD, "Command: Version\n");
+ LOGPARAM;
+
+ m_output_fifo[0] = 0x83;
+ m_output_fifo[1] = 0x00; // manufacturer ID
+ m_output_fifo[2] = 0x10; // ^
+ m_output_fifo[3] = 0x00; // manufacturer number
+ m_output_fifo[4] = 0x01; // ^
+ m_output_fifo[5] = 0x00;
+ m_output_fifo[6] = 0x00;
+ m_output_fifo[7] = 0x00; // revision number
+ m_output_fifo[8] = 0x00; // ^
+ m_output_fifo[9] = 0x00; // flag
+ m_output_fifo[10] = 0x00; // ^?
+ m_output_fifo[11] = m_status;
+
+// status_change(status);
+ status_enable(12);
+}
+
diff --git a/src/devices/machine/cr560b.h b/src/devices/machine/cr560b.h
new file mode 100644
index 00000000000..0fb9ef7426a
--- /dev/null
+++ b/src/devices/machine/cr560b.h
@@ -0,0 +1,146 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_MACHINE_CR560B_H
+#define MAME_MACHINE_CR560B_H
+
+#pragma once
+
+#include "imagedev/cdromimg.h"
+#include "sound/cdda.h"
+
+
+class cr560b_device : public cdrom_image_device, public device_mixer_interface
+{
+public:
+ cr560b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // callbacks
+ auto stch_cb() { return m_stch_cb.bind(); }
+ auto sten_cb() { return m_sten_cb.bind(); }
+ auto drq_cb() { return m_drq_cb.bind(); }
+ auto dten_cb() { return m_dten_cb.bind(); }
+ auto scor_cb() { return m_scor_cb.bind(); }
+
+ uint8_t read();
+ void write(uint8_t data);
+
+ void cmd_w(int state);
+ void enable_w(int state);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
+
+private:
+ uint32_t lba_to_msf(int32_t lba);
+ int32_t msf_to_lba(uint32_t msf);
+ int size_to_track_type();
+
+ TIMER_CALLBACK_MEMBER(frame_cb);
+
+ TIMER_CALLBACK_MEMBER(stch);
+ void status_change(uint8_t status);
+
+ TIMER_CALLBACK_MEMBER(sten);
+ void status_enable(uint8_t output_length);
+
+ void audio_end_cb(int state);
+
+ // commands
+ void cmd_seek();
+ void cmd_motor_on();
+ void cmd_motor_off();
+// void cmd_diag();
+ void cmd_read_status();
+ //void cmd_drawer_open();
+ //void cmd_drawer_close();
+ //void cmd_set_mode();
+ //void cmd_reset();
+ //void cmd_flush();
+ //void cmd_lock();
+ //void cmd_pause_resume();
+ void cmd_play_msf();
+ void cmd_play_track();
+ void cmd_read();
+ //void cmd_read_subq();
+
+ void cmd_data_path_check();
+ //void cmd_read_status();
+ void cmd_read_error();
+ void cmd_version();
+ //void cmd_mode_sense();
+ //void cmd_read_capacity();
+ //void cmd_read_header();
+ //void cmd_read_subq();
+ //void cmd_read_upc();
+ //void cmd_read_isrc();
+ //void cmd_read_disc_code();
+ //void cmd_read_disc_info();
+ //void cmd_read_toc();
+ //void cmd_read_session_info();
+ //void cmd_read_device_driver();
+
+ // drive status
+ static constexpr uint8_t STATUS_DOOR_CLOSED = 0x80; // unverified, not used
+ static constexpr uint8_t STATUS_MEDIA = 0x40;
+ static constexpr uint8_t STATUS_MOTOR = 0x20;
+ static constexpr uint8_t STATUS_ERROR = 0x10;
+ static constexpr uint8_t STATUS_SUCCESS = 0x08; // last command has successfully executed
+ static constexpr uint8_t STATUS_PLAYING = 0x04;
+ static constexpr uint8_t STATUS_DOOR_LOCKED = 0x02; // unverified, not used
+ static constexpr uint8_t STATUS_READY = 0x01;
+
+ // audio status
+ static constexpr uint8_t AUDIO_STATUS_INVALID = 0x00;
+ static constexpr uint8_t AUDIO_STATUS_PLAY = 0x11;
+ static constexpr uint8_t AUDIO_STATUS_PAUSED = 0x12;
+ static constexpr uint8_t AUDIO_STATUS_COMPLETED = 0x13;
+ static constexpr uint8_t AUDIO_STATUS_ERROR = 0x14;
+ static constexpr uint8_t AUDIO_STATUS_NO_STATUS = 0x15;
+
+ required_device<cdda_device> m_cdda;
+
+ devcb_write_line m_stch_cb;
+ devcb_write_line m_sten_cb;
+ devcb_write_line m_drq_cb;
+ devcb_write_line m_dten_cb;
+ devcb_write_line m_scor_cb;
+
+ emu_timer *m_frame_timer;
+ emu_timer *m_stch_timer;
+ emu_timer *m_sten_timer;
+
+ uint8_t m_input_fifo[16];
+ uint8_t m_input_fifo_pos;
+
+ uint8_t m_output_fifo[16];
+ uint8_t m_output_fifo_pos;
+ uint8_t m_output_fifo_length;
+
+ uint8_t m_status;
+ uint16_t m_sector_size;
+
+ uint32_t m_transfer_lba;
+ uint16_t m_transfer_sectors;
+ uint32_t m_transfer_length;
+ uint8_t m_transfer_buffer[2352];
+ uint16_t m_transfer_buffer_pos;
+
+ // external lines
+ bool m_enabled;
+ bool m_cmd;
+
+ bool m_status_ready;
+ bool m_data_ready;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(CR560B, cr560b_device)
+
+#endif // MAME_MACHINE_CR560B_H
diff --git a/src/mame/misc/3do.cpp b/src/mame/misc/3do.cpp
index 979f98d22d9..dd61a0182dd 100644
--- a/src/mame/misc/3do.cpp
+++ b/src/mame/misc/3do.cpp
@@ -76,6 +76,8 @@ Models:
- Goldstar 3DO ALIVE II (South Korea)
- Sanyo TRY 3DO Interactive Multiplayer (Japan)
- Creative 3DO Blaster - PC Card (ISA)
+- Panasonic Robo 3DO (Japan), based on FZ-1 with 5x CD media changer and VCD adapter built-in
+- a Scientific Atlanta STT, with a Nicky device in BIGTRACE space
===========================================================================
@@ -105,6 +107,8 @@ Part list of Goldstar 3DO Interactive Multiplayer
#include "cpu/arm7/arm7.h"
#include "imagedev/cdromimg.h"
+#include "speaker.h"
+
#define DIAG_ENABLE 0
@@ -166,18 +170,12 @@ void _3do_state::machine_reset()
m_bank1->set_entry(1);
}
-void _3do_state::_3do(machine_config &config)
+// TODO: clocks (doubled vs. ARM?)
+void _3do_state::green_config(machine_config &config)
{
- /* Basic machine hardware */
- ARM7_BE(config, m_maincpu, XTAL(50'000'000)/4); // DA86C06020XV
- m_maincpu->set_addrmap(AS_PROGRAM, &_3do_state::main_mem);
-
- NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
-
MADAM(config, m_madam, XTAL(50'000'000)/4);
m_madam->diag_cb().set([] (u8 data) {
- // TODO: how this really connects?
- // is it expecting a Mac terminal on the other end, where the baud is set there?
+ // Logic Analyser (sic) ping, supposedly repeated in ZSIO debug port
if (DIAG_ENABLE)
{
if(data == 0x0a)
@@ -193,15 +191,56 @@ void _3do_state::_3do(machine_config &config)
m_maincpu->pulse_input_line(arm7_cpu_device::ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time());
});
m_clio->set_screen_tag("screen");
+ m_clio->xbus_read_cb().set([this] (offs_t offset) -> u8 {
+ if (offset == 0)
+ {
+ return m_cdrom->read();
+ }
+
+ return 0;
+ });
+ m_clio->xbus_write_cb().set([this] (offs_t offset, u8 data) {
+ if (offset == 0)
+ {
+ m_cdrom->enable_w(0);
+ m_cdrom->cmd_w(0);
+ m_cdrom->write(data);
+ return;
+ }
+ m_cdrom->enable_w(1);
+ m_cdrom->cmd_w(1);
+ });
+
+ CR560B(config, m_cdrom, 0);
+ m_cdrom->add_route(0, "speaker", 1.0, 0);
+ m_cdrom->add_route(1, "speaker", 1.0, 1);
+ m_cdrom->set_interface("cdrom");
+// m_cdrom->scor_cb().set(m_clio, FUNC(clio_device::xbus...)).invert();
+// m_cdrom->stch_cb().set(m_clio, FUNC(clio_device::xbus...)).invert();
+// m_cdrom->sten_cb().set(m_clio, FUNC(clio_device::xbus...));
+ m_cdrom->sten_cb().set(m_clio, FUNC(clio_device::xbus_rdy_w)).invert();
+// m_cdrom->drq_cb().set(m_clio, FUNC(clio_device::xbus...));
+}
+
+void _3do_state::_3do(machine_config &config)
+{
+ /* Basic machine hardware */
+ ARM7_BE(config, m_maincpu, XTAL(50'000'000)/4); // DA86C06020XV
+ m_maincpu->set_addrmap(AS_PROGRAM, &_3do_state::main_mem);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
+
+ green_config(config);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ // TODO: proper params (mostly running in interlace mode)
m_screen->set_raw(X2_CLOCK_NTSC / 2, 1592, 254, 1534, 263, 22, 262);
m_screen->set_screen_update(FUNC(_3do_state::screen_update));
+ m_screen->screen_vblank().set(m_clio, FUNC(clio_device::vint1_w));
- CDROM(config, "cdrom");
+ SPEAKER(config, "speaker", 2).front();
}
-
void _3do_state::_3do_pal(machine_config &config)
{
/* Basic machine hardware */
@@ -210,29 +249,21 @@ void _3do_state::_3do_pal(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
- MADAM(config, m_madam, XTAL(50'000'000)/4);
- m_madam->diag_cb().set([] (u8 data) {
- if (DIAG_ENABLE)
- {
- if(data == 0x0a)
- printf("\n");
- else
- printf("%c",data & 0xff);
- }
- });
-
- CLIO(config, m_clio, XTAL(50'000'000)/4);
- m_clio->firq_cb().set([this] (int state) {
- if (state)
- m_maincpu->pulse_input_line(arm7_cpu_device::ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time());
- });
- m_clio->set_screen_tag("screen");
+ green_config(config);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_raw(X2_CLOCK_PAL / 2, 1592, 254, 1534, 263, 22, 262); // TODO: proper params
+ // TODO: proper params
+ m_screen->set_raw(X2_CLOCK_PAL / 2, 1592, 254, 1534, 263, 22, 262);
m_screen->set_screen_update(FUNC(_3do_state::screen_update));
+ m_screen->screen_vblank().set(m_clio, FUNC(clio_device::vint1_w));
- CDROM(config, "cdrom");
+ SPEAKER(config, "speaker", 2).front();
+}
+
+void _3do_state::arcade_ntsc(machine_config &config)
+{
+ _3do(config);
+ m_cdrom->add_region("cdimage");
}
// TODO: split into separate CONS drivers
@@ -289,7 +320,7 @@ ROM_END
ROM_START(orbatak)
NTSC_BIOS
- DISK_REGION( "cdrom" )
+ DISK_REGION( "cdimage" )
DISK_IMAGE_READONLY( "orbatak", 0, SHA1(25cb3b889cf09dbe5faf2b0ca4aae5e03453da00) )
ROM_END
@@ -309,14 +340,14 @@ ROM_END
ROM_START(md23do)
ALG_BIOS
- DISK_REGION( "cdrom" )
+ DISK_REGION( "cdimage" )
DISK_IMAGE_READONLY( "mad dog ii", 0, SHA1(0117c1fd279f42e942648ca55fa75dd45da37a4f) )
ROM_END
ROM_START(sht3do)
ALG_BIOS
- DISK_REGION( "cdrom" )
+ DISK_REGION( "cdimage" )
DISK_IMAGE_READONLY( "shootout at old tucson", 0, SHA1(bd42213c6b460b5b6153a8b2b41d0a114171e86e) )
ROM_END
@@ -334,15 +365,15 @@ CONS( 1993, 3do_pal, 3do, 0, _3do_pal, 3do, _3do_state, empty_init,
/* YEAR NAME PARENT MACHINE INPUT STATE INIT MONITOR COMPANY FULLNAME FLAGS */
// Misc 3do Arcade games
-GAME( 1993, 3dobios, 0, _3do, 3do, _3do_state, empty_init, ROT0, "The 3DO Company", "3DO BIOS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IS_BIOS_ROOT )
+GAME( 1993, 3dobios, 0, arcade_ntsc, 3do, _3do_state, empty_init, ROT0, "The 3DO Company", "3DO BIOS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IS_BIOS_ROOT )
-GAME( 1995, orbatak, 3dobios, _3do, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Orbatak (prototype)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
-// Beavis and Butthead (prototype)
+GAME( 1995, orbatak, 3dobios, arcade_ntsc, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Orbatak (prototype)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
+// Beavis and Butthead (prototype), different CD drive, Jaguar CD derived?
-// American Laser Games uses its own BIOS (with additional protection according to serial output?)
-GAME( 1993, alg3do, 0, _3do, 3do, _3do_state, empty_init, ROT0, "American Laser Games / The 3DO Company", "ALG 3DO BIOS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_IS_BIOS_ROOT )
+// American Laser Games uses its own BIOS (with additional "FKr-Severe-System-extended-RSA failed in CreateTask")
+GAME( 1993, alg3do, 0, arcade_ntsc, 3do, _3do_state, empty_init, ROT0, "American Laser Games / The 3DO Company", "ALG 3DO BIOS", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND | MACHINE_IS_BIOS_ROOT )
-GAME( 199?, md23do, alg3do, _3do, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Mad Dog II: The Lost Gold (3DO hardware)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
-GAME( 1994, sht3do, alg3do, _3do, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Shootout at Old Tucson (3DO hardware)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
+GAME( 199?, md23do, alg3do, arcade_ntsc, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Mad Dog II: The Lost Gold (3DO hardware)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND )
+GAME( 1994, sht3do, alg3do, arcade_ntsc, 3do, _3do_state, empty_init, ROT0, "American Laser Games", "Shootout at Old Tucson (3DO hardware)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND )
diff --git a/src/mame/misc/3do.h b/src/mame/misc/3do.h
index a11638093bd..574a36180bc 100644
--- a/src/mame/misc/3do.h
+++ b/src/mame/misc/3do.h
@@ -9,6 +9,7 @@
#ifndef MAME_MISC_3DO_H
#define MAME_MISC_3DO_H
+#include "machine/cr560b.h"
#include "machine/nvram.h"
#include "machine/timer.h"
#include "screen.h"
@@ -27,17 +28,21 @@ public:
m_nvram(*this, "nvram"),
m_madam(*this, "madam"),
m_clio(*this, "clio"),
+ m_cdrom(*this, "cdrom"),
m_screen(*this, "screen"),
m_bank1(*this, "bank1") { }
void _3do(machine_config &config);
void _3do_pal(machine_config &config);
+ void arcade_ntsc(machine_config &config);
protected:
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
virtual void video_start() override ATTR_COLD;
+ void green_config(machine_config &config);
+
private:
struct SLOW2 {
/* 03180000 - 0318003f - configuration group */
@@ -68,6 +73,7 @@ private:
required_device<nvram_device> m_nvram;
required_device<madam_device> m_madam;
required_device<clio_device> m_clio;
+ required_device<cr560b_device> m_cdrom;
required_device<screen_device> m_screen;
required_memory_bank m_bank1;
diff --git a/src/mame/misc/3do_clio.cpp b/src/mame/misc/3do_clio.cpp
index 55a522403f0..e7ed70fe14a 100644
--- a/src/mame/misc/3do_clio.cpp
+++ b/src/mame/misc/3do_clio.cpp
@@ -4,12 +4,12 @@
#include "emu.h"
#include "3do_clio.h"
-#define LOG_IRQ (1U << 1)
+#define LOG_IRQ (1U << 1) // enable bits (verbose)
#define LOG_TIMER (1U << 2)
#define LOG_XBUS (1U << 3)
#define LOG_DSPP (1U << 4)
-#define VERBOSE (LOG_GENERAL | LOG_IRQ | LOG_XBUS | LOG_DSPP)
+#define VERBOSE (LOG_GENERAL | LOG_XBUS | LOG_DSPP)
//#define LOG_OUTPUT_FUNC osd_printf_warning
#include "logmacro.h"
@@ -27,6 +27,8 @@ clio_device::clio_device(const machine_config &mconfig, const char *tag, device_
, m_screen(*this, finder_base::DUMMY_TAG)
, m_dspp(*this, "dspp")
, m_firq_cb(*this)
+ , m_xbus_read_cb(*this, 0xff)
+ , m_xbus_write_cb(*this)
{
}
@@ -43,15 +45,43 @@ void clio_device::device_add_mconfig(machine_config &config)
void clio_device::device_start()
{
- // Clio Preen (Toshiba/MEC)
- // 0x04000000 for Anvil
- m_revision = 0x02022000 /* 0x04000000 */;
+ // Clio Green (Toshiba/MEC)
+ m_revision = 0x02020000;
+ // Clio Preen
+// m_revision = 0x02022000;
+ // Anvil
+// m_revision = 0x04000000;
m_expctl = 0x80; /* ARM has the expansion bus */
+
+ save_item(NAME(m_irq0_enable));
+ save_item(NAME(m_irq1_enable));
}
void clio_device::device_reset()
{
m_cstatbits = 0x01; /* bit 0 = reset of clio caused by power on */
+
+ m_irq0_enable = m_irq1_enable = 0;
+}
+
+void clio_device::vint1_w(int state)
+{
+ // currently used by the BIOS to set periodic stuff up (namely watchdog)
+ if (state && m_screen->frame_number() & 1)
+ {
+ request_fiq(1 << 1, 0);
+ }
+}
+
+void clio_device::xbus_rdy_w(int state)
+{
+ //if ((m_sel & 0x0f) == 0)
+ //{
+ // if (state)
+ // m_poll |= 0x10;
+ // else
+ // m_poll &= ~0x10;
+ //}
}
// $0340'0000 base
@@ -101,9 +131,10 @@ void clio_device::map(address_map &map)
})
);
map(0x002c, 0x002f).lw32(
- // during boot 0000000B is written here, counter reload related?
+ // during boot and vblanks 0000000B is written here, counter reload related?
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
- LOG("watchdog: %08x & %08x\n", data, mem_mask);
+ if (data != 0xb)
+ LOG("watchdog: %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_wdog);
})
);
@@ -133,7 +164,8 @@ void clio_device::map(address_map &map)
map(0x0038, 0x003b).lrw32(
NAME([this] () { return m_seed; }),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
- LOG("seed: %08x & %08x\n", data, mem_mask);
+ if (data != 0xc693b70f)
+ LOG("seed: %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_seed);
m_seed &= 0x0fff0fff;
})
@@ -226,7 +258,8 @@ void clio_device::map(address_map &map)
map(0x0084, 0x0087).lrw32(
NAME([this] () { return m_adbio; }),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
- LOG("adbio %08x & %08x\n", data, mem_mask);
+ if (data != 0x62)
+ LOG("adbio %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_adbio);
m_adbio &= 0xff;
})
@@ -359,7 +392,12 @@ void clio_device::map(address_map &map)
})
);
map(0x0540, 0x057f).lrw32(
- NAME([this] () { return m_poll; }),
+ NAME([this] () {
+ // HACK: until I understand semantics
+ if (m_sel == 0)
+ return (m_poll & 0xef) | (machine().rand() & 0x10);
+ return m_poll;
+ }),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
LOGXBUS("xbus poll: %02x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_poll);
@@ -367,10 +405,13 @@ void clio_device::map(address_map &map)
m_poll |= data & 7;
})
);
-// map(0x0580, 0x05bf) (w) CD Command/(r) CD status return
+ map(0x0580, 0x05bf).lrw32(
+ NAME([this] () { return m_xbus_read_cb(m_sel & 0xf); }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) { m_xbus_write_cb(m_sel & 0xf, data & 0xff); })
+ );
// map(0x05c0, 0x05ff) Data
- // TODO: for debug, to be removed once that we hookup the CPU core
+ // TODO: should really map these directly in DSPP core
// map(0x17d0, 0x17d3) Semaphore
// map(0x17d4, 0x17d7) Semaphore ACK
// map(0x17e0, 0x17ff) DSPP DMA and state
diff --git a/src/mame/misc/3do_clio.h b/src/mame/misc/3do_clio.h
index b928eb452ca..8fe0aca3fe2 100644
--- a/src/mame/misc/3do_clio.h
+++ b/src/mame/misc/3do_clio.h
@@ -21,6 +21,12 @@ public:
template <typename T> void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward<T>(tag)); }
auto firq_cb() { return m_firq_cb.bind(); }
+ auto xbus_read_cb() { return m_xbus_read_cb.bind(); }
+ auto xbus_write_cb() { return m_xbus_write_cb.bind(); }
+
+ void xbus_rdy_w(int state);
+
+ void vint1_w(int state);
protected:
// device-level overrides
@@ -32,6 +38,8 @@ private:
required_device<screen_device> m_screen;
required_device<dspp_device> m_dspp;
devcb_write_line m_firq_cb;
+ devcb_read8 m_xbus_read_cb;
+ devcb_write8 m_xbus_write_cb;
uint32_t m_revision = 0; /* 03400000 */
uint32_t m_csysbits = 0; /* 03400004 */
diff --git a/src/mame/misc/3do_madam.cpp b/src/mame/misc/3do_madam.cpp
index 6e733c01b0e..daf3445bcde 100644
--- a/src/mame/misc/3do_madam.cpp
+++ b/src/mame/misc/3do_madam.cpp
@@ -76,7 +76,8 @@ void madam_device::map(address_map &map)
map(0x0008, 0x000b).lrw32(
NAME([this] () { return m_mctl; }),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
- LOG("mctl: %08x & %08x\n", data, mem_mask);
+ if (data != 0x0001e000)
+ LOG("mctl: %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_mctl);
})
);