summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2026-05-06 15:49:32 -0400
committer arbee <rb6502@users.noreply.github.com>2026-05-06 15:49:32 -0400
commitff6fea5156ac4d68f0fab3a957638eb6625aa354 (patch)
tree36eed2bd597cf6b67c9a28153465461aa318fd9a /src/devices
parent511bdffa5e2f113be0b0af403db8341c6f9d9236 (diff)
nscsi/cd.cpp: Added a CDROM_2X device that reasonably throttles the read speed to what you'd see with a 2X CD-ROM drive. [R. Belmont]
sound/l7a1045_l6028_dsp_a.cpp: Throttled DMA wave RAM writes to a more reasonable (but still very fast) rate. akai/s3000.cpp: Improvements. [R. Belmont] - Fixed crackling samples: the CD-ROM code in these machines was running a single-buffer race condition and hoping it never lost. Slower DSP wave RAM DMA and realistic 2X CD-ROM read speeds cracked the case. - S3000 and CD3000i copy all 256K of ROM to RAM at boot and then bank out the ROM in favor of 256K of RAM. Implementing this resolved the S3000 crashing when loading from CD-ROM and many other small instabilities. - S3000 and CD3000i key matrix repeat delay depended on timer 2 which depended on the V53 external timer input, which was running far too fast. Fixed, the buttons now feel reasonable.
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/bus/nscsi/cd.cpp27
-rw-r--r--src/devices/bus/nscsi/cd.h11
-rw-r--r--src/devices/bus/nscsi/devices.cpp1
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.cpp52
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.h7
5 files changed, 85 insertions, 13 deletions
diff --git a/src/devices/bus/nscsi/cd.cpp b/src/devices/bus/nscsi/cd.cpp
index 6e55cece473..fdb75661f6c 100644
--- a/src/devices/bus/nscsi/cd.cpp
+++ b/src/devices/bus/nscsi/cd.cpp
@@ -13,6 +13,7 @@
#include "logmacro.h"
DEFINE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device, "scsi_cdrom", "SCSI CD-ROM")
+DEFINE_DEVICE_TYPE(NSCSI_CDROM_2X, nscsi_cdrom_2x_device, "scsi_cdrom2x", "SCSI CD-ROM (2X speed)")
DEFINE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device, "scsi_cdrom_sgi", "SCSI CD-ROM SGI")
DEFINE_DEVICE_TYPE(NSCSI_CDROM_NEWS, nscsi_cdrom_news_device, "scsi_cdrom_news", "SCSI CD-ROM NEWS")
DEFINE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device, "nrrd45", "RRD45 CD-ROM (New)")
@@ -45,6 +46,11 @@ nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, const char
{
}
+nscsi_cdrom_2x_device::nscsi_cdrom_2x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ nscsi_cdrom_device(mconfig, NSCSI_CDROM_2X, tag, owner, "Sony", "CDU-76S", "1.0", 0x00, 0x05)
+{
+}
+
nscsi_cdrom_sgi_device::nscsi_cdrom_sgi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nscsi_cdrom_device(mconfig, NSCSI_CDROM_SGI, tag, owner, "Sony", "CDU-76S", "1.0", 0x00, 0x05)
{
@@ -1104,6 +1110,27 @@ void nscsi_cdrom_device::scsi_command()
}
}
+attotime nscsi_cdrom_2x_device::scsi_data_byte_period()
+{
+ // 150 sectors/second * 2048 bytes/sector = 307,200 bytes/second
+ return attotime::from_ticks(1, 307'200);
+}
+
+attotime nscsi_cdrom_2x_device::scsi_data_command_delay()
+{
+ switch (m_scsi_cmdbuf[0])
+ {
+ case SC_READ_6:
+ case SC_READ_10:
+ case SC_READ_12:
+ case SC_READ_TOC_PMA_ATIP:
+ return attotime::from_usec(100);
+
+ default:
+ return attotime::zero;
+ }
+}
+
enum sgi_scsi_command_e : uint8_t {
/*
* The SGI supplied CD-ROM drives (and possibly those from some other vendors)
diff --git a/src/devices/bus/nscsi/cd.h b/src/devices/bus/nscsi/cd.h
index eef3c2ec403..86a70ccfbfd 100644
--- a/src/devices/bus/nscsi/cd.h
+++ b/src/devices/bus/nscsi/cd.h
@@ -78,6 +78,16 @@ private:
std::vector<uint8_t> m_xfer_buffer;
};
+class nscsi_cdrom_2x_device : public nscsi_cdrom_device
+{
+public:
+ nscsi_cdrom_2x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ virtual attotime scsi_data_byte_period() override;
+ virtual attotime scsi_data_command_delay() override;
+};
+
class nscsi_cdrom_sgi_device : public nscsi_cdrom_device
{
public:
@@ -165,6 +175,7 @@ protected:
};
DECLARE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device)
+DECLARE_DEVICE_TYPE(NSCSI_CDROM_2X, nscsi_cdrom_2x_device)
DECLARE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device)
DECLARE_DEVICE_TYPE(NSCSI_CDROM_NEWS, nscsi_cdrom_news_device)
DECLARE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device)
diff --git a/src/devices/bus/nscsi/devices.cpp b/src/devices/bus/nscsi/devices.cpp
index 0c592e47d7d..4b8dadfccb7 100644
--- a/src/devices/bus/nscsi/devices.cpp
+++ b/src/devices/bus/nscsi/devices.cpp
@@ -23,6 +23,7 @@
void default_scsi_devices(device_slot_interface &device)
{
device.option_add("cdrom", NSCSI_CDROM);
+ device.option_add("cdrom_2x", NSCSI_CDROM_2X);
device.option_add("harddisk", NSCSI_HARDDISK);
device.option_add("tape", NSCSI_TAPE);
device.option_add("s1410", NSCSI_S1410);
diff --git a/src/devices/sound/l7a1045_l6028_dsp_a.cpp b/src/devices/sound/l7a1045_l6028_dsp_a.cpp
index 8a8c95aaf96..bd1fe109163 100644
--- a/src/devices/sound/l7a1045_l6028_dsp_a.cpp
+++ b/src/devices/sound/l7a1045_l6028_dsp_a.cpp
@@ -58,8 +58,7 @@
0 ffffffffssssaaaa aaaaaaaaaaaaaaaa aaaa------------
f = flags? always 01
- s = sample format, 0 = 16 bits, 1 = 8 bits.
- also 0 = RAM address space, 1 = ROM address space
+ s = 0 for RAM address space, 1 for ROM address space
a = sample start address (24 bits, 16 MiB addressable)
For DMA, this is set to the DMA start address on channel 0
@@ -90,7 +89,7 @@
A = loop start address, bits 23-20
3 ---------------- vvvvvvvvvvvvvvvv ----------------
- v = volume envelope starting value (16 bit, maaaaybe signed?)
+ v = volume envelope starting value (16 bit unsigned)
4 ---------------- vvvvvvvvvvvvvvvv rrrrrrrrrrrrrrrr
v = volume envelope target value
@@ -183,6 +182,11 @@ l7a1045_sound_device::l7a1045_sound_device(const machine_config &mconfig, const
m_drq_handler(*this),
m_stream(nullptr),
m_key(0),
+ m_control(0),
+ m_dma_timer(nullptr),
+ m_cur_channel(0),
+ m_cur_register(0),
+ m_sample_rate(44100.0),
m_mem_config("l6028", ENDIANNESS_LITTLE, 16, 25),
m_rom_config("l6028_rom", ENDIANNESS_LITTLE, 16, 25)
{
@@ -214,6 +218,8 @@ void l7a1045_sound_device::device_start()
m_sample_rate = clock() / 768.0f;
m_stream = stream_alloc(0, 10, m_sample_rate);
+ m_dma_timer = timer_alloc(FUNC(l7a1045_sound_device::dma_timer_callback), this);
+
save_item(STRUCT_MEMBER(m_voice, loop_start));
save_item(STRUCT_MEMBER(m_voice, start));
save_item(STRUCT_MEMBER(m_voice, end));
@@ -417,20 +423,20 @@ uint16_t l7a1045_sound_device::voiceregs_r(offs_t offset)
m_regs[0][m_cur_channel] |= (uint64_t(current_addr) << 12);
m_regs[0][m_cur_channel] |= vptr->frac & 0x0fff;
- LOGMASKED(LOG_READBACK_POSITION, "ch %d cur pos %08x final %012llx (%s)\n", m_cur_channel, current_addr, m_regs[0][m_cur_channel], machine().describe_context());
+ LOGMASKED(LOG_READBACK_POSITION, "ch %d cur pos %08x final %012llx (%s)\n", m_cur_channel, current_addr, m_regs[L6028_Start][m_cur_channel], machine().describe_context());
}
break;
case L6028_Volume_Env:
- m_regs[3][m_cur_channel] &= 0xffff'0000'ffff;
- m_regs[3][m_cur_channel] |= (uint64_t(vptr->env_volume) << 16);
- LOGMASKED(LOG_READBACK_VOL, "ch %d read env vol %x => %012llx (%s)\n", m_cur_channel, vptr->env_volume, m_regs[3][m_cur_channel], machine().describe_context());
+ m_regs[L6028_Volume_Env][m_cur_channel] &= 0xffff'0000'ffff;
+ m_regs[L6028_Volume_Env][m_cur_channel] |= (uint64_t(vptr->env_volume) << 16);
+ LOGMASKED(LOG_READBACK_VOL, "ch %d read env vol %x => %012llx (%s)\n", m_cur_channel, vptr->env_volume, m_regs[L6028_Volume_Env][m_cur_channel], machine().describe_context());
break;
case L6028_Filter_Env:
- m_regs[5][m_cur_channel] &= 0xffff'0000'ffff;
- m_regs[5][m_cur_channel] |= (uint64_t(vptr->flt_freq) << 16);
- LOGMASKED(LOG_READBACK_FILTER, "ch %d read filter cutoff %x => %012llx\n", m_cur_channel, vptr->env_volume, m_regs[3][m_cur_channel]);
+ m_regs[L6028_Filter_Env][m_cur_channel] &= 0xffff'0000'ffff;
+ m_regs[L6028_Filter_Env][m_cur_channel] |= (uint64_t(vptr->flt_freq) << 16);
+ LOGMASKED(LOG_READBACK_FILTER, "ch %d read filter cutoff %x => %012llx\n", m_cur_channel, vptr->flt_freq, m_regs[L6028_Filter_Env][m_cur_channel]);
break;
}
@@ -547,14 +553,14 @@ void l7a1045_sound_device::recalc_loop_start(l7a1045_voice *vptr)
else
{
const uint32_t multiplier = (((m_regs[L6028_Loop_Start][m_cur_channel] & 0xffff'0000) >> 16) ^ 0xffff) + 1;
- const uint32_t base = m_regs[2][m_cur_channel] & 0xffff;
+ const uint32_t base = m_regs[L6028_Loop_Start][m_cur_channel] & 0xffff;
vptr->loop_start = (base * multiplier) >> 12;
}
}
uint16_t l7a1045_sound_device::control_r()
{
- return 0;
+ return m_control;
}
// bit 0 = set for wave DMA transfers
// bit 1 = set for wave DMA transfers
@@ -572,6 +578,8 @@ void l7a1045_sound_device::control_w(uint16_t data)
LOGMASKED(LOG_REGISTERS, "%s: %04x to control (ch %d)\n", tag(), data, m_cur_channel);
+ m_control = data;
+
if (BIT(data, CONTROL_KEY_ON))
{
l7a1045_voice* const vptr = &m_voice[m_cur_channel];
@@ -588,7 +596,16 @@ void l7a1045_sound_device::control_w(uint16_t data)
LOGMASKED(LOG_KEYON, " raw 6 %012llx 7 %012llx\n", m_regs[6][m_cur_channel], m_regs[7][m_cur_channel]);
}
- m_drq_handler(BIT(data, CONTROL_DMA_START));
+ if (BIT(m_control, CONTROL_DMA_START))
+ {
+ // 8x the sample period
+ const auto time = attotime::from_ticks(64, clock());
+ m_dma_timer->adjust(time, 0, time);
+ }
+ else
+ {
+ m_dma_timer->adjust(attotime::never);
+ }
}
void l7a1045_sound_device::atomic_w(uint16_t data)
@@ -601,6 +618,8 @@ uint16_t l7a1045_sound_device::dma_r16_cb()
{
const offs_t byteoffs = (m_voice[0].start << 1) + (m_voice[0].pos << 1);
+ m_drq_handler(CLEAR_LINE);
+
m_voice[0].pos++;
if (m_voice[0].sample_type == 1)
{
@@ -616,6 +635,8 @@ void l7a1045_sound_device::dma_w16_cb(uint16_t data)
{
const offs_t byteoffs = (m_voice[0].start << 1) + (m_voice[0].pos << 1);
+ m_drq_handler(CLEAR_LINE);
+
if (m_voice[0].sample_type == 1)
{
m_rom_cache.write_word(byteoffs, data);
@@ -629,3 +650,8 @@ void l7a1045_sound_device::dma_w16_cb(uint16_t data)
m_voice[0].pos++;
}
+
+TIMER_CALLBACK_MEMBER(l7a1045_sound_device::dma_timer_callback)
+{
+ m_drq_handler(ASSERT_LINE);
+}
diff --git a/src/devices/sound/l7a1045_l6028_dsp_a.h b/src/devices/sound/l7a1045_l6028_dsp_a.h
index 3ec43c977ab..177569569df 100644
--- a/src/devices/sound/l7a1045_l6028_dsp_a.h
+++ b/src/devices/sound/l7a1045_l6028_dsp_a.h
@@ -4,6 +4,9 @@
#define MAME_SOUND_L7A1045_L6028_DSP_A_H
#pragma once
+
+#include "machine/timer.h"
+
class l7a1045_sound_device : public device_t,
public device_sound_interface,
public device_memory_interface
@@ -79,6 +82,8 @@ private:
sound_stream *m_stream;
l7a1045_voice m_voice[NUM_VOICES];
uint32_t m_key;
+ uint16_t m_control;
+ emu_timer *m_dma_timer;
uint8_t m_cur_channel;
uint8_t m_cur_register;
@@ -99,6 +104,8 @@ private:
void atomic_w(uint16_t data);
void recalc_loop_start(l7a1045_voice *vptr);
+
+ TIMER_CALLBACK_MEMBER(dma_timer_callback);
};
DECLARE_DEVICE_TYPE(L7A1045, l7a1045_sound_device)