diff --git a/src/mame/drivers/segac2.c b/src/mame/drivers/segac2.c index 103b3ba6fcb..fa2de5d018b 100644 --- a/src/mame/drivers/segac2.c +++ b/src/mame/drivers/segac2.c @@ -1278,6 +1278,30 @@ static SCREEN_UPDATE_RGB32(segac2_new) } +// the main interrupt on C2 comes from the vdp line used to drive the z80 interrupt on a regular genesis(!) +void genesis_vdp_sndirqline_callback_segac2(running_machine &machine, bool state) +{ + if (state==true) + cputag_set_input_line(machine, "maincpu", 6, HOLD_LINE); +} + +// the line usually used to drive irq6 is not connected +void genesis_vdp_lv6irqline_callback_segac2(running_machine &machine, bool state) +{ + // +} + +// the scanline interrupt seems connected as usual +void genesis_vdp_lv4irqline_callback_segac2(running_machine &machine, bool state) +{ + if (state==true) + cputag_set_input_line(machine, "maincpu", 4, HOLD_LINE); + else + cputag_set_input_line(machine, "maincpu", 4, CLEAR_LINE); +} + + + static MACHINE_CONFIG_START( segac, segac2_state ) /* basic machine hardware */ @@ -1291,6 +1315,9 @@ static MACHINE_CONFIG_START( segac, segac2_state ) MCFG_FRAGMENT_ADD(megadriv_timers) MCFG_DEVICE_ADD("gen_vdp", SEGA_GEN_VDP, 0) + sega_genesis_vdp_device::set_genesis_vdp_sndirqline_callback(*device, genesis_vdp_sndirqline_callback_segac2); + sega_genesis_vdp_device::set_genesis_vdp_lv6irqline_callback(*device, genesis_vdp_lv6irqline_callback_segac2); + sega_genesis_vdp_device::set_genesis_vdp_lv4irqline_callback(*device, genesis_vdp_lv4irqline_callback_segac2); MCFG_SCREEN_ADD("megadriv", RASTER) MCFG_SCREEN_REFRESH_RATE(60) @@ -1762,7 +1789,6 @@ void segac2_state::segac2_common_init(running_machine& machine, int (*func)(int state->m_prot_func = func; genvdp_use_cram = 0; - genesis_always_irq6 = 1; genesis_other_hacks = 0; if (upd != NULL) diff --git a/src/mame/includes/megadriv.h b/src/mame/includes/megadriv.h index 931e6ae04b7..601a35f5ec2 100644 --- a/src/mame/includes/megadriv.h +++ b/src/mame/includes/megadriv.h @@ -14,6 +14,8 @@ #include "machine/nvram.h" #include "cpu/ssp1601/ssp1601.h" +#include "machine/megavdp.h" + #define MASTER_CLOCK_NTSC 53693175 #define MASTER_CLOCK_PAL 53203424 #define SEGACD_CLOCK 12500000 @@ -98,7 +100,6 @@ extern int segac2_bg_pal_lookup[4]; extern int segac2_sp_pal_lookup[4]; extern int genvdp_use_cram; -extern int genesis_always_irq6; extern int genesis_other_hacks; extern int megadrive_6buttons_pad; @@ -115,8 +116,11 @@ class md_base_state : public driver_device { public: md_base_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) { } - + : driver_device(mconfig, type, tag), + m_vdp(*this,"gen_vdp") + { } + required_device m_vdp; + DECLARE_DRIVER_INIT(megadriv_c2); DECLARE_DRIVER_INIT(megadrie); DECLARE_DRIVER_INIT(megadriv); diff --git a/src/mame/machine/megadriv.c b/src/mame/machine/megadriv.c index 187ff1ffbc0..68a52fcaf5e 100644 --- a/src/mame/machine/megadriv.c +++ b/src/mame/machine/megadriv.c @@ -53,11 +53,9 @@ Known Non-Issues (confirmed on Real Genesis) static cpu_device *_genesis_snd_z80_cpu; +int genesis_other_hacks = 0; // misc hacks timer_device* megadriv_scanline_timer; -timer_device* irq6_on_timer; -timer_device* irq4_on_timer; -//emu_timer* vblankirq_off_timer; genesis_z80_vars genz80; @@ -955,11 +953,6 @@ SCREEN_UPDATE_RGB32(megadriv) -static TIMER_DEVICE_CALLBACK( irq4_on_callback ) -{ - //mame_printf_debug("irq4 active on %d\n",genesis_scanline_counter); - cputag_set_input_line(timer.machine(), "maincpu", 4, HOLD_LINE); -} /*****************************************************************************************/ @@ -992,10 +985,7 @@ MACHINE_RESET( megadriv ) megadrive_reset_io(machine); megadriv_scanline_timer = machine.device("md_scan_timer"); - megadriv_render_timer = machine.device("md_render_timer"); - irq6_on_timer = machine.device("irq6_timer"); - irq4_on_timer = machine.device("irq4_timer"); megadriv_scanline_timer->adjust(attotime::zero); @@ -1039,15 +1029,6 @@ void megadriv_stop_scanline_timer(void) megadriv_scanline_timer->reset(); } -/* - 999999999999999960 -1000000000000000000 subseconds = 1 second - -/ 60 - -*/ - -/* VIDEO_EOF is used to resync the scanline counters */ UINT16* megadriv_backupram; @@ -1076,11 +1057,43 @@ static NVRAM_HANDLER( megadriv ) } +// this comes from the VDP on lines 240 (on) 241 (off) and is connected to the z80 irq 0 +void genesis_vdp_sndirqline_callback_genesis_z80(running_machine &machine, bool state) +{ + if (machine.device(":genesis_snd_z80") != NULL) + { + if (state == true) + { + megadriv_z80_hold(machine); + } + else if (state == false) + { + megadriv_z80_clear(machine); + } + } +} + +// this comes from the vdp, and is connected to 68k irq level 6 (main vbl interrupt) +void genesis_vdp_lv6irqline_callback_genesis_68k(running_machine &machine, bool state) +{ + if (state==true) + cputag_set_input_line(machine, "maincpu", 6, HOLD_LINE); + else + cputag_set_input_line(machine, "maincpu", 6, CLEAR_LINE); +} + +// this comes from the vdp, and is connected to 68k irq level 4 (raster interrupt) +void genesis_vdp_lv4irqline_callback_genesis_68k(running_machine &machine, bool state) +{ + if (state==true) + cputag_set_input_line(machine, "maincpu", 4, HOLD_LINE); + else + cputag_set_input_line(machine, "maincpu", 4, CLEAR_LINE); +} + + MACHINE_CONFIG_FRAGMENT( megadriv_timers ) MCFG_TIMER_ADD("md_scan_timer", megadriv_scanline_timer_callback) - MCFG_TIMER_ADD("md_render_timer", megadriv_render_timer_callback) - MCFG_TIMER_ADD("irq6_timer", irq6_on_callback) - MCFG_TIMER_ADD("irq4_timer", irq4_on_callback) MACHINE_CONFIG_END @@ -1100,6 +1113,11 @@ MACHINE_CONFIG_FRAGMENT( md_ntsc ) MCFG_FRAGMENT_ADD(megadriv_timers) MCFG_DEVICE_ADD("gen_vdp", SEGA_GEN_VDP, 0) + sega_genesis_vdp_device::set_genesis_vdp_sndirqline_callback(*device, genesis_vdp_sndirqline_callback_genesis_z80); + sega_genesis_vdp_device::set_genesis_vdp_lv6irqline_callback(*device, genesis_vdp_lv6irqline_callback_genesis_68k); + sega_genesis_vdp_device::set_genesis_vdp_lv4irqline_callback(*device, genesis_vdp_lv4irqline_callback_genesis_68k); + + MCFG_SCREEN_ADD("megadriv", RASTER) MCFG_SCREEN_REFRESH_RATE(60) @@ -1150,6 +1168,9 @@ MACHINE_CONFIG_FRAGMENT( md_pal ) MCFG_FRAGMENT_ADD(megadriv_timers) MCFG_DEVICE_ADD("gen_vdp", SEGA_GEN_VDP, 0) + sega_genesis_vdp_device::set_genesis_vdp_sndirqline_callback(*device, genesis_vdp_sndirqline_callback_genesis_z80); + sega_genesis_vdp_device::set_genesis_vdp_lv6irqline_callback(*device, genesis_vdp_lv6irqline_callback_genesis_68k); + sega_genesis_vdp_device::set_genesis_vdp_lv4irqline_callback(*device, genesis_vdp_lv4irqline_callback_genesis_68k); MCFG_SCREEN_ADD("megadriv", RASTER) MCFG_SCREEN_REFRESH_RATE(50) @@ -1489,7 +1510,6 @@ static void megadriv_init_common(running_machine &machine) DRIVER_INIT_MEMBER(md_base_state,megadriv_c2) { genvdp_use_cram = 0; - genesis_always_irq6 = 1; genesis_other_hacks = 0; megadriv_init_common(machine()); @@ -1503,7 +1523,6 @@ DRIVER_INIT_MEMBER(md_base_state,megadriv_c2) DRIVER_INIT_MEMBER(md_base_state,megadriv) { genvdp_use_cram = 1; - genesis_always_irq6 = 0; genesis_other_hacks = 1; megadriv_init_common(machine()); @@ -1515,7 +1534,6 @@ DRIVER_INIT_MEMBER(md_base_state,megadriv) DRIVER_INIT_MEMBER(md_base_state,megadrij) { genvdp_use_cram = 1; - genesis_always_irq6 = 0; genesis_other_hacks = 1; megadriv_init_common(machine()); @@ -1527,7 +1545,6 @@ DRIVER_INIT_MEMBER(md_base_state,megadrij) DRIVER_INIT_MEMBER(md_base_state,megadrie) { genvdp_use_cram = 1; - genesis_always_irq6 = 0; genesis_other_hacks = 1; megadriv_init_common(machine()); @@ -1585,9 +1602,6 @@ void megatech_set_megadrive_z80_as_megadrive_z80(running_machine &machine, const machine.device(tag)->memory().space(AS_PROGRAM)->install_ram(0x0000, 0x1fff, genz80.z80_prgram); - // not allowed?? -// machine.device(tag)->memory().space(AS_PROGRAM)->install_readwrite_bank(0x2000, 0x3fff, "bank1"); - machine.device(tag)->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(*ym, 0x4000, 0x4003, FUNC(ym2612_r), FUNC(ym2612_w)); machine.device(tag)->memory().space(AS_PROGRAM)->install_legacy_write_handler (0x6000, 0x6000, FUNC(megadriv_z80_z80_bank_w)); machine.device(tag)->memory().space(AS_PROGRAM)->install_legacy_write_handler (0x6001, 0x6001, FUNC(megadriv_z80_z80_bank_w)); @@ -1596,6 +1610,31 @@ void megatech_set_megadrive_z80_as_megadrive_z80(running_machine &machine, const machine.device(tag)->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x8000, 0xffff, FUNC(z80_read_68k_banked_data), FUNC(z80_write_68k_banked_data)); } -// these are tests for 'special case' hardware to make sure I don't break anything while rearranging things -// +// called at the start of each scanline +TIMER_DEVICE_CALLBACK( megadriv_scanline_timer_callback ) +{ + md_base_state *state = timer.machine().driver_data(); + + timer.machine().scheduler().synchronize(); + state->m_vdp->vdp_handle_scanline_callback(timer.machine(), param); + + megadriv_scanline_timer->adjust(attotime::from_hz(megadriv_framerate) / megadrive_total_scanlines); +} + + + +SCREEN_VBLANK(megadriv) +{ + md_base_state *state = screen.machine().driver_data(); + + if (screen.machine().root_device().ioport(":RESET")->read_safe(0x00) & 0x01) + cputag_set_input_line(screen.machine(), ":maincpu", INPUT_LINE_RESET, PULSE_LINE); + + // rising edge + if (vblank_on) + { + state->m_vdp->vdp_handle_vblank(screen); + megadriv_scanline_timer->adjust(attotime::zero); + } +} diff --git a/src/mame/machine/megavdp.c b/src/mame/machine/megavdp.c index 84c2719ac91..60317efa10e 100644 --- a/src/mame/machine/megavdp.c +++ b/src/mame/machine/megavdp.c @@ -14,8 +14,6 @@ extern int megadrive_irq6_scanline; extern cpu_device *_svp_cpu; extern int segacd_wordram_mapped; extern timer_device* megadriv_scanline_timer; -extern timer_device* irq6_on_timer; -extern timer_device* irq4_on_timer; extern UINT32* _32x_render_videobuffer_to_screenbuffer_helper(running_machine &machine, int scanline); extern void _32x_scanline_cb0(running_machine& machine); @@ -26,8 +24,6 @@ extern int _32x_displaymode; extern int _32x_videopriority; extern int _32x_is_connected; -extern void megadriv_z80_hold(running_machine &machine); -extern void megadriv_z80_clear(running_machine &machine); #define MAX_HPOSITION 480 @@ -37,7 +33,6 @@ extern void megadriv_z80_clear(running_machine &machine); int megadrive_visible_scanlines; int megadrive_irq6_scanline; int megadrive_z80irq_scanline; -int megadrive_imode = 0; int megadriv_framerate; int megadrive_total_scanlines; int megadrive_vblank_flag = 0; @@ -50,8 +45,6 @@ int segac2_sp_pal_lookup[4]; // hacks for C2 int genvdp_use_cram = 0; // c2 uses it's own palette ram -int genesis_always_irq6 = 0; // c2 never enables the irq6, different source?? -int genesis_other_hacks = 0; // misc hacks UINT16* megadrive_vdp_palette_lookup; UINT16* megadrive_vdp_palette_lookup_sprite; // for C2 @@ -62,23 +55,90 @@ UINT16* megadrive_ram; int megadrive_region_export; int megadrive_region_pal; -timer_device* megadriv_render_timer; +void genesis_vdp_sndirqline_callback_default(running_machine &machine, bool state) +{ + // if you haven't actually hooked this up.... + fatalerror("m_genesis_vdp_sndirqline_callback should be connected to something!\n"); +} + +void genesis_vdp_lv6irqline_callback_default(running_machine &machine, bool state) +{ + // or this... + fatalerror("m_genesis_vdp_lv6irqline_callback should be connected to something!\n"); +} + +void genesis_vdp_lv4irqline_callback_default(running_machine &machine, bool state) +{ + // or this... + fatalerror("m_genesis_vdp_lv4irqline_callback should be connected to something!\n"); +} const device_type SEGA_GEN_VDP = &device_creator; sega_genesis_vdp_device::sega_genesis_vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, SEGA_GEN_VDP, "sega_genesis_vdp_device", tag, owner, clock) { + m_genesis_vdp_sndirqline_callback = genesis_vdp_sndirqline_callback_default; + m_genesis_vdp_lv6irqline_callback = genesis_vdp_lv6irqline_callback_default; + m_genesis_vdp_lv4irqline_callback = genesis_vdp_lv4irqline_callback_default; +} +static TIMER_CALLBACK( megadriv_render_timer_callback ) +{ + sega_genesis_vdp_device* vdp = (sega_genesis_vdp_device*)ptr; + vdp->genesis_render_scanline(machine); +} + +void sega_genesis_vdp_device::vdp_handle_irq6_on_timer_callback(running_machine &machine, int param) +{ +// megadrive_irq6_pending = 1; + if (MEGADRIVE_REG01_IRQ6_ENABLE) + m_genesis_vdp_lv6irqline_callback(machine, true); +} + +static TIMER_CALLBACK( irq6_on_timer_callback ) +{ + sega_genesis_vdp_device* vdp = (sega_genesis_vdp_device*)ptr; + vdp->vdp_handle_irq6_on_timer_callback(machine, param); +} + +void sega_genesis_vdp_device::vdp_handle_irq4_on_timer_callback(running_machine &machine, int param) +{ + m_genesis_vdp_lv4irqline_callback(machine, true); +} + +static TIMER_CALLBACK( irq4_on_timer_callback ) +{ + sega_genesis_vdp_device* vdp = (sega_genesis_vdp_device*)ptr; + vdp->vdp_handle_irq4_on_timer_callback(machine, param); } + +void sega_genesis_vdp_device::set_genesis_vdp_sndirqline_callback(device_t &device, genesis_vdp_sndirqline_callback_func callback) +{ + sega_genesis_vdp_device &dev = downcast(device); + dev.m_genesis_vdp_sndirqline_callback = callback; +} + +void sega_genesis_vdp_device::set_genesis_vdp_lv6irqline_callback(device_t &device, genesis_vdp_lv6irqline_callback_func callback) +{ + sega_genesis_vdp_device &dev = downcast(device); + dev.m_genesis_vdp_lv6irqline_callback = callback; +} + +void sega_genesis_vdp_device::set_genesis_vdp_lv4irqline_callback(device_t &device, genesis_vdp_lv4irqline_callback_func callback) +{ + sega_genesis_vdp_device &dev = downcast(device); + dev.m_genesis_vdp_lv4irqline_callback = callback; +} + void sega_genesis_vdp_device::device_start() { @@ -111,6 +171,7 @@ void sega_genesis_vdp_device::device_start() save_item(NAME(m_irq4counter)); save_item(NAME(m_imode_odd_frame)); save_item(NAME(m_sprite_collision)); + save_item(NAME(megadrive_imode)); @@ -120,6 +181,9 @@ void sega_genesis_vdp_device::device_start() m_render_bitmap = auto_bitmap_ind16_alloc(machine(), machine().primary_screen->width(), machine().primary_screen->height()); + irq6_on_timer = machine().scheduler().timer_alloc(FUNC(irq6_on_timer_callback), (void*)this); + irq4_on_timer = machine().scheduler().timer_alloc(FUNC(irq4_on_timer_callback), (void*)this); + megadriv_render_timer = machine().scheduler().timer_alloc(FUNC(megadriv_render_timer_callback), (void*)this); } @@ -132,17 +196,16 @@ void sega_genesis_vdp_device::device_reset() m_vdp_address = 0; m_vram_fill_pending = 0; m_vram_fill_length = 0; - m_irq4counter = 0; + m_irq4counter = -1; m_imode_odd_frame = 0; m_sprite_collision = 0; + megadrive_imode = 0; } void sega_genesis_vdp_device::device_reset_old() { // other stuff, are we sure we want to set some of these every reset? - // it's called from MACHIN_RESET( megadriv ) - megadrive_imode = 0; - m_irq4counter = -1; + // it's called from MACHINE_RESET( megadriv ) megadrive_total_scanlines = 262; megadrive_visible_scanlines = 224; megadrive_irq6_scanline = 224; @@ -335,9 +398,9 @@ void sega_genesis_vdp_device::megadrive_vdp_set_register(running_machine &machin if (megadrive_irq4_pending) { if (MEGADRIVE_REG0_IRQ4_ENABLE) - cputag_set_input_line(machine, ":maincpu", 4, HOLD_LINE); + m_genesis_vdp_lv4irqline_callback(machine, true); else - cputag_set_input_line(machine, ":maincpu", 4, CLEAR_LINE); + m_genesis_vdp_lv4irqline_callback(machine, false); } /* ??? Fatal Rewind needs this but I'm not sure it's accurate behavior @@ -352,9 +415,10 @@ void sega_genesis_vdp_device::megadrive_vdp_set_register(running_machine &machin if (megadrive_irq6_pending) { if (MEGADRIVE_REG01_IRQ6_ENABLE ) - cputag_set_input_line(machine, ":maincpu", 6, HOLD_LINE); + m_genesis_vdp_lv6irqline_callback(machine, true); else - cputag_set_input_line(machine, ":maincpu", 6, CLEAR_LINE); + m_genesis_vdp_lv6irqline_callback(machine, false); + } /* ??? */ @@ -2587,21 +2651,21 @@ void sega_genesis_vdp_device::genesis_render_videobuffer_to_screenbuffer(running } } -void sega_genesis_vdp_device::genesis_render_scanline(running_machine &machine, int scanline) +void sega_genesis_vdp_device::genesis_render_scanline(running_machine &machine) { - //if (MEGADRIVE_REG01_DMA_ENABLE==0) mame_printf_debug("off\n"); - genesis_render_spriteline_to_spritebuffer(genesis_scanline_counter); - genesis_render_videoline_to_videobuffer(scanline); - genesis_render_videobuffer_to_screenbuffer(machine, scanline); + int scanline = genesis_scanline_counter; + if (scanline>=0 && scanlineadjust(attotime::from_hz(megadriv_framerate) / megadrive_total_scanlines); megadriv_render_timer->adjust(attotime::from_usec(1)); if (genesis_scanline_counter==megadrive_irq6_scanline ) @@ -2697,19 +2760,14 @@ void sega_genesis_vdp_device::vdp_handle_scanline_callback(running_machine &mach _32x_scanline_cb1(); } - - if (machine.device(":genesis_snd_z80") != NULL) + if (genesis_scanline_counter == megadrive_z80irq_scanline) { - if (genesis_scanline_counter == megadrive_z80irq_scanline) - { - megadriv_z80_hold(machine); - } - if (genesis_scanline_counter == megadrive_z80irq_scanline + 1) - { - megadriv_z80_clear(machine); - } + m_genesis_vdp_sndirqline_callback(machine, true); + } + if (genesis_scanline_counter == megadrive_z80irq_scanline + 1) + { + m_genesis_vdp_sndirqline_callback(machine, false); } - } else /* pretend we're still on the same scanline to compensate for rounding errors */ { @@ -2718,35 +2776,8 @@ void sega_genesis_vdp_device::vdp_handle_scanline_callback(running_machine &mach } -TIMER_DEVICE_CALLBACK( megadriv_scanline_timer_callback ) -{ - sega_genesis_vdp_device *vdp = timer.machine().device("gen_vdp"); // yuck - /* This function is called at the very start of every scanline starting at the very - top-left of the screen. The first scanline is scanline 0 (we set scanline to -1 in - VIDEO_EOF) */ - timer.machine().scheduler().synchronize(); - vdp->vdp_handle_scanline_callback(timer.machine(), param); - -} - -void sega_genesis_vdp_device::vdp_handle_irq6_on_callback(running_machine &machine, int param) -{ - //mame_printf_debug("irq6 active on %d\n",genesis_scanline_counter); - - { -// megadrive_irq6_pending = 1; - if (MEGADRIVE_REG01_IRQ6_ENABLE || genesis_always_irq6) - cputag_set_input_line(machine, ":maincpu", 6, HOLD_LINE); - } -} - -TIMER_DEVICE_CALLBACK( irq6_on_callback ) -{ - sega_genesis_vdp_device *vdp = timer.machine().device("gen_vdp"); // yuck - vdp->vdp_handle_irq6_on_callback(timer.machine(), param); -} void sega_genesis_vdp_device::vdp_handle_vblank(screen_device &screen) { @@ -2763,8 +2794,6 @@ void sega_genesis_vdp_device::vdp_handle_vblank(screen_device &screen) m_imode_odd_frame^=1; // cputag_set_input_line(machine, "genesis_snd_z80", 0, CLEAR_LINE); // if the z80 interrupt hasn't happened by now, clear it.. - if (screen.machine().root_device().ioport(":RESET")->read_safe(0x00) & 0x01) - cputag_set_input_line(screen.machine(), ":maincpu", INPUT_LINE_RESET, PULSE_LINE); if (MEGADRIVE_REG01_240_LINE) @@ -2827,7 +2856,6 @@ void sega_genesis_vdp_device::vdp_handle_vblank(screen_device &screen) screen.machine().primary_screen->configure(scr_width, megadrive_visible_scanlines, visarea, HZ_TO_ATTOSECONDS(megadriv_framerate)); - megadriv_scanline_timer->adjust(attotime::zero); if(_32x_is_connected) _32x_hcount_compare_val = -1; @@ -2835,28 +2863,8 @@ void sega_genesis_vdp_device::vdp_handle_vblank(screen_device &screen) -SCREEN_VBLANK(megadriv) -{ - // rising edge - if (vblank_on) - { - sega_genesis_vdp_device *vdp = screen.machine().device("gen_vdp"); // yuck - vdp->vdp_handle_vblank(screen); - } -} -TIMER_DEVICE_CALLBACK( megadriv_render_timer_callback ) -{ - sega_genesis_vdp_device *vdp = timer.machine().device("gen_vdp"); // yuck - - if (genesis_scanline_counter>=0 && genesis_scanline_countergenesis_render_scanline(timer.machine(), genesis_scanline_counter); - } -} - void megadriv_reset_vdp(running_machine &machine) { sega_genesis_vdp_device *vdp = machine.device("gen_vdp"); // yuck diff --git a/src/mame/machine/megavdp.h b/src/mame/machine/megavdp.h index 5a741ec97b8..15a322f61bf 100644 --- a/src/mame/machine/megavdp.h +++ b/src/mame/machine/megavdp.h @@ -1,5 +1,6 @@ /* Sega Megadrive / Genesis VDP */ +#pragma once /* The VDP occupies addresses C00000h to C0001Fh. @@ -141,19 +142,27 @@ #define MEGADRIVE_REG17_UNUSED ((m_vdp_regs[0x17]&0x3f)>>0) - +typedef void (*genesis_vdp_sndirqline_callback_func)(running_machine &machine, bool state); +typedef void (*genesis_vdp_lv6irqline_callback_func)(running_machine &machine, bool state); +typedef void (*genesis_vdp_lv4irqline_callback_func)(running_machine &machine, bool state); class sega_genesis_vdp_device : public device_t { public: sega_genesis_vdp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + static void set_genesis_vdp_sndirqline_callback(device_t &device, genesis_vdp_sndirqline_callback_func callback); + static void set_genesis_vdp_lv6irqline_callback(device_t &device, genesis_vdp_lv6irqline_callback_func callback); + static void set_genesis_vdp_lv4irqline_callback(device_t &device, genesis_vdp_lv4irqline_callback_func callback); + DECLARE_READ16_MEMBER( megadriv_vdp_r ); DECLARE_WRITE16_MEMBER( megadriv_vdp_w ); - void genesis_render_scanline(running_machine &machine, int scanline); + + void genesis_render_scanline(running_machine &machine); void vdp_handle_scanline_callback(running_machine &machine, int scanline); - void vdp_handle_irq6_on_callback(running_machine &machine, int param); + void vdp_handle_irq6_on_timer_callback(running_machine &machine, int param); + void vdp_handle_irq4_on_timer_callback(running_machine &machine, int param); void vdp_handle_vblank(screen_device &screen); void device_reset_old(); @@ -163,6 +172,10 @@ protected: virtual void device_start(); virtual void device_reset(); + // called when we hit 240 and 241 (used to control the z80 irq line on genesis, or the main irq on c2) + genesis_vdp_sndirqline_callback_func m_genesis_vdp_sndirqline_callback; + genesis_vdp_lv6irqline_callback_func m_genesis_vdp_lv6irqline_callback; + genesis_vdp_lv6irqline_callback_func m_genesis_vdp_lv4irqline_callback; private: @@ -177,6 +190,8 @@ private: int m_imode_odd_frame; int m_sprite_collision; + int megadrive_imode; + UINT16* m_vdp_regs; UINT16* m_vram; UINT16* m_cram; @@ -185,6 +200,13 @@ private: to speed up processing, Castlevania Bloodlines abuses this on the upside down level */ UINT16* m_internal_sprite_attribute_table; + // these are used internally by the VDP to schedule when after the start of a scanline + // to trigger the various interrupts / rendering to our bitmap, bit of a hack really + emu_timer* irq6_on_timer; + emu_timer* irq4_on_timer; + emu_timer* megadriv_render_timer; + + UINT16 vdp_vram_r(void); UINT16 vdp_vsram_r(void);