diff --git a/.gitattributes b/.gitattributes index d0c5096de38..a5053b87f9b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1202,6 +1202,8 @@ src/emu/validity.c svneol=native#text/plain src/emu/validity.h svneol=native#text/plain src/emu/video.c svneol=native#text/plain src/emu/video.h svneol=native#text/plain +src/emu/video/cdp1861.c svneol=native#text/plain +src/emu/video/cdp1861.h svneol=native#text/plain src/emu/video/crt9007.c svneol=native#text/plain src/emu/video/crt9007.h svneol=native#text/plain src/emu/video/crt9021.c svneol=native#text/plain diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 25b0926fc9d..3bd2e8169dc 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -231,6 +231,7 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/z8536.o \ EMUVIDEOOBJS = \ + $(EMUVIDEO)/cdp1861.o \ $(EMUVIDEO)/crt9007.o \ $(EMUVIDEO)/crt9021.o \ $(EMUVIDEO)/crt9212.o \ diff --git a/src/emu/video/cdp1861.c b/src/emu/video/cdp1861.c new file mode 100644 index 00000000000..2ca7b7888b8 --- /dev/null +++ b/src/emu/video/cdp1861.c @@ -0,0 +1,279 @@ +/********************************************************************** + + RCA CDP1861 Video Display Controller emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "emu.h" +#include "cdp1861.h" +#include "machine/devhelpr.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define CDP1861_CYCLES_DMA_START 2*8 +#define CDP1861_CYCLES_DMA_ACTIVE 8*8 +#define CDP1861_CYCLES_DMA_WAIT 6*8 + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// devices +const device_type CDP1861 = cdp1861_device_config::static_alloc_device_config; + + + +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** + +GENERIC_DEVICE_CONFIG_SETUP(cdp1861, "CDP1861") + + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void cdp1861_device_config::device_config_complete() +{ + // inherit a copy of the static data + const cdp1861_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) + *static_cast(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_int_func, 0, sizeof(m_out_int_func)); + memset(&m_out_dmao_func, 0, sizeof(m_out_dmao_func)); + memset(&m_out_efx_func, 0, sizeof(m_out_efx_func)); + } +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// cdp1861_device - constructor +//------------------------------------------------- + +cdp1861_device::cdp1861_device(running_machine &_machine, const cdp1861_device_config &config) + : device_t(_machine, config), + m_config(config) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void cdp1861_device::device_start() +{ + // resolve callbacks + devcb_resolve_write_line(&m_out_int_func, &m_config.m_out_int_func, this); + devcb_resolve_write_line(&m_out_dmao_func, &m_config.m_out_dmao_func, this); + devcb_resolve_write_line(&m_out_efx_func, &m_config.m_out_efx_func, this); + + // allocate timers + m_int_timer = timer_alloc(TIMER_INT); + m_efx_timer = timer_alloc(TIMER_EFX); + m_dma_timer = timer_alloc(TIMER_DMA); + + // find devices + m_cpu = m_machine.device(m_config.m_cpu_tag); + m_screen = m_machine.device(m_config.m_screen_tag); + m_bitmap = auto_bitmap_alloc(m_machine, m_screen->width(), m_screen->height(), m_screen->format()); + + // register for state saving + save_item(NAME(m_disp)); + save_item(NAME(m_dispon)); + save_item(NAME(m_dispoff)); + save_item(NAME(m_dmaout)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void cdp1861_device::device_reset() +{ + m_int_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_INT_START, 0)); + m_efx_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_EFX_TOP_START, 0)); + m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1861_CYCLES_DMA_START)); + + m_disp = 0; + m_dmaout = 0; + + devcb_call_write_line(&m_out_int_func, CLEAR_LINE); + devcb_call_write_line(&m_out_dmao_func, CLEAR_LINE); + devcb_call_write_line(&m_out_efx_func, CLEAR_LINE); +} + + +//------------------------------------------------- +// device_timer - handle timer events +//------------------------------------------------- + +void cdp1861_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + int scanline = m_screen->vpos(); + + switch (id) + { + case TIMER_INT: + if (scanline == CDP1861_SCANLINE_INT_START) + { + if (m_disp) + { + devcb_call_write_line(&m_out_int_func, ASSERT_LINE); + } + + m_int_timer->adjust(m_screen->time_until_pos( CDP1861_SCANLINE_INT_END, 0)); + } + else + { + if (m_disp) + { + devcb_call_write_line(&m_out_int_func, CLEAR_LINE); + } + + m_int_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_INT_START, 0)); + } + break; + + case TIMER_EFX: + switch (scanline) + { + case CDP1861_SCANLINE_EFX_TOP_START: + devcb_call_write_line(&m_out_efx_func, ASSERT_LINE); + m_efx_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_EFX_TOP_END, 0)); + break; + + case CDP1861_SCANLINE_EFX_TOP_END: + devcb_call_write_line(&m_out_efx_func, CLEAR_LINE); + m_efx_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_EFX_BOTTOM_START, 0)); + break; + + case CDP1861_SCANLINE_EFX_BOTTOM_START: + devcb_call_write_line(&m_out_efx_func, ASSERT_LINE); + m_efx_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_EFX_BOTTOM_END, 0)); + break; + + case CDP1861_SCANLINE_EFX_BOTTOM_END: + devcb_call_write_line(&m_out_efx_func, CLEAR_LINE); + m_efx_timer->adjust(m_screen->time_until_pos(CDP1861_SCANLINE_EFX_TOP_START, 0)); + break; + } + break; + + case TIMER_DMA: + if (m_dmaout) + { + if (m_disp) + { + if (scanline >= CDP1861_SCANLINE_DISPLAY_START && scanline < CDP1861_SCANLINE_DISPLAY_END) + { + devcb_call_write_line(&m_out_dmao_func, CLEAR_LINE); + } + } + + m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1861_CYCLES_DMA_WAIT)); + + m_dmaout = 0; + } + else + { + if (m_disp) + { + if (scanline >= CDP1861_SCANLINE_DISPLAY_START && scanline < CDP1861_SCANLINE_DISPLAY_END) + { + devcb_call_write_line(&m_out_dmao_func, ASSERT_LINE); + } + } + + m_dma_timer->adjust(m_cpu->cycles_to_attotime(CDP1861_CYCLES_DMA_ACTIVE)); + + m_dmaout = 1; + } + break; + } +} + + +//------------------------------------------------- +// dma_w - +//------------------------------------------------- + +WRITE8_MEMBER( cdp1861_device::dma_w ) +{ + int sx = m_screen->hpos() + 4; + int y = m_screen->vpos(); + int x; + + for (x = 0; x < 8; x++) + { + int color = BIT(data, 7); + *BITMAP_ADDR16(m_bitmap, y, sx + x) = color; + data <<= 1; + } +} + + +//------------------------------------------------- +// disp_on_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( cdp1861_device::disp_on_w ) +{ + if (!m_dispon && state) m_disp = 1; + + m_dispon = state; +} + + +//------------------------------------------------- +// disp_off_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( cdp1861_device::disp_off_w ) +{ + if (!m_dispon && !m_dispoff && state) m_disp = 0; + + m_dispoff = state; + + devcb_call_write_line(&m_out_int_func, CLEAR_LINE); + devcb_call_write_line(&m_out_dmao_func, CLEAR_LINE); +} + + +//------------------------------------------------- +// update_screen - +//------------------------------------------------- + +void cdp1861_device::update_screen(bitmap_t *bitmap, const rectangle *cliprect) +{ + if (m_disp) + { + copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); + } + else + { + bitmap_fill(bitmap, cliprect, get_black_pen(m_machine)); + } +} diff --git a/src/emu/video/cdp1861.h b/src/emu/video/cdp1861.h new file mode 100644 index 00000000000..0bce7e8d497 --- /dev/null +++ b/src/emu/video/cdp1861.h @@ -0,0 +1,180 @@ +/********************************************************************** + + RCA CDP1861 Video Display Controller emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +********************************************************************** + _____ _____ + _CLK 1 |* \_/ | 24 Vdd + _DMAO 2 | | 23 _CLEAR + _INT 3 | | 22 SC1 + TPA 4 | | 21 SC0 + TPB 5 | | 20 DI7 + _COMP SYNC 6 | CDP1861 | 19 DI6 + VIDEO 7 | | 18 DI5 + _RESET 8 | | 17 DI4 + _EFX 9 | | 16 DI3 + DISP ON 10 | | 15 DI2 + DISP OFF 11 | | 14 DI1 + Vss 12 |_____________| 13 DI0 + +**********************************************************************/ + +#pragma once + +#ifndef __CDP1861__ +#define __CDP1861__ + +#include "emu.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define CDP1861_VISIBLE_COLUMNS 64 +#define CDP1861_VISIBLE_LINES 128 + +#define CDP1861_HBLANK_START 14 * 8 +#define CDP1861_HBLANK_END 12 +#define CDP1861_HSYNC_START 0 +#define CDP1861_HSYNC_END 12 +#define CDP1861_SCREEN_WIDTH 14 * 8 + +#define CDP1861_TOTAL_SCANLINES 262 + +#define CDP1861_SCANLINE_DISPLAY_START 80 +#define CDP1861_SCANLINE_DISPLAY_END 208 +#define CDP1861_SCANLINE_VBLANK_START 262 +#define CDP1861_SCANLINE_VBLANK_END 16 +#define CDP1861_SCANLINE_VSYNC_START 16 +#define CDP1861_SCANLINE_VSYNC_END 0 +#define CDP1861_SCANLINE_INT_START CDP1861_SCANLINE_DISPLAY_START - 2 +#define CDP1861_SCANLINE_INT_END CDP1861_SCANLINE_DISPLAY_START +#define CDP1861_SCANLINE_EFX_TOP_START CDP1861_SCANLINE_DISPLAY_START - 4 +#define CDP1861_SCANLINE_EFX_TOP_END CDP1861_SCANLINE_DISPLAY_START +#define CDP1861_SCANLINE_EFX_BOTTOM_START CDP1861_SCANLINE_DISPLAY_END - 4 +#define CDP1861_SCANLINE_EFX_BOTTOM_END CDP1861_SCANLINE_DISPLAY_END + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_CDP1861_ADD(_tag, _clock, _config) \ + MCFG_DEVICE_ADD(_tag, CDP1861, _clock) \ + MCFG_DEVICE_CONFIG(_config) + + +#define MCFG_CDP1861_SCREEN_ADD(_tag, _clock) \ + MCFG_SCREEN_ADD(_tag, RASTER) \ + MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) \ + MCFG_SCREEN_RAW_PARAMS(_clock, CDP1861_SCREEN_WIDTH, CDP1861_HBLANK_END, CDP1861_HBLANK_START, CDP1861_TOTAL_SCANLINES, CDP1861_SCANLINE_VBLANK_END, CDP1861_SCANLINE_VBLANK_START) + + +#define CDP1861_INTERFACE(name) \ + const cdp1861_interface (name) = + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> cdp1861_interface + +struct cdp1861_interface +{ + const char *m_cpu_tag; + const char *m_screen_tag; + + devcb_write_line m_out_int_func; + devcb_write_line m_out_dmao_func; + devcb_write_line m_out_efx_func; +}; + + + +// ======================> cdp1861_device_config + +class cdp1861_device_config : public device_config, + public cdp1861_interface +{ + friend class cdp1861_device; + + // construction/destruction + cdp1861_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + +public: + // allocators + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + +protected: + // device_config overrides + virtual void device_config_complete(); +}; + + + +// ======================> cdp1861_device + +class cdp1861_device : public device_t +{ + friend class cdp1861_device_config; + + // construction/destruction + cdp1861_device(running_machine &_machine, const cdp1861_device_config &_config); + +public: + DECLARE_WRITE8_MEMBER( dma_w ); + DECLARE_WRITE_LINE_MEMBER( disp_on_w ); + DECLARE_WRITE_LINE_MEMBER( disp_off_w ); + + void update_screen(bitmap_t *bitmap, const rectangle *cliprect); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + +private: + static const device_timer_id TIMER_INT = 0; + static const device_timer_id TIMER_EFX = 1; + static const device_timer_id TIMER_DMA = 2; + + devcb_resolved_write_line m_out_int_func; + devcb_resolved_write_line m_out_dmao_func; + devcb_resolved_write_line m_out_efx_func; + + screen_device *m_screen; // screen + bitmap_t *m_bitmap; // bitmap + + int m_disp; // display enabled + int m_dispon; // display on latch + int m_dispoff; // display off latch + int m_dmaout; // DMA request active + + // timers + emu_timer *m_int_timer; // interrupt timer + emu_timer *m_efx_timer; // EFx timer + emu_timer *m_dma_timer; // DMA timer + + cpu_device *m_cpu; + + const cdp1861_device_config &m_config; +}; + + +// device type definition +extern const device_type CDP1861; + + + +#endif