diff options
Diffstat (limited to 'src/mame/video/taitojc.c')
-rw-r--r-- | src/mame/video/taitojc.c | 644 |
1 files changed, 644 insertions, 0 deletions
diff --git a/src/mame/video/taitojc.c b/src/mame/video/taitojc.c new file mode 100644 index 00000000000..5a3808fa2d2 --- /dev/null +++ b/src/mame/video/taitojc.c @@ -0,0 +1,644 @@ +#include "driver.h" +#include "video/poly.h" + +UINT8 *taitojc_texture; +static mame_bitmap *framebuffer; +static mame_bitmap *zbuffer; + +extern UINT32 *taitojc_vram; +extern UINT32 *taitojc_objlist; + +//static int debug_tex_pal = 0; + +typedef struct _poly_extra_data poly_extra_data; +struct _poly_extra_data +{ + int tex_base_x; + int tex_base_y; + int tex_wrap_x; + int tex_wrap_y; +}; + + +static int taitojc_gfx_index; + +static UINT8 *taitojc_dirty_map; +static UINT32 *taitojc_char_ram; +static UINT32 *taitojc_tile_ram; +static int taitojc_char_dirty = 1; +static tilemap *taitojc_tilemap; + +static poly_manager *poly; + +#define TAITOJC_NUM_TILES 0x80 + +static const gfx_layout taitojc_char_layout = +{ + 16,16, + TAITOJC_NUM_TILES, + 4, + { 0,1,2,3 }, + { 24,28,16,20,8,12,0,4, 56,60,48,52,40,44,32,36 }, + { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,8*64,9*64,10*64,11*64,12*64,13*64,14*64,15*64 }, + 16*64 +}; + +static TILE_GET_INFO( taitojc_tile_info ) +{ + UINT32 val = taitojc_tile_ram[tile_index]; + int color = (val >> 22) & 0xff; + int tile = (val >> 2) & 0x7f; + SET_TILE_INFO(taitojc_gfx_index, tile, color, 0); +} + +static void taitojc_tile_update(running_machine *machine) +{ + int i; + if (taitojc_char_dirty) + { + for (i=0; i < TAITOJC_NUM_TILES; i++) + { + if (taitojc_dirty_map[i]) + { + taitojc_dirty_map[i] = 0; + decodechar(Machine->gfx[taitojc_gfx_index], i, (UINT8 *)taitojc_char_ram, &taitojc_char_layout); + } + } + tilemap_mark_all_tiles_dirty(taitojc_tilemap); + taitojc_char_dirty = 0; + } +} + +READ32_HANDLER(taitojc_tile_r) +{ + return taitojc_tile_ram[offset]; +} + +READ32_HANDLER(taitojc_char_r) +{ + return taitojc_char_ram[offset]; +} + +WRITE32_HANDLER(taitojc_tile_w) +{ + COMBINE_DATA(taitojc_tile_ram + offset); + tilemap_mark_tile_dirty(taitojc_tilemap, offset); +} + +WRITE32_HANDLER(taitojc_char_w) +{ + COMBINE_DATA(taitojc_char_ram + offset); + taitojc_dirty_map[offset/32] = 1; + taitojc_char_dirty = 1; +} + +// Object data format: +// +// 0x00: xxxxxx-- -------- -------- -------- Height +// 0x00: ------xx xxxxxxxx -------- -------- Y +// 0x00: -------- -------- xxxxxx-- -------- Width +// 0x00: -------- -------- ------xx xxxxxxxx X +// 0x01: ---xxxxx xx------ -------- -------- Palette +// 0x01: -------- --x----- -------- -------- Priority (0 = below 3D, 1 = above 3D) +// 0x01: -------- -------- -xxxxxxx xxxxxxxx VRAM data address + +static void draw_object(mame_bitmap *bitmap, const rectangle *cliprect, UINT32 w1, UINT32 w2) +{ + int x, y, width, height, palette; + int i, j; + int x1, x2, y1, y2; + int ix, iy; + UINT32 address; + UINT8 *v; + + address = (w2 & 0x7fff) * 0x20; + if (w2 & 0x4000) + address |= 0x40000; + + x = ((w1 >> 0) & 0x3ff); + if (x & 0x200) + x |= ~0x1ff; // sign-extend + + y = ((w1 >> 16) & 0x3ff); + if (y & 0x200) + y |= ~0x1ff; // sign-extend + + width = ((w1 >> 10) & 0x3f) * 16; + height = ((w1 >> 26) & 0x3f) * 16; + palette = ((w2 >> 22) & 0x7f) << 8; + + v = (UINT8*)&taitojc_vram[address/4]; + + if (address >= 0xf8000 || width == 0 || height == 0) + return; + + x1 = x; + x2 = x + width; + y1 = y; + y2 = y + height; + + // trivial rejection + if (x1 > cliprect->max_x || x2 < cliprect->min_x || y1 > cliprect->max_y || y2 < cliprect->min_y) + { + return; + } + +// mame_printf_debug("draw_object: %08X %08X, X: %d, Y: %d, W: %d, H: %d\n", w1, w2, x, y, width, height); + + ix = 0; + iy = 0; + + // clip + if (x1 < cliprect->min_x) + { + ix = abs(cliprect->min_x - x1); + x1 = cliprect->min_x; + } + if (x2 > cliprect->max_x) + { + x2 = cliprect->max_x; + } + if (y1 < cliprect->min_y) + { + iy = abs(cliprect->min_y - y1); + y1 = cliprect->min_y; + } + if (y2 > cliprect->max_y) + { + y2 = cliprect->max_y; + } + + for (j=y1; j < y2; j++) + { + UINT16 *d = BITMAP_ADDR16(bitmap, j, 0); + int index = (iy * width) + ix; + + for (i=x1; i < x2; i++) + { + UINT8 pen = v[BYTE4_XOR_BE(index)]; + if (pen != 0) + { + d[i] = palette + pen; + } + index++; + } + + iy++; + } +} + +static void taitojc_exit(running_machine *machine) +{ + poly_free(poly); +} + +VIDEO_START( taitojc ) +{ + poly = poly_alloc(4000, sizeof(poly_extra_data), POLYFLAG_ALLOW_QUADS); + add_exit_callback(machine, taitojc_exit); + + /* find first empty slot to decode gfx */ + for (taitojc_gfx_index = 0; taitojc_gfx_index < MAX_GFX_ELEMENTS; taitojc_gfx_index++) + if (machine->gfx[taitojc_gfx_index] == 0) + break; + + assert(taitojc_gfx_index != MAX_GFX_ELEMENTS); + + taitojc_tilemap = tilemap_create(taitojc_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 16, 16, 64, 64); + taitojc_dirty_map = auto_malloc(TAITOJC_NUM_TILES); + + tilemap_set_transparent_pen(taitojc_tilemap, 0); + + taitojc_char_ram = auto_malloc(0x4000); + taitojc_tile_ram = auto_malloc(0x4000); + + memset(taitojc_char_ram, 0, 0x4000); + memset(taitojc_tile_ram, 0, 0x4000); + + /* create the char set (gfx will then be updated dynamically from RAM) */ + machine->gfx[taitojc_gfx_index] = allocgfx(&taitojc_char_layout); + + /* set the color information */ + if (machine->drv->color_table_len) + machine->gfx[taitojc_gfx_index]->total_colors = machine->drv->color_table_len / 16; + else + machine->gfx[taitojc_gfx_index]->total_colors = machine->drv->total_colors / 16; + + taitojc_texture = auto_malloc(0x400000); + + framebuffer = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format); + + zbuffer = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, BITMAP_FORMAT_INDEXED16); +} + +//static int tick = 0; +VIDEO_UPDATE( taitojc ) +{ + int i; + + /* + tick++; + if( tick >= 5 ) { + tick = 0; + + if( input_code_pressed(KEYCODE_O) ) + debug_tex_pal++; + + if( input_code_pressed(KEYCODE_I) ) + debug_tex_pal--; + + debug_tex_pal &= 0x7f; + } + */ + + fillbitmap(bitmap, 0, cliprect); + + for (i=(0xc00/4)-2; i >= 0; i-=2) + { + UINT32 w1 = taitojc_objlist[i + 0]; + UINT32 w2 = taitojc_objlist[i + 1]; + + if ((w2 & 0x200000) == 0) + { + draw_object(bitmap, cliprect, w1, w2); + } + } + + copybitmap(bitmap, framebuffer, 0, 0, 0, 0, cliprect, TRANSPARENCY_PEN, 0); + + for (i=(0xc00/4)-2; i >= 0; i-=2) + { + UINT32 w1 = taitojc_objlist[i + 0]; + UINT32 w2 = taitojc_objlist[i + 1]; + + if ((w2 & 0x200000) != 0) + { + draw_object(bitmap, cliprect, w1, w2); + } + } + + taitojc_tile_update(machine); + tilemap_draw(bitmap, cliprect, taitojc_tilemap, 0,0); + + /* + if (debug_tex_pal > 0) + { + int j; + for (j=cliprect->min_y; j <= cliprect->max_y; j++) + { + UINT16 *d = BITMAP_ADDR16(bitmap, j, 0); + int index = 2048 * j; + + for (i=cliprect->min_x; i <= cliprect->max_x; i++) + { + UINT8 t = taitojc_texture[index+i]; + UINT32 color; + + //color = 0xff000000 | (t << 16) | (t << 8) | (t); + color = (debug_tex_pal << 8) | t; + + d[i] = color; + } + } + + { + char string[200]; + sprintf(string, "Texture palette %d", debug_tex_pal); + popmessage("%s", string); + } + } + */ + + return 0; +} + + + + +static void render_solid_scan(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) +{ + mame_bitmap *destmap = dest; + float z = extent->param[0].start; + int color = extent->param[1].start; + float dz = extent->param[0].dpdx; + UINT16 *fb = BITMAP_ADDR16(destmap, scanline, 0); + UINT16 *zb = BITMAP_ADDR16(zbuffer, scanline, 0); + int x; + + for (x = extent->startx; x < extent->stopx; x++) + { + int iz = (int)z & 0xffff; + + if (iz <= zb[x]) + { + fb[x] = color; + zb[x] = iz; + } + + z += dz; + } +} + +static void render_shade_scan(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) +{ + mame_bitmap *destmap = dest; + float z = extent->param[0].start; + float color = extent->param[1].start; + float dz = extent->param[0].dpdx; + float dcolor = extent->param[1].dpdx; + UINT16 *fb = BITMAP_ADDR16(destmap, scanline, 0); + UINT16 *zb = BITMAP_ADDR16(zbuffer, scanline, 0); + int x; + + for (x = extent->startx; x < extent->stopx; x++) + { + int ic = (int)color & 0xffff; + int iz = (int)z & 0xffff; + + if (iz <= zb[x]) + { + fb[x] = ic; + zb[x] = iz; + } + + color += dcolor; + z += dz; + } +} + +static void render_texture_scan(void *dest, INT32 scanline, const poly_extent *extent, const void *extradata, int threadid) +{ + const poly_extra_data *extra = extradata; + mame_bitmap *destmap = dest; + float z = extent->param[0].start; + float u = extent->param[1].start; + float v = extent->param[2].start; + float color = extent->param[3].start; + float dz = extent->param[0].dpdx; + float du = extent->param[1].dpdx; + float dv = extent->param[2].dpdx; + float dcolor = extent->param[3].dpdx; + UINT16 *fb = BITMAP_ADDR16(destmap, scanline, 0); + UINT16 *zb = BITMAP_ADDR16(zbuffer, scanline, 0); + int tex_wrap_x = extra->tex_wrap_x; + int tex_wrap_y = extra->tex_wrap_y; + int tex_base_x = extra->tex_base_x; + int tex_base_y = extra->tex_base_y; + int x; + + for (x = extent->startx; x < extent->stopx; x++) + { + int iu, iv; + UINT8 texel; + int palette = ((int)color & 0x7f) << 8; + int iz = (int)z & 0xffff; + + if (!tex_wrap_x) + { + iu = ((int)u >> 4) & 0x7ff; + } + else + { + iu = (tex_base_x + (((int)u >> 4) & 0x3f)) & 0x7ff; + } + + if (!tex_wrap_y) + { + iv = ((int)v >> 4) & 0x7ff; + } + else + { + iv = (tex_base_y + (((int)v >> 4) & 0x3f)) & 0x7ff; + } + + texel = taitojc_texture[(iv * 2048) + iu]; + + if (iz <= zb[x] && texel != 0) + { + fb[x] = palette | texel; + zb[x] = iz; + } + + u += du; + v += dv; + color += dcolor; + z += dz; + } +} + +void taitojc_render_polygons(UINT16 *polygon_fifo, int length) +{ + poly_vertex vert[4]; + int i; + int ptr; + + ptr = 0; + while (ptr < length) + { + UINT16 cmd = polygon_fifo[ptr++]; + + switch (cmd & 0x7) + { + case 0x03: // Textured Triangle + { + // 0x00: Command ID (0x0003) + // 0x01: Texture base + // 0x02: Vertex 1 Palette + // 0x03: Vertex 1 V + // 0x04: Vertex 1 U + // 0x05: Vertex 1 Y + // 0x06: Vertex 1 X + // 0x07: Vertex 1 Z + // 0x08: Vertex 2 Palette + // 0x09: Vertex 2 V + // 0x0a: Vertex 2 U + // 0x0b: Vertex 2 Y + // 0x0c: Vertex 2 X + // 0x0d: Vertex 2 Z + // 0x0e: Vertex 3 Palette + // 0x0f: Vertex 3 V + // 0x10: Vertex 3 U + // 0x11: Vertex 3 Y + // 0x12: Vertex 3 X + // 0x13: Vertex 3 Z + + poly_extra_data *extra = poly_get_extra_data(poly); + UINT16 texbase; + + /* + printf("CMD3: "); + for (i=0; i < 0x13; i++) + { + printf("%04X ", polygon_fifo[ptr+i]); + } + printf("\n"); + */ + + texbase = polygon_fifo[ptr++]; + + extra->tex_base_x = ((texbase >> 0) & 0xff) << 4; + extra->tex_base_y = ((texbase >> 8) & 0xff) << 4; + + extra->tex_wrap_x = (cmd & 0xc0) ? 1 : 0; + extra->tex_wrap_y = (cmd & 0x30) ? 1 : 0; + + for (i=0; i < 3; i++) + { + vert[i].p[3] = polygon_fifo[ptr++]; // palette + vert[i].p[2] = (UINT16)(polygon_fifo[ptr++]); + vert[i].p[1] = (UINT16)(polygon_fifo[ptr++]); + vert[i].y = (INT16)(polygon_fifo[ptr++]); + vert[i].x = (INT16)(polygon_fifo[ptr++]); + vert[i].p[0] = (UINT16)(polygon_fifo[ptr++]); + } + + if (vert[0].p[0] < 0x8000 && vert[1].p[0] < 0x8000 && vert[2].p[0] < 0x8000) + { + poly_render_triangle(poly, framebuffer, &Machine->screen[0].visarea, render_texture_scan, 4, &vert[0], &vert[1], &vert[2]); + } + break; + } + case 0x04: // Gouraud shaded Quad + { + // 0x00: Command ID (0x0004) + // 0x01: Vertex 0 color + // 0x02: Vertex 0 Y + // 0x03: Vertex 0 X + // 0x04: Vertex 0 Z + // 0x05: Vertex 1 color + // 0x06: Vertex 1 Y + // 0x07: Vertex 1 X + // 0x08: Vertex 1 Z + // 0x09: Vertex 2 color + // 0x0a: Vertex 2 Y + // 0x0b: Vertex 2 X + // 0x0c: Vertex 2 Z + // 0x0d: Vertex 3 color + // 0x0e: Vertex 3 Y + // 0x0f: Vertex 3 X + // 0x10: Vertex 3 Z + + /* + printf("CMD4: "); + for (i=0; i < 0x10; i++) + { + printf("%04X ", polygon_fifo[ptr+i]); + } + printf("\n"); + */ + + for (i=0; i < 4; i++) + { + vert[i].p[1] = polygon_fifo[ptr++]; + vert[i].y = (INT16)(polygon_fifo[ptr++]); + vert[i].x = (INT16)(polygon_fifo[ptr++]); + vert[i].p[0] = (UINT16)(polygon_fifo[ptr++]); + } + + if (vert[0].p[0] < 0x8000 && vert[1].p[0] < 0x8000 && vert[2].p[0] < 0x8000 && vert[3].p[0] < 0x8000) + { + if (vert[0].p[1] == vert[1].p[1] && + vert[1].p[1] == vert[2].p[1] && + vert[2].p[1] == vert[3].p[1]) + { + // optimization: all colours the same -> render solid + poly_render_quad(poly, framebuffer, &Machine->screen[0].visarea, render_solid_scan, 2, &vert[0], &vert[1], &vert[2], &vert[3]); + } + else + { + poly_render_quad(poly, framebuffer, &Machine->screen[0].visarea, render_shade_scan, 2, &vert[0], &vert[1], &vert[2], &vert[3]); + } + } + break; + } + case 0x06: // Textured Quad + { + // 0x00: Command ID (0x0006) + // 0x01: Texture base + // 0x02: Vertex 1 Palette + // 0x03: Vertex 1 V + // 0x04: Vertex 1 U + // 0x05: Vertex 1 Y + // 0x06: Vertex 1 X + // 0x07: Vertex 1 Z + // 0x08: Vertex 2 Palette + // 0x09: Vertex 2 V + // 0x0a: Vertex 2 U + // 0x0b: Vertex 2 Y + // 0x0c: Vertex 2 X + // 0x0d: Vertex 2 Z + // 0x0e: Vertex 3 Palette + // 0x0f: Vertex 3 V + // 0x10: Vertex 3 U + // 0x11: Vertex 3 Y + // 0x12: Vertex 3 X + // 0x13: Vertex 3 Z + // 0x14: Vertex 4 Palette + // 0x15: Vertex 4 V + // 0x16: Vertex 4 U + // 0x17: Vertex 4 Y + // 0x18: Vertex 4 X + // 0x19: Vertex 4 Z + + poly_extra_data *extra = poly_get_extra_data(poly); + UINT16 texbase; + + /* + printf("CMD6: "); + for (i=0; i < 0x19; i++) + { + printf("%04X ", polygon_fifo[ptr+i]); + } + printf("\n"); + */ + + texbase = polygon_fifo[ptr++]; + + extra->tex_base_x = ((texbase >> 0) & 0xff) << 4; + extra->tex_base_y = ((texbase >> 8) & 0xff) << 4; + + extra->tex_wrap_x = (cmd & 0xc0) ? 1 : 0; + extra->tex_wrap_y = (cmd & 0x30) ? 1 : 0; + + for (i=0; i < 4; i++) + { + vert[i].p[3] = polygon_fifo[ptr++]; // palette + vert[i].p[2] = (UINT16)(polygon_fifo[ptr++]); + vert[i].p[1] = (UINT16)(polygon_fifo[ptr++]); + vert[i].y = (INT16)(polygon_fifo[ptr++]); + vert[i].x = (INT16)(polygon_fifo[ptr++]); + vert[i].p[0] = (UINT16)(polygon_fifo[ptr++]); + } + + if (vert[0].p[0] < 0x8000 && vert[1].p[0] < 0x8000 && vert[2].p[0] < 0x8000 && vert[3].p[0] < 0x8000) + { + poly_render_quad(poly, framebuffer, &Machine->screen[0].visarea, render_texture_scan, 4, &vert[0], &vert[1], &vert[2], &vert[3]); + } + break; + } + case 0x00: + { + ptr += 6; + break; + } + default: + { + //printf("render_polygons: unknown command %04X\n", cmd); + } + } + }; + poly_wait(poly, "Finished render"); +} + +void taitojc_clear_frame(void) +{ + rectangle cliprect; + + cliprect.min_x = 0; + cliprect.min_y = 0; + cliprect.max_x = Machine->screen[0].width-1; + cliprect.max_y = Machine->screen[0].height-1; + + fillbitmap(framebuffer, 0, &cliprect); + fillbitmap(zbuffer, 0xffff, &cliprect); +} |