Ported over CD-i cleanup from MESS. [Harmony]

This commit is contained in:
Ryan Holtz 2010-09-26 22:08:49 +00:00
parent a383b8b20d
commit 179a81a030
12 changed files with 5105 additions and 4495 deletions

9
.gitattributes vendored
View File

@ -2532,6 +2532,7 @@ src/mame/includes/ccastles.h svneol=native#text/plain
src/mame/includes/cchasm.h svneol=native#text/plain
src/mame/includes/cchip.h svneol=native#text/plain
src/mame/includes/cclimber.h svneol=native#text/plain
src/mame/includes/cdi.h svneol=native#text/plain
src/mame/includes/centiped.h svneol=native#text/plain
src/mame/includes/chaknpop.h svneol=native#text/plain
src/mame/includes/champbas.h svneol=native#text/plain
@ -3265,6 +3266,12 @@ src/mame/machine/carpolo.c svneol=native#text/plain
src/mame/machine/cchasm.c svneol=native#text/plain
src/mame/machine/cchip.c svneol=native#text/plain
src/mame/machine/cclimber.c svneol=native#text/plain
src/mame/machine/cdi070.c svneol=native#text/plain
src/mame/machine/cdi070.h svneol=native#text/plain
src/mame/machine/cdicdic.c svneol=native#text/plain
src/mame/machine/cdicdic.h svneol=native#text/plain
src/mame/machine/cdislave.c svneol=native#text/plain
src/mame/machine/cdislave.h svneol=native#text/plain
src/mame/machine/chaknpop.c svneol=native#text/plain
src/mame/machine/copsnrob.c svneol=native#text/plain
src/mame/machine/cps2crpt.c svneol=native#text/plain
@ -3801,6 +3808,8 @@ src/mame/video/mario.c svneol=native#text/plain
src/mame/video/markham.c svneol=native#text/plain
src/mame/video/matmania.c svneol=native#text/plain
src/mame/video/mcatadv.c svneol=native#text/plain
src/mame/video/mcd212.c svneol=native#text/plain
src/mame/video/mcd212.h svneol=native#text/plain
src/mame/video/mcr.c svneol=native#text/plain
src/mame/video/mcr3.c svneol=native#text/plain
src/mame/video/mcr68.c svneol=native#text/plain

File diff suppressed because it is too large Load Diff

42
src/mame/includes/cdi.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef _INCLUDES_CDI_H_
#define _INCLUDES_CDI_H_
#include "machine/cdi070.h"
#include "machine/cdislave.h"
#include "machine/cdicdic.h"
#include "sound/dmadac.h"
#include "video/mcd212.h"
/*----------- driver state -----------*/
#define CLOCK_A XTAL_30MHz
#define CLOCK_B XTAL_19_6608MHz
class cdi_state : public driver_device
{
public:
cdi_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config) { }
UINT16 *planea;
UINT16 *planeb;
dmadac_sound_device *dmadac[2];
UINT8 timer_set;
emu_timer *test_timer;
bitmap_t* lcdbitmap;
scc68070_regs_t scc68070_regs;
mcd212_regs_t mcd212_regs;
mcd212_ab_t mcd212_ab;
};
/*----------- debug defines -----------*/
#define VERBOSE_LEVEL (5)
#define ENABLE_VERBOSE_LOG (1)
#define ENABLE_UART_PRINTING (0)
#endif // _INCLUDES_CDI_H_

754
src/mame/machine/cdi070.c Normal file
View File

