mirror of
https://github.com/holub/mame
synced 2025-06-06 12:53:46 +03:00
amiga: CDTV CD-ROM support
- CDTV can boot from CD and play audio discs - Alternatively use the A570 expansion for the A500
This commit is contained in:
parent
32a2633ba7
commit
48b7920613
@ -12,14 +12,17 @@
|
||||
- ROM label for the A690: "391298-01 V1.0 Copyright ©1991 CBM C480"
|
||||
- The ROM P/N 391298-01 seems to have been used for multiple versions
|
||||
- There are expansion slots for a 2 MB RAM expansion and a SCSI module
|
||||
- Uses the CR-512-B drive from MKE (Matsushita Kotobuki Electronics)
|
||||
- An FPGA is used in place of many discrete logic chips of the CDTV
|
||||
|
||||
TODO:
|
||||
- DMAC/CD-ROM drive hookup (needs DMAC rev 2)
|
||||
- Volume control (LC7883M)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "a570.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define VERBOSE (LOG_GENERAL)
|
||||
|
||||
@ -37,7 +40,10 @@ namespace bus::amiga::cpuslot {
|
||||
a570_device::a570_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, AMIGA_CPUSLOT_A570, tag, owner, clock),
|
||||
device_amiga_cpuslot_interface(mconfig, *this),
|
||||
m_irq(*this, "irq"),
|
||||
m_dmac(*this, "dmac"),
|
||||
m_tpi(*this, "tpi"),
|
||||
m_drive(*this, "drive"),
|
||||
m_config(*this, "config")
|
||||
{
|
||||
}
|
||||
@ -94,12 +100,39 @@ const tiny_rom_entry *a570_device::device_rom_region() const
|
||||
|
||||
void a570_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
INPUT_MERGER_ANY_HIGH(config, m_irq);
|
||||
m_irq->output_handler().set([this] (int state) { m_host->int2_w(state); });
|
||||
|
||||
AMIGA_DMAC_REV2(config, m_dmac, 28.37516_MHz_XTAL / 4); // 7M
|
||||
m_dmac->cfgout_cb().set([this] (int state) { m_host->cfgout_w(state); });
|
||||
m_dmac->int_cb().set([this] (int state) { m_host->int2_w(state); });
|
||||
m_dmac->int_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<0>));
|
||||
m_dmac->csx0_read_cb().set(m_drive, FUNC(cr511b_device::read));
|
||||
m_dmac->csx0_write_cb().set(m_drive, FUNC(cr511b_device::write));
|
||||
m_dmac->csx0_a4_read_cb().set(m_tpi, FUNC(tpi6525_device::read));
|
||||
m_dmac->csx0_a4_write_cb().set(m_tpi, FUNC(tpi6525_device::write));
|
||||
m_dmac->xdack_read_cb().set(m_drive, FUNC(cr511b_device::read));
|
||||
|
||||
AT28C16(config, "nvram0", 0);
|
||||
AT28C16(config, "nvram1", 0);
|
||||
|
||||
TPI6525(config, m_tpi, 0);
|
||||
m_tpi->out_irq_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<1>));
|
||||
m_tpi->out_pb_cb().set(FUNC(a570_device::tpi_portb_w));
|
||||
|
||||
CR511B(config, m_drive, 0);
|
||||
m_drive->add_route(0, "lspeaker", 1.0);
|
||||
m_drive->add_route(1, "rspeaker", 1.0);
|
||||
m_drive->scor_cb().set(m_tpi, FUNC(tpi6525_device::i1_w)).invert();
|
||||
m_drive->stch_cb().set(m_tpi, FUNC(tpi6525_device::i2_w)).invert();
|
||||
m_drive->sten_cb().set(m_tpi, FUNC(tpi6525_device::i3_w));
|
||||
m_drive->sten_cb().append(FUNC(a570_device::sten_w));
|
||||
m_drive->drq_cb().set(m_tpi, FUNC(tpi6525_device::i4_w));
|
||||
m_drive->drq_cb().append(FUNC(a570_device::drq_w));
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
|
||||
// TODO: Add stereo input for Amiga sound
|
||||
}
|
||||
|
||||
|
||||
@ -118,6 +151,33 @@ void a570_device::device_start()
|
||||
|
||||
// register for save states
|
||||
save_pointer(NAME(m_ram), 0x200000/2);
|
||||
save_item(NAME(m_sten));
|
||||
}
|
||||
|
||||
void a570_device::sten_w(int state)
|
||||
{
|
||||
m_sten = bool(state);
|
||||
}
|
||||
|
||||
void a570_device::drq_w(int state)
|
||||
{
|
||||
if (m_sten)
|
||||
m_dmac->xdreq_w(state);
|
||||
}
|
||||
|
||||
void a570_device::tpi_portb_w(uint8_t data)
|
||||
{
|
||||
// 7------- daclch (lc7883m)
|
||||
// -6------ dacst (lc7883m)
|
||||
// --5----- dacatt (lc7883m)
|
||||
// ---4---- weprom
|
||||
// ----3--- dten (drive)
|
||||
// -----2-- xaen (drive)
|
||||
// ------1- enable (drive)
|
||||
// -------0 cmd (drive)
|
||||
|
||||
m_drive->enable_w(BIT(data, 1));
|
||||
m_drive->cmd_w(BIT(data, 0));
|
||||
}
|
||||
|
||||
// the dmac handles this
|
||||
|
@ -14,8 +14,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "cpuslot.h"
|
||||
#include "machine/6525tpi.h"
|
||||
#include "machine/at28c16.h"
|
||||
#include "machine/cr511b.h"
|
||||
#include "machine/dmac.h"
|
||||
#include "machine/input_merger.h"
|
||||
|
||||
|
||||
namespace bus::amiga::cpuslot {
|
||||
|
||||
@ -38,9 +42,19 @@ protected:
|
||||
private:
|
||||
void map(address_map &map) ATTR_COLD;
|
||||
|
||||
void sten_w(int state);
|
||||
void drq_w(int state);
|
||||
|
||||
void tpi_portb_w(uint8_t data);
|
||||
|
||||
required_device<input_merger_any_high_device> m_irq;
|
||||
required_device<amiga_dmac_rev2_device> m_dmac;
|
||||
required_device<tpi6525_device> m_tpi;
|
||||
required_device<cr511b_device> m_drive;
|
||||
required_ioport m_config;
|
||||
|
||||
bool m_sten;
|
||||
|
||||
std::unique_ptr<uint16_t[]> m_ram;
|
||||
};
|
||||
|
||||
|
@ -1,97 +1,764 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Dirk Best
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Dirk Best
|
||||
/***************************************************************************
|
||||
|
||||
CR-511-B CD-ROM drive
|
||||
|
||||
CD-ROM drive with a custom MKE/Panasonic interface as used in the
|
||||
Commodore CDTV and early SoundBlaster cards.
|
||||
Commodore CDTV. Similar to the interface on early SoundBlaster cards.
|
||||
|
||||
Hardware:
|
||||
- MN188161REB1
|
||||
- M50423FP
|
||||
- 4464S-08LL
|
||||
- LC8951
|
||||
|
||||
TODO:
|
||||
- Subcode P-W data
|
||||
- Timing for status data or status change
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cr511b.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 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"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(CR511B, cr511b_device, "cr511b", "CR-511-B CD-ROM drive")
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
cdrom_image_device(mconfig, CR511B, tag, owner, clock),
|
||||
device_mixer_interface(mconfig, *this, 2),
|
||||
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 cr511b_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
CDROM(config, m_cdrom).set_interface("cdrom");
|
||||
CDDA(config, m_cdda);
|
||||
m_cdda->add_route(0, ":lspeaker", 1.0);
|
||||
m_cdda->add_route(1, ":rspeaker", 1.0);
|
||||
m_cdda->set_cdrom_tag("cdrom");
|
||||
m_cdda->add_route(0, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 0);
|
||||
m_cdda->add_route(1, DEVICE_SELF, 1.0, AUTO_ALLOC_INPUT, 1);
|
||||
m_cdda->set_cdrom_tag(*this);
|
||||
m_cdda->audio_end_cb().set(FUNC(cr511b_device::audio_end_cb));
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
// MACHINE EMULATION
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// cr511b_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, CR511B, tag, owner, clock),
|
||||
m_cdrom(*this, "cdrom"),
|
||||
m_cdda(*this, "cdda"),
|
||||
m_stch_handler(*this),
|
||||
m_sten_handler(*this),
|
||||
m_drq_handler(*this),
|
||||
m_dten_handler(*this),
|
||||
m_scor_handler(*this),
|
||||
m_xaen_handler(*this),
|
||||
//m_motor(false),
|
||||
m_enabled(-1),
|
||||
m_cmd(-1)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void cr511b_device::device_start()
|
||||
{
|
||||
}
|
||||
cdrom_image_device::device_start();
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
m_frame_timer = timer_alloc(FUNC(cr511b_device::frame_cb), this);
|
||||
m_stch_timer = timer_alloc(FUNC(cr511b_device::stch), this);
|
||||
m_sten_timer = timer_alloc(FUNC(cr511b_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 cr511b_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);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// IMPLEMENTATION
|
||||
//**************************************************************************
|
||||
std::pair<std::error_condition, std::string> cr511b_device::call_load()
|
||||
{
|
||||
auto ret = cdrom_image_device::call_load();
|
||||
|
||||
if (!ret.first)
|
||||
status_change(m_status | STATUS_MEDIA);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cr511b_device::call_unload()
|
||||
{
|
||||
status_change(STATUS_READY);
|
||||
|
||||
cdrom_image_device::call_unload();
|
||||
}
|
||||
|
||||
uint32_t cr511b_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 cr511b_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 cr511b_device::size_to_track_type()
|
||||
{
|
||||
switch (m_sector_size)
|
||||
{
|
||||
case 2048: return cdrom_file::CD_TRACK_MODE1;
|
||||
}
|
||||
|
||||
// have only seen 2048 so far
|
||||
fatalerror("Unknown sector mode: %d\n", m_sector_size);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(cr511b_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(cr511b_device::stch)
|
||||
{
|
||||
m_stch_cb(1);
|
||||
m_stch_cb(0);
|
||||
}
|
||||
|
||||
void cr511b_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(cr511b_device::sten)
|
||||
{
|
||||
m_status_ready = true;
|
||||
|
||||
m_sten_cb(0);
|
||||
m_sten_cb(1);
|
||||
}
|
||||
|
||||
void cr511b_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
|
||||
}
|
||||
}
|
||||
|
||||
void cr511b_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 cr511b_device::read()
|
||||
{
|
||||
return 0xff;
|
||||
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 cr511b_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;
|
||||
}
|
||||
|
||||
void cr511b_device::enable_w(int state)
|
||||
{
|
||||
m_enabled = state;
|
||||
m_input_fifo[m_input_fifo_pos++] = data;
|
||||
|
||||
switch (m_input_fifo[0])
|
||||
{
|
||||
case 0x01: if (m_input_fifo_pos == 7) cmd_seek(); break;
|
||||
case 0x02: if (m_input_fifo_pos == 7) cmd_read(); break;
|
||||
case 0x04: if (m_input_fifo_pos == 7) cmd_motor_on(); break;
|
||||
case 0x05: if (m_input_fifo_pos == 7) cmd_motor_off(); break;
|
||||
case 0x09: if (m_input_fifo_pos == 7) cmd_play_lba(); break;
|
||||
case 0x0a: if (m_input_fifo_pos == 7) cmd_play_msf(); break;
|
||||
case 0x0b: if (m_input_fifo_pos == 7) cmd_play_track(); break;
|
||||
case 0x81: if (m_input_fifo_pos == 1) cmd_read_status(); break;
|
||||
case 0x82: if (m_input_fifo_pos == 7) cmd_read_error(); break;
|
||||
case 0x84: if (m_input_fifo_pos == 7) cmd_set_mode(); break;
|
||||
case 0x87: if (m_input_fifo_pos == 7) cmd_read_subq(); break;
|
||||
case 0x89: if (m_input_fifo_pos == 7) cmd_read_disc_info(); break;
|
||||
case 0x8a: if (m_input_fifo_pos == 7) cmd_read_toc(); break;
|
||||
case 0x8b: if (m_input_fifo_pos == 7) cmd_pause(); break;
|
||||
case 0xa3: if (m_input_fifo_pos == 7) cmd_front_panel(); break;
|
||||
|
||||
default:
|
||||
LOG("Unknown command: %02x\n", m_input_fifo[0]);
|
||||
status_enable(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_w(int state)
|
||||
{
|
||||
m_cmd = state;
|
||||
m_cmd = !bool(state); // active low
|
||||
}
|
||||
|
||||
void cr511b_device::enable_w(int state)
|
||||
{
|
||||
m_enabled = !bool(state); // active low
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_seek()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Seek\n");
|
||||
LOGPARAM;
|
||||
|
||||
// TODO: Does this enable STATUS_SUCCESS?
|
||||
|
||||
status_change(m_status | STATUS_MOTOR);
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Read\n");
|
||||
LOGPARAM;
|
||||
|
||||
m_transfer_lba = (m_input_fifo[1] << 16) | (m_input_fifo[2] << 8) | (m_input_fifo[3] << 0);
|
||||
m_transfer_sectors = (m_input_fifo[4] << 8) | (m_input_fifo[5] << 0);
|
||||
m_transfer_length = m_transfer_sectors * m_sector_size;
|
||||
|
||||
LOGMASKED(LOG_CMD, "-> LBA %d, sectors %d\n", m_transfer_lba, m_transfer_sectors);
|
||||
|
||||
m_cdda->stop_audio();
|
||||
|
||||
uint8_t status = m_status;
|
||||
|
||||
status &= ~STATUS_PLAYING;
|
||||
status |= STATUS_MOTOR;
|
||||
|
||||
status_change(status);
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_motor_on()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Motor On\n");
|
||||
LOGPARAM;
|
||||
|
||||
// TODO: Does this enable STATUS_SUCCESS?
|
||||
|
||||
status_change(m_status | STATUS_MOTOR);
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_motor_off()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Motor Off\n");
|
||||
LOGPARAM;
|
||||
|
||||
// TODO: Does this enable STATUS_SUCCESS?
|
||||
|
||||
status_change(m_status & ~STATUS_MOTOR);
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_play_lba()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Play LBA\n");
|
||||
LOGPARAM;
|
||||
|
||||
// haven't found anything that uses it yet
|
||||
fatalerror("Play LBA: Not implemented\n");
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_play_msf()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Play MSF\n");
|
||||
LOGPARAM;
|
||||
|
||||
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");
|
||||
|
||||
uint8_t status = m_status;
|
||||
|
||||
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);
|
||||
|
||||
uint8_t status = m_status;
|
||||
|
||||
status |= STATUS_PLAYING;
|
||||
status |= STATUS_MOTOR;
|
||||
|
||||
status_change(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Invalid range %d to %d!\n", start_lba, end_lba);
|
||||
status_change(m_status | STATUS_ERROR);
|
||||
}
|
||||
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_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);
|
||||
|
||||
status_change(m_status | STATUS_PLAYING | STATUS_MOTOR);
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read_status()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Read Status\n");
|
||||
|
||||
m_status &= ~STATUS_SUCCESS;
|
||||
|
||||
m_output_fifo[0] = m_status;
|
||||
|
||||
status_enable(1);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read_error()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Read Error\n");
|
||||
LOGPARAM;
|
||||
|
||||
m_status &= ~STATUS_ERROR;
|
||||
m_status |= STATUS_READY;
|
||||
m_status |= STATUS_SUCCESS;
|
||||
|
||||
m_output_fifo[2] |= (m_status & 0x10);
|
||||
|
||||
status_enable(6);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_version()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Version\n");
|
||||
LOGPARAM;
|
||||
|
||||
// haven't found anything that uses it yet
|
||||
fatalerror("Version: Not implemented\n");
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_set_mode()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Set Mode\n");
|
||||
LOGPARAM;
|
||||
|
||||
// 01: unknown (value seen: 02)
|
||||
// 02: sector size hi
|
||||
// 03: sector size lo
|
||||
// 04: unknown (value seen 00)
|
||||
// 05: unknown (value seen 0f)
|
||||
// 06: unknown (value seen 00)
|
||||
|
||||
m_sector_size = (m_input_fifo[2] << 8) | m_input_fifo[3];
|
||||
|
||||
LOGMASKED(LOG_CMD, "Sector size = %d\n", m_sector_size);
|
||||
|
||||
m_status |= STATUS_SUCCESS; // ?
|
||||
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read_subq()
|
||||
{
|
||||
LOGMASKED(LOG_SUBQ, "Command: Read SubQ\n");
|
||||
if (VERBOSE & LOG_SUBQ)
|
||||
LOGPARAM;
|
||||
|
||||
// 01: bit 1 - msf or lba
|
||||
// 02: unknown
|
||||
// 03: unknown
|
||||
// 04: unknown
|
||||
// 05: unknown
|
||||
// 06: unknown
|
||||
|
||||
bool msf = bool(BIT(m_input_fifo[1], 1));
|
||||
|
||||
if (m_cdda->audio_active())
|
||||
{
|
||||
uint32_t lba = m_cdda->get_audio_lba();
|
||||
uint8_t track = get_track(lba);
|
||||
|
||||
uint32_t disc_pos = lba;
|
||||
uint32_t track_pos = lba - get_track_start(track);
|
||||
|
||||
if (msf)
|
||||
{
|
||||
disc_pos = lba_to_msf(disc_pos);
|
||||
track_pos = lba_to_msf(track_pos - 150);
|
||||
|
||||
if (VERBOSE & LOG_SUBQ2)
|
||||
popmessage("Playing track %d at %02d:%02d.%02d (disc %02d:%02d.%02d)", track + 1,
|
||||
track_pos >> 16 & 0xff, track_pos >> 8 & 0xff, track_pos & 0xff,
|
||||
disc_pos >> 16 & 0xff, disc_pos >> 8 & 0xff, disc_pos & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VERBOSE & LOG_SUBQ2)
|
||||
popmessage("Playing track %d at %d (disc %d)", track, track_pos, disc_pos);
|
||||
}
|
||||
|
||||
m_output_fifo[1] = get_adr_control(track);
|
||||
m_output_fifo[2] = track + 1;
|
||||
m_output_fifo[3] = 0x01; // TODO: index
|
||||
|
||||
m_output_fifo[4] = disc_pos >> 24;
|
||||
m_output_fifo[5] = disc_pos >> 16;
|
||||
m_output_fifo[6] = disc_pos >> 8;
|
||||
m_output_fifo[7] = disc_pos >> 0;
|
||||
m_output_fifo[8] = track_pos >> 24;
|
||||
m_output_fifo[9] = track_pos >> 16;
|
||||
m_output_fifo[10] = track_pos >> 8;
|
||||
m_output_fifo[11] = track_pos >> 0;
|
||||
m_output_fifo[12] = 0; // TODO: upc flag
|
||||
|
||||
if (m_cdda->audio_paused())
|
||||
m_output_fifo[0] = AUDIO_STATUS_PAUSED;
|
||||
else
|
||||
m_output_fifo[0] = AUDIO_STATUS_PLAY;
|
||||
}
|
||||
else if (m_cdda->audio_ended())
|
||||
m_output_fifo[0] = AUDIO_STATUS_COMPLETED;
|
||||
else
|
||||
m_output_fifo[0] = AUDIO_STATUS_NO_STATUS;
|
||||
|
||||
LOGMASKED(LOG_SUBQ, "-> Audio status = %02x\n", m_output_fifo[0]);
|
||||
|
||||
status_enable(13);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read_disc_info()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Read Disc Info\n");
|
||||
LOGPARAM;
|
||||
|
||||
uint8_t last_track = get_last_track();
|
||||
uint32_t last_lba = get_track_start(0xaa);
|
||||
uint32_t last_msf = lba_to_msf(last_lba);
|
||||
|
||||
m_output_fifo[0] = 1; // first track
|
||||
m_output_fifo[1] = last_track;
|
||||
m_output_fifo[2] = last_msf >> 16;
|
||||
m_output_fifo[3] = last_msf >> 8;
|
||||
m_output_fifo[4] = last_msf >> 0;
|
||||
|
||||
status_change(m_status | STATUS_MOTOR | STATUS_SUCCESS);
|
||||
status_enable(5);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_read_toc()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Read TOC\n");
|
||||
LOGPARAM;
|
||||
|
||||
// 01: bit 1 - msf or lba
|
||||
// 02: track
|
||||
// 03: unused?
|
||||
// 04: unused?
|
||||
// 05: unused?
|
||||
// 06: unused?
|
||||
|
||||
bool msf = bool(BIT(m_input_fifo[1], 1));
|
||||
uint8_t track = m_input_fifo[2];
|
||||
|
||||
uint8_t status = m_status;
|
||||
|
||||
status |= STATUS_MOTOR;
|
||||
|
||||
if (track > get_last_track())
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Invalid track requested: %d\n", track);
|
||||
|
||||
status |= STATUS_ERROR;
|
||||
status_enable(0);
|
||||
}
|
||||
else if (track == 0)
|
||||
{
|
||||
uint32_t track_start = get_track_start(0xaa);
|
||||
|
||||
LOGMASKED(LOG_CMD, "Track 0 requested, lead out start %d\n", track_start);
|
||||
|
||||
if (msf)
|
||||
track_start = lba_to_msf(track_start);
|
||||
|
||||
m_output_fifo[1] = get_adr_control(0xaa);
|
||||
m_output_fifo[2] = 1; // first track
|
||||
m_output_fifo[3] = get_last_track();
|
||||
m_output_fifo[4] = track_start >> 24;
|
||||
m_output_fifo[5] = track_start >> 16;
|
||||
m_output_fifo[6] = track_start >> 8;
|
||||
m_output_fifo[7] = track_start >> 0;
|
||||
|
||||
status_enable(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t track_start = get_track_start(track - 1);
|
||||
|
||||
LOGMASKED(LOG_CMD, "Track %d requested, start %d\n", track, track_start);
|
||||
|
||||
if (msf)
|
||||
track_start = lba_to_msf(track_start);
|
||||
|
||||
m_output_fifo[1] = get_adr_control(track - 1);
|
||||
m_output_fifo[2] = track;
|
||||
m_output_fifo[3] = 0;
|
||||
m_output_fifo[4] = track_start >> 24;
|
||||
m_output_fifo[5] = track_start >> 16;
|
||||
m_output_fifo[6] = track_start >> 8;
|
||||
m_output_fifo[7] = track_start >> 0;
|
||||
|
||||
status_enable(8);
|
||||
}
|
||||
|
||||
status_change(status);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_pause()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Pause\n");
|
||||
LOGPARAM;
|
||||
|
||||
// 01: 00 = pause audio, other values?
|
||||
// 02: unused?
|
||||
// 03: unused?
|
||||
// 04: unused?
|
||||
// 05: unused?
|
||||
// 06: unused?
|
||||
|
||||
m_cdda->pause_audio(m_input_fifo[1] == 0x00);
|
||||
|
||||
status_enable(0);
|
||||
}
|
||||
|
||||
void cr511b_device::cmd_front_panel()
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "Command: Front Panel\n");
|
||||
LOGPARAM;
|
||||
|
||||
// enables direct control of the drive by the front panel buttons: stop, play/pause, ff, rew
|
||||
|
||||
// 01: enable/disable
|
||||
// 02: unused?
|
||||
// 03: unused?
|
||||
// 04: unused?
|
||||
// 05: unused?
|
||||
// 06: unused?
|
||||
|
||||
status_enable(0);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Dirk Best
|
||||
// license: BSD-3-Clause
|
||||
// copyright-holders: Dirk Best
|
||||
/***************************************************************************
|
||||
|
||||
CR-511-B CD-ROM drive
|
||||
|
||||
CD-ROM drive with a custom MKE/Panasonic interface as used in the
|
||||
Commodore CDTV and early SoundBlaster cards.
|
||||
Commodore CDTV. Similar to the interface on early SoundBlaster cards.
|
||||
|
||||
1 _RESET 2 GND
|
||||
3 EFFK 4 SCCK
|
||||
@ -38,65 +38,122 @@
|
||||
#include "imagedev/cdromimg.h"
|
||||
#include "sound/cdda.h"
|
||||
|
||||
class cr511b_device : public device_t
|
||||
|
||||
class cr511b_device : public cdrom_image_device, public device_mixer_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// callbacks
|
||||
auto stch_handler() { return m_stch_handler.bind(); }
|
||||
auto sten_handler() { return m_sten_handler.bind(); }
|
||||
auto drq_handler() { return m_drq_handler.bind(); }
|
||||
auto dten_handler() { return m_dten_handler.bind(); }
|
||||
auto scor_handler() { return m_scor_handler.bind(); }
|
||||
auto xaen_handler() { return m_xaen_handler.bind(); }
|
||||
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 enable_w(int state);
|
||||
void cmd_w(int state);
|
||||
void enable_w(int state);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
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;
|
||||
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||
|
||||
// device_image_interface implementation
|
||||
virtual std::pair<std::error_condition, std::string> call_load() override;
|
||||
virtual void call_unload() override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
STATUS_DOOR_CLOSED = 0x80,
|
||||
STATUS_MEDIA = 0x40,
|
||||
STATUS_MOTOR = 0x20,
|
||||
STATUS_ERROR = 0x10,
|
||||
STATUS_SUCCESS = 0x08,
|
||||
STATUS_PLAYING = 0x04,
|
||||
STATUS_DOOR_LOCKED = 0x02,
|
||||
STATUS_READY = 0x01
|
||||
};
|
||||
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_read();
|
||||
void cmd_motor_on();
|
||||
void cmd_motor_off();
|
||||
void cmd_play_lba();
|
||||
void cmd_play_msf();
|
||||
void cmd_play_track();
|
||||
void cmd_read_status();
|
||||
void cmd_read_error();
|
||||
void cmd_version();
|
||||
void cmd_set_mode();
|
||||
void cmd_read_subq();
|
||||
void cmd_read_disc_info();
|
||||
void cmd_read_toc();
|
||||
void cmd_pause();
|
||||
void cmd_front_panel();
|
||||
|
||||
// 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<cdrom_image_device> m_cdrom;
|
||||
required_device<cdda_device> m_cdda;
|
||||
|
||||
devcb_write_line m_stch_handler;
|
||||
devcb_write_line m_sten_handler;
|
||||
devcb_write_line m_drq_handler;
|
||||
devcb_write_line m_dten_handler;
|
||||
devcb_write_line m_scor_handler;
|
||||
devcb_write_line m_xaen_handler;
|
||||
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;
|
||||
|
||||
//bool m_motor;
|
||||
emu_timer *m_frame_timer;
|
||||
emu_timer *m_stch_timer;
|
||||
emu_timer *m_sten_timer;
|
||||
|
||||
// state of lines
|
||||
int m_enabled;
|
||||
int m_cmd;
|
||||
uint8_t m_input_fifo[16];
|
||||
uint8_t m_input_fifo_pos;
|
||||
|
||||
// data transfer
|
||||
//uint8_t m_sector_buffer[CD_MAX_SECTOR_DATA];
|
||||
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(CR511B, cr511b_device)
|
||||
|
||||
#endif // MAME_MACHINE_CR511B_H
|
||||
|
@ -14,7 +14,7 @@
|
||||
- SCSI
|
||||
- Support newer variant
|
||||
- DAWR
|
||||
- Data corruption when installing WB31
|
||||
- Rev 1: Data corruption when installing WB31
|
||||
- FIFO?
|
||||
|
||||
***************************************************************************/
|
||||
@ -47,6 +47,8 @@ amiga_dmac_device::amiga_dmac_device(const machine_config &mconfig, device_type
|
||||
m_css_write_cb(*this),
|
||||
m_csx0_read_cb(*this, 0),
|
||||
m_csx0_write_cb(*this),
|
||||
m_csx0_a4_read_cb(*this, 0),
|
||||
m_csx0_a4_write_cb(*this),
|
||||
m_csx1_read_cb(*this, 0),
|
||||
m_csx1_write_cb(*this),
|
||||
m_sdack_read_cb(*this, 0),
|
||||
@ -99,6 +101,7 @@ void amiga_dmac_device::map(address_map &map)
|
||||
map(0x008e, 0x008f).w(FUNC(amiga_dmac_device::dawr_w));
|
||||
map(0x0090, 0x0093).rw(FUNC(amiga_dmac_device::css_r), FUNC(amiga_dmac_device::css_w)).umask16(0x00ff);
|
||||
map(0x00a0, 0x00a7).rw(FUNC(amiga_dmac_device::csx0_r), FUNC(amiga_dmac_device::csx0_w)).umask16(0x00ff);
|
||||
map(0x00b0, 0x00bf).rw(FUNC(amiga_dmac_device::csx0_a4_r), FUNC(amiga_dmac_device::csx0_a4_w)).umask16(0x00ff); // a4 + csx0
|
||||
map(0x00c0, 0x00c7).rw(FUNC(amiga_dmac_device::csx1_r), FUNC(amiga_dmac_device::csx1_w)).umask16(0x00ff);
|
||||
map(0x00e0, 0x00e1).rw(FUNC(amiga_dmac_device::st_dma_r), FUNC(amiga_dmac_device::st_dma_w));
|
||||
map(0x00e2, 0x00e3).rw(FUNC(amiga_dmac_device::sp_dma_r), FUNC(amiga_dmac_device::sp_dma_w));
|
||||
@ -192,7 +195,7 @@ TIMER_CALLBACK_MEMBER(amiga_dmac_device::update_dma)
|
||||
|
||||
m_acr++;
|
||||
|
||||
if (m_rev1 && (m_cntr & CNTR_TCEN))
|
||||
if (m_cntr & CNTR_TCEN)
|
||||
{
|
||||
// we count words
|
||||
if ((m_acr & 1) == 0)
|
||||
@ -201,6 +204,8 @@ TIMER_CALLBACK_MEMBER(amiga_dmac_device::update_dma)
|
||||
{
|
||||
LOGMASKED(LOG_DMA, "Terminal count\n");
|
||||
|
||||
stop_dma();
|
||||
|
||||
m_istr |= ISTR_E_INT;
|
||||
update_interrupts();
|
||||
}
|
||||
@ -254,22 +259,16 @@ void amiga_dmac_device::wtc_hi_w(offs_t offset, uint16_t data, uint16_t mem_mask
|
||||
{
|
||||
LOGMASKED(LOG_REGS, "wtc_hi_w: %04x & %04x\n", data, mem_mask);
|
||||
|
||||
if (m_rev1)
|
||||
{
|
||||
m_wtc &= (~(uint32_t) mem_mask) << 16 | 0x0000ffff;
|
||||
m_wtc |= ((uint32_t) data & mem_mask) << 16;
|
||||
}
|
||||
m_wtc &= (~(uint32_t) mem_mask) << 16 | 0x0000ffff;
|
||||
m_wtc |= ((uint32_t) data & mem_mask) << 16;
|
||||
}
|
||||
|
||||
void amiga_dmac_device::wtc_lo_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_REGS, "wtc_lo_w: %04x & %04x\n", data, mem_mask);
|
||||
|
||||
if (m_rev1)
|
||||
{
|
||||
m_wtc &= 0xffff0000 & (~mem_mask);
|
||||
m_wtc |= data & mem_mask;
|
||||
}
|
||||
m_wtc &= 0xffff0000 & (~mem_mask);
|
||||
m_wtc |= data & mem_mask;
|
||||
}
|
||||
|
||||
void amiga_dmac_device::acr_hi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
@ -298,6 +297,8 @@ uint8_t amiga_dmac_device::css_r(offs_t offset) { return m_css_read_cb(offset);
|
||||
void amiga_dmac_device::css_w(offs_t offset, uint8_t data) { m_css_write_cb(offset, data); }
|
||||
uint8_t amiga_dmac_device::csx0_r(offs_t offset) { return m_csx0_read_cb(offset); }
|
||||
void amiga_dmac_device::csx0_w(offs_t offset, uint8_t data) { m_csx0_write_cb(offset, data); }
|
||||
uint8_t amiga_dmac_device::csx0_a4_r(offs_t offset) { return m_csx0_a4_read_cb(offset); }
|
||||
void amiga_dmac_device::csx0_a4_w(offs_t offset, uint8_t data) { m_csx0_a4_write_cb(offset, data); }
|
||||
uint8_t amiga_dmac_device::csx1_r(offs_t offset) { return m_csx1_read_cb(offset); }
|
||||
void amiga_dmac_device::csx1_w(offs_t offset, uint8_t data) { m_csx1_write_cb(offset, data); }
|
||||
|
||||
|
@ -26,6 +26,8 @@ public:
|
||||
auto css_write_cb() { return m_css_write_cb.bind(); }
|
||||
auto csx0_read_cb() { return m_csx0_read_cb.bind(); }
|
||||
auto csx0_write_cb() { return m_csx0_write_cb.bind(); }
|
||||
auto csx0_a4_read_cb() { return m_csx0_a4_read_cb.bind(); }
|
||||
auto csx0_a4_write_cb() { return m_csx0_a4_write_cb.bind(); }
|
||||
auto csx1_read_cb() { return m_csx1_read_cb.bind(); }
|
||||
auto csx1_write_cb() { return m_csx1_write_cb.bind(); }
|
||||
auto sdack_read_cb() { return m_sdack_read_cb.bind(); }
|
||||
@ -77,6 +79,8 @@ private:
|
||||
void css_w(offs_t offset, uint8_t data);
|
||||
uint8_t csx0_r(offs_t offset);
|
||||
void csx0_w(offs_t offset, uint8_t data);
|
||||
uint8_t csx0_a4_r(offs_t offset);
|
||||
void csx0_a4_w(offs_t offset, uint8_t data);
|
||||
uint8_t csx1_r(offs_t offset);
|
||||
void csx1_w(offs_t offset, uint8_t data);
|
||||
|
||||
@ -120,6 +124,8 @@ private:
|
||||
devcb_write8 m_css_write_cb;
|
||||
devcb_read8 m_csx0_read_cb;
|
||||
devcb_write8 m_csx0_write_cb;
|
||||
devcb_read8 m_csx0_a4_read_cb;
|
||||
devcb_write8 m_csx0_a4_write_cb;
|
||||
devcb_read8 m_csx1_read_cb;
|
||||
devcb_write8 m_csx1_write_cb;
|
||||
devcb_read8 m_sdack_read_cb;
|
||||
@ -165,7 +171,7 @@ public:
|
||||
amiga_dmac_rev2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
// device type declaration
|
||||
DECLARE_DEVICE_TYPE(AMIGA_DMAC_REV1, amiga_dmac_rev1_device)
|
||||
DECLARE_DEVICE_TYPE(AMIGA_DMAC_REV2, amiga_dmac_rev2_device)
|
||||
|
||||
|
@ -354,13 +354,6 @@ public:
|
||||
u16 clock_r(offs_t offset);
|
||||
void clock_w(offs_t offset, u16 data);
|
||||
|
||||
uint8_t dmac_scsi_data_read(offs_t offset);
|
||||
void dmac_scsi_data_write(offs_t offset, uint8_t data);
|
||||
void dmac_int_w(int state);
|
||||
|
||||
void tpi_port_b_write(uint8_t data);
|
||||
void tpi_int_w(int state);
|
||||
|
||||
void cdtv(machine_config &config);
|
||||
void cdtvn(machine_config &config);
|
||||
void cdtv_mem(address_map &map) ATTR_COLD;
|
||||
@ -369,21 +362,30 @@ public:
|
||||
protected:
|
||||
// driver_device overrides
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
virtual void machine_reset() override ATTR_COLD;
|
||||
|
||||
// amiga_state overrides
|
||||
virtual bool int2_pending() override;
|
||||
virtual bool int6_pending() override;
|
||||
|
||||
private:
|
||||
// devices
|
||||
void dmac_int_w(int state);
|
||||
|
||||
void tpi_portb_w(uint8_t data);
|
||||
void tpi_int_w(int state);
|
||||
|
||||
void sten_w(int state);
|
||||
void drq_w(int state);
|
||||
|
||||
required_device<msm6242_device> m_rtc;
|
||||
required_device<amiga_dmac_rev1_device> m_dmac;
|
||||
required_device<amiga_dmac_rev2_device> m_dmac;
|
||||
required_device<tpi6525_device> m_tpi;
|
||||
required_device<cr511b_device> m_cdrom;
|
||||
|
||||
// internal state
|
||||
int m_dmac_irq;
|
||||
int m_tpi_irq;
|
||||
bool m_sten;
|
||||
};
|
||||
|
||||
class a3000_state : public amiga_state
|
||||
@ -643,43 +645,6 @@ void a500p_state::clock_w(offs_t offset, u16 data)
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CD-ROM CONTROLLER
|
||||
//**************************************************************************
|
||||
|
||||
uint8_t cdtv_state::dmac_scsi_data_read(offs_t offset)
|
||||
{
|
||||
if (offset >= 0xb0 && offset <= 0xbf)
|
||||
return m_tpi->read(offset);
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void cdtv_state::dmac_scsi_data_write(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (offset >= 0xb0 && offset <= 0xbf)
|
||||
m_tpi->write(offset, data);
|
||||
}
|
||||
|
||||
void cdtv_state::dmac_int_w(int state)
|
||||
{
|
||||
m_dmac_irq = state;
|
||||
update_int2();
|
||||
}
|
||||
|
||||
void cdtv_state::tpi_port_b_write(uint8_t data)
|
||||
{
|
||||
m_cdrom->cmd_w(BIT(data, 0));
|
||||
m_cdrom->enable_w(BIT(data, 1));
|
||||
}
|
||||
|
||||
void cdtv_state::tpi_int_w(int state)
|
||||
{
|
||||
m_tpi_irq = state;
|
||||
update_int2();
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DRIVER INIT
|
||||
//**************************************************************************
|
||||
@ -949,6 +914,15 @@ void cdtv_state::machine_start()
|
||||
m_dmac->ramsz_w(0);
|
||||
}
|
||||
|
||||
void cdtv_state::machine_reset()
|
||||
{
|
||||
amiga_state::machine_reset();
|
||||
|
||||
// start autoconfig
|
||||
m_dmac->configin_w(0);
|
||||
m_dmac->configin_w(1);
|
||||
}
|
||||
|
||||
bool cdtv_state::int2_pending()
|
||||
{
|
||||
return m_cia_0_irq || m_dmac_irq || m_tpi_irq;
|
||||
@ -959,6 +933,35 @@ bool cdtv_state::int6_pending()
|
||||
return m_cia_1_irq;
|
||||
}
|
||||
|
||||
void cdtv_state::dmac_int_w(int state)
|
||||
{
|
||||
m_dmac_irq = state;
|
||||
update_int2();
|
||||
}
|
||||
|
||||
void cdtv_state::tpi_portb_w(uint8_t data)
|
||||
{
|
||||
m_cdrom->enable_w(BIT(data, 1));
|
||||
m_cdrom->cmd_w(BIT(data, 0));
|
||||
}
|
||||
|
||||
void cdtv_state::tpi_int_w(int state)
|
||||
{
|
||||
m_tpi_irq = state;
|
||||
update_int2();
|
||||
}
|
||||
|
||||
void cdtv_state::sten_w(int state)
|
||||
{
|
||||
m_sten = bool(state);
|
||||
}
|
||||
|
||||
void cdtv_state::drq_w(int state)
|
||||
{
|
||||
if (m_sten)
|
||||
m_dmac->xdreq_w(state);
|
||||
}
|
||||
|
||||
u32 a3000_state::scsi_r(offs_t offset, u32 mem_mask)
|
||||
{
|
||||
u32 data = 0xffffffff;
|
||||
@ -1961,31 +1964,30 @@ void cdtv_state::cdtv(machine_config &config)
|
||||
// 256kb memory card
|
||||
NVRAM(config, "memcard", nvram_device::DEFAULT_ALL_0);
|
||||
|
||||
// real-time clock
|
||||
MSM6242(config, m_rtc, XTAL(32'768));
|
||||
|
||||
// cd-rom controller
|
||||
AMIGA_DMAC_REV1(config, m_dmac, amiga_state::CLK_7M_PAL);
|
||||
m_dmac->css_read_cb().set(FUNC(cdtv_state::dmac_scsi_data_read));
|
||||
m_dmac->css_write_cb().set(FUNC(cdtv_state::dmac_scsi_data_write));
|
||||
AMIGA_DMAC_REV2(config, m_dmac, amiga_state::CLK_7M_PAL);
|
||||
m_dmac->int_cb().set(FUNC(cdtv_state::dmac_int_w));
|
||||
m_dmac->csx0_read_cb().set(m_cdrom, FUNC(cr511b_device::read));
|
||||
m_dmac->csx0_write_cb().set(m_cdrom, FUNC(cr511b_device::write));
|
||||
m_dmac->int_cb().set(FUNC(cdtv_state::dmac_int_w));
|
||||
m_dmac->csx0_a4_read_cb().set(m_tpi, FUNC(tpi6525_device::read));
|
||||
m_dmac->csx0_a4_write_cb().set(m_tpi, FUNC(tpi6525_device::write));
|
||||
m_dmac->xdack_read_cb().set(m_cdrom, FUNC(cr511b_device::read));
|
||||
|
||||
TPI6525(config, m_tpi, 0);
|
||||
m_tpi->out_irq_cb().set(FUNC(cdtv_state::tpi_int_w));
|
||||
m_tpi->out_pb_cb().set(FUNC(cdtv_state::tpi_port_b_write));
|
||||
m_tpi->out_pb_cb().set(FUNC(cdtv_state::tpi_portb_w));
|
||||
|
||||
// cd-rom
|
||||
CR511B(config, m_cdrom, 0);
|
||||
m_cdrom->scor_handler().set(m_tpi, FUNC(tpi6525_device::i1_w)).invert();
|
||||
m_cdrom->stch_handler().set(m_tpi, FUNC(tpi6525_device::i2_w)).invert();
|
||||
m_cdrom->sten_handler().set(m_tpi, FUNC(tpi6525_device::i3_w));
|
||||
m_cdrom->xaen_handler().set(m_tpi, FUNC(tpi6525_device::pb2_w));
|
||||
m_cdrom->drq_handler().set(m_dmac, FUNC(amiga_dmac_device::xdreq_w));
|
||||
m_cdrom->dten_handler().set(m_dmac, FUNC(amiga_dmac_device::xdreq_w));
|
||||
m_cdrom->add_route(0, "lspeaker", 1.0);
|
||||
m_cdrom->add_route(1, "rspeaker", 1.0);
|
||||
m_cdrom->scor_cb().set(m_tpi, FUNC(tpi6525_device::i1_w)).invert();
|
||||
m_cdrom->stch_cb().set(m_tpi, FUNC(tpi6525_device::i2_w)).invert();
|
||||
m_cdrom->sten_cb().set(m_tpi, FUNC(tpi6525_device::i3_w));
|
||||
m_cdrom->sten_cb().append(FUNC(cdtv_state::sten_w));
|
||||
m_cdrom->drq_cb().set(m_tpi, FUNC(tpi6525_device::i4_w));
|
||||
m_cdrom->drq_cb().append(FUNC(cdtv_state::drq_w));
|
||||
|
||||
// software
|
||||
SOFTWARE_LIST(config, "cd_list").set_original("cdtv");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user