1 #include "driver.h"
2 #include "cpu/z80/z80.h"
3
4
5 /**********************************************************************************************
6
7 It seems like 1 nibble commands are only for control purposes.
8 2 nibble commands are the real messages passed from one board to the other.
9
10 **********************************************************************************************/
11
12 /* Some logging defines */
13 #if 0
14 #define REPORT_SLAVE_MODE_CHANGE
15 #define REPORT_SLAVE_MODE_READ_ITSELF
16 #define REPORT_MAIN_MODE_READ_SLAVE
17 #define REPORT_DATA_FLOW
18 #endif
19
20
21
22
23 #define TC0140SYT_PORT01_FULL (0x01)
24 #define TC0140SYT_PORT23_FULL (0x02)
25 #define TC0140SYT_PORT01_FULL_MASTER (0x04)
26 #define TC0140SYT_PORT23_FULL_MASTER (0x08)
27
28 typedef struct TC0140SYT
29 {
30 unsigned char slavedata[4]; /* Data on master->slave port (4 nibbles) */
31 unsigned char masterdata[4];/* Data on slave->master port (4 nibbles) */
32 unsigned char mainmode; /* Access mode on master cpu side */
33 unsigned char submode; /* Access mode on slave cpu side */
34 unsigned char status; /* Status data */
35 unsigned char nmi_enabled; /* 1 if slave cpu has nmi's enabled */
36 unsigned char nmi_req; /* 1 if slave cpu has a pending nmi */
37 } TC0140SYT;
38
39 static struct TC0140SYT tc0140syt;
40
41
Interrupt_Controller(void)42 static void Interrupt_Controller(void)
43 {
44 if ( tc0140syt.nmi_req && tc0140syt.nmi_enabled )
45 {
46 cpu_cause_interrupt( 1, Z80_NMI_INT );
47 tc0140syt.nmi_req = 0;
48 }
49 }
50
WRITE_HANDLER(taitosound_port_w)51 WRITE_HANDLER( taitosound_port_w )
52 {
53 data &= 0x0f;
54
55 tc0140syt.mainmode = data;
56 //logerror("taitosnd: Master cpu mode [%02x]\n", data);
57 /*if (data > 4)
58 {
59 logerror("tc0140syt : error Master entering unknown mode[%02x]\n", data);
60 }*/
61 }
62
WRITE_HANDLER(taitosound_comm_w)63 WRITE_HANDLER( taitosound_comm_w )
64 {
65
66 data &= 0x0f; /*this is important, otherwise ballbros won't work*/
67
68 switch( tc0140syt.mainmode )
69 {
70 case 0x00: // mode #0
71 tc0140syt.slavedata[tc0140syt.mainmode ++] = data;
72 //logerror("taitosnd: Master cpu written port 0, data %01x\n", data);
73 break;
74
75 case 0x01: // mode #1
76 tc0140syt.slavedata[tc0140syt.mainmode ++] = data;
77 tc0140syt.status |= TC0140SYT_PORT01_FULL;
78 tc0140syt.nmi_req = 1;
79 //logerror("taitosnd: Master cpu sends 0/1 : %01x%01x\n",tc0140syt.slavedata[1],tc0140syt.slavedata[0]);
80 break;
81
82 case 0x02: // mode #2
83 tc0140syt.slavedata[tc0140syt.mainmode ++] = data;
84 //logerror("taitosnd: Master cpu written port 2, data %01\n", data);
85 break;
86
87 case 0x03: // mode #3
88 tc0140syt.slavedata[tc0140syt.mainmode ++] = data;
89 tc0140syt.status |= TC0140SYT_PORT23_FULL;
90 tc0140syt.nmi_req = 1;
91 //logerror("taitosnd: Master cpu sends 2/3 : %01x%01x\n",tc0140syt.slavedata[3],tc0140syt.slavedata[2]);
92 break;
93
94 case 0x04: // port status
95 //#ifdef REPORT_DATA_FLOW
96 //logerror("taitosnd: Master issued control value %02x (PC = %08x) \n",data, cpu_get_pc() );
97 //#endif
98 /* this does a hi-lo transition to reset the sound cpu */
99 if (data)
100 cpu_set_reset_line(1,ASSERT_LINE);
101 else
102 {
103 cpu_set_reset_line(1,CLEAR_LINE);
104 cpu_spin(); /* otherwise no sound in driftout */
105 }
106 break;
107
108 default:
109 //logerror("taitosnd: Master cpu written in mode [%02x] data[%02x]\n",tc0140syt.mainmode, data);
110 break;
111 }
112
113 }
114
READ_HANDLER(taitosound_comm_r)115 READ_HANDLER( taitosound_comm_r )
116 {
117 switch( tc0140syt.mainmode )
118 {
119 case 0x00: // mode #0
120 //logerror("taitosnd: Master cpu read portdata %01x\n", tc0140syt.masterdata[0]);
121 return tc0140syt.masterdata[tc0140syt.mainmode ++];
122 break;
123
124 case 0x01: // mode #1
125 //logerror("taitosnd: Master cpu receives 0/1 : %01x%01x\n", tc0140syt.masterdata[1],tc0140syt.masterdata[0]);
126 tc0140syt.status &= ~TC0140SYT_PORT01_FULL_MASTER;
127 return tc0140syt.masterdata[tc0140syt.mainmode ++];
128 break;
129
130 case 0x02: // mode #2
131 //logerror("taitosnd: Master cpu read masterdata %01x\n", tc0140syt.masterdata[2]);
132 return tc0140syt.masterdata[tc0140syt.mainmode ++];
133 break;
134
135 case 0x03: // mode #3
136 //logerror("taitosnd: Master cpu receives 2/3 : %01x%01x\n", tc0140syt.masterdata[3],tc0140syt.masterdata[2]);
137 tc0140syt.status &= ~TC0140SYT_PORT23_FULL_MASTER;
138 return tc0140syt.masterdata[tc0140syt.mainmode ++];
139 break;
140
141 case 0x04: // port status
142 //logerror("tc0140syt : Master cpu read status : %02x\n", tc0140syt.status);
143 return tc0140syt.status;
144 break;
145
146 default:
147 //logerror("tc0140syt : Master cpu read in mode [%02x]\n", tc0140syt.mainmode);
148 return 0;
149 }
150 }
151
152 //SLAVE SIDE
153
WRITE_HANDLER(taitosound_slave_port_w)154 WRITE_HANDLER( taitosound_slave_port_w )
155 {
156 data &= 0x0f;
157 tc0140syt.submode = data;
158 //logerror("taitosnd: Slave cpu mode [%02x]\n", data);
159 /*if (data > 6)
160 logerror("tc0140syt error : Slave cpu unknown mode[%02x]\n", data);*/
161 }
162
WRITE_HANDLER(taitosound_slave_comm_w)163 WRITE_HANDLER( taitosound_slave_comm_w )
164 {
165 data &= 0x0f;
166
167 switch ( tc0140syt.submode )
168 {
169 case 0x00: // mode #0
170 tc0140syt.masterdata[tc0140syt.submode ++] = data;
171 //logerror("taitosnd: Slave cpu written port 0, data %01x\n", data);
172 break;
173
174 case 0x01: // mode #1
175 tc0140syt.masterdata[tc0140syt.submode ++] = data;
176 tc0140syt.status |= TC0140SYT_PORT01_FULL_MASTER;
177 //logerror("taitosnd: Slave cpu sends 0/1 : %01x%01x\n",tc0140syt.masterdata[1],tc0140syt.masterdata[0]);
178 cpu_spin(); /* writing should take longer than emulated, so spin */
179 break;
180
181 case 0x02: // mode #2
182 //logerror("taitosnd: Slave cpu written port 2, data %01x\n", data);
183 tc0140syt.masterdata[tc0140syt.submode ++] = data;
184 break;
185
186 case 0x03: // mode #3
187 tc0140syt.masterdata[tc0140syt.submode ++] = data;
188 tc0140syt.status |= TC0140SYT_PORT23_FULL_MASTER;
189 //logerror("taitosnd: Slave cpu sends 2/3 : %01x%01x\n",tc0140syt.masterdata[3],tc0140syt.masterdata[2]);
190 cpu_spin(); /* writing should take longer than emulated, so spin */
191 break;
192
193 case 0x04: // port status
194 //tc0140syt.status = TC0140SYT_SET_OK;
195 //logerror("tc0140syt : Slave cpu status ok.\n");
196 break;
197
198 case 0x05: // nmi disable
199 tc0140syt.nmi_enabled = 0;
200 break;
201
202 case 0x06: // nmi enable
203 tc0140syt.nmi_enabled = 1;
204 break;
205
206 default:
207 //logerror("tc0140syt: Slave cpu written in mode [%02x] data[%02x]\n",tc0140syt.submode, data & 0xff);
208 break;
209 }
210
211 Interrupt_Controller();
212
213 }
214
READ_HANDLER(taitosound_slave_comm_r)215 READ_HANDLER( taitosound_slave_comm_r )
216 {
217 unsigned char res = 0;
218
219 switch ( tc0140syt.submode )
220 {
221 case 0x00: // mode #0
222 //logerror("taitosnd: Slave cpu read slavedata %01x\n", tc0140syt.slavedata[0]);
223 res = tc0140syt.slavedata[tc0140syt.submode ++];
224 break;
225
226 case 0x01: // mode #1
227 //logerror("taitosnd: Slave cpu receives 0/1 : %01x%01x PC=%4x\n", tc0140syt.slavedata[1],tc0140syt.slavedata[0],cpu_get_pc());
228 tc0140syt.status &= ~TC0140SYT_PORT01_FULL;
229 res = tc0140syt.slavedata[tc0140syt.submode ++];
230 break;
231
232 case 0x02: // mode #2
233 //logerror("taitosnd: Slave cpu read slavedata %01x\n", tc0140syt.slavedata[2]);
234 res = tc0140syt.slavedata[tc0140syt.submode ++];
235 break;
236
237 case 0x03: // mode #3
238 //logerror("taitosnd: Slave cpu receives 2/3 : %01x%01x\n", tc0140syt.slavedata[3],tc0140syt.slavedata[2]);
239 tc0140syt.status &= ~TC0140SYT_PORT23_FULL;
240 res = tc0140syt.slavedata[tc0140syt.submode ++];
241 break;
242
243 case 0x04: // port status
244 //logerror("tc0140syt : Slave cpu read status : %02x\n", tc0140syt.status);
245 res = tc0140syt.status;
246 break;
247
248 default:
249 //logerror("tc0140syt : Slave cpu read in mode [%02x]\n", tc0140syt.submode);
250 res = 0;
251 break;
252 }
253
254 Interrupt_Controller();
255
256 return res;
257 }
258
259
260
261
262
263
264 #if 0
265 /* wrapper functions for 16bit handlers */
266
267 WRITE16_HANDLER( taitosound_port16_lsb_w )
268 {
269 if (ACCESSING_LSB)
270 taitosound_port_w(0,data & 0xff);
271 }
272 WRITE16_HANDLER( taitosound_comm16_lsb_w )
273 {
274 if (ACCESSING_LSB)
275 taitosound_comm_w(0,data & 0xff);
276 }
277 READ16_HANDLER( taitosound_comm16_lsb_r )
278 {
279 return taitosound_comm_r(0);
280 }
281
282
283 WRITE16_HANDLER( taitosound_port16_msb_w )
284 {
285 if (ACCESSING_MSB)
286 taitosound_port_w(0,data >> 8);
287 }
288 WRITE16_HANDLER( taitosound_comm16_msb_w )
289 {
290 if (ACCESSING_MSB)
291 taitosound_comm_w(0,data >> 8);
292 }
293 READ16_HANDLER( taitosound_comm16_msb_r )
294 {
295 return taitosound_comm_r(0) << 8;
296 }
297 #endif
298