@ -0,0 +1,754 @@
/******************************************************************************
CD-i-specific SCC68070 SoC peripheral emulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Skeleton. Just enough for the CD-i to run.
TODO:
- Proper handling of the 68070's internal devices (UART, DMA, Timers, etc.)
*******************************************************************************/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "machine/cdi070.h"
#include "includes/cdi.h"
#if ENABLE_VERBOSE_LOG
INLINE void verboselog(running_machine *machine, int n_level, const char *s_fmt, ...)
{
if( VERBOSE_LEVEL >= n_level )
{
va_list v;
char buf[ 32768 ];
va_start( v, s_fmt );
vsprintf( buf, s_fmt, v );
va_end( v );
logerror( "%08x: %s", cpu_get_pc(machine->device("maincpu")), buf );
}
}
#else
#define verboselog(x,y,z,...)
#endif
static void scc68070_set_timer_callback(scc68070_regs_t *scc68070, int channel)
{
UINT32 compare = 0;
attotime period;
switch(channel)
{
case 0:
compare = 0x10000 - scc68070->timers.timer0;
period = attotime_mul(ATTOTIME_IN_HZ(CLOCK_A/192), compare);
timer_adjust_oneshot(scc68070->timers.timer0_timer, period, 0);
break;
default:
fatalerror( "Unsupported timer channel to scc68070_set_timer_callback!" );
}
}
TIMER_CALLBACK( scc68070_timer0_callback )
{
cdi_state *state = machine->driver_data<cdi_state>();
scc68070_regs_t *scc68070 = &state->scc68070_regs;
scc68070->timers.timer0 = scc68070->timers.reload_register;
scc68070->timers.timer_status_register |= TSR_OV0;
if(scc68070->picr1 & 7)
{
UINT8 interrupt = scc68070->picr1 & 7;
scc68070->timers.timer_status_register |= TSR_OV0;
cpu_set_input_line_vector(machine->device("maincpu"), M68K_IRQ_1 + (interrupt - 1), 56 + interrupt);
cputag_set_input_line(machine, "maincpu", M68K_IRQ_1 + (interrupt - 1), ASSERT_LINE);
}
scc68070_set_timer_callback(&state->scc68070_regs, 0);
}
READ16_HANDLER( scc68070_periphs_r )
{
cdi_state *state = space->machine->driver_data<cdi_state>();
scc68070_regs_t *scc68070 = &state->scc68070_regs;
switch(offset)
{
// Interupts: 80001001
case 0x1000/2: // LIR priority level
return scc68070->lir;
// I2C interface: 80002001 to 80002009
case 0x2000/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Data Register: %04x & %04x\n", scc68070->i2c.data_register, mem_mask);
}
return scc68070->i2c.data_register;
case 0x2002/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Address Register: %04x & %04x\n", scc68070->i2c.address_register, mem_mask);
}
return scc68070->i2c.address_register;
case 0x2004/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Status Register: %04x & %04x\n", scc68070->i2c.status_register, mem_mask);
}
return scc68070->i2c.status_register;
case 0x2006/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Control Register: %04x & %04x\n", scc68070->i2c.control_register, mem_mask);
}
return scc68070->i2c.control_register;
case 0x2008/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Clock Control Register: %04x & %04x\n", scc68070->i2c.clock_control_register, mem_mask);
}
return scc68070->i2c.clock_control_register;
// UART interface: 80002011 to 8000201b
case 0x2010/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Mode Register: %04x & %04x\n", scc68070->uart.mode_register, mem_mask);
}
return scc68070->uart.mode_register | 0x20;
case 0x2012/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Status Register: %04x & %04x\n", scc68070->uart.status_register, mem_mask);
}
return scc68070->uart.status_register /*| USR_TXEMT*/ | USR_TXRDY | (1 << 1) | USR_RXRDY;
case 0x2014/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Clock Select: %04x & %04x\n", scc68070->uart.clock_select, mem_mask);
}
return scc68070->uart.clock_select | 0x08;
case 0x2016/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Command Register: %02x & %04x\n", scc68070->uart.command_register, mem_mask);
}
return scc68070->uart.command_register | 0x80;
case 0x2018/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Transmit Holding Register: %02x & %04x\n", scc68070->uart.transmit_holding_register, mem_mask);
}
return scc68070->uart.transmit_holding_register;
case 0x201a/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: UART Receive Holding Register: %02x & %04x\n", scc68070->uart.receive_holding_register, mem_mask);
return scc68070->uart.receive_holding_register;
}
return 0;
// Timers: 80002020 to 80002029
case 0x2020/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: Timer Control Register: %02x & %04x\n", scc68070->timers.timer_control_register, mem_mask);
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 12, "scc68070_periphs_r: Timer Status Register: %02x & %04x\n", scc68070->timers.timer_status_register, mem_mask);
}
return (scc68070->timers.timer_status_register << 8) | scc68070->timers.timer_control_register;
case 0x2022/2:
verboselog(space->machine, 2, "scc68070_periphs_r: Timer Reload Register: %04x & %04x\n", scc68070->timers.reload_register, mem_mask);
return scc68070->timers.reload_register;
case 0x2024/2:
verboselog(space->machine, 2, "scc68070_periphs_r: Timer 0: %04x & %04x\n", scc68070->timers.timer0, mem_mask);
return scc68070->timers.timer0;
case 0x2026/2:
verboselog(space->machine, 2, "scc68070_periphs_r: Timer 1: %04x & %04x\n", scc68070->timers.timer1, mem_mask);
printf( "Timer 1 read\n" );
return scc68070->timers.timer1;
case 0x2028/2:
verboselog(space->machine, 2, "scc68070_periphs_r: Timer 2: %04x & %04x\n", scc68070->timers.timer2, mem_mask);
printf( "Timer 2 read\n" );
return scc68070->timers.timer2;
// PICR1: 80002045
case 0x2044/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: Peripheral Interrupt Control Register 1: %02x & %04x\n", scc68070->picr1, mem_mask);
}
return scc68070->picr1;
// PICR2: 80002047
case 0x2046/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: Peripheral Interrupt Control Register 2: %02x & %04x\n", scc68070->picr2, mem_mask);
}
return scc68070->picr2;
// DMA controller: 80004000 to 8000406d
case 0x4000/2:
case 0x4040/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Error Register: %04x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].channel_error, mem_mask);
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Status Register: %04x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].channel_status, mem_mask);
}
return (scc68070->dma.channel[(offset - 0x2000) / 32].channel_status << 8) | scc68070->dma.channel[(offset - 0x2000) / 32].channel_error;
case 0x4004/2:
case 0x4044/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Operation Control Register: %02x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].operation_control, mem_mask);
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Device Control Register: %02x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].device_control, mem_mask);
}
return (scc68070->dma.channel[(offset - 0x2000) / 32].device_control << 8) | scc68070->dma.channel[(offset - 0x2000) / 32].operation_control;
case 0x4006/2:
case 0x4046/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Channel Control Register: %02x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].channel_control, mem_mask);
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Sequence Control Register: %02x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].sequence_control, mem_mask);
}
return (scc68070->dma.channel[(offset - 0x2000) / 32].sequence_control << 8) | scc68070->dma.channel[(offset - 0x2000) / 32].channel_control;
case 0x400a/2:
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Memory Transfer Counter: %04x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].transfer_counter, mem_mask);
return scc68070->dma.channel[(offset - 0x2000) / 32].transfer_counter;
case 0x400c/2:
case 0x404c/2:
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Memory Address Counter (High Word): %04x & %04x\n", (offset - 0x2000) / 32, (scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter >> 16), mem_mask);
return (scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter >> 16);
case 0x400e/2:
case 0x404e/2:
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Memory Address Counter (Low Word): %04x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter, mem_mask);
return scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter;
case 0x4014/2:
case 0x4054/2:
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Device Address Counter (High Word): %04x & %04x\n", (offset - 0x2000) / 32, (scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter >> 16), mem_mask);
return (scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter >> 16);
case 0x4016/2:
case 0x4056/2:
verboselog(space->machine, 2, "scc68070_periphs_r: DMA(%d) Device Address Counter (Low Word): %04x & %04x\n", (offset - 0x2000) / 32, scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter, mem_mask);
return scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter;
// MMU: 80008000 to 8000807f
case 0x8000/2: // Status / Control register
if(ACCESSING_BITS_0_7)
{ // Control
verboselog(space->machine, 2, "scc68070_periphs_r: MMU Control: %02x & %04x\n", scc68070->mmu.control, mem_mask);
return scc68070->mmu.control;
} // Status
else
{
verboselog(space->machine, 2, "scc68070_periphs_r: MMU Status: %02x & %04x\n", scc68070->mmu.status, mem_mask);
return scc68070->mmu.status;
}
break;
case 0x8040/2:
case 0x8048/2:
case 0x8050/2:
case 0x8058/2:
case 0x8060/2:
case 0x8068/2:
case 0x8070/2:
case 0x8078/2: // Attributes (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_r: MMU descriptor %d attributes: %04x & %04x\n", (offset - 0x4020) / 4, scc68070->mmu.desc[(offset - 0x4020) / 4].attr, mem_mask);
return scc68070->mmu.desc[(offset - 0x4020) / 4].attr;
case 0x8042/2:
case 0x804a/2:
case 0x8052/2:
case 0x805a/2:
case 0x8062/2:
case 0x806a/2:
case 0x8072/2:
case 0x807a/2: // Segment Length (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_r: MMU descriptor %d length: %04x & %04x\n", (offset - 0x4020) / 4, scc68070->mmu.desc[(offset - 0x4020) / 4].length, mem_mask);
return scc68070->mmu.desc[(offset - 0x4020) / 4].length;
case 0x8044/2:
case 0x804c/2:
case 0x8054/2:
case 0x805c/2:
case 0x8064/2:
case 0x806c/2:
case 0x8074/2:
case 0x807c/2: // Segment Number (SD0-7, A0=1 only)
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_r: MMU descriptor %d segment: %02x & %04x\n", (offset - 0x4020) / 4, scc68070->mmu.desc[(offset - 0x4020) / 4].segment, mem_mask);
return scc68070->mmu.desc[(offset - 0x4020) / 4].segment;
}
break;
case 0x8046/2:
case 0x804e/2:
case 0x8056/2:
case 0x805e/2:
case 0x8066/2:
case 0x806e/2:
case 0x8076/2:
case 0x807e/2: // Base Address (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_r: MMU descriptor %d base: %04x & %04x\n", (offset - 0x4020) / 4, scc68070->mmu.desc[(offset - 0x4020) / 4].base, mem_mask);
return scc68070->mmu.desc[(offset - 0x4020) / 4].base;
default:
verboselog(space->machine, 0, "scc68070_periphs_r: Unknown address: %04x & %04x\n", offset * 2, mem_mask);
break;
}
return 0;
}
WRITE16_HANDLER( scc68070_periphs_w )
{
cdi_state *state = space->machine->driver_data<cdi_state>();
scc68070_regs_t *scc68070 = &state->scc68070_regs;
switch(offset)
{
// Interupts: 80001001
case 0x1000/2: // LIR priority level
verboselog(space->machine, 2, "scc68070_periphs_w: LIR: %04x & %04x\n", data, mem_mask);
COMBINE_DATA(&scc68070->lir);
break;
// I2C interface: 80002001 to 80002009
case 0x2000/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Data Register: %04x & %04x\n", data, mem_mask);
scc68070->i2c.data_register = data & 0x00ff;
}
break;
case 0x2002/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Address Register: %04x & %04x\n", data, mem_mask);
scc68070->i2c.address_register = data & 0x00ff;
}
break;
case 0x2004/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Status Register: %04x & %04x\n", data, mem_mask);
scc68070->i2c.status_register = data & 0x00ff;
}
break;
case 0x2006/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Control Register: %04x & %04x\n", data, mem_mask);
scc68070->i2c.control_register = data & 0x00ff;
}
break;
case 0x2008/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: I2C Clock Control Register: %04x & %04x\n", data, mem_mask);
scc68070->i2c.clock_control_register = data & 0x00ff;
}
break;
// UART interface: 80002011 to 8000201b
case 0x2010/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Mode Register: %04x & %04x\n", data, mem_mask);
scc68070->uart.mode_register = data & 0x00ff;
}
break;
case 0x2012/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Status Register: %04x & %04x\n", data, mem_mask);
scc68070->uart.status_register = data & 0x00ff;
}
break;
case 0x2014/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Clock Select: %04x & %04x\n", data, mem_mask);
scc68070->uart.clock_select = data & 0x00ff;
}
break;
case 0x2016/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Command Register: %04x & %04x\n", data, mem_mask);
scc68070->uart.command_register = data & 0x00ff;
}
break;
case 0x2018/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Transmit Holding Register: %04x & %04x: %c\n", data, mem_mask, (data >= 0x20 && data < 0x7f) ? (data & 0x00ff) : ' ');
if((data >= 0x20 && data < 0x7f) || data == 0x08)
{
printf( "%c", data & 0x00ff );
}
if(data == 0x0d)
{
printf( "\n" );
}
scc68070->uart.transmit_holding_register = data & 0x00ff;
}
break;
case 0x201a/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: UART Receive Holding Register: %04x & %04x\n", data, mem_mask);
scc68070->uart.receive_holding_register = data & 0x00ff;
}
break;
// Timers: 80002020 to 80002029
case 0x2020/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: Timer Control Register: %04x & %04x\n", data, mem_mask);
scc68070->timers.timer_control_register = data & 0x00ff;
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 12, "scc68070_periphs_w: Timer Status Register: %04x & %04x\n", data, mem_mask);
scc68070->timers.timer_status_register &= ~(data >> 8);
if(!scc68070->timers.timer_status_register)
{
UINT8 interrupt = scc68070->picr1 & 7;
cputag_set_input_line(space->machine, "maincpu", M68K_IRQ_1 + (interrupt - 1), CLEAR_LINE);
}
}
break;
case 0x2022/2:
verboselog(space->machine, 2, "scc68070_periphs_w: Timer Reload Register: %04x & %04x\n", data, mem_mask);
COMBINE_DATA(&scc68070->timers.reload_register);
break;
case 0x2024/2:
verboselog(space->machine, 2, "scc68070_periphs_w: Timer 0: %04x & %04x\n", data, mem_mask);
COMBINE_DATA(&scc68070->timers.timer0);
scc68070_set_timer_callback(&state->scc68070_regs, 0);
break;
case 0x2026/2:
verboselog(space->machine, 2, "scc68070_periphs_w: Timer 1: %04x & %04x\n", data, mem_mask);
COMBINE_DATA(&scc68070->timers.timer1);
printf( "Timer 1 write: %04x\n", data );
break;
case 0x2028/2:
verboselog(space->machine, 2, "scc68070_periphs_w: Timer 2: %04x & %04x\n", data, mem_mask);
COMBINE_DATA(&scc68070->timers.timer2);
printf( "Timer 2 write: %04x\n", data );
break;
// PICR1: 80002045
case 0x2044/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: Peripheral Interrupt Control Register 1: %04x & %04x\n", data, mem_mask);
scc68070->picr1 = data & 0x00ff;
}
break;
// PICR2: 80002047
case 0x2046/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: Peripheral Interrupt Control Register 2: %04x & %04x\n", data, mem_mask);
scc68070->picr2 = data & 0x00ff;
}
break;
// DMA controller: 80004000 to 8000406d
case 0x4000/2:
case 0x4040/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Error (invalid): %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Status: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].channel_status &= ~(data & 0xb0);
}
break;
case 0x4004/2:
case 0x4044/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Operation Control Register: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].operation_control = data & 0x00ff;
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Device Control Register: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].device_control = data >> 8;
}
break;
case 0x4006/2:
case 0x4046/2:
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Channel Control Register: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].channel_control = data & 0x007f;
if(data & CCR_SO)
{
scc68070->dma.channel[(offset - 0x2000) / 32].channel_status |= CSR_COC;
}
}
if(ACCESSING_BITS_8_15)
{
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Sequence Control Register: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].sequence_control = data >> 8;
}
break;
case 0x400a/2:
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Memory Transfer Counter: %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
COMBINE_DATA(&scc68070->dma.channel[(offset - 0x2000) / 32].transfer_counter);
break;
case 0x400c/2:
case 0x404c/2:
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Memory Address Counter (High Word): %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter &= ~(mem_mask << 16);
scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter |= data << 16;
break;
case 0x400e/2:
case 0x404e/2:
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Memory Address Counter (Low Word): %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter &= ~mem_mask;
scc68070->dma.channel[(offset - 0x2000) / 32].memory_address_counter |= data;
break;
case 0x4014/2:
case 0x4054/2:
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Device Address Counter (High Word): %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter &= ~(mem_mask << 16);
scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter |= data << 16;
break;
case 0x4016/2:
case 0x4056/2:
verboselog(space->machine, 2, "scc68070_periphs_w: DMA(%d) Device Address Counter (Low Word): %04x & %04x\n", (offset - 0x2000) / 32, data, mem_mask);
scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter &= ~mem_mask;
scc68070->dma.channel[(offset - 0x2000) / 32].device_address_counter |= data;
break;
// MMU: 80008000 to 8000807f
case 0x8000/2: // Status / Control register
if(ACCESSING_BITS_0_7)
{ // Control
verboselog(space->machine, 2, "scc68070_periphs_w: MMU Control: %04x & %04x\n", data, mem_mask);
scc68070->mmu.control = data & 0x00ff;
} // Status
else
{
verboselog(space->machine, 0, "scc68070_periphs_w: MMU Status (invalid): %04x & %04x\n", data, mem_mask);
}
break;
case 0x8040/2:
case 0x8048/2:
case 0x8050/2:
case 0x8058/2:
case 0x8060/2:
case 0x8068/2:
case 0x8070/2:
case 0x8078/2: // Attributes (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_w: MMU descriptor %d attributes: %04x & %04x\n", (offset - 0x4020) / 4, data, mem_mask);
COMBINE_DATA(&scc68070->mmu.desc[(offset - 0x4020) / 4].attr);
break;
case 0x8042/2:
case 0x804a/2:
case 0x8052/2:
case 0x805a/2:
case 0x8062/2:
case 0x806a/2:
case 0x8072/2:
case 0x807a/2: // Segment Length (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_w: MMU descriptor %d length: %04x & %04x\n", (offset - 0x4020) / 4, data, mem_mask);
COMBINE_DATA(&scc68070->mmu.desc[(offset - 0x4020) / 4].length);
break;
case 0x8044/2:
case 0x804c/2:
case 0x8054/2:
case 0x805c/2:
case 0x8064/2:
case 0x806c/2:
case 0x8074/2:
case 0x807c/2: // Segment Number (SD0-7, A0=1 only)
if(ACCESSING_BITS_0_7)
{
verboselog(space->machine, 2, "scc68070_periphs_w: MMU descriptor %d segment: %04x & %04x\n", (offset - 0x4020) / 4, data, mem_mask);
scc68070->mmu.desc[(offset - 0x4020) / 4].segment = data & 0x00ff;
}
break;
case 0x8046/2:
case 0x804e/2:
case 0x8056/2:
case 0x805e/2:
case 0x8066/2:
case 0x806e/2:
case 0x8076/2:
case 0x807e/2: // Base Address (SD0-7)
verboselog(space->machine, 2, "scc68070_periphs_w: MMU descriptor %d base: %04x & %04x\n", (offset - 0x4020) / 4, data, mem_mask);
COMBINE_DATA(&scc68070->mmu.desc[(offset - 0x4020) / 4].base);
break;
default:
verboselog(space->machine, 0, "scc68070_periphs_w: Unknown address: %04x = %04x & %04x\n", offset * 2, data, mem_mask);
break;
}
}
void scc68070_init(running_machine *machine, scc68070_regs_t *scc68070)
{
int index = 0;
scc68070->lir = 0;
scc68070->picr1 = 0;
scc68070->picr2 = 0;
scc68070->i2c.data_register = 0;
scc68070->i2c.address_register = 0;
scc68070->i2c.status_register = 0;
scc68070->i2c.control_register = 0;
scc68070->i2c.clock_control_register = 0;
scc68070->uart.mode_register = 0;
scc68070->uart.status_register = 0;
scc68070->uart.clock_select = 0;
scc68070->uart.command_register = 0;
scc68070->uart.transmit_holding_register = 0;
scc68070->uart.receive_holding_register = 0;
scc68070->timers.timer_status_register = 0;
scc68070->timers.timer_control_register = 0;
scc68070->timers.reload_register = 0;
scc68070->timers.timer0 = 0;
scc68070->timers.timer1 = 0;
scc68070->timers.timer2 = 0;
for(index = 0; index < 2; index++)
{
scc68070->dma.channel[index].channel_status = 0;
scc68070->dma.channel[index].channel_error = 0;
scc68070->dma.channel[index].device_control = 0;
scc68070->dma.channel[index].operation_control = 0;
scc68070->dma.channel[index].sequence_control = 0;
scc68070->dma.channel[index].channel_control = 0;
scc68070->dma.channel[index].transfer_counter = 0;
scc68070->dma.channel[index].memory_address_counter = 0;
scc68070->dma.channel[index].device_address_counter = 0;
}
scc68070->mmu.status = 0;
scc68070->mmu.control = 0;
for(index = 0; index < 8; index++)
{
scc68070->mmu.desc[index].attr = 0;
scc68070->mmu.desc[index].length = 0;
scc68070->mmu.desc[index].segment = 0;
scc68070->mmu.desc[index].base = 0;
}
}
void scc68070_register_globals(running_machine *machine, scc68070_regs_t *scc68070)
{
state_save_register_global(machine, scc68070->lir);
state_save_register_global(machine, scc68070->picr1);
state_save_register_global(machine, scc68070->picr2);
state_save_register_global(machine, scc68070->i2c.data_register);
state_save_register_global(machine, scc68070->i2c.address_register);
state_save_register_global(machine, scc68070->i2c.status_register);
state_save_register_global(machine, scc68070->i2c.control_register);
state_save_register_global(machine, scc68070->i2c.clock_control_register);
state_save_register_global(machine, scc68070->uart.mode_register);
state_save_register_global(machine, scc68070->uart.status_register);
state_save_register_global(machine, scc68070->uart.clock_select);
state_save_register_global(machine, scc68070->uart.command_register);
state_save_register_global(machine, scc68070->uart.transmit_holding_register);
state_save_register_global(machine, scc68070->uart.receive_holding_register);
state_save_register_global(machine, scc68070->timers.timer_status_register);
state_save_register_global(machine, scc68070->timers.timer_control_register);
state_save_register_global(machine, scc68070->timers.reload_register);
state_save_register_global(machine, scc68070->timers.timer0);
state_save_register_global(machine, scc68070->timers.timer1);
state_save_register_global(machine, scc68070->timers.timer2);
state_save_register_global(machine, scc68070->dma.channel[0].channel_status);
state_save_register_global(machine, scc68070->dma.channel[0].channel_error);
state_save_register_global(machine, scc68070->dma.channel[0].device_control);
state_save_register_global(machine, scc68070->dma.channel[0].operation_control);
state_save_register_global(machine, scc68070->dma.channel[0].sequence_control);
state_save_register_global(machine, scc68070->dma.channel[0].channel_control);
state_save_register_global(machine, scc68070->dma.channel[0].transfer_counter);
state_save_register_global(machine, scc68070->dma.channel[0].memory_address_counter);
state_save_register_global(machine, scc68070->dma.channel[0].device_address_counter);
state_save_register_global(machine, scc68070->dma.channel[1].channel_status);
state_save_register_global(machine, scc68070->dma.channel[1].channel_error);
state_save_register_global(machine, scc68070->dma.channel[1].device_control);
state_save_register_global(machine, scc68070->dma.channel[1].operation_control);
state_save_register_global(machine, scc68070->dma.channel[1].sequence_control);
state_save_register_global(machine, scc68070->dma.channel[1].channel_control);
state_save_register_global(machine, scc68070->dma.channel[1].transfer_counter);
state_save_register_global(machine, scc68070->dma.channel[1].memory_address_counter);
state_save_register_global(machine, scc68070->dma.channel[1].device_address_counter);
state_save_register_global(machine, scc68070->mmu.status);
state_save_register_global(machine, scc68070->mmu.control);
state_save_register_global(machine, scc68070->mmu.desc[0].attr);
state_save_register_global(machine, scc68070->mmu.desc[0].length);
state_save_register_global(machine, scc68070->mmu.desc[0].segment);
state_save_register_global(machine, scc68070->mmu.desc[0].base);
state_save_register_global(machine, scc68070->mmu.desc[1].attr);
state_save_register_global(machine, scc68070->mmu.desc[1].length);
state_save_register_global(machine, scc68070->mmu.desc[1].segment);
state_save_register_global(machine, scc68070->mmu.desc[1].base);
state_save_register_global(machine, scc68070->mmu.desc[2].attr);
state_save_register_global(machine, scc68070->mmu.desc[2].length);
state_save_register_global(machine, scc68070->mmu.desc[2].segment);
state_save_register_global(machine, scc68070->mmu.desc[2].base);
state_save_register_global(machine, scc68070->mmu.desc[3].attr);
state_save_register_global(machine, scc68070->mmu.desc[3].length);
state_save_register_global(machine, scc68070->mmu.desc[3].segment);
state_save_register_global(machine, scc68070->mmu.desc[3].base);
state_save_register_global(machine, scc68070->mmu.desc[4].attr);
state_save_register_global(machine, scc68070->mmu.desc[4].length);
state_save_register_global(machine, scc68070->mmu.desc[4].segment);
state_save_register_global(machine, scc68070->mmu.desc[4].base);
state_save_register_global(machine, scc68070->mmu.desc[5].attr);
state_save_register_global(machine, scc68070->mmu.desc[5].length);
state_save_register_global(machine, scc68070->mmu.desc[5].segment);
state_save_register_global(machine, scc68070->mmu.desc[5].base);
state_save_register_global(machine, scc68070->mmu.desc[6].attr);
state_save_register_global(machine, scc68070->mmu.desc[6].length);
state_save_register_global(machine, scc68070->mmu.desc[6].segment);
state_save_register_global(machine, scc68070->mmu.desc[6].base);
state_save_register_global(machine, scc68070->mmu.desc[7].attr);
state_save_register_global(machine, scc68070->mmu.desc[7].length);
state_save_register_global(machine, scc68070->mmu.desc[7].segment);
state_save_register_global(machine, scc68070->mmu.desc[7].base);
}
#if ENABLE_UART_PRINTING
READ16_HANDLER( uart_loopback_enable )
{
return 0x1234;
}
#endif

