// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller, David Haywood
/***********************************************************************
DECO Cassette System machine
***********************************************************************/
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "cpu/mcs48/mcs48.h"
#include "includes/decocass.h"
#include "machine/decocass_tape.h"
/* dongle type #1: jumpers C and D assignments */
#define MAKE_MAP(m0,m1,m2,m3,m4,m5,m6,m7) \
((uint32_t)(m0)) | \
((uint32_t)(m1) << 3) | \
((uint32_t)(m2) << 6) | \
((uint32_t)(m3) << 9) | \
((uint32_t)(m4) << 12) | \
((uint32_t)(m5) << 15) | \
((uint32_t)(m6) << 18) | \
((uint32_t)(m7) << 21)
#define T1MAP(x, m) (((m)>>(x*3))&7)
enum {
TYPE3_SWAP_01,
TYPE3_SWAP_12,
TYPE3_SWAP_13,
TYPE3_SWAP_24,
TYPE3_SWAP_25,
TYPE3_SWAP_34_0,
TYPE3_SWAP_34_7,
TYPE3_SWAP_45,
TYPE3_SWAP_23_56,
TYPE3_SWAP_56,
TYPE3_SWAP_67
};
WRITE8_MEMBER(decocass_state::decocass_coin_counter_w)
{
}
READ8_MEMBER( decocass_state::decocass_sound_command_main_r)
{
// cgraplop2 needs to read something here or it will reset when you coin-up
// could do with further investigation
return 0xc0;
}
WRITE8_MEMBER(decocass_state::decocass_sound_command_w)
{
LOG(2,("CPU %s sound command -> $%02x\n", m_maincpu->tag(), data));
m_soundlatch->write(data);
m_sound_ack |= 0x80;
/* remove snd cpu data ack bit. i don't see it in the schems, but... */
m_sound_ack &= ~0x40;
m_audiocpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
}
READ8_MEMBER(decocass_state::decocass_sound_data_r)
{
uint8_t data = m_soundlatch2->read();
LOG(2,("CPU %s sound data <- $%02x\n", m_maincpu->tag(), data));
return data;
}
READ8_MEMBER(decocass_state::decocass_sound_ack_r)
{
uint8_t data = m_sound_ack; /* D6+D7 */
LOG(4,("CPU %s sound ack <- $%02x\n", m_maincpu->tag(), data));
return data;
}
WRITE8_MEMBER(decocass_state::decocass_sound_data_w)
{
LOG(2,("CPU %s sound data -> $%02x\n", m_audiocpu->tag(), data));
m_soundlatch2->write(data);
m_sound_ack |= 0x40;
}
READ8_MEMBER(decocass_state::decocass_sound_command_r)
{
uint8_t data = m_soundlatch->read();
LOG(4,("CPU %s sound command <- $%02x\n", m_audiocpu->tag(), data));
m_audiocpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
m_sound_ack &= ~0x80;
return data;
}
TIMER_DEVICE_CALLBACK_MEMBER(decocass_state::decocass_audio_nmi_gen)
{
int scanline = param;
m_audio_nmi_state = scanline & 8;
m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_audio_nmi_enabled && m_audio_nmi_state) ? ASSERT_LINE : CLEAR_LINE);
}
WRITE8_MEMBER(decocass_state::decocass_sound_nmi_enable_w)
{
m_audio_nmi_enabled = 1;
m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_audio_nmi_enabled && m_audio_nmi_state) ? ASSERT_LINE : CLEAR_LINE);
}
READ8_MEMBER(decocass_state::decocass_sound_nmi_enable_r)
{
m_audio_nmi_enabled = 1;
m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_audio_nmi_enabled && m_audio_nmi_state) ? ASSERT_LINE : CLEAR_LINE);
return 0xff;
}
READ8_MEMBER(decocass_state::decocass_sound_data_ack_reset_r)
{
uint8_t data = 0xff;
LOG(2,("CPU %s sound ack rst <- $%02x\n", m_audiocpu->tag(), data));
m_sound_ack &= ~0x40;
return data;
}
WRITE8_MEMBER(decocass_state::decocass_sound_data_ack_reset_w)
{
LOG(2,("CPU %s sound ack rst -> $%02x\n", m_audiocpu->tag(), data));
m_sound_ack &= ~0x40;
}
WRITE8_MEMBER(decocass_state::decocass_nmi_reset_w)
{
m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE );
}
WRITE8_MEMBER(decocass_state::decocass_quadrature_decoder_reset_w)
{
/* just latch the analog controls here */
m_quadrature_decoder[0] = ioport("AN0")->read();
m_quadrature_decoder[1] = ioport("AN1")->read();
m_quadrature_decoder[2] = ioport("AN2")->read();
m_quadrature_decoder[3] = ioport("AN3")->read();
}
WRITE8_MEMBER(decocass_state::decocass_adc_w)
{
}
/*
* E6x0 inputs
* E6x1 inputs
* E6x2 coin inp
* E6x3 quadrature decoder read
* E6x4 ""
* E6x5 ""
* E6x6 ""
* E6x7 a/d converter read
*/
READ8_MEMBER(decocass_state::decocass_input_r)
{
uint8_t data = 0xff;
static const char *const portnames[] = { "IN0", "IN1", "IN2" };
switch (offset & 7)
{
case 0: case 1: case 2:
data = machine().root_device().ioport(portnames[offset & 7])->read();
break;
case 3: case 4: case 5: case 6:
data = m_quadrature_decoder[(offset & 7) - 3];
break;
default:
break;
}
return data;
}
/*
* D0 - REQ/ data request (8041 pin 34 port 1.7)
* D1 - FNO/ function number (8041 pin 21 port 2.0)
* D2 - EOT/ end-of-tape (8041 pin 22 port 2.1)
* D3 - ERR/ error condition (8041 pin 23 port 2.2)
* D4 - BOT-EOT from tape
* D5 -
* D6 -
* D7 - cassette present
*/
#define E5XX_MASK 0x02 /* use 0x0e for old style board */
WRITE8_MEMBER(decocass_state::decocass_reset_w)
{
LOG(1,("%10s 6502-PC: %04x decocass_reset_w(%02x): $%02x\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
m_decocass_reset = data;
/* CPU #1 active high reset */
m_audiocpu->set_input_line(INPUT_LINE_RESET, data & 0x01);
/* on reset also disable audio NMI */
if (data & 1)
{
m_audio_nmi_enabled = 0;
m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_audio_nmi_enabled && m_audio_nmi_state) ? ASSERT_LINE : CLEAR_LINE);
}
/* 8041 active low reset */
m_mcu->set_input_line(INPUT_LINE_RESET, (data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
}
#ifdef MAME_DEBUG
void decocass_state::decocass_fno( offs_t offset, uint8_t data )
{
/* 8041ENA/ and is this a FNO write (function number)? */
if (0 == (m_i8041_p2 & 0x01))
{
switch (data)
{
case 0x25: logerror("8041 FNO 25: write_block\n"); break;
case 0x26: logerror("8041 FNO 26: rewind_block\n"); break;
case 0x27: logerror("8041 FNO 27: read_block_a\n"); break;
case 0x28: logerror("8041 FNO 28: read_block_b\n"); break;
case 0x29: logerror("8041 FNO 29: tape_rewind_fast\n"); break;
case 0x2a: logerror("8041 FNO 2a: tape_forward\n"); break;
case 0x2b: logerror("8041 FNO 2b: tape_rewind\n"); break;
case 0x2c: logerror("8041 FNO 2c: force_abort\n"); break;
case 0x2d: logerror("8041 FNO 2d: tape_erase\n"); break;
case 0x2e: logerror("8041 FNO 2e: search_tape_mark\n"); break;
case 0x2f: logerror("8041 FNO 2f: search_eot\n"); break;
case 0x30: logerror("8041 FNO 30: advance_block\n"); break;
case 0x31: logerror("8041 FNO 31: write_tape_mark\n"); break;
case 0x32: logerror("8041 FNO 32: reset_error\n"); break;
case 0x33: logerror("8041 FNO 33: flag_status_report\n"); break;
case 0x34: logerror("8041 FNO 34: report_status_to_main\n"); break;
default: logerror("8041 FNO %02x: invalid\n", data);
}
}
}
#endif
READ8_MEMBER(decocass_type1_state::decocass_type1_r)
{
if (!m_type1_map)
return 0x00;
uint8_t data;
if (1 == (offset & 1))
{
if (0 == (offset & E5XX_MASK))
data = m_mcu->upi41_master_r(space,1);
else
data = 0xff;
data = (BIT(data, 0) << 0) | (BIT(data, 1) << 1) | 0x7c;
LOG(4,("%10s 6502-PC: %04x decocass_type1_r(%02x): $%02x <- (%s %s)\n",
machine().time().as_string(6), m_maincpu->pcbase(), offset, data,
(data & 1) ? "OBF" : "-",
(data & 2) ? "IBF" : "-"));
}
else
{
offs_t promaddr;
uint8_t save;
uint8_t *prom = machine().root_device().memregion("dongle")->base();
if (m_firsttime)
{
LOG(3,("prom data:\n"));
for (promaddr = 0; promaddr < 32; promaddr++)
{
if (promaddr % 8 == 0)
LOG(3,(" %02x:", promaddr));
LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
}
m_firsttime = 0;
m_latch1 = 0; /* reset latch (??) */
}
if (0 == (offset & E5XX_MASK))
data = m_mcu->upi41_master_r(space,0);
else
data = 0xff;
save = data; /* save the unmodifed data for the latch */
promaddr = 0;
int promshift = 0;
for (int i=0;i<8;i++)
{
if (m_type1_map[i] == T1PROM) { promaddr |= (((data >> T1MAP(i,m_type1_inmap)) & 1) << promshift); promshift++; }
}
if (promshift!=5)
printf("promshift != 5? (you specified more/less than 5 prom source bits)");
data = 0;
promshift = 0;
for (int i=0;i<8;i++)
{
if (m_type1_map[i] == T1PROM) { data |= (((prom[promaddr] >> promshift) & 1) << T1MAP(i,m_type1_outmap)); promshift++; }
if (m_type1_map[i] == T1LATCHINV) { data |= ((1 - ((m_latch1 >> T1MAP(i,m_type1_inmap)) & 1)) << T1MAP(i,m_type1_outmap)); }
if (m_type1_map[i] == T1LATCH) { data |= (((m_latch1 >> T1MAP(i,m_type1_inmap)) & 1) << T1MAP(i,m_type1_outmap)); }
if (m_type1_map[i] == T1DIRECT) { data |= (((save >> T1MAP(i,m_type1_inmap)) & 1) << T1MAP(i,m_type1_outmap)); }
}
LOG(3,("%10s 6502-PC: %04x decocass_type1_r(%02x): $%02x\n",
machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
m_latch1 = save; /* latch the data for the next A0 == 0 read */
}
return data;
}
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Terranian
* - Super Astro Fighter
* - Lock 'n Chase
* - Pro Golf
* - Lucky Poker
* - Treasure Island
*
* Latch bits 2 and 6, pass bit 3, invert bit 2.
* Lookup PROM DE-0061 using bits 0, 1, 4, 5, and 7 as the
* address bits; take PROM data 0-4 as data bits 0, 1, 4, 5, and 7.
*
***************************************************************************/
static uint8_t type1_latch_26_pass_3_inv_2_table[8] = { T1PROM,T1PROM,T1LATCHINV,T1DIRECT,T1PROM, T1PROM,T1LATCH,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061?)
* - Treasure Island (Region D)
*
***************************************************************************/
static uint8_t type1_latch_ctisland3[8] = { T1LATCHINV,T1PROM,T1PROM,T1DIRECT,T1PROM, T1PROM,T1LATCH,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Test Tape
*
* Pass bits 1, 3, and 6. Lookup PROM DE-0061 using bits 0, 2, 4, 5, and 7
* as the address bits; take PROM data 0-4 as data bits 0, 2, 4, 5, and 7.
*
***************************************************************************/
static uint8_t type1_pass_136_table[8] ={ T1PROM,T1DIRECT,T1PROM,T1DIRECT,T1PROM,T1PROM,T1DIRECT,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Manhattan
*
* Input bits that are passed uninverted = $54 (3 true bits)
* Input bits that are passed inverted = $00 (0 inverted bits)
* Remaining bits for addressing PROM = $AB (5 bits)
*
***************************************************************************/
static uint8_t type1_latch_xab_pass_x54_table[8] = { T1PROM,T1PROM,T1DIRECT,T1PROM,T1DIRECT,T1PROM,T1DIRECT,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Highway Chase
*
* Latch bits 2 and 7, pass bit 3, invert bit 2 to the output.
* Lookup PROM (Highway Chase) using data bits 0, 1, 4, 5, and 6 as the
* address bits. Take PROM data 0-4 as data bits 0, 1, 4, 5, and 6.
*
***************************************************************************/
static uint8_t type1_latch_27_pass_3_inv_2_table[8] = { T1PROM,T1PROM,T1LATCHINV,T1DIRECT,T1PROM,T1PROM,T1PROM,T1LATCH };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Explorer
*
* Latch bits 2 and 6, pass bit 5, invert bit 2 to the output.
* Lookup PROM (Explorer) using bits 0, 1, 3, 4, and 7 as the
* address bits. Take PROM data 0-4 as data bits 0, 1, 3, 4, and 7.
*
***************************************************************************/
static uint8_t type1_latch_26_pass_5_inv_2_table[8] = { T1PROM,T1PROM,T1LATCHINV,T1PROM,T1PROM,T1DIRECT,T1LATCH,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE (DE-0061)
* - Astro Fantazia
*
* Latch bits 1 and 6, pass bit 3, invert bit 1.
* Lookup PROM DE-0061 using bits 0, 2, 4, 5, and 7 as the
* address bits; take PROM data 0-4 as data bits 0, 2, 4, 5, and 7.
*
***************************************************************************/
static uint8_t type1_latch_16_pass_3_inv_1_table[8] = { T1PROM,T1LATCHINV,T1PROM,T1DIRECT,T1PROM,T1PROM,T1LATCH,T1PROM };
/***************************************************************************
*
* TYPE1 DONGLE DP-1100/DP-2100 map for Ocean to Ocean
*
* Latched bits = $44 (2 latch bits)
* Input bits that are passed uninverted = $10 (1 true bits)
* Input bits that are passed inverted = $00 (0 inverted bits)
* Remaining bits for addressing PROM = $AB (5 bits)
* Latched bit #0:
* Input bit position = 2
* Output bit position = 2
* Type = Inverting latch
* Latched bit #1:
* Input bit position = 6
* Output bit position = 6
* Type = Non-inverting latch
*
***************************************************************************/
static uint8_t type1_map1100[8] = { T1PROM,T1PROM,T1LATCHINV,T1PROM,T1DIRECT,T1PROM,T1LATCH,T1PROM };
MACHINE_RESET_MEMBER(decocass_type1_state,cocean1a) /* 10 */
{
machine_reset();
LOG(0,("dongle type #1 (DP-1100 map)\n"));
m_type1_map = type1_map1100;
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
}
/***************************************************************************
*
* TYPE1 DONGLE DP-1120/DP-2120 map for Flash Boy/The Deco Kid
*
* Latched bits = $24 (2 latch bits)
* Input bits that are passed uninverted = $08 (1 true bits)
* Input bits that are passed inverted = $00 (0 inverted bits)
* Remaining bits for addressing PROM = $D3 (5 bits)
* Latched bit #0:
* Input bit position = 2
* Output bit position = 2
* Type = Inverting latch
* Latched bit #1:
* Input bit position = 5
* Output bit position = 5
* Type = Non-inverting latch
*
***************************************************************************/
static uint8_t type1_map1120[8] = { T1PROM,T1PROM,T1LATCHINV,T1DIRECT,T1PROM,T1LATCH,T1PROM,T1PROM };
MACHINE_RESET_MEMBER(decocass_type1_state,cfboy0a1) /* 12 */
{
machine_reset();
LOG(0,("dongle type #1 (DP-1120 map)\n"));
m_type1_map = type1_map1120;
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
}
/*
TYPE 1
* Latched bits = $48 (2 latch bits)
* Input bits that are passed uninverted = $04 (1 true bits)
* Input bits that are passed inverted = $00 (0 inverted bits)
* Remaining bits for addressing PROM = $B3 (5 bits)
* Latched bit #0:
- Input bit position = 3
- Output bit position = 3
- Type = Inverting latch
* Latched bit #1:
- Input bit position = 6
- Output bit position = 6
- Type = Non-inverting latch
*/
static uint8_t type1_map_clocknchj[8] = { T1PROM,T1PROM,T1DIRECT,T1LATCHINV,T1PROM,T1PROM,T1LATCH,T1PROM };
MACHINE_RESET_MEMBER(decocass_type1_state,clocknchj) /* 11 */
{
machine_reset();
LOG(0,("dongle type #1 (type1_map_clocknchj map)\n"));
m_type1_map = type1_map_clocknchj;
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
}
/***************************************************************************
*
* TYPE2 DONGLE (CS82-007)
* - Disco No 1
* - Tornado
* - Mission X
* - Pro Tennis
*
***************************************************************************/
READ8_MEMBER(decocass_type2_state::decocass_type2_r)
{
uint8_t data;
if (1 == m_type2_xx_latch)
{
if (1 == (offset & 1))
{
uint8_t *prom = memregion("dongle")->base();
data = prom[256 * m_type2_d2_latch + m_type2_promaddr];
LOG(3,("%10s 6502-PC: %04x decocass_type2_r(%02x): $%02x <- prom[%03x]\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, 256 * m_type2_d2_latch + m_type2_promaddr));
}
else
{
data = 0xff; /* floating input? */
}
}
else
{
if (0 == (offset & E5XX_MASK))
data = m_mcu->upi41_master_r(space,offset);
else
data = offset & 0xff;
LOG(3,("%10s 6502-PC: %04x decocass_type2_r(%02x): $%02x <- 8041-%s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "STATUS" : "DATA"));
}
return data;
}
WRITE8_MEMBER(decocass_type2_state::decocass_type2_w)
{
if (1 == m_type2_xx_latch)
{
if (1 == (offset & 1))
{
LOG(4,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM+D2 latch", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
m_type2_promaddr = data;
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM addr $%02x\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_type2_promaddr));
return;
}
}
else
{
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s ", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041 DATA"));
}
if (1 == (offset & 1))
{
if (0xc0 == (data & 0xf0))
{
m_type2_xx_latch = 1;
m_type2_d2_latch = (data & 0x04) ? 1 : 0;
LOG(3,("PROM:%s D2:%d", m_type2_xx_latch ? "on" : "off", m_type2_d2_latch));
}
}
m_mcu->upi41_master_w(space,offset & 1, data);
#ifdef MAME_DEBUG
decocass_fno(offset, data);
#endif
}
/***************************************************************************
*
* TYPE3 DONGLE
* - Burger Time
* - Bump 'n Jump
* - Burnin' Rubber
* - Graplop
* - Cluster Buster
* - LaPaPa
* - Skater
* - Pro Bowling
* - Night Star
* - Pro Soccer
* - Super Doubles Tennis
* - Peter Pepper's Ice Cream Factory
* - Fighting Ice Hockey
*
***************************************************************************/
READ8_MEMBER(decocass_type3_state::decocass_type3_r)
{
uint8_t data, save;
if (1 == (offset & 1))
{
if (1 == m_type3_pal_19)
{
uint8_t *prom = memregion("dongle")->base();
data = prom[m_type3_ctrs];
LOG(3,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x <- prom[$%03x]\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_type3_ctrs));
if (++m_type3_ctrs == 4096)
m_type3_ctrs = 0;
}
else
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,1);
LOG(4,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x <- 8041 STATUS\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
}
else
{
if (1 == m_type3_pal_19)
{
save = data = 0xff; /* open data bus? */
LOG(3,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
if (0 == (offset & E5XX_MASK))
{
save = m_mcu->upi41_master_r(space,0);
switch (m_type3_swap)
{
case TYPE3_SWAP_01:
data =
(BIT(save, 1) << 0) |
(m_type3_d0_latch << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_12:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 2) << 1) |
(BIT(save, 1) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_13:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 3) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 1) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_24:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 1) << 1) |
(BIT(save, 4) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 2) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_25:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 1) << 1) |
(BIT(save, 5) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 2) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_34_0:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 4) |
(BIT(save, 4) << 3) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_34_7:
data =
(BIT(save, 7) << 0) |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 4) << 3) |
(BIT(save, 3) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(m_type3_d0_latch << 7);
break;
case TYPE3_SWAP_45:
data =
m_type3_d0_latch |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 5) << 4) |
(BIT(save, 4) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_23_56:
data =
(m_type3_d0_latch << 0) |
(BIT(save, 1) << 1) |
(BIT(save, 3) << 2) |
(BIT(save, 2) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 6) << 5) |
(BIT(save, 5) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_56:
data =
m_type3_d0_latch |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 6) << 5) |
(BIT(save, 5) << 6) |
(BIT(save, 7) << 7);
break;
case TYPE3_SWAP_67:
data =
m_type3_d0_latch |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 7) << 6) |
(BIT(save, 6) << 7);
break;
default:
data =
m_type3_d0_latch |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 6) |
(BIT(save, 7) << 7);
}
m_type3_d0_latch = save & 1;
LOG(3,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- 8041-DATA\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
save = 0xff; /* open data bus? */
data =
m_type3_d0_latch |
(BIT(save, 1) << 1) |
(BIT(save, 2) << 2) |
(BIT(save, 3) << 3) |
(BIT(save, 4) << 4) |
(BIT(save, 5) << 5) |
(BIT(save, 6) << 7) |
(BIT(save, 7) << 6);
LOG(3,("%10s 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
m_type3_d0_latch = save & 1;
}
}
}
return data;
}
WRITE8_MEMBER(decocass_type3_state::decocass_type3_w)
{
if (1 == (offset & 1))
{
if (1 == m_type3_pal_19)
{
m_type3_ctrs = data << 4;
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, "LDCTRS"));
return;
}
else
if (0xc0 == (data & 0xf0))
m_type3_pal_19 = 1;
}
else
{
if (1 == m_type3_pal_19)
{
/* write nowhere?? */
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, "nowhere?"));
return;
}
}
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
m_mcu->upi41_master_w(space,offset, data);
}
/***************************************************************************
*
* TYPE4 DONGLE
* - Scrum Try
* - Oozumou/The Grand Sumo
* Contains a 32K (EP)ROM that can be read from any byte
* boundary sequentially. The EPROM is enable after writing
* 1100xxxx to E5x1 once. Then an address is written LSB
* to E5x0 MSB to E5x1 and every read from E5x1 returns the
* next byte of the contents.
*
***************************************************************************/
READ8_MEMBER(decocass_type4_state::decocass_type4_r)
{
uint8_t data;
if (1 == (offset & 1))
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,1);
LOG(4,("%10s 6502-PC: %04x decocass_type4_r(%02x): $%02x <- 8041 STATUS\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
else
{
if (m_type4_latch)
{
uint8_t *prom = machine().root_device().memregion("dongle")->base();
data = prom[m_type4_ctrs];
LOG(3,("%10s 6502-PC: %04x decocass_type4_r(%02x): $%02x '%c' <- PROM[%04x]\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.', m_type4_ctrs));
m_type4_ctrs = (m_type4_ctrs + 1) & 0x7fff;
}
else
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,0);
LOG(3,("%10s 6502-PC: %04x decocass_type4_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
}
return data;
}
WRITE8_MEMBER(decocass_type4_state::decocass_type4_w)
{
if (1 == (offset & 1))
{
if (1 == m_type4_latch)
{
m_type4_ctrs = (m_type4_ctrs & 0x00ff) | ((data & 0x7f) << 8);
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS MSB (%04x)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_type4_ctrs));
return;
}
else
if (0xc0 == (data & 0xf0))
{
m_type4_latch = 1;
}
}
else
{
if (m_type4_latch)
{
m_type4_ctrs = (m_type4_ctrs & 0xff00) | data;
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS LSB (%04x)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_type4_ctrs));
return;
}
}
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
m_mcu->upi41_master_w(space,offset, data);
}
/***************************************************************************
*
* TYPE4 DONGLE
* - Boulder Dash
* Actually a NOP dongle returning 0x55 after triggering a latch
* by writing 1100xxxx to E5x1
*
***************************************************************************/
READ8_MEMBER(decocass_type5_state::decocass_type5_r)
{
uint8_t data;
if (1 == (offset & 1))
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,1);
LOG(4,("%10s 6502-PC: %04x decocass_type5_r(%02x): $%02x <- 8041 STATUS\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
else
{
if (m_type5_latch)
{
data = 0x55; /* Only a fixed value? It looks like this is all we need to do */
LOG(3,("%10s 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- fixed value???\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,0);
LOG(3,("%10s 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
}
return data;
}
WRITE8_MEMBER(decocass_type5_state::decocass_type5_w)
{
if (1 == (offset & 1))
{
if (1 == m_type5_latch)
{
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, "latch #2??"));
return;
}
else
if (0xc0 == (data & 0xf0))
m_type5_latch = 1;
}
else
{
if (m_type5_latch)
{
/* write nowhere?? */
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, "nowhere?"));
return;
}
}
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
m_mcu->upi41_master_w(space,offset, data);
}
/***************************************************************************
*
* NO DONGLE
* - Flying Ball
* A NOP dongle returning the data read from cassette as is.
*
***************************************************************************/
READ8_MEMBER(decocass_nodong_state::decocass_nodong_r)
{
uint8_t data;
if (1 == (offset & 1))
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,1);
LOG(4,("%10s 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- 8041 STATUS\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
else
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,0);
LOG(3,("%10s 6502-PC: %04x decocass_nodong_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
return data;
}
/***************************************************************************
*
* Widel Multigame Dongle
* - provides access to a large ROM
*
***************************************************************************/
READ8_MEMBER(decocass_widel_state::decocass_widel_r)
{
uint8_t data;
if (1 == (offset & 1))
{
if (0 == (offset & E5XX_MASK))
{
if (m_widel_latch && !machine().side_effects_disabled())
m_widel_ctrs = (m_widel_ctrs + 0x100) & 0xfffff;
data = m_mcu->upi41_master_r(space,1);
LOG(4,("%10s 6502-PC: %04x decocass_widel_r(%02x): $%02x <- 8041 STATUS\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_widel_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
else
{
if (m_widel_latch)
{
uint8_t *prom = machine().root_device().memregion("dongle")->base();
data = prom[m_widel_ctrs];
LOG(3,("%10s 6502-PC: %04x decocass_widel_r(%02x): $%02x '%c' <- PROM[%04x]\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.', m_widel_ctrs));
if (!machine().side_effects_disabled())
m_widel_ctrs = (m_widel_ctrs + 1) & 0xfffff;
}
else
{
if (0 == (offset & E5XX_MASK))
{
data = m_mcu->upi41_master_r(space,0);
LOG(3,("%10s 6502-PC: %04x decocass_widel_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, (data >= 32) ? data : '.'));
}
else
{
data = 0xff; /* open data bus? */
LOG(4,("%10s 6502-PC: %04x decocass_widel_r(%02x): $%02x <- open bus\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
}
return data;
}
WRITE8_MEMBER(decocass_widel_state::decocass_widel_w)
{
if (1 == (offset & 1))
{
if (1 == m_widel_latch)
{
// BIOS follows writes to here by counting out a lot of dummy reads from the
// same location, probably to advance a 74HC4040 or similar counter.
// Counterintuitive though it may seem, the value written is probably just ignored.
// Treasure Island depends on this clearing the lower bits as well.
m_widel_ctrs = 0;
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS MSB (%04x)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_widel_ctrs));
return;
}
else
if (0xc0 == (data & 0xf0))
{
m_widel_latch = 1;
}
}
else
{
if (m_widel_latch)
{
m_widel_ctrs = (m_widel_ctrs & 0xfff00) | data;
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS LSB (%04x)\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, m_widel_ctrs));
return;
}
}
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
m_mcu->upi41_master_w(space,offset, data);
}
/***************************************************************************
*
* Main dongle and 8041 interface
*
***************************************************************************/
READ8_MEMBER(decocass_state::decocass_e5xx_r)
{
uint8_t data;
/* E5x2-E5x3 and mirrors */
if (2 == (offset & E5XX_MASK))
{
uint8_t bot_eot = (m_cassette->get_status_bits() >> 5) & 1;
data =
(BIT(m_i8041_p1, 7) << 0) | /* D0 = P17 - REQ/ */
(BIT(m_i8041_p2, 0) << 1) | /* D1 = P20 - FNO/ */
(BIT(m_i8041_p2, 1) << 2) | /* D2 = P21 - EOT/ */
(BIT(m_i8041_p2, 2) << 3) | /* D3 = P22 - ERR/ */
((bot_eot) << 4) | /* D4 = BOT/EOT (direct from drive) */
(1 << 5) | /* D5 floating input */
(1 << 6) | /* D6 floating input */
(!m_cassette->is_present() << 7); /* D7 = cassette present */
LOG(4,("%10s 6502-PC: %04x decocass_e5xx_r(%02x): $%02x <- STATUS (%s%s%s%s%s%s%s%s)\n",
machine().time().as_string(6),
m_maincpu->pcbase(),
offset, data,
data & 0x01 ? "" : "REQ/",
data & 0x02 ? "" : " FNO/",
data & 0x04 ? "" : " EOT/",
data & 0x08 ? "" : " ERR/",
data & 0x10 ? " [BOT-EOT]" : "",
data & 0x20 ? " [BIT5?]" : "",
data & 0x40 ? " [BIT6?]" : "",
data & 0x80 ? "" : " [CASS-PRESENT/]"));
}
else
{
if (!m_dongle_r.isnull())
data = m_dongle_r(space, offset, mem_mask);
else
data = 0xff;
}
return data;
}
WRITE8_MEMBER(decocass_state::decocass_e5xx_w)
{
if (!m_dongle_w.isnull())
{
m_dongle_w(space, offset, data, mem_mask);
return;
}
if (0 == (offset & E5XX_MASK))
{
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
m_mcu->upi41_master_w(space,offset & 1, data);
#ifdef MAME_DEBUG
decocass_fno(offset, data);
#endif
}
else
{
LOG(3,("%10s 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> dongle\n", machine().time().as_string(6), m_maincpu->pcbase(), offset, data));
}
}
/***************************************************************************
*
* DE-0091xx daughter board handler
*
* The DE-0091xx daughter board seems to be a read-only ROM board with
* two times five 4K ROMs.
*
* The board's ROMs are mapped into view for reads between addresses
* 0x6000 and 0xafff by setting bits 0 and 1 of address 0xe900.
*
***************************************************************************/
WRITE8_MEMBER(decocass_state::decocass_e900_w)
{
m_de0091_enable = data & 3;
if (m_de0091_enable == 0x3) // invalid
return;
membank("bank1")->set_entry(data & 3);
}
WRITE8_MEMBER(decocass_state::decocass_de0091_w)
{
/* don't allow writes to the ROMs - actually cexplore requires us to allow them */
//if (!m_de0091_enable)
decocass_charram_w(space, offset, data);
}
/***************************************************************************
*
* state save setup
*
***************************************************************************/
/* To be called once from driver_init, i.e. decocass_init */
void decocass_state::decocass_machine_state_save_init()
{
save_item(NAME(m_firsttime));
save_item(NAME(m_decocass_reset));
save_item(NAME(m_i8041_p1));
save_item(NAME(m_i8041_p2));
save_item(NAME(m_de0091_enable));
save_item(NAME(m_sound_ack));
save_item(NAME(m_quadrature_decoder));
save_item(NAME(m_latch1));
save_item(NAME(m_audio_nmi_enabled));
save_item(NAME(m_audio_nmi_state));
save_item(NAME(m_i8041_p1_write_latch));
save_item(NAME(m_i8041_p2_write_latch));
save_item(NAME(m_i8041_p1_read_latch));
save_item(NAME(m_i8041_p2_read_latch));
}
/***************************************************************************
*
* init machine functions (select dongle and determine tape image size)
*
***************************************************************************/
void decocass_state::machine_start()
{
}
void decocass_state::machine_reset()
{
m_firsttime = 1;
m_latch1 = 0;
m_dongle_r = read8_delegate(*this);
m_dongle_w = write8_delegate(*this);
m_decocass_reset = 0;
m_i8041_p1 = 0xff;
m_i8041_p2 = 0xff;
m_i8041_p1_write_latch = 0xff;
m_i8041_p2_write_latch = 0xff;
m_i8041_p1_read_latch = 0xff;
m_i8041_p2_read_latch = 0xff;
m_de0091_enable = 0;
memset(m_quadrature_decoder, 0, sizeof(m_quadrature_decoder));
m_sound_ack = 0;
m_audio_nmi_enabled = 0;
m_audio_nmi_state = 0;
/* video-related */
m_watchdog_flip = 0;
m_color_missiles = 0;
m_color_center_bot = 0;
m_mode_set = 0;
m_back_h_shift = 0;
m_back_vl_shift = 0;
m_back_vr_shift = 0;
m_part_h_shift = 0;
m_part_v_shift = 0;
m_center_h_shift_space = 0;
m_center_v_shift = 0;
}
void decocass_type1_state::machine_start()
{
save_item(NAME(m_type1_inmap));
save_item(NAME(m_type1_outmap));
}
void decocass_type1_state::machine_reset()
{
decocass_state::machine_reset();
m_dongle_r = read8_delegate(*this, FUNC(decocass_type1_state::decocass_type1_r));
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
}
void decocass_type2_state::machine_start()
{
save_item(NAME(m_type2_d2_latch));
save_item(NAME(m_type2_xx_latch));
save_item(NAME(m_type2_promaddr));
}
void decocass_type2_state::machine_reset()
{
decocass_state::machine_reset();
LOG(0,("dongle type #2 (CS82-007)\n"));
m_dongle_r = read8_delegate(*this, FUNC(decocass_type2_state::decocass_type2_r));
m_dongle_w = write8_delegate(*this, FUNC(decocass_type2_state::decocass_type2_w));
m_type2_d2_latch = 0;
m_type2_xx_latch = 0;
m_type2_promaddr = 0;
}
void decocass_type3_state::machine_start()
{
save_item(NAME(m_type3_ctrs));
save_item(NAME(m_type3_d0_latch));
save_item(NAME(m_type3_pal_19));
save_item(NAME(m_type3_swap));
}
void decocass_type3_state::machine_reset()
{
decocass_state::machine_reset();
m_dongle_r = read8_delegate(*this, FUNC(decocass_type3_state::decocass_type3_r));
m_dongle_w = write8_delegate(*this, FUNC(decocass_type3_state::decocass_type3_w));
m_type3_ctrs = 0;
m_type3_d0_latch = 0;
m_type3_pal_19 = 0;
m_type3_swap = 0;
}
void decocass_type4_state::machine_start()
{
save_item(NAME(m_type4_ctrs));
save_item(NAME(m_type4_latch));
}
void decocass_type4_state::machine_reset()
{
decocass_state::machine_reset();
LOG(0,("dongle type #4 (32K ROM)\n"));
m_dongle_r = read8_delegate(*this, FUNC(decocass_type4_state::decocass_type4_r));
m_dongle_w = write8_delegate(*this, FUNC(decocass_type4_state::decocass_type4_w));
m_type4_ctrs = 0;
m_type4_latch = 0;
}
void decocass_type5_state::machine_start()
{
save_item(NAME(m_type5_latch));
}
void decocass_type5_state::machine_reset()
{
decocass_state::machine_reset();
LOG(0,("dongle type #5 (NOP)\n"));
m_dongle_r = read8_delegate(*this, FUNC(decocass_type5_state::decocass_type5_r));
m_dongle_w = write8_delegate(*this, FUNC(decocass_type5_state::decocass_type5_w));
m_type5_latch = 0;
}
void decocass_nodong_state::machine_reset()
{
decocass_state::machine_reset();
LOG(0, ("no dongle\n"));
m_dongle_r = read8_delegate(*this, FUNC(decocass_nodong_state::decocass_nodong_r));
}
MACHINE_RESET_MEMBER(decocass_type1_state,ctsttape)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061)\n"));
m_type1_map = type1_pass_136_table;
}
MACHINE_RESET_MEMBER(decocass_type1_state,chwy)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 own PROM)\n"));
m_type1_map = type1_latch_27_pass_3_inv_2_table;
}
MACHINE_RESET_MEMBER(decocass_type1_state,cdsteljn)
{
machine_reset();
LOG(0,("dongle type #1 (A-0061)\n"));
m_type1_map = type1_latch_27_pass_3_inv_2_table;
}
MACHINE_RESET_MEMBER(decocass_type1_state,cterrani)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 straight)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,castfant)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061)\n"));
m_type1_map = type1_latch_16_pass_3_inv_1_table;
}
MACHINE_RESET_MEMBER(decocass_type1_state,csuperas)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 flip 4-5)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(0,1,2,3,5,4,6,7);
m_type1_outmap = MAKE_MAP(0,1,2,3,5,4,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,cmanhat)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061)\n"));
m_type1_map = type1_latch_xab_pass_x54_table;
}
MACHINE_RESET_MEMBER(decocass_type1_state,clocknch)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 flip 2-3)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(0,1,3,2,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,1,3,2,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,cprogolf)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 flip 0-1)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(1,0,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(1,0,2,3,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,cprogolfj)
{
machine_reset();
LOG(0,("dongle type #1 (A-0061 flip 0-1)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(1,0,2,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(1,0,2,3,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,cluckypo)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 flip 1-3)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(0,3,2,1,4,5,6,7);
m_type1_outmap = MAKE_MAP(0,3,2,1,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,ctisland)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 flip 0-2)\n"));
m_type1_map = type1_latch_26_pass_3_inv_2_table;
m_type1_inmap = MAKE_MAP(2,1,0,3,4,5,6,7);
m_type1_outmap = MAKE_MAP(2,1,0,3,4,5,6,7);
}
MACHINE_RESET_MEMBER(decocass_type1_state,ctisland3)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 custom)\n"));
m_type1_map = type1_latch_ctisland3;
m_type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7); // correct for handcrafted prom
m_type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7); // ^
}
MACHINE_RESET_MEMBER(decocass_type1_state,cexplore)
{
machine_reset();
LOG(0,("dongle type #1 (DE-0061 own PROM)\n"));
m_type1_map = type1_latch_26_pass_5_inv_2_table;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cfishing)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_01;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cbtime)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_12;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cburnrub)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_67;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cgraplop)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_56;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cgraplop2)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_67;
}
MACHINE_RESET_MEMBER(decocass_type3_state,clapapa)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_34_7;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cskater)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_45;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cprobowl)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_34_0;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cnightst)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_13;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cpsoccer)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_24;
}
MACHINE_RESET_MEMBER(decocass_type3_state,csdtenis)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_23_56;
}
MACHINE_RESET_MEMBER(decocass_type3_state,czeroize)
{
uint8_t *mem = memregion("dongle")->base();
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_23_56;
/*
* FIXME: remove if the original ROM is available.
* The Zeroize 6502 code at 0x3707 issues LODCTRS with 0x8a,
* and expects to read 0x18 from 0x08a0 ff. within 7 bytes
* and 0xf7 from 0x8a1 (which 0xd is subtracted from presumably in order
* to form a NOP of 0xea).
* This hack seems to be sufficient to get around
* the missing dongle ROM contents and play the game.
*/
memset(mem, 0x00, 0x1000);
mem[0x08a0] = 0x18;
mem[0x08a1] = 0xf7;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cppicf)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_01;
}
MACHINE_RESET_MEMBER(decocass_type3_state,cfghtice)
{
machine_reset();
LOG(0,("dongle type #3 (PAL)\n"));
m_type3_swap = TYPE3_SWAP_25;
}
void decocass_widel_state::machine_start()
{
decocass_state::machine_start();
save_item(NAME(m_widel_ctrs));
save_item(NAME(m_widel_latch));
}
void decocass_widel_state::machine_reset()
{
decocass_state::machine_reset();
LOG(0,("Deco Multigame Dongle\n"));
m_dongle_r = read8_delegate(*this, FUNC(decocass_widel_state::decocass_widel_r));
m_dongle_w = write8_delegate(*this, FUNC(decocass_widel_state::decocass_widel_w));
m_widel_ctrs = 0;
m_widel_latch = 0;
}
/***************************************************************************
*
* 8041 port handlers
*
***************************************************************************/
WRITE8_MEMBER(decocass_state::i8041_p1_w)
{
if (data != m_i8041_p1_write_latch)
{
LOG(4,("%10s 8041-PC: %03x i8041_p1_w: $%02x (%s%s%s%s%s%s%s%s)\n",
machine().time().as_string(6),
m_maincpu->pcbase(),
data,
data & 0x01 ? "" : "DATA-WRT",
data & 0x02 ? "" : " DATA-CLK",
data & 0x04 ? "" : " FAST",
data & 0x08 ? "" : " BIT3",
data & 0x10 ? "" : " REW",
data & 0x20 ? "" : " FWD",
data & 0x40 ? "" : " WREN",
data & 0x80 ? "" : " REQ"));
m_i8041_p1_write_latch = data;
}
/* change in FAST/REW/FWD signals? */
if ((data ^ m_i8041_p1) & 0x34)
{
int newspeed = 0;
if ((data & 0x30) == 0x20)
newspeed = (data & 0x04) ? -1 : -7;
else if ((data & 0x30) == 0x10)
newspeed = (data & 0x04) ? 1 : 7;
m_cassette->change_speed(newspeed);
}
m_i8041_p1 = data;
}
READ8_MEMBER(decocass_state::i8041_p1_r)
{
uint8_t data = m_i8041_p1;
if (data != m_i8041_p1_read_latch)
{
LOG(4,("%10s 8041-PC: %03x i8041_p1_r: $%02x (%s%s%s%s%s%s%s%s)\n",
machine().time().as_string(6),
m_maincpu->pcbase(),
data,
data & 0x01 ? "" : "DATA-WRT",
data & 0x02 ? "" : " DATA-CLK",
data & 0x04 ? "" : " FAST",
data & 0x08 ? "" : " BIT3",
data & 0x10 ? "" : " REW",
data & 0x20 ? "" : " FWD",
data & 0x40 ? "" : " WREN",
data & 0x80 ? "" : " REQ"));
m_i8041_p1_read_latch = data;
}
return data;
}
WRITE8_MEMBER(decocass_state::i8041_p2_w)
{
if (data != m_i8041_p2_write_latch)
{
LOG(4,("%10s 8041-PC: %03x i8041_p2_w: $%02x (%s%s%s%s%s%s%s%s)\n",
machine().time().as_string(6),
m_maincpu->pcbase(),
data,
data & 0x01 ? "" : "FNO/",
data & 0x02 ? "" : " EOT/",
data & 0x04 ? "" : " ERR/",
data & 0x08 ? "" : " OUT3?/",
data & 0x10 ? " [IN4]" : "",
data & 0x20 ? " [BOT-EOT]" : "",
data & 0x40 ? " [RCLK]" : "",
data & 0x80 ? " [RDATA]" : ""));
m_i8041_p2_write_latch = data;
}
m_i8041_p2 = (m_i8041_p2 & 0xe0) | (data & ~0xe0);
}
READ8_MEMBER(decocass_state::i8041_p2_r)
{
uint8_t data;
data = (m_i8041_p2 & ~0xe0) | m_cassette->get_status_bits();
if (data != m_i8041_p2_read_latch)
{
LOG(4,("%10s 8041-PC: %03x i8041_p2_r: $%02x (%s%s%s%s%s%s%s%s)\n",
machine().time().as_string(6),
m_maincpu->pcbase(),
data,
data & 0x01 ? "" : "FNO/",
data & 0x02 ? "" : " EOT/",
data & 0x04 ? "" : " ERR/",
data & 0x08 ? "" : " OUT3?/",
data & 0x10 ? " [IN4]" : "",
data & 0x20 ? " [BOT-EOT]" : "",
data & 0x40 ? " [RCLK]" : "",
data & 0x80 ? " [RDATA]" : ""));
m_i8041_p2_read_latch = data;
}
return data;
}