summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author MooglyGuy <MooglyGuy@users.noreply.github.com>2021-12-25 13:49:11 +0100
committer GitHub <noreply@github.com>2021-12-25 13:49:11 +0100
commit022361c6830f6b60c050f019f8e660da9f8ce3d9 (patch)
tree2f697ed0bc3c4b3dfbde9a8432d9e51f24752d26
parent5594736bd550264a69cef454215c8689ea3addbc (diff)
Complete re-write of Philips CD-i CDIC handling; re-promoted to working (#9038)
* -cdi: Significantly improved compatibility and re-promoted to working. [Ryan Holtz, CD-i Fan]
-rw-r--r--src/mame/drivers/cdi.cpp108
-rw-r--r--src/mame/includes/cdi.h3
-rw-r--r--src/mame/machine/cdicdic.cpp1492
-rw-r--r--src/mame/machine/cdicdic.h176
-rw-r--r--src/mame/machine/cdislavehle.cpp119
-rw-r--r--src/mame/machine/cdislavehle.h24
6 files changed, 915 insertions, 1007 deletions
diff --git a/src/mame/drivers/cdi.cpp b/src/mame/drivers/cdi.cpp
index f5579cf659a..37095ebe8ac 100644
--- a/src/mame/drivers/cdi.cpp
+++ b/src/mame/drivers/cdi.cpp
@@ -80,63 +80,59 @@ TODO:
void cdi_state::cdimono1_mem(address_map &map)
{
- map(0x00000000, 0x0007ffff).ram().share("mcd212:planea");
- map(0x00200000, 0x0027ffff).ram().share("mcd212:planeb");
- map(0x00300000, 0x00303bff).rw(m_cdic, FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
+ map(0x000000, 0xffffff).rw(FUNC(cdi_state::bus_error_r), FUNC(cdi_state::bus_error_w));
+ map(0x000000, 0x07ffff).ram().share("mcd212:planea");
+ map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
+ map(0x300000, 0x303bff).rw(m_cdic, FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
#if ENABLE_UART_PRINTING
- map(0x00301400, 0x00301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
+ map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
#endif
- map(0x00303c00, 0x00303fff).rw(m_cdic, FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
- map(0x00310000, 0x00317fff).rw(m_slave_hle, FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
- map(0x00318000, 0x0031ffff).noprw();
- map(0x00320000, 0x00323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
- map(0x00400000, 0x0047ffff).rom().region("maincpu", 0);
- map(0x004fffe0, 0x004fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
- map(0x00500000, 0x0057ffff).ram();
- map(0x00580000, 0x00cfffff).noprw();
- map(0x00d00000, 0x00dfffff).ram(); // DVC RAM block 1
- map(0x00e00000, 0x00e7ffff).rw(FUNC(cdi_state::dvc_r), FUNC(cdi_state::dvc_w));
- map(0x00e80000, 0x00efffff).ram(); // DVC RAM block 2
- map(0x00f00000, 0x00ffffff).noprw();
+ map(0x303c00, 0x303fff).rw(m_cdic, FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
+ map(0x310000, 0x317fff).rw(m_slave_hle, FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
+ map(0x318000, 0x31ffff).noprw();
+ map(0x320000, 0x323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
+ map(0x400000, 0x47ffff).rom().region("maincpu", 0);
+ map(0x4fffe0, 0x4fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
+ map(0x500000, 0x57ffff).ram();
+ map(0xd00000, 0xdfffff).ram(); // DVC RAM block 1
+ map(0xe00000, 0xe7ffff).rw(FUNC(cdi_state::dvc_r), FUNC(cdi_state::dvc_w));
+ map(0xe80000, 0xefffff).ram(); // DVC RAM block 2
}
void cdi_state::cdimono2_mem(address_map &map)
{
- map(0x00000000, 0x0007ffff).ram().share("mcd212:planea");
- map(0x00200000, 0x0027ffff).ram().share("mcd212:planeb");
+ map(0x000000, 0x07ffff).ram().share("mcd212:planea");
+ map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
#if ENABLE_UART_PRINTING
- map(0x00301400, 0x00301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
+ map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
#endif
- //map(0x00300000, 0x00303bff).rw("cdic", FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
- //map(0x00303c00, 0x00303fff).rw("cdic", FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
- //map(0x00310000, 0x00317fff).rw("slave", FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
- //map(0x00318000, 0x0031ffff).noprw();
- map(0x00320000, 0x00323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
- map(0x00400000, 0x0047ffff).rom().region("maincpu", 0);
- map(0x004fffe0, 0x004fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
- //map(0x00500000, 0x0057ffff).ram();
- map(0x00500000, 0x00ffffff).noprw();
- //map(0x00e00000, 0x00efffff).ram();
+ //map(0x300000, 0x303bff).rw("cdic", FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
+ //map(0x303c00, 0x303fff).rw("cdic", FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
+ //map(0x310000, 0x317fff).rw("slave", FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
+ //map(0x318000, 0x31ffff).noprw();
+ map(0x320000, 0x323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
+ map(0x400000, 0x47ffff).rom().region("maincpu", 0);
+ map(0x4fffe0, 0x4fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
}
void cdi_state::cdi910_mem(address_map &map)
{
- map(0x00000000, 0x0007ffff).ram().share("mcd212:planea");
- map(0x00180000, 0x001fffff).rom().region("maincpu", 0); // boot vectors point here
+ map(0x000000, 0x07ffff).ram().share("mcd212:planea");
+ map(0x180000, 0x1fffff).rom().region("maincpu", 0); // boot vectors point here
- map(0x00200000, 0x0027ffff).ram().share("mcd212:planeb");
+ map(0x200000, 0x27ffff).ram().share("mcd212:planeb");
#if ENABLE_UART_PRINTING
- map(0x00301400, 0x00301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
+ map(0x301400, 0x301403).r(m_maincpu, FUNC(scc68070_device::uart_loopback_enable));
#endif
-// map(0x00300000, 0x00303bff).rw("cdic", FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
-// map(0x00303c00, 0x00303fff).rw("cdic", FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
-// map(0x00310000, 0x00317fff).rw("slave_hle", FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
-// map(0x00318000, 0x0031ffff).noprw();
- map(0x00320000, 0x00323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
- map(0x004fffe0, 0x004fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
-// map(0x00500000, 0x0057ffff).ram();
- map(0x00500000, 0x00ffffff).noprw();
-// map(0x00e00000, 0x00efffff).ram(); // DVC
+// map(0x300000, 0x303bff).rw("cdic", FUNC(cdicdic_device::ram_r), FUNC(cdicdic_device::ram_w));
+// map(0x303c00, 0x303fff).rw("cdic", FUNC(cdicdic_device::regs_r), FUNC(cdicdic_device::regs_w));
+// map(0x310000, 0x317fff).rw("slave_hle", FUNC(cdislave_hle_device::slave_r), FUNC(cdislave_hle_device::slave_w));
+// map(0x318000, 0x31ffff).noprw();
+ map(0x320000, 0x323fff).rw("mk48t08", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write)).umask16(0xff00); /* nvram (only low bytes used) */
+ map(0x4fffe0, 0x4fffff).rw(m_mcd212, FUNC(mcd212_device::regs_r), FUNC(mcd212_device::regs_w));
+// map(0x500000, 0x57ffff).ram();
+ map(0x500000, 0xffffff).noprw();
+// map(0xe00000, 0xefffff).ram(); // DVC
}
@@ -266,6 +262,32 @@ void quizard_state::machine_reset()
/**********************
+* BERR Handling *
+**********************/
+
+uint16_t cdi_state::bus_error_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ {
+ m_maincpu->set_buserror_details(offset*2, true, m_maincpu->get_fc());
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
+ return 0xff;
+}
+
+void cdi_state::bus_error_w(offs_t offset, uint16_t data)
+{
+ if(!machine().side_effects_disabled())
+ {
+ m_maincpu->set_buserror_details(offset*2, false, m_maincpu->get_fc());
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
+}
+
+
+/**********************
* Quizard Protection *
**********************/
@@ -885,7 +907,7 @@ ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
// BIOS / System
-CONS( 1991, cdimono1, 0, 0, cdimono1, cdi, cdi_state, empty_init, "Philips", "CD-i (Mono-I) (PAL)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+CONS( 1991, cdimono1, 0, 0, cdimono1, cdi, cdi_state, empty_init, "Philips", "CD-i (Mono-I) (PAL)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
CONS( 1991, cdimono2, 0, 0, cdimono2, cdimono2, cdi_state, empty_init, "Philips", "CD-i (Mono-II) (NTSC)", MACHINE_NOT_WORKING )
CONS( 1991, cdi910, 0, 0, cdi910, cdimono2, cdi_state, empty_init, "Philips", "CD-i 910-17P Mini-MMC (PAL)", MACHINE_NOT_WORKING )
CONS( 1991, cdi490a, 0, 0, cdimono1, cdi, cdi_state, empty_init, "Philips", "CD-i 490", MACHINE_NOT_WORKING )
diff --git a/src/mame/includes/cdi.h b/src/mame/includes/cdi.h
index a77b8390b27..5b9f88e456b 100644
--- a/src/mame/includes/cdi.h
+++ b/src/mame/includes/cdi.h
@@ -64,6 +64,9 @@ private:
uint16_t dvc_r(offs_t offset, uint16_t mem_mask = ~0);
void dvc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bus_error_r(offs_t offset);
+ void bus_error_w(offs_t offset, uint16_t data);
+
required_shared_ptr<uint16_t> m_planea;
optional_device<cdislave_hle_device> m_slave_hle;
optional_device<m68hc05c8_device> m_servo;
diff --git a/src/mame/machine/cdicdic.cpp b/src/mame/machine/cdicdic.cpp
index f7d5d6bb1bc..098b3f4769a 100644
--- a/src/mame/machine/cdicdic.cpp
+++ b/src/mame/machine/cdicdic.cpp
@@ -17,7 +17,7 @@ STATUS:
TODO:
-- Decapping and proper emulation.
+- Work out more low-level functionality.
*******************************************************************************/
@@ -39,196 +39,103 @@ TODO:
#define LOG_RAM (1 << 9)
#define LOG_ALL (LOG_DECODES | LOG_SAMPLES | LOG_COMMANDS | LOG_SECTORS | LOG_IRQS | LOG_READS | LOG_WRITES | LOG_UNKNOWNS | LOG_RAM)
-#define VERBOSE (LOG_ALL)
+#define VERBOSE (0)
#include "logmacro.h"
// device type definition
DEFINE_DEVICE_TYPE(CDI_CDIC, cdicdic_device, "cdicdic", "CD-i CDIC")
-
//**************************************************************************
-// GLOBAL VARIABLES
+// STATIC MEMBERS
//**************************************************************************
-const int32_t cdicdic_device::s_cdic_adpcm_filter_coef[5][2] =
+const int16_t cdicdic_device::s_xa_filter_coef[4][2] =
{
- { 0,0 },
- { 60,0 },
- { 115,-52 },
- { 98,-55 },
- { 122,-60 },
+ { 0x000, 0x000 },
+ { 0x0F0, 0x000 },
+ { 0x1CC, -0x0D0 },
+ { 0x188, -0x0DC }
};
-//**************************************************************************
-// INLINES
-//**************************************************************************
+const int32_t cdicdic_device::s_samples_per_sector = 18 * 28 * 2;
-int cdicdic_device::is_valid_sample_buf(uint16_t addr) const
+const uint16_t cdicdic_device::s_crc_ccitt_table[256] =
{
- const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr;
- if (cdram8[10] != 0xff)
- {
- return 1;
- }
- return 0;
-}
-
-double cdicdic_device::sample_buf_freq(uint16_t addr) const
-{
- const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr + 8;
- switch (cdram8[2] & 0x3f)
- {
- case 0:
- case 1:
- case 16:
- case 17:
- return clock2() / 512.0f;
-
- case 4:
- case 5:
- return clock2() / 1024.0f;
-
- default:
- return clock2() / 1024.0f;
- }
-}
-
-int cdicdic_device::sample_buf_size(uint16_t addr) const
-{
- const uint8_t *cdram8 = ((uint8_t*)m_ram.get()) + addr + 8;
- switch (cdram8[2] & 0x3f)
- {
- case 0:
- case 4:
- return 4;
-
- case 1:
- case 5:
- case 16:
- return 2;
-
- case 17:
- return 1;
-
- default:
- return 2;
- }
-}
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
-static inline int16_t clamp(int16_t in)
-{
- return in;
-}
+#define CRC_CCITT_ROUND(accum, data) (((accum << 8) | data) ^ s_crc_ccitt_table[accum >> 8])
//**************************************************************************
// MEMBER FUNCTIONS
//**************************************************************************
-uint32_t cdicdic_device::increment_cdda_frame_bcd(uint32_t bcd)
+void cdicdic_device::decode_xa_mono(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
{
- uint8_t nybbles[6] =
- {
- static_cast<uint8_t>(bcd & 0x0000000f),
- static_cast<uint8_t>((bcd & 0x000000f0) >> 4),
- static_cast<uint8_t>((bcd & 0x00000f00) >> 8),
- static_cast<uint8_t>((bcd & 0x0000f000) >> 12),
- static_cast<uint8_t>((bcd & 0x000f0000) >> 16),
- static_cast<uint8_t>((bcd & 0x00f00000) >> 20)
- };
- nybbles[0]++;
- if (nybbles[0] == 5 && nybbles[1] == 7)
- {
- nybbles[0] = 0;
- nybbles[1] = 0;
- nybbles[2]++;
- }
- else if (nybbles[0] == 10)
- {
- nybbles[1]++;
- }
- if (nybbles[2] == 10)
- {
- nybbles[3]++;
- nybbles[2] = 0;
- }
- if (nybbles[3] == 6)
- {
- nybbles[4]++;
- nybbles[3] = 0;
- }
- if (nybbles[4] == 10)
- {
- nybbles[5]++;
- nybbles[4] = 0;
- }
- return (nybbles[5] << 20) | (nybbles[4] << 16) | (nybbles[3] << 12) | (nybbles[2] << 8) | (nybbles[1] << 4) | nybbles[0];
-}
-
-uint32_t cdicdic_device::increment_cdda_sector_bcd(uint32_t bcd)
-{
- uint8_t nybbles[6] =
- {
- static_cast<uint8_t>(bcd & 0x0000000f),
- static_cast<uint8_t>((bcd & 0x000000f0) >> 4),
- static_cast<uint8_t>((bcd & 0x00000f00) >> 8),
- static_cast<uint8_t>((bcd & 0x0000f000) >> 12),
- static_cast<uint8_t>((bcd & 0x000f0000) >> 16),
- static_cast<uint8_t>((bcd & 0x00f00000) >> 20)
- };
- nybbles[2]++;
- if (nybbles[2] == 10)
- {
- nybbles[3]++;
- nybbles[2] = 0;
- }
- if (nybbles[3] == 6)
- {
- nybbles[4]++;
- nybbles[3] = 0;
- }
- if (nybbles[4] == 10)
- {
- nybbles[5]++;
- nybbles[4] = 0;
- }
- return (nybbles[5] << 20) | (nybbles[4] << 16) | (nybbles[3] << 12) | (nybbles[2] << 8) | (nybbles[1] << 4) | nybbles[0];
-}
-
-void cdicdic_device::decode_xa_mono(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
-{
- int32_t l0 = cdic_xa_last[0];
- int32_t l1 = cdic_xa_last[1];
+ int16_t l0 = cdic_xa_last[0];
+ int16_t l1 = cdic_xa_last[1];
for (int32_t b = 0; b < 18; b++)
{
for (int32_t s = 0; s < 4; s++)
{
- uint8_t flags = xa[(4 + (s << 1)) ^ 1];
+ uint8_t flags = xa[4 + (s << 1)];
uint8_t shift = flags & 0xf;
- uint8_t filter = flags >> 4;
- int32_t f0 = s_cdic_adpcm_filter_coef[filter][0];
- int32_t f1 = s_cdic_adpcm_filter_coef[filter][1];
+ uint8_t filter = (flags >> 4) & 3;
+ int16_t f0 = s_xa_filter_coef[filter][0];
+ int16_t f1 = s_xa_filter_coef[filter][1];
for (int32_t i = 0; i < 28; i++)
{
- int16_t d = (xa[(16 + (i << 2) + s) ^ 1] & 0xf) << 12;
- d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
+ int16_t d = (xa[16 + (i << 2) + s] & 0xf) << 12;
+ d = (d >> shift) + (((l0 * f0) + (l1 * f1) + 128) >> 8);
*dp = d;
dp++;
l1 = l0;
l0 = d;
}
- flags = xa[(5 + (s << 1)) ^ 1];
+ flags = xa[5 + (s << 1)];
shift = flags & 0xf;
filter = flags >> 4;
- f0 = s_cdic_adpcm_filter_coef[filter][0];
- f1 = s_cdic_adpcm_filter_coef[filter][1];
+ f0 = s_xa_filter_coef[filter][0];
+ f1 = s_xa_filter_coef[filter][1];
for (int32_t i = 0; i < 28; i++)
{
- int16_t d = (xa[(16 + (i << 2) + s) ^ 1] >> 4) << 12;
- d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
+ int16_t d = (xa[16 + (i << 2) + s] >> 4) << 12;
+ d = (d >> shift) + (((l0 * f0) + (l1 * f1) + 128) >> 8);
*dp = d;
dp++;
l1 = l0;
@@ -243,25 +150,25 @@ void cdicdic_device::decode_xa_mono(int32_t *cdic_xa_last, const uint8_t *xa, in
cdic_xa_last[1] = l1;
}
-void cdicdic_device::decode_xa_mono8(int *cdic_xa_last, const unsigned char *xa, signed short *dp)
+void cdicdic_device::decode_xa_mono8(int16_t *cdic_xa_last, const unsigned char *xa, signed short *dp)
{
- int32_t l0 = cdic_xa_last[0];
- int32_t l1 = cdic_xa_last[1];
+ int16_t l0 = cdic_xa_last[0];
+ int16_t l1 = cdic_xa_last[1];
for (int32_t b = 0; b < 18; b++)
{
for (int32_t s = 0; s < 4; s++)
{
- uint8_t flags = xa[(4 + s) ^ 1];
+ uint8_t flags = xa[4 + s];
uint8_t shift = flags & 0xf;
- uint8_t filter = flags >> 4;
- int32_t f0 = s_cdic_adpcm_filter_coef[filter][0];
- int32_t f1 = s_cdic_adpcm_filter_coef[filter][1];
+ uint8_t filter = (flags >> 4) & 3;
+ int16_t f0 = s_xa_filter_coef[filter][0];
+ int16_t f1 = s_xa_filter_coef[filter][1];
for (int32_t i = 0; i < 28; i++)
{
- int16_t d = (xa[(16 + (i << 2) + s) ^ 1] << 8);
- d = clamp((d >> shift) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
+ int16_t d = (xa[16 + (i << 2) + s] << 8);
+ d = (d >> shift) + (((l0 * f0) + (l1 * f1) + 128) >> 8);
*dp = d;
dp++;
l1 = l0;
@@ -276,41 +183,41 @@ void cdicdic_device::decode_xa_mono8(int *cdic_xa_last, const unsigned char *xa,
cdic_xa_last[1] = l1;
}
-void cdicdic_device::decode_xa_stereo(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
+void cdicdic_device::decode_xa_stereo(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
{
- int32_t l0 = cdic_xa_last[0];
- int32_t l1 = cdic_xa_last[1];
- int32_t l2 = cdic_xa_last[2];
- int32_t l3 = cdic_xa_last[3];
+ int16_t l0 = cdic_xa_last[0];
+ int16_t l1 = cdic_xa_last[1];
+ int16_t l2 = cdic_xa_last[2];
+ int16_t l3 = cdic_xa_last[3];
for (int32_t b = 0; b < 18; b++)
{
for (int32_t s = 0; s < 4; s++)
{
- uint8_t flags0 = xa[(4 + (s << 1)) ^ 1];
+ uint8_t flags0 = xa[4 + (s << 1)];
uint8_t shift0 = flags0 & 0xf;
- uint8_t filter0 = flags0 >> 4;
- uint8_t flags1 = xa[(5 + (s << 1)) ^ 1];
+ uint8_t filter0 = (flags0 >> 4) & 3;
+ uint8_t flags1 = xa[5 + (s << 1)];
uint8_t shift1 = flags1 & 0xf;
- uint8_t filter1 = flags1 >> 4;
+ uint8_t filter1 = (flags1 >> 4) & 3;
- int32_t f0 = s_cdic_adpcm_filter_coef[filter0][0];
- int32_t f1 = s_cdic_adpcm_filter_coef[filter0][1];
- int32_t f2 = s_cdic_adpcm_filter_coef[filter1][0];
- int32_t f3 = s_cdic_adpcm_filter_coef[filter1][1];
+ int16_t f0 = s_xa_filter_coef[filter0][0];
+ int16_t f1 = s_xa_filter_coef[filter0][1];
+ int16_t f2 = s_xa_filter_coef[filter1][0];
+ int16_t f3 = s_xa_filter_coef[filter1][1];
for (int32_t i = 0; i < 28; i++)
{
- int16_t d = xa[(16 + (i << 2) + s) ^ 1];
+ int16_t d = xa[16 + (i << 2) + s];
int16_t d0 = (d & 0xf) << 12;
int16_t d1 = (d >> 4) << 12;
- d0 = clamp((d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
+ d0 = (d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 128) >> 8);
*dp = d0;
dp++;
l1 = l0;
l0 = d0;
- d1 = clamp((d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 32) >> 6));
+ d1 = (d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 128) >> 8);
*dp = d1;
dp++;
l3 = l2;
@@ -327,40 +234,40 @@ void cdicdic_device::decode_xa_stereo(int32_t *cdic_xa_last, const uint8_t *xa,
cdic_xa_last[3] = l3;
}
-void cdicdic_device::decode_xa_stereo8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
+void cdicdic_device::decode_xa_stereo8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp)
{
- int32_t l0 = cdic_xa_last[0];
- int32_t l1 = cdic_xa_last[1];
- int32_t l2 = cdic_xa_last[2];
- int32_t l3 = cdic_xa_last[3];
+ int16_t l0 = cdic_xa_last[0];
+ int16_t l1 = cdic_xa_last[1];
+ int16_t l2 = cdic_xa_last[2];
+ int16_t l3 = cdic_xa_last[3];
for (int32_t b = 0; b < 18; b++)
{
for (int32_t s = 0; s < 4; s += 2)
{
- uint8_t flags0 = xa[(4 + s) ^ 1];
+ uint8_t flags0 = xa[4 + s];
uint8_t shift0 = flags0 & 0xf;
- uint8_t filter0 = flags0 >> 4;
- uint8_t flags1 = xa[(5 + s) ^ 1];
+ uint8_t filter0 = (flags0 >> 4) & 3;
+ uint8_t flags1 = xa[5 + s];
uint8_t shift1 = flags1 & 0xf;
- uint8_t filter1 = flags1 >> 4;
- int32_t f0 = s_cdic_adpcm_filter_coef[filter0][0];
- int32_t f1 = s_cdic_adpcm_filter_coef[filter0][1];
- int32_t f2 = s_cdic_adpcm_filter_coef[filter1][0];
- int32_t f3 = s_cdic_adpcm_filter_coef[filter1][1];
+ uint8_t filter1 = (flags1 >> 4) & 3;
+ int16_t f0 = s_xa_filter_coef[filter0][0];
+ int16_t f1 = s_xa_filter_coef[filter0][1];
+ int16_t f2 = s_xa_filter_coef[filter1][0];
+ int16_t f3 = s_xa_filter_coef[filter1][1];
for (int32_t i = 0; i < 28; i++)
{
- int16_t d0 = (xa[(16 + (i << 2) + s + 0) ^ 1] << 8);
- int16_t d1 = (xa[(16 + (i << 2) + s + 1) ^ 1] << 8);
+ int16_t d0 = (xa[16 + (i << 2) + s + 0] << 8);
+ int16_t d1 = (xa[16 + (i << 2) + s + 1] << 8);
- d0 = clamp((d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 32) >> 6));
+ d0 = (d0 >> shift0) + (((l0 * f0) + (l1 * f1) + 128) >> 8);
*dp = d0;
dp++;
l1 = l0;
l0 = d0;
- d1 = clamp((d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 32) >> 6));
+ d1 = (d1 >> shift1) + (((l2 * f2) + (l3 * f3) + 128) >> 8);
*dp = d1;
dp++;
l3 = l2;
@@ -377,599 +284,528 @@ void cdicdic_device::decode_xa_stereo8(int32_t *cdic_xa_last, const uint8_t *xa,
cdic_xa_last[3] = l3;
}
-void cdicdic_device::play_audio_sector()
+void cdicdic_device::decode_8bit_xa_unit(int channel, uint8_t param, const uint8_t *data, int16_t *out_buffer)
{
-}
+ int gain_shift = 8 - (param & 0xf);
-void cdicdic_device::decode_audio_sector(const uint8_t *xa, int32_t triggered)
-{
- // Get XA format from sector header
- const uint8_t *hdr = xa + 4;
- int32_t channels;
- int32_t bits = 4;
+ const int16_t *filter = s_xa_filter_coef[(param >> 4) & 3];
+ int16_t *old_samples = &m_xa_last[channel << 1];
- if (hdr[2] == 0xff && triggered == 1)
+ for (int i = 0; i < 28; i++)
{
- return;
+ int32_t sample = *data;
+ if (sample >= 128)
+ sample -= 256;
+ data += 4;
+
+ sample <<= gain_shift;
+
+ sample += (filter[0] * old_samples[0] + filter[1] * old_samples[1] + 128) / 256;
+
+ int16_t sample16 = (int16_t)sample;
+ if (sample < -32768)
+ sample16 = -32768;
+ else if (sample > 32767)
+ sample16 = 32767;
+
+ old_samples[1] = old_samples[0];
+ old_samples[0] = sample16;
+
+ out_buffer[i] = sample16;
}
+}
+
+void cdicdic_device::decode_4bit_xa_unit(int channel, uint8_t param, const uint8_t *data, uint8_t shift, int16_t *out_buffer)
+{
+ int gain_shift = 12 - (param & 0xf);
- int16_t *samples = &m_samples[m_decode_addr == 0x2800 ? 0 : 1][0];
- LOGMASKED(LOG_DECODES, "%s: decode_audio_sector: got header type %02x\n", machine().describe_context(), hdr[2]);
+ const int16_t *filter = s_xa_filter_coef[(param >> 4) & 3];
+ int16_t *old_samples = &m_xa_last[channel << 1];
- switch (hdr[2] & 0x3f) // ignore emphasis and reserved bits
+ for (int i = 0; i < 28; i++)
{
- case 0:
- channels = 1;
- m_audio_sample_freq = clock2() / 512.0f; // / 1024.0f;
- bits = 4;
- m_audio_sample_size = 4;
- break;
+ int32_t sample = (*data >> shift) & 0xf;
+ if (BIT(sample, 3))
+ sample -= 16;
+ data += 4;
- case 1:
- channels = 2;
- m_audio_sample_freq = clock2() / 512.0f;
- bits = 4;
- m_audio_sample_size = 2;
- break;
+ sample <<= gain_shift;
- case 4:
- channels = 1;
- m_audio_sample_freq = clock2() / 1024.0f; ///2.0f;
- bits = 4;
- m_audio_sample_size = 4;
- break;
+ sample += (filter[0] * old_samples[0] + filter[1] * old_samples[1] + 128) / 256;
- case 5:
- channels = 2;
- m_audio_sample_freq = clock2() / 1024.0f; //37800.0f/2.0f;
- bits = 4;
- m_audio_sample_size = 2;
- break;
+ int16_t sample16 = (int16_t)(uint16_t)(sample & 0xffff);
+ if (sample < -32768)
+ sample16 = -32768;
+ else if (sample > 32767)
+ sample16 = 32767;
- case 16:
- channels = 1;
- m_audio_sample_freq = clock2() / 512.0f;
- bits = 8;
- m_audio_sample_size = 2;
- break;
+ old_samples[1] = old_samples[0];
+ old_samples[0] = sample16;
- case 17:
- channels = 2;
- m_audio_sample_freq = clock2() / 512.0f;
- bits = 8;
- m_audio_sample_size = 1;
- break;
+ out_buffer[i] = sample16;
+ }
+}
- default:
- fatalerror("play_xa: unhandled xa mode %08x\n", hdr[2]);
+void cdicdic_device::play_raw_group(const uint8_t *data)
+{
+ int16_t samples[28];
+ for (int i = 0; i < 28; i++)
+ {
+ samples[i] = (int16_t)((data[1] << 8) | data[0]);
+ data += 4;
}
- m_dmadac[0]->set_frequency(m_audio_sample_freq);
- m_dmadac[1]->set_frequency(m_audio_sample_freq);
+ m_dmadac[0]->transfer(0, 1, 1, 28, samples);
+ m_dmadac[1]->transfer(0, 1, 1, 28, samples);
+}
+
+void cdicdic_device::play_xa_group(const uint8_t coding, const uint8_t *data)
+{
+ static const uint16_t s_4bit_header_offsets[8] = { 0, 1, 2, 3, 8, 9, 10, 11 };
+ static const uint16_t s_8bit_header_offsets[4] = { 0, 1, 2, 3 };
+ static const uint16_t s_4bit_data_offsets[8] = { 16, 16, 17, 17, 18, 18, 19, 19 };
+ static const uint16_t s_8bit_data_offsets[4] = { 16, 17, 18, 19 };
+
+ int16_t samples[28];
- switch (channels)
+ switch (coding & (CODING_BPS_MASK | CODING_CHAN_MASK))
{
- case 1:
- switch (bits)
+ case CODING_4BPS | CODING_MONO:
+ for (uint8_t i = 0; i < 8; i++)
{
- case 4:
- decode_xa_mono(m_xa_last, hdr + 4, samples);
- for (int32_t index = 18*28*8 - 1; index >= 0; index--)
- {
- samples[index*2 + 1] = samples[index];
- samples[index*2 + 0] = samples[index];
- }
- samples[18*28*16 + 0] = samples[18*28*16 + 2] = samples[18*28*16 + 4] = samples[18*28*16 + 6] = samples[18*28*16 + 8] = samples[18*28*16 + 10] = samples[18*28*16 + 12] = samples[18*28*16 + 14] = samples[18*28*16 - 2];
- samples[18*28*16 + 1] = samples[18*28*16 + 3] = samples[18*28*16 + 5] = samples[18*28*16 + 7] = samples[18*28*16 + 9] = samples[18*28*16 + 11] = samples[18*28*16 + 13] = samples[18*28*16 + 15] = samples[18*28*16 - 1];
- break;
- case 8:
- decode_xa_mono8(m_xa_last, hdr + 4, samples);
- for (int32_t index = 18*28*8 - 1; index >= 0; index--)
- {
- samples[index*2 + 1] = samples[index];
- samples[index*2 + 0] = samples[index];
- }
- samples[18*28*8 + 0] = samples[18*28*8 + 2] = samples[18*28*8 + 4] = samples[18*28*8 + 6] = samples[18*28*8 + 8] = samples[18*28*8 + 10] = samples[18*28*8 + 12] = samples[18*28*8 + 14] = samples[18*28*8 - 2];
- samples[18*28*8 + 1] = samples[18*28*8 + 3] = samples[18*28*8 + 5] = samples[18*28*8 + 7] = samples[18*28*8 + 9] = samples[18*28*8 + 11] = samples[18*28*8 + 13] = samples[18*28*8 + 15] = samples[18*28*8 - 1];
- break;
+ decode_4bit_xa_unit(0, data[s_4bit_header_offsets[i]], data + s_4bit_data_offsets[i], (i & 1) ? 4 : 0, samples);
+ m_dmadac[0]->transfer(0, 1, 1, 28, samples);
+ m_dmadac[1]->transfer(0, 1, 1, 28, samples);
}
- break;
- case 2:
- switch (bits)
+ return;
+
+ case CODING_4BPS | CODING_STEREO:
+ for (uint8_t i = 0; i < 8; i++)
{
- case 4:
- decode_xa_stereo(m_xa_last, hdr + 4, samples);
- samples[18*28*8 + 0] = samples[18*28*8 + 2] = samples[18*28*8 + 4] = samples[18*28*8 + 6] = samples[18*28*8 + 8] = samples[18*28*8 + 10] = samples[18*28*8 + 12] = samples[18*28*8 + 14] = samples[18*28*8 - 2];
- samples[18*28*8 + 1] = samples[18*28*8 + 3] = samples[18*28*8 + 5] = samples[18*28*8 + 7] = samples[18*28*8 + 9] = samples[18*28*8 + 11] = samples[18*28*8 + 13] = samples[18*28*8 + 15] = samples[18*28*8 - 1];
- //fwrite(samples, 1, 18*28*4*m_audio_sample_size, temp_adpcm);
- break;
- case 8:
- decode_xa_stereo8(m_xa_last, hdr + 4, samples);
- samples[18*28*4 + 0] = samples[18*28*4 + 2] = samples[18*28*4 + 4] = samples[18*28*4 + 6] = samples[18*28*4 + 8] = samples[18*28*4 + 10] = samples[18*28*4 + 12] = samples[18*28*4 + 14] = samples[18*28*4 - 2];
- samples[18*28*4 + 1] = samples[18*28*4 + 3] = samples[18*28*4 + 5] = samples[18*28*4 + 7] = samples[18*28*4 + 9] = samples[18*28*4 + 11] = samples[18*28*4 + 13] = samples[18*28*4 + 15] = samples[18*28*4 - 1];
- break;
+ decode_4bit_xa_unit(i & 1, data[s_4bit_header_offsets[i]], data + s_4bit_data_offsets[i], (i & 1) ? 4 : 0, samples);
+ m_dmadac[i & 1]->transfer(0, 1, 1, 28, samples);
}
- break;
- }
+ return;
- for (int i = 0; i < 2; i++)
- {
- m_dmadac[i]->enable(1);
- m_dmadac[i]->transfer(i, 1, 2, 18*28*2*m_audio_sample_size, &m_samples[m_decode_addr == 0x2800 ? 0 : 1][0]);
- m_dmadac[i]->flush();
+ case CODING_8BPS | CODING_MONO:
+ for (uint8_t i = 0; i < 4; i++)
+ {
+ decode_8bit_xa_unit(0, data[s_8bit_header_offsets[i]], data + s_8bit_data_offsets[i], samples);
+ m_dmadac[0]->transfer(0, 1, 1, 28, samples);
+ m_dmadac[1]->transfer(0, 1, 1, 28, samples);
+ }
+ return;
+
+ case CODING_8BPS | CODING_STEREO:
+ for (uint8_t i = 0; i < 4; i++)
+ {
+ decode_8bit_xa_unit(i & 1, data[s_8bit_header_offsets[i]], data + s_8bit_data_offsets[i], samples);
+ m_dmadac[i & 1]->transfer(0, 1, 1, 28, samples);
+ }
+ return;
}
}
-TIMER_CALLBACK_MEMBER( cdicdic_device::periodic_sample_trigger )
+void cdicdic_device::play_audio_sector(const uint8_t coding, const uint8_t *data)
{
- // Indicate that data has been decoded
- LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
- m_audio_buffer |= 0x8000;
+ if ((coding & CODING_CHAN_MASK) > CODING_STEREO || (coding & CODING_BPS_MASK) == CODING_BPS_MPEG || (coding & CODING_RATE_MASK) == CODING_RATE_RESV)
+ {
+ LOGMASKED(LOG_SECTORS, "Invalid coding (%02x), ignoring\n", coding);
+ return;
+ }
+
+ int channels = 2;
+ offs_t buffer_length = 1;
+ if (!(coding & CODING_STEREO))
+ {
+ channels = 1;
+ buffer_length *= 2;
+ }
+
+ int bits = 4;
+ switch (coding & CODING_BPS_MASK)
+ {
+ case CODING_8BPS:
+ bits = 8;
+ break;
+ case CODING_16BPS:
+ bits = 16;
+ fatalerror("play_audio_sector: unhandled 16-bit coding mode\n");
+ break;
+ default:
+ bits = 4;
+ buffer_length *= 2;
+ break;
+ }
+
+ int32_t sample_frequency = 0;
+ switch (coding & CODING_RATE_MASK)
+ {
+ case CODING_37KHZ:
+ sample_frequency = clock2() / 512.0f;
+ break;
+ case CODING_18KHZ:
+ sample_frequency = clock2() / 1024.0f;
+ break;
+ case CODING_44KHZ:
+ fatalerror("play_audio_sector: unhandled 44KHz coding mode\n");
+ break;
+ default:
+ // Can't happen due to above early-out
+ break;
+ }
+
+ LOGMASKED(LOG_SECTORS, "Coding %02x, %d channels, %d bits, %08x frequency\n", coding, channels, bits, sample_frequency);
+
+ m_dmadac[0]->set_frequency(sample_frequency);
+ m_dmadac[1]->set_frequency(sample_frequency);
+ m_dmadac[0]->set_volume(0x100);
+ m_dmadac[1]->set_volume(0x100);
+
+ std::fill_n(&m_xa_last[0], 4, 0);
- // Set the CDIC interrupt line
- //LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
- //m_intreq_callback(ASSERT_LINE);
+ if (bits == 16 && channels == 2)
+ {
+ for (uint16_t i = 0; i < SECTOR_AUDIO_SIZE; i += 112, data += 112)
+ {
+ play_raw_group(data);
+ }
+ }
+ else
+ {
+ for (uint16_t i = 0; i < SECTOR_AUDIO_SIZE; i += 128, data += 128)
+ {
+ play_xa_group(coding, data);
+ }
+ }
}
-TIMER_CALLBACK_MEMBER( cdicdic_device::initial_sample_trigger )
+TIMER_CALLBACK_MEMBER( cdicdic_device::audio_tick )
{
- // Indicate that data has been decoded
- LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
- m_audio_buffer |= 0x8000;
-
- // Set the CDIC interrupt line
- LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
- m_intreq_callback(ASSERT_LINE);
+ if (m_audio_sector_counter > 0)
+ {
+ m_audio_sector_counter--;
+ if (m_audio_sector_counter > 0)
+ {
+ LOGMASKED(LOG_SAMPLES, "Audio sector counter %d, deducting and skipping\n", m_audio_sector_counter);
+ return;
+ }
+ LOGMASKED(LOG_SAMPLES, "Audio sector counter now 0, deducting and playing\n");
+ }
- sample_trigger();
+ if (m_decoding_audio_map)
+ {
+ process_audio_map();
+ }
}
-TIMER_CALLBACK_MEMBER( cdicdic_device::audio_sample_trigger )
+void cdicdic_device::process_audio_map()
{
- if (is_valid_sample_buf(m_decode_addr))
+ if (m_decode_addr == 0xffff)
{
- // Indicate that data has been decoded
- LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
- m_audio_buffer |= 0x8000;
+ m_audio_sector_counter = 0;
+ m_audio_format_sectors = 0;
+ m_decoding_audio_map = false;
+ return;
+ }
+
+ LOGMASKED(LOG_SAMPLES, "Procesing audio map from %04x\n", m_decode_addr);
- // Set the CDIC interrupt line
- LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
- m_intreq_callback(ASSERT_LINE);
+ uint8_t *ram = &m_ram[m_decode_addr & 0x3ffe];
+ m_decode_addr ^= 0x1a00;
- sample_trigger();
+ const bool was_decoding = (m_audio_format_sectors != 0);
+
+ const uint8_t coding = ram[(SECTOR_CODING2 - SECTOR_HEADER) ^ 1];
+ LOGMASKED(LOG_SAMPLES, "Coding is %02x\n", coding);
+ if (coding != 0xff)
+ {
+ m_decoding_audio_map = true;
+ m_audio_format_sectors = get_sector_count_for_coding(coding);
+ m_audio_sector_counter = m_audio_format_sectors;
+
+ ram += SECTOR_DATA - SECTOR_HEADER;
+ uint8_t swapped_data[(SECTOR_SIZE - (SECTOR_DATA - SECTOR_HEADER))];
+ for (uint16_t i = 0; i < (SECTOR_SIZE - (SECTOR_DATA - SECTOR_HEADER)); i++)
+ {
+ swapped_data[i ^ 1] = ram[i];
+ }
+ play_audio_sector(coding, swapped_data);
}
else
{
- // Indicate that data has been decoded
- LOGMASKED(LOG_SAMPLES, "Flagging end of sample\n");
- m_audio_buffer |= 0x8000;
+ m_decode_addr = 0xffff;
+ }
- // Set the CDIC interrupt line
- //LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line to flag that sample decoding is done\n");
- //m_intreq_callback(ASSERT_LINE);
- m_z_buffer |= 1;
+ if (was_decoding)
+ {
+ m_audio_buffer |= 0x8000;
+ update_interrupt_state();
}
}
-void cdicdic_device::sample_trigger()
+void cdicdic_device::update_interrupt_state()
+{
+ const bool interrupt_active = (bool)BIT(m_x_buffer | m_audio_buffer, 15);
+ m_intreq_callback(interrupt_active ? ASSERT_LINE : CLEAR_LINE);
+}
+
+bool cdicdic_device::is_mode2_sector_selected(const uint8_t *buffer)
{
- LOGMASKED(LOG_SAMPLES, "sample_trigger with m_decode_addr == %04x\n", m_decode_addr);
+ if ((buffer[SECTOR_FILE2] << 8) != m_file)
+ {
+ LOGMASKED(LOG_SECTORS, "Mode 2 sector is not selected, current file: %04x, disc file: %04x\n", m_file, buffer[SECTOR_FILE2]);
+ return false;
+ }
+
+ if (buffer[SECTOR_SUBMODE2] & SUBMODE_EOF)
+ {
+ LOGMASKED(LOG_SECTORS, "Mode 2 sector is EOF, queueing end of read\n");
+ m_disc_command = 0;
+ }
- bool decoding = true;
- bool had_valid_sample = false;
- m_decode_period = attotime::zero;
- //const uint16_t decode_start = m_decode_addr;
- do
+ // End-of-File, End-of-Record, or Trigger sectors skip selection beyond initial file selection.
+ if (buffer[SECTOR_SUBMODE2] & (SUBMODE_EOF | SUBMODE_TRIG | SUBMODE_EOR))
{
- const bool valid_sample = is_valid_sample_buf(m_decode_addr & 0x3ffe);
+ LOGMASKED(LOG_SECTORS, "Mode 2 sector is selected due to EOF, TRIG, or EOR (%02x)\n", buffer[SECTOR_SUBMODE2]);
+ return true;
+ }
- if (valid_sample)
- {
- had_valid_sample = true;
+ // Sectors with no applicable data are skipped.
+ if (!(buffer[SECTOR_SUBMODE2] & (SUBMODE_DATA | SUBMODE_AUDIO | SUBMODE_VIDEO)))
+ {
+ LOGMASKED(LOG_SECTORS, "Mode 2 sector is not selected due to being a message sector (%02x)\n", buffer[SECTOR_SUBMODE2]);
+ return false;
+ }
- LOGMASKED(LOG_SAMPLES, "Hit audio_sample_trigger, with m_decode_addr == %04x, calling decode_audio_sector\n", m_decode_addr);
+ // Select based on the specified channel mask.
+ const bool channel_selected = (bool)BIT(m_channel, buffer[SECTOR_CHAN2]);
- // Decode the data at Z+4, the same offset as a normal CD sector.
- decode_audio_sector(((uint8_t*)m_ram.get()) + (m_decode_addr & 0x3ffe) + 4, 1);
- play_audio_sector();
+ LOGMASKED(LOG_SECTORS, "Mode 2 sector is %sselected due to channel (register %04x, buffer channel %04x)\n", channel_selected ? "" : "not ", m_channel, buffer[SECTOR_CHAN2]);
- // Delay until sample completion before requesting more data
- LOGMASKED(LOG_SAMPLES, "Data is valid, setting up a new callback\n");
- m_decode_period += attotime::from_hz(sample_buf_freq(m_decode_addr & 0x3ffe)) * (18*28*2*sample_buf_size(m_decode_addr & 0x3ffe));
- //m_periodic_sample_timer[m_decode_addr == 0x2800 ? 0 : 1]->adjust(m_decode_period);
- m_audio_sample_timer->adjust(m_decode_period);
- //dmadac_enable(&dmadac[0], 2, 0);
+ return channel_selected;
+}
- m_decode_addr ^= 0x1a00;
- m_z_buffer ^= 0x1a00;
- LOGMASKED(LOG_SAMPLES, "Updated m_decode_addr, new value is %04x\n", m_decode_addr);
+bool cdicdic_device::is_mode2_audio_selected(const uint8_t *buffer)
+{
+ // Non-Mode-2, Non-Audio sectors are never selected for audio playback.
+ if (!(buffer[SECTOR_SUBMODE2] & SUBMODE_FORM) || !(buffer[SECTOR_SUBMODE2] & SUBMODE_AUDIO))
+ {
+ LOGMASKED(LOG_SECTORS, "Audio is not selected; submode %02x\n", buffer[SECTOR_SUBMODE2]);
+ return false;
+ }
- // Indicate that data has been decoded
- //LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
- //m_audio_buffer |= 0x8000;
+ // Select based on the specified audio channel mask.
+ const bool channel_selected = (bool)BIT(m_audio_channel, buffer[SECTOR_CHAN2]);
- // Set the CDIC interrupt line
- //LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
- //m_intreq_callback(ASSERT_LINE);
+ LOGMASKED(LOG_SECTORS, "Mode 2 audio is %sselected due to channel (register %04x, buffer channel %04x)\n", channel_selected ? "" : "not ", m_audio_channel, buffer[SECTOR_CHAN2]);
- // Swap buffer positions to indicate our new buffer position at the next read
+ return channel_selected;
+}
- //if (m_decode_addr == decode_start)
- {
- decoding = false;
- }
- }
- else
- {
- LOGMASKED(LOG_SAMPLES, "Data is not valid, stopping playback\n");
- m_audio_sample_timer->adjust(attotime::never);
- decoding = false;
+TIMER_CALLBACK_MEMBER( cdicdic_device::sector_tick )
+{
+ if (m_disc_command == 0)
+ {
+ return;
+ }
- // Indicate that data has been decoded
- LOGMASKED(LOG_SAMPLES, "Flagging that audio data has been decoded\n");
- //m_audio_buffer |= 0x8000;
+ if (m_disc_spinup_counter != 0)
+ {
+ LOGMASKED(LOG_SECTORS, "Sector tick, waiting on spinup\n");
+ m_disc_spinup_counter--;
+ return;
+ }
- // Set the CDIC interrupt line
- LOGMASKED(LOG_SAMPLES, "Setting CDIC interrupt line for soundmap decode\n");
- m_intreq_callback(ASSERT_LINE);
+ LOGMASKED(LOG_SECTORS, "About to process a disc sector\n");
- m_z_buffer |= 1;
- }
- } while (decoding);
+ process_disc_sector();
- if (had_valid_sample)
+ if (m_disc_command == 0)
{
- //m_periodic_sample_timer->adjust(m_decode_period);
+ LOGMASKED(LOG_SECTORS, "Disc command has been reset after processing; stopping processing.\n");
+ cancel_disc_read();
+ return;
}
-}
-TIMER_CALLBACK_MEMBER( cdicdic_device::trigger_readback_int )
-{
- process_delayed_command();
+ m_curr_lba++;
}
-void cdicdic_device::process_delayed_command()
+uint8_t cdicdic_device::get_sector_count_for_coding(uint8_t coding)
{
- switch (m_command)
+ uint8_t base_count = 2;
+
+ switch (coding & CODING_BPS_MASK)
{
- case 0x23: // Reset Mode 1
- case 0x24: // Reset Mode 2
- case 0x29: // Read Mode 1
- case 0x2a: // Read Mode 2
- {
- static const char* const s_cmds[8] =
- {
- "Reset Mode 1",
- "Reset Mode 2", 0, 0, 0, 0,
- "Read Mode 1",
- "Read Mode 2"
- };
- uint8_t buffer[2560] = { 0 };
- uint32_t msf = m_time >> 8;
- LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command with MSF %06x: %s\n", machine().describe_context(), msf, s_cmds[m_command - 0x23]);
- uint8_t nybbles[6] =
- {
- static_cast<uint8_t>(msf & 0x0000000f),
- static_cast<uint8_t>((msf & 0x000000f0) >> 4),
- static_cast<uint8_t>((msf & 0x00000f00) >> 8),
- static_cast<uint8_t>((msf & 0x0000f000) >> 12),
- static_cast<uint8_t>((msf & 0x000f0000) >> 16),
- static_cast<uint8_t>((msf & 0x00f00000) >> 20)
- };
- if ((msf & 0x0000ff) >= 0x75)
- {
- LOGMASKED(LOG_COMMANDS, "%s: Weird frame timestamp detected: %02x\n", machine().describe_context(), (uint8_t)msf);
- msf &= 0xffff00;
- nybbles[0] = 0;
- nybbles[1] = 0;
- }
- if (nybbles[2] >= 2)
- {
- nybbles[2] -= 2;
- }
- else
- {
- nybbles[2] = 8 + nybbles[2];
- if (nybbles[3] > 0)
- {
- nybbles[3]--;
- }
- else
- {
- nybbles[3] = 5;
- if (nybbles[4] > 0)
- {
- nybbles[4]--;
- }
- else
- {
- nybbles[4] = 9;
- nybbles[5]--;
- }
- }
- }
- uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
+ case CODING_4BPS:
+ // Twice as many 4bpp audio frames fit as usual
+ base_count *= 2;
+ break;
+ case CODING_8BPS:
+ case CODING_16BPS:
+ // No multiplier vs. base
+ break;
+ case CODING_BPS_MPEG:
+ // Unsupported; clear to zero for now
+ base_count = 0;
+ break;
+ }
- LOGMASKED(LOG_COMMANDS, "%s: Reading Mode %d sector from MSF location %06x / %x%x%x%x%x%x, LBA %08x\n", machine().describe_context(), m_command - 0x28,
- (m_time >> 8) - 0x200, nybbles[5], nybbles[4], nybbles[3], nybbles[2], nybbles[1], nybbles[0], lba);
+ switch (coding & CODING_RATE_MASK)
+ {
+ case CODING_18KHZ:
+ // Twice as many half-rate audio frames fit as usual
+ base_count *= 2;
+ break;
+ case CODING_37KHZ:
+ case CODING_44KHZ:
+ // No multiplier vs. base
+ break;
+ case CODING_RATE_RESV:
+ // Unsupported reserved mode; clear to zero for now
+ base_count = 0;
+ break;
+ }
- cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE);
+ switch (coding & CODING_CHAN_MASK)
+ {
+ case CODING_MONO:
+ // Twice as many mono audio frames fit vs. stereo
+ base_count *= 2;
+ break;
+ case CODING_STEREO:
+ // No multiplier vs. base
+ break;
+ case CODING_CHAN_RESV:
+ case CODING_CHAN_MPEG:
+ // MPEG mode and reserved modes are unsupported; clear to zero for now
+ base_count = 0;
+ break;
+ }
- m_time += 0x100;
- if ((m_time & 0x00000f00) == 0x00000a00)
- {
- m_time &= 0xfffff0ff;
- m_time += 0x00001000;
- }
- if ((m_time & 0x0000ff00) == 0x00007500)
- {
- m_time &= 0xffff00ff;
- m_time += 0x00010000;
- if ((m_time & 0x000f0000) == 0x000a0000)
- {
- m_time &= 0xfff0ffff;
- m_time += 0x00100000;
- }
- }
- if ((m_time & 0x00ff0000) == 0x00600000)
- {
- m_time &= 0xff00ffff;
- m_time += 0x01000000;
- if ((m_time & 0x0f000000) == 0x0a000000)
- {
- m_time &= 0xf0ffffff;
- m_time += 0x10000000;
- }
- }
+ return base_count;
+}
- m_data_buffer &= ~0x0004;
- m_data_buffer ^= 0x0001;
+void cdicdic_device::process_disc_sector()
+{
+ const uint32_t real_lba = m_curr_lba + 150;
+ const uint8_t mins = real_lba / (60 * 75);
+ const uint8_t secs = (real_lba / 75) % 60;
+ const uint8_t frac = real_lba % 75;
+ const uint8_t mins_bcd = ((mins / 10) << 4) | (mins % 10);
+ const uint8_t secs_bcd = ((secs / 10) << 4) | (secs % 10);
+ const uint8_t frac_bcd = ((frac / 10) << 4) | (frac % 10);
- const bool file_match = (buffer[CDIC_SECTOR_FILE2] << 8) == m_file;
- const bool channel_match = (m_channel & (1 << buffer[CDIC_SECTOR_CHAN2])) != 0;
- const bool audio_channel_match = (m_audio_channel & (1 << buffer[CDIC_SECTOR_CHAN2])) != 0;
- const bool is_audio = (buffer[CDIC_SECTOR_SUBMODE2] & (CDIC_SUBMODE_FORM | CDIC_SUBMODE_DATA | CDIC_SUBMODE_AUDIO | CDIC_SUBMODE_VIDEO)) == (CDIC_SUBMODE_FORM | CDIC_SUBMODE_AUDIO);
- if (file_match)
- {
- if (is_audio && channel_match && audio_channel_match)
- {
- m_x_buffer |= 0x8000;
- //m_data_buffer |= 0x4000;
- m_data_buffer |= 4;
-
- LOGMASKED(LOG_SECTORS, "%s: Audio sector into %04x\n", machine().describe_context(), (m_data_buffer & 5) * 0xa00);
-
- for (int index = 6; index < 2352/2; index++)
- {
- m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
- }
-
- decode_audio_sector(((uint8_t*)m_ram.get()) + ((m_data_buffer & 5) * 0xa00 + 4), 0);
-
- LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for audio sector\n", machine().describe_context());
- //}
- m_intreq_callback(ASSERT_LINE);
- //else
- //{
- // LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for ignored audio sector (m_channel %04x, m_audio_channel %04x, sector channel %04x\n",
- // machine().describe_context(), m_channel, m_audio_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
- // m_intreq_callback(ASSERT_LINE);
- //}
- }
- else if ((buffer[CDIC_SECTOR_SUBMODE2] & (CDIC_SUBMODE_DATA | CDIC_SUBMODE_AUDIO | CDIC_SUBMODE_VIDEO)) == 0x00)
- {
- m_x_buffer |= 0x8000;
- //m_data_buffer |= 0x4000;
-
- for (int index = 6; index < 2352/2; index++)
- {
- m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
- }
-
- if ((buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_TRIG) == CDIC_SUBMODE_TRIG ||
- (buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOR) == CDIC_SUBMODE_EOR ||
- (buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) == CDIC_SUBMODE_EOF)
- {
- LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for message sector\n", machine().describe_context());
- m_intreq_callback(ASSERT_LINE);
- }
- else
- {
- LOGMASKED(LOG_SECTORS, "%s: Setting CDIC interrupt line for ignored message sector\n", machine().describe_context());
- m_intreq_callback(ASSERT_LINE);
- }
- }
- else if (channel_match)
- {
- m_x_buffer |= 0x8000;
- //m_data_buffer |= 0x4000;
-
- if (is_audio)
- {
- //m_data_buffer |= 4;
- //m_z_buffer = (m_data_buffer & 5) * 0xa00;
- }
-
- for (int index = 6; index < 2352/2; index++)
- {
- m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
- }
-
- LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for data sector to %04x, submode 2 flags are:\n", machine().describe_context(), (m_data_buffer & 5) * 0xa00);
- LOGMASKED(LOG_IRQS, "%s: Channel reg is: %08x, versus submode channel: %08x\n", machine().describe_context(), m_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
- if (!BIT(m_channel, buffer[CDIC_SECTOR_CHAN2]))
- {
- LOGMASKED(LOG_IRQS, "%s: Channel mismatch\n", machine().describe_context());
- m_intreq_callback(ASSERT_LINE);
- }
- else
- {
- m_intreq_callback(ASSERT_LINE);
- }
- const uint16_t submode2 = buffer[CDIC_SECTOR_SUBMODE2];
- if (submode2 & CDIC_SUBMODE_EOF) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOF\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_RT) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_RT\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_FORM) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_FORM\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_TRIG) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_TRIG\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_DATA) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_DATA\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_AUDIO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_AUDIO\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_VIDEO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_VIDEO\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_EOR) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOR\n", machine().describe_context());
- }
- else
- {
- //m_x_buffer |= 0x8000;
-
- LOGMASKED(LOG_IRQS, "%s: No match: m_channel %04x, m_audio_channel %04x, sector channel %04x\n",
- machine().describe_context(), m_channel, m_audio_channel, (1 << buffer[CDIC_SECTOR_CHAN2]));
- const uint16_t submode2 = buffer[CDIC_SECTOR_SUBMODE2];
- if (submode2 & CDIC_SUBMODE_EOF) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOF\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_RT) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_RT\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_FORM) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_FORM\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_TRIG) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_TRIG\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_DATA) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_DATA\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_AUDIO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_AUDIO\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_VIDEO) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_VIDEO\n", machine().describe_context());
- if (submode2 & CDIC_SUBMODE_EOR) LOGMASKED(LOG_IRQS, "%s: CDIC_SUBMODE_EOR\n", machine().describe_context());
- //m_intreq_callback(ASSERT_LINE);
- }
+ LOGMASKED(LOG_SECTORS, "Disc sector, current LBA: %08x, MSF: %02x %02x %02x\n", real_lba, mins_bcd, secs_bcd, frac_bcd);
- if ((buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) == 0 && m_command != 0x23)
- {
- LOGMASKED(LOG_IRQS, "Setting CDIC processing to trigger in 75Hz due to non-EOF.\n");
- m_interrupt_timer->adjust(attotime::from_hz(75)); // 75Hz = 1x CD-ROM speed
- }
- else
- {
- LOGMASKED(LOG_IRQS, "Not setting CDIC processing, EOF is %d\n", (buffer[CDIC_SECTOR_SUBMODE2] & CDIC_SUBMODE_EOF) ? 1 : 0);
- m_interrupt_timer->adjust(attotime::never);
- //m_data_buffer &= ~0x4000;
- //m_interrupt_timer->adjust(attotime::from_hz(75));
- }
- }
- else
- {
- LOGMASKED(LOG_IRQS, "File mismatch\n");
- }
- break;
- }
+ uint8_t buffer[2560] = { 0 };
+ cdrom_read_data(m_cd, m_curr_lba, buffer, CD_TRACK_RAW_DONTCARE);
- case 0x2e: // Abort
- LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Abort\n", machine().describe_context());
- m_interrupt_timer->adjust(attotime::never);
- //m_data_buffer &= ~4;
- break;
+ LOGMASKED(LOG_SECTORS, "Sector header data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buffer[ 0], buffer[ 1], buffer[ 2], buffer[ 3], buffer[ 4], buffer[ 5], buffer[ 6], buffer[ 7], buffer[ 8], buffer[ 9],
+ buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18], buffer[19],
+ buffer[20], buffer[21], buffer[22], buffer[23]);
- case 0x28: // Play CDDA audio
+ if (buffer[SECTOR_MODE] == 2 && m_disc_mode == DISC_MODE2)
+ {
+ // First, filter whether we want to process this sector at all.
+ if (!is_mode2_sector_selected(buffer))
{
- LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Play CDDA Audio\n", machine().describe_context());
- uint8_t buffer[2560] = { 0 };
- uint32_t msf = (m_time & 0xffff7f00) >> 8;
- uint32_t next_msf = increment_cdda_frame_bcd((m_time & 0xffff7f00) >> 8);
- uint32_t rounded_next_msf = increment_cdda_sector_bcd((m_time & 0xffff0000) >> 8);
- uint8_t nybbles[6] =
- {
- static_cast<uint8_t>(msf & 0x0000000f),
- static_cast<uint8_t>((msf & 0x000000f0) >> 4),
- static_cast<uint8_t>((msf & 0x00000f00) >> 8),
- static_cast<uint8_t>((msf & 0x0000f000) >> 12),
- static_cast<uint8_t>((msf & 0x000f0000) >> 16),
- static_cast<uint8_t>((msf & 0x00f00000) >> 20)
- };
+ return;
+ }
- uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
+ // Next, determine if we want to process this sector as an audio sector.
+ if (is_mode2_audio_selected(buffer))
+ {
+ LOGMASKED(LOG_SECTORS, "Audio is selected\n");
+ if (m_audio_sector_counter == 0)
+ std::fill_n(&m_xa_last[0], 4, 0);
- if (!cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE))
- {
- osd_printf_verbose("Unable to read CD-ROM data.\n", machine().describe_context());
- }
+ m_audio_sector_counter = get_sector_count_for_coding(buffer[SECTOR_CODING2]);
+ m_decoding_audio_map = false;
- if (!(msf & 0x0000ff))
- {
- LOGMASKED(LOG_COMMANDS, "%s: Playing CDDA sector from MSF location %06x\n", machine().describe_context(), m_time | 2);
- m_cdda->start_audio(lba, rounded_next_msf);
- }
+ play_audio_sector(buffer[SECTOR_CODING2], buffer + SECTOR_DATA);
+ }
+ }
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x924/2] = 0x0001; // CTRL
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x926/2] = 0x0001; // TRACK
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x928/2] = 0x0000; // INDEX
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92a/2] = (m_time >> 24) & 0x000000ff; // MIN
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92c/2] = (m_time >> 16) & 0x000000ff; // SEC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92e/2] = (m_time >> 8) & 0x0000007f; // FRAC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x930/2] = 0x0000; // ZERO
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x932/2] = (m_time >> 24) & 0x000000ff; // AMIN
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x934/2] = (m_time >> 16) & 0x000000ff; // ASEC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x936/2] = (m_time >> 8) & 0x0000007f; // AFRAC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x938/2] = 0x0000; // CRC1
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x93a/2] = 0x0000; // CRC2
+ // Calculate subcode data
+ uint8_t subcode_buffer[96];
+ memset(subcode_buffer, 0, sizeof(subcode_buffer));
- m_time = next_msf << 8;
+ if (m_disc_command == DISC_TOC)
+ {
+ uint32_t entry_index = 0;
+ for (; buffer[entry_index * 5] != 0; entry_index++);
+
+ uint8_t *toc_data = &buffer[(m_curr_lba % entry_index) * 5];
+
+ subcode_buffer[SUBCODE_Q_CONTROL] = toc_data[0];
+ subcode_buffer[SUBCODE_Q_TRACK] = 0x00;
+ subcode_buffer[SUBCODE_Q_INDEX] = toc_data[1];
+ subcode_buffer[SUBCODE_Q_MODE1_MINS] = 0xa0;
+ subcode_buffer[SUBCODE_Q_MODE1_SECS] = secs_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_FRAC] = frac_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_ZERO] = 0x00;
+ subcode_buffer[SUBCODE_Q_MODE1_AMINS] = toc_data[2];
+ subcode_buffer[SUBCODE_Q_MODE1_ASECS] = toc_data[3];
+ subcode_buffer[SUBCODE_Q_MODE1_AFRAC] = toc_data[4];
+ subcode_buffer[SUBCODE_Q_CRC0] = 0xff;
+ subcode_buffer[SUBCODE_Q_CRC1] = 0xff;
+ }
+ else
+ {
+ subcode_buffer[SUBCODE_Q_CONTROL] = (m_disc_command == DISC_CDDA ? 0x01 : 0x41);
+ subcode_buffer[SUBCODE_Q_TRACK] = 0x01;
+ subcode_buffer[SUBCODE_Q_INDEX] = 0x01;
+ subcode_buffer[SUBCODE_Q_MODE1_MINS] = mins_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_SECS] = secs_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_FRAC] = frac_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_ZERO] = 0x00;
+ subcode_buffer[SUBCODE_Q_MODE1_AMINS] = mins_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_ASECS] = secs_bcd;
+ subcode_buffer[SUBCODE_Q_MODE1_AFRAC] = frac_bcd;
+ subcode_buffer[SUBCODE_Q_CRC0] = 0xff;
+ subcode_buffer[SUBCODE_Q_CRC1] = 0xff;
+ }
- // the following line BREAKS 'The Apprentice', hangs when you attempt to start the game
- //m_interrupt_timer->adjust(attotime::from_hz(75));
+ uint16_t crc_accum = 0;
+ for (int i = 0; i < 12; i++)
+ crc_accum = CRC_CCITT_ROUND(crc_accum, subcode_buffer[SUBCODE_Q_CONTROL + i]);
- m_x_buffer |= 0x8000;
- //m_data_buffer |= 0x4000;
+ subcode_buffer[SUBCODE_Q_CRC0] = (uint8_t)(crc_accum >> 8);
+ subcode_buffer[SUBCODE_Q_CRC1] = (uint8_t)crc_accum;
- for (int index = 6; index < 2352/2; index++)
- {
- m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
- }
+ process_sector_data(buffer, subcode_buffer);
+}
- LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for CDDA sector\n", machine().describe_context());
- m_intreq_callback(ASSERT_LINE);
- break;
- }
- case 0x2c: // Seek
- {
- LOGMASKED(LOG_COMMANDS, "%s: Processing Delayed Command: Seek\n", machine().describe_context());
- uint8_t buffer[2560] = { 0 };
- uint32_t msf = (m_time & 0xffff7f00) >> 8;
- uint32_t next_msf = increment_cdda_frame_bcd((m_time & 0xffff7f00) >> 8);
- uint8_t nybbles[6] =
- {
- static_cast<uint8_t>(msf & 0x0000000f),
- static_cast<uint8_t>((msf & 0x000000f0) >> 4),
- static_cast<uint8_t>((msf & 0x00000f00) >> 8),
- static_cast<uint8_t>((msf & 0x0000f000) >> 12),
- static_cast<uint8_t>((msf & 0x000f0000) >> 16),
- static_cast<uint8_t>((msf & 0x00f00000) >> 20)
- };
- uint32_t lba = nybbles[0] + nybbles[1]*10 + ((nybbles[2] + nybbles[3]*10)*75) + ((nybbles[4] + nybbles[5]*10)*75*60);
+void cdicdic_device::process_sector_data(const uint8_t *buffer, const uint8_t *subcode_buffer)
+{
+ m_data_buffer ^= 0x0001;
+ m_data_buffer &= ~0x0004;
- m_interrupt_timer->adjust(attotime::from_hz(75));
+ uint16_t *dev_buffer = (uint16_t *)&m_ram[(m_data_buffer & 0x0005) * 0xa00];
- cdrom_read_data(m_cd, lba, buffer, CD_TRACK_RAW_DONTCARE);
+ for (int i = SECTOR_HEADER; i < SECTOR_FILE2; i += 2)
+ *dev_buffer++ = ((uint16_t)buffer[i] << 8) | buffer[i + 1];
- m_data_buffer ^= 0x0001;
- m_x_buffer |= 0x8000;
- m_data_buffer |= 0x4000;
+ if (m_command == 0x2a && is_mode2_audio_selected(buffer))
+ {
+ m_data_buffer |= 0x0004;
+ dev_buffer += 0x1400;
+ }
- for (int index = 6; index < 2352/2; index++)
- {
- m_ram[(m_data_buffer & 5) * (0xa00/2) + (index - 6)] = (buffer[index*2] << 8) | buffer[index*2 + 1];
- }
+ for (int i = SECTOR_FILE2; i < SECTOR_SIZE; i += 2)
+ *dev_buffer++ = ((uint16_t)buffer[i] << 8) | buffer[i + 1];
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x924/2] = 0x0041; // CTRL
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x926/2] = 0x0001; // TRACK
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x928/2] = 0x0000; // INDEX
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92a/2] = (m_time >> 24) & 0x000000ff; // MIN
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92c/2] = (m_time >> 16) & 0x000000ff; // SEC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x92e/2] = (m_time >> 8) & 0x0000007f; // FRAC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x930/2] = 0x0000; // ZERO
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x932/2] = (m_time >> 24) & 0x000000ff; // AMIN
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x934/2] = (m_time >> 16) & 0x000000ff; // ASEC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x936/2] = (m_time >> 8) & 0x0000007f; // AFRAC
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x938/2] = 0x0000; // CRC1
- m_ram[(m_data_buffer & 5) * (0xa00/2) + 0x93a/2] = 0x0000; // CRC2
-
- m_time = next_msf << 8;
-
- LOGMASKED(LOG_IRQS, "%s: Setting CDIC interrupt line for Seek sector\n", machine().describe_context());
- m_intreq_callback(ASSERT_LINE);
- break;
- }
- }
+ for (int i = SUBCODE_Q_CONTROL; i <= SUBCODE_Q_CRC1; i++)
+ *dev_buffer++ = subcode_buffer[i];
+
+ m_x_buffer |= 0x8000;
+ m_data_buffer |= 0x4000;
+ update_interrupt_state();
+
+ if (m_command == 0x23) // Reset Mode 1? If so, stop.
+ cancel_disc_read();
}
uint16_t cdicdic_device::regs_r(offs_t offset, uint16_t mem_mask)
@@ -1004,10 +840,6 @@ uint16_t cdicdic_device::regs_r(offs_t offset, uint16_t mem_mask)
case 0x3c0c/2: // Audio Channel register
LOGMASKED(LOG_READS, "%s: cdic_r: Audio Channel Register = %04x & %04x\n", machine().describe_context(), m_audio_channel, mem_mask);
- if (m_break_on_achan)
- {
- machine().debug_break();
- }
return m_audio_channel;
case 0x3ff4/2: // ABUF
@@ -1015,11 +847,7 @@ uint16_t cdicdic_device::regs_r(offs_t offset, uint16_t mem_mask)
uint16_t temp = m_audio_buffer;
LOGMASKED(LOG_READS, "%s: cdic_r: Audio Buffer Register = %04x & %04x\n", machine().describe_context(), temp, mem_mask);
m_audio_buffer &= 0x7fff;
- if (!((m_audio_buffer | m_x_buffer) & 0x8000))
- {
- m_intreq_callback(CLEAR_LINE);
- LOGMASKED(LOG_IRQS, "%s: Clearing CDIC interrupt line\n", machine().describe_context());
- }
+ update_interrupt_state();
return temp;
}
@@ -1028,29 +856,20 @@ uint16_t cdicdic_device::regs_r(offs_t offset, uint16_t mem_mask)
uint16_t temp = m_x_buffer;
LOGMASKED(LOG_READS, "%s: cdic_r: X-Buffer Register = %04x & %04x\n", machine().describe_context(), temp, mem_mask);
m_x_buffer &= 0x7fff;
- if (!((m_audio_buffer | m_x_buffer) & 0x8000))
- {
- m_intreq_callback(CLEAR_LINE);
- LOGMASKED(LOG_IRQS, "%s: Clearing CDIC interrupt line\n", machine().describe_context());
- }
+ update_interrupt_state();
return temp;
}
case 0x3ffa/2: // AUDCTL
- {
+ if (!m_decoding_audio_map)
+ m_z_buffer ^= 0x0001;
LOGMASKED(LOG_READS, "%s: cdic_r: Z-Buffer Register Read: %04x & %04x\n", machine().describe_context(), m_z_buffer, mem_mask);
- if (m_audio_playback_timer->remaining().is_never() && m_audio_sample_timer->remaining().is_never())
- {
- return m_z_buffer | 1;
- }
return m_z_buffer;
- }
case 0x3ffe/2:
- {
LOGMASKED(LOG_READS, "%s: cdic_r: Data buffer Register = %04x & %04x\n", machine().describe_context(), m_data_buffer, mem_mask);
return m_data_buffer;
- }
+
default:
LOGMASKED(LOG_READS | LOG_UNKNOWNS, "%s: cdic_r: Unknown address: %04x & %04x\n", machine().describe_context(), addr*2, mem_mask);
return 0;
@@ -1117,19 +936,19 @@ void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
uint32_t start = m_scc->dma().channel[0].memory_address_counter;
uint32_t count = m_scc->dma().channel[0].transfer_counter;
uint32_t device_index = (data & 0x3fff) >> 1;
+ uint16_t *ram = (uint16_t *)m_ram.get();
LOGMASKED(LOG_WRITES, "%s: cdic_w: DMA Control Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
LOGMASKED(LOG_WRITES, "%s: Memory address counter: %08x\n", machine().describe_context(), m_scc->dma().channel[0].memory_address_counter);
LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & OCR_D) ? "to main RAM" : "to device RAM");
- printf("\n");
for (uint32_t index = start / 2; index < (start / 2 + count); index++)
{
if (m_scc->dma().channel[0].operation_control & OCR_D)
{
- m_memory_space->write_word(index * 2, m_ram[device_index++]);
+ m_memory_space->write_word(index * 2, ram[device_index++]);
}
else
{
- m_ram[device_index++] = m_memory_space->read_word(index * 2);
+ ram[device_index++] = m_memory_space->read_word(index * 2);
}
}
m_scc->dma().channel[0].memory_address_counter += m_scc->dma().channel[0].transfer_counter * 2;
@@ -1137,29 +956,21 @@ void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
}
case 0x3ffa/2:
- {
LOGMASKED(LOG_WRITES, "%s: cdic_w: Z-Buffer Register Write: %04x & %04x\n", machine().describe_context(), data, mem_mask);
COMBINE_DATA(&m_z_buffer);
- if (m_z_buffer & 0x2000)
+ if (!(m_z_buffer & 0x2000))
{
- //if (m_audio_sample_timer->remaining().is_never())
- {
- m_decode_addr = m_z_buffer & 0x3a00;
- LOGMASKED(LOG_WRITES, "%s: New decode address: %04x\n", machine().describe_context(), m_decode_addr);
- m_audio_playback_timer->adjust(attotime::from_hz(1000));
- //m_decode_delay = 1;
- //m_audio_sample_timer->adjust(attotime::from_hz(75));
- }
+ m_decode_addr = 0xffff;
}
- else
+ else if (!m_decoding_audio_map)
{
- m_decode_addr = 0xffff;
- m_audio_sample_timer->adjust(attotime::never);
- m_periodic_sample_timer[0]->adjust(attotime::never);
- m_periodic_sample_timer[1]->adjust(attotime::never);
+ m_decode_addr = m_z_buffer & 0x3a00;
+ m_audio_format_sectors = 0;
+ m_audio_sector_counter = 1;
+ m_decoding_audio_map = true;
+ std::fill_n(&m_xa_last[0], 4, 0);
}
break;
- }
case 0x3ffc/2:
LOGMASKED(LOG_WRITES, "%s: cdic_w: Interrupt Vector Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
@@ -1167,73 +978,105 @@ void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
break;
case 0x3ffe/2:
- {
LOGMASKED(LOG_WRITES, "%s: cdic_w: Data Buffer Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
COMBINE_DATA(&m_data_buffer);
if (m_data_buffer & 0x8000)
{
- m_audio_sample_timer->adjust(attotime::never);
- m_audio_playback_timer->adjust(attotime::never);
- m_periodic_sample_timer[0]->adjust(attotime::never);
- m_periodic_sample_timer[1]->adjust(attotime::never);
LOGMASKED(LOG_WRITES, "%s: cdic_w: Data Buffer high-bit set, beginning command processing\n", machine().describe_context());
- switch (m_command)
- {
- case 0x23: // Reset Mode 1
- case 0x24: // Reset Mode 2
- LOGMASKED(LOG_WRITES, "%s: cdic_w: Reset Mode %d command\n", machine().describe_context(), m_command - 0x22);
- m_interrupt_timer->adjust(attotime::never);
- m_dmadac[0]->enable(0);
- m_dmadac[1]->enable(0);
- m_data_buffer &= 0x7fff;
- break;
- case 0x2e: // Abort
- LOGMASKED(LOG_WRITES, "%s: cdic_w: Abort command\n", machine().describe_context());
- m_interrupt_timer->adjust(attotime::never);
- //m_audio_sample_timer->adjust(attotime::never);
- //m_periodic_sample_timer->adjust(attotime::never);
- m_dmadac[0]->enable(0);
- m_dmadac[1]->enable(0);
- m_data_buffer &= 0x3fff;
- break;
- case 0x2b: // Stop CDDA
- LOGMASKED(LOG_WRITES, "%s: cdic_w: Stop CDDA\n", machine().describe_context());
- m_cdda->stop_audio();
- m_interrupt_timer->adjust(attotime::never);
- m_data_buffer &= 0x7fff;
- break;
- case 0x29: // Read Mode 1
- case 0x2a: // Read Mode 2
- case 0x28: // Play CDDA
- case 0x2c: // Seek
- {
- attotime period = m_interrupt_timer->remaining();
- if (!period.is_never())
- {
- LOGMASKED(LOG_WRITES, "%s: cdic_w: Other command (%02x), interrupt in-flight, letting it ride\n", machine().describe_context(), m_command);
- m_interrupt_timer->adjust(period);
- }
- else
- {
- LOGMASKED(LOG_WRITES, "%s: cdic_w: Other command (%02x), interrupt not in-flight, interrupting in 75Hz\n", machine().describe_context(), m_command);
- m_interrupt_timer->adjust(attotime::from_hz(75));
- }
- m_data_buffer &= 0x7fff;
- break;
- }
- default:
- LOGMASKED(LOG_COMMANDS, "%s: Unknown CDIC command: %02x\n", machine().describe_context(), m_command);
- break;
- }
+ handle_cdic_command();
+ }
+ if (!(m_data_buffer & 0x4000))
+ {
+ m_disc_command = 0;
+ m_disc_mode = 0;
+ m_disc_spinup_counter = 0;
+ m_curr_lba = 0;
}
break;
- }
+
default:
LOGMASKED(LOG_WRITES | LOG_UNKNOWNS, "%s: cdic_w: Unknown address: %04x = %04x & %04x\n", machine().describe_context(), addr*2, data, mem_mask);
break;
}
}
+void cdicdic_device::init_disc_read(uint8_t disc_mode)
+{
+ m_disc_command = m_command;
+ m_disc_mode = disc_mode;
+ m_curr_lba = lba_from_time();
+ m_disc_spinup_counter = 1;
+}
+
+void cdicdic_device::cancel_disc_read()
+{
+ m_disc_command = 0;
+ m_disc_mode = 0;
+ m_curr_lba = 0;
+ m_disc_spinup_counter = 0;
+}
+
+void cdicdic_device::handle_cdic_command()
+{
+ switch (m_command)
+ {
+ case 0x23: // Reset Mode 1
+ if (m_disc_command == 0)
+ init_disc_read(DISC_MODE1);
+ break;
+ case 0x24: // Reset Mode 2
+ case 0x2b: // Stop CDDA
+ case 0x2e: // Abort
+ cancel_disc_read();
+ break;
+ case 0x27: // Fetch TOC
+ init_disc_read(DISC_TOC);
+ break;
+ case 0x28: // Play CDDA
+ init_disc_read(DISC_CDDA);
+ break;
+ case 0x29: // Read Mode 1
+ case 0x2c: // Seek
+ init_disc_read(DISC_MODE1);
+ break;
+ case 0x2a: // Read Mode 2
+ init_disc_read(DISC_MODE2);
+ break;
+ }
+
+ m_data_buffer &= ~0x8000;
+}
+
+uint32_t cdicdic_device::lba_from_time()
+{
+ const uint8_t bcd_mins = (m_time >> 24) & 0xff;
+ const uint8_t mins_upper_digit = bcd_mins >> 4;
+ const uint8_t mins_lower_digit = bcd_mins & 0xf;
+ const uint8_t raw_mins = (mins_upper_digit * 10) + mins_lower_digit;
+
+ const uint8_t bcd_secs = (m_time >> 16) & 0xff;
+ const uint8_t secs_upper_digit = bcd_secs >> 4;
+ const uint8_t secs_lower_digit = bcd_secs & 0xf;
+ const uint8_t raw_secs = (secs_upper_digit * 10) + secs_lower_digit;
+
+ uint32_t lba = ((raw_mins * 60) + raw_secs) * 75;
+
+ const uint8_t bcd_frac = (m_time >> 8) & 0xff;
+ const bool even_second = BIT(bcd_frac, 7);
+ if (!even_second)
+ {
+ const uint8_t frac_upper_digit = bcd_frac >> 4;
+ const uint8_t frac_lower_digit = bcd_frac & 0xf;
+ const uint8_t raw_frac = (frac_upper_digit * 10) + frac_lower_digit;
+ lba += raw_frac;
+ }
+
+ if (lba >= 150)
+ lba -= 150;
+
+ return lba;
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -1271,6 +1114,14 @@ void cdicdic_device::device_resolve_objects()
void cdicdic_device::device_start()
{
+ m_ram = std::make_unique<uint8_t[]>(0x4000);
+ m_samples[0] = std::make_unique<int16_t[]>(s_samples_per_sector * 8 + 16);
+ m_samples[1] = std::make_unique<int16_t[]>(s_samples_per_sector * 8 + 16);
+
+ save_pointer(NAME(m_ram), 0x4000);
+ save_pointer(NAME(m_samples[0]), s_samples_per_sector * 8 + 16);
+ save_pointer(NAME(m_samples[1]), s_samples_per_sector * 8 + 16);
+
save_item(NAME(m_command));
save_item(NAME(m_time));
save_item(NAME(m_file));
@@ -1283,26 +1134,23 @@ void cdicdic_device::device_start()
save_item(NAME(m_interrupt_vector));
save_item(NAME(m_data_buffer));
- save_item(NAME(m_audio_sample_freq));
- save_item(NAME(m_audio_sample_size));
-
- m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::trigger_readback_int), this));
- m_interrupt_timer->adjust(attotime::never);
+ save_item(NAME(m_disc_command));
+ save_item(NAME(m_disc_mode));
+ save_item(NAME(m_disc_spinup_counter));
+ save_item(NAME(m_curr_lba));
- m_audio_sample_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::audio_sample_trigger), this));
- m_audio_sample_timer->adjust(attotime::never);
+ save_item(NAME(m_audio_sector_counter));
+ save_item(NAME(m_audio_format_sectors));
+ save_item(NAME(m_decoding_audio_map));
+ save_item(NAME(m_decode_addr));
- m_audio_playback_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::initial_sample_trigger), this));
- m_audio_playback_timer->adjust(attotime::never);
+ save_item(NAME(m_xa_last));
- m_periodic_sample_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::periodic_sample_trigger), this));
- m_periodic_sample_timer[0]->adjust(attotime::never);
- m_periodic_sample_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::periodic_sample_trigger), this));
- m_periodic_sample_timer[1]->adjust(attotime::never);
+ m_audio_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::audio_tick), this));
+ m_audio_timer->adjust(attotime::never);
- m_ram = std::make_unique<uint16_t[]>(0x3c00/2);
- m_samples[0] = std::make_unique<int16_t[]>(18*28*16+16);
- m_samples[1] = std::make_unique<int16_t[]>(18*28*16+16);
+ m_sector_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdicdic_device::sector_tick), this));
+ m_sector_timer->adjust(attotime::never);
}
//-------------------------------------------------
@@ -1323,11 +1171,15 @@ void cdicdic_device::device_reset()
m_interrupt_vector = 0x0f;
m_data_buffer = 0;
- m_audio_sample_freq = 0;
- m_audio_sample_size = 0;
+ m_disc_command = 0;
+ m_disc_mode = 0;
+ m_disc_spinup_counter = 0;
+ m_curr_lba = 0;
+ m_audio_sector_counter = 0;
+ m_audio_format_sectors = 0;
+ m_decoding_audio_map = false;
m_decode_addr = 0;
- m_decode_delay = 0;
if (m_cdrom_dev)
{
@@ -1342,28 +1194,28 @@ void cdicdic_device::device_reset()
m_cdda->set_cdrom(m_cd);
}
- m_interrupt_timer->adjust(attotime::never);
- m_audio_sample_timer->adjust(attotime::never);
- m_audio_playback_timer->adjust(attotime::never);
- m_periodic_sample_timer[0]->adjust(attotime::never);
- m_periodic_sample_timer[1]->adjust(attotime::never);
-
- m_break_on_achan = false;
- m_valid_audio_sample = false;
+ m_audio_timer->adjust(attotime::from_hz(75), 0, attotime::from_hz(75));
+ m_sector_timer->adjust(attotime::from_hz(75), 0, attotime::from_hz(75));
m_intreq_callback(CLEAR_LINE);
+
+ m_dmadac[0]->enable(1);
+ m_dmadac[1]->enable(1);
+
+ std::fill_n(&m_xa_last[0], 4, 0);
}
void cdicdic_device::ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
LOGMASKED(LOG_RAM, "%s: ram_w: %04x = %04x & %04x\n", machine().describe_context(), offset << 1, data, mem_mask);
- COMBINE_DATA(&m_ram[offset]);
+ COMBINE_DATA((uint16_t *)&m_ram[offset << 1]);
}
uint16_t cdicdic_device::ram_r(offs_t offset, uint16_t mem_mask)
{
- LOGMASKED(LOG_RAM, "%s: ram_r: %04x : %04x & %04x\n", machine().describe_context(), offset << 1, m_ram[offset], mem_mask);
- return m_ram[offset];
+ const uint16_t data = ((uint16_t)m_ram[(offset << 1) + 1] << 8) | m_ram[offset << 1];
+ LOGMASKED(LOG_RAM, "%s: ram_r: %04x : %04x & %04x\n", machine().describe_context(), offset << 1, data, mem_mask);
+ return data;
}
uint8_t cdicdic_device::intack_r()
diff --git a/src/mame/machine/cdicdic.h b/src/mame/machine/cdicdic.h
index 3eafa710345..0feacafb5dc 100644
--- a/src/mame/machine/cdicdic.h
+++ b/src/mame/machine/cdicdic.h
@@ -32,7 +32,6 @@ TODO:
#include "sound/dmadac.h"
#include "cdrom.h"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -53,7 +52,6 @@ public:
// non-static internal members
void sample_trigger();
- void process_delayed_command();
uint16_t regs_r(offs_t offset, uint16_t mem_mask = ~0);
void regs_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
@@ -69,51 +67,86 @@ protected:
virtual void device_reset() override;
// internal callbacks
- TIMER_CALLBACK_MEMBER( periodic_sample_trigger );
- TIMER_CALLBACK_MEMBER( audio_sample_trigger );
- TIMER_CALLBACK_MEMBER( initial_sample_trigger );
- TIMER_CALLBACK_MEMBER( trigger_readback_int );
+ TIMER_CALLBACK_MEMBER(sector_tick);
+ TIMER_CALLBACK_MEMBER(audio_tick);
private:
- enum
+ enum : uint8_t
{
- CDIC_SECTOR_SYNC = 0,
-
- CDIC_SECTOR_HEADER = 12,
-
- CDIC_SECTOR_MODE = 15,
-
- CDIC_SECTOR_FILE1 = 16,
- CDIC_SECTOR_CHAN1 = 17,
- CDIC_SECTOR_SUBMODE1 = 18,
- CDIC_SECTOR_CODING1 = 19,
-
- CDIC_SECTOR_FILE2 = 20,
- CDIC_SECTOR_CHAN2 = 21,
- CDIC_SECTOR_SUBMODE2 = 22,
- CDIC_SECTOR_CODING2 = 23,
-
- CDIC_SECTOR_DATA = 24,
-
- CDIC_SECTOR_SIZE = 2352,
-
- CDIC_SECTOR_DATASIZE = 2048,
- CDIC_SECTOR_AUDIOSIZE = 2304,
- CDIC_SECTOR_VIDEOSIZE = 2324,
-
- CDIC_SUBMODE_EOF = 0x80,
- CDIC_SUBMODE_RT = 0x40,
- CDIC_SUBMODE_FORM = 0x20,
- CDIC_SUBMODE_TRIG = 0x10,
- CDIC_SUBMODE_DATA = 0x08,
- CDIC_SUBMODE_AUDIO = 0x04,
- CDIC_SUBMODE_VIDEO = 0x02,
- CDIC_SUBMODE_EOR = 0x01
+ DISC_NONE,
+ DISC_MODE1,
+ DISC_MODE2,
+ DISC_CDDA,
+ DISC_TOC
};
- int is_valid_sample_buf(uint16_t addr) const;
- double sample_buf_freq(uint16_t addr) const;
- int sample_buf_size(uint16_t addr) const;
+ enum
+ {
+ SECTOR_SYNC = 0,
+
+ SECTOR_HEADER = 12,
+
+ SECTOR_MODE = 15,
+
+ SECTOR_FILE1 = 16,
+ SECTOR_CHAN1 = 17,
+ SECTOR_SUBMODE1 = 18,
+ SECTOR_CODING1 = 19,
+
+ SECTOR_FILE2 = 20,
+ SECTOR_CHAN2 = 21,
+ SECTOR_SUBMODE2 = 22,
+ SECTOR_CODING2 = 23,
+
+ SECTOR_DATA = 24,
+
+ SECTOR_SIZE = 2352,
+ SECTOR_AUDIO_SIZE = 2304,
+
+ SECTOR_DATASIZE = 2048,
+ SECTOR_AUDIOSIZE = 2304,
+ SECTOR_VIDEOSIZE = 2324,
+
+ SUBMODE_EOF = 0x80,
+ SUBMODE_RT = 0x40,
+ SUBMODE_FORM = 0x20,
+ SUBMODE_TRIG = 0x10,
+ SUBMODE_DATA = 0x08,
+ SUBMODE_AUDIO = 0x04,
+ SUBMODE_VIDEO = 0x02,
+ SUBMODE_EOR = 0x01,
+
+ CODING_BPS_MASK = 0x30,
+ CODING_4BPS = 0x00,
+ CODING_8BPS = 0x10,
+ CODING_16BPS = 0x20,
+ CODING_BPS_MPEG = 0x30,
+
+ CODING_RATE_MASK = 0x0c,
+ CODING_37KHZ = 0x00,
+ CODING_18KHZ = 0x04,
+ CODING_RATE_RESV = 0x08,
+ CODING_44KHZ = 0x0c,
+
+ CODING_CHAN_MASK = 0x03,
+ CODING_MONO = 0x00,
+ CODING_STEREO = 0x01,
+ CODING_CHAN_RESV = 0x02,
+ CODING_CHAN_MPEG = 0x03,
+
+ SUBCODE_Q_CONTROL = 12,
+ SUBCODE_Q_TRACK = 13,
+ SUBCODE_Q_INDEX = 14,
+ SUBCODE_Q_MODE1_MINS = 15,
+ SUBCODE_Q_MODE1_SECS = 16,
+ SUBCODE_Q_MODE1_FRAC = 17,
+ SUBCODE_Q_MODE1_ZERO = 18,
+ SUBCODE_Q_MODE1_AMINS = 19,
+ SUBCODE_Q_MODE1_ASECS = 20,
+ SUBCODE_Q_MODE1_AFRAC = 21,
+ SUBCODE_Q_CRC0 = 22,
+ SUBCODE_Q_CRC1 = 23
+ };
devcb_write_line m_intreq_callback;
@@ -139,36 +172,53 @@ private:
uint16_t m_interrupt_vector; // CDIC Interrupt Vector Register (0x303ffc)
uint16_t m_data_buffer; // CDIC Data Buffer Register (0x303ffe)
- emu_timer *m_interrupt_timer;
cdrom_file *m_cd;
- emu_timer *m_audio_sample_timer;
- emu_timer *m_audio_playback_timer;
- emu_timer *m_periodic_sample_timer[2];
- int32_t m_audio_sample_freq;
- int32_t m_audio_sample_size;
+ emu_timer *m_sector_timer;
+ uint8_t m_disc_command;
+ uint8_t m_disc_mode;
+ uint8_t m_disc_spinup_counter;
+ uint32_t m_curr_lba;
+ emu_timer *m_audio_timer;
+ uint8_t m_audio_sector_counter;
+ uint8_t m_audio_format_sectors;
+ bool m_decoding_audio_map;
uint16_t m_decode_addr;
- uint8_t m_decode_delay;
- attotime m_decode_period;
- bool m_break_on_achan;
- bool m_valid_audio_sample;
- int m_xa_last[4];
- std::unique_ptr<uint16_t[]> m_ram;
+ int16_t m_xa_last[4];
+ std::unique_ptr<uint8_t[]> m_ram;
std::unique_ptr<int16_t[]> m_samples[2];
- static void decode_xa_mono(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
- static void decode_xa_mono8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
- static void decode_xa_stereo(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
- static void decode_xa_stereo8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
+ void decode_8bit_xa_unit(int channel, uint8_t param, const uint8_t *data, int16_t *out_buffer);
+ void decode_4bit_xa_unit(int channel, uint8_t param, const uint8_t *data, uint8_t shift, int16_t *out_buffer);
+ void play_raw_group(const uint8_t *data);
+ void play_xa_group(const uint8_t coding, const uint8_t *data);
+ void play_audio_sector(const uint8_t coding, const uint8_t *data);
+ void process_audio_map();
+
+ bool is_mode2_sector_selected(const uint8_t *buffer);
+ bool is_mode2_audio_selected(const uint8_t *buffer);
+
+ void process_disc_sector();
+ void process_sector_data(const uint8_t *buffer, const uint8_t *subcode_buffer);
+ void init_disc_read(uint8_t disc_mode);
+ void cancel_disc_read();
+ void handle_cdic_command();
+
+ void update_interrupt_state();
+
+ uint32_t lba_from_time();
- static const int32_t s_cdic_adpcm_filter_coef[5][2];
+ static uint8_t get_sector_count_for_coding(uint8_t coding);
+ static void decode_xa_mono(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
+ static void decode_xa_mono8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
+ static void decode_xa_stereo(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
+ static void decode_xa_stereo8(int16_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
- uint32_t increment_cdda_frame_bcd(uint32_t bcd);
- uint32_t increment_cdda_sector_bcd(uint32_t bcd);
- void decode_audio_sector(const uint8_t *xa, int32_t triggered);
- void play_audio_sector();
+ static const int16_t s_xa_filter_coef[4][2];
+ static const int32_t s_samples_per_sector;
+ static const uint16_t s_crc_ccitt_table[256];
};
// device type definition
diff --git a/src/mame/machine/cdislavehle.cpp b/src/mame/machine/cdislavehle.cpp
index c8e01d67a10..4c103f24a37 100644
--- a/src/mame/machine/cdislavehle.cpp
+++ b/src/mame/machine/cdislavehle.cpp
@@ -18,6 +18,8 @@ TODO:
#include "emu.h"
#include "machine/cdislavehle.h"
+#include <algorithm>
+
#define LOG_IRQS (1 << 0)
#define LOG_COMMANDS (1 << 1)
#define LOG_READS (1 << 2)
@@ -56,62 +58,57 @@ void cdislave_hle_device::prepare_readback(const attotime &delay, uint8_t channe
m_interrupt_timer->adjust(delay);
}
-void cdislave_hle_device::perform_mouse_update()
+INPUT_CHANGED_MEMBER( cdislave_hle_device::mouse_update )
{
- uint16_t x = m_mousex->read();
- uint16_t y = m_mousey->read();
- uint8_t buttons = m_mousebtn->read();
-
- uint16_t old_mouse_x = m_real_mouse_x;
- uint16_t old_mouse_y = m_real_mouse_y;
-
- if (m_real_mouse_x == 0xffff)
+ const uint8_t button_state = m_mousebtn->read();
+ uint8_t button_bits = 0x01;
+ if (BIT(button_state, 0))
+ button_bits |= 0x02;
+ if (BIT(button_state, 1))
+ button_bits |= 0x04;
+ if (BIT(button_state, 2))
+ button_bits |= 0x06;
+
+ const uint16_t x = m_mousex->read();
+ const uint16_t y = m_mousey->read();
+
+ int16_t deltax = 0;
+ int16_t deltay = 0;
+
+ if (m_input_mouse_x != 0xffff && m_input_mouse_y != 0xffff)
{
- old_mouse_x = x & 0x3ff;
- old_mouse_y = y & 0x3ff;
+ deltax = -(m_input_mouse_x - x);
+ deltay = -(m_input_mouse_y - y);
}
- m_real_mouse_x = x & 0x3ff;
- m_real_mouse_y = y & 0x3ff;
+ m_input_mouse_x = x;
+ m_input_mouse_y = y;
- m_fake_mouse_x += (m_real_mouse_x - old_mouse_x);
- m_fake_mouse_y += (m_real_mouse_y - old_mouse_y);
-
- while (m_fake_mouse_x > 0x3ff)
- {
- m_fake_mouse_x += 0x400;
- }
-
- while (m_fake_mouse_y > 0x3ff)
- {
- m_fake_mouse_y += 0x400;
- }
-
- x = m_fake_mouse_x;
- y = m_fake_mouse_y;
+ m_device_mouse_x = std::clamp(m_device_mouse_x + deltax, 0, 767);
+ m_device_mouse_y = std::clamp(m_device_mouse_y + deltay, 0, 559);
if (m_polling_active)
{
- prepare_readback(attotime::zero, 0, 4, ((x & 0x380) >> 7) | (buttons << 4), x & 0x7f, (y & 0x380) >> 7, y & 0x7f, 0xf7);
+ const uint8_t byte3 = ((m_device_mouse_x & 0x380) >> 7) | (button_bits << 3);
+ const uint8_t byte2 = m_device_mouse_x & 0x7f;
+ const uint8_t byte1 = (m_device_mouse_y & 0x380) >> 7;
+ const uint8_t byte0 = m_device_mouse_y & 0x7f;
+ prepare_readback(attotime::zero, 0, 4, byte3, byte2, byte1, byte0, 0xf7);
}
}
-INPUT_CHANGED_MEMBER( cdislave_hle_device::mouse_update )
-{
- perform_mouse_update();
-}
-
static INPUT_PORTS_START(cdislave_mouse)
PORT_START("MOUSEX")
- PORT_BIT(0x3ff, 0x000, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0x3ff) PORT_KEYDELTA(2) PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
+ PORT_BIT(0xffff, 0x000, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
PORT_START("MOUSEY")
- PORT_BIT(0x3ff, 0x000, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_MINMAX(0x000, 0x3ff) PORT_KEYDELTA(2) PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
+ PORT_BIT(0xffff, 0x000, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
PORT_START("MOUSEBTN")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Mouse Button 1") PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Mouse Button 2") PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
- PORT_BIT(0xfc, IP_ACTIVE_HIGH, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Button 1") PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Button 2") PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_CODE(MOUSECODE_BUTTON3) PORT_NAME("Button 3") PORT_CHANGED_MEMBER(DEVICE_SELF, cdislave_hle_device, mouse_update, 0)
+ PORT_BIT(0xf8, IP_ACTIVE_HIGH, IPT_UNUSED)
INPUT_PORTS_END
ioport_constructor cdislave_hle_device::device_input_ports() const
@@ -156,20 +153,8 @@ uint16_t cdislave_hle_device::slave_r(offs_t offset)
void cdislave_hle_device::set_mouse_position()
{
-// uint16_t x, y;
-
- //printf( "Set mouse position: %02x %02x %02x\n", m_in_buf[0], m_in_buf[1], m_in_buf[2] );
-
- m_fake_mouse_y = ((m_in_buf[1] & 0x0f) << 6) | (m_in_buf[0] & 0x3f);
- m_fake_mouse_x = ((m_in_buf[1] & 0x70) << 3) | m_in_buf[2];
-
-// x = m_fake_mouse_x;
-// y = m_fake_mouse_y;
-
- if (m_polling_active)
- {
- //prepare_readback(attotime::zero, 0, 4, (x & 0x380) >> 7, x & 0x7f, (y & 0x380) >> 7, y & 0x7f, 0xf7);
- }
+ m_device_mouse_x = ((m_in_buf[1] & 0x70) << 3) | (m_in_buf[2] & 0x7f);
+ m_device_mouse_y = ((m_in_buf[1] & 0x0f) << 6) | (m_in_buf[0] & 0x3f);
}
void cdislave_hle_device::slave_w(offs_t offset, uint16_t data)
@@ -290,20 +275,24 @@ void cdislave_hle_device::slave_w(offs_t offset, uint16_t data)
switch (data & 0x00ff)
{
case 0x82: // Mute Audio
+ {
LOGMASKED(LOG_COMMANDS, "slave_w: Channel %d: Mute Audio (0x82)\n", offset);
- m_dmadac[0]->enable(0);
- m_dmadac[1]->enable(0);
+ m_dmadac[0]->set_volume(0);
+ m_dmadac[1]->set_volume(0);
m_in_index = 0;
m_in_count = 0;
//cdic->audio_sample_timer->adjust(attotime::never);
break;
+ }
case 0x83: // Unmute Audio
+ {
LOGMASKED(LOG_COMMANDS, "slave_w: Channel %d: Unmute Audio (0x83)\n", offset);
- m_dmadac[0]->enable(1);
- m_dmadac[1]->enable(1);
+ m_dmadac[0]->set_volume(0x100);
+ m_dmadac[1]->set_volume(0x100);
m_in_index = 0;
m_in_count = 0;
break;
+ }
case 0xf0: // Set Front Panel LCD
LOGMASKED(LOG_COMMANDS, "slave_w: Channel %d: Set Front Panel LCD (0xf0)\n", offset);
m_in_count = 17;
@@ -476,11 +465,11 @@ void cdislave_hle_device::device_start()
save_item(NAME(m_lcd_state));
- save_item(NAME(m_real_mouse_x));
- save_item(NAME(m_real_mouse_y));
+ save_item(NAME(m_input_mouse_x));
+ save_item(NAME(m_input_mouse_y));
- save_item(NAME(m_fake_mouse_x));
- save_item(NAME(m_fake_mouse_y));
+ save_item(NAME(m_device_mouse_x));
+ save_item(NAME(m_device_mouse_y));
m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cdislave_hle_device::trigger_readback_int), this));
m_interrupt_timer->adjust(attotime::never);
@@ -513,11 +502,11 @@ void cdislave_hle_device::device_reset()
memset(m_lcd_state, 0, 16);
- m_real_mouse_x = 0xffff;
- m_real_mouse_y = 0xffff;
+ m_input_mouse_x = 0xffff;
+ m_input_mouse_y = 0xffff;
- m_fake_mouse_x = 0;
- m_fake_mouse_y = 0;
+ m_device_mouse_x = 0;
+ m_device_mouse_y = 0;
m_int_callback(CLEAR_LINE);
}
diff --git a/src/mame/machine/cdislavehle.h b/src/mame/machine/cdislavehle.h
index 167437722fe..f4e31d7d117 100644
--- a/src/mame/machine/cdislavehle.h
+++ b/src/mame/machine/cdislavehle.h
@@ -55,6 +55,9 @@ protected:
TIMER_CALLBACK_MEMBER( trigger_readback_int );
private:
+ void prepare_readback(const attotime &delay, uint8_t channel, uint8_t count, uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t cmd);
+ void set_mouse_position();
+
devcb_write_line m_int_callback;
required_device_array<dmadac_sound_device, 2> m_dmadac;
@@ -63,12 +66,8 @@ private:
required_ioport m_mousey;
required_ioport m_mousebtn;
- // internal state
- class channel_state
+ struct channel_state
{
- public:
- channel_state() { }
-
uint8_t m_out_buf[4];
uint8_t m_out_index;
uint8_t m_out_count;
@@ -88,18 +87,11 @@ private:
uint8_t m_lcd_state[16];
- uint16_t m_real_mouse_x;
- uint16_t m_real_mouse_y;
+ uint16_t m_input_mouse_x;
+ uint16_t m_input_mouse_y;
- uint16_t m_fake_mouse_x;
- uint16_t m_fake_mouse_y;
-
- // static internal members
-
- // non-static internal members
- void prepare_readback(const attotime &delay, uint8_t channel, uint8_t count, uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3, uint8_t cmd);
- void perform_mouse_update();
- void set_mouse_position();
+ int16_t m_device_mouse_x;
+ int16_t m_device_mouse_y;
};