1 // license:BSD-3-Clause
2 // copyright-holders:Frank Palazzolo
3
4 /* Ramtek - Star Cruiser */
5
6 #include "emu.h"
7 #include "includes/starcrus.h"
8 #include "sound/samples.h"
9 #include "screen.h"
10
11 /* The collision detection techniques use in this driver
12 are well explained in the comments in the sprint2 driver */
13
s1_x_w(uint8_t data)14 void starcrus_state::s1_x_w(uint8_t data){ m_s1_x = data^0xff; }
s1_y_w(uint8_t data)15 void starcrus_state::s1_y_w(uint8_t data){ m_s1_y = data^0xff; }
s2_x_w(uint8_t data)16 void starcrus_state::s2_x_w(uint8_t data){ m_s2_x = data^0xff; }
s2_y_w(uint8_t data)17 void starcrus_state::s2_y_w(uint8_t data){ m_s2_y = data^0xff; }
p1_x_w(uint8_t data)18 void starcrus_state::p1_x_w(uint8_t data){ m_p1_x = data^0xff; }
p1_y_w(uint8_t data)19 void starcrus_state::p1_y_w(uint8_t data){ m_p1_y = data^0xff; }
p2_x_w(uint8_t data)20 void starcrus_state::p2_x_w(uint8_t data){ m_p2_x = data^0xff; }
p2_y_w(uint8_t data)21 void starcrus_state::p2_y_w(uint8_t data){ m_p2_y = data^0xff; }
22
video_start()23 void starcrus_state::video_start()
24 {
25 m_ship1_vid = std::make_unique<bitmap_ind16>(16, 16);
26 m_ship2_vid = std::make_unique<bitmap_ind16>(16, 16);
27
28 m_proj1_vid = std::make_unique<bitmap_ind16>(16, 16);
29 m_proj2_vid = std::make_unique<bitmap_ind16>(16, 16);
30
31 save_item(NAME(m_s1_x));
32 save_item(NAME(m_s1_y));
33 save_item(NAME(m_s2_x));
34 save_item(NAME(m_s2_y));
35 save_item(NAME(m_p1_x));
36 save_item(NAME(m_p1_y));
37 save_item(NAME(m_p2_x));
38 save_item(NAME(m_p2_y));
39 save_item(NAME(m_p1_sprite));
40 save_item(NAME(m_p2_sprite));
41 save_item(NAME(m_s1_sprite));
42 save_item(NAME(m_s2_sprite));
43 save_item(NAME(m_collision_reg));
44 }
45
ship_parm_1_w(uint8_t data)46 void starcrus_state::ship_parm_1_w(uint8_t data)
47 {
48 m_s1_sprite = data & 0x1f;
49 m_engine[0]->write_line(BIT(data, 5));
50 }
51
ship_parm_2_w(uint8_t data)52 void starcrus_state::ship_parm_2_w(uint8_t data)
53 {
54 m_s2_sprite = data & 0x1f;
55 m_led = !BIT(data, 7); /* game over lamp */
56 machine().bookkeeping().coin_counter_w(0, ((data & 0x40) >> 6) ^ 0x01); /* coin counter */
57 m_engine[1]->write_line(BIT(data, 5));
58 }
59
proj_parm_1_w(uint8_t data)60 void starcrus_state::proj_parm_1_w(uint8_t data)
61 {
62 m_p1_sprite = data & 0x0f;
63 m_launch[0]->write_line(BIT(data, 5));
64 m_explode[0]->write_line(BIT(data, 4));
65 }
66
proj_parm_2_w(uint8_t data)67 void starcrus_state::proj_parm_2_w(uint8_t data)
68 {
69 m_p2_sprite = data & 0x0f;
70 m_launch[1]->write_line(BIT(data, 5));
71 m_explode[1]->write_line(BIT(data, 4));
72 }
73
collision_check_s1s2()74 int starcrus_state::collision_check_s1s2()
75 {
76 rectangle clip(0, 15, 0, 15);
77
78 m_ship1_vid->fill(0, clip);
79 m_ship2_vid->fill(0, clip);
80
81 /* origin is with respect to ship1 */
82
83 int org_x = m_s1_x;
84 int org_y = m_s1_y;
85
86 /* Draw ship 1 */
87
88 m_gfxdecode->gfx(8 + ((m_s1_sprite & 0x04) >> 2))->opaque(*m_ship1_vid,
89 clip,
90 (m_s1_sprite & 0x03) ^ 0x03,
91 0,
92 (m_s1_sprite & 0x08) >> 3, (m_s1_sprite & 0x10) >> 4,
93 m_s1_x - org_x, m_s1_y - org_y);
94
95 /* Draw ship 2 */
96
97 m_gfxdecode->gfx(10 + ((m_s2_sprite & 0x04) >> 2))->opaque(*m_ship2_vid,
98 clip,
99 (m_s2_sprite & 0x03) ^ 0x03,
100 0,
101 (m_s2_sprite & 0x08) >> 3, (m_s2_sprite & 0x10) >> 4,
102 m_s2_x - org_x, m_s2_y - org_y);
103
104 /* Now check for collisions */
105 for (int sy = 0; sy < 16; sy++)
106 for (int sx = 0; sx < 16; sx++)
107 /* Condition 1 - ship 1 = ship 2 */
108 if ((m_ship1_vid->pix(sy, sx) == 1) && (m_ship2_vid->pix(sy, sx) == 1))
109 return 1;
110
111 return 0;
112 }
113
collision_check_p1p2()114 int starcrus_state::collision_check_p1p2()
115 {
116 rectangle clip(0, 15, 0, 15);
117
118 /* if both are scores, return */
119 if ( ((m_p1_sprite & 0x08) == 0) &&
120 ((m_p2_sprite & 0x08) == 0) )
121 {
122 return 0;
123 }
124
125 m_proj1_vid->fill(0, clip);
126 m_proj2_vid->fill(0, clip);
127
128 /* origin is with respect to proj1 */
129
130 int org_x = m_p1_x;
131 int org_y = m_p1_y;
132
133 if (m_p1_sprite & 0x08) /* if p1 is a projectile */
134 {
135 /* Draw score/projectile 1 */
136
137 m_gfxdecode->gfx((m_p1_sprite & 0x0c) >> 2)->opaque(*m_proj1_vid,
138 clip,
139 (m_p1_sprite & 0x03) ^ 0x03,
140 0,
141 0, 0,
142 m_p1_x - org_x, m_p1_y - org_y);
143 }
144
145 if (m_p2_sprite & 0x08) /* if p2 is a projectile */
146 {
147 /* Draw score/projectile 2 */
148
149 m_gfxdecode->gfx(4 + ((m_p2_sprite & 0x0c) >> 2))->opaque(*m_proj2_vid,
150 clip,
151 (m_p2_sprite & 0x03) ^ 0x03,
152 0,
153 0, 0,
154 m_p2_x - org_x, m_p2_y - org_y);
155 }
156
157 /* Now check for collisions */
158 for (int sy = 0; sy < 16; sy++)
159 for (int sx = 0; sx < 16; sx++)
160 /* Condition 1 - proj 1 = proj 2 */
161 if ((m_proj1_vid->pix(sy, sx) == 1) && (m_proj2_vid->pix(sy, sx) == 1))
162 return 1;
163
164 return 0;
165 }
166
collision_check_s1p1p2()167 int starcrus_state::collision_check_s1p1p2()
168 {
169 rectangle clip(0, 15, 0, 15);
170
171 /* if both are scores, return */
172 if ((m_p1_sprite & 0x08) == 0 && (m_p2_sprite & 0x08) == 0)
173 {
174 return 0;
175 }
176
177 m_ship1_vid->fill(0, clip);
178 m_proj1_vid->fill(0, clip);
179 m_proj2_vid->fill(0, clip);
180
181 /* origin is with respect to ship1 */
182
183 int org_x = m_s1_x;
184 int org_y = m_s1_y;
185
186 /* Draw ship 1 */
187
188 m_gfxdecode->gfx(8 + ((m_s1_sprite & 0x04) >> 2))->opaque(*m_ship1_vid,
189 clip,
190 (m_s1_sprite & 0x03) ^ 0x03,
191 0,
192 (m_s1_sprite & 0x08) >> 3, (m_s1_sprite & 0x10) >> 4,
193 m_s1_x - org_x, m_s1_y - org_y);
194
195 if (m_p1_sprite & 0x08) /* if p1 is a projectile */
196 {
197 /* Draw projectile 1 */
198
199 m_gfxdecode->gfx((m_p1_sprite & 0x0c) >> 2)->opaque(*m_proj1_vid,
200 clip,
201 (m_p1_sprite & 0x03) ^ 0x03,
202 0,
203 0, 0,
204 m_p1_x - org_x, m_p1_y - org_y);
205 }
206
207 if (m_p2_sprite & 0x08) /* if p2 is a projectile */
208 {
209 /* Draw projectile 2 */
210
211 m_gfxdecode->gfx(4 + ((m_p2_sprite & 0x0c) >> 2))->opaque(*m_proj2_vid,
212 clip,
213 (m_p2_sprite & 0x03) ^ 0x03,
214 0,
215 0, 0,
216 m_p2_x - org_x, m_p2_y - org_y);
217 }
218
219 /* Now check for collisions */
220 for (int sy = 0; sy < 16; sy++)
221 for (int sx = 0; sx < 16; sx++)
222 if (m_ship1_vid->pix(sy, sx) == 1)
223 {
224 /* Condition 1 - ship 1 = proj 1 */
225 if (m_proj1_vid->pix(sy, sx) == 1)
226 return 1;
227 /* Condition 2 - ship 1 = proj 2 */
228 if (m_proj2_vid->pix(sy, sx) == 1)
229 return 1;
230 }
231
232 return 0;
233 }
234
collision_check_s2p1p2()235 int starcrus_state::collision_check_s2p1p2()
236 {
237 rectangle clip(0, 15, 0, 15);
238
239 /* if both are scores, return */
240 if ((m_p1_sprite & 0x08) == 0 && (m_p2_sprite & 0x08) == 0)
241 {
242 return 0;
243 }
244
245 m_ship2_vid->fill(0, clip);
246 m_proj1_vid->fill(0, clip);
247 m_proj2_vid->fill(0, clip);
248
249 /* origin is with respect to ship2 */
250
251 int org_x = m_s2_x;
252 int org_y = m_s2_y;
253
254 /* Draw ship 2 */
255
256 m_gfxdecode->gfx(10 + ((m_s2_sprite & 0x04) >> 2))->opaque(*m_ship2_vid,
257 clip,
258 (m_s2_sprite & 0x03) ^ 0x03,
259 0,
260 (m_s2_sprite & 0x08) >> 3, (m_s2_sprite & 0x10) >> 4,
261 m_s2_x - org_x, m_s2_y - org_y);
262
263 if (m_p1_sprite & 0x08) /* if p1 is a projectile */
264 {
265 /* Draw projectile 1 */
266
267 m_gfxdecode->gfx((m_p1_sprite & 0x0c) >> 2)->opaque(*m_proj1_vid,
268 clip,
269 (m_p1_sprite & 0x03) ^ 0x03,
270 0,
271 0, 0,
272 m_p1_x - org_x, m_p1_y - org_y);
273 }
274
275 if (m_p2_sprite & 0x08) /* if p2 is a projectile */
276 {
277 /* Draw projectile 2 */
278 m_gfxdecode->gfx(4 + ((m_p2_sprite & 0x0c) >> 2))->opaque(*m_proj2_vid,
279 clip,
280 (m_p2_sprite & 0x03) ^ 0x03,
281 0,
282 0, 0,
283 m_p2_x - org_x, m_p2_y - org_y);
284 }
285
286 /* Now check for collisions */
287 for (int sy = 0; sy < 16; sy++)
288 for (int sx = 0; sx < 16; sx++)
289 if (m_ship2_vid->pix(sy, sx) == 1)
290 {
291 /* Condition 1 - ship 2 = proj 1 */
292 if (m_proj1_vid->pix(sy, sx) == 1)
293 return 1;
294 /* Condition 2 - ship 2 = proj 2 */
295 if (m_proj2_vid->pix(sy, sx) == 1)
296 return 1;
297 }
298
299 return 0;
300 }
301
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)302 uint32_t starcrus_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
303 {
304 bitmap.fill(0, cliprect);
305
306 /* Draw ship 1 */
307 m_gfxdecode->gfx(8 + ((m_s1_sprite & 0x04) >> 2))->transpen(bitmap,
308 cliprect,
309 (m_s1_sprite & 0x03) ^ 0x03,
310 0,
311 (m_s1_sprite & 0x08) >> 3, (m_s1_sprite & 0x10) >> 4,
312 m_s1_x, m_s1_y,
313 0);
314
315 /* Draw ship 2 */
316 m_gfxdecode->gfx(10 + ((m_s2_sprite & 0x04) >> 2))->transpen(bitmap,
317 cliprect,
318 (m_s2_sprite & 0x03) ^ 0x03,
319 0,
320 (m_s2_sprite & 0x08) >> 3, (m_s2_sprite & 0x10) >> 4,
321 m_s2_x, m_s2_y,
322 0);
323
324 /* Draw score/projectile 1 */
325 m_gfxdecode->gfx((m_p1_sprite & 0x0c) >> 2)->transpen(bitmap,
326 cliprect,
327 (m_p1_sprite & 0x03) ^ 0x03,
328 0,
329 0, 0,
330 m_p1_x, m_p1_y,
331 0);
332
333 /* Draw score/projectile 2 */
334 m_gfxdecode->gfx(4 + ((m_p2_sprite & 0x0c) >> 2))->transpen(bitmap,
335 cliprect,
336 (m_p2_sprite & 0x03) ^ 0x03,
337 0,
338 0, 0,
339 m_p2_x, m_p2_y,
340 0);
341
342 /* Collision detection */
343 if (cliprect.max_y == screen.visible_area().max_y)
344 {
345 m_collision_reg = 0x00;
346
347 /* Check for collisions between ship1 and ship2 */
348 if (collision_check_s1s2())
349 {
350 m_collision_reg |= 0x08;
351 }
352 /* Check for collisions between ship1 and projectiles */
353 if (collision_check_s1p1p2())
354 {
355 m_collision_reg |= 0x02;
356 }
357 /* Check for collisions between ship1 and projectiles */
358 if (collision_check_s2p1p2())
359 {
360 m_collision_reg |= 0x01;
361 }
362 /* Check for collisions between ship1 and projectiles */
363 /* Note: I don't think this is used by the game */
364 if (collision_check_p1p2())
365 {
366 m_collision_reg |= 0x04;
367 }
368 }
369
370 return 0;
371 }
372
coll_det_r()373 uint8_t starcrus_state::coll_det_r()
374 {
375 return m_collision_reg ^ 0xff;
376 }
377