summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/seta2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/seta2.c')
-rw-r--r--src/mame/video/seta2.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/mame/video/seta2.c b/src/mame/video/seta2.c
new file mode 100644
index 00000000000..1f33316dd4f
--- /dev/null
+++ b/src/mame/video/seta2.c
@@ -0,0 +1,390 @@
+/***************************************************************************
+
+ -= Newer Seta Hardware =-
+
+ 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. All games write the sprites list
+ at offset 0x3000. Each entry in the list holds data for a multi-sprite
+ of up to 256 single-sprites. The list looks like this:
+
+ Offset: Bits: Value:
+
+ 0.w f--- ---- ---- ---- Last sprite
+ -edc ---- ---- ---- ?
+ ---c ---- ---- ---- 0 = Each sprite specifies its size, 1 = use the size in the following words
+ ---- b--- ---- ---- ?
+ ---- -a98 ---- ---- tile color depth
+ ---- ---- 7654 3210 Number of sprites - 1
+
+ 2.w fedc ---- ---- ---- Number of tiles?
+ ---- ba-- ---- ---- Number of tiles along X (1 << n)
+ ---- --98 7654 3210 X displacement
+
+ 4.w fedc ---- ---- ---- Number of tiles?
+ ---- ba-- ---- ---- Number of tiles along Y (1 << n)
+ ---- --98 7654 3210 Y displacement
+
+ 6.w f--- ---- ---- ---- Single-sprite(s) type: tile (0) or row of tiles (1)
+ -edc ba98 7654 3210 Offset of the single-sprite(s) data
+
+
+ A single-sprite can be a tile or some horizontal rows of tiles.
+
+ Tile case:
+
+ 0.w fedc ---- ---- ---- Number of tiles?
+ ---- ba-- ---- ---- Number of tiles along X (1 << n)
+ ---- --98 7654 3210 X
+
+ 2.w fedc ---- ---- ---- Number of tiles?
+ ---- ba-- ---- ---- Number of tiles along Y (1 << n)
+ ---- --98 7654 3210 Y
+
+ 4.w fedc ba98 765- ---- Color code (16 color steps)
+ ---- ---- ---4 ---- Flip X
+ ---- ---- ---- 3--- Flip Y
+ ---- ---- ---- -210 Code (high bits)
+
+ 6.w Code (low bits)
+
+
+ Row case:
+
+ 0.w fedc ba-- ---- ----
+ ---- --98 7654 3210 X
+
+ 2.w fedc ba-- ---- ---- Number of rows - 1
+ ---- --98 7654 3210 Y
+
+ 4.w f--- ---- ---- ---- Tile size: 8x8 (0) or 16x16 (1)
+ -edc ba-- ---- ---- "Tilemap" page
+ ---- --98 7654 3210 "Tilemap" Scroll X
+
+ 6.w fedc ba9- ---- ----
+ ---- ---8 7654 3210 "Tilemap" Scroll Y
+
+***************************************************************************/
+
+#include "driver.h"
+#include "seta.h"
+
+UINT16 *seta2_vregs;
+
+static int yoffset;
+
+/***************************************************************************
+
+
+ Video Registers
+
+ Offset: Bits: Value:
+
+ 0/2/4/6 ? Horizontal
+ 8/a/c/e ? Vertical
+
+ 10
+ 12 Offset X?
+ 14 Zoom X? low bits
+ 16 Zoom X? high bits *
+
+ 18
+ 1a Offset Y?
+ 1c Zoom Y? low bits
+ 1e Zoom Y? high bits
+
+ 30 fedc ba98 7654 321-
+ ---- ---- ---- ---0 Disable video
+
+ 32..3f ?
+
+
+ * A value of 1 is means no zoom, a value of 2 will halve the size.
+ It's unknown whether a value less than 1 means magnification (probably yes)
+
+***************************************************************************/
+
+WRITE16_HANDLER( seta2_vregs_w )
+{
+ /* 02/04 = horizontal display start/end
+ mj4simai = 0065/01E5 (0180 visible area)
+ myangel = 005D/01D5 (0178 visible area)
+ pzlbowl = 0058/01D8 (0180 visible area)
+ penbros = 0065/01A5 (0140 visible area)
+ grdians = 0059/0188 (012f visible area)
+ 06 = horizontal total?
+ mj4simai = 0204
+ myangel = 0200
+ pzlbowl = 0204
+ penbros = 01c0
+ grdians = 019a
+ */
+
+ COMBINE_DATA(&seta2_vregs[offset]);
+ switch( offset*2 )
+ {
+ case 0x1c: // FLIP SCREEN (myangel) <- this is actually zoom
+ flip_screen_set( data & 1 );
+ if (data & ~1) logerror("CPU #0 PC %06X: flip screen unknown bits %04X\n",activecpu_get_pc(),data);
+ break;
+ case 0x2a: // FLIP X (pzlbowl)
+ flip_screen_x_set( data & 1 );
+ if (data & ~1) logerror("CPU #0 PC %06X: flipx unknown bits %04X\n",activecpu_get_pc(),data);
+ break;
+ case 0x2c: // FLIP Y (pzlbowl)
+ flip_screen_y_set( data & 1 );
+ if (data & ~1) logerror("CPU #0 PC %06X: flipy unknown bits %04X\n",activecpu_get_pc(),data);
+ break;
+
+ case 0x30: // BLANK SCREEN (pzlbowl, myangel)
+ if (data & ~1) logerror("CPU #0 PC %06X: blank unknown bits %04X\n",activecpu_get_pc(),data);
+ break;
+
+ default:
+ logerror("CPU #0 PC %06X: Video Reg %02X <- %04X\n",activecpu_get_pc(),offset*2,data);
+ }
+}
+
+
+/***************************************************************************
+
+
+ Sprites Drawing
+
+
+***************************************************************************/
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap,const rectangle *cliprect)
+{
+ /* Sprites list */
+
+ UINT16 *s1 = buffered_spriteram16 + 0x3000/2;
+ UINT16 *end = &buffered_spriteram16[spriteram_size/2];
+
+ for ( ; s1 < end; s1+=4 )
+ {
+ int gfx;
+ int num = s1[0];
+ int xoffs = s1[1];
+ int yoffs = s1[2];
+ int sprite = s1[3];
+
+ /* Single-sprite address */
+ UINT16 *s2 = &buffered_spriteram16[(sprite & 0x7fff) * 4];
+
+ /* Single-sprite tile size */
+ int global_sizex = xoffs & 0x0c00;
+ int global_sizey = yoffs & 0x0c00;
+
+ int use_global_size = num & 0x1000;
+
+ xoffs &= 0x3ff;
+ yoffs &= 0x3ff;
+
+ /* Color depth */
+ switch (num & 0x0700)
+ {
+ default:
+ popmessage("unknown gfxset %x",(num & 0x0700)>>8);
+ gfx = mame_rand(machine)&3; break;
+ case 0x0700: // 8bpp tiles (76543210)
+ gfx = 3; break;
+ case 0x0600: // 6bpp tiles (--543210) (myangel sliding blocks test)
+ gfx = 2; break;
+ case 0x0500: // 4bpp tiles (3210----)
+ gfx = 1; break;
+ case 0x0400: // 4bpp tiles (----3210)
+ gfx = 0; break;
+// case 0x0300:
+// unknown
+ case 0x0200: // 3bpp tiles? (-----210) (myangel "Graduate Tests")
+ gfx = 4; break;
+ case 0x0100: // 2bpp tiles??? (--10----) (myangel2 question bubble, myangel endgame)
+ gfx = 5; break;
+ case 0x0000: // no idea!
+ gfx = 0; break;
+ }
+
+ /* Number of single-sprites */
+ num = (num & 0x00ff) + 1;
+
+ for( ; num > 0; num--,s2+=4 )
+ {
+ if (s2 >= end) break;
+
+// "tilemap" sprite
+
+ if (sprite & 0x8000)
+ {
+ rectangle clip;
+ int dx,x,y;
+ int flipx;
+ int flipy;
+ int sx = s2[0];
+ int sy = s2[1];
+ int scrollx = s2[2];
+ int scrolly = s2[3];
+ int tilesize = (scrollx & 0x8000) >> 15;
+ int page = (scrollx & 0x7c00) >> 10;
+ int height = ((sy & 0xfc00) >> 10) + 1;
+
+ sx &= 0x3ff;
+ sy &= 0x1ff;
+ scrollx &= 0x3ff;
+ scrolly &= 0x1ff;
+
+ clip.min_y = (sy + yoffs) & 0x1ff;
+ clip.max_y = clip.min_y + height * 0x10 - 1;
+
+ if (clip.min_y > cliprect->max_y) continue;
+ if (clip.max_y < cliprect->min_y) continue;
+
+ clip.min_x = cliprect->min_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;
+
+ dx = sx + (scrollx & 0x3ff) + xoffs + 0x10;
+
+ /* Draw the rows */
+ /* I don't think the following is entirely correct (when using 16x16
+ tiles x should probably loop from 0 to 0x20) but it seems to work
+ fine in all the games we have for now. */
+ for (y = 0; y < (0x40 >> tilesize); y++)
+ {
+ int py = ((scrolly - (y+1) * (8 << tilesize) + 0x10) & 0x1ff) - 0x10 - yoffset;
+
+ if (py < clip.min_y - 0x10) continue;
+ if (py > clip.max_y) continue;
+
+ for (x = 0; x < 0x40;x++)
+ {
+ int px = ((dx + x * (8 << tilesize) + 0x10) & 0x3ff) - 0x10;
+ int tx, ty;
+ int attr, code, color;
+ UINT16 *s3;
+
+ if (px < clip.min_x - 0x10) continue;
+ if (px > clip.max_x) continue;
+
+ s3 = &buffered_spriteram16[2 * ((page * 0x2000/4) + ((y & 0x1f) << 6) + (x & 0x03f))];
+
+ attr = s3[0];
+ code = s3[1] + ((attr & 0x0007) << 16);
+ flipx = (attr & 0x0010);
+ flipy = (attr & 0x0008);
+ color = (attr & 0xffe0) >> 5;
+
+ if (tilesize) code &= ~3;
+
+ for (ty = 0; ty <= tilesize; ty++)
+ {
+ for (tx = 0; tx <= tilesize; tx++)
+ {
+ drawgfx(bitmap, machine->gfx[gfx],
+ code ^ tx ^ (ty<<1),
+ color,
+ flipx, flipy,
+ px + (flipx ? tilesize-tx : tx) * 8, py + (flipy ? tilesize-ty : ty) * 8,
+ cliprect,TRANSPARENCY_PEN,0 );
+ }
+ }
+
+ }
+ }
+ }
+ else
+// "normal" sprite
+ {
+ int sx = s2[0];
+ int sy = s2[1];
+ int attr = s2[2];
+ int code = s2[3] + ((attr & 0x0007) << 16);
+ int flipx = (attr & 0x0010);
+ int flipy = (attr & 0x0008);
+ int color = (attr & 0xffe0) >> 5;
+
+ int sizex = use_global_size ? global_sizex : sx;
+ int sizey = use_global_size ? global_sizey : sy;
+ int x,y;
+ sizex = (1 << ((sizex & 0x0c00)>> 10))-1;
+ sizey = (1 << ((sizey & 0x0c00)>> 10))-1;
+
+
+ sx += xoffs;
+ sy += yoffs;
+
+ sx = (sx & 0x1ff) - (sx & 0x200);
+ sy &= 0x1ff;
+ sy -= yoffset;
+
+ code &= ~((sizex+1) * (sizey+1) - 1); // see myangel, myangel2 and grdians
+
+ for (y = 0; y <= sizey; y++)
+ {
+ for (x = 0; x <= sizex; x++)
+ {
+ drawgfx(bitmap, machine->gfx[gfx],
+ code++,
+ color,
+ flipx, flipy,
+ sx + (flipx ? sizex-x : x) * 8, sy + (flipy ? sizey-y : y) * 8,
+ cliprect,TRANSPARENCY_PEN,0 );
+ }
+ }
+ }
+ }
+
+ if (s1[0] & 0x8000) break; /* end of list marker */
+ } /* sprite list */
+}
+
+
+/***************************************************************************
+
+
+ Screen Drawing
+
+
+***************************************************************************/
+
+VIDEO_START( seta2 )
+{
+ machine->gfx[2]->color_granularity = 16;
+ machine->gfx[3]->color_granularity = 16;
+ machine->gfx[4]->color_granularity = 16;
+ machine->gfx[5]->color_granularity = 16;
+
+ buffered_spriteram16 = auto_malloc(spriteram_size);
+
+ yoffset = 0;
+}
+
+VIDEO_START( seta2_offset )
+{
+ video_start_seta2(machine);
+
+ yoffset = 0x10;
+}
+
+VIDEO_UPDATE( seta2 )
+{
+ /* Black or pens[0]? */
+ fillbitmap(bitmap,machine->pens[0],cliprect);
+
+ if (seta2_vregs[0x30/2] & 1) return 0; // BLANK SCREEN
+
+ draw_sprites(machine,bitmap,cliprect);
+ return 0;
+}
+
+VIDEO_EOF( seta2 )
+{
+ /* Buffer sprites by 1 frame */
+ memcpy(buffered_spriteram16,spriteram16,spriteram_size);
+}