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