1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 ***************************************************************************/
8 
9 #include "driver.h"
10 #include "vidhrdw/generic.h"
11 
12 extern int sidearms_gameid;
13 
14 UINT8 *sidearms_bg_scrollx;
15 UINT8 *sidearms_bg_scrolly;
16 
17 static int tilebank_base[4] = { 0, 0x100, 0x200, 0x100 };
18 static UINT8 *tilerom;
19 static int bgon, objon, staron, charon, flipon;
20 static unsigned int hflop_74a_n, hcount_191, vcount_191, latch_374;
21 
22 static struct tilemap *bg_tilemap, *fg_tilemap;
23 
WRITE_HANDLER(sidearms_videoram_w)24 WRITE_HANDLER( sidearms_videoram_w )
25 {
26 	if (videoram[offset] != data)
27 	{
28 		videoram[offset] = data;
29 		tilemap_mark_tile_dirty(fg_tilemap, offset);
30 	}
31 }
32 
WRITE_HANDLER(sidearms_colorram_w)33 WRITE_HANDLER( sidearms_colorram_w )
34 {
35 	if (colorram[offset] != data)
36 	{
37 		colorram[offset] = data;
38 		tilemap_mark_tile_dirty(fg_tilemap, offset);
39 	}
40 }
41 
WRITE_HANDLER(sidearms_c804_w)42 WRITE_HANDLER( sidearms_c804_w )
43 {
44 	/* bits 0 and 1 are coin counters */
45 	coin_counter_w(0, data & 0x01);
46 	coin_counter_w(1, data & 0x02);
47 
48 	/* bit 2 and 3 lock the coin chutes */
49 	if (!sidearms_gameid || sidearms_gameid==3)
50 	{
51 		coin_lockout_w(0, !(data & 0x04));
52 		coin_lockout_w(1, !(data & 0x08));
53 	}
54 	else
55 	{
56 		coin_lockout_w(0, data & 0x04);
57 		coin_lockout_w(1, data & 0x08);
58 	}
59 
60 	/* bit 4 resets the sound CPU */
61 	if (data & 0x10)
62 	{
63 		cpuint_reset_cpu(1);
64 	}
65 
66 	/* bit 5 enables starfield */
67 	if (staron != (data & 0x20))
68 	{
69 		staron = data & 0x20;
70 		hflop_74a_n = 1;
71 		hcount_191 = vcount_191 = 0;
72 	}
73 
74 	/* bit 6 enables char layer */
75 	charon = data & 0x40;
76 
77 	/* bit 7 flips screen */
78 	if (flipon != (data & 0x80))
79 	{
80 		flipon = data & 0x80;
81 		flip_screen_set(flipon);
82 		tilemap_mark_all_tiles_dirty(ALL_TILEMAPS);
83 	}
84 }
85 
WRITE_HANDLER(sidearms_gfxctrl_w)86 WRITE_HANDLER( sidearms_gfxctrl_w )
87 {
88 	objon = data & 0x01;
89 	bgon = data & 0x02;
90 }
91 
WRITE_HANDLER(sidearms_star_scrollx_w)92 WRITE_HANDLER( sidearms_star_scrollx_w )
93 {
94 	unsigned int last_state = hcount_191;
95 
96 	hcount_191++;
97 	hcount_191 &= 0x1ff;
98 
99 	/* invert 74LS74A(flipflop) output on 74LS191(hscan counter) carry's rising edge*/
100 	if (hcount_191 & ~last_state & 0x100)
101 		hflop_74a_n ^= 1;
102 }
103 
WRITE_HANDLER(sidearms_star_scrolly_w)104 WRITE_HANDLER( sidearms_star_scrolly_w )
105 {
106 	vcount_191++;
107 	vcount_191 &= 0xff;
108 }
109 
110 
get_sidearms_bg_tile_info(int offs)111 static INLINE void get_sidearms_bg_tile_info(int offs)
112 {
113 	int code, attr, color, flags;
114 
115 	code = tilerom[offs];
116 	attr = tilerom[offs + 1];
117 	code |= attr<<8 & 0x100;
118 	color = attr>>3 & 0x1f;
119 	flags = attr>>1 & 0x03;
120 
121 	SET_TILE_INFO(1, code, color, flags)
122 }
123 
get_philko_bg_tile_info(int offs)124 static INLINE void get_philko_bg_tile_info(int offs)
125 {
126 	int code, attr, color, flags;
127 
128 	code = tilerom[offs];
129 	attr = tilerom[offs + 1];
130 	code |= tilebank_base[(attr>>6 & 0x02) | (attr & 0x01)];
131 	color = attr>>3 & 0x0f;
132 	flags = attr>>1 & 0x03;
133 
134 	SET_TILE_INFO(1, code, color, flags)
135 }
136 
get_whizz_bg_tile_info(int offs)137 static INLINE void get_whizz_bg_tile_info(int offs)
138 {
139 	int code, attr, color, flags;
140 
141 	code = tilerom[offs];
142 	attr = tilerom[offs + 1];
143 	code |= ((attr&0xc0)<<2);
144 	if((attr&40))code+=256*4;/* test only */
145 
146 
147 	color = attr>>3 & 0x0f;
148 	flags = attr>>1 & 0x03;
149 
150 	SET_TILE_INFO(1, code, color, flags)
151 }
152 
get_fg_tile_info(int tile_index)153 static INLINE void get_fg_tile_info(int tile_index)
154 {
155 	int attr = colorram[tile_index];
156 	int code = videoram[tile_index] + (attr<<2 & 0x300);
157 	int color = attr & 0x3f;
158 
159 	SET_TILE_INFO(0, code, color, 0)
160 }
161 
sidearms_tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)162 static INLINE UINT32 sidearms_tilemap_scan( UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows )
163 {
164 	/* logical (col,row) -> memory offset */
165 	int offset = ((row << 7) + col) << 1;
166 
167 	/* swap bits 1-7 and 8-10 of the address to compensate for the funny layout of the ROM data */
168 	return ((offset & 0xf801) | ((offset & 0x0700) >> 7) | ((offset & 0x00fe) << 3)) & 0x7fff;
169 }
170 
VIDEO_START(sidearms)171 VIDEO_START( sidearms )
172 {
173 	tilerom = memory_region(REGION_GFX4);
174 
175 	if (!sidearms_gameid)
176 	{
177 		bg_tilemap = tilemap_create(get_sidearms_bg_tile_info, sidearms_tilemap_scan,
178 			TILEMAP_TRANSPARENT, 32, 32, 128, 128);
179 
180 		if ( !bg_tilemap ) return 1;
181 
182 		tilemap_set_transparent_pen(bg_tilemap, 15);
183 	}
184 	else
185 	{
186 		if(sidearms_gameid==3)
187 			bg_tilemap = tilemap_create(get_whizz_bg_tile_info, sidearms_tilemap_scan,TILEMAP_OPAQUE, 32, 32, 128, 128);
188 		else
189 			bg_tilemap = tilemap_create(get_philko_bg_tile_info, sidearms_tilemap_scan,TILEMAP_OPAQUE, 32, 32, 128, 128);
190 
191 
192 
193 		if ( !bg_tilemap ) return 1;
194 	}
195 
196 	fg_tilemap = tilemap_create(get_fg_tile_info, tilemap_scan_rows,
197 		TILEMAP_TRANSPARENT, 8, 8, 64, 64);
198 
199 	if ( !fg_tilemap ) return 1;
200 
201 	tilemap_set_transparent_pen(fg_tilemap, 3);
202 
203 	hflop_74a_n = 1;
204 	latch_374 = vcount_191 = hcount_191 = 0;
205 
206 	flipon = charon = staron = objon = bgon = 0;
207 
208 	return 0;
209 }
210 
sidearms_draw_sprites_region(struct mame_bitmap * bitmap,int start_offset,int end_offset)211 void sidearms_draw_sprites_region( struct mame_bitmap *bitmap, int start_offset, int end_offset )
212 {
213 	const struct GfxElement *gfx = Machine->gfx[2];
214 	struct rectangle *cliprect = &Machine->visible_area;
215 	int offs, attr, color, code, x, y, flipx, flipy;
216 
217 	flipy = flipx = flipon;
218 
219 	for (offs = end_offset - 32; offs >= start_offset; offs -= 32)
220 	{
221 		y = buffered_spriteram[offs + 2];
222 		if (!y || buffered_spriteram[offs + 5] == 0xc3) continue;
223 
224 		attr = buffered_spriteram[offs + 1];
225 		color = attr & 0xf;
226 		code = buffered_spriteram[offs] + ((attr << 3) & 0x700);
227 		x = buffered_spriteram[offs + 3] + ((attr << 4) & 0x100);
228 
229 		if (flipon)
230 		{
231 			x = (62 * 8) - x;
232 			y = (30 * 8) - y;
233 		}
234 
235 		drawgfx(bitmap, gfx,
236 			code, color,
237 			flipx, flipy,
238 			x, y,
239 			cliprect,
240 			TRANSPARENCY_PEN, 15);
241 	}
242 }
243 
sidearms_draw_starfield(struct mame_bitmap * bitmap)244 static void sidearms_draw_starfield( struct mame_bitmap *bitmap )
245 {
246 	int x, y, i;
247 	unsigned int hadd_283, vadd_283, _hflop_74a_n, _hcount_191, _vcount_191;
248 	UINT8 *sf_rom;
249 	UINT16 *lineptr;
250 	int pixadv, lineadv;
251 
252 	/* clear starfield background*/
253 	lineptr = (UINT16 *)bitmap->line[16] + 64;
254 	lineadv = bitmap->rowpixels;
255 
256 	for (i=224; i; i--) { memset(lineptr, 0, 768); lineptr += lineadv; }
257 
258 	/* bail if not Side Arms or the starfield has been disabled*/
259 	if (sidearms_gameid || !staron) return;
260 
261 	/* init and cache some global vars in stack frame*/
262 	hadd_283 = 0;
263 
264 	_hflop_74a_n = hflop_74a_n;
265 	_vcount_191 = vcount_191;
266 	_hcount_191 = hcount_191 & 0xff;
267 
268 	sf_rom = memory_region(REGION_USER1);
269 
270 #if 0 /* old loop (for reference; easier to read)*/
271 	if (!flipon)
272 	{
273 		lineptr = (UINT16 *)bitmap->line[0];
274 		pixadv  = 1;
275 		lineadv = lineadv - 512;
276 	}
277 	else
278 	{
279 		lineptr = (UINT16 *)bitmap->line[255] + 512 - 1;
280 		pixadv  = -1;
281 		lineadv = -lineadv + 512;
282 	}
283 
284 	for (y=0; y<256; y++) /* 8-bit V-clock input*/
285 	{
286 		for (x=0; x<512; lineptr+=pixadv,x++) /* 9-bit H-clock input*/
287 		{
288 			i = hadd_283; /* store horizontal adder's previous state in i*/
289 			hadd_283 = _hcount_191 + (x & 0xff); /* add lower 8 bits and preserve carry*/
290 
291 			if (x<64 || x>447 || y<16 || y>239) continue; /* clip rejection*/
292 
293 			vadd_283 = _vcount_191 + y; /* add lower 8 bits and discard carry (later)*/
294 
295 			if (!((vadd_283 ^ (x>>3)) & 4)) continue;		/* logic rejection 1*/
296 			if ((vadd_283 | (hadd_283>>1)) & 2) continue;	/* logic rejection 2*/
297 
298 			/* latch data from starfield EPROM on rising edge of 74LS374's clock input*/
299 			if (!(~i & 0x1f))
300 			{
301 				i = vadd_283<<4 & 0xff0;				/* to starfield EPROM A04-A11 (8 bits)*/
302 				i |= (_hflop_74a_n^(hadd_283>>8)) << 3;	/* to starfield EPROM A03     (1 bit)*/
303 				i |= hadd_283>>5 & 7;					/* to starfield EPROM A00-A02 (3 bits)*/
304 				latch_374 = sf_rom[i + 0x3000];			/* lines A12-A13 are always high*/
305 			}
306 
307 			if ((~((latch_374^hadd_283)^1) & 0x1f)) continue; /* logic rejection 3*/
308 
309 			*lineptr = (UINT16)(latch_374>>5 | 0x378); /* to color mixer*/
310 		}
311 		lineptr += lineadv;
312 	}
313 #else /* optimized loop*/
314 	if (!flipon)
315 	{
316 		lineptr = (UINT16 *)bitmap->line[16] + 64;
317 		pixadv  = 1;
318 		lineadv = lineadv - 384;
319 	}
320 	else
321 	{
322 		lineptr = (UINT16 *)bitmap->line[239] + 512 - 64 - 1;
323 		pixadv  = -1;
324 		lineadv = -lineadv + 384;
325 	}
326 
327 	for (y=16; y<240; y++) /* 8-bit V-clock input (clipped against vertical visible area)*/
328 	{
329 		/* inner loop pre-entry conditioning*/
330 		hadd_283 = (_hcount_191 + 64) & ~0x1f;
331 		vadd_283 = _vcount_191 + y;
332 
333 		i = vadd_283<<4 & 0xff0;				/* to starfield EPROM A04-A11 (8 bits)*/
334 		i |= (_hflop_74a_n^(hadd_283>>8)) << 3;	/* to starfield EPROM A03     (1 bit)*/
335 		i |= hadd_283>>5 & 7;					/* to starfield EPROM A00-A02 (3 bits)*/
336 		latch_374 = sf_rom[i + 0x3000];			/* lines A12-A13 are always high*/
337 
338 		hadd_283 = _hcount_191 + 63;
339 
340 		for (x=64; x<448; lineptr+=pixadv,x++) /* 9-bit H-clock input (clipped against horizontal visible area)*/
341 		{
342 			i = hadd_283;							/* store horizontal adder's previous state in i*/
343 			hadd_283 = _hcount_191 + (x & 0xff);	/* add lower 8 bits and preserve carry*/
344 			vadd_283 = _vcount_191 + y;				/* add lower 8 bits and discard carry (later)*/
345 
346 			if (!((vadd_283 ^ (x>>3)) & 4)) continue;		/* logic rejection 1*/
347 			if ((vadd_283 | (hadd_283>>1)) & 2) continue;	/* logic rejection 2*/
348 
349 			/* latch data from starfield EPROM on rising edge of 74LS374's clock input*/
350 			if (!(~i & 0x1f))
351 			{
352 				i = vadd_283<<4 & 0xff0;				/* to starfield EPROM A04-A11 (8 bits)*/
353 				i |= (_hflop_74a_n^(hadd_283>>8)) << 3;	/* to starfield EPROM A03     (1 bit)*/
354 				i |= hadd_283>>5 & 7;					/* to starfield EPROM A00-A02 (3 bits)*/
355 				latch_374 = sf_rom[i + 0x3000];			/* lines A12-A13 are always high*/
356 			}
357 
358 			if ((~((latch_374^hadd_283)^1) & 0x1f)) continue; /* logic rejection 3*/
359 
360 			*lineptr = (UINT16)(latch_374>>5 | 0x378); /* to color mixer*/
361 		}
362 		lineptr += lineadv;
363 	}
364 #endif
365 }
366 
sidearms_draw_sprites(struct mame_bitmap * bitmap)367 static void sidearms_draw_sprites( struct mame_bitmap *bitmap )
368 {
369 	if (sidearms_gameid == 2) /* Dyger has simple front-to-back sprite priority*/
370 		sidearms_draw_sprites_region(bitmap, 0x0000, 0x1000);
371 	else
372 	{
373 		sidearms_draw_sprites_region(bitmap, 0x0700, 0x0800);
374 		sidearms_draw_sprites_region(bitmap, 0x0e00, 0x1000);
375 		sidearms_draw_sprites_region(bitmap, 0x0800, 0x0f00);
376 		sidearms_draw_sprites_region(bitmap, 0x0000, 0x0700);
377 	}
378 }
379 
VIDEO_UPDATE(sidearms)380 VIDEO_UPDATE( sidearms )
381 {
382 	sidearms_draw_starfield(bitmap);
383 
384 	tilemap_set_scrollx(bg_tilemap, 0, sidearms_bg_scrollx[0] + (sidearms_bg_scrollx[1] << 8 & 0xf00));
385 	tilemap_set_scrolly(bg_tilemap, 0, sidearms_bg_scrolly[0] + (sidearms_bg_scrolly[1] << 8 & 0xf00));
386 
387 	if (bgon)
388 		tilemap_draw(bitmap, cliprect, bg_tilemap, 0, 0);
389 
390 	if (objon)
391 		sidearms_draw_sprites(bitmap);
392 
393 	if (charon)
394 		tilemap_draw(bitmap, cliprect, fg_tilemap, 0, 0);
395 }
396 
VIDEO_EOF(sidearms)397 VIDEO_EOF( sidearms )
398 {
399 	buffer_spriteram_w(0, 0);
400 }
401