summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/ssv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/ssv.c')
-rw-r--r--src/mame/video/ssv.c1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/src/mame/video/ssv.c b/src/mame/video/ssv.c
new file mode 100644
index 00000000000..f50c87828c7
--- /dev/null
+++ b/src/mame/video/ssv.c
@@ -0,0 +1,1169 @@
+/***************************************************************************
+
+ -= Seta, Sammy, Visco (SSV) System =-
+
+ driver by Luca Elia (l.elia@tin.it)
+
+ This hardware only generates sprites. But they're of various types,
+ including some large "floating tilemap" ones.
+
+ Sprites RAM is 0x40000 bytes long. The first 0x2000 bytes hold a list
+ of sprites to display (the list can be made shorter using an end-of-list
+ marker).
+
+ Each entry in the list (8 bytes) is a multi-sprite (e.g it tells the
+ hardware to display up to 32 single-sprites).
+
+ The list looks like this:
+
+ Offset: Bits: Value:
+
+ 0.h f--- ---- ---- ---- Shadow
+ -edc ---- ---- ---- Each bit enables 2 bitplanes*
+ ---- ba-- ---- ---- X Size (1,2,4,8 tiles)
+ ---- --98 ---- ---- Y Size (1,2,4,8 tiles)
+ ---- ---- 765- ---- Index of a scroll to apply to the single-sprite(s)
+ ---- ---- ---4 3210 Number of single-sprites, minus 1
+
+ 2.h f--- ---- ---- ---- List end
+ -edc ba98 7654 3210 Offset of the single-sprite(s) data
+
+ 4.h fedc ba-- ---- ----
+ ---- --98 7654 3210 X displacement (ignored by tilemap sprites?)
+
+ 6.h fedc ba-- ---- ----
+ ---- --98 7654 3210 Y displacement (ignored by tilemap sprites?)
+
+
+* bit c, which enables/disables the 2 high order bitplanes (256 / 64 color tiles)
+ is the only one implemented. Needed by keithlcy (logo), drifto94 (wheels).
+
+ A single-sprite can be:
+
+ 1. a rectangle of tiles (only 1 tile code needs to be specified)
+ 2. a row of tiles of a tilemap in ram. The row is (always?) as wide
+ as the screen and 64 pixels tall.
+
+ Rectangle case(1):
+ Offset: Bits: Value:
+
+ 0.h Code (low bits)
+
+ 2.h f--- ---- ---- ---- Flip X
+ -e-- ---- ---- ---- Flip Y
+ --dc ba-- ---- ---- Code (high bits)
+ ---- --9- ---- ---- Code? Color?
+ ---- ---8 7654 3210 Color code (64 color steps)
+
+ 4.h f--- ---- ---- ---- Shadow
+ -edc ---- ---- ---- Each bit enables 2 bitplanes*
+ ---- ba-- ---- ---- X Size (1,2,4,8 tiles)
+ ---- --98 7654 3210 X
+
+ 6.h fedc ---- ---- ----
+ ---- ba-- ---- ---- Y Size (1,2,4 tiles) **
+ ---- --98 7654 3210 Y
+
+
+ Tilemap case(2):
+ Offset: Bits: Value:
+
+ 0.h fedc ba98 7654 3---
+ ---- ---- ---- -210 Scroll index (see below)
+
+ 2.h Always 0
+
+ 4.h fedc ba-- ---- ----
+ ---- --98 7654 3210 X?
+
+ 6.h fedc ---- ---- ----
+ ---- ba-- ---- ---- **
+ ---- --98 7654 3210 Y
+
+** ? both bits set means "Row Sprite" if the single-sprite type hasn't been
+ specified in the sprites list ?
+
+ There are 8 scroll values for the tilemap sprites, in the
+ 1c0000-1c003f area (each scroll value uses 8 bytes):
+
+ Offset: Bits: Value:
+
+ 0.h Scroll X
+
+ 2.h Scroll Y
+
+ 4.h Priority ? (0000, 0401, 0440, 057f, 05ff)
+
+ 6.h fed- ---- ---- ---- Tilemap width (games only use 1 -> $200, 2 -> $400)
+ ---c ---- ---- ---- ?
+ ---- b--- ---- ---- Shadow
+ ---- -a98 ---- ---- Each bit enables 2 bitplanes*
+ ---- ---- 7654 3210 ? some games leave it to 0, others
+ use e.g 28 for scroll 0, 29 for
+ scroll 1, 2a etc.
+
+ Where scroll x&y refer to a virtual $8000 x $200 tilemap (filling the
+ whole spriteram) made of 16x16 tiles. A tile uses 4 bytes:
+
+ Offset: Bits: Value:
+
+ 0.h Code (low bits)***
+
+ 2.h f--- ---- ---- ---- Flip X
+ -e-- ---- ---- ---- Flip Y
+ --dc ba-- ---- ---- Code (high bits)
+ ---- --9- ---- ---- Code? Color?
+ ---- ---8 7654 3210 Color code (64 color steps)
+
+ The tilemap is stored in ram by column.
+
+*** The tiles size is (always?) 16x16 so Code and Code+1 are used.
+
+
+ Note that there is a "background layer": a series of tilemap sprites
+ that fill up the screen and use scroll 0 as the source tilemap are
+ always displayed before the sprites in the sprites list.
+
+ Shadows:
+
+ The low bits of the pens from a "shadowing" tile (regardless of color code)
+ substitute the top bits of the color index (0-7fff) in the frame buffer.
+ The number of low bits from the "shadowing tile" is 4 or 2, depending on
+ bit 7 of 1c0076.
+
+Note: press Z to show some info on each sprite (debug builds only)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "seta.h"
+#ifdef MAME_DEBUG
+#include "ui.h"
+#endif
+
+static int shadow_pen_mask, shadow_pen_shift;
+
+static void ssv_drawgfx( mame_bitmap *bitmap, const gfx_element *gfx,
+ UINT32 code,UINT32 color,int flipx,int flipy,int x0,int y0,
+ const rectangle *cliprect, int shadow )
+{
+ UINT8 *source, *addr, pen;
+ UINT16 *dest;
+ int sx, x1, dx;
+ int sy, y1, dy;
+
+ addr = (code % gfx->total_elements) * gfx->char_modulo + gfx->gfxdata;
+ color = gfx->color_granularity * (color % gfx->total_colors);
+
+ if ( flipx ) { x1 = x0-1; x0 += gfx->width-1; dx = -1; }
+ else { x1 = x0 + gfx->width; dx = 1; }
+
+ if ( flipy ) { y1 = y0-1; y0 += gfx->height-1; dy = -1; }
+ else { y1 = y0 + gfx->height; dy = 1; }
+
+#define SSV_DRAWGFX(SETPIXELCOLOR) \
+ for ( sy = y0; sy != y1; sy += dy ) \
+ { \
+ if ( sy >= cliprect->min_y && sy <= cliprect->max_y ) \
+ { \
+ source = addr; \
+ dest = BITMAP_ADDR16(bitmap, sy, 0); \
+ \
+ for ( sx = x0; sx != x1; sx += dx ) \
+ { \
+ pen = *source++; \
+ \
+ if ( pen && sx >= cliprect->min_x && sx <= cliprect->max_x ) \
+ SETPIXELCOLOR \
+ } \
+ } \
+ \
+ addr += gfx->line_modulo; \
+ }
+
+ if (shadow)
+ {
+ SSV_DRAWGFX( { dest[sx] = ((dest[sx] & shadow_pen_mask) | (pen << shadow_pen_shift)) & 0x7fff; } )
+ }
+ else
+ {
+ SSV_DRAWGFX( { dest[sx] = (color + pen) & 0x7fff; } )
+ }
+}
+
+
+VIDEO_START( ssv )
+{
+ machine->gfx[0]->color_granularity = 64; /* 256 colour sprites with palette selectable on 64 colour boundaries */
+}
+
+VIDEO_START( eaglshot )
+{
+ video_start_ssv(machine);
+
+ eaglshot_gfxram = (UINT16*)auto_malloc(16 * 0x40000);
+ eaglshot_dirty_tile = (char*)auto_malloc(16 * 0x40000 / (16*8));
+}
+
+static tilemap *gdfs_tmap;
+
+static TILE_GET_INFO( get_tile_info_0 )
+{
+ UINT16 tile = gdfs_tmapram[tile_index];
+ SET_TILE_INFO(3, tile, 0, TILE_FLIPXY( tile >> 14 ));
+}
+
+WRITE16_HANDLER( gdfs_tmapram_w )
+{
+ COMBINE_DATA(&gdfs_tmapram[offset]);
+ tilemap_mark_tile_dirty(gdfs_tmap, offset);
+}
+
+VIDEO_START( gdfs )
+{
+ video_start_ssv(machine);
+
+ machine->gfx[2]->color_granularity = 64; /* 256 colour sprites with palette selectable on 64 colour boundaries */
+
+ eaglshot_gfxram = (UINT16*)auto_malloc(4 * 0x100000);
+ eaglshot_dirty_tile = (char*)auto_malloc(4 * 0x100000 / (16*8));
+
+ gdfs_tmap = tilemap_create( get_tile_info_0, tilemap_scan_rows,
+ TILEMAP_TYPE_PEN, 16,16, 0x100,0x100 );
+
+ tilemap_set_transparent_pen(gdfs_tmap, 0);
+}
+
+/* Scroll values + CRT controller registers */
+UINT16 *ssv_scroll;
+
+int ssv_special; // game specific kludges
+
+int ssv_tile_code[16];
+
+int ssv_sprites_offsx, ssv_sprites_offsy;
+int ssv_tilemap_offsx, ssv_tilemap_offsy;
+
+UINT16 *eaglshot_gfxram, *gdfs_tmapram, *gdfs_tmapscroll;
+char eaglshot_dirty, *eaglshot_dirty_tile;
+
+/***************************************************************************
+
+ CRT controller, registers that are read
+ (vblank etc.?)
+
+ 1c0000 (wait for bit .. to become ..)
+
+ keithlcy: bit D, 0 -> 1
+
+ mslider: bit A, 0
+
+ hypreact:
+ meosism:
+ srmp7:
+ sxyreact:
+ ultrax: bit F, 0
+
+ twineag2:
+ hypreac2: bit C, 1 -> 0
+ bit F, 0
+
+ janjans1:
+ srmp4:
+ survarts: No checks
+
+ ryorioh:
+ drifto94: bit D, 0 -> 1
+ bit A, 0
+
+
+ CRT controller, registers that are written
+ (resolution, visible area, flipping etc. ?)
+
+
+
+ 1c0060-7f:
+
+ drifto94: 0000 0025 00cd 01c6 - 0001 0013 0101 0106
+ 0300 0711 0500 0000 - 0015 5940 0000 0000
+ 03ea 5558 (flip)
+
+ dynagear: 002b 002c 00d4 01c6 - 0001 0012 0102 0106
+ 02fd 0000 0500 0000 - 0015 5940 0000 0000
+ ???? ???? (flip)
+
+ eaglshot: 0021 002a 00ca 01c6 - 0001 0016 00f6 0106
+ 0301 0000 0500 d000 - 0015 5940 0000 0000
+ ???? ???? (flip)
+
+ gdfs: 002b 002c 00d5 01c6 - 0001 0012 0102 0106
+ 03ec 0711 0500 0000 - 00d5 5950 0000 0000
+ 03ec 1557 (flip)
+
+ hypreact: 0021 0022 00cb 01c6 - 0001 000e 00fe 0106
+ 0301 0000 0500 c000 - 0015 5140 0000 0000
+ 03f0 5558 (flip)
+
+ hypreac2: 0021 0022 00cb 01c6 - 0001 000e 00fe 0106
+ 0301 0000 05ff c000 - 0015 5140 0000 0000
+ 03ea 5558 (flip)
+
+ janjans1: 0021 0023 00cb 01c6 - 0001 000f 00fe 0106
+ 0300 0000 0500 c000 - 0015 5140 0000 0000
+ same! (flip)
+
+ keithlcy: 002b 0025 00cd 01c6 - 0001 0013 0101 0106
+ 0300 0711 0500 0000 - 0015 5940 0000 0000
+ 03ea 5558 (flip)
+
+ meosism: 002b 002c 00d5 01c6 - 0001 0012 00fe 0106
+ 0301 0000 0500 c000 - 0015 5140 0000 0000
+ (no flip)
+
+ mslider: 0021 0026 00d6 01c6 - 0001 000e 00fe 0106
+ 03f1 0711 5550 c080 - 0015 5940 0000 0000
+ 0301 0500 (flip)
+
+ ryorioh: 0021 0023*00cb 01c6 - 0001 000f 00fe 0106
+ 0300 0000 0500 c000 - 0015 5140 0000 0000
+ 03ed 5558 (flip) *0025
+
+ srmp4: 002b 002c 00d4 01c6 - 0001 0012 0102 0106
+ 0301 0711 0500 0000 - 0015 4940 0000 0000
+ ffe8 5557 (flip)
+
+ srmp7: 002b 002c 00d4 01c6 - 0001 000e 00fd 0106
+ 0000 0000 e500 0000 - 0015 7140 0000 0000
+ 02f2 b558 (flip)
+
+ stmblade: 0021 0026 00d6 01c6 - 0001 000e 00fe 0106
+ 03f1 0711 5550 c080 - 0015 5940 0000 0000 <- 711 becomes 0 during gameplay
+ 0301 0500 (flip)
+
+ survarts: 002b 002c 00d4 01c6 - 0001 0012 0102 0106
+ 0301 0000 0500 0000 - 0015 5140 0000 0000
+ 03e9 5558 (flip)
+
+ sxyreact: 0021 0022 00cb 01c6 - 0001 000e 00fe 0106
+ 0301 0000 0500 c000 - 0015 5140 0000 0000
+ 03ef 5558 (flip)
+
+ sxyreac2: 0021 0023 00cb 01c6 - 0001 000e 00fe 0106
+ 0301 0000 0500 c000 - 0015 5140 0000 0000
+ ???? ???? (flip)
+
+ twineag2: 002b 002c 00d4 01c6 - 0001 0012 0102 0106
+ ffec 0000 e500 4000 - 0315 7940 0000 0000
+ ???? ???? (flip)
+
+ ultrax: 002b 002c 00d4 01c6 - 0001 0012 0102 0106
+ ffec 0000 e500 4000 - 0315 7940 0000 0000
+ 02fe b558 (flip)
+
+ vasara & 0021 0024 00cc 01c6 - 0001 000e 00fe 0106
+ vasara2: 03f1 0000 6500 c000 - 0015 5140 0000 0000
+ 0301 3558 (flip)
+
+
+***************************************************************************/
+
+READ16_HANDLER( ssv_vblank_r )
+{
+ if (video_screen_get_vblank(0))
+ return 0x2000 | 0x1000;
+ else
+ return 0x0000;
+}
+
+WRITE16_HANDLER( ssv_scroll_w )
+{
+ COMBINE_DATA(ssv_scroll + offset);
+
+/* offsets 60-7f: CRT Controller */
+
+}
+
+WRITE16_HANDLER( paletteram16_xrgb_swap_word_w )
+{
+ int r, g, b;
+ UINT16 data0, data1;
+
+ COMBINE_DATA(paletteram16 + offset);
+
+ offset &= ~1;
+
+ data0 = paletteram16[offset + 1];
+ data1 = paletteram16[offset];
+
+ r = data0 & 0xff;
+ g = data1 >> 8;
+ b = data1 & 0xff;
+
+ palette_set_color(Machine, offset>>1, MAKE_RGB(r, g, b));
+}
+
+/***************************************************************************
+
+
+ Sprites Drawing
+
+[mslider]
+"Insert coins" 101f60: 0006 0825 00b0 000c
+ 104128: 1a3a 0000 63d4 0400 (16x16)
+
+Character tilemap 100080: 000f 0410 0000 0000
+ 102080: 0002 0000 6200 0c00
+ 0002 0000 6200 0c40
+ 0002 0000 6200 0c80
+ 0002 0000 6200 0cc0
+ 0002 0000 6200 0d00
+ ..
+ 0002 0000 6200 0fc0
+ 1c0010: 73f0 00f1 05ff 4600
+
+
+[hypreact]
+intro 100140: 6003 04ca 0000 0000 (tilemap sprite)
+ 102650: 0003 0000 0000 0c00
+ 0003 0000 0000 0c40
+ 0003 0000 0000 0c80
+ 0003 0000 0000 0cc0
+ 1c0018: 15f8 00e8 057f 2600
+
+game 100058: 6003 00db 0050 0040 (normal sprite)
+ 1006d8: 037c 001b 6400 0400
+
+tiles 100060: 6019 0120 0014 000a (sometimes 6619!)
+ 100900: 0a8c 0012 6400 0420 (32x16)
+ 0400 0012 6400 0800 (32x32)
+ ...
+
+[hypreac2]
+"warning" 100f60: 6106 3893 0068 00c8 (128x32)
+ 11c498: 00e0 00b2 6c00 0800
+ 0000 0000 0000 0000
+text below "warning" 100f70: 6016 389b 0048 00b0 ((16 or 8)x8)
+ 11c4d8: 0054 0007 6000 0000
+
+black regions 100af8: 6303 2d64 0000 03f8 (yoffs should be used)
+ 116b20: 0004 0000 0000 0fa0 <- move up and down
+ 0004 0000 0000 0fe0
+ 0004 0000 0000 0ce0
+ 0004 0000 0000 0d20
+ 1c0020: 6c00 00ef 057f 2600
+
+"credits" 1012f0: 6007 440e 00e0 0008 (16x8)
+ 122070: 0043 0006 6000 0000
+
+tiles 100ce8: 6111 3464 0008 0030 (16x32,empty tile frames)
+ 11a320: 0460 006b 6110 0800
+ 0460 006b 6100 0800
+ ..
+ 100d68: 6205 34de 0008 0030 (16x32, tiles on frames)
+ 11a6f0: 050c 0059 6000 0800
+ 04c0 005a 6010 0800
+ 04d4 005a 6020 0800
+ 0500 0059 6030 0800
+ ..
+ 100cf8: 6105 348a 0008 fff8 (16x16 x 2x3, big tiles below)
+ 11a450: 61d6 0059 6000 0420
+ 61f2 0059 6000 0410
+ 6212 0059 6000 0400
+ 61d8 0059 6010 0420
+ 61f4 0059 6010 0410
+ 6214 0059 6010 0400
+
+[keithlcy]
+high scores 101030: 717f 40c0 0010 0000
+ 120600: 0000 0000 00c0 0025 (16x16)
+ 0000 0000 00d0 0025
+ ..
+ 0000 0000 0000 ffff (ysize should be 16!)
+ 0000 0000 0010 ffff
+ ..
+
+K of "KEITH" 101180: 610e 4600 0020 0090
+ 123000: 4ef4 016a 0000 0040 (16x16)
+ 4ef6 016a 0010 0040
+ ..
+
+floating robot (demo) 101000: 713d 4000 03b0 0088
+ 120000: ..
+ 71f6 0020 0000 0030
+ 71f8 0020 0010 0030
+ ..
+
+cityscape 100030: 7304 1600 0000 007c (yoffs should not be used)
+ 10b000: 0001 0000 0200 0000
+ 0001 0000 0200 0040
+ 0001 0000 0200 0080
+ 0001 0000 0200 00c0
+ 1c0008: 0800 00f2 05ff 5729
+
+
+[meosism]
+shadows 100100: 701f 051b 0041 0020 (16x16 shadow)
+ 1028d8: 05aa 0030 f000 0470
+
+[srmp4]
+logo 100000: 6303 1680 0180 0078 (yoffs?)
+ 10b400: 0001 0000 0000 0060
+ 0001 0000 0000 0020
+ 0001 0000 0000 ffe0
+ 0001 0000 0000 ffa0
+ 1c0008: 0800 00ec 05ff 5629
+
+tiles 100088: 6103 25b7 0028 000a (16x16)
+ 112db8: f4aa 0009 03f8 0018
+ f4a8 0009 0008 0018
+ f4ba 0009 03f8 0008
+ f4bc 0009 0008 0008
+
+[survarts]
+tilemap 100030: 6303 2048 0000 0000
+ 110240: 0002 0000 0160 03fc
+ 0002 0000 0160 003c
+ 0002 0000 0160 007c
+ 0002 0000 0160 00bc
+ 1c0010: 0c2e 01f5 05ff 4628
+
+player 100030: 611f 1da0 0000 fffc
+ 10ed00: eb16 200f 005c fffa (16x16)
+
+"push start" 100130: 601d 1920 0048 0000
+ 10c900: 0441 0004 0000 004c (16x8)
+
+[drifto94]
+car shadow 100010: 8137 0640 0080 0030
+ 103200: ..
+ 544a 21e4 0030 0030 (16x16)
+
+writings on finish 100130: 6109 4840 004e 0058 "good work"
+ 124200: ee6e 0135 0024 0000 (16x16)
+ 100158: 611e 4860 0058 0020 "you have proved yOur"..
+ 124300: ee92 0137 0024 0014 (16x16)
+ ..
+ ee7e 0137 fff4 0000 (16x16!!) ; 'O'
+ ..
+
+[ultrax]
+sprite begin of lev1 100010: 6b60 4280 0016 00a0
+ 121400: 51a0 0042 6800 0c00 (64x64)
+
+[eaglshot]
+title logo 100040: 001b 2920 0048 00e0
+ 114900: 2130 0060 7018 0fd0 (16x64)
+
+play 100020: 0003 290c 0000 0000
+ 114860: 0003 0000 03f0 0ce0 (tilemap)
+
+sammy logo 100020: 0003 1000 0000 0000
+ 108000: 0001 0000 4380 0ce0 (tilemap)
+
+From the above some noteworthy cases are:
+
+ 101f60: 0006 0825 00b0 000c
+ 104128: 1a3a 0000 63d4 0400 consider y size
+
+ 101030: 717f 40c0 0010 0000
+ 120600: 0000 0000 0000 ffff ignore y size & depth
+
+ 100158: 611e 4860 0058 0020
+ 124300 ee7e 0137 fff4 0000 ignore x size & depth
+
+ 100f60: 6106 3893 0068 00c8
+ 11c498: 00e0 00b2 6c00 0800 consider x size & y size
+
+ 100100: 701f 051b 0041 0020
+ 1028d8: 05aa 0030 f000 0470 consider shadow (16x16 shadow)
+
+ 100010: 6b60 4280 0016 00a0
+ 121400: 51a0 0042 6800 0c00 (64x64)
+
+ 100140: 6003 04ca 0000 0000 tilemap
+ 102650: 0003 0000 0000 0c00
+
+ 100080: 000f 0410 0000 0000 tilemap
+ 102080: 0002 0000 6200 0c00
+
+**************************************************************************/
+
+/* Draw a tilemap sprite */
+
+static void draw_row(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int sx, int sy, int scroll)
+{
+ rectangle clip;
+ int attr, code, color, mode, size, page, shadow;
+ int x, x1, sx1, flipx, xnum, xstart, xend, xinc;
+ int y, y1, sy1, flipy, ynum, ystart, yend, yinc;
+ UINT16 *s3;
+
+ xnum = 0x20; // width in tiles (screen-wide)
+ ynum = 0x8; // height in tiles (always 64 pixels?)
+
+ scroll &= 0x7; // scroll register index
+
+ /* Sign extend the position */
+ sx = 0;
+ sy = (sy & 0x1ff) - (sy & 0x200);
+
+ /* Set up a clipping region for the tilemap slice .. */
+
+ clip.min_x = sx;
+ clip.max_x = sx + xnum * 0x10 - 1;
+ clip.min_y = sy;
+ clip.max_y = sy + ynum * 0x8 - 1;
+
+ /* .. and clip it against the visible screen */
+
+ if (clip.min_x > cliprect->max_x) return;
+ if (clip.min_y > cliprect->max_y) return;
+
+ if (clip.max_x < cliprect->min_x) return;
+ if (clip.max_y < cliprect->min_y) return;
+
+ if (clip.min_x < cliprect->min_x) clip.min_x = cliprect->min_x;
+ if (clip.max_x > cliprect->max_x) clip.max_x = cliprect->max_x;
+
+ if (clip.min_y < cliprect->min_y) clip.min_y = cliprect->min_y;
+ if (clip.max_y > cliprect->max_y) clip.max_y = cliprect->max_y;
+
+ /* Get the scroll data */
+
+ x = ssv_scroll[ scroll * 4 + 0 ]; // x scroll
+ y = ssv_scroll[ scroll * 4 + 1 ]; // y scroll
+ // ssv_scroll[ scroll * 4 + 2 ]; // Priority ?
+ mode = ssv_scroll[ scroll * 4 + 3 ]; // shadow, depth etc.
+
+ // Priority ?
+ if ( (ssv_scroll[ scroll * 4 + 2 ] < ssv_scroll[ 0 * 4 + 2 ]) )
+ return;
+
+ /* How is the background layer disabled ? */
+ if ((mode & 0x0700) == 0) return;
+
+ shadow = (mode & 0x0800);
+
+ /* Decide the actual size of the tilemap. $200 and $400 pixels
+ are the only values actually used AFAIK */
+ size = 1 << (8 + ((mode & 0xe000) >> 13));
+ page = (x & 0x7fff) / size;
+
+ /* Given a fixed scroll value, the portion of tilemap displayed changes
+ with the sprite postion */
+ x += sx;
+ y += sy;
+
+ /* Tweak the scroll values (game specific) */
+ x += ssv_tilemap_offsx;
+ y += ssv_tilemap_offsy;
+
+ /* Draw the rows */
+
+ x1 = x;
+ y1 = y;
+ sx1 = sx - (x & 0xf);
+ sy1 = sy - (y & 0xf);
+
+ for (sx=sx1,x=x1; sx <= clip.max_x; sx+=0x10,x+=0x10)
+ {
+ for (sy=sy1,y=y1; sy <= clip.max_y; sy+=0x10,y+=0x10)
+ {
+ int tx, ty, gfx;
+
+ s3 = &spriteram16[ page * (size * ((0x1000/0x200)/2)) +
+ ((x & ((size -1) & ~0xf)) << 2) +
+ ((y & ((0x200-1) & ~0xf)) >> 3) ];
+
+ code = s3[0]; // code high bits
+ attr = s3[1]; // code low bits + color
+
+ /* Code's high bits are scrambled */
+ code += ssv_tile_code[(attr & 0x3c00)>>10];
+ flipy = (attr & 0x4000);
+ flipx = (attr & 0x8000);
+ color = attr;
+
+ /* Select 256 or 64 color tiles */
+ gfx = ((mode & 0x0100) ? 0 : 1);
+
+ /* Force 16x16 tiles ? */
+ if (flipx) { xstart = 1-1; xend = -1; xinc = -1; }
+ else { xstart = 0; xend = 1; xinc = +1; }
+
+ if (flipy) { ystart = 2-1; yend = -1; yinc = -1; }
+ else { ystart = 0; yend = 2; yinc = +1; }
+
+ /* Draw a tile (16x16) */
+ for (tx = xstart; tx != xend; tx += xinc)
+ {
+ for (ty = ystart; ty != yend; ty += yinc)
+ {
+ ssv_drawgfx( bitmap, machine->gfx[gfx],
+ code++,
+ color,
+ flipx, flipy,
+ sx + tx * 16, sy + ty * 8,
+ &clip, shadow );
+ } /* ty */
+ } /* tx */
+
+ } /* sy */
+ } /* sx */
+
+}
+
+/* Draw the "background layer" using multiple tilemap sprites */
+
+static void draw_layer(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int nr)
+{
+ int sy;
+ for ( sy = 0; sy <= machine->screen[0].visarea.max_y; sy += 0x40 )
+ draw_row(machine, bitmap, cliprect, 0, sy, nr);
+}
+
+/* Draw sprites in the sprites list */
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect)
+{
+ /* Sprites list */
+
+ UINT16 *s1 = spriteram16;
+ UINT16 *end1 = spriteram16 + 0x02000/2;
+ UINT16 *end2 = spriteram16 + 0x40000/2;
+ UINT16 *s2;
+
+ for ( ; s1 < end1; s1+=4 )
+ {
+ int attr, code, color, num, sprite;
+ int sx, x, xoffs, flipx, xnum, xstart, xend, xinc;
+ int sy, y, yoffs, flipy, ynum, ystart, yend, yinc;
+ int mode,global_depth,global_xnum,global_ynum;
+
+ mode = s1[ 0 ];
+ sprite = s1[ 1 ];
+ xoffs = s1[ 2 ];
+ yoffs = s1[ 3 ];
+
+ /* Last sprite */
+ if (sprite & 0x8000) break;
+
+ /* Single-sprite address */
+ s2 = &spriteram16[ (sprite & 0x7fff) * 4 ];
+
+ /* Every single sprite is offset by x & yoffs, and additionally
+ by one of the 8 x & y offsets in the 1c0040-1c005f area */
+
+ xoffs += ssv_scroll[((mode & 0x00e0) >> 4) + 0x40/2];
+ yoffs += ssv_scroll[((mode & 0x00e0) >> 4) + 0x42/2];
+
+ /* Number of single-sprites (1-32) */
+ num = (mode & 0x001f) + 1;
+ global_ynum = (mode & 0x0300) << 2;
+ global_xnum = (mode & 0x0c00);
+ global_depth = (mode & 0xf000);
+
+ for( ; num > 0; num--,s2+=4 )
+ {
+ int depth, local_depth, local_xnum, local_ynum;
+
+ if (s2 >= end2) break;
+
+ sx = s2[ 2 ];
+ sy = s2[ 3 ];
+
+ local_depth = sx & 0xf000;
+ local_xnum = sx & 0x0c00;
+ local_ynum = sy & 0x0c00;
+
+ if (ssv_scroll[0x76/2] & 0x4000)
+ {
+ xnum = local_xnum;
+ ynum = local_ynum;
+ depth = local_depth;
+ }
+ else
+ {
+ xnum = global_xnum;
+ ynum = global_ynum;
+ depth = global_depth;
+ }
+
+ if ( s2[0] <= 7 && s2[1] == 0 && xnum == 0 && ynum == 0x0c00)
+ {
+ // Tilemap Sprite
+ int scroll;
+
+ scroll = s2[ 0 ]; // scroll index
+
+ switch( ssv_scroll[0x7a/2] )
+ {
+ case 0x4940: sy += 0x60; break; // srmp4
+ case 0x5940: sy -= 0x20; break; // drifto94, dynagear, eaglshot, keithlcy, mslider, stmblade
+ case 0x5950: sy += 0xdf; break; // gdfs
+ case 0x7940: sy -= 0x10; break; // ultrax, twineag2
+ }
+
+ draw_row(machine, bitmap, cliprect, sx, sy, scroll);
+ }
+ else
+ {
+ // "Normal" Sprite
+/*
+ hot spots:
+ "warning" in hypreac2 has mode & 0x0100 and is not 16x16
+ keithlcy high scores has mode & 0x0100 and y & 0x0c00 can be 0x0c00
+ drifto94 "you have proved yOur".. has mode & 0x0100 and x & 0x0c00 can be 0x0c00
+ ultrax (begin of lev1): 100010: 6b60 4280 0016 00a0
+ 121400: 51a0 0042 6800 0c00 needs to be a normal sprite
+*/
+
+ int shadow, gfx;
+ if (s2 >= end2) break;
+
+ code = s2[0]; // code high bits
+ attr = s2[1]; // code low bits + color
+
+ /* Code's high bits are scrambled */
+ code += ssv_tile_code[(attr & 0x3c00)>>10];
+ flipy = (attr & 0x4000);
+ flipx = (attr & 0x8000);
+ color = attr;
+
+ /* Select 256 or 64 color tiles */
+ gfx = (depth & 0x1000) ? 0 : 1;
+ shadow = (depth & 0x8000);
+
+ /* Single-sprite tile size */
+ xnum = 1 << (xnum >> 10); // 1, 2, 4 or 8 tiles
+ ynum = 1 << (ynum >> 10); // 1, 2, 4 tiles (8 means tilemap sprite?)
+
+ if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; }
+ else { xstart = 0; xend = xnum; xinc = +1; }
+
+ if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; }
+ else { ystart = 0; yend = ynum; yinc = +1; }
+
+ /* Apply global offsets */
+ sx += xoffs;
+ sy += yoffs;
+
+ /* Sign extend the position */
+ sx = (sx & 0x1ff) - (sx & 0x200);
+ sy = (sy & 0x1ff) - (sy & 0x200);
+
+ if (ssv_scroll[0x74/2] == 0x6500) // vasara
+ sy = 0xe8 - sy;
+
+ if (ssv_scroll[0x74/2] & 0x8000) // srmp7, twineag2, ultrax
+ {
+ if (ssv_scroll[0x76/2] & 0x4000) { // twineag2, ultrax
+ sx = ssv_sprites_offsx + sx - (xnum-1) * 8;
+ sy = ssv_sprites_offsy + sy - (ynum * 8) / 2;
+ } else { // srmp7
+ sx = ssv_sprites_offsx + sx;
+ sy = ssv_sprites_offsy + sy;
+ }
+ }
+ else if (ssv_scroll[0x76/2] & 0x1000) // eaglshot
+ {
+ sx = ssv_sprites_offsx + sx - (xnum-1) * 8;
+ sy = ssv_sprites_offsy - sy - (ynum * 8) / 2; // sy is the sprite center
+ }
+ else
+ {
+ sx = ssv_sprites_offsx + sx;
+ sy = ssv_sprites_offsy - sy - (ynum-1) * 8;
+ }
+
+ /* Draw the tiles */
+
+ for (x = xstart; x != xend; x += xinc)
+ {
+ for (y = ystart; y != yend; y += yinc)
+ {
+ ssv_drawgfx( bitmap, machine->gfx[gfx],
+ code++,
+ color,
+ flipx, flipy,
+ sx + x * 16, sy + y * 8,
+ cliprect, shadow );
+ }
+ }
+
+ #ifdef MAME_DEBUG
+ if (input_code_pressed(KEYCODE_Z)) /* Display some info on each sprite */
+ { char buf[10];
+ sprintf(buf, "%02X",/*(s2[2] & ~0x3ff)>>8*/mode>>8);
+ ui_draw_text(buf, sx, sy);
+ }
+ #endif
+
+ } /* sprite type */
+
+ } /* single-sprites */
+
+ } /* sprites list */
+}
+
+
+/***************************************************************************
+
+
+ Screen Drawing
+
+
+***************************************************************************/
+
+VIDEO_UPDATE( eaglshot )
+{
+ int tile;
+
+ // Decode tiles from ram
+ if (eaglshot_dirty)
+ {
+ eaglshot_dirty = 0;
+
+ for (tile = 0; tile < (16 * 0x40000 / (16*8)); tile++)
+ {
+ if (eaglshot_dirty_tile[tile])
+ {
+ eaglshot_dirty_tile[tile] = 0;
+
+ decodechar(machine->gfx[0], tile, (UINT8 *)eaglshot_gfxram, machine->drv->gfxdecodeinfo[0].gfxlayout);
+ decodechar(machine->gfx[1], tile, (UINT8 *)eaglshot_gfxram, machine->drv->gfxdecodeinfo[1].gfxlayout);
+ }
+ }
+ }
+
+ video_update_ssv(machine, screen, bitmap, cliprect);
+ return 0;
+}
+
+/*
+ Sprites RAM is 0x80000 bytes long. The first 0x2000? bytes hold a list
+ of sprites to display (the list can be made shorter using an end-of-list
+ marker).
+
+ Each entry in the list (16 bytes) is a multi-sprite (e.g it tells the
+ hardware to display several single-sprites).
+
+ The list looks like this:
+
+ Offset: Bits: Value:
+
+ 0.h fedc ba-- ---- ----
+ ---- --98 7654 3210 X displacement
+
+ 2.h fedc ba-- ---- ----
+ ---- --98 7654 3210 Y displacement
+
+ 4.h f--- ---- ---- ---- List end
+ -edc ba98 7654 3210 Offset of the single-sprite(s) data
+
+ 0.h Number of single-sprites (how many bits?)
+
+ A single-sprite is:
+
+ Offset: Bits: Value:
+
+ 0.h Code
+
+ 2.h f--- ---- ---- ---- Flip X
+ -e-- ---- ---- ---- Flip Y
+ ---- -a-- ---- ---- 0 = 256 color steps, 1 = 64 color steps
+ ---- --98 7654 3210 Color code
+
+ 4.h fedc ba-- ---- ----
+ ---- --98 7654 3210 X displacement
+
+ 6.h fedc ba-- ---- ----
+ ---- --98 7654 3210 Y displacement
+
+ 8.h fedc ba98 ---- ---- Y Size
+ ---- ---- 7654 3210 X Size
+
+ A.h fedc ba98 ---- ----
+ ---- ---- 7654 ---- Priority
+ ---- ---- ---- 32-- Y Tiles (1,2,4,8)
+ ---- ---- ---- --10 X Tiles (1,2,4,8)
+
+ C.h Unused
+
+ E.h Unused
+
+*/
+static void gdfs_draw_zooming_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int priority)
+{
+ /* Sprites list */
+
+ UINT16 *s1 = spriteram16_2;
+ UINT16 *end1 = spriteram16_2 + 0x02000/2;
+ UINT16 *s2;
+
+ priority <<= 4;
+
+ for ( ; s1 < end1; s1+=8/2 )
+ {
+ int attr, code, color, num, sprite, zoom, size;
+ int sx, x, xoffs, flipx, xnum, xstart, xend, xinc, xdim, xscale;
+ int sy, y, yoffs, flipy, ynum, ystart, yend, yinc, ydim, yscale;
+
+ xoffs = s1[ 0 ];
+ yoffs = s1[ 1 ];
+ sprite = s1[ 2 ];
+ num = s1[ 3 ] % 0x101;
+
+ /* Last sprite */
+ if (sprite & 0x8000) break;
+
+ /* Single-sprite address */
+ s2 = &spriteram16_2[ (sprite & 0x7fff) * 16/2 ];
+
+ for( ; num > 0; num--,s2+=16/2 )
+ {
+ code = s2[ 0 ];
+ attr = s2[ 1 ];
+ sx = s2[ 2 ];
+ sy = s2[ 3 ];
+ zoom = s2[ 4 ];
+ size = s2[ 5 ];
+
+ if (priority != (size & 0xf0))
+ break;
+
+ flipx = (attr & 0x8000);
+ flipy = (attr & 0x4000);
+ color = (attr & 0x0400) ? attr : attr * 4;
+
+ /* Single-sprite tile size */
+ xnum = 1 << ((size >> 0) & 3);
+ ynum = 1 << ((size >> 2) & 3);
+
+ xnum = (xnum + 1) / 2;
+
+ if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; }
+ else { xstart = 0; xend = xnum; xinc = +1; }
+
+ if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; }
+ else { ystart = 0; yend = ynum; yinc = +1; }
+
+ /* Apply global offsets */
+ sx += xoffs;
+ sy += yoffs;
+
+ /* Sign extend the position */
+ sx = (sx & 0x1ff) - (sx & 0x200);
+ sy = (sy & 0x1ff) - (sy & 0x200);
+
+ sy = -sy;
+
+ /* Use fixed point values (16.16), for accuracy */
+ sx <<= 16;
+ sy <<= 16;
+
+ xdim = ( ( ((zoom >> 0) & 0xff) + 1) << 16 ) / xnum;
+ ydim = ( ( ((zoom >> 8) & 0xff) + 1) << 16 ) / ynum;
+
+ xscale = xdim / 16;
+ yscale = ydim / 8;
+
+ /* Let's approximate to the nearest greater integer value
+ to avoid holes in between tiles */
+ if (xscale & 0xffff) xscale += (1<<16) / 16;
+ if (yscale & 0xffff) yscale += (1<<16) / 8;
+
+ /* Draw the tiles */
+
+ for (x = xstart; x != xend; x += xinc)
+ {
+ for (y = ystart; y != yend; y += yinc)
+ {
+ drawgfxzoom( bitmap, machine->gfx[2],
+ code++,
+ color,
+ flipx, flipy,
+ (sx + x * xdim) / 0x10000, (sy + y * ydim) / 0x10000,
+ cliprect, TRANSPARENCY_PEN, 0,
+ xscale, yscale
+ );
+ }
+ }
+
+ #ifdef MAME_DEBUG
+ if (input_code_pressed(KEYCODE_Z)) /* Display some info on each sprite */
+ {
+ char buf[10];
+ sprintf(buf, "%X",size);
+ ui_draw_text(buf, sx / 0x10000, sy / 0x10000);
+ }
+ #endif
+ } /* single-sprites */
+
+ } /* sprites list */
+}
+
+VIDEO_UPDATE( gdfs )
+{
+ int tile, pri;
+
+ video_update_ssv(machine, screen, bitmap, cliprect);
+
+ // Decode zooming sprites tiles from ram
+ if (eaglshot_dirty)
+ {
+ eaglshot_dirty = 0;
+
+ for (tile = 0; tile < (4 * 0x100000 / (16*8)); tile++)
+ {
+ if (eaglshot_dirty_tile[tile])
+ {
+ eaglshot_dirty_tile[tile] = 0;
+
+ decodechar(machine->gfx[2], tile, (UINT8 *)eaglshot_gfxram, machine->drv->gfxdecodeinfo[2].gfxlayout);
+ }
+ }
+ }
+
+ for (pri = 0; pri <= 0xf; pri++)
+ gdfs_draw_zooming_sprites(machine, bitmap, cliprect, pri);
+
+ tilemap_set_scrollx(gdfs_tmap,0,gdfs_tmapscroll[0x0c/2]);
+ tilemap_set_scrolly(gdfs_tmap,0,gdfs_tmapscroll[0x10/2]);
+ tilemap_draw(bitmap,cliprect, gdfs_tmap, 0, 0);
+
+ return 0;
+}
+
+static int enable_video;
+
+void ssv_enable_video(int enable)
+{
+ enable_video = enable;
+}
+
+VIDEO_UPDATE( ssv )
+{
+ if (ssv_scroll[0x76/2] & 0x0080)
+ {
+ // 4 bit shadows (mslider, stmblade)
+ shadow_pen_mask = 0x1fff;
+ shadow_pen_shift = 11;
+ }
+ else
+ {
+ // 2 bit shadows
+ shadow_pen_mask = 0x3fff;
+ shadow_pen_shift = 13;
+ }
+
+ /* The background color is the first one in the palette */
+ fillbitmap(bitmap,machine->pens[0], cliprect);
+
+ if (!enable_video) return 0;
+
+ draw_layer(machine, bitmap, cliprect, 0); // "background layer"
+
+ draw_sprites(machine, bitmap, cliprect); // sprites list
+ return 0;
+}