1 /****************************************************************************
2  *	Twin Cobra																*
3  *	Communications and memory functions between shared CPU memory spaces	*
4  ****************************************************************************/
5 
6 #include "driver.h"
7 #include "cpu/tms32010/tms32010.h"
8 
9 #define LOG_DSP_CALLS 0
10 #define CLEAR 0
11 #define ASSERT 1
12 
13 
14 
15 unsigned char *twincobr_68k_dsp_ram;
16 unsigned char *twincobr_sharedram;
17 unsigned char *wardner_mainram;
18 
19 extern unsigned char *spriteram;
20 extern unsigned char *paletteram;
21 
22 
23 extern int twincobr_fg_rom_bank;
24 extern int twincobr_bg_ram_bank;
25 extern int twincobr_display_on;
26 extern int twincobr_flip_screen;
27 extern int twincobr_flip_x_base;
28 extern int twincobr_flip_y_base;
29 extern int wardner_sprite_hack;
30 
31 static int coin_count;	/* coin count increments on startup ? , so stop it */
32 static int dsp_execute;
33 static unsigned int dsp_addr_w, main_ram_seg;
34 int toaplan_main_cpu;   /* Main CPU type.  0 = 68000, 1 = Z80 */
35 #if LOG_DSP_CALLS
36 static char *toaplan_cpu_type[2] = { "68K" , "Z80" };
37 #endif
38 
39 int twincobr_intenable;
40 int fsharkbt_8741;
41 
42 
fsharkbt_reset_8741_mcu(void)43 void fsharkbt_reset_8741_mcu(void)
44 {
45 	/* clean out high score tables in these game hardware */
46 	int twincobr_cnt;
47 	int twinc_hisc_addr[12] =
48 	{
49 		0x15a4, 0x15a8, 0x170a, 0x170c, /* Twin Cobra */
50 		0x1282, 0x1284, 0x13ea, 0x13ec, /* Kyukyo Tiger */
51 		0x016c, 0x0170, 0x02d2, 0x02d4	/* Flying shark */
52 	};
53 	for (twincobr_cnt=0; twincobr_cnt < 12; twincobr_cnt++)
54 	{
55 		WRITE_WORD(&twincobr_68k_dsp_ram[(twinc_hisc_addr[twincobr_cnt])],0xffff);
56 	}
57 
58 	toaplan_main_cpu = 0;		/* 68000 */
59 	twincobr_display_on = 0;
60 	fsharkbt_8741 = -1;
61 	twincobr_intenable = 0;
62 	dsp_addr_w = dsp_execute = 0;
63 	main_ram_seg = 0;
64 
65 	/* coin count increments on startup ? , so stop it */
66 	coin_count = 0;
67 
68 	/* blank out the screen */
69 	osd_clearbitmap(Machine->scrbitmap);
70 }
71 
wardner_reset(void)72 void wardner_reset(void)
73 {
74 	/* clean out high score tables in these game hardware */
75 	wardner_mainram[0x0117] = 0xff;
76 	wardner_mainram[0x0118] = 0xff;
77 	wardner_mainram[0x0119] = 0xff;
78 	wardner_mainram[0x011a] = 0xff;
79 	wardner_mainram[0x011b] = 0xff;
80 	wardner_mainram[0x0170] = 0xff;
81 	wardner_mainram[0x0171] = 0xff;
82 	wardner_mainram[0x0172] = 0xff;
83 
84 	toaplan_main_cpu = 1;		/* Z80 */
85 	twincobr_intenable = 0;
86 	twincobr_display_on = 1;
87 	dsp_addr_w = dsp_execute = 0;
88 	main_ram_seg = 0;
89 
90 	/* coin count increments on startup ? , so stop it */
91 	coin_count = 0;
92 
93 	/* blank out the screen */
94 	osd_clearbitmap(Machine->scrbitmap);
95 }
96 
97 
READ_HANDLER(twincobr_dsp_r)98 READ_HANDLER( twincobr_dsp_r )
99 {
100 	/* DSP can read data from main CPU RAM via DSP IO port 1 */
101 
102 	unsigned int input_data = 0;
103 	switch (main_ram_seg) {
104 		case 0x30000:	input_data = READ_WORD(&twincobr_68k_dsp_ram[dsp_addr_w]); break;
105 		case 0x40000:	input_data = READ_WORD(&spriteram[dsp_addr_w]); break;
106 		case 0x50000:	input_data = READ_WORD(&paletteram[dsp_addr_w]); break;
107 		case 0x7000:	input_data = wardner_mainram[dsp_addr_w] + (wardner_mainram[dsp_addr_w+1]<<8); break;
108 		case 0x8000:	input_data = spriteram[dsp_addr_w] + (spriteram[dsp_addr_w+1]<<8); break;
109 		case 0xa000:	input_data = paletteram[dsp_addr_w] + (paletteram[dsp_addr_w+1]<<8); break;
110 		default:		//logerror("DSP PC:%04x Warning !!! IO reading from %08x (port 1)\n",cpu_getpreviouspc(),main_ram_seg + dsp_addr_w);
111 		    break;
112 	}
113 #if LOG_DSP_CALLS
114 	logerror("DSP PC:%04x IO read %04x at %08x (port 1)\n",cpu_getpreviouspc(),input_data,main_ram_seg + dsp_addr_w);
115 #endif
116 	return input_data;
117 }
118 
READ_HANDLER(fsharkbt_dsp_r)119 READ_HANDLER( fsharkbt_dsp_r )
120 {
121 	/* Flying Shark bootleg uses IO port 2 */
122 	/* DSP reads data from an extra MCU (8741) at IO port 2 */
123 	/* Boot-leggers using their own copy protection ?? */
124 	/* Port is read three times during startup. First and last data */
125 	/*	 read must equal, but second read data must be different */
126 	fsharkbt_8741 += 1;
127 #if LOG_DSP_CALLS
128 	logerror("DSP PC:%04x IO read %04x from 8741 MCU (port 2)\n",cpu_getpreviouspc(),(fsharkbt_8741 & 0x08));
129 #endif
130 	return (fsharkbt_8741 & 1);
131 }
132 
WRITE_HANDLER(twincobr_dsp_w)133 WRITE_HANDLER( twincobr_dsp_w )
134 {
135 	if (offset == 0) {
136 		/* This sets the main CPU RAM address the DSP should */
137 		/*		read/write, via the DSP IO port 0 */
138 		/* Top three bits of data need to be shifted left 3 places */
139 		/*		to select which memory bank from main CPU address */
140 		/*		space to use */
141 		/* Lower thirteen bits of this data is shifted left one position */
142 		/*		to move it to an even address word boundary */
143 
144 		dsp_addr_w = ((data & 0x1fff) << 1);
145 		main_ram_seg = ((data & 0xe000) << 3);
146 		if (toaplan_main_cpu == 1) {		/* Z80 */
147 			dsp_addr_w &= 0xfff;
148 			if (main_ram_seg == 0x30000) main_ram_seg = 0x7000;
149 			if (main_ram_seg == 0x40000) main_ram_seg = 0x8000;
150 			if (main_ram_seg == 0x50000) main_ram_seg = 0xa000;
151 		}
152 #if LOG_DSP_CALLS
153 		logerror("DSP PC:%04x IO write %04x (%08x) at port 0\n",cpu_getpreviouspc(),data,main_ram_seg + dsp_addr_w);
154 #endif
155 	}
156 	if (offset == 1) {
157 		/* Data written to main CPU RAM via DSP IO port 1*/
158 		dsp_execute = 0;
159 		switch (main_ram_seg) {
160 			case 0x30000:	WRITE_WORD(&twincobr_68k_dsp_ram[dsp_addr_w],data);
161 								if ((dsp_addr_w < 3) && (data == 0)) dsp_execute = 1; break;
162 			case 0x40000:	WRITE_WORD(&spriteram[dsp_addr_w],data); break;
163 			case 0x50000:	WRITE_WORD(&paletteram[dsp_addr_w],data); break;
164 			case 0x7000:	wardner_mainram[dsp_addr_w] = data & 0xff;
165 							wardner_mainram[dsp_addr_w + 1] = (data >> 8) & 0xff;
166 							if ((dsp_addr_w < 3) && (data == 0)) dsp_execute = 1; break;
167 			case 0x8000:	spriteram[dsp_addr_w] = data & 0xff;
168 							spriteram[dsp_addr_w + 1] = (data >> 8) & 0xff;break;
169 			case 0xa000:	paletteram[dsp_addr_w] = data & 0xff;
170 							paletteram[dsp_addr_w + 1] = (data >> 8) & 0xff; break;
171 			default:		//logerror("DSP PC:%04x Warning !!! IO writing to %08x (port 1)\n",cpu_getpreviouspc(),main_ram_seg + dsp_addr_w);
172 			    break;
173 		}
174 #if LOG_DSP_CALLS
175 		logerror("DSP PC:%04x IO write %04x at %08x (port 1)\n",cpu_getpreviouspc(),data,main_ram_seg + dsp_addr_w);
176 #endif
177 	}
178 	if (offset == 2) {
179 		/* Flying Shark bootleg DSP writes data to an extra MCU (8741) at IO port 2 */
180 #if 0
181 		logerror("DSP PC:%04x IO write from DSP RAM:%04x to 8741 MCU (port 2)\n",cpu_getpreviouspc(),fsharkbt_8741);
182 #endif
183 	}
184 	if (offset == 3) {
185 		/* data 0xffff	means inhibit BIO line to DSP and enable  */
186 		/*				communication to main processor */
187 		/*				Actually only DSP data bit 15 controls this */
188 		/* data 0x0000	means set DSP BIO line active and disable */
189 		/*				communication to main processor*/
190 #if LOG_DSP_CALLS
191 		logerror("DSP PC:%04x IO write %04x at port 3\n",cpu_getpreviouspc(),data);
192 #endif
193 		if (data & 0x8000) {
194 			cpu_set_irq_line(2, TMS320C10_ACTIVE_BIO, CLEAR_LINE);
195 		}
196 		if (data == 0) {
197 			if (dsp_execute) {
198 #if LOG_DSP_CALLS
199 				logerror("Turning %s on\n",toaplan_cpu_type[toaplan_main_cpu]);
200 #endif
201 				timer_suspendcpu(0, CLEAR, SUSPEND_REASON_HALT);
202 				dsp_execute = 0;
203 			}
204 			cpu_set_irq_line(2, TMS320C10_ACTIVE_BIO, ASSERT_LINE);
205 		}
206 	}
207 }
208 
READ_HANDLER(twincobr_68k_dsp_r)209 READ_HANDLER( twincobr_68k_dsp_r )
210 {
211 	return READ_WORD(&twincobr_68k_dsp_ram[offset]);
212 }
213 
WRITE_HANDLER(twincobr_68k_dsp_w)214 WRITE_HANDLER( twincobr_68k_dsp_w )
215 {
216 #if LOG_DSP_CALLS
217 	if (offset < 10) logerror("%s:%08x write %08x at %08x\n",toaplan_cpu_type[toaplan_main_cpu],cpu_get_pc(),data,0x30000+offset);
218 #endif
219 	COMBINE_WORD_MEM(&twincobr_68k_dsp_ram[offset],data);
220 }
221 
222 
WRITE_HANDLER(wardner_mainram_w)223 WRITE_HANDLER( wardner_mainram_w )
224 {
225 #if 0
226 	if ((offset == 4) && (data != 4)) logerror("CPU #0:%04x  Writing %02x to %04x of main RAM (DSP command number)\n",cpu_get_pc(),data, offset + 0x7000);
227 #endif
228 	wardner_mainram[offset] = data;
229 
230 }
READ_HANDLER(wardner_mainram_r)231 READ_HANDLER( wardner_mainram_r )
232 {
233 	return wardner_mainram[offset];
234 }
235 
236 
WRITE_HANDLER(twincobr_7800c_w)237 WRITE_HANDLER( twincobr_7800c_w )
238 {
239 #if 0
240 	logerror("%s:%08x  Writing %08x to %08x.\n",toaplan_cpu_type[toaplan_main_cpu],cpu_get_pc(),data,toaplan_port_type[toaplan_main_cpu] - offset);
241 #endif
242 
243 	if (toaplan_main_cpu == 1) {
244 		if (data == 0x0c) { data = 0x1c; wardner_sprite_hack=0; }	/* Z80 ? */
245 		if (data == 0x0d) { data = 0x1d; wardner_sprite_hack=1; }	/* Z80 ? */
246 	}
247 
248 	switch (data) {
249 		case 0x0004: twincobr_intenable = 0; break;
250 		case 0x0005: twincobr_intenable = 1; break;
251 		case 0x0006: twincobr_flip_screen = 0; twincobr_flip_x_base=0x037; twincobr_flip_y_base=0x01e; break;
252 		case 0x0007: twincobr_flip_screen = 1; twincobr_flip_x_base=0x085; twincobr_flip_y_base=0x0f2; break;
253 		case 0x0008: twincobr_bg_ram_bank = 0x0000; break;
254 		case 0x0009: twincobr_bg_ram_bank = 0x2000; break;
255 		case 0x000a: twincobr_fg_rom_bank = 0x0000; break;
256 		case 0x000b: twincobr_fg_rom_bank = 0x1000; break;
257 		case 0x000e: twincobr_display_on  = 0x0000; break; /* Turn display off */
258 		case 0x000f: twincobr_display_on  = 0x0001; break; /* Turn display on */
259 		case 0x000c: if (twincobr_display_on) {
260 						/* This means assert the INT line to the DSP */
261 #if LOG_DSP_CALLS
262 						logerror("Turning DSP on and %s off\n",toaplan_cpu_type[toaplan_main_cpu]);
263 #endif
264 						timer_suspendcpu(2, CLEAR, SUSPEND_REASON_HALT);
265 						cpu_set_irq_line(2, TMS320C10_ACTIVE_INT, ASSERT_LINE);
266 						timer_suspendcpu(0, ASSERT, SUSPEND_REASON_HALT);
267 					} break;
268 		case 0x000d: if (twincobr_display_on) {
269 						/* This means inhibit the INT line to the DSP */
270 #if LOG_DSP_CALLS
271 						logerror("Turning DSP off\n");
272 #endif
273 						cpu_set_irq_line(2, TMS320C10_ACTIVE_INT, CLEAR_LINE);
274 						timer_suspendcpu(2, ASSERT, SUSPEND_REASON_HALT);
275 					} break;
276 	}
277 }
278 
279 
280 
READ_HANDLER(twincobr_sharedram_r)281 READ_HANDLER( twincobr_sharedram_r )
282 {
283 	return twincobr_sharedram[offset / 2];
284 }
285 
WRITE_HANDLER(twincobr_sharedram_w)286 WRITE_HANDLER( twincobr_sharedram_w )
287 {
288 	twincobr_sharedram[offset / 2] = data;
289 }
290 
WRITE_HANDLER(fshark_coin_dsp_w)291 WRITE_HANDLER( fshark_coin_dsp_w )
292 {
293 #if 0
294 	if (data > 1)
295 		logerror("%s:%08x  Writing %08x to %08x.\n",toaplan_cpu_type[toaplan_main_cpu],cpu_get_pc(),data,toaplan_port_type[toaplan_main_cpu] - offset);
296 #endif
297 	switch (data) {
298 		case 0x08: if (coin_count) { coin_counter_w(0,1); coin_counter_w(0,0); } break;
299 		case 0x09: if (coin_count) { coin_counter_w(2,1); coin_counter_w(2,0); } break;
300 		case 0x0a: if (coin_count) { coin_counter_w(1,1); coin_counter_w(1,0); } break;
301 		case 0x0b: if (coin_count) { coin_counter_w(3,1); coin_counter_w(3,0); } break;
302 		case 0x0c: coin_lockout_w(0,1); coin_lockout_w(2,1); break;
303 		case 0x0d: coin_lockout_w(0,0); coin_lockout_w(2,0); break;
304 		case 0x0e: coin_lockout_w(1,1); coin_lockout_w(3,1); break;
305 		case 0x0f: coin_lockout_w(1,0); coin_lockout_w(3,0); coin_count=1; break;
306 		case 0x00:	/* This means assert the INT line to the DSP */
307 #if LOG_DSP_CALLS
308 					logerror("Turning DSP on and %s off\n",toaplan_cpu_type[toaplan_main_cpu]);
309 #endif
310 					timer_suspendcpu(2, CLEAR, SUSPEND_REASON_HALT);
311 					cpu_set_irq_line(2, TMS320C10_ACTIVE_INT, ASSERT_LINE);
312 					timer_suspendcpu(0, ASSERT, SUSPEND_REASON_HALT);
313 					break;
314 		case 0x01:	/* This means inhibit the INT line to the DSP */
315 #if LOG_DSP_CALLS
316 					logerror("Turning DSP off\n");
317 #endif
318 					cpu_set_irq_line(2, TMS320C10_ACTIVE_INT, CLEAR_LINE);
319 					timer_suspendcpu(2, ASSERT, SUSPEND_REASON_HALT);
320 					break;
321 	}
322 }
323