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