summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/sidearms.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/sidearms.c')
-rw-r--r--src/mame/video/sidearms.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/mame/video/sidearms.c b/src/mame/video/sidearms.c
new file mode 100644
index 00000000000..701042a6f78
--- /dev/null
+++ b/src/mame/video/sidearms.c
@@ -0,0 +1,363 @@
+/***************************************************************************
+
+ video.c
+
+ Functions to emulate the video hardware of the machine.
+
+***************************************************************************/
+
+#include "driver.h"
+
+extern int sidearms_gameid;
+
+UINT8 *sidearms_bg_scrollx;
+UINT8 *sidearms_bg_scrolly;
+
+static UINT8 *tilerom;
+static int bgon, objon, staron, charon, flipon;
+static UINT32 hflop_74a_n, hcount_191, vcount_191, latch_374;
+
+static tilemap *bg_tilemap, *fg_tilemap;
+
+WRITE8_HANDLER( sidearms_videoram_w )
+{
+ videoram[offset] = data;
+ tilemap_mark_tile_dirty(fg_tilemap, offset);
+}
+
+WRITE8_HANDLER( sidearms_colorram_w )
+{
+ colorram[offset] = data;
+ tilemap_mark_tile_dirty(fg_tilemap, offset);
+}
+
+WRITE8_HANDLER( sidearms_c804_w )
+{
+ /* bits 0 and 1 are coin counters */
+ coin_counter_w(0, data & 0x01);
+ coin_counter_w(1, data & 0x02);
+
+ /* bit 2 and 3 lock the coin chutes */
+ if (!sidearms_gameid || sidearms_gameid==3)
+ {
+ coin_lockout_w(0, !(data & 0x04));
+ coin_lockout_w(1, !(data & 0x08));
+ }
+ else
+ {
+ coin_lockout_w(0, data & 0x04);
+ coin_lockout_w(1, data & 0x08);
+ }
+
+ /* bit 4 resets the sound CPU */
+ if (data & 0x10)
+ {
+ cpunum_set_input_line(1, INPUT_LINE_RESET, PULSE_LINE);
+ }
+
+ /* bit 5 enables starfield */
+ if (staron != (data & 0x20))
+ {
+ staron = data & 0x20;
+ hflop_74a_n = 1;
+ hcount_191 = vcount_191 = 0;
+ }
+
+ /* bit 6 enables char layer */
+ charon = data & 0x40;
+
+ /* bit 7 flips screen */
+ if (flipon != (data & 0x80))
+ {
+ flipon = data & 0x80;
+ flip_screen_set(flipon);
+ tilemap_mark_all_tiles_dirty(ALL_TILEMAPS);
+ }
+}
+
+WRITE8_HANDLER( sidearms_gfxctrl_w )
+{
+ objon = data & 0x01;
+ bgon = data & 0x02;
+}
+
+WRITE8_HANDLER( sidearms_star_scrollx_w )
+{
+ UINT32 last_state = hcount_191;
+
+ hcount_191++;
+ hcount_191 &= 0x1ff;
+
+ // invert 74LS74A(flipflop) output on 74LS191(hscan counter) carry's rising edge
+ if (hcount_191 & ~last_state & 0x100)
+ hflop_74a_n ^= 1;
+}
+
+WRITE8_HANDLER( sidearms_star_scrolly_w )
+{
+ vcount_191++;
+ vcount_191 &= 0xff;
+}
+
+
+static TILE_GET_INFO( get_sidearms_bg_tile_info )
+{
+ int code, attr, color, flags;
+
+ code = tilerom[tile_index];
+ attr = tilerom[tile_index + 1];
+ code |= attr<<8 & 0x100;
+ color = attr>>3 & 0x1f;
+ flags = attr>>1 & 0x03;
+
+ SET_TILE_INFO(1, code, color, flags);
+}
+
+static TILE_GET_INFO( get_philko_bg_tile_info )
+{
+ int code, attr, color, flags;
+
+ code = tilerom[tile_index];
+ attr = tilerom[tile_index + 1];
+ code |= (((attr>>6 & 0x02) | (attr & 0x01)) * 0x100);
+ color = attr>>3 & 0x0f;
+ flags = attr>>1 & 0x03;
+
+ SET_TILE_INFO(1, code, color, flags);
+}
+
+static TILE_GET_INFO( get_fg_tile_info )
+{
+ int attr = colorram[tile_index];
+ int code = videoram[tile_index] + (attr<<2 & 0x300);
+ int color = attr & 0x3f;
+
+ SET_TILE_INFO(0, code, color, 0);
+}
+
+static TILEMAP_MAPPER( sidearms_tilemap_scan )
+{
+ /* logical (col,row) -> memory offset */
+ int offset = ((row << 7) + col) << 1;
+
+ /* swap bits 1-7 and 8-10 of the address to compensate for the funny layout of the ROM data */
+ return ((offset & 0xf801) | ((offset & 0x0700) >> 7) | ((offset & 0x00fe) << 3)) & 0x7fff;
+}
+
+VIDEO_START( sidearms )
+{
+ tilerom = memory_region(REGION_GFX4);
+
+ if (!sidearms_gameid)
+ {
+ bg_tilemap = tilemap_create(get_sidearms_bg_tile_info, sidearms_tilemap_scan,
+ TILEMAP_TYPE_PEN, 32, 32, 128, 128);
+
+ tilemap_set_transparent_pen(bg_tilemap, 15);
+ }
+ else
+ {
+ bg_tilemap = tilemap_create(get_philko_bg_tile_info, sidearms_tilemap_scan,TILEMAP_TYPE_PEN, 32, 32, 128, 128);
+ }
+
+ fg_tilemap = tilemap_create(get_fg_tile_info, tilemap_scan_rows,
+ TILEMAP_TYPE_PEN, 8, 8, 64, 64);
+
+ tilemap_set_transparent_pen(fg_tilemap, 3);
+
+ hflop_74a_n = 1;
+ latch_374 = vcount_191 = hcount_191 = 0;
+
+ flipon = charon = staron = objon = bgon = 0;
+}
+
+static void draw_sprites_region(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int start_offset, int end_offset )
+{
+ const gfx_element *gfx = machine->gfx[2];
+ int offs, attr, color, code, x, y, flipx, flipy;
+
+ flipy = flipx = flipon;
+
+ for (offs = end_offset - 32; offs >= start_offset; offs -= 32)
+ {
+ y = buffered_spriteram[offs + 2];
+ if (!y || buffered_spriteram[offs + 5] == 0xc3) continue;
+
+ attr = buffered_spriteram[offs + 1];
+ color = attr & 0xf;
+ code = buffered_spriteram[offs] + ((attr << 3) & 0x700);
+ x = buffered_spriteram[offs + 3] + ((attr << 4) & 0x100);
+
+ if (flipon)
+ {
+ x = (62 * 8) - x;
+ y = (30 * 8) - y;
+ }
+
+ drawgfx(bitmap, gfx,
+ code, color,
+ flipx, flipy,
+ x, y,
+ cliprect,
+ TRANSPARENCY_PEN, 15);
+ }
+}
+
+static void sidearms_draw_starfield( mame_bitmap *bitmap )
+{
+ int x, y, i;
+ UINT32 hadd_283, vadd_283, _hflop_74a_n, _hcount_191, _vcount_191;
+ UINT8 *sf_rom;
+ UINT16 *lineptr;
+ int pixadv, lineadv;
+
+ // clear starfield background
+ lineptr = BITMAP_ADDR16(bitmap, 16, 64);
+ lineadv = bitmap->rowpixels;
+
+ for (i=224; i; i--) { memset(lineptr, 0, 768); lineptr += lineadv; }
+
+ // bail if not Side Arms or the starfield has been disabled
+ if (sidearms_gameid || !staron) return;
+
+ // init and cache some global vars in stack frame
+ hadd_283 = 0;
+
+ _hflop_74a_n = hflop_74a_n;
+ _vcount_191 = vcount_191;
+ _hcount_191 = hcount_191 & 0xff;
+
+ sf_rom = memory_region(REGION_USER1);
+
+#if 0 // old loop (for reference; easier to read)
+ if (!flipon)
+ {
+ lineptr = bitmap->base;
+ pixadv = 1;
+ lineadv = lineadv - 512;
+ }
+ else
+ {
+ lineptr = BITMAP_ADDR16(bitmap, 255, 512 - 1);
+ pixadv = -1;
+ lineadv = -lineadv + 512;
+ }
+
+ for (y=0; y<256; y++) // 8-bit V-clock input
+ {
+ for (x=0; x<512; lineptr+=pixadv,x++) // 9-bit H-clock input
+ {
+ i = hadd_283; // store horizontal adder's previous state in i
+ hadd_283 = _hcount_191 + (x & 0xff); // add lower 8 bits and preserve carry
+
+ if (x<64 || x>447 || y<16 || y>239) continue; // clip rejection
+
+ vadd_283 = _vcount_191 + y; // add lower 8 bits and discard carry (later)
+
+ if (!((vadd_283 ^ (x>>3)) & 4)) continue; // logic rejection 1
+ if ((vadd_283 | (hadd_283>>1)) & 2) continue; // logic rejection 2
+
+ // latch data from starfield EPROM on rising edge of 74LS374's clock input
+ if (!(~i & 0x1f))
+ {
+ i = vadd_283<<4 & 0xff0; // to starfield EPROM A04-A11 (8 bits)
+ i |= (_hflop_74a_n^(hadd_283>>8)) << 3; // to starfield EPROM A03 (1 bit)
+ i |= hadd_283>>5 & 7; // to starfield EPROM A00-A02 (3 bits)
+ latch_374 = sf_rom[i + 0x3000]; // lines A12-A13 are always high
+ }
+
+ if ((~((latch_374^hadd_283)^1) & 0x1f)) continue; // logic rejection 3
+
+ *lineptr = (UINT16)(latch_374>>5 | 0x378); // to color mixer
+ }
+ lineptr += lineadv;
+ }
+#else // optimized loop
+ if (!flipon)
+ {
+ lineptr = BITMAP_ADDR16(bitmap, 16, 64);
+ pixadv = 1;
+ lineadv = lineadv - 384;
+ }
+ else
+ {
+ lineptr = BITMAP_ADDR16(bitmap, 239, 512 - 64 - 1);
+ pixadv = -1;
+ lineadv = -lineadv + 384;
+ }
+
+ for (y=16; y<240; y++) // 8-bit V-clock input (clipped against vertical visible area)
+ {
+ // inner loop pre-entry conditioning
+ hadd_283 = (_hcount_191 + 64) & ~0x1f;
+ vadd_283 = _vcount_191 + y;
+
+ i = vadd_283<<4 & 0xff0; // to starfield EPROM A04-A11 (8 bits)
+ i |= (_hflop_74a_n^(hadd_283>>8)) << 3; // to starfield EPROM A03 (1 bit)
+ i |= hadd_283>>5 & 7; // to starfield EPROM A00-A02 (3 bits)
+ latch_374 = sf_rom[i + 0x3000]; // lines A12-A13 are always high
+
+ hadd_283 = _hcount_191 + 63;
+
+ for (x=64; x<448; lineptr+=pixadv,x++) // 9-bit H-clock input (clipped against horizontal visible area)
+ {
+ i = hadd_283; // store horizontal adder's previous state in i
+ hadd_283 = _hcount_191 + (x & 0xff); // add lower 8 bits and preserve carry
+ vadd_283 = _vcount_191 + y; // add lower 8 bits and discard carry (later)
+
+ if (!((vadd_283 ^ (x>>3)) & 4)) continue; // logic rejection 1
+ if ((vadd_283 | (hadd_283>>1)) & 2) continue; // logic rejection 2
+
+ // latch data from starfield EPROM on rising edge of 74LS374's clock input
+ if (!(~i & 0x1f))
+ {
+ i = vadd_283<<4 & 0xff0; // to starfield EPROM A04-A11 (8 bits)
+ i |= (_hflop_74a_n^(hadd_283>>8)) << 3; // to starfield EPROM A03 (1 bit)
+ i |= hadd_283>>5 & 7; // to starfield EPROM A00-A02 (3 bits)
+ latch_374 = sf_rom[i + 0x3000]; // lines A12-A13 are always high
+ }
+
+ if ((~((latch_374^hadd_283)^1) & 0x1f)) continue; // logic rejection 3
+
+ *lineptr = (UINT16)(latch_374>>5 | 0x378); // to color mixer
+ }
+ lineptr += lineadv;
+ }
+#endif
+}
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ if (sidearms_gameid == 2 || sidearms_gameid == 3) // Dyger and Whizz have simple front-to-back sprite priority
+ draw_sprites_region(machine, bitmap, cliprect, 0x0000, 0x1000);
+ else
+ {
+ draw_sprites_region(machine, bitmap, cliprect, 0x0700, 0x0800);
+ draw_sprites_region(machine, bitmap, cliprect, 0x0e00, 0x1000);
+ draw_sprites_region(machine, bitmap, cliprect, 0x0800, 0x0f00);
+ draw_sprites_region(machine, bitmap, cliprect, 0x0000, 0x0700);
+ }
+}
+
+VIDEO_UPDATE( sidearms )
+{
+ sidearms_draw_starfield(bitmap);
+
+ tilemap_set_scrollx(bg_tilemap, 0, sidearms_bg_scrollx[0] + (sidearms_bg_scrollx[1] << 8 & 0xf00));
+ tilemap_set_scrolly(bg_tilemap, 0, sidearms_bg_scrolly[0] + (sidearms_bg_scrolly[1] << 8 & 0xf00));
+
+ if (bgon)
+ tilemap_draw(bitmap, cliprect, bg_tilemap, 0, 0);
+
+ if (objon)
+ draw_sprites(machine, bitmap, cliprect);
+
+ if (charon)
+ tilemap_draw(bitmap, cliprect, fg_tilemap, 0, 0);
+ return 0;
+}
+
+VIDEO_EOF( sidearms )
+{
+ buffer_spriteram_w(0, 0);
+}