Converted amiga drivers to use driver_devices. Merged common code between

legacy Amiga and AGA video systems. [Atari Ace]

From: Atari Ace <atari_ace@frontier.com>
Date: Sun, Sep 19, 2010 at 4:17 PM
Subject: [patch] Implement amiga_state
To: submit@mamedev.org
Cc: atariace@hotmail.com


Hi mamedev,

These two patches add an amiga_state class to the amiga drivers.  The
first adds missing machine, device params to external functions, makes
akiko a proper device and adjusts video/amiga.c and video/amigaaga.c
to be more similar.  The second patch then implements the classes,
also merging ~300 lines of identical code in amigaaga.c.  More code
code be merged if desired with a little more effort.

~aa
This commit is contained in:
Aaron Giles 2010-09-19 20:46:16 +00:00
parent 5c0e08dce2
commit 2dd1a7191f
12 changed files with 1036 additions and 1220 deletions

View File

@ -63,16 +63,13 @@ struct _amiga_audio
}; };
INLINE amiga_audio *get_safe_token( running_device *device )
{
assert(device != NULL);
assert(device->type() == AMIGA);
/************************************* return (amiga_audio *)downcast<legacy_device_base *>(device)->token();
* }
* Globals
*
*************************************/
static amiga_audio *audio_state;
/************************************* /*************************************
* *
@ -86,7 +83,7 @@ static TIMER_CALLBACK( signal_irq )
} }
static void dma_reload(audio_channel *chan) static void dma_reload(amiga_state *state, audio_channel *chan)
{ {
chan->curlocation = CUSTOM_REG_LONG(REG_AUD0LCH + chan->index * 8); chan->curlocation = CUSTOM_REG_LONG(REG_AUD0LCH + chan->index * 8);
chan->curlength = CUSTOM_REG(REG_AUD0LEN + chan->index * 8); chan->curlength = CUSTOM_REG(REG_AUD0LEN + chan->index * 8);
@ -102,8 +99,10 @@ static void dma_reload(audio_channel *chan)
* *
*************************************/ *************************************/
void amiga_audio_data_w(int which, UINT16 data) void amiga_audio_data_w(running_device *device, int which, UINT16 data)
{ {
amiga_audio *audio_state = get_safe_token(device);
audio_state->channel[which].manualmode = TRUE; audio_state->channel[which].manualmode = TRUE;
} }
@ -115,8 +114,10 @@ void amiga_audio_data_w(int which, UINT16 data)
* *
*************************************/ *************************************/
void amiga_audio_update(void) void amiga_audio_update(running_device *device)
{ {
amiga_audio *audio_state = get_safe_token(device);
stream_update(audio_state->stream); stream_update(audio_state->stream);
} }
@ -124,6 +125,7 @@ void amiga_audio_update(void)
static STREAM_UPDATE( amiga_stream_update ) static STREAM_UPDATE( amiga_stream_update )
{ {
amiga_state *state = device->machine->driver_data<amiga_state>();
amiga_audio *audio = (amiga_audio *)param; amiga_audio *audio = (amiga_audio *)param;
int channum, sampoffs = 0; int channum, sampoffs = 0;
@ -148,7 +150,7 @@ static STREAM_UPDATE( amiga_stream_update )
{ {
audio_channel *chan = &audio->channel[channum]; audio_channel *chan = &audio->channel[channum];
if (!chan->dmaenabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1)) if (!chan->dmaenabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1))
dma_reload(chan); dma_reload(state, chan);
chan->dmaenabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1; chan->dmaenabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1;
} }
@ -223,13 +225,13 @@ static STREAM_UPDATE( amiga_stream_update )
chan->curlocation++; chan->curlocation++;
if (chan->dmaenabled && !(chan->curlocation & 1)) if (chan->dmaenabled && !(chan->curlocation & 1))
{ {
CUSTOM_REG(REG_AUD0DAT + channum * 8) = amiga_chip_ram_r(chan->curlocation); CUSTOM_REG(REG_AUD0DAT + channum * 8) = (*state->chip_ram_r)(state, chan->curlocation);
if (chan->curlength != 0) if (chan->curlength != 0)
chan->curlength--; chan->curlength--;
/* if we run out of data, reload the dma */ /* if we run out of data, reload the dma */
if (chan->curlength == 0) if (chan->curlength == 0)
dma_reload(chan); dma_reload(state, chan);
} }
/* latch the next byte of the sample */ /* latch the next byte of the sample */
@ -263,15 +265,13 @@ static STREAM_UPDATE( amiga_stream_update )
static DEVICE_START( amiga_sound ) static DEVICE_START( amiga_sound )
{ {
running_machine *machine = device->machine; amiga_audio *audio_state = get_safe_token(device);
int i; int i;
/* allocate a new audio state */
audio_state = (amiga_audio *)downcast<legacy_device_base *>(device)->token();
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
audio_state->channel[i].index = i; audio_state->channel[i].index = i;
audio_state->channel[i].irq_timer = timer_alloc(machine, signal_irq, NULL); audio_state->channel[i].irq_timer = timer_alloc(device->machine, signal_irq, NULL);
} }
/* create the stream */ /* create the stream */
@ -284,7 +284,7 @@ DEVICE_GET_INFO( amiga_sound )
switch (state) switch (state)
{ {
/* --- the following bits of info are returned as 64-bit signed integers --- */ /* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(*audio_state); break; case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(amiga_audio); break;
/* --- the following bits of info are returned as pointers to data or functions --- */ /* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(amiga_sound); break; case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(amiga_sound); break;

View File

@ -29,10 +29,18 @@
#include "machine/nvram.h" #include "machine/nvram.h"
static running_device *laserdisc; class alg_state : public amiga_state
static emu_timer *serial_timer; {
static UINT8 serial_timer_active; public:
static UINT16 input_select; alg_state(running_machine &machine, const driver_device_config_base &config)
: amiga_state(machine, config) { }
running_device *laserdisc;
emu_timer *serial_timer;
UINT8 serial_timer_active;
UINT16 input_select;
};
static TIMER_CALLBACK( response_timer ); static TIMER_CALLBACK( response_timer );
@ -74,7 +82,7 @@ static VIDEO_START( alg )
/* configure pen 4096 as transparent in the renderer and use it for the genlock color */ /* configure pen 4096 as transparent in the renderer and use it for the genlock color */
palette_set_color(machine, 4096, MAKE_ARGB(0,0,0,0)); palette_set_color(machine, 4096, MAKE_ARGB(0,0,0,0));
amiga_set_genlock_color(4096); amiga_set_genlock_color(machine, 4096);
} }
@ -87,10 +95,11 @@ static VIDEO_START( alg )
static MACHINE_START( alg ) static MACHINE_START( alg )
{ {
laserdisc = machine->device("laserdisc"); alg_state *state = machine->driver_data<alg_state>();
state->laserdisc = machine->device("laserdisc");
serial_timer = timer_alloc(machine, response_timer, NULL); state->serial_timer = timer_alloc(machine, response_timer, NULL);
serial_timer_active = FALSE; state->serial_timer_active = FALSE;
} }
@ -109,44 +118,50 @@ static MACHINE_RESET( alg )
static TIMER_CALLBACK( response_timer ) static TIMER_CALLBACK( response_timer )
{ {
alg_state *state = machine->driver_data<alg_state>();
/* if we still have data to send, do it now */ /* if we still have data to send, do it now */
if (laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE) if (laserdisc_line_r(state->laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
{ {
UINT8 data = laserdisc_data_r(laserdisc); UINT8 data = laserdisc_data_r(state->laserdisc);
if (data != 0x0a) if (data != 0x0a)
mame_printf_debug("Sending serial data = %02X\n", data); mame_printf_debug("Sending serial data = %02X\n", data);
amiga_serial_in_w(machine, data); amiga_serial_in_w(machine, data);
} }
/* if there's more to come, set another timer */ /* if there's more to come, set another timer */
if (laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE) if (laserdisc_line_r(state->laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
timer_adjust_oneshot(serial_timer, amiga_get_serial_char_period(machine), 0); timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
else else
serial_timer_active = FALSE; state->serial_timer_active = FALSE;
} }
static void vsync_callback(running_machine *machine) static void vsync_callback(running_machine *machine)
{ {
alg_state *state = machine->driver_data<alg_state>();
/* if we have data available, set a timer to read it */ /* if we have data available, set a timer to read it */
if (!serial_timer_active && laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE) if (!state->serial_timer_active && laserdisc_line_r(state->laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
{ {
timer_adjust_oneshot(serial_timer, amiga_get_serial_char_period(machine), 0); timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
serial_timer_active = TRUE; state->serial_timer_active = TRUE;
} }
} }
static void serial_w(running_machine *machine, UINT16 data) static void serial_w(running_machine *machine, UINT16 data)
{ {
alg_state *state = machine->driver_data<alg_state>();
/* write to the laserdisc player */ /* write to the laserdisc player */
laserdisc_data_w(laserdisc, data & 0xff); laserdisc_data_w(state->laserdisc, data & 0xff);
/* if we have data available, set a timer to read it */ /* if we have data available, set a timer to read it */
if (!serial_timer_active && laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE) if (!state->serial_timer_active && laserdisc_line_r(state->laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
{ {
timer_adjust_oneshot(serial_timer, amiga_get_serial_char_period(machine), 0); timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
serial_timer_active = TRUE; state->serial_timer_active = TRUE;
} }
} }
@ -160,33 +175,40 @@ static void serial_w(running_machine *machine, UINT16 data)
static void alg_potgo_w(running_machine *machine, UINT16 data) static void alg_potgo_w(running_machine *machine, UINT16 data)
{ {
alg_state *state = machine->driver_data<alg_state>();
/* bit 15 controls whether pin 9 is input/output */ /* bit 15 controls whether pin 9 is input/output */
/* bit 14 controls the value, which selects which player's controls to read */ /* bit 14 controls the value, which selects which player's controls to read */
input_select = (data & 0x8000) ? ((data >> 14) & 1) : 0; state->input_select = (data & 0x8000) ? ((data >> 14) & 1) : 0;
} }
static CUSTOM_INPUT( lightgun_pos_r ) static CUSTOM_INPUT( lightgun_pos_r )
{ {
alg_state *state = field->port->machine->driver_data<alg_state>();
int x = 0, y = 0; int x = 0, y = 0;
/* get the position based on the input select */ /* get the position based on the input select */
get_lightgun_pos(*field->port->machine->primary_screen, input_select, &x, &y); get_lightgun_pos(*field->port->machine->primary_screen, state->input_select, &x, &y);
return (y << 8) | (x >> 2); return (y << 8) | (x >> 2);
} }
static CUSTOM_INPUT( lightgun_trigger_r ) static CUSTOM_INPUT( lightgun_trigger_r )
{ {
alg_state *state = field->port->machine->driver_data<alg_state>();
/* read the trigger control based on the input select */ /* read the trigger control based on the input select */
return (input_port_read(field->port->machine, "TRIGGERS") >> input_select) & 1; return (input_port_read(field->port->machine, "TRIGGERS") >> state->input_select) & 1;
} }
static CUSTOM_INPUT( lightgun_holster_r ) static CUSTOM_INPUT( lightgun_holster_r )
{ {
alg_state *state = field->port->machine->driver_data<alg_state>();
/* read the holster control based on the input select */ /* read the holster control based on the input select */
return (input_port_read(field->port->machine, "TRIGGERS") >> (2 + input_select)) & 1; return (input_port_read(field->port->machine, "TRIGGERS") >> (2 + state->input_select)) & 1;
} }
@ -257,9 +279,9 @@ static WRITE8_DEVICE_HANDLER( alg_cia_1_porta_w )
static ADDRESS_MAP_START( main_map_r1, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map_r1, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(alg_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(alg_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */ AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -270,9 +292,9 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( main_map_r2, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map_r2, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(alg_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(alg_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */ AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -283,9 +305,9 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( main_map_picmatic, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map_picmatic, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(alg_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(alg_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */ AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -404,7 +426,7 @@ static const mos6526_interface cia_1_intf =
DEVCB_NULL /* port B */ DEVCB_NULL /* port B */
}; };
static MACHINE_CONFIG_START( alg_r1, driver_device ) static MACHINE_CONFIG_START( alg_r1, alg_state )
/* basic machine hardware */ /* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK) MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
@ -658,6 +680,7 @@ ROM_END
static void alg_init(running_machine *machine) static void alg_init(running_machine *machine)
{ {
alg_state *state = machine->driver_data<alg_state>();
static const amiga_machine_interface alg_intf = static const amiga_machine_interface alg_intf =
{ {
ANGUS_CHIP_RAM_MASK, ANGUS_CHIP_RAM_MASK,
@ -672,7 +695,7 @@ static void alg_init(running_machine *machine)
amiga_machine_config(machine, &alg_intf); amiga_machine_config(machine, &alg_intf);
/* set up memory */ /* set up memory */
memory_configure_bank(machine, "bank1", 0, 1, amiga_chip_ram, 0); memory_configure_bank(machine, "bank1", 0, 1, state->chip_ram, 0);
memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0); memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0);
} }

View File

@ -55,13 +55,14 @@
/************************************* class arcadia_state : public amiga_state
* {
* Globals public:
* arcadia_state(running_machine &machine, const driver_device_config_base &config)
*************************************/ : amiga_state(machine, config) { }
static UINT8 coin_counter[2]; UINT8 coin_counter[2];
};
@ -136,6 +137,8 @@ static WRITE8_DEVICE_HANDLER( arcadia_cia_0_portb_w )
/* writing a 0 in the low bit clears one of the coins */ /* writing a 0 in the low bit clears one of the coins */
if ((data & 1) == 0) if ((data & 1) == 0)
{ {
UINT8 *coin_counter = device->machine->driver_data<arcadia_state>()->coin_counter;
if (coin_counter[0] > 0) if (coin_counter[0] > 0)
coin_counter[0]--; coin_counter[0]--;
else if (coin_counter[1] > 0) else if (coin_counter[1] > 0)
@ -153,23 +156,29 @@ static WRITE8_DEVICE_HANDLER( arcadia_cia_0_portb_w )
static CUSTOM_INPUT( coin_counter_r ) static CUSTOM_INPUT( coin_counter_r )
{ {
int coin = (FPTR)param;
UINT8 *coin_counter = field->port->machine->driver_data<arcadia_state>()->coin_counter;
/* return coin counter values */ /* return coin counter values */
return *(UINT8 *)param & 3; return coin_counter[coin] & 3;
} }
static INPUT_CHANGED( coin_changed_callback ) static INPUT_CHANGED( coin_changed_callback )
{ {
UINT8 *counter = (UINT8 *)param; int coin = (FPTR)param;
UINT8 *coin_counter = field->port->machine->driver_data<arcadia_state>()->coin_counter;
/* check for a 0 -> 1 transition */ /* check for a 0 -> 1 transition */
if (!oldval && newval && *counter < 3) if (!oldval && newval && coin_counter[coin] < 3)
*counter += 1; coin_counter[coin] += 1;
} }
static void arcadia_reset_coins(running_machine *machine) static void arcadia_reset_coins(running_machine *machine)
{ {
UINT8 *coin_counter = machine->driver_data<arcadia_state>()->coin_counter;
/* reset coin counters */ /* reset coin counters */
coin_counter[0] = coin_counter[1] = 0; coin_counter[0] = coin_counter[1] = 0;
} }
@ -184,9 +193,9 @@ static void arcadia_reset_coins(running_machine *machine)
static ADDRESS_MAP_START( amiga_map, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( amiga_map, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(arcadia_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(arcadia_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* Kickstart BIOS */ AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* Kickstart BIOS */
@ -218,8 +227,8 @@ static INPUT_PORTS_START( arcadia )
PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(coin_counter_r, &coin_counter[0]) PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(coin_counter_r, 0)
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(coin_counter_r, &coin_counter[1]) PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(coin_counter_r, 1)
PORT_START("JOY0DAT") PORT_START("JOY0DAT")
PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY") PORT_BIT( 0x0303, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(amiga_joystick_convert, "P1JOY")
@ -249,8 +258,8 @@ static INPUT_PORTS_START( arcadia )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
PORT_START("COINS") PORT_START("COINS")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(coin_changed_callback, &coin_counter[0]) PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(coin_changed_callback, 0)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(coin_changed_callback, &coin_counter[1]) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(coin_changed_callback, 1)
INPUT_PORTS_END INPUT_PORTS_END
@ -287,7 +296,7 @@ static const mos6526_interface cia_1_intf =
DEVCB_NULL DEVCB_NULL
}; };
static MACHINE_CONFIG_START( arcadia, driver_device ) static MACHINE_CONFIG_START( arcadia, arcadia_state )
/* basic machine hardware */ /* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK) MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
@ -753,6 +762,7 @@ INLINE void generic_decode(running_machine *machine, const char *tag, int bit7,
static void arcadia_init(running_machine *machine) static void arcadia_init(running_machine *machine)
{ {
arcadia_state *state = machine->driver_data<arcadia_state>();
static const amiga_machine_interface arcadia_intf = static const amiga_machine_interface arcadia_intf =
{ {
ANGUS_CHIP_RAM_MASK, ANGUS_CHIP_RAM_MASK,
@ -768,7 +778,7 @@ static void arcadia_init(running_machine *machine)
amiga_machine_config(machine, &arcadia_intf); amiga_machine_config(machine, &arcadia_intf);
/* set up memory */ /* set up memory */
memory_configure_bank(machine, "bank1", 0, 1, amiga_chip_ram, 0); memory_configure_bank(machine, "bank1", 0, 1, state->chip_ram, 0);
memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0); memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0);
/* OnePlay bios is encrypted, TenPlay is not */ /* OnePlay bios is encrypted, TenPlay is not */

View File

@ -338,7 +338,7 @@ routines :
#define MGNUMBER_USE_JOY 1 #define MGNUMBER_USE_JOY 1
static void handle_cd32_joystick_cia(UINT8 pra, UINT8 dra); static void handle_cd32_joystick_cia(running_machine *machine, UINT8 pra, UINT8 dra);
static WRITE32_HANDLER( aga_overlay_w ) static WRITE32_HANDLER( aga_overlay_w )
{ {
@ -382,7 +382,7 @@ static WRITE8_DEVICE_HANDLER( cd32_cia_0_porta_w )
/* bit 2 = Power Led on Amiga */ /* bit 2 = Power Led on Amiga */
set_led_status(device->machine, 0, (data & 2) ? 0 : 1); set_led_status(device->machine, 0, (data & 2) ? 0 : 1);
handle_cd32_joystick_cia(data, mos6526_r(device, 2)); handle_cd32_joystick_cia(device->machine, data, mos6526_r(device, 2));
} }
/************************************* /*************************************
@ -415,13 +415,13 @@ static WRITE8_DEVICE_HANDLER( cd32_cia_0_portb_w )
static ADDRESS_MAP_START( cd32_map, ADDRESS_SPACE_PROGRAM, 32 ) static ADDRESS_MAP_START( cd32_map, ADDRESS_SPACE_PROGRAM, 32 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram32) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x1fffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(cubocd32_state, chip_ram, chip_ram_size)
AM_RANGE(0x800000, 0x800003) AM_READ_PORT("DIPSW1") AM_RANGE(0x800000, 0x800003) AM_READ_PORT("DIPSW1")
AM_RANGE(0x800010, 0x800013) AM_READ_PORT("DIPSW2") AM_RANGE(0x800010, 0x800013) AM_READ_PORT("DIPSW2")
AM_RANGE(0xb80000, 0xb8003f) AM_READWRITE(amiga_akiko32_r, amiga_akiko32_w) AM_RANGE(0xb80000, 0xb8003f) AM_DEVREADWRITE("akiko", amiga_akiko32_r, amiga_akiko32_w)
AM_RANGE(0xbfa000, 0xbfa003) AM_WRITE(aga_overlay_w) AM_RANGE(0xbfa000, 0xbfa003) AM_WRITE(aga_overlay_w)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE16(amiga_cia_r, amiga_cia_w, 0xffffffff) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE16(amiga_cia_r, amiga_cia_w, 0xffffffff)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE16(amiga_custom_r, amiga_custom_w, 0xffffffff) AM_BASE((UINT32**)&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE16(amiga_custom_r, amiga_custom_w, 0xffffffff) AM_BASE_MEMBER(cubocd32_state, custom_regs)
AM_RANGE(0xe00000, 0xe7ffff) AM_ROM AM_REGION("user1", 0x80000) /* CD32 Extended ROM */ AM_RANGE(0xe00000, 0xe7ffff) AM_ROM AM_REGION("user1", 0x80000) /* CD32 Extended ROM */
AM_RANGE(0xa00000, 0xf7ffff) AM_NOP AM_RANGE(0xa00000, 0xf7ffff) AM_NOP
AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0x0) /* Kickstart */ AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0x0) /* Kickstart */
@ -433,19 +433,16 @@ ADDRESS_MAP_END
* *
*************************************/ *************************************/
static UINT16 potgo_value = 0;
static int cd32_shifter[2];
static void (*cubocd32_input_hack)(running_machine *machine) = 0;
static void cubocd32_potgo_w(running_machine *machine, UINT16 data) static void cubocd32_potgo_w(running_machine *machine, UINT16 data)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
int i; int i;
if (cubocd32_input_hack != NULL) if (state->input_hack != NULL)
cubocd32_input_hack(machine); (*state->input_hack)(machine);
potgo_value = potgo_value & 0x5500; state->potgo_value = state->potgo_value & 0x5500;
potgo_value |= data & 0xaa00; state->potgo_value |= data & 0xaa00;
for (i = 0; i < 8; i += 2) for (i = 0; i < 8; i += 2)
{ {
@ -453,22 +450,22 @@ static void cubocd32_potgo_w(running_machine *machine, UINT16 data)
if (data & dir) if (data & dir)
{ {
UINT16 d = 0x0100 << i; UINT16 d = 0x0100 << i;
potgo_value &= ~d; state->potgo_value &= ~d;
potgo_value |= data & d; state->potgo_value |= data & d;
} }
} }
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */ UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */ UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
if ((potgo_value & p5dir) && (potgo_value & p5dat)) if ((state->potgo_value & p5dir) && (state->potgo_value & p5dat))
cd32_shifter[i] = 8; state->cd32_shifter[i] = 8;
} }
} }
static void handle_cd32_joystick_cia(UINT8 pra, UINT8 dra) static void handle_cd32_joystick_cia(running_machine *machine, UINT8 pra, UINT8 dra)
{ {
static int oldstate[2]; cubocd32_state *state = machine->driver_data<cubocd32_state>();
int i; int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
@ -477,24 +474,25 @@ static void handle_cd32_joystick_cia(UINT8 pra, UINT8 dra)
UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */ UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */ UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
if (!(potgo_value & p5dir) || !(potgo_value & p5dat)) if (!(state->potgo_value & p5dir) || !(state->potgo_value & p5dat))
{ {
if ((dra & but) && (pra & but) != oldstate[i]) if ((dra & but) && (pra & but) != state->oldstate[i])
{ {
if (!(pra & but)) if (!(pra & but))
{ {
cd32_shifter[i]--; state->cd32_shifter[i]--;
if (cd32_shifter[i] < 0) if (state->cd32_shifter[i] < 0)
cd32_shifter[i] = 0; state->cd32_shifter[i] = 0;
} }
} }
} }
oldstate[i] = pra & but; state->oldstate[i] = pra & but;
} }
} }
static UINT16 handle_joystick_potgor(running_machine *machine, UINT16 potgor) static UINT16 handle_joystick_potgor(running_machine *machine, UINT16 potgor)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
static const char *const player_portname[] = { "P2", "P1" }; static const char *const player_portname[] = { "P2", "P1" };
int i; int i;
@ -507,16 +505,16 @@ static UINT16 handle_joystick_potgor (running_machine *machine, UINT16 potgor)
/* p5 is floating in input-mode */ /* p5 is floating in input-mode */
potgor &= ~p5dat; potgor &= ~p5dat;
potgor |= potgo_value & p5dat; potgor |= state->potgo_value & p5dat;
if (!(potgo_value & p9dir)) if (!(state->potgo_value & p9dir))
potgor |= p9dat; potgor |= p9dat;
/* P5 output and 1 -> shift register is kept reset (Blue button) */ /* P5 output and 1 -> shift register is kept reset (Blue button) */
if ((potgo_value & p5dir) && (potgo_value & p5dat)) if ((state->potgo_value & p5dir) && (state->potgo_value & p5dat))
cd32_shifter[i] = 8; state->cd32_shifter[i] = 8;
/* shift at 1 == return one, >1 = return button states */ /* shift at 1 == return one, >1 = return button states */
if (cd32_shifter[i] == 0) if (state->cd32_shifter[i] == 0)
potgor &= ~p9dat; /* shift at zero == return zero */ potgor &= ~p9dat; /* shift at zero == return zero */
if (cd32_shifter[i] >= 2 && (input_port_read(machine, player_portname[i]) & (1 << (cd32_shifter[i] - 2)))) if (state->cd32_shifter[i] >= 2 && (input_port_read(machine, player_portname[i]) & (1 << (state->cd32_shifter[i] - 2))))
potgor &= ~p9dat; potgor &= ~p9dat;
} }
return potgor; return potgor;
@ -524,7 +522,8 @@ static UINT16 handle_joystick_potgor (running_machine *machine, UINT16 potgor)
static CUSTOM_INPUT(cubo_input) static CUSTOM_INPUT(cubo_input)
{ {
return handle_joystick_potgor(field->port->machine, potgo_value) >> 10; cubocd32_state *state = field->port->machine->driver_data<cubocd32_state>();
return handle_joystick_potgor(field->port->machine, state->potgo_value) >> 10;
} }
static INPUT_PORTS_START( cd32 ) static INPUT_PORTS_START( cd32 )
@ -1051,11 +1050,12 @@ static const i2cmem_interface i2cmem_interface =
I2CMEM_SLAVE_ADDRESS, NVRAM_PAGE_SIZE, NVRAM_SIZE I2CMEM_SLAVE_ADDRESS, NVRAM_PAGE_SIZE, NVRAM_SIZE
}; };
static MACHINE_CONFIG_START( cd32, driver_device ) static MACHINE_CONFIG_START( cd32, cubocd32_state )
/* basic machine hardware */ /* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68EC020, AMIGA_68EC020_PAL_CLOCK) /* 14.3 Mhz */ MDRV_CPU_ADD("maincpu", M68EC020, AMIGA_68EC020_PAL_CLOCK) /* 14.3 Mhz */
MDRV_CPU_PROGRAM_MAP(cd32_map) MDRV_CPU_PROGRAM_MAP(cd32_map)
MDRV_DEVICE_ADD("akiko", AKIKO, 0)
MDRV_MACHINE_RESET(amiga) MDRV_MACHINE_RESET(amiga)
@ -1157,6 +1157,7 @@ ROM_END
static DRIVER_INIT( cd32 ) static DRIVER_INIT( cd32 )
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
static const amiga_machine_interface cubocd32_intf = static const amiga_machine_interface cubocd32_intf =
{ {
AGA_CHIP_RAM_MASK, AGA_CHIP_RAM_MASK,
@ -1171,14 +1172,11 @@ static DRIVER_INIT( cd32 )
amiga_machine_config(machine, &cubocd32_intf); amiga_machine_config(machine, &cubocd32_intf);
/* set up memory */ /* set up memory */
memory_configure_bank(machine, "bank1", 0, 1, amiga_chip_ram32, 0); memory_configure_bank(machine, "bank1", 0, 1, state->chip_ram, 0);
memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0); memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0);
/* intialize akiko */
amiga_akiko_init(machine);
/* input hack */ /* input hack */
cubocd32_input_hack = NULL; state->input_hack = NULL;
} }
@ -1190,126 +1188,147 @@ static DRIVER_INIT( cd32 )
static void cndypuzl_input_hack(running_machine *machine) static void cndypuzl_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w(0x051c02, 0x0000); //(*state->chip_ram_w)(0x051c02, 0x0000);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
amiga_chip_ram_w(r_A5 - 0x7ebe, 0x0000); (*state->chip_ram_w)(state, r_A5 - 0x7ebe, 0x0000);
} }
} }
static DRIVER_INIT(cndypuzl) static DRIVER_INIT(cndypuzl)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = cndypuzl_input_hack; state->input_hack = cndypuzl_input_hack;
} }
static void haremchl_input_hack(running_machine *machine) static void haremchl_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w8(0x002907, 0x00); //amiga_chip_ram_w8(state, 0x002907, 0x00);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
UINT32 r_A2 = (amiga_chip_ram_r(r_A5 - 0x7f00 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7f00 + 2)); UINT32 r_A2 = ((*state->chip_ram_r)(state, r_A5 - 0x7f00 + 0) << 16) | ((*state->chip_ram_r)(state, r_A5 - 0x7f00 + 2));
amiga_chip_ram_w8(r_A2 + 0x1f, 0x00); amiga_chip_ram_w8(state, r_A2 + 0x1f, 0x00);
} }
} }
static DRIVER_INIT(haremchl) static DRIVER_INIT(haremchl)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = haremchl_input_hack; state->input_hack = haremchl_input_hack;
} }
static void lsrquiz_input_hack(running_machine *machine) static void lsrquiz_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w8(0x001e1b, 0x00); //amiga_chip_ram_w8(state, 0x001e1b, 0x00);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
UINT32 r_A2 = (amiga_chip_ram_r(r_A5 - 0x7fe0 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fe0 + 2)); UINT32 r_A2 = ((*state->chip_ram_r)(state, r_A5 - 0x7fe0 + 0) << 16) | ((*state->chip_ram_r)(state, r_A5 - 0x7fe0 + 2));
amiga_chip_ram_w8(r_A2 + 0x13, 0x00); amiga_chip_ram_w8(state, r_A2 + 0x13, 0x00);
} }
} }
static DRIVER_INIT(lsrquiz) static DRIVER_INIT(lsrquiz)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = lsrquiz_input_hack; state->input_hack = lsrquiz_input_hack;
} }
/* The hack isn't working if you exit the test mode with P1 button 2 ! */ /* The hack isn't working if you exit the test mode with P1 button 2 ! */
static void lsrquiz2_input_hack(running_machine *machine) static void lsrquiz2_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w8(0x046107, 0x00); //amiga_chip_ram_w8(state, 0x046107, 0x00);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
UINT32 r_A2 = (amiga_chip_ram_r(r_A5 - 0x7fdc + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fdc + 2)); UINT32 r_A2 = ((*state->chip_ram_r)(state, r_A5 - 0x7fdc + 0) << 16) | ((*state->chip_ram_r)(state, r_A5 - 0x7fdc + 2));
amiga_chip_ram_w8(r_A2 + 0x17, 0x00); amiga_chip_ram_w8(state, r_A2 + 0x17, 0x00);
} }
} }
static DRIVER_INIT(lsrquiz2) static DRIVER_INIT(lsrquiz2)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = lsrquiz2_input_hack; state->input_hack = lsrquiz2_input_hack;
} }
static void lasstixx_input_hack(running_machine *machine) static void lasstixx_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w8(0x00281c, 0x00); //amiga_chip_ram_w8(state, 0x00281c, 0x00);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
UINT32 r_A2 = (amiga_chip_ram_r(r_A5 - 0x7fa2 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fa2 + 2)); UINT32 r_A2 = ((*state->chip_ram_r)(state, r_A5 - 0x7fa2 + 0) << 16) | ((*state->chip_ram_r)(state, r_A5 - 0x7fa2 + 2));
amiga_chip_ram_w8(r_A2 + 0x24, 0x00); amiga_chip_ram_w8(state, r_A2 + 0x24, 0x00);
} }
} }
static DRIVER_INIT(lasstixx) static DRIVER_INIT(lasstixx)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = lasstixx_input_hack; state->input_hack = lasstixx_input_hack;
} }
static void mgnumber_input_hack(running_machine *machine) static void mgnumber_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w(0x04bfa0, 0x0000); //(*state->chip_ram_w)(0x04bfa0, 0x0000);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
amiga_chip_ram_w(r_A5 - 0x7ed8, 0x0000); (*state->chip_ram_w)(state, r_A5 - 0x7ed8, 0x0000);
} }
} }
static DRIVER_INIT(mgnumber) static DRIVER_INIT(mgnumber)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = mgnumber_input_hack; state->input_hack = mgnumber_input_hack;
} }
static void mgprem11_input_hack(running_machine *machine) static void mgprem11_input_hack(running_machine *machine)
{ {
if(cpu_get_pc(machine->device("maincpu")) < amiga_chip_ram_size) cubocd32_state *state = machine->driver_data<cubocd32_state>();
if (cpu_get_pc(machine->device("maincpu")) < state->chip_ram_size)
{ {
// amiga_chip_ram_w8(0x044f7e, 0x00); //amiga_chip_ram_w8(state, 0x044f7e, 0x00);
UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5); UINT32 r_A5 = cpu_get_reg(machine->device("maincpu"), M68K_A5);
amiga_chip_ram_w8(r_A5 - 0x7eca, 0x00); amiga_chip_ram_w8(state, r_A5 - 0x7eca, 0x00);
} }
} }
static DRIVER_INIT(mgprem11) static DRIVER_INIT(mgprem11)
{ {
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32); DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = mgprem11_input_hack; state->input_hack = mgprem11_input_hack;
} }
/***************************************************************************************************/ /***************************************************************************************************/

