/***************************************************************************

    Atari Cloud 9 (prototype) hardware

    driver by Mike Balfour

    Games supported:
        * Cloud 9
        * Firebeast

    Known issues:
        * none at this time

****************************************************************************

    Horizontal sync chain:

        Appears to be the same as Crystal Castles. See ccastles.c for
        details.

        Pixel clock = 5MHz
        HBLANK ends at H = 0
        HBLANK begins at H = 256
        HSYNC begins at H = 260 (? unconfirmed)
        HSYNC ends at H = 288 (? unconfirmed)
        HTOTAL = 320

    Vertical sync chain:

        Appears to be similar to Crystal Castles. The PROM at 10E seems
        to have a similar layout to the SYNC PROM used by Crystal
        Castles. The standard PROM maps as follows:

        VBLANK ends at V = 23
        VBLANK begins at V = 255
        VSYNC begins at V = 3
        VSYNC ends at V = 6
        VTOTAL = 256

    Interrupts:

        IRQ is clocked by /32V, so IRQs are generated a V = 0,64,128,192.

****************************************************************************

    This hardware is very similar to Crystal Castles. The primary
    difference is the lack of banked ROM and the mapping of the bitmap
    layer into the lower 20k instead of the lower 32k. In order to do
    this, they split the bitmap into two banks. Bank 0 holds pixels
    0,1,4,5,... while bank 1 holds pixels 2,3,6,7,... This is all handled
    transparently by bitmode.

    The lower 24 lines of video RAM are used for working RAM. This amounts
    to $600 bytes at $0000. In order to provide more work RAM, the write
    protect logic selects bank 1 for accesses to VRAM at $4000, so the
    other $600 bytes can be accessed there. Only Firebeast seems to use
    this RAM.

    0000        R/W     Write to bit mode X latch (and through to RAM)
    0001        R/W     Write to bit mode Y latch (and through to RAM)
    0002        R/W     Access the bitmap via bit mode
    0000-3FFF   R/W     Video RAM bank 0 (or 1 or both, depending on video control)
    4000-4FFF   R/W     Video RAM bank 1
    5000-53FF   R/W     Motion Object RAM
    5400        W       Watchdog
    5480        W       IRQ Acknowledge
    5500-557F   W       Color RAM (9 bits, 4 banks, LSB of Blue is addr&$40)
    5580        W       Auto-increment X bitmap index (~D7)
    5581        W       Auto-increment Y bitmap index (~D7)
    5584        W       VRAM Both Banks - (D7) seems to allow writing to both banks
    5585        W       Invert screen?
    5586        W       VRAM Bank select?
    5587        W       Color bank select
    5600        W       Coin Counter 1 (D7)
    5601        W       Coin Counter 2 (D7)
    5602        W       Start1 LED (~D7)
    5603        W       Start2 LED (~D7)
    5700        W       EAROM recall
    5800        R       IN0 (D7=Vblank, D6=Right Coin, D5=Left Coin, D4=Aux, D3=Self Test)
    5801        R       IN1 (D7=Start1, D6=Start2, D5=Fire, D4=Zap)
    5900        R       Trackball Vert
    5901        R       Trackball Horiz
    5A00-5A0F   R/W     Pokey 1
    5B00-5B0F   R/W     Pokey 2
    5C00-5CFF   W       EAROM
    6000-FFFF   R       Program ROM

    If you have any questions about how this driver works, don't hesitate to
    ask.  - Mike Balfour (mab22@po.cwru.edu)

***************************************************************************/

#include "driver.h"
#include "cpu/m6502/m6502.h"
#include "sound/pokey.h"
#include "cloud9.h"


#define MASTER_CLOCK	(10000000)

#define PIXEL_CLOCK		(MASTER_CLOCK/2)
#define HTOTAL			(320)
#define VTOTAL			(256)



/*************************************
 *
 *  Globals
 *
 *************************************/

static UINT8 *nvram_stage;
static const UINT8 *syncprom;
static UINT8 irq_state;
static emu_timer *irq_timer;

int cloud9_vblank_start;
int cloud9_vblank_end;



/*************************************
 *
 *  VBLANK and IRQ generation
 *
 *************************************/

INLINE void schedule_next_irq(running_machine *machine, int curscanline)
{
	/* IRQ is clocked by /32V, so every 64 scanlines */
	curscanline = (curscanline + 64) & 255;

	/* next one at the start of this scanline */
	timer_adjust_oneshot(irq_timer, video_screen_get_time_until_pos(machine->primary_screen, curscanline, 0), curscanline);
}