232
src/mame/machine/cdi070.h Normal file
View File

@ -0,0 +1,232 @@
/******************************************************************************
CD-i-specific SCC68070 SoC peripheral emulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Skeleton. Just enough for the CD-i to run.
TODO:
- Proper handling of the 68070's internal devices (UART, DMA, Timers, etc.)
*******************************************************************************/
#ifndef _MACHINE_CDI070_H_
#define _MACHINE_CDI070_H_
#include "emu.h"
typedef struct
{
UINT8 reserved0;
UINT8 data_register;
UINT8 reserved1;
UINT8 address_register;
UINT8 reserved2;
UINT8 status_register;
UINT8 reserved3;
UINT8 control_register;
UINT8 reserved;
UINT8 clock_control_register;
} scc68070_i2c_regs_t;
#define ISR_MST 0x80 // Master
#define ISR_TRX 0x40 // Transmitter
#define ISR_BB 0x20 // Busy
#define ISR_PIN 0x10 // No Pending Interrupt
#define ISR_AL 0x08 // Arbitration Lost
#define ISR_AAS 0x04 // Addressed As Slave
#define ISR_AD0 0x02 // Address Zero
#define ISR_LRB 0x01 // Last Received Bit
typedef struct
{
UINT8 reserved0;
UINT8 mode_register;
UINT8 reserved1;
UINT8 status_register;
UINT8 reserved2;
UINT8 clock_select;
UINT8 reserved3;
UINT8 command_register;
UINT8 reserved4;
UINT8 transmit_holding_register;
UINT8 reserved5;
UINT8 receive_holding_register;
} scc68070_uart_regs_t;
#define UMR_OM 0xc0
#define UMR_OM_NORMAL 0x00
#define UMR_OM_ECHO 0x40
#define UMR_OM_LOOPBACK 0x80
#define UMR_OM_RLOOP 0xc0
#define UMR_TXC 0x10
#define UMR_PC 0x08
#define UMR_P 0x04
#define UMR_SB 0x02
#define UMR_CL 0x01
#define USR_RB 0x80
#define USR_FE 0x40
#define USR_PE 0x20
#define USR_OE 0x10
#define USR_TXEMT 0x08
#define USR_TXRDY 0x04
#define USR_RXRDY 0x01
typedef struct
{
UINT8 timer_status_register;
UINT8 timer_control_register;
UINT16 reload_register;
UINT16 timer0;
UINT16 timer1;
UINT16 timer2;
emu_timer* timer0_timer;
} scc68070_timer_regs_t;
#define TSR_OV0 0x80
#define TSR_MA1 0x40
#define TSR_CAP1 0x20
#define TSR_OV1 0x10
#define TSR_MA2 0x08
#define TSR_CAP2 0x04
#define TSR_OV2 0x02
#define TCR_E1 0xc0
#define TCR_E1_NONE 0x00
#define TCR_E1_RISING 0x40
#define TCR_E1_FALLING 0x80
#define TCR_E1_BOTH 0xc0
#define TCR_M1 0x30
#define TCR_M1_NONE 0x00
#define TCR_M1_MATCH 0x10
#define TCR_M1_CAPTURE 0x20
#define TCR_M1_COUNT 0x30
#define TCR_E2 0x0c
#define TCR_E2_NONE 0x00
#define TCR_E2_RISING 0x04
#define TCR_E2_FALLING 0x08
#define TCR_E2_BOTH 0x0c
#define TCR_M2 0x03
#define TCR_M2_NONE 0x00
#define TCR_M2_MATCH 0x01
#define TCR_M2_CAPTURE 0x02
#define TCR_M2_COUNT 0x03
typedef struct
{
UINT8 channel_status;
UINT8 channel_error;
UINT8 reserved0[2];
UINT8 device_control;
UINT8 operation_control;
UINT8 sequence_control;
UINT8 channel_control;
UINT8 reserved1[3];
UINT16 transfer_counter;
UINT32 memory_address_counter;
UINT8 reserved2[4];
UINT32 device_address_counter;
UINT8 reserved3[40];
} scc68070_dma_channel_t;
#define CSR_COC 0x80
#define CSR_NDT 0x20
#define CSR_ERR 0x10
#define CSR_CA 0x08
#define CER_EC 0x1f
#define CER_NONE 0x00
#define CER_TIMING 0x02
#define CER_BUSERR_MEM 0x09
#define CER_BUSERR_DEV 0x0a
#define CER_SOFT_ABORT 0x11
#define DCR1_ERM 0x80
#define DCR1_DT 0x30
#define DCR2_ERM 0x80
#define DCR2_DT 0x30
#define DCR2_DS 0x08
#define OCR_D 0x80
#define OCR_D_M2D 0x00
#define OCR_D_D2M 0x80
#define OCR_OS 0x30
#define OCR_OS_BYTE 0x00
#define OCR_OS_WORD 0x10
#define SCR2_MAC 0x0c
#define SCR2_MAC_NONE 0x00
#define SCR2_MAC_INC 0x04
#define SCR2_DAC 0x03
#define SCR2_DAC_NONE 0x00
#define SCR2_DAC_INC 0x01
#define CCR_SO 0x80
#define CCR_SA 0x10
#define CCR_INE 0x08
#define CCR_IPL 0x07
typedef struct
{
scc68070_dma_channel_t channel[2];
} scc68070_dma_regs_t;
typedef struct
{
UINT16 attr;
UINT16 length;
UINT8 undefined;
UINT8 segment;
UINT16 base;
} scc68070_mmu_desc_t;
typedef struct
{
UINT8 status;
UINT8 control;
UINT8 reserved[0x3e];
scc68070_mmu_desc_t desc[8];
} scc68070_mmu_regs_t;
typedef struct
{
UINT16 lir;
UINT8 picr1;
UINT8 picr2;
scc68070_i2c_regs_t i2c;
scc68070_uart_regs_t uart;
scc68070_timer_regs_t timers;
scc68070_dma_regs_t dma;
scc68070_mmu_regs_t mmu;
} scc68070_regs_t;
// Member functions
extern TIMER_CALLBACK( scc68070_timer0_callback );
extern READ16_HANDLER( scc68070_periphs_r );
extern WRITE16_HANDLER( scc68070_periphs_w );
extern void scc68070_init(running_machine *machine, scc68070_regs_t *scc68070);
extern void scc68070_register_globals(running_machine *machine, scc68070_regs_t *scc68070);
#endif // _MACHINE_CDI070_H_

