diff options
Diffstat (limited to 'src/mame/video/cloud9.c')
-rw-r--r-- | src/mame/video/cloud9.c | 332 |
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; +} |