diff options
Diffstat (limited to 'src/mame/video/cosmic.c')
-rw-r--r-- | src/mame/video/cosmic.c | 667 |
1 files changed, 667 insertions, 0 deletions
diff --git a/src/mame/video/cosmic.c b/src/mame/video/cosmic.c new file mode 100644 index 00000000000..b7aebdfa96b --- /dev/null +++ b/src/mame/video/cosmic.c @@ -0,0 +1,667 @@ +/*************************************************************************** + + COSMIC.C + + emulation of video hardware of cosmic machines of 1979-1980(ish) + +***************************************************************************/ + +#include "driver.h" + + +static pen_t (*map_color)(UINT8 x, UINT8 y); + +static int color_registers[3]; +static int background_enable; +static int magspot_pen_mask; + + + +WRITE8_HANDLER( cosmic_color_register_w ) +{ + color_registers[offset] = data ? 1 : 0; +} + + +static pen_t panic_map_color(UINT8 x, UINT8 y) +{ + offs_t offs; + pen_t pen; + + + offs = (color_registers[0] << 9) | (color_registers[2] << 10) | ((x >> 4) << 5) | (y >> 3); + pen = memory_region(REGION_USER1)[offs]; + + if (color_registers[1]) + pen >>= 4; + + return pen & 0x0f; +} + +static pen_t cosmica_map_color(UINT8 x, UINT8 y) +{ + offs_t offs; + pen_t pen; + + + offs = (color_registers[0] << 9) | ((x >> 4) << 5) | (y >> 3); + pen = memory_region(REGION_USER1)[offs]; + + if (color_registers[0]) /* yes, 0 again according to the schematics */ + pen >>= 4; + + return pen & 0x07; +} + +static pen_t cosmicg_map_color(UINT8 x, UINT8 y) +{ + offs_t offs; + pen_t pen; + + + offs = (color_registers[0] << 8) | (color_registers[1] << 9) | ((y >> 4) << 4) | (x >> 4); + pen = memory_region(REGION_USER1)[offs]; + + /* the upper 4 bits are for cocktail mode support */ + + return pen & 0x0f; +} + +static pen_t magspot2_map_color(UINT8 x, UINT8 y) +{ + offs_t offs; + pen_t pen; + + + offs = (color_registers[0] << 9) | ((x >> 3) << 4) | (y >> 4); + pen = memory_region(REGION_USER1)[offs]; + + if (color_registers[1]) + pen >>= 4; + + return pen & magspot_pen_mask; +} + + + +/* + * Panic Color table setup + * + * Bit 0 = RED, Bit 1 = GREEN, Bit 2 = BLUE + * + * First 8 colors are normal intensities + * + * But, bit 3 can be used to pull Blue via a 2k resistor to 5v + * (1k to ground) so second version of table has blue set to 2/3 + */ + +PALETTE_INIT( panic ) +{ + int i; + #define TOTAL_COLORS(gfxn) (machine->gfx[gfxn]->total_colors * machine->gfx[gfxn]->color_granularity) + #define COLOR(gfxn,offs) (colortable[machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs]) + + for (i = 0;i < machine->drv->total_colors;i++) + { + int r = 0xff * ((i >> 0) & 1); + int g = 0xff * ((i >> 1) & 1); + int b; + if ((i & 0x0c) == 0x08) + b = 0xaa; + else + b = 0xff * ((i >> 2) & 1); + palette_set_color(machine,i,MAKE_RGB(r,g,b)); + } + + + for (i = 0;i < TOTAL_COLORS(0);i++) + COLOR(0,i) = *(color_prom++) & 0x07; + + + map_color = panic_map_color; +} + + +/* + * Cosmic Alien Color table setup + * + * 8 colors, 16 sprite color codes + * + * Bit 0 = RED, Bit 1 = GREEN, Bit 2 = BLUE + * + */ + +PALETTE_INIT( cosmica ) +{ + int i; + + #define TOTAL_COLORS(gfxn) (machine->gfx[gfxn]->total_colors * machine->gfx[gfxn]->color_granularity) + #define COLOR(gfxn,offs) (colortable[machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs]) + + for (i = 0;i < machine->drv->total_colors;i++) + palette_set_color_rgb(machine,i,pal1bit(i >> 0),pal1bit(i >> 1),pal1bit(i >> 2)); + + + for (i = 0;i < TOTAL_COLORS(0)/2;i++) + { + COLOR(0,i) = * color_prom & 0x07; + COLOR(0,i+(TOTAL_COLORS(0)/2)) = (*(color_prom++) >> 4) & 0x07; + } + + + map_color = cosmica_map_color; +} + + +/* + * Cosmic guerilla table setup + * + * Use AA for normal, FF for Full Red + * Bit 0 = R, bit 1 = G, bit 2 = B, bit 4 = High Red + * + * It's possible that the background is dark gray and not black, as the + * resistor chain would never drop to zero, Anybody know ? + */ + +PALETTE_INIT( cosmicg ) +{ + int i; + + for (i = 0;i < machine->drv->total_colors;i++) + { + int r,g,b; + + if (i > 8) r = 0xff; + else r = 0xaa * ((i >> 0) & 1); + + g = 0xaa * ((i >> 1) & 1); + b = 0xaa * ((i >> 2) & 1); + palette_set_color(machine,i,MAKE_RGB(r,g,b)); + } + + + map_color = cosmicg_map_color; +} + +PALETTE_INIT( magspot2 ) +{ + int i; + #define TOTAL_COLORS(gfxn) (machine->gfx[gfxn]->total_colors * machine->gfx[gfxn]->color_granularity) + #define COLOR(gfxn,offs) (colortable[machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs]) + + + for (i = 0;i < machine->drv->total_colors;i++) + { + int r,g,b; + + if ((i & 0x09) == 0x08) + r = 0xaa; + else + r = 0xff * ((i >> 0) & 1); + + g = 0xff * ((i >> 1) & 1); + b = 0xff * ((i >> 2) & 1); + palette_set_color(machine,i,MAKE_RGB(r,g,b)); + } + + + for (i = 0;i < TOTAL_COLORS(0);i++) + { + COLOR(0,i) = *(color_prom++) & 0x0f; + } + + + map_color = magspot2_map_color; + magspot_pen_mask = 0x0f; +} + + +PALETTE_INIT( nomnlnd ) +{ + int i; + #define TOTAL_COLORS(gfxn) (machine->gfx[gfxn]->total_colors * machine->gfx[gfxn]->color_granularity) + #define COLOR(gfxn,offs) (colortable[machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs]) + + + for (i = 0;i < machine->drv->total_colors;i++) + palette_set_color_rgb(machine,i,pal1bit(i >> 0),pal1bit(i >> 1),pal1bit(i >> 2)); + + + for (i = 0;i < TOTAL_COLORS(0);i++) + { + COLOR(0,i) = *(color_prom++) & 0x07; + } + + + map_color = magspot2_map_color; + magspot_pen_mask = 0x07; +} + + +WRITE8_HANDLER( cosmic_background_enable_w ) +{ + background_enable = data; +} + + +static void draw_bitmap(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ + offs_t offs; + + + for (offs = 0; offs < videoram_size; offs++) + { + UINT8 data = videoram[offs]; + + if (data != 0) /* optimization, not absolutely neccessary */ + { + int i; + UINT8 x = offs << 3; + UINT8 y = offs >> 5; + + pen_t pen = machine->pens[map_color(x, y)]; + + + for (i = 0; i < 8; i++) + { + if (data & 0x80) + { + if (flip_screen) + *BITMAP_ADDR16(bitmap, 255-y, 255-x) = pen; + else + *BITMAP_ADDR16(bitmap, y, x) = pen; + } + + x++; + data <<= 1; + } + } + } +} + + +static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, int color_mask, int extra_sprites) +{ + int offs; + + + for (offs = spriteram_size - 4;offs >= 0;offs -= 4) + { + if (spriteram[offs] != 0) + { + int code, color; + + code = ~spriteram[offs ] & 0x3f; + color = ~spriteram[offs+3] & color_mask; + + if (extra_sprites) + { + code |= (spriteram[offs+3] & 0x08) << 3; + } + + if (spriteram[offs] & 0x80) + { + /* 16x16 sprite */ + + drawgfx(bitmap,machine->gfx[0], + code, color, + 0, ~spriteram[offs] & 0x40, + 256-spriteram[offs+2],spriteram[offs+1], + cliprect,TRANSPARENCY_PEN,0); + } + else + { + /* 32x32 sprite */ + + drawgfx(bitmap,machine->gfx[1], + code >> 2, color, + 0, ~spriteram[offs] & 0x40, + 256-spriteram[offs+2],spriteram[offs+1], + cliprect,TRANSPARENCY_PEN,0); + } + } + } +} + + +static void cosmica_draw_starfield(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ + UINT8 y = 0; + UINT8 map = 0; + UINT8 *PROM = memory_region(REGION_USER2); + + + while (1) + { + int va = y & 0x01; + int vb = (y >> 1) & 0x01; + + + UINT8 x = 0; + + while (1) + { + UINT8 x1; + int hc, hb_; + + + if (flip_screen) + x1 = x - cpu_getcurrentframe(); + else + x1 = x + cpu_getcurrentframe(); + + + hc = (x1 >> 2) & 0x01; + hb_ = (x >> 5) & 0x01; /* not a bug, this one is the real x */ + + + if ((x1 & 0x1f) == 0) + { + // flip-flop at IC11 is clocked + map = PROM[(x1 >> 5) | (y >> 1 << 3)]; + } + + + if ((!(hc & va) & (vb ^ hb_)) && /* right network */ + (((x1 ^ map) & (hc | 0x1e)) == 0x1e)) /* left network */ + { + /* RGB order is reversed -- bit 7=R, 6=G, 5=B */ + int col = (map >> 7) | ((map >> 5) & 0x02) | ((map >> 3) & 0x04); + + *BITMAP_ADDR16(bitmap, y, x) = machine->pens[col]; + } + + + x++; + if (x == 0) break; + } + + + y++; + if (y == 0) break; + } +} + + +static void devzone_draw_grid(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ + UINT8 y; + UINT8 *horz_PROM = memory_region(REGION_USER2); + UINT8 *vert_PROM = memory_region(REGION_USER3); + offs_t horz_addr = 0; + + UINT8 count = 0; + UINT8 horz_data = 0; + UINT8 vert_data; + + + for (y = 32; y < 224; y++) + { + UINT8 x = 0; + + + while (1) + { + int x1; + + + /* for the vertical lines, each bit indicates + if there should be a line at the x position */ + vert_data = vert_PROM[x >> 3]; + + + /* the horizontal (perspective) lines are RLE encoded. + When the screen is flipped, the address should be + decrementing. But since it's just a mirrored image, + this is easier. */ + if (count == 0) + { + count = horz_PROM[horz_addr++]; + } + + count++; + + if (count == 0) + { + horz_data = horz_PROM[horz_addr++]; + } + + + for (x1 = 0; x1 < 8; x1++) + { + if (!(vert_data & horz_data & 0x80)) /* NAND gate */ + { + pen_t pen = machine->pens[4]; /* blue */ + + if (flip_screen) + *BITMAP_ADDR16(bitmap, 255-y, 255-x) = pen; + else + *BITMAP_ADDR16(bitmap, y, x) = pen; + } + + horz_data = (horz_data << 1) | 0x01; + vert_data = (vert_data << 1) | 0x01; + + x++; + } + + + if (x == 0) break; + } + } +} + + +static void nomnlnd_draw_background(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ + UINT8 y = 0; + UINT8 water = cpu_getcurrentframe(); + UINT8 *PROM = memory_region(REGION_USER2); + + + /* all positioning is via logic gates: + + tree is displayed where + + __ __ + HD' ^ HC' ^ HB' + + and + __ __ __ + (VB' ^ VC' ^ VD') X (VB' ^ VC' ^ VD') + + + water is displayed where + __ __ + HD' ^ HC' ^ HB ^ HA' + + and vertically the same equation as the trees, + but final result inverted. + + + The colors are coded in logic gates: + + trees: + P1 P2 BGR + R = Plane1 ^ Plane2 0 0 000 + G = Plane2 0 1 010 + B = Plane1 ^ ~Plane2 1 0 100 + 1 1 011 + + water: + P1 P2 BGR or + R = Plane1 ^ Plane2 0 0 100 000 + G = Plane2 v Plane2 0 1 110 010 + B = ~Plane1 or 1 0 010 010 + 0 based oh HD 1 1 011 011 + + Not sure about B, the logic seems convulated for such + a simple result. + + */ + + while (1) + { + int vb_ = (y >> 5) & 0x01; + int vc_ = (y >> 6) & 0x01; + int vd_ = y >> 7; + + UINT8 x = 0; + + + while (1) + { + int color = 0; + + int hd = (x >> 3) & 0x01; + int ha_ = (x >> 4) & 0x01; + int hb_ = (x >> 5) & 0x01; + int hc_ = (x >> 6) & 0x01; + int hd_ = x >> 7; + + + if ((!vb_ & vc_ & !vd_) ^ (vb_ & !vc_ & vd_)) + { + /* tree */ + if (!hd_ & hc_ & !hb_) + { + offs_t offs = ((x >> 3) & 0x03) | ((y & 0x1f) << 2) | + (flip_screen ? 0x80 : 0); + + UINT8 plane1 = PROM[offs ] << (x & 0x07); + UINT8 plane2 = PROM[offs | 0x0400] << (x & 0x07); + + plane1 >>= 7; + plane2 >>= 7; + + color = (plane1 & plane2) | // R + (plane2 ) << 1 | // G + (plane1 & !plane2) << 2; // B + } + } + else + { + /* water */ + if (hd_ & !hc_ & hb_ & !ha_) + { + offs_t offs = hd | (water << 1) | 0x0200; + + UINT8 plane1 = PROM[offs ] << (x & 0x07); + UINT8 plane2 = PROM[offs | 0x0400] << (x & 0x07); + + plane1 >>= 7; + plane2 >>= 7; + + color = ( plane1 & plane2) | // R + ( plane1 | plane2) << 1 | // G + (!plane1 & hd) << 2; // B - see above + } + } + + + if (color != 0) + { + pen_t pen = machine->pens[color]; + + if (flip_screen) + *BITMAP_ADDR16(bitmap, 255-y, 255-x) = pen; + else + *BITMAP_ADDR16(bitmap, y, x) = pen; + } + + + x++; + if (x == 0) break; + } + + + // this is obviously wrong +// if (vb_) +// { + water++; +// } + + + y++; + if (y == 0) break; + } +} + + +VIDEO_UPDATE( cosmicg ) +{ + fillbitmap(bitmap, machine->pens[0], cliprect); + + draw_bitmap(machine, bitmap, cliprect); + return 0; +} + + +VIDEO_UPDATE( panic ) +{ + fillbitmap(bitmap, machine->pens[0], cliprect); + + draw_bitmap(machine, bitmap, cliprect); + + draw_sprites(machine, bitmap, cliprect, 0x07, 1); + return 0; +} + + +VIDEO_UPDATE( cosmica ) +{ + fillbitmap(bitmap, machine->pens[0], cliprect); + + cosmica_draw_starfield(machine, bitmap, cliprect); + + draw_bitmap(machine, bitmap, cliprect); + + draw_sprites(machine, bitmap, cliprect, 0x0f, 0); + return 0; +} + + +VIDEO_UPDATE( magspot2 ) +{ + fillbitmap(bitmap, machine->pens[0], cliprect); + + draw_bitmap(machine, bitmap, cliprect); + + draw_sprites(machine, bitmap, cliprect, 0x07, 0); + return 0; +} + + +VIDEO_UPDATE( devzone ) +{ + fillbitmap(bitmap, machine->pens[0], cliprect); + + if (background_enable) + { + devzone_draw_grid(machine, bitmap, cliprect); + } + + draw_bitmap(machine, bitmap, cliprect); + + draw_sprites(machine, bitmap, cliprect, 0x07, 0); + return 0; +} + + +VIDEO_UPDATE( nomnlnd ) +{ + /* according to the video summation logic on pg4, the trees and river + have the highest priority */ + + fillbitmap(bitmap, machine->pens[0], cliprect); + + draw_bitmap(machine, bitmap, cliprect); + + draw_sprites(machine, bitmap, cliprect, 0x07, 0); + + if (background_enable) + { + nomnlnd_draw_background(machine, bitmap, cliprect); + } + return 0; +} |