1299
src/mame/machine/cdicdic.c Normal file

File diff suppressed because it is too large Load Diff

165
src/mame/machine/cdicdic.h Normal file
View File

@ -0,0 +1,165 @@
/******************************************************************************
CD-i Mono-I CDIC MCU simulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Just enough for the Mono-I CD-i board to work somewhat properly.
TODO:
- Decapping and proper emulation.
*******************************************************************************/
#pragma once
#ifndef __CDICDIC_H__
#define __CDICDIC_H__
#include "emu.h"
#include "cdrom.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MDRV_CDICDIC_ADD(_tag) \
MDRV_DEVICE_ADD(_tag, MACHINE_CDICDIC, 0) \
#define MDRV_CDICDIC_REPLACE(_tag) \
MDRV_DEVICE_REPLACE(_tag, MACHINE_CDICDIC, 0) \
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> cdicdic_device_config
class cdicdic_device_config : public device_config
{
friend class cdicdic_device;
// construction/destruction
cdicdic_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
// inline configuration indexes go here (none yet)
protected:
// device_config overrides (none yet)
// internal state goes here (none yet)
};
// ======================> cdicdic_device
class cdicdic_device : public device_t
{
friend class cdicdic_device_config;
// construction/destruction
cdicdic_device(running_machine &_machine, const cdicdic_device_config &config);
public:
// non-static internal members
void sample_trigger();
void process_delayed_command();
void ram_write(const UINT32 offset, const UINT16 data, const UINT16 mem_mask);
UINT16 ram_read(const UINT32 offset, const UINT16 mem_mask);
void register_write(const UINT32 offset, const UINT16 data, const UINT16 mem_mask);
UINT16 register_read(const UINT32 offset, const UINT16 mem_mask);
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_post_load() { }
virtual void device_clock_changed() { }
// internal callbacks
static TIMER_CALLBACK( audio_sample_trigger );
static TIMER_CALLBACK( trigger_readback_int );
// internal state
const cdicdic_device_config &m_config;
private:
UINT16 m_command; // CDIC Command Register (0x303c00)
UINT32 m_time; // CDIC Time Register (0x303c02)
UINT16 m_file; // CDIC File Register (0x303c06)
UINT32 m_channel; // CDIC Channel Register (0x303c08)
UINT16 m_audio_channel; // CDIC Audio Channel Register (0x303c0c)
UINT16 m_audio_buffer; // CDIC Audio Buffer Register (0x303ff4)
UINT16 m_x_buffer; // CDIC X-Buffer Register (0x303ff6)
UINT16 m_dma_control; // CDIC DMA Control Register (0x303ff8)
UINT16 m_z_buffer; // CDIC Z-Buffer Register (0x303ffa)
UINT16 m_interrupt_vector; // CDIC Interrupt Vector Register (0x303ffc)
UINT16 m_data_buffer; // CDIC Data Buffer Register (0x303ffe)
emu_timer *m_interrupt_timer;
cdrom_file *m_cd;
emu_timer *m_audio_sample_timer;
INT32 m_audio_sample_freq;
INT32 m_audio_sample_size;
UINT16 m_decode_addr;
UINT8 m_decode_delay;
attotime m_decode_period;
int m_xa_last[4];
UINT16 *m_ram;
void register_globals();
void init();
// static internal members
static void decode_xa_mono(INT32 *cdic_xa_last, const UINT8 *xa, INT16 *dp);
static void decode_xa_mono8(INT32 *cdic_xa_last, const UINT8 *xa, INT16 *dp);
static void decode_xa_stereo(INT32 *cdic_xa_last, const UINT8 *xa, INT16 *dp);
static void decode_xa_stereo8(INT32 *cdic_xa_last, const UINT8 *xa, INT16 *dp);
static const INT32 s_cdic_adpcm_filter_coef[5][2];
// non-static internal members
UINT32 increment_cdda_frame_bcd(UINT32 bcd);
UINT32 increment_cdda_sector_bcd(UINT32 bcd);
void decode_audio_sector(const UINT8 *xa, INT32 triggered);
};
// device type definition
extern const device_type MACHINE_CDICDIC;
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
READ16_DEVICE_HANDLER( cdic_r );
WRITE16_DEVICE_HANDLER( cdic_w );
READ16_DEVICE_HANDLER( cdic_ram_r );
WRITE16_DEVICE_HANDLER( cdic_ram_w );
#endif // __CDICDIC_H__

