From 12dc9f81a65965f989b747c6e8590b23bb669df2 Mon Sep 17 00:00:00 2001 From: angelosa Date: Thu, 29 Jun 2017 00:29:47 +0200 Subject: ygv608.cpp: added CRTC function, moved irqs in handler callbacks [Angelo Salese] --- src/mame/drivers/namcond1.cpp | 44 +++--- src/mame/includes/namcond1.h | 4 +- src/mame/video/ygv608.cpp | 345 +++++++++++++++++++++++------------------- src/mame/video/ygv608.h | 75 ++++++++- 4 files changed, 286 insertions(+), 182 deletions(-) diff --git a/src/mame/drivers/namcond1.cpp b/src/mame/drivers/namcond1.cpp index bb260b22a7c..1aba50dc0c3 100644 --- a/src/mame/drivers/namcond1.cpp +++ b/src/mame/drivers/namcond1.cpp @@ -202,9 +202,6 @@ static ADDRESS_MAP_START( namcond1_map, AS_PROGRAM, 16, namcond1_state ) AM_RANGE(0x400000, 0x40ffff) AM_RAM AM_SHARE("shared_ram") AM_RANGE(0x800000, 0x80000f) AM_DEVICE8("ygv608", ygv608_device, port_map, 0xff00) AM_RANGE(0xa00000, 0xa00fff) AM_DEVREADWRITE8("at28c16", at28c16_device, read, write, 0xff00) -#ifdef MAME_DEBUG - AM_RANGE(0xb00000, 0xb00001) AM_DEVREAD("ygv608", ygv608_device, debug_trigger_r) -#endif AM_RANGE(0xc3ff00, 0xc3ffff) AM_READWRITE(cuskey_r,cuskey_w) ADDRESS_MAP_END @@ -216,9 +213,6 @@ static ADDRESS_MAP_START( abcheck_map, AS_PROGRAM, 16, namcond1_state ) AM_RANGE(0x780000, 0x780001) AM_READ(printer_r) AM_RANGE(0x800000, 0x80000f) AM_DEVICE8("ygv608", ygv608_device, port_map, 0xff00) AM_RANGE(0xa00000, 0xa00fff) AM_DEVREADWRITE8("at28c16", at28c16_device, read, write, 0xff00) -#ifdef MAME_DEBUG - AM_RANGE(0xb00000, 0xb00001) AM_DEVREAD("ygv608", ygv608_device, debug_trigger_r) -#endif AM_RANGE(0xc3ff00, 0xc3ffff) AM_READWRITE(cuskey_r,cuskey_w) ADDRESS_MAP_END @@ -335,19 +329,22 @@ INTERRUPT_GEN_MEMBER(namcond1_state::mcu_interrupt) - The level 1 interrupt to the 68k has been measured at 60Hz. *******************************************/ +WRITE_LINE_MEMBER( namcond1_state::vblank_irq_w ) +{ + m_maincpu->set_input_line(1, state ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE_LINE_MEMBER( namcond1_state::raster_irq_w ) +{ + m_maincpu->set_input_line(2, state ? ASSERT_LINE : CLEAR_LINE); +} + static MACHINE_CONFIG_START( namcond1 ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", M68000, XTAL_49_152MHz/4) MCFG_CPU_PROGRAM_MAP(namcond1_map) - MCFG_CPU_VBLANK_INT_DRIVER("screen", namcond1_state, irq1_line_hold) - - // I've disabled this for now, I don't think it's correct, it breaks ncv2 'game options' in test - // mode (and could also be responsible for the random resets?) - // also, if you log the timing of it and the scanlines on which the interrupt fires, it doesn't - // seem correct for the intended purpose? - //MCFG_DEVICE_PERIODIC_INT_DEVICE("ygv608", ygv608_device, timed_interrupt, 1000) - +// MCFG_CPU_VBLANK_INT_DRIVER("screen", namcond1_state, irq1_line_hold) MCFG_CPU_ADD("mcu", H83002, XTAL_49_152MHz/3 ) MCFG_CPU_PROGRAM_MAP( nd1h8rwmap) @@ -357,12 +354,18 @@ static MACHINE_CONFIG_START( namcond1 ) MCFG_QUANTUM_TIME(attotime::from_hz(6000)) + MCFG_YGV608_ADD("ygv608") + MCFG_YGV608_PALETTE("palette") + MCFG_YGV608_VBLANK_HANDLER(WRITELINE(namcond1_state, vblank_irq_w)) + MCFG_YGV608_RASTER_HANDLER(WRITELINE(namcond1_state, raster_irq_w)) + /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) - MCFG_SCREEN_REFRESH_RATE(60.0) - MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) - MCFG_SCREEN_SIZE(288, 224) // maximum display resolution (512x512 in theory) - MCFG_SCREEN_VISIBLE_AREA(0, 287, 0, 223) // default visible area + /* + H 804 108 576 48 32 + V 261 26 224 3 0 + */ + MCFG_SCREEN_RAW_PARAMS( XTAL_49_152MHz/8, 804/2, 108/2, (108+576)/2, 261, 26, 26+224) MCFG_SCREEN_UPDATE_DEVICE("ygv608", ygv608_device, update_screen) MCFG_SCREEN_PALETTE("palette") @@ -379,14 +382,13 @@ static MACHINE_CONFIG_START( namcond1 ) MCFG_AT28C16_ADD( "at28c16", nullptr ) - MCFG_YGV608_ADD("ygv608") - MCFG_YGV608_PALETTE("palette") + MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( abcheck, namcond1 ) MCFG_CPU_REPLACE("maincpu", M68000, XTAL_49_152MHz/4) MCFG_CPU_PROGRAM_MAP(abcheck_map) - MCFG_CPU_VBLANK_INT_DRIVER("screen", namcond1_state, irq1_line_hold) +// MCFG_CPU_VBLANK_INT_DRIVER("screen", namcond1_state, irq1_line_hold) MCFG_NVRAM_ADD_0FILL("zpr1") MCFG_NVRAM_ADD_0FILL("zpr2") diff --git a/src/mame/includes/namcond1.h b/src/mame/includes/namcond1.h index c30a35e095e..6396f9d989a 100644 --- a/src/mame/includes/namcond1.h +++ b/src/mame/includes/namcond1.h @@ -43,5 +43,7 @@ public: virtual void machine_start() override; virtual void machine_reset() override; - INTERRUPT_GEN_MEMBER(mcu_interrupt); + DECLARE_WRITE_LINE_MEMBER( vblank_irq_w ); + DECLARE_WRITE_LINE_MEMBER( raster_irq_w ); + INTERRUPT_GEN_MEMBER(mcu_interrupt); }; diff --git a/src/mame/video/ygv608.cpp b/src/mame/video/ygv608.cpp index 32e7b097e75..cbbd7f31514 100644 --- a/src/mame/video/ygv608.cpp +++ b/src/mame/video/ygv608.cpp @@ -361,7 +361,12 @@ GFXDECODE_END * ***************************************/ + // we use decimals here to match documentation static ADDRESS_MAP_START( regs_map, AS_IO, 8, ygv608_device ) + AM_RANGE(14, 14) AM_READWRITE(irq_mask_r,irq_mask_w) + AM_RANGE(15, 16) AM_READWRITE(irq_ctrl_r,irq_ctrl_w) + + AM_RANGE(39, 46) AM_WRITE(crtc_w) ADDRESS_MAP_END /*************************************** @@ -390,7 +395,9 @@ ygv608_device::ygv608_device( const machine_config &mconfig, const char *tag, de : device_t(mconfig, YGV608, tag, owner, clock), device_gfx_interface(mconfig, *this, GFXDECODE_NAME(ygv608)), device_memory_interface(mconfig, *this), - m_io_space_config("io", ENDIANNESS_BIG, 8, 6, 0, *ADDRESS_MAP_NAME(regs_map)) + m_io_space_config("io", ENDIANNESS_BIG, 8, 6, 0, *ADDRESS_MAP_NAME(regs_map)), + m_vblank_handler(*this), + m_raster_handler(*this) { } @@ -446,7 +453,14 @@ void ygv608_device::device_start() m_tilemap_B = nullptr; m_iospace = &space(AS_IO); - + + // TODO: tagging configuration + m_screen = downcast(machine().device("screen")); + m_vblank_handler.resolve(); + m_raster_handler.resolve(); + m_vblank_timer = timer_alloc(VBLANK_TIMER); + m_raster_timer = timer_alloc(RASTER_TIMER); + register_state_save(); } @@ -460,42 +474,32 @@ const address_space_config *ygv608_device::memory_space_config(address_spacenum return (spacenum == AS_IO) ? &m_io_space_config : nullptr; } +void ygv608_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch(id) + { + case VBLANK_TIMER: + { + m_screen_status |= 8; // FV + if(m_vblank_irq_mask == true) + m_vblank_handler(ASSERT_LINE); + break; + } + case RASTER_TIMER: + { + m_screen_status |= 0x10; // FP + if(m_raster_irq_mask == true) + m_raster_handler(ASSERT_LINE); + } + } +} + void ygv608_device::set_gfxbank(uint8_t gfxbank) { m_namcond1_gfxbank = gfxbank; } -/* interrupt generated every 1ms second */ -INTERRUPT_GEN_MEMBER(ygv608_device::timed_interrupt ) -{ -/* - this is not quite generic, because we trigger a 68k interrupt - - if this chip is ever used by another driver, we should make - this more generic - or move it into the machine driver -*/ - - static int timer = 0; - - if( ++timer == 1000 ) - timer = 0; - - /* once every 60Hz, set the vertical border interval start flag */ - if( ( timer % (1000/60) ) == 0 ) - { - m_ports.s.p6 |= p6_fv; - if (m_regs.s.r14 & r14_iev) - device.execute().set_input_line(2, HOLD_LINE); - } - - /* once every 60Hz, set the position detection flag (somewhere) */ - else if( ( timer % (1000/60) ) == 7 ) - { - m_ports.s.p6 |= p6_fp; - if (m_regs.s.r14 & r14_iep) - device.execute().set_input_line(2, HOLD_LINE); - } -} TILEMAP_MAPPER_MEMBER( ygv608_device::get_tile_offset ) @@ -1138,13 +1142,6 @@ uint32_t ygv608_device::update_screen(screen_device &screen, bitmap_ind16 &bitma if( m_screen_resize ) { -#ifdef _ENABLE_SCREEN_RESIZE - // hdw should be scaled by 16, not 8 - // - is it something to do with double dot-clocks??? - screen.set_visible_area(0, ((int)(m_regs.s.hdw)<<3/*4*/)-1, - 0, ((int)(m_regs.s.vdw)<<3)-1 ); -#endif - m_work_bitmap.resize(screen.width(), screen.height()); // reset resize flag @@ -1455,7 +1452,7 @@ READ8_MEMBER(ygv608_device::register_data_r) ***/ READ8_MEMBER( ygv608_device::status_port_r ) { - return (uint8_t)(m_ports.b[6]); + return m_screen_status; } // P#7R - system control port @@ -1628,7 +1625,11 @@ WRITE8_MEMBER( ygv608_device::register_select_w ) WRITE8_MEMBER( ygv608_device::status_port_w ) { /* writing a '1' resets that bit */ - m_ports.b[6] &= ~data; + m_screen_status &= ~data; + if(data & 8) + m_vblank_handler(0); + if(data & 0x10) + m_raster_handler(0); } // P#7W - system control port @@ -1729,30 +1730,166 @@ void ygv608_device::HandleRomTransfers(uint8_t type) #endif } -#if 0 -void nvsram( offs_t offset, uint16_t data ) +/*************************************** + * + * Register Interface routines + * + ****************************************/ + +// R#14R interrupt mask control +READ8_MEMBER( ygv608_device::irq_mask_r ) { - static int i = 0; + return (m_raster_irq_mask << 1) | (m_vblank_irq_mask << 0); +} - data = ( data >> 8 ) & 0xff; +// R#14W interrupt mask control +WRITE8_MEMBER( ygv608_device::irq_mask_w ) +{ + m_vblank_irq_mask = BIT(data, 0); + m_raster_irq_mask = BIT(data, 1); +} - if( 1 ) { - static char ascii[16]; - if( i%16 == 0 ) - logerror( "%04X: ", offset ); - logerror( "%02X ", data ); - ascii[i%16] = (data > 0x20) ? data : '.'; - if( i%16 == 15 ) - logerror( "| %-16.16s\n", ascii ); +// R#15R / R#16R raster interrupt control +READ8_MEMBER( ygv608_device::irq_ctrl_r ) +{ + uint8_t res; + + if(offset == 0) // R#15 + res = m_raster_irq_vpos & 0xff; + else // R#16 + { + res = (m_raster_irq_mode << 7); + + res|= (BIT(m_raster_irq_vpos, 8) << 6); + + res|= (m_raster_irq_hpos / 32) & 0x1f; } + + return res; +} - i++; +// R#15W / R#16W raster interrupt control +WRITE8_MEMBER( ygv608_device::irq_ctrl_w ) +{ + if(offset == 0) // R#15 + { + m_raster_irq_vpos &= ~0xff; + m_raster_irq_vpos |= data & 0xff; + } + else // R#16 + { + m_raster_irq_mode = BIT(data,7); + + m_raster_irq_vpos &= ~0x100; + m_raster_irq_vpos |= BIT(data,6) << 8; + + m_raster_irq_hpos = (data & 0x1f) * 32; + } +} + +// R#39W - R#46W display scan control write +WRITE8_MEMBER( ygv608_device::crtc_w ) +{ + //printf("[%d] <- %02x\n",offset+39,data); + + switch(offset+39) + { + case 39: + { + m_crtc.display_hsync = ((data >> 5) & 7) * 16; + m_crtc.border_width = (data & 0x1f) * 16; + break; + } + + case 40: + { + m_crtc.htotal &= ~0x600; + m_crtc.htotal |= (data & 0xc0) << 3; + + m_crtc.display_width = (data & 0x3f) * 16; + break; + } + + case 41: + { + m_crtc.display_hstart &= ~0x1fe; + m_crtc.display_hstart |= (data & 0xff) << 1; + break; + } + + case 42: + { + m_crtc.htotal &= ~0x1fe; + m_crtc.htotal |= (data & 0xff) << 1; + + printf("H %d %d %d %d %d\n",m_crtc.htotal,m_crtc.display_hstart,m_crtc.display_width,m_crtc.display_hsync,m_crtc.border_width); + break; + } + + case 43: + { + m_crtc.display_vsync = (data >> 5) & 7; + m_crtc.border_height = (data & 0x1f) * 8; + break; + } + + case 44: + { + // TODO: VSLS, bit 6 + + m_crtc.display_height = (data & 0x3f) * 8; + break; + } + + case 45: + { + m_crtc.vtotal &= ~0x100; + m_crtc.vtotal |= BIT(data,7) << 8; + + // TODO: TRES, bit 6 + + m_crtc.display_vstart = data & 0x3f; + break; + } + + case 46: + { + m_crtc.vtotal &= ~0xff; + m_crtc.vtotal |= data & 0xff; + + // TODO: call it for all mods in the CRTC + screen_configure(); + + //printf("V %d %d %d %d %d\n",m_crtc.vtotal,m_crtc.display_vstart,m_crtc.display_height,m_crtc.display_vsync,m_crtc.border_height); + break; + } + } +} + +// TODO: all horizontal values needs to be divided by 2, presumably some other register? +// TODO: h/vstart not taken into account (needs video mods) +void ygv608_device::screen_configure() +{ +// int display_hend = (m_crtc.display_hstart + (m_crtc.display_width / 2)) - 1; + int display_hend = (m_crtc.display_width / 2) - 1; +// int display_vend = (m_crtc.display_vstart + m_crtc.display_height) - 1; + int display_vend = (m_crtc.display_height) - 1; + + //rectangle visarea(m_crtc.display_hstart, display_hend, m_crtc.display_vstart, display_vend); + rectangle visarea(0, display_hend, 0, display_vend); + + attoseconds_t period = HZ_TO_ATTOSECONDS(m_screen->clock()) * m_crtc.vtotal * (m_crtc.htotal / 2); + + m_screen->configure(m_crtc.htotal / 2, m_crtc.vtotal, visarea, period ); + + // reset vblank timer + m_vblank_timer->reset(); + //m_vblank_timer->adjust(m_screen->time_until_pos(m_crtc.display_vstart+m_crtc.display_height,0), 0, m_screen->frame_period()); + m_vblank_timer->adjust(m_screen->time_until_pos(m_crtc.display_height,0), 0, m_screen->frame_period()); } -#endif // Set any "short-cut" variables before we update the YGV608 registers // - these are used only in optimisation of the emulation - void ygv608_device::SetPreShortcuts( int reg, int data ) { switch( reg ) { @@ -1937,106 +2074,10 @@ void ygv608_device::SetPostShortcuts(int reg ) } -/* - * The rest of this stuff is for debugging only! - */ -//#define SHOW_SOURCE_MODE -#if 0 -void dump_block( char *name, uint8_t *block, int len ) -{ - int i; - logerror( "uint8_t %s[] = {\n", name ); - for( i=0; i= 0x20) - ascii[i%16] = m_pattern_name_table[i]; - else - ascii[i%16] = '.'; - if( i % 16 == 15 ) - logerror( " | %-16.16s\n", ascii ); - } - logerror( "\n" ); -#endif - - /* - * Dump scroll table ram - */ - - logerror( "Scroll Table\n" ); - for( i=0; i<256; i++ ) { - if( i % 16 == 0 ) - logerror( "$%04X : ", i ); - logerror( "%02X ", m_scroll_data_table[0][i] ); - if( m_scroll_data_table[0][i] >= 0x20 ) - ascii[i%16] = m_scroll_data_table[0][i]; - else - ascii[i%16] = '.'; - if( i % 16 == 15 ) - logerror( " | %-16.16s\n", ascii ); - } - logerror( "\n" ); - -#endif - - return( 0 ); -} void ygv608_device::ShowYGV608Registers() { diff --git a/src/mame/video/ygv608.h b/src/mame/video/ygv608.h index dba90a33646..731144458fb 100644 --- a/src/mame/video/ygv608.h +++ b/src/mame/video/ygv608.h @@ -1,15 +1,17 @@ // license:BSD-3-Clause // copyright-holders:Mark McDougall +/* + * Yamaha YGV608 - PVDC2 Pattern mode Video Display Controller 2 + * - Mark McDougall + */ + #ifndef MAME_VIDEO_YGV608_H #define MAME_VIDEO_YGV608_H #pragma once #include "tilemap.h" -/* - * Yamaha YGV608 - PVDC2 Pattern mode Video Display Controller 2 - * - Mark McDougall - */ +#include "screen.h" class ygv608_device : public device_t, public device_gfx_interface, @@ -21,6 +23,7 @@ public: DECLARE_ADDRESS_MAP(port_map, 8); + // ports section DECLARE_READ8_MEMBER(pattern_name_table_r); DECLARE_READ8_MEMBER(sprite_data_r); DECLARE_READ8_MEMBER(scroll_data_r); @@ -38,21 +41,35 @@ public: DECLARE_WRITE8_MEMBER(status_port_w); DECLARE_WRITE8_MEMBER(system_control_w); + // register section + DECLARE_READ8_MEMBER(irq_mask_r); + DECLARE_WRITE8_MEMBER(irq_mask_w); + DECLARE_READ8_MEMBER(irq_ctrl_r); + DECLARE_WRITE8_MEMBER(irq_ctrl_w); + DECLARE_WRITE8_MEMBER(crtc_w); + // TODO: is this even a real connection? void set_gfxbank(uint8_t gfxbank); uint32_t update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - INTERRUPT_GEN_MEMBER( timed_interrupt ); - // to be removed - DECLARE_READ16_MEMBER( debug_trigger_r ); + template static devcb_base &static_set_vblank_callback(device_t &device, Object &&cb) + { + return downcast(device).m_vblank_handler.set_callback(std::forward(cb)); + } + template static devcb_base &static_set_raster_callback(device_t &device, Object &&cb) + { + return downcast(device).m_raster_handler.set_callback(std::forward(cb)); + } + protected: // device-level overrides virtual void device_start() override; virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_IO) const override; + void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; address_space *m_iospace; private: const address_space_config m_io_space_config; @@ -226,7 +243,42 @@ private: // new variable handling starts here uint8_t m_register_address; /**< RN: Register address select */ bool m_register_autoinc_r; /**< RRAI: Register address auto-increment on read */ - bool m_register_autoinc_w; /**< RWAI: Register address auto-increment on write */ + bool m_register_autoinc_w; /**< RWAI: Register address auto-increment on write */ + uint8_t m_screen_status; /**< CD: status port r/w */ + + bool m_raster_irq_mask; /**< IEP: raster irq mask (INT1 occurs if 1) */ + bool m_vblank_irq_mask; /**< IEV: vblank irq mask (INT0 occurs if 1) */ + int m_raster_irq_hpos; /**< IH: horizontal position where raster irq occurs x 32 */ + int m_raster_irq_vpos; /**< IV: vertical position where raster irq occurs */ + bool m_raster_irq_mode; /**< FPM: if 1 vertical position becomes invalid for raster irqs (irqs occur for every line) */ + + // screen section + devcb_write_line m_vblank_handler; + devcb_write_line m_raster_handler; + screen_device *m_screen; + emu_timer *m_vblank_timer; + emu_timer *m_raster_timer; + + enum + { + VBLANK_TIMER, + RASTER_TIMER + }; + + struct { + int htotal; /**< HTL: horizontal total number of dots x 2 */ + int vtotal; /**< VTL: vertical total number of lines x 1 */ + int display_hstart; /**< HDS: horizontal display starting position x 2*/ + int display_vstart; /**< VDS: vertical display starting position x 1 */ + int display_width; /**< HDW: horizontal display size x 16 */ + int display_height; /**< VDW: vertical display size x 8 */ + int display_hsync; /**< HSW: horizontal sync signal x 16 */ + int display_vsync; /**< VSW: vertical sync signal x 1 */ + int border_width; /**< HBW: horizontal border size x 16 */ + int border_height; /**< VBW: vertical border size x 8 */ + }m_crtc; + + void screen_configure(); }; // device type definition @@ -243,4 +295,11 @@ DECLARE_DEVICE_TYPE(YGV608, ygv608_device) #define MCFG_YGV608_PALETTE(_palette_tag) \ MCFG_GFX_PALETTE(_palette_tag) +#define MCFG_YGV608_VBLANK_HANDLER( _intcallb ) \ + devcb = &ygv608_device::static_set_vblank_callback( *device, DEVCB_##_intcallb ); + +#define MCFG_YGV608_RASTER_HANDLER( _intcallb ) \ + devcb = &ygv608_device::static_set_raster_callback( *device, DEVCB_##_intcallb ); + + #endif -- cgit v1.2.3