diff options
Diffstat (limited to 'src/mame/drivers/x68k.c')
-rw-r--r-- | src/mame/drivers/x68k.c | 1854 |
1 files changed, 1854 insertions, 0 deletions
diff --git a/src/mame/drivers/x68k.c b/src/mame/drivers/x68k.c new file mode 100644 index 00000000000..af0a91a4948 --- /dev/null +++ b/src/mame/drivers/x68k.c @@ -0,0 +1,1854 @@ +// license:BSD-3-Clause +// copyright-holders:Barry Rodewald,Carl + +// Preliminary X68000 driver for MESS +// Started 18/11/2006 +// Written by Barry Rodewald + +/* + *** Basic memory map + + 0x000000 - 0xbfffff RAM (Max 12MB), vector table from ROM at 0xff0000 maps to 0x000000 at reset only + 0xc00000 - 0xdfffff Graphic VRAM + 0xe00000 - 0xe1ffff Text VRAM Plane 1 + 0xe20000 - 0xe3ffff Text VRAM Plane 2 + 0xe40000 - 0xe5ffff Text VRAM Plane 3 + 0xe60000 - 0xe7ffff Text VRAM Plane 4 + 0xe80000 CRTC + 0xe82000 Video Controller + 0xe84000 DMA Controller + 0xe86000 Supervisor Area set + 0xe88000 MFP + 0xe8a000 RTC + 0xe8c000 Printer + 0xe8e000 System Port (?) + 0xe90000 FM Sound source + 0xe92000 ADPCM + 0xe94000 FDC + 0xe96000 HDC + 0xe96021 SCSI (internal model) + 0xe98000 SCC + 0xe9a000 Serial I/O (PPI) + 0xe9c000 I/O controller + + [Expansions] + 0xe9c000 / 0xe9e000 FPU (Optional, X68000 only) + 0xea0000 SCSI + 0xeaf900 FAX + 0xeafa00 / 0xeafa10 MIDI (1st/2nd) + 0xeafb00 Serial + 0xeafc00/10/20/30 EIA232E + 0xeafd00 EIA232E + 0xeafe00 GPIB (?) + 0xec0000 - 0xecffff User I/O Expansion + + 0xeb0000 - 0xeb7fff Sprite registers + 0xeb8000 - 0xebffff Sprite VRAM + 0xed0000 - 0xed3fff SRAM + 0xf00000 - 0xfb0000 ROM (CGROM.DAT) + 0xfe0000 - 0xffffff ROM (IPLROM.DAT) + + + *** System hardware + + CPU : X68000: 68000 at 10MHz + X68000 XVI: 68000 at 16MHz + X68030: 68EC030 at 25MHz + + RAM : between 1MB and 4MB stock, expandable to 12MB + + FDD : 2x 5.25", Compact models use 2x 3.5" drives. + FDC : NEC uPD72065 + + HDD : HD models have up to an 81MB HDD. + HDC : Fujitsu MB89352A (SCSI) + + SCC : Serial controller - Zilog z85C30 (Dual channel, 1 for RS232, 1 for mouse) + PPI : Parallel controller - NEC 8255 (Printer, Joystick) + + Sound : FM - YM2151, with YM3012 DAC + ADPCM - Okidata MSM6258 + + DMA : Hitachi HD63450, DMA I/O for FDD, HDD, Expansion slots, and ADPCM + + MFP : Motorola MC68901 - monitor sync, serial port, RTC, soft power, FM synth, IRQs, keyboard + + RTC : Ricoh RP5C15 + + ...plus a number of custom chips for video and other stuff... + + + *** Current status (28/12/08) + MFP : Largely works, as far as the X68000 goes. + + PPI : Joystick controls work okay. + + HDC/HDD : SCSI is not implemented, not a requirement at this point. + + RTC : Seems to work. (Tested using SX-Window's Timer application) + + DMA : Works fine. + + Sound : FM works, ADPCM mostly works (timing(?) issues in a few games). + + SCC : Works enough to get the mouse running, although only with the IPL v1.0 BIOS + + Video : Text mode works, but is rather slow, especially scrolling up (uses multple "raster copy" commands). + Graphic layers work. + BG tiles and sprites work, but many games have the sprites offset by a small amount (some by a lot :)) + Still a few minor priority issues around. + + Other issues: + Bus error exceptions are a bit late at times. Currently using a fake bus error for MIDI expansion checks. These + are used determine if a piece of expansion hardware is present. + Keyboard doesn't work properly (MFP USART). + Supervisor area set isn't implemented. + + Some minor game-specific issues: + Salamander: System error when using keys in-game. No error if a joystick is used. + Some text is drawn incorrectly. + Dragon Buster: Text is black and unreadable. (Text layer actually covers it) + Tetris: Black dots over screen (text layer). + Parodius Da!: Black squares in areas. + + More detailed documentation at http://x68kdev.emuvibes.com/iomap.html - if you can stand broken english :) + +*/ + +#include "emu.h" +#include "machine/mc68901.h" +#include "machine/upd765.h" +#include "sound/okim6258.h" +#include "machine/rp5c15.h" +#include "machine/mb89352.h" +#include "formats/xdf_dsk.h" +#include "formats/dim_dsk.h" +#include "machine/x68k_hdc.h" +#include "machine/x68k_kbd.h" +#include "includes/x68k.h" +#include "machine/ram.h" +#include "machine/nvram.h" +#include "bus/x68k/x68kexp.h" +#include "bus/x68k/x68k_neptunex.h" +#include "bus/x68k/x68k_scsiext.h" +#include "bus/scsi/scsi.h" +#include "bus/scsi/scsihd.h" +#include "x68000.lh" + + + +void x68k_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_X68K_LED: + x68k_led_callback(ptr, param); + break; + case TIMER_X68K_SCC_ACK: + x68k_scc_ack(ptr, param); + break; + case TIMER_MD_6BUTTON_PORT1_TIMEOUT: + md_6button_port1_timeout(ptr, param); + break; + case TIMER_MD_6BUTTON_PORT2_TIMEOUT: + md_6button_port2_timeout(ptr, param); + break; + case TIMER_X68K_BUS_ERROR: + x68k_bus_error(ptr, param); + break; + case TIMER_X68K_NET_IRQ: + x68k_net_irq(ptr, param); + break; + case TIMER_X68K_CRTC_OPERATION_END: + x68k_crtc_operation_end(ptr, param); + break; + case TIMER_X68K_HSYNC: + x68k_hsync(ptr, param); + break; + case TIMER_X68K_CRTC_RASTER_END: + x68k_crtc_raster_end(ptr, param); + break; + case TIMER_X68K_CRTC_RASTER_IRQ: + x68k_crtc_raster_irq(ptr, param); + break; + case TIMER_X68K_CRTC_VBLANK_IRQ: + x68k_crtc_vblank_irq(ptr, param); + break; + case TIMER_X68K_FDC_TC: + m_upd72065->tc_w(ASSERT_LINE); + m_upd72065->tc_w(CLEAR_LINE); + break; + case TIMER_X68K_ADPCM: + m_hd63450->drq3_w(1); + m_hd63450->drq3_w(0); + break; + default: + assert_always(FALSE, "Unknown id in x68k_state::device_timer"); + } +} + +// LED timer callback +TIMER_CALLBACK_MEMBER(x68k_state::x68k_led_callback) +{ + int drive; + if(m_led_state == 0) + m_led_state = 1; + else + m_led_state = 0; + if(m_led_state == 1) + { + for(drive=0;drive<4;drive++) + output_set_indexed_value("ctrl_drv",drive,m_fdc.led_ctrl[drive] ? 0 : 1); + } + else + { + for(drive=0;drive<4;drive++) + output_set_indexed_value("ctrl_drv",drive,1); + } + +} + + +// mouse input +// port B of the Z8530 SCC +// typically read from the SCC data port on receive buffer full interrupt per byte +int x68k_state::x68k_read_mouse() +{ + char val = 0; + char ipt = 0; + + if(!(m_scc->get_reg_b(5) & 0x02)) + return 0xff; + + switch(m_mouse.inputtype) + { + case 0: + ipt = m_mouse1->read(); + break; + case 1: + val = m_mouse2->read(); + ipt = val - m_mouse.last_mouse_x; + m_mouse.last_mouse_x = val; + break; + case 2: + val = m_mouse3->read(); + ipt = val - m_mouse.last_mouse_y; + m_mouse.last_mouse_y = val; + break; + } + m_mouse.inputtype++; + if(m_mouse.inputtype > 2) + { + int i_val = m_scc->get_reg_b(0); + m_mouse.inputtype = 0; + m_mouse.bufferempty = 1; + i_val &= ~0x01; + m_scc->set_reg_b(0, i_val); + logerror("SCC: mouse buffer empty\n"); + } + + return ipt; +} + +/* + 0xe98001 - Z8530 command port B + 0xe98003 - Z8530 data port B (mouse input) + 0xe98005 - Z8530 command port A + 0xe98007 - Z8530 data port A (RS232) +*/ +READ16_MEMBER(x68k_state::x68k_scc_r ) +{ + offset %= 4; + switch(offset) + { + case 0: + return m_scc->reg_r(space, 0); + case 1: + return x68k_read_mouse(); + case 2: + return m_scc->reg_r(space, 1); + case 3: + return m_scc->reg_r(space, 3); + default: + return 0xff; + } +} + +WRITE16_MEMBER(x68k_state::x68k_scc_w ) +{ + offset %= 4; + + switch(offset) + { + case 0: + m_scc->reg_w(space, 0,(UINT8)data); + if((m_scc->get_reg_b(5) & 0x02) != m_scc_prev) + { + if(m_scc->get_reg_b(5) & 0x02) // Request to Send + { + int val = m_scc->get_reg_b(0); + m_mouse.bufferempty = 0; + val |= 0x01; + m_scc->set_reg_b(0,val); + } + } + break; + case 1: + m_scc->reg_w(space, 2,(UINT8)data); + break; + case 2: + m_scc->reg_w(space, 1,(UINT8)data); + break; + case 3: + m_scc->reg_w(space, 3,(UINT8)data); + break; + } + m_scc_prev = m_scc->get_reg_b(5) & 0x02; +} + +TIMER_CALLBACK_MEMBER(x68k_state::x68k_scc_ack) +{ + if(m_mouse.bufferempty != 0) // nothing to do if the mouse data buffer is empty + return; + +// if((m_ioc.irqstatus & 0xc0) != 0) +// return; + + // hard-code the IRQ vector for now, until the SCC code is more complete + if((m_scc->get_reg_a(9) & 0x08) || (m_scc->get_reg_b(9) & 0x08)) // SCC reg WR9 is the same for both channels + { + if((m_scc->get_reg_b(1) & 0x18) != 0) // if bits 3 and 4 of WR1 are 0, then Rx IRQs are disabled on this channel + { + if(m_scc->get_reg_b(5) & 0x02) // RTS signal + { + m_mouse.irqactive = 1; + m_current_vector[5] = 0x54; + m_current_irq_line = 5; + m_maincpu->set_input_line_and_vector(5,ASSERT_LINE,0x54); + } + } + } +} + +void x68k_state::x68k_set_adpcm() +{ + UINT32 rate = 0; + + switch(m_adpcm.rate & 0x0c) + { + case 0x00: + rate = 7812/2; + break; + case 0x04: + rate = 10417/2; + break; + case 0x08: + rate = 15625/2; + break; + default: + logerror("PPI: Invalid ADPCM sample rate set.\n"); + rate = 15625/2; + } + if(m_adpcm.clock != 0) + rate = rate/2; + m_adpcm_timer->adjust(attotime::from_hz(rate), 0, attotime::from_hz(rate)); +} + +// Megadrive 3 button gamepad +// According to XM6, bits 4 and 7 are always 1 (is this correct?) +// Bits 4 and 5 of PPI port C control each controller's multiplexer +// Button inputs (Start, A, B and C) are read in bits 5 and 6 (rather than 4 +// and 5 like on a Megadrive) + +UINT8 x68k_state::md_3button_r(int port) +{ + if(port == 1) + { + UINT8 porta = m_md3b->read() & 0xff; + UINT8 portb = (m_md3b->read() >> 8) & 0xff; + if(m_mdctrl.mux1 & 0x10) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | (porta & 0x03) | 0x90; + } + } + if(port == 2) + { + UINT8 porta = (m_md3b->read() >> 16) & 0xff; + UINT8 portb = (m_md3b->read() >> 24) & 0xff; + if(m_mdctrl.mux2 & 0x20) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | (porta & 0x03) | 0x90; + } + } + return 0xff; +} + +// Megadrive 6 button gamepad +TIMER_CALLBACK_MEMBER(x68k_state::md_6button_port1_timeout) +{ + m_mdctrl.seq1 = 0; +} + +TIMER_CALLBACK_MEMBER(x68k_state::md_6button_port2_timeout) +{ + m_mdctrl.seq2 = 0; +} + +void x68k_state::md_6button_init() +{ + m_mdctrl.io_timeout1 = timer_alloc(TIMER_MD_6BUTTON_PORT1_TIMEOUT); + m_mdctrl.io_timeout2 = timer_alloc(TIMER_MD_6BUTTON_PORT2_TIMEOUT); +} + +UINT8 x68k_state::md_6button_r(int port) +{ + if(port == 1) + { + UINT8 porta = m_md6b->read() & 0xff; + UINT8 portb = (m_md6b->read() >> 8) & 0xff; + UINT8 extra = m_md6b_extra->read() & 0x0f; + + switch(m_mdctrl.seq1) + { + case 1: + default: + if(m_mdctrl.mux1 & 0x10) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | (porta & 0x03) | 0x90; + } + case 2: + if(m_mdctrl.mux1 & 0x10) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | 0x90; + } + case 3: + if(m_mdctrl.mux1 & 0x10) + { + return (porta & 0x60) | (extra & 0x0f) | 0x90; + } + else + { + return (portb & 0x60) | 0x9f; + } + } + } + if(port == 2) + { + UINT8 porta = (m_md6b->read() >> 16) & 0xff; + UINT8 portb = (m_md6b->read() >> 24) & 0xff; + UINT8 extra = (m_md6b_extra->read() >> 4) & 0x0f; + + switch(m_mdctrl.seq2) + { + case 1: + default: + if(m_mdctrl.mux2 & 0x20) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | (porta & 0x03) | 0x90; + } + case 2: + if(m_mdctrl.mux2 & 0x20) + { + return porta | 0x90; + } + else + { + return (portb & 0x60) | 0x90; + } + case 3: + if(m_mdctrl.mux2 & 0x20) + { + return (porta & 0x60) | (extra & 0x0f) | 0x90; + } + else + { + return (portb & 0x60) | 0x9f; + } + } + } + return 0xff; +} + +// XPD-1LR dual D-pad controller. +// Sold with Video Game Anthology Vol 4: Libble Rabble. +// Also compatible with Video Game Anthology Vol 5: Crazy Climber 1 & 2 +// Uses the same input multiplexer hardware as Megadrive controllers +// Output is the same as for standard controllers, but when ctl is high, +// the directions refer to the right D-pad, and when low, the left D-pad +// The buttons are read the same as normal, regardless of ctl. +UINT8 x68k_state::xpd1lr_r(int port) +{ + if(port == 1) + { + UINT8 porta = m_xpd1lr->read() & 0xff; + UINT8 portb = (m_xpd1lr->read() >> 8) & 0xff; + if(m_mdctrl.mux1 & 0x10) + { + return porta; + } + else + { + return portb | (porta & 0x60); + } + } + if(port == 2) + { + UINT8 porta = (m_xpd1lr->read() >> 16) & 0xff; + UINT8 portb = (m_xpd1lr->read() >> 24) & 0xff; + if(m_mdctrl.mux2 & 0x20) + { + return porta; + } + else + { + return portb | (porta & 0x60); + } + } + return 0xff; +} + +// Judging from the XM6 source code, PPI ports A and B are joystick inputs +READ8_MEMBER(x68k_state::ppi_port_a_r) +{ + int ctrl = m_ctrltype->read() & 0x0f; + + switch(ctrl) + { + case 0x00: // standard MSX/FM-Towns joystick + if(m_joy.joy1_enable == 0) + return m_joy1->read(); + else + return 0xff; + case 0x01: // 3-button Megadrive gamepad + return md_3button_r(1); + case 0x02: // 6-button Megadrive gamepad + return md_6button_r(1); + case 0x03: // XPD-1LR + return xpd1lr_r(1); + } + + return 0xff; +} + +READ8_MEMBER(x68k_state::ppi_port_b_r) +{ + int ctrl = m_ctrltype->read() & 0xf0; + + switch(ctrl) + { + case 0x00: // standard MSX/FM-Towns joystick + if(m_joy.joy2_enable == 0) + return m_joy2->read(); + else + return 0xff; + case 0x10: // 3-button Megadrive gamepad + return md_3button_r(2); + case 0x20: // 6-button Megadrive gamepad + return md_6button_r(2); + case 0x30: // XPD-1LR + return xpd1lr_r(2); + } + + return 0xff; +} + +READ8_MEMBER(x68k_state::ppi_port_c_r) +{ + return m_ppi_port[2]; +} + +/* PPI port C (Joystick control, R/W) + bit 7 - IOC7 - Function B operation of joystick 1 (?) + bit 6 - IOC6 - Function A operation of joystick 1 (?) + bit 5 - IOC5 - Enable Joystick 2 + bit 4 - IOC4 - Enable Joystick 1 + bits 3,2 - ADPCM Sample rate + bits 1,0 - ADPCM Pan +*/ +WRITE8_MEMBER(x68k_state::ppi_port_c_w) +{ + // ADPCM / Joystick control + m_ppi_port[2] = data; + if((data & 0x0f) != (m_ppi_prev & 0x0f)) + { + m_adpcm.pan = data & 0x03; + m_adpcm.rate = data & 0x0c; + x68k_set_adpcm(); + m_okim6258->set_divider((data >> 2) & 3); + } + + // The joystick enable bits also handle the multiplexer for various controllers + m_joy.joy1_enable = data & 0x10; + m_mdctrl.mux1 = data & 0x10; + if((m_ppi_prev & 0x10) == 0x00 && (data & 0x10) == 0x10) + { + m_mdctrl.seq1++; + m_mdctrl.io_timeout1->adjust(m_maincpu->cycles_to_attotime(8192)); + } + + m_joy.joy2_enable = data & 0x20; + m_mdctrl.mux2 = data & 0x20; + if((m_ppi_prev & 0x20) == 0x00 && (data & 0x20) == 0x20) + { + m_mdctrl.seq2++; + m_mdctrl.io_timeout2->adjust(m_maincpu->cycles_to_attotime(8192)); + } + m_ppi_prev = data; + + m_joy.ioc6 = data & 0x40; + m_joy.ioc7 = data & 0x80; +} + + +// NEC uPD72065 at 0xe94000 +WRITE16_MEMBER(x68k_state::x68k_fdc_w) +{ + unsigned int drive, x; + switch(offset) + { + case 0x00: // drive option signal control + x = data & 0x0f; + for(drive=0;drive<4;drive++) + { + if(m_fdc.control_drives & (1 << drive)) + { + if(!(x & (1 << drive))) // functions take place on 1->0 transitions of drive bits only + { + m_fdc.led_ctrl[drive] = data & 0x80; // blinking drive LED if no disk inserted + m_fdc.led_eject[drive] = data & 0x40; // eject button LED (on when set to 0) + output_set_indexed_value("eject_drv",drive,(data & 0x40) ? 1 : 0); + if((data & 0x60) == 0x20) // ejects disk + m_fdc.floppy[drive]->unload(); + } + } + } + m_fdc.control_drives = data & 0x0f; + logerror("FDC: signal control set to %02x\n",data); + break; + case 0x01: { + x = data & 3; + m_upd72065->set_floppy(m_fdc.floppy[x]); + m_upd72065->set_rate((data & 0x10) ? 300000 : 500000); + m_fdc.motor = data & 0x80; + + for(int i = 0; i < 4; i++) + if(m_fdc.floppy[i]->exists()) + m_fdc.floppy[i]->mon_w(!BIT(data, 7)); + + output_set_indexed_value("access_drv",x,0); + if(x != m_fdc.select_drive) + output_set_indexed_value("access_drv",m_fdc.select_drive,1); + m_fdc.select_drive = x; + logerror("FDC: Drive #%i: Drive selection set to %02x\n",x,data); + break; + } + } +} + +READ16_MEMBER(x68k_state::x68k_fdc_r) +{ + unsigned int ret; + int x; + + switch(offset) + { + case 0x00: + ret = 0x00; + for(x=0;x<4;x++) + { + if(m_fdc.control_drives & (1 << x)) + { + ret = 0x00; + if(m_fdc.floppy[x]->exists()) + { + ret |= 0x80; + } + // bit 7 = disk inserted + // bit 6 = disk error (in insertion, presumably) + logerror("FDC: Drive #%i Disk check - returning %02x\n",x,ret); + } + } + return ret; + case 0x01: + logerror("FDC: IOC selection is write-only\n"); + return 0xff; + } + return 0xff; +} + +WRITE_LINE_MEMBER( x68k_state::fdc_irq ) +{ + if((m_ioc.irqstatus & 0x04) && state) + { + m_current_vector[1] = m_ioc.fdcvector; + m_ioc.irqstatus |= 0x80; + m_current_irq_line = 1; + logerror("FDC: IRQ triggered\n"); + m_maincpu->set_input_line_and_vector(1, ASSERT_LINE, m_current_vector[1]); + } + else + m_maincpu->set_input_line(1, CLEAR_LINE); +} + +WRITE8_MEMBER(x68k_state::x68k_ct_w) +{ + // CT1 and CT2 bits from YM2151 port 0x1b + // CT1 - ADPCM clock - 0 = 8MHz, 1 = 4MHz + // CT2 - 1 = Set ready state of FDC + if(data & 1) + { + m_upd72065->set_ready_line_connected(0); + m_upd72065->ready_w(0); + } + else + m_upd72065->set_ready_line_connected(1); + + m_adpcm.clock = data & 0x02; + x68k_set_adpcm(); + m_okim6258->set_clock(data & 0x02 ? 4000000 : 8000000); +} + +/* + Custom I/O controller at 0xe9c000 + 0xe9c001 (R) - Interrupt status + 0xe9c001 (W) - Interrupt mask (low nibble only) + - bit 7 = FDC interrupt + - bit 6 = FDD interrupt + - bit 5 = Printer Busy signal + - bit 4 = HDD interrupt + - bit 3 = HDD interrupts enabled + - bit 2 = FDC interrupts enabled + - bit 1 = FDD interrupts enabled + - bit 0 = Printer interrupts enabled + 0xe9c003 (W) - Interrupt vector + - bits 7-2 = vector + - bits 1,0 = device (00 = FDC, 01 = FDD, 10 = HDD, 11 = Printer) +*/ +WRITE16_MEMBER(x68k_state::x68k_ioc_w) +{ + switch(offset) + { + case 0x00: + m_ioc.irqstatus = data & 0x0f; + logerror("I/O: Status register write %02x\n",data); + break; + case 0x01: + switch(data & 0x03) + { + case 0x00: + m_ioc.fdcvector = data & 0xfc; + logerror("IOC: FDC IRQ vector = 0x%02x\n",data & 0xfc); + break; + case 0x01: + m_ioc.fddvector = data & 0xfc; + logerror("IOC: FDD IRQ vector = 0x%02x\n",data & 0xfc); + break; + case 0x02: + m_ioc.hdcvector = data & 0xfc; + logerror("IOC: HDD IRQ vector = 0x%02x\n",data & 0xfc); + break; + case 0x03: + m_ioc.prnvector = data & 0xfc; + logerror("IOC: Printer IRQ vector = 0x%02x\n",data & 0xfc); + break; + } + break; + } +} + +READ16_MEMBER(x68k_state::x68k_ioc_r) +{ + switch(offset) + { + case 0x00: + logerror("I/O: Status register read\n"); + return (m_ioc.irqstatus & 0xdf) | 0x20; + default: + return 0x00; + } +} + +/* + System ports at 0xe8e000 + Port 1 (0xe8e001) - Monitor contrast (bits 3-0) + Port 2 (0xe8e003) - Display / 3D scope control + - bit 3 - Display control signal (0 = on) + - bit 1 - 3D scope left shutter (0 = closed) + - bit 0 - 3D scope right shutter + Port 3 (0xe8e005) - Colour image unit control (bits 3-0) + Port 4 (0xe8e007) - Keyboard/NMI/Dot clock + - bit 3 - (R) 1 = Keyboard connected, (W) 1 = Key data can be transmitted + - bit 1 - NMI Reset + - bit 0 - HRL - high resolution dot clock - 1 = 1/2, 1/4, 1/8, 0 = 1/2, 1/3, 1/6 (normal) + Port 5 (0xe8e009) - ROM (bits 7-4)/DRAM (bits 3-0) wait, X68030 only + Port 6 (0xe8e00b) - CPU type and clock speed (XVI or later only, X68000 returns 0xFF) + - bits 7-4 - CPU Type (1100 = 68040, 1101 = 68030, 1110 = 68020, 1111 = 68000) + - bits 3-0 - clock speed (1001 = 50MHz, 40, 33, 25, 20, 16, 1111 = 10MHz) + Port 7 (0xe8e00d) - SRAM write enable - if 0x31 is written to this port, writing to SRAM is allowed. + Any other value, then SRAM is read only. + Port 8 (0xe8e00f) - Power off control - write 0x00, 0x0f, 0x0f sequentially to switch power off. +*/ +WRITE16_MEMBER(x68k_state::x68k_sysport_w) +{ + switch(offset) + { + case 0x00: + m_sysport.contrast = data & 0x0f; // often used for screen fades / blanking + m_screen->set_brightness(m_sysport.contrast * 0x11); + break; + case 0x01: + m_sysport.monitor = data & 0x08; + break; + case 0x03: + m_sysport.keyctrl = data & 0x08; // bit 3 = enable keyboard data transmission + break; + case 0x06: + COMBINE_DATA(&m_sysport.sram_writeprotect); + break; + default: +// logerror("SYS: [%08x] Wrote %04x to invalid or unimplemented system port %04x\n",space.device().safe_pc(),data,offset); + break; + } +} + +READ16_MEMBER(x68k_state::x68k_sysport_r) +{ + int ret = 0; + switch(offset) + { + case 0x00: // monitor contrast setting (bits3-0) + return m_sysport.contrast; + case 0x01: // monitor control (bit3) / 3D Scope (bits1,0) + ret |= m_sysport.monitor; + return ret; + case 0x03: // bit 3 = key control (is 1 if keyboard is connected) + return 0x08; + case 0x05: // CPU type and speed + return m_sysport.cputype; + default: + logerror("Read from invalid or unimplemented system port %04x\n",offset); + return 0xff; + } +} + +WRITE16_MEMBER(x68k_state::x68k_ppi_w) +{ + m_ppi->write(space,offset & 0x03,data); +} + +READ16_MEMBER(x68k_state::x68k_ppi_r) +{ + return m_ppi->read(space,offset & 0x03); +} + + +WRITE16_MEMBER(x68k_state::x68k_sram_w) +{ + if(m_sysport.sram_writeprotect == 0x31) + { + COMBINE_DATA(&m_nvram[offset]); + } +} + +READ16_MEMBER(x68k_state::x68k_sram_r) +{ + // HACKS! +// if(offset == 0x5a/2) // 0x5a should be 0 if no SASI HDs are present. +// return 0x0000; + if(offset == 0x08/2) + return m_ram->size() >> 16; // RAM size + return m_nvram[offset]; +} + +WRITE16_MEMBER(x68k_state::x68k_vid_w) +{ + switch(offset) + { + case 0x000: + COMBINE_DATA(m_video.reg); + break; + case 0x080: // priority levels + COMBINE_DATA(m_video.reg+1); + if(ACCESSING_BITS_0_7) + { + m_video.gfxlayer_pri[0] = data & 0x0003; + m_video.gfxlayer_pri[1] = (data & 0x000c) >> 2; + m_video.gfxlayer_pri[2] = (data & 0x0030) >> 4; + m_video.gfxlayer_pri[3] = (data & 0x00c0) >> 6; + } + if(ACCESSING_BITS_8_15) + { + m_video.gfx_pri = (data & 0x0300) >> 8; + m_video.text_pri = (data & 0x0c00) >> 10; + m_video.sprite_pri = (data & 0x3000) >> 12; + if(m_video.gfx_pri == 3) + m_video.gfx_pri--; + if(m_video.text_pri == 3) + m_video.text_pri--; + if(m_video.sprite_pri == 3) + m_video.sprite_pri--; + } + break; + case 0x100: + COMBINE_DATA(m_video.reg+2); + break; + default: + logerror("VC: Invalid video controller write (offset = 0x%04x, data = %04x)\n",offset,data); + } +} + +READ16_MEMBER(x68k_state::x68k_vid_r) +{ + switch(offset) + { + case 0x000: + return m_video.reg[0]; + case 0x080: + return m_video.reg[1]; + case 0x100: + return m_video.reg[2]; + default: + logerror("VC: Invalid video controller read (offset = 0x%04x)\n",offset); + } + + return 0xff; +} + +READ16_MEMBER(x68k_state::x68k_areaset_r) +{ + // register is write-only + return 0xffff; +} + +WRITE16_MEMBER(x68k_state::x68k_areaset_w) +{ + // TODO + logerror("SYS: Supervisor area set: 0x%02x\n",data & 0xff); +} + +WRITE16_MEMBER(x68k_state::x68k_enh_areaset_w ) +{ + // TODO + logerror("SYS: Enhanced Supervisor area set (from %iMB): 0x%02x\n",(offset + 1) * 2,data & 0xff); +} + +TIMER_CALLBACK_MEMBER(x68k_state::x68k_bus_error) +{ + m_bus_error = false; +} + +void x68k_state::set_bus_error(UINT32 address, bool write, UINT16 mem_mask) +{ + if(m_bus_error) + return; + if(!ACCESSING_BITS_8_15) + address++; + m_bus_error = true; + m_maincpu->set_buserror_details(address, write, m_maincpu->get_fc()); + m_maincpu->mmu_tmp_buserror_address = address; // Hack for x68030 + m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE); + m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE); + m_bus_error_timer->adjust(m_maincpu->cycles_to_attotime(16)); // let rmw cycles complete + logerror("%s: Bus error: Unused RAM access [%08x]\n", machine().describe_context(), address); +} + +READ16_MEMBER(x68k_state::x68k_rom0_r) +{ + /* this location contains the address of some expansion device ROM, if no ROM exists, + then access causes a bus error */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1) + 0xbffffc, 0, mem_mask); + return 0xff; +} + +WRITE16_MEMBER(x68k_state::x68k_rom0_w) +{ + /* this location contains the address of some expansion device ROM, if no ROM exists, + then access causes a bus error */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1) + 0xbffffc, 1, mem_mask); +} + +READ16_MEMBER(x68k_state::x68k_emptyram_r) +{ + /* this location is unused RAM, access here causes a bus error + Often a method for detecting amount of installed RAM, is to read or write at 1MB intervals, until a bus error occurs */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1), 0, mem_mask); + return 0xff; +} + +WRITE16_MEMBER(x68k_state::x68k_emptyram_w) +{ + /* this location is unused RAM, access here causes a bus error + Often a method for detecting amount of installed RAM, is to read or write at 1MB intervals, until a bus error occurs */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1), 1, mem_mask); +} + +READ16_MEMBER(x68k_state::x68k_exp_r) +{ + /* These are expansion devices, if not present, they cause a bus error */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1) + 0xeafa00, 0, mem_mask); + return 0xff; +} + +WRITE16_MEMBER(x68k_state::x68k_exp_w) +{ + /* These are expansion devices, if not present, they cause a bus error */ + if((m_options->read() & 0x02) && !space.debugger_access()) + set_bus_error((offset << 1) + 0xeafa00, 1, mem_mask); +} + +void x68k_state::dma_irq(int channel) +{ + m_current_vector[3] = m_hd63450->get_vector(channel); + m_current_irq_line = 3; + logerror("DMA#%i: DMA End (vector 0x%02x)\n",channel,m_current_vector[3]); + m_maincpu->set_input_line_and_vector(3,ASSERT_LINE,m_current_vector[3]); +} + +WRITE8_MEMBER(x68k_state::dma_end) +{ + if(data != 0) + { + dma_irq(offset); + } + if(offset == 0) + { + m_fdc_tc->adjust(attotime::from_usec(1), 0, attotime::never); + } +} + +WRITE8_MEMBER(x68k_state::dma_error) +{ + if(data != 0) + { + m_current_vector[3] = m_hd63450->get_error_vector(offset); + m_current_irq_line = 3; + logerror("DMA#%i: DMA Error (vector 0x%02x)\n",offset,m_current_vector[3]); + m_maincpu->set_input_line_and_vector(3,ASSERT_LINE,m_current_vector[3]); + } +} + +WRITE_LINE_MEMBER(x68k_state::x68k_fm_irq) +{ + if(state == CLEAR_LINE) + { + m_mfpdev->i3_w(1); + } + else + { + m_mfpdev->i3_w(0); + } +} + +WRITE8_MEMBER(x68k_state::x68030_adpcm_w) +{ + switch(offset) + { + case 0x00: + m_okim6258->okim6258_ctrl_w(space,0,data); + break; + case 0x01: + m_okim6258->okim6258_data_w(space,0,data); + break; + } +} + +WRITE_LINE_MEMBER(x68k_state::mfp_irq_callback) +{ + if(m_mfp_prev == CLEAR_LINE && state == CLEAR_LINE) // eliminate unnecessary calls to set the IRQ line for speed reasons + return; + if(state != CLEAR_LINE) + state = HOLD_LINE; // to get around erroneous spurious interrupt +// if((m_ioc.irqstatus & 0xc0) != 0) // if the FDC is busy, then we don't want to miss that IRQ +// return; + m_maincpu->set_input_line(6, state); + m_current_vector[6] = 0; + m_mfp_prev = state; +} + +IRQ_CALLBACK_MEMBER(x68k_state::x68k_int_ack) +{ + if(irqline == 6) // MFP + { + if(m_current_vector[6] != 0x4b && m_current_vector[6] != 0x4c) + m_current_vector[6] = m_mfpdev->get_vector(); + else + m_maincpu->set_input_line_and_vector(irqline,CLEAR_LINE,m_current_vector[irqline]); + logerror("SYS: IRQ acknowledged (vector=0x%02x, line = %i)\n",m_current_vector[6],irqline); + return m_current_vector[6]; + } + + m_maincpu->set_input_line_and_vector(irqline,CLEAR_LINE,m_current_vector[irqline]); + if(irqline == 1) // IOSC + { + m_ioc.irqstatus &= ~0xf0; + } + if(irqline == 5) // SCC + { + m_mouse.irqactive = 0; + } + + logerror("SYS: IRQ acknowledged (vector=0x%02x, line = %i)\n",m_current_vector[irqline],irqline); + return m_current_vector[irqline]; +} + +WRITE_LINE_MEMBER(x68k_state::x68k_scsi_irq) +{ + // TODO : Internal SCSI IRQ vector 0x6c, External SCSI IRQ vector 0xf6, IRQs go through the IOSC (IRQ line 1) + if(state != 0) + { + m_current_vector[1] = 0x6c; + m_current_irq_line = 1; + m_maincpu->set_input_line_and_vector(1,ASSERT_LINE,m_current_vector[1]); + } +} + +WRITE_LINE_MEMBER(x68k_state::x68k_scsi_drq) +{ + // TODO +} + +static ADDRESS_MAP_START(x68k_map, AS_PROGRAM, 16, x68k_state ) + AM_RANGE(0x000000, 0xbffffb) AM_READWRITE(x68k_emptyram_r, x68k_emptyram_w) + AM_RANGE(0xbffffc, 0xbfffff) AM_READWRITE(x68k_rom0_r, x68k_rom0_w) + AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(x68k_gvram_r, x68k_gvram_w) + AM_RANGE(0xe00000, 0xe7ffff) AM_READWRITE(x68k_tvram_r, x68k_tvram_w) + AM_RANGE(0xe80000, 0xe81fff) AM_READWRITE(x68k_crtc_r, x68k_crtc_w) + AM_RANGE(0xe82000, 0xe821ff) AM_DEVREADWRITE("gfxpalette", palette_device, read, write) AM_SHARE("gfxpalette") + AM_RANGE(0xe82200, 0xe823ff) AM_DEVREADWRITE("pcgpalette", palette_device, read, write) AM_SHARE("pcgpalette") + AM_RANGE(0xe82400, 0xe83fff) AM_READWRITE(x68k_vid_r, x68k_vid_w) + AM_RANGE(0xe84000, 0xe85fff) AM_DEVREADWRITE("hd63450", hd63450_device, read, write) + AM_RANGE(0xe86000, 0xe87fff) AM_READWRITE(x68k_areaset_r, x68k_areaset_w) + AM_RANGE(0xe88000, 0xe89fff) AM_DEVREADWRITE8(MC68901_TAG, mc68901_device, read, write, 0x00ff) + AM_RANGE(0xe8a000, 0xe8bfff) AM_DEVREADWRITE8(RP5C15_TAG, rp5c15_device, read, write, 0x00ff) +// AM_RANGE(0xe8c000, 0xe8dfff) AM_READWRITE(x68k_printer_r, x68k_printer_w) + AM_RANGE(0xe8e000, 0xe8ffff) AM_READWRITE(x68k_sysport_r, x68k_sysport_w) + AM_RANGE(0xe90000, 0xe91fff) AM_DEVREADWRITE8("ym2151", ym2151_device, read, write, 0x00ff) + AM_RANGE(0xe92000, 0xe92001) AM_DEVREADWRITE8("okim6258", okim6258_device, okim6258_status_r, okim6258_ctrl_w, 0x00ff) + AM_RANGE(0xe92002, 0xe92003) AM_DEVREADWRITE8("okim6258", okim6258_device, okim6258_status_r, okim6258_data_w, 0x00ff) + AM_RANGE(0xe94000, 0xe94003) AM_DEVICE8("upd72065", upd72065_device, map, 0x00ff) + AM_RANGE(0xe94004, 0xe94007) AM_READWRITE(x68k_fdc_r, x68k_fdc_w) + AM_RANGE(0xe96000, 0xe9601f) AM_DEVREADWRITE("x68k_hdc", x68k_hdc_image_device, hdc_r, hdc_w) + AM_RANGE(0xe98000, 0xe99fff) AM_READWRITE(x68k_scc_r, x68k_scc_w) + AM_RANGE(0xe9a000, 0xe9bfff) AM_READWRITE(x68k_ppi_r, x68k_ppi_w) + AM_RANGE(0xe9c000, 0xe9dfff) AM_READWRITE(x68k_ioc_r, x68k_ioc_w) + AM_RANGE(0xe9e000, 0xe9e3ff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // FPU (Optional) + AM_RANGE(0xea0000, 0xea1fff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // external SCSI ROM and controller + AM_RANGE(0xeafa00, 0xeafa1f) AM_READWRITE(x68k_exp_r, x68k_exp_w) + AM_RANGE(0xeafa80, 0xeafa89) AM_READWRITE(x68k_areaset_r, x68k_enh_areaset_w) + AM_RANGE(0xeb0000, 0xeb7fff) AM_READWRITE(x68k_spritereg_r, x68k_spritereg_w) + AM_RANGE(0xeb8000, 0xebffff) AM_READWRITE(x68k_spriteram_r, x68k_spriteram_w) + AM_RANGE(0xece000, 0xece3ff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // User I/O + AM_RANGE(0xed0000, 0xed3fff) AM_READWRITE(x68k_sram_r, x68k_sram_w) + AM_RANGE(0xed4000, 0xefffff) AM_NOP + AM_RANGE(0xf00000, 0xfbffff) AM_ROM + AM_RANGE(0xfc0000, 0xfdffff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // internal SCSI ROM + AM_RANGE(0xfe0000, 0xffffff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START(x68kxvi_map, AS_PROGRAM, 16, x68k_state ) + AM_RANGE(0x000000, 0xbffffb) AM_READWRITE(x68k_emptyram_r, x68k_emptyram_w) + AM_RANGE(0xbffffc, 0xbfffff) AM_READWRITE(x68k_rom0_r, x68k_rom0_w) + AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE(x68k_gvram_r, x68k_gvram_w) + AM_RANGE(0xe00000, 0xe7ffff) AM_READWRITE(x68k_tvram_r, x68k_tvram_w) + AM_RANGE(0xe80000, 0xe81fff) AM_READWRITE(x68k_crtc_r, x68k_crtc_w) + AM_RANGE(0xe82000, 0xe821ff) AM_DEVREADWRITE("gfxpalette", palette_device, read, write) AM_SHARE("gfxpalette") + AM_RANGE(0xe82200, 0xe823ff) AM_DEVREADWRITE("pcgpalette", palette_device, read, write) AM_SHARE("pcgpalette") + AM_RANGE(0xe82400, 0xe83fff) AM_READWRITE(x68k_vid_r, x68k_vid_w) + AM_RANGE(0xe84000, 0xe85fff) AM_DEVREADWRITE("hd63450", hd63450_device, read, write) + AM_RANGE(0xe86000, 0xe87fff) AM_READWRITE(x68k_areaset_r, x68k_areaset_w) + AM_RANGE(0xe88000, 0xe89fff) AM_DEVREADWRITE8(MC68901_TAG, mc68901_device, read, write, 0x00ff) + AM_RANGE(0xe8a000, 0xe8bfff) AM_DEVREADWRITE8(RP5C15_TAG, rp5c15_device, read, write, 0x00ff) +// AM_RANGE(0xe8c000, 0xe8dfff) AM_READWRITE(x68k_printer_r, x68k_printer_w) + AM_RANGE(0xe8e000, 0xe8ffff) AM_READWRITE(x68k_sysport_r, x68k_sysport_w) + AM_RANGE(0xe90000, 0xe91fff) AM_DEVREADWRITE8("ym2151", ym2151_device, read, write, 0x00ff) + AM_RANGE(0xe92000, 0xe92001) AM_DEVREADWRITE8("okim6258", okim6258_device, okim6258_status_r, okim6258_ctrl_w, 0x00ff) + AM_RANGE(0xe92002, 0xe92003) AM_DEVREADWRITE8("okim6258", okim6258_device, okim6258_status_r, okim6258_data_w, 0x00ff) + AM_RANGE(0xe94000, 0xe94003) AM_DEVICE8("upd72065", upd72065_device, map, 0x00ff) + AM_RANGE(0xe94004, 0xe94007) AM_READWRITE(x68k_fdc_r, x68k_fdc_w) +// AM_RANGE(0xe96000, 0xe9601f) AM_DEVREADWRITE("x68k_hdc", x68k_hdc_image_device, hdc_r, hdc_w) + AM_RANGE(0xe96020, 0xe9603f) AM_DEVREADWRITE8("mb89352",mb89352_device,mb89352_r,mb89352_w,0x00ff) + AM_RANGE(0xe98000, 0xe99fff) AM_READWRITE(x68k_scc_r, x68k_scc_w) + AM_RANGE(0xe9a000, 0xe9bfff) AM_READWRITE(x68k_ppi_r, x68k_ppi_w) + AM_RANGE(0xe9c000, 0xe9dfff) AM_READWRITE(x68k_ioc_r, x68k_ioc_w) + AM_RANGE(0xe9e000, 0xe9e3ff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // FPU (Optional) + AM_RANGE(0xea0000, 0xea1fff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // external SCSI ROM and controller + AM_RANGE(0xeafa00, 0xeafa1f) AM_READWRITE(x68k_exp_r, x68k_exp_w) + AM_RANGE(0xeafa80, 0xeafa89) AM_READWRITE(x68k_areaset_r, x68k_enh_areaset_w) + AM_RANGE(0xeb0000, 0xeb7fff) AM_READWRITE(x68k_spritereg_r, x68k_spritereg_w) + AM_RANGE(0xeb8000, 0xebffff) AM_READWRITE(x68k_spriteram_r, x68k_spriteram_w) + AM_RANGE(0xece000, 0xece3ff) AM_READWRITE(x68k_exp_r, x68k_exp_w) // User I/O + AM_RANGE(0xed0000, 0xed3fff) AM_READWRITE(x68k_sram_r, x68k_sram_w) + AM_RANGE(0xed4000, 0xefffff) AM_NOP + AM_RANGE(0xf00000, 0xfbffff) AM_ROM + AM_RANGE(0xfc0000, 0xfdffff) AM_ROM // internal SCSI ROM + AM_RANGE(0xfe0000, 0xffffff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START(x68030_map, AS_PROGRAM, 32, x68k_state ) + ADDRESS_MAP_GLOBAL_MASK(0x00ffffff) // Still only has 24-bit address space + AM_RANGE(0x000000, 0xbffffb) AM_READWRITE16(x68k_emptyram_r, x68k_emptyram_w,0xffffffff) + AM_RANGE(0xbffffc, 0xbfffff) AM_READWRITE16(x68k_rom0_r, x68k_rom0_w,0xffffffff) + AM_RANGE(0xc00000, 0xdfffff) AM_READWRITE16(x68k_gvram_r, x68k_gvram_w, 0xffffffff) + AM_RANGE(0xe00000, 0xe7ffff) AM_READWRITE16(x68k_tvram_r, x68k_tvram_w, 0xffffffff) + AM_RANGE(0xe80000, 0xe81fff) AM_READWRITE16(x68k_crtc_r, x68k_crtc_w,0xffffffff) + AM_RANGE(0xe82000, 0xe821ff) AM_DEVREADWRITE("gfxpalette", palette_device, read, write) AM_SHARE("gfxpalette") + AM_RANGE(0xe82200, 0xe823ff) AM_DEVREADWRITE("pcgpalette", palette_device, read, write) AM_SHARE("pcgpalette") + AM_RANGE(0xe82400, 0xe83fff) AM_READWRITE16(x68k_vid_r, x68k_vid_w,0xffffffff) + AM_RANGE(0xe84000, 0xe85fff) AM_DEVREADWRITE16("hd63450", hd63450_device, read, write, 0xffffffff) + AM_RANGE(0xe86000, 0xe87fff) AM_READWRITE16(x68k_areaset_r, x68k_areaset_w,0xffffffff) + AM_RANGE(0xe88000, 0xe89fff) AM_DEVREADWRITE8(MC68901_TAG, mc68901_device, read, write, 0x00ff00ff) + AM_RANGE(0xe8a000, 0xe8bfff) AM_DEVREADWRITE8(RP5C15_TAG, rp5c15_device, read, write, 0x00ff00ff) +// AM_RANGE(0xe8c000, 0xe8dfff) AM_READWRITE(x68k_printer_r, x68k_printer_w) + AM_RANGE(0xe8e000, 0xe8ffff) AM_READWRITE16(x68k_sysport_r, x68k_sysport_w,0xffffffff) + AM_RANGE(0xe90000, 0xe91fff) AM_DEVREADWRITE8("ym2151", ym2151_device, read, write, 0x00ff00ff) + AM_RANGE(0xe92000, 0xe92003) AM_DEVREAD8("okim6258", okim6258_device, okim6258_status_r, 0x00ff00ff) AM_WRITE8(x68030_adpcm_w, 0x00ff00ff) + AM_RANGE(0xe94000, 0xe94003) AM_DEVICE8("upd72065", upd72065_device, map, 0x00ff00ff) + AM_RANGE(0xe94004, 0xe94007) AM_READWRITE16(x68k_fdc_r, x68k_fdc_w,0xffffffff) +// AM_RANGE(0xe96000, 0xe9601f) AM_DEVREADWRITE16("x68k_hdc", x68k_hdc_image_device, hdc_r, hdc_w, 0xffffffff) + AM_RANGE(0xe96020, 0xe9603f) AM_DEVREADWRITE8("mb89352",mb89352_device,mb89352_r,mb89352_w,0x00ff00ff) + AM_RANGE(0xe98000, 0xe99fff) AM_READWRITE16(x68k_scc_r, x68k_scc_w,0xffffffff) + AM_RANGE(0xe9a000, 0xe9bfff) AM_READWRITE16(x68k_ppi_r, x68k_ppi_w,0xffffffff) + AM_RANGE(0xe9c000, 0xe9dfff) AM_READWRITE16(x68k_ioc_r, x68k_ioc_w,0xffffffff) + AM_RANGE(0xe9e000, 0xe9e3ff) AM_READWRITE16(x68k_exp_r, x68k_exp_w,0xffffffff) // FPU (Optional) + AM_RANGE(0xea0000, 0xea1fff) AM_NOP//AM_READWRITE16(x68k_exp_r, x68k_exp_w,0xffffffff) // external SCSI ROM and controller + AM_RANGE(0xeafa00, 0xeafa1f) AM_READWRITE16(x68k_exp_r, x68k_exp_w,0xffffffff) + AM_RANGE(0xeafa80, 0xeafa8b) AM_READWRITE16(x68k_areaset_r, x68k_enh_areaset_w,0xffffffff) + AM_RANGE(0xeb0000, 0xeb7fff) AM_READWRITE16(x68k_spritereg_r, x68k_spritereg_w,0xffffffff) + AM_RANGE(0xeb8000, 0xebffff) AM_READWRITE16(x68k_spriteram_r, x68k_spriteram_w,0xffffffff) + AM_RANGE(0xece000, 0xece3ff) AM_READWRITE16(x68k_exp_r, x68k_exp_w,0xffffffff) // User I/O + AM_RANGE(0xed0000, 0xed3fff) AM_READWRITE16(x68k_sram_r, x68k_sram_w, 0xffffffff) + AM_RANGE(0xed4000, 0xefffff) AM_NOP + AM_RANGE(0xf00000, 0xfbffff) AM_ROM + AM_RANGE(0xfc0000, 0xfdffff) AM_ROM // internal SCSI ROM + AM_RANGE(0xfe0000, 0xffffff) AM_ROM +ADDRESS_MAP_END + +static INPUT_PORTS_START( x68000 ) + PORT_START("ctrltype") + PORT_CONFNAME(0x0f, 0x00, "Joystick Port 1") + PORT_CONFSETTING(0x00, "Standard 2-button MSX/FM-Towns joystick") + PORT_CONFSETTING(0x01, "3-button Megadrive gamepad") + PORT_CONFSETTING(0x02, "6-button Megadrive gamepad") + PORT_CONFSETTING(0x03, "XPD-1LR dual D-pad gamepad") + PORT_CONFNAME(0xf0, 0x00, "Joystick Port 2") + PORT_CONFSETTING(0x00, "Standard 2-button MSX/FM-Towns joystick") + PORT_CONFSETTING(0x10, "3-button Megadrive gamepad") + PORT_CONFSETTING(0x20, "6-button Megadrive gamepad") + PORT_CONFSETTING(0x30, "XPD-1LR dual D-pad gamepad") +// TODO: Sharp Cyber Stick (CZ-8NJ2) support + + PORT_START( "joy1" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) + + PORT_START( "joy2" ) + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) + + PORT_START("options") + PORT_CONFNAME( 0x02, 0x02, "Enable fake bus errors") + PORT_CONFSETTING( 0x00, DEF_STR( Off )) + PORT_CONFSETTING( 0x02, DEF_STR( On )) + PORT_CONFNAME( 0x04, 0x04, "Enable partial updates on each HSync") + PORT_CONFSETTING( 0x00, DEF_STR( Off )) + PORT_CONFSETTING( 0x04, DEF_STR( On )) + + PORT_START("mouse1") // mouse buttons + PORT_BIT( 0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON9) PORT_NAME("Left mouse button") PORT_CODE(MOUSECODE_BUTTON1) + PORT_BIT( 0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON10) PORT_NAME("Right mouse button") PORT_CODE(MOUSECODE_BUTTON2) + + PORT_START("mouse2") // X-axis + PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + + PORT_START("mouse3") // Y-axis + PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + + // 3-button Megadrive gamepad + PORT_START("md3b") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 1 Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 1 Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 1 Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 1 Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 C Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + + PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Start Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) + + PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 2 Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 2 Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 2 Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 2 Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 C Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + + PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Start Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) + + // 6-button Megadrive gamepad + PORT_START("md6b") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 1 Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 1 Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 1 Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 1 Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 C Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + + PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Start Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + + PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 2 Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 2 Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 2 Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 2 Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 C Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + + PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Start Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + + // extra inputs + PORT_START("md6b_extra") + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Z Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Y Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 X Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Mode Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) + + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Z Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Y Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 X Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Mode Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) + + // Dempa/Micomsoft XPD-1LR (dual D-pad gamepad sold with Libble Rabble) + PORT_START("xpd1lr") + PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP ) PORT_NAME("XPD Pad 1 Left/Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN ) PORT_NAME("XPD Pad 1 Left/Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT ) PORT_NAME("XPD Pad 1 Left/Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT ) PORT_NAME("XPD Pad 1 Left/Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("XPD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("XPD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + + PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP ) PORT_NAME("XPD Pad 1 Right/Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN ) PORT_NAME("XPD Pad 1 Right/Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT ) PORT_NAME("XPD Pad 1 Right/Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT ) PORT_NAME("XPD Pad 1 Right/Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) + + PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP ) PORT_NAME("XPD Pad 2 Left/Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN ) PORT_NAME("XPD Pad 2 Left/Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT ) PORT_NAME("XPD Pad 2 Left/Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT ) PORT_NAME("XPD Pad 2 Left/Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("XPD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("XPD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + + PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP ) PORT_NAME("XPD Pad 2 Right/Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN ) PORT_NAME("XPD Pad 2 Right/Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT ) PORT_NAME("XPD Pad 2 Right/Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT ) PORT_NAME("XPD Pad 2 Right/Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) + +INPUT_PORTS_END + +void x68k_state::floppy_load_unload(bool load, floppy_image_device *dev) +{ + dev->mon_w(m_fdc.motor && !load); + if(m_ioc.irqstatus & 0x02) + { + m_current_vector[1] = 0x61; + m_ioc.irqstatus |= 0x40; + m_current_irq_line = 1; + m_maincpu->set_input_line_and_vector(1,ASSERT_LINE,m_current_vector[1]); // Disk insert/eject interrupt + logerror("IOC: Disk image inserted\n"); + } +} + +int x68k_state::floppy_load(floppy_image_device *dev) +{ + floppy_load_unload(true, dev); + return IMAGE_INIT_PASS; +} + +void x68k_state::floppy_unload(floppy_image_device *dev) +{ + floppy_load_unload(false, dev); +} + +TIMER_CALLBACK_MEMBER(x68k_state::x68k_net_irq) +{ + m_current_vector[2] = 0xf9; + m_current_irq_line = 2; + m_maincpu->set_input_line_and_vector(2,ASSERT_LINE,m_current_vector[2]); +} + +WRITE_LINE_MEMBER(x68k_state::x68k_irq2_line) +{ + if(state==ASSERT_LINE) + { + m_net_timer->adjust(attotime::from_usec(16)); + } + else + m_maincpu->set_input_line_and_vector(2,CLEAR_LINE,m_current_vector[2]); + logerror("EXP: IRQ2 set to %i\n",state); + +} + +static SLOT_INTERFACE_START(x68000_exp_cards) + SLOT_INTERFACE("neptunex",X68K_NEPTUNEX) // Neptune-X ethernet adapter (ISA NE2000 bridge) + SLOT_INTERFACE("cz6bs1",X68K_SCSIEXT) // Sharp CZ-6BS1 SCSI-1 controller +SLOT_INTERFACE_END + +MACHINE_RESET_MEMBER(x68k_state,x68000) +{ + /* The last half of the IPLROM is mapped to 0x000000 on reset only + Just copying the inital stack pointer and program counter should + more or less do the same job */ + + int drive; + UINT8* romdata = memregion("user2")->base(); + attotime irq_time; + + memset(m_ram->pointer(),0,m_ram->size()); + memcpy(m_ram->pointer(),romdata,8); + + // initialise CRTC, set registers to defaults for the standard text mode (768x512) + m_crtc.reg[0] = 137; // Horizontal total (in characters) + m_crtc.reg[1] = 14; // Horizontal sync end + m_crtc.reg[2] = 28; // Horizontal start + m_crtc.reg[3] = 124; // Horizontal end + m_crtc.reg[4] = 567; // Vertical total + m_crtc.reg[5] = 5; // Vertical sync end + m_crtc.reg[6] = 40; // Vertical start + m_crtc.reg[7] = 552; // Vertical end + m_crtc.reg[8] = 27; // Horizontal adjust + + m_scanline = machine().first_screen()->vpos();// = m_crtc.reg[6]; // Vertical start + + // start VBlank timer + m_crtc.vblank = 1; + irq_time = m_screen->time_until_pos(m_crtc.reg[6],2); + m_vblank_irq->adjust(irq_time); + + // start HBlank timer + m_scanline_timer->adjust(m_screen->scan_period(), 1); + + /// TODO: get callbacks to trigger these + m_mfpdev->i0_w(1); // alarm + m_mfpdev->i1_w(1); // expon + m_mfpdev->i2_w(0); // pow sw + m_mfpdev->i3_w(1); // fmirq + m_mfpdev->i4_w(1); // v-disp + m_mfpdev->i5_w(1); // unused (always set) + m_mfpdev->i6_w(1); // cirq + m_mfpdev->i7_w(1); // h-sync + + // reset output values + output_set_value("key_led_kana",1); + output_set_value("key_led_romaji",1); + output_set_value("key_led_code",1); + output_set_value("key_led_caps",1); + output_set_value("key_led_insert",1); + output_set_value("key_led_hiragana",1); + output_set_value("key_led_fullsize",1); + for(drive=0;drive<4;drive++) + { + output_set_indexed_value("eject_drv",drive,1); + output_set_indexed_value("ctrl_drv",drive,1); + output_set_indexed_value("access_drv",drive,1); + } + m_fdc.select_drive = 0; + + // reset CPU + m_maincpu->reset(); +} + +MACHINE_START_MEMBER(x68k_state,x68000) +{ + address_space &space = m_maincpu->space(AS_PROGRAM); + /* Install RAM handlers */ + m_spriteram = (UINT16*)(memregion("user1")->base()); + space.install_readwrite_bank(0x000000,m_ram->size()-1,0xffffffff,0,"bank1"); + membank("bank1")->set_base(m_ram->pointer()); + + // start mouse timer + m_mouse_timer->adjust(attotime::zero, 0, attotime::from_msec(1)); // a guess for now + m_mouse.inputtype = 0; + + // start LED timer + m_led_timer->adjust(attotime::zero, 0, attotime::from_msec(400)); + + for(int drive=0;drive<4;drive++) + { + char devname[16]; + sprintf(devname, "%d", drive); + floppy_image_device *floppy = m_upd72065->subdevice<floppy_connector>(devname)->get_device(); + m_fdc.floppy[drive] = floppy; + if(floppy) { + floppy->setup_load_cb(floppy_image_device::load_cb(FUNC(x68k_state::floppy_load), this)); + floppy->setup_unload_cb(floppy_image_device::unload_cb(FUNC(x68k_state::floppy_unload), this)); + } + } + m_fdc.motor = 0; +} + +DRIVER_INIT_MEMBER(x68k_state,x68000) +{ + unsigned char* rom = memregion("maincpu")->base(); + unsigned char* user2 = memregion("user2")->base(); + + machine().device<nvram_device>("nvram")->set_base(&m_nvram[0], m_nvram.size()*sizeof(m_nvram[0])); + +#ifdef USE_PREDEFINED_SRAM + { + unsigned char* ramptr = memregion("user3")->base(); + memcpy(m_sram,ramptr,0x4000); + } +#endif + + // copy last half of BIOS to a user region, to use for inital startup + memcpy(user2,(rom+0xff0000),0x10000); + + m_scanline_timer = timer_alloc(TIMER_X68K_HSYNC); + m_raster_irq = timer_alloc(TIMER_X68K_CRTC_RASTER_IRQ); + m_vblank_irq = timer_alloc(TIMER_X68K_CRTC_VBLANK_IRQ); + m_mouse_timer = timer_alloc(TIMER_X68K_SCC_ACK); + m_led_timer = timer_alloc(TIMER_X68K_LED); + m_net_timer = timer_alloc(TIMER_X68K_NET_IRQ); + m_fdc_tc = timer_alloc(TIMER_X68K_FDC_TC); + m_adpcm_timer = timer_alloc(TIMER_X68K_ADPCM); + m_bus_error_timer = timer_alloc(TIMER_X68K_BUS_ERROR); + + // Initialise timers for 6-button MD controllers + md_6button_init(); + + m_sysport.cputype = 0xff; // 68000, 10MHz + m_is_32bit = false; + + save_item(NAME(m_tvram)); + save_item(NAME(m_gvram)); + save_item(NAME(m_spritereg)); +} + +DRIVER_INIT_MEMBER(x68k_state,x68kxvi) +{ + DRIVER_INIT_CALL( x68000 ); + m_sysport.cputype = 0xfe; // 68000, 16MHz + m_is_32bit = false; +} + +DRIVER_INIT_MEMBER(x68k_state,x68030) +{ + DRIVER_INIT_CALL( x68000 ); + m_sysport.cputype = 0xdc; // 68030, 25MHz + m_is_32bit = true; +} + +FLOPPY_FORMATS_MEMBER( x68k_state::floppy_formats ) + FLOPPY_XDF_FORMAT, + FLOPPY_DIM_FORMAT +FLOPPY_FORMATS_END + +static SLOT_INTERFACE_START( x68k_floppies ) + SLOT_INTERFACE( "525hd", FLOPPY_525_HD ) +SLOT_INTERFACE_END + +static SLOT_INTERFACE_START(keyboard) + SLOT_INTERFACE("x68k", X68K_KEYBOARD) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_START( x68000, x68k_state ) + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", M68000, 10000000) /* 10 MHz */ + MCFG_CPU_PROGRAM_MAP(x68k_map) + MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(x68k_state,x68k_int_ack) + + MCFG_QUANTUM_TIME(attotime::from_hz(60)) + + MCFG_MACHINE_START_OVERRIDE(x68k_state, x68000 ) + MCFG_MACHINE_RESET_OVERRIDE(x68k_state, x68000 ) + + /* device hardware */ + MCFG_DEVICE_ADD(MC68901_TAG, MC68901, 4000000) + MCFG_MC68901_TIMER_CLOCK(4000000) + MCFG_MC68901_RX_CLOCK(0) + MCFG_MC68901_TX_CLOCK(0) + MCFG_MC68901_OUT_IRQ_CB(WRITELINE(x68k_state, mfp_irq_callback)) + MCFG_MC68901_OUT_TBO_CB(DEVWRITELINE(MC68901_TAG, mc68901_device, clock_w)) + MCFG_MC68901_OUT_SO_CB(DEVWRITELINE("keyboard", rs232_port_device, write_txd)) + + MCFG_RS232_PORT_ADD("keyboard", keyboard, "x68k") + MCFG_RS232_RXD_HANDLER(DEVWRITELINE(MC68901_TAG, mc68901_device, write_rx)) + + MCFG_DEVICE_ADD("ppi8255", I8255A, 0) + MCFG_I8255_IN_PORTA_CB(READ8(x68k_state, ppi_port_a_r)) + MCFG_I8255_IN_PORTB_CB(READ8(x68k_state, ppi_port_b_r)) + MCFG_I8255_IN_PORTC_CB(READ8(x68k_state, ppi_port_c_r)) + MCFG_I8255_OUT_PORTC_CB(WRITE8(x68k_state, ppi_port_c_w)) + + MCFG_DEVICE_ADD("hd63450", HD63450, 0) + MCFG_HD63450_CPU("maincpu") // CPU - 68000 + MCFG_HD63450_CLOCKS(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2)) + MCFG_HD63450_BURST_CLOCKS(attotime::from_usec(2), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50)) + MCFG_HD63450_DMA_END_CB(WRITE8(x68k_state, dma_end)) + MCFG_HD63450_DMA_ERROR_CB(WRITE8(x68k_state, dma_error)) + MCFG_HD63450_DMA_READ_0_CB(DEVREAD8("upd72065", upd72065_device, mdma_r)) + MCFG_HD63450_DMA_WRITE_0_CB(DEVWRITE8("upd72065", upd72065_device, mdma_w)) + + MCFG_DEVICE_ADD("scc", SCC8530, 5000000) + + MCFG_DEVICE_ADD(RP5C15_TAG, RP5C15, XTAL_32_768kHz) + MCFG_RP5C15_OUT_ALARM_CB(DEVWRITELINE(MC68901_TAG, mc68901_device, i0_w)) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(55.45) + MCFG_SCREEN_SIZE(1096, 568) // inital setting + MCFG_SCREEN_VISIBLE_AREA(0, 767, 0, 511) + MCFG_SCREEN_UPDATE_DRIVER(x68k_state, screen_update_x68000) + + MCFG_GFXDECODE_ADD("gfxdecode", "pcgpalette", empty) + + MCFG_PALETTE_ADD("gfxpalette", 256) + MCFG_PALETTE_FORMAT_CLASS(2, x68k_state, GGGGGRRRRRBBBBBI) + MCFG_PALETTE_ADD("pcgpalette", 256) + MCFG_PALETTE_FORMAT_CLASS(2, x68k_state, GGGGGRRRRRBBBBBI) + + MCFG_VIDEO_START_OVERRIDE(x68k_state, x68000 ) + + MCFG_DEFAULT_LAYOUT( layout_x68000 ) + + /* sound hardware */ + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + MCFG_YM2151_ADD("ym2151", 4000000) + MCFG_YM2151_IRQ_HANDLER(WRITELINE(x68k_state,x68k_fm_irq)) + MCFG_YM2151_PORT_WRITE_HANDLER(WRITE8(x68k_state,x68k_ct_w)) // CT1, CT2 from YM2151 port 0x1b + MCFG_SOUND_ROUTE(0, "lspeaker", 0.50) + MCFG_SOUND_ROUTE(1, "rspeaker", 0.50) + + MCFG_OKIM6258_ADD("okim6258", 4000000) + MCFG_OKIM6258_DIVIDER(FOSC_DIV_BY_512) + MCFG_OKIM6258_ADPCM_TYPE(TYPE_4BITS) + MCFG_OKIM6258_OUT_BITS(OUTPUT_10BITS) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50) + + MCFG_UPD72065_ADD("upd72065", true, false) + MCFG_UPD765_INTRQ_CALLBACK(WRITELINE(x68k_state, fdc_irq)) + MCFG_UPD765_DRQ_CALLBACK(DEVWRITELINE("hd63450", hd63450_device, drq0_w)) + MCFG_FLOPPY_DRIVE_ADD("upd72065:0", x68k_floppies, "525hd", x68k_state::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("upd72065:1", x68k_floppies, "525hd", x68k_state::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("upd72065:2", x68k_floppies, "525hd", x68k_state::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("upd72065:3", x68k_floppies, "525hd", x68k_state::floppy_formats) + + MCFG_SOFTWARE_LIST_ADD("flop_list","x68k_flop") + + MCFG_DEVICE_ADD("exp", X68K_EXPANSION_SLOT, 0) + MCFG_DEVICE_SLOT_INTERFACE(x68000_exp_cards, NULL, false) + MCFG_X68K_EXPANSION_SLOT_OUT_IRQ2_CB(WRITELINE(x68k_state, x68k_irq2_line)) + MCFG_X68K_EXPANSION_SLOT_OUT_IRQ4_CB(INPUTLINE("maincpu", M68K_IRQ_4)) + MCFG_X68K_EXPANSION_SLOT_OUT_NMI_CB(INPUTLINE("maincpu", INPUT_LINE_NMI)) + + /* internal ram */ + MCFG_RAM_ADD(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("4M") + MCFG_RAM_EXTRA_OPTIONS("1M,2M,3M,5M,6M,7M,8M,9M,10M,11M,12M") + + MCFG_NVRAM_ADD_0FILL("nvram") + + MCFG_X68KHDC_ADD( "x68k_hdc" ) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( x68ksupr, x68000 ) + MCFG_DEVICE_REMOVE("x68k_hdc") + + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(x68kxvi_map) + + MCFG_DEVICE_ADD("scsi", SCSI_PORT, 0) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_0) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE2, "harddisk", SCSIHD, SCSI_ID_1) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE3, "harddisk", SCSIHD, SCSI_ID_2) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE4, "harddisk", SCSIHD, SCSI_ID_3) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE5, "harddisk", SCSIHD, SCSI_ID_4) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE6, "harddisk", SCSIHD, SCSI_ID_5) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE7, "harddisk", SCSIHD, SCSI_ID_6) + + MCFG_DEVICE_ADD("mb89352", MB89352A, 0) + MCFG_LEGACY_SCSI_PORT("scsi") + MCFG_MB89352A_IRQ_CB(WRITELINE(x68k_state, x68k_scsi_irq)) + MCFG_MB89352A_DRQ_CB(WRITELINE(x68k_state, x68k_scsi_drq)) +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( x68kxvi, x68ksupr ) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_CLOCK(16000000) /* 16 MHz */ +MACHINE_CONFIG_END + +static MACHINE_CONFIG_DERIVED( x68030, x68ksupr ) + MCFG_CPU_REPLACE("maincpu", M68030, 25000000) /* 25 MHz 68EC030 */ + MCFG_CPU_PROGRAM_MAP(x68030_map) + MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(x68k_state,x68k_int_ack) +MACHINE_CONFIG_END + +ROM_START( x68000 ) + ROM_REGION16_BE(0x1000000, "maincpu", 0) // 16MB address space + ROM_DEFAULT_BIOS("ipl10") + ROM_LOAD( "cgrom.dat", 0xf00000, 0xc0000, CRC(9f3195f1) SHA1(8d72c5b4d63bb14c5dbdac495244d659aa1498b6) ) + ROM_SYSTEM_BIOS(0, "ipl10", "IPL-ROM V1.0 (87/05/07)") + ROMX_LOAD( "iplrom.dat", 0xfe0000, 0x20000, CRC(72bdf532) SHA1(0ed038ed2133b9f78c6e37256807424e0d927560), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "ipl11", "IPL-ROM V1.1 (91/01/11)") + ROMX_LOAD( "iplromxv.dat", 0xfe0000, 0x020000, CRC(00eeb408) SHA1(e33cdcdb69cd257b0b211ef46e7a8b144637db57), ROM_BIOS(2) ) + ROM_SYSTEM_BIOS(2, "ipl12", "IPL-ROM V1.2 (91/10/24)") + ROMX_LOAD( "iplromco.dat", 0xfe0000, 0x020000, CRC(6c7ef608) SHA1(77511fc58798404701f66b6bbc9cbde06596eba7), ROM_BIOS(3) ) + ROM_SYSTEM_BIOS(3, "ipl13", "IPL-ROM V1.3 (92/11/27)") + ROMX_LOAD( "iplrom30.dat", 0xfe0000, 0x020000, CRC(e8f8fdad) SHA1(239e9124568c862c31d9ec0605e32373ea74b86a), ROM_BIOS(4) ) + ROM_REGION(0x8000, "user1",0) // For Background/Sprite decoding + ROM_FILL(0x0000,0x8000,0x00) + ROM_REGION(0x20000, "user2", 0) + ROM_FILL(0x000,0x20000,0x00) +ROM_END + +ROM_START( x68ksupr ) + ROM_REGION16_BE(0x1000000, "maincpu", 0) // 16MB address space + ROM_DEFAULT_BIOS("ipl11") + ROM_LOAD( "cgrom.dat", 0xf00000, 0xc0000, CRC(9f3195f1) SHA1(8d72c5b4d63bb14c5dbdac495244d659aa1498b6) ) + ROM_SYSTEM_BIOS(0, "ipl10", "IPL-ROM V1.0 (87/05/07)") + ROMX_LOAD( "iplrom.dat", 0xfe0000, 0x20000, CRC(72bdf532) SHA1(0ed038ed2133b9f78c6e37256807424e0d927560), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "ipl11", "IPL-ROM V1.1 (91/01/11)") + ROMX_LOAD( "iplromxv.dat", 0xfe0000, 0x020000, CRC(00eeb408) SHA1(e33cdcdb69cd257b0b211ef46e7a8b144637db57), ROM_BIOS(2) ) + ROM_SYSTEM_BIOS(2, "ipl12", "IPL-ROM V1.2 (91/10/24)") + ROMX_LOAD( "iplromco.dat", 0xfe0000, 0x020000, CRC(6c7ef608) SHA1(77511fc58798404701f66b6bbc9cbde06596eba7), ROM_BIOS(3) ) + ROM_SYSTEM_BIOS(3, "ipl13", "IPL-ROM V1.3 (92/11/27)") + ROMX_LOAD( "iplrom30.dat", 0xfe0000, 0x020000, CRC(e8f8fdad) SHA1(239e9124568c862c31d9ec0605e32373ea74b86a), ROM_BIOS(4) ) + ROM_LOAD("scsiinsu.bin",0xfc0000, 0x002000, CRC(f65a3e24) SHA1(15a17798839a3f7f361119205aebc301c2df5967) ) // Dumped from an X68000 Super HD +// ROM_LOAD("scsiexrom.dat",0xea0000, 0x002000, NO_DUMP ) + ROM_REGION(0x8000, "user1",0) // For Background/Sprite decoding + ROM_FILL(0x0000,0x8000,0x00) + ROM_REGION(0x20000, "user2", 0) + ROM_FILL(0x000,0x20000,0x00) +ROM_END + +ROM_START( x68kxvi ) + ROM_REGION16_BE(0x1000000, "maincpu", 0) // 16MB address space + ROM_DEFAULT_BIOS("ipl11") + ROM_LOAD( "cgrom.dat", 0xf00000, 0xc0000, CRC(9f3195f1) SHA1(8d72c5b4d63bb14c5dbdac495244d659aa1498b6) ) + ROM_SYSTEM_BIOS(0, "ipl10", "IPL-ROM V1.0 (87/05/07)") + ROMX_LOAD( "iplrom.dat", 0xfe0000, 0x20000, CRC(72bdf532) SHA1(0ed038ed2133b9f78c6e37256807424e0d927560), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "ipl11", "IPL-ROM V1.1 (91/01/11)") + ROMX_LOAD( "iplromxv.dat", 0xfe0000, 0x020000, CRC(00eeb408) SHA1(e33cdcdb69cd257b0b211ef46e7a8b144637db57), ROM_BIOS(2) ) + ROM_SYSTEM_BIOS(2, "ipl12", "IPL-ROM V1.2 (91/10/24)") + ROMX_LOAD( "iplromco.dat", 0xfe0000, 0x020000, CRC(6c7ef608) SHA1(77511fc58798404701f66b6bbc9cbde06596eba7), ROM_BIOS(3) ) + ROM_SYSTEM_BIOS(3, "ipl13", "IPL-ROM V1.3 (92/11/27)") + ROMX_LOAD( "iplrom30.dat", 0xfe0000, 0x020000, CRC(e8f8fdad) SHA1(239e9124568c862c31d9ec0605e32373ea74b86a), ROM_BIOS(4) ) + ROM_LOAD("scsiinco.bin",0xfc0000, 0x002000, CRC(2485e14d) SHA1(101a9bba8ea4bb90965c144bcfd7182f889ab958) ) // Dumped from an X68000 XVI Compact +// ROM_LOAD("scsiexrom.dat",0xea0000, 0x002000, NO_DUMP ) + ROM_REGION(0x8000, "user1",0) // For Background/Sprite decoding + ROM_FILL(0x0000,0x8000,0x00) + ROM_REGION(0x20000, "user2", 0) + ROM_FILL(0x000,0x20000,0x00) +ROM_END + +ROM_START( x68030 ) + ROM_REGION16_BE(0x1000000, "maincpu", 0) // 16MB address space + ROM_DEFAULT_BIOS("ipl13") + ROM_LOAD( "cgrom.dat", 0xf00000, 0xc0000, CRC(9f3195f1) SHA1(8d72c5b4d63bb14c5dbdac495244d659aa1498b6) ) + ROM_SYSTEM_BIOS(0, "ipl10", "IPL-ROM V1.0 (87/05/07)") + ROMX_LOAD( "iplrom.dat", 0xfe0000, 0x20000, CRC(72bdf532) SHA1(0ed038ed2133b9f78c6e37256807424e0d927560), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS(1, "ipl11", "IPL-ROM V1.1 (91/01/11)") + ROMX_LOAD( "iplromxv.dat", 0xfe0000, 0x020000, CRC(00eeb408) SHA1(e33cdcdb69cd257b0b211ef46e7a8b144637db57), ROM_BIOS(2) ) + ROM_SYSTEM_BIOS(2, "ipl12", "IPL-ROM V1.2 (91/10/24)") + ROMX_LOAD( "iplromco.dat", 0xfe0000, 0x020000, CRC(6c7ef608) SHA1(77511fc58798404701f66b6bbc9cbde06596eba7), ROM_BIOS(3) ) + ROM_SYSTEM_BIOS(3, "ipl13", "IPL-ROM V1.3 (92/11/27)") + ROMX_LOAD( "iplrom30.dat", 0xfe0000, 0x020000, CRC(e8f8fdad) SHA1(239e9124568c862c31d9ec0605e32373ea74b86a), ROM_BIOS(4) ) + ROM_LOAD("scsiinrom.dat",0xfc0000, 0x002000, CRC(1c6c889e) SHA1(3f063d4231cdf53da6adc4db96533725e260076a) BAD_DUMP ) +// ROM_LOAD("scsiexrom.dat",0xea0000, 0x002000, NO_DUMP ) + ROM_REGION(0x8000, "user1",0) // For Background/Sprite decoding + ROM_FILL(0x0000,0x8000,0x00) + ROM_REGION(0x20000, "user2", 0) + ROM_FILL(0x000,0x20000,0x00) +ROM_END + + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ +COMP( 1987, x68000, 0, 0, x68000, x68000, x68k_state, x68000, "Sharp", "X68000", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1990, x68ksupr,x68000, 0, x68ksupr,x68000, x68k_state,x68000, "Sharp", "X68000 Super", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +COMP( 1991, x68kxvi,x68000, 0, x68kxvi,x68000, x68k_state, x68kxvi,"Sharp", "X68000 XVI", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) +COMP( 1993, x68030, x68000, 0, x68030, x68000, x68k_state, x68030, "Sharp", "X68030", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) |