/*************************************************************************** Psychic 5 Functions to emulate the video hardware of the machine. ***************************************************************************/ #include "driver.h" #include "jalblend.c" #define BG_SCROLLX_LSB 0x308 #define BG_SCROLLX_MSB 0x309 #define BG_SCROLLY_LSB 0x30a #define BG_SCROLLY_MSB 0x30b #define BG_SCREEN_MODE 0x30c #define BG_PAL_INTENSITY_RG 0x1fe #define BG_PAL_INTENSITY_BU 0x1ff static int ps5_vram_page; static int bg_clip_mode; static int title_screen; /* Paged RAM 0 */ static UINT8 *psychic5_bg_videoram; static UINT8 *ps5_dummy_bg_ram; /* Paged RAM 1 */ static UINT8 *ps5_io_ram; static UINT8 *ps5_palette_ram; static UINT8 *psychic5_fg_videoram; static tilemap *bg_tilemap, *fg_tilemap; MACHINE_RESET( psychic5 ) { bg_clip_mode = -10; flip_screen_set(0); } WRITE8_HANDLER( psychic5_vram_page_select_w ) { ps5_vram_page = data; } READ8_HANDLER( psychic5_vram_page_select_r ) { return ps5_vram_page; } WRITE8_HANDLER( psychic5_title_screen_w ) { title_screen = data & 0x01; } static void psychic5_paletteram_w(int color_offs, int offset, int data) { int r,g,b,a,val; ps5_palette_ram[offset] = data; /* red component */ r = (ps5_palette_ram[offset & ~1] >> 4) & 0x0f ; /* green component */ g = (ps5_palette_ram[offset & ~1]) & 0x0f ; /* blue component */ b = (ps5_palette_ram[offset | 1] >> 4) & 0x0f ; /* "alpha" component */ val = (ps5_palette_ram[offset | 1] & 0x0f) & 0x0f ; a = (val << 4) | val ; jal_blend_table[(offset / 2)-color_offs] = a ; palette_set_color_rgb(Machine,(offset / 2)-color_offs,pal4bit(r),pal4bit(g),pal4bit(b)); } static void set_background_palette_intensity(running_machine *machine) { int i,r,g,b,val,lo,hi,ir,ig,ib,ix; /* red,green,blue intensites */ ir = ps5_palette_ram[BG_PAL_INTENSITY_RG] >> 4 ; ir = (ir << 4) | ir ; ig = ps5_palette_ram[BG_PAL_INTENSITY_RG] & 15 ; ig = (ig << 4) | ig ; ib = ps5_palette_ram[BG_PAL_INTENSITY_BU] >> 4 ; ib = (ib << 4) | ib ; ix = ps5_palette_ram[0x1ff] & 0x0f ; /* for all of the background palette */ for (i = 0; i < 0x100; i++) { lo = ps5_palette_ram[0x400+i*2]; hi = ps5_palette_ram[0x400+i*2+1]; /* red component */ val = (lo >> 4) & 0x0f; r = (val << 4) | val ; /* green component */ val = (lo & 15) & 0x0f; g = (val << 4) | val ; /* blue component */ val = (hi >> 4) & 0x0f; b = (val << 4) | val ; /* Grey background enable */ if (ps5_io_ram[BG_SCREEN_MODE] & 0x02) { val = (UINT8)((r + g + b) / 3); /* Grey */ if (ix != 0x0) /* Tint the grey */ { UINT32 result = jal_blend_func(MAKE_RGB(val,val,val), MAKE_RGB(ir, ig, ib), jal_blend_table[0xff]) ; palette_set_color(machine, 0x100+i, result) ; } else /* Just leave plain grey */ { palette_set_color(machine,0x100+i,MAKE_RGB(val,val,val)); } } else { /* Seems fishy, but the title screen would be black otherwise... */ if (!title_screen) { if (ix != 0x0) /* Tint the world */ { UINT32 result = jal_blend_func(MAKE_RGB(r, g, b), MAKE_RGB(ir, ig, ib), jal_blend_table[0xff]) ; palette_set_color(machine, 0x100+i, result) ; } else /* Leave the world as-is */ { palette_set_color(machine,0x100+i,MAKE_RGB(r,g,b)) ; } } } } } static WRITE8_HANDLER( psychic5_bg_videoram_w ) { psychic5_bg_videoram[offset] = data; tilemap_mark_tile_dirty(bg_tilemap, offset / 2); } static WRITE8_HANDLER( psychic5_fg_videoram_w ) { psychic5_fg_videoram[offset] = data; tilemap_mark_tile_dirty(fg_tilemap, offset / 2); } READ8_HANDLER( psychic5_paged_ram_r ) { int val; if (!ps5_vram_page) { if (offset < 0x1000) return psychic5_bg_videoram[offset]; else return ps5_dummy_bg_ram[offset & 0xfff]; } else { if (offset < 0x400) { val = 0; switch(offset) { case 0x00: val = input_port_0_r(0); break; case 0x01: val = input_port_1_r(0); break; case 0x02: val = input_port_2_r(0); break; case 0x03: val = input_port_3_r(0); break; case 0x04: val = input_port_4_r(0); break; default: val = ps5_io_ram[offset]; } return (val); } else if (offset < 0x1000) { return ps5_palette_ram[offset-0x400]; } else { return psychic5_fg_videoram[offset & 0xfff]; } } return 0; } WRITE8_HANDLER( psychic5_paged_ram_w ) { if (!ps5_vram_page) { if (offset < 0x1000) psychic5_bg_videoram_w(offset,data); else ps5_dummy_bg_ram[offset & 0xfff] = data; } else { if (offset < 0x400) { ps5_io_ram[offset] = data; } else if (offset < 0x600) { psychic5_paletteram_w(000, offset-0x400, data); } else if (offset > 0x5ff && offset< 0x800) { ps5_palette_ram[offset-0x400] = data; } else if (offset > 0x7ff && offset < 0xa00) { psychic5_paletteram_w(256, offset-0x400, data); } else if (offset > 0x9ff && offset < 0xc00) { psychic5_paletteram_w(256, offset-0x400, data); } else if (offset < 0x1000) { ps5_palette_ram[offset-0x400] = data; } else { psychic5_fg_videoram_w(offset & 0xfff, data); } } } static TILE_GET_INFO( get_bg_tile_info ) { int offs = tile_index * 2; int attr = psychic5_bg_videoram[offs + 1]; int code = psychic5_bg_videoram[offs] + ((attr & 0xc0) << 2); int color = attr & 0x0f; int flags = ((attr & 0x10) ? TILE_FLIPX : 0) + ((attr & 0x20) ? TILE_FLIPY : 0); SET_TILE_INFO(1, code, color, flags); } static TILE_GET_INFO( get_fg_tile_info ) { int offs = tile_index * 2; int attr = psychic5_fg_videoram[offs + 1]; int code = psychic5_fg_videoram[offs] + ((attr & 0xc0) << 2); int color = attr & 0x0f; int flags = ((attr & 0x10) ? TILE_FLIPX : 0) + ((attr & 0x20) ? TILE_FLIPY : 0); SET_TILE_INFO(2, code, color, flags); } VIDEO_START( psychic5 ) { psychic5_bg_videoram = auto_malloc(0x1000); psychic5_fg_videoram = auto_malloc(0x1000); ps5_dummy_bg_ram = auto_malloc(0x1000); ps5_io_ram = auto_malloc(0x400); ps5_palette_ram = auto_malloc(0xc00); jal_blend_table = auto_malloc(0xc00); memset(psychic5_bg_videoram, 0,0x1000); memset(psychic5_fg_videoram,0,0x1000); memset(ps5_dummy_bg_ram,0,0x1000); memset(ps5_io_ram,0,0x400); memset(ps5_palette_ram,0,0xc00); memset(jal_blend_table,0,0xc00) ; bg_tilemap = tilemap_create(get_bg_tile_info, tilemap_scan_cols, TILEMAP_TYPE_PEN, 16, 16, 64, 32); fg_tilemap = tilemap_create(get_fg_tile_info, tilemap_scan_cols, TILEMAP_TYPE_PEN, 8, 8, 32, 32); tilemap_set_transparent_pen(fg_tilemap, 15); } #define DRAW_SPRITE(code, sx, sy) jal_blend_drawgfx(bitmap, machine->gfx[0], code, color, flipx, flipy, sx, sy, cliprect, TRANSPARENCY_PEN, 15); /* #define DRAW_SPRITE(code, sx, sy) drawgfx(bitmap, machine->gfx[0], code, color, flipx, flipy, sx, sy, cliprect, TRANSPARENCY_PEN, 15); */ static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect ) { int offs; if (title_screen) return; else bg_clip_mode = -10; for (offs = 11; offs < spriteram_size; offs += 16) { int tileofs0, tileofs1, tileofs2, tileofs3, temp1, temp2; int attr = spriteram[offs + 2]; int code = spriteram[offs + 3] + ((attr & 0xc0) << 2); int color = spriteram[offs + 4] & 0x0f; int flipx = attr & 0x10; int flipy = attr & 0x20; int sx = spriteram[offs + 1]; int sy = spriteram[offs]; int size32 = attr & 0x08; if (attr & 0x01) sx -= 256; if (attr & 0x04) sy -= 256; if (flip_screen) { sx = 224 - sx; sy = 224 - sy; flipx = !flipx; flipy = !flipy; } if (flipy) { tileofs0 = 1; tileofs1 = 0; tileofs2 = 3; tileofs3 = 2; } else { tileofs0 = 0; tileofs1 = 1; tileofs2 = 2; tileofs3 = 3; } if (flipx) { temp1 = tileofs0; temp2 = tileofs1; tileofs0 = tileofs2; tileofs1 = tileofs3; tileofs2 = temp1; tileofs3 = temp2; } if (size32) { DRAW_SPRITE(code + tileofs0, sx, sy) DRAW_SPRITE(code + tileofs1, sx, sy + 16) DRAW_SPRITE(code + tileofs2, sx + 16, sy) DRAW_SPRITE(code + tileofs3, sx + 16, sy + 16) } else { if (flip_screen) DRAW_SPRITE(code, sx + 16, sy + 16) else DRAW_SPRITE(code, sx, sy) } } } static void draw_background(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect ) { int bg_scrollx = (ps5_io_ram[BG_SCROLLX_LSB] + ((ps5_io_ram[BG_SCROLLX_MSB] & 0x03) << 8)) & 0x3ff; int bg_scrolly = (ps5_io_ram[BG_SCROLLY_LSB] + ((ps5_io_ram[BG_SCROLLY_MSB] & 0x01) << 8)) & 0x1ff; tilemap_set_scrollx(bg_tilemap, 0, bg_scrollx); tilemap_set_scrolly(bg_tilemap, 0, bg_scrolly); set_background_palette_intensity(machine); if (ps5_io_ram[BG_SCREEN_MODE] & 0x01) /* background enable */ { if (title_screen) { rectangle clip = *cliprect; int sx1 = spriteram[12]; /* sprite 0 */ int sy1 = spriteram[11]; int tile = spriteram[14]; int sy2 = spriteram[11+128]; /* sprite 8 */ if (bg_clip_mode >=0 && bg_clip_mode < 3 && sy1==240) bg_clip_mode = 0; if (bg_clip_mode > 2 && bg_clip_mode < 5 && sy2==240) bg_clip_mode = -10; if (bg_clip_mode > 4 && bg_clip_mode < 7 && sx1==240) bg_clip_mode = 0; if (bg_clip_mode > 6 && bg_clip_mode < 9 && (sx1==240 || sx1==0)) bg_clip_mode = -10; if (sy1!=240 && sy1!=0 && bg_clip_mode<=0) { if (sy1 > 128) bg_clip_mode = 1; else bg_clip_mode = 2; } if (sy2!=240 && sy2!=0 && bg_clip_mode<=0) { if (sy2 > 128) bg_clip_mode = 3; else bg_clip_mode = 4; } if (sx1!=240 && sx1!=0 && bg_clip_mode<=0 && tile==0x3c) { if (sx1 > 128) bg_clip_mode = 5; else bg_clip_mode = 6; } if (sx1!=240 && sx1!=0 && bg_clip_mode<=0 && tile==0x1c) { if (sx1 > 128) bg_clip_mode = 7; else bg_clip_mode = 8; } if (bg_clip_mode) { if (bg_clip_mode == 1) clip.min_y = sy1; else if (bg_clip_mode == 2) clip.max_y = sy1; else if (bg_clip_mode == 3) clip.max_y = sy2; else if (bg_clip_mode == 4) clip.min_y = sy2; else if (bg_clip_mode == 5) clip.min_x = sx1; else if (bg_clip_mode == 6) clip.max_x = sx1; else if (bg_clip_mode == 7) clip.max_x = sx1; else if (bg_clip_mode == 8) clip.min_x = sx1; else if (bg_clip_mode == -10) { clip.min_x = 0; clip.min_y = 0; clip.max_x = 0; clip.max_y = 0; } fillbitmap(bitmap, get_black_pen(machine), cliprect); tilemap_draw(bitmap, &clip, bg_tilemap, 0, 0); } else tilemap_draw(bitmap, cliprect, bg_tilemap, 0, 0); } else tilemap_draw(bitmap, cliprect, bg_tilemap, 0, 0); } else fillbitmap(bitmap, get_black_pen(machine), cliprect); } VIDEO_UPDATE( psychic5 ) { draw_background(machine, bitmap, cliprect); draw_sprites(machine, bitmap, cliprect); tilemap_draw(bitmap, cliprect, fg_tilemap, 0, 0); return 0; }