// license:BSD-3-Clause // copyright-holders:Zsolt Vasvari /*************************************************************************** suprloco.c Functions to emulate the video hardware of the machine. ***************************************************************************/ #include "emu.h" #include "includes/suprloco.h" #define SPR_Y_TOP 0 #define SPR_Y_BOTTOM 1 #define SPR_X 2 #define SPR_COL 3 #define SPR_SKIP_LO 4 #define SPR_SKIP_HI 5 #define SPR_GFXOFS_LO 6 #define SPR_GFXOFS_HI 7 /*************************************************************************** Convert the color PROMs into a more useable format. I'm not sure about the resistor values, I'm using the Galaxian ones. ***************************************************************************/ void suprloco_state::suprloco_palette(palette_device &palette) const { const uint8_t *color_prom = memregion("proms")->base(); for (int i = 0; i < 512; i++) { int bit0, bit1, bit2; // red component bit0 = BIT(color_prom[i], 0); bit1 = BIT(color_prom[i], 1); bit2 = BIT(color_prom[i], 2); int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; // green component bit0 = BIT(color_prom[i], 3); bit1 = BIT(color_prom[i], 4); bit2 = BIT(color_prom[i], 5); int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; // blue component bit0 = 0; bit1 = BIT(color_prom[i], 6); bit2 = BIT(color_prom[i], 7); int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2; palette.set_pen_color(i, rgb_t(r, g, b)); // hack: generate a second bank of sprite palette with red changed to purple if (i >= 256) palette.set_pen_color(i + 256, rgb_t(r, g, ((i & 0x0f) == 0x09) ? 0xff : b)); } } /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ TILE_GET_INFO_MEMBER(suprloco_state::get_tile_info) { uint8_t attr = m_videoram[2*tile_index+1]; SET_TILE_INFO_MEMBER(0, m_videoram[2*tile_index] | ((attr & 0x03) << 8), (attr & 0x1c) >> 2, 0); tileinfo.category = (attr & 0x20) >> 5; } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ void suprloco_state::video_start() { m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(suprloco_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,32); m_bg_tilemap->set_scroll_rows(32); save_item(NAME(m_control)); } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE8_MEMBER(suprloco_state::videoram_w) { m_videoram[offset] = data; m_bg_tilemap->mark_tile_dirty(offset/2); } WRITE8_MEMBER(suprloco_state::scrollram_w) { int adj = flip_screen() ? -8 : 8; m_scrollram[offset] = data; m_bg_tilemap->set_scrollx(offset, data - adj); } WRITE8_MEMBER(suprloco_state::control_w) { /* There is probably a palette select in here */ /* Bit 0 - coin counter A */ /* Bit 1 - coin counter B (only used if coinage differs from A) */ /* Bit 2-3 - probably unused */ /* Bit 4 - ??? */ /* Bit 5 - pulsated when loco turns "super" */ /* Bit 6 - probably unused */ /* Bit 7 - flip screen */ if ((m_control & 0x10) != (data & 0x10)) { /*logerror("Bit 4 = %d\n", (data >> 4) & 1); */ } machine().bookkeeping().coin_counter_w(0, data & 0x01); machine().bookkeeping().coin_counter_w(1, data & 0x02); flip_screen_set(data & 0x80); m_control = data; } inline void suprloco_state::draw_pixel(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int color,int flip) { if (flip) { x = bitmap.width() - x - 1; y = bitmap.height() - y - 1; } if (cliprect.contains(x, y)) bitmap.pix16(y, x) = color; } void suprloco_state::draw_sprite(bitmap_ind16 &bitmap,const rectangle &cliprect,int spr_number) { int flip = flip_screen(); int sx,sy,col,row,height,src,adjy,dy; uint8_t *spr_reg; uint8_t *gfx2; pen_t pen_base; short skip; /* bytes to skip before drawing each row (can be negative) */ spr_reg = m_spriteram + 0x10 * spr_number; src = spr_reg[SPR_GFXOFS_LO] + (spr_reg[SPR_GFXOFS_HI] << 8); skip = spr_reg[SPR_SKIP_LO] + (spr_reg[SPR_SKIP_HI] << 8); height = spr_reg[SPR_Y_BOTTOM] - spr_reg[SPR_Y_TOP]; pen_base = 0x100 + 0x10 * (spr_reg[SPR_COL]&0x03) + ((m_control & 0x20)?0x100:0); sx = spr_reg[SPR_X]; sy = spr_reg[SPR_Y_TOP] + 1; if (!flip_screen()) { adjy = sy; dy = 1; } else { adjy = sy + height - 1; /* some of the sprites are still off by a pixel */ dy = -1; } gfx2 = memregion("gfx2")->base(); for (row = 0;row < height;row++,adjy+=dy) { int color1,color2,flipx; uint8_t data; uint8_t *gfx; src += skip; col = 0; /* get pointer to packed sprite data */ gfx = &(gfx2[src & 0x7fff]); flipx = src & 0x8000; /* flip x */ while (1) { if (flipx) /* flip x */ { data = *gfx--; color1 = data & 0x0f; color2 = data >> 4; } else { data = *gfx++; color1 = data >> 4; color2 = data & 0x0f; } if (color1 == 15) break; if (color1) draw_pixel(bitmap,cliprect,sx+col, adjy,pen_base + color1, flip); if (color2 == 15) break; if (color2) draw_pixel(bitmap,cliprect,sx+col+1,adjy,pen_base + color2, flip); col += 2; } } } void suprloco_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) { int spr_number; uint8_t *spr_reg; for (spr_number = 0;spr_number < (m_spriteram.bytes() >> 4);spr_number++) { spr_reg = m_spriteram + 0x10 * spr_number; if (spr_reg[SPR_X] != 0xff) draw_sprite(bitmap, cliprect, spr_number); } } uint32_t suprloco_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0); draw_sprites(bitmap,cliprect); m_bg_tilemap->draw(screen, bitmap, cliprect, 1,0); return 0; }