// license:BSD-3-Clause // copyright-holders:Luca Elia /*************************************************************************** -= SunA 16 Bit Games =- driver by Luca Elia (l.elia@tin.it) These games have only sprites, of a peculiar type: there is a region of memory where 32 pages of 32x32 tile codes can be written like a tilemap made of 32 pages of 256x256 pixels. Each tile uses 2 words. Sprites are rectangular regions of *tiles* fetched from there and sent to the screen. Each sprite uses 4 words, held where the last page of tiles would be. [ Sprites Format ] Offset: Bits: Value: 0.w fedc ---- ---- ---- Source Page (Low Bits) ---- ba98 ---- ---- Source Column (Bit 8 = Sprite Flip X) ---- ---- 7654 3210 Screen Y Position 2.w fedc ---- ---- ---- Tile Bank ---- ba-- ---- ---- ---- --9- ---- ---- Source Page (High Bit) ---- ---8 7654 3210 Screen X Position $10000.w fedc ba98 ---- ---- ---- ---- 76-- ---- Sprite Size: 00 -> 16 x 16 (2x2 tiles) 01 -> 32 x 32 (4x4 tiles) 10 -> 16 x 256 (2x32 tiles) 11 -> 32 x 256 (4x32 tiles) ---- ---- --54 ---- ? (Bit 4 used by uballoon) ---- ---- ---- 3210 Source Row $10002.w - [ Sprite's Tiles Format ] Offset: Bits: Value: 0.w f--- ---- ---- ---- Flip Y -e-- ---- ---- ---- Flip X --dc ba98 7654 3210 Code $10000.w fedc ba98 7654 ---- ---- ---- ---- 3210 Color ***************************************************************************/ #include "emu.h" #include "includes/suna16.h" WRITE16_MEMBER(suna16_state::flipscreen_w) { if (ACCESSING_BITS_0_7) { flip_screen_set(data & 1 ); m_color_bank = ( data & 4 ) >> 2; } if (data & ~(1|4)) logerror("CPU#0 PC %06X - Flip screen unknown bits: %04X\n", m_maincpu->pc(), data); } WRITE16_MEMBER(suna16_state::bestbest_flipscreen_w) { if (ACCESSING_BITS_0_7) { flip_screen_set(data & 0x10 ); //m_color_bank = ( data & 0x07 ); } if (data & ~(0x10)) logerror("CPU#0 PC %06X - Flip screen unknown bits: %04X\n", m_maincpu->pc(), data); } /*************************************************************************** Banked Palette RAM. Format is xBBBBBGGGGRRRRR ***************************************************************************/ void suna16_state::video_start() { m_paletteram = std::make_unique(m_palette->entries()); save_item(NAME(m_color_bank)); } READ16_MEMBER(suna16_state::paletteram_r) { return m_paletteram[offset + m_color_bank * 256]; } WRITE16_MEMBER(suna16_state::paletteram_w) { offset += m_color_bank * 256; data = COMBINE_DATA(&m_paletteram[offset]); m_palette->set_pen_color( offset, pal5bit(data >> 0),pal5bit(data >> 5),pal5bit(data >> 10)); } /*************************************************************************** Sprites Drawing ***************************************************************************/ void suna16_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint16_t *sprites, int gfx) { int max_x = m_screen->width() - 8; int max_y = m_screen->height() - 8; for ( int offs = 0xfc00/2; offs < 0x10000/2 ; offs += 4/2 ) { int srcpg, srcx,srcy, dimx,dimy; int tile_x, tile_xinc, tile_xstart; int tile_y, tile_yinc; int dx, dy; int flipx, y0; int y = sprites[ offs + 0 + 0x00000 / 2 ]; int x = sprites[ offs + 1 + 0x00000 / 2 ]; int dim = sprites[ offs + 0 + 0x10000 / 2 ]; int bank = (x >> 12) & 0xf; srcpg = ((y & 0xf000) >> 12) + ((x & 0x0200) >> 5); // src page srcx = ((y >> 8) & 0xf) * 2; // src col srcy = ((dim >> 0) & 0xf) * 2; // src row switch ( (dim >> 4) & 0xc ) { case 0x0: dimx = 2; dimy = 2; y0 = 0x100; break; case 0x4: dimx = 4; dimy = 4; y0 = 0x100; break; case 0x8: dimx = 2; dimy = 32; y0 = 0x130; break; default: case 0xc: dimx = 4; dimy = 32; y0 = 0x120; break; } if (dimx==4) { flipx = srcx & 2; srcx &= ~2; } else { flipx = 0; } x = (x & 0xff) - (x & 0x100); y = (y0 - (y & 0xff) - dimy*8 ) & 0xff; if (flipx) { tile_xstart = dimx-1; tile_xinc = -1; } else { tile_xstart = 0; tile_xinc = +1; } tile_y = 0; tile_yinc = +1; for (dy = 0; dy < dimy * 8; dy += 8) { tile_x = tile_xstart; for (dx = 0; dx < dimx * 8; dx += 8) { int addr = (srcpg * 0x20 * 0x20) + ((srcx + tile_x) & 0x1f) * 0x20 + ((srcy + tile_y) & 0x1f); int tile = sprites[ addr + 0x00000 / 2 ]; int attr = sprites[ addr + 0x10000 / 2 ]; int sx = x + dx; int sy = (y + dy) & 0xff; int tile_flipx = tile & 0x4000; int tile_flipy = tile & 0x8000; if (flipx) tile_flipx = !tile_flipx; if (flip_screen()) { sx = max_x - sx; sy = max_y - sy; tile_flipx = !tile_flipx; tile_flipy = !tile_flipy; } m_gfxdecode->gfx(gfx)->transpen(bitmap,cliprect, (tile & 0x3fff) + bank*0x4000, attr + (m_color_bank << 4), tile_flipx, tile_flipy, sx, sy,15 ); tile_x += tile_xinc; } tile_y += tile_yinc; } } } /*************************************************************************** Screen Drawing ***************************************************************************/ uint32_t suna16_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { /* Suna Quiz indicates the background is the last pen */ bitmap.fill(0xff, cliprect); draw_sprites(bitmap, cliprect, m_spriteram, 0); return 0; } uint32_t suna16_state::screen_update_bestbest(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int layers_ctrl = -1; #ifdef MAME_DEBUG if (machine().input().code_pressed(KEYCODE_Z)) { int msk = 0; if (machine().input().code_pressed(KEYCODE_Q)) msk |= 1; if (machine().input().code_pressed(KEYCODE_W)) msk |= 2; if (msk != 0) layers_ctrl &= msk; } #endif /* Suna Quiz indicates the background is the last pen */ bitmap.fill(0xff, cliprect); if (layers_ctrl & 1) draw_sprites(bitmap, cliprect, m_spriteram, 0); if (layers_ctrl & 2) draw_sprites(bitmap, cliprect, m_spriteram2, 1); return 0; }