static TIMER_CALLBACK( clock_irq )
{
	/* assert the IRQ if not already asserted */
	if (!irq_state)
	{
		cputag_set_input_line(machine, "maincpu", 0, ASSERT_LINE);
		irq_state = 1;
	}

	/* force an update now */
	video_screen_update_partial(machine->primary_screen, video_screen_get_vpos(machine->primary_screen));

	/* find the next edge */
	schedule_next_irq(machine, param);
}


static CUSTOM_INPUT( get_vblank )
{
	int scanline = video_screen_get_vpos(field->port->machine->primary_screen);
	return (~syncprom[scanline & 0xff] >> 1) & 1;
}



/*************************************
 *
 *  Machine setup
 *
 *************************************/

static MACHINE_START( cloud9 )
{
	rectangle visarea;

	/* initialize globals */
	syncprom = memory_region(machine, "proms") + 0x000;

	/* find the start of VBLANK in the SYNC PROM */
	for (cloud9_vblank_start = 0; cloud9_vblank_start < 256; cloud9_vblank_start++)
		if ((syncprom[(cloud9_vblank_start - 1) & 0xff] & 2) != 0 && (syncprom[cloud9_vblank_start] & 2) == 0)
			break;
	if (cloud9_vblank_start == 0)
		cloud9_vblank_start = 256;

	/* find the end of VBLANK in the SYNC PROM */
	for (cloud9_vblank_end = 0; cloud9_vblank_end < 256; cloud9_vblank_end++)
		if ((syncprom[(cloud9_vblank_end - 1) & 0xff] & 2) == 0 && (syncprom[cloud9_vblank_end] & 2) != 0)
			break;

	/* can't handle the wrapping case */
	assert(cloud9_vblank_end < cloud9_vblank_start);

	/* reconfigure the visible area to match */
	visarea.min_x = 0;
	visarea.max_x = 255;
	visarea.min_y = cloud9_vblank_end + 1;
	visarea.max_y = cloud9_vblank_start;
	video_screen_configure(machine->primary_screen, 320, 256, &visarea, HZ_TO_ATTOSECONDS(PIXEL_CLOCK) * VTOTAL * HTOTAL);

	/* create a timer for IRQs and set up the first callback */
	irq_timer = timer_alloc(machine, clock_irq, NULL);
	irq_state = 0;
	schedule_next_irq(machine, 0-64);

	/* allocate backing memory for the NVRAM */
	generic_nvram = auto_alloc_array(machine, UINT8, generic_nvram_size);

	/* setup for save states */
	state_save_register_global(machine, irq_state);
	state_save_register_global_pointer(machine, generic_nvram, generic_nvram_size);
}


static MACHINE_RESET( cloud9 )
{
	cputag_set_input_line(machine, "maincpu", 0, CLEAR_LINE);
	irq_state = 0;
}



/*************************************
 *
 *  Output ports
 *
 *************************************/

static WRITE8_HANDLER( irq_ack_w )
{
	if (irq_state)
	{
		cputag_set_input_line(space->machine, "maincpu", 0, CLEAR_LINE);
		irq_state = 0;
	}
}


static WRITE8_HANDLER( cloud9_led_w )
{
	set_led_status(offset, ~data & 0x80);
}


static WRITE8_HANDLER( cloud9_coin_counter_w )
{
	coin_counter_w(offset, data & 0x80);
}


static READ8_HANDLER( leta_r )
{
	return input_port_read(space->machine, offset ? "TRACKX" : "TRACKY");
}



/*************************************
 *
 *  NVRAM handling
 *
 *************************************/

static NVRAM_HANDLER( cloud9 )
{
	if (read_or_write)
	{
		/* on power down, the EAROM is implicitly stored */
		memcpy(generic_nvram, nvram_stage, generic_nvram_size);
		mame_fwrite(file, generic_nvram, generic_nvram_size);
	}
	else if (file)
		mame_fread(file, generic_nvram, generic_nvram_size);
	else
		memset(generic_nvram, 0, generic_nvram_size);
}


static WRITE8_HANDLER( nvram_recall_w )
{
	memcpy(nvram_stage, generic_nvram, generic_nvram_size);
}


static WRITE8_HANDLER( nvram_store_w )
{
	memcpy(generic_nvram, nvram_stage, generic_nvram_size);
}


