summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/genesis.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/genesis.c')
-rw-r--r--src/mame/drivers/genesis.c814
1 files changed, 814 insertions, 0 deletions
diff --git a/src/mame/drivers/genesis.c b/src/mame/drivers/genesis.c
new file mode 100644
index 00000000000..ed7b462d77d
--- /dev/null
+++ b/src/mame/drivers/genesis.c
@@ -0,0 +1,814 @@
+/* Some Generic Sega Genesis stuff used by Megatech / Megaplay etc. */
+
+/*
+
+Genesis hardware games are in
+
+megatech.c
+megaplay.c
+gene_sm.c
+segac2.c
+
+*/
+
+#include "driver.h"
+#include "genesis.h"
+
+#define MASTER_CLOCK 53693100
+
+
+/******************** Sega Genesis ******************************/
+
+/* Genesis based */
+static UINT32 z80_68000_latch = 0;
+static UINT32 z80_latch_bitcount = 0;
+
+/* interrupt states */
+static UINT8 irq2_int; /* INT2 */
+static UINT8 scanline_int; /* INT4 - programmable */
+static UINT8 vblank_int; /* INT6 - on every VBLANK */
+
+static emu_timer * scan_timer;
+
+
+static int z80running;
+UINT16 *genesis_68k_ram;
+UINT8 *genesis_z80_ram;
+
+
+
+/******************************************************************************
+ Interrupt handling
+*******************************************************************************
+
+ The Genesis uses 2 Different Interrupts, IRQ4 and IRQ6.
+ The C2 system uses IRQ2 as well.
+
+ IRQ6 = Vblank, this happens after the last visible line of the display has
+ been drawn (after line 224)
+
+ IRQ4 = H-Int, this happens based upon the value in H-Int Counter. If the
+ Horizontal Interrupt is enabled and the Counter Value = 0 there
+ will be a Level 4 Interrupt Triggered
+
+ IRQ2 = sound int, generated by the YM3438
+
+ --------
+
+ More H-Counter Information:
+
+ Providing Horizontal Interrupts are active the H-Counter will be loaded
+ with the value stored in register #10 (0x0A) at the following times:
+ (1) At the top of the display, before drawing the first line
+ (2) When the counter has expired
+ (3) During the VBlank Period (lines 224-261)
+ The Counter is decreased by 1 after every line.
+
+******************************************************************************/
+
+/* call this whenever the interrupt state has changed */
+static void update_interrupts(void)
+{
+ int level = 0;
+
+ /* determine which interrupt is active */
+ if (irq2_int) level = 2;
+ if (scanline_int) level = 4;
+ if (vblank_int) level = 6;
+
+ /* either set or clear the appropriate lines */
+ if (level)
+ cpunum_set_input_line(0, level, ASSERT_LINE);
+ else
+ cpunum_set_input_line(0, 7, CLEAR_LINE);
+}
+
+
+/* timer callback to turn off the IRQ4 signal after a short while */
+static TIMER_CALLBACK( vdp_int4_off )
+{
+ scanline_int = 0;
+ update_interrupts();
+}
+
+
+/* timer callback to handle reloading the H counter and generate IRQ4 */
+static TIMER_CALLBACK( vdp_reload_counter )
+{
+ int scanline = param;
+
+ /* generate an int if they're enabled */
+ if (genesis_vdp_regs[0] & 0x10)/* && !(misc_io_data[7] & 0x10))*/
+ if (scanline != 0 || genesis_vdp_regs[10] == 0)
+ {
+ scanline_int = 1;
+ update_interrupts();
+ timer_set(video_screen_get_time_until_pos(0, scanline + 1, 0), 0, vdp_int4_off);
+ }
+
+ /* advance to the next scanline */
+ /* behavior 2: 0 count means interrupt after one scanline */
+ /* (this behavior matches the Sega C2 emulator) */
+ scanline += genesis_vdp_regs[10] + 1;
+ if (scanline >= 224)
+ scanline = 0;
+
+ /* set a timer */
+ timer_adjust(scan_timer, video_screen_get_time_until_pos(0, scanline, 320), scanline, attotime_zero);
+}
+
+
+/* timer callback to turn off the IRQ6 signal after a short while */
+static TIMER_CALLBACK( vdp_int6_off )
+{
+ vblank_int = 0;
+ update_interrupts();
+}
+
+
+/* interrupt callback to generate the VBLANK interrupt */
+INTERRUPT_GEN( genesis_vblank_interrupt )
+{
+ /* generate the interrupt */
+ vblank_int = 1;
+ update_interrupts();
+
+ /* set a timer to turn it off */
+ timer_set(video_screen_get_time_until_pos(0, video_screen_get_vpos(0), 22), 0, vdp_int6_off);
+}
+
+
+/* interrupt callback to generate the YM3438 interrupt */
+void genesis_irq2_interrupt(int state)
+{
+ irq2_int = state;
+ update_interrupts();
+}
+
+
+MACHINE_START( genesis )
+{
+ state_save_register_global(irq2_int);
+ state_save_register_global(scanline_int);
+ state_save_register_global(vblank_int);
+}
+
+
+MACHINE_RESET( genesis )
+{
+ /* C2 doesn't have a Z80, so we can't just assume */
+ if (machine->drv->cpu[1].type == CPU_Z80)
+ {
+ /* the following ensures that the Z80 begins without running away from 0 */
+ /* 0x76 is just a forced 'halt' as soon as the CPU is initially run */
+ genesis_z80_ram[0] = 0x76;
+ genesis_z80_ram[0x38] = 0x76;
+
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+
+ z80running = 0;
+ }
+
+ logerror("Machine init\n");
+
+ /* set the first scanline 0 timer to go off */
+ scan_timer = timer_alloc(vdp_reload_counter);
+ timer_adjust(scan_timer, video_screen_get_time_until_pos(0, 0, 320), 0, attotime_zero);
+}
+
+
+/* from MESS */
+READ16_HANDLER(genesis_ctrl_r)
+{
+/* int returnval; */
+
+/* logerror("genesis_ctrl_r %x\n", offset); */
+ switch (offset)
+ {
+ case 0: /* DRAM mode is write only */
+ return 0xffff;
+ break;
+ case 0x80: /* return Z80 CPU Function Stop Accessible or not */
+ /* logerror("Returning z80 state\n"); */
+ return (z80running ? 0x0100 : 0x0);
+ break;
+ case 0x100: /* Z80 CPU Reset - write only */
+ return 0xffff;
+ break;
+ }
+ return 0x00;
+
+}
+
+/* from MESS */
+WRITE16_HANDLER(genesis_ctrl_w)
+{
+ data &= ~mem_mask;
+
+/* logerror("genesis_ctrl_w %x, %x\n", offset, data); */
+
+ switch (offset)
+ {
+ case 0: /* set DRAM mode... we have to ignore this for production cartridges */
+ return;
+ break;
+ case 0x80: /* Z80 BusReq */
+ if (data == 0x100)
+ {
+ z80running = 0;
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE); /* halt Z80 */
+ /* logerror("z80 stopped by 68k BusReq\n"); */
+ }
+ else
+ {
+ z80running = 1;
+// memory_set_bankptr(1, &genesis_z80_ram[0]);
+
+ cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
+ /* logerror("z80 started, BusReq ends\n"); */
+ }
+ return;
+ break;
+ case 0x100: /* Z80 CPU Reset */
+ if (data == 0x00)
+ {
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ cpunum_set_input_line(1, INPUT_LINE_RESET, PULSE_LINE);
+
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ /* logerror("z80 reset, ram is %p\n", &genesis_z80_ram[0]); */
+ z80running = 0;
+ return;
+ }
+ else
+ {
+ /* logerror("z80 out of reset\n"); */
+ }
+ return;
+
+ break;
+ }
+}
+
+READ16_HANDLER ( genesis_68k_to_z80_r )
+{
+ offset *= 2;
+ offset &= 0x7fff;
+
+ /* Shared Ram */
+ if ((offset >= 0x0000) && (offset <= 0x3fff))
+ {
+ offset &=0x1fff;
+// logerror("soundram_r returning %x\n",(gen_z80_shared[offset] << 8) + gen_z80_shared[offset+1]);
+ return (genesis_z80_ram[offset] << 8) + genesis_z80_ram[offset+1];
+ }
+
+
+ /* YM2610 */
+ if ((offset >= 0x4000) && (offset <= 0x5fff))
+ {
+ switch (offset & 3)
+ {
+ case 0:
+ if (ACCESSING_MSB) return YM3438_status_port_0_A_r(0) << 8;
+ else return YM3438_read_port_0_r(0);
+ break;
+ case 2:
+ if (ACCESSING_MSB) return YM3438_status_port_0_B_r(0) << 8;
+ else return 0;
+ break;
+ }
+ }
+
+ /* Bank Register */
+ if ((offset >= 0x6000) && (offset <= 0x60ff))
+ {
+
+ }
+
+ /* Unused / Illegal */
+ if ((offset >= 0x6100) && (offset <= 0x7eff))
+ {
+ /* nothing */
+ }
+
+ /* VDP */
+ if ((offset >= 0x7f00) && (offset <= 0x7fff))
+ {
+
+ }
+
+ return 0x0000;
+}
+
+
+READ16_HANDLER ( megaplay_68k_to_z80_r )
+{
+ offset *= 2;
+ offset &= 0x7fff;
+
+ /* Shared Ram */
+ if ((offset >= 0x0000) && (offset <= 0x1fff))
+ {
+ offset &=0x1fff;
+// logerror("soundram_r returning %x\n",(gen_z80_shared[offset] << 8) + gen_z80_shared[offset+1]);
+ return (genesis_z80_ram[offset] << 8) + genesis_z80_ram[offset+1];
+ }
+
+ if ((offset >= 0x2000) && (offset <= 0x3fff))
+ {
+ offset &=0x1fff;
+// if(offset == 0)
+// return (readinputport(8) << 8) ^ 0xff00;
+ return (ic36_ram[offset] << 8) + ic36_ram[offset+1];
+ }
+
+
+ /* YM2610 */
+ if ((offset >= 0x4000) && (offset <= 0x5fff))
+ {
+ switch (offset & 3)
+ {
+ case 0:
+ if (ACCESSING_MSB) return YM3438_status_port_0_A_r(0) << 8;
+ else return YM3438_read_port_0_r(0);
+ break;
+ case 2:
+ if (ACCESSING_MSB) return YM3438_status_port_0_B_r(0) << 8;
+ else return 0;
+ break;
+ }
+ }
+
+ /* Bank Register */
+ if ((offset >= 0x6000) && (offset <= 0x60ff))
+ {
+
+ }
+
+ /* Unused / Illegal */
+ if ((offset >= 0x6100) && (offset <= 0x7eff))
+ {
+ /* nothing */
+ }
+
+ /* VDP */
+ if ((offset >= 0x7f00) && (offset <= 0x7fff))
+ {
+
+ }
+
+ return 0x0000;
+}
+
+WRITE16_HANDLER ( genesis_68k_to_z80_w )
+{
+ offset *= 2;
+ offset &= 0x7fff;
+
+ /* Shared Ram */
+ if ((offset >= 0x0000) && (offset <= 0x3fff))
+ {
+ offset &=0x1fff;
+
+ if (ACCESSING_LSB) genesis_z80_ram[offset+1] = data & 0xff;
+ if (ACCESSING_MSB) genesis_z80_ram[offset] = (data >> 8) & 0xff;
+ }
+
+
+ /* YM2610 */
+ if ((offset >= 0x4000) && (offset <= 0x5fff))
+ {
+ switch (offset & 3)
+ {
+ case 0:
+ if (ACCESSING_MSB) YM3438_control_port_0_A_w (0, (data >> 8) & 0xff);
+ else YM3438_data_port_0_A_w (0, (data >> 0) & 0xff);
+ break;
+ case 2:
+ if (ACCESSING_MSB) YM3438_control_port_0_B_w (0, (data >> 8) & 0xff);
+ else YM3438_data_port_0_B_w (0, (data >> 0) & 0xff);
+ break;
+ }
+ }
+
+ /* Bank Register */
+ if ((offset >= 0x6000) && (offset <= 0x60ff))
+ {
+
+ }
+
+ /* Unused / Illegal */
+ if ((offset >= 0x6100) && (offset <= 0x7eff))
+ {
+ /* nothing */
+ }
+
+ /* VDP */
+ if ((offset >= 0x7f00) && (offset <= 0x7fff))
+ {
+ offset &= 0x1f;
+
+ if ( (offset >= 0x10) && (offset <=0x17) )
+ {
+ if (ACCESSING_LSB) SN76496_0_w(0, data & 0xff);
+ if (ACCESSING_MSB) SN76496_0_w(0, (data >>8) & 0xff);
+ }
+
+ }
+}
+
+/* Gen I/O */
+
+/*
+cgfm info
+
+$A10001 Version
+$A10003 Port A data
+$A10005 Port B data
+$A10007 Port C data
+$A10009 Port A control
+$A1000B Port B control
+$A1000D Port C control
+$A1000F Port A TxData
+$A10011 Port A RxData
+$A10013 Port A serial control
+$A10015 Port B TxData
+$A10017 Port B RxData
+$A10019 Port B serial control
+$A1001B Port C TxData
+$A1001D Port C RxData
+$A1001F Port C serial control
+
+*/
+
+UINT16 *genesis_io_ram;
+
+READ16_HANDLER ( genesis_io_r )
+{
+ /* 8-bit only, data is mirrored in both halves */
+
+ UINT8 return_value = 0;
+
+ switch (offset)
+ {
+ case 0:
+ /* Charles MacDonald ( http://cgfm2.emuviews.com/ )
+ D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan)
+ D6 : Video type is 1= PAL, 0= NTSC
+ D5 : Sega CD unit is 1= not present, 0= connected.
+ D4 : Unused (always returns zero)
+ D3 : Bit 3 of version number
+ D2 : Bit 2 of version number
+ D1 : Bit 1 of version number
+ D0 : Bit 0 of version number
+ */
+ return_value = 0x80; /* ? megatech is usa? */
+ break;
+
+ case 1: /* port A data (joypad 1) */
+
+ if (genesis_io_ram[offset] & 0x40)
+ {
+ int iport = readinputport(9);
+ return_value = iport & 0x3f;
+ }
+ else
+ {
+ int iport1 = readinputport(12);
+ int iport2 = readinputport(7) >> 1;
+ return_value = (iport1 & 0x10) + (iport2 & 0x20);
+ if(iport1 & 0x10 || iport2 & 0x20)
+ return_value+=1;
+ }
+
+ return_value = (genesis_io_ram[offset] & 0x80) | return_value;
+// logerror ("reading joypad 1 , type %02x %02x\n",genesis_io_ram[offset] & 0x80, return_value &0x7f);
+ if(bios_ctrl_inputs & 0x04) return_value = 0xff;
+ break;
+
+ case 2: /* port B data (joypad 2) */
+
+ if (genesis_io_ram[offset] & 0x40)
+ {
+ int iport1 = (readinputport(9) & 0xc0) >> 6;
+ int iport2 = (readinputport(8) & 0x0f) << 2;
+ return_value = (iport1 + iport2) & 0x3f;
+ }
+ else
+ {
+ int iport1 = readinputport(12) << 2;
+ int iport2 = readinputport(7) >> 2;
+ return_value = (iport1 & 0x10) + (iport2 & 0x20);
+ if(iport1 & 0x10 || iport2 & 0x20)
+ return_value+=1;
+ }
+ return_value = (genesis_io_ram[offset] & 0x80) | return_value;
+// logerror ("reading joypad 2 , type %02x %02x\n",genesis_io_ram[offset] & 0x80, return_value &0x7f);
+ if(bios_ctrl_inputs & 0x04) return_value = 0xff;
+ break;
+
+ default:
+ return_value = 0xe0;
+
+ }
+ return return_value | return_value << 8;
+}
+
+READ16_HANDLER ( megaplay_genesis_io_r )
+{
+ /* 8-bit only, data is mirrored in both halves */
+
+ UINT8 return_value = 0;
+
+ switch (offset)
+ {
+ case 0:
+ /* Charles MacDonald ( http://cgfm2.emuviews.com/ )
+ D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan)
+ D6 : Video type is 1= PAL, 0= NTSC
+ D5 : Sega CD unit is 1= not present, 0= connected.
+ D4 : Unused (always returns zero)
+ D3 : Bit 3 of version number
+ D2 : Bit 2 of version number
+ D1 : Bit 1 of version number
+ D0 : Bit 0 of version number
+ */
+ return_value = 0x80; /* ? megatech is usa? */
+ break;
+
+ case 1: /* port A data (joypad 1) */
+
+ if (genesis_io_ram[offset] & 0x40)
+ return_value = readinputport(1) & (genesis_io_ram[4]^0xff);
+ else
+ {
+ return_value = readinputport(2) & (genesis_io_ram[4]^0xff);
+ return_value |= readinputport(1) & 0x03;
+ }
+ return_value = (genesis_io_ram[offset] & 0x80) | return_value;
+// logerror ("reading joypad 1 , type %02x %02x\n",genesis_io_ram[offset] & 0xb0, return_value &0x7f);
+ break;
+
+ case 2: /* port B data (joypad 2) */
+
+ if (genesis_io_ram[offset] & 0x40)
+ return_value = readinputport(3) & (genesis_io_ram[5]^0xff);
+ else
+ {
+ return_value = readinputport(4) & (genesis_io_ram[5]^0xff);
+ return_value |= readinputport(3) & 0x03;
+ }
+ return_value = (genesis_io_ram[offset] & 0x80) | return_value;
+// logerror ("reading joypad 2 , type %02x %02x\n",genesis_io_ram[offset] & 0xb0, return_value &0x7f);
+ break;
+
+// case 3: /* port C data */
+// return_value = bios_6402 << 3;
+// break;
+
+ default:
+ return_value = genesis_io_ram[offset];
+
+ }
+ return return_value | return_value << 8;
+}
+
+WRITE16_HANDLER ( genesis_io_w )
+{
+// logerror ("write io offset :%02x data %04x PC: 0x%06x\n",offset,data,activecpu_get_previouspc());
+
+ switch (offset)
+ {
+ case 0x00:
+ /*??*/
+ break;
+
+ case 0x01:/* port A data */
+ genesis_io_ram[offset] = (data & (genesis_io_ram[0x04])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x04]));
+ break;
+
+ case 0x02: /* port B data */
+ genesis_io_ram[offset] = (data & (genesis_io_ram[0x05])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x05]));
+ break;
+
+ case 0x03: /* port C data */
+ genesis_io_ram[offset] = (data & (genesis_io_ram[0x06])) | (genesis_io_ram[offset] & ~(genesis_io_ram[0x06]));
+ bios_6204 = data & 0x07;
+ break;
+
+ case 0x04: /* port A control */
+ genesis_io_ram[offset] = data;
+ break;
+
+ case 0x05: /* port B control */
+ genesis_io_ram[offset] = data;
+ break;
+
+ case 0x06: /* port C control */
+ genesis_io_ram[offset] = data;
+ break;
+
+ case 0x07: /* port A TxData */
+ genesis_io_ram[offset] = data;
+ break;
+
+ default:
+ genesis_io_ram[offset] = data;
+ }
+
+}
+
+#if 0
+static ADDRESS_MAP_START( genesis_readmem, ADDRESS_SPACE_PROGRAM, 16 )
+ AM_RANGE(0x000000, 0x3fffff) AM_READ(MRA16_ROM) /* Cartridge Program Rom */
+ AM_RANGE(0xa10000, 0xa1001f) AM_READ(genesis_io_r) /* Genesis Input */
+ AM_RANGE(0xa00000, 0xa0ffff) AM_READ(genesis_68k_to_z80_r)
+ AM_RANGE(0xc00000, 0xc0001f) AM_READ(genesis_vdp_r) /* VDP Access */
+ AM_RANGE(0xfe0000, 0xfeffff) AM_READ(MRA16_BANK3) /* Main Ram */
+ AM_RANGE(0xff0000, 0xffffff) AM_READ(MRA16_RAM) /* Main Ram */
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( genesis_writemem, ADDRESS_SPACE_PROGRAM, 16 )
+ AM_RANGE(0x000000, 0x3fffff) AM_WRITE(MWA16_ROM) /* Cartridge Program Rom */
+ AM_RANGE(0xa10000, 0xa1001f) AM_WRITE(genesis_io_w) AM_BASE(&genesis_io_ram) /* Genesis Input */
+ AM_RANGE(0xa11000, 0xa11203) AM_WRITE(genesis_ctrl_w)
+ AM_RANGE(0xa00000, 0xa0ffff) AM_WRITE(genesis_68k_to_z80_w)
+ AM_RANGE(0xc00000, 0xc0001f) AM_WRITE(genesis_vdp_w) /* VDP Access */
+ AM_RANGE(0xfe0000, 0xfeffff) AM_WRITE(MWA16_BANK3) /* Main Ram */
+ AM_RANGE(0xff0000, 0xffffff) AM_WRITE(MWA16_RAM) AM_BASE(&genesis_68k_ram)/* Main Ram */
+ADDRESS_MAP_END
+#endif
+
+/* Z80 Sound Hardware - based on MESS code, to be improved, it can do some strange things */
+
+#ifdef LSB_FIRST
+ #define BYTE_XOR(a) ((a) ^ 1)
+#else
+ #define BYTE_XOR(a) (a)
+#endif
+
+
+
+static WRITE8_HANDLER ( genesis_bank_select_w ) /* note value will be meaningless unless all bits are correctly set in */
+{
+ if (offset !=0 ) return;
+// if (!z80running) logerror("undead Z80 latch write!\n");
+ if (z80_latch_bitcount == 0) z80_68000_latch = 0;
+
+ z80_68000_latch = z80_68000_latch | ((( ((UINT8)data) & 0x01) << (15+z80_latch_bitcount)));
+ logerror("value %x written to latch\n", data);
+ z80_latch_bitcount++;
+ if (z80_latch_bitcount == 9)
+ {
+ z80_latch_bitcount = 0;
+ logerror("latch set, value %x\n", z80_68000_latch);
+ }
+}
+
+READ8_HANDLER ( genesis_z80_r )
+{
+ offset += 0x4000;
+
+ /* YM2610 */
+ if ((offset >= 0x4000) && (offset <= 0x5fff))
+ {
+ switch (offset & 3)
+ {
+ case 0: return YM3438_status_port_0_A_r(0);
+ case 1: return YM3438_read_port_0_r(0);
+ case 2: return YM3438_status_port_0_B_r(0);
+ case 3: return 0;
+ }
+ }
+
+ /* Bank Register */
+ if ((offset >= 0x6000) && (offset <= 0x60ff))
+ {
+
+ }
+
+ /* Unused / Illegal */
+ if ((offset >= 0x6100) && (offset <= 0x7eff))
+ {
+ /* nothing */
+ }
+
+ /* VDP */
+ if ((offset >= 0x7f00) && (offset <= 0x7fff))
+ {
+
+ }
+
+ return 0x00;
+}
+
+WRITE8_HANDLER ( genesis_z80_w )
+{
+ offset += 0x4000;
+
+ /* YM2610 */
+ if ((offset >= 0x4000) && (offset <= 0x5fff))
+ {
+ switch (offset & 3)
+ {
+ case 0: YM3438_control_port_0_A_w (0, data);
+ break;
+ case 1: YM3438_data_port_0_A_w (0, data);
+ break;
+ case 2: YM3438_control_port_0_B_w (0, data);
+ break;
+ case 3: YM3438_data_port_0_B_w (0, data);
+ break;
+ }
+ }
+
+ /* Bank Register */
+ if ((offset >= 0x6000) && (offset <= 0x60ff))
+ {
+ genesis_bank_select_w(offset & 0xff, data);
+ }
+
+ /* Unused / Illegal */
+ if ((offset >= 0x6100) && (offset <= 0x7eff))
+ {
+ /* nothing */
+ }
+
+ /* VDP */
+ if ((offset >= 0x7f00) && (offset <= 0x7fff))
+ {
+
+ }
+}
+
+READ8_HANDLER ( genesis_z80_bank_r )
+{
+ int address = (z80_68000_latch) + (offset & 0x7fff);
+
+ if (!z80running) logerror("undead Z80->68000 read!\n");
+
+ if (z80_latch_bitcount != 0) logerror("reading whilst latch being set!\n");
+
+ logerror("z80 read from address %x\n", address);
+
+ /* Read the data out of the 68k ROM */
+ if (address < 0x400000) return memory_region(REGION_CPU1)[BYTE_XOR(address)];
+ /* else read the data out of the 68k RAM */
+// else if (address > 0xff0000) return genesis_68k_ram[BYTE_XOR(offset)];
+
+ return -1;
+}
+
+
+#if 0
+static ADDRESS_MAP_START( genesis_z80_readmem, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x1fff) AM_READ(MRA8_BANK1)
+ AM_RANGE(0x2000, 0x3fff) AM_READ(MRA8_BANK2) /* mirror */
+ AM_RANGE(0x4000, 0x7fff) AM_READ(genesis_z80_r)
+ AM_RANGE(0x8000, 0xffff) AM_READ(genesis_z80_bank_r)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( genesis_z80_writemem, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x1fff) AM_WRITE(MWA8_BANK1) AM_BASE(&genesis_z80_ram)
+ AM_RANGE(0x2000, 0x3fff) AM_WRITE(MWA8_BANK2) /* mirror */
+ AM_RANGE(0x4000, 0x7fff) AM_WRITE(genesis_z80_w)
+ // AM_RANGE(0x8000, 0xffff) AM_WRITE(genesis_z80_bank_w)
+ADDRESS_MAP_END
+
+static MACHINE_DRIVER_START( genesis_base )
+ /*basic machine hardware */
+ MDRV_CPU_ADD_TAG("main", M68000, MASTER_CLOCK / 7)
+ MDRV_CPU_PROGRAM_MAP(genesis_readmem, genesis_writemem)
+ MDRV_CPU_VBLANK_INT(genesis_vblank_interrupt,1)
+
+ MDRV_CPU_ADD_TAG("sound", Z80, MASTER_CLOCK / 15)
+ MDRV_CPU_PROGRAM_MAP(genesis_z80_readmem, genesis_z80_writemem)
+ MDRV_CPU_VBLANK_INT(irq0_line_hold, 1) /* from vdp at scanline 0xe0 */
+
+ MDRV_SCREEN_REFRESH_RATE(60)
+
+ MDRV_INTERLEAVE(100)
+
+ MDRV_MACHINE_START(genesis)
+ MDRV_MACHINE_RESET(genesis)
+
+ /* video hardware */
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER | VIDEO_HAS_SHADOWS | VIDEO_HAS_HIGHLIGHTS)
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
+ MDRV_SCREEN_SIZE(342,262)
+ MDRV_SCREEN_VISIBLE_AREA(0, 319, 0, 223)
+ MDRV_PALETTE_LENGTH(2048)
+
+ MDRV_VIDEO_START(genesis)
+ MDRV_VIDEO_UPDATE(genesis)
+
+ /* sound hardware */
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(YM3438, MASTER_CLOCK/7)
+ MDRV_SOUND_ROUTE(0, "mono", 0.50)
+ MDRV_SOUND_ROUTE(1, "mono", 0.50)
+MACHINE_DRIVER_END
+#endif