1 /***************************************************************************
2
3 -= Psikyo Games =-
4
5 driver by Luca Elia (l.elia@tin.it)
6
7
8 CPU: 68EC020 + PIC16C57 [Optional MCU]
9
10 Sound: Z80A + YM2610
11 Or: LZ8420M (Z80 core) + YMF286-K (YM2610 compatible)
12
13 Chips: PS2001B
14 PS3103
15 PS3204
16 PS3305
17
18 ---------------------------------------------------------------------------
19 Name Year Board Notes
20 ---------------------------------------------------------------------------
21 Sengoku Ace (J) 1993 SH201B
22 Gun Bird (J) 1994 KA302C
23 Battle K-Road (J) 1994 ""
24 Strikers 1945 (J) 1995 SH403/SH404 SH403 is similiar to KA302C
25 Tengai (J) 1996 SH404 SH404 has MCU, ymf278-b for sound and gfx banking
26 ---------------------------------------------------------------------------
27
28 To Do:
29
30 - Flip Screen support
31
32 ***************************************************************************/
33
34 /***** Gun Bird Japan Crash Notes
35
36 The Following Section of Code in Gunbird causes reads from the
37 0x080000 - 0x0fffff region
38
39 002894: E2817000 asr.l #1, D1
40 002896: 70001030 moveq #$0, D0
41 002898: 10301804 move.b ($4,A0,D1.l), D0 <-- *
42 00289C: 60183202 bra 28b6
43 00289E: 3202C2C7 move.w D2, D1
44 0028A0: C2C77000 mulu.w D7, D1
45 0028A2: 70003005 moveq #$0, D0
46 0028A4: 3005D280 move.w D5, D0
47 0028A6: D280E281 add.l D0, D1
48 0028A8: E2812071 asr.l #1, D1
49 0028AA: 20713515 movea.l ([A1],D3.w*4), A0
50 0028AE: 70001030 moveq #$0, D0
51 0028B0: 10301804 move.b ($4,A0,D1.l), D0 <-- *
52 0028B4: E880720F asr.l #4, D0
53 0028B6: 720FC041 moveq #$f, D1
54
55 This causes Gunbird to crash if the ROM Region Size
56 allocated during loading is smaller than the SMH_ROM
57 region as it trys to read beyond the allocated rom region
58
59 This was pointed out by Bart Puype
60
61 *****/
62
63 #include
"driver.h"
64 #include
"sound/2610intf.h"
65 #include
"sound/ymf278b.h"
66
67
68 /* Variables defined in video */
69
70 extern UINT32 *psikyo_vram_0, *psikyo_vram_1, *psikyo_vregs;
71 extern
int psikyo_ka302c_banking;
72
73 /* Functions defined in video */
74
75 WRITE32_HANDLER( psikyo_vram_0_w );
76 WRITE32_HANDLER( psikyo_vram_1_w );
77
78 VIDEO_START( psikyo );
79 VIDEO_EOF( psikyo );
80 VIDEO_UPDATE( psikyo );
81
82 extern
void psikyo_switch_banks( int tmap, int bank );
83
84 /* Variables only used here */
85
86 static UINT8 psikyo_soundlatch;
87 static
int z80_nmi, mcu_status;
88
89 static MACHINE_RESET( psikyo )
90 {
91 z80_nmi = mcu_status = 0;
92 }
93
94
95 /***************************************************************************
96
97
98 Main CPU
99
100
101 ***************************************************************************/
102
103 static
int psikyo_readcoinport(running_machine *machine, int has_mcu)
104 {
105 int ret = input_port_read(machine, "COIN") & ~0x84;
106
107 if (has_mcu)
108 {
109 /* Don't know exactly what this bit is, but s1945 and tengai
110 both spin waiting for it to go low during POST. Also,
111 the following code in tengai (don't know where or if it is
112 reached) waits for it to pulse:
113
114 01A546: move.b (A2), D0 ; A2 = $c00003
115 01A548: andi.b #$4, D0
116 01A54C: beq $1a546
117 01A54E: move.b (A2), D0
118 01A550: andi.b #$4, D0
119 01A554: bne $1a54e
120
121 Interestingly, s1945jn has the code that spins on this bit,
122 but said code is never reached. Prototype? */
123 if (mcu_status) ret |= 0x04;
124 mcu_status = !mcu_status; /* hack */
125 }
126
127 if (z80_nmi)
128 {
129 ret |= 0x80;
130
131 /* main CPU might be waiting for sound CPU to finish NMI,
132 so set a timer to give sound CPU a chance to run */
133 timer_call_after_resynch(NULL, 0, NULL);
134 // logerror("PC %06X - Read coin port during Z80 NMI\n", activecpu_get_pc());
135 }
136
137 return ret;
138 }
139
140 static READ32_HANDLER( sngkace_input_r )
141 {
142 switch(offset)
143 {
144 case 0x0: return (input_port_read(machine, "IN0") << 16) | 0xffff;
145 case 0x1: return (input_port_read(machine, "DSW1") << 16) | input_port_read(machine, "DSW3");
146 case 0x2: return (psikyo_readcoinport(machine, 0) << 16) | input_port_read(machine, "DSW2");
147 default: logerror("PC %06X - Read input %02X !\n", activecpu_get_pc(), offset * 2);
148 return 0;
149 }
150 }
151
152 static READ32_HANDLER( gunbird_input_r )
153 {
154 switch(offset)
155 {
156 case 0x0: return (input_port_read(machine, "IN0") << 16) | psikyo_readcoinport(machine, 0);
157 case 0x1: return (input_port_read(machine, "DSW1") << 16) | input_port_read(machine, "DSW2");
158 default: logerror("PC %06X - Read input %02X !\n", activecpu_get_pc(), offset*2);
159 return 0;
160 }
161 }
162
163
164 static TIMER_CALLBACK( psikyo_soundlatch_callback )
165 {
166 psikyo_soundlatch = param;
167 cpunum_set_input_line(machine, 1, INPUT_LINE_NMI, ASSERT_LINE);
168 z80_nmi = 1;
169 }
170
171 static WRITE32_HANDLER( psikyo_soundlatch_w )
172 {
173 if (ACCESSING_BITS_0_7)
174 timer_call_after_resynch(NULL, data & 0xff, psikyo_soundlatch_callback);
175 }
176
177 /***************************************************************************
178 Strikers 1945 / Tengai
179 ***************************************************************************/
180
181 static WRITE32_HANDLER( s1945_soundlatch_w )
182 {
183 if (ACCESSING_BITS_16_23)
184 timer_call_after_resynch(NULL, (data >> 16) & 0xff, psikyo_soundlatch_callback);
185 }
186
187 static
const UINT8 s1945_table[256] = {
188 0x00, 0x00, 0x64, 0xae, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc,
189 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc5, 0x1e,
190 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xac, 0x5c, 0x00, 0x00, 0x2b, 0xc0
191 };
192
193 static
const UINT8 s1945a_table[256] = {
194 0x00, 0x00, 0x64, 0xbe, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc,
195 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc7, 0x2a,
196 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xad, 0x4c, 0x00, 0x00, 0x2b, 0xc0
197 };
198
199 static
const UINT8 s1945j_table[256] = {
200 0x00, 0x00, 0x64, 0xb6, 0x00, 0x00, 0x26, 0x2c, 0x00, 0x00, 0x2c, 0xda, 0x00, 0x00, 0x2c, 0xbc,
201 0x00, 0x00, 0x2c, 0x9e, 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0xc5, 0x92,
202 0x00, 0x00, 0x32, 0x90, 0x00, 0x00, 0xac, 0x64, 0x00, 0x00, 0x2b, 0xc0
203 };
204
205 static UINT8 s1945_mcu_direction, s1945_mcu_latch1, s1945_mcu_latch2, s1945_mcu_inlatch, s1945_mcu_index;
206 static UINT8 s1945_mcu_latching, s1945_mcu_mode, s1945_mcu_direction, s1945_mcu_control, s1945_mcu_bctrl;
207 static
const UINT8 *s1945_mcu_table;
208
209 static
void s1945_mcu_init(const UINT8 *mcu_table)
210 {
211 s1945_mcu_direction = 0x00;
212 s1945_mcu_inlatch = 0xff;
213 s1945_mcu_latch1 = 0xff;
214 s1945_mcu_latch2 = 0xff;
215 s1945_mcu_latching = 0x5;
216 s1945_mcu_control = 0xff;
217 s1945_mcu_index = 0;
218 s1945_mcu_mode = 0;
219 s1945_mcu_table = mcu_table;
220 s1945_mcu_bctrl = 0x00;
221 }
222
223 static WRITE32_HANDLER( s1945_mcu_w )
224 {
225 // Accesses are always bytes, so resolve it
226 int suboff;
227 for(suboff=0; suboff < 3; suboff++)
228 if((0xff << (8*suboff)) & mem_mask)
229 break;
230 data >>= 8*suboff;
231 offset = offset*4+4+(3-suboff);
232
233 switch(offset) {
234 case 0x06:
235 s1945_mcu_inlatch = data;
236 break;
237 case 0x08:
238 s1945_mcu_control = data;
239 break;
240 case 0x09:
241 s1945_mcu_direction = data;
242 break;
243 case 0x07:
244 psikyo_switch_banks(1, (data >> 6) & 3);
245 psikyo_switch_banks(0, (data >> 4) & 3);
246 s1945_mcu_bctrl = data;
247 break;
248 case 0x0b:
249 switch(data | (s1945_mcu_direction ? 0x100 : 0)) {
250 case 0x11c:
251 s1945_mcu_latching = 5;
252 s1945_mcu_index = s1945_mcu_inlatch;
253 break;
254 case 0x013:
255 // logerror("MCU: Table read index %02x\n", s1945_mcu_index);
256 s1945_mcu_latching = 1;
257 s1945_mcu_latch1 = s1945_mcu_table[s1945_mcu_index];
258 break;
259 case 0x113:
260 s1945_mcu_mode = s1945_mcu_inlatch;
261 if(s1945_mcu_mode == 1) {
262 s1945_mcu_latching &= ~1;
263 s1945_mcu_latch2 = 0x55;
264 } else {
265 // Go figure.
266 s1945_mcu_latching &= ~1;
267 s1945_mcu_latching |= 2;
268 }
269 s1945_mcu_latching &= ~4;
270 s1945_mcu_latch1 = s1945_mcu_inlatch;
271 break;
272 case 0x010:
273 case 0x110:
274 s1945_mcu_latching |= 4;
275 break;
276 default:
277 // logerror("MCU: function %02x, direction %02x, latch1 %02x, latch2 %02x (%x)\n", data, s1945_mcu_direction, s1945_mcu_latch1, s1945_mcu_latch2, activecpu_get_pc());
278 break;
279 }
280 break;
281 default:
282 // logerror("MCU.w %x, %02x (%x)\n", offset, data, activecpu_get_pc());
283 ;
284 }
285 }
286
287 static READ32_HANDLER( s1945_mcu_r )
288 {
289 switch(offset) {
290 case 0: {
291 UINT32 res;
292 if(s1945_mcu_control & 16) {
293 res = s1945_mcu_latching & 4 ? 0x0000ff00 : s1945_mcu_latch1 << 8;
294 s1945_mcu_latching |= 4;
295 } else {
296 res = s1945_mcu_latching & 1 ? 0x0000ff00 : s1945_mcu_latch2 << 8;
297 s1945_mcu_latching |= 1;
298 }
299 res |= s1945_mcu_bctrl & 0xf0;
300 return res;
301 }
302 case 1:
303 return (s1945_mcu_latching << 24) | 0x08000000;
304 }
305 return 0;
306 }
307
308 static READ32_HANDLER( s1945_input_r )
309 {
310 switch(offset)
311 {
312 case 0x0: return (input_port_read(machine, "IN0") << 16) | psikyo_readcoinport(machine, 1);
313 case 0x1: return (((input_port_read(machine, "DSW1") << 16) | input_port_read(machine, "DSW2")) & 0xffff000f) | s1945_mcu_r(machine, offset-1, mem_mask);
314 case 0x2: return s1945_mcu_r(machine, offset-1, mem_mask);
315 default: logerror("PC %06X - Read input %02X !\n", activecpu_get_pc(), offset*2);
316 return 0;
317 }
318 }
319
|