561
src/mame/machine/cdislave.c Normal file
View File

@ -0,0 +1,561 @@
/******************************************************************************
CD-i Mono-I SLAVE MCU simulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Just enough for the Mono-I CD-i board to work somewhat properly.
TODO:
- Decapping and proper emulation.
*******************************************************************************/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "machine/cdislave.h"
#include "includes/cdi.h"
#if ENABLE_VERBOSE_LOG
INLINE void verboselog(running_machine *machine, int n_level, const char *s_fmt, ...)
{
if( VERBOSE_LEVEL >= n_level )
{
va_list v;
char buf[ 32768 ];
va_start( v, s_fmt );
vsprintf( buf, s_fmt, v );
va_end( v );
logerror( "%08x: %s", cpu_get_pc(machine->device("maincpu")), buf );
}
}
#else
#define verboselog(x,y,z,...)
#endif
//**************************************************************************
// DEVICE CONFIGURATION
//**************************************************************************
//-------------------------------------------------
// cdislave_device_config - constructor
//-------------------------------------------------
cdislave_device_config::cdislave_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
: device_config(mconfig, static_alloc_device_config, "CDISLAVE", tag, owner, clock)
{
}
//-------------------------------------------------
// static_alloc_device_config - allocate a new
// configuration object
//-------------------------------------------------
device_config *cdislave_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
{
return global_alloc(cdislave_device_config(mconfig, tag, owner, clock));
}
//-------------------------------------------------
// alloc_device - allocate a new device object
//-------------------------------------------------
device_t *cdislave_device_config::alloc_device(running_machine &machine) const
{
return auto_alloc(&machine, cdislave_device(machine, *this));
}
//**************************************************************************
// MEMBER FUNCTIONS
//**************************************************************************
TIMER_CALLBACK( cdislave_device::trigger_readback_int )
{
cdislave_device *slave = reinterpret_cast<cdislave_device *>(machine->device("slave"));
slave->readback_trigger();
}
void cdislave_device::readback_trigger()
{
verboselog(&m_machine, 0, "Asserting IRQ2\n" );
cpu_set_input_line_vector(m_machine.device("maincpu"), M68K_IRQ_2, 26);
cputag_set_input_line(&m_machine, "maincpu", M68K_IRQ_2, ASSERT_LINE);
timer_adjust_oneshot(m_interrupt_timer, attotime_never, 0);
}
void cdislave_device::prepare_readback(attotime delay, UINT8 channel, UINT8 count, UINT8 data0, UINT8 data1, UINT8 data2, UINT8 data3, UINT8 cmd)
{
m_channel[channel].m_out_index = 0;
m_channel[channel].m_out_count = count;
m_channel[channel].m_out_buf[0] = data0;
m_channel[channel].m_out_buf[1] = data1;
m_channel[channel].m_out_buf[2] = data2;
m_channel[channel].m_out_buf[3] = data3;
m_channel[channel].m_out_cmd = cmd;
timer_adjust_oneshot(m_interrupt_timer, delay, 0);
}
void cdislave_device::perform_mouse_update()
{
UINT16 x = input_port_read(&m_machine, "MOUSEX");
UINT16 y = input_port_read(&m_machine, "MOUSEY");
UINT8 buttons = input_port_read(&m_machine, "MOUSEBTN");
UINT16 old_mouse_x = m_real_mouse_x;
UINT16 old_mouse_y = m_real_mouse_y;
if(m_real_mouse_x == 0xffff)
{
old_mouse_x = x & 0x3ff;
old_mouse_y = y & 0x3ff;
}
m_real_mouse_x = x & 0x3ff;
m_real_mouse_y = y & 0x3ff;
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;
if(m_polling_active)
{
prepare_readback(attotime_zero, 0, 4, ((x & 0x380) >> 7) | (buttons << 4), x & 0x7f, (y & 0x380) >> 7, y & 0x7f, 0xf7);
}
}
INPUT_CHANGED( cdislave_device::mouse_update )
{
cdislave_device *slave = reinterpret_cast<cdislave_device *>(field->port->machine->device("slave"));
slave->perform_mouse_update();
}
READ16_DEVICE_HANDLER( slave_r )
{
return downcast<cdislave_device *>(device)->register_read(offset, mem_mask);
}
UINT16 cdislave_device::register_read(const UINT32 offset, const UINT16 mem_mask)
{
if(m_channel[offset].m_out_count)
{
UINT8 ret = m_channel[offset].m_out_buf[m_channel[offset].m_out_index];
verboselog(&m_machine, 0, "slave_r: Channel %d: %d, %02x\n", offset, m_channel[offset].m_out_index, ret );
if(m_channel[offset].m_out_index == 0)
{
switch(m_channel[offset].m_out_cmd)
{
case 0xb0:
case 0xb1:
case 0xf0:
case 0xf3:
case 0xf7:
verboselog(&m_machine, 0, "slave_r: De-asserting IRQ2\n" );
cputag_set_input_line(&m_machine, "maincpu", M68K_IRQ_2, CLEAR_LINE);
break;
}
}
m_channel[offset].m_out_index++;
m_channel[offset].m_out_count--;
if(!m_channel[offset].m_out_count)
{
m_channel[offset].m_out_index = 0;
m_channel[offset].m_out_cmd = 0;
memset(m_channel[offset].m_out_buf, 0, 4);
}
return ret;
}
verboselog(&m_machine, 0, "slave_r: Channel %d: %d\n", offset, m_channel[offset].m_out_index );
return 0xff;
}
void cdislave_device::set_mouse_position()
{
UINT16 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);
}
}
WRITE16_DEVICE_HANDLER( slave_w )
{
downcast<cdislave_device *>(device)->register_write(offset, data, mem_mask);
}
void cdislave_device::register_write(const UINT32 offset, const UINT16 data, const UINT16 mem_mask)
{
cdi_state *state = m_machine.driver_data<cdi_state>();
switch(offset)
{
case 0:
if(m_in_index)
{
verboselog(&m_machine, 0, "slave_w: Channel %d: %d = %02x\n", offset, m_in_index, data & 0x00ff );
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
if(m_in_index == m_in_count)
{
switch(m_in_buf[0])
{
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: // Update Mouse Position
set_mouse_position();
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
}
else
{
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
switch(data & 0x00ff)
{
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
verboselog(&m_machine, 0, "slave_w: Channel %d: Update Mouse Position (0x%02x)\n", offset, data & 0x00ff );
m_in_count = 3;
break;
default:
verboselog(&m_machine, 0, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff );
m_in_index = 0;
break;
}
}
break;
case 1:
if(m_in_index)
{
verboselog(&m_machine, 0, "slave_w: Channel %d: %d = %02x\n", offset, m_in_index, data & 0x00ff );
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
if(m_in_index == m_in_count)
{
switch(m_in_buf[0])
{
case 0xf0: // Set Front Panel LCD
memcpy(m_lcd_state, m_in_buf + 1, 16);
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
default:
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
}
else
{
switch(data & 0x00ff)
{
default:
verboselog(&m_machine, 0, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff );
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
break;
case 2:
if(m_in_index)
{
verboselog(&m_machine, 0, "slave_w: Channel %d: %d = %02x\n", offset, m_in_index, data & 0x00ff );
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
if(m_in_index == m_in_count)
{
switch(m_in_buf[0])
{
case 0xf0: // Set Front Panel LCD
memset(m_in_buf + 1, 0, 16);
m_in_count = 17;
break;
default:
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
}
else
{
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
switch(data & 0x00ff)
{
case 0x82: // Mute audio
verboselog(&m_machine, 0, "slave_w: Channel %d: Mute Audio (0x82)\n", offset );
dmadac_enable(&state->dmadac[0], 2, 0);
m_in_index = 0;
m_in_count = 0;
//timer_adjust_oneshot(cdic->audio_sample_timer, attotime_never, 0);
break;
case 0x83: // Unmute audio
verboselog(&m_machine, 0, "slave_w: Channel %d: Unmute Audio (0x83)\n", offset );
dmadac_enable(&state->dmadac[0], 2, 1);
m_in_index = 0;
m_in_count = 0;
break;
case 0xf0: // Set Front Panel LCD
verboselog(&m_machine, 0, "slave_w: Channel %d: Set Front Panel LCD (0xf0)\n", offset );
m_in_count = 17;
break;
default:
verboselog(&m_machine, 0, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff );
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
break;
case 3:
if(m_in_index)
{
verboselog(&m_machine, 0, "slave_w: Channel %d: %d = %02x\n", offset, m_in_index, data & 0x00ff );
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
if(m_in_index == m_in_count)
{
switch(m_in_buf[0])
{
case 0xb0: // Request Disc Status
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
prepare_readback(ATTOTIME_IN_HZ(4), 3, 4, 0xb0, 0x00, 0x02, 0x15, 0xb0);
break;
//case 0xb1: // Request Disc Base
//memset(m_in_buf, 0, 17);
//m_in_index = 0;
//m_in_count = 0;
//prepare_readback(ATTOTIME_IN_HZ(10000), 3, 4, 0xb1, 0x00, 0x00, 0x00, 0xb1);
//break;
default:
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
}
else
{
m_in_buf[m_in_index] = data & 0x00ff;
m_in_index++;
switch(data & 0x00ff)
{
case 0xb0: // Request Disc Status
verboselog(&m_machine, 0, "slave_w: Channel %d: Request Disc Status (0xb0)\n", offset );
m_in_count = 4;
break;
case 0xb1: // Request Disc Status
verboselog(&m_machine, 0, "slave_w: Channel %d: Request Disc Base (0xb1)\n", offset );
m_in_count = 4;
break;
case 0xf0: // Get SLAVE revision
verboselog(&m_machine, 0, "slave_w: Channel %d: Get SLAVE Revision (0xf0)\n", offset );
prepare_readback(ATTOTIME_IN_HZ(10000), 2, 2, 0xf0, 0x32, 0x31, 0, 0xf0);
m_in_index = 0;
break;
case 0xf3: // Query Pointer Type
verboselog(&m_machine, 0, "slave_w: Channel %d: Query Pointer Type (0xf3)\n", offset );
m_in_index = 0;
prepare_readback(ATTOTIME_IN_HZ(10000), 2, 2, 0xf3, 1, 0, 0, 0xf3);
break;
case 0xf6: // NTSC/PAL
verboselog(&m_machine, 0, "slave_w: Channel %d: Check NTSC/PAL (0xf6)\n", offset );
prepare_readback(attotime_never, 2, 2, 0xf6, 1, 0, 0, 0xf6);
m_in_index = 0;
break;
case 0xf7: // Activate input polling
verboselog(&m_machine, 0, "slave_w: Channel %d: Activate Input Polling (0xf7)\n", offset );
m_polling_active = 1;
m_in_index = 0;
break;
case 0xfa: // Enable X-Bus interrupts
verboselog(&m_machine, 0, "slave_w: Channel %d: X-Bus Interrupt Enable (0xfa)\n", offset );
m_xbus_interrupt_enable = 1;
m_in_index = 0;
break;
default:
verboselog(&m_machine, 0, "slave_w: Channel %d: Unknown register: %02x\n", offset, data & 0x00ff );
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
break;
}
}
break;
}
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// cdislave_device - constructor
//-------------------------------------------------
cdislave_device::cdislave_device(running_machine &_machine, const cdislave_device_config &config)
: device_t(_machine, config),
m_config(config)
{
init();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void cdislave_device::device_start()
{
register_globals();
m_interrupt_timer = timer_alloc(&m_machine, trigger_readback_int, 0);
timer_adjust_oneshot(m_interrupt_timer, attotime_never, 0);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void cdislave_device::device_reset()
{
init();
}
void cdislave_device::init()
{
for(INT32 index = 0; index < 4; index++)
{
m_channel[index].m_out_buf[0] = 0;
m_channel[index].m_out_buf[1] = 0;
m_channel[index].m_out_buf[2] = 0;
m_channel[index].m_out_buf[3] = 0;
m_channel[index].m_out_index = 0;
m_channel[index].m_out_count = 0;
m_channel[index].m_out_cmd = 0;
}
memset(m_in_buf, 0, 17);
m_in_index = 0;
m_in_count = 0;
m_polling_active = 0;
m_xbus_interrupt_enable = 0;
memset(m_lcd_state, 0, 16);
m_real_mouse_x = 0xffff;
m_real_mouse_y = 0xffff;
m_fake_mouse_x = 0;
m_fake_mouse_y = 0;
}
void cdislave_device::register_globals()
{
state_save_register_device_item(this, 0, m_channel[0].m_out_buf[0]);
state_save_register_device_item(this, 0, m_channel[0].m_out_buf[1]);
state_save_register_device_item(this, 0, m_channel[0].m_out_buf[2]);
state_save_register_device_item(this, 0, m_channel[0].m_out_buf[3]);
state_save_register_device_item(this, 0, m_channel[0].m_out_index);
state_save_register_device_item(this, 0, m_channel[0].m_out_count);
state_save_register_device_item(this, 0, m_channel[0].m_out_cmd);
state_save_register_device_item(this, 0, m_channel[1].m_out_buf[0]);
state_save_register_device_item(this, 0, m_channel[1].m_out_buf[1]);
state_save_register_device_item(this, 0, m_channel[1].m_out_buf[2]);
state_save_register_device_item(this, 0, m_channel[1].m_out_buf[3]);
state_save_register_device_item(this, 0, m_channel[1].m_out_index);
state_save_register_device_item(this, 0, m_channel[1].m_out_count);
state_save_register_device_item(this, 0, m_channel[1].m_out_cmd);
state_save_register_device_item(this, 0, m_channel[2].m_out_buf[0]);
state_save_register_device_item(this, 0, m_channel[2].m_out_buf[1]);
state_save_register_device_item(this, 0, m_channel[2].m_out_buf[2]);
state_save_register_device_item(this, 0, m_channel[2].m_out_buf[3]);
state_save_register_device_item(this, 0, m_channel[2].m_out_index);
state_save_register_device_item(this, 0, m_channel[2].m_out_count);
state_save_register_device_item(this, 0, m_channel[2].m_out_cmd);
state_save_register_device_item(this, 0, m_channel[3].m_out_buf[0]);
state_save_register_device_item(this, 0, m_channel[3].m_out_buf[1]);
state_save_register_device_item(this, 0, m_channel[3].m_out_buf[2]);
state_save_register_device_item(this, 0, m_channel[3].m_out_buf[3]);
state_save_register_device_item(this, 0, m_channel[3].m_out_index);
state_save_register_device_item(this, 0, m_channel[3].m_out_count);
state_save_register_device_item(this, 0, m_channel[3].m_out_cmd);
state_save_register_device_item_array(this, 0, m_in_buf);
state_save_register_device_item(this, 0, m_in_index);
state_save_register_device_item(this, 0, m_in_count);
state_save_register_device_item(this, 0, m_polling_active);
state_save_register_device_item(this, 0, m_xbus_interrupt_enable);
state_save_register_device_item_array(this, 0, m_lcd_state);
state_save_register_device_item(this, 0, m_real_mouse_x);
state_save_register_device_item(this, 0, m_real_mouse_y);
state_save_register_device_item(this, 0, m_fake_mouse_x);
state_save_register_device_item(this, 0, m_fake_mouse_y);
}
const device_type MACHINE_CDISLAVE = cdislave_device_config::static_alloc_device_config;

155
src/mame/machine/cdislave.h Normal file
View File

@ -0,0 +1,155 @@
/******************************************************************************
CD-i Mono-I SLAVE MCU simulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Just enough for the Mono-I CD-i board to work somewhat properly.
TODO:
- Decapping and proper emulation.
*******************************************************************************/
#pragma once
#ifndef __CDISLAVE_H__
#define __CDISLAVE_H__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MDRV_CDISLAVE_ADD(_tag) \
MDRV_DEVICE_ADD(_tag, MACHINE_CDISLAVE, 0) \
#define MDRV_CDISLAVE_REPLACE(_tag) \
MDRV_DEVICE_REPLACE(_tag, MACHINE_CDISLAVE, 0) \
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> cdislave_device_config
class cdislave_device_config : public device_config
{
friend class cdislave_device;
// construction/destruction
cdislave_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
// inline configuration indexes go here (none yet)
protected:
// device_config overrides (none yet)
// internal state goes here (none yet)
};
// ======================> cdislave_device
class cdislave_device : public device_t
{
friend class cdislave_device_config;
// construction/destruction
cdislave_device(running_machine &_machine, const cdislave_device_config &config);
public:
// external callbacks
static INPUT_CHANGED( mouse_update );
UINT8* get_lcd_state() { return m_lcd_state; }
void readback_trigger();
void register_write(const UINT32 offset, const UINT16 data, const UINT16 mem_mask);
UINT16 register_read(const UINT32 offset, const UINT16 mem_mask);
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_post_load() { }
virtual void device_clock_changed() { }
// internal callbacks
static TIMER_CALLBACK( trigger_readback_int );
// internal state
const cdislave_device_config &m_config;
private:
class channel_state
{
public:
channel_state() { }
UINT8 m_out_buf[4];
UINT8 m_out_index;
UINT8 m_out_count;
UINT8 m_out_cmd;
};
channel_state m_channel[4];
emu_timer *m_interrupt_timer;
UINT8 m_in_buf[17];
UINT8 m_in_index;
UINT8 m_in_count;
UINT8 m_polling_active;
UINT8 m_xbus_interrupt_enable;
UINT8 m_lcd_state[16];
UINT16 m_real_mouse_x;
UINT16 m_real_mouse_y;
UINT16 m_fake_mouse_x;
UINT16 m_fake_mouse_y;
void register_globals();
void init();
// static internal members
// non-static internal members
void prepare_readback(attotime delay, UINT8 channel, UINT8 count, UINT8 data0, UINT8 data1, UINT8 data2, UINT8 data3, UINT8 cmd);
void perform_mouse_update();
void set_mouse_position();
};
// device type definition
extern const device_type MACHINE_CDISLAVE;
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
READ16_DEVICE_HANDLER( slave_r );
WRITE16_DEVICE_HANDLER( slave_w );
#endif // __CDISLAVE_H__

View File

@ -1506,7 +1506,7 @@ $(MAMEOBJ)/misc.a: \
$(DRIVERS)/carrera.o \
$(DRIVERS)/cave.o $(VIDEO)/cave.o \
$(DRIVERS)/cb2001.o \
$(DRIVERS)/cdi.o \
$(DRIVERS)/cdi.o $(VIDEO)/mcd212.o $(MACHINE)/cdi070.o $(MACHINE)/cdislave.o $(MACHINE)/cdicdic.o \
$(DRIVERS)/chsuper.o \
$(DRIVERS)/cidelsa.o $(VIDEO)/cidelsa.o \
$(DRIVERS)/coinmstr.o \

1680
src/mame/video/mcd212.c Normal file

File diff suppressed because it is too large Load Diff

192
src/mame/video/mcd212.h Normal file
View File

@ -0,0 +1,192 @@
/******************************************************************************
CD-i MCD212 video emulation
-------------------
MESS implementation by Harmony
*******************************************************************************
STATUS:
- Just enough for the Mono-I CD-i board to work somewhat properly.
TODO:
- Unknown yet.
*******************************************************************************/
#ifndef _VIDEO_MCD212_H_
#define _VIDEO_MCD212_H_
#include "emu.h"
typedef struct
{
UINT8 csrr;
UINT16 csrw;
UINT16 dcr;
UINT16 vsr;
UINT16 ddr;
UINT16 dcp;
UINT32 dca;
UINT8 clut_r[256];
UINT8 clut_g[256];
UINT8 clut_b[256];
UINT32 image_coding_method;
UINT32 transparency_control;
UINT32 plane_order;
UINT32 clut_bank;
UINT32 transparent_color_a;
UINT32 reserved0;
UINT32 transparent_color_b;
UINT32 mask_color_a;
UINT32 reserved1;
UINT32 mask_color_b;
UINT32 dyuv_abs_start_a;
UINT32 dyuv_abs_start_b;
UINT32 reserved2;
UINT32 cursor_position;
UINT32 cursor_control;
UINT32 cursor_pattern[16];
UINT32 region_control[8];
UINT32 backdrop_color;
UINT32 mosaic_hold_a;
UINT32 mosaic_hold_b;
UINT8 weight_factor_a[768];
UINT8 weight_factor_b[768];
} mcd212_channel_t;
typedef struct
{
mcd212_channel_t channel[2];
emu_timer *scan_timer;
UINT8 region_flag_0[768];
UINT8 region_flag_1[768];
running_machine *machine;
} mcd212_regs_t;
#define MCD212_CURCNT_COLOR 0x00000f // Cursor color
#define MCD212_CURCNT_CUW 0x008000 // Cursor width
#define MCD212_CURCNT_COF 0x070000 // Cursor off time
#define MCD212_CURCNT_COF_SHIFT 16
#define MCD212_CURCNT_CON 0x280000 // Cursor on time
#define MCD212_CURCNT_CON_SHIFT 19
#define MCD212_CURCNT_BLKC 0x400000 // Blink type
#define MCD212_CURCNT_EN 0x800000 // Cursor enable
#define MCD212_ICM_CS 0x400000 // CLUT select
#define MCD212_ICM_NR 0x080000 // Number of region flags
#define MCD212_ICM_EV 0x040000 // External video
#define MCD212_ICM_MODE2 0x000f00 // Plane 2
#define MCD212_ICM_MODE2_SHIFT 8
#define MCD212_ICM_MODE1 0x00000f // Plane 1
#define MCD212_ICM_MODE1_SHIFT 0
#define MCD212_TCR_DISABLE_MX 0x800000 // Mix disable
#define MCD212_TCR_TB 0x000f00 // Plane B
#define MCD212_TCR_TB_SHIFT 8
#define MCD212_TCR_TA 0x00000f // Plane A
#define MCD212_TCR_COND_1 0x0 // Transparent if: Always (Plane Disabled)
#define MCD212_TCR_COND_KEY_1 0x1 // Transparent if: Color Key = True
#define MCD212_TCR_COND_XLU_1 0x2 // Transparent if: Transparency Bit = 1
#define MCD212_TCR_COND_RF0_1 0x3 // Transparent if: Region Flag 0 = True
#define MCD212_TCR_COND_RF1_1 0x4 // Transparent if: Region Flag 1 = True
#define MCD212_TCR_COND_RF0KEY_1 0x5 // Transparent if: Region Flag 0 = True || Color Key = True
#define MCD212_TCR_COND_RF1KEY_1 0x6 // Transparent if: Region Flag 1 = True || Color Key = True
#define MCD212_TCR_COND_UNUSED0 0x7 // Unused
#define MCD212_TCR_COND_0 0x8 // Transparent if: Never (No Transparent Area)
#define MCD212_TCR_COND_KEY_0 0x9 // Transparent if: Color Key = False
#define MCD212_TCR_COND_XLU_0 0xa // Transparent if: Transparency Bit = 0
#define MCD212_TCR_COND_RF0_0 0xb // Transparent if: Region Flag 0 = False
#define MCD212_TCR_COND_RF1_0 0xc // Transparent if: Region Flag 1 = False
#define MCD212_TCR_COND_RF0KEY_0 0xd // Transparent if: Region Flag 0 = False && Color Key = False
#define MCD212_TCR_COND_RF1KEY_0 0xe // Transparent if: Region Flag 1 = False && Color Key = False
#define MCD212_TCR_COND_UNUSED1 0xf // Unused
#define MCD212_POR_AB 0 // Plane A in front of Plane B
#define MCD212_POR_BA 1 // Plane B in front of Plane A
#define MCD212_RC_X 0x0003ff // X position
#define MCD212_RC_WF 0x00fc00 // Weight position
#define MCD212_RC_WF_SHIFT 10
#define MCD212_RC_RF 0x010000 // Region flag
#define MCD212_RC_RF_SHIFT 16
#define MCD212_RC_OP 0xf00000 // Operation
#define MCD212_RC_OP_SHIFT 20
#define MCD212_CSR1W_ST 0x0002 // Standard
#define MCD212_CSR1W_BE 0x0001 // Bus Error
#define MCD212_CSR2R_IT1 0x0004 // Interrupt 1
#define MCD212_CSR2R_IT2 0x0002 // Interrupt 2
#define MCD212_CSR2R_BE 0x0001 // Bus Error
#define MCD212_DCR_DE 0x8000 // Display Enable
#define MCD212_DCR_CF 0x4000 // Crystal Frequency
#define MCD212_DCR_FD 0x2000 // Frame Duration
#define MCD212_DCR_SM 0x1000 // Scan Mode
#define MCD212_DCR_CM 0x0800 // Color Mode Ch.1/2
#define MCD212_DCR_ICA 0x0200 // ICA Enable Ch.1/2
#define MCD212_DCR_DCA 0x0100 // DCA Enable Ch.1/2
#define MCD212_DDR_FT 0x0300 // Display File Type
#define MCD212_DDR_FT_BMP 0x0000 // Bitmap
#define MCD212_DDR_FT_BMP2 0x0100 // Bitmap (alt.)
#define MCD212_DDR_FT_RLE 0x0200 // Run-Length Encoded
#define MCD212_DDR_FT_MOSAIC 0x0300 // Mosaic
#define MCD212_DDR_MT 0x0c00 // Mosaic File Type
#define MCD212_DDR_MT_2 0x0000 // 2x1
#define MCD212_DDR_MT_4 0x0400 // 4x1
#define MCD212_DDR_MT_8 0x0800 // 8x1
#define MCD212_DDR_MT_16 0x0c00 // 16x1
#define MCD212_DDR_MT_SHIFT 10
typedef UINT8 BYTE68K;
typedef UINT16 WORD68K;
typedef INT16 SWORD68K;
#define BYTE68K_MAX 255
typedef struct _mcd212_ab_t mcd212_ab_t;
struct _mcd212_ab_t
{
//* Color limit array.
BYTE68K limit[3 * BYTE68K_MAX];
//* Color clamp array.
BYTE68K clamp[3 * BYTE68K_MAX];
//* U-to-B matrix array.
SWORD68K matrixUB[BYTE68K_MAX + 1];
//* U-to-G matrix array.
SWORD68K matrixUG[BYTE68K_MAX + 1];
//* V-to-G matrix array.
SWORD68K matrixVG[BYTE68K_MAX + 1];
//* V-to-R matrix array.
SWORD68K matrixVR[BYTE68K_MAX + 1];
//* Delta-Y decoding array.
BYTE68K deltaY[BYTE68K_MAX + 1];
//* Delta-U/V decoding array.
BYTE68K deltaUV[BYTE68K_MAX + 1];
};
// Member functions
extern READ16_HANDLER( mcd212_r );
extern WRITE16_HANDLER( mcd212_w );
extern TIMER_CALLBACK( mcd212_perform_scan );
extern VIDEO_START( cdimono1 );
extern VIDEO_UPDATE( cdimono1 );
#endif // _VIDEO_MCD212_H_