View File

@ -140,9 +140,9 @@ static WRITE16_HANDLER( coin_chip_w )
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(amiga_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(amiga_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */ AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -357,7 +357,7 @@ static const mos6526_interface cia_1_intf =
DEVCB_NULL DEVCB_NULL
}; };
static MACHINE_CONFIG_START( mquake, driver_device ) static MACHINE_CONFIG_START( mquake, amiga_state )
/* basic machine hardware */ /* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK) MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
@ -447,6 +447,7 @@ ROM_END
static DRIVER_INIT(mquake) static DRIVER_INIT(mquake)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
static const amiga_machine_interface mquake_intf = static const amiga_machine_interface mquake_intf =
{ {
ANGUS_CHIP_RAM_MASK, ANGUS_CHIP_RAM_MASK,
@ -459,7 +460,7 @@ static DRIVER_INIT(mquake)
amiga_machine_config(machine, &mquake_intf); amiga_machine_config(machine, &mquake_intf);
/* set up memory */ /* set up memory */
memory_configure_bank(machine, "bank1", 0, 1, amiga_chip_ram, 0); memory_configure_bank(machine, "bank1", 0, 1, state->chip_ram, 0);
memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0); memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0);
} }

View File

@ -30,11 +30,11 @@
#include "machine/nvram.h" #include "machine/nvram.h"
class upscope_state : public driver_device class upscope_state : public amiga_state
{ {
public: public:
upscope_state(running_machine &machine, const driver_device_config_base &config) upscope_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config) { } : amiga_state(machine, config) { }
UINT8 m_nvram[0x100]; UINT8 m_nvram[0x100];
}; };
@ -248,9 +248,9 @@ static WRITE8_DEVICE_HANDLER( upscope_cia_1_porta_w )
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE(&amiga_chip_ram) AM_SIZE(&amiga_chip_ram_size) AM_RANGE(0x000000, 0x07ffff) AM_RAMBANK("bank1") AM_BASE_SIZE_MEMBER(upscope_state, chip_ram, chip_ram_size)
AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w) AM_RANGE(0xbfd000, 0xbfefff) AM_READWRITE(amiga_cia_r, amiga_cia_w)
AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE(&amiga_custom_regs) AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(amiga_custom_r, amiga_custom_w) AM_BASE_MEMBER(upscope_state, custom_regs)
AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w) AM_RANGE(0xe80000, 0xe8ffff) AM_READWRITE(amiga_autoconfig_r, amiga_autoconfig_w)
AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */ AM_RANGE(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -391,6 +391,7 @@ ROM_END
static DRIVER_INIT( upscope ) static DRIVER_INIT( upscope )
{ {
upscope_state *state = machine->driver_data<upscope_state>();
static const amiga_machine_interface upscope_intf = static const amiga_machine_interface upscope_intf =
{ {
ANGUS_CHIP_RAM_MASK, ANGUS_CHIP_RAM_MASK,
@ -403,11 +404,10 @@ static DRIVER_INIT( upscope )
amiga_machine_config(machine, &upscope_intf); amiga_machine_config(machine, &upscope_intf);
/* allocate NVRAM */ /* allocate NVRAM */
upscope_state *state = machine->driver_data<upscope_state>();
machine->device<nvram_device>("nvram")->set_base(state->m_nvram, sizeof(state->m_nvram)); machine->device<nvram_device>("nvram")->set_base(state->m_nvram, sizeof(state->m_nvram));
/* set up memory */ /* set up memory */
memory_configure_bank(machine, "bank1", 0, 1, amiga_chip_ram, 0); memory_configure_bank(machine, "bank1", 0, 1, state->chip_ram, 0);
memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0); memory_configure_bank(machine, "bank1", 1, 1, memory_region(machine, "user1"), 0);
} }

View File

@ -13,13 +13,23 @@ Ernesto Corvi & Mariusz Wojcieszek
#include "devlegcy.h" #include "devlegcy.h"
/*************************************
*
* Debugging
*
*************************************/
#define LOG_COPPER 0
#define GUESS_COPPER_OFFSET 0
#define LOG_SPRITE_DMA 0
/* A bit of a trick here: some registers are 32-bit. In order to efficiently */ /* A bit of a trick here: some registers are 32-bit. In order to efficiently */
/* read them on both big-endian and little-endian systems, we store the custom */ /* read them on both big-endian and little-endian systems, we store the custom */
/* registers in 32-bit natural order. This means we need to XOR the register */ /* registers in 32-bit natural order. This means we need to XOR the register */
/* address with 1 on little-endian systems. */ /* address with 1 on little-endian systems. */
#define CUSTOM_REG(x) (amiga_custom_regs[BYTE_XOR_BE(x)]) #define CUSTOM_REG(x) (state->custom_regs[BYTE_XOR_BE(x)])
#define CUSTOM_REG_SIGNED(x) ((INT16)CUSTOM_REG(x)) #define CUSTOM_REG_SIGNED(x) ((INT16)CUSTOM_REG(x))
#define CUSTOM_REG_LONG(x) (*(UINT32 *)&amiga_custom_regs[x]) #define CUSTOM_REG_LONG(x) (*(UINT32 *)&state->custom_regs[x])
/* /*
A = Angus A = Angus
@ -354,22 +364,79 @@ struct _amiga_autoconfig_device
void (*uninstall)(running_machine *machine, offs_t base); /* memory uninstallation */ void (*uninstall)(running_machine *machine, offs_t base); /* memory uninstallation */
}; };
typedef struct _autoconfig_device autoconfig_device;
struct _autoconfig_device
{
autoconfig_device * next;
amiga_autoconfig_device device;
offs_t base;
};
class amiga_state : public driver_device
{
public:
amiga_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config) { }
UINT16 *chip_ram;
size_t chip_ram_size;
UINT16 (*chip_ram_r)(amiga_state *state, offs_t offset);
void (*chip_ram_w)(amiga_state *state, offs_t offset, UINT16 data);
UINT16 *custom_regs;
const amiga_machine_interface *intf;
autoconfig_device *autoconfig_list;
autoconfig_device *cur_autoconfig;
emu_timer * irq_timer;
emu_timer * blitter_timer;
running_device *sound_device;
/* sprite states */
UINT8 sprite_comparitor_enable_mask;
UINT8 sprite_dma_reload_mask;
UINT8 sprite_dma_live_mask;
UINT8 sprite_ctl_written;
UINT32 sprite_shiftreg[8];
UINT8 sprite_remain[8];
/* copper states */
UINT32 copper_pc;
UINT8 copper_waiting;
UINT8 copper_waitblit;
UINT16 copper_waitval;
UINT16 copper_waitmask;
UINT16 copper_pending_offset;
UINT16 copper_pending_data;
#if GUESS_COPPER_OFFSET
int wait_offset;
#endif
/* playfield states */
int last_scanline;
int ham_color;
/* misc states */
UINT16 genlock_color;
/* separate 6 in-order bitplanes into 2 x 3-bit bitplanes in two nibbles */
UINT8 separate_bitplanes[2][64];
/* aga */
int aga_diwhigh_written;
pen_t aga_palette[256];
UINT64 aga_bpldat[8];
UINT16 aga_sprdata[8][4];
UINT16 aga_sprdatb[8][4];
int aga_sprite_fetched_words;
int aga_sprite_dma_used_words[8];
};
/*----------- defined in machine/amiga.c -----------*/ /*----------- defined in machine/amiga.c -----------*/
extern UINT16 *amiga_chip_ram;
extern UINT32 *amiga_chip_ram32;
extern size_t amiga_chip_ram_size;
extern UINT16 *amiga_custom_regs;
extern UINT16 *amiga_expansion_ram;
extern UINT16 *amiga_autoconfig_mem;
extern const char *const amiga_custom_names[0x100]; extern const char *const amiga_custom_names[0x100];
extern UINT16 (*amiga_chip_ram_r)(offs_t offset); extern void amiga_chip_ram_w8(amiga_state *state, offs_t offset, UINT8 data);
extern void (*amiga_chip_ram_w)(offs_t offset, UINT16 data);
extern void amiga_chip_ram_w8(offs_t offset, UINT8 data);
void amiga_machine_config(running_machine *machine, const amiga_machine_interface *intf); void amiga_machine_config(running_machine *machine, const amiga_machine_interface *intf);
@ -393,42 +460,41 @@ WRITE16_HANDLER( amiga_autoconfig_w );
void amiga_cia_0_irq(running_device *device, int state); void amiga_cia_0_irq(running_device *device, int state);
void amiga_cia_1_irq(running_device *device, int state); void amiga_cia_1_irq(running_device *device, int state);
const amiga_machine_interface *amiga_get_interface(void); const amiga_machine_interface *amiga_get_interface(running_machine *machine);
/*----------- defined in audio/amiga.c -----------*/ /*----------- defined in audio/amiga.c -----------*/
DECLARE_LEGACY_SOUND_DEVICE(AMIGA, amiga_sound); DECLARE_LEGACY_SOUND_DEVICE(AMIGA, amiga_sound);
void amiga_audio_update(void); void amiga_audio_update(running_device *device);
void amiga_audio_data_w(int which, UINT16 data); void amiga_audio_data_w(running_device *device, int which, UINT16 data);
/*----------- defined in video/amiga.c -----------*/ /*----------- defined in video/amiga.c -----------*/
extern const UINT16 amiga_expand_byte[256];
PALETTE_INIT( amiga ); PALETTE_INIT( amiga );
VIDEO_START( amiga ); VIDEO_START( amiga );
VIDEO_UPDATE( amiga ); VIDEO_UPDATE( amiga );
void amiga_copper_setpc(running_machine *machine, UINT32 pc);
int amiga_copper_execute_next(running_machine *machine, int xpos);
UINT32 amiga_gethvpos(screen_device &screen); UINT32 amiga_gethvpos(screen_device &screen);
void copper_setpc(UINT32 pc); void amiga_set_genlock_color(running_machine *machine, UINT16 color);
void amiga_set_genlock_color(UINT16 color);
void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline); void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline);
void amiga_sprite_dma_reset(int which); void amiga_sprite_dma_reset(running_machine *machine, int which);
void amiga_sprite_enable_comparitor(int which, int enable); void amiga_sprite_enable_comparitor(running_machine *machine, int which, int enable);
/*----------- defined in video/amigaaga.c -----------*/ /*----------- defined in video/amigaaga.c -----------*/
VIDEO_START( amiga_aga ); VIDEO_START( amiga_aga );
VIDEO_UPDATE( amiga_aga ); VIDEO_UPDATE( amiga_aga );
UINT32 amiga_aga_gethvpos(screen_device &screen);
void aga_copper_setpc(UINT32 pc);
void amiga_aga_set_genlock_color(UINT16 color);
void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline); void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline);
void amiga_aga_sprite_dma_reset(int which); void amiga_aga_palette_write(running_machine *machine, int color_reg, UINT16 data);
void amiga_aga_sprite_enable_comparitor(int which, int enable); void amiga_aga_diwhigh_written(running_machine *machine, int written);
void aga_palette_write(int color_reg, UINT16 data);
void aga_diwhigh_written(int written);
#endif /* __AMIGA_H__ */ #endif /* __AMIGA_H__ */

View File

@ -7,10 +7,23 @@ CuboCD32 definitions
#ifndef __CUBOCD32_H__ #ifndef __CUBOCD32_H__
#define __CUBOCD32_H__ #define __CUBOCD32_H__
class cubocd32_state : public amiga_state
{
public:
cubocd32_state(running_machine &machine, const driver_device_config_base &config)
: amiga_state(machine, config) { }
UINT16 potgo_value;
int cd32_shifter[2];
void (*input_hack)(running_machine *machine);
int oldstate[2];
};
/*----------- defined in machine/cubocd32.c -----------*/ /*----------- defined in machine/cubocd32.c -----------*/
extern void amiga_akiko_init(running_machine* machine); READ32_DEVICE_HANDLER( amiga_akiko32_r );
extern READ32_HANDLER(amiga_akiko32_r); WRITE32_DEVICE_HANDLER( amiga_akiko32_w );
extern WRITE32_HANDLER(amiga_akiko32_w);
DECLARE_LEGACY_DEVICE(AKIKO, akiko);
#endif /* __CUBOCD32_H__ */ #endif /* __CUBOCD32_H__ */

View File

@ -40,43 +40,12 @@
/*************************************
*
* Type definitions
*
*************************************/
typedef struct _autoconfig_device autoconfig_device;
struct _autoconfig_device
{
autoconfig_device * next;
amiga_autoconfig_device device;
offs_t base;
};
/************************************* /*************************************
* *
* Globals * Globals
* *
*************************************/ *************************************/
UINT16 *amiga_chip_ram;
UINT32 *amiga_chip_ram32;
size_t amiga_chip_ram_size;
UINT16 *amiga_custom_regs;
UINT16 *amiga_expansion_ram;
UINT16 *amiga_autoconfig_mem;
static const amiga_machine_interface *amiga_intf;
static autoconfig_device *autoconfig_list;
static autoconfig_device *cur_autoconfig;
static emu_timer * amiga_irq_timer;
static emu_timer * amiga_blitter_timer;
const char *const amiga_custom_names[0x100] = const char *const amiga_custom_names[0x100] =
{ {
/* 0x000 */ /* 0x000 */
@ -183,23 +152,19 @@ static TIMER_CALLBACK( scanline_callback );
* *
*************************************/ *************************************/
UINT16 (*amiga_chip_ram_r)(offs_t offset); static UINT16 amiga_chip_ram16_r(amiga_state *state, offs_t offset)
void (*amiga_chip_ram_w)(offs_t offset, UINT16 data);
static UINT16 amiga_chip_ram16_r(offs_t offset)
{ {
extern const amiga_machine_interface *amiga_intf; offset &= state->intf->chip_ram_mask;
offset &= amiga_intf->chip_ram_mask; return (offset < state->chip_ram_size) ? state->chip_ram[offset/2] : 0xffff;
return (offset < amiga_chip_ram_size) ? amiga_chip_ram[offset/2] : 0xffff;
} }
static UINT16 amiga_chip_ram32_r(offs_t offset) static UINT16 amiga_chip_ram32_r(amiga_state *state, offs_t offset)
{ {
extern const amiga_machine_interface *amiga_intf; offset &= state->intf->chip_ram_mask;
offset &= amiga_intf->chip_ram_mask;
if ( offset < amiga_chip_ram_size ) if (offset < state->chip_ram_size)
{ {
UINT32 *amiga_chip_ram32 = (UINT32 *)state->chip_ram;
UINT32 dat = amiga_chip_ram32[offset / 4]; UINT32 dat = amiga_chip_ram32[offset / 4];
if ( offset & 2 ) if ( offset & 2 )
@ -211,22 +176,21 @@ static UINT16 amiga_chip_ram32_r(offs_t offset)
return 0xffff; return 0xffff;
} }
static void amiga_chip_ram16_w(offs_t offset, UINT16 data) static void amiga_chip_ram16_w(amiga_state *state, offs_t offset, UINT16 data)
{ {
extern const amiga_machine_interface *amiga_intf; offset &= state->intf->chip_ram_mask;
offset &= amiga_intf->chip_ram_mask;
if (offset < amiga_chip_ram_size) if (offset < state->chip_ram_size)
amiga_chip_ram[offset/2] = data; state->chip_ram[offset/2] = data;
} }
static void amiga_chip_ram32_w(offs_t offset, UINT16 data) static void amiga_chip_ram32_w(amiga_state *state, offs_t offset, UINT16 data)
{ {
extern const amiga_machine_interface *amiga_intf; offset &= state->intf->chip_ram_mask;
offset &= amiga_intf->chip_ram_mask;
if ( offset < amiga_chip_ram_size ) if (offset < state->chip_ram_size)
{ {
UINT32 *amiga_chip_ram32 = (UINT32 *)state->chip_ram;
UINT32 dat = amiga_chip_ram32[offset / 4]; UINT32 dat = amiga_chip_ram32[offset / 4];
if ( offset & 2 ) if ( offset & 2 )
@ -245,11 +209,11 @@ static void amiga_chip_ram32_w(offs_t offset, UINT16 data)
} }
void amiga_chip_ram_w8(offs_t offset, UINT8 data) void amiga_chip_ram_w8(amiga_state *state, offs_t offset, UINT8 data)
{ {
UINT16 dat; UINT16 dat;
dat = amiga_chip_ram_r(offset); dat = (*state->chip_ram_r)(state, offset);
if (offset & 0x01) if (offset & 0x01)
{ {
dat &= 0xff00; dat &= 0xff00;
@ -260,7 +224,7 @@ void amiga_chip_ram_w8(offs_t offset, UINT8 data)
dat &= 0x00ff; dat &= 0x00ff;
dat |= ((UINT16)data) << 8; dat |= ((UINT16)data) << 8;
} }
amiga_chip_ram_w(offset,dat); (*state->chip_ram_w)(state, offset, dat);
} }
/************************************* /*************************************
@ -271,28 +235,32 @@ void amiga_chip_ram_w8(offs_t offset, UINT8 data)
void amiga_machine_config(running_machine *machine, const amiga_machine_interface *intf) void amiga_machine_config(running_machine *machine, const amiga_machine_interface *intf)
{ {
amiga_intf = intf; amiga_state *state = machine->driver_data<amiga_state>();
state->intf = intf;
/* setup chipmem handlers */ /* setup chipmem handlers */
if ( IS_AGA(intf) ) if ( IS_AGA(intf) )
{ {
amiga_chip_ram_r = amiga_chip_ram32_r; state->chip_ram_r = amiga_chip_ram32_r;
amiga_chip_ram_w = amiga_chip_ram32_w; state->chip_ram_w = amiga_chip_ram32_w;
} }
else else
{ {
amiga_chip_ram_r = amiga_chip_ram16_r; state->chip_ram_r = amiga_chip_ram16_r;
amiga_chip_ram_w = amiga_chip_ram16_w; state->chip_ram_w = amiga_chip_ram16_w;
} }
/* setup the timers */ /* setup the timers */
amiga_irq_timer = timer_alloc(machine, amiga_irq_proc, NULL); state->irq_timer = timer_alloc(machine, amiga_irq_proc, NULL);
amiga_blitter_timer = timer_alloc(machine, amiga_blitter_proc, NULL); state->blitter_timer = timer_alloc(machine, amiga_blitter_proc, NULL);
state->sound_device = machine->device("amiga");
} }
static void amiga_m68k_reset(running_device *device) static void amiga_m68k_reset(running_device *device)
{ {
amiga_state *state = device->machine->driver_data<amiga_state>();
address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM); address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM);
logerror("Executed RESET at PC=%06x\n", cpu_get_pc(space->cpu)); logerror("Executed RESET at PC=%06x\n", cpu_get_pc(space->cpu));
@ -304,7 +272,7 @@ static void amiga_m68k_reset(running_device *device)
autoconfig_reset(device->machine); autoconfig_reset(device->machine);
/* set the overlay bit */ /* set the overlay bit */
if ( IS_AGA(amiga_intf) ) if ( IS_AGA(state->intf) )
{ {
space->write_byte( 0xbfa001, 1 ); space->write_byte( 0xbfa001, 1 );
} }
@ -317,14 +285,16 @@ static void amiga_m68k_reset(running_device *device)
MACHINE_RESET( amiga ) MACHINE_RESET( amiga )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
/* set m68k reset function */ /* set m68k reset function */
m68k_set_reset_callback(machine->device("maincpu"), amiga_m68k_reset); m68k_set_reset_callback(machine->device("maincpu"), amiga_m68k_reset);
amiga_m68k_reset(machine->device("maincpu")); amiga_m68k_reset(machine->device("maincpu"));
/* call the system-specific callback */ /* call the system-specific callback */
if (amiga_intf->reset_callback) if (state->intf->reset_callback)
(*amiga_intf->reset_callback)(machine); (*state->intf->reset_callback)(machine);
/* start the scanline timer */ /* start the scanline timer */
timer_set(machine, machine->primary_screen->time_until_pos(0), NULL, 0, scanline_callback); timer_set(machine, machine->primary_screen->time_until_pos(0), NULL, 0, scanline_callback);
@ -340,6 +310,7 @@ MACHINE_RESET( amiga )
static TIMER_CALLBACK( scanline_callback ) static TIMER_CALLBACK( scanline_callback )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
int scanline = param; int scanline = param;
running_device *cia_0 = machine->device("cia_0"); running_device *cia_0 = machine->device("cia_0");
running_device *cia_1 = machine->device("cia_1"); running_device *cia_1 = machine->device("cia_1");
@ -354,8 +325,8 @@ static TIMER_CALLBACK( scanline_callback )
mos6526_tod_w(cia_0, 1); mos6526_tod_w(cia_0, 1);
/* call the system-specific callback */ /* call the system-specific callback */
if (amiga_intf->scanline0_callback != NULL) if (state->intf->scanline0_callback != NULL)
(*amiga_intf->scanline0_callback)(machine); (*state->intf->scanline0_callback)(machine);
} }
/* on every scanline, clock the second CIA TOD */ /* on every scanline, clock the second CIA TOD */
@ -364,14 +335,14 @@ static TIMER_CALLBACK( scanline_callback )
/* render up to this scanline */ /* render up to this scanline */
if (!machine->primary_screen->update_partial(scanline)) if (!machine->primary_screen->update_partial(scanline))
{ {
if (IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
amiga_aga_render_scanline(machine, NULL, scanline); amiga_aga_render_scanline(machine, NULL, scanline);
else else
amiga_render_scanline(machine, NULL, scanline); amiga_render_scanline(machine, NULL, scanline);
} }
/* force a sound update */ /* force a sound update */
amiga_audio_update(); amiga_audio_update(state->sound_device);
/* set timer for next line */ /* set timer for next line */
scanline = (scanline + 1) % machine->primary_screen->height(); scanline = (scanline + 1) % machine->primary_screen->height();
@ -388,6 +359,7 @@ static TIMER_CALLBACK( scanline_callback )
static void update_irqs(running_machine *machine) static void update_irqs(running_machine *machine)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
int ints = CUSTOM_REG(REG_INTENA) & CUSTOM_REG(REG_INTREQ); int ints = CUSTOM_REG(REG_INTENA) & CUSTOM_REG(REG_INTREQ);
/* Master interrupt switch */ /* Master interrupt switch */
@ -425,8 +397,10 @@ static void update_irqs(running_machine *machine)
static TIMER_CALLBACK( amiga_irq_proc ) static TIMER_CALLBACK( amiga_irq_proc )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
update_irqs(machine); update_irqs(machine);
timer_reset( amiga_irq_timer, attotime_never); timer_reset( state->irq_timer, attotime_never);
} }
@ -459,7 +433,7 @@ CUSTOM_INPUT( amiga_joystick_convert )
* *
*************************************/ *************************************/
static UINT32 blit_ascending(void) static UINT32 blit_ascending(amiga_state *state)
{ {
UINT32 shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf; UINT32 shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf;
UINT32 shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf; UINT32 shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
@ -482,21 +456,21 @@ static UINT32 blit_ascending(void)
/* fetch data for A */ /* fetch data for A */
if (CUSTOM_REG(REG_BLTCON0) & 0x0800) if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
{ {
CUSTOM_REG(REG_BLTADAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTAPTH)); CUSTOM_REG(REG_BLTADAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTAPTH));
CUSTOM_REG_LONG(REG_BLTAPTH) += 2; CUSTOM_REG_LONG(REG_BLTAPTH) += 2;
} }
/* fetch data for B */ /* fetch data for B */
if (CUSTOM_REG(REG_BLTCON0) & 0x0400) if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
{ {
CUSTOM_REG(REG_BLTBDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTBPTH)); CUSTOM_REG(REG_BLTBDAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTBPTH));
CUSTOM_REG_LONG(REG_BLTBPTH) += 2; CUSTOM_REG_LONG(REG_BLTBPTH) += 2;
} }
/* fetch data for C */ /* fetch data for C */
if (CUSTOM_REG(REG_BLTCON0) & 0x0200) if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
{ {
CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH)); CUSTOM_REG(REG_BLTCDAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTCPTH));
CUSTOM_REG_LONG(REG_BLTCPTH) += 2; CUSTOM_REG_LONG(REG_BLTCPTH) += 2;
} }
@ -552,7 +526,7 @@ static UINT32 blit_ascending(void)
/* write to the destination */ /* write to the destination */
if (CUSTOM_REG(REG_BLTCON0) & 0x0100) if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
{ {
amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd); (*state->chip_ram_w)(state, CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
CUSTOM_REG_LONG(REG_BLTDPTH) += 2; CUSTOM_REG_LONG(REG_BLTDPTH) += 2;
} }
} }
@ -580,7 +554,7 @@ static UINT32 blit_ascending(void)
* *
*************************************/ *************************************/
static UINT32 blit_descending(void) static UINT32 blit_descending(amiga_state *state)
{ {
UINT32 fill_exclusive = (CUSTOM_REG(REG_BLTCON1) >> 4); UINT32 fill_exclusive = (CUSTOM_REG(REG_BLTCON1) >> 4);
UINT32 fill_inclusive = (CUSTOM_REG(REG_BLTCON1) >> 3); UINT32 fill_inclusive = (CUSTOM_REG(REG_BLTCON1) >> 3);
@ -607,21 +581,21 @@ static UINT32 blit_descending(void)
/* fetch data for A */ /* fetch data for A */
if (CUSTOM_REG(REG_BLTCON0) & 0x0800) if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
{ {
CUSTOM_REG(REG_BLTADAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTAPTH)); CUSTOM_REG(REG_BLTADAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTAPTH));
CUSTOM_REG_LONG(REG_BLTAPTH) -= 2; CUSTOM_REG_LONG(REG_BLTAPTH) -= 2;
} }
/* fetch data for B */ /* fetch data for B */
if (CUSTOM_REG(REG_BLTCON0) & 0x0400) if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
{ {
CUSTOM_REG(REG_BLTBDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTBPTH)); CUSTOM_REG(REG_BLTBDAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTBPTH));
CUSTOM_REG_LONG(REG_BLTBPTH) -= 2; CUSTOM_REG_LONG(REG_BLTBPTH) -= 2;
} }
/* fetch data for C */ /* fetch data for C */
if (CUSTOM_REG(REG_BLTCON0) & 0x0200) if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
{ {
CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH)); CUSTOM_REG(REG_BLTCDAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTCPTH));
CUSTOM_REG_LONG(REG_BLTCPTH) -= 2; CUSTOM_REG_LONG(REG_BLTCPTH) -= 2;
} }
@ -694,7 +668,7 @@ static UINT32 blit_descending(void)
/* write to the destination */ /* write to the destination */
if (CUSTOM_REG(REG_BLTCON0) & 0x0100) if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
{ {
amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd); (*state->chip_ram_w)(state, CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
CUSTOM_REG_LONG(REG_BLTDPTH) -= 2; CUSTOM_REG_LONG(REG_BLTDPTH) -= 2;
} }
} }
@ -761,7 +735,7 @@ static UINT32 blit_descending(void)
BLTAMOD = 4 * (dy - dx) and BLTBMOD = 4 * dy. BLTAMOD = 4 * (dy - dx) and BLTBMOD = 4 * dy.
*/ */
static UINT32 blit_line(void) static UINT32 blit_line(amiga_state *state)
{ {
UINT32 singlemode = (CUSTOM_REG(REG_BLTCON1) & 0x0002) ? 0x0000 : 0xffff; UINT32 singlemode = (CUSTOM_REG(REG_BLTCON1) & 0x0002) ? 0x0000 : 0xffff;
UINT32 singlemask = 0xffff; UINT32 singlemask = 0xffff;
@ -786,7 +760,7 @@ static UINT32 blit_line(void)
/* fetch data for C */ /* fetch data for C */
if (CUSTOM_REG(REG_BLTCON0) & 0x0200) if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH)); CUSTOM_REG(REG_BLTCDAT) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BLTCPTH));
/* rotate the A data according to the shift */ /* rotate the A data according to the shift */
tempa = CUSTOM_REG(REG_BLTADAT) >> (CUSTOM_REG(REG_BLTCON0) >> 12); tempa = CUSTOM_REG(REG_BLTADAT) >> (CUSTOM_REG(REG_BLTCON0) >> 12);
@ -837,7 +811,7 @@ static UINT32 blit_line(void)
blitsum |= tempd; blitsum |= tempd;
/* write to the destination */ /* write to the destination */
amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd); (*state->chip_ram_w)(state, CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
/* always increment along the major axis */ /* always increment along the major axis */
if (CUSTOM_REG(REG_BLTCON1) & 0x0010) if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
@ -914,6 +888,7 @@ static UINT32 blit_line(void)
static TIMER_CALLBACK( amiga_blitter_proc ) static TIMER_CALLBACK( amiga_blitter_proc )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
UINT32 blitsum = 0; UINT32 blitsum = 0;
/* logging */ /* logging */
@ -938,16 +913,16 @@ static TIMER_CALLBACK( amiga_blitter_proc )
switch (CUSTOM_REG(REG_BLTCON1) & 0x0003) switch (CUSTOM_REG(REG_BLTCON1) & 0x0003)
{ {
case 0: /* ascending */ case 0: /* ascending */
blitsum = blit_ascending(); blitsum = blit_ascending(state);
break; break;
case 2: /* descending */ case 2: /* descending */
blitsum = blit_descending(); blitsum = blit_descending(state);
break; break;
case 1: /* line */ case 1: /* line */
case 3: case 3:
blitsum = blit_line(); blitsum = blit_line(state);
break; break;
} }
@ -962,7 +937,7 @@ static TIMER_CALLBACK( amiga_blitter_proc )
amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), REG_INTREQ, 0x8000 | INTENA_BLIT, 0xffff); amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), REG_INTREQ, 0x8000 | INTENA_BLIT, 0xffff);
/* reset the blitter timer */ /* reset the blitter timer */
timer_reset( amiga_blitter_timer, attotime_never); timer_reset( state->blitter_timer, attotime_never);
} }
@ -975,6 +950,7 @@ static TIMER_CALLBACK( amiga_blitter_proc )
static void blitter_setup(address_space *space) static void blitter_setup(address_space *space)
{ {
amiga_state *state = space->machine->driver_data<amiga_state>();
int ticks, width, height, blittime; int ticks, width, height, blittime;
/* is there another blitting in progress? */ /* is there another blitting in progress? */
@ -1019,14 +995,14 @@ static void blitter_setup(address_space *space)
} }
/* AGA has twice the bus bandwidth, so blits take half the time */ /* AGA has twice the bus bandwidth, so blits take half the time */
if ( IS_AGA(amiga_intf) ) if ( IS_AGA(state->intf) )
blittime /= 2; blittime /= 2;
/* signal blitter busy */ /* signal blitter busy */
CUSTOM_REG(REG_DMACON) |= 0x4000; CUSTOM_REG(REG_DMACON) |= 0x4000;
/* set a timer */ /* set a timer */
timer_adjust_oneshot( amiga_blitter_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( blittime ), 0); timer_adjust_oneshot( state->blitter_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( blittime ), 0);
} }
@ -1132,6 +1108,7 @@ void amiga_cia_1_irq(running_device *device, int state)
static void custom_reset(running_machine *machine) static void custom_reset(running_machine *machine)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
int clock = cputag_get_clock(machine, "maincpu"); int clock = cputag_get_clock(machine, "maincpu");
UINT16 vidmode = (clock == AMIGA_68000_NTSC_CLOCK || clock == AMIGA_68EC020_NTSC_CLOCK ) ? 0x1000 : 0x0000; /* NTSC or PAL? */ UINT16 vidmode = (clock == AMIGA_68000_NTSC_CLOCK || clock == AMIGA_68EC020_NTSC_CLOCK ) ? 0x1000 : 0x0000; /* NTSC or PAL? */
@ -1141,7 +1118,7 @@ static void custom_reset(running_machine *machine)
CUSTOM_REG(REG_VPOSR) = vidmode; CUSTOM_REG(REG_VPOSR) = vidmode;
CUSTOM_REG(REG_SERDATR) = 0x3000; CUSTOM_REG(REG_SERDATR) = 0x3000;
switch (amiga_intf->chip_ram_mask) switch (state->intf->chip_ram_mask)
{ {
case ANGUS_CHIP_RAM_MASK: case ANGUS_CHIP_RAM_MASK:
case FAT_ANGUS_CHIP_RAM_MASK: case FAT_ANGUS_CHIP_RAM_MASK:
@ -1151,7 +1128,7 @@ static void custom_reset(running_machine *machine)
case ECS_CHIP_RAM_MASK: case ECS_CHIP_RAM_MASK:
CUSTOM_REG(REG_VPOSR) |= 0x2000; CUSTOM_REG(REG_VPOSR) |= 0x2000;
CUSTOM_REG(REG_DENISEID) = 0x00FC; CUSTOM_REG(REG_DENISEID) = 0x00FC;
if (IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
{ {
CUSTOM_REG(REG_VPOSR) |= 0x0300; CUSTOM_REG(REG_VPOSR) |= 0x0300;
CUSTOM_REG(REG_DENISEID) = 0x00F8; CUSTOM_REG(REG_DENISEID) = 0x00F8;
@ -1170,6 +1147,7 @@ static void custom_reset(running_machine *machine)
READ16_HANDLER( amiga_custom_r ) READ16_HANDLER( amiga_custom_r )
{ {
amiga_state *state = space->machine->driver_data<amiga_state>();
UINT16 temp; UINT16 temp;
switch (offset & 0xff) switch (offset & 0xff)
@ -1182,16 +1160,10 @@ READ16_HANDLER( amiga_custom_r )
case REG_VPOSR: case REG_VPOSR:
CUSTOM_REG(REG_VPOSR) &= 0xff00; CUSTOM_REG(REG_VPOSR) &= 0xff00;
if (IS_AGA(amiga_intf))
CUSTOM_REG(REG_VPOSR) |= amiga_aga_gethvpos(*space->machine->primary_screen) >> 16;
else
CUSTOM_REG(REG_VPOSR) |= amiga_gethvpos(*space->machine->primary_screen) >> 16; CUSTOM_REG(REG_VPOSR) |= amiga_gethvpos(*space->machine->primary_screen) >> 16;
return CUSTOM_REG(REG_VPOSR); return CUSTOM_REG(REG_VPOSR);
case REG_VHPOSR: case REG_VHPOSR:
if (IS_AGA(amiga_intf))
return amiga_aga_gethvpos(*space->machine->primary_screen) & 0xffff;
else
return amiga_gethvpos(*space->machine->primary_screen) & 0xffff; return amiga_gethvpos(*space->machine->primary_screen) & 0xffff;
case REG_SERDATR: case REG_SERDATR:
@ -1200,13 +1172,13 @@ READ16_HANDLER( amiga_custom_r )
return CUSTOM_REG(REG_SERDATR); return CUSTOM_REG(REG_SERDATR);
case REG_JOY0DAT: case REG_JOY0DAT:
if (amiga_intf->joy0dat_r != NULL) if (state->intf->joy0dat_r != NULL)
return (*amiga_intf->joy0dat_r)(space->machine); return (*state->intf->joy0dat_r)(space->machine);
return input_port_read_safe(space->machine, "JOY0DAT", 0xffff); return input_port_read_safe(space->machine, "JOY0DAT", 0xffff);
case REG_JOY1DAT: case REG_JOY1DAT:
if (amiga_intf->joy1dat_r != NULL) if (state->intf->joy1dat_r != NULL)
return (*amiga_intf->joy1dat_r)(space->machine); return (*state->intf->joy1dat_r)(space->machine);
return input_port_read_safe(space->machine, "JOY1DAT", 0xffff); return input_port_read_safe(space->machine, "JOY1DAT", 0xffff);
case REG_ADKCONR: case REG_ADKCONR:
@ -1222,8 +1194,8 @@ READ16_HANDLER( amiga_custom_r )
return input_port_read_safe(space->machine, "POT1DAT", 0x0000); return input_port_read_safe(space->machine, "POT1DAT", 0x0000);
case REG_DSKBYTR: case REG_DSKBYTR:
if (amiga_intf->dskbytr_r != NULL) if (state->intf->dskbytr_r != NULL)
return (*amiga_intf->dskbytr_r)(space->machine); return (*state->intf->dskbytr_r)(space->machine);
return 0x0000; return 0x0000;
case REG_INTENAR: case REG_INTENAR:
@ -1233,17 +1205,11 @@ READ16_HANDLER( amiga_custom_r )
return CUSTOM_REG(REG_INTREQ); return CUSTOM_REG(REG_INTREQ);
case REG_COPJMP1: case REG_COPJMP1:
if (IS_AGA(amiga_intf)) amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP1LCH));
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
break; break;
case REG_COPJMP2: case REG_COPJMP2:
if (IS_AGA(amiga_intf)) amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP2LCH));
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
break; break;
case REG_CLXDAT: case REG_CLXDAT:
@ -1271,6 +1237,8 @@ READ16_HANDLER( amiga_custom_r )
static TIMER_CALLBACK( finish_serial_write ) static TIMER_CALLBACK( finish_serial_write )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
/* mark the transfer buffer empty */ /* mark the transfer buffer empty */
CUSTOM_REG(REG_SERDATR) |= 0x3000; CUSTOM_REG(REG_SERDATR) |= 0x3000;
@ -1281,6 +1249,7 @@ static TIMER_CALLBACK( finish_serial_write )
WRITE16_HANDLER( amiga_custom_w ) WRITE16_HANDLER( amiga_custom_w )
{ {
amiga_state *state = space->machine->driver_data<amiga_state>();
running_device *cia_0; running_device *cia_0;
running_device *cia_1; running_device *cia_1;
UINT16 temp; UINT16 temp;
@ -1299,18 +1268,18 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_DSKLEN: case REG_DSKLEN:
if (amiga_intf->dsklen_w != NULL) if (state->intf->dsklen_w != NULL)
(*amiga_intf->dsklen_w)(space->machine, data); (*state->intf->dsklen_w)(space->machine, data);
break; break;
case REG_POTGO: case REG_POTGO:
if (amiga_intf->potgo_w != NULL) if (state->intf->potgo_w != NULL)
(*amiga_intf->potgo_w)(space->machine, data); (*state->intf->potgo_w)(space->machine, data);
break; break;
case REG_SERDAT: case REG_SERDAT:
if (amiga_intf->serdat_w != NULL) if (state->intf->serdat_w != NULL)
(*amiga_intf->serdat_w)(space->machine, data); (*state->intf->serdat_w)(space->machine, data);
CUSTOM_REG(REG_SERDATR) &= ~0x3000; CUSTOM_REG(REG_SERDATR) &= ~0x3000;
timer_set(space->machine, amiga_get_serial_char_period(space->machine), NULL, 0, finish_serial_write); timer_set(space->machine, amiga_get_serial_char_period(space->machine), NULL, 0, finish_serial_write);
break; break;
@ -1325,7 +1294,7 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_BLTSIZV: /* ECS-AGA only */ case REG_BLTSIZV: /* ECS-AGA only */
if ( IS_ECS_OR_AGA(amiga_intf) ) if ( IS_ECS_OR_AGA(state->intf) )
{ {
CUSTOM_REG(REG_BLTSIZV) = data & 0x7fff; CUSTOM_REG(REG_BLTSIZV) = data & 0x7fff;
if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x8000; if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x8000;
@ -1333,7 +1302,7 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_BLTSIZH: /* ECS-AGA only */ case REG_BLTSIZH: /* ECS-AGA only */
if ( IS_ECS_OR_AGA(amiga_intf) ) if ( IS_ECS_OR_AGA(state->intf) )
{ {
CUSTOM_REG(REG_BLTSIZH) = data & 0x7ff; CUSTOM_REG(REG_BLTSIZH) = data & 0x7ff;
if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800; if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800;
@ -1342,7 +1311,7 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_BLTCON0L: /* ECS-AGA only */ case REG_BLTCON0L: /* ECS-AGA only */
if ( IS_ECS_OR_AGA(amiga_intf) ) if ( IS_ECS_OR_AGA(state->intf) )
{ {
CUSTOM_REG(REG_BLTCON0) &= 0xff00; CUSTOM_REG(REG_BLTCON0) &= 0xff00;
CUSTOM_REG(REG_BLTCON0) |= data & 0xff; CUSTOM_REG(REG_BLTCON0) |= data & 0xff;
@ -1351,51 +1320,36 @@ WRITE16_HANDLER( amiga_custom_w )
case REG_SPR0PTH: case REG_SPR1PTH: case REG_SPR2PTH: case REG_SPR3PTH: case REG_SPR0PTH: case REG_SPR1PTH: case REG_SPR2PTH: case REG_SPR3PTH:
case REG_SPR4PTH: case REG_SPR5PTH: case REG_SPR6PTH: case REG_SPR7PTH: case REG_SPR4PTH: case REG_SPR5PTH: case REG_SPR6PTH: case REG_SPR7PTH:
data &= ( amiga_intf->chip_ram_mask >> 16 ); data &= ( state->intf->chip_ram_mask >> 16 );
break; break;
case REG_SPR0PTL: case REG_SPR1PTL: case REG_SPR2PTL: case REG_SPR3PTL: case REG_SPR0PTL: case REG_SPR1PTL: case REG_SPR2PTL: case REG_SPR3PTL:
case REG_SPR4PTL: case REG_SPR5PTL: case REG_SPR6PTL: case REG_SPR7PTL: case REG_SPR4PTL: case REG_SPR5PTL: case REG_SPR6PTL: case REG_SPR7PTL:
if (IS_AGA(amiga_intf)) amiga_sprite_dma_reset(space->machine, (offset - REG_SPR0PTL) / 2);
amiga_aga_sprite_dma_reset((offset - REG_SPR0PTL) / 2);
else
amiga_sprite_dma_reset((offset - REG_SPR0PTL) / 2);
break; break;
case REG_SPR0CTL: case REG_SPR1CTL: case REG_SPR2CTL: case REG_SPR3CTL: case REG_SPR0CTL: case REG_SPR1CTL: case REG_SPR2CTL: case REG_SPR3CTL:
case REG_SPR4CTL: case REG_SPR5CTL: case REG_SPR6CTL: case REG_SPR7CTL: case REG_SPR4CTL: case REG_SPR5CTL: case REG_SPR6CTL: case REG_SPR7CTL:
/* disable comparitor on writes here */ /* disable comparitor on writes here */
if (IS_AGA(amiga_intf)) amiga_sprite_enable_comparitor(space->machine, (offset - REG_SPR0CTL) / 4, FALSE);
amiga_aga_sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, FALSE);
else
amiga_sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, FALSE);
break; break;
case REG_SPR0DATA: case REG_SPR1DATA: case REG_SPR2DATA: case REG_SPR3DATA: case REG_SPR0DATA: case REG_SPR1DATA: case REG_SPR2DATA: case REG_SPR3DATA:
case REG_SPR4DATA: case REG_SPR5DATA: case REG_SPR6DATA: case REG_SPR7DATA: case REG_SPR4DATA: case REG_SPR5DATA: case REG_SPR6DATA: case REG_SPR7DATA:
/* enable comparitor on writes here */ /* enable comparitor on writes here */
if (IS_AGA(amiga_intf)) amiga_sprite_enable_comparitor(space->machine, (offset - REG_SPR0DATA) / 4, TRUE);
amiga_aga_sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, TRUE);
else
amiga_sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, TRUE);
break; break;
case REG_COP1LCH: case REG_COP2LCH: case REG_COP1LCH: case REG_COP2LCH:
data &= ( amiga_intf->chip_ram_mask >> 16 ); data &= ( state->intf->chip_ram_mask >> 16 );
break; break;
case REG_COPJMP1: case REG_COPJMP1:
if (IS_AGA(amiga_intf)) amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP1LCH));
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
break; break;
case REG_COPJMP2: case REG_COPJMP2:
if (IS_AGA(amiga_intf)) amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP2LCH));
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
break; break;
case REG_DDFSTRT: case REG_DDFSTRT:
@ -1413,7 +1367,7 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_DMACON: case REG_DMACON:
amiga_audio_update(); amiga_audio_update(state->sound_device);
/* bits BBUSY (14) and BZERO (13) are read-only */ /* bits BBUSY (14) and BZERO (13) are read-only */
data &= 0x9fff; data &= 0x9fff;
@ -1421,7 +1375,7 @@ WRITE16_HANDLER( amiga_custom_w )
/* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */ /* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) ) if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
timer_adjust_oneshot( amiga_blitter_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( BLITTER_NASTY_DELAY ), 0); timer_adjust_oneshot( state->blitter_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( BLITTER_NASTY_DELAY ), 0);
break; break;
@ -1432,7 +1386,7 @@ WRITE16_HANDLER( amiga_custom_w )
CUSTOM_REG(offset) = data; CUSTOM_REG(offset) = data;
if ( temp & 0x8000 ) /* if we're enabling irq's, delay a bit */ if ( temp & 0x8000 ) /* if we're enabling irq's, delay a bit */
timer_adjust_oneshot( amiga_irq_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( AMIGA_IRQ_DELAY_CYCLES ), 0); timer_adjust_oneshot( state->irq_timer, downcast<cpu_device *>(space->cpu)->cycles_to_attotime( AMIGA_IRQ_DELAY_CYCLES ), 0);
else /* if we're disabling irq's, process right away */ else /* if we're disabling irq's, process right away */
update_irqs(space->machine); update_irqs(space->machine);
break; break;
@ -1451,13 +1405,13 @@ WRITE16_HANDLER( amiga_custom_w )
CUSTOM_REG(offset) = data; CUSTOM_REG(offset) = data;
if ( temp & 0x8000 ) /* if we're generating irq's, delay a bit */ if ( temp & 0x8000 ) /* if we're generating irq's, delay a bit */
timer_adjust_oneshot( amiga_irq_timer, space->machine->device<cpu_device>("maincpu")->cycles_to_attotime( AMIGA_IRQ_DELAY_CYCLES ), 0); timer_adjust_oneshot( state->irq_timer, space->machine->device<cpu_device>("maincpu")->cycles_to_attotime( AMIGA_IRQ_DELAY_CYCLES ), 0);
else /* if we're clearing irq's, process right away */ else /* if we're clearing irq's, process right away */
update_irqs(space->machine); update_irqs(space->machine);
break; break;
case REG_ADKCON: case REG_ADKCON:
amiga_audio_update(); amiga_audio_update(state->sound_device);
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff)); data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
break; break;
@ -1465,16 +1419,16 @@ WRITE16_HANDLER( amiga_custom_w )
case REG_AUD1LCL: case REG_AUD1LCH: case REG_AUD1LEN: case REG_AUD1PER: case REG_AUD1VOL: case REG_AUD1LCL: case REG_AUD1LCH: case REG_AUD1LEN: case REG_AUD1PER: case REG_AUD1VOL:
case REG_AUD2LCL: case REG_AUD2LCH: case REG_AUD2LEN: case REG_AUD2PER: case REG_AUD2VOL: case REG_AUD2LCL: case REG_AUD2LCH: case REG_AUD2LEN: case REG_AUD2PER: case REG_AUD2VOL:
case REG_AUD3LCL: case REG_AUD3LCH: case REG_AUD3LEN: case REG_AUD3PER: case REG_AUD3VOL: case REG_AUD3LCL: case REG_AUD3LCH: case REG_AUD3LEN: case REG_AUD3PER: case REG_AUD3VOL:
amiga_audio_update(); amiga_audio_update(state->sound_device);
break; break;
case REG_AUD0DAT: case REG_AUD1DAT: case REG_AUD2DAT: case REG_AUD3DAT: case REG_AUD0DAT: case REG_AUD1DAT: case REG_AUD2DAT: case REG_AUD3DAT:
amiga_audio_data_w((offset - REG_AUD0DAT) / 8, data); amiga_audio_data_w(state->sound_device, (offset - REG_AUD0DAT) / 8, data);
break; break;
case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH: case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH:
case REG_BPL5PTH: case REG_BPL6PTH: case REG_BPL5PTH: case REG_BPL6PTH:
data &= ( amiga_intf->chip_ram_mask >> 16 ); data &= ( state->intf->chip_ram_mask >> 16 );
break; break;
case REG_BPLCON0: case REG_BPLCON0:
@ -1494,9 +1448,9 @@ WRITE16_HANDLER( amiga_custom_w )
case REG_COLOR20: case REG_COLOR21: case REG_COLOR22: case REG_COLOR23: case REG_COLOR20: case REG_COLOR21: case REG_COLOR22: case REG_COLOR23:
case REG_COLOR24: case REG_COLOR25: case REG_COLOR26: case REG_COLOR27: case REG_COLOR24: case REG_COLOR25: case REG_COLOR26: case REG_COLOR27:
case REG_COLOR28: case REG_COLOR29: case REG_COLOR30: case REG_COLOR31: case REG_COLOR28: case REG_COLOR29: case REG_COLOR30: case REG_COLOR31:
if ( IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
{ {
aga_palette_write(offset - REG_COLOR00, data); amiga_aga_palette_write(space->machine, offset - REG_COLOR00, data);
} }
else else
{ {
@ -1506,19 +1460,19 @@ WRITE16_HANDLER( amiga_custom_w )
break; break;
case REG_DIWSTRT: case REG_DIWSTRT:
case REG_DIWSTOP: case REG_DIWSTOP:
if (IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
aga_diwhigh_written(0); amiga_aga_diwhigh_written(space->machine, 0);
break; break;
case REG_DIWHIGH: case REG_DIWHIGH:
if (IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
aga_diwhigh_written(1); amiga_aga_diwhigh_written(space->machine, 1);
break; break;
default: default:
break; break;
} }
if (IS_AGA(amiga_intf)) if (IS_AGA(state->intf))
CUSTOM_REG(offset) = data; CUSTOM_REG(offset) = data;
else else
if (offset <= REG_COLOR31) if (offset <= REG_COLOR31)
@ -1535,6 +1489,7 @@ WRITE16_HANDLER( amiga_custom_w )
void amiga_serial_in_w(running_machine *machine, UINT16 data) void amiga_serial_in_w(running_machine *machine, UINT16 data)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
int mask = (CUSTOM_REG(REG_SERPER) & 0x8000) ? 0x1ff : 0xff; int mask = (CUSTOM_REG(REG_SERPER) & 0x8000) ? 0x1ff : 0xff;
@ -1556,6 +1511,7 @@ void amiga_serial_in_w(running_machine *machine, UINT16 data)
attotime amiga_get_serial_char_period(running_machine *machine) attotime amiga_get_serial_char_period(running_machine *machine)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
UINT32 divisor = (CUSTOM_REG(REG_SERPER) & 0x7fff) + 1; UINT32 divisor = (CUSTOM_REG(REG_SERPER) & 0x7fff) + 1;
UINT32 baud = cputag_get_clock(machine, "maincpu") / 2 / divisor; UINT32 baud = cputag_get_clock(machine, "maincpu") / 2 / divisor;
UINT32 numbits = 2 + ((CUSTOM_REG(REG_SERPER) & 0x8000) ? 9 : 8); UINT32 numbits = 2 + ((CUSTOM_REG(REG_SERPER) & 0x8000) ? 9 : 8);
@ -1572,6 +1528,7 @@ attotime amiga_get_serial_char_period(running_machine *machine)
void amiga_add_autoconfig(running_machine *machine, const amiga_autoconfig_device *device) void amiga_add_autoconfig(running_machine *machine, const amiga_autoconfig_device *device)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
autoconfig_device *dev, **d; autoconfig_device *dev, **d;
/* validate the data */ /* validate the data */
@ -1581,7 +1538,7 @@ void amiga_add_autoconfig(running_machine *machine, const amiga_autoconfig_devic
/* allocate memory and link it in at the end of the list */ /* allocate memory and link it in at the end of the list */
dev = auto_alloc(machine, autoconfig_device); dev = auto_alloc(machine, autoconfig_device);
dev->next = NULL; dev->next = NULL;
for (d = &autoconfig_list; *d; d = &(*d)->next) ; for (d = &state->autoconfig_list; *d; d = &(*d)->next) ;
*d = dev; *d = dev;
/* fill in the data */ /* fill in the data */
@ -1599,10 +1556,11 @@ void amiga_add_autoconfig(running_machine *machine, const amiga_autoconfig_devic
static void autoconfig_reset(running_machine *machine) static void autoconfig_reset(running_machine *machine)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
autoconfig_device *dev; autoconfig_device *dev;
/* uninstall any installed devices */ /* uninstall any installed devices */
for (dev = autoconfig_list; dev; dev = dev->next) for (dev = state->autoconfig_list; dev; dev = dev->next)
if (dev->base && dev->device.uninstall) if (dev->base && dev->device.uninstall)
{ {
(*dev->device.uninstall)(machine, dev->base); (*dev->device.uninstall)(machine, dev->base);
@ -1610,7 +1568,7 @@ static void autoconfig_reset(running_machine *machine)
} }
/* reset the current autoconfig */ /* reset the current autoconfig */
cur_autoconfig = autoconfig_list; state->cur_autoconfig = state->autoconfig_list;
} }
@ -1623,6 +1581,8 @@ static void autoconfig_reset(running_machine *machine)
READ16_HANDLER( amiga_autoconfig_r ) READ16_HANDLER( amiga_autoconfig_r )
{ {
amiga_state *state = space->machine->driver_data<amiga_state>();
autoconfig_device *cur_autoconfig = state->cur_autoconfig;
UINT8 byte; UINT8 byte;
int i; int i;
@ -1760,6 +1720,8 @@ READ16_HANDLER( amiga_autoconfig_r )
WRITE16_HANDLER( amiga_autoconfig_w ) WRITE16_HANDLER( amiga_autoconfig_w )
{ {
amiga_state *state = space->machine->driver_data<amiga_state>();
autoconfig_device *cur_autoconfig = state->cur_autoconfig;
int move_to_next = FALSE; int move_to_next = FALSE;
logerror("autoconfig_w(%02X) = %04X & %04X\n", offset, data, mem_mask); logerror("autoconfig_w(%02X) = %04X & %04X\n", offset, data, mem_mask);
@ -1797,7 +1759,7 @@ WRITE16_HANDLER( amiga_autoconfig_w )
logerror("Install to %06X\n", cur_autoconfig->base); logerror("Install to %06X\n", cur_autoconfig->base);
if (cur_autoconfig->base && cur_autoconfig->device.install) if (cur_autoconfig->base && cur_autoconfig->device.install)
(*cur_autoconfig->device.install)(space->machine, cur_autoconfig->base); (*cur_autoconfig->device.install)(space->machine, cur_autoconfig->base);
cur_autoconfig = cur_autoconfig->next; state->cur_autoconfig = cur_autoconfig->next;
} }
} }
@ -1809,7 +1771,7 @@ WRITE16_HANDLER( amiga_autoconfig_w )
* *
*************************************/ *************************************/
const amiga_machine_interface *amiga_get_interface(void) const amiga_machine_interface *amiga_get_interface(running_machine *machine)
{ {
return amiga_intf; return machine->driver_data<amiga_state>()->intf;
} }

View File

@ -27,8 +27,12 @@ TODO: Add CDDA support
#define CD_SECTOR_TIME (1000/((150*1024)/2048)) /* 1X CDROM sector time in msec (300KBps) */ #define CD_SECTOR_TIME (1000/((150*1024)/2048)) /* 1X CDROM sector time in msec (300KBps) */
static struct akiko_def typedef struct _akiko_state akiko_state;
struct _akiko_state
{ {
running_machine *machine;
address_space *space;
/* chunky to planar converter */ /* chunky to planar converter */
UINT32 c2p_input_buffer[8]; UINT32 c2p_input_buffer[8];
UINT32 c2p_output_buffer[8]; UINT32 c2p_output_buffer[8];
@ -61,75 +65,88 @@ static struct akiko_def
emu_timer *dma_timer; emu_timer *dma_timer;
emu_timer *frame_timer; emu_timer *frame_timer;
running_device *i2cmem; running_device *i2cmem;
} akiko; };
static TIMER_CALLBACK(akiko_dma_proc); static TIMER_CALLBACK(akiko_dma_proc);
static TIMER_CALLBACK(akiko_frame_proc); static TIMER_CALLBACK(akiko_frame_proc);
static void amiga_akiko_exit(running_machine& machine) INLINE akiko_state *get_safe_token(running_device *device)
{ {
if( akiko.cdrom ) { assert(device != NULL);
cdrom_close(akiko.cdrom); assert(device->type() == AKIKO);
akiko.cdrom = (cdrom_file *)NULL;
return (akiko_state *)downcast<legacy_device_base *>(device)->token();
}
static DEVICE_STOP( akiko )
{
akiko_state *state = get_safe_token(device);
if( state->cdrom )
{
cdrom_close(state->cdrom);
state->cdrom = (cdrom_file *)NULL;
} }
} }
void amiga_akiko_init(running_machine* machine) static DEVICE_START( akiko )
{ {
akiko.c2p_input_index = 0; running_machine *machine = device->machine;
akiko.c2p_output_index = 0; akiko_state *state = get_safe_token(device);
akiko.i2c_scl_out = 0; state->machine = machine;
akiko.i2c_scl_dir = 0; state->space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
akiko.i2c_sda_out = 0; state->c2p_input_index = 0;
akiko.i2c_sda_dir = 0; state->c2p_output_index = 0;
akiko.cdrom_status[0] = akiko.cdrom_status[1] = 0; state->i2c_scl_out = 0;
akiko.cdrom_address[0] = akiko.cdrom_address[1] = 0; state->i2c_scl_dir = 0;
akiko.cdrom_track_index = 0; state->i2c_sda_out = 0;
akiko.cdrom_lba_start = 0; state->i2c_sda_dir = 0;
akiko.cdrom_lba_end = 0;
akiko.cdrom_lba_cur = 0;
akiko.cdrom_readmask = 0;
akiko.cdrom_readreqmask = 0;
akiko.cdrom_dmacontrol = 0;
akiko.cdrom_numtracks = 0;
akiko.cdrom_speed = 0;
akiko.cdrom_cmd_start = 0;
akiko.cdrom_cmd_end = 0;
akiko.cdrom_cmd_resp = 0;
akiko.cdrom = cdrom_open(get_disk_handle(machine, "cdrom"));
akiko.cdrom_toc = NULL;
akiko.dma_timer = timer_alloc(machine, akiko_dma_proc, NULL);
akiko.frame_timer = timer_alloc(machine, akiko_frame_proc, NULL);
akiko.i2cmem = machine->device("i2cmem");
machine->add_notifier(MACHINE_NOTIFY_EXIT, amiga_akiko_exit); state->cdrom_status[0] = state->cdrom_status[1] = 0;
state->cdrom_address[0] = state->cdrom_address[1] = 0;
state->cdrom_track_index = 0;
state->cdrom_lba_start = 0;
state->cdrom_lba_end = 0;
state->cdrom_lba_cur = 0;
state->cdrom_readmask = 0;
state->cdrom_readreqmask = 0;
state->cdrom_dmacontrol = 0;
state->cdrom_numtracks = 0;
state->cdrom_speed = 0;
state->cdrom_cmd_start = 0;
state->cdrom_cmd_end = 0;
state->cdrom_cmd_resp = 0;
state->cdrom = cdrom_open(get_disk_handle(machine, "cdrom"));
state->cdrom_toc = NULL;
state->dma_timer = timer_alloc(machine, akiko_dma_proc, state);
state->frame_timer = timer_alloc(machine, akiko_frame_proc, state);
state->i2cmem = machine->device("i2cmem");
/* create the TOC table */ /* create the TOC table */
if ( akiko.cdrom != NULL && cdrom_get_last_track(akiko.cdrom) ) if ( state->cdrom != NULL && cdrom_get_last_track(state->cdrom) )
{ {
UINT8 *p; UINT8 *p;
int i, addrctrl = cdrom_get_adr_control( akiko.cdrom, 0 ); int i, addrctrl = cdrom_get_adr_control( state->cdrom, 0 );
UINT32 discend; UINT32 discend;
discend = cdrom_get_track_start(akiko.cdrom,cdrom_get_last_track(akiko.cdrom)-1); discend = cdrom_get_track_start(state->cdrom,cdrom_get_last_track(state->cdrom)-1);
discend += cdrom_get_toc(akiko.cdrom)->tracks[cdrom_get_last_track(akiko.cdrom)-1].frames; discend += cdrom_get_toc(state->cdrom)->tracks[cdrom_get_last_track(state->cdrom)-1].frames;
discend = lba_to_msf(discend); discend = lba_to_msf(discend);
akiko.cdrom_numtracks = cdrom_get_last_track(akiko.cdrom)+3; state->cdrom_numtracks = cdrom_get_last_track(state->cdrom)+3;
akiko.cdrom_toc = auto_alloc_array(machine, UINT8, 13*akiko.cdrom_numtracks); state->cdrom_toc = auto_alloc_array(machine, UINT8, 13*state->cdrom_numtracks);
memset( akiko.cdrom_toc, 0, 13*akiko.cdrom_numtracks); memset( state->cdrom_toc, 0, 13*state->cdrom_numtracks);
p = akiko.cdrom_toc; p = state->cdrom_toc;
p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
p[3] = 0xa0; /* first track */ p[3] = 0xa0; /* first track */
p[8] = 1; p[8] = 1;
p += 13; p += 13;
p[1] = 0x01; p[1] = 0x01;
p[3] = 0xa1; /* last track */ p[3] = 0xa1; /* last track */
p[8] = cdrom_get_last_track(akiko.cdrom); p[8] = cdrom_get_last_track(state->cdrom);
p += 13; p += 13;
p[1] = 0x01; p[1] = 0x01;
p[3] = 0xa2; /* disc end */ p[3] = 0xa2; /* disc end */
@ -138,12 +155,12 @@ void amiga_akiko_init(running_machine* machine)
p[10] = discend & 0xff; p[10] = discend & 0xff;
p += 13; p += 13;
for( i = 0; i < cdrom_get_last_track(akiko.cdrom); i++ ) for( i = 0; i < cdrom_get_last_track(state->cdrom); i++ )
{ {
UINT32 trackpos = cdrom_get_track_start(akiko.cdrom,i); UINT32 trackpos = cdrom_get_track_start(state->cdrom,i);
trackpos = lba_to_msf(trackpos); trackpos = lba_to_msf(trackpos);
addrctrl = cdrom_get_adr_control( akiko.cdrom, i ); addrctrl = cdrom_get_adr_control( state->cdrom, i );
p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
p[3] = dec_2_bcd( i+1 ); p[3] = dec_2_bcd( i+1 );
@ -156,41 +173,41 @@ void amiga_akiko_init(running_machine* machine)
} }
} }
static void akiko_nvram_write(running_machine *machine, UINT32 data) static void akiko_nvram_write(akiko_state *state, UINT32 data)
{ {
akiko.i2c_scl_out = BIT(data,31); state->i2c_scl_out = BIT(data,31);
akiko.i2c_sda_out = BIT(data,30); state->i2c_sda_out = BIT(data,30);
akiko.i2c_scl_dir = BIT(data,15); state->i2c_scl_dir = BIT(data,15);
akiko.i2c_sda_dir = BIT(data,14); state->i2c_sda_dir = BIT(data,14);
i2cmem_scl_write( akiko.i2cmem, akiko.i2c_scl_out ); i2cmem_scl_write( state->i2cmem, state->i2c_scl_out );
i2cmem_sda_write( akiko.i2cmem, akiko.i2c_sda_out ); i2cmem_sda_write( state->i2cmem, state->i2c_sda_out );
} }
static UINT32 akiko_nvram_read(running_machine *machine) static UINT32 akiko_nvram_read(akiko_state *state)
{ {
UINT32 v = 0; UINT32 v = 0;
if ( akiko.i2c_scl_dir ) if ( state->i2c_scl_dir )
{ {
v |= akiko.i2c_scl_out << 31; v |= state->i2c_scl_out << 31;
} }
else else
{ {
v |= 0 << 31; v |= 0 << 31;
} }
if ( akiko.i2c_sda_dir ) if ( state->i2c_sda_dir )
{ {
v |= akiko.i2c_sda_out << 30; v |= state->i2c_sda_out << 30;
} }
else else
{ {
v |= i2cmem_sda_read( akiko.i2cmem ) << 30; v |= i2cmem_sda_read( state->i2cmem ) << 30;
} }
v |= akiko.i2c_scl_dir << 15; v |= state->i2c_scl_dir << 15;
v |= akiko.i2c_sda_dir << 14; v |= state->i2c_sda_dir << 14;
return v; return v;
} }
@ -201,34 +218,35 @@ static UINT32 akiko_nvram_read(running_machine *machine)
* *
************************************/ ************************************/
static void akiko_c2p_write(UINT32 data) static void akiko_c2p_write(akiko_state *state, UINT32 data)
{ {
akiko.c2p_input_buffer[akiko.c2p_input_index] = data; state->c2p_input_buffer[state->c2p_input_index] = data;
akiko.c2p_input_index++; state->c2p_input_index++;
akiko.c2p_input_index &= 7; state->c2p_input_index &= 7;
akiko.c2p_output_index = 0; state->c2p_output_index = 0;
} }
static UINT32 akiko_c2p_read(void) static UINT32 akiko_c2p_read(akiko_state *state)
{ {
UINT32 val; UINT32 val;
if ( akiko.c2p_output_index == 0 ) if ( state->c2p_output_index == 0 )
{ {
int i; int i;
for ( i = 0; i < 8; i++ ) for ( i = 0; i < 8; i++ )
akiko.c2p_output_buffer[i] = 0; state->c2p_output_buffer[i] = 0;
for (i = 0; i < 8 * 32; i++) { for (i = 0; i < 8 * 32; i++)
if (akiko.c2p_input_buffer[7 - (i >> 5)] & (1 << (i & 31))) {
akiko.c2p_output_buffer[i & 7] |= 1 << (i >> 3); if (state->c2p_input_buffer[7 - (i >> 5)] & (1 << (i & 31)))
state->c2p_output_buffer[i & 7] |= 1 << (i >> 3);
} }
} }
akiko.c2p_input_index = 0; state->c2p_input_index = 0;
val = akiko.c2p_output_buffer[akiko.c2p_output_index]; val = state->c2p_output_buffer[state->c2p_output_index];
akiko.c2p_output_index++; state->c2p_output_index++;
akiko.c2p_output_index &= 7; state->c2p_output_index &= 7;
return val; return val;
} }
@ -269,30 +287,30 @@ static const char* get_akiko_reg_name(int reg)
* *
************************************/ ************************************/
static void akiko_cdda_stop( running_machine *machine ) static void akiko_cdda_stop(akiko_state *state)
{ {
running_device *cdda = cdda_from_cdrom(machine, akiko.cdrom); running_device *cdda = cdda_from_cdrom(state->machine, state->cdrom);
if (cdda != NULL) if (cdda != NULL)
{ {
cdda_stop_audio(cdda); cdda_stop_audio(cdda);
timer_reset( akiko.frame_timer, attotime_never ); timer_reset( state->frame_timer, attotime_never );
} }
} }
static void akiko_cdda_play( running_machine *machine, UINT32 lba, UINT32 num_blocks ) static void akiko_cdda_play(akiko_state *state, UINT32 lba, UINT32 num_blocks)
{ {
running_device *cdda = cdda_from_cdrom(machine, akiko.cdrom); running_device *cdda = cdda_from_cdrom(state->machine, state->cdrom);
if (cdda != NULL) if (cdda != NULL)
{ {
cdda_start_audio(cdda, lba, num_blocks); cdda_start_audio(cdda, lba, num_blocks);
timer_adjust_oneshot( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0 ); timer_adjust_oneshot( state->frame_timer, ATTOTIME_IN_HZ( 75 ), 0 );
} }
} }
static void akiko_cdda_pause( running_machine *machine, int pause ) static void akiko_cdda_pause(akiko_state *state, int pause)
{ {
running_device *cdda = cdda_from_cdrom(machine, akiko.cdrom); running_device *cdda = cdda_from_cdrom(state->machine, state->cdrom);
if (cdda != NULL) if (cdda != NULL)
{ {
if (cdda_audio_active(cdda) && cdda_audio_paused(cdda) != pause ) if (cdda_audio_active(cdda) && cdda_audio_paused(cdda) != pause )
@ -301,19 +319,19 @@ static void akiko_cdda_pause( running_machine *machine, int pause )
if ( pause ) if ( pause )
{ {
timer_reset( akiko.frame_timer, attotime_never ); timer_reset( state->frame_timer, attotime_never );
} }
else else
{ {
timer_adjust_oneshot( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0 ); timer_adjust_oneshot( state->frame_timer, ATTOTIME_IN_HZ( 75 ), 0 );
} }
} }
} }
} }
static UINT8 akiko_cdda_getstatus( running_machine *machine, UINT32 *lba ) static UINT8 akiko_cdda_getstatus(akiko_state *state, UINT32 *lba)
{ {
running_device *cdda = cdda_from_cdrom(machine, akiko.cdrom); running_device *cdda = cdda_from_cdrom(state->machine, state->cdrom);
if ( lba ) *lba = 0; if ( lba ) *lba = 0;
@ -341,33 +359,34 @@ static UINT8 akiko_cdda_getstatus( running_machine *machine, UINT32 *lba )
return 0x15; /* no audio status */ return 0x15; /* no audio status */
} }
static void akiko_set_cd_status( running_machine *machine, UINT32 status ) static void akiko_set_cd_status(akiko_state *state, UINT32 status)
{ {
akiko.cdrom_status[0] |= status; state->cdrom_status[0] |= status;
if ( akiko.cdrom_status[0] & akiko.cdrom_status[1] ) if ( state->cdrom_status[0] & state->cdrom_status[1] )
{ {
if (LOG_AKIKO_CD) logerror( "Akiko CD IRQ\n" ); if (LOG_AKIKO_CD) logerror( "Akiko CD IRQ\n" );
amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff); amiga_custom_w(state->space, REG_INTREQ, 0x8000 | INTENA_PORTS, 0xffff);
} }
} }
static TIMER_CALLBACK(akiko_frame_proc) static TIMER_CALLBACK(akiko_frame_proc)
{ {
running_device *cdda = cdda_from_cdrom(machine, akiko.cdrom); akiko_state *state = (akiko_state *)param;
running_device *cdda = cdda_from_cdrom(machine, state->cdrom);
(void)param; (void)param;
if (cdda != NULL) if (cdda != NULL)
{ {
UINT8 s = akiko_cdda_getstatus(machine, NULL); UINT8 s = akiko_cdda_getstatus(state, NULL);
if ( s == 0x11 ) if ( s == 0x11 )
{ {
akiko_set_cd_status( machine, 0x80000000 ); /* subcode ready */ akiko_set_cd_status(state, 0x80000000); /* subcode ready */
} }
timer_adjust_oneshot( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0 ); timer_adjust_oneshot( state->frame_timer, ATTOTIME_IN_HZ( 75 ), 0 );
} }
} }
@ -384,28 +403,30 @@ static UINT32 lba_from_triplet( UINT8 *triplet )
static TIMER_CALLBACK(akiko_dma_proc) static TIMER_CALLBACK(akiko_dma_proc)
{ {
akiko_state *state = (akiko_state *)ptr;
UINT8 buf[2352]; UINT8 buf[2352];
int index; int index;
if ( (akiko.cdrom_dmacontrol & 0x04000000) == 0 ) if ( (state->cdrom_dmacontrol & 0x04000000) == 0 )
return; return;
if ( akiko.cdrom_readreqmask == 0 ) if ( state->cdrom_readreqmask == 0 )
return; return;
index = (akiko.cdrom_lba_cur - akiko.cdrom_lba_start) & 0x0f; index = (state->cdrom_lba_cur - state->cdrom_lba_start) & 0x0f;
if ( akiko.cdrom_readreqmask & ( 1 << index ) ) if ( state->cdrom_readreqmask & ( 1 << index ) )
{ {
UINT32 track = cdrom_get_track( akiko.cdrom, akiko.cdrom_lba_cur ); amiga_state *amiga = machine->driver_data<amiga_state>();
UINT32 datasize = cdrom_get_toc( akiko.cdrom )->tracks[track].datasize; UINT32 track = cdrom_get_track( state->cdrom, state->cdrom_lba_cur );
UINT32 subsize = cdrom_get_toc( akiko.cdrom )->tracks[track].subsize; UINT32 datasize = cdrom_get_toc( state->cdrom )->tracks[track].datasize;
UINT32 subsize = cdrom_get_toc( state->cdrom )->tracks[track].subsize;
int i; int i;
UINT32 curmsf = lba_to_msf( akiko.cdrom_lba_cur ); UINT32 curmsf = lba_to_msf( state->cdrom_lba_cur );
memset( buf, 0, 16 ); memset( buf, 0, 16 );
buf[3] = akiko.cdrom_lba_cur - akiko.cdrom_lba_start; buf[3] = state->cdrom_lba_cur - state->cdrom_lba_start;
memset( &buf[4], 0xff, 8 ); memset( &buf[4], 0xff, 8 );
buf[12] = (curmsf >> 16) & 0xff; buf[12] = (curmsf >> 16) & 0xff;
@ -414,22 +435,22 @@ static TIMER_CALLBACK(akiko_dma_proc)
buf[15] = 0x01; /* mode1 */ buf[15] = 0x01; /* mode1 */
datasize = 2048; datasize = 2048;
if ( !cdrom_read_data( akiko.cdrom, akiko.cdrom_lba_cur, &buf[16], CD_TRACK_MODE1 ) ) if ( !cdrom_read_data( state->cdrom, state->cdrom_lba_cur, &buf[16], CD_TRACK_MODE1 ) )
{ {
logerror( "AKIKO: Read error trying to read sector %08x!\n", akiko.cdrom_lba_cur ); logerror( "AKIKO: Read error trying to read sector %08x!\n", state->cdrom_lba_cur );
return; return;
} }
if ( subsize ) if ( subsize )
{ {
if ( !cdrom_read_subcode( akiko.cdrom, akiko.cdrom_lba_cur, &buf[16+datasize] ) ) if ( !cdrom_read_subcode( state->cdrom, state->cdrom_lba_cur, &buf[16+datasize] ) )
{ {
logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", akiko.cdrom_lba_cur ); logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", state->cdrom_lba_cur );
return; return;
} }
} }
if (LOG_AKIKO_CD) logerror( "DMA: sector %d - address %08x\n", akiko.cdrom_lba_cur, akiko.cdrom_address[0] + (index*4096) ); if (LOG_AKIKO_CD) logerror( "DMA: sector %d - address %08x\n", state->cdrom_lba_cur, state->cdrom_address[0] + (index*4096) );
for( i = 0; i < 2352; i += 2 ) for( i = 0; i < 2352; i += 2 )
{ {
@ -439,39 +460,39 @@ static TIMER_CALLBACK(akiko_dma_proc)
data <<= 8; data <<= 8;
data |= buf[i+1]; data |= buf[i+1];
amiga_chip_ram_w( akiko.cdrom_address[0] + (index*4096) + i, data ); (*amiga->chip_ram_w)( amiga, state->cdrom_address[0] + (index*4096) + i, data );
} }
akiko.cdrom_readmask |= ( 1 << index ); state->cdrom_readmask |= ( 1 << index );
akiko.cdrom_readreqmask &= ~( 1 << index ); state->cdrom_readreqmask &= ~( 1 << index );
akiko.cdrom_lba_cur++; state->cdrom_lba_cur++;
} }
if ( akiko.cdrom_readreqmask == 0 ) if ( state->cdrom_readreqmask == 0 )
akiko_set_cd_status(machine, 0x04000000); akiko_set_cd_status(state, 0x04000000);
else else
timer_adjust_oneshot( akiko.dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / akiko.cdrom_speed ), 0 ); timer_adjust_oneshot( state->dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / state->cdrom_speed ), 0 );
} }
static void akiko_start_dma( void ) static void akiko_start_dma(akiko_state *state)
{ {
if ( akiko.cdrom_readreqmask == 0 ) if ( state->cdrom_readreqmask == 0 )
return; return;
if ( akiko.cdrom_lba_start > akiko.cdrom_lba_end ) if ( state->cdrom_lba_start > state->cdrom_lba_end )
return; return;
if ( akiko.cdrom_speed == 0 ) if ( state->cdrom_speed == 0 )
return; return;
akiko.cdrom_lba_cur = akiko.cdrom_lba_start; state->cdrom_lba_cur = state->cdrom_lba_start;
timer_adjust_oneshot( akiko.dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / akiko.cdrom_speed ), 0 ); timer_adjust_oneshot( state->dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / state->cdrom_speed ), 0 );
} }
static void akiko_setup_response( address_space *space, int len, UINT8 *r1 ) static void akiko_setup_response( akiko_state *state, int len, UINT8 *r1 )
{ {
int resp_addr = akiko.cdrom_address[1]; int resp_addr = state->cdrom_address[1];
UINT8 resp_csum = 0xff; UINT8 resp_csum = 0xff;
UINT8 resp_buffer[32]; UINT8 resp_buffer[32];
int i; int i;
@ -488,23 +509,24 @@ static void akiko_setup_response( address_space *space, int len, UINT8 *r1 )
for( i = 0; i < len; i++ ) for( i = 0; i < len; i++ )
{ {
space->write_byte( resp_addr + ((akiko.cdrom_cmd_resp + i) & 0xff), resp_buffer[i] ); state->space->write_byte( resp_addr + ((state->cdrom_cmd_resp + i) & 0xff), resp_buffer[i] );
} }
akiko.cdrom_cmd_resp = (akiko.cdrom_cmd_resp+len) & 0xff; state->cdrom_cmd_resp = (state->cdrom_cmd_resp+len) & 0xff;
akiko_set_cd_status( space->machine, 0x10000000 ); /* new data available */ akiko_set_cd_status(state, 0x10000000); /* new data available */
} }
static TIMER_CALLBACK( akiko_cd_delayed_cmd ) static TIMER_CALLBACK( akiko_cd_delayed_cmd )
{ {
akiko_state *state = (akiko_state *)ptr;
UINT8 resp[32]; UINT8 resp[32];
UINT8 cddastatus; UINT8 cddastatus;
if ( akiko.cdrom_status[0] & 0x10000000 ) if ( state->cdrom_status[0] & 0x10000000 )
return; return;
cddastatus = akiko_cdda_getstatus(machine, NULL); cddastatus = akiko_cdda_getstatus(state, NULL);
if ( cddastatus == 0x11 || cddastatus == 0x12 ) if ( cddastatus == 0x11 || cddastatus == 0x12 )
return; return;
@ -516,39 +538,38 @@ static TIMER_CALLBACK( akiko_cd_delayed_cmd )
if ( param == 0x05 ) if ( param == 0x05 )
{ {
address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param ); if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param );
resp[0] = 0x06; resp[0] = 0x06;
if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 ) if ( state->cdrom == NULL || state->cdrom_numtracks == 0 )
{ {
resp[1] = 0x80; resp[1] = 0x80;
akiko_setup_response( space, 15, resp ); akiko_setup_response( state, 15, resp );
} }
else else
{ {
resp[1] = 0x00; resp[1] = 0x00;
memcpy( &resp[2], &akiko.cdrom_toc[13*akiko.cdrom_track_index], 13 ); memcpy( &resp[2], &state->cdrom_toc[13*state->cdrom_track_index], 13 );
akiko.cdrom_track_index = ( akiko.cdrom_track_index + 1 ) % akiko.cdrom_numtracks; state->cdrom_track_index = ( state->cdrom_track_index + 1 ) % state->cdrom_numtracks;
akiko_setup_response( space, 15, resp ); akiko_setup_response( state, 15, resp );
} }
} }
} }
static void akiko_update_cdrom(address_space *space) static void akiko_update_cdrom(akiko_state *state)
{ {
UINT8 resp[32], cmdbuf[32]; UINT8 resp[32], cmdbuf[32];
if ( akiko.cdrom_status[0] & 0x10000000 ) if ( state->cdrom_status[0] & 0x10000000 )
return; return;
while ( akiko.cdrom_cmd_start != akiko.cdrom_cmd_end ) while ( state->cdrom_cmd_start != state->cdrom_cmd_end )
{ {
UINT32 cmd_addr = akiko.cdrom_address[1] + 0x200 + akiko.cdrom_cmd_start; UINT32 cmd_addr = state->cdrom_address[1] + 0x200 + state->cdrom_cmd_start;
int cmd = space->read_byte( cmd_addr ); int cmd = state->space->read_byte( cmd_addr );
memset( resp, 0, sizeof( resp ) ); memset( resp, 0, sizeof( resp ) );
resp[0] = cmd; resp[0] = cmd;
@ -561,27 +582,27 @@ static void akiko_update_cdrom(address_space *space)
{ {
resp[1] = 0x00; resp[1] = 0x00;
if ( akiko_cdda_getstatus(space->machine, NULL) == 0x11 ) if ( akiko_cdda_getstatus(state, NULL) == 0x11 )
resp[1] = 0x08; resp[1] = 0x08;
akiko_cdda_pause( space->machine, 1 ); akiko_cdda_pause(state, 1);
akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff; state->cdrom_cmd_start = (state->cdrom_cmd_start+2) & 0xff;
akiko_setup_response( space, 2, resp ); akiko_setup_response( state, 2, resp );
} }
else if ( cmd == 0x03 ) /* unpause audio (and check audiocd playing status) */ else if ( cmd == 0x03 ) /* unpause audio (and check audiocd playing status) */
{ {
resp[1] = 0x00; resp[1] = 0x00;
if ( akiko_cdda_getstatus(space->machine, NULL) == 0x11 ) if ( akiko_cdda_getstatus(state, NULL) == 0x11 )
resp[1] = 0x08; resp[1] = 0x08;
akiko_cdda_pause( space->machine, 0 ); akiko_cdda_pause(state, 0);
akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff; state->cdrom_cmd_start = (state->cdrom_cmd_start+2) & 0xff;
akiko_setup_response( space, 2, resp ); akiko_setup_response( state, 2, resp );
} }
else if ( cmd == 0x04 ) /* seek/read/play cd multi command */ else if ( cmd == 0x04 ) /* seek/read/play cd multi command */
{ {
@ -590,67 +611,67 @@ static void akiko_update_cdrom(address_space *space)
for( i = 0; i < 13; i++ ) for( i = 0; i < 13; i++ )
{ {
cmdbuf[i] = space->read_byte( cmd_addr ); cmdbuf[i] = state->space->read_byte( cmd_addr );
cmd_addr &= 0xffffff00; cmd_addr &= 0xffffff00;
cmd_addr += ( akiko.cdrom_cmd_start + i + 1 ) & 0xff; cmd_addr += ( state->cdrom_cmd_start + i + 1 ) & 0xff;
} }
akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+13) & 0xff; state->cdrom_cmd_start = (state->cdrom_cmd_start+13) & 0xff;
if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 ) if ( state->cdrom == NULL || state->cdrom_numtracks == 0 )
{ {
resp[1] = 0x80; resp[1] = 0x80;
akiko_setup_response( space, 2, resp ); akiko_setup_response( state, 2, resp );
} }
else else
{ {
startpos = lba_from_triplet( &cmdbuf[1] ); startpos = lba_from_triplet( &cmdbuf[1] );
endpos = lba_from_triplet( &cmdbuf[4] ); endpos = lba_from_triplet( &cmdbuf[4] );
akiko_cdda_stop(space->machine); akiko_cdda_stop(state);
resp[1] = 0x00; resp[1] = 0x00;
if ( cmdbuf[7] == 0x80 ) if ( cmdbuf[7] == 0x80 )
{ {
if (LOG_AKIKO_CD) logerror( "%s:AKIKO CD: Data read - start lba: %08x - end lba: %08x\n", cpuexec_describe_context(space->machine), startpos, endpos ); if (LOG_AKIKO_CD) logerror( "%s:AKIKO CD: Data read - start lba: %08x - end lba: %08x\n", cpuexec_describe_context(state->machine), startpos, endpos );
akiko.cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1; state->cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
akiko.cdrom_lba_start = startpos; state->cdrom_lba_start = startpos;
akiko.cdrom_lba_end = endpos; state->cdrom_lba_end = endpos;
resp[1] = 0x02; resp[1] = 0x02;
} }
else if ( cmdbuf[10] & 0x04 ) else if ( cmdbuf[10] & 0x04 )
{ {
logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos ); logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
akiko_cdda_play( space->machine, startpos, endpos - startpos ); akiko_cdda_play(state, startpos, endpos - startpos);
resp[1] = 0x08; resp[1] = 0x08;
} }
else else
{ {
if (LOG_AKIKO_CD) logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos ); if (LOG_AKIKO_CD) logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
akiko.cdrom_track_index = 0; state->cdrom_track_index = 0;
for( i = 0; i < cdrom_get_last_track(akiko.cdrom); i++ ) for( i = 0; i < cdrom_get_last_track(state->cdrom); i++ )
{ {
if ( startpos <= cdrom_get_track_start( akiko.cdrom, i ) ) if ( startpos <= cdrom_get_track_start( state->cdrom, i ) )
{ {
/* reset to 0 */ /* reset to 0 */
akiko.cdrom_track_index = i + 2; state->cdrom_track_index = i + 2;
akiko.cdrom_track_index %= akiko.cdrom_numtracks; state->cdrom_track_index %= state->cdrom_numtracks;
break; break;
} }
} }
} }
akiko_setup_response( space, 2, resp ); akiko_setup_response( state, 2, resp );
} }
} }
else if ( cmd == 0x05 ) /* read toc */ else if ( cmd == 0x05 ) /* read toc */
{ {
akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+3) & 0xff; state->cdrom_cmd_start = (state->cdrom_cmd_start+3) & 0xff;
timer_set( space->machine, ATTOTIME_IN_MSEC(1), NULL, resp[0], akiko_cd_delayed_cmd ); timer_set( state->machine, ATTOTIME_IN_MSEC(1), state, resp[0], akiko_cd_delayed_cmd );
break; break;
} }
@ -660,7 +681,7 @@ static void akiko_update_cdrom(address_space *space)
resp[1] = 0x00; resp[1] = 0x00;
(void)akiko_cdda_getstatus( space->machine, &lba ); (void)akiko_cdda_getstatus(state, &lba);
if ( lba > 0 ) if ( lba > 0 )
{ {
@ -669,8 +690,8 @@ static void akiko_update_cdrom(address_space *space)
UINT32 track; UINT32 track;
int addrctrl; int addrctrl;
track = cdrom_get_track(akiko.cdrom, lba); track = cdrom_get_track(state->cdrom, lba);
addrctrl = cdrom_get_adr_control(akiko.cdrom, track); addrctrl = cdrom_get_adr_control(state->cdrom, track);
resp[2] = 0x00; resp[2] = 0x00;
resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
@ -678,7 +699,7 @@ static void akiko_update_cdrom(address_space *space)
resp[5] = 0; /* index */ resp[5] = 0; /* index */
disk_pos = lba_to_msf(lba); disk_pos = lba_to_msf(lba);
track_pos = lba_to_msf(lba - cdrom_get_track_start(akiko.cdrom, track)); track_pos = lba_to_msf(lba - cdrom_get_track_start(state->cdrom, track));
/* track position */ /* track position */
resp[6] = (track_pos >> 16) & 0xff; resp[6] = (track_pos >> 16) & 0xff;
@ -696,18 +717,18 @@ static void akiko_update_cdrom(address_space *space)
resp[1] = 0x80; resp[1] = 0x80;
} }
akiko_setup_response( space, 15, resp ); akiko_setup_response( state, 15, resp );
} }
else if ( cmd == 0x07 ) /* check door status */ else if ( cmd == 0x07 ) /* check door status */
{ {
resp[1] = 0x01; resp[1] = 0x01;
akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff; state->cdrom_cmd_start = (state->cdrom_cmd_start+2) & 0xff;
if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 ) if ( state->cdrom == NULL || state->cdrom_numtracks == 0 )
resp[1] = 0x80; resp[1] = 0x80;
akiko_setup_response( space, 20, resp ); akiko_setup_response( state, 20, resp );
break; break;
} }
else else
@ -717,8 +738,10 @@ static void akiko_update_cdrom(address_space *space)
} }
} }
READ32_HANDLER(amiga_akiko32_r) READ32_DEVICE_HANDLER( amiga_akiko32_r )
{ {
akiko_state *state = get_safe_token(device);
address_space *space = state->space;
UINT32 retval; UINT32 retval;
if ( LOG_AKIKO && offset < (0x30/4) ) if ( LOG_AKIKO && offset < (0x30/4) )
@ -729,48 +752,48 @@ READ32_HANDLER(amiga_akiko32_r)
switch( offset ) switch( offset )
{ {
case 0x00/4: /* ID */ case 0x00/4: /* ID */
if ( akiko.cdrom != NULL ) cdda_set_cdrom(space->machine->device("cdda"), akiko.cdrom); if ( state->cdrom != NULL ) cdda_set_cdrom(space->machine->device("cdda"), state->cdrom);
return 0x0000cafe; return 0x0000cafe;
case 0x04/4: /* CDROM STATUS 1 */ case 0x04/4: /* CDROM STATUS 1 */
return akiko.cdrom_status[0]; return state->cdrom_status[0];
case 0x08/4: /* CDROM STATUS 2 */ case 0x08/4: /* CDROM STATUS 2 */
return akiko.cdrom_status[1]; return state->cdrom_status[1];
case 0x10/4: /* CDROM ADDRESS 1 */ case 0x10/4: /* CDROM ADDRESS 1 */
return akiko.cdrom_address[0]; return state->cdrom_address[0];
case 0x14/4: /* CDROM ADDRESS 2 */ case 0x14/4: /* CDROM ADDRESS 2 */
return akiko.cdrom_address[1]; return state->cdrom_address[1];
case 0x18/4: /* CDROM COMMAND 1 */ case 0x18/4: /* CDROM COMMAND 1 */
akiko_update_cdrom(space); akiko_update_cdrom(state);
retval = akiko.cdrom_cmd_start; retval = state->cdrom_cmd_start;
retval <<= 8; retval <<= 8;
retval |= akiko.cdrom_cmd_resp; retval |= state->cdrom_cmd_resp;
retval <<= 8; retval <<= 8;
return retval; return retval;
case 0x1C/4: /* CDROM COMMAND 2 */ case 0x1C/4: /* CDROM COMMAND 2 */
akiko_update_cdrom(space); akiko_update_cdrom(state);
retval = akiko.cdrom_cmd_end; retval = state->cdrom_cmd_end;
retval <<= 16; retval <<= 16;
return retval; return retval;
case 0x20/4: /* CDROM DMA SECTOR READ MASK */ case 0x20/4: /* CDROM DMA SECTOR READ MASK */
retval = akiko.cdrom_readmask << 16; retval = state->cdrom_readmask << 16;
return retval; return retval;
case 0x24/4: /* CDROM DMA ENABLE? */ case 0x24/4: /* CDROM DMA ENABLE? */
retval = akiko.cdrom_dmacontrol; retval = state->cdrom_dmacontrol;
return retval; return retval;
case 0x30/4: /* NVRAM */ case 0x30/4: /* NVRAM */
return akiko_nvram_read(space->machine); return akiko_nvram_read(state);
case 0x38/4: /* C2P */ case 0x38/4: /* C2P */
return akiko_c2p_read(); return akiko_c2p_read(state);
default: default:
break; break;
@ -779,8 +802,11 @@ READ32_HANDLER(amiga_akiko32_r)
return 0; return 0;
} }
WRITE32_HANDLER(amiga_akiko32_w) WRITE32_DEVICE_HANDLER( amiga_akiko32_w )
{ {
akiko_state *state = get_safe_token(device);
address_space *space = state->space;
if ( LOG_AKIKO && offset < (0x30/4) ) if ( LOG_AKIKO && offset < (0x30/4) )
{ {
logerror( "Writing AKIKO reg %0x [%s] with %08x at PC=%06x\n", offset, get_akiko_reg_name(offset), data, cpu_get_pc(space->cpu) ); logerror( "Writing AKIKO reg %0x [%s] with %08x at PC=%06x\n", offset, get_akiko_reg_name(offset), data, cpu_get_pc(space->cpu) );
@ -789,67 +815,82 @@ WRITE32_HANDLER(amiga_akiko32_w)
switch( offset ) switch( offset )
{ {
case 0x04/4: /* CDROM STATUS 1 */ case 0x04/4: /* CDROM STATUS 1 */
akiko.cdrom_status[0] = data; state->cdrom_status[0] = data;
break; break;
case 0x08/4: /* CDROM STATUS 2 */ case 0x08/4: /* CDROM STATUS 2 */
akiko.cdrom_status[1] = data; state->cdrom_status[1] = data;
akiko.cdrom_status[0] &= data; state->cdrom_status[0] &= data;
break; break;
case 0x10/4: /* CDROM ADDRESS 1 */ case 0x10/4: /* CDROM ADDRESS 1 */
akiko.cdrom_address[0] = data; state->cdrom_address[0] = data;
break; break;
case 0x14/4: /* CDROM ADDRESS 2 */ case 0x14/4: /* CDROM ADDRESS 2 */
akiko.cdrom_address[1] = data; state->cdrom_address[1] = data;
break; break;
case 0x18/4: /* CDROM COMMAND 1 */ case 0x18/4: /* CDROM COMMAND 1 */
if ( ACCESSING_BITS_16_23 ) if ( ACCESSING_BITS_16_23 )
akiko.cdrom_cmd_start = ( data >> 16 ) & 0xff; state->cdrom_cmd_start = ( data >> 16 ) & 0xff;
if ( ACCESSING_BITS_8_15 ) if ( ACCESSING_BITS_8_15 )
akiko.cdrom_cmd_resp = ( data >> 8 ) & 0xff; state->cdrom_cmd_resp = ( data >> 8 ) & 0xff;
akiko_update_cdrom(space); akiko_update_cdrom(state);
break; break;
case 0x1C/4: /* CDROM COMMAND 2 */ case 0x1C/4: /* CDROM COMMAND 2 */
if ( ACCESSING_BITS_16_23 ) if ( ACCESSING_BITS_16_23 )
akiko.cdrom_cmd_end = ( data >> 16 ) & 0xff; state->cdrom_cmd_end = ( data >> 16 ) & 0xff;
akiko_update_cdrom(space); akiko_update_cdrom(state);
break; break;
case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */ case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */
if (LOG_AKIKO_CD) logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask ); if (LOG_AKIKO_CD) logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ACCESSING_BITS_16_31 ) if ( ACCESSING_BITS_16_31 )
{ {
akiko.cdrom_readreqmask = (data >> 16); state->cdrom_readreqmask = (data >> 16);
akiko.cdrom_readmask = 0; state->cdrom_readmask = 0;
} }
break; break;
case 0x24/4: /* CDROM DMA ENABLE? */ case 0x24/4: /* CDROM DMA ENABLE? */
if (LOG_AKIKO_CD) logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask ); if (LOG_AKIKO_CD) logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ( akiko.cdrom_dmacontrol ^ data ) & 0x04000000 ) if ( ( state->cdrom_dmacontrol ^ data ) & 0x04000000 )
{ {
if ( data & 0x04000000 ) if ( data & 0x04000000 )
akiko_start_dma(); akiko_start_dma(state);
} }
akiko.cdrom_dmacontrol = data; state->cdrom_dmacontrol = data;
break; break;
case 0x30/4: case 0x30/4:
akiko_nvram_write(space->machine, data); akiko_nvram_write(state, data);
break; break;
case 0x38/4: case 0x38/4:
akiko_c2p_write(data); akiko_c2p_write(state, data);
break; break;
default: default:
break; break;
} }
} }
/*-------------------------------------------------
device definition
-------------------------------------------------*/
static const char DEVTEMPLATE_SOURCE[] = __FILE__;
#define DEVTEMPLATE_ID(p,s) p##akiko##s
#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_STOP
#define DEVTEMPLATE_NAME "Akiko"
#define DEVTEMPLATE_FAMILY "Amiga"
#include "devtempl.h"
DEFINE_LEGACY_DEVICE(AKIKO, akiko);

