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