diff --git a/src/mame/ussr/1801vp033.cpp b/src/mame/ussr/1801vp033.cpp new file mode 100644 index 0000000000000..8b7eb3fc68331 --- /dev/null +++ b/src/mame/ussr/1801vp033.cpp @@ -0,0 +1,227 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + 1801VP1-033 Gate Array emulation + + https://github.com/1801BM1/k1801/blob/master/033/doc/bpic.md + + Multifunction device; function is chosen at power-up time: + + BPIC - bidirectional 8-bit parallel port with interrupt support + (for printers, paper tape readers and terminals) + PIC - bidirectional 16-bit parallel port with interrupt support + FDIC - bidirectional parallel-to-serial interface + (for external floppy drive, clone of RX01 or RX02) + + Unimplemented: FDIC function and bidirectional mode of BPIC function + +**********************************************************************/ + +#include "emu.h" +#include "1801vp033.h" + +//#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(K1801VP033, k1801vp033_device, "1801vp1_033", "1801VP1-033") + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// k1801vp033_device - constructor +//------------------------------------------------- + +k1801vp033_device::k1801vp033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, K1801VP033, tag, owner, clock) + , device_z80daisy_interface(mconfig, *this) + , m_bpic_write_rxrdy(*this) + , m_bpic_write_txrdy(*this) + , m_bpic_write_reset(*this) + , m_bpic_write_strobe(*this) + , m_bpic_write_pd(*this) + , m_pic_write_reqa(*this) + , m_pic_write_reqb(*this) + , m_pic_write_csr0(*this) + , m_pic_write_csr1(*this) + , m_pic_write_out(*this) + , m_rxvec(0) + , m_txvec(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void k1801vp033_device::device_start() +{ + m_rcsr = m_tcsr = m_rbuf = m_tbuf = 0; + m_rxrdy = m_txrdy = CLEAR_LINE; + + m_bpic_write_strobe(1); + + // register for state saving + save_item(NAME(m_rcsr)); + save_item(NAME(m_rbuf)); + save_item(NAME(m_tcsr)); + save_item(NAME(m_tbuf)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void k1801vp033_device::device_reset() +{ + m_tbuf = 0; + m_txrdy = CLEAR_LINE; + m_tcsr &= ~(CSR_IE | PICCSR_IEA | PICCSR_IEB); + m_tcsr |= BPICCSR_DRQ; +} + +//------------------------------------------------- +// daisy chained interrupts +//------------------------------------------------- + +int k1801vp033_device::z80daisy_irq_state() +{ + if (m_rxrdy == ASSERT_LINE || m_txrdy == ASSERT_LINE) + return Z80_DAISY_INT; + else + return 0; +} + +int k1801vp033_device::z80daisy_irq_ack() +{ + int vec = -1; + + if (m_rxrdy == ASSERT_LINE) + { + m_rxrdy = CLEAR_LINE; + vec = m_rxvec; + } + else if (m_txrdy == ASSERT_LINE) + { + m_txrdy = CLEAR_LINE; + vec = m_txvec; + } + + return vec; +} + + +//------------------------------------------------- +// read - register read +//------------------------------------------------- + +uint16_t k1801vp033_device::bpic_read(offs_t offset) +{ + uint16_t data = 0; + + switch (offset & 3) + { + case 0: + data = m_tcsr & BPICCSR_RD; + break; + + case 2: + data = m_tbuf; + break; + } + + return data; +} + + +uint16_t k1801vp033_device::pic_read(offs_t offset) +{ + uint16_t data = 0; + + switch (offset & 3) + { + case 0: + data = m_tcsr & PICCSR_RD; + break; + + case 1: + data = m_tbuf; + break; + + case 2: + data = m_rbuf; + break; + } + + return data; +} + +//------------------------------------------------- +// write - register write +//------------------------------------------------- + +void k1801vp033_device::bpic_write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + LOG("%s W %06o <- %06o & %06o\n", machine().describe_context(), 0177510 + (offset << 1), data, mem_mask); + + switch (offset & 3) + { + case 0: + if ((data & CSR_IE) == 0) + { + clear_virq(m_bpic_write_txrdy, 1, 1, m_txrdy); + } + else if ((m_tcsr & (BPICCSR_DRQ + CSR_IE)) == BPICCSR_DRQ) + { + raise_virq(m_bpic_write_txrdy, 1, 1, m_txrdy); + } + m_tcsr = ((m_tcsr & ~BPICCSR_WR) | (data & BPICCSR_WR)); + m_bpic_write_reset(!BIT(m_tcsr, 14)); + break; + + case 2: + m_tbuf = data & 0377; + m_tcsr &= ~BPICCSR_DRQ; + clear_virq(m_bpic_write_txrdy, m_tcsr, CSR_IE, m_txrdy); + m_bpic_write_pd(m_tbuf); + m_bpic_write_strobe(0); + m_bpic_write_strobe(1); + break; + } +} + +void k1801vp033_device::pic_write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + LOG("%s W %06o <- %06o & %06o\n", machine().describe_context(), 0177510 + (offset << 1), data, mem_mask); + + switch (offset & 3) + { + case 0: + m_tcsr = ((m_tcsr & ~PICCSR_WR) | (data & PICCSR_WR)); + m_pic_write_csr0(BIT(m_tcsr, 0)); + m_pic_write_csr1(BIT(m_tcsr, 1)); + break; + + case 1: + COMBINE_DATA(&m_tbuf); + m_pic_write_out(0, m_tbuf, mem_mask); + break; + } +} diff --git a/src/mame/ussr/1801vp033.h b/src/mame/ussr/1801vp033.h new file mode 100644 index 0000000000000..021f7db6ce5fe --- /dev/null +++ b/src/mame/ussr/1801vp033.h @@ -0,0 +1,117 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + 1801VP1-033 Gate Array emulation + +**********************************************************************/ + +#ifndef MAME_USSR_1801VP033_H +#define MAME_USSR_1801VP033_H + +#pragma once + +#include "machine/pdp11.h" +#include "machine/z80daisy.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> k1801vp033_device + +class k1801vp033_device : public device_t, + public device_z80daisy_interface +{ +public: + // construction/destruction + k1801vp033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // BPIC mode + + void set_txvec(int vec) { m_txvec = vec; } + void set_rxvec(int vec) { m_rxvec = vec; } + + auto bpic_txrdy_wr_callback() { return m_bpic_write_txrdy.bind(); } + auto bpic_reset_wr_callback() { return m_bpic_write_reset.bind(); } + auto bpic_strobe_wr_callback() { return m_bpic_write_strobe.bind(); } + auto bpic_pd_wr_callback() { return m_bpic_write_pd.bind(); } + + uint16_t bpic_read(offs_t offset); + void bpic_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + void bpic_write_drq(int state) { if (state) { m_tcsr |= BPICCSR_DRQ; raise_virq(m_bpic_write_txrdy, m_tcsr, CSR_IE, m_txrdy); } } + void bpic_write_err(int state) { if (state) m_tcsr |= CSR_ERR; else m_tcsr &= ~CSR_ERR; } + + // PIC mode + + void set_vec_a(int vec) { m_txvec = vec; } + void set_vec_b(int vec) { m_rxvec = vec; } + + auto pic_out_wr_callback() { return m_pic_write_out.bind(); } + auto pic_csr0_wr_callback() { return m_pic_write_csr0.bind(); } + auto pic_csr1_wr_callback() { return m_pic_write_csr1.bind(); } + + uint16_t pic_read(offs_t offset); + void pic_write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + void pic_write_reqa(int state) { if (state) { m_tcsr |= PICCSR_REQA; raise_virq(m_pic_write_reqa, m_tcsr, PICCSR_IEA, m_txrdy); } } + void pic_write_reqb(int state) { if (state) { m_tcsr |= PICCSR_REQB; raise_virq(m_pic_write_reqb, m_tcsr, PICCSR_IEB, m_rxrdy); } } + void pic_write_rbuf(uint16_t data) { m_rbuf = data; } + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_z80daisy_interface overrides + virtual int z80daisy_irq_state() override; + virtual int z80daisy_irq_ack() override; + virtual void z80daisy_irq_reti() override {}; + +private: + static constexpr uint16_t BPICCSR_RDY = 0000040; + static constexpr uint16_t BPICCSR_DRQ = 0000200; + static constexpr uint16_t BPICCSR_RESET = 0040000; + static constexpr uint16_t BPICCSR_RD = (CSR_DONE | CSR_IE | CSR_ERR | BPICCSR_RDY | BPICCSR_DRQ); + static constexpr uint16_t BPICCSR_WR = (CSR_IE | BPICCSR_RESET); + + static constexpr uint16_t PICCSR_CSR0 = 0000001; + static constexpr uint16_t PICCSR_CSR1 = 0000002; + static constexpr uint16_t PICCSR_IEB = 0000040; + static constexpr uint16_t PICCSR_IEA = 0000100; + static constexpr uint16_t PICCSR_REQA = 0000200; + static constexpr uint16_t PICCSR_REQB = 0100000; + static constexpr uint16_t PICCSR_RD = (PICCSR_REQB | PICCSR_REQA | PICCSR_IEA | PICCSR_IEB | PICCSR_CSR1 | PICCSR_CSR0); + static constexpr uint16_t PICCSR_WR = (PICCSR_IEA | PICCSR_IEB | PICCSR_CSR1 | PICCSR_CSR0); + + devcb_write_line m_bpic_write_rxrdy; + devcb_write_line m_bpic_write_txrdy; + devcb_write_line m_bpic_write_reset; + devcb_write_line m_bpic_write_strobe; + devcb_write8 m_bpic_write_pd; + + devcb_write_line m_pic_write_reqa; + devcb_write_line m_pic_write_reqb; + devcb_write_line m_pic_write_csr0; + devcb_write_line m_pic_write_csr1; + devcb_write16 m_pic_write_out; + + line_state m_rxrdy; + line_state m_txrdy; + + int m_rxvec; + int m_txvec; + + uint16_t m_rcsr; + uint16_t m_rbuf; + uint16_t m_tcsr; + uint16_t m_tbuf; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(K1801VP033, k1801vp033_device) + +#endif // MAME_USSR_1801VP033_H diff --git a/src/mame/ussr/dvk_kcgd.cpp b/src/mame/ussr/dvk_kcgd.cpp index d9e3a55c08b85..c6c1f8c81f42c 100644 --- a/src/mame/ussr/dvk_kcgd.cpp +++ b/src/mame/ussr/dvk_kcgd.cpp @@ -16,9 +16,6 @@ To do: - K1801VM2 CPU core (interrupts and EVNT pin, full EIS set, other insns) - verify hsync/vsync frequencies - - interlace - - scanline table selection - - interrupts - mouse - mono/color CRT - KeyGP ROM @@ -36,11 +33,14 @@ #include "emu.h" +#include "1801vp033.h" +#include "bus/generic/slot.h" #include "bus/rs232/rs232.h" #include "cpu/t11/t11.h" #include "machine/dl11.h" -#include "ms7004.h" #include "machine/timer.h" +#include "ms7004.h" + #include "emupal.h" #include "screen.h" @@ -48,7 +48,7 @@ #define LOG_VRAM (1U << 1) #define LOG_DEBUG (1U << 2) -//#define VERBOSE (LOG_DEBUG) +//#define VERBOSE (LOG_DEBUG | LOG_VRAM) //#define LOG_OUTPUT_FUNC osd_printf_info #include "logmacro.h" @@ -77,51 +77,44 @@ class kcgd_state : public driver_device kcgd_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_pic(*this, "pic") , m_dl11host(*this, "dl11host") , m_rs232(*this, "rs232") , m_dl11kbd(*this, "dl11kbd") , m_ms7004(*this, "ms7004") , m_palette(*this, "palette") , m_screen(*this, "screen") + , m_buttons(*this, "mouse_buttons") { } void kcgd(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(mouse_x_changed); + DECLARE_INPUT_CHANGED_MEMBER(mouse_y_changed); + DECLARE_INPUT_CHANGED_MEMBER(buttons_changed); + private: virtual void machine_reset() override ATTR_COLD; virtual void machine_start() override ATTR_COLD; - //TIMER_CALLBACK_MEMBER(vsync_tick); + TIMER_CALLBACK_MEMBER(vsync_tick); TIMER_CALLBACK_MEMBER(toggle_500hz); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); TIMER_DEVICE_CALLBACK_MEMBER(scanline_callback); void kcgd_palette(palette_device &palette) const; - enum status_bits : unsigned - { - KCGD_STATUS_PAGE = 0, - KCGD_STATUS_INTERLACE = 1, - KCGD_STATUS_TIMER_INT = 5, - KCGD_STATUS_MODE_INT = 6, - KCGD_STATUS_MODE_LAST = 7, - KCGD_STATUS_TIMER_VAL = 15 - }; + void reset_w(int state); uint16_t vram_addr_r(); uint16_t vram_data_r(); uint16_t vram_mmap_r(offs_t offset); void vram_addr_w(uint16_t data); - void vram_data_w(uint16_t data); - void vram_mmap_w(offs_t offset, uint16_t data); - uint16_t status_r(); - void status_w(uint16_t data); - uint8_t palette_index_r(); - uint8_t palette_data_r(); - void palette_index_w(uint8_t data); - void palette_data_w(uint8_t data); - - //emu_timer *m_vsync_on_timer; + void vram_data_w(offs_t offset, uint16_t data, uint16_t mem_mask); + void vram_mmap_w(offs_t offset, uint16_t data, uint16_t mem_mask); + void palette_control(offs_t offset, uint16_t data, uint16_t mem_mask); + + emu_timer *m_vsync_timer = nullptr; emu_timer *m_500hz_timer = nullptr; void kcgd_mem(address_map &map) ATTR_COLD; @@ -130,46 +123,77 @@ class kcgd_state : public driver_device rectangle m_tmpclip; bitmap_ind16 m_tmpbmp; - struct - { - uint16_t status = 0; // 167770 - uint8_t control = 0; // 167772 - int palette_index = 0, vram_addr = 0; - uint8_t palette[16]{}; - } m_video; + int m_page, m_interlace, m_palette_index, m_vram_addr, m_500hz; + uint8_t m_video_control; + uint8_t m_palette_data[16]{}; + std::unique_ptr m_videoram; + int8_t m_x, m_y, m_sr; + protected: required_device m_maincpu; + required_device m_pic; required_device m_dl11host; required_device m_rs232; required_device m_dl11kbd; required_device m_ms7004; required_device m_palette; required_device m_screen; + required_ioport m_buttons; }; + +INPUT_CHANGED_MEMBER(kcgd_state::mouse_x_changed) +{ + m_x += newval - oldval; + logerror("X %3d->%3d d %3d m_x %3d\n", oldval, newval, newval-oldval, m_x); +} + +INPUT_CHANGED_MEMBER(kcgd_state::mouse_y_changed) +{ + m_y += newval - oldval; + logerror("Y %3d->%3d d %3d m_y %3d\n", oldval, newval, newval-oldval, m_y); +} + +INPUT_CHANGED_MEMBER(kcgd_state::buttons_changed) +{ + m_sr = m_buttons->read(); +} + +INPUT_PORTS_START(kcgd) + PORT_START("mouse_x") + PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(kcgd_state::mouse_x_changed), 0) + + PORT_START("mouse_y") + PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(kcgd_state::mouse_y_changed), 0) + + PORT_START("mouse_buttons") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(kcgd_state::buttons_changed), 0) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(kcgd_state::buttons_changed), 0) + PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNUSED ) +INPUT_PORTS_END + void kcgd_state::kcgd_mem(address_map &map) { map.unmap_value_high(); + map(0000000, 0177777).lrw16( + NAME([this](offs_t offset) { if (!machine().side_effects_disabled()) m_maincpu->pulse_input_line(t11_device::BUS_ERROR, attotime::zero); return 0; }), + NAME([this](offs_t offset, u16 data) { m_maincpu->pulse_input_line(t11_device::BUS_ERROR, attotime::zero); })); + map(0000000, 0077777).rw(FUNC(kcgd_state::vram_mmap_r), FUNC(kcgd_state::vram_mmap_w)); - map(0100000, 0157777).rom(); + map(0100000, 0117777).rom().region("maincpu", 0); // 1802VV1 chips map(0160000, 0160001).mirror(03774).rw(FUNC(kcgd_state::vram_addr_r), FUNC(kcgd_state::vram_addr_w)); map(0160002, 0160003).mirror(03774).rw(FUNC(kcgd_state::vram_data_r), FUNC(kcgd_state::vram_data_w)); - // 1801VP1-033 "pic" chip - map(0167770, 0167771).rw(FUNC(kcgd_state::status_r), FUNC(kcgd_state::status_w)); - map(0167772, 0167772).rw(FUNC(kcgd_state::palette_index_r), FUNC(kcgd_state::palette_index_w)); // reads always return 0 - map(0167773, 0167773).rw(FUNC(kcgd_state::palette_data_r), FUNC(kcgd_state::palette_data_w)); - // 1801VP1-065 chips, not 100% DL11 compatible (error bits are in RCSR, not RBUF) - map(0176560, 0176567).rw(m_dl11host, FUNC(dl11_device::read), FUNC(dl11_device::write)); - map(0177560, 0177567).rw(m_dl11kbd, FUNC(dl11_device::read), FUNC(dl11_device::write)); + map(0167770, 0167777).rw(m_pic, FUNC(k1801vp033_device::pic_read), FUNC(k1801vp033_device::pic_write)); + map(0176560, 0176567).rw(m_dl11host, FUNC(k1801vp065_device::read), FUNC(k1801vp065_device::write)); + map(0177560, 0177567).rw(m_dl11kbd, FUNC(k1801vp065_device::read), FUNC(k1801vp065_device::write)); } -// future static const z80_daisy_config daisy_chain[] = { -// { "pic" }, + { "pic" }, { "dl11kbd" }, { "dl11host" }, { nullptr } @@ -185,21 +209,23 @@ static DEVICE_INPUT_DEFAULTS_START( host_rs232_defaults ) DEVICE_INPUT_DEFAULTS_END -/* TIMER_CALLBACK_MEMBER(kcgd_state::vsync_tick) { - m_maincpu->set_input_line(INPUT_LINE_EVNT, ASSERT_LINE); + m_maincpu->pulse_input_line(t11_device::CP2_LINE, m_maincpu->minimum_quantum_time()); } -*/ TIMER_CALLBACK_MEMBER(kcgd_state::toggle_500hz) { - m_video.status ^= (1 << KCGD_STATUS_TIMER_VAL); + m_500hz ^= 1; + m_pic->pic_write_reqb(m_500hz); } void kcgd_state::machine_reset() { - m_video = decltype(m_video)(); + m_page = m_interlace = m_palette_index = m_vram_addr = m_500hz = 0; + m_video_control = 0; + m_x = m_y = 0; + memset(&m_palette_data, 0, sizeof(m_palette_data)); } void kcgd_state::machine_start() @@ -209,11 +235,23 @@ void kcgd_state::machine_start() m_tmpclip = rectangle(0, KCGD_DISP_HORZ - 1, 0, KCGD_DISP_VERT - 1); m_tmpbmp.allocate(KCGD_DISP_HORZ, KCGD_DISP_VERT); -// future -// m_vsync_on_timer = timer_alloc(FUNC(kcgd_state::vsync_tick), this); -// m_vsync_on_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->frame_period()); - m_500hz_timer = timer_alloc(FUNC(kcgd_state::toggle_500hz), this); - m_500hz_timer->adjust(attotime::from_hz(500), 0, attotime::from_hz(500)); + m_vsync_timer = timer_alloc(FUNC(kcgd_state::vsync_tick), this); + m_vsync_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->frame_period()); + if (system_bios() > 0) + { + m_500hz_timer = timer_alloc(FUNC(kcgd_state::toggle_500hz), this); + m_500hz_timer->adjust(attotime::from_hz(500), 0, attotime::from_hz(500)); + } +} + +void kcgd_state::reset_w(int state) +{ + if (state == ASSERT_LINE) + { + m_pic->reset(); + m_dl11kbd->reset(); + m_dl11host->reset(); + } } void kcgd_state::kcgd_palette(palette_device &palette) const @@ -226,78 +264,95 @@ void kcgd_state::kcgd_palette(palette_device &palette) const void kcgd_state::vram_addr_w(uint16_t data) { LOGDBG("VRAM WA %06o\n", data); - m_video.vram_addr = data; + m_vram_addr = data; } uint16_t kcgd_state::vram_addr_r() { - LOGDBG("VRAM RA %06o\n", m_video.vram_addr); - return m_video.vram_addr; + LOGDBG("VRAM RA %06o\n", m_vram_addr); + return m_vram_addr; } -void kcgd_state::vram_data_w(uint16_t data) +void kcgd_state::vram_data_w(offs_t offset, uint16_t data, uint16_t mem_mask) { - LOGVRAM("VRAM W2 %06o <- %04XH\n", m_video.vram_addr, data); - m_videoram[m_video.vram_addr] = data | (BIT(m_video.control, 7) << 16); + LOGVRAM("VRAM W2 %06o <- %04XH\n", m_vram_addr, data); + COMBINE_DATA(&m_videoram[m_vram_addr]); + m_videoram[m_vram_addr] &= ~(1 << 16); + m_videoram[m_vram_addr] |= (BIT(m_video_control, 7) << 16); } uint16_t kcgd_state::vram_data_r() { - LOGVRAM("VRAM R2 %06o\n", m_video.vram_addr); - m_video.status = (m_video.status & 0xff7f) | (BIT(m_videoram[m_video.vram_addr], 16) << 7); - return (uint16_t)(m_videoram[m_video.vram_addr] & 0xffff); + int hires = BIT(m_videoram[m_vram_addr], 16); + LOGVRAM("VRAM R2 %06o\n", m_vram_addr); + m_pic->pic_write_reqa(hires ^ BIT(m_video_control, 6)); + return m_videoram[m_vram_addr]; } -void kcgd_state::vram_mmap_w(offs_t offset, uint16_t data) +void kcgd_state::vram_mmap_w(offs_t offset, uint16_t data, uint16_t mem_mask) { LOGVRAM("VRAM W1 %06o <- %04XH\n", offset, data); - m_videoram[offset] = data | (BIT(m_video.control, 7) << 16); + COMBINE_DATA(&m_videoram[offset]); + m_videoram[offset] &= ~(1 << 16); + m_videoram[offset] |= (BIT(m_video_control, 7) << 16); } uint16_t kcgd_state::vram_mmap_r(offs_t offset) { LOGVRAM("VRAM R1 %06o\n", offset); - return (uint16_t)m_videoram[offset]; -} - -void kcgd_state::status_w(uint16_t data) -{ - LOG("Status W data %04XH (useful %02XH)\n", data, data & 0x63); - // bits 7 and 15 are read-only - m_video.status = (m_video.status & 0x8080) | (data & 0x7f7f); -} - -uint16_t kcgd_state::status_r() -{ - uint16_t data = m_video.status ^ (BIT(m_video.control, 6) << 7); - LOG("Status R data %04X index %d\n", data, m_video.palette_index); - return data; -} - -void kcgd_state::palette_index_w(uint8_t data) -{ - m_video.control = data; - m_video.palette_index = ((data >> 2) & 15); - LOG("Palette index, Control W data %02XH index %d\n", data, m_video.palette_index); -} - -void kcgd_state::palette_data_w(uint8_t data) -{ - LOG("Palette data W data %02XH index %d\n", data, m_video.palette_index); - m_video.palette[m_video.palette_index] = data; - m_palette->set_pen_color(m_video.palette_index, - 85*(data & 3), 85*((data >> 2) & 3), 85*((data >> 4) & 3)); -} - -uint8_t kcgd_state::palette_index_r() -{ - return 0; + return m_videoram[offset]; } -uint8_t kcgd_state::palette_data_r() +/* + * 167770: + * + * 0 RW CSR0 scanline table select (0 = table 0, 1 = table 1) + * 1 RW CSR1 progressive or interlaced mode (1 = 480i, 0 = 240p) + * 5 RW IEB 500 Hz timer interrupt enable (1 = enabled) + * 6 RW IEA hires mode interrupt enable (1 = enabled) + * 7 R REQA hires mode of last word read via data register + * 15 R REQB 500 Hz timer flipflop state + * + * RESET signal clears bits 0, 1, 5 and 6. + * + * 167772: + * + * 2 W mouse coordinate and button select (0 = X and button 0, 1 = Y and button 1) + * 2-5 W palette index + * 6 W invert bit 7 of status register 167770 + * 7 W hires mode on writes to vram (0 = hires) + * + * 167774: + * + * 0-2 R mouse coordinate data + * 3 R mouse button state + */ + +void kcgd_state::palette_control(offs_t offset, uint16_t data, uint16_t mem_mask) { - LOG("Palette data R index %d\n", m_video.palette_index); - return m_video.palette[m_video.palette_index]; + if (ACCESSING_BITS_0_7) + { + m_video_control = data; + m_palette_index = (data >> 2) & 15; + if (BIT(data, 2)) + { + m_pic->pic_write_rbuf((m_x & 7) | (BIT(m_sr, 0) << 3)); + } + else + { + m_pic->pic_write_rbuf((m_y & 7) | (BIT(m_sr, 1) << 3)); + } + LOGDBG("Palette/Control W mask %06o data %06o = index %d control 0x%x\n", + mem_mask, data, m_palette_index, m_video_control); + } + if (ACCESSING_BITS_8_15) + { + m_palette_data[m_palette_index] = data >> 8; + m_palette->set_pen_color(m_palette_index, + 85*((data >> 8) & 3), 85*((data >> 10) & 3), 85*((data >> 12) & 3)); + LOGDBG("Palette/Control W mask %06o data %06o = value 0x%x\n", + mem_mask, data, m_palette_data[m_palette_index]); + } } /* @@ -311,9 +366,7 @@ uint8_t kcgd_state::palette_data_r() void kcgd_state::draw_scanline(uint16_t *p, uint16_t offset) { - int i; - - for (i = 0; i < 100; i++) + for (int i = 0; i < 100; i++) { uint32_t data = m_videoram[offset++]; if (BIT(data, 16)) @@ -343,19 +396,20 @@ void kcgd_state::draw_scanline(uint16_t *p, uint16_t offset) TIMER_DEVICE_CALLBACK_MEMBER(kcgd_state::scanline_callback) { - uint16_t y = m_screen->vpos(); + int y = m_screen->vpos(); if (y < KCGD_VERT_START) return; y -= KCGD_VERT_START; if (y >= KCGD_DISP_VERT) return; - uint16_t const offset = BIT(m_video.status, KCGD_STATUS_PAGE) ? (KCGD_PAGE_1 >> 1) : (KCGD_PAGE_0 >> 1); + uint16_t offset = m_page ? (KCGD_PAGE_1 >> 1) : (KCGD_PAGE_0 >> 1); LOGDBG("scanline_cb frame %d y %.3d page %d offset %04X *offset %04X\n", - m_screen->frame_number(), BIT(m_video.status, KCGD_STATUS_PAGE), - y, offset + y, m_videoram[offset + y]); + m_screen->frame_number(), y, m_page, offset + y, m_videoram[offset + y]); - draw_scanline(&m_tmpbmp.pix(y), m_videoram[offset + (KCGD_DISP_VERT - 1) - y]); + // in progressive mode, display only odd scanlines + offset = offset + (KCGD_DISP_VERT - 1) - (m_interlace ? y : (y & 0xfffe)); + draw_scanline(&m_tmpbmp.pix(y), m_videoram[offset]); } uint32_t kcgd_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) @@ -379,7 +433,7 @@ static const gfx_layout kcgd_charlayout = }; static GFXDECODE_START( gfx_kcgd ) - GFXDECODE_ENTRY("maincpu", 0112236, kcgd_charlayout, 0, 1) + GFXDECODE_ENTRY("maincpu", 012236, kcgd_charlayout, 0, 1) GFXDECODE_END void kcgd_state::kcgd(machine_config &config) @@ -387,8 +441,8 @@ void kcgd_state::kcgd(machine_config &config) K1801VM2(config, m_maincpu, XTAL(30'800'000) / 4); m_maincpu->set_addrmap(AS_PROGRAM, &kcgd_state::kcgd_mem); m_maincpu->set_initial_mode(0100000); -// future -// m_maincpu->set_daisy_config(daisy_chain); + m_maincpu->set_daisy_config(daisy_chain); + m_maincpu->out_reset().set(FUNC(kcgd_state::reset_w)); timer_device &scantimer(TIMER(config, "scantimer")); scantimer.configure_periodic(FUNC(kcgd_state::scanline_callback), attotime::from_hz(50 * 28 * 11)); @@ -405,6 +459,13 @@ void kcgd_state::kcgd(machine_config &config) GFXDECODE(config, "gfxdecode", m_palette, gfx_kcgd); + K1801VP033(config, m_pic, 0); + m_pic->set_vec_a(0300); + m_pic->set_vec_b(0304); + m_pic->pic_out_wr_callback().set(FUNC(kcgd_state::palette_control)); + m_pic->pic_csr0_wr_callback().set([this] (int state) { m_page = state; }); + m_pic->pic_csr1_wr_callback().set([this] (int state) { m_interlace = state; }); + K1801VP065(config, m_dl11host, XTAL(4'608'000)); m_dl11host->set_rxc(57600); m_dl11host->set_txc(57600); @@ -416,7 +477,7 @@ void kcgd_state::kcgd(machine_config &config) m_dl11host->rxrdy_wr_callback().set_inputline(m_maincpu, t11_device::VEC_LINE); RS232_PORT(config, m_rs232, default_rs232_devices, "null_modem"); - m_rs232->rxd_handler().set(m_dl11host, FUNC(dl11_device::rx_w)); + m_rs232->rxd_handler().set(m_dl11host, FUNC(k1801vp065_device::rx_w)); m_rs232->set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(host_rs232_defaults)); K1801VP065(config, m_dl11kbd, XTAL(4'608'000)); @@ -429,16 +490,16 @@ void kcgd_state::kcgd(machine_config &config) m_dl11kbd->rxrdy_wr_callback().set_inputline(m_maincpu, t11_device::VEC_LINE); MS7004(config, m_ms7004, 0); - m_ms7004->tx_handler().set(m_dl11kbd, FUNC(dl11_device::rx_w)); + m_ms7004->tx_handler().set(m_dl11kbd, FUNC(k1801vp065_device::rx_w)); } ROM_START( dvk_kcgd ) - ROM_REGION16_BE(0x100000, "maincpu", ROMREGION_ERASE00) + ROM_REGION16_BE(060000, "maincpu", ROMREGION_ERASE00) ROM_DEFAULT_BIOS("181") ROM_SYSTEM_BIOS(0, "181", "mask 181") - ROMX_LOAD("kr1801re2-181.bin", 0100000, 020000, CRC(acac124f) SHA1(412c3eb71bece6f791fc5a9d707cf4692fd0b45b), ROM_BIOS(0)) + ROMX_LOAD("kr1801re2-181.bin", 0, 020000, CRC(acac124f) SHA1(412c3eb71bece6f791fc5a9d707cf4692fd0b45b), ROM_BIOS(0)) ROM_SYSTEM_BIOS(1, "182", "mask 182") - ROMX_LOAD("kr1801re2-182.bin", 0100000, 020000, CRC(3ca2921a) SHA1(389b30c40ed7e41dae71d58c7bff630359a48153), ROM_BIOS(1)) + ROMX_LOAD("kr1801re2-182.bin", 0, 020000, CRC(3ca2921a) SHA1(389b30c40ed7e41dae71d58c7bff630359a48153), ROM_BIOS(1)) ROM_END } // anonymous namespace @@ -447,4 +508,4 @@ ROM_END /* Driver */ /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1987, dvk_kcgd, 0, 0, kcgd, 0, kcgd_state, empty_init, "USSR", "DVK KCGD", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW ) +COMP( 1987, dvk_kcgd, 0, 0, kcgd, kcgd, kcgd_state, empty_init, "USSR", "DVK KCGD", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )