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);
/*************************************
*
* Globals
*
*************************************/
static amiga_audio *audio_state;
return (amiga_audio *)downcast<legacy_device_base *>(device)->token();
}
/*************************************
*
@ -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->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;
}
@ -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);
}
@ -124,6 +125,7 @@ void amiga_audio_update(void)
static STREAM_UPDATE( amiga_stream_update )
{
amiga_state *state = device->machine->driver_data<amiga_state>();
amiga_audio *audio = (amiga_audio *)param;
int channum, sampoffs = 0;
@ -148,7 +150,7 @@ static STREAM_UPDATE( amiga_stream_update )
{
audio_channel *chan = &audio->channel[channum];
if (!chan->dmaenabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1))
dma_reload(chan);
dma_reload(state, chan);
chan->dmaenabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1;
}
@ -223,13 +225,13 @@ static STREAM_UPDATE( amiga_stream_update )
chan->curlocation++;
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)
chan->curlength--;
/* if we run out of data, reload the dma */
if (chan->curlength == 0)
dma_reload(chan);
dma_reload(state, chan);
}
/* latch the next byte of the sample */
@ -263,15 +265,13 @@ static STREAM_UPDATE( amiga_stream_update )
static DEVICE_START( amiga_sound )
{
running_machine *machine = device->machine;
amiga_audio *audio_state = get_safe_token(device);
int i;
/* allocate a new audio state */
audio_state = (amiga_audio *)downcast<legacy_device_base *>(device)->token();
for (i = 0; i < 4; 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 */
@ -284,7 +284,7 @@ DEVICE_GET_INFO( amiga_sound )
switch (state)
{
/* --- 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 --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(amiga_sound); break;

View File

@ -29,10 +29,18 @@
#include "machine/nvram.h"
static running_device *laserdisc;
static emu_timer *serial_timer;
static UINT8 serial_timer_active;
static UINT16 input_select;
class alg_state : public amiga_state
{
public:
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 );
@ -74,7 +82,7 @@ static VIDEO_START( alg )
/* 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));
amiga_set_genlock_color(4096);
amiga_set_genlock_color(machine, 4096);
}
@ -87,10 +95,11 @@ static VIDEO_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);
serial_timer_active = FALSE;
state->serial_timer = timer_alloc(machine, response_timer, NULL);
state->serial_timer_active = FALSE;
}
@ -109,44 +118,50 @@ static MACHINE_RESET( alg )
static TIMER_CALLBACK( response_timer )
{
alg_state *state = machine->driver_data<alg_state>();
/* 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)
mame_printf_debug("Sending serial data = %02X\n", data);
amiga_serial_in_w(machine, data);
}
/* if there's more to come, set another timer */
if (laserdisc_line_r(laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
timer_adjust_oneshot(serial_timer, amiga_get_serial_char_period(machine), 0);
if (laserdisc_line_r(state->laserdisc, LASERDISC_LINE_DATA_AVAIL) == ASSERT_LINE)
timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
else
serial_timer_active = FALSE;
state->serial_timer_active = FALSE;
}
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 (!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);
serial_timer_active = TRUE;
timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
state->serial_timer_active = TRUE;
}
}
static void serial_w(running_machine *machine, UINT16 data)
{
alg_state *state = machine->driver_data<alg_state>();
/* 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 (!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);
serial_timer_active = TRUE;
timer_adjust_oneshot(state->serial_timer, amiga_get_serial_char_period(machine), 0);
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)
{
alg_state *state = machine->driver_data<alg_state>();
/* bit 15 controls whether pin 9 is input/output */
/* 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 )
{
alg_state *state = field->port->machine->driver_data<alg_state>();
int x = 0, y = 0;
/* 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);
}
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 */
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 )
{
alg_state *state = field->port->machine->driver_data<alg_state>();
/* 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 )
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(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(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 )
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(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(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 )
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(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(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 */
};
static MACHINE_CONFIG_START( alg_r1, driver_device )
static MACHINE_CONFIG_START( alg_r1, alg_state )
/* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
@ -418,7 +440,7 @@ static MACHINE_CONFIG_START( alg_r1, driver_device )
MDRV_LASERDISC_OVERLAY(amiga, 512*2, 262, BITMAP_FORMAT_INDEXED16)
MDRV_LASERDISC_OVERLAY_CLIP((129-8)*2, (449+8-1)*2, 44-8, 244+8-1)
/* video hardware */
/* video hardware */
MDRV_LASERDISC_SCREEN_ADD_NTSC("screen", BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_REFRESH_RATE(59.997)
MDRV_SCREEN_SIZE(512*2, 262)
@ -658,6 +680,7 @@ ROM_END
static void alg_init(running_machine *machine)
{
alg_state *state = machine->driver_data<alg_state>();
static const amiga_machine_interface alg_intf =
{
ANGUS_CHIP_RAM_MASK,
@ -672,7 +695,7 @@ static void alg_init(running_machine *machine)
amiga_machine_config(machine, &alg_intf);
/* 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);
}

View File

@ -55,13 +55,14 @@
/*************************************
*
* Globals
*
*************************************/
class arcadia_state : public amiga_state
{
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 */
if ((data & 1) == 0)
{
UINT8 *coin_counter = device->machine->driver_data<arcadia_state>()->coin_counter;
if (coin_counter[0] > 0)
coin_counter[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 )
{
int coin = (FPTR)param;
UINT8 *coin_counter = field->port->machine->driver_data<arcadia_state>()->coin_counter;
/* return coin counter values */
return *(UINT8 *)param & 3;
return coin_counter[coin] & 3;
}
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 */
if (!oldval && newval && *counter < 3)
*counter += 1;
if (!oldval && newval && coin_counter[coin] < 3)
coin_counter[coin] += 1;
}
static void arcadia_reset_coins(running_machine *machine)
{
UINT8 *coin_counter = machine->driver_data<arcadia_state>()->coin_counter;
/* reset coin counters */
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 )
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(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(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_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 )
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( 0xc0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(coin_counter_r, &coin_counter[1])
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, 1)
PORT_START("JOY0DAT")
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_START("COINS")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(coin_changed_callback, &coin_counter[0])
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(coin_changed_callback, &coin_counter[1])
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, 1)
INPUT_PORTS_END
@ -287,7 +296,7 @@ static const mos6526_interface cia_1_intf =
DEVCB_NULL
};
static MACHINE_CONFIG_START( arcadia, driver_device )
static MACHINE_CONFIG_START( arcadia, arcadia_state )
/* basic machine hardware */
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)
{
arcadia_state *state = machine->driver_data<arcadia_state>();
static const amiga_machine_interface arcadia_intf =
{
ANGUS_CHIP_RAM_MASK,
@ -768,7 +778,7 @@ static void arcadia_init(running_machine *machine)
amiga_machine_config(machine, &arcadia_intf);
/* 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);
/* OnePlay bios is encrypted, TenPlay is not */

View File

@ -338,7 +338,7 @@ routines :
#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 )
{
@ -382,7 +382,7 @@ static WRITE8_DEVICE_HANDLER( cd32_cia_0_porta_w )
/* bit 2 = Power Led on Amiga */
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 )
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(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(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(0xa00000, 0xf7ffff) AM_NOP
AM_RANGE(0xf80000, 0xffffff) AM_ROM AM_REGION("user1", 0x0) /* Kickstart */
@ -433,98 +433,97 @@ 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)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
int i;
if (cubocd32_input_hack != NULL)
cubocd32_input_hack(machine);
if (state->input_hack != NULL)
(*state->input_hack)(machine);
potgo_value = potgo_value & 0x5500;
potgo_value |= data & 0xaa00;
state->potgo_value = state->potgo_value & 0x5500;
state->potgo_value |= data & 0xaa00;
for (i = 0; i < 8; i += 2)
for (i = 0; i < 8; i += 2)
{
UINT16 dir = 0x0200 << i;
if (data & dir)
{
UINT16 d = 0x0100 << i;
potgo_value &= ~d;
potgo_value |= data & d;
state->potgo_value &= ~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 p5dat = 0x0100 << (i * 4); /* data P5 */
if ((potgo_value & p5dir) && (potgo_value & p5dat))
cd32_shifter[i] = 8;
}
UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
if ((state->potgo_value & p5dir) && (state->potgo_value & p5dat))
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];
int i;
cubocd32_state *state = machine->driver_data<cubocd32_state>();
int i;
for (i = 0; i < 2; i++)
for (i = 0; i < 2; i++)
{
UINT8 but = 0x40 << i;
UINT16 p5dir = 0x0200 << (i * 4); /* output enable 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))
{
cd32_shifter[i]--;
if (cd32_shifter[i] < 0)
cd32_shifter[i] = 0;
state->cd32_shifter[i]--;
if (state->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" };
int i;
int i;
for (i = 0; i < 2; i++)
for (i = 0; i < 2; i++)
{
UINT16 p9dir = 0x0800 << (i * 4); /* output enable P9 */
UINT16 p9dat = 0x0400 << (i * 4); /* data P9 */
UINT16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
UINT16 p5dat = 0x0100 << (i * 4); /* data P5 */
/* p5 is floating in input-mode */
potgor &= ~p5dat;
potgor |= potgo_value & p5dat;
if (!(potgo_value & p9dir))
/* p5 is floating in input-mode */
potgor &= ~p5dat;
potgor |= state->potgo_value & p5dat;
if (!(state->potgo_value & p9dir))
potgor |= p9dat;
/* P5 output and 1 -> shift register is kept reset (Blue button) */
if ((potgo_value & p5dir) && (potgo_value & p5dat))
cd32_shifter[i] = 8;
/* shift at 1 == return one, >1 = return button states */
if (cd32_shifter[i] == 0)
/* P5 output and 1 -> shift register is kept reset (Blue button) */
if ((state->potgo_value & p5dir) && (state->potgo_value & p5dat))
state->cd32_shifter[i] = 8;
/* shift at 1 == return one, >1 = return button states */
if (state->cd32_shifter[i] == 0)
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;
}
return potgor;
}
return potgor;
}
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 )
@ -1051,11 +1050,12 @@ static const i2cmem_interface i2cmem_interface =
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 */
MDRV_CPU_ADD("maincpu", M68EC020, AMIGA_68EC020_PAL_CLOCK) /* 14.3 Mhz */
MDRV_CPU_PROGRAM_MAP(cd32_map)
MDRV_DEVICE_ADD("akiko", AKIKO, 0)
MDRV_MACHINE_RESET(amiga)
@ -1075,15 +1075,15 @@ static MACHINE_CONFIG_START( cd32, driver_device )
MDRV_VIDEO_UPDATE(amiga_aga)
/* sound hardware */
MDRV_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MDRV_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MDRV_SOUND_ADD("amiga", AMIGA, 3579545)
MDRV_SOUND_ROUTE(0, "lspeaker", 0.25)
MDRV_SOUND_ROUTE(1, "rspeaker", 0.25)
MDRV_SOUND_ROUTE(2, "rspeaker", 0.25)
MDRV_SOUND_ROUTE(3, "lspeaker", 0.25)
MDRV_SOUND_ADD("amiga", AMIGA, 3579545)
MDRV_SOUND_ROUTE(0, "lspeaker", 0.25)
MDRV_SOUND_ROUTE(1, "rspeaker", 0.25)
MDRV_SOUND_ROUTE(2, "rspeaker", 0.25)
MDRV_SOUND_ROUTE(3, "lspeaker", 0.25)
MDRV_SOUND_ADD( "cdda", CDDA, 0 )
MDRV_SOUND_ADD( "cdda", CDDA, 0 )
MDRV_SOUND_ROUTE( 0, "lspeaker", 0.50 )
MDRV_SOUND_ROUTE( 1, "rspeaker", 0.50 )
@ -1157,6 +1157,7 @@ ROM_END
static DRIVER_INIT( cd32 )
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
static const amiga_machine_interface cubocd32_intf =
{
AGA_CHIP_RAM_MASK,
@ -1171,14 +1172,11 @@ static DRIVER_INIT( cd32 )
amiga_machine_config(machine, &cubocd32_intf);
/* 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);
/* intialize akiko */
amiga_akiko_init(machine);
/* 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)
{
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);
amiga_chip_ram_w(r_A5 - 0x7ebe, 0x0000);
(*state->chip_ram_w)(state, r_A5 - 0x7ebe, 0x0000);
}
}
static DRIVER_INIT(cndypuzl)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = cndypuzl_input_hack;
state->input_hack = cndypuzl_input_hack;
}
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_A2 = (amiga_chip_ram_r(r_A5 - 0x7f00 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7f00 + 2));
amiga_chip_ram_w8(r_A2 + 0x1f, 0x00);
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(state, r_A2 + 0x1f, 0x00);
}
}
static DRIVER_INIT(haremchl)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = haremchl_input_hack;
state->input_hack = haremchl_input_hack;
}
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_A2 = (amiga_chip_ram_r(r_A5 - 0x7fe0 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fe0 + 2));
amiga_chip_ram_w8(r_A2 + 0x13, 0x00);
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(state, r_A2 + 0x13, 0x00);
}
}
static DRIVER_INIT(lsrquiz)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
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 ! */
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_A2 = (amiga_chip_ram_r(r_A5 - 0x7fdc + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fdc + 2));
amiga_chip_ram_w8(r_A2 + 0x17, 0x00);
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(state, r_A2 + 0x17, 0x00);
}
}
static DRIVER_INIT(lsrquiz2)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = lsrquiz2_input_hack;
state->input_hack = lsrquiz2_input_hack;
}
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_A2 = (amiga_chip_ram_r(r_A5 - 0x7fa2 + 0) << 16) | (amiga_chip_ram_r(r_A5 - 0x7fa2 + 2));
amiga_chip_ram_w8(r_A2 + 0x24, 0x00);
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(state, r_A2 + 0x24, 0x00);
}
}
static DRIVER_INIT(lasstixx)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = lasstixx_input_hack;
state->input_hack = lasstixx_input_hack;
}
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);
amiga_chip_ram_w(r_A5 - 0x7ed8, 0x0000);
(*state->chip_ram_w)(state, r_A5 - 0x7ed8, 0x0000);
}
}
static DRIVER_INIT(mgnumber)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
DRIVER_INIT_CALL(cd32);
cubocd32_input_hack = mgnumber_input_hack;
state->input_hack = mgnumber_input_hack;
}
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);
amiga_chip_ram_w8(r_A5 - 0x7eca, 0x00);
amiga_chip_ram_w8(state, r_A5 - 0x7eca, 0x00);
}
}
static DRIVER_INIT(mgprem11)
{
cubocd32_state *state = machine->driver_data<cubocd32_state>();
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 )
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(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(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -357,7 +357,7 @@ static const mos6526_interface cia_1_intf =
DEVCB_NULL
};
static MACHINE_CONFIG_START( mquake, driver_device )
static MACHINE_CONFIG_START( mquake, amiga_state )
/* basic machine hardware */
MDRV_CPU_ADD("maincpu", M68000, AMIGA_68000_NTSC_CLOCK)
@ -366,7 +366,7 @@ static MACHINE_CONFIG_START( mquake, driver_device )
MDRV_MACHINE_RESET(mquake)
MDRV_NVRAM_ADD_0FILL("nvram")
/* video hardware */
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
MDRV_SCREEN_ADD("screen", RASTER)
@ -447,6 +447,7 @@ ROM_END
static DRIVER_INIT(mquake)
{
amiga_state *state = machine->driver_data<amiga_state>();
static const amiga_machine_interface mquake_intf =
{
ANGUS_CHIP_RAM_MASK,
@ -459,7 +460,7 @@ static DRIVER_INIT(mquake)
amiga_machine_config(machine, &mquake_intf);
/* 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);
}

View File

@ -30,11 +30,11 @@
#include "machine/nvram.h"
class upscope_state : public driver_device
class upscope_state : public amiga_state
{
public:
upscope_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config) { }
: amiga_state(machine, config) { }
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 )
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(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(0xfc0000, 0xffffff) AM_ROM AM_REGION("user1", 0) /* System ROM */
@ -321,7 +321,7 @@ static MACHINE_CONFIG_START( upscope, upscope_state )
MDRV_MACHINE_RESET(amiga)
MDRV_NVRAM_ADD_0FILL("nvram")
/* video hardware */
/* video hardware */
MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
MDRV_SCREEN_ADD("screen", RASTER)
@ -391,6 +391,7 @@ ROM_END
static DRIVER_INIT( upscope )
{
upscope_state *state = machine->driver_data<upscope_state>();
static const amiga_machine_interface upscope_intf =
{
ANGUS_CHIP_RAM_MASK,
@ -403,11 +404,10 @@ static DRIVER_INIT( upscope )
amiga_machine_config(machine, &upscope_intf);
/* allocate NVRAM */
upscope_state *state = machine->driver_data<upscope_state>();
machine->device<nvram_device>("nvram")->set_base(state->m_nvram, sizeof(state->m_nvram));
/* 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);
}

View File

@ -13,13 +13,23 @@ Ernesto Corvi & Mariusz Wojcieszek
#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 */
/* 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 */
/* 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_LONG(x) (*(UINT32 *)&amiga_custom_regs[x])
#define CUSTOM_REG_LONG(x) (*(UINT32 *)&state->custom_regs[x])
/*
A = Angus
@ -354,22 +364,79 @@ struct _amiga_autoconfig_device
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 -----------*/
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 UINT16 (*amiga_chip_ram_r)(offs_t offset);
extern void (*amiga_chip_ram_w)(offs_t offset, UINT16 data);
extern void amiga_chip_ram_w8(offs_t offset, UINT8 data);
extern void amiga_chip_ram_w8(amiga_state *state, offs_t offset, UINT8 data);
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_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 -----------*/
DECLARE_LEGACY_SOUND_DEVICE(AMIGA, amiga_sound);
void amiga_audio_update(void);
void amiga_audio_data_w(int which, UINT16 data);
void amiga_audio_update(running_device *device);
void amiga_audio_data_w(running_device *device, int which, UINT16 data);
/*----------- defined in video/amiga.c -----------*/
extern const UINT16 amiga_expand_byte[256];
PALETTE_INIT( amiga );
VIDEO_START( 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);
void copper_setpc(UINT32 pc);
void amiga_set_genlock_color(UINT16 color);
void amiga_set_genlock_color(running_machine *machine, UINT16 color);
void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline);
void amiga_sprite_dma_reset(int which);
void amiga_sprite_enable_comparitor(int which, int enable);
void amiga_sprite_dma_reset(running_machine *machine, int which);
void amiga_sprite_enable_comparitor(running_machine *machine, int which, int enable);
/*----------- defined in video/amigaaga.c -----------*/
VIDEO_START( 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_sprite_dma_reset(int which);
void amiga_aga_sprite_enable_comparitor(int which, int enable);
void aga_palette_write(int color_reg, UINT16 data);
void aga_diwhigh_written(int written);
void amiga_aga_palette_write(running_machine *machine, int color_reg, UINT16 data);
void amiga_aga_diwhigh_written(running_machine *machine, int written);
#endif /* __AMIGA_H__ */

View File

@ -7,10 +7,23 @@ CuboCD32 definitions
#ifndef __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 -----------*/
extern void amiga_akiko_init(running_machine* machine);
extern READ32_HANDLER(amiga_akiko32_r);
extern WRITE32_HANDLER(amiga_akiko32_w);
READ32_DEVICE_HANDLER( amiga_akiko32_r );
WRITE32_DEVICE_HANDLER( amiga_akiko32_w );
DECLARE_LEGACY_DEVICE(AKIKO, akiko);
#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
*
*************************************/
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] =
{
/* 0x000 */
@ -183,23 +152,19 @@ static TIMER_CALLBACK( scanline_callback );
*
*************************************/
UINT16 (*amiga_chip_ram_r)(offs_t offset);
void (*amiga_chip_ram_w)(offs_t offset, UINT16 data);
static UINT16 amiga_chip_ram16_r(offs_t offset)
static UINT16 amiga_chip_ram16_r(amiga_state *state, offs_t offset)
{
extern const amiga_machine_interface *amiga_intf;
offset &= amiga_intf->chip_ram_mask;
return (offset < amiga_chip_ram_size) ? amiga_chip_ram[offset/2] : 0xffff;
offset &= state->intf->chip_ram_mask;
return (offset < state->chip_ram_size) ? state->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 &= amiga_intf->chip_ram_mask;
offset &= state->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];
if ( offset & 2 )
@ -211,22 +176,21 @@ static UINT16 amiga_chip_ram32_r(offs_t offset)
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 &= amiga_intf->chip_ram_mask;
offset &= state->intf->chip_ram_mask;
if (offset < amiga_chip_ram_size)
amiga_chip_ram[offset/2] = data;
if (offset < state->chip_ram_size)
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 &= amiga_intf->chip_ram_mask;
offset &= state->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];
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;
dat = amiga_chip_ram_r(offset);
dat = (*state->chip_ram_r)(state, offset);
if (offset & 0x01)
{
dat &= 0xff00;
@ -260,7 +224,7 @@ void amiga_chip_ram_w8(offs_t offset, UINT8 data)
dat &= 0x00ff;
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)
{
amiga_intf = intf;
amiga_state *state = machine->driver_data<amiga_state>();
state->intf = intf;
/* setup chipmem handlers */
if ( IS_AGA(intf) )
{
amiga_chip_ram_r = amiga_chip_ram32_r;
amiga_chip_ram_w = amiga_chip_ram32_w;
state->chip_ram_r = amiga_chip_ram32_r;
state->chip_ram_w = amiga_chip_ram32_w;
}
else
{
amiga_chip_ram_r = amiga_chip_ram16_r;
amiga_chip_ram_w = amiga_chip_ram16_w;
state->chip_ram_r = amiga_chip_ram16_r;
state->chip_ram_w = amiga_chip_ram16_w;
}
/* setup the timers */
amiga_irq_timer = timer_alloc(machine, amiga_irq_proc, NULL);
amiga_blitter_timer = timer_alloc(machine, amiga_blitter_proc, NULL);
state->irq_timer = timer_alloc(machine, amiga_irq_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)
{
amiga_state *state = device->machine->driver_data<amiga_state>();
address_space *space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM);
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);
/* set the overlay bit */
if ( IS_AGA(amiga_intf) )
if ( IS_AGA(state->intf) )
{
space->write_byte( 0xbfa001, 1 );
}
@ -317,14 +285,16 @@ static void amiga_m68k_reset(running_device *device)
MACHINE_RESET( amiga )
{
amiga_state *state = machine->driver_data<amiga_state>();
/* set m68k reset function */
m68k_set_reset_callback(machine->device("maincpu"), amiga_m68k_reset);
amiga_m68k_reset(machine->device("maincpu"));
/* call the system-specific callback */
if (amiga_intf->reset_callback)
(*amiga_intf->reset_callback)(machine);
if (state->intf->reset_callback)
(*state->intf->reset_callback)(machine);
/* start the scanline timer */
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 )
{
amiga_state *state = machine->driver_data<amiga_state>();
int scanline = param;
running_device *cia_0 = machine->device("cia_0");
running_device *cia_1 = machine->device("cia_1");
@ -354,8 +325,8 @@ static TIMER_CALLBACK( scanline_callback )
mos6526_tod_w(cia_0, 1);
/* call the system-specific callback */
if (amiga_intf->scanline0_callback != NULL)
(*amiga_intf->scanline0_callback)(machine);
if (state->intf->scanline0_callback != NULL)
(*state->intf->scanline0_callback)(machine);
}
/* on every scanline, clock the second CIA TOD */
@ -364,14 +335,14 @@ static TIMER_CALLBACK( scanline_callback )
/* render up to this 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);
else
amiga_render_scanline(machine, NULL, scanline);
}
/* force a sound update */
amiga_audio_update();
amiga_audio_update(state->sound_device);
/* set timer for next line */
scanline = (scanline + 1) % machine->primary_screen->height();
@ -388,6 +359,7 @@ static TIMER_CALLBACK( scanline_callback )
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);
/* Master interrupt switch */
@ -425,8 +397,10 @@ static void update_irqs(running_machine *machine)
static TIMER_CALLBACK( amiga_irq_proc )
{
amiga_state *state = machine->driver_data<amiga_state>();
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 shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
@ -482,21 +456,21 @@ static UINT32 blit_ascending(void)
/* fetch data for A */
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;
}
/* fetch data for B */
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;
}
/* fetch data for C */
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;
}
@ -552,7 +526,7 @@ static UINT32 blit_ascending(void)
/* write to the destination */
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;
}
}
@ -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_inclusive = (CUSTOM_REG(REG_BLTCON1) >> 3);
@ -607,21 +581,21 @@ static UINT32 blit_descending(void)
/* fetch data for A */
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;
}
/* fetch data for B */
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;
}
/* fetch data for C */
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;
}
@ -694,7 +668,7 @@ static UINT32 blit_descending(void)
/* write to the destination */
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;
}
}
@ -761,7 +735,7 @@ static UINT32 blit_descending(void)
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 singlemask = 0xffff;
@ -786,7 +760,7 @@ static UINT32 blit_line(void)
/* fetch data for C */
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 */
tempa = CUSTOM_REG(REG_BLTADAT) >> (CUSTOM_REG(REG_BLTCON0) >> 12);
@ -837,7 +811,7 @@ static UINT32 blit_line(void)
blitsum |= tempd;
/* 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 */
if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
@ -914,6 +888,7 @@ static UINT32 blit_line(void)
static TIMER_CALLBACK( amiga_blitter_proc )
{
amiga_state *state = machine->driver_data<amiga_state>();
UINT32 blitsum = 0;
/* logging */
@ -938,16 +913,16 @@ static TIMER_CALLBACK( amiga_blitter_proc )
switch (CUSTOM_REG(REG_BLTCON1) & 0x0003)
{
case 0: /* ascending */
blitsum = blit_ascending();
blitsum = blit_ascending(state);
break;
case 2: /* descending */
blitsum = blit_descending();
blitsum = blit_descending(state);
break;
case 1: /* line */
case 3:
blitsum = blit_line();
blitsum = blit_line(state);
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);
/* 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)
{
amiga_state *state = space->machine->driver_data<amiga_state>();
int ticks, width, height, blittime;
/* 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 */
if ( IS_AGA(amiga_intf) )
if ( IS_AGA(state->intf) )
blittime /= 2;
/* signal blitter busy */
CUSTOM_REG(REG_DMACON) |= 0x4000;
/* 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)
{
amiga_state *state = machine->driver_data<amiga_state>();
int clock = cputag_get_clock(machine, "maincpu");
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_SERDATR) = 0x3000;
switch (amiga_intf->chip_ram_mask)
switch (state->intf->chip_ram_mask)
{
case 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:
CUSTOM_REG(REG_VPOSR) |= 0x2000;
CUSTOM_REG(REG_DENISEID) = 0x00FC;
if (IS_AGA(amiga_intf))
if (IS_AGA(state->intf))
{
CUSTOM_REG(REG_VPOSR) |= 0x0300;
CUSTOM_REG(REG_DENISEID) = 0x00F8;
@ -1170,6 +1147,7 @@ static void custom_reset(running_machine *machine)
READ16_HANDLER( amiga_custom_r )
{
amiga_state *state = space->machine->driver_data<amiga_state>();
UINT16 temp;
switch (offset & 0xff)
@ -1182,17 +1160,11 @@ READ16_HANDLER( amiga_custom_r )
case REG_VPOSR:
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);
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:
CUSTOM_REG(REG_SERDATR) &= ~0x4000;
@ -1200,13 +1172,13 @@ READ16_HANDLER( amiga_custom_r )
return CUSTOM_REG(REG_SERDATR);
case REG_JOY0DAT:
if (amiga_intf->joy0dat_r != NULL)
return (*amiga_intf->joy0dat_r)(space->machine);
if (state->intf->joy0dat_r != NULL)
return (*state->intf->joy0dat_r)(space->machine);
return input_port_read_safe(space->machine, "JOY0DAT", 0xffff);
case REG_JOY1DAT:
if (amiga_intf->joy1dat_r != NULL)
return (*amiga_intf->joy1dat_r)(space->machine);
if (state->intf->joy1dat_r != NULL)
return (*state->intf->joy1dat_r)(space->machine);
return input_port_read_safe(space->machine, "JOY1DAT", 0xffff);
case REG_ADKCONR:
@ -1222,8 +1194,8 @@ READ16_HANDLER( amiga_custom_r )
return input_port_read_safe(space->machine, "POT1DAT", 0x0000);
case REG_DSKBYTR:
if (amiga_intf->dskbytr_r != NULL)
return (*amiga_intf->dskbytr_r)(space->machine);
if (state->intf->dskbytr_r != NULL)
return (*state->intf->dskbytr_r)(space->machine);
return 0x0000;
case REG_INTENAR:
@ -1233,17 +1205,11 @@ READ16_HANDLER( amiga_custom_r )
return CUSTOM_REG(REG_INTREQ);
case REG_COPJMP1:
if (IS_AGA(amiga_intf))
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP1LCH));
break;
case REG_COPJMP2:
if (IS_AGA(amiga_intf))
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP2LCH));
break;
case REG_CLXDAT:
@ -1271,6 +1237,8 @@ READ16_HANDLER( amiga_custom_r )
static TIMER_CALLBACK( finish_serial_write )
{
amiga_state *state = machine->driver_data<amiga_state>();
/* mark the transfer buffer empty */
CUSTOM_REG(REG_SERDATR) |= 0x3000;
@ -1281,6 +1249,7 @@ static TIMER_CALLBACK( finish_serial_write )
WRITE16_HANDLER( amiga_custom_w )
{
amiga_state *state = space->machine->driver_data<amiga_state>();
running_device *cia_0;
running_device *cia_1;
UINT16 temp;
@ -1299,18 +1268,18 @@ WRITE16_HANDLER( amiga_custom_w )
break;
case REG_DSKLEN:
if (amiga_intf->dsklen_w != NULL)
(*amiga_intf->dsklen_w)(space->machine, data);
if (state->intf->dsklen_w != NULL)
(*state->intf->dsklen_w)(space->machine, data);
break;
case REG_POTGO:
if (amiga_intf->potgo_w != NULL)
(*amiga_intf->potgo_w)(space->machine, data);
if (state->intf->potgo_w != NULL)
(*state->intf->potgo_w)(space->machine, data);
break;
case REG_SERDAT:
if (amiga_intf->serdat_w != NULL)
(*amiga_intf->serdat_w)(space->machine, data);
if (state->intf->serdat_w != NULL)
(*state->intf->serdat_w)(space->machine, data);
CUSTOM_REG(REG_SERDATR) &= ~0x3000;
timer_set(space->machine, amiga_get_serial_char_period(space->machine), NULL, 0, finish_serial_write);
break;
@ -1325,7 +1294,7 @@ WRITE16_HANDLER( amiga_custom_w )
break;
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;
if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x8000;
@ -1333,7 +1302,7 @@ WRITE16_HANDLER( amiga_custom_w )
break;
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;
if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800;
@ -1342,7 +1311,7 @@ WRITE16_HANDLER( amiga_custom_w )
break;
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) |= 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_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;
case REG_SPR0PTL: case REG_SPR1PTL: case REG_SPR2PTL: case REG_SPR3PTL:
case REG_SPR4PTL: case REG_SPR5PTL: case REG_SPR6PTL: case REG_SPR7PTL:
if (IS_AGA(amiga_intf))
amiga_aga_sprite_dma_reset((offset - REG_SPR0PTL) / 2);
else
amiga_sprite_dma_reset((offset - REG_SPR0PTL) / 2);
amiga_sprite_dma_reset(space->machine, (offset - REG_SPR0PTL) / 2);
break;
case REG_SPR0CTL: case REG_SPR1CTL: case REG_SPR2CTL: case REG_SPR3CTL:
case REG_SPR4CTL: case REG_SPR5CTL: case REG_SPR6CTL: case REG_SPR7CTL:
/* disable comparitor on writes here */
if (IS_AGA(amiga_intf))
amiga_aga_sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, FALSE);
else
amiga_sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, FALSE);
amiga_sprite_enable_comparitor(space->machine, (offset - REG_SPR0CTL) / 4, FALSE);
break;
case REG_SPR0DATA: case REG_SPR1DATA: case REG_SPR2DATA: case REG_SPR3DATA:
case REG_SPR4DATA: case REG_SPR5DATA: case REG_SPR6DATA: case REG_SPR7DATA:
/* enable comparitor on writes here */
if (IS_AGA(amiga_intf))
amiga_aga_sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, TRUE);
else
amiga_sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, TRUE);
amiga_sprite_enable_comparitor(space->machine, (offset - REG_SPR0DATA) / 4, TRUE);
break;
case REG_COP1LCH: case REG_COP2LCH:
data &= ( amiga_intf->chip_ram_mask >> 16 );
data &= ( state->intf->chip_ram_mask >> 16 );
break;
case REG_COPJMP1:
if (IS_AGA(amiga_intf))
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP1LCH));
break;
case REG_COPJMP2:
if (IS_AGA(amiga_intf))
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
else
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
amiga_copper_setpc(space->machine, CUSTOM_REG_LONG(REG_COP2LCH));
break;
case REG_DDFSTRT:
@ -1413,7 +1367,7 @@ WRITE16_HANDLER( amiga_custom_w )
break;
case REG_DMACON:
amiga_audio_update();
amiga_audio_update(state->sound_device);
/* bits BBUSY (14) and BZERO (13) are read-only */
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 ( ( 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;
@ -1432,7 +1386,7 @@ WRITE16_HANDLER( amiga_custom_w )
CUSTOM_REG(offset) = data;
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 */
update_irqs(space->machine);
break;
@ -1451,13 +1405,13 @@ WRITE16_HANDLER( amiga_custom_w )
CUSTOM_REG(offset) = data;
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 */
update_irqs(space->machine);
break;
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));
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_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:
amiga_audio_update();
amiga_audio_update(state->sound_device);
break;
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;
case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH:
case REG_BPL5PTH: case REG_BPL6PTH:
data &= ( amiga_intf->chip_ram_mask >> 16 );
data &= ( state->intf->chip_ram_mask >> 16 );
break;
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_COLOR24: case REG_COLOR25: case REG_COLOR26: case REG_COLOR27:
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
{
@ -1506,19 +1460,19 @@ WRITE16_HANDLER( amiga_custom_w )
break;
case REG_DIWSTRT:
case REG_DIWSTOP:
if (IS_AGA(amiga_intf))
aga_diwhigh_written(0);
if (IS_AGA(state->intf))
amiga_aga_diwhigh_written(space->machine, 0);
break;
case REG_DIWHIGH:
if (IS_AGA(amiga_intf))
aga_diwhigh_written(1);
if (IS_AGA(state->intf))
amiga_aga_diwhigh_written(space->machine, 1);
break;
default:
break;
}
if (IS_AGA(amiga_intf))
if (IS_AGA(state->intf))
CUSTOM_REG(offset) = data;
else
if (offset <= REG_COLOR31)
@ -1535,6 +1489,7 @@ WRITE16_HANDLER( amiga_custom_w )
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);
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)
{
amiga_state *state = machine->driver_data<amiga_state>();
UINT32 divisor = (CUSTOM_REG(REG_SERPER) & 0x7fff) + 1;
UINT32 baud = cputag_get_clock(machine, "maincpu") / 2 / divisor;
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)
{
amiga_state *state = machine->driver_data<amiga_state>();
autoconfig_device *dev, **d;
/* 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 */
dev = auto_alloc(machine, autoconfig_device);
dev->next = NULL;
for (d = &autoconfig_list; *d; d = &(*d)->next) ;
for (d = &state->autoconfig_list; *d; d = &(*d)->next) ;
*d = dev;
/* 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)
{
amiga_state *state = machine->driver_data<amiga_state>();
autoconfig_device *dev;
/* 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)
{
(*dev->device.uninstall)(machine, dev->base);
@ -1610,7 +1568,7 @@ static void autoconfig_reset(running_machine *machine)
}
/* 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 )
{
amiga_state *state = space->machine->driver_data<amiga_state>();
autoconfig_device *cur_autoconfig = state->cur_autoconfig;
UINT8 byte;
int i;
@ -1760,6 +1720,8 @@ READ16_HANDLER( amiga_autoconfig_r )
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;
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);
if (cur_autoconfig->base && cur_autoconfig->device.install)
(*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) */
static struct akiko_def
typedef struct _akiko_state akiko_state;
struct _akiko_state
{
running_machine *machine;
address_space *space;
/* chunky to planar converter */
UINT32 c2p_input_buffer[8];
UINT32 c2p_output_buffer[8];
@ -61,75 +65,88 @@ static struct akiko_def
emu_timer *dma_timer;
emu_timer *frame_timer;
running_device *i2cmem;
} akiko;
};
static TIMER_CALLBACK(akiko_dma_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 ) {
cdrom_close(akiko.cdrom);
akiko.cdrom = (cdrom_file *)NULL;
assert(device != NULL);
assert(device->type() == AKIKO);
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;
akiko.c2p_output_index = 0;
running_machine *machine = device->machine;
akiko_state *state = get_safe_token(device);
akiko.i2c_scl_out = 0;
akiko.i2c_scl_dir = 0;
akiko.i2c_sda_out = 0;
akiko.i2c_sda_dir = 0;
state->machine = machine;
state->space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM);
state->c2p_input_index = 0;
state->c2p_output_index = 0;
akiko.cdrom_status[0] = akiko.cdrom_status[1] = 0;
akiko.cdrom_address[0] = akiko.cdrom_address[1] = 0;
akiko.cdrom_track_index = 0;
akiko.cdrom_lba_start = 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");
state->i2c_scl_out = 0;
state->i2c_scl_dir = 0;
state->i2c_sda_out = 0;
state->i2c_sda_dir = 0;
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 */
if ( akiko.cdrom != NULL && cdrom_get_last_track(akiko.cdrom) )
if ( state->cdrom != NULL && cdrom_get_last_track(state->cdrom) )
{
UINT8 *p;
int i, addrctrl = cdrom_get_adr_control( akiko.cdrom, 0 );
int i, addrctrl = cdrom_get_adr_control( state->cdrom, 0 );
UINT32 discend;
discend = cdrom_get_track_start(akiko.cdrom,cdrom_get_last_track(akiko.cdrom)-1);
discend += cdrom_get_toc(akiko.cdrom)->tracks[cdrom_get_last_track(akiko.cdrom)-1].frames;
discend = cdrom_get_track_start(state->cdrom,cdrom_get_last_track(state->cdrom)-1);
discend += cdrom_get_toc(state->cdrom)->tracks[cdrom_get_last_track(state->cdrom)-1].frames;
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);
memset( akiko.cdrom_toc, 0, 13*akiko.cdrom_numtracks);
state->cdrom_toc = auto_alloc_array(machine, UINT8, 13*state->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[3] = 0xa0; /* first track */
p[8] = 1;
p += 13;
p[1] = 0x01;
p[3] = 0xa1; /* last track */
p[8] = cdrom_get_last_track(akiko.cdrom);
p[8] = cdrom_get_last_track(state->cdrom);
p += 13;
p[1] = 0x01;
p[3] = 0xa2; /* disc end */
@ -138,12 +155,12 @@ void amiga_akiko_init(running_machine* machine)
p[10] = discend & 0xff;
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);
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[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);
akiko.i2c_sda_out = BIT(data,30);
akiko.i2c_scl_dir = BIT(data,15);
akiko.i2c_sda_dir = BIT(data,14);
state->i2c_scl_out = BIT(data,31);
state->i2c_sda_out = BIT(data,30);
state->i2c_scl_dir = BIT(data,15);
state->i2c_sda_dir = BIT(data,14);
i2cmem_scl_write( akiko.i2cmem, akiko.i2c_scl_out );
i2cmem_sda_write( akiko.i2cmem, akiko.i2c_sda_out );
i2cmem_scl_write( state->i2cmem, state->i2c_scl_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;
if ( akiko.i2c_scl_dir )
if ( state->i2c_scl_dir )
{
v |= akiko.i2c_scl_out << 31;
v |= state->i2c_scl_out << 31;
}
else
{
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
{
v |= i2cmem_sda_read( akiko.i2cmem ) << 30;
v |= i2cmem_sda_read( state->i2cmem ) << 30;
}
v |= akiko.i2c_scl_dir << 15;
v |= akiko.i2c_sda_dir << 14;
v |= state->i2c_scl_dir << 15;
v |= state->i2c_sda_dir << 14;
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;
akiko.c2p_input_index++;
akiko.c2p_input_index &= 7;
akiko.c2p_output_index = 0;
state->c2p_input_buffer[state->c2p_input_index] = data;
state->c2p_input_index++;
state->c2p_input_index &= 7;
state->c2p_output_index = 0;
}
static UINT32 akiko_c2p_read(void)
static UINT32 akiko_c2p_read(akiko_state *state)
{
UINT32 val;
if ( akiko.c2p_output_index == 0 )
if ( state->c2p_output_index == 0 )
{
int 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++) {
if (akiko.c2p_input_buffer[7 - (i >> 5)] & (1 << (i & 31)))
akiko.c2p_output_buffer[i & 7] |= 1 << (i >> 3);
for (i = 0; i < 8 * 32; i++)
{
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;
val = akiko.c2p_output_buffer[akiko.c2p_output_index];
akiko.c2p_output_index++;
akiko.c2p_output_index &= 7;
state->c2p_input_index = 0;
val = state->c2p_output_buffer[state->c2p_output_index];
state->c2p_output_index++;
state->c2p_output_index &= 7;
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)
{
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)
{
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_audio_active(cdda) && cdda_audio_paused(cdda) != pause )
@ -301,19 +319,19 @@ static void akiko_cdda_pause( running_machine *machine, int pause )
if ( pause )
{
timer_reset( akiko.frame_timer, attotime_never );
timer_reset( state->frame_timer, attotime_never );
}
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;
@ -341,33 +359,34 @@ static UINT8 akiko_cdda_getstatus( running_machine *machine, UINT32 *lba )
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" );
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)
{
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;
if (cdda != NULL)
{
UINT8 s = akiko_cdda_getstatus(machine, NULL);
UINT8 s = akiko_cdda_getstatus(state, NULL);
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)
{
akiko_state *state = (akiko_state *)ptr;
UINT8 buf[2352];
int index;
if ( (akiko.cdrom_dmacontrol & 0x04000000) == 0 )
if ( (state->cdrom_dmacontrol & 0x04000000) == 0 )
return;
if ( akiko.cdrom_readreqmask == 0 )
if ( state->cdrom_readreqmask == 0 )
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 );
UINT32 datasize = cdrom_get_toc( akiko.cdrom )->tracks[track].datasize;
UINT32 subsize = cdrom_get_toc( akiko.cdrom )->tracks[track].subsize;
amiga_state *amiga = machine->driver_data<amiga_state>();
UINT32 track = cdrom_get_track( state->cdrom, state->cdrom_lba_cur );
UINT32 datasize = cdrom_get_toc( state->cdrom )->tracks[track].datasize;
UINT32 subsize = cdrom_get_toc( state->cdrom )->tracks[track].subsize;
int i;
UINT32 curmsf = lba_to_msf( akiko.cdrom_lba_cur );
UINT32 curmsf = lba_to_msf( state->cdrom_lba_cur );
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 );
buf[12] = (curmsf >> 16) & 0xff;
@ -414,22 +435,22 @@ static TIMER_CALLBACK(akiko_dma_proc)
buf[15] = 0x01; /* mode1 */
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;
}
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;
}
}
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 )
{
@ -439,39 +460,39 @@ static TIMER_CALLBACK(akiko_dma_proc)
data <<= 8;
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 );
akiko.cdrom_readreqmask &= ~( 1 << index );
akiko.cdrom_lba_cur++;
state->cdrom_readmask |= ( 1 << index );
state->cdrom_readreqmask &= ~( 1 << index );
state->cdrom_lba_cur++;
}
if ( akiko.cdrom_readreqmask == 0 )
akiko_set_cd_status(machine, 0x04000000);
if ( state->cdrom_readreqmask == 0 )
akiko_set_cd_status(state, 0x04000000);
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;
if ( akiko.cdrom_lba_start > akiko.cdrom_lba_end )
if ( state->cdrom_lba_start > state->cdrom_lba_end )
return;
if ( akiko.cdrom_speed == 0 )
if ( state->cdrom_speed == 0 )
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_buffer[32];
int i;
@ -488,23 +509,24 @@ static void akiko_setup_response( address_space *space, int len, UINT8 *r1 )
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 )
{
akiko_state *state = (akiko_state *)ptr;
UINT8 resp[32];
UINT8 cddastatus;
if ( akiko.cdrom_status[0] & 0x10000000 )
if ( state->cdrom_status[0] & 0x10000000 )
return;
cddastatus = akiko_cdda_getstatus(machine, NULL);
cddastatus = akiko_cdda_getstatus(state, NULL);
if ( cddastatus == 0x11 || cddastatus == 0x12 )
return;
@ -516,39 +538,38 @@ static TIMER_CALLBACK( akiko_cd_delayed_cmd )
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 );
resp[0] = 0x06;
if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 )
if ( state->cdrom == NULL || state->cdrom_numtracks == 0 )
{
resp[1] = 0x80;
akiko_setup_response( space, 15, resp );
akiko_setup_response( state, 15, resp );
}
else
{
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];
if ( akiko.cdrom_status[0] & 0x10000000 )
if ( state->cdrom_status[0] & 0x10000000 )
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;
int cmd = space->read_byte( cmd_addr );
UINT32 cmd_addr = state->cdrom_address[1] + 0x200 + state->cdrom_cmd_start;
int cmd = state->space->read_byte( cmd_addr );
memset( resp, 0, sizeof( resp ) );
resp[0] = cmd;
@ -561,27 +582,27 @@ static void akiko_update_cdrom(address_space *space)
{
resp[1] = 0x00;
if ( akiko_cdda_getstatus(space->machine, NULL) == 0x11 )
if ( akiko_cdda_getstatus(state, NULL) == 0x11 )
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) */
{
resp[1] = 0x00;
if ( akiko_cdda_getstatus(space->machine, NULL) == 0x11 )
if ( akiko_cdda_getstatus(state, NULL) == 0x11 )
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 */
{
@ -590,67 +611,67 @@ static void akiko_update_cdrom(address_space *space)
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 += ( 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;
akiko_setup_response( space, 2, resp );
akiko_setup_response( state, 2, resp );
}
else
{
startpos = lba_from_triplet( &cmdbuf[1] );
endpos = lba_from_triplet( &cmdbuf[4] );
akiko_cdda_stop(space->machine);
akiko_cdda_stop(state);
resp[1] = 0x00;
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 );
akiko.cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
akiko.cdrom_lba_start = startpos;
akiko.cdrom_lba_end = 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 );
state->cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
state->cdrom_lba_start = startpos;
state->cdrom_lba_end = endpos;
resp[1] = 0x02;
}
else if ( cmdbuf[10] & 0x04 )
{
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;
}
else
{
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 */
akiko.cdrom_track_index = i + 2;
akiko.cdrom_track_index %= akiko.cdrom_numtracks;
state->cdrom_track_index = i + 2;
state->cdrom_track_index %= state->cdrom_numtracks;
break;
}
}
}
akiko_setup_response( space, 2, resp );
akiko_setup_response( state, 2, resp );
}
}
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;
}
@ -660,7 +681,7 @@ static void akiko_update_cdrom(address_space *space)
resp[1] = 0x00;
(void)akiko_cdda_getstatus( space->machine, &lba );
(void)akiko_cdda_getstatus(state, &lba);
if ( lba > 0 )
{
@ -669,8 +690,8 @@ static void akiko_update_cdrom(address_space *space)
UINT32 track;
int addrctrl;
track = cdrom_get_track(akiko.cdrom, lba);
addrctrl = cdrom_get_adr_control(akiko.cdrom, track);
track = cdrom_get_track(state->cdrom, lba);
addrctrl = cdrom_get_adr_control(state->cdrom, track);
resp[2] = 0x00;
resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
@ -678,7 +699,7 @@ static void akiko_update_cdrom(address_space *space)
resp[5] = 0; /* index */
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 */
resp[6] = (track_pos >> 16) & 0xff;
@ -696,18 +717,18 @@ static void akiko_update_cdrom(address_space *space)
resp[1] = 0x80;
}
akiko_setup_response( space, 15, resp );
akiko_setup_response( state, 15, resp );
}
else if ( cmd == 0x07 ) /* check door status */
{
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;
akiko_setup_response( space, 20, resp );
akiko_setup_response( state, 20, resp );
break;
}
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;
if ( LOG_AKIKO && offset < (0x30/4) )
@ -729,48 +752,48 @@ READ32_HANDLER(amiga_akiko32_r)
switch( offset )
{
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;
case 0x04/4: /* CDROM STATUS 1 */
return akiko.cdrom_status[0];
return state->cdrom_status[0];
case 0x08/4: /* CDROM STATUS 2 */
return akiko.cdrom_status[1];
return state->cdrom_status[1];
case 0x10/4: /* CDROM ADDRESS 1 */
return akiko.cdrom_address[0];
return state->cdrom_address[0];
case 0x14/4: /* CDROM ADDRESS 2 */
return akiko.cdrom_address[1];
return state->cdrom_address[1];
case 0x18/4: /* CDROM COMMAND 1 */
akiko_update_cdrom(space);
retval = akiko.cdrom_cmd_start;
akiko_update_cdrom(state);
retval = state->cdrom_cmd_start;
retval <<= 8;
retval |= akiko.cdrom_cmd_resp;
retval |= state->cdrom_cmd_resp;
retval <<= 8;
return retval;
case 0x1C/4: /* CDROM COMMAND 2 */
akiko_update_cdrom(space);
retval = akiko.cdrom_cmd_end;
akiko_update_cdrom(state);
retval = state->cdrom_cmd_end;
retval <<= 16;
return retval;
case 0x20/4: /* CDROM DMA SECTOR READ MASK */
retval = akiko.cdrom_readmask << 16;
retval = state->cdrom_readmask << 16;
return retval;
case 0x24/4: /* CDROM DMA ENABLE? */
retval = akiko.cdrom_dmacontrol;
retval = state->cdrom_dmacontrol;
return retval;
case 0x30/4: /* NVRAM */
return akiko_nvram_read(space->machine);
return akiko_nvram_read(state);
case 0x38/4: /* C2P */
return akiko_c2p_read();
return akiko_c2p_read(state);
default:
break;
@ -779,8 +802,11 @@ READ32_HANDLER(amiga_akiko32_r)
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) )
{
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 )
{
case 0x04/4: /* CDROM STATUS 1 */
akiko.cdrom_status[0] = data;
state->cdrom_status[0] = data;
break;
case 0x08/4: /* CDROM STATUS 2 */
akiko.cdrom_status[1] = data;
akiko.cdrom_status[0] &= data;
state->cdrom_status[1] = data;
state->cdrom_status[0] &= data;
break;
case 0x10/4: /* CDROM ADDRESS 1 */
akiko.cdrom_address[0] = data;
state->cdrom_address[0] = data;
break;
case 0x14/4: /* CDROM ADDRESS 2 */
akiko.cdrom_address[1] = data;
state->cdrom_address[1] = data;
break;
case 0x18/4: /* CDROM COMMAND 1 */
if ( ACCESSING_BITS_16_23 )
akiko.cdrom_cmd_start = ( data >> 16 ) & 0xff;
state->cdrom_cmd_start = ( data >> 16 ) & 0xff;
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;
case 0x1C/4: /* CDROM COMMAND 2 */
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;
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 ( ACCESSING_BITS_16_31 )
{
akiko.cdrom_readreqmask = (data >> 16);
akiko.cdrom_readmask = 0;
state->cdrom_readreqmask = (data >> 16);
state->cdrom_readmask = 0;
}
break;
case 0x24/4: /* CDROM DMA ENABLE? */
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 )
akiko_start_dma();
akiko_start_dma(state);
}
akiko.cdrom_dmacontrol = data;
state->cdrom_dmacontrol = data;
break;
case 0x30/4:
akiko_nvram_write(space->machine, data);
akiko_nvram_write(state, data);
break;
case 0x38/4:
akiko_c2p_write(data);
akiko_c2p_write(state, data);
break;
default:
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
@ -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
@ -75,7 +28,7 @@ static int wait_offset = 3;
*************************************/
/* 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,
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
};
/* 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 )
{
amiga_state *state = machine->driver_data<amiga_state>();
int j;
/* 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 pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4);
separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
state->separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
state->separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
}
#if GUESS_COPPER_OFFSET
state->wait_offset = 3;
#endif
/* 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 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);
/* 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))
if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (state->last_scanline >= 20 && hvpos < latchedpos))
return hvpos;
/* 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)
logerror("copper_setpc(%06x)\n", pc);
copper_pc = pc;
copper_waiting = FALSE;
state->copper_pc = pc;
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;
/* bail if not enabled */
@ -219,34 +182,34 @@ static int copper_execute_next(running_machine *machine, int xpos)
return 511;
/* flush any pending writes */
if (copper_pending_offset)
if (state->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);
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);
copper_pending_offset = 0;
amiga_custom_w(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), state->copper_pending_offset, state->copper_pending_data, 0xffff);
state->copper_pending_offset = 0;
}
/* 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 ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
if ((curpos & state->copper_waitmask) >= (state->copper_waitval & state->copper_waitmask) &&
(!state->copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{
copper_waiting = FALSE;
state->copper_waiting = FALSE;
#if GUESS_COPPER_OFFSET
return xpos + COPPER_CYCLES_TO_PIXELS(1 + wait_offset);
return xpos + COPPER_CYCLES_TO_PIXELS(1 + state->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))
if (((curpos | 0xff) & state->copper_waitmask) < (state->copper_waitval & state->copper_waitmask))
return 511;
/* else just advance another pixel */
@ -255,17 +218,17 @@ static int copper_execute_next(running_machine *machine, int xpos)
}
/* fetch the first data word */
word0 = amiga_chip_ram_r(copper_pc);
copper_pc += 2;
word0 = (*state->chip_ram_r)(state, state->copper_pc);
state->copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
/* fetch the second data word */
word1 = amiga_chip_ram_r(copper_pc);
copper_pc += 2;
word1 = (*state->chip_ram_r)(state, state->copper_pc);
state->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);
logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", state->last_scanline, xpos / 2, state->copper_pc, word0, word1);
/* handle a move */
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 */
/* needed for Arcadia's Fast Break */
copper_pending_offset = word0;
copper_pending_data = word1;
state->copper_pending_offset = word0;
state->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);
logerror("%02X.%02X: Aborting copper on illegal write\n", state->last_scanline, xpos / 2);
copper_waitval = 0xffff;
copper_waitmask = 0xffff;
copper_waitblit = FALSE;
copper_waiting = TRUE;
state->copper_waitval = 0xffff;
state->copper_waitmask = 0xffff;
state->copper_waitblit = FALSE;
state->copper_waiting = TRUE;
return 511;
}
}
else
{
/* extract common wait/skip values */
copper_waitval = word0 & 0xfffe;
copper_waitmask = word1 | 0x8001;
copper_waitblit = (~word1 >> 15) & 1;
state->copper_waitval = word0 & 0xfffe;
state->copper_waitmask = word1 | 0x8001;
state->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));
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 */
else
{
int curpos = (last_scanline << 8) | (xpos >> 1);
int curpos = (state->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));
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 ((curpos & copper_waitmask) >= (copper_waitval & copper_waitmask) &&
(!copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
if ((curpos & state->copper_waitmask) >= (state->copper_waitval & state->copper_waitmask) &&
(!state->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;
state->copper_pc += 4;
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;
sprite_dma_live_mask |= 1 << which;
amiga_state *state = machine->driver_data<amiga_state>();
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)
{
sprite_comparitor_enable_mask |= 1 << which;
sprite_dma_live_mask &= ~(1 << which);
state->sprite_comparitor_enable_mask |= 1 << which;
state->sprite_dma_live_mask &= ~(1 << which);
}
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 num, maxdma;
@ -388,15 +368,15 @@ static void update_sprite_dma(int scanline)
int vstart, vstop;
/* 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 */
sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask &= ~bitmask;
state->sprite_comparitor_enable_mask &= ~bitmask;
state->sprite_dma_reload_mask &= ~bitmask;
/* 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_SPR0CTL + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
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) = (*state->chip_ram_r)(state, 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: 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 (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 we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask |= 1 << num;
state->sprite_ctl_written &= ~bitmask;
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_SPR0DATB + 4 * num) = 0;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}
/* 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);
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));
fetch_sprite_data(state, scanline, num);
}
}
}
@ -443,37 +421,37 @@ static void update_sprite_dma(int scanline)
INLINE UINT32 interleave_sprite_data(UINT16 lobits, UINT16 hibits)
{
return (expand_byte[lobits & 0xff] << 0) | (expand_byte[lobits >> 8] << 16) |
(expand_byte[hibits & 0xff] << 1) | (expand_byte[hibits >> 8] << 17);
return (amiga_expand_byte[lobits & 0xff] << 0) | (amiga_expand_byte[lobits >> 8] << 16) |
(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 num, pair;
/* loop over sprite channels */
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 (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);
if (hstart == x)
{
sprite_remain[num] = 16;
sprite_shiftreg[num] = interleave_sprite_data(CUSTOM_REG(REG_SPR0DATA + 4 * num), CUSTOM_REG(REG_SPR0DATB + 4 * num));
state->sprite_remain[num] = 16;
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 */
if (sprite_remain[num] != 0)
if (state->sprite_remain[num] != 0)
{
sprite_remain[num]--;
pixels |= (sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
sprite_shiftreg[num] <<= 2;
state->sprite_remain[num]--;
pixels |= (state->sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
state->sprite_shiftreg[num] <<= 2;
}
}
@ -491,6 +469,7 @@ static int get_sprite_pixel(int x)
0x0000, 0x0800, 0x2000, 0x2a00, 0x4000, 0x4c00, 0x7000, 0x7e00
};
int collide;
const int esprm = 0x10, osprm = 0x10;
/* OR the two sprite bits together so we only have 1 bit per sprite */
collide = pixels | (pixels >> 1);
@ -513,18 +492,19 @@ static int get_sprite_pixel(int x)
sprite present bitmask in bits 6-9
topmost sprite pair index in bits 10-11
*/
UINT32 result = (collide << 6) | (pair << 10);
/* attached case */
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 */
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 */
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;
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;
if (planes >= 2)
@ -568,6 +548,11 @@ INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs)
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)
{
case 0:
ham_color = CUSTOM_REG(REG_COLOR00 + (newpix & 0xf));
state->ham_color = CUSTOM_REG(REG_COLOR00 + (newpix & 0xf));
break;
case 1:
ham_color = (ham_color & 0xff0) | ((newpix & 0xf) << 0);
state->ham_color = (state->ham_color & 0xff0) | ((newpix & 0xf) << 0);
break;
case 2:
ham_color = (ham_color & 0x0ff) | ((newpix & 0xf) << 8);
state->ham_color = (state->ham_color & 0x0ff) | ((newpix & 0xf) << 8);
break;
case 3:
ham_color = (ham_color & 0xf0f) | ((newpix & 0xf) << 4);
state->ham_color = (state->ham_color & 0xf0f) | ((newpix & 0xf) << 4);
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)
{
amiga_state *state = machine->driver_data<amiga_state>();
UINT16 save_color0 = CUSTOM_REG(REG_COLOR00);
int ddf_start_pixel = 0, ddf_stop_pixel = 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 next_copper_x;
int pl;
const int defbitoffs = 15;
last_scanline = scanline;
state->last_scanline = scanline;
/* on the first scanline, reset the COPPER and HAM color */
if (scanline == 0)
{
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
ham_color = CUSTOM_REG(REG_COLOR00);
amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH));
state->ham_color = CUSTOM_REG(REG_COLOR00);
}
/* 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 */
if (bitmap != NULL)
dst = BITMAP_ADDR16(bitmap, scanline, 0);
/* 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 */
if (genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color;
if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* loop over the line */
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 */
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);
if (genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color;
if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* compute update-related register values */
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 */
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 )
ddf_stop_pixel += 8;
/* compute the horizontal start/stop */
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 */
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 */
pf1pri = CUSTOM_REG(REG_BPLCON2) & 7;
@ -708,8 +697,8 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if ( hires )
{
obitoffs = 15 + ( odelay << 1 );
ebitoffs = 15 + ( edelay << 1 );
obitoffs = defbitoffs + ( odelay << 1 );
ebitoffs = defbitoffs + ( edelay << 1 );
}
else
{
@ -719,8 +708,8 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
edelay = ( edelay + 8 ) & 0x0f;
}
obitoffs = 15 + odelay;
ebitoffs = 15 + edelay;
obitoffs = defbitoffs + odelay;
ebitoffs = defbitoffs + edelay;
}
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 */
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 */
/* 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 we need to fetch more data, do it now */
if (obitoffs == 15)
if (obitoffs == defbitoffs)
{
for (pl = 0; pl < planes; pl += 2)
{
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
fetch_bitplane_data(state, pl);
}
}
/* now assemble the bits */
pfpix0 |= assemble_odd_bitplanes(planes, obitoffs);
pfpix0 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--;
/* 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 */
if (obitoffs < 0)
{
obitoffs = 15;
obitoffs = defbitoffs;
for (pl = 0; pl < planes; pl += 2)
{
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
fetch_bitplane_data(state, pl);
}
}
pfpix1 |= assemble_odd_bitplanes(planes, obitoffs);
pfpix1 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--;
}
else
@ -775,22 +764,23 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets if needed */
if (obitoffs < 0)
obitoffs = 15;
obitoffs = defbitoffs;
}
/* fetch the even bits if we are within the fetching region */
if (x >= ddf_start_pixel && x <= ddf_stop_pixel + edelay)
{
/* if we need to fetch more data, do it now */
if (ebitoffs == 15)
if (ebitoffs == defbitoffs)
{
for (pl = 1; pl < planes; pl += 2)
{
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
fetch_bitplane_data(state, pl);
}
}
/* now assemble the bits */
pfpix0 |= assemble_even_bitplanes(planes, ebitoffs);
pfpix0 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--;
/* 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 */
if (ebitoffs < 0)
{
ebitoffs = 15;
ebitoffs = defbitoffs;
for (pl = 1; pl < planes; pl += 2)
{
CUSTOM_REG(REG_BPL1DAT + pl) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2));
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += 2;
fetch_bitplane_data(state, pl);
}
}
pfpix1 |= assemble_even_bitplanes(planes, ebitoffs);
pfpix1 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--;
}
else
@ -816,7 +805,7 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* reset bit offsets if needed */
if (ebitoffs < 0)
ebitoffs = 15;
ebitoffs = defbitoffs;
}
/* 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 (dst != NULL && x >= hstart && x < hstop)
{
int pix, pri;
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
if (ham)
{
/* update the HAM color */
pfpix0 = update_ham(pfpix0);
pfpix0 = update_ham(state, pfpix0);
pix = sprpix & 0x1f;
pri = (sprpix >> 10);
/* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10))
if (sprpix && pf1pri > pri)
{
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 */
@ -864,15 +858,14 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
/* dual playfield mode */
else if (dualpf)
{
int pix;
/* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f;
pri = (sprpix >> 10);
if (pix)
{
if ((pfpix0 & 0x15) && pf1pri <= (sprpix >> 10))
if ((pfpix0 & 0x15) && pf1pri <= pri)
pix = 0;
if ((pfpix0 & 0x2a) && pf2pri <= (sprpix >> 10))
if ((pfpix0 & 0x2a) && pf2pri <= pri)
pix = 0;
}
@ -880,15 +873,15 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (pix)
dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pix);
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 */
pix = sprpix & 0x1f;
if (pix)
{
if ((pfpix1 & 0x15) && pf1pri <= (sprpix >> 10))
if ((pfpix1 & 0x15) && pf1pri <= pri)
pix = 0;
if ((pfpix1 & 0x2a) && pf2pri <= (sprpix >> 10))
if ((pfpix1 & 0x2a) && pf2pri <= pri)
pix = 0;
}
@ -896,17 +889,20 @@ void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanl
if (pix)
dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix);
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 */
else
{
pix = sprpix & 0x1f;
pri = (sprpix >> 10);
/* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10))
if (sprpix && pf1pri > pri)
{
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 */
@ -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 (input_code_pressed(machine, KEYCODE_Q))
popmessage("%d", wait_offset -= 1);
popmessage("%d", state->wait_offset -= 1);
if (input_code_pressed(machine, KEYCODE_W))
popmessage("%d", wait_offset += 1);
popmessage("%d", state->wait_offset += 1);
}
#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
*
*************************************/
/* 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
*
*************************************/
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 cr,cg,cb;
int color;
@ -181,232 +73,11 @@ void aga_palette_write(int color_reg, UINT16 data)
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 */
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);
VIDEO_START_CALL( amiga );
separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
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);
}
state->aga_diwhigh_written = 0;
}
@ -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)
{
case 0:
aga_sprdata[sprite][0] = amiga_chip_ram_r(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_sprdata[sprite][0] = (*state->chip_ram_r)(state, 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) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) += 4;
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]);
state->aga_sprite_fetched_words = 1;
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;
case 1:
case 2:
aga_sprdata[sprite][0] = amiga_chip_ram_r(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][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
aga_sprdatb[sprite][0] = amiga_chip_ram_r(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][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
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] );
state->aga_sprite_fetched_words = 2;
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;
case 3:
aga_sprdata[sprite][0] = amiga_chip_ram_r(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][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
aga_sprdata[sprite][2] = amiga_chip_ram_r(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][2] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
aga_sprdatb[sprite][0] = amiga_chip_ram_r(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][0] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
aga_sprdatb[sprite][2] = amiga_chip_ram_r(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][2] = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * sprite) + 0);
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;
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",
scanline, sprite,
aga_sprdata[sprite][0], aga_sprdatb[sprite][0],
aga_sprdata[sprite][1], aga_sprdatb[sprite][1],
aga_sprdata[sprite][2], aga_sprdatb[sprite][2],
aga_sprdata[sprite][3], aga_sprdatb[sprite][3]);
state->aga_sprdata[sprite][0], state->aga_sprdatb[sprite][0],
state->aga_sprdata[sprite][1], state->aga_sprdatb[sprite][1],
state->aga_sprdata[sprite][2], state->aga_sprdatb[sprite][2],
state->aga_sprdata[sprite][3], state->aga_sprdatb[sprite][3]);
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 num, maxdma;
@ -481,15 +152,15 @@ static void update_sprite_dma(int scanline)
int vstart, vstop;
/* 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 */
sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask &= ~bitmask;
state->sprite_comparitor_enable_mask &= ~bitmask;
state->sprite_dma_reload_mask &= ~bitmask;
/* 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_SPR0CTL + 4 * num) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
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) = (*state->chip_ram_r)(state, CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
/* fetch additional words */
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 (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 we hit vstop, disable the comparitor and trigger a reload for the next scanline */
if (scanline == vstop)
{
sprite_ctl_written &= ~bitmask;
sprite_comparitor_enable_mask &= ~bitmask;
sprite_dma_reload_mask |= 1 << num;
state->sprite_ctl_written &= ~bitmask;
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_SPR0DATB + 4 * num) = 0;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d comparitor disable, prepare for reload\n", scanline, num);
}
/* 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)
{
return (expand_byte[lobits & 0xff] << 0) | (expand_byte[lobits >> 8] << 16) |
(expand_byte[hibits & 0xff] << 1) | (expand_byte[hibits >> 8] << 17);
return (amiga_expand_byte[lobits & 0xff] << 0) | (amiga_expand_byte[lobits >> 8] << 16) |
(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 num, pair;
/* loop over sprite channels */
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 (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);
if (hstart == x)
{
sprite_remain[num] = 16;
sprite_shiftreg[num] = interleave_sprite_data(aga_sprdata[num][0], aga_sprdatb[num][0]);
aga_sprite_dma_used_words[num] = 1;
state->sprite_remain[num] = 16;
state->sprite_shiftreg[num] = interleave_sprite_data(state->aga_sprdata[num][0], state->aga_sprdatb[num][0]);
state->aga_sprite_dma_used_words[num] = 1;
}
}
/* clock the next pixel if we're doing it */
if (sprite_remain[num] != 0)
if (state->sprite_remain[num] != 0)
{
sprite_remain[num]--;
pixels |= (sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
sprite_shiftreg[num] <<= 2;
state->sprite_remain[num]--;
pixels |= (state->sprite_shiftreg[num] & 0xc0000000) >> (16 + 2 * (7 - num));
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;
sprite_shiftreg[num] = interleave_sprite_data(aga_sprdata[num][aga_sprite_dma_used_words[num]], aga_sprdatb[num][aga_sprite_dma_used_words[num]]);
aga_sprite_dma_used_words[num]++;
int w = state->aga_sprite_dma_used_words[num];
state->sprite_remain[num] = 16;
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:
topmost sprite color in bits 0-7
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 */
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 */
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 */
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;
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;
if (planes >= 2)
{
UINT64 *aga_bpldat = state->aga_bpldat;
pix |= ((aga_bpldat[1] >> ebitoffs) & 1) << 1;
if (planes >= 4)
{
@ -695,37 +370,41 @@ INLINE UINT8 assemble_even_bitplanes(int planes, int ebitoffs)
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)
{
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;
break;
case 1:
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;
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;
break;
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;
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;
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;
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;
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)
{
case 0:
ham_color = aga_palette[(newpix >> 2) & 0x3f];
state->ham_color = state->aga_palette[(newpix >> 2) & 0x3f];
break;
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;
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;
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;
}
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)
{
amiga_state *state = machine->driver_data<amiga_state>();
UINT16 save_color0 = CUSTOM_REG(REG_COLOR00);
int ddf_start_pixel = 0, ddf_stop_pixel = 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 next_copper_x;
int pl;
pen_t ham_pix;
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 */
if (scanline == 0)
{
aga_copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
ham_color = CUSTOM_REG(REG_COLOR00);
amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH));
state->ham_color = CUSTOM_REG(REG_COLOR00);
}
/* 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 */
if (bitmap != NULL)
dst = BITMAP_ADDR32(bitmap, scanline, 0);
/* 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 */
if (genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color;
if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* loop over the line */
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 */
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);
if (genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = genlock_color;
if (state->genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = state->genlock_color;
/* compute update-related register values */
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;
hstop = (CUSTOM_REG(REG_DIWSTOP) & 0xff);
if (diwhigh_written)
if (state->aga_diwhigh_written)
{
hstart |= ((CUSTOM_REG(REG_DIWHIGH) >> 5) & 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 */
vstart = CUSTOM_REG(REG_DIWSTRT) >> 8;
vstop = (CUSTOM_REG(REG_DIWSTOP) >> 8);
if (diwhigh_written)
if (state->aga_diwhigh_written)
{
vstart |= (CUSTOM_REG(REG_DIWHIGH) & 7) << 8;
vstop |= ((CUSTOM_REG(REG_DIWHIGH) >> 8) & 7) << 8;
}
else
{
if ((vstop & 0x80) == 0)
vstop |= 0x100;
vstop |= ((~CUSTOM_REG(REG_DIWSTOP) >> 7) & 0x100);
}
/* extract playfield priorities */
@ -890,7 +569,6 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
/* extract collision masks */
ocolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x15;
ecolmask = (CUSTOM_REG(REG_CLXCON) >> 6) & 0x2a;
}
/* 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++)
aga_bpldat[pl] = 0;
state->aga_bpldat[pl] = 0;
}
/* 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 */
/* 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)
{
fetch_bitplane_data(pl);
fetch_bitplane_data(state, pl);
}
}
/* now assemble the bits */
pfpix0 |= assemble_odd_bitplanes(planes, obitoffs);
pfpix0 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--;
/* 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)
{
fetch_bitplane_data(pl);
fetch_bitplane_data(state, pl);
}
}
pfpix1 |= assemble_odd_bitplanes(planes, obitoffs);
pfpix1 |= assemble_odd_bitplanes(state, planes, obitoffs);
obitoffs--;
}
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)
{
fetch_bitplane_data(pl);
fetch_bitplane_data(state, pl);
}
}
/* now assemble the bits */
pfpix0 |= assemble_even_bitplanes(planes, ebitoffs);
pfpix0 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--;
/* 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)
{
fetch_bitplane_data(pl);
fetch_bitplane_data(state, pl);
}
}
pfpix1 |= assemble_even_bitplanes(planes, ebitoffs);
pfpix1 |= assemble_even_bitplanes(state, planes, ebitoffs);
ebitoffs--;
}
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 (dst != NULL && x >= hstart && x < hstop)
{
int pix, pri;
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
if (ham)
{
/* update the HAM color */
ham_pix = update_ham(pfpix0);
pfpix0 = update_ham(state, pfpix0);
pix = sprpix & 0xff;
pri = (sprpix >> 10);
/* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 10))
if (sprpix && pf1pri > pri)
{
dst[x*2+0] =
dst[x*2+1] = aga_palette[sprpix & 0xff];
dst[x*2+1] = aga_palette[pix];
}
/* playfield has priority */
else
{
dst[x*2+0] =
dst[x*2+1] = ham_pix;
dst[x*2+1] = pfpix0;
}
}
/* dual playfield mode */
else if (dualpf)
{
int pix;
/* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f;
pri = (sprpix >> 12);
if (pix)
{
if ((pfpix0 & 0x15) && pf1pri <= (sprpix >> 12))
if ((pfpix0 & 0x15) && pf1pri <= pri)
pix = 0;
if ((pfpix0 & 0x2a) && pf2pri <= (sprpix >> 12))
if ((pfpix0 & 0x2a) && pf2pri <= pri)
pix = 0;
}
@ -1078,15 +760,15 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
if (pix)
dst[x*2+0] = aga_palette[pix];
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 */
pix = sprpix & 0xff;
if (pix)
{
if ((pfpix1 & 0x15) && pf1pri <= (sprpix >> 12))
if ((pfpix1 & 0x15) && pf1pri <= pri)
pix = 0;
if ((pfpix1 & 0x2a) && pf2pri <= (sprpix >> 12))
if ((pfpix1 & 0x2a) && pf2pri <= pri)
pix = 0;
}
@ -1094,17 +776,20 @@ void amiga_aga_render_scanline(running_machine *machine, bitmap_t *bitmap, int s
if (pix)
dst[x*2+1] = aga_palette[pix];
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 */
else
{
pix = sprpix & 0xff;
pri = (sprpix >> 12);
/* sprite has priority */
if (sprpix && pf1pri > (sprpix >> 12))
if (sprpix && pf1pri > pri)
{
dst[x*2+0] =
dst[x*2+1] = aga_palette[(sprpix & 0xff)];
dst[x*2+1] = aga_palette[pix];
}
/* playfield has priority */