diff options
Diffstat (limited to 'src/mess/machine/apple2gs.c')
-rw-r--r-- | src/mess/machine/apple2gs.c | 2033 |
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); +} + |