summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/akiko.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/akiko.cpp')
-rw-r--r--src/devices/machine/akiko.cpp261
1 files changed, 120 insertions, 141 deletions
diff --git a/src/devices/machine/akiko.cpp b/src/devices/machine/akiko.cpp
index eb5fa929059..5ebe4603a0e 100644
--- a/src/devices/machine/akiko.cpp
+++ b/src/devices/machine/akiko.cpp
@@ -11,21 +11,34 @@
- Chunky to planar converter
- 2x CIA chips
+ TODO:
+ - Reportedly the CD drive should be a Sony KSM-2101BAM,
+ schematics shows Akiko connected to a laconic "26-pin CD connector"
+ - NVRAM needs inheriting from i2c_24c08_device;
+ - Handle tray open/close events, needed at very least by:
+ \- cdtv:cdremix2 load sequences;
+ \- kangfu on cd32 as "out of memory" workaround;
+
***************************************************************************/
#include "emu.h"
#include "akiko.h"
-#include "imagedev/chd_cd.h"
+
#include "coreutil.h"
-#include "romload.h"
+#include "multibyte.h"
+#define LOG_WARN (1U << 1) // Show warnings
+#define LOG_REGS (1U << 2) // Show register r/w
+#define LOG_CD (1U << 3) // Show CD interactions and commands
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
+#define VERBOSE (LOG_WARN)
+//#define LOG_OUTPUT_STREAM std::cout
-#define LOG_AKIKO 0
-#define LOG_AKIKO_CD 0
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__)
+#define LOGCD(...) LOGMASKED(LOG_CD, __VA_ARGS__)
//**************************************************************************
@@ -40,6 +53,11 @@ DEFINE_DEVICE_TYPE(AKIKO, akiko_device, "akiko", "CBM AKIKO")
void akiko_device::device_add_mconfig(machine_config &config)
{
+ CDROM(config, m_cdrom).set_interface("cdrom");
+ CDDA(config, m_cdda);
+ m_cdda->add_route(0, ":lspeaker", 0.50);
+ m_cdda->add_route(1, ":rspeaker", 0.50);
+ m_cdda->set_cdrom_tag(m_cdrom);
}
@@ -52,33 +70,32 @@ void akiko_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
akiko_device::akiko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, AKIKO, tag, owner, clock),
- m_c2p_input_index(0),
- m_c2p_output_index(0),
- m_i2c_scl_out(0),
- m_i2c_scl_dir(0),
- m_i2c_sda_out(0),
- m_i2c_sda_dir(0),
- m_cdrom_track_index(0),
- m_cdrom_lba_start(0),
- m_cdrom_lba_end(0),
- m_cdrom_lba_cur(0),
- m_cdrom_readmask(0),
- m_cdrom_readreqmask(0),
- m_cdrom_dmacontrol(0),
- m_cdrom_numtracks(0),
- m_cdrom_speed(0),
- m_cdrom_cmd_start(0),
- m_cdrom_cmd_end(0),
- m_cdrom_cmd_resp(0),
- m_cdda(nullptr),
- m_cdrom(nullptr),
- m_cdrom_toc(nullptr),
- m_dma_timer(nullptr),
- m_frame_timer(nullptr),
- m_cdrom_is_device(0),
- m_mem_r(*this), m_mem_w(*this), m_int_w(*this),
- m_scl_w(*this), m_sda_r(*this), m_sda_w(*this)
+ : device_t(mconfig, AKIKO, tag, owner, clock)
+ , m_c2p_input_index(0)
+ , m_c2p_output_index(0)
+ , m_i2c_scl_out(0)
+ , m_i2c_scl_dir(0)
+ , m_i2c_sda_out(0)
+ , m_i2c_sda_dir(0)
+ , m_cdrom_track_index(0)
+ , m_cdrom_lba_start(0)
+ , m_cdrom_lba_end(0)
+ , m_cdrom_lba_cur(0)
+ , m_cdrom_readmask(0)
+ , m_cdrom_readreqmask(0)
+ , m_cdrom_dmacontrol(0)
+ , m_cdrom_numtracks(0)
+ , m_cdrom_speed(0)
+ , m_cdrom_cmd_start(0)
+ , m_cdrom_cmd_end(0)
+ , m_cdrom_cmd_resp(0)
+ , m_cdda(*this, "cdda")
+ , m_cdrom(*this, "cdrom")
+ , m_cdrom_toc(nullptr)
+ , m_dma_timer(nullptr)
+ , m_frame_timer(nullptr)
+ , m_mem_r(*this, 0xffff), m_mem_w(*this), m_int_w(*this)
+ , m_scl_w(*this), m_sda_r(*this, 1), m_sda_w(*this)
{
for (int i = 0; i < 8; i++)
{
@@ -99,14 +116,6 @@ akiko_device::akiko_device(const machine_config &mconfig, const char *tag, devic
void akiko_device::device_start()
{
- // resolve callbacks
- m_mem_r.resolve_safe(0xffff);
- m_mem_w.resolve_safe();
- m_int_w.resolve_safe();
- m_scl_w.resolve_safe();
- m_sda_r.resolve_safe(1);
- m_sda_w.resolve_safe();
-
m_c2p_input_index = 0;
m_c2p_output_index = 0;
@@ -131,9 +140,8 @@ void akiko_device::device_start()
m_cdrom_cmd_resp = 0;
m_cdrom_toc = nullptr;
- m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(akiko_device::dma_proc), this));
- m_frame_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(akiko_device::frame_proc), this));
- m_cdda = machine().device<cdda_device>("cdda");
+ m_dma_timer = timer_alloc(FUNC(akiko_device::dma_proc), this);
+ m_frame_timer = timer_alloc(FUNC(akiko_device::frame_proc), this);
}
//-------------------------------------------------
@@ -142,33 +150,18 @@ void akiko_device::device_start()
void akiko_device::device_reset()
{
- cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
-
- if (cddevice != nullptr)
- {
- // MESS case
- m_cdrom = cddevice->get_cdrom_file();
- m_cdrom_is_device = 1;
- }
- else
- {
- // MAME case
- m_cdrom = cdrom_open(machine().rom_load().get_disk_handle(":cdrom"));
- m_cdrom_is_device = 0;
- }
-
/* create the TOC table */
- if ( m_cdrom != nullptr && cdrom_get_last_track(m_cdrom) )
+ if ( m_cdrom->exists() && m_cdrom->get_last_track() )
{
uint8_t *p;
- int i, addrctrl = cdrom_get_adr_control( m_cdrom, 0 );
+ int i, addrctrl = m_cdrom->get_adr_control( 0 );
uint32_t discend;
- discend = cdrom_get_track_start(m_cdrom,cdrom_get_last_track(m_cdrom)-1);
- discend += cdrom_get_toc(m_cdrom)->tracks[cdrom_get_last_track(m_cdrom)-1].frames;
- discend = lba_to_msf(discend);
+ discend = m_cdrom->get_track_start(m_cdrom->get_last_track()-1);
+ discend += m_cdrom->get_toc().tracks[m_cdrom->get_last_track()-1].frames;
+ discend = cdrom_file::lba_to_msf(discend);
- m_cdrom_numtracks = cdrom_get_last_track(m_cdrom)+3;
+ m_cdrom_numtracks = m_cdrom->get_last_track()+3;
m_cdrom_toc = std::make_unique<uint8_t[]>(13*m_cdrom_numtracks);
memset( m_cdrom_toc.get(), 0, 13*m_cdrom_numtracks);
@@ -180,27 +173,23 @@ void akiko_device::device_reset()
p += 13;
p[1] = 0x01;
p[3] = 0xa1; /* last track */
- p[8] = cdrom_get_last_track(m_cdrom);
+ p[8] = m_cdrom->get_last_track();
p += 13;
p[1] = 0x01;
p[3] = 0xa2; /* disc end */
- p[8] = (discend >> 16 ) & 0xff;
- p[9] = (discend >> 8 ) & 0xff;
- p[10] = discend & 0xff;
+ put_u24be(&p[8], discend);
p += 13;
- for( i = 0; i < cdrom_get_last_track(m_cdrom); i++ )
+ for( i = 0; i < m_cdrom->get_last_track(); i++ )
{
- uint32_t trackpos = cdrom_get_track_start(m_cdrom,i);
+ uint32_t trackpos = m_cdrom->get_track_start(i);
- trackpos = lba_to_msf(trackpos);
- addrctrl = cdrom_get_adr_control( m_cdrom, i );
+ trackpos = cdrom_file::lba_to_msf(trackpos);
+ addrctrl = m_cdrom->get_adr_control( i );
p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
p[3] = dec_2_bcd( i+1 );
- p[8] = (trackpos >> 16 ) & 0xff;
- p[9] = (trackpos >> 8 ) & 0xff;
- p[10] = trackpos & 0xff;
+ put_u24be(&p[8], trackpos);
p += 13;
}
@@ -214,14 +203,6 @@ void akiko_device::device_reset()
void akiko_device::device_stop()
{
- if (!m_cdrom_is_device)
- {
- if( m_cdrom )
- {
- cdrom_close(m_cdrom);
- m_cdrom = (cdrom_file *)nullptr;
- }
- }
}
void akiko_device::nvram_write(uint32_t data)
@@ -265,6 +246,11 @@ void akiko_device::mem_w8(offs_t offset, uint8_t data)
m_mem_w(offset, data << shift, 0xff << shift);
}
+void akiko_device::set_mute(bool mute)
+{
+ m_cdda->set_output_gain( 0, mute ? 0.0 : 1.0 );
+}
+
/*************************************
*
@@ -346,7 +332,7 @@ void akiko_device::cdda_stop()
if (m_cdda != nullptr)
{
m_cdda->stop_audio();
- m_frame_timer->reset( );
+ m_frame_timer->reset();
}
}
@@ -413,8 +399,7 @@ void akiko_device::set_cd_status(uint32_t status)
if ( m_cdrom_status[0] & m_cdrom_status[1] )
{
- if (LOG_AKIKO_CD)
- logerror("Akiko CD IRQ\n");
+ LOGCD("Akiko CD IRQ\n");
m_int_w(1);
}
@@ -453,6 +438,9 @@ TIMER_CALLBACK_MEMBER(akiko_device::dma_proc)
uint8_t buf[2352];
int index;
+ if ( !m_cdrom->exists() )
+ return;
+
if ( (m_cdrom_dmacontrol & 0x04000000) == 0 )
return;
@@ -463,38 +451,36 @@ TIMER_CALLBACK_MEMBER(akiko_device::dma_proc)
if ( m_cdrom_readreqmask & ( 1 << index ) )
{
- uint32_t track = cdrom_get_track( m_cdrom, m_cdrom_lba_cur );
- uint32_t datasize;// = cdrom_get_toc(m_cdrom)->tracks[track].datasize;
- uint32_t subsize = cdrom_get_toc( m_cdrom )->tracks[track].subsize;
+ uint32_t track = m_cdrom->get_track( m_cdrom_lba_cur );
+ uint32_t datasize;// = m_cdrom->get_toc().tracks[track].datasize;
+ uint32_t subsize = m_cdrom->get_toc().tracks[track].subsize;
- uint32_t curmsf = lba_to_msf( m_cdrom_lba_cur );
+ uint32_t curmsf = cdrom_file::lba_to_msf( m_cdrom_lba_cur );
memset( buf, 0, 16 );
buf[3] = m_cdrom_lba_cur - m_cdrom_lba_start;
memset( &buf[4], 0xff, 8 );
- buf[12] = (curmsf >> 16) & 0xff;
- buf[13] = (curmsf >> 8) & 0xff;
- buf[14] = curmsf & 0xff;
+ put_u24be(&buf[12], curmsf);
buf[15] = 0x01; /* mode1 */
datasize = 2048;
- if ( !cdrom_read_data( m_cdrom, m_cdrom_lba_cur, &buf[16], CD_TRACK_MODE1 ) )
+ if ( !m_cdrom->read_data( m_cdrom_lba_cur, &buf[16], cdrom_file::CD_TRACK_MODE1 ) )
{
- logerror( "AKIKO: Read error trying to read sector %08x!\n", m_cdrom_lba_cur );
+ LOGWARN( "AKIKO: Read error trying to read sector %08x!\n", m_cdrom_lba_cur );
return;
}
if ( subsize )
{
- if ( !cdrom_read_subcode( m_cdrom, m_cdrom_lba_cur, &buf[16+datasize] ) )
+ if ( !m_cdrom->read_subcode( m_cdrom_lba_cur, &buf[16+datasize] ) )
{
- logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", m_cdrom_lba_cur );
+ LOGWARN( "AKIKO: Read error trying to read subcode for sector %08x!\n", m_cdrom_lba_cur );
return;
}
}
- if (LOG_AKIKO_CD) logerror( "DMA: sector %d - address %08x\n", m_cdrom_lba_cur, m_cdrom_address[0] + (index*4096) );
+ LOGCD( "DMA: sector %d - address %08x\n", m_cdrom_lba_cur, m_cdrom_address[0] + (index*4096) );
// write sector data to host memory
for (int i = 0; i < 2352; i++)
@@ -575,11 +561,11 @@ TIMER_CALLBACK_MEMBER( akiko_device::cd_delayed_cmd )
if ( param == 0x05 )
{
- if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param );
+ LOGCD( "AKIKO: Completing Command %d\n", param );
resp[0] = 0x06;
- if ( m_cdrom == nullptr || m_cdrom_numtracks == 0 )
+ if ( !m_cdrom->exists() || m_cdrom_numtracks == 0 )
{
resp[1] = 0x80;
setup_response( 15, resp );
@@ -613,7 +599,7 @@ void akiko_device::update_cdrom()
cmd &= 0x0f;
- if (LOG_AKIKO_CD) logerror( "CDROM command: %02X\n", cmd );
+ LOGCD( "CDROM command: %02X\n", cmd );
if ( cmd == 0x02 ) /* pause audio */
{
@@ -624,7 +610,7 @@ void akiko_device::update_cdrom()
cdda_pause(1);
- m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
setup_response( 2, resp );
}
@@ -637,7 +623,7 @@ void akiko_device::update_cdrom()
cdda_pause(0);
- m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
setup_response( 2, resp );
}
@@ -653,9 +639,9 @@ void akiko_device::update_cdrom()
cmd_addr += ( m_cdrom_cmd_start + i + 1 ) & 0xff;
}
- m_cdrom_cmd_start = (m_cdrom_cmd_start+13) & 0xff;
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 13) & 0xff;
- if ( m_cdrom == nullptr || m_cdrom_numtracks == 0 )
+ if ( !m_cdrom->exists() || m_cdrom_numtracks == 0 )
{
resp[1] = 0x80;
setup_response( 2, resp );
@@ -671,8 +657,8 @@ void akiko_device::update_cdrom()
if ( cmdbuf[7] == 0x80 )
{
- if (LOG_AKIKO_CD) logerror( "%s:AKIKO CD: Data read - start lba: %08x - end lba: %08x\n", machine().describe_context(), startpos, endpos );
m_cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
+ LOGCD("AKIKO CD: Data read - start lba: %08x - end lba: %08x - divider speed: %d\n", startpos, endpos, m_cdrom_speed );
m_cdrom_lba_start = startpos;
m_cdrom_lba_end = endpos;
@@ -680,18 +666,18 @@ void akiko_device::update_cdrom()
}
else if ( cmdbuf[10] & 0x04 )
{
- logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
+ LOGCD("AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
cdda_play(startpos, endpos - startpos);
resp[1] = 0x08;
}
else
{
- if (LOG_AKIKO_CD) logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
+ LOGCD("AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
m_cdrom_track_index = 0;
- for( i = 0; i < cdrom_get_last_track(m_cdrom); i++ )
+ for( i = 0; i < m_cdrom->get_last_track(); i++ )
{
- if ( startpos <= cdrom_get_track_start( m_cdrom, i ) )
+ if ( startpos <= m_cdrom->get_track_start( i ) )
{
/* reset to 0 */
m_cdrom_track_index = i + 2;
@@ -706,9 +692,9 @@ void akiko_device::update_cdrom()
}
else if ( cmd == 0x05 ) /* read toc */
{
- m_cdrom_cmd_start = (m_cdrom_cmd_start+3) & 0xff;
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 3) & 0xff;
- machine().scheduler().timer_set( attotime::from_msec(1), timer_expired_delegate(FUNC(akiko_device::cd_delayed_cmd ), this), resp[0]);
+ machine().scheduler().timer_set( attotime::from_msec(1), timer_expired_delegate( FUNC( akiko_device::cd_delayed_cmd ), this ), resp[0] );
break;
}
@@ -720,49 +706,47 @@ void akiko_device::update_cdrom()
(void)cdda_getstatus(&lba);
- if ( lba > 0 )
+ if ( lba > 0 && m_cdrom->exists() )
{
uint32_t disk_pos;
uint32_t track_pos;
uint32_t track;
int addrctrl;
- track = cdrom_get_track(m_cdrom, lba);
- addrctrl = cdrom_get_adr_control(m_cdrom, track);
+ track = m_cdrom->get_track(lba);
+ addrctrl = m_cdrom->get_adr_control(track);
resp[2] = 0x00;
resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
resp[4] = dec_2_bcd(track+1);
resp[5] = 0; /* index */
- disk_pos = lba_to_msf(lba);
- track_pos = lba_to_msf(lba - cdrom_get_track_start(m_cdrom, track));
+ disk_pos = cdrom_file::lba_to_msf(lba);
+ track_pos = cdrom_file::lba_to_msf(lba - m_cdrom->get_track_start(track));
/* track position */
- resp[6] = (track_pos >> 16) & 0xff;
- resp[7] = (track_pos >> 8) & 0xff;
- resp[8] = track_pos & 0xff;
+ put_u24be(&resp[6], track_pos);
/* disk position */
- resp[9] = (disk_pos >> 24) & 0xff;
- resp[10] = (disk_pos >> 16) & 0xff;
- resp[11] = (disk_pos >> 8) & 0xff;
- resp[12] = disk_pos & 0xff;
+ put_u32be(&resp[9], disk_pos);
}
else
{
resp[1] = 0x80;
}
+ // needed by cdtv:defcrown (would otherwise hardlock emulation)
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
+
setup_response( 15, resp );
}
else if ( cmd == 0x07 ) /* check door status */
{
resp[1] = 0x01;
- m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
+ m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
- if ( m_cdrom == nullptr || m_cdrom_numtracks == 0 )
+ if ( !m_cdrom->exists() || m_cdrom_numtracks == 0 )
resp[1] = 0x80;
setup_response( 20, resp );
@@ -775,19 +759,16 @@ void akiko_device::update_cdrom()
}
}
-READ32_MEMBER( akiko_device::read )
+uint32_t akiko_device::read(offs_t offset)
{
uint32_t retval;
- if ( LOG_AKIKO && offset < (0x30/4) )
- {
- logerror( "Reading AKIKO reg %0x [%s] at %s\n", offset, get_akiko_reg_name(offset), machine().describe_context());
- }
+ if ( offset < (0x30/4) )
+ LOGREGS("Reading AKIKO reg %0x [%s] at %s\n", offset, get_akiko_reg_name(offset), machine().describe_context());
switch( offset )
{
case 0x00/4: /* ID */
- if ( m_cdrom != nullptr ) m_cdda->set_cdrom(m_cdrom);
return 0x0000cafe;
case 0x04/4: /* CDROM STATUS 1 */
@@ -837,12 +818,10 @@ READ32_MEMBER( akiko_device::read )
return 0;
}
-WRITE32_MEMBER( akiko_device::write )
+void akiko_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- if ( LOG_AKIKO && offset < (0x30/4) )
- {
- logerror( "Writing AKIKO reg %0x [%s] with %08x at %s\n", offset, get_akiko_reg_name(offset), data, machine().describe_context());
- }
+ if ( offset < (0x30/4) )
+ LOGREGS("Writing AKIKO reg %0x [%s] with %08x at %s\n", offset, get_akiko_reg_name(offset), data, machine().describe_context());
switch( offset )
{
@@ -881,7 +860,7 @@ WRITE32_MEMBER( akiko_device::write )
break;
case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */
- if (LOG_AKIKO_CD) logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
+ LOGCD( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ACCESSING_BITS_16_31 )
{
m_cdrom_readreqmask = (data >> 16);
@@ -890,7 +869,7 @@ WRITE32_MEMBER( akiko_device::write )
break;
case 0x24/4: /* CDROM DMA ENABLE? */
- if (LOG_AKIKO_CD) logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
+ LOGCD( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ( m_cdrom_dmacontrol ^ data ) & 0x04000000 )
{
if ( data & 0x04000000 )