// license:BSD-3-Clause // copyright-holders:Curt Coder /********************************************************************** Luxor ABC 1600 Mover emulation **********************************************************************/ #include "emu.h" #include "includes/abc1600.h" #include "abc1600.lh" #include "render.h" //************************************************************************** // CONSTANTS / MACROS //************************************************************************** #define LOG 0 #define SY6845E_TAG "sy6845e" // video RAM #define VIDEORAM_SIZE 0x40000 #define VIDEORAM16_MASK 0x3ffff #define VIDEORAM8_MASK 0x7fffe // flag register #define L_P BIT(m_flag, 0) #define BLANK BIT(m_flag, 1) #define PIX_POL BIT(m_flag, 2) #define FRAME_POL BIT(m_flag, 3) #define HOLD_FY BIT(m_flag, 4) #define HOLD_FX BIT(m_flag, 5) #define COMP_MOVE BIT(m_flag, 6) #define REPLACE BIT(m_flag, 7) //************************************************************************** // DEVICE DEFINITIONS //************************************************************************** DEFINE_DEVICE_TYPE(ABC1600_MOVER, abc1600_mover_device, "abc1600mover", "ABC 1600 Mover") void abc1600_mover_device::vram_map(address_map &map) { map(0x00000, 0x7ffff).rw(this, FUNC(abc1600_mover_device::video_ram_r), FUNC(abc1600_mover_device::video_ram_w)); } void abc1600_mover_device::crtc_map(address_map &map) { map(0x00, 0x00).mirror(0xfe).rw(SY6845E_TAG, FUNC(mc6845_device::status_r), FUNC(mc6845_device::address_w)); map(0x01, 0x01).mirror(0xfe).rw(SY6845E_TAG, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); } void abc1600_mover_device::iowr0_map(address_map &map) { map(0x00, 0x00).mirror(0xff).r(this, FUNC(abc1600_mover_device::iord0_r)); map(0x00, 0x00).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldsx_hb_w)); map(0x01, 0x01).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldsx_lb_w)); map(0x02, 0x02).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldsy_hb_w)); map(0x03, 0x03).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldsy_lb_w)); map(0x04, 0x04).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldtx_hb_w)); map(0x05, 0x05).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldtx_lb_w)); map(0x06, 0x06).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldty_hb_w)); map(0x07, 0x07).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldty_lb_w)); } void abc1600_mover_device::iowr1_map(address_map &map) { map(0x00, 0x00).mirror(0xff).nopr(); map(0x00, 0x00).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldfx_hb_w)); map(0x01, 0x01).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldfx_lb_w)); map(0x02, 0x02).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldfy_hb_w)); map(0x03, 0x03).mirror(0xf8).w(this, FUNC(abc1600_mover_device::ldfy_lb_w)); map(0x05, 0x05).mirror(0xf8).w(this, FUNC(abc1600_mover_device::wrml_w)); map(0x07, 0x07).mirror(0xf8).w(this, FUNC(abc1600_mover_device::wrdl_w)); } void abc1600_mover_device::iowr2_map(address_map &map) { map(0x00, 0x00).mirror(0xff).nopr(); map(0x00, 0x00).mirror(0xf8).w(this, FUNC(abc1600_mover_device::wrmask_strobe_hb_w)); map(0x01, 0x01).mirror(0xf8).w(this, FUNC(abc1600_mover_device::wrmask_strobe_lb_w)); map(0x02, 0x02).mirror(0xf8).w(this, FUNC(abc1600_mover_device::enable_clocks_w)); map(0x03, 0x03).mirror(0xf8).w(this, FUNC(abc1600_mover_device::flag_strobe_w)); map(0x04, 0x04).mirror(0xf8).w(this, FUNC(abc1600_mover_device::endisp_w)); } void abc1600_mover_device::mover_map(address_map &map) { map(0x00000, 0x3ffff).ram(); } //------------------------------------------------- // ROM( abc1600_mover ) //------------------------------------------------- ROM_START( abc1600_mover ) ROM_REGION16_BE( 0x2000, "wrmsk", 0 ) ROM_LOAD16_BYTE( "wrmskl 6490362-01.1g", 0x0001, 0x1000, CRC(bc737538) SHA1(80e2c3757eb7f713018808d6e41ebef612425028) ) ROM_LOAD16_BYTE( "wrmskh 6490363-01.1j", 0x0000, 0x1000, CRC(6b7c9f0b) SHA1(7155a993adcf08a5a8a2f22becf9fd66fda698be) ) ROM_REGION( 0x200, "shinf", 0 ) ROM_LOAD( "shinf 6490361-01.1f", 0x000, 0x200, CRC(20260f8f) SHA1(29bf49c64e7cc7592e88cde2768ac57c7ce5e085) ) ROM_REGION16_BE( 0x40, "drmsk", 0 ) ROM_LOAD16_BYTE( "drmskl 6490359-01.1k", 0x01, 0x20, CRC(6e71087c) SHA1(0acf67700d6227f4b315cf8fb0fb31c0e7fb9496) ) ROM_LOAD16_BYTE( "drmskh 6490358-01.1l", 0x00, 0x20, CRC(a4a9a9dc) SHA1(d8575c0335d6021cbb5f7bcd298b41c35294a80a) ) ROM_REGION( 0x104, "plds", 0 ) ROM_LOAD( "drmsk 6490360-01.1m", 0x000, 0x104, CRC(5f7143c1) SHA1(1129917845f8e505998b15288f02bf907487e4ac) ) // PAL16L8 mover word mixer @ 1m,1n,1t,2t ROM_END //------------------------------------------------- // rom_region - device-specific ROM region //------------------------------------------------- const tiny_rom_entry *abc1600_mover_device::device_rom_region() const { return ROM_NAME( abc1600_mover ); } //------------------------------------------------- // mc6845 //------------------------------------------------- inline uint16_t abc1600_mover_device::get_crtca(uint16_t ma, uint8_t ra, uint8_t column) { /* bit description CRTCA0 0 CRTCA1 0 CRTCA2 CC1/MA1 CRTCA3 CC2/MA2 CRTCA4 CC3/MA3 CRTCA5 CC4/MA4 CRTCA6 RA0 CRTCA7 RA1 CRTCA8 RA2 CRTCA9 RA3 CRTCA10 CR0/MA8 CRTCA11 CR1/MA9 CRTCA12 CR2/MA10 CRTCA13 CR3/MA11 CRTCA14 CR4/MA12 CRTCA15 CR5/MA13 */ uint8_t cc = (ma & 0xff) + column; uint8_t cr = ma >> 8; return (cr << 10) | ((ra & 0x0f) << 6) | ((cc << 1) & 0x3c); } MC6845_UPDATE_ROW(abc1600_mover_device::crtc_update_row) { int x = 0; const pen_t *pen = m_palette->pens(); for (int column = 0; column < x_count; column += 2) { uint16_t dma = get_crtca(ma, ra, column); // data is read out of video RAM in nibble mode by strobing CAS 4 times for (int cas = 0; cas < 4; cas++) { uint16_t data = read_videoram(dma + cas); for (int bit = 0; bit < 16; bit++) { int color = ((BIT(data, 15) ^ PIX_POL) && !BLANK) && de; bitmap.pix32(vbp + y, hbp + x++) = pen[color]; data <<= 1; } } } } MC6845_ON_UPDATE_ADDR_CHANGED( abc1600_mover_device::crtc_update ) { } //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- MACHINE_CONFIG_START(abc1600_mover_device::device_add_mconfig) MCFG_DEFAULT_LAYOUT(layout_abc1600) MCFG_SCREEN_ADD_MONOCHROME(SCREEN_TAG, RASTER, rgb_t::green()) MCFG_SCREEN_UPDATE_DRIVER(abc1600_mover_device, screen_update) MCFG_SCREEN_RAW_PARAMS(XTAL(64'000'000), 0x3e0, 0, 0x300, 0x433, 0, 0x400) MCFG_PALETTE_ADD_MONOCHROME("palette") MCFG_MC6845_ADD(SY6845E_TAG, SY6845E, SCREEN_TAG, XTAL(64'000'000)/32) MCFG_MC6845_SHOW_BORDER_AREA(true) MCFG_MC6845_CHAR_WIDTH(32) MCFG_MC6845_UPDATE_ROW_CB(abc1600_mover_device, crtc_update_row) MCFG_MC6845_ADDR_CHANGED_CB(abc1600_mover_device, crtc_update) MACHINE_CONFIG_END //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- // abc1600_mover_device - constructor //------------------------------------------------- abc1600_mover_device::abc1600_mover_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, ABC1600_MOVER, tag, owner, clock), device_memory_interface(mconfig, *this), m_space_config("vram", ENDIANNESS_BIG, 16, 18, -1, address_map_constructor(FUNC(abc1600_mover_device::mover_map), this)), m_crtc(*this, SY6845E_TAG), m_palette(*this, "palette"), m_wrmsk_rom(*this, "wrmsk"), m_shinf_rom(*this, "shinf"), m_drmsk_rom(*this, "drmsk") { } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void abc1600_mover_device::device_start() { // state saving save_item(NAME(m_endisp)); save_item(NAME(m_clocks_disabled)); save_item(NAME(m_gmdi)); save_item(NAME(m_wrm)); save_item(NAME(m_ms)); save_item(NAME(m_ds)); save_item(NAME(m_flag)); save_item(NAME(m_xsize)); save_item(NAME(m_ysize)); save_item(NAME(m_udx)); save_item(NAME(m_udy)); save_item(NAME(m_xfrom)); save_item(NAME(m_xto)); save_item(NAME(m_yto)); save_item(NAME(m_ty)); save_item(NAME(m_mfa)); save_item(NAME(m_mta)); save_item(NAME(m_sh)); save_item(NAME(m_mdor)); save_item(NAME(m_hold_1w_cyk)); save_item(NAME(m_wrms0)); save_item(NAME(m_wrms1)); save_item(NAME(m_rmc)); save_item(NAME(m_cmc)); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void abc1600_mover_device::device_reset() { // disable display m_clocks_disabled = 1; m_endisp = 0; } //------------------------------------------------- // memory_space_config - return a description of // any address spaces owned by this device //------------------------------------------------- device_memory_interface::space_config_vector abc1600_mover_device::memory_space_config() const { return space_config_vector { std::make_pair(0, &m_space_config) }; } //------------------------------------------------- // read_videoram - //------------------------------------------------- inline uint16_t abc1600_mover_device::read_videoram(offs_t offset) { return space().read_word((offset & VIDEORAM16_MASK) << 1); } //------------------------------------------------- // write_videoram - //------------------------------------------------- inline void abc1600_mover_device::write_videoram(offs_t offset, uint16_t data, uint16_t mask) { uint16_t old_data = read_videoram(offset); space().write_word((offset & VIDEORAM16_MASK) << 1, (data & mask) | (old_data & (mask ^ 0xffff))); } //------------------------------------------------- // video_ram_r - //------------------------------------------------- READ8_MEMBER( abc1600_mover_device::video_ram_r ) { offs_t addr = (offset & VIDEORAM8_MASK) >> 1; uint8_t data = 0; if (offset & 0x01) { data = read_videoram(addr) & 0xff; } else { data = read_videoram(addr) >> 8; } return data; } //------------------------------------------------- // video_ram_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::video_ram_w ) { offs_t addr = (offset & VIDEORAM8_MASK) >> 1; if (offset & 0x01) { if (REPLACE) { // WRPORT_LB m_wrm = (m_wrm & 0xff00) | data; if (LOG) logerror("WRM LB %02x -> %04x\n", data, m_wrm); } else { // DATAPORT_LB m_gmdi = (m_gmdi & 0xff00) | data; if (LOG) logerror("GMDI LB %02x -> %04x\n", data, m_gmdi); } write_videoram(addr, m_gmdi, m_wrm & 0x00ff); if (LOG) logerror("Video RAM write LB to %05x : %04x\n", addr, read_videoram(addr)); } else { if (REPLACE) { // WRPORT_HB m_wrm = (data << 8) | (m_wrm & 0xff); if (LOG) logerror("WRM HB %02x -> %04x\n", data, m_wrm); } else { // DATAPORT_HB m_gmdi = (data << 8) | (m_gmdi & 0xff); if (LOG) logerror("GMDI HB %02x -> %04x\n", data, m_gmdi); } write_videoram(addr, m_gmdi, m_wrm & 0xff00); if (LOG) logerror("Video RAM write HB to %05x : %04x\n", addr, read_videoram(addr)); } } //------------------------------------------------- // iord0_r - //------------------------------------------------- READ8_MEMBER( abc1600_mover_device::iord0_r ) { /* bit description 0 0 1 SCREENPOS 2 3 4 5 6 VSYNC 7 BUSY */ uint8_t data = 0; // monitor orientation (portrait/landscape) data |= machine().render().first_target()->view() << 1; // vertical sync data |= m_crtc->vsync_r() << 6; return data; } //------------------------------------------------- // ldsx_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldsx_hb_w ) { /* bit description 0 XSIZE8 1 XSIZE9 2 U/D* Y 3 U/D* X 4 5 6 7 */ if (LOG) logerror("%s LDSX HB: %02x\n", machine().describe_context(), data); m_xsize = ((data & 0x03) << 8) | (m_xsize & 0xff); m_udy = BIT(data, 2); m_udx = BIT(data, 3); } //------------------------------------------------- // ldsx_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldsx_lb_w ) { /* bit description 0 XSIZE0 1 XSIZE1 2 XSIZE2 3 XSIZE3 4 XSIZE4 5 XSIZE5 6 XSIZE6 7 XSIZE7 */ if (LOG) logerror("%s LDSX LB: %02x\n", machine().describe_context(), data); m_xsize = (m_xsize & 0x300) | data; } //------------------------------------------------- // ldsy_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldsy_hb_w ) { /* bit description 0 YSIZE8 1 YSIZE9 2 YSIZE10 3 YSIZE11 4 5 6 7 */ if (LOG) logerror("%s LDSY HB: %02x\n", machine().describe_context(), data); m_ysize = ((data & 0x0f) << 8) | (m_ysize & 0xff); } //------------------------------------------------- // ldsy_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldsy_lb_w ) { /* bit description 0 YSIZE0 1 YSIZE1 2 YSIZE2 3 YSIZE3 4 YSIZE4 5 YSIZE5 6 YSIZE6 7 YSIZE7 */ if (LOG) logerror("%s LDSY LB: %02x\n", machine().describe_context(), data); m_ysize = (m_ysize & 0xf00) | data; } //------------------------------------------------- // ldtx_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldtx_hb_w ) { /* bit description 0 XTO8, MTA4 1 XTO9, MTA5 2 3 4 5 6 7 */ if (LOG) logerror("%s LDTX HB: %02x\n", machine().describe_context(), data); m_xto = ((data & 0x03) << 8) | (m_xto & 0xff); m_mta = (m_mta & 0x3ffcf) | ((data & 0x03) << 4); } //------------------------------------------------- // ldtx_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldtx_lb_w ) { /* bit description 0 XTO0 1 XTO1 2 XTO2 3 XTO3 4 XTO4, MTA0 5 XTO5, MTA1 6 XTO6, MTA2 7 XTO7, MTA3 */ if (LOG) logerror("%s LDTX LB: %02x\n", machine().describe_context(), data); m_xto = (m_xto & 0x300) | data; m_mta = (m_mta & 0x3fff0) | (data >> 4); } //------------------------------------------------- // ldty_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldty_hb_w ) { /* bit description 0 YTO8, MTA14 1 YTO9, MTA15 2 YTO10, MTA16 3 YTO11, MTA17 4 5 6 7 */ if (LOG) logerror("%s LDTY HB: %02x\n", machine().describe_context(), data); if (L_P) return; m_ty = ((data & 0x0f) << 8) | (m_yto & 0xff); m_yto = ((data & 0x0f) << 8) | (m_yto & 0xff); m_mta = ((data & 0x0f) << 14) | (m_mta & 0x3fff); } //------------------------------------------------- // ldty_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldty_lb_w ) { /* bit description 0 YTO0, MTA6 1 YTO1, MTA7 2 YTO2, MTA8 3 YTO3, MTA9 4 YTO4, MTA10 5 YTO5, MTA11 6 YTO6, MTA12 7 YTO7, MTA13 */ if (LOG) logerror("%s LDTY LB: %02x\n", machine().describe_context(), data); if (L_P) return; m_ty = (m_ty & 0xf00) | data; m_yto = (m_yto & 0xf00) | data; m_mta = (m_mta & 0x3c03f) | (data << 6); } //------------------------------------------------- // ldfx_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldfx_hb_w ) { /* bit description 0 XFROM8, MFA4 1 XFROM9, MFA5 2 3 4 5 6 7 */ if (LOG) logerror("%s LDFX HB: %02x\n", machine().describe_context(), data); m_xfrom = ((data & 0x03) << 8) | (m_xfrom & 0xff); m_mfa = (m_mfa & 0x3ffcf) | ((data & 0x03) << 4); } //------------------------------------------------- // ldfx_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldfx_lb_w ) { /* bit description 0 XFROM0 1 XFROM1 2 XFROM2 3 XFROM3 4 XFROM4, MFA0 5 XFROM5, MFA1 6 XFROM6, MFA2 7 XFROM7, MFA3 */ if (LOG) logerror("%s LDFX LB: %02x\n", machine().describe_context(), data); m_xfrom = (m_xfrom & 0x300) | data; m_mfa = (m_mfa & 0x3fff0) | (data >> 4); } //------------------------------------------------- // ldfy_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldfy_hb_w ) { /* bit description 0 MFA14 1 MFA15 2 MFA16 3 MFA17 4 5 6 7 */ if (LOG) logerror("%s LDFY HB: %02x\n", machine().describe_context(), data); m_mfa = ((data & 0x0f) << 14) | (m_mfa & 0x3fff); } //------------------------------------------------- // ldfy_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::ldfy_lb_w ) { /* bit description 0 MFA6 1 MFA7 2 MFA8 3 MFA9 4 MFA10 5 MFA11 6 MFA12 7 MFA13 */ if (LOG) logerror("%s LDFY LB: %02x\n", machine().describe_context(), data); m_mfa = (m_mfa & 0x3c03f) | (data << 6); mover(); } //------------------------------------------------- // wrml_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::wrml_w ) { /* bit description 0 MOVE CYK CLK 1 DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK) 2 DATA CLK 3 _DISP MEM WE 4 _CAS HB 5 DTACK CLK / BLANK TEST (+2 PIXCLK) 6 DISPREC CLK 7 _RAS HB */ if (LOG) logerror("MS %u : %02x\n", (offset >> 4) & 0x0f, data); if (m_clocks_disabled) { m_ms[(offset >> 4) & 0x0f] = data; } } //------------------------------------------------- // wrdl_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::wrdl_w ) { /* bit description 0 MOVE CYK CLK 1 DISP CYC SEL / DISP CYK PRE FETCH (+1 PIXCLK) 2 DATA CLK 3 _DISP MEM WE 4 _CAS HB 5 DTACK CLK / BLANK TEST (+2 PIXCLK) 6 DISPREC CLK 7 _RAS HB */ if (LOG) logerror("WS %u : %02x\n", (offset >> 4) & 0x0f, data); if (m_clocks_disabled) { m_ds[(offset >> 4) & 0x0f] = data; } } //------------------------------------------------- // wrmask_strobe_hb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::wrmask_strobe_hb_w ) { if (REPLACE) { // DATAPORT_HB m_gmdi = (data << 8) | (m_gmdi & 0xff); if (LOG) logerror("GMDI HB %04x\n", m_gmdi); } else { // WRPORT_HB m_wrm = (data << 8) | (m_wrm & 0xff); if (LOG) logerror("WRM HB %04x\n", m_gmdi); } } //------------------------------------------------- // wrmask_strobe_lb_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::wrmask_strobe_lb_w ) { if (REPLACE) { // DATAPORT_LB m_gmdi = (m_gmdi & 0xff00) | data; if (LOG) logerror("GMDI LB %04x\n", m_gmdi); } else { // WRPORT_LB m_wrm = (m_wrm & 0xff00) | data; if (LOG) logerror("WRM LB %04x\n", m_gmdi); } } //------------------------------------------------- // enable_clocks_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::enable_clocks_w ) { if (LOG) logerror("ENABLE CLOCKS\n"); m_clocks_disabled = 0; } //------------------------------------------------- // flag_strobe_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::flag_strobe_w ) { /* bit description 0 L/_P FLAG 1 BLANK FLAG 2 PIX POL 3 FRAME POL 4 HOLD FY 5 HOLD FX 6 COMP MOVE FLAG 7 REPLACE/SET & RESET */ m_flag = data; if (LOG) logerror("FLAG %02x\n", m_flag); } //------------------------------------------------- // endisp_w - //------------------------------------------------- WRITE8_MEMBER( abc1600_mover_device::endisp_w ) { m_endisp = 1; if (LOG) logerror("ENDISP\n"); } //************************************************************************** // MOVER //************************************************************************** //------------------------------------------------- // clock_mfa_x - //------------------------------------------------- inline void abc1600_mover_device::clock_mfa_x() { uint16_t mfa_y = m_mfa >> 6; uint8_t mfa_x = m_mfa & 0x3f; if (!HOLD_FX) { mfa_x += m_udx ? 1 : -1; mfa_x &= 0x3f; } m_mfa = (mfa_y << 6) | mfa_x; } //------------------------------------------------- // clock_mfa_y - //------------------------------------------------- inline void abc1600_mover_device::clock_mfa_y() { uint16_t mfa_y = m_mfa >> 6; uint8_t mfa_x = m_mfa & 0x3f; if (!HOLD_FY) { mfa_y += m_udy ? 1 : -1; mfa_y &= 0xfff; } m_mfa = (mfa_y << 6) | mfa_x; } //------------------------------------------------- // clock_mta_x - //------------------------------------------------- inline void abc1600_mover_device::clock_mta_x() { uint16_t mta_y = m_mta >> 6; uint8_t mta_x = m_mta & 0x3f; mta_x += m_udx ? 1 : -1; mta_x &= 0x3f; m_mta = (mta_y << 6) | mta_x; } //------------------------------------------------- // clock_mta_y - //------------------------------------------------- inline void abc1600_mover_device::clock_mta_y() { uint16_t mta_y = m_mta >> 6; uint8_t mta_x = m_mta & 0x3f; mta_y += m_udy ? 1 : -1; mta_y &= 0xfff; m_mta = (mta_y << 6) | mta_x; } //------------------------------------------------- // load_mfa_x - //------------------------------------------------- inline void abc1600_mover_device::load_mfa_x() { uint16_t mfa_y = m_mfa >> 6; uint8_t mfa_x = m_xfrom >> 4; m_mfa = (mfa_y << 6) | mfa_x; } //------------------------------------------------- // load_mta_x - //------------------------------------------------- inline void abc1600_mover_device::load_mta_x() { uint16_t mta_y = m_mta >> 6; uint8_t mta_x = m_xto >> 4; m_mta = (mta_y << 6) | mta_x; } //------------------------------------------------- // load_xy_reg - //------------------------------------------------- inline void abc1600_mover_device::load_xy_reg() { if (L_P) return; uint16_t sum = m_xto + m_xsize; m_xto = sum & 0x3ff; m_yto = m_ty & 0xfff; m_mta = (m_ty << 6) | (sum >> 4); } //------------------------------------------------- // compare_mta_x - //------------------------------------------------- inline void abc1600_mover_device::compare_mta_x() { uint8_t mta_x_end = ((m_xto + m_xsize) >> 4) & 0x3f; uint8_t mta_x = m_mta & 0x3f; if (mta_x == mta_x_end) { m_cmc = 0; } m_wrms1 = m_cmc & m_amm; } //------------------------------------------------- // compare_mta_y - //------------------------------------------------- inline void abc1600_mover_device::compare_mta_y() { int mta_y_end = (m_yto + m_ysize) & 0xfff; uint16_t mta_y = m_mta >> 6; if (mta_y == mta_y_end) { m_rmc = 0; } } //------------------------------------------------- // get_shinf - //------------------------------------------------- inline void abc1600_mover_device::get_shinf() { /* bit description A0 XFROM0 A1 XFROM1 A2 XFROM2 A3 XFROM3 A4 XTO0 A5 XTO1 A6 XTO2 A7 XTO3 A8 U/D* X */ uint16_t shinf_addr = (m_udx << 8) | ((m_xto & 0x0f) << 4) | (m_xfrom & 0x0f); uint8_t shinf = m_shinf_rom[shinf_addr]; m_sh = shinf & 0x0f; m_hold_1w_cyk = BIT(shinf, 5); } //------------------------------------------------- // get_drmsk - //------------------------------------------------- inline uint16_t abc1600_mover_device::get_drmsk() { /* bit description A0 SH0 A1 SH1 A2 SH2 A3 SH3 A4 U/D* X */ uint16_t drmsk_addr = (m_udx << 4) | (m_sh & 0x0f); return m_drmsk_rom[drmsk_addr]; } //------------------------------------------------- // get_wrmsk - get mover write mask //------------------------------------------------- inline uint16_t abc1600_mover_device::get_wrmsk() { /* bit description A0 XTO0 A1 XTO1 A2 XTO2 A3 XTO3 A4 XSIZE0 A5 XSIZE1 A6 XSIZE2 A7 XSIZE3 A8 U/D* X A9 ANDED MASKS A10 WRMS0 A11 WRMS1 */ uint16_t wrmsk_addr = (m_wrms1 << 11) | (m_wrms0 << 10) | ((!m_wrms1 && !m_wrms0) << 9) | (m_udx << 8) | ((m_xsize & 0x0f) << 4) | (m_xto & 0x0f); return m_wrmsk_rom[wrmsk_addr] ^ 0xffff; } //------------------------------------------------- // barrel_shift - //------------------------------------------------- inline uint16_t abc1600_mover_device::barrel_shift(uint16_t gmdr) { uint16_t rot = gmdr; for (int sh = 0; sh < m_sh; sh++) { int msb = BIT(rot, 15); rot <<= 1; rot |= msb; } return rot; } //------------------------------------------------- // word_mixer - //------------------------------------------------- inline uint16_t abc1600_mover_device::word_mixer(uint16_t rot) { uint16_t drmsk = get_drmsk(); uint16_t gmdi = (rot & drmsk) | (m_mdor & (drmsk ^ 0xffff)); if (COMP_MOVE) { gmdi ^= 0xffff; } m_mdor = rot; return gmdi; } //------------------------------------------------- // mover - //------------------------------------------------- void abc1600_mover_device::mover() { if (LOG) logerror("XFROM %u XSIZE %u YSIZE %u XTO %u YTO %u MFA %05x MTA %05x U/D*X %u U/D*Y %u\n", m_xfrom, m_xsize, m_ysize, m_xto, m_yto, m_mfa, m_mta, m_udx, m_udy); m_amm = 1; m_rmc = 1; get_shinf(); do { compare_mta_y(); load_mfa_x(); load_mta_x(); m_cmc = 1; m_wrms0 = 0; if (m_hold_1w_cyk) { // read one word in advance uint16_t gmdr = read_videoram(m_mfa); uint16_t rot = barrel_shift(gmdr); word_mixer(rot); clock_mfa_x(); } do { compare_mta_x(); uint16_t gmdr = read_videoram(m_mfa); uint16_t rot = barrel_shift(gmdr); uint16_t gmdi = word_mixer(rot); uint16_t mask = get_wrmsk(); write_videoram(m_mta, gmdi, mask); clock_mfa_x(); clock_mta_x(); m_wrms0 = 1; } while (m_cmc); clock_mfa_y(); clock_mta_y(); } while (m_rmc); load_xy_reg(); m_amm = 0; } uint32_t abc1600_mover_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { if (m_endisp) { bitmap.fill(m_palette->pen(FRAME_POL), cliprect); m_crtc->screen_update(screen, bitmap, cliprect); } else { bitmap.fill(rgb_t::black(), cliprect); } return 0; }