summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/cchip.c
blob: 8424f33b711a896601fa29b45600f527fba1b317 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/***************************************************************************

   cchip.c

This file contains routines to interface with the Taito Controller Chip
(or "Command Chip") version 1. It's currently used by Superman and Mega
Blast. [Further cchip emulation is in machine/rainbow.c, machine/volfied.c,
drivers/opwolf.c]

According to Richard Bush, the C-Chip is an encrypted Z80 which communicates
with the main board as a protection feature.


Superman (revised SJ 060601)
--------

In Superman, the C-chip's main purpose is to handle player inputs and
coins and pass commands along to the sound chip.

The 68k queries the c-chip, which passes back $100 bytes of 68k code which
are then executed in RAM. To get around this, we hack in our own code to
communicate with the sound board, since we are familiar with the interface
as it's used in Rastan and Super Space Invaders '91.

It is believed that the NOPs in the 68k code are there to supply the
necessary cycles to the cchip to switch banks.

This code requires that the player & coin inputs be in input ports 2-4.


Mega Blast
----------

C-Chip simply used as RAM, the game doesn't even bother to change banks.
It does read the chip id though. The dump is confirmed to be from an
original board.

***************************************************************************/

#include "driver.h"
#include "includes/taito_f2.h"

static UINT16 current_bank = 0;

static UINT8 cc_port = 0;

/* This code for sound communication is a hack, it will not be
   identical to the code derived from the real c-chip */

static UINT8 superman_code[40] =
{
	0x48, 0xe7, 0x80, 0x80,	            /* MOVEM.L  D0/A0,-(A7)   ( Preserve Regs ) */
	0x20, 0x6d, 0x1c, 0x40,             /* MOVEA.L  ($1C40,A5),A0 ( Load sound pointer in A0 ) */
	0x30, 0x2f, 0x00, 0x0c,             /* MOVE.W   ($0C,A7),D0   ( Fetch sound number ) */
	0x10, 0x80,                         /* MOVE.B   D0,(A0)       ( Store it on sound pointer ) */
	0x52, 0x88,                         /* ADDQ.W   #1,A0         ( Increment sound pointer ) */
	0x20, 0x3c, 0x00, 0xf0, 0x1c, 0x40, /* MOVE.L   #$F01C40,D0   ( Load top of buffer in D0 ) */
	0xb1, 0xc0,                         /* CMPA.L   D0,A0         ( Are we there yet? ) */
	0x66, 0x04,                         /* BNE.S    *+$6          ( No, we arent, skip next line ) */
	0x41, 0xed, 0x1c, 0x20,             /* LEA      ($1C20,A5),A0 ( Point to the start of the buffer ) */
	0x2b, 0x48, 0x1c, 0x40,	            /* MOVE.L   A0,($1C40,A5) ( Store new sound pointer ) */
	0x4c, 0xdf, 0x01, 0x01,	            /* MOVEM.L  (A7)+, D0/A0  ( Restore Regs ) */
	0x4e, 0x75                          /* RTS                    ( Return ) */
};

MACHINE_RESET( cchip1 )
{
	state_save_register_global(current_bank);
	state_save_register_global(cc_port);
}

/*************************************
 *
 * Writes to C-Chip - Important Bits
 *
 *************************************/

WRITE16_HANDLER( cchip1_ctrl_w )
{
	/* value 2 is written here */
}

WRITE16_HANDLER( cchip1_bank_w )
{
	current_bank = data & 7;
}

WRITE16_HANDLER( cchip1_ram_w )
{
	if (current_bank == 0 && offset == 0x03)
	{
		cc_port = data;

		coin_lockout_w(1, data & 0x08);
		coin_lockout_w(0, data & 0x04);
		coin_counter_w(1, data & 0x02);
		coin_counter_w(0, data & 0x01);
	}
	else
	{
logerror("cchip1_w pc: %06x bank %02x offset %04x: %02x\n",activecpu_get_pc(),current_bank,offset,data);
	}
}


/*************************************
 *
 * Reads from C-Chip
 *
 *************************************/

READ16_HANDLER( cchip1_ctrl_r )
{
	/*
        Bit 2 = Error signal
        Bit 0 = Ready signal
    */
	return 0x01; /* Return 0x05 for C-Chip error */
}

READ16_HANDLER( cchip1_ram_r )
{
	/* Check for input ports */
	if (current_bank == 0)
	{
		switch (offset)
		{
		case 0x00: return readinputportbytag("IN0");    /* Player 1 controls + START1 */
		case 0x01: return readinputportbytag("IN1");    /* Player 2 controls + START2 */
		case 0x02: return readinputportbytag("IN2");    /* COINn + SERVICE1 + TILT */
		case 0x03: return cc_port;
		}
	}

	/* Other non-standard offsets */

	if (current_bank == 1 && offset <= 0xff)
	{
		if (offset < 40)	/* our hack code is only 40 bytes long */
			return superman_code[offset];
		else	/* so pad with zeros */
			return 0;
	}

	if (current_bank == 2)
	{
		switch (offset)
		{
			case 0x000: return 0x47;
			case 0x001: return 0x57;
			case 0x002: return 0x4b;
		}
	}

logerror("cchip1_r bank: %02x offset: %04x\n",current_bank,offset);
	return 0;
}


/* Mega Blast */

UINT16 *cchip2_ram;

WRITE16_HANDLER( cchip2_word_w )
{
    logerror("cchip2_w pc: %06x offset %04x: %02x\n", activecpu_get_pc(), offset, data);

    COMBINE_DATA(&cchip2_ram[offset]);
}

READ16_HANDLER( cchip2_word_r )
{
	/* C-Chip ID */

	if (offset == 0x401)
	{
		return 0x01;
	}

	logerror("cchip2_r offset: %04x\n", offset);

	return cchip2_ram[offset];
}