diff options
Diffstat (limited to 'src/devices/video/h63484.cpp')
-rw-r--r-- | src/devices/video/h63484.cpp | 2190 |
1 files changed, 2190 insertions, 0 deletions
diff --git a/src/devices/video/h63484.cpp b/src/devices/video/h63484.cpp new file mode 100644 index 00000000000..906c01573e4 --- /dev/null +++ b/src/devices/video/h63484.cpp @@ -0,0 +1,2190 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese, Sandro Ronco +/*************************************************************************** + + HD63484 ACRTC (rewrite in progress) + + TODO: + - 8-bit support for FIFO, parameters and command values + - execution cycles; + +***************************************************************************/ + +#include "emu.h" +#include "h63484.h" + +#define LOG 0 +#define FIFO_LOG 0 +#define CMD_LOG 0 + +// default address map +static ADDRESS_MAP_START( h63484_vram, AS_0, 16, h63484_device ) +// AM_RANGE(0x00000, 0x7ffff) AM_RAM +// AM_RANGE(0x80000, 0xfffff) AM_NOP +ADDRESS_MAP_END + + +//------------------------------------------------- +// h63484_device - constructor +//------------------------------------------------- + +h63484_device::h63484_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, H63484, "HD63484 CRTC (rewrite)", tag, owner, clock, "h63484", __FILE__), + device_memory_interface(mconfig, *this), + device_video_interface(mconfig, *this), + m_ar(0), + m_sr(0), + m_fifo_ptr(-1), + m_fifo_r_ptr(-1), + m_cr(0), + m_param_ptr(0), + m_rwp_dn(0), + m_org_dpa(0), + m_org_dn(0), + m_org_dpd(0), + m_cl0(0), + m_cl1(0), + m_dcr(0), + m_space_config("videoram", ENDIANNESS_BIG, 16, 20, -1, NULL, *ADDRESS_MAP_NAME(h63484_vram)) +{ +} + +enum +{ + FIFO_READ = 0, + FIFO_WRITE +}; + +enum +{ + FIFO_EMPTY = -1, + FIFO_PARAMETER, + FIFO_COMMAND +}; + +#define H63484_SR_CER 0x80 // Command Error +#define H63484_SR_ARD 0x40 // Area Detect +#define H63484_SR_CED 0x20 // Command End +#define H63484_SR_LPD 0x10 // Light Pen Strobe Detect +#define H63484_SR_RFF 0x08 // Read FIFO Full +#define H63484_SR_RFR 0x04 // Read FIFO Ready +#define H63484_SR_WFR 0x02 // Write FIFO Ready +#define H63484_SR_WFE 0x01 // Write FIFO Empty + + +static const char *const acrtc_regnames[0x100/2] = +{ + "FIFO Entry", // 0x00 + "Command Control (CCR)", // 0x02 + "Operation Mode (OMR)", // 0x04 + "Display Control (DCR)", // 0x06 + "(Undefined)", // 0x08 + "(Undefined)", // 0x0a + "(Undefined)", // 0x0c + "(Undefined)", // 0x0e + "(Undefined)", // 0x10 + "(Undefined)", // 0x12 + "(Undefined)", // 0x14 + "(Undefined)", // 0x16 + "(Undefined)", // 0x18 + "(Undefined)", // 0x1a + "(Undefined)", // 0x1c + "(Undefined)", // 0x1e + "(Undefined)", // 0x20 + "(Undefined)", // 0x22 + "(Undefined)", // 0x24 + "(Undefined)", // 0x26 + "(Undefined)", // 0x28 + "(Undefined)", // 0x2a + "(Undefined)", // 0x2c + "(Undefined)", // 0x2e + "(Undefined)", // 0x30 + "(Undefined)", // 0x32 + "(Undefined)", // 0x34 + "(Undefined)", // 0x36 + "(Undefined)", // 0x38 + "(Undefined)", // 0x3a + "(Undefined)", // 0x3c + "(Undefined)", // 0x3e + "(Undefined)", // 0x40 + "(Undefined)", // 0x42 + "(Undefined)", // 0x44 + "(Undefined)", // 0x46 + "(Undefined)", // 0x48 + "(Undefined)", // 0x4a + "(Undefined)", // 0x4c + "(Undefined)", // 0x4e + "(Undefined)", // 0x50 + "(Undefined)", // 0x52 + "(Undefined)", // 0x54 + "(Undefined)", // 0x56 + "(Undefined)", // 0x58 + "(Undefined)", // 0x5a + "(Undefined)", // 0x5c + "(Undefined)", // 0x5e + "(Undefined)", // 0x60 + "(Undefined)", // 0x62 + "(Undefined)", // 0x64 + "(Undefined)", // 0x66 + "(Undefined)", // 0x68 + "(Undefined)", // 0x6a + "(Undefined)", // 0x6c + "(Undefined)", // 0x6e + "(Undefined)", // 0x70 + "(Undefined)", // 0x72 + "(Undefined)", // 0x74 + "(Undefined)", // 0x76 + "(Undefined)", // 0x78 + "(Undefined)", // 0x7a + "(Undefined)", // 0x7c + "(Undefined)", // 0x7e + "Raster Count (RCR)", // 0x80 + "Horizontal Sync (HSR)", // 0x82 + "Horizontal Display (HDR)", // 0x84 + "Vertical Sync (VSR)", // 0x86 + "Vertical Display (VDR)", // 0x88 + "Split Screen Width (SSW) 0x8a", // 0x8a + "Split Screen Width (SSW) 0x8c", // 0x8c + "Split Screen Width (SSW) 0x8e", // 0x8e + "Blink Control (BCR)", // 0x90 + "Horizontal Window Display (HWR)", // 0x92 + "Vertical Window Display (VWR) 0x94", // 0x94 + "Vertical Window Display (VWR) 0x96", // 0x96 + "Graphic Cursor (GCR0)", // 0x98 + "Graphic Cursor (GCR1)", // 0x9a + "Graphic Cursor (GCR2)", // 0x9c + "(Undefined)", // 0x9e + "(Undefined)", // 0xa0 + "(Undefined)", // 0xa2 + "(Undefined)", // 0xa4 + "(Undefined)", // 0xa6 + "(Undefined)", // 0xa8 + "(Undefined)", // 0xaa + "(Undefined)", // 0xac + "(Undefined)", // 0xae + "(Undefined)", // 0xb0 + "(Undefined)", // 0xb2 + "(Undefined)", // 0xb4 + "(Undefined)", // 0xb6 + "(Undefined)", // 0xb8 + "(Undefined)", // 0xba + "(Undefined)", // 0xbc + "(Undefined)", // 0xbe + // upper screen + "Raster Address 0 (RAR0)", // 0xc0 + "Memory Width 0 (MWR0)", // 0xc2 + "Start Address 0 (SAR0) 0xc4", // 0xc4 + "Start Address 0 (SAR0) 0xc6", // 0xc6 + // base screen + "Raster Address 1 (RAR1)", // 0xc8 + "Memory Width 1 (MWR1)", // 0xca + "Start Address 1 (SAR1) 0xcc", // 0xcc + "Start Address 1 (SAR1) 0xce", // 0xce + // lower screen + "Raster Address 2 (RAR2)", // 0xd0 + "Memory Width 2 (MWR2)", // 0xd2 + "Start Address 2 (SAR2) 0xd4", // 0xd4 + "Start Address 2 (SAR2) 0xd6", // 0xd6 + // window screen + "Raster Address 3 (RAR3)", // 0xd8 + "Memory Width 3 (MWR3)", // 0xda + "Start Address 3 (SAR3) 0xdc", // 0xdc + "Start Address 3 (SAR3) 0xde", // 0xde + // block cursor 1 + "Block Cursor 1 (BCUR1) 0xe0", + "Block Cursor 1 (BCUR1) 0xe2", + // block cursor 2 + "Block Cursor 2 (BCUR2) 0xe4", + "Block Cursor 2 (BCUR2) 0xe6", + "Cursor Definition (CDR)", + "Zoom Factor (ZFR)", + "Lightpen Address (LPAR) 0xec", + "Lightpen Address (LPAR) 0xee", + "(Undefined)", // 0xf0 + "(Undefined)", // 0xf2 + "(Undefined)", // 0xf4 + "(Undefined)", // 0xf6 + "(Undefined)", // 0xf8 + "(Undefined)", // 0xfa + "(Undefined)", // 0xfc + "(Undefined)" // 0xfe +}; + +static const char *const wpr_regnames[0x20] = +{ + "Color 0 (CL0)", + "Color 1 (CL1)", + "Color Comparison (COMP)", + "Edge Color (EDG)", + "Mask (MASK)", + "Pattern RAM Control (PRC) 0x05", + "Pattern RAM Control (PRC) 0x06", + "Pattern RAM Control (PRC) 0x07", + "Area Definition (ADR) 0x08", + "Area Definition (ADR) 0x09", + "Area Definition (ADR) 0x0a", + "Area Definition (ADR) 0x0b", + "Read Write Pointer (RWP) H", + "Read Write Pointer (RWP) L", + "(Undefined)", + "(Undefined)", + "Drawing Pointer (DP) H", + "Drawing Pointer (DP) L", + "Current Pointer (CP) H", + "Current Pointer (CP) L", + "(Undefined)", // 0x14 + "(Undefined)", + "(Undefined)", // 0x16 + "(Undefined)", + "(Undefined)", // 0x18 + "(Undefined)", + "(Undefined)", // 0x1a + "(Undefined)", + "(Undefined)", // 0x1c + "(Undefined)", + "(Undefined)", // 0x1e + "(Undefined)" +}; + +enum +{ + COMMAND_INVALID = -1, + COMMAND_ORG, + COMMAND_WPR, + COMMAND_RPR, + COMMAND_WPTN, + COMMAND_RPTN, + COMMAND_DRD, + COMMAND_DWT, + COMMAND_DMOD, + COMMAND_RD, + COMMAND_WT, + COMMAND_MOD, + COMMAND_CLR, + COMMAND_SCLR, + COMMAND_CPY, + COMMAND_SCPY, + COMMAND_AMOVE, + COMMAND_RMOVE, + COMMAND_ALINE, + COMMAND_RLINE, + COMMAND_ARCT, + COMMAND_RRCT, + COMMAND_APLL, + COMMAND_RPLL, + COMMAND_APLG, + COMMAND_RPLG, + COMMAND_CRCL, + COMMAND_ELPS, + COMMAND_AARC, + COMMAND_RARC, + COMMAND_AEARC, + COMMAND_REARC, + COMMAND_AFRCT, + COMMAND_RFRCT, + COMMAND_PAINT, + COMMAND_DOT, + COMMAND_PTN, + COMMAND_AGCPY, + COMMAND_RGCPY +}; + +#define H63484_COMMAND_ORG 0x0400 // p: 2 +#define H63484_COMMAND_WPR 0x0800 // & ~0x1f p: 1 +#define H63484_COMMAND_RPR 0x0c00 // & ~0x1f p: 0 +#define H63484_COMMAND_WPTN 0x1800 // & ~0xf p: 1 + n +#define H63484_COMMAND_RPTN 0x1c00 // & ~0xf p: 1 +#define H63484_COMMAND_DRD 0x2400 // p: 2 +#define H63484_COMMAND_DWT 0x2800 // p: 2 +#define H63484_COMMAND_DMOD 0x2c00 // & ~3 p: 2 +#define H63484_COMMAND_RD 0x4400 // p: 0 +#define H63484_COMMAND_WT 0x4800 // p: 1 +#define H63484_COMMAND_MOD 0x4c00 // & ~3 p: 1 +#define H63484_COMMAND_CLR 0x5800 // p: 3 +#define H63484_COMMAND_SCLR 0x5c00 // & ~3 p: 3 +#define H63484_COMMAND_CPY 0x6000 // & ~0x0f03 p: 4 +#define H63484_COMMAND_SCPY 0x7000 // & ~0x0f03 p: 4 +#define H63484_COMMAND_AMOVE 0x8000 // p: 2 +#define H63484_COMMAND_RMOVE 0x8400 // p: 2 +#define H63484_COMMAND_ALINE 0x8800 // & ~0x00ff p: 2 +#define H63484_COMMAND_RLINE 0x8c00 // & ~0x00ff p: 2 +#define H63484_COMMAND_ARCT 0x9000 // & ~0x00ff p: 2 +#define H63484_COMMAND_RRCT 0x9400 // & ~0x00ff p: 2 +#define H63484_COMMAND_APLL 0x9800 // & ~0x00ff p: 1 + n +#define H63484_COMMAND_RPLL 0x9c00 // & ~0x00ff p: 1 + n +#define H63484_COMMAND_APLG 0xa000 // & ~0x00ff p: 1 + n +#define H63484_COMMAND_RPLG 0xa400 // & ~0x00ff p: 1 + n +#define H63484_COMMAND_CRCL 0xa800 // & ~0x01ff p: 1 +#define H63484_COMMAND_ELPS 0xac00 // & ~0x01ff p: 3 +#define H63484_COMMAND_AARC 0xb000 // & ~0x01ff p: 4 +#define H63484_COMMAND_RARC 0xb400 // & ~0x01ff p: 4 +#define H63484_COMMAND_AEARC 0xb800 // & ~0x01ff p: 6 +#define H63484_COMMAND_REARC 0xbc00 // & ~0x01ff p: 6 +#define H63484_COMMAND_AFRCT 0xc000 // & ~0x00ff p: 2 +#define H63484_COMMAND_RFRCT 0xc400 // & ~0x00ff p: 2 +#define H63484_COMMAND_PAINT 0xc800 // & ~0x01ff p: 0 +#define H63484_COMMAND_DOT 0xcc00 // & ~0x00ff p: 0 +#define H63484_COMMAND_PTN 0xd000 // & ~0x0fff p: 1 +#define H63484_COMMAND_AGCPY 0xe000 // & ~0x0fff p: 4 +#define H63484_COMMAND_RGCPY 0xf000 // & ~0x0fff p: 4 + + +/*------------------------------------------------- + ROM( h63484 ) +-------------------------------------------------*/ + +// devices +const device_type H63484 = &device_creator<h63484_device>; + + +ROM_START( h63484 ) + ROM_REGION( 0x100, "h63484", 0 ) + ROM_LOAD( "h63484.bin", 0x000, 0x100, NO_DUMP ) /* internal control ROM */ +ROM_END + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +const address_space_config *h63484_device::memory_space_config(address_spacenum spacenum) const +{ + return (spacenum == AS_0) ? &m_space_config : NULL; +} + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *h63484_device::device_rom_region() const +{ + return ROM_NAME( h63484 ); +} + +//------------------------------------------------- +// readword - read a word at the given address +//------------------------------------------------- + +inline UINT16 h63484_device::readword(offs_t address) +{ + return space().read_word(address << 1); +} + + +//------------------------------------------------- +// writeword - write a word at the given address +//------------------------------------------------- + +inline void h63484_device::writeword(offs_t address, UINT16 data) +{ + space().write_word(address << 1, data); +} + + +inline void h63484_device::inc_ar(int value) +{ + if(m_ar & 0x80) + { + if (m_ar + value > 0xff) // TODO: what happens if it overflows? + logerror("HD63484 '%s': Address Register overflows 0x%02x\n", tag(), m_ar + value); + + m_ar = (m_ar + value) & 0xff; + } +} + +inline void h63484_device::fifo_w_clear() +{ + int i; + + for (i = 0; i < 16; i++) + m_fifo[i] = 0; + + m_fifo_ptr = -1; + + m_sr |= H63484_SR_WFR; + m_sr |= H63484_SR_WFE; +} + +inline void h63484_device::queue_w(UINT8 data) +{ + if (m_fifo_ptr < 15) + { + m_fifo_ptr++; + + m_fifo[m_fifo_ptr] = data; + + if (m_fifo_ptr == 16) + m_sr &= ~H63484_SR_WFR; + + m_sr &= ~H63484_SR_WFE; + } + else + { + // TODO what happen? somebody set us up the bomb + printf("FIFO?\n"); + } +} + +inline void h63484_device::dequeue_w(UINT8 *data) +{ + int i; + + *data = m_fifo[0]; + + if (m_fifo_ptr > -1) + { + for (i = 0; i < 15; i++) + m_fifo[i] = m_fifo[i + 1]; + + m_fifo[15] = 0; + + m_fifo_ptr--; + + m_sr |= H63484_SR_WFR; + + if (m_fifo_ptr == -1) + m_sr |= H63484_SR_WFE; + + } +} + +inline void h63484_device::fifo_r_clear() +{ + int i; + + for (i = 0; i < 16; i++) + m_fifo_r[i] = 0; + + m_fifo_r_ptr = -1; + + m_sr &= ~H63484_SR_RFR; + m_sr &= ~H63484_SR_RFF; +} + +inline void h63484_device::queue_r(UINT8 data) +{ + if (m_fifo_r_ptr < 15) + { + m_fifo_r_ptr++; + + m_fifo_r[m_fifo_r_ptr] = data; + + if (m_fifo_r_ptr == 16) + m_sr |= H63484_SR_RFF; + + m_sr |= H63484_SR_RFR; + } + else + { + // TODO what happen? somebody set us up the bomb + printf("FIFO?\n"); + } +} + +inline void h63484_device::dequeue_r(UINT8 *data) +{ + int i; + + *data = m_fifo_r[0]; + + if (m_fifo_r_ptr > -1) + { + for (i = 0; i < 15; i++) + m_fifo_r[i] = m_fifo_r[i + 1]; + + m_fifo_r[15] = 0; + + m_fifo_r_ptr--; + + m_sr &= ~H63484_SR_RFF; + + if (m_fifo_r_ptr == -1) + m_sr &= ~H63484_SR_RFR; + } +} + +//------------------------------------------------- +// recompute_parameters - +//------------------------------------------------- + +inline void h63484_device::recompute_parameters() +{ + if(m_hdw < 3 || m_hc == 0 || m_vc == 0) //bail out if screen params aren't valid + return; + + if (LOG) + { + printf("HC %d HSW %d HDS %d HDW %d HWS %d HWW %d\n",m_hc,m_hsw,m_hds,m_hdw,m_hws,m_hww); + printf("VC %d VDS %d VSW %d VWS %d VWW %d\n",m_vc,m_vds,m_vsw,m_vws,m_vww); + printf("SP0 %d SP1 %d SP2 %d\n",m_sp[0],m_sp[1],m_sp[2]); + } + + int gai = (m_omr>>4) & 0x07; + if (gai > 3) printf("unsupported GAI=%d\n", gai); + int acm = (m_omr & 0x08) ? 2 : 1; + int ppw = 16 / get_bpp(); + int ppmc = ppw * (1 << gai) / acm; // TODO: GAI > 3 + int vbstart = m_vds + m_sp[1]; + if (BIT(m_dcr, 13)) vbstart += m_sp[0]; + if (BIT(m_dcr, 11)) vbstart += m_sp[2]; + + rectangle visarea = m_screen->visible_area(); + visarea.set((m_hsw + m_hds) * ppmc, (m_hsw + m_hds + m_hdw) * ppmc - 1, m_vds, vbstart - 1); + attoseconds_t frame_period = m_screen->frame_period().attoseconds(); // TODO: use clock() to calculate the frame_period + m_screen->configure(m_hc * ppmc, m_vc, visarea, frame_period); +} + + +/***************************************************************************** + IMPLEMENTATION +*****************************************************************************/ + +int h63484_device::translate_command(UINT16 data) +{ + /* annoying switch-case sequence, but it's the only way to get invalid commands ... */ + switch (data) + { + case H63484_COMMAND_ORG: return COMMAND_ORG; + case H63484_COMMAND_DRD: return COMMAND_DRD; + case H63484_COMMAND_DWT: return COMMAND_DWT; + case H63484_COMMAND_RD: return COMMAND_RD; + case H63484_COMMAND_WT: return COMMAND_WT; + case H63484_COMMAND_CLR: return COMMAND_CLR; + case H63484_COMMAND_AMOVE: return COMMAND_AMOVE; + case H63484_COMMAND_RMOVE: return COMMAND_RMOVE; + } + + switch(data & ~0x3) + { + case H63484_COMMAND_DMOD: return COMMAND_DMOD; + case H63484_COMMAND_MOD: return COMMAND_MOD; + case H63484_COMMAND_SCLR: return COMMAND_SCLR; + } + + switch(data & ~0xf) + { + case H63484_COMMAND_WPTN: return COMMAND_WPTN; + case H63484_COMMAND_RPTN: return COMMAND_RPTN; + } + + switch(data & ~0x1f) + { + case H63484_COMMAND_WPR: return COMMAND_WPR; + case H63484_COMMAND_RPR: return COMMAND_RPR; + } + + switch(data & ~0x0f03) + { + case H63484_COMMAND_CPY: return COMMAND_CPY; + case H63484_COMMAND_SCPY: return COMMAND_SCPY; + } + + switch(data & ~0x00ff) + { + case H63484_COMMAND_ALINE: return COMMAND_ALINE; + case H63484_COMMAND_RLINE: return COMMAND_RLINE; + case H63484_COMMAND_ARCT: return COMMAND_ARCT; + case H63484_COMMAND_RRCT: return COMMAND_RRCT; + case H63484_COMMAND_APLL: return COMMAND_APLL; + case H63484_COMMAND_RPLL: return COMMAND_RPLL; + case H63484_COMMAND_APLG: return COMMAND_APLG; + case H63484_COMMAND_RPLG: return COMMAND_RPLG; + case H63484_COMMAND_AFRCT: return COMMAND_AFRCT; + case H63484_COMMAND_RFRCT: return COMMAND_RFRCT; + case H63484_COMMAND_DOT: return COMMAND_DOT; + } + + switch(data & ~0x01ff) + { + case H63484_COMMAND_CRCL: return COMMAND_CRCL; + case H63484_COMMAND_ELPS: return COMMAND_ELPS; + case H63484_COMMAND_AARC: return COMMAND_AARC; + case H63484_COMMAND_RARC: return COMMAND_RARC; + case H63484_COMMAND_AEARC: return COMMAND_AEARC; + case H63484_COMMAND_REARC: return COMMAND_REARC; + case H63484_COMMAND_PAINT: return COMMAND_PAINT; + } + + switch(data & ~0x0fff) + { + case H63484_COMMAND_PTN: return COMMAND_PTN; + case H63484_COMMAND_AGCPY: return COMMAND_AGCPY; + case H63484_COMMAND_RGCPY: return COMMAND_RGCPY; + } + + return COMMAND_INVALID; +} + +inline void h63484_device::command_end_seq() +{ + //h63484->param_ptr = 0; + m_sr |= H63484_SR_CED; + + /* TODO: we might need to be more aggressive and clear the params in there */ +} + +int h63484_device::get_bpp() +{ + int gbm = (m_ccr >> 8) & 0x07; + + if (gbm <= 4) + return 1 << gbm; + + //logerror ("Invalid Graphic Bit Mode (%d)\n", gbm); + return 1; +} + +void h63484_device::calc_offset(INT16 x, INT16 y, UINT32 &offset, UINT8 &bit_pos) +{ + int bpp = get_bpp(); + int ppw = 16 / bpp; + int gbm = (m_ccr >> 8) & 0x07; + x += (m_org_dpd >> gbm); + if (x >= 0) + { + offset = x / ppw; + bit_pos = x % ppw; + } + else + { + offset = x / ppw; + bit_pos= (-x) % ppw; + if (bit_pos != 0) + { + offset--; + bit_pos = ppw - bit_pos; + } + } + + offset += m_org_dpa - y * m_mwr[m_org_dn]; + bit_pos *= bpp; +} + +UINT16 h63484_device::get_dot(INT16 x, INT16 y) +{ + UINT8 bpp = get_bpp(); + UINT32 offset = 0; + UINT8 bit_pos = 0; + + calc_offset(x, y, offset, bit_pos); + + return (readword(offset) >> bit_pos) & ((1 << bpp) - 1); +} + +bool h63484_device::set_dot(INT16 x, INT16 y, INT16 px, INT16 py) +{ + int xs = m_pex - m_psx + 1; + int ys = m_pey - m_psy + 1; + int zx = m_pzx + 1; + int zy = m_pzy + 1; + int xp = m_psx + ((px % (xs * zx)) / zx); + int yp = m_psy + ((py % (ys * zy)) / zy); + + if (xp < m_psx) + xp = (m_pex + 1) - (m_psx - xp); + + if (yp < m_psy) + yp = (m_pey + 1) - (m_psy - yp); + + int pix = (m_pram[yp & 0x0f] >> (xp & 0x0f)) & 0x01; + + UINT8 col = (m_cr >> 3) & 0x03; + UINT8 bpp = get_bpp(); + UINT16 mask = (1 << bpp) - 1; + UINT16 xmask = (16 / bpp) - 1; + UINT16 cl0 = (m_cl0 >> ((x & xmask) * bpp)) & mask; + UINT16 cl1 = (m_cl1 >> ((x & xmask) * bpp)) & mask; + + switch (col) + { + case 0x00: + return set_dot(x, y, pix ? cl1 : cl0); + case 0x01: + if (pix) + return set_dot(x, y, cl1); + break; + case 0x02: + if (!pix) + return set_dot(x, y, cl0); + break; + case 0x03: + fatalerror("HD63484 color modes (Pattern RAM indirect)\n"); + // TODO + } + + return false; +} + +bool h63484_device::set_dot(INT16 x, INT16 y, UINT16 color) +{ + UINT8 bpp = get_bpp(); + UINT32 offset = 0; + UINT8 bit_pos = 0; + UINT8 opm = m_cr & 0x07; + UINT8 area = (m_cr >> 5) & 0x07; + + calc_offset(x, y, offset, bit_pos); + + UINT16 mask = ((1 << bpp) - 1) << bit_pos; + UINT16 color_shifted = (color << bit_pos) & mask; + + UINT16 data = readword(offset); + UINT16 res = data; + + switch (opm) + { + case 0: + res = (data & ~mask) | color_shifted; + break; + case 1: + res = (data & ~mask) | ((data & mask) | color_shifted); + break; + case 2: + res = (data & ~mask) | ((data & mask) & color_shifted); + break; + case 3: + res = (data & ~mask) | ((data & mask) ^ color_shifted); + break; + case 4: + if (get_dot(x, y) == ((m_ccmp & mask) >> bit_pos)) + res = (data & ~mask) | color_shifted; + break; + case 5: + if (get_dot(x, y) != ((m_ccmp & mask) >> bit_pos)) + res = (data & ~mask) | color_shifted; + break; + case 6: + if (get_dot(x, y) < ((m_cl0 & mask) >> bit_pos)) + res = (data & ~mask) | color_shifted; + break; + case 7: + if (get_dot(x, y) > ((m_cl1 & mask) >> bit_pos)) + res = (data & ~mask) | color_shifted; + break; + } + + writeword(offset, res); + + if (area) + logerror("HD63484 '%s': unsupported area detection %x (%d %d)\n", tag(), area, x, y); + + return false; // TODO: return area detection status +} + +void h63484_device::draw_line(INT16 sx, INT16 sy, INT16 ex, INT16 ey) +{ + UINT16 delta_x = abs(ex - sx) * 2; + UINT16 delta_y = abs(ey - sy) * 2; + int dir_x = (ex < sx) ? -1 : ((ex > sx) ? +1 : 0); + int dir_y = (ey < sy) ? -1 : ((ey > sy) ? +1 : 0); + int pram_pos = 0; + + if(delta_x > delta_y) + { + int delta = delta_y - delta_x / 2; + while(sx != ex) + { + set_dot(sx, sy, pram_pos, 0); + + if(delta >= 0) + { + sy += dir_y; + delta -= delta_x; + } + pram_pos++; + sx += dir_x; + delta += delta_y; + } + } + else + { + int delta = delta_x - delta_y / 2; + while(sy != ey) + { + set_dot(sx, sy, pram_pos, 0); + + if(delta >= 0) + { + sx += dir_x; + delta -= delta_y; + } + pram_pos++; + sy += dir_y; + delta += delta_x; + } + } +} + +void h63484_device::draw_ellipse(INT16 cx, INT16 cy, double dx, double dy, double s_angol, double e_angol, bool c) +{ + double inc = 1.0 / (MAX(dx, dy) * 100); + for (double angol = s_angol; fabs(angol - e_angol) >= inc*2; angol += inc * (c ? -1 : +1)) + { + if (angol > DEGREE_TO_RADIAN(360)) angol -= DEGREE_TO_RADIAN(360); + if (angol < DEGREE_TO_RADIAN(0)) angol += DEGREE_TO_RADIAN(360); + + double px = cos(angol) * dx; + double py = sin(angol) * dy; + set_dot(cx + round(px), cy + round(py), 0, 0); + } +} + +void h63484_device::paint(INT16 sx, INT16 sy) +{ +/* + This is not accurate since real hardware can only paint 4 'unpaintable' areas, + the other 'unpaintable' points are pushed into the read FIFO to be processed + later by the program, but currently is impossible suspend/resume the command + in case the read FIFO is full, so all 'unpaintable' areas are painted. + Also CP is not in the correct position after this command. +*/ + UINT8 e = BIT(m_cr, 8); + UINT8 bpp = get_bpp(); + UINT16 mask = (1 << bpp) - 1; + UINT16 xmask = (16 / bpp) - 1; + + for (int ydir=0; ydir<2; ydir++) + for(UINT16 y=0;y<0x7fff; y++) + { + bool limit = true; + bool unpaintable_up = false; + bool unpaintable_dn = false; + + for (int xdir=0; xdir<2; xdir++) + for(UINT16 x=0; x<0x7fff; x++) + { + INT16 px = sx + (xdir ? -x : x); + INT16 py = sy + (ydir ? -y : y); + + UINT16 dot = get_dot(px, py); + UINT16 edg = (m_edg >> (px & xmask) * bpp) & mask; + UINT16 cl0 = (m_cl0 >> (px & xmask) * bpp) & mask; + UINT16 cl1 = (m_cl1 >> (px & xmask) * bpp) & mask; + + if ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1) + break; + + if ((!ydir && !xdir && x && y) || (xdir && y) || (ydir && x) || (ydir && xdir)) + set_dot(px, py, px - m_cpx, py - m_cpy); + + dot = get_dot(px, py + 1); + if (unpaintable_up && !((e && dot == edg) && (!e && dot != edg) && dot != cl0 && dot != cl1)) + paint(px, py + 1); + else if (!unpaintable_up && ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1)) + unpaintable_up = true; + + dot = get_dot(px, py - 1); + if (unpaintable_dn && !((e && dot == edg) && (!e && dot != edg) && dot != cl0 && dot != cl1)) + paint(px, py - 1); + else if (!unpaintable_dn && ((e && dot != edg) || (!e && dot == edg) || dot == cl0 || dot == cl1)) + unpaintable_dn = true; + + limit = false; + } + if (limit) break; + } +} + +UINT16 h63484_device::command_rpr_exec() +{ + switch(m_cr & 0x1f) + { + case 0x00: // color 0 + return m_cl0; + case 0x01: // color 1 + return m_cl1; + case 0x02: // color comparison + return m_ccmp; + case 0x03: // edge color + return m_edg; + case 0x04: // mask + return m_mask; + case 0x05: // Pattern RAM Control 1 + return (m_ppy << 12) | (m_pzcy << 8) | (m_ppx << 4) | m_pzcx; + case 0x06: // Pattern RAM Control 2 + return (m_psy << 12) | (m_psx << 4); + case 0x07: // Pattern RAM Control 3 + return (m_pey << 12) | (m_pzy << 8) | (m_pex << 4) | m_pzx; + case 0x08: // Area Definition XMIN + return m_xmin; + case 0x09: // Area Definition YMIN + return m_ymin; + case 0x0a: // Area Definition XMAX + return m_xmax; + case 0x0b: // Area Definition YMAX + return m_ymax; + case 0x0c: // Read Write Pointer H + return (m_rwp_dn << 14) | ((m_rwp[m_rwp_dn] >> 12) & 0xff); + case 0x0d: // Read Write Pointer L + return (m_rwp[m_rwp_dn] & 0x0fff) << 4; + default: + if(LOG) printf("Read %sx\n", wpr_regnames[m_cr & 0x1f]); + return 0; + } +} + +void h63484_device::command_wpr_exec() +{ + switch(m_cr & 0x1f) + { + case 0x00: // color 0 + m_cl0 = m_pr[0]; + break; + case 0x01: // color 1 + m_cl1 = m_pr[0]; + break; + case 0x02: // color comparison + m_ccmp = m_pr[0]; + break; + case 0x03: // edge color + m_edg = m_pr[0]; + break; + case 0x04: // mask + m_mask = m_pr[0]; + break; + case 0x05: // Pattern RAM Control 1 + m_pzcx = (m_pr[0] >> 0) & 0x0f; + m_ppx = (m_pr[0] >> 4) & 0x0f; + m_pzcy = (m_pr[0] >> 8) & 0x0f; + m_ppy = (m_pr[0] >> 12) & 0x0f; + break; + case 0x06: // Pattern RAM Control 2 + m_psx = (m_pr[0] >> 4) & 0x0f; + m_psy = (m_pr[0] >> 12) & 0x0f; + break; + case 0x07: // Pattern RAM Control 3 + m_pzx = (m_pr[0] >> 0) & 0x0f; + m_pex = (m_pr[0] >> 4) & 0x0f; + m_pzy = (m_pr[0] >> 8) & 0x0f; + m_pey = (m_pr[0] >> 12) & 0x0f; + break; + case 0x08: // Area Definition XMIN + m_xmin = m_pr[0]; + break; + case 0x09: // Area Definition YMIN + m_ymin = m_pr[0]; + break; + case 0x0a: // Area Definition XMAX + m_xmax = m_pr[0]; + break; + case 0x0b: // Area Definition YMAX + m_ymax = m_pr[0]; + break; + case 0x0c: // Read Write Pointer H + m_rwp_dn = (m_pr[0] & 0xc000) >> 14; + m_rwp[m_rwp_dn] = (m_rwp[m_rwp_dn] & 0x00fff) | ((m_pr[0] & 0x00ff) << 12); + break; + case 0x0d: // Read Write Pointer L + m_rwp[m_rwp_dn] = (m_rwp[m_rwp_dn] & 0xff000) | ((m_pr[0] & 0xfff0) >> 4); + break; + default: + if(LOG) printf("%s -> %02x\n",wpr_regnames[m_cr & 0x1f],m_pr[0]); + break; + } +} + +void h63484_device::command_clr_exec() +{ + UINT8 mm = m_cr & 0x03; + UINT16 d = m_pr[0]; + INT16 ax = (INT16)m_pr[1]; + INT16 ay = (INT16)m_pr[2]; + + int d0_inc = (ax < 0) ? -1 : 1; + int d1_inc = (ay < 0) ? -1 : 1; + + for(INT16 d1=0; d1!=ay+d1_inc; d1+=d1_inc) + { + for(INT16 d0=0; d0!=ax+d0_inc; d0+=d0_inc) + { + UINT32 offset = m_rwp[m_rwp_dn] - d1 * m_mwr[m_rwp_dn] + d0; + UINT16 data = readword(offset); + UINT16 res = 0; + + if (BIT(m_cr, 10)) + { + switch(mm) + { + case 0: // replace + res = (data & ~m_mask) | (d & m_mask); + break; + case 1: // OR + res = (data & ~m_mask) | ((data | d) & m_mask); + break; + case 2: // AND + res = (data & ~m_mask) | ((data & d) & m_mask); + break; + case 3: // EOR + res = (data & ~m_mask) | ((data ^ d) & m_mask); + break; + } + } + else + res = d; + + writeword(offset, res); + } + } + + m_rwp[m_rwp_dn] -= (ay + d1_inc) * m_mwr[m_rwp_dn]; + m_rwp[m_rwp_dn] &= 0xfffff; +} + +void h63484_device::command_cpy_exec() +{ + UINT8 mm = m_cr & 0x03; + UINT8 dsd = (m_cr >> 8) & 0x07; + UINT8 s = BIT(m_cr, 11); + UINT32 SA = ((m_pr[0] & 0xff) << 12) | ((m_pr[1]&0xfff0) >> 4); + INT16 DX = (INT16)m_pr[s ? 3 : 2]; + INT16 DY = (INT16)m_pr[s ? 2 : 3]; + + int sd0_inc = (DX < 0) ? -1 : 1; + int sd1_inc = (DY < 0) ? -1 : 1; + int dd0_inc, dd1_inc; + if (dsd & 0x04) + { + dd0_inc = dsd & 0x01 ? -1 : +1; + dd1_inc = dsd & 0x02 ? -1 : +1; + } + else + { + dd0_inc = dsd & 0x02 ? -1 : +1; + dd1_inc = dsd & 0x01 ? -1 : +1; + } + + for(INT16 sd1=0, dd1=0; sd1!=DY+sd1_inc; sd1+=sd1_inc, dd1+=dd1_inc) + { + for(INT16 sd0=0, dd0=0; sd0!=DX+sd0_inc; sd0+=sd0_inc, dd0+=dd0_inc) + { + UINT32 src_offset, dst_offset; + + if (s) + src_offset = SA + sd1 - sd0 * m_mwr[m_rwp_dn]; + else + src_offset = SA + sd0 - sd1 * m_mwr[m_rwp_dn]; + + if (BIT(dsd, 2)) + dst_offset = m_rwp[m_rwp_dn] + dd1 - dd0 * m_mwr[m_rwp_dn]; + else + dst_offset = m_rwp[m_rwp_dn] + dd0 - dd1 * m_mwr[m_rwp_dn]; + + UINT16 src_data = readword(src_offset); + UINT16 dst_data = readword(dst_offset); + + if (BIT(m_cr, 12)) + { + switch(mm) + { + case 0: // replace + dst_data = (dst_data & ~m_mask) | (src_data & m_mask); + break; + case 1: // OR + dst_data = (dst_data & ~m_mask) | ((dst_data | src_data) & m_mask); + break; + case 2: // AND + dst_data = (dst_data & ~m_mask) | ((dst_data & src_data) & m_mask); + break; + case 3: // EOR + dst_data = (dst_data & ~m_mask) | ((dst_data ^ src_data) & m_mask); + break; + } + } + else + dst_data = src_data; + + writeword(dst_offset, dst_data); + } + } + + m_rwp[m_rwp_dn] += dsd & 0x04 ? (DY + dd1_inc) : (-(DY + dd1_inc) * m_mwr[m_rwp_dn]); + m_rwp[m_rwp_dn] &= 0xfffff; +} + +void h63484_device::command_line_exec() +{ + INT16 x = (INT16)m_pr[0]; + INT16 y = (INT16)m_pr[1]; + + if (BIT(m_cr, 10)) + { + x += m_cpx; + y += m_cpy; + } + + draw_line(m_cpx, m_cpy, x, y); + + m_cpx = x; + m_cpy = y; +} + +void h63484_device::command_rct_exec() +{ + INT16 dX = m_pr[0]; + INT16 dY = m_pr[1]; + + if (BIT(m_cr, 10)) // relative (RRCT) + { + dX += m_cpx; + dY += m_cpy; + } + + /* + 3<-2 + | ^ + v | + 0->1 + */ + + /* 0 -> 1 */ + draw_line(m_cpx, m_cpy, dX, m_cpy); + + /* 1 -> 2 */ + draw_line(dX, m_cpy, dX, dY); + + /* 2 -> 3 */ + draw_line(dX, dY, m_cpx, dY); + + /* 3 -> 4 */ + draw_line(m_cpx, dY, m_cpx, m_cpy); +} + +void h63484_device::command_gcpy_exec() +{ + UINT8 dsd = (m_cr >> 8) & 0x07; + UINT8 s = BIT(m_cr, 11); + INT16 Xs = (INT16)m_pr[0]; + INT16 Ys = (INT16)m_pr[1]; + INT16 DX = (INT16)m_pr[s ? 3 : 2]; + INT16 DY = (INT16)m_pr[s ? 2 : 3]; + + if (BIT(m_cr, 12)) // relative (RGCPY) + { + Xs += m_cpx; + Ys += m_cpy; + } + + int sd0_inc = (DX < 0) ? -1 : 1; + int sd1_inc = (DY < 0) ? -1 : 1; + int dd0_inc, dd1_inc; + if (dsd & 0x04) + { + dd0_inc = dsd & 0x01 ? -1 : +1; + dd1_inc = dsd & 0x02 ? -1 : +1; + } + else + { + dd0_inc = dsd & 0x02 ? -1 : +1; + dd1_inc = dsd & 0x01 ? -1 : +1; + } + + for(INT16 sd1=0, dd1=0; sd1!=DY+sd1_inc; sd1+=sd1_inc, dd1+=dd1_inc) + { + for(INT16 sd0=0, dd0=0; sd0!=DX+sd0_inc; sd0+=sd0_inc, dd0+=dd0_inc) + { + UINT16 color; + if (s) + color = get_dot(Xs + sd1, Ys + sd0); + else + color = get_dot(Xs + sd0, Ys + sd1); + + if (BIT(dsd, 2)) + set_dot(m_cpx + dd1, m_cpy + dd0, color); + else + set_dot(m_cpx + dd0, m_cpy + dd1, color); + } + } + + if (dsd & 0x04) + m_cpx += DY + dd1_inc; + else + m_cpy += DY + dd1_inc; + +} + +void h63484_device::command_frct_exec() +{ + INT16 X = (INT16)m_pr[0]; + INT16 Y = (INT16)m_pr[1]; + + if (!BIT(m_cr, 10)) + { + X -= m_cpx; + Y -= m_cpy; + } + + int d0_inc = (X < 0) ? -1 : 1; + int d1_inc = (Y < 0) ? -1 : 1; + + for(INT16 d1=0; d1!=Y+d1_inc; d1+=d1_inc) + { + for(INT16 d0=0; d0!=X+d0_inc; d0+=d0_inc) + set_dot(m_cpx + d0, m_cpy + d1, d0, d1); + } + + m_cpy += (Y + d1_inc); +} + +void h63484_device::command_ptn_exec() +{ + INT16 szx = ((m_pr[0] >> 0) & 0xff); + INT16 szy = ((m_pr[0] >> 8) & 0xff); + UINT8 sl_sd = (m_cr >> 8) & 0x0f; + INT16 px = 0; + INT16 py = 0; + + for(INT16 d1=0; d1!=szy+1; d1++) + { + switch (sl_sd) + { + case 0x00: px = 0; py = d1; break; + case 0x01: px = -d1; py = d1; break; + case 0x02: py = 0; px = -d1; break; + case 0x03: px = -d1; py = -d1; break; + case 0x04: px = 0; py = -d1; break; + case 0x05: px = d1; py = -d1; break; + case 0x06: py = 0; px = d1; break; + case 0x07: px = d1; py = d1; break; + case 0x08: px = d1; py = d1; break; + case 0x09: px = 0; py = d1; break; + case 0x0a: px = -d1; py = d1; break; + case 0x0b: px = -d1; py = 0; break; + case 0x0c: px = -d1; py = -d1; break; + case 0x0d: px = 0; py = -d1; break; + case 0x0e: px = +d1; py = -d1; break; + case 0x0f: px = +d1; py = 0; break; + } + + for(INT16 d0=0; d0!=szx+1; d0++) + { + set_dot(m_cpx + px, m_cpy + py, d0, d1); + + switch (sl_sd) + { + case 0x00: px++; break; + case 0x01: px++; py++; break; + case 0x02: py++; break; + case 0x03: px--; py++; break; + case 0x04: px--; break; + case 0x05: px--; py--; break; + case 0x06: py--; break; + case 0x07: px++; py--; break; + case 0x08: px++; break; + case 0x09: px++; py++; break; + case 0x0a: py++; break; + case 0x0b: px--; py++; break; + case 0x0c: px--; break; + case 0x0d: px--; py--; break; + case 0x0e: py--; break; + case 0x0f: px++; py--; break; + } + } + } + + switch (sl_sd) + { + case 0x00: m_cpy += (szy + 1); break; + case 0x01: m_cpx -= (szy + 1); m_cpy += (szy + 1); break; + case 0x02: m_cpx -= (szy + 1); break; + case 0x03: m_cpx -= (szy + 1); m_cpy -= (szy + 1); break; + case 0x04: m_cpy -= (szy + 1); break; + case 0x05: m_cpx += (szy + 1); m_cpy -= (szy + 1); break; + case 0x06: m_cpx += (szy + 1); break; + case 0x07: m_cpx += (szy + 1); m_cpy += (szy + 1); break; + case 0x08: m_cpx += (szy + 1); m_cpy += (szy + 1); break; + case 0x09: m_cpy += (szy + 1); break; + case 0x0a: m_cpx -= (szy + 1); m_cpy += (szy + 1); break; + case 0x0b: m_cpx -= (szy + 1); break; + case 0x0c: m_cpx -= (szy + 1); m_cpy -= (szy + 1); break; + case 0x0d: m_cpy -= (szy + 1); break; + case 0x0e: m_cpx += (szy + 1); m_cpy -= (szy + 1); break; + case 0x0f: m_cpx += (szy + 1); break; + } +} + +void h63484_device::command_plg_exec() +{ + int sx = m_cpx; + int sy = m_cpy; + int ex=0; + int ey=0; + + for (int i = 0; i < m_dn; i++) + { + if (BIT(m_cr, 10)) + { + ex = sx + (INT16)m_pr[1 + i * 2]; + ey = sy + (INT16)m_pr[1 + i * 2 + 1]; + } + else + { + ex = (INT16)m_pr[1 + i * 2]; + ey = (INT16)m_pr[1 + i * 2 + 1]; + } + + draw_line(sx, sy, ex, ey); + + sx = ex; + sy = ey; + } + + if (m_cr & 0x2000) + { + // APLG/RPLG + draw_line(sx, sy, m_cpx, m_cpy); + } + else + { + // APLL/RPLL + m_cpx = ex; + m_cpy = ey; + } +} + +void h63484_device::command_arc_exec() +{ + INT16 xc = (INT16)m_pr[0]; + INT16 yc = (INT16)m_pr[1]; + INT16 xe = (INT16)m_pr[2]; + INT16 ye = (INT16)m_pr[3]; + + if (BIT(m_cr, 10)) + { + xc += m_cpx; + yc += m_cpy; + xe += m_cpx; + ye += m_cpy; + } + + double r = sqrt(pow((double)(xc - m_cpx), 2) + pow((double)(yc - m_cpy), 2)); + double s_angol = atan2((double)(m_cpy - yc), (double)(m_cpx - xc)); + double e_angol = atan2((double)(ye - yc), (double)(xe - xc)); + if (s_angol < 0) s_angol += DEGREE_TO_RADIAN(360); + if (e_angol < 0) e_angol += DEGREE_TO_RADIAN(360); + + draw_ellipse(xc, yc, r, r, s_angol, e_angol, BIT(m_cr, 8)); + + m_cpx = xe; + m_cpy = ye; +} + +void h63484_device::command_earc_exec() +{ + UINT16 a = m_pr[0]; + UINT16 b = m_pr[1]; + INT16 xc = (INT16)m_pr[2]; + INT16 yc = (INT16)m_pr[3]; + INT16 xe = (INT16)m_pr[4]; + INT16 ye = (INT16)m_pr[5]; + + if (BIT(m_cr, 10)) + { + xc += m_cpx; + yc += m_cpy; + xe += m_cpx; + ye += m_cpy; + } + + double r = sqrt(pow((double)(xc - m_cpx), 2) / a + pow((double)(yc - m_cpy), 2) / b); + double dx = sqrt((double)a); + double dy = sqrt((double)b); + double s_angol = atan2((double)(m_cpy - yc) / dy, (double)(m_cpx - xc) / dx); + double e_angol = atan2((double)(ye - yc) / dy, (double)(xe - xc) / dx); + if (s_angol < 0) s_angol += DEGREE_TO_RADIAN(360); + if (e_angol < 0) e_angol += DEGREE_TO_RADIAN(360); + + draw_ellipse(xc, yc, r * dx, r * dy, s_angol, e_angol, BIT(m_cr, 8)); + + m_cpx = xe; + m_cpy = ye; +} + +void h63484_device::process_fifo() +{ + UINT8 data; + + dequeue_w(&data); + + if (m_sr & H63484_SR_CED) + { + m_cr = (data & 0xff) << 8; + dequeue_w(&data); + m_cr |= data & 0xff; + m_param_ptr = 0; + m_sr &= ~H63484_SR_CED; + } + else + { + m_pr[m_param_ptr] = (data & 0xff) << 8; + dequeue_w(&data); + m_pr[m_param_ptr] |= (data & 0xff); + m_param_ptr++; + } + + switch (translate_command(m_cr)) + { + case COMMAND_INVALID: + if (CMD_LOG) logerror("HD63484 '%s': <invalid %04x>\n", tag(), m_cr); + printf("H63484 '%s' Invalid Command Byte %02x\n", tag(), m_cr); + m_sr |= H63484_SR_CER; // command error + command_end_seq(); + break; + + case COMMAND_ORG: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': ORG 0x%04x, 0x%04x\n", tag(), m_pr[0], m_pr[1]); + m_org_dn = (m_pr[0] & 0xc000) >> 14; + m_org_dpa = ((m_pr[0] & 0xff) << 12) | ((m_pr[1] & 0xfff0) >> 4); + m_org_dpd = (m_pr[1] & 0xf); + m_cpx = m_cpy = 0; + command_end_seq(); + } + break; + + case COMMAND_WPR: // 0x0800 & ~0x1f + if (m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': WPR (%d) 0x%04x\n", tag(), m_cr & 0x1f, m_pr[0]); + command_wpr_exec(); + command_end_seq(); + } + break; + + case COMMAND_RPR: + if (m_param_ptr == 0) + { + if (CMD_LOG) logerror("HD63484 '%s': RPR (%d)\n", tag(), m_cr & 0x1f); + UINT16 data = command_rpr_exec(); + queue_r((data >> 8) & 0xff); + queue_r((data >> 0) & 0xff); + command_end_seq(); + } + break; + + case COMMAND_WPTN: + if(m_param_ptr == 1) + { + m_dn = m_pr[0]; // number of param words + + //if(m_dn > 0x10 || m_dn == 0) + // fatalerror("stop!\n"); + } + + if(m_param_ptr == (1 + m_dn)) + { + if (CMD_LOG) logerror("HD63484 '%s': WPTN (%d) %d", tag(), m_cr & 0x0f, m_pr[0]); + + int pra = m_cr & 0xf; + for(int i=0; i<m_dn; i++) + { + if (CMD_LOG) logerror(", 0x%04x", m_pr[1 + i]); + m_pram[(i + pra) & 0xf] = m_pr[1 + i]; + } + + if (CMD_LOG) logerror("\n"); + command_end_seq(); + } + break; + + case COMMAND_RPTN: + if(m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': RPTN (%d) %d\n", tag(), m_cr & 0x0f, m_pr[0]); + command_end_seq(); + fatalerror("HD63484 COMMAND_RPTN!\n"); + } + break; + + case COMMAND_DRD: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': DRD %d, %d\n", tag(), m_pr[0], m_pr[1]); + command_end_seq(); + fatalerror("HD63484 COMMAND_DRD!\n"); + } + break; + + case COMMAND_DWT: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': DWT %d, %d\n", tag(), m_pr[0], m_pr[1]); + command_end_seq(); + fatalerror("HD63484 COMMAND_DWT!\n"); + } + break; + + case COMMAND_DMOD: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': DMOD (%d) %d, %d\n", tag(), m_cr & 0x03, m_pr[0], m_pr[1]); + command_end_seq(); + fatalerror("HD63484 COMMAND_DMOD!\n"); + } + break; + + case COMMAND_RD: + if (m_param_ptr == 0) + { + if (CMD_LOG) logerror("HD63484 '%s': RD\n", tag()); + UINT16 data = readword(m_rwp[m_rwp_dn]); + queue_r((data >> 8) & 0xff); + queue_r((data >> 0) & 0xff); + m_rwp[m_rwp_dn]+=1; + m_rwp[m_rwp_dn]&=0xfffff; + command_end_seq(); + } + break; + + case COMMAND_WT: + if (m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': WT 0x%04x\n", tag(), m_pr[0]); + writeword(m_rwp[m_rwp_dn], m_pr[0]); + m_rwp[m_rwp_dn]+=1; + m_rwp[m_rwp_dn]&=0xfffff; + command_end_seq(); + } + break; + + case COMMAND_MOD: + if(m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': MOD (%d) 0x%04x\n", tag(), m_cr & 0x03, m_pr[0]); + UINT16 d = m_pr[0]; + UINT16 data = readword(m_rwp[m_rwp_dn]); + UINT16 res = 0; + + switch(m_cr & 0x03) + { + case 0: // replace + res = (data & ~m_mask) | (d & m_mask); + break; + case 1: // OR + res = (data & ~m_mask) | ((data | d) & m_mask); + break; + case 2: // AND + res = (data & ~m_mask) | ((data & d) & m_mask); + break; + case 3: // EOR + res = (data & ~m_mask) | ((data ^ d) & m_mask); + break; + } + + writeword(m_rwp[m_rwp_dn], res); + command_end_seq(); + } + break; + + case COMMAND_CLR: + case COMMAND_SCLR: + if (m_param_ptr == 3) + { + if (CMD_LOG) + { + if (BIT(m_cr, 10)) + logerror("HD63484 '%s': SCLR (%d) 0x%04x, %d, %d\n", tag(), m_cr & 0x03, m_pr[0], (INT16)m_pr[1], (INT16)m_pr[2]); + else + logerror("HD63484 '%s': CLR 0x%04x, %d, %d\n", tag(), m_pr[0], (INT16)m_pr[1], (INT16)m_pr[2]); + } + + command_clr_exec(); + command_end_seq(); + } + break; + + case COMMAND_CPY: + case COMMAND_SCPY: + if (m_param_ptr == 4) + { + if (CMD_LOG) + { + if (BIT(m_cr, 12)) + logerror("HD63484 '%s': SCPY (%d, %d, %d) 0x%x, 0x%x, %d, %d\n", tag(), BIT(m_cr, 11), (m_cr >> 8) & 0x07, m_cr & 0x07, m_pr[0] & 0xff, (m_pr[1]&0xfff0) >> 4, (INT16)m_pr[2], (INT16)m_pr[3]); + else + logerror("HD63484 '%s': CPY (%d, %d) 0x%x, 0x%x, %d, %d\n", tag(), BIT(m_cr, 11), (m_cr >> 8) & 0x07, m_pr[0] & 0xff, (m_pr[1]&0xfff0) >> 4, (INT16)m_pr[2], (INT16)m_pr[3]); + } + + command_cpy_exec(); + command_end_seq(); + } + break; + + case COMMAND_AMOVE: + case COMMAND_RMOVE: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': %cMOVE %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (INT16)m_pr[0], (INT16)m_pr[1]); + if (BIT(m_cr, 10)) + { + m_cpx += (INT16)m_pr[0]; + m_cpy += (INT16)m_pr[1]; + } + else + { + m_cpx = (INT16)m_pr[0]; + m_cpy = (INT16)m_pr[1]; + } + command_end_seq(); + } + break; + + case COMMAND_RRCT: + case COMMAND_ARCT: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': %cRTC (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (INT16)m_pr[0], (INT16)m_pr[1]); + command_rct_exec(); + command_end_seq(); + } + break; + + case COMMAND_RLINE: + case COMMAND_ALINE: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': %cLINE (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (INT16)m_pr[0], (INT16)m_pr[1]); + command_line_exec(); + command_end_seq(); + } + break; + + case COMMAND_APLG: + case COMMAND_RPLG: + case COMMAND_APLL: + case COMMAND_RPLL: + if(m_param_ptr == 1) + m_dn = m_pr[0]; // number of param words + + if(m_param_ptr == (1 + m_dn*2)) + { + if (CMD_LOG) + { + logerror("HD63484 '%s': %cPL%c (%d, %d, %d) %d", tag(), BIT(m_cr, 10) ? 'R' : 'A', m_cr & 0x2000 ? 'G' : 'L', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]); + for (int i=0; i<m_dn; i++) + logerror(", %d, %d", (INT16)m_pr[1 + i * 2], (INT16)m_pr[1 + i * 2 + 1]); + logerror("\n"); + } + + command_plg_exec(); + command_end_seq(); + } + break; + + case COMMAND_CRCL: + if(m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': CRCL (%d, %d, %d, %d) %d\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]); + UINT16 r = m_pr[0] & 0x1fff; + draw_ellipse(m_cpx, m_cpy, r, r, DEGREE_TO_RADIAN(0), DEGREE_TO_RADIAN(360), BIT(m_cr, 8)); + command_end_seq(); + } + break; + + case COMMAND_ELPS: + if(m_param_ptr == 3) + { + if (CMD_LOG) logerror("HD63484 '%s': ELPS (%d, %d, %d, %d) %d, %d, %d\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0], m_pr[1], m_pr[2]); + double dx = (double)m_pr[3]; + double dy = sqrt(pow(dx, 2) / ((double)m_pr[0] / m_pr[1])); + draw_ellipse(m_cpx, m_cpy, dx, dy, DEGREE_TO_RADIAN(0), DEGREE_TO_RADIAN(360), BIT(m_cr, 8)); + command_end_seq(); + } + break; + + case COMMAND_AARC: + case COMMAND_RARC: + if(m_param_ptr == 4) + { + if (CMD_LOG) logerror("HD63484 '%s': %cARC (%d, %d, %d, %d) %d, %d, %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (INT16)m_pr[0], (INT16)m_pr[1], (INT16)m_pr[2], (INT16)m_pr[3]); + command_arc_exec(); + command_end_seq(); + } + break; + + case COMMAND_AEARC: + case COMMAND_REARC: + if(m_param_ptr == 6) + { + if (CMD_LOG) logerror("HD63484 '%s': %cEARC (%d, %d, %d, %d) %d, %d, %d, %d, %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0], m_pr[1], m_pr[2], m_pr[3], m_pr[4], m_pr[5]); + command_earc_exec(); + command_end_seq(); + } + break; + + case COMMAND_AFRCT: + case COMMAND_RFRCT: + if (m_param_ptr == 2) + { + if (CMD_LOG) logerror("HD63484 '%s': %cFRCT (%d, %d, %d) %d, %d\n", tag(), BIT(m_cr, 10) ? 'R' : 'A', (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (INT16)m_pr[0], (INT16)m_pr[1]); + + command_frct_exec(); + command_end_seq(); + } + break; + + case COMMAND_PAINT: + if (m_param_ptr == 0) + { + if (CMD_LOG) logerror("HD63484 '%s': PAINT (%d, %d, %d, %d)\n", tag(), BIT(m_cr, 8), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07); + paint(m_cpx, m_cpy); + command_end_seq(); + } + break; + + case COMMAND_DOT: + if (m_param_ptr == 0) + { + if (CMD_LOG) logerror("HD63484 '%s': DOT (%d, %d, %d)\n", tag(), (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07); + set_dot(m_cpx, m_cpy, 0, 0); + command_end_seq(); + } + break; + + case COMMAND_PTN: + if (m_param_ptr == 1) + { + if (CMD_LOG) logerror("HD63484 '%s': PTN (%d, %d, %d, %d, %d) 0x%04x\n", tag(), (m_cr >> 11) & 0x01, (m_cr >> 8) & 0x07, (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, m_pr[0]); + command_ptn_exec(); + command_end_seq(); + } + break; + + case COMMAND_RGCPY: + case COMMAND_AGCPY: + if (m_param_ptr == 4) + { + if (CMD_LOG) logerror("HD63484 '%s': %cGCPY (%d, %d, %d, %d, %d) %d, %d, %d, %d\n", tag(), BIT(m_cr, 12) ? 'R' : 'A', (m_cr >> 11) & 0x01, (m_cr >> 8) & 0x07, (m_cr >> 5) & 0x07, (m_cr >> 3) & 0x03, (m_cr >> 0) & 0x07, (INT16)m_pr[0], (INT16)m_pr[1], (INT16)m_pr[2], (INT16)m_pr[3]); + + command_gcpy_exec(); + command_end_seq(); + } + break; + + default: + printf("%04x\n",m_cr); + fatalerror("stop!\n"); + } +} + +void h63484_device::exec_abort_sequence() +{ + fifo_w_clear(); + fifo_r_clear(); + m_sr = H63484_SR_WFR | H63484_SR_WFE | H63484_SR_CED; // hard-set to 0x23 +} + +UINT16 h63484_device::video_registers_r(int offset) +{ + UINT16 res = (m_vreg[offset] << 8) | (m_vreg[offset+1] & 0xff); + + switch(offset) + { + case 0x06: + res = m_dcr; + break; + + case 0x80: + res = m_screen->vpos() & 0xfff; // Raster Count + break; + + default: + if(LOG) printf("%s R\n",acrtc_regnames[m_ar/2]); + break; + } + + return res; +} + +void h63484_device::video_registers_w(int offset) +{ + UINT16 vreg_data; + + vreg_data = (m_vreg[offset]<<8)|(m_vreg[offset+1]&0xff); + + switch(offset) + { + case 0x00: // FIFO entry + queue_w((vreg_data & 0xff00) >> 8); + queue_w((vreg_data & 0x00ff) >> 0); + if(FIFO_LOG) printf("%s -> %04x\n",acrtc_regnames[m_ar/2],vreg_data); + process_fifo(); + break; + + case 0x02: // Command Entry + + if(vreg_data & 0x8000) // abort sequence (ABT) + exec_abort_sequence(); + + /* + x--- ---- ---- ---- ABorT + -x-- ---- ---- ---- PauSE + ... + ---- -xxx ---- ---- Graphic Bit Mode (bpp) + ---- ---- xxxx xxxx irq mask, directly correlated to sr + */ + m_ccr = vreg_data; + break; + + case 0x04: + m_omr = vreg_data; + break; + + case 0x06: + m_dcr = vreg_data; + recompute_parameters(); + break; + + case 0x82: // Horizontal Sync Register + m_hc = ((vreg_data & 0xff00) >> 8) + 1; + m_hsw = vreg_data & 0x1f; + recompute_parameters(); + break; + case 0x84: // Horizontal Display Register + m_hds = ((vreg_data & 0xff00) >> 8) + 1; + m_hdw = ((vreg_data & 0x00ff) >> 0) + 1; + recompute_parameters(); + break; + case 0x92: // Horizontal Window Register + m_hws = ((vreg_data & 0xff00) >> 8) + 1; + m_hww = ((vreg_data & 0x00ff) >> 0) + 1; + recompute_parameters(); + break; + + case 0x86: // Vertical Sync Register + m_vc = (vreg_data & 0xfff); + recompute_parameters(); + break; + case 0x88: // Vertical Display Register + m_vds = ((vreg_data & 0xff00) >> 8) + 1; + m_vsw = (vreg_data & 0x1f); + recompute_parameters(); + break; + case 0x8a: // Split Screen Width 1 + m_sp[1] = vreg_data & 0x0fff; + recompute_parameters(); + break; + case 0x8c: // Split Screen Width 0 + m_sp[0] = vreg_data & 0x0fff; + recompute_parameters(); + break; + case 0x8e: // Split Screen Width 2 + m_sp[2] = vreg_data & 0x0fff; + recompute_parameters(); + break; + case 0x94: // Vertical Window Register A + m_vws = (vreg_data & 0xfff) + 1; + recompute_parameters(); + break; + case 0x96: // Vertical Window Register B + m_vww = (vreg_data & 0xfff); + recompute_parameters(); + break; + + case 0xc2: // Memory Width Register + case 0xca: + case 0xd2: + case 0xda: + m_mwr[(offset & 0x18) >> 3] = vreg_data & 0xfff; // pitch + m_mwr_chr[(offset & 0x18) >> 3] = (vreg_data & 0x8000) >> 15; + break; + + case 0xc4: // Start Address Register + case 0xcc: + case 0xd4: + case 0xdc: + m_sar[(offset & 0x18) >> 3] = ((vreg_data & 0xf) << 16) | (m_sar[(offset & 0x18) >> 3] & 0xffff); + m_sda[(offset & 0x18) >> 3] = (vreg_data & 0x0f00) >> 8; + break; + + case 0xc6: // Start Address Register + case 0xce: + case 0xd6: + case 0xde: + m_sar[(offset & 0x18) >> 3] = (vreg_data & 0xffff) | (m_sar[(offset & 0x18) >> 3] & 0xf0000); + break; + + default: + if(LOG) printf("%s -> %04x\n",acrtc_regnames[m_ar/2],vreg_data); + break; + } +} + +READ16_MEMBER( h63484_device::status_r ) +{ + return m_sr; +} + +READ16_MEMBER( h63484_device::data_r ) +{ + UINT16 res = 0xffff; + + if(m_ar == 0) // FIFO read + { + UINT8 data; + + dequeue_r(&data); + res = (data & 0xff) << 8; + dequeue_r(&data); + res |= data & 0xff; + } + else + res = video_registers_r(m_ar); + + inc_ar(2); + + return res; +} + +WRITE16_MEMBER( h63484_device::address_w ) +{ + if(ACCESSING_BITS_0_7) + m_ar = data & 0xfe; +} + +WRITE16_MEMBER( h63484_device::data_w ) +{ + if(ACCESSING_BITS_8_15) + m_vreg[m_ar] = (data & 0xff00) >> 8; + + if(ACCESSING_BITS_0_7) + m_vreg[m_ar+1] = (data & 0xff); + + video_registers_w(m_ar); + + inc_ar(2); +} + +READ8_MEMBER( h63484_device::status_r ) +{ + return m_sr; +} + +WRITE8_MEMBER( h63484_device::address_w ) +{ + m_ar = data; +} + +READ8_MEMBER( h63484_device::data_r ) +{ + UINT8 res = 0xff; + + if(m_ar < 2) // FIFO read + dequeue_r(&res); + else + res = video_registers_r(m_ar & 0xfe) >> (m_ar & 1 ? 0 : 8); + + inc_ar(1); + + return res; +} + +WRITE8_MEMBER( h63484_device::data_w ) +{ + m_vreg[m_ar] = data; + + if(m_ar < 2) // FIFO write + { + queue_w(data); + if (m_ar & 1) + process_fifo(); + + m_ar ^= 1; + } + else + video_registers_w(m_ar & 0xfe); + + inc_ar(1); +} + +void h63484_device::device_start() +{ + m_display_cb.bind_relative_to(*owner()); + + register_save_state(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void h63484_device::device_reset() +{ + m_sr = H63484_SR_CED | H63484_SR_WFR | H63484_SR_WFE; + m_ccr = m_omr = m_edg = m_dcr = m_hsw = 0; + m_hc = m_hds = m_hdw = m_hws = m_hww = 0; + m_vc = m_vws = m_vww = m_vds = m_vsw = 0; + m_sp[0] = m_sp[1] = m_sp[2] = 0; + m_ppx = m_ppy = 0; + m_cl0 = m_cl1 = 0; + m_xmin = m_ymin = m_xmax = m_ymax = 0; + m_ppx = m_pzcx = m_psx = m_pzx = m_pex = 0; + m_ppy = m_pzcy= m_psy = m_pzy = m_pey = 0; + m_ar = m_cr = 0; + m_param_ptr = 0; + m_rwp_dn = 0; + m_org_dpa = 0; + m_org_dn = 0; + m_org_dpd = 0; + m_ccmp = 0; + m_mask = -1; + m_cpx = m_cpy = 0; + m_dn = 0; + + memset(m_vreg, 0, sizeof(m_vreg)); + memset(m_fifo, 0, sizeof(m_fifo)); + memset(m_fifo_r, 0, sizeof(m_fifo_r)); + memset(m_pr, 0, sizeof(m_pr)); + memset(m_rwp, 0, sizeof(m_rwp)); + memset(m_mwr, 0, sizeof(m_mwr)); + memset(m_mwr_chr, 0, sizeof(m_mwr_chr)); + memset(m_sar, 0, sizeof(m_sar)); + memset(m_sda, 0, sizeof(m_sda)); + memset(m_pram, 0, sizeof(m_pram)); +} + +//------------------------------------------------- +// draw_graphics_line - +//------------------------------------------------- + +void h63484_device::draw_graphics_line(bitmap_ind16 &bitmap, const rectangle &cliprect, int vs, int y, int layer_n, bool active, bool ins_window) +{ + int bpp = get_bpp(); + int ppw = 16 / bpp; + UINT32 mask = (1 << bpp) - 1; + UINT32 base_offs = m_sar[layer_n] + (y - vs) * m_mwr[layer_n]; + UINT32 wind_offs = m_sar[3] + (y - m_vws) * m_mwr[3]; + int step = (m_omr & 0x08) ? 2 : 1; + int gai = (m_omr>>4) & 0x07; + int ppmc = ppw * (1 << gai) / step; // TODO: GAI > 3 + int ws = m_hsw + m_hws; + + if (m_omr & 0x08) + { + /* + According to the datasheet, in interleaved and superimposed modes: + - HDW and HWW must be even + - the relation between HDS and HWS must be even/even or odd/odd + */ + + if (m_hww & 1) + ws += step; + + if ((m_hws & 1) ^ (m_hds & 1)) + wind_offs++; + } + + for(int x=cliprect.min_x; x<=cliprect.max_x; x+=ppw) + { + UINT16 data = 0; + if (ins_window && x >= ws * ppmc && x < (ws + m_hww) * ppmc) + { + data = readword(wind_offs); + wind_offs++; + } + else if (active) + data = readword(base_offs); + + for (int b=0; b<ppw; b++) + { + int px = x + b; + if (!m_display_cb.isnull()) + m_display_cb(bitmap, cliprect, y, px, data & mask); + else if (cliprect.contains(px, y)) + bitmap.pix16(y, px) = data & mask; + + data >>= bpp; + } + + base_offs++; + } +} + +//------------------------------------------------- +// update_screen - +//------------------------------------------------- + +UINT32 h63484_device::update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + int l0 = cliprect.min_y + (BIT(m_dcr, 13) ? m_sp[0] : 0); + int l1 = l0 + m_sp[1]; + int l2 = l1 + (BIT(m_dcr, 11) ? m_sp[2] : 0); + + if(m_omr & 0x4000) + { + for(int y=cliprect.min_y; y<=cliprect.max_y; y++) + { + bool ins_window = BIT(m_dcr, 9) && y >= m_vws && y < m_vws+m_vww; + + if (BIT(m_dcr, 13) && y >= cliprect.min_y && y < l0) + draw_graphics_line(bitmap, cliprect, cliprect.min_y, y, 0, BIT(m_dcr, 12), ins_window); + else if (y >= l0 && y < l1) + draw_graphics_line(bitmap, cliprect, l0, y, 1, BIT(m_dcr, 14), ins_window); + else if (BIT(m_dcr, 11) && y >= l1 && y < l2) + draw_graphics_line(bitmap, cliprect, l1, y, 2, BIT(m_dcr, 10), ins_window); + } + } + return 0; +} + +void h63484_device::register_save_state() +{ + save_item(NAME(m_ar)); + save_item(NAME(m_vreg)); + save_item(NAME(m_sr)); + save_item(NAME(m_fifo)); + save_item(NAME(m_fifo_ptr)); + save_item(NAME(m_fifo_r)); + save_item(NAME(m_fifo_r_ptr)); + save_item(NAME(m_cr)); + save_item(NAME(m_pr)); + save_item(NAME(m_param_ptr)); + save_item(NAME(m_rwp)); + save_item(NAME(m_rwp_dn)); + save_item(NAME(m_org_dpa)); + save_item(NAME(m_org_dn)); + save_item(NAME(m_org_dpd)); + save_item(NAME(m_cl0)); + save_item(NAME(m_cl1)); + save_item(NAME(m_ccmp)); + save_item(NAME(m_mask)); + save_item(NAME(m_cpx)); + save_item(NAME(m_cpy)); + save_item(NAME(m_mwr)); + save_item(NAME(m_mwr_chr)); + save_item(NAME(m_sar)); + save_item(NAME(m_sda)); + save_item(NAME(m_pram)); + save_item(NAME(m_dn)); + save_item(NAME(m_ccr)); + save_item(NAME(m_omr)); + save_item(NAME(m_edg)); + save_item(NAME(m_dcr)); + save_item(NAME(m_hc)); + save_item(NAME(m_hds)); + save_item(NAME(m_hdw)); + save_item(NAME(m_hws)); + save_item(NAME(m_hww)); + save_item(NAME(m_sp)); + save_item(NAME(m_hsw)); + save_item(NAME(m_vc)); + save_item(NAME(m_vws)); + save_item(NAME(m_vww)); + save_item(NAME(m_vds)); + save_item(NAME(m_vsw)); + save_item(NAME(m_ppy)); + save_item(NAME(m_pzcy)); + save_item(NAME(m_ppx)); + save_item(NAME(m_pzcx)); + save_item(NAME(m_psx)); + save_item(NAME(m_pex)); + save_item(NAME(m_pzx)); + save_item(NAME(m_psy)); + save_item(NAME(m_pzy)); + save_item(NAME(m_pey)); + save_item(NAME(m_xmin)); + save_item(NAME(m_ymin)); + save_item(NAME(m_xmax)); + save_item(NAME(m_ymax)); +} |