diff options
| author | 2026-01-15 16:38:35 +0100 | |
|---|---|---|
| committer | 2026-01-15 16:38:43 +0100 | |
| commit | 22664673d449f1bea33c6d60015b276e6e2118bd (patch) | |
| tree | 4491783b1c90627839855035244c5ed7b28b669e | |
| parent | b8b6c5967e1e769c394916f0c9a4383a4eedf9a9 (diff) | |
misc/3do_clio.cpp: initial hookup of a CR-560-B CDROM drive
| -rw-r--r-- | scripts/src/machine.lua | 13 | ||||
| -rw-r--r-- | src/devices/machine/cr560b.cpp | 653 | ||||
| -rw-r--r-- | src/devices/machine/cr560b.h | 146 | ||||
| -rw-r--r-- | src/mame/misc/3do.cpp | 111 | ||||
| -rw-r--r-- | src/mame/misc/3do.h | 6 | ||||
| -rw-r--r-- | src/mame/misc/3do_clio.cpp | 65 | ||||
| -rw-r--r-- | src/mame/misc/3do_clio.h | 8 | ||||
| -rw-r--r-- | src/mame/misc/3do_madam.cpp | 3 |
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); }) ); |
