summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/cosmic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/cosmic.c')
-rw-r--r--src/mame/video/cosmic.c667
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;
+}