summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/apple2gs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/apple2gs.c')
-rw-r--r--src/mess/machine/apple2gs.c2033
1 files changed, 2033 insertions, 0 deletions
diff --git a/src/mess/machine/apple2gs.c b/src/mess/machine/apple2gs.c
new file mode 100644
index 00000000000..098b0f13f0a
--- /dev/null
+++ b/src/mess/machine/apple2gs.c
@@ -0,0 +1,2033 @@
+/*********************************************************************
+
+ apple2gs.c
+
+ Apple IIgs code
+
+
+ Apple IIgs specific softswitches:
+
+ C019 - RDVBLBAR
+ bits 7 - set during vblank (when at scanline 192 or higher)
+
+ C022 - TBCOLOR
+ bits 7-4 - text foreground color
+ bits 3-0 - text background color
+
+ C023 - VGCINT
+ bit 7 - set for interrupt generated by VGC
+
+ bit 6 - set during one second interrupt
+ bit 5 - set during scanline interrupt
+
+ bit 4 - set during external interrupt
+ bit 3 - ???
+ bit 2 - set for interrupt every second
+
+ bit 1 - set for scanline interrupt
+ bit 0 - set for external interrupt
+
+ C025 - KEYMODREG
+ bit 7 - option key pressed
+ bit 6 - command key presssed
+ bit 5 - modified latch
+ bit 4 - keypad key pressed
+ bit 3 - repeating
+ bit 2 - caps lock latched
+ bit 1 - control key pressed
+ bit 0 - shift key pressed
+
+ C027 - KMSTATUS
+ bit 7 - set if mouse register full
+ bit 6 - mouse interupt enable flag
+ bit 5 - set if data register full
+ bit 4 - data interrupt enabled
+ bit 3 - set if key data full
+ bit 2 - key data interurpt enabled
+ bit 1 - clear if horizontal mouse data, set if vertical
+ bit 0 - command register full
+
+ C029 - NEWVIDEO
+ bit 7 - 1 for Super Hi-Res mode, 0 for old Apple II video modes
+ bit 6 - 1 to enable memory linearization (2000-9D00 in banks 01/E1), 0 for physical layout
+ bit 5 - 1 to display double hi-res mode in monochrome, 0 for color
+ bit 4 - ???
+ bit 3 - ???
+ bit 2 - ???
+ bit 1 - ???
+ bit 0 - ???
+
+ C02D - SLTROMSEL
+
+ C031 - DISKREG
+ bit 7 - set to select head on 3.5" drive
+ bit 6 - set to enable 3.5" drive, clear to enable 5.25" drive
+
+ C035 - SHADOW
+ bit 7 - ???
+ bit 6 - set to inhibit I/O and LC operations ($C000-$FFFF)
+ bit 5 - ???
+ bit 4 - set to inhibit shadowing aux hires page
+ bit 3 - set to inhibit shadowing super hires video
+ bit 2 - set to inhibit shadowing hires page 2
+ bit 1 - set to inhibit shadowing hires page 2
+ bit 0 - set to inhibit shadowing text pages
+
+ C036 - CYAREG
+ bit 7 - clear for slow speed, set for hi speed
+ bit 6 - ???
+ bit 5 - ???
+ bit 4 - shadow in all RAM banks
+ bit 3 - slot 7 motor on
+ bit 2 - slot 6 motor on
+ bit 1 - slot 5 motor on
+ bit 0 - slot 4 motor on
+
+ C041 - INTEN
+ bit 4 - set to enable quarter second interrupts
+ bit 3 - set to enable VBL interrupts
+ bit 2 - set to enable Mega II mouse switch interrupts
+ bit 1 - set to enable Mega II mouse movement interrupts
+ bit 0 - set to enable Mega II mouse mouse operation
+
+ C046 - DIAGTYPE/INTFLAG
+ bit 7 - set if mouse button currently down
+ bit 6 - set if mouse button down on last read
+ bit 5 - set for AN3
+ bit 4 - set if currently in quarter second interrupt
+ bit 3 - set if currently in VBL interrupt
+ bit 2 - set if currently in Mega II mouse switch interrupt
+ bit 1 - set if currently in Mega II mouse movement interrupt
+ bit 0 - set if system IRQ line asserted
+
+ C047 - CLRVBLINT
+
+ C068 - STATEREG
+ bit 7 - ALTZP status
+ bit 6 - PAGE2 status
+ bit 5 - RAMRD status
+ bit 4 - RAMWRT status
+ bit 3 - !LCRAM status (inverted)
+ bit 2 - LCRAM2 status
+ bit 1 - ROMBANK status (unimplemented)
+ bit 0 - INTCXROM status
+
+*********************************************************************/
+
+#include <assert.h>
+#include "emu.h"
+
+#include "includes/apple2gs.h"
+#include "includes/apple2.h"
+#include "machine/ay3600.h"
+#include "machine/applefdc.h"
+#include "devices/sonydriv.h"
+#include "machine/8530scc.h"
+#include "imagedev/flopdrv.h"
+#include "cpu/g65816/g65816.h"
+#include "sound/es5503.h"
+#include "machine/ram.h"
+#include "debugger.h"
+#include "machine/a2bus.h"
+
+#define LOG_C0XX 0
+#define LOG_ADB 0
+#define LOG_IRQ 0
+
+/* -----------------------------------------------------------------------
+ * Apple IIgs clock
+ * ----------------------------------------------------------------------- */
+
+static void process_clock(running_machine &machine)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ UINT8 operation;
+ seconds_t current_interval;
+
+ /* update clock_curtime */
+ current_interval = machine.time().seconds;
+ state->m_clock_curtime += current_interval - state->m_clock_curtime_interval;
+ state->m_clock_curtime_interval = current_interval;
+
+ switch(state->m_clock_mode)
+ {
+ case CLOCKMODE_IDLE:
+ state->m_clock_read = (state->m_clock_data >> 7);
+ state->m_clock_reg1 = (state->m_clock_data >> 2) & 0x03;
+ operation = (state->m_clock_data >> 4) & 0x07;
+
+ if ((state->m_clock_data & 0x40) == 0x00)
+ {
+ switch(operation)
+ {
+ case 0x00:
+ /* read/write seconds register */
+ state->m_clock_mode = CLOCKMODE_TIME;
+ break;
+
+ case 0x03:
+ /* internal registers */
+ if (state->m_clock_reg1 & 0x02)
+ {
+ state->m_clock_mode = CLOCKMODE_BRAM2;
+ state->m_clock_reg1 = (state->m_clock_data & 0x07) << 5;
+ }
+ else
+ {
+ state->m_clock_mode = CLOCKMODE_INTERNALREGS;
+ }
+ break;
+
+ default:
+ //fatalerror("NYI");
+ break;
+ }
+ }
+ break;
+
+ case CLOCKMODE_BRAM1:
+ if (state->m_clock_read)
+ state->m_clock_data = state->m_clock_bram[state->m_clock_reg1];
+ else
+ state->m_clock_bram[state->m_clock_reg1] = state->m_clock_data;
+ state->m_clock_mode = CLOCKMODE_IDLE;
+ break;
+
+ case CLOCKMODE_BRAM2:
+ state->m_clock_reg1 |= (state->m_clock_data >> 2) & 0x1F;
+ state->m_clock_mode = CLOCKMODE_BRAM1;
+ break;
+
+ case CLOCKMODE_INTERNALREGS:
+ switch (state->m_clock_reg1)
+ {
+ case 0x00:
+ /* test register */
+ break;
+
+ case 0x01:
+ /* write protect register */
+ break;
+ }
+ state->m_clock_mode = CLOCKMODE_IDLE;
+ break;
+
+ case CLOCKMODE_TIME:
+ if (state->m_clock_data & 0x40)
+ {
+ state->m_clock_data = state->m_clock_curtime >> (state->m_clock_reg1 * 8);
+ }
+ else
+ {
+ state->m_clock_curtime &= ~(0xFF << (state->m_clock_reg1 * 8));
+ state->m_clock_curtime |= state->m_clock_data << (state->m_clock_reg1 * 8);
+ }
+ state->m_clock_mode = CLOCKMODE_IDLE;
+ break;
+
+ default:
+ //fatalerror("NYI");
+ break;
+ }
+}
+
+/* -----------------------------------------------------------------------
+ * Interrupts
+ * ----------------------------------------------------------------------- */
+
+static const char *apple2gs_irq_name(UINT16 irq_mask)
+{
+ switch(irq_mask)
+ {
+ case IRQ_KBD_SRQ: return "IRQ_KBD_SRQ";
+ case IRQ_ADB_DATA: return "IRQ_ADB_DATA";
+ case IRQ_ADB_MOUSE: return "IRQ_ADB_MOUSE";
+ case IRQ_VGC_SCANLINE: return "IRQ_VGC_SCANLINE";
+ case IRQ_VGC_SECOND: return "IRQ_VGC_SECOND";
+ case IRQ_INTEN_QSECOND: return "IRQ_INTEN_QSECOND";
+ case IRQ_INTEN_VBL: return "IRQ_INTEN_VBL";
+ case IRQ_DOC: return "IRQ_DOC";
+ case IRQ_SLOT: return "IRQ_SLOT";
+ }
+ return NULL;
+}
+
+void apple2gs_add_irq(running_machine &machine, UINT16 irq_mask)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if ((state->m_pending_irqs & irq_mask) == 0x00)
+ {
+ if (LOG_IRQ)
+ logerror("apple2gs_add_irq(): adding %s\n", apple2gs_irq_name(irq_mask));
+
+ state->m_pending_irqs |= irq_mask;
+ cputag_set_input_line(machine, "maincpu", G65816_LINE_IRQ, state->m_pending_irqs ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+
+
+void apple2gs_remove_irq(running_machine &machine, UINT16 irq_mask)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_pending_irqs & irq_mask)
+ {
+ if (LOG_IRQ)
+ logerror("apple2gs_remove_irq(): removing %s\n", apple2gs_irq_name(irq_mask));
+
+ state->m_pending_irqs &= ~irq_mask;
+ cputag_set_input_line(machine, "maincpu", G65816_LINE_IRQ, state->m_pending_irqs ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+void apple2gs_doc_irq(device_t *device, int state)
+{
+ if (state)
+ {
+ apple2gs_add_irq(device->machine(), IRQ_DOC);
+ }
+ else
+ {
+ apple2gs_remove_irq(device->machine(), IRQ_DOC);
+ }
+}
+
+
+/* Clock interrupt */
+static TIMER_CALLBACK( apple2gs_clock_tick )
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if ((state->m_vgcint & 0x04) && !(state->m_vgcint & 0x40))
+ {
+ state->m_vgcint |= 0xc0;
+ apple2gs_add_irq(machine, IRQ_VGC_SECOND);
+ }
+}
+
+
+/* Quarter-second interrupt */
+static TIMER_CALLBACK( apple2gs_qsecond_tick )
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if ((state->m_inten & 0x10) && !(state->m_intflag & 0x10))
+ {
+ state->m_intflag |= 0x10;
+ apple2gs_add_irq(machine, IRQ_INTEN_QSECOND);
+ }
+}
+
+
+/* -----------------------------------------------------------------------
+ * ADB
+ * ----------------------------------------------------------------------- */
+
+
+
+static UINT8 adb_read_memory(apple2gs_state *state, UINT32 address)
+{
+ if (address < ARRAY_LENGTH(state->m_adb_memory))
+ return state->m_adb_memory[address];
+ else
+ return 0x00;
+}
+
+
+
+static void adb_write_memory(apple2gs_state *state, UINT32 address, UINT8 data)
+{
+ if (address < ARRAY_LENGTH(state->m_adb_memory))
+ state->m_adb_memory[address] = data;
+}
+
+
+
+static void adb_set_mode(apple2gs_state *state, UINT8 mode)
+{
+ state->m_adb_mode = mode;
+}
+
+
+
+static void adb_set_config(UINT8 b1, UINT8 b2, UINT8 b3)
+{
+ /* ignore for now */
+}
+
+
+
+static void adb_post_response(apple2gs_state *state, const UINT8 *bytes, size_t length)
+{
+ assert(length < ARRAY_LENGTH(state->m_adb_response_bytes));
+ memcpy(state->m_adb_response_bytes, bytes, length);
+
+ state->m_adb_state = ADBSTATE_INRESPONSE;
+ state->m_adb_response_length = length;
+ state->m_adb_response_pos = 0;
+}
+
+
+
+static void adb_post_response_1(apple2gs_state *state, UINT8 b)
+{
+ adb_post_response(state, &b, 1);
+}
+
+
+
+static void adb_post_response_2(apple2gs_state *state, UINT8 b1, UINT8 b2)
+{
+ UINT8 b[2];
+ b[0] = b1;
+ b[1] = b2;
+ adb_post_response(state, b, 2);
+}
+
+
+
+static void adb_do_command(apple2gs_state *state)
+{
+ int device;
+ UINT32 address;
+ UINT8 val;
+
+ state->m_adb_state = ADBSTATE_IDLE;
+ if (LOG_ADB)
+ logerror("adb_do_command(): adb_command=0x%02x\n", state->m_adb_command);
+
+ switch(state->m_adb_command)
+ {
+ case 0x00: /* ??? */
+ break;
+
+ case 0x03: /* flush keyboard buffer */
+ break;
+
+ case 0x04: /* set modes */
+ adb_set_mode(state, state->m_adb_mode | state->m_adb_command_bytes[0]);
+ break;
+
+ case 0x05: /* clear modes */
+ adb_set_mode(state, state->m_adb_mode & ~state->m_adb_command_bytes[0]);
+ break;
+
+ case 0x06: /* set config */
+ adb_set_config(state->m_adb_command_bytes[0], state->m_adb_command_bytes[1], state->m_adb_command_bytes[2]);
+ break;
+
+ case 0x07: /* synchronize */
+ adb_set_mode(state, state->m_adb_command_bytes[0]);
+ adb_set_config(state->m_adb_command_bytes[1], state->m_adb_command_bytes[2], state->m_adb_command_bytes[3]);
+ break;
+
+ case 0x08: /* write memory */
+ address = state->m_adb_command_bytes[0];
+ val = state->m_adb_command_bytes[1];
+ adb_write_memory(state, address, val);
+ break;
+
+ case 0x09: /* read memory */
+ address = (state->m_adb_command_bytes[1] << 8) | state->m_adb_command_bytes[0];
+ adb_post_response_1(state, adb_read_memory(state, address));
+ break;
+
+ case 0x0a: /* ??? */
+ case 0x0b: /* ??? */
+ break;
+
+ case 0x0d: /* get version */
+ adb_post_response_1(state, 0x06);
+ break;
+
+ case 0x0e: /* read available charsets */
+ adb_post_response_2(state, 0x01, 0x00);
+ break;
+
+ case 0x0f: /* read available layouts */
+ adb_post_response_2(state, 0x01, 0x00);
+ break;
+
+ case 0x12: /* mystery command 0x12 */
+ case 0x13: /* mystery command 0x13 */
+ break;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ /* send data to device */
+ device = state->m_adb_command & 0x0f;
+ if (device == state->m_adb_address_keyboard)
+ {
+ }
+ else if (device == state->m_adb_address_mouse)
+ {
+ }
+ break;
+
+ case 0xf2:
+ break;
+
+ default:
+ fatalerror("ADB command 0x%02x unimplemented", state->m_adb_command);
+ break;
+ }
+ state->m_adb_kmstatus |= 0x20;
+}
+
+
+
+UINT8 apple2gs_state::adb_read_datareg()
+{
+ UINT8 result;
+
+ switch(m_adb_state)
+ {
+ case ADBSTATE_INRESPONSE:
+ result = m_adb_response_bytes[m_adb_response_pos++];
+ if (m_adb_response_pos >= m_adb_response_length)
+ {
+ m_adb_state = ADBSTATE_IDLE;
+ m_adb_latent_result = result;
+ m_adb_kmstatus &= ~0x20;
+ }
+ break;
+
+ default:
+ result = 0; //state->m_adb_latent_result & 0x7f;
+ break;
+ }
+
+ if (LOG_ADB)
+ logerror("adb_read_datareg(): result=0x%02x\n", result);
+
+ return result;
+}
+
+
+
+static void adb_write_datareg(running_machine &machine, UINT8 data)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (LOG_ADB)
+ logerror("adb_write_datareg(): data=0x%02x\n", data);
+
+ switch(state->m_adb_state)
+ {
+ case ADBSTATE_IDLE:
+ state->m_adb_command = data;
+ state->m_adb_command_length = 0;
+ state->m_adb_command_pos = 0;
+
+ switch(data)
+ {
+ case 0x00: /* ??? */
+ case 0x01: /* abort */
+ /* do nothing for now */
+ break;
+
+ case 0x03: /* flush keyboard buffer */
+ state->m_adb_command_length = 0;
+ break;
+
+ case 0x04: /* set modes */
+ case 0x05: /* clear modes */
+ state->m_adb_command_length = 1;
+ break;
+
+ case 0x06: /* set config */
+ state->m_adb_command_length = 3;
+ break;
+
+ case 0x07: /* synchronize */
+ if (state->memregion("maincpu")->bytes() == 0x40000) /* HACK */
+ state->m_adb_command_length = 8;
+ else
+ state->m_adb_command_length = 4;
+ break;
+
+ case 0x08: /* write memory */
+ case 0x09: /* read memory */
+ state->m_adb_command_length = 2;
+ break;
+
+ case 0x0a: /* ??? */
+ case 0x0b: /* ??? */
+ state->m_adb_command_length = 0;
+ break;
+
+ case 0x0d: /* get version */
+ state->m_adb_command_length = 0;
+ break;
+
+ case 0x0e: /* read available charsets */
+ state->m_adb_command_length = 0;
+ state->m_adb_state = ADBSTATE_INCOMMAND; /* HACK */
+ break;
+
+ case 0x0f: /* read available layouts */
+ state->m_adb_command_length = 0;
+ state->m_adb_state = ADBSTATE_INCOMMAND; /* HACK */
+ break;
+
+ case 0x12: /* mystery command 0x12 */
+ case 0x13: /* mystery command 0x13 */
+ state->m_adb_command_length = 2;
+ break;
+
+ case 0x70: /* disable SRQ device 0 */
+ case 0x71: /* disable SRQ device 1 */
+ case 0x72: /* disable SRQ device 2 */
+ case 0x73: /* disable SRQ device 3 */
+ /* ignore for now */
+ break;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ /* send data to device */
+ state->m_adb_command_length = 2;
+ break;
+
+ case 0xf2:
+ break;
+
+ default:
+ fatalerror("ADB command 0x%02x unimplemented", data);
+ break;
+
+ }
+
+ if (state->m_adb_command_length > 0)
+ {
+ state->m_adb_state = ADBSTATE_INCOMMAND;
+ if (LOG_ADB)
+ logerror("adb_write_datareg(): in command length %u\n", (unsigned) state->m_adb_command_length);
+ }
+ break;
+
+ case ADBSTATE_INCOMMAND:
+ assert(state->m_adb_command_pos < ARRAY_LENGTH(state->m_adb_command_bytes));
+ state->m_adb_command_bytes[state->m_adb_command_pos++] = data;
+ break;
+
+ case ADBSTATE_INRESPONSE:
+ state->m_adb_state = ADBSTATE_IDLE;
+ break;
+ }
+
+ /* do command if necessary */
+ if ((state->m_adb_state == ADBSTATE_INCOMMAND) && (state->m_adb_command_pos >= state->m_adb_command_length))
+ adb_do_command(state);
+}
+
+
+// real rom 3 h/w reads 0x90 when idle, 0x98 when key pressed
+// current MESS reads back 0xb0 when idle
+UINT8 apple2gs_state::adb_read_kmstatus()
+{
+ return m_adb_kmstatus;
+}
+
+
+
+static void adb_write_kmstatus(apple2gs_state *state, UINT8 data)
+{
+ state->m_adb_kmstatus &= ~0x54;
+ state->m_adb_kmstatus |= data & 0x54;
+}
+
+
+
+static UINT8 adb_read_mousedata(running_machine &machine)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ UINT8 result = 0x00;
+ UINT8 absolute;
+ INT8 delta;
+
+ if (state->m_adb_kmstatus & 0x80) // mouse register full
+ {
+ if (state->m_adb_kmstatus & 0x02) // H/V mouse data select
+ {
+ absolute = state->m_mouse_y;
+ delta = state->m_mouse_dy;
+ state->m_adb_kmstatus &= ~0x82;
+ apple2gs_remove_irq(machine, IRQ_ADB_MOUSE);
+ }
+ else
+ {
+ absolute = state->m_mouse_x;
+ delta = state->m_mouse_dx;
+ state->m_adb_kmstatus |= 0x02;
+ }
+
+ if (delta > 63)
+ delta = 63;
+ else if (delta < -64)
+ delta = -64;
+
+ result = (absolute & 0x80) | (delta & 0x7F);
+ }
+ return result;
+}
+
+
+
+static INT8 seven_bit_diff(UINT8 v1, UINT8 v2)
+{
+ v1 -= v2;
+ if (v1 & 0x40)
+ v1 |= 0x80;
+ else
+ v1 &= ~0x80;
+ return v1;
+}
+
+
+
+static void adb_check_mouse(running_machine &machine)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ UINT8 new_mouse_x, new_mouse_y;
+
+ /* read mouse values */
+ if ((state->m_adb_kmstatus & 0x80) == 0x00)
+ {
+ new_mouse_x = machine.root_device().ioport("adb_mouse_x")->read();
+ new_mouse_y = machine.root_device().ioport("adb_mouse_y")->read();
+
+ if ((state->m_mouse_x != new_mouse_x) || (state->m_mouse_y != new_mouse_y))
+ {
+ state->m_mouse_dx = seven_bit_diff(new_mouse_x, state->m_mouse_x);
+ state->m_mouse_dy = seven_bit_diff(new_mouse_y, state->m_mouse_y);
+ state->m_mouse_x = new_mouse_x;
+ state->m_mouse_y = new_mouse_y;
+
+ state->m_adb_kmstatus |= 0x80;
+ state->m_adb_kmstatus &= ~0x02;
+ if (state->m_adb_kmstatus & 0x40)
+ apple2gs_add_irq(machine, IRQ_ADB_MOUSE);
+ }
+ }
+}
+
+
+
+static void apple2gs_set_scanint(running_machine &machine, UINT8 data)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ /* second interrupt */
+ if ((state->m_vgcint & 0x40) && !(data & 0x40))
+ {
+ apple2gs_remove_irq(machine, IRQ_VGC_SECOND);
+ state->m_vgcint &= ~0xC0;
+ }
+
+ /* scanline interrupt */
+ if ((state->m_vgcint & 0x20) && !(data & 0x20))
+ {
+ apple2gs_remove_irq(machine, IRQ_VGC_SCANLINE);
+ state->m_vgcint &= ~0xA0;
+ }
+
+ if (state->m_pending_irqs & (IRQ_VGC_SECOND | IRQ_VGC_SCANLINE))
+ state->m_vgcint |= 0x80;
+}
+
+
+static TIMER_CALLBACK(apple2gs_scanline_tick)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ int scanline;
+
+ scanline = machine.primary_screen->vpos();
+ machine.primary_screen->update_partial(scanline);
+
+ /* check scanline interrupt bits if we're in super hi-res and the current scanline is within the active display area */
+ if ((state->m_newvideo & 0x80) && (scanline >= (BORDER_TOP-1)) && (scanline < (200+BORDER_TOP-1)))
+ {
+ UINT8 scb;
+
+ scb = state->m_slowmem[0x19D00 + scanline - BORDER_TOP + 1];
+
+ if (scb & 0x40)
+ {
+ // scanline int flag is set even when the actual interrupt is disabled
+ state->m_vgcint |= 0x20;
+
+ // see if the interrupt is also enabled and trigger it if so
+ if (state->m_vgcint & 0x02)
+ {
+ state->m_vgcint |= 0x80;
+ apple2gs_add_irq(machine, IRQ_VGC_SCANLINE);
+ }
+ }
+ }
+
+ if (scanline == (192+BORDER_TOP))
+ {
+ /* VBL interrupt */
+ if ((state->m_inten & 0x08) && !(state->m_intflag & 0x08))
+ {
+ state->m_intflag |= 0x08;
+ apple2gs_add_irq(machine, IRQ_INTEN_VBL);
+ }
+ }
+
+ /* check the mouse status */
+ if ((scanline % 8) == 0)
+ {
+ adb_check_mouse(machine);
+
+ /* call Apple II interrupt handler */
+ if ((machine.primary_screen->vpos() % 8) == 7)
+ {
+ //apple2_interrupt(machine.device("maincpu"));
+ /* TODO: check me! */
+ machine.primary_screen->update_partial(machine.primary_screen->vpos());
+ }
+ }
+
+ state->m_scanline_timer->adjust(machine.primary_screen->time_until_pos((scanline+1)%262, 0));
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * Sound handlers
+ * ----------------------------------------------------------------------- */
+
+
+static READ8_HANDLER( gssnd_r )
+{
+ apple2gs_state *state = space->machine().driver_data<apple2gs_state>();
+ UINT8 ret = 0;
+
+ switch (offset)
+ {
+ case 0: // control
+ ret = state->m_sndglu_ctrl;
+ break;
+ case 1: // data read
+ ret = state->m_sndglu_dummy_read;
+
+ if (state->m_sndglu_ctrl & 0x40) // docram access
+ {
+ UINT8 *docram = state->memregion("es5503")->base();
+ state->m_sndglu_dummy_read = docram[state->m_sndglu_addr];
+ }
+ else
+ {
+ state->m_sndglu_dummy_read = state->m_es5503->read(*space, state->m_sndglu_addr);
+ }
+
+ if (state->m_sndglu_ctrl & 0x20) // auto-increment
+ {
+ state->m_sndglu_addr++;
+ }
+ break;
+ case 2: // addr l
+ ret = state->m_sndglu_addr & 0xff;
+ break;
+ case 3: // addr h
+ ret = (state->m_sndglu_addr >> 8) & 0xff;
+ break;
+ }
+
+ return ret;
+}
+
+
+
+static WRITE8_HANDLER( gssnd_w )
+{
+ apple2gs_state *state = space->machine().driver_data<apple2gs_state>();
+ switch (offset)
+ {
+ case 0: // control
+ state->m_sndglu_ctrl = data & 0x7f; // make sure DOC is never busy
+ if (!(state->m_sndglu_ctrl & 0x40)) // clear hi byte of address pointer on DOC access
+ {
+ state->m_sndglu_addr &= 0xff;
+ }
+ break;
+ case 1: // data write
+ if (state->m_sndglu_ctrl & 0x40) // docram access
+ {
+ UINT8 *docram = space->machine().root_device().memregion("es5503")->base();
+ docram[state->m_sndglu_addr] = data;
+ }
+ else
+ {
+ state->m_es5503->write(*space, state->m_sndglu_addr, data);
+ }
+
+ if (state->m_sndglu_ctrl & 0x20) // auto-increment
+ {
+ state->m_sndglu_addr++;
+ }
+ break;
+ case 2: // addr l
+ state->m_sndglu_addr &= 0xff00;
+ state->m_sndglu_addr |= data;
+ break;
+ case 3: // addr h
+ state->m_sndglu_addr &= 0x00ff;
+ state->m_sndglu_addr |= data<<8;
+ break;
+ }
+}
+
+/* -----------------------------------------------------------------------
+ * IO handlers
+ * ----------------------------------------------------------------------- */
+
+// apple2gs_get_vpos - return the correct vertical counter value for the current scanline,
+// keeping borders in mind.
+
+static int apple2gs_get_vpos(running_machine &machine)
+{
+ int result, scan;
+ static const UINT8 top_border_vert[BORDER_TOP] =
+ {
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+ 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff,
+
+ };
+
+ scan = machine.primary_screen->vpos();
+
+ if (scan < BORDER_TOP)
+ {
+ result = top_border_vert[scan];
+ }
+ else
+ {
+ result = scan - BORDER_TOP + 0x100 + 1;
+ }
+
+ return result;
+}
+
+READ8_MEMBER( apple2gs_state::apple2gs_c0xx_r )
+{
+ UINT8 result;
+ scc8530_t *scc;
+
+ if(space.debugger_access())
+ {
+ return 0;
+ }
+
+ offset &= 0xFF;
+
+ switch(offset)
+ {
+ case 0x19: /* C019 - RDVBLBAR */
+ result = (space.machine().primary_screen->vpos() >= (192+BORDER_TOP)) ? 0x80 : 0x00;
+ break;
+
+ case 0x22: /* C022 - TBCOLOR */
+ result = (m_fgcolor << 4) | m_bgcolor;
+ break;
+
+ case 0x23: /* C023 - VGCINT */
+ result = m_vgcint;
+ break;
+
+ case 0x24: /* C024 - MOUSEDATA */
+ result = adb_read_mousedata(space.machine());
+ break;
+
+ case 0x25: /* C025 - KEYMODREG */
+ result = AY3600_keymod_r(space.machine());
+ break;
+
+ case 0x26: /* C026 - DATAREG */
+ result = adb_read_datareg();
+ break;
+
+ case 0x27: /* C027 - KMSTATUS */
+ result = adb_read_kmstatus();
+ break;
+
+ case 0x29: /* C029 - NEWVIDEO */
+ result = m_newvideo;
+ break;
+
+ case 0x2B: /* C02B - LANGSEL */
+ result = m_langsel;
+ break;
+
+ case 0x2D: /* C02D - SLTROMSEL */
+ result = m_sltromsel;
+ break;
+
+ case 0x2E: /* C02E - VERTCNT */
+ result = apple2gs_get_vpos(space.machine()) >> 1;
+ break;
+
+ case 0x2F: /* C02F - HORIZCNT */
+ result = space.machine().primary_screen->hpos() / 11;
+ if (result > 0)
+ {
+ result += 0x40;
+ }
+
+ if (apple2gs_get_vpos(space.machine()) & 1)
+ {
+ result |= 0x80;
+ }
+ break;
+
+ case 0x31: /* C031 - DISKREG */
+ result = m_fdc_diskreg;
+ break;
+
+ case 0x33: /* C033 - CLOCKDATA */
+ result = m_clock_data;
+ break;
+
+ case 0x34: /* C034 - CLOCKCTL */
+ result = m_clock_control;
+ break;
+
+ case 0x35: /* C035 - SHADOW */
+ result = m_shadow;
+ break;
+
+ case 0x36: /* C036 - CYAREG */
+ result = m_cyareg;
+ break;
+
+ case 0x38: /* C038 - SCCBREG */
+ case 0x39: /* C039 - SCCAREG */
+ case 0x3A: /* C03A - SCCBDATA */
+ case 0x3B: /* C03B - SCCADATA */
+ scc = space.machine().device<scc8530_t>("scc");
+ result = scc->reg_r(space, offset & 0x03);
+ break;
+
+ case 0x3C: /* C03C - SOUNDCTL */
+ case 0x3D: /* C03D - SOUNDDATA */
+ case 0x3E: /* C03E - SOUNDADRL */
+ case 0x3F: /* C03F - SOUNDADRH */
+ result = gssnd_r(&space, offset & 0x03);
+ break;
+
+ case 0x41: /* C041 - INTEN */
+ result = m_inten;
+ break;
+
+ case 0x46: /* C046 - INTFLAG */
+ result = m_intflag;
+ break;
+
+ case 0x68: /* C068 - STATEREG */
+ result = ((m_flags & VAR_ALTZP) ? 0x80 : 0x00)
+ | ((m_flags & VAR_PAGE2) ? 0x40 : 0x00)
+ | ((m_flags & VAR_RAMRD) ? 0x20 : 0x00)
+ | ((m_flags & VAR_RAMWRT) ? 0x10 : 0x00)
+ | ((m_flags & VAR_LCRAM) ? 0x00 : 0x08)
+ | ((m_flags & VAR_LCRAM2) ? 0x04 : 0x00)
+ | ((m_flags & VAR_INTCXROM)? 0x01 : 0x00);
+ break;
+
+ case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ offset |= (space.machine().root_device().memregion("maincpu")->bytes() - 1) & ~0x3FFF;
+ result = space.machine().root_device().memregion("maincpu")->base()[offset];
+ break;
+
+ case 0x21: /* C021 - MONOCOLOR */
+ case 0x2C: /* C02C - CHARROM */
+ result = 0x00;
+ break;
+
+ // slot 6 registers should go to applefdc if slot 6 not "Your Card"
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ if ((m_sltromsel & (1 << 6)) == 0)
+ {
+ result = applefdc_r(m_fdc, offset);
+ }
+ else
+ {
+ result = apple2_c0xx_r(space, offset, 0);
+ }
+ break;
+
+ default:
+ if (offset < 0x80)
+ {
+ result = apple2_c0xx_r(space, offset, 0);
+ }
+ else
+ {
+ result = apple2_c080_r(space, offset, 0);
+ }
+ break;
+ }
+
+ if (LOG_C0XX)
+ logerror("apple2gs_c0xx_r(): offset=0x%02x result=0x%02x\n", offset, result);
+ return result;
+}
+
+
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_c0xx_w )
+{
+ scc8530_t *scc;
+
+ offset &= 0xFF;
+
+ if (LOG_C0XX)
+ logerror("apple2gs_c0xx_w(): offset=0x%02x data=0x%02x\n", offset, data);
+
+ switch(offset)
+ {
+ case 0x22: /* C022 - TBCOLOR */
+ m_fgcolor = (data >> 4) & 0x0F;
+ m_bgcolor = (data >> 0) & 0x0F;
+ break;
+
+ case 0x23: /* C023 - VGCINT */
+ m_vgcint &= ~0x0F;
+ m_vgcint |= data & 0x0F;
+ break;
+
+ case 0x24: /* C024 - MOUSEDATA */
+ case 0x25: /* C025 - KEYMODREG */
+ case 0x28: /* C028 - ROMBANK */
+ case 0x2C: /* C02C - CHARROM */
+ case 0x2E: /* C02E - VERTCNT */
+ case 0x2F: /* C02F - HORIZCNT */
+ /* ignore these writes */
+ break;
+
+ case 0x26: /* C026 - DATAREG */
+ adb_write_datareg(space.machine(), data);
+ break;
+
+ case 0x27: /* C027 - KMSTATUS */
+ adb_write_kmstatus(this, data);
+ break;
+
+ case 0x29: /* C029 - NEWVIDEO */
+ m_newvideo = data;
+ break;
+
+ case 0x2B: /* C02B - LANGSEL */
+ m_langsel = data;
+ break;
+
+ case 0x2D: /* C02D - SLTROMSEL */
+ m_sltromsel = data;
+ apple2_update_memory(space.machine());
+ break;
+
+ case 0x31: /* C031 - DISKREG */
+ apple2_iwm_setdiskreg(space.machine(), data);
+ break;
+
+ case 0x32: /* C032 - SCANINT */
+ apple2gs_set_scanint(space.machine(), data);
+ break;
+
+ case 0x33: /* C033 - CLOCKDATA */
+ m_clock_data = data;
+ break;
+
+ case 0x34: /* C034 - CLOCKCTL */
+ m_clock_control = data & 0x7F;
+ m_bordercolor = data & 0x0F;
+ if (data & 0x80)
+ process_clock(space.machine());
+ break;
+
+ case 0x35: /* C035 - SHADOW */
+ if (m_shadow != data)
+ {
+ m_shadow = data;
+ apple2_update_memory(space.machine());
+ }
+ break;
+
+ case 0x36: /* C036 - CYAREG */
+ m_cyareg = data & ~0x20;
+ space.machine().device("maincpu")->set_unscaled_clock((data & 0x80) ? APPLE2GS_14M/5 : APPLE2GS_7M/7);
+ break;
+
+ case 0x38: /* C038 - SCCBREG */
+ case 0x39: /* C039 - SCCAREG */
+ case 0x3A: /* C03A - SCCBDATA */
+ case 0x3B: /* C03B - SCCADATA */
+ scc = space.machine().device<scc8530_t>("scc");
+ scc->reg_w(space, offset & 0x03, data);
+ break;
+
+ case 0x3C: /* C03C - SOUNDCTL */
+ case 0x3D: /* C03D - SOUNDDATA */
+ case 0x3E: /* C03E - SOUNDADRL */
+ case 0x3F: /* C03F - SOUNDADRH */
+ gssnd_w(&space, offset & 0x03, data);
+ break;
+
+ case 0x41: /* C041 - INTEN */
+ m_inten = data & 0x1F;
+ if ((m_inten & 0x10) == 0x00)
+ apple2gs_remove_irq(space.machine(), IRQ_INTEN_QSECOND);
+ if ((m_inten & 0x08) == 0x00)
+ apple2gs_remove_irq(space.machine(), IRQ_INTEN_VBL);
+ break;
+
+ case 0x47: /* C047 - CLRVBLINT */
+ m_intflag &= ~0x18;
+ apple2gs_remove_irq(space.machine(), IRQ_INTEN_QSECOND);
+ apple2gs_remove_irq(space.machine(), IRQ_INTEN_VBL);
+ break;
+
+ case 0x68: /* C068 - STATEREG */
+ apple2_setvar(space.machine(),
+ ((data & 0x80) ? VAR_ALTZP : 0) |
+ ((data & 0x40) ? VAR_PAGE2 : 0) |
+ ((data & 0x20) ? VAR_RAMRD : 0) |
+ ((data & 0x10) ? VAR_RAMWRT : 0) |
+ ((data & 0x08) ? 0 : VAR_LCRAM) |
+ ((data & 0x04) ? VAR_LCRAM2 : 0) |
+ ((data & 0x01) ? VAR_INTCXROM : 0),
+ VAR_ALTZP | VAR_PAGE2 | VAR_RAMRD | VAR_RAMWRT | VAR_LCRAM | VAR_LCRAM2 | VAR_INTCXROM);
+ break;
+
+ // slot 6 registers should go to applefdc if slot 6 not "Your Card"
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ if ((m_sltromsel & (1 << 6)) == 0)
+ {
+ applefdc_w(m_fdc, offset, data);
+ }
+ else
+ {
+ apple2_c0xx_w(space, offset, data, 0);
+ }
+ break;
+
+ default:
+ if (offset < 0x80)
+ {
+ apple2_c0xx_w(space, offset, data, 0);
+ }
+ else
+ {
+ apple2_c080_w(space, offset, data, 0);
+ }
+ break;
+ }
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * Memory management
+ * ----------------------------------------------------------------------- */
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_main0400_w )
+{
+ offset += 0x000400;
+ m_rambase[offset] = data;
+
+ if (!(m_shadow & 0x01))
+ {
+ m_slowmem[offset] = data;
+ }
+}
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_aux0400_w )
+{
+ offset += 0x010400;
+ m_rambase[offset] = data;
+
+ if (!(m_shadow & 0x01))
+ {
+ m_slowmem[offset] = data;
+ }
+}
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_main2000_w )
+{
+ offset += 0x002000;
+ m_rambase[offset] = data;
+
+ if (!(m_shadow & 0x02))
+ {
+ m_slowmem[offset] = data;
+ }
+}
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_aux2000_w )
+{
+ offset += 0x012000;
+ m_rambase[offset] = data;
+
+ if (!(m_shadow & 0x12) || !(m_shadow & 0x08))
+ {
+ m_slowmem[offset] = data;
+ }
+}
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_main4000_w )
+{
+ offset += 0x004000;
+ m_rambase[offset] = data;
+
+ if ((offset >= 0x004000) && (offset <= 0x005FFF))
+ {
+ if (!(m_shadow & 0x04))
+ m_slowmem[offset] = data;
+ }
+}
+
+WRITE8_MEMBER( apple2gs_state::apple2gs_aux4000_w )
+{
+ offset += 0x014000;
+ m_rambase[offset] = data;
+
+ if ((offset >= 0x014000) && (offset <= 0x015FFF))
+ {
+ if (!(m_shadow & 0x14) || !(m_shadow & 0x08))
+ m_slowmem[offset] = data;
+ }
+ else if ((offset >= 0x016000) && (offset <= 0x019FFF))
+ {
+ if (!(m_shadow & 0x08))
+ {
+ m_slowmem[offset] = data;
+
+ if (offset >= 0x19e00)
+ {
+ int color = (offset - 0x19e00) >> 1;
+
+ palette_set_color_rgb(space.machine(), color + 16,
+ ((m_slowmem[0x19E00 + (color * 2) + 1] >> 0) & 0x0F) * 17,
+ ((m_slowmem[0x19E00 + (color * 2) + 0] >> 4) & 0x0F) * 17,
+ ((m_slowmem[0x19E00 + (color * 2) + 0] >> 0) & 0x0F) * 17);
+ }
+ }
+ }
+}
+
+
+
+static void apple2gs_mem_000000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ meminfo->read_mem = (state->m_flags & VAR_ALTZP) ? 0x010000 : 0x000000;
+ meminfo->write_mem = (state->m_flags & VAR_ALTZP) ? 0x010000 : 0x000000;
+}
+
+static void apple2gs_mem_000200(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x010200 : 0x000200;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x010200 : 0x000200;
+}
+
+static void apple2gs_mem_000400(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_flags & VAR_80STORE)
+ {
+ meminfo->read_mem = (state->m_flags & VAR_PAGE2) ? 0x010400 : 0x000400;
+ meminfo->write_mem = (state->m_flags & VAR_PAGE2) ? 0x010400 : 0x000400;
+ meminfo->write_handler = (state->m_flags & VAR_PAGE2) ? &state->write_delegates_2gs0400[0] : &state->write_delegates_2gs0400[1];
+ }
+ else
+ {
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x010400 : 0x000400;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x010400 : 0x000400;
+ meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_2gs0400[0] : &state->write_delegates_2gs0400[1];
+ }
+}
+
+static void apple2gs_mem_000800(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x010800 : 0x000800;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x010800 : 0x000800;
+}
+
+static void apple2gs_mem_002000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if ((state->m_flags & (VAR_80STORE|VAR_HIRES)) == (VAR_80STORE|VAR_HIRES))
+ {
+ meminfo->read_mem = (state->m_flags & VAR_PAGE2) ? 0x012000 : 0x002000;
+ meminfo->write_mem = (state->m_flags & VAR_PAGE2) ? 0x012000 : 0x002000;
+ meminfo->write_handler = (state->m_flags & VAR_PAGE2) ? &state->write_delegates_2gs2000[0] : &state->write_delegates_2gs2000[1];
+ }
+ else
+ {
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x012000 : 0x002000;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x012000 : 0x002000;
+ meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_2gs2000[0] : &state->write_delegates_2gs2000[1];
+ }
+}
+
+static void apple2gs_mem_004000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x014000 : 0x004000;
+ meminfo->write_handler = (state->m_flags & VAR_RAMWRT) ? &state->write_delegates_2gs4000[0] : &state->write_delegates_2gs4000[1];
+}
+
+static void apple2gs_mem_xxD000(running_machine &machine,apple2_meminfo *meminfo, UINT32 lcmem)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_flags & VAR_LCRAM)
+ {
+ if (state->m_flags & VAR_LCRAM2)
+ meminfo->read_mem = lcmem | 0x00C000;
+ else
+ meminfo->read_mem = lcmem | 0x00D000;
+ }
+ else
+ {
+ meminfo->read_mem = 0x03D000 | APPLE2_MEM_ROM;
+ }
+
+ if (state->m_flags & VAR_LCWRITE)
+ {
+ if (state->m_flags & VAR_LCRAM2)
+ meminfo->write_mem = lcmem | 0x00C000;
+ else
+ meminfo->write_mem = lcmem | 0x00D000;
+ }
+ else
+ {
+ meminfo->write_mem = APPLE2_MEM_FLOATING;
+ }
+}
+
+static void apple2gs_mem_xxE000(running_machine &machine,apple2_meminfo *meminfo, UINT32 lcmem)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_flags & VAR_LCRAM)
+ meminfo->read_mem = lcmem | 0x00E000;
+ else
+ meminfo->read_mem = 0x03E000 | APPLE2_MEM_ROM;
+
+ if (state->m_flags & VAR_LCWRITE)
+ meminfo->write_mem = lcmem | 0x00E000;
+ else
+ meminfo->write_mem = APPLE2_MEM_FLOATING;
+}
+
+static void apple2gs_mem_00D000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_shadow & 0x40)
+ {
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x01D000 : 0x00D000;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x01D000 : 0x00D000;
+ }
+ else
+ {
+ apple2gs_mem_xxD000(machine,meminfo, (state->m_flags & VAR_ALTZP) ? 0x010000 : 0x000000);
+ }
+}
+
+static void apple2gs_mem_00E000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_shadow & 0x40)
+ {
+ meminfo->read_mem = (state->m_flags & VAR_RAMRD) ? 0x01E000 : 0x00E000;
+ meminfo->write_mem = (state->m_flags & VAR_RAMWRT) ? 0x01E000 : 0x00E000;
+ }
+ else
+ {
+ apple2gs_mem_xxE000(machine,meminfo, (state->m_flags & VAR_ALTZP) ? 0x010000 : 0x000000);
+ }
+}
+
+static void apple2gs_mem_01D000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_shadow & 0x40)
+ {
+ meminfo->read_mem = 0x01D000;
+ meminfo->write_mem = 0x01D000;
+ }
+ else
+ {
+ apple2gs_mem_xxD000(machine,meminfo, 0x010000);
+ }
+}
+
+static void apple2gs_mem_01E000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ if (state->m_shadow & 0x40)
+ {
+ meminfo->read_mem = 0x01E000;
+ meminfo->write_mem = 0x01E000;
+ }
+ else
+ {
+ apple2gs_mem_xxE000(machine,meminfo, 0x010000);
+ }
+}
+
+static void apple2gs_mem_E0D000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_mem_xxD000(machine,meminfo, 0x000000 | APPLE2_MEM_AUX);
+}
+
+static void apple2gs_mem_E0E000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_mem_xxE000(machine,meminfo, 0x000000 | APPLE2_MEM_AUX);
+}
+
+static void apple2gs_mem_E1D000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_mem_xxD000(machine,meminfo, 0x010000 | APPLE2_MEM_AUX);
+}
+
+static void apple2gs_mem_E1E000(running_machine &machine,offs_t begin, offs_t end, apple2_meminfo *meminfo)
+{
+ apple2gs_mem_xxE000(machine,meminfo, 0x010000 | APPLE2_MEM_AUX);
+}
+
+
+
+static const apple2_memmap_entry apple2gs_memmap_entries[] =
+{
+ { 0x000000, 0x0001FF, apple2gs_mem_000000, A2MEM_MONO },
+ { 0x000200, 0x0003FF, apple2gs_mem_000200, A2MEM_DUAL },
+ { 0x000400, 0x0007FF, apple2gs_mem_000400, A2MEM_DUAL },
+ { 0x000800, 0x001FFF, apple2gs_mem_000800, A2MEM_DUAL },
+ { 0x002000, 0x003FFF, apple2gs_mem_002000, A2MEM_DUAL },
+ { 0x004000, 0x00BFFF, apple2gs_mem_004000, A2MEM_DUAL },
+ { 0x00D000, 0x00DFFF, apple2gs_mem_00D000, A2MEM_DUAL },
+ { 0x00E000, 0x00FFFF, apple2gs_mem_00E000, A2MEM_DUAL },
+
+ { 0x01D000, 0x01DFFF, apple2gs_mem_01D000, A2MEM_DUAL },
+ { 0x01E000, 0x01FFFF, apple2gs_mem_01E000, A2MEM_DUAL },
+ { 0xE0D000, 0xE0DFFF, apple2gs_mem_E0D000, A2MEM_DUAL },
+ { 0xE0E000, 0xE0FFFF, apple2gs_mem_E0E000, A2MEM_DUAL },
+ { 0xE1D000, 0xE1DFFF, apple2gs_mem_E1D000, A2MEM_DUAL },
+ { 0xE1E000, 0xE1FFFF, apple2gs_mem_E1E000, A2MEM_DUAL },
+
+ { 0 }
+};
+
+
+
+static UINT8 *apple2gs_getslotmem(running_machine &machine, offs_t address)
+{
+ UINT8 *rom;
+
+ address %= 0x00FFFF;
+ assert(address >= 0xC000);
+ assert(address <= 0xCFFF);
+
+ rom = machine.root_device().memregion("maincpu")->base();
+ rom += 0x030000 % machine.root_device().memregion("maincpu")->bytes();
+ return &rom[address];
+}
+
+
+
+static UINT8 apple2gs_xxCxxx_r(address_space &space, running_machine &machine, offs_t address)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ UINT8 result;
+ int slot;
+
+ if ((state->m_shadow & 0x40) && ((address & 0xF00000) == 0x000000)) // shadow all banks and C0xx?
+ {
+ result = machine.device<ram_device>(RAM_TAG)->pointer()[address];
+ }
+ else if ((address & 0x000F00) == 0x000000) // accessing C0xx?
+ {
+ result = state->apple2gs_c0xx_r(*machine.device("maincpu")->memory().space(AS_PROGRAM), address, 0);
+ }
+ else
+ {
+ device_a2bus_card_interface *slotdevice;
+
+ slot = (address & 0x000F00) / 0x100;
+ if (slot <= 7) // slots 1-7, it's the slot
+ {
+ slotdevice = state->m_a2bus->get_a2bus_card(slot);
+
+ // is this slot internal or "Your Card"?
+ if ((state->m_sltromsel & (1 << slot)) == 0)
+ {
+ // accessing a slot mapped to internal, let's put back the internal ROM
+ state->m_a2_cnxx_slot = -1;
+ apple2_update_memory(space.machine());
+ result = *apple2gs_getslotmem(machine, address);
+ }
+ else
+ {
+ // accessing a slot mapped to "Your Card", C800 should belong to that card
+ if (slotdevice != NULL)
+ {
+ if (slotdevice->take_c800())
+ {
+ state->m_a2_cnxx_slot = slot;
+ apple2_update_memory(space.machine());
+ }
+ result = slotdevice->read_cnxx(space, address&0xff);
+ }
+ else
+ {
+ result = apple2_getfloatingbusvalue(machine);
+ }
+ }
+ }
+ else // C800-CFFF, not cards
+ {
+ slotdevice = NULL;
+
+ // if CFFF accessed, reset C800 area to internal ROM
+ if(!space.debugger_access())
+ {
+ if ((address & 0xfff) == 0xfff)
+ {
+ state->m_a2_cnxx_slot = -1;
+ apple2_update_memory(space.machine());
+ }
+ }
+
+ if ( state->m_a2_cnxx_slot >= 0 && state->m_a2_cnxx_slot <= 7 )
+ {
+ slotdevice = state->m_a2bus->get_a2bus_card(state->m_a2_cnxx_slot);
+ }
+
+ if (slotdevice)
+ {
+ result = slotdevice->read_c800(space, address&0x7ff);
+ }
+ else
+ {
+ result = *apple2gs_getslotmem(machine, address);
+ }
+ }
+ }
+ return result;
+}
+
+
+
+static void apple2gs_xxCxxx_w(address_space &space, running_machine &machine, offs_t address, UINT8 data)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ int slot;
+
+ // if CFFF accessed, reset C800 area to internal ROM
+ if(!space.debugger_access())
+ {
+ if ((address & 0xfff) == 0xfff)
+ {
+ state->m_a2_cnxx_slot = -1;
+ apple2_update_memory(space.machine());
+ }
+ }
+
+ if ((state->m_shadow & 0x40) && ((address & 0xF00000) == 0x000000))
+ {
+ machine.device<ram_device>(RAM_TAG)->pointer()[address] = data;
+ }
+ else if ((address & 0x000F00) == 0x000000)
+ {
+ state->apple2gs_c0xx_w(*machine.device("maincpu")->memory().space(AS_PROGRAM), address, data, 0);
+ }
+ else
+ {
+ device_a2bus_card_interface *slotdevice;
+
+ slot = (address & 0x000F00) / 0x100;
+
+ if (slot <= 7) // slots 1-7, it's the slot
+ {
+ slotdevice = state->m_a2bus->get_a2bus_card(slot);
+
+ // is this slot internal or "Your Card"?
+ if ((state->m_sltromsel & (1 << slot)) == 0)
+ {
+ // accessing a slot mapped to internal, let's put back the internal ROM
+ state->m_a2_cnxx_slot = -1;
+ apple2_update_memory(space.machine());
+ *apple2gs_getslotmem(machine, address) = data;
+ }
+ else
+ {
+ // accessing a slot mapped to "Your Card", C800 should belong to that card if it can take it
+ if (slotdevice != NULL)
+ {
+ if (slotdevice->take_c800())
+ {
+ state->m_a2_cnxx_slot = slot;
+ apple2_update_memory(space.machine());
+ }
+ slotdevice->write_cnxx(space, address&0xff, data);
+ }
+ // (else slot is your card but there's no card inserted so the write goes nowhere)
+ }
+ }
+ else // C800-CFFF, not cards
+ {
+ slotdevice = NULL;
+
+ // if CFFF accessed, reset C800 area to internal ROM
+ if ((address & 0xfff) == 0xfff)
+ {
+ state->m_a2_cnxx_slot = -1;
+ apple2_update_memory(space.machine());
+ }
+
+ if ( state->m_a2_cnxx_slot >= 0 && state->m_a2_cnxx_slot <= 7 )
+ {
+ slotdevice = state->m_a2bus->get_a2bus_card(state->m_a2_cnxx_slot);
+ }
+
+ if (slotdevice)
+ {
+ slotdevice->write_c800(space, address&0x7ff, data);
+ }
+ else
+ {
+ *apple2gs_getslotmem(machine, address) = data;
+ }
+ }
+ }
+}
+
+
+
+DIRECT_UPDATE_MEMBER(apple2gs_state::apple2gs_opbase)
+{
+ UINT8 *opptr = NULL;
+ int slot;
+
+ if (((address & 0xFEF000) == 0x00C000) || ((address & 0xFEF000) == 0xE0C000))
+ {
+ if ((m_shadow & 0x40) && ((address & 0xF00000) == 0x000000))
+ {
+ opptr = &machine().device<ram_device>(RAM_TAG)->pointer()[address];
+ }
+ else if ((address & 0x000F00) == 0x000000)
+ {
+ if (((address & 0xFF) >= 0x71) && ((address & 0xFF) <= 0x7F))
+ opptr = apple2gs_getslotmem(machine(), address);
+ }
+ else
+ {
+ slot = (address & 0x000F00) / 0x100;
+
+ if ((slot > 7) || ((m_sltromsel & (1 << slot)) == 0))
+ opptr = apple2gs_getslotmem(machine(), address);
+ }
+
+ if (opptr != NULL)
+ {
+ direct.explicit_configure(address, address, ~0, opptr - address);
+
+ address = ~0;
+ }
+ }
+ return address;
+}
+
+
+
+static READ8_HANDLER( apple2gs_00Cxxx_r ) { return apple2gs_xxCxxx_r(*space, space->machine(), offset | 0x00C000); }
+static READ8_HANDLER( apple2gs_01Cxxx_r ) { return apple2gs_xxCxxx_r(*space, space->machine(), offset | 0x01C000); }
+static READ8_HANDLER( apple2gs_E0Cxxx_r ) { return apple2gs_xxCxxx_r(*space, space->machine(), offset | 0xE0C000); }
+static READ8_HANDLER( apple2gs_E1Cxxx_r ) { return apple2gs_xxCxxx_r(*space, space->machine(), offset | 0xE1C000); }
+
+static WRITE8_HANDLER( apple2gs_00Cxxx_w ) { apple2gs_xxCxxx_w(*space, space->machine(), offset | 0x00C000, data); }
+static WRITE8_HANDLER( apple2gs_01Cxxx_w ) { apple2gs_xxCxxx_w(*space, space->machine(), offset | 0x01C000, data); }
+static WRITE8_HANDLER( apple2gs_E0Cxxx_w ) { apple2gs_xxCxxx_w(*space, space->machine(), offset | 0xE0C000, data); }
+static WRITE8_HANDLER( apple2gs_E1Cxxx_w ) { apple2gs_xxCxxx_w(*space, space->machine(), offset | 0xE1C000, data); }
+
+static WRITE8_HANDLER( apple2gs_Exxxxx_w )
+{
+ apple2gs_state *state = space->machine().driver_data<apple2gs_state>();
+ state->m_slowmem[offset] = data;
+}
+
+static WRITE8_HANDLER( apple2gs_E004xx_w ) { apple2gs_Exxxxx_w(space, offset + 0x00400, data); }
+static WRITE8_HANDLER( apple2gs_E02xxx_w ) { apple2gs_Exxxxx_w(space, offset + 0x02000, data); }
+static WRITE8_HANDLER( apple2gs_E104xx_w ) { apple2gs_Exxxxx_w(space, offset + 0x10400, data); }
+static WRITE8_HANDLER( apple2gs_E12xxx_w ) { apple2gs_Exxxxx_w(space, offset + 0x12000, data); }
+
+static WRITE8_HANDLER( apple2gs_slowmem_w )
+{
+ apple2gs_state *state = space->machine().driver_data<apple2gs_state>();
+ state->m_slowmem[offset] = data;
+
+ if ((offset >= 0x19e00) && (offset < 0x19fff))
+ {
+ int color = (offset - 0x19e00) >> 1;
+
+ palette_set_color_rgb(space->machine(), color + 16,
+ ((state->m_slowmem[0x19E00 + (color * 2) + 1] >> 0) & 0x0F) * 17,
+ ((state->m_slowmem[0x19E00 + (color * 2) + 0] >> 4) & 0x0F) * 17,
+ ((state->m_slowmem[0x19E00 + (color * 2) + 0] >> 0) & 0x0F) * 17);
+ }
+}
+
+// Because the bank address multiplexes on the 65816 data bus, reading a memory area
+// which doesn't drive the bus results in reading back the bank number.
+static READ8_HANDLER(apple2gs_bank_echo_r)
+{
+ apple2gs_state *state = space->machine().driver_data<apple2gs_state>();
+
+ return state->m_echo_bank + (offset>>16);
+}
+
+static void apple2gs_setup_memory(running_machine &machine)
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ address_space* space = machine.device("maincpu")->memory().space(AS_PROGRAM);
+ offs_t begin, end;
+ apple2_memmap_config cfg;
+
+ /* allocate memory for E00000-E1FFFF */
+ state->m_slowmem = auto_alloc_array_clear(machine, UINT8, 128*1024);
+ state_save_register_item_pointer(machine, "APPLE2GS_SLOWMEM", NULL, 0, state->m_slowmem, 128*1024);
+
+ // install expanded memory
+ // fair warning: other code assumes banks 0 and 1 are the first 128k of the RAM device, so you must install bank 1 at 0x10000
+ // otherwise nothing works :)
+ if (state->m_is_rom3)
+ {
+ int ramsize = machine.device<ram_device>(RAM_TAG)->size();
+
+ // ROM 03 hardware: the quoted "1 MB" for a base machine doesn't include banks e0/e1, so map accordingly
+ space->install_readwrite_bank(0x010000, ramsize - 1, "bank1");
+ state->membank("bank1")->set_base(machine.device<ram_device>(RAM_TAG)->pointer() + 0x010000);
+
+ space->install_legacy_read_handler( ramsize, 0xdfffff, FUNC(apple2gs_bank_echo_r));
+ state->m_echo_bank = (ramsize >> 16);
+ }
+ else
+ {
+ int ramsize = machine.device<ram_device>(RAM_TAG)->size()-0x30000;
+
+ // ROM 00/01 hardware: the quoted "256K" for a base machine *does* include banks e0/e1.
+ space->install_readwrite_bank(0x010000, ramsize - 1 + 0x10000, "bank1");
+ state->membank("bank1")->set_base(machine.device<ram_device>(RAM_TAG)->pointer() + 0x010000);
+
+ space->install_legacy_read_handler( ramsize + 0x10000, 0xdfffff, FUNC(apple2gs_bank_echo_r));
+ state->m_echo_bank = (ramsize+0x10000) >> 16;
+ }
+
+ /* install hi memory */
+ space->install_read_bank(0xe00000, 0xe1ffff, "bank2");
+ space->install_legacy_write_handler(0xe00000, 0xe1ffff, FUNC(apple2gs_slowmem_w));
+ space->install_legacy_write_handler(0xe00400, 0xe007ff, FUNC(apple2gs_E004xx_w));
+ space->install_legacy_write_handler(0xe02000, 0xe03fff, FUNC(apple2gs_E02xxx_w));
+ space->install_legacy_write_handler(0xe10400, 0xe107ff, FUNC(apple2gs_E104xx_w));
+ space->install_legacy_write_handler(0xe12000, 0xe13fff, FUNC(apple2gs_E12xxx_w));
+ state->membank("bank2")->set_base(state->m_slowmem);
+
+ /* install alternate ROM bank */
+ begin = 0x1000000 - machine.root_device().memregion("maincpu")->bytes();
+ end = 0xffffff;
+ space->install_read_bank(begin, end, "bank3");
+ state->membank("bank3")->set_base(machine.root_device().memregion("maincpu")->base());
+
+ /* install new xxC000-xxCFFF handlers */
+ space->install_legacy_read_handler(0x00c000, 0x00cfff, FUNC(apple2gs_00Cxxx_r));
+ space->install_legacy_write_handler(0x00c000, 0x00cfff, FUNC(apple2gs_00Cxxx_w));
+ space->install_legacy_read_handler(0x01c000, 0x01cfff, FUNC(apple2gs_01Cxxx_r));
+ space->install_legacy_write_handler(0x01c000, 0x01cfff, FUNC(apple2gs_01Cxxx_w));
+ space->install_legacy_read_handler(0xe0c000, 0xe0cfff, FUNC(apple2gs_E0Cxxx_r));
+ space->install_legacy_write_handler(0xe0c000, 0xe0cfff, FUNC(apple2gs_E0Cxxx_w));
+ space->install_legacy_read_handler(0xe1c000, 0xe1cfff, FUNC(apple2gs_E1Cxxx_r));
+ space->install_legacy_write_handler(0xe1c000, 0xe1cfff, FUNC(apple2gs_E1Cxxx_w));
+ space->set_direct_update_handler(direct_update_delegate(FUNC(apple2gs_state::apple2gs_opbase), state));
+
+
+ /* install aux memory writes (for shadowing) */
+ space->install_write_handler(0x010400, 0x0107FF, write8_delegate(FUNC(apple2gs_state::apple2gs_aux0400_w), state));
+ space->install_write_handler(0x012000, 0x013FFF, write8_delegate(FUNC(apple2gs_state::apple2gs_aux2000_w), state));
+ space->install_write_handler(0x014000, 0x019FFF, write8_delegate(FUNC(apple2gs_state::apple2gs_aux4000_w), state));
+
+ /* setup the Apple II memory system */
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.first_bank = 4;
+ cfg.memmap = apple2gs_memmap_entries;
+ cfg.auxmem = state->m_slowmem;
+ cfg.auxmem_length = 0x20000;
+ apple2_setup_memory(machine, &cfg);
+}
+
+
+
+/* -----------------------------------------------------------------------
+ * Driver Init
+ * ----------------------------------------------------------------------- */
+
+static READ8_HANDLER( apple2gs_read_vector )
+{
+ return space->read_byte(offset | 0xFF0000);
+}
+
+MACHINE_RESET( apple2gs )
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+
+ state->apple2gs_refresh_delegates();
+
+ state->m_cur_slot6_image = NULL;
+ state->m_newvideo = 0x00;
+ state->m_vgcint = 0x00;
+ state->m_langsel = 0x00;
+ state->m_sltromsel = 0x00;
+ state->m_cyareg = 0x80;
+ state->m_inten = 0x00;
+ state->m_intflag = 0x00;
+ state->m_shadow = 0x00;
+ state->m_pending_irqs = 0x00;
+ state->m_mouse_x = 0x00;
+ state->m_mouse_y = 0x00;
+ state->m_mouse_dx = 0x00;
+ state->m_mouse_dy = 0x00;
+ state->m_adb_state = ADBSTATE_IDLE;
+ state->m_adb_kmstatus = 0x00;
+ state->m_adb_command = 0;
+ state->m_adb_mode = 0;
+ state->m_adb_latent_result = 0;
+ state->m_adb_command_length = 0;
+ state->m_adb_command_pos = 0;
+ memset(state->m_adb_command_bytes, 0, sizeof(state->m_adb_command_bytes));
+ memset(state->m_adb_response_bytes, 0, sizeof(state->m_adb_response_bytes));
+ state->m_adb_response_length = 0;
+ state->m_adb_response_pos = 0;
+ memset(state->m_adb_memory, 0, sizeof(state->m_adb_memory));
+ state->m_adb_address_keyboard = 2;
+ state->m_adb_address_mouse = 3;
+
+ /* init time */
+ state->m_clock_data = 0;
+ state->m_clock_control =0;
+ state->m_clock_read = 0;
+ state->m_clock_reg1 = 0;
+ state->m_clock_mode = CLOCKMODE_IDLE;
+ state->m_clock_curtime = 0;
+ state->m_clock_curtime_interval = 0;
+
+ state->m_sndglu_ctrl = 0x00;
+ state->m_sndglu_addr = 0;
+ state->m_sndglu_dummy_read = 0;
+}
+
+MACHINE_START( apple2gscommon )
+{
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+
+ state->apple2gs_refresh_delegates();
+ apple2_init_common(machine);
+
+ /* set up Apple IIgs vectoring */
+ g65816_set_read_vector_callback(machine.device("maincpu"), apple2gs_read_vector);
+
+ /* setup globals */
+ state->m_is_rom3 = true;
+
+ machine.device<nvram_device>("nvram")->set_base(state->m_clock_bram, sizeof(state->m_clock_bram));
+
+ /* save state stuff. note that the driver takes care of docram. */
+ UINT8* ram = machine.device<ram_device>(RAM_TAG)->pointer();
+ state_save_register_item_pointer(machine, "APPLE2GS_RAM", NULL, 0, ram, machine.device<ram_device>(RAM_TAG)->size());
+
+ state_save_register_item(machine, "NEWVIDEO", NULL, 0, state->m_newvideo);
+
+ state_save_register_item(machine, "VGCINT", NULL,0, state->m_vgcint);
+ state_save_register_item(machine, "LANGSEL", NULL,0, state->m_langsel);
+ state_save_register_item(machine, "SLTROMSEL", NULL,0, state->m_sltromsel);
+ state_save_register_item(machine, "CYAREG", NULL,0, state->m_cyareg);
+ state_save_register_item(machine, "INTEN", NULL,0, state->m_inten);
+ state_save_register_item(machine, "INTFLAG", NULL,0, state->m_intflag);
+ state_save_register_item(machine, "SHADOW", NULL,0, state->m_shadow);
+ state_save_register_item(machine, "PENDIRQ", NULL,0, state->m_pending_irqs);
+ state_save_register_item(machine, "MX", NULL,0, state->m_mouse_x);
+ state_save_register_item(machine, "MY", NULL,0, state->m_mouse_y);
+ state_save_register_item(machine, "MDX", NULL,0, state->m_mouse_dx);
+ state_save_register_item(machine, "MDY", NULL,0, state->m_mouse_dy);
+
+ state_save_register_item(machine, "CLKDATA", NULL,0, state->m_clock_data);
+ state_save_register_item(machine, "CLKCTRL", NULL,0, state->m_clock_control);
+ state_save_register_item(machine, "CLKRD", NULL,0, state->m_clock_read);
+ state_save_register_item(machine, "CLKREG1", NULL,0, state->m_clock_reg1);
+ state_save_register_item(machine, "CLKCURTIME", NULL,0, state->m_clock_curtime);
+ state_save_register_item(machine, "CLKCURTIMEINT", NULL,0, state->m_clock_curtime_interval);
+// state_save_register_item(machine, "CLKMODE", NULL,0, state->m_clock_mode);
+ state->save_item(NAME(state->m_clock_bram));
+
+ state->save_item(NAME(state->m_adb_memory));
+ state->save_item(NAME(state->m_adb_command_bytes));
+ state->save_item(NAME(state->m_adb_response_bytes));
+// state_save_register_item(machine, "ADB", NULL,0, state->m_adb_state);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_command);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_mode);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_kmstatus);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_latent_result);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_command_length);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_command_pos);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_response_length);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_response_pos);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_address_keyboard);
+ state_save_register_item(machine, "ADB", NULL,0, state->m_adb_address_mouse);
+
+ state_save_register_item(machine, "SNDGLUCTRL", NULL,0, state->m_sndglu_ctrl);
+ state_save_register_item(machine, "SNDGLUADDR", NULL,0, state->m_sndglu_addr);
+ state_save_register_item(machine, "SNDGLUDUMMYRD", NULL,0, state->m_sndglu_dummy_read);
+
+ state->m_clock_timer = machine.scheduler().timer_alloc(FUNC(apple2gs_clock_tick));
+ state->m_clock_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
+
+ state->m_qsecond_timer = machine.scheduler().timer_alloc(FUNC(apple2gs_qsecond_tick));
+ state->m_qsecond_timer->adjust(attotime::from_usec(266700), 0, attotime::from_usec(266700));
+
+ state->m_scanline_timer = machine.scheduler().timer_alloc(FUNC(apple2gs_scanline_tick));
+ state->m_scanline_timer->adjust(attotime::never);
+
+ // fire on scanline zero
+ state->m_scanline_timer->adjust(machine.primary_screen->time_until_pos(0, 0));
+}
+
+MACHINE_START( apple2gs )
+{
+ MACHINE_START_NAME(apple2gscommon)(machine);
+ apple2gs_setup_memory(machine);
+}
+
+MACHINE_START( apple2gsr1 )
+{
+ MACHINE_START_NAME(apple2gscommon)(machine);
+
+ apple2gs_state *state = machine.driver_data<apple2gs_state>();
+ state->m_is_rom3 = false;
+ apple2gs_setup_memory(machine);
+}
+
+void apple2gs_state::apple2gs_refresh_delegates()
+{
+ write_delegates_2gs0400[0] = write8_delegate(FUNC(apple2gs_state::apple2gs_aux0400_w), this);
+ write_delegates_2gs0400[1] = write8_delegate(FUNC(apple2gs_state::apple2gs_main0400_w), this);
+ write_delegates_2gs2000[0] = write8_delegate(FUNC(apple2gs_state::apple2gs_aux2000_w), this);
+ write_delegates_2gs2000[1] = write8_delegate(FUNC(apple2gs_state::apple2gs_main2000_w), this);
+ write_delegates_2gs4000[0] = write8_delegate(FUNC(apple2gs_state::apple2gs_aux4000_w), this);
+ write_delegates_2gs4000[1] = write8_delegate(FUNC(apple2gs_state::apple2gs_main4000_w), this);
+}
+