View File

@ -11,18 +11,6 @@
/*************************************
*
* Debugging
*
*************************************/
#define LOG_COPPER 0
#define GUESS_COPPER_OFFSET 0
#define LOG_SPRITE_DMA 0
/************************************* /*************************************
* *
* Macros * Macros
@ -33,41 +21,6 @@
/*************************************
*
* Statics
*
*************************************/
/* sprite states */
static UINT8 sprite_comparitor_enable_mask;
static UINT8 sprite_dma_reload_mask;
static UINT8 sprite_dma_live_mask;
static UINT32 sprite_shiftreg[8];
static UINT8 sprite_remain[8];
/* playfield states */
static int last_scanline;
static UINT16 ham_color;
/* copper states */
static UINT32 copper_pc;
static UINT8 copper_waiting;
static UINT8 copper_waitblit;
static UINT16 copper_waitval;
static UINT16 copper_waitmask;
static UINT16 copper_pending_offset;
static UINT16 copper_pending_data;
/* misc states */
static UINT16 genlock_color;
#if GUESS_COPPER_OFFSET
static int wait_offset = 3;
#endif
/************************************* /*************************************
* *
* Tables * Tables
@ -75,7 +28,7 @@ static int wait_offset = 3;
*************************************/ *************************************/
/* expand an 8-bit bit pattern into 16 bits, every other bit */ /* expand an 8-bit bit pattern into 16 bits, every other bit */
static const UINT16 expand_byte[256] = const UINT16 amiga_expand_byte[256] =
{ {
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
@ -112,9 +65,6 @@ static const UINT16 expand_byte[256] =
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
}; };
/* separate 6 in-order bitplanes into 2 x 3-bit bitplanes in two nibbles */
static UINT8 separate_bitplanes[2][64];
/************************************* /*************************************
@ -141,6 +91,7 @@ PALETTE_INIT( amiga )
VIDEO_START( amiga ) VIDEO_START( amiga )
{ {
amiga_state *state = machine->driver_data<amiga_state>();
int j; int j;
/* generate tables that produce the correct playfield color for dual playfield mode */ /* generate tables that produce the correct playfield color for dual playfield mode */
@ -149,12 +100,18 @@ VIDEO_START( amiga )
int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4); int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4);
int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4); int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4);
separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8); state->separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix; state->separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
} }
#if GUESS_COPPER_OFFSET
state->wait_offset = 3;
#endif
/* reset the genlock color */ /* reset the genlock color */
genlock_color = 0xffff; state->genlock_color = 0xffff;
state->sprite_ctl_written = 0;
} }
@ -167,12 +124,13 @@ VIDEO_START( amiga )
UINT32 amiga_gethvpos(screen_device &screen) UINT32 amiga_gethvpos(screen_device &screen)
{ {
UINT32 hvpos = (last_scanline << 8) | (screen.hpos() >> 2); amiga_state *state = screen.machine->driver_data<amiga_state>();
UINT32 hvpos = (state->last_scanline << 8) | (screen.hpos() >> 2);
UINT32 latchedpos = input_port_read_safe(screen.machine, "HVPOS", 0); UINT32 latchedpos = input_port_read_safe(screen.machine, "HVPOS", 0);
/* if there's no latched position, or if we are in the active display area */ /* if there's no latched position, or if we are in the active display area */
/* but before the latching point, return the live HV position */ /* but before the latching point, return the live HV position */
if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (last_scanline >= 20 && hvpos < latchedpos)) if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (state->last_scanline >= 20 && hvpos < latchedpos))
return hvpos; return hvpos;
/* otherwise, return the latched position */ /* otherwise, return the latched position */
@ -187,9 +145,11 @@ UINT32 amiga_gethvpos(screen_device &screen)
* *
*************************************/ *************************************/
void amiga_set_genlock_color(UINT16 color) void amiga_set_genlock_color(running_machine *machine, UINT16 color)
{ {
genlock_color = color; amiga_state *state = machine->driver_data<amiga_state>();
state->genlock_color = color;
} }
@ -200,18 +160,21 @@ void amiga_set_genlock_color(UINT16 color)
* *
*************************************/ *************************************/
void copper_setpc(UINT32 pc) void amiga_copper_setpc(running_machine *machine, UINT32 pc)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
if (LOG_COPPER) if (LOG_COPPER)
logerror("copper_setpc(%06x)\n", pc); logerror("copper_setpc(%06x)\n", pc);
copper_pc = pc; state->copper_pc = pc;
copper_waiting = FALSE; state->copper_waiting = FALSE;
} }
static int copper_execute_next(running_machine *machine, int xpos) int amiga_copper_execute_next(running_machine *machine, int xpos)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
int word0, word1; int word0, word1;
/* bail if not enabled */ /* bail if not enabled */
@ -219,34 +182,34 @@ static int copper_execute_next(running_machine *machine, int xpos)
return 511; return 511;
/* flush any pending writes */ /* flush any pending writes */
if (copper_pending_offset) if (state->copper_pending_offset)
{ {
if (LOG_COPPER) if (LOG_COPPER)
logerror("%02X.%02X: Write to %s = %04x\n", last_scanline, xpos / 2, amiga_custom_names[copper_pending_offset & 0xff], copper_pending_data); logerror("%02X.%02X: Write to %s = %04x\n", state->last_scanline, xpos / 2, amiga_custom_names[state->copper_pending_offset & 0xff], state->copper_pending_data);
amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), copper_pending_offset, copper_pending_data, 0xffff); amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), state->copper_pending_offset, state->copper_pending_data, 0xffff);
copper_pending_offset = 0; state->copper_pending_offset = 0;
} }
/* if we're waiting, check for a breakthrough */ /* if we're waiting, check for a breakthrough */
if (copper_waiting) if (state->copper_waiting)
{ {
int curpos = (last_scanline << 8) | (xpos >> 1); int curpos = (state->last_scanline << 8) | (xpos >> 1);
/* if we're past the wait time, stop it and hold up 2 cycles */ /* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) && if ((curpos & state->copper_waitmask) >= (state->copper_waitval & state->copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY))) (!state->copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{ {
copper_waiting = FALSE; state->copper_waiting = FALSE;
#if GUESS_COPPER_OFFSET #if GUESS_COPPER_OFFSET
return xpos + COPPER_CYCLES_TO_PIXELS(1 + wait_offset); return xpos + COPPER_CYCLES_TO_PIXELS(1 + state->wait_offset);
#else #else
return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3); return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3);
#endif #endif
} }
/* otherwise, see if this line is even a possibility; if not, punt */ /* otherwise, see if this line is even a possibility; if not, punt */
if (((curpos | 0xff) & copper_waitmask) < (copper_waitval & copper_waitmask)) if (((curpos | 0xff) & state->copper_waitmask) < (state->copper_waitval & state->copper_waitmask))
return 511; return 511;
/* else just advance another pixel */ /* else just advance another pixel */
@ -255,17 +218,17 @@ static int copper_execute_next(running_machine *machine, int xpos)
} }
/* fetch the first data word */ /* fetch the first data word */
word0 = amiga_chip_ram_r(copper_pc); word0 = (*state->chip_ram_r)(state, state->copper_pc);
copper_pc += 2; state->copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1); xpos += COPPER_CYCLES_TO_PIXELS(1);
/* fetch the second data word */ /* fetch the second data word */
word1 = amiga_chip_ram_r(copper_pc); word1 = (*state->chip_ram_r)(state, state->copper_pc);
copper_pc += 2; state->copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1); xpos += COPPER_CYCLES_TO_PIXELS(1);
if (LOG_COPPER) if (LOG_COPPER)
logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", last_scanline, xpos / 2, copper_pc, word0, word1); logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", state->last_scanline, xpos / 2, state->copper_pc, word0, word1);
/* handle a move */ /* handle a move */
if ((word0 & 1) == 0) if ((word0 & 1) == 0)
@ -278,56 +241,56 @@ static int copper_execute_next(running_machine *machine, int xpos)
{ {
/* write it at the *end* of this instruction's cycles */ /* write it at the *end* of this instruction's cycles */
/* needed for Arcadia's Fast Break */ /* needed for Arcadia's Fast Break */
copper_pending_offset = word0; state->copper_pending_offset = word0;
copper_pending_data = word1; state->copper_pending_data = word1;
} }
/* illegal writes suspend until next frame */ /* illegal writes suspend until next frame */
else else
{ {
if (LOG_COPPER) if (LOG_COPPER)
logerror("%02X.%02X: Aborting copper on illegal write\n", last_scanline, xpos / 2); logerror("%02X.%02X: Aborting copper on illegal write\n", state->last_scanline, xpos / 2);
copper_waitval = 0xffff; state->copper_waitval = 0xffff;
copper_waitmask = 0xffff; state->copper_waitmask = 0xffff;
copper_waitblit = FALSE; state->copper_waitblit = FALSE;
copper_waiting = TRUE; state->copper_waiting = TRUE;
return 511; return 511;
} }
} }
else else
{ {
/* extract common wait/skip values */ /* extract common wait/skip values */
copper_waitval = word0 & 0xfffe; state->copper_waitval = word0 & 0xfffe;
copper_waitmask = word1 | 0x8001; state->copper_waitmask = word1 | 0x8001;
copper_waitblit = (~word1 >> 15) & 1; state->copper_waitblit = (~word1 >> 15) & 1;
/* handle a wait */ /* handle a wait */
if ((word1 & 1) == 0) if ((word1 & 1) == 0)
{ {
if (LOG_COPPER) if (LOG_COPPER)
logerror(" Waiting for %04x & %04x (currently %04x)\n", copper_waitval, copper_waitmask, (last_scanline << 8) | (xpos >> 1)); logerror(" Waiting for %04x & %04x (currently %04x)\n", state->copper_waitval, state->copper_waitmask, (state->last_scanline << 8) | (xpos >> 1));
copper_waiting = TRUE; state->copper_waiting = TRUE;
} }
/* handle a skip */ /* handle a skip */
else else
{ {
int curpos = (last_scanline << 8) | (xpos >> 1); int curpos = (state->last_scanline << 8) | (xpos >> 1);
if (LOG_COPPER) if (LOG_COPPER)
logerror(" Skipping if %04x & %04x (currently %04x)\n", copper_waitval, copper_waitmask, (last_scanline << 8) | (xpos >> 1)); logerror(" Skipping if %04x & %04x (currently %04x)\n", state->copper_waitval, state->copper_waitmask, (state->last_scanline << 8) | (xpos >> 1));
/* if we're past the wait time, stop it and hold up 2 cycles */ /* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) && if ((curpos & state->copper_waitmask) >= (state->copper_waitval & state->copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY))) (!state->copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{ {
if (LOG_COPPER) if (LOG_COPPER)
logerror(" Skipped\n"); logerror(" Skipped\n");
/* count the cycles it out have taken to fetch the next instruction */ /* count the cycles it out have taken to fetch the next instruction */
copper_pc += 4; state->copper_pc += 4;
xpos += COPPER_CYCLES_TO_PIXELS(2); xpos += COPPER_CYCLES_TO_PIXELS(2);
} }
} }
@ -345,22 +308,31 @@ static int copper_execute_next(running_machine *machine, int xpos)
* *
*************************************/ *************************************/
void amiga_sprite_dma_reset(int which) void amiga_sprite_dma_reset(running_machine *machine, int which)
{ {
sprite_dma_reload_mask |= 1 << which; amiga_state *state = machine->driver_data<amiga_state>();
sprite_dma_live_mask |= 1 << which;
if (LOG_SPRITE_DMA) logerror("sprite %d dma reset\n", which );
state->sprite_dma_reload_mask |= 1 << which;
state->sprite_dma_live_mask |= 1 << which;
} }
void amiga_sprite_enable_comparitor(int which, int enable) void amiga_sprite_enable_comparitor(running_machine *machine, int which, int enable)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
if (LOG_SPRITE_DMA) logerror("sprite %d comparitor %sable\n", which, enable ? "en" : "dis" );
if (enable) if (enable)
{ {
sprite_comparitor_enable_mask |= 1 << which; state->sprite_comparitor_enable_mask |= 1 << which;
sprite_dma_live_mask &= ~(1 << which); state->sprite_dma_live_mask &= ~(1 << which);
} }
else else
sprite_comparitor_enable_mask &= ~(1 << which); {
state->sprite_comparitor_enable_mask &= ~(1 << which);
state->sprite_ctl_written |= (1 << which);
}
} }
@ -371,7 +343,15 @@ void amiga_sprite_enable_comparitor(int which, int enable)
* *
*************************************/ *************************************/
static void update_sprite_dma(int scanline) INLINE void fetch_sprite_data(amiga_state *state, int scanline, int sprite)
{
CUSTOM_REG(REG_SPR0DATA + 4 * sprite) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
CUSTOM_REG(REG_SPR0DATB + 4 * sprite) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X\n", scanline, sprite, CUSTOM_REG(REG_SPR0DATA + 4 * sprite), CUSTOM_REG(REG_SPR0DATB + 4 * sprite));
}
static void update_sprite_dma(amiga_state *state, int scanline)
{ {
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN); int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
int num, maxdma; int num, maxdma;
@ -388,15 +368,15 @@ static void update_sprite_dma(int scanline)
int vstart, vstop; int vstart, vstop;
/* if we are == VSTOP, fetch new control words */ /* if we are == VSTOP, fetch new control words */
if (dmaenable && (sprite_dma_live_mask & bitmask) && (sprite_dma_reload_mask & bitmask)) if (dmaenable && (state->sprite_dma_live_mask & bitmask) && (state->sprite_dma_reload_mask & bitmask))
{ {
/* disable the sprite */ /* disable the sprite */
sprite_comparitor_enable_mask &= ~bitmask; state->sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask &= ~bitmask; state->sprite_dma_reload_mask &= ~bitmask;
/* fetch data into the control words */ /* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0); CUSTOM_REG(REG_SPR0POS + 4 * num) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
CUSTOM_REG(REG_SPR0CTL + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2); CUSTOM_REG(REG_SPR0CTL + 4 * num) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num)); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
} }
@ -408,27 +388,25 @@ static void update_sprite_dma(int scanline)
/* if we hit vstart, enable the comparitor */ /* if we hit vstart, enable the comparitor */
if (scanline == vstart) if (scanline == vstart)
{ {
sprite_comparitor_enable_mask |= 1 << num; state->sprite_comparitor_enable_mask |= 1 << num;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor enable\n", scanline, num); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor enable\n", scanline, num);
} }
/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */ /* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop) if (scanline == vstop)
{ {
sprite_comparitor_enable_mask &= ~bitmask; state->sprite_ctl_written &= ~bitmask;
sprite_dma_reload_mask |= 1 << num; state->sprite_comparitor_enable_mask &= ~bitmask;
state->sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */ CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0; CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
} }
/* fetch data if this sprite is enabled */ /* fetch data if this sprite is enabled */
if (dmaenable && (sprite_dma_live_mask & bitmask) && (sprite_comparitor_enable_mask & bitmask)) if (dmaenable && (state->sprite_dma_live_mask & bitmask) && (state->sprite_comparitor_enable_mask & bitmask))
{ {
CUSTOM_REG(REG_SPR0DATA + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0); fetch_sprite_data(state, scanline, num);
CUSTOM_REG(REG_SPR0DATB + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X\n", scanline, num, CUSTOM_REG(REG_SPR0DATA + 4 * num), CUSTOM_REG(REG_SPR0DATB + 4 * num));
} }
} }
} }
@ -443,37 +421,37 @@ static void update_sprite_dma(int scanline)
INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits) INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits)
{ {
return (expand_byte[lobits & 0xff] << 0) | (expand_byte[lobits >> 8] << 16) | return (amiga_expand_byte[lobits & 0xff] << 0) | (amiga_expand_byte[lobits >> 8] << 16) |
(expand_byte[hibits & 0xff] << 1) | (expand_byte[hibits >> 8] << 17); (amiga_expand_byte[hibits & 0xff] << 1) | (amiga_expand_byte[hibits >> 8] << 17);
} }
static int get_sprite_pixel(int x) static int get_sprite_pixel(amiga_state *state, int x)
{ {
int pixels = 0; int pixels = 0;
int num, pair; int num, pair;
/* loop over sprite channels */ /* loop over sprite channels */
for (num = 0; num < 8; num++) for (num = 0; num < 8; num++)
if (sprite_comparitor_enable_mask & (1 << num)) if (state->sprite_comparitor_enable_mask & (1 << num))
{ {
/* if we're not currently clocking, check against hstart */ /* if we're not currently clocking, check against hstart */
if (sprite_remain[num] == 0) if (state->sprite_remain[num] == 0)
{ {
int hstart = ((CUSTOM_REG(REG_SPR0POS + 4 * num) & 0xff) << 1) | (CUSTOM_REG(REG_SPR0CTL + 4 * num) & 1); int hstart = ((CUSTOM_REG(REG_SPR0POS + 4 * num) & 0xff) << 1) | (CUSTOM_REG(REG_SPR0CTL + 4 * num) & 1);
if (hstart == x) if (hstart == x)
{ {
sprite_remain[num] = 16; state->sprite_remain[num] = 16;
sprite_shiftreg[num] = interleave_sprite_data(CUSTOM_REG(REG_SPR0DATA + 4 * num), CUSTOM_REG(REG_SPR0DATB + 4 * num)); state->sprite_shiftreg[num] = interleave_sprite_data(CUSTOM_REG(REG_SPR0DATA + 4 * num), CUSTOM_REG(REG_SPR0DATB + 4 * num));
} }
} }
/* clock the next pixel if we're doing it */ /* clock the next pixel if we're doing it */
if (sprite_remain[num] != 0) if (state->sprite_remain[num] != 0)
{ {
sprite_remain[num]--; state->sprite_remain[num]--;
pixels |= (sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num)); pixels |= (state->sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
sprite_shiftreg[num] <<= 2; state->sprite_shiftreg[num] <<= 2;
} }
} }
@ -491,6 +469,7 @@ static int get_sprite_pixel(int x)
0x0000, 0x0800, 0x2000, 0x2a00, 0x4000, 0x4c00, 0x7000, 0x7e00 0x0000, 0x0800, 0x2000, 0x2a00, 0x4000, 0x4c00, 0x7000, 0x7e00
}; };
int collide; int collide;
const int esprm = 0x10, osprm = 0x10;
/* OR the two sprite bits together so we only have 1 bit per sprite */ /* OR the two sprite bits together so we only have 1 bit per sprite */
collide = pixels | (pixels >> 1); collide = pixels | (pixels >> 1);
@ -513,18 +492,19 @@ static int get_sprite_pixel(int x)
sprite present bitmask in bits 6-9 sprite present bitmask in bits 6-9
topmost sprite pair index in bits 10-11 topmost sprite pair index in bits 10-11
*/ */
UINT32 result = (collide << 6) | (pair << 10);
/* attached case */ /* attached case */
if (CUSTOM_REG(REG_SPR1CTL + 8 * pair) & 0x0080) if (CUSTOM_REG(REG_SPR1CTL + 8 * pair) & 0x0080)
return (pixels & 0xf) | 0x10 | (collide << 6) | (pair << 10); return (pixels & 0xf) | osprm | result;
/* lower-numbered sprite of pair */ /* lower-numbered sprite of pair */
else if (pixels & 3) else if (pixels & 3)
return (pixels & 3) | 0x10 | (pair << 2) | (collide << 6) | (pair << 10); return (pixels & 3) | esprm | (pair << 2) | result;
/* higher-numbered sprite of pair */ /* higher-numbered sprite of pair */
else else
return ((pixels >> 2) & 3) | 0x10 | (pair << 2) | (collide << 6) | (pair << 10); return ((pixels >> 2) & 3) | osprm | (pair << 2) | result;
} }
} }
@ -539,7 +519,7 @@ static int get_sprite_pixel(int x)
* *
*************************************/ *************************************/
INLINE UINT8 assemble_odd_bitplanes(int planes, int obitoffs) INLINE UINT8 assemble_odd_bitplanes(amiga_state *state, int planes, int obitoffs)
{ {
UINT8 pix = (CUSTOM_REG(REG_BPL1DAT) >> obitoffs) & 1; UINT8 pix = (CUSTOM_REG(REG_BPL1DAT) >> obitoffs) & 1;
if (planes >= 3) if (planes >= 3)
@ -552,7 +532,7 @@ INLINE UINT8 assemble_odd_bitplanes(int planes, int obitoffs)
} }
INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs) INLINE UINT8 assemble_even_bitplanes(amiga_state *state, int planes, int ebitoffs)
{ {
UINT8 pix = 0; UINT8 pix = 0;
if (planes >= 2) if (planes >= 2)
@ -568,6 +548,11 @@ INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs)
return pix; return pix;
} }
INLINE void fetch_bitplane_data(amiga_state *state, int plane)
{
CUSTOM_REG(REG_BPL1DAT + plane) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
}
/************************************* /*************************************
@ -576,27 +561,27 @@ INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs)
* *
*************************************/ *************************************/
INLINE int update_ham(int newpix) INLINE int update_ham(amiga_state *state, int newpix)
{ {
switch (newpix >> 4) switch (newpix >> 4)
{ {
case 0: case 0:
ham_color = CUSTOM_REG(REG_COLOR00 + (newpix & 0xf)); state->ham_color = CUSTOM_REG(REG_COLOR00 + (newpix & 0xf));
break; break;
case 1: case 1:
ham_color = (ham_color & 0xff0) | ((newpix & 0xf) << 0); state->ham_color = (state->ham_color & 0xff0) | ((newpix & 0xf) << 0);
break; break;
case 2: case 2:
ham_color = (ham_color & 0x0ff) | ((newpix & 0xf) << 8); state->ham_color = (state->ham_color & 0x0ff) | ((newpix & 0xf) << 8);
break; break;
case 3: case 3:
ham_color = (ham_color & 0xf0f) | ((newpix & 0xf) << 4); state->ham_color = (state->ham_color & 0xf0f) | ((newpix & 0xf) << 4);
break; break;
} }
return ham_color; return state->ham_color;
} }
@ -609,6 +594,7 @@ INLINE int update_ham(int newpix)
void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline) void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
UINT16 save_color0 = CUSTOM_REG(REG_COLOR00); UINT16 save_color0 = CUSTOM_REG(REG_COLOR00);
int ddf_start_pixel = 0, ddf_stop_pixel = 0; int ddf_start_pixel = 0, ddf_stop_pixel = 0;
int hires = 0, dualpf = 0, lace = 0, ham = 0; int hires = 0, dualpf = 0, lace = 0, ham = 0;
@ -624,29 +610,30 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
int edelay = 0, odelay = 0; int edelay = 0, odelay = 0;
int next_copper_x; int next_copper_x;
int pl; int pl;
const int defbitoffs = 15;
last_scanline = scanline; state->last_scanline = scanline;
/* on the first scanline, reset the COPPER and HAM color */ /* on the first scanline, reset the COPPER and HAM color */
if (scanline == 0) if (scanline == 0)
{ {
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH)); amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH));
ham_color = CUSTOM_REG(REG_COLOR00); state->ham_color = CUSTOM_REG(REG_COLOR00);
} }
/* update sprite data fetching */ /* update sprite data fetching */
update_sprite_dma(scanline); update_sprite_dma(state, scanline);
/* start of a new line, signal we're not done with it and fill up vars */ /* start of a new line, signal we're not done with it and fill up vars */
if (bitmap != NULL) if (bitmap != NULL)
dst = BITMAP_ADDR16(bitmap, scanline, 0); dst = BITMAP_ADDR16(bitmap, scanline, 0);
/* all sprites off at the start of the line */ /* all sprites off at the start of the line */
memset(sprite_remain, 0, sizeof(sprite_remain)); memset(state->sprite_remain, 0, sizeof(state->sprite_remain));
/* temporary set color 0 to the genlock color */ /* temporary set color 0 to the genlock color */
if (genlock_color != 0xffff) if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color; CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* loop over the line */ /* loop over the line */
next_copper_x = 2; /* copper runs on odd timeslots */ next_copper_x = 2; /* copper runs on odd timeslots */
@ -659,10 +646,10 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
{ {
/* execute the next batch, restoring and re-saving color 0 around it */ /* execute the next batch, restoring and re-saving color 0 around it */
CUSTOM_REG(REG_COLOR00) = save_color0; CUSTOM_REG(REG_COLOR00) = save_color0;
next_copper_x = copper_execute_next(machine, x); next_copper_x = amiga_copper_execute_next(machine, x);
save_color0 = CUSTOM_REG(REG_COLOR00); save_color0 = CUSTOM_REG(REG_COLOR00);
if (genlock_color != 0xffff) if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color; CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* compute update-related register values */ /* compute update-related register values */
planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12; planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12;
@ -673,18 +660,20 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* compute the pixel fetch parameters */ /* compute the pixel fetch parameters */
ddf_start_pixel = ( CUSTOM_REG(REG_DDFSTRT) & 0xfc ) * 2 + (hires ? 9 : 17); ddf_start_pixel = ( CUSTOM_REG(REG_DDFSTRT) & 0xfc ) * 2 + (hires ? 9 : 17);
ddf_stop_pixel = ( CUSTOM_REG(REG_DDFSTOP) & 0xfc ) * 2 + (hires ? (9 + 15) : (17 + 15)); ddf_stop_pixel = ( CUSTOM_REG(REG_DDFSTOP) & 0xfc ) * 2 + (hires ? (9 + defbitoffs) : (17 + defbitoffs));
if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 ) if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 )
ddf_stop_pixel += 8; ddf_stop_pixel += 8;
/* compute the horizontal start/stop */ /* compute the horizontal start/stop */
hstart = CUSTOM_REG(REG_DIWSTRT) & 0xff; hstart = CUSTOM_REG(REG_DIWSTRT) & 0xff;
hstop = 0x100 + (CUSTOM_REG(REG_DIWSTOP) & 0xff); hstop = (CUSTOM_REG(REG_DIWSTOP) & 0xff);
hstop |= 0x100;
/* compute the vertical start/stop */ /* compute the vertical start/stop */
vstart = CUSTOM_REG(REG_DIWSTRT) >> 8; vstart = CUSTOM_REG(REG_DIWSTRT) >> 8;
vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8) | ((~CUSTOM_REG(REG_DIWSTOP) >> 7) & 0x100); vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8);
vstop |= ((~CUSTOM_REG(REG_DIWSTOP) >> 7) & 0x100);
/* extract playfield priorities */ /* extract playfield priorities */
pf1pri = CUSTOM_REG(REG_BPLCON2) & 7; pf1pri = CUSTOM_REG(REG_BPLCON2) & 7;
@ -708,8 +697,8 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if ( hires ) if ( hires )
{ {
obitoffs = 15 + ( odelay << 1 ); obitoffs = defbitoffs + ( odelay << 1 );
ebitoffs = 15 + ( edelay << 1 ); ebitoffs = defbitoffs + ( edelay << 1 );
} }
else else
{ {
@ -719,8 +708,8 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
edelay = ( edelay + 8 ) & 0x0f; edelay = ( edelay + 8 ) & 0x0f;
} }
obitoffs = 15 + odelay; obitoffs = defbitoffs + odelay;
ebitoffs = 15 + edelay; ebitoffs = defbitoffs + edelay;
} }
for (pl = 0; pl < 6; pl++) for (pl = 0; pl < 6; pl++)
@ -728,7 +717,7 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
} }
/* need to run the sprite engine every pixel to ensure display */ /* need to run the sprite engine every pixel to ensure display */
sprpix = get_sprite_pixel(x); sprpix = get_sprite_pixel(state, x);
/* to render, we must have bitplane DMA enabled, at least 1 plane, and be within the */ /* to render, we must have bitplane DMA enabled, at least 1 plane, and be within the */
/* vertical display window */ /* vertical display window */
@ -741,15 +730,16 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (x >= ddf_start_pixel && x <= ddf_stop_pixel + odelay) if (x >= ddf_start_pixel && x <= ddf_stop_pixel + odelay)
{ {
/* if we need to fetch more data, do it now */ /* if we need to fetch more data, do it now */
if (obitoffs == 15) if (obitoffs == defbitoffs)
{
for (pl = 0; pl < planes; pl += 2) for (pl = 0; pl < planes; pl += 2)
{ {
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2)); fetch_bitplane_data(state, pl);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2; }
} }
/* now assemble the bits */ /* now assemble the bits */
pfpix0 |= assemble_odd_bitplanes(planes, obitoffs); pfpix0 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--; obitoffs--;
/* for high res, assemble a second set of bits */ /* for high res, assemble a second set of bits */
@ -758,16 +748,15 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets and fetch more data if needed */ /* reset bit offsets and fetch more data if needed */
if (obitoffs < 0) if (obitoffs < 0)
{ {
obitoffs = 15; obitoffs = defbitoffs;
for (pl = 0; pl < planes; pl += 2) for (pl = 0; pl < planes; pl += 2)
{ {
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2)); fetch_bitplane_data(state, pl);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
} }
} }
pfpix1 |= assemble_odd_bitplanes(planes, obitoffs); pfpix1 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--; obitoffs--;
} }
else else
@ -775,22 +764,23 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets if needed */ /* reset bit offsets if needed */
if (obitoffs < 0) if (obitoffs < 0)
obitoffs = 15; obitoffs = defbitoffs;
} }
/* fetch the even bits if we are within the fetching region */ /* fetch the even bits if we are within the fetching region */
if (x >= ddf_start_pixel && x <= ddf_stop_pixel + edelay) if (x >= ddf_start_pixel && x <= ddf_stop_pixel + edelay)
{ {
/* if we need to fetch more data, do it now */ /* if we need to fetch more data, do it now */
if (ebitoffs == 15) if (ebitoffs == defbitoffs)
{
for (pl = 1; pl < planes; pl += 2) for (pl = 1; pl < planes; pl += 2)
{ {
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2)); fetch_bitplane_data(state, pl);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2; }
} }
/* now assemble the bits */ /* now assemble the bits */
pfpix0 |= assemble_even_bitplanes(planes, ebitoffs); pfpix0 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--; ebitoffs--;
/* for high res, assemble a second set of bits */ /* for high res, assemble a second set of bits */
@ -799,16 +789,15 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets and fetch more data if needed */ /* reset bit offsets and fetch more data if needed */
if (ebitoffs < 0) if (ebitoffs < 0)
{ {
ebitoffs = 15; ebitoffs = defbitoffs;
for (pl = 1; pl < planes; pl += 2) for (pl = 1; pl < planes; pl += 2)
{ {
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2)); fetch_bitplane_data(state, pl);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
} }
} }
pfpix1 |= assemble_even_bitplanes(planes, ebitoffs); pfpix1 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--; ebitoffs--;
} }
else else
@ -816,7 +805,7 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets if needed */ /* reset bit offsets if needed */
if (ebitoffs < 0) if (ebitoffs < 0)
ebitoffs = 15; ebitoffs = defbitoffs;
} }
/* compute playfield/sprite collisions for first pixel */ /* compute playfield/sprite collisions for first pixel */
@ -840,17 +829,22 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* if we are within the display region, render */ /* if we are within the display region, render */
if (dst != NULL && x >= hstart && x < hstop) if (dst != NULL && x >= hstart && x < hstop)
{ {
int pix, pri;
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */ /* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
if (ham) if (ham)
{ {
/* update the HAM color */ /* update the HAM color */
pfpix0 = update_ham(pfpix0); pfpix0 = update_ham(state, pfpix0);
pix = sprpix & 0x1f;
pri = (sprpix >> 10);
/* sprite has priority */ /* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10)) if (sprpix && pf1pri > pri)
{ {
dst[x*2+0] = dst[x*2+0] =
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + (sprpix & 0x1f)); dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
} }
/* playfield has priority */ /* playfield has priority */
@ -864,15 +858,14 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* dual playfield mode */ /* dual playfield mode */
else if (dualpf) else if (dualpf)
{ {
int pix;
/* mask out the sprite if it doesn't have priority */ /* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f; pix = sprpix & 0x1f;
pri = (sprpix >> 10);
if (pix) if (pix)
{ {
if ((pfpix0 & 0x15) && pf1pri <= (sprpix >> 10)) if ((pfpix0 & 0x15) && pf1pri <= pri)
pix = 0; pix = 0;
if ((pfpix0 & 0x2a) && pf2pri <= (sprpix >> 10)) if ((pfpix0 & 0x2a) && pf2pri <= pri)
pix = 0; pix = 0;
} }
@ -880,15 +873,15 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (pix) if (pix)
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pix); dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pix);
else else
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]); dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + state->separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]);
/* mask out the sprite if it doesn't have priority */ /* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f; pix = sprpix & 0x1f;
if (pix) if (pix)
{ {
if ((pfpix1 & 0x15) && pf1pri <= (sprpix >> 10)) if ((pfpix1 & 0x15) && pf1pri <= pri)
pix = 0; pix = 0;
if ((pfpix1 & 0x2a) && pf2pri <= (sprpix >> 10)) if ((pfpix1 & 0x2a) && pf2pri <= pri)
pix = 0; pix = 0;
} }
@ -896,17 +889,20 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (pix) if (pix)
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix); dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
else else
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]); dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + state->separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]);
} }
/* single playfield mode */ /* single playfield mode */
else else
{ {
pix = sprpix & 0x1f;
pri = (sprpix >> 10);
/* sprite has priority */ /* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10)) if (sprpix && pf1pri > pri)
{ {
dst[x*2+0] = dst[x*2+0] =
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + (sprpix & 0x1f)); dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
} }
/* playfield has priority */ /* playfield has priority */
@ -961,9 +957,9 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (machine->primary_screen->frame_number() % 64 == 0 && scanline == 0) if (machine->primary_screen->frame_number() % 64 == 0 && scanline == 0)
{ {
if (input_code_pressed(machine, KEYCODE_Q)) if (input_code_pressed(machine, KEYCODE_Q))
popmessage("%d", wait_offset -= 1); popmessage("%d", state->wait_offset -= 1);
if (input_code_pressed(machine, KEYCODE_W)) if (input_code_pressed(machine, KEYCODE_W))
popmessage("%d", wait_offset += 1); popmessage("%d", state->wait_offset += 1);
} }
#endif #endif
} }

View File

@ -22,130 +22,22 @@ To do:
/*************************************
*
* Debugging
*
*************************************/
#define LOG_COPPER 0
#define GUESS_COPPER_OFFSET 0
#define LOG_SPRITE_DMA 0
/*************************************
*
* Macros
*
*************************************/
#define COPPER_CYCLES_TO_PIXELS(x) (4 * (x))
/************************************* /*************************************
* *
* Statics * Statics
* *
*************************************/ *************************************/
/* palette */
static pen_t aga_palette[256];
/* AGA bpldat registers */
static UINT64 aga_bpldat[8];
/* sprite states */
static UINT8 sprite_comparitor_enable_mask;
static UINT8 sprite_dma_reload_mask;
static UINT8 sprite_dma_live_mask;
static UINT8 sprite_ctl_written;
static UINT32 sprite_shiftreg[8];
static UINT8 sprite_remain[8];
static UINT16 aga_sprdata[8][4];
static UINT16 aga_sprdatb[8][4];
static int aga_sprite_fetched_words;
static int aga_sprite_dma_used_words[8];
/* playfield states */
static int last_scanline;
static pen_t ham_color;
static int diwhigh_written;
/* copper states */
static UINT32 copper_pc;
static UINT8 copper_waiting;
static UINT8 copper_waitblit;
static UINT16 copper_waitval;
static UINT16 copper_waitmask;
static UINT16 copper_pending_offset;
static UINT16 copper_pending_data;
/* misc states */
static UINT16 genlock_color;
#if GUESS_COPPER_OFFSET
static int wait_offset = 3;
#endif
/*************************************
*
* Tables
*
*************************************/
/* expand an 8-bit bit pattern into 16 bits, every other bit */
static const UINT16 expand_byte[256] =
{
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
};
/* separate 6 in-order bitplanes into 2 x 3-bit bitplanes in two nibbles */
static UINT8 separate_bitplanes[2][64];
/************************************* /*************************************
* *
* Palette * Palette
* *
*************************************/ *************************************/
void aga_palette_write(int color_reg, UINT16 data) void amiga_aga_palette_write(running_machine *machine, int color_reg, UINT16 data)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
pen_t *aga_palette = state->aga_palette;
int r,g,b; int r,g,b;
int cr,cg,cb; int cr,cg,cb;
int color; int color;
@ -181,232 +73,11 @@ void aga_palette_write(int color_reg, UINT16 data)
VIDEO_START( amiga_aga ) VIDEO_START( amiga_aga )
{ {
int j; amiga_state *state = machine->driver_data<amiga_state>();
/* generate tables that produce the correct playfield color for dual playfield mode */ VIDEO_START_CALL( amiga );
for (j = 0; j < 64; j++)
{
int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4);
int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4);
separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8); state->aga_diwhigh_written = 0;
separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
}
/* reset the genlock color */
genlock_color = 0xffff;
sprite_ctl_written = 0;
diwhigh_written = 0;
}
/*************************************
*
* Beam position
*
*************************************/
UINT32 amiga_aga_gethvpos(screen_device &screen)
{
UINT32 hvpos = (last_scanline << 8) | (screen.hpos() >> 2);
UINT32 latchedpos = input_port_read_safe(screen.machine, "HVPOS", 0);
/* if there's no latched position, or if we are in the active display area */
/* but before the latching point, return the live HV position */
if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (last_scanline >= 20 && hvpos < latchedpos))
return hvpos;
/* otherwise, return the latched position */
return latchedpos;
}
/*************************************
*
* Genlock interaction
*
*************************************/
void amiga_aga_set_genlock_color(UINT16 color)
{
genlock_color = color;
}
/*************************************
*
* Copper emulation
*
*************************************/
void aga_copper_setpc(UINT32 pc)
{
if (LOG_COPPER)
logerror("copper_setpc(%06x)\n", pc);
copper_pc = pc;
copper_waiting = FALSE;
}
static int copper_execute_next(running_machine *machine, int xpos)
{
int word0, word1;
/* bail if not enabled */
if ((CUSTOM_REG(REG_DMACON) & (DMACON_COPEN | DMACON_DMAEN)) != (DMACON_COPEN | DMACON_DMAEN))
return 511;
/* flush any pending writes */
if (copper_pending_offset)
{
if (LOG_COPPER)
logerror("%02X.%02X: Write to %s = %04x\n", last_scanline, xpos / 2, amiga_custom_names[copper_pending_offset & 0xff], copper_pending_data);
amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), copper_pending_offset, copper_pending_data, 0xffff);
copper_pending_offset = 0;
}
/* if we're waiting, check for a breakthrough */
if (copper_waiting)
{
int curpos = (last_scanline << 8) | (xpos >> 1);
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{
copper_waiting = FALSE;
#if GUESS_COPPER_OFFSET
return xpos + COPPER_CYCLES_TO_PIXELS(1 + wait_offset);
#else
return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3);
#endif
}
/* otherwise, see if this line is even a possibility; if not, punt */
if (((curpos | 0xff) & copper_waitmask) < (copper_waitval & copper_waitmask))
return 511;
/* else just advance another pixel */
xpos += COPPER_CYCLES_TO_PIXELS(1);
return xpos;
}
/* fetch the first data word */
word0 = amiga_chip_ram_r(copper_pc);
copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
/* fetch the second data word */
word1 = amiga_chip_ram_r(copper_pc);
copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
if (LOG_COPPER)
logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", last_scanline, xpos / 2, copper_pc, word0, word1);
/* handle a move */
if ((word0 & 1) == 0)
{
int min = (CUSTOM_REG(REG_COPCON) & 2) ? 0x20 : 0x40;
/* do the write if we're allowed */
word0 = (word0 >> 1) & 0xff;
if (word0 >= min)
{
/* write it at the *end* of this instruction's cycles */
/* needed for Arcadia's Fast Break */
copper_pending_offset = word0;
copper_pending_data = word1;
}
/* illegal writes suspend until next frame */
else
{
if (LOG_COPPER)
logerror("%02X.%02X: Aborting copper on illegal write\n", last_scanline, xpos / 2);
copper_waitval = 0xffff;
copper_waitmask = 0xffff;
copper_waitblit = FALSE;
copper_waiting = TRUE;
return 511;
}
}
else
{
/* extract common wait/skip values */
copper_waitval = word0 & 0xfffe;
copper_waitmask = word1 | 0x8001;
copper_waitblit = (~word1 >> 15) & 1;
/* handle a wait */
if ((word1 & 1) == 0)
{
if (LOG_COPPER)
logerror(" Waiting for %04x & %04x (currently %04x)\n", copper_waitval, copper_waitmask, (last_scanline << 8) | (xpos >> 1));
copper_waiting = TRUE;
}
/* handle a skip */
else
{
int curpos = (last_scanline << 8) | (xpos >> 1);
if (LOG_COPPER)
logerror(" Skipping if %04x & %04x (currently %04x)\n", copper_waitval, copper_waitmask, (last_scanline << 8) | (xpos >> 1));
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{
if (LOG_COPPER)
logerror(" Skipped\n");
/* count the cycles it out have taken to fetch the next instruction */
copper_pc += 4;
xpos += COPPER_CYCLES_TO_PIXELS(2);
}
}
}
/* advance and consume 8 cycles */
return xpos;
}
/*************************************
*
* External sprite controls
*
*************************************/
void amiga_aga_sprite_dma_reset(int which)
{
if (LOG_SPRITE_DMA) logerror("sprite %d dma reset\n", which );
sprite_dma_reload_mask |= 1 << which;
sprite_dma_live_mask |= 1 << which;
}
void amiga_aga_sprite_enable_comparitor(int which, int enable)
{
if (LOG_SPRITE_DMA) logerror("sprite %d comparitor %sable\n", which, enable ? "en" : "dis" );
if (enable)
{
sprite_comparitor_enable_mask |= 1 << which;
sprite_dma_live_mask &= ~(1 << which);
}
else
{
sprite_comparitor_enable_mask &= ~(1 << which);
sprite_ctl_written |= (1 << which);
}
} }
@ -417,54 +88,54 @@ void amiga_aga_sprite_enable_comparitor(int which, int enable)
* *
*************************************/ *************************************/
INLINE void fetch_sprite_data(int scanline, int sprite) INLINE void fetch_sprite_data(amiga_state *state, int scanline, int sprite)
{ {
switch((CUSTOM_REG(REG_FMODE) >> 2) & 0x03) switch((CUSTOM_REG(REG_FMODE) >> 2) & 0x03)
{ {
case 0: case 0:
aga_sprdata[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdata[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdatb[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdatb[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprite_fetched_words = 1; state->aga_sprite_fetched_words = 1;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X\n", scanline, sprite, aga_sprdata[sprite][0], aga_sprdatb[sprite][0]); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X\n", scanline, sprite, state->aga_sprdata[sprite][0], state->aga_sprdatb[sprite][0]);
break; break;
case 1: case 1:
case 2: case 2:
aga_sprdata[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdata[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdata[sprite][1] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdata[sprite][1] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprdatb[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdatb[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdatb[sprite][1] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdatb[sprite][1] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprite_fetched_words = 2; state->aga_sprite_fetched_words = 2;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X %04X-%04X\n", scanline, sprite, aga_sprdata[sprite][0], aga_sprdatb[sprite][0], aga_sprdata[sprite][1], aga_sprdatb[sprite][1] ); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X %04X-%04X\n", scanline, sprite, state->aga_sprdata[sprite][0], state->aga_sprdatb[sprite][0], state->aga_sprdata[sprite][1], state->aga_sprdatb[sprite][1] );
break; break;
case 3: case 3:
aga_sprdata[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdata[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdata[sprite][1] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdata[sprite][1] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprdata[sprite][2] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdata[sprite][2] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdata[sprite][3] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdata[sprite][3] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprdatb[sprite][0] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdatb[sprite][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdatb[sprite][1] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdatb[sprite][1] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprdatb[sprite][2] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0); state->aga_sprdatb[sprite][2] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
aga_sprdatb[sprite][3] = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2); state->aga_sprdatb[sprite][3] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
aga_sprite_fetched_words = 4; state->aga_sprite_fetched_words = 4;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X %04X-%04X %04X-%04X %04X-%04X\n", if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: data=%04X-%04X %04X-%04X %04X-%04X %04X-%04X\n",
scanline, sprite, scanline, sprite,
aga_sprdata[sprite][0], aga_sprdatb[sprite][0], state->aga_sprdata[sprite][0], state->aga_sprdatb[sprite][0],
aga_sprdata[sprite][1], aga_sprdatb[sprite][1], state->aga_sprdata[sprite][1], state->aga_sprdatb[sprite][1],
aga_sprdata[sprite][2], aga_sprdatb[sprite][2], state->aga_sprdata[sprite][2], state->aga_sprdatb[sprite][2],
aga_sprdata[sprite][3], aga_sprdatb[sprite][3]); state->aga_sprdata[sprite][3], state->aga_sprdatb[sprite][3]);
break; break;
} }
aga_sprite_dma_used_words[sprite] = 0; state->aga_sprite_dma_used_words[sprite] = 0;
} }
static void update_sprite_dma(int scanline) static void update_sprite_dma(amiga_state *state, int scanline)
{ {
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN); int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
int num, maxdma; int num, maxdma;
@ -481,15 +152,15 @@ static void update_sprite_dma(int scanline)
int vstart, vstop; int vstart, vstop;
/* if we are == VSTOP, fetch new control words */ /* if we are == VSTOP, fetch new control words */
if (dmaenable && (sprite_dma_live_mask & bitmask) && (sprite_dma_reload_mask & bitmask) && !(sprite_ctl_written & bitmask)) if (dmaenable && (state->sprite_dma_live_mask & bitmask) && (state->sprite_dma_reload_mask & bitmask) && !(state->sprite_ctl_written & bitmask))
{ {
/* disable the sprite */ /* disable the sprite */
sprite_comparitor_enable_mask &= ~bitmask; state->sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask &= ~bitmask; state->sprite_dma_reload_mask &= ~bitmask;
/* fetch data into the control words */ /* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0); CUSTOM_REG(REG_SPR0POS + 4 * num) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
CUSTOM_REG(REG_SPR0CTL + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2); CUSTOM_REG(REG_SPR0CTL + 4 * num) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4; CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
/* fetch additional words */ /* fetch additional words */
switch((CUSTOM_REG(REG_FMODE) >> 2) & 0x03) switch((CUSTOM_REG(REG_FMODE) >> 2) & 0x03)
@ -514,25 +185,25 @@ static void update_sprite_dma(int scanline)
/* if we hit vstart, enable the comparitor */ /* if we hit vstart, enable the comparitor */
if (scanline == vstart) if (scanline == vstart)
{ {
sprite_comparitor_enable_mask |= 1 << num; state->sprite_comparitor_enable_mask |= 1 << num;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor enable\n", scanline, num); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor enable\n", scanline, num);
} }
/* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */ /* if we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop) if (scanline == vstop)
{ {
sprite_ctl_written &= ~bitmask; state->sprite_ctl_written &= ~bitmask;
sprite_comparitor_enable_mask &= ~bitmask; state->sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask |= 1 << num; state->sprite_dma_reload_mask |= 1 << num;
CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */ CUSTOM_REG(REG_SPR0DATA + 4 * num) = 0; /* just a guess */
CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0; CUSTOM_REG(REG_SPR0DATB + 4 * num) = 0;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num); if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
} }
/* fetch data if this sprite is enabled */ /* fetch data if this sprite is enabled */
if (dmaenable && (sprite_dma_live_mask & bitmask) && (sprite_comparitor_enable_mask & bitmask)) if (dmaenable && (state->sprite_dma_live_mask & bitmask) && (state->sprite_comparitor_enable_mask & bitmask))
{ {
fetch_sprite_data(scanline, num); fetch_sprite_data(state, scanline, num);
} }
} }
} }
@ -547,46 +218,47 @@ static void update_sprite_dma(int scanline)
INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits) INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits)
{ {
return (expand_byte[lobits & 0xff] << 0) | (expand_byte[lobits >> 8] << 16) | return (amiga_expand_byte[lobits & 0xff] << 0) | (amiga_expand_byte[lobits >> 8] << 16) |
(expand_byte[hibits & 0xff] << 1) | (expand_byte[hibits >> 8] << 17); (amiga_expand_byte[hibits & 0xff] << 1) | (amiga_expand_byte[hibits >> 8] << 17);
} }
static int get_sprite_pixel(int x) static int get_sprite_pixel(amiga_state *state, int x)
{ {
int pixels = 0; int pixels = 0;
int num, pair; int num, pair;
/* loop over sprite channels */ /* loop over sprite channels */
for (num = 0; num < 8; num++) for (num = 0; num < 8; num++)
if (sprite_comparitor_enable_mask & (1 << num)) if (state->sprite_comparitor_enable_mask & (1 << num))
{ {
/* if we're not currently clocking, check against hstart */ /* if we're not currently clocking, check against hstart */
if (sprite_remain[num] == 0) if (state->sprite_remain[num] == 0)
{ {
int hstart = ((CUSTOM_REG(REG_SPR0POS + 4 * num) & 0xff) << 1) | (CUSTOM_REG(REG_SPR0CTL + 4 * num) & 1); int hstart = ((CUSTOM_REG(REG_SPR0POS + 4 * num) & 0xff) << 1) | (CUSTOM_REG(REG_SPR0CTL + 4 * num) & 1);
if (hstart == x) if (hstart == x)
{ {
sprite_remain[num] = 16; state->sprite_remain[num] = 16;
sprite_shiftreg[num] = interleave_sprite_data(aga_sprdata[num][0], aga_sprdatb[num][0]); state->sprite_shiftreg[num] = interleave_sprite_data(state->aga_sprdata[num][0], state->aga_sprdatb[num][0]);
aga_sprite_dma_used_words[num] = 1; state->aga_sprite_dma_used_words[num] = 1;
} }
} }
/* clock the next pixel if we're doing it */ /* clock the next pixel if we're doing it */
if (sprite_remain[num] != 0) if (state->sprite_remain[num] != 0)
{ {
sprite_remain[num]--; state->sprite_remain[num]--;
pixels |= (sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num)); pixels |= (state->sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
sprite_shiftreg[num] <<= 2; state->sprite_shiftreg[num] <<= 2;
if (sprite_remain[num] == 0) if (state->sprite_remain[num] == 0)
{ {
if (aga_sprite_dma_used_words[num] < aga_sprite_fetched_words) if (state->aga_sprite_dma_used_words[num] < state->aga_sprite_fetched_words)
{ {
sprite_remain[num] = 16; int w = state->aga_sprite_dma_used_words[num];
sprite_shiftreg[num] = interleave_sprite_data(aga_sprdata[num][aga_sprite_dma_used_words[num]], aga_sprdatb[num][aga_sprite_dma_used_words[num]]); state->sprite_remain[num] = 16;
aga_sprite_dma_used_words[num]++; state->sprite_shiftreg[num] = interleave_sprite_data(state->aga_sprdata[num][w], state->aga_sprdatb[num][w]);
state->aga_sprite_dma_used_words[num]++;
} }
} }
} }
@ -630,20 +302,21 @@ static int get_sprite_pixel(int x)
/* final result is: /* final result is:
topmost sprite color in bits 0-7 topmost sprite color in bits 0-7
sprite present bitmask in bits 8-9 sprite present bitmask in bits 8-9
topmost sprite pair index in bits 12-11 topmost sprite pair index in bits 12-13
*/ */
UINT32 result = (collide << 8) | (pair << 12);
/* attached case */ /* attached case */
if (CUSTOM_REG(REG_SPR1CTL + 8 * pair) & 0x0080) if (CUSTOM_REG(REG_SPR1CTL + 8 * pair) & 0x0080)
return (pixels & 0xf) | osprm | (collide << 8) | (pair << 12); return (pixels & 0xf) | osprm | result;
/* lower-numbered sprite of pair */ /* lower-numbered sprite of pair */
else if (pixels & 3) else if (pixels & 3)
return (pixels & 3) | esprm | (pair << 2) | (collide << 8) | (pair << 12); return (pixels & 3) | esprm | (pair << 2) | result;
/* higher-numbered sprite of pair */ /* higher-numbered sprite of pair */
else else
return ((pixels >> 2) & 3) | osprm | (pair << 2) | (collide << 8) | (pair << 12); return ((pixels >> 2) & 3) | osprm | (pair << 2) | result;
} }
} }
@ -658,8 +331,9 @@ static int get_sprite_pixel(int x)
* *
*************************************/ *************************************/
INLINE UINT8 assemble_odd_bitplanes(int planes, int obitoffs) INLINE UINT8 assemble_odd_bitplanes(amiga_state *state, int planes, int obitoffs)
{ {
UINT64 *aga_bpldat = state->aga_bpldat;
UINT8 pix = (aga_bpldat[0] >> obitoffs) & 1; UINT8 pix = (aga_bpldat[0] >> obitoffs) & 1;
if (planes >= 3) if (planes >= 3)
{ {
@ -675,11 +349,12 @@ INLINE UINT8 assemble_odd_bitplanes(int planes, int obitoffs)
} }
INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs) INLINE UINT8 assemble_even_bitplanes(amiga_state *state, int planes, int ebitoffs)
{ {
UINT8 pix = 0; UINT8 pix = 0;
if (planes >= 2) if (planes >= 2)
{ {
UINT64 *aga_bpldat = state->aga_bpldat;
pix |= ((aga_bpldat[1] >> ebitoffs) & 1) << 1; pix |= ((aga_bpldat[1] >> ebitoffs) & 1) << 1;
if (planes >= 4) if (planes >= 4)
{ {
@ -695,37 +370,41 @@ INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs)
return pix; return pix;
} }
INLINE void fetch_bitplane_data(int plane) INLINE void fetch_bitplane_data(amiga_state *state, int plane)
{ {
UINT64 *aga_bpldat = state->aga_bpldat;
switch (CUSTOM_REG(REG_FMODE) & 0x03) switch (CUSTOM_REG(REG_FMODE) & 0x03)
{ {
case 0: case 0:
aga_bpldat[plane] = (UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)); aga_bpldat[plane] = (UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
break; break;
case 1: case 1:
case 2: case 2:
aga_bpldat[plane] = (UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)) << 16; aga_bpldat[plane] = (UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)) << 16;
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
aga_bpldat[plane] |= ((UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2))); aga_bpldat[plane] |= ((UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)));
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
break; break;
case 3: case 3:
aga_bpldat[plane] = (UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)) << 48; aga_bpldat[plane] = (UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)) << 48;
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
aga_bpldat[plane] |= ((UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2))) << 32; aga_bpldat[plane] |= ((UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2))) << 32;
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
aga_bpldat[plane] |= ((UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2))) << 16; aga_bpldat[plane] |= ((UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2))) << 16;
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
aga_bpldat[plane] |= (UINT64)amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2)); aga_bpldat[plane] |= (UINT64)(*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2; CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2) += 2;
break; break;
} }
} }
void aga_diwhigh_written(int written) void amiga_aga_diwhigh_written(running_machine *machine, int written)
{ {
diwhigh_written = written; amiga_state *state = machine->driver_data<amiga_state>();
state->aga_diwhigh_written = written;
} }
/************************************* /*************************************
@ -734,27 +413,27 @@ void aga_diwhigh_written(int written)
* *
*************************************/ *************************************/
INLINE int update_ham(int newpix) INLINE int update_ham(amiga_state *state, int newpix)
{ {
switch (newpix & 0x03) switch (newpix & 0x03)
{ {
case 0: case 0:
ham_color = aga_palette[(newpix >> 2) & 0x3f]; state->ham_color = state->aga_palette[(newpix >> 2) & 0x3f];
break; break;
case 1: case 1:
ham_color = MAKE_RGB(RGB_RED(ham_color), RGB_GREEN(ham_color), (newpix & 0xfc) | (RGB_BLUE(ham_color) & 0x03)); state->ham_color = MAKE_RGB(RGB_RED(state->ham_color), RGB_GREEN(state->ham_color), (newpix & 0xfc) | (RGB_BLUE(state->ham_color) & 0x03));
break; break;
case 2: case 2:
ham_color = MAKE_RGB((newpix & 0xfc) | (RGB_RED(ham_color) & 0x03), RGB_GREEN(ham_color), RGB_BLUE(ham_color)); state->ham_color = MAKE_RGB((newpix & 0xfc) | (RGB_RED(state->ham_color) & 0x03), RGB_GREEN(state->ham_color), RGB_BLUE(state->ham_color));
break; break;
case 3: case 3:
ham_color = MAKE_RGB(RGB_RED(ham_color), (newpix & 0xfc) | (RGB_GREEN(ham_color) & 0x03), RGB_BLUE(ham_color)); state->ham_color = MAKE_RGB(RGB_RED(state->ham_color), (newpix & 0xfc) | (RGB_GREEN(state->ham_color) & 0x03), RGB_BLUE(state->ham_color));
break; break;
} }
return ham_color; return state->ham_color;
} }
@ -767,6 +446,7 @@ INLINE int update_ham(int newpix)
void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline) void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline)
{ {
amiga_state *state = machine->driver_data<amiga_state>();
UINT16 save_color0 = CUSTOM_REG(REG_COLOR00); UINT16 save_color0 = CUSTOM_REG(REG_COLOR00);
int ddf_start_pixel = 0, ddf_stop_pixel = 0; int ddf_start_pixel = 0, ddf_stop_pixel = 0;
int hires = 0, dualpf = 0, lace = 0, ham = 0; int hires = 0, dualpf = 0, lace = 0, ham = 0;
@ -782,31 +462,31 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
int edelay = 0, odelay = 0; int edelay = 0, odelay = 0;
int next_copper_x; int next_copper_x;
int pl; int pl;
pen_t ham_pix;
int defbitoffs = 0; int defbitoffs = 0;
pen_t *aga_palette = state->aga_palette;
last_scanline = scanline; state->last_scanline = scanline;
/* on the first scanline, reset the COPPER and HAM color */ /* on the first scanline, reset the COPPER and HAM color */
if (scanline == 0) if (scanline == 0)
{ {
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH)); amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH));
ham_color = CUSTOM_REG(REG_COLOR00); state->ham_color = CUSTOM_REG(REG_COLOR00);
} }
/* update sprite data fetching */ /* update sprite data fetching */
update_sprite_dma(scanline); update_sprite_dma(state, scanline);
/* start of a new line, signal we're not done with it and fill up vars */ /* start of a new line, signal we're not done with it and fill up vars */
if (bitmap != NULL) if (bitmap != NULL)
dst = BITMAP_ADDR32(bitmap, scanline, 0); dst = BITMAP_ADDR32(bitmap, scanline, 0);
/* all sprites off at the start of the line */ /* all sprites off at the start of the line */
memset(sprite_remain, 0, sizeof(sprite_remain)); memset(state->sprite_remain, 0, sizeof(state->sprite_remain));
/* temporary set color 0 to the genlock color */ /* temporary set color 0 to the genlock color */
if (genlock_color != 0xffff) if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color; CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* loop over the line */ /* loop over the line */
next_copper_x = 2; /* copper runs on odd timeslots */ next_copper_x = 2; /* copper runs on odd timeslots */
@ -819,10 +499,10 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
{ {
/* execute the next batch, restoring and re-saving color 0 around it */ /* execute the next batch, restoring and re-saving color 0 around it */
CUSTOM_REG(REG_COLOR00) = save_color0; CUSTOM_REG(REG_COLOR00) = save_color0;
next_copper_x = copper_execute_next(machine, x); next_copper_x = amiga_copper_execute_next(machine, x);
save_color0 = CUSTOM_REG(REG_COLOR00); save_color0 = CUSTOM_REG(REG_COLOR00);
if (genlock_color != 0xffff) if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color; CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* compute update-related register values */ /* compute update-related register values */
planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12; planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12;
@ -854,7 +534,7 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
hstart = CUSTOM_REG(REG_DIWSTRT) & 0xff; hstart = CUSTOM_REG(REG_DIWSTRT) & 0xff;
hstop = (CUSTOM_REG(REG_DIWSTOP) & 0xff); hstop = (CUSTOM_REG(REG_DIWSTOP) & 0xff);
if (diwhigh_written) if (state->aga_diwhigh_written)
{ {
hstart |= ((CUSTOM_REG(REG_DIWHIGH) >> 5) & 1) << 8; hstart |= ((CUSTOM_REG(REG_DIWHIGH) >> 5) & 1) << 8;
hstop |= ((CUSTOM_REG(REG_DIWHIGH) >> 13) & 1) << 8; hstop |= ((CUSTOM_REG(REG_DIWHIGH) >> 13) & 1) << 8;
@ -872,15 +552,14 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
/* compute the vertical start/stop */ /* compute the vertical start/stop */
vstart = CUSTOM_REG(REG_DIWSTRT) >> 8; vstart = CUSTOM_REG(REG_DIWSTRT) >> 8;
vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8); vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8);
if (diwhigh_written) if (state->aga_diwhigh_written)
{ {
vstart |= (CUSTOM_REG(REG_DIWHIGH) & 7) << 8; vstart |= (CUSTOM_REG(REG_DIWHIGH) & 7) << 8;
vstop |= ((CUSTOM_REG(REG_DIWHIGH) >> 8) & 7) << 8; vstop |= ((CUSTOM_REG(REG_DIWHIGH) >> 8) & 7) << 8;
} }
else else
{ {
if ((vstop & 0x80) == 0) vstop |= ((~CUSTOM_REG(REG_DIWSTOP) >> 7) & 0x100);
vstop |= 0x100;
} }
/* extract playfield priorities */ /* extract playfield priorities */
@ -890,7 +569,6 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
/* extract collision masks */ /* extract collision masks */
ocolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x15; ocolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x15;
ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a; ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a;
} }
/* clear the target pixels to the background color as a starting point */ /* clear the target pixels to the background color as a starting point */
@ -922,11 +600,11 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
} }
for (pl = 0; pl < 8; pl++) for (pl = 0; pl < 8; pl++)
aga_bpldat[pl] = 0; state->aga_bpldat[pl] = 0;
} }
/* need to run the sprite engine every pixel to ensure display */ /* need to run the sprite engine every pixel to ensure display */
sprpix = get_sprite_pixel(x); sprpix = get_sprite_pixel(state, x);
/* to render, we must have bitplane DMA enabled, at least 1 plane, and be within the */ /* to render, we must have bitplane DMA enabled, at least 1 plane, and be within the */
/* vertical display window */ /* vertical display window */
@ -943,12 +621,12 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
{ {
for (pl = 0; pl < planes; pl += 2) for (pl = 0; pl < planes; pl += 2)
{ {
fetch_bitplane_data(pl); fetch_bitplane_data(state, pl);
} }
} }
/* now assemble the bits */ /* now assemble the bits */
pfpix0 |= assemble_odd_bitplanes(planes, obitoffs); pfpix0 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--; obitoffs--;
/* for high res, assemble a second set of bits */ /* for high res, assemble a second set of bits */
@ -961,11 +639,11 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
for (pl = 0; pl < planes; pl += 2) for (pl = 0; pl < planes; pl += 2)
{ {
fetch_bitplane_data(pl); fetch_bitplane_data(state, pl);
} }
} }
pfpix1 |= assemble_odd_bitplanes(planes, obitoffs); pfpix1 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--; obitoffs--;
} }
else else
@ -984,12 +662,12 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
{ {
for (pl = 1; pl < planes; pl += 2) for (pl = 1; pl < planes; pl += 2)
{ {
fetch_bitplane_data(pl); fetch_bitplane_data(state, pl);
} }
} }
/* now assemble the bits */ /* now assemble the bits */
pfpix0 |= assemble_even_bitplanes(planes, ebitoffs); pfpix0 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--; ebitoffs--;
/* for high res, assemble a second set of bits */ /* for high res, assemble a second set of bits */
@ -1002,11 +680,11 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
for (pl = 1; pl < planes; pl += 2) for (pl = 1; pl < planes; pl += 2)
{ {
fetch_bitplane_data(pl); fetch_bitplane_data(state, pl);
} }
} }
pfpix1 |= assemble_even_bitplanes(planes, ebitoffs); pfpix1 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--; ebitoffs--;
} }
else else
@ -1038,39 +716,43 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
/* if we are within the display region, render */ /* if we are within the display region, render */
if (dst != NULL && x >= hstart && x < hstop) if (dst != NULL && x >= hstart && x < hstop)
{ {
int pix, pri;
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */ /* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
if (ham) if (ham)
{ {
/* update the HAM color */ /* update the HAM color */
ham_pix = update_ham(pfpix0); pfpix0 = update_ham(state, pfpix0);
pix = sprpix & 0xff;
pri = (sprpix >> 10);
/* sprite has priority */ /* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10)) if (sprpix && pf1pri > pri)
{ {
dst[x*2+0] = dst[x*2+0] =
dst[x*2+1] = aga_palette[sprpix & 0xff]; dst[x*2+1] = aga_palette[pix];
} }
/* playfield has priority */ /* playfield has priority */
else else
{ {
dst[x*2+0] = dst[x*2+0] =
dst[x*2+1] = ham_pix; dst[x*2+1] = pfpix0;
} }
} }
/* dual playfield mode */ /* dual playfield mode */
else if (dualpf) else if (dualpf)
{ {
int pix;
/* mask out the sprite if it doesn't have priority */ /* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f; pix = sprpix & 0x1f;
pri = (sprpix >> 12);
if (pix) if (pix)
{ {
if ((pfpix0 & 0x15) && pf1pri <= (sprpix >> 12)) if ((pfpix0 & 0x15) && pf1pri <= pri)
pix = 0; pix = 0;
if ((pfpix0 & 0x2a) && pf2pri <= (sprpix >> 12)) if ((pfpix0 & 0x2a) && pf2pri <= pri)
pix = 0; pix = 0;
} }
@ -1078,15 +760,15 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
if (pix) if (pix)
dst[x*2+0] = aga_palette[pix]; dst[x*2+0] = aga_palette[pix];
else else
dst[x*2+0] = aga_palette[separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]]; dst[x*2+0] = aga_palette[state->separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]];
/* mask out the sprite if it doesn't have priority */ /* mask out the sprite if it doesn't have priority */
pix = sprpix & 0xff; pix = sprpix & 0xff;
if (pix) if (pix)
{ {
if ((pfpix1 & 0x15) && pf1pri <= (sprpix >> 12)) if ((pfpix1 & 0x15) && pf1pri <= pri)
pix = 0; pix = 0;
if ((pfpix1 & 0x2a) && pf2pri <= (sprpix >> 12)) if ((pfpix1 & 0x2a) && pf2pri <= pri)
pix = 0; pix = 0;
} }
@ -1094,17 +776,20 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
if (pix) if (pix)
dst[x*2+1] = aga_palette[pix]; dst[x*2+1] = aga_palette[pix];
else else
dst[x*2+1] = aga_palette[separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]]; dst[x*2+1] = aga_palette[state->separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]];
} }
/* single playfield mode */ /* single playfield mode */
else else
{ {
pix = sprpix & 0xff;
pri = (sprpix >> 12);
/* sprite has priority */ /* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 12)) if (sprpix && pf1pri > pri)
{ {
dst[x*2+0] = dst[x*2+0] =
dst[x*2+1] = aga_palette[(sprpix & 0xff)]; dst[x*2+1] = aga_palette[pix];
} }
/* playfield has priority */ /* playfield has priority */