mirror of
https://github.com/holub/mame
synced 2025-05-22 21:58:57 +03:00
Ported over CD-i cleanup from MESS. [Harmony]
This commit is contained in:
parent
a383b8b20d
commit
179a81a030
9
.gitattributes
vendored
9
.gitattributes
vendored
@ -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
42
src/mame/includes/cdi.h
Normal 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
754
src/mame/machine/cdi070.c
Normal 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
232
src/mame/machine/cdi070.h
Normal 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
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
165
src/mame/machine/cdicdic.h
Normal 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
561
src/mame/machine/cdislave.c
Normal 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
155
src/mame/machine/cdislave.h
Normal 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__
|
@ -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
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
192
src/mame/video/mcd212.h
Normal 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_
|
Loading…
Reference in New Issue
Block a user