static READ8_HANDLER( nvram_r )
{
	/* only a single XD2212 for 4 bits of NVRAM */
	return nvram_stage[offset] | 0xf0;
}



/*************************************
 *
 *  Main CPU memory handlers
 *
 *************************************/

static ADDRESS_MAP_START( cloud9_map, ADDRESS_SPACE_PROGRAM, 8 )
	AM_RANGE(0x0000, 0x0001) AM_WRITE(cloud9_bitmode_addr_w)
	AM_RANGE(0x0002, 0x0002) AM_READWRITE(cloud9_bitmode_r, cloud9_bitmode_w)
	AM_RANGE(0x0000, 0x4fff) AM_READWRITE(SMH_BANK(1), cloud9_videoram_w)
	AM_RANGE(0x5000, 0x53ff) AM_RAM AM_BASE(&spriteram)
	AM_RANGE(0x5400, 0x547f) AM_WRITE(watchdog_reset_w)
	AM_RANGE(0x5480, 0x54ff) AM_WRITE(irq_ack_w)
	AM_RANGE(0x5500, 0x557f) AM_RAM_WRITE(cloud9_paletteram_w) AM_BASE(&paletteram)
	AM_RANGE(0x5580, 0x5587) AM_MIRROR(0x0078) AM_WRITE(cloud9_video_control_w)
	AM_RANGE(0x5600, 0x5601) AM_MIRROR(0x0078) AM_WRITE(cloud9_coin_counter_w)
	AM_RANGE(0x5602, 0x5603) AM_MIRROR(0x0078) AM_WRITE(cloud9_led_w)
	AM_RANGE(0x5680, 0x56ff) AM_WRITE(nvram_store_w)
	AM_RANGE(0x5700, 0x577f) AM_WRITE(nvram_recall_w)
	AM_RANGE(0x5800, 0x5800) AM_MIRROR(0x007e) AM_READ_PORT("IN0")
	AM_RANGE(0x5801, 0x5801) AM_MIRROR(0x007e) AM_READ_PORT("IN1")
	AM_RANGE(0x5900, 0x5903) AM_MIRROR(0x007c) AM_READ(leta_r)
	AM_RANGE(0x5a00, 0x5a0f) AM_MIRROR(0x00f0) AM_DEVREADWRITE("pokey1", pokey_r, pokey_w)
	AM_RANGE(0x5b00, 0x5b0f) AM_MIRROR(0x00f0) AM_DEVREADWRITE("pokey2", pokey_r, pokey_w)
	AM_RANGE(0x5c00, 0x5cff) AM_MIRROR(0x0300) AM_READWRITE(nvram_r, SMH_RAM) AM_BASE(&nvram_stage) AM_SIZE(&generic_nvram_size)
	AM_RANGE(0x6000, 0xffff) AM_ROM
ADDRESS_MAP_END



/*************************************
 *
 *  Port definitions
 *
 *************************************/

static INPUT_PORTS_START( cloud9 )
	PORT_START("IN0")
	PORT_BIT( 0x07, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_SERVICE( 0x08, IP_ACTIVE_LOW )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(get_vblank, NULL)

	PORT_START("IN1")
	PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )

	PORT_START("DSW")
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x01, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0xfe, 0x04, DEF_STR( Coinage ) )
	PORT_DIPSETTING(	0x22, DEF_STR( 9C_1C ) )
	PORT_DIPSETTING(	0x1e, DEF_STR( 8C_1C ) )
	PORT_DIPSETTING(	0x1a, DEF_STR( 7C_1C ) )
	PORT_DIPSETTING(	0x16, DEF_STR( 6C_1C ) )
	PORT_DIPSETTING(	0x12, DEF_STR( 5C_1C ) )
	PORT_DIPSETTING(	0x0e, DEF_STR( 4C_1C ) )
	PORT_DIPSETTING(	0x0a, DEF_STR( 3C_1C ) )
	PORT_DIPSETTING(	0x06, DEF_STR( 2C_1C ) )
	PORT_DIPSETTING(	0x04, DEF_STR( 1C_1C ) )
	PORT_DIPSETTING(	0x02, DEF_STR( 1C_2C ) )
	PORT_DIPSETTING(	0x00, DEF_STR( Free_Play ) )

	PORT_START("TRACKY")
	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_REVERSE

	PORT_START("TRACKX")
	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30)
INPUT_PORTS_END


