summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/tceptor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/tceptor.c')
-rw-r--r--src/mame/video/tceptor.c597
1 files changed, 597 insertions, 0 deletions
diff --git a/src/mame/video/tceptor.c b/src/mame/video/tceptor.c
new file mode 100644
index 00000000000..944a19340cf
--- /dev/null
+++ b/src/mame/video/tceptor.c
@@ -0,0 +1,597 @@
+/*
+ * Thunder Ceptor board
+ * emulate video hardware
+ */
+
+#include "driver.h"
+#include "namcoic.h"
+
+#define TX_TILE_OFFSET_CENTER (32 * 2)
+#define TX_TILE_OFFSET_RIGHT (32 * 0 + 2)
+#define TX_TILE_OFFSET_LEFT (32 * 31 + 2)
+
+#define SPR_TRANS_COLOR (0xff + 768)
+#define SPR_MASK_COLOR (0xfe + 768)
+
+
+UINT8 *tceptor_tile_ram;
+UINT8 *tceptor_tile_attr;
+UINT8 *tceptor_bg_ram;
+UINT16 *tceptor_sprite_ram;
+
+static int sprite16;
+static int sprite32;
+static int bg;
+
+static tilemap *tx_tilemap;
+
+static tilemap *bg1_tilemap;
+static tilemap *bg2_tilemap;
+
+static INT32 bg1_scroll_x, bg1_scroll_y;
+static INT32 bg2_scroll_x, bg2_scroll_y;
+
+static mame_bitmap *temp_bitmap;
+
+static int is_mask_spr[1024/16];
+
+/*******************************************************************/
+
+PALETTE_INIT( tceptor )
+{
+ int totcolors, totlookup;
+ int i;
+
+ totcolors = machine->drv->total_colors;
+ totlookup = machine->drv->color_table_len;
+
+ for (i = 0; i < totcolors; i++)
+ {
+ int bit0, bit1, bit2, bit3, r, g, b;
+
+ bit0 = (color_prom[0] >> 0) & 0x01;
+ bit1 = (color_prom[0] >> 1) & 0x01;
+ bit2 = (color_prom[0] >> 2) & 0x01;
+ bit3 = (color_prom[0] >> 3) & 0x01;
+ r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+ bit0 = (color_prom[totcolors] >> 0) & 0x01;
+ bit1 = (color_prom[totcolors] >> 1) & 0x01;
+ bit2 = (color_prom[totcolors] >> 2) & 0x01;
+ bit3 = (color_prom[totcolors] >> 3) & 0x01;
+ g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+ bit0 = (color_prom[2*totcolors] >> 0) & 0x01;
+ bit1 = (color_prom[2*totcolors] >> 1) & 0x01;
+ bit2 = (color_prom[2*totcolors] >> 2) & 0x01;
+ bit3 = (color_prom[2*totcolors] >> 3) & 0x01;
+ b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
+
+ palette_set_color(machine, i, MAKE_RGB(r, g, b));
+ color_prom++;
+ }
+
+ color_prom += 2 * totcolors;
+ /* color_prom now points to the beginning of the lookup table */
+
+ /*
+ color lookup table:
+ 0- +1024 ( 4 * 256) colors: text (use 0- 256 colors)
+ 1024- +1024 (16 * 64) colors: sprite (use 768- 256 colors)
+ 2048- +512 ( 8 * 64) colors: bg (use 0- 512 colors)
+ 3840- +256 ( 4 * 64) colors: road (use 512- 256 colors)
+ */
+
+ /* tiles lookup table (1024 colors) */
+ for (i = 0; i < 1024;i++)
+ colortable[i] = *color_prom++;
+
+ /* road lookup table (256 colors) */
+ for (i = 0; i < 256; i++)
+ colortable[i + 0xf00] = *(color_prom++) + 512;
+
+ /* sprites lookup table (1024 colors) */
+ for (i = 0;i < 1024; i++)
+ colortable[i + 1024] = *(color_prom++) + 768;
+
+ /* background: lookup prom is not presented, use prom directly (512 colors) */
+ for (i = 0;i < 512; i++)
+ colortable[i + 2048] = i;
+
+ /* setup sprite mask color map */
+ /* tceptor2: only 0x23 */
+ memset(is_mask_spr, 0, sizeof is_mask_spr);
+ for (i = 0; i < 1024; i++)
+ if (colortable[i + 1024] == SPR_MASK_COLOR)
+ is_mask_spr[i / 16] = 1;
+}
+
+
+/*******************************************************************/
+
+INLINE int get_tile_addr(int tile_index)
+{
+ int x = tile_index / 28;
+ int y = tile_index % 28;
+
+ switch (x)
+ {
+ case 0:
+ return TX_TILE_OFFSET_LEFT + y;
+ case 33:
+ return TX_TILE_OFFSET_RIGHT + y;
+ }
+
+ return TX_TILE_OFFSET_CENTER + (x - 1) + y * 32;
+}
+
+static TILE_GET_INFO( get_tx_tile_info )
+{
+ int offset = get_tile_addr(tile_index);
+ int code = tceptor_tile_ram[offset];
+ int color = tceptor_tile_attr[offset];
+
+ SET_TILE_INFO(0, code, color, 0);
+}
+
+static void tile_mark_dirty(int offset)
+{
+ int x = -1;
+ int y = -1;
+
+ if (offset >= TX_TILE_OFFSET_LEFT && offset < TX_TILE_OFFSET_LEFT + 28)
+ {
+ x = 0;
+ y = offset - TX_TILE_OFFSET_LEFT;
+ }
+ else if (offset >= TX_TILE_OFFSET_RIGHT && offset < TX_TILE_OFFSET_RIGHT + 28)
+ {
+ x = 33;
+ y = offset - TX_TILE_OFFSET_RIGHT;
+ }
+ else if (offset >= TX_TILE_OFFSET_CENTER && offset < TX_TILE_OFFSET_CENTER + 32 * 28)
+ {
+ offset -= TX_TILE_OFFSET_CENTER;
+ x = (offset % 32) + 1;
+ y = offset / 32;
+ }
+
+ if (x >= 0)
+ tilemap_mark_tile_dirty(tx_tilemap, x * 28 + y);
+}
+
+
+READ8_HANDLER( tceptor_tile_ram_r )
+{
+ return tceptor_tile_ram[offset];
+}
+
+WRITE8_HANDLER( tceptor_tile_ram_w )
+{
+ if (tceptor_tile_ram[offset] != data)
+ {
+ tceptor_tile_ram[offset] = data;
+ tile_mark_dirty(offset);
+ }
+}
+
+READ8_HANDLER( tceptor_tile_attr_r )
+{
+ return tceptor_tile_attr[offset];
+}
+
+WRITE8_HANDLER( tceptor_tile_attr_w )
+{
+ if (tceptor_tile_attr[offset] != data)
+ {
+ tceptor_tile_attr[offset] = data;
+ tile_mark_dirty(offset);
+ }
+}
+
+
+/*******************************************************************/
+
+static TILE_GET_INFO( get_bg1_tile_info )
+{
+ UINT16 data = tceptor_bg_ram[tile_index * 2] | (tceptor_bg_ram[tile_index * 2 + 1] << 8);
+ int code = (data & 0x3ff) | 0x000;
+ int color = (data & 0xfc00) >> 10;
+
+ SET_TILE_INFO(bg, code, color, 0);
+}
+
+static TILE_GET_INFO( get_bg2_tile_info )
+{
+ UINT16 data = tceptor_bg_ram[tile_index * 2 + 0x1000] | (tceptor_bg_ram[tile_index * 2 + 1 + 0x1000] << 8);
+ int code = (data & 0x3ff) | 0x400;
+ int color = (data & 0xfc00) >> 10;
+
+ SET_TILE_INFO(bg, code, color, 0);
+}
+
+READ8_HANDLER( tceptor_bg_ram_r )
+{
+ return tceptor_bg_ram[offset];
+}
+
+WRITE8_HANDLER( tceptor_bg_ram_w )
+{
+ tceptor_bg_ram[offset] = data;
+
+ offset /= 2;
+ if (offset < 0x800)
+ tilemap_mark_tile_dirty(bg1_tilemap, offset);
+ else
+ tilemap_mark_tile_dirty(bg2_tilemap, offset - 0x800);
+}
+
+WRITE8_HANDLER( tceptor_bg_scroll_w )
+{
+ switch (offset)
+ {
+ case 0:
+ bg1_scroll_x &= 0xff;
+ bg1_scroll_x |= data << 8;
+ break;
+ case 1:
+ bg1_scroll_x &= 0xff00;
+ bg1_scroll_x |= data;
+ break;
+ case 2:
+ bg1_scroll_y = data;
+ break;
+
+ case 4:
+ bg2_scroll_x &= 0xff;
+ bg2_scroll_x |= data << 8;
+ break;
+ case 5:
+ bg2_scroll_x &= 0xff00;
+ bg2_scroll_x |= data;
+ break;
+ case 6:
+ bg2_scroll_y = data;
+ break;
+ }
+}
+
+
+/*******************************************************************/
+
+static void decode_bg(running_machine *machine, int region)
+{
+ static const gfx_layout bg_layout =
+ {
+ 8, 8,
+ 2048,
+ 3,
+ { 0x40000+4, 0, 4 },
+ { 0, 1, 2, 3, 8, 9, 10, 11 },
+ { 0, 16, 32, 48, 64, 80, 96, 112 },
+ 128
+ };
+
+ int gfx_index = bg;
+ UINT8 *src = memory_region(region) + 0x8000;
+ UINT8 *buffer;
+ int len = 0x8000;
+ int i;
+
+ buffer = malloc_or_die(len);
+
+ /* expand rom tc2-19.10d */
+ for (i = 0; i < len / 2; i++)
+ {
+ buffer[i*2+1] = src[i] & 0x0f;
+ buffer[i*2] = (src[i] & 0xf0) >> 4;
+ }
+
+ memcpy(src, buffer, len);
+ free(buffer);
+
+ /* decode the graphics */
+ machine->gfx[gfx_index] = allocgfx(&bg_layout);
+ decodegfx(machine->gfx[gfx_index], memory_region(region), 0, machine->gfx[gfx_index]->total_elements);
+
+ /* set the color information */
+ machine->gfx[gfx_index]->color_base = 2048;
+ machine->gfx[gfx_index]->total_colors = 64;
+}
+
+static void decode_sprite(running_machine *machine, int gfx_index, const gfx_layout *layout, const void *data)
+{
+ /* decode the graphics */
+ machine->gfx[gfx_index] = allocgfx(layout);
+ decodegfx(machine->gfx[gfx_index], data, 0, machine->gfx[gfx_index]->total_elements);
+
+ /* set the color information */
+ machine->gfx[gfx_index]->color_base = 1024;
+ machine->gfx[gfx_index]->total_colors = 64;
+}
+
+// fix sprite order
+static void decode_sprite16(running_machine *machine, int region)
+{
+ static const gfx_layout spr16_layout =
+ {
+ 16, 16,
+ 512,
+ 4,
+ { 0x00000, 0x00004, 0x40000, 0x40004 },
+ {
+ 0*8, 0*8+1, 0*8+2, 0*8+3, 1*8, 1*8+1, 1*8+2, 1*8+3,
+ 2*8, 2*8+1, 2*8+2, 2*8+3, 3*8, 3*8+1, 3*8+2, 3*8+3
+ },
+ {
+ 0*2*16, 1*2*16, 2*2*16, 3*2*16, 4*2*16, 5*2*16, 6*2*16, 7*2*16,
+ 8*2*16, 9*2*16, 10*2*16, 11*2*16, 12*2*16, 13*2*16, 14*2*16, 15*2*16
+ },
+ 2*16*16
+ };
+
+ UINT8 *src = memory_region(region);
+ int len = memory_region_length(region);
+ UINT8 *dst;
+ int i, y;
+
+ dst = malloc_or_die(len);
+
+ for (i = 0; i < len / (4*4*16); i++)
+ for (y = 0; y < 16; y++)
+ {
+ memcpy(&dst[(i*4 + 0) * (2*16*16/8) + y * (2*16/8)],
+ &src[i * (2*32*32/8) + y * (2*32/8)],
+ 4);
+ memcpy(&dst[(i*4 + 1) * (2*16*16/8) + y * (2*16/8)],
+ &src[i * (2*32*32/8) + y * (2*32/8) + (4*8/8)],
+ 4);
+ memcpy(&dst[(i*4 + 2) * (2*16*16/8) + y * (2*16/8)],
+ &src[i * (2*32*32/8) + y * (2*32/8) + (16*2*32/8)],
+ 4);
+ memcpy(&dst[(i*4 + 3) * (2*16*16/8) + y * (2*16/8)],
+ &src[i * (2*32*32/8) + y * (2*32/8) + (4*8/8) + (16*2*32/8)],
+ 4);
+ }
+
+ decode_sprite(machine, sprite16, &spr16_layout, dst);
+
+ free(dst);
+}
+
+// fix sprite order
+static void decode_sprite32(running_machine *machine, int region)
+{
+ static const gfx_layout spr32_layout =
+ {
+ 32, 32,
+ 1024,
+ 4,
+ { 0x000000, 0x000004, 0x200000, 0x200004 },
+ {
+ 0*8, 0*8+1, 0*8+2, 0*8+3, 1*8, 1*8+1, 1*8+2, 1*8+3,
+ 2*8, 2*8+1, 2*8+2, 2*8+3, 3*8, 3*8+1, 3*8+2, 3*8+3,
+ 4*8, 4*8+1, 4*8+2, 4*8+3, 5*8, 5*8+1, 5*8+2, 5*8+3,
+ 6*8, 6*8+1, 6*8+2, 6*8+3, 7*8, 7*8+1, 7*8+2, 7*8+3
+ },
+ {
+ 0*2*32, 1*2*32, 2*2*32, 3*2*32, 4*2*32, 5*2*32, 6*2*32, 7*2*32,
+ 8*2*32, 9*2*32, 10*2*32, 11*2*32, 12*2*32, 13*2*32, 14*2*32, 15*2*32,
+ 16*2*32, 17*2*32, 18*2*32, 19*2*32, 20*2*32, 21*2*32, 22*2*32, 23*2*32,
+ 24*2*32, 25*2*32, 26*2*32, 27*2*32, 28*2*32, 29*2*32, 30*2*32, 31*2*32
+ },
+ 2*32*32
+ };
+
+ UINT8 *src = memory_region(region);
+ int len = memory_region_length(region);
+ int total = spr32_layout.total;
+ int size = spr32_layout.charincrement / 8;
+ UINT8 *dst;
+ int i;
+
+ dst = malloc_or_die(len);
+
+ memset(dst, 0, len);
+
+ for (i = 0; i < total; i++)
+ {
+ int code;
+
+ code = (i & 0x07f) | ((i & 0x180) << 1) | 0x80;
+ code &= ~((i & 0x200) >> 2);
+
+ memcpy(&dst[size * (i + 0)], &src[size * (code + 0)], size);
+ memcpy(&dst[size * (i + total)], &src[size * (code + total)], size);
+ }
+
+ decode_sprite(machine, sprite32, &spr32_layout, dst);
+
+ free(dst);
+}
+
+static void mark_all_tiles_dirty(void)
+{
+ tilemap_mark_all_tiles_dirty(tx_tilemap);
+ tilemap_mark_all_tiles_dirty(bg1_tilemap);
+ tilemap_mark_all_tiles_dirty(bg2_tilemap);
+}
+
+VIDEO_START( tceptor )
+{
+ int gfx_index;
+
+ /* find first empty slot to decode gfx */
+ for (gfx_index = 0; gfx_index < MAX_GFX_ELEMENTS; gfx_index++)
+ if (machine->gfx[gfx_index] == 0)
+ break;
+ assert(gfx_index + 4 <= MAX_GFX_ELEMENTS);
+
+ bg = gfx_index++;
+ decode_bg(machine, REGION_GFX2);
+
+ sprite16 = gfx_index++;
+ decode_sprite16(machine, REGION_GFX3);
+
+ sprite32 = gfx_index++;
+ decode_sprite32(machine, REGION_GFX4);
+
+ /* allocate temp bitmaps */
+ temp_bitmap = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format);
+
+ namco_road_init(machine, gfx_index);
+
+ namco_road_set_transparent_color(machine->remapped_colortable[0xfff]);
+
+ tx_tilemap = tilemap_create(get_tx_tile_info, tilemap_scan_cols, TILEMAP_TYPE_COLORTABLE, 8, 8, 34, 28);
+
+ tilemap_set_scrollx(tx_tilemap, 0, -2*8);
+ tilemap_set_scrolly(tx_tilemap, 0, 0);
+ tilemap_set_transparent_pen(tx_tilemap, 7);
+
+ bg1_tilemap = tilemap_create(get_bg1_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8, 8, 64, 32);
+ bg2_tilemap = tilemap_create(get_bg2_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8, 8, 64, 32);
+
+ state_save_register_global(bg1_scroll_x);
+ state_save_register_global(bg1_scroll_y);
+ state_save_register_global(bg2_scroll_x);
+ state_save_register_global(bg2_scroll_y);
+
+ state_save_register_func_postload(mark_all_tiles_dirty);
+}
+
+
+/*******************************************************************/
+
+/*
+ Sprite data format
+
+ 000: zzzzzzBB BTTTTTTT
+ 002: ZZZZZZPP PPCCCCCC
+ 100: fFL---YY YYYYYYYY
+ 102: ------XX XXXXXXXX
+
+ B: bank
+ T: number
+ P: priority
+ C: color
+ X: x
+ Y: y
+ L: large sprite
+ F: flip x
+ f: flip y
+ Z: zoom x
+ z: zoom y
+*/
+
+static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int sprite_priority)
+{
+ UINT16 *mem1 = &tceptor_sprite_ram[0x000/2];
+ UINT16 *mem2 = &tceptor_sprite_ram[0x100/2];
+ int need_mask = 0;
+ int i;
+
+ for (i = 0; i < 0x100; i += 2)
+ {
+ int scalex = (mem1[1 + i] & 0xfc00) << 1;
+ int scaley = (mem1[0 + i] & 0xfc00) << 1;
+ int pri = 7 - ((mem1[1 + i] & 0x3c0) >> 6);
+
+ if (pri == sprite_priority && scalex && scaley)
+ {
+ int x = mem2[1 + i] & 0x3ff;
+ int y = 512 - (mem2[0 + i] & 0x3ff);
+ int flipx = mem2[0 + i] & 0x4000;
+ int flipy = mem2[0 + i] & 0x8000;
+ int color = mem1[1 + i] & 0x3f;
+ int gfx;
+ int code;
+
+ if (mem2[0 + i] & 0x2000)
+ {
+ gfx = sprite32;
+ code = mem1[0 + i] & 0x3ff;
+
+ }
+ else
+ {
+ gfx = sprite16;
+ code = mem1[0 + i] & 0x1ff;
+ scaley *= 2;
+ }
+
+ if (is_mask_spr[color])
+ {
+ if (!need_mask)
+ {
+ // backup previous bitmap
+ copybitmap(temp_bitmap, bitmap, 0, 0, 0, 0, cliprect, TRANSPARENCY_NONE, 0);
+ }
+
+ need_mask = 1;
+ }
+
+ // round off
+ scalex += 0x800;
+ scaley += 0x800;
+
+ x -= 64;
+ y -= 78;
+
+ drawgfxzoom(bitmap,
+ machine->gfx[gfx],
+ code,
+ color,
+ flipx, flipy,
+ x, y,
+ cliprect,
+ TRANSPARENCY_COLOR, SPR_TRANS_COLOR,
+ scalex,
+ scaley);
+ }
+ }
+
+ /* if SPR_MASK_COLOR pen is used, restore pixels from previous bitmap */
+ if (need_mask)
+ {
+ int x, y;
+
+ for (x = cliprect->min_x; x <= cliprect->max_x; x++)
+ for (y = cliprect->min_y; y <= cliprect->max_y; y++)
+ if (*BITMAP_ADDR16(bitmap, y, x) == SPR_MASK_COLOR)
+ {
+ // restore pixel
+ *BITMAP_ADDR16(bitmap, y, x) = *BITMAP_ADDR16(temp_bitmap, y, x);
+ }
+ }
+}
+
+
+VIDEO_UPDATE( tceptor )
+{
+ rectangle rect;
+ int pri;
+ int bg_center = 144 - ((((bg1_scroll_x + bg2_scroll_x ) & 0x1ff) - 288) / 2);
+
+ // left background
+ rect = *cliprect;
+ rect.max_x = bg_center;
+ tilemap_set_scrollx(bg1_tilemap, 0, bg1_scroll_x + 12);
+ tilemap_set_scrolly(bg1_tilemap, 0, bg1_scroll_y + 20); //32?
+ tilemap_draw(bitmap, &rect, bg1_tilemap, 0, 0);
+
+ // right background
+ rect.min_x = bg_center;
+ rect.max_x = cliprect->max_x;
+ tilemap_set_scrollx(bg2_tilemap, 0, bg2_scroll_x + 20);
+ tilemap_set_scrolly(bg2_tilemap, 0, bg2_scroll_y + 20); // 32?
+ tilemap_draw(bitmap, &rect, bg2_tilemap, 0, 0);
+
+ for (pri = 0; pri < 8; pri++)
+ {
+ namco_road_draw(machine, bitmap, cliprect, pri * 2);
+ namco_road_draw(machine, bitmap, cliprect, pri * 2 + 1);
+ draw_sprites(machine, bitmap, cliprect, pri);
+ }
+
+ tilemap_draw(bitmap, cliprect, tx_tilemap, 0, 0);
+ return 0;
+}