summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2025-07-12 15:34:23 +0200
committer Dirk Best <mail@dirk-best.de>2025-07-12 17:24:02 +0200
commitef7add9d10b218a1dd75f2f0266c621f955a25eb (patch)
treee89d5a128987180bb9a70bb12f13aad150529ec7 /src/devices/machine
parent7c7e7cef68872bef0a3f38611745fc2f8aeebe8b (diff)
cdtv: Subcode supportcdtv_subcode
Diffstat (limited to 'src/devices/machine')
-rw-r--r--src/devices/machine/6525tpi.cpp199
-rw-r--r--src/devices/machine/6525tpi.h18
-rw-r--r--src/devices/machine/cr511b.cpp192
-rw-r--r--src/devices/machine/cr511b.h15
4 files changed, 220 insertions, 204 deletions
diff --git a/src/devices/machine/6525tpi.cpp b/src/devices/machine/6525tpi.cpp
index addebf837b1..ed399e0f27c 100644
--- a/src/devices/machine/6525tpi.cpp
+++ b/src/devices/machine/6525tpi.cpp
@@ -119,23 +119,17 @@ tpi6525_device::tpi6525_device(const machine_config &mconfig, const char *tag, d
m_out_cb_cb(*this),
m_port_a(0),
m_ddr_a(0),
- m_in_a(0),
+ m_in_a(0xff),
m_port_b(0),
m_ddr_b(0),
- m_in_b(0),
+ m_in_b(0xff),
m_port_c(0),
m_ddr_c(0),
- m_in_c(0),
- m_ca_level(0),
- m_cb_level(0),
- m_interrupt_level(0),
+ m_in_c(0xff),
m_cr(0),
- m_air(0)
+ m_air(0),
+ m_irq_latch(0)
{
- for (auto & elem : m_irq_level)
- {
- elem = 0;
- }
}
//-------------------------------------------------
@@ -144,12 +138,7 @@ tpi6525_device::tpi6525_device(const machine_config &mconfig, const char *tag, d
void tpi6525_device::device_start()
{
- /* setup some initial values */
- m_in_a = 0xff;
- m_in_b = 0xff;
- m_in_c = 0xff;
-
- /* register for state saving */
+ // register for state saving
save_item(NAME(m_port_a));
save_item(NAME(m_ddr_a));
save_item(NAME(m_in_a));
@@ -159,12 +148,9 @@ void tpi6525_device::device_start()
save_item(NAME(m_port_c));
save_item(NAME(m_ddr_c));
save_item(NAME(m_in_c));
- save_item(NAME(m_ca_level));
- save_item(NAME(m_cb_level));
- save_item(NAME(m_interrupt_level));
save_item(NAME(m_cr));
save_item(NAME(m_air));
- save_item(NAME(m_irq_level));
+ save_item(NAME(m_irq_latch));
}
//-------------------------------------------------
@@ -182,108 +168,74 @@ void tpi6525_device::device_reset()
void tpi6525_device::set_interrupt()
{
- if (!m_interrupt_level && (m_air != 0))
+ if ((BIT(m_irq_latch, 5) == 0) && (m_air != 0))
{
- m_interrupt_level = 1;
+ m_irq_latch |= 1 << 5;
DBG_LOG(machine(), 3, "tpi6525", ("%s set interrupt\n", tag()));
- m_out_irq_cb(m_interrupt_level);
+ m_out_irq_cb(1);
}
}
void tpi6525_device::clear_interrupt()
{
- if (m_interrupt_level && (m_air == 0))
+ if ((BIT(m_irq_latch, 5) == 1) && (m_air == 0))
{
- m_interrupt_level = 0;
+ m_irq_latch &= ~(1 << 5);
DBG_LOG(machine(), 3, "tpi6525", ("%s clear interrupt\n", tag()));
- m_out_irq_cb(m_interrupt_level);
- }
-}
-
-
-void tpi6525_device::i0_w(int state)
-{
- if (INTERRUPT_MODE && (state != m_irq_level[0]))
- {
- m_irq_level[0] = state;
-
- if ((state == 0) && !(m_air & 1) && (m_ddr_c & 1))
- {
- m_air |= 1;
- set_interrupt();
- }
+ m_out_irq_cb(0);
}
}
-void tpi6525_device::i1_w(int state)
+void tpi6525_device::portc_line_w(int line, int state)
{
- if (INTERRUPT_MODE && (state != m_irq_level[1]))
- {
- m_irq_level[1] = state;
-
- if ((state == 0) && !(m_air & 2) && (m_ddr_c & 2))
- {
- m_air |= 2;
- set_interrupt();
- }
- }
-}
-
+ bool active = false;
-void tpi6525_device::i2_w(int state)
-{
- if (INTERRUPT_MODE && (state != m_irq_level[2]))
+ switch (line)
{
- m_irq_level[2] = state;
-
- if ((state == 0) && !(m_air & 4) && (m_ddr_c & 4))
- {
- m_air |= 4;
- set_interrupt();
- }
+ case 0:
+ case 1:
+ case 2:
+ active = (state == 0) && (BIT(m_in_c, line) == 1);
+ break;
+
+ case 3:
+ if (INTERRUPT3_RISING_EDGE)
+ active = (state == 1) && (BIT(m_in_c, line) == 0);
+ else
+ active = (state == 0) && (BIT(m_in_c, line) == 1);
+ break;
+
+ case 4:
+ if (INTERRUPT4_RISING_EDGE)
+ active = (state == 1) && (BIT(m_in_c, line) == 0);
+ else
+ active = (state == 0) && (BIT(m_in_c, line) == 1);
+ break;
}
-}
+ m_in_c &= ~(1 << line);
+ m_in_c |= state << line;
-void tpi6525_device::i3_w(int state)
-{
- if (INTERRUPT_MODE && (state != m_irq_level[3]))
+ if (INTERRUPT_MODE && active)
{
- m_irq_level[3] = state;
+ m_irq_latch |= 1 << line;
- if (((INTERRUPT3_RISING_EDGE && (state == 1))
- || (!INTERRUPT3_RISING_EDGE && (state == 0)))
- && !(m_air & 8) && (m_ddr_c & 8))
+ // set interrupt if not yet active and not masked
+ if (BIT(m_air, line) == 0 && BIT(m_ddr_c, line) == 1)
{
- m_air |= 8;
+ m_air |= 1 << line;
set_interrupt();
}
}
}
-void tpi6525_device::i4_w(int state)
-{
- if (INTERRUPT_MODE && (state != m_irq_level[4]) )
- {
- m_irq_level[4] = state;
-
- if (((INTERRUPT4_RISING_EDGE && (state == 1))
- ||(!INTERRUPT4_RISING_EDGE&&(state == 0)))
- && !(m_air & 0x10) && (m_ddr_c & 0x10))
- {
- m_air |= 0x10;
- set_interrupt();
- }
- }
-}
-
uint8_t tpi6525_device::pa_r()
{
uint8_t data = m_in_a;
@@ -370,16 +322,7 @@ uint8_t tpi6525_device::read(offs_t offset)
case 2:
if (INTERRUPT_MODE)
{
- data = 0;
-
- if (m_irq_level[0]) data |= 0x01;
- if (m_irq_level[1]) data |= 0x02;
- if (m_irq_level[2]) data |= 0x04;
- if (m_irq_level[3]) data |= 0x08;
- if (m_irq_level[4]) data |= 0x10;
- if (!m_interrupt_level) data |= 0x20;
- if (m_ca_level) data |= 0x40;
- if (m_cb_level) data |= 0x80;
+ data = m_irq_latch;
}
else
{
@@ -413,36 +356,22 @@ uint8_t tpi6525_device::read(offs_t offset)
case 7: /* air */
if (PRIORIZED_INTERRUPTS)
{
- if (m_air & 0x10)
- {
- data = 0x10;
- m_air &= ~0x10;
- }
- else if (m_air & 8)
- {
- data = 8;
- m_air &= ~8;
- }
- else if (m_air & 4)
- {
- data = 4;
- m_air &= ~4;
- }
- else if (m_air & 2)
- {
- data = 2;
- m_air &= ~2;
- }
- else if (m_air & 1)
+ for (int i = 4; i >= 0; i--)
{
- data = 1;
- m_air &= ~1;
+ if (BIT(m_air, i))
+ {
+ data = 1 << i;
+ m_air &= ~(1 << i);
+ m_irq_latch &= ~(1 << i);
+ break;
+ }
}
}
else
{
data = m_air;
m_air = 0;
+ m_irq_latch &= 0xe0;
}
clear_interrupt();
@@ -481,12 +410,10 @@ void tpi6525_device::write(offs_t offset, uint8_t data)
}
else
{
- // clear latches
- if (BIT(data, 0) == 0) m_irq_level[0] = 1;
- if (BIT(data, 1) == 0) m_irq_level[1] = 1;
- if (BIT(data, 2) == 0) m_irq_level[2] = 1;
- if (BIT(data, 3) == 0) m_irq_level[3] = INTERRUPT3_RISING_EDGE ? 0 : 1;
- if (BIT(data, 4) == 0) m_irq_level[4] = INTERRUPT4_RISING_EDGE ? 0 : 1;
+ for (int i = 0; i <= 4; i++)
+ if (BIT(data, i) == 0)
+ m_irq_latch &= ~(1 << i);
+
}
break;
@@ -514,18 +441,20 @@ void tpi6525_device::write(offs_t offset, uint8_t data)
{
if (CA_MANUAL_OUT)
{
- if (m_ca_level != CA_MANUAL_LEVEL)
+ if (BIT(m_irq_latch, 6) != CA_MANUAL_LEVEL)
{
- m_ca_level = CA_MANUAL_LEVEL;
- m_out_ca_cb(m_ca_level);
+ m_irq_latch &= ~(1 << 6);
+ m_irq_latch |= CA_MANUAL_LEVEL << 6;
+ m_out_ca_cb(BIT(m_irq_latch, 6));
}
}
if (CB_MANUAL_OUT)
{
- if (m_cb_level != CB_MANUAL_LEVEL)
+ if (BIT(m_irq_latch, 7) != CB_MANUAL_LEVEL)
{
- m_cb_level = CB_MANUAL_LEVEL;
- m_out_cb_cb(m_cb_level);
+ m_irq_latch &= ~(1 << 7);
+ m_irq_latch |= CB_MANUAL_LEVEL << 7;
+ m_out_ca_cb(BIT(m_irq_latch, 7));
}
}
}
diff --git a/src/devices/machine/6525tpi.h b/src/devices/machine/6525tpi.h
index c2487bde39b..3aa576b3eb6 100644
--- a/src/devices/machine/6525tpi.h
+++ b/src/devices/machine/6525tpi.h
@@ -56,12 +56,6 @@ public:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- void i0_w(int state);
- void i1_w(int state);
- void i2_w(int state);
- void i3_w(int state);
- void i4_w(int state);
-
uint8_t pa_r();
uint8_t pb_r();
uint8_t pc_r();
@@ -78,6 +72,12 @@ public:
void pb6_w(int state) { port_line_w(m_in_b, 6, state); }
void pb7_w(int state) { port_line_w(m_in_b, 7, state); }
+ void pc0_w(int state) { portc_line_w(0, state); }
+ void pc1_w(int state) { portc_line_w(1, state); }
+ void pc2_w(int state) { portc_line_w(2, state); }
+ void pc3_w(int state) { portc_line_w(3, state); }
+ void pc4_w(int state) { portc_line_w(4, state); }
+
protected:
// device-level overrides
virtual void device_start() override ATTR_COLD;
@@ -103,16 +103,16 @@ private:
uint8_t m_port_b, m_ddr_b, m_in_b;
uint8_t m_port_c, m_ddr_c, m_in_c;
- uint8_t m_ca_level, m_cb_level, m_interrupt_level;
-
uint8_t m_cr;
uint8_t m_air;
- uint8_t m_irq_level[5];
+ uint8_t m_irq_latch;
void set_interrupt();
void clear_interrupt();
+ void portc_line_w(int line, int state);
+
// helper function to write a single line
static void port_line_w(uint8_t &port, int line, int state);
};
diff --git a/src/devices/machine/cr511b.cpp b/src/devices/machine/cr511b.cpp
index 7f52ced1e20..8d0f6261430 100644
--- a/src/devices/machine/cr511b.cpp
+++ b/src/devices/machine/cr511b.cpp
@@ -22,11 +22,12 @@
#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 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 LOG_SUBCODE (1 << 6)
#define VERBOSE (LOG_GENERAL | LOG_CMD | LOG_PARAM)
@@ -52,6 +53,8 @@ cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, dev
m_drq_cb(*this),
m_dten_cb(*this),
m_scor_cb(*this),
+ m_sbcp_cb(*this),
+ m_subcode_data_cb(*this),
m_input_fifo_pos(0),
m_output_fifo_pos(0),
m_output_fifo_length(0),
@@ -88,8 +91,10 @@ void cr511b_device::device_start()
cdrom_image_device::device_start();
m_frame_timer = timer_alloc(FUNC(cr511b_device::frame_cb), this);
+ m_subcode_timer = timer_alloc(FUNC(cr511b_device::subcode_cb), this);
m_stch_timer = timer_alloc(FUNC(cr511b_device::stch), this);
m_sten_timer = timer_alloc(FUNC(cr511b_device::sten), this);
+ m_scor_timer = timer_alloc(FUNC(cr511b_device::scor), 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);
@@ -102,6 +107,9 @@ void cr511b_device::device_start()
save_item(NAME(m_output_fifo_length));
save_item(NAME(m_status));
save_item(NAME(m_sector_size));
+ save_item(NAME(m_subcode_count));
+ save_item(NAME(m_subcode_buffer));
+ save_item(NAME(m_subcode_valid));
save_item(NAME(m_transfer_lba));
save_item(NAME(m_transfer_sectors));
save_item(NAME(m_transfer_length));
@@ -210,16 +218,52 @@ TIMER_CALLBACK_MEMBER(cr511b_device::frame_cb)
}
else if (m_status & STATUS_PLAYING)
{
- // TODO: subcode handling
- m_scor_cb(0);
- m_scor_cb(1);
+ if (!m_cdda->audio_paused())
+ {
+ uint32_t lba = m_cdda->get_audio_lba();
+
+ LOGMASKED(LOG_SUBCODE, "Fetching new subchannel data for sector %d\n", lba);
+
+ uint32_t subsize = get_toc().tracks[get_track(lba)].subsize;
+
+ m_subcode_count = 0;
+ m_subcode_valid = read_subcode(lba, m_subcode_buffer) && (subsize == 96);
+
+ if (m_subcode_valid)
+ m_subcode_timer->adjust(attotime::zero, 0, attotime::from_hz(75 * 98));
+ }
+
+ m_scor_timer->adjust(attotime::from_usec(64), 1); // TODO: Timing
+ }
+}
+
+TIMER_CALLBACK_MEMBER(cr511b_device::subcode_cb)
+{
+ if (!m_cdda->audio_paused())
+ {
+ // we skip the first two (sync) bytes
+ if (m_subcode_count > 1 && m_subcode_count < 98)
+ {
+ uint8_t data = m_subcode_buffer[m_subcode_count - 2];
+
+ LOGMASKED(LOG_SUBCODE, "Subcode %d = %02x\n", m_subcode_count - 2, data);
+
+ m_subcode_data_cb(bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7));
+
+ m_sbcp_cb(0);
+ m_sbcp_cb(1);
+ }
+
+ m_subcode_count++;
}
}
TIMER_CALLBACK_MEMBER(cr511b_device::stch)
{
- m_stch_cb(1);
- m_stch_cb(0);
+ m_sten_cb(param);
+
+ if (param == 0)
+ m_stch_timer->adjust(attotime::from_usec(64 / 64), 1);
}
void cr511b_device::status_change(uint8_t status)
@@ -233,16 +277,19 @@ void cr511b_device::status_change(uint8_t status)
else
m_frame_timer->adjust(attotime::never);
- m_stch_timer->adjust(attotime::from_usec(64 * 3)); // TODO
+ if (!(m_status & STATUS_PLAYING))
+ m_subcode_timer->adjust(attotime::never);
+
+ m_stch_timer->adjust(attotime::from_usec(64 * 3), 0); // TODO: Timing
}
}
TIMER_CALLBACK_MEMBER(cr511b_device::sten)
{
- m_status_ready = true;
+ m_sten_cb(param);
- m_sten_cb(0);
- m_sten_cb(1);
+ if (param == 0)
+ m_sten_timer->adjust(attotime::from_usec(64 / 64), 1);
}
void cr511b_device::status_enable(uint8_t output_length)
@@ -257,10 +304,19 @@ void cr511b_device::status_enable(uint8_t output_length)
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_status_ready = true;
+ m_sten_timer->adjust(attotime::from_usec(64 * 4), 0); // TODO: Timing
}
}
+TIMER_CALLBACK_MEMBER(cr511b_device::scor)
+{
+ m_scor_cb(param);
+
+ if (param == 1)
+ m_scor_timer->adjust(attotime::from_usec(64), 0);
+}
+
void cr511b_device::audio_end_cb(int state)
{
if (!state)
@@ -271,6 +327,47 @@ void cr511b_device::audio_end_cb(int state)
status_change(m_status & ~STATUS_PLAYING);
}
+void cr511b_device::play_audio(uint32_t start, uint32_t end)
+{
+ 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 < end)
+ {
+ 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, end);
+
+ m_cdda->start_audio(start, end - start);
+
+ 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, end);
+
+ status_change(m_status | STATUS_ERROR);
+ }
+}
+
uint8_t cr511b_device::read()
{
uint8_t data = 0xff;
@@ -439,8 +536,15 @@ 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");
+ 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);
+
+ // play to the end of the disc?
+ if (end == 0x7fffff)
+ end = get_track_start(0xaa) - 1;
+
+ play_audio(start, end);
+ status_enable(0);
}
void cr511b_device::cmd_play_msf()
@@ -448,53 +552,17 @@ 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);
+ uint32_t start_msf = (m_input_fifo[1] << 16) | (m_input_fifo[2] << 8) | (m_input_fifo[3] << 0);
+ uint32_t end_msf = (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);
+ int32_t start = start_msf ? msf_to_lba(start_msf) : 0;
+ int32_t end = end_msf ? msf_to_lba(end_msf) : 0;
// 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);
- }
+ end = get_track_start(0xaa) - 1;
+ play_audio(start, end);
status_enable(0);
}
@@ -508,6 +576,10 @@ void cr511b_device::cmd_play_track()
uint8_t end_track = m_input_fifo[3];
uint8_t end_index = m_input_fifo[4]; // TODO
+ // cd+g/cd+midi mode sends an all 0x00 cmd after starting the motor?
+ if (start_track == 0 || end_track == 0)
+ return;
+
uint32_t start_lba = get_track_start(start_track - 1);
uint32_t end_lba = get_track_start(end_track - 1) - 1;
@@ -515,7 +587,7 @@ void cr511b_device::cmd_play_track()
m_cdda->start_audio(start_lba, end_lba - start_lba);
- status_change(m_status | STATUS_PLAYING | STATUS_MOTOR);
+ status_change(m_status | STATUS_PLAYING | STATUS_MOTOR);
status_enable(0);
}
diff --git a/src/devices/machine/cr511b.h b/src/devices/machine/cr511b.h
index e773c8b1f82..b5c7727872e 100644
--- a/src/devices/machine/cr511b.h
+++ b/src/devices/machine/cr511b.h
@@ -50,6 +50,8 @@ public:
auto drq_cb() { return m_drq_cb.bind(); }
auto dten_cb() { return m_dten_cb.bind(); }
auto scor_cb() { return m_scor_cb.bind(); }
+ auto sbcp_cb() { return m_sbcp_cb.bind(); }
+ auto subcode_data_cb() { return m_subcode_data_cb.bind(); }
uint8_t read();
void write(uint8_t data);
@@ -72,6 +74,7 @@ private:
int size_to_track_type();
TIMER_CALLBACK_MEMBER(frame_cb);
+ TIMER_CALLBACK_MEMBER(subcode_cb);
TIMER_CALLBACK_MEMBER(stch);
void status_change(uint8_t status);
@@ -79,7 +82,10 @@ private:
TIMER_CALLBACK_MEMBER(sten);
void status_enable(uint8_t output_length);
+ TIMER_CALLBACK_MEMBER(scor);
+
void audio_end_cb(int state);
+ void play_audio(uint32_t start, uint32_t end);
// commands
void cmd_seek();
@@ -124,10 +130,15 @@ private:
devcb_write_line m_drq_cb;
devcb_write_line m_dten_cb;
devcb_write_line m_scor_cb;
+ devcb_write_line m_sbcp_cb;
+ devcb_write8 m_subcode_data_cb;
emu_timer *m_frame_timer;
+ emu_timer *m_subcode_timer;
+
emu_timer *m_stch_timer;
emu_timer *m_sten_timer;
+ emu_timer *m_scor_timer;
uint8_t m_input_fifo[16];
uint8_t m_input_fifo_pos;
@@ -139,6 +150,10 @@ private:
uint8_t m_status;
uint16_t m_sector_size;
+ uint8_t m_subcode_count;
+ uint8_t m_subcode_buffer[96];
+ bool m_subcode_valid;
+
uint32_t m_transfer_lba;
uint16_t m_transfer_sectors;
uint32_t m_transfer_length;