summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/cloud9.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/cloud9.c')
-rw-r--r--src/mame/video/cloud9.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/src/mame/video/cloud9.c b/src/mame/video/cloud9.c
new file mode 100644
index 00000000000..239c140bd7d
--- /dev/null
+++ b/src/mame/video/cloud9.c
@@ -0,0 +1,332 @@
+/***************************************************************************
+
+ Atari Cloud 9 (prototype) hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cloud9.h"
+#include "video/resnet.h"
+
+
+/*************************************
+ *
+ * Globals
+ *
+ *************************************/
+
+static double rweights[3], gweights[3], bweights[3];
+static mame_bitmap *spritebitmap;
+
+static UINT8 video_control[8];
+static UINT8 bitmode_addr[2];
+
+static const UINT8 *syncprom;
+static const UINT8 *wpprom;
+static const UINT8 *priprom;
+
+
+
+/*************************************
+ *
+ * Video startup
+ *
+ *************************************/
+
+VIDEO_START( cloud9 )
+{
+ static const int resistances[3] = { 22000, 10000, 4700 };
+
+ /* allocate second bank of videoram */
+ videoram = auto_malloc(0x8000);
+ memory_set_bankptr(1, videoram);
+
+ /* get pointers to our PROMs */
+ syncprom = memory_region(REGION_PROMS) + 0x000;
+ wpprom = memory_region(REGION_PROMS) + 0x200;
+ priprom = memory_region(REGION_PROMS) + 0x300;
+
+ /* compute the color output resistor weights at startup */
+ compute_resistor_weights(0, 255, -1.0,
+ 3, resistances, rweights, 1000, 0,
+ 3, resistances, gweights, 1000, 0,
+ 3, resistances, bweights, 1000, 0);
+
+ /* allocate a bitmap for drawing sprites */
+ spritebitmap = auto_bitmap_alloc(machine->screen[0].width, machine->screen[0].height, machine->screen[0].format);
+
+ /* register for savestates */
+ state_save_register_global_pointer(videoram, 0x8000);
+ state_save_register_global_array(video_control);
+ state_save_register_global_array(bitmode_addr);
+}
+
+
+
+/*************************************
+ *
+ * Video control registers
+ *
+ *************************************/
+
+WRITE8_HANDLER( cloud9_video_control_w )
+{
+ /* only D7 matters */
+ video_control[offset] = (data >> 7) & 1;
+}
+
+
+
+/*************************************
+ *
+ * Palette RAM accesses
+ *
+ *************************************/
+
+WRITE8_HANDLER( cloud9_paletteram_w )
+{
+ int bit0, bit1, bit2;
+ int r, g, b;
+
+ /* extract the raw RGB bits */
+ r = (data & 0xe0) >> 5;
+ g = (data & 0x1c) >> 2;
+ b = ((data & 0x03) << 1) | ((offset & 0x40) >> 6);
+
+ /* red component (inverted) */
+ bit0 = (~r >> 0) & 0x01;
+ bit1 = (~r >> 1) & 0x01;
+ bit2 = (~r >> 2) & 0x01;
+ r = combine_3_weights(rweights, bit0, bit1, bit2);
+
+ /* green component (inverted) */
+ bit0 = (~g >> 0) & 0x01;
+ bit1 = (~g >> 1) & 0x01;
+ bit2 = (~g >> 2) & 0x01;
+ g = combine_3_weights(gweights, bit0, bit1, bit2);
+
+ /* blue component (inverted) */
+ bit0 = (~b >> 0) & 0x01;
+ bit1 = (~b >> 1) & 0x01;
+ bit2 = (~b >> 2) & 0x01;
+ b = combine_3_weights(bweights, bit0, bit1, bit2);
+
+ palette_set_color(Machine, offset & 0x3f, MAKE_RGB(r, g, b));
+}
+
+
+
+/*************************************
+ *
+ * Video RAM access via the write
+ * protect PROM
+ *
+ *************************************/
+
+INLINE void cloud9_write_vram(UINT16 addr, UINT8 data, UINT8 bitmd, UINT8 pixba)
+{
+ UINT8 *dest = &videoram[0x0000 | (addr & 0x3fff)];
+ UINT8 *dest2 = &videoram[0x4000 | (addr & 0x3fff)];
+ UINT8 promaddr = 0;
+ UINT8 wpbits;
+
+ /*
+ Inputs to the write-protect PROM:
+
+ Bit 7 = BITMD
+ Bit 6 = video_control[4]
+ Bit 5 = video_control[6]
+ Bit 4 = 1 if (A15-A12 != 4)
+ Bit 3 = !(A13 | A12 | A11)
+ Bit 2 = A9 & A10
+ Bit 1 = PIXB
+ Bit 0 = PIXA
+ */
+ promaddr |= bitmd << 7;
+ promaddr |= video_control[4] << 6;
+ promaddr |= video_control[6] << 5;
+ promaddr |= ((addr & 0xf000) != 0x4000) << 4;
+ promaddr |= ((addr & 0x3800) == 0x0000) << 3;
+ promaddr |= ((addr & 0x0600) == 0x0600) << 2;
+ promaddr |= (pixba << 0);
+
+ /* look up the PROM result */
+ wpbits = wpprom[promaddr];
+
+ /* write to the appropriate parts of VRAM depending on the result */
+ if (!(wpbits & 1))
+ dest2[0] = (dest2[0] & 0x0f) | (data & 0xf0);
+ if (!(wpbits & 2))
+ dest2[0] = (dest2[0] & 0xf0) | (data & 0x0f);
+ if (!(wpbits & 4))
+ dest[0] = (dest[0] & 0x0f) | (data & 0xf0);
+ if (!(wpbits & 8))
+ dest[0] = (dest[0] & 0xf0) | (data & 0x0f);
+}
+
+
+
+/*************************************
+ *
+ * Autoincrement control for bit mode
+ *
+ *************************************/
+
+INLINE void bitmode_autoinc(void)
+{
+ /* auto increment in the x-direction if it's enabled */
+ if (!video_control[0]) /* /AX */
+ bitmode_addr[0]++;
+
+ /* auto increment in the y-direction if it's enabled */
+ if (!video_control[1]) /* /AY */
+ bitmode_addr[1]++;
+}
+
+
+
+/*************************************
+ *
+ * Standard video RAM access
+ *
+ *************************************/
+
+WRITE8_HANDLER( cloud9_videoram_w )
+{
+ /* direct writes to VRAM go through the write protect PROM as well */
+ cloud9_write_vram(offset, data, 0, 0);
+}
+
+
+
+/*************************************
+ *
+ * Bit mode video RAM access
+ *
+ *************************************/
+
+READ8_HANDLER( cloud9_bitmode_r )
+{
+ /* in bitmode, the address comes from the autoincrement latches */
+ UINT16 addr = (bitmode_addr[1] << 6) | (bitmode_addr[0] >> 2);
+
+ /* the appropriate pixel is selected into the upper 4 bits */
+ UINT8 result = videoram[((~bitmode_addr[0] & 2) << 13) | addr] << ((bitmode_addr[0] & 1) * 4);
+
+ /* autoincrement because /BITMD was selected */
+ bitmode_autoinc();
+
+ /* the upper 4 bits of the data lines are not driven so make them all 1's */
+ return (result >> 4) | 0xf0;
+}
+
+
+WRITE8_HANDLER( cloud9_bitmode_w )
+{
+ /* in bitmode, the address comes from the autoincrement latches */
+ UINT16 addr = (bitmode_addr[1] << 6) | (bitmode_addr[0] >> 2);
+
+ /* the lower 4 bits of data are replicated to the upper 4 bits */
+ data = (data & 0x0f) | (data << 4);
+
+ /* write through the generic VRAM routine, passing the low 2 X bits as PIXB/PIXA */
+ cloud9_write_vram(addr, data, 1, bitmode_addr[0] & 3);
+
+ /* autoincrement because /BITMD was selected */
+ bitmode_autoinc();
+}
+
+
+WRITE8_HANDLER( cloud9_bitmode_addr_w )
+{
+ /* write through to video RAM and also to the addressing latches */
+ cloud9_write_vram(offset, data, 0, 0);
+ bitmode_addr[offset] = data;
+}
+
+
+
+/*************************************
+ *
+ * Video updating
+ *
+ *************************************/
+
+VIDEO_UPDATE( cloud9 )
+{
+ UINT8 *spriteaddr = spriteram;
+ int flip = video_control[5] ? 0xff : 0x00; /* PLAYER2 */
+ pen_t black = get_black_pen(machine);
+ int x, y, offs;
+
+ /* draw the sprites */
+ fillbitmap(spritebitmap, 0x00, cliprect);
+ for (offs = 0; offs < 0x20; offs++)
+ if (spriteaddr[offs + 0x00] != 0)
+ {
+ int x = spriteaddr[offs + 0x60];
+ int y = 256 - 15 - spriteaddr[offs + 0x00];
+ int xflip = spriteaddr[offs + 0x40] & 0x80;
+ int yflip = spriteaddr[offs + 0x40] & 0x40;
+ int which = spriteaddr[offs + 0x20];
+ int color = 0;
+
+ drawgfx(spritebitmap, machine->gfx[0], which, color, xflip, yflip, x, y, cliprect, TRANSPARENCY_PEN, 0);
+ if (x >= 256 - 16)
+ drawgfx(spritebitmap, machine->gfx[0], which, color, xflip, yflip, x - 256, y, cliprect, TRANSPARENCY_PEN, 0);
+ }
+
+ /* draw the bitmap to the screen, looping over Y */
+ for (y = cliprect->min_y; y <= cliprect->max_y; y++)
+ {
+ UINT16 *dst = (UINT16 *)bitmap->base + y * bitmap->rowpixels;
+
+ /* if we're in the VBLANK region, just fill with black */
+ if (~syncprom[y] & 2)
+ {
+ for (x = cliprect->min_x; x <= cliprect->max_x; x++)
+ dst[x] = black;
+ }
+
+ /* non-VBLANK region: merge the sprites and the bitmap */
+ else
+ {
+ UINT16 *mosrc = (UINT16 *)spritebitmap->base + y * spritebitmap->rowpixels;
+ int effy = y ^ flip;
+ UINT8 *src[2];
+
+ /* two videoram arrays */
+ src[0] = &videoram[0x4000 | (effy * 64)];
+ src[1] = &videoram[0x0000 | (effy * 64)];
+
+ /* loop over X */
+ for (x = cliprect->min_x; x <= cliprect->max_x; x++)
+ {
+ /* if we're in the HBLANK region, just store black */
+ if (x >= 256)
+ dst[x] = black;
+
+ /* otherwise, process normally */
+ else
+ {
+ int effx = x ^ flip;
+
+ /* low 4 bits = left pixel, high 4 bits = right pixel */
+ UINT8 pix = (src[(effx >> 1) & 1][effx / 4] >> ((~effx & 1) * 4)) & 0x0f;
+ UINT8 mopix = mosrc[x];
+
+ /* sprites have priority if sprite pixel != 0 or some other condition */
+ if (mopix != 0)
+ pix = mopix | 0x10;
+
+ /* the high bit is the bank select */
+ pix |= video_control[7] << 5;
+
+ /* store the pixel value and also a priority value based on the topmost bit */
+ dst[x] = pix;
+ }
+ }
+ }
+ }
+ return 0;
+}