/*************************************************************************** video\cvs.c Functions to emulate the video hardware of the machine. ***************************************************************************/ #include "driver.h" #include "video/s2636.h" #include "cpu/s2650/s2650.h" #define MAX_STARS 250 #define STARS_COLOR_BASE 16 #ifdef LSB_FIRST #define BL0 0 #define BL1 1 #define BL2 2 #define BL3 3 #define WL0 0 #define WL1 1 #else #define BL0 3 #define BL1 2 #define BL2 1 #define BL3 0 #define WL0 1 #define WL1 0 #endif struct star { int x,y,code; }; static struct star stars[MAX_STARS]; static int total_stars; static int scroll[8]; static int stars_on=0; static int character_mode=0; static int character_page=0; static int scroll_reg = 0; static int stars_scroll=0; static UINT8 *dirty_character; static UINT8 *character_1_ram; static UINT8 *character_2_ram; static UINT8 *character_3_ram; UINT8 *bullet_ram; mame_bitmap *collision_bitmap; mame_bitmap *collision_background; static mame_bitmap *scrolled_background; int CollisionRegister=0; static int ModeOffset[4] = {223,191,255,127}; /****************************************************** * Convert Colour prom to format for Mame Colour Map * * * * There is a prom used for colour mapping and plane * * priority. This is converted to a colour table here * * * * colours are taken from SRAM and are programmable * ******************************************************/ PALETTE_INIT( cvs ) { int attr,col,map; #define COLOR(gfxn,offs) (colortable[machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs]) /* Colour Mapping Prom */ for(attr = 0;attr < 256; attr++) { for(col = 0; col < 8; col++) { map = color_prom[(col * 256) + attr]; /* bits 1 and 3 are swopped over */ COLOR(0,attr*8 + col) = ((map & 1) << 2) + (map & 2) + ((map & 4) >> 2); } } /* Background Collision Map */ for(map=0;map<8;map++) { COLOR(0,2048+map) = (map & 4) >> 2; COLOR(0,2056+map) = (map & 2) >> 1; COLOR(0,2064+map) = ((map & 2) >> 1) || ((map & 4) >> 2); } /* Sprites */ for(map=0;map<8;map++) { COLOR(0,map*2 + 2072) = 0; COLOR(0,map*2 + 2073) = 8 + map; } /* Initialise Dirty Character Array */ dirty_character = auto_malloc(0x100); character_1_ram = auto_malloc(0x2000); character_2_ram = character_1_ram + 0x800; character_3_ram = character_2_ram + 0x800; memset(dirty_character, 0, 256); memset(character_1_ram, 0, 1024); memset(character_2_ram, 0, 1024); memset(character_3_ram, 0, 1024); /* Set Sprite chip offsets */ s2636_x_offset = -26; s2636_y_offset = 3; /* Set Scroll fixed areas */ scroll[0]=0; scroll[6]=0; scroll[7]=0; } WRITE8_HANDLER( cvs_video_fx_w ) { logerror("%4x : Data Port = %2x\n",activecpu_get_pc(),data); /* Unimplemented */ if(data & 2) logerror(" SHADE BRIGHTER TO RIGHT\n"); if(data & 4) logerror(" SCREEN ROTATE\n"); if(data & 8) logerror(" SHADE BRIGHTER TO LEFT\n"); if(data & 64) logerror(" SHADE BRIGHTER TO BOTTOM\n"); if(data & 128) logerror(" SHADE BRIGHTER TO TOP\n"); /* Implemented */ stars_on = data & 1; set_led_status(1,data & 16); /* Lamp 1 */ set_led_status(2,data & 32); /* Lamp 2 */ } READ8_HANDLER( cvs_character_mode_r ) { /* Really a write - uses address info */ int value = offset + 0x10; int newmode = (value >> 4) & 3; character_mode = newmode; character_page = (value << 2) & 0x300; return 0; } READ8_HANDLER( cvs_collision_r ) { return CollisionRegister; } READ8_HANDLER( cvs_collision_clear ) { CollisionRegister=0; return 0; } WRITE8_HANDLER( cvs_scroll_w ) { scroll_reg = 255 - data; scroll[1]=scroll_reg; scroll[2]=scroll_reg; scroll[3]=scroll_reg; scroll[4]=scroll_reg; scroll[5]=scroll_reg; } WRITE8_HANDLER( cvs_videoram_w ) { if(!activecpu_get_reg(S2650_FO)) { // Colour Map colorram_w(offset,data); } else { // Data videoram_w(offset,data); } } READ8_HANDLER( cvs_videoram_r ) { if(!activecpu_get_reg(S2650_FO)) { // Colour Map return colorram[offset]; } else { // Data return videoram[offset]; } } WRITE8_HANDLER( cvs_bullet_w ) { if(!activecpu_get_reg(S2650_FO)) { // Bullet Ram bullet_ram[offset] = data; } else { // Pallette Ram - Inverted ? offset &= 0x0f; data ^= 0xff; paletteram[offset] = data; palette_set_color_rgb(Machine, offset, pal2bit(data >> 0), pal3bit(data >> 2), pal3bit(data >> 5)); } } READ8_HANDLER( cvs_bullet_r ) { if(!activecpu_get_reg(S2650_FO)) { // Bullet Ram return bullet_ram[offset]; } else { // Pallette Ram return (paletteram[offset] ^ 0xff); } } WRITE8_HANDLER( cvs_2636_1_w ) { if(!activecpu_get_reg(S2650_FO)) { // First 2636 s2636_w(s2636_1_ram,offset,data,s2636_1_dirty); } else { // Character Ram 1 if(character_1_ram[character_page + offset] != data) { character_1_ram[character_page + offset] = data; dirty_character[128+((character_page + offset)>>3)] = 1; } } } READ8_HANDLER( cvs_2636_1_r ) { if(!activecpu_get_reg(S2650_FO)) { // First 2636 return s2636_1_ram[offset]; } else { // Character Ram 1 return character_1_ram[character_page + offset]; } } WRITE8_HANDLER( cvs_2636_2_w ) { if(!activecpu_get_reg(S2650_FO)) { // Second 2636 s2636_w(s2636_2_ram,offset,data,s2636_2_dirty); } else { // Character Ram 2 if(character_2_ram[character_page + offset] != data) { character_2_ram[character_page + offset] = data; dirty_character[128+((character_page + offset)>>3)] = 1; } } } READ8_HANDLER( cvs_2636_2_r ) { if(!activecpu_get_reg(S2650_FO)) { // Second 2636 return s2636_2_ram[offset]; } else { // Character Ram 2 return character_2_ram[character_page + offset]; } } WRITE8_HANDLER( cvs_2636_3_w ) { if(!activecpu_get_reg(S2650_FO)) { // Third 2636 s2636_w(s2636_3_ram,offset,data,s2636_3_dirty); } else { // Character Ram 3 if(character_3_ram[character_page + offset] != data) { character_3_ram[character_page + offset] = data; dirty_character[128+((character_page + offset)>>3)] = 1; } } } READ8_HANDLER( cvs_2636_3_r ) { if(!activecpu_get_reg(S2650_FO)) { // Third 2636 return s2636_3_ram[offset]; } else { // Character Ram 3 return character_3_ram[character_page + offset]; } } VIDEO_START( cvs ) { int generator = 0; int x,y; colorram = auto_malloc(0x400); paletteram = auto_malloc(0x100); video_start_generic(machine); /* precalculate the star background */ total_stars = 0; for (y = 255;y >= 0;y--) { for (x = 511;x >= 0;x--) { int bit1,bit2; generator <<= 1; bit1 = (~generator >> 17) & 1; bit2 = (generator >> 5) & 1; if (bit1 ^ bit2) generator |= 1; if (((~generator >> 16) & 1) && (generator & 0xfe) == 0xfe) { if(((~(generator >> 12)) & 0x01) && ((~(generator >> 13)) & 0x01)) { if (total_stars < MAX_STARS) { stars[total_stars].x = x; stars[total_stars].y = y; stars[total_stars].code = 1; total_stars++; } } } } } /* Need 3 bitmaps for 2636 chips */ s2636_1_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); s2636_2_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); s2636_3_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); /* 3 bitmaps for collision detection */ collision_bitmap = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); collision_background = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); scrolled_background = auto_bitmap_alloc(machine->screen[0].width,machine->screen[0].height,BITMAP_FORMAT_INDEXED8); } INTERRUPT_GEN( cvs_interrupt ) { stars_scroll++; cpunum_set_input_line_vector(0,0,0x03); cpunum_set_input_line(0,0,PULSE_LINE); } INLINE void plot_star(running_machine* machine, mame_bitmap *bitmap, int x, int y) { if (flip_screen_x) { x = 255 - x; } if (flip_screen_y) { y = 255 - y; } if (*BITMAP_ADDR16(bitmap, y, x) == machine->pens[0]) { *BITMAP_ADDR16(bitmap, y, x) = machine->pens[7]; } } VIDEO_UPDATE( cvs ) { int offs; /* for every character in the Video RAM, check if it has been modified */ /* since last time and update it accordingly. */ for (offs = videoram_size - 1;offs >= 0;offs--) { int character_bank; int forecolor; int character = videoram[offs]; int sx = (offs % 32) * 8; int sy = (offs / 32) * 8; /* Decide if RAM or ROM based character */ if(character > ModeOffset[character_mode]) { /* re-generate character if dirty */ if (dirty_character[character]) { decodechar(machine->gfx[1],character,character_1_ram-1024,machine->drv->gfxdecodeinfo[1].gfxlayout); dirty_character[character] = 0; } character_bank=1; } else { character_bank=0; } /* Main Screen */ drawgfx(tmpbitmap,machine->gfx[character_bank], character, colorram[offs], 0,0, sx,sy, 0,TRANSPARENCY_NONE,0); /* Foreground for Collision Detection */ forecolor = 0; if(colorram[offs] & 0x80) { forecolor=258; } else { if((colorram[offs] & 0x03) == 3) forecolor=256; else if((colorram[offs] & 0x01) == 0) forecolor=257; } if(forecolor) drawgfx(collision_background,machine->gfx[character_bank], character, forecolor, 0,0, sx,sy, 0,TRANSPARENCY_NONE,0); } /* Update screen - 8 regions, fixed scrolling area */ copyscrollbitmap(bitmap,tmpbitmap,0,0,8,scroll,&machine->screen[0].visarea,TRANSPARENCY_NONE,0); copyscrollbitmap(scrolled_background,collision_background,0,0,8,scroll,&machine->screen[0].visarea,TRANSPARENCY_NONE,0); /* 2636's */ fillbitmap(s2636_1_bitmap,0,0); s2636_update_bitmap(machine,s2636_1_bitmap,s2636_1_ram,s2636_1_dirty,2,collision_bitmap); fillbitmap(s2636_2_bitmap,0,0); s2636_update_bitmap(machine,s2636_2_bitmap,s2636_2_ram,s2636_2_dirty,3,collision_bitmap); fillbitmap(s2636_3_bitmap,0,0); s2636_update_bitmap(machine,s2636_3_bitmap,s2636_3_ram,s2636_3_dirty,4,collision_bitmap); /* Bullet Hardware */ for (offs = 8; offs < 256; offs++ ) { if(bullet_ram[offs] != 0) { int ct; for(ct=0;ct<4;ct++) { int bx=255-7-bullet_ram[offs]-ct; /* Bullet/Object Collision */ if((CollisionRegister & 8) == 0) { if ((*BITMAP_ADDR8(s2636_1_bitmap, offs, bx) != 0) || (*BITMAP_ADDR8(s2636_2_bitmap, offs, bx) != 0) || (*BITMAP_ADDR8(s2636_3_bitmap, offs, bx) != 0)) CollisionRegister |= 8; } /* Bullet/Background Collision */ if((CollisionRegister & 0x80) == 0) { if (*BITMAP_ADDR8(scrolled_background, offs, bx) != machine->pens[0]) CollisionRegister |= 0x80; } *BITMAP_ADDR16(bitmap, offs, bx) = machine->pens[7]; } } } /* Update 2636 images */ { int sx; UINT32 S1,S2,S3,SB,pen; for(sx=255;sx>7;sx--) { UINT32 *sp1 = (UINT32 *)BITMAP_ADDR8(s2636_1_bitmap, sx, 0); UINT32 *sp2 = (UINT32 *)BITMAP_ADDR8(s2636_2_bitmap, sx, 0); UINT32 *sp3 = (UINT32 *)BITMAP_ADDR8(s2636_3_bitmap, sx, 0); UINT64 *dst = (UINT64 *)BITMAP_ADDR16(bitmap, sx, 0); UINT8 *spb = (UINT8 *)BITMAP_ADDR8(scrolled_background, sx, 0); for(offs=0;offs<62;offs++) { S1 = (*sp1++); S2 = (*sp2++); S3 = (*sp3++); pen = S1 | S2 | S3; if(pen) { UINT16 *address = (UINT16 *)dst; if (pen & 0xff000000) address[BL3] = machine->pens[(pen >> 24) & 15]; if (pen & 0x00ff0000) address[BL2] = machine->pens[(pen >> 16) & 15]; if (pen & 0x0000ff00) address[BL1] = machine->pens[(pen >> 8) & 15]; if (pen & 0x000000ff) address[BL0] = machine->pens[(pen & 15)]; /* Collision Detection */ SB = 0; if (spb[BL3] != machine->pens[0]) SB = 0x08000000; if (spb[BL2] != machine->pens[0]) SB |= 0x00080000; if (spb[BL1] != machine->pens[0]) SB |= 0x00000800; if (spb[BL0] != machine->pens[0]) SB |= 0x00000008; if (S1 & S2) CollisionRegister |= 1; if (S2 & S3) CollisionRegister |= 2; if (S1 & S3) CollisionRegister |= 4; if (SB) { if (S1 & SB) CollisionRegister |= 16; if (S2 & SB) CollisionRegister |= 32; if (S3 & SB) CollisionRegister |= 64; } } dst++; spb+=4; } } } /* Stars */ if(stars_on) { for (offs = 0;offs < total_stars;offs++) { int x,y; x = ((stars[offs].x + stars_scroll) % 512) / 2; y = (stars[offs].y + (stars_scroll + stars[offs].x) / 512) % 256; if (y >= machine->screen[0].visarea.min_y && y <= machine->screen[0].visarea.max_y) { if ((y & 1) ^ ((x >> 4) & 1)) { plot_star(machine, bitmap, x, y); } } } } return 0; }