static INPUT_PORTS_START( firebeas )
	PORT_START("IN0")
	PORT_BIT( 0x07, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_SERVICE( 0x08, IP_ACTIVE_LOW )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE1 )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(get_vblank, NULL)

	PORT_START("IN1")
	PORT_BIT( 0x07, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 )
	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )

	PORT_START("DSW")
	PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x01, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x02, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x04, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x08, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x10, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x20, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x40, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )
	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
	PORT_DIPSETTING(	0x80, DEF_STR( Off ) )
	PORT_DIPSETTING(	0x00, DEF_STR( On ) )

	PORT_START("TRACKY")
	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_REVERSE

	PORT_START("TRACKX")
	PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(30) PORT_KEYDELTA(30) PORT_REVERSE
INPUT_PORTS_END



/*************************************
 *
 *  Graphics definitions
 *
 *************************************/

static GFXDECODE_START( cloud9 )
	GFXDECODE_ENTRY( "gfx1", 0x0000, gfx_16x16x4_planar, 0, 4 )
GFXDECODE_END



/*************************************
 *
 *  Sound interfaces
 *
 *************************************/

static const pokey_interface pokey_config =
{
	{ DEVCB_NULL },
	DEVCB_INPUT_PORT("DSW"),
};



/*************************************
 *
 *  Machine driver
 *
 *************************************/

static MACHINE_DRIVER_START( cloud9 )

	/* basic machine hardware */
	MDRV_CPU_ADD("maincpu", M6502, MASTER_CLOCK/8)
	MDRV_CPU_PROGRAM_MAP(cloud9_map)

	MDRV_MACHINE_START(cloud9)
	MDRV_MACHINE_RESET(cloud9)
	MDRV_NVRAM_HANDLER(cloud9)
	MDRV_WATCHDOG_VBLANK_INIT(8)

	/* video hardware */
	MDRV_GFXDECODE(cloud9)
	MDRV_PALETTE_LENGTH(64)

	MDRV_SCREEN_ADD("screen", RASTER)
	MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
	MDRV_SCREEN_REFRESH_RATE((float)PIXEL_CLOCK / (float)VTOTAL / (float)HTOTAL)
	MDRV_SCREEN_SIZE(HTOTAL, VTOTAL)
	MDRV_SCREEN_VBLANK_TIME(0)			/* VBLANK is handled manually */
	MDRV_SCREEN_VISIBLE_AREA(0, 255, 0, 231)

	MDRV_VIDEO_START(cloud9)
	MDRV_VIDEO_UPDATE(cloud9)

	/* sound hardware */
	MDRV_SPEAKER_STANDARD_MONO("mono")

	MDRV_SOUND_ADD("pokey1", POKEY, MASTER_CLOCK/8)
	MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)

	MDRV_SOUND_ADD("pokey2", POKEY, MASTER_CLOCK/8)
	MDRV_SOUND_CONFIG(pokey_config)
	MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_DRIVER_END



/*************************************
 *
 *  ROM definitions
 *
 *************************************/

ROM_START( cloud9 )
	ROM_REGION( 0x10000, "maincpu", 0 )
	ROM_LOAD( "c9_6000.bin", 0x6000, 0x2000, CRC(b5d95d98) SHA1(9a347e5fc6e9e753e5c6972341725b5f4412e451) )
	ROM_LOAD( "c9_8000.bin", 0x8000, 0x2000, CRC(49af8f22) SHA1(c118372bec0c428c2b60d29df95f358b302d5e66) )
	ROM_LOAD( "c9_a000.bin", 0xa000, 0x2000, CRC(7cf404a6) SHA1(d20b662102f8426af51b1ca4ed8e18b00d711365) )
	ROM_LOAD( "c9_c000.bin", 0xc000, 0x2000, CRC(26a4d7df) SHA1(8eef0a5f5d1ff13eec75d0c50f5a5dea28486ae5) )
	ROM_LOAD( "c9_e000.bin", 0xe000, 0x2000, CRC(6e663bce) SHA1(4f4a5dc57ba6bc38a17973a6644849f6f5a2dfd1) )

	ROM_REGION( 0x4000, "gfx1", ROMREGION_DISPOSE )
	ROM_LOAD( "c9_gfx0.bin", 0x0000, 0x1000, CRC(d01a8019) SHA1(a77d6125b116ab4bf9446e3b99469dad2719f7e5) )
	ROM_LOAD( "c9_gfx1.bin", 0x1000, 0x1000, CRC(514ac009) SHA1(f05081d8da47e650b0bd12cd00460c98a4f745b1) )
	ROM_LOAD( "c9_gfx2.bin", 0x2000, 0x1000, CRC(930c1ade) SHA1(ba22cb7b105da2ab8c40574e70f18d594d833452) )
	ROM_LOAD( "c9_gfx3.bin", 0x3000, 0x1000, CRC(27e9b88d) SHA1(a1d27e62eea9cdff662a3c160f650bbdb32b7f47) )

	ROM_REGION( 0x400, "proms", 0 )
	ROM_LOAD( "63s141.e10",  0x0000, 0x0100, BAD_DUMP CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) )	/* Sync PROM */
	ROM_LOAD( "63s141.m10",  0x0100, 0x0100, BAD_DUMP CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) )	/* ??? PROM */
	ROM_LOAD( "82s129.p3",   0x0200, 0x0100, BAD_DUMP CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) )	/* VRAM Write Protect PROM */
	ROM_LOAD( "63s141.m8",   0x0300, 0x0100, BAD_DUMP CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) )	/* ??? PROM */
ROM_END


ROM_START( firebeas )
	ROM_REGION( 0x10000, "maincpu", 0 )
	ROM_LOAD( "6000.j2",  0x6000, 0x2000, CRC(dbd04782) SHA1(1237511b00a4121fae01a07bca05a76202d74058) )
	ROM_LOAD( "8000.kl2", 0x8000, 0x2000, CRC(96231ca4) SHA1(e865d4396968f94a284fe9993f066d55f9c225a4) )
	ROM_LOAD( "a000.lm2", 0xa000, 0x2000, CRC(f7e0bf25) SHA1(d116cbc7643a3328f7a1fe4ff03d8a087b8c7648) )
	ROM_LOAD( "c000.n2",  0xc000, 0x2000, CRC(43a91b74) SHA1(6b38703e793ebcbee7b060053485072d9dac6b8b) )
	ROM_LOAD( "e000.p2",  0xe000, 0x1000, CRC(8e5045ab) SHA1(8e5e8dd7710dc5ec68602f069dfc30e1bcaf7411) )
	ROM_RELOAD(           0xf000, 0x1000 )

	ROM_REGION( 0x8000, "gfx1", ROMREGION_DISPOSE )
	ROM_LOAD( "mo0000.r12", 0x0000, 0x2000, CRC(5246c979) SHA1(a975ede0a6c2c91f4373ecba1e2f61f1aedcee62) )
	ROM_LOAD( "mo2000.p12", 0x2000, 0x2000, CRC(1a3b6d57) SHA1(d9015140e69fdc3f73113f0afc3be2579197017a) )
	ROM_LOAD( "mo4000.n12", 0x4000, 0x2000, CRC(69e18319) SHA1(3bf3cbe4ea06ea71928eff8a57c2ef7dc6e6716a) )
	ROM_LOAD( "mo6000.m12", 0x6000, 0x2000, CRC(b722997f) SHA1(65a2618ecd8b4923f30f59c1fb95124cf0391964) )

	ROM_REGION( 0x400, "proms", 0 )
	ROM_LOAD( "63s141.e10", 0x0000, 0x0100, CRC(8e98083f) SHA1(ed29c7ed2226613ed5d09ecef4e645e3b53f7f8d) )	/* Sync PROM */
	ROM_LOAD( "63s141.m10", 0x0100, 0x0100, CRC(b0b039c0) SHA1(724fa88f3f3c62b3c9345cdb13e114a10b7bbdb0) )	/* ??? PROM */
	ROM_LOAD( "82s129.p3",  0x0200, 0x0100, CRC(615d784d) SHA1(e7e6397ae45d6ae8b3670b457ede79c42d18d71f) )	/* VRAM Write Protect PROM */
	ROM_LOAD( "63s141.m8",  0x0300, 0x0100, CRC(6d7479ec) SHA1(7a7c30f5846b98afaaca2af9aab82416ebafe4cc) )	/* ??? PROM */
ROM_END



/*************************************
 *
 *  Game drivers
 *
 *************************************/

GAME( 1983, cloud9,   0, cloud9, cloud9,   0, ROT0, "Atari", "Cloud 9 (prototype)", GAME_SUPPORTS_SAVE )
GAME( 1983, firebeas, 0, cloud9, firebeas, 0, ROT0, "Atari", "Firebeast (prototype)", GAME_SUPPORTS_SAVE )
