From 1e32a43b50742c418fc169535f6add2ba725875a Mon Sep 17 00:00:00 2001 From: holub Date: Fri, 24 Dec 2021 14:58:14 -0500 Subject: Added preliminary TS-Configuration for ZX Evolution driver. (#8989) New machines marked as not working ------------------------- NedoPC, TS-Labs ZX Evolution TS-Configuration --- scripts/src/machine.lua | 22 ++ scripts/target/mame/mess.lua | 5 + src/devices/machine/glukrs.cpp | 60 ++++ src/devices/machine/glukrs.h | 35 ++ src/devices/machine/tsconfdma.cpp | 195 ++++++++++++ src/devices/machine/tsconfdma.h | 58 ++++ src/mame/drivers/atm.cpp | 18 +- src/mame/drivers/pentagon.cpp | 18 +- src/mame/drivers/scorpion.cpp | 20 +- src/mame/drivers/spec128.cpp | 8 +- src/mame/drivers/spectrum.cpp | 6 +- src/mame/drivers/tsconf.cpp | 296 +++++++++++++++++ src/mame/includes/spectrum.h | 5 +- src/mame/includes/tsconf.h | 191 +++++++++++ src/mame/machine/tsconf.cpp | 653 ++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/video/spectrum.cpp | 6 +- 17 files changed, 1561 insertions(+), 38 deletions(-) create mode 100644 src/devices/machine/glukrs.cpp create mode 100644 src/devices/machine/glukrs.h create mode 100644 src/devices/machine/tsconfdma.cpp create mode 100644 src/devices/machine/tsconfdma.h create mode 100644 src/mame/drivers/tsconf.cpp create mode 100644 src/mame/includes/tsconf.h create mode 100644 src/mame/machine/tsconf.cpp diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index e0c955ce9aa..8900f14a108 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -4881,3 +4881,25 @@ if (MACHINES["NS32082"]~=null) then MAME_DIR .. "src/devices/machine/ns32082.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/tsconfdma.h,MACHINES["TSCONF_DMA"] = true +--------------------------------------------------- +if (MACHINES["TSCONF_DMA"]~=null) then + files { + MAME_DIR .. "src/devices/machine/tsconfdma.cpp", + MAME_DIR .. "src/devices/machine/tsconfdma.h", + } +end + +--------------------------------------------------- +-- +--@src/devices/machine/glukrs.h,MACHINES["GLUKRS"] = true +--------------------------------------------------- +if (MACHINES["GLUKRS"]~=null) then + files { + MAME_DIR .. "src/devices/machine/glukrs.cpp", + MAME_DIR .. "src/devices/machine/glukrs.h", + } +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 2b15464d324..66e11808b98 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -534,6 +534,7 @@ MACHINES["ER2055"] = true MACHINES["EXORTERM"] = true MACHINES["F3853"] = true MACHINES["F4702"] = true +MACHINES["GLUKRS"] = true MACHINES["GT913"] = true MACHINES["HD63450"] = true MACHINES["HD64610"] = true @@ -716,6 +717,7 @@ MACHINES["TMS9901"] = true MACHINES["TMS9902"] = true MACHINES["TMS9914"] = true MACHINES["TPI6525"] = true +MACHINES["TSCONF_DMA"] = true MACHINES["TTL7400"] = true MACHINES["TTL7404"] = true --MACHINES["TSB12LV01A"] = true @@ -3800,6 +3802,9 @@ files { MAME_DIR .. "src/mame/video/zx8301.h", MAME_DIR .. "src/mame/machine/zx8302.cpp", MAME_DIR .. "src/mame/machine/zx8302.h", + MAME_DIR .. "src/mame/drivers/tsconf.cpp", + MAME_DIR .. "src/mame/includes/tsconf.h", + MAME_DIR .. "src/mame/machine/tsconf.cpp", } createMESSProjects(_target, _subtarget, "siemens") diff --git a/src/devices/machine/glukrs.cpp b/src/devices/machine/glukrs.cpp new file mode 100644 index 00000000000..e5cbf3f1424 --- /dev/null +++ b/src/devices/machine/glukrs.cpp @@ -0,0 +1,60 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/*************************************************************************** + + Mr Gluk Reset Service + + Refs: + https://zxart.ee/spa/software/prikladnoe-po/electronics/pzu/mr-gluk-reset-service-663/mr-gluk-reset-service-663/action:viewFile/id:250389/fileId:814961/ + +****************************************************************************/ + +#include "emu.h" +#include "glukrs.h" + +glukrs_device::glukrs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, GLUKRS, tag, owner, clock), + device_rtc_interface(mconfig, *this), + m_nvram(*this, "nvram") {} + +void glukrs_device::device_add_mconfig(machine_config &config) +{ + NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_1); +} + +void glukrs_device::device_start() +{ + m_nvram->set_base(&m_cmos, sizeof(m_cmos)); + + m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(glukrs_device::timer_callback), this)); + m_timer->adjust(attotime::from_hz(clock() / XTAL(32'768)), 0, attotime::from_hz(clock() / XTAL(32'768))); +} + +u8 glukrs_device::read(offs_t address) +{ + return m_cmos[address]; +} + +void glukrs_device::write(offs_t address, u8 data) +{ + m_cmos[address] = data; +} + +void glukrs_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + m_cmos[0x00] = convert_to_bcd(second); + m_cmos[0x02] = convert_to_bcd(minute); + m_cmos[0x04] = convert_to_bcd(hour); + m_cmos[0x06] = convert_to_bcd(day_of_week); + m_cmos[0x07] = convert_to_bcd(day); + m_cmos[0x08] = convert_to_bcd(month); + m_cmos[0x09] = convert_to_bcd(year % 100); +} + +TIMER_CALLBACK_MEMBER(glukrs_device::timer_callback) +{ + advance_seconds(); +} + +// device type definition +DEFINE_DEVICE_TYPE(GLUKRS, glukrs_device, "glukrs", "Mr Gluk Reset Service") diff --git a/src/devices/machine/glukrs.h b/src/devices/machine/glukrs.h new file mode 100644 index 00000000000..fc088bc779e --- /dev/null +++ b/src/devices/machine/glukrs.h @@ -0,0 +1,35 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub + +#ifndef MAME_MACHINE_GLUKRS_H +#define MAME_MACHINE_GLUKRS_H + +#pragma once + +#include "machine/nvram.h" +#include "dirtc.h" + +class glukrs_device : public device_t, + public device_rtc_interface +{ +public: + glukrs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32'768); + + u8 read(offs_t address); + void write(offs_t address, u8 data); + + TIMER_CALLBACK_MEMBER(timer_callback); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override; + +private: + u8 m_cmos[0x100]; + required_device m_nvram; + emu_timer *m_timer; +}; + +DECLARE_DEVICE_TYPE(GLUKRS, glukrs_device) +#endif // MAME_MACHINE_GLUKRS_H diff --git a/src/devices/machine/tsconfdma.cpp b/src/devices/machine/tsconfdma.cpp new file mode 100644 index 00000000000..5ba61e33cd3 --- /dev/null +++ b/src/devices/machine/tsconfdma.cpp @@ -0,0 +1,195 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/********************************************************************** + + TS-Conf (ZX-Evolution) DMA Controller + +**********************************************************************/ + +#include "emu.h" +#include "tsconfdma.h" + +tsconfdma_device::tsconfdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, TSCONF_DMA, tag, owner, clock), + m_in_mreq_cb(*this), + m_out_mreq_cb(*this), + m_in_mspi_cb(*this), + m_out_cram_cb(*this) +{ +} + +void tsconfdma_device::device_start() +{ + m_in_mreq_cb.resolve_safe(0); + m_out_mreq_cb.resolve_safe(); + m_in_mspi_cb.resolve_safe(0); + m_out_cram_cb.resolve_safe(); + + save_item(NAME(m_ready)); + save_item(NAME(m_address_s)); + save_item(NAME(m_address_d)); + save_item(NAME(m_block_len)); + save_item(NAME(m_block_num)); + save_item(NAME(m_align_s)); + save_item(NAME(m_align_d)); + save_item(NAME(m_align)); +} + +void tsconfdma_device::device_reset() +{ + m_block_num = 0; + m_ready = ASSERT_LINE; +} + +int tsconfdma_device::is_ready() +{ + return m_ready; +} + +void tsconfdma_device::set_saddr_l(u8 addr_l) +{ + m_address_s = (m_address_s & 0xffffff00) | (addr_l & 0xfe); +} + +void tsconfdma_device::set_saddr_h(u8 addr_h) +{ + m_address_s = (m_address_s & 0xffffc0ff) | ((addr_h & 0x3f) << 8); +} + +void tsconfdma_device::set_saddr_x(u8 addr_x) +{ + m_address_s = (m_address_s & 0x0003fff) | (addr_x << 14); +} + +void tsconfdma_device::set_daddr_l(u8 addr_l) +{ + m_address_d = (m_address_d & 0xffffff00) | (addr_l & 0xfe); +} + +void tsconfdma_device::set_daddr_h(u8 addr_h) +{ + m_address_d = (m_address_d & 0xffffc0ff) | ((addr_h & 0x3f) << 8); +} + +void tsconfdma_device::set_daddr_x(u8 addr_x) +{ + m_address_d = (m_address_d & 0x0003fff) | (addr_x << 14); +} + +void tsconfdma_device::set_block_len(u8 len) +{ + // 1..256 + m_block_len = len; +} + +void tsconfdma_device::set_block_num_l(u8 num_l) +{ + m_block_num = (m_block_num & 0xff00) | num_l; +} + +void tsconfdma_device::set_block_num_h(u8 num_h) +{ + // 1..1025 * 2 + m_block_num = (m_block_num & 0x00ff) | ((num_h & 0x03) << 8); +} + +void tsconfdma_device::start_tx(u8 dev, bool s_align, bool d_align, bool align_opt) +{ + m_ready = CLEAR_LINE; + m_align = align_opt ? 512 : 256; + + // TODO Transfers 2 byte/cycle at 7MHz + switch (dev) + { + case 0b0001: // Mem -> Mem + for (u16 block = 0; block <= m_block_num; block++) + { + auto s_addr = m_address_s; + auto d_addr = m_address_d; + for (u16 len = 0; len <= m_block_len; len++) + { + m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr)); + s_addr += 2; + d_addr += 2; + } + m_address_s = s_align ? (m_address_s + m_align) : s_addr; + m_address_d = d_align ? (m_address_d + m_align) : d_addr; + } + break; + + case 0b0010: // SPI -> Mem + for (u16 block = 0; block <= m_block_num; block++) + { + auto d_addr = m_address_d; + for (u16 len = 0; len <= m_block_len; len++) + { + m_out_mreq_cb(d_addr, m_in_mspi_cb()); + d_addr += 2; + } + m_address_d = d_align ? (m_address_d + m_align) : d_addr; + } + break; + + case 0b0100: // Fill + for (u16 block = 0; block <= m_block_num; block++) + { + u16 data = m_in_mreq_cb(m_address_s); + auto d_addr = m_address_d; + for (u16 len = 0; len <= m_block_len; len++) + { + m_out_mreq_cb(d_addr, data); + d_addr += 2; + } + m_address_d = d_align ? (m_address_d + m_align) : d_addr; + } + break; + + case 0b1001: // Blt -> Mem + for (u16 block = 0; block <= m_block_num; block++) + { + auto s_addr = m_address_s; + auto d_addr = m_address_d; + for (u16 len = 0; len <= m_block_len; len++) + { + u16 d_val = m_in_mreq_cb(d_addr); + if (d_val != 0) + { + m_out_mreq_cb(d_addr, m_in_mreq_cb(s_addr)); + } + s_addr += 2; + d_addr += 2; + } + m_address_s = s_align ? (m_address_s + m_align) : s_addr; + m_address_d = d_align ? (m_address_d + m_align) : d_addr; + } + break; + + case 0b1100: // RAM -> CRAM + for (u16 block = 0; block <= m_block_num; block++) + { + auto s_addr = m_address_s; + auto d_addr = m_address_d; + for (u16 len = 0; len <= m_block_len; len++) + { + m_out_cram_cb(d_addr, m_in_mreq_cb(s_addr)); + s_addr += 2; + d_addr += 2; + } + m_address_s = s_align ? (m_address_s + m_align) : s_addr; + m_address_d = d_align ? (m_address_d + m_align) : d_addr; + } + break; + + //case 0b1101: // RAM -> SFILE + // break; + + default: + logerror("'tsdma': TX %02X: %06X (%02X:%04X) -> %06X\n", dev, m_address_s, m_block_len, m_block_num, m_address_d); + break; + } + + m_ready = ASSERT_LINE; +} + +// device type definition +DEFINE_DEVICE_TYPE(TSCONF_DMA, tsconfdma_device, "tsconfdma", "TS-Conf DMA Controller") diff --git a/src/devices/machine/tsconfdma.h b/src/devices/machine/tsconfdma.h new file mode 100644 index 00000000000..dc8c246b83a --- /dev/null +++ b/src/devices/machine/tsconfdma.h @@ -0,0 +1,58 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/*************************************************************************** + + TS-Conf (ZX-Evolution) DMA + +***************************************************************************/ + +#ifndef MAME_MACHINE_TSCONF_DMA_H +#define MAME_MACHINE_TSCONF_DMA_H + +#pragma once + +class tsconfdma_device : public device_t +{ +public: + tsconfdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto in_mreq_callback() { return m_in_mreq_cb.bind(); } + auto out_mreq_callback() { return m_out_mreq_cb.bind(); } + auto in_spireq_callback() { return m_in_mspi_cb.bind(); } + auto out_cram_callback() { return m_out_cram_cb.bind(); } + + int is_ready(); + + void set_saddr_l(uint8_t addr_l); + void set_saddr_h(uint8_t addr_h); + void set_saddr_x(uint8_t addr_x); + void set_daddr_l(uint8_t addr_l); + void set_daddr_h(uint8_t addr_h); + void set_daddr_x(uint8_t addr_x); + void set_block_len(uint8_t len); + void set_block_num_l(uint8_t num_l); + void set_block_num_h(uint8_t num_h); + void start_tx(uint8_t dev, bool s_align, bool d_align, bool blitting_opt); + +private: + virtual void device_start() override; + virtual void device_reset() override; + + devcb_read16 m_in_mreq_cb; + devcb_write16 m_out_mreq_cb; + devcb_read16 m_in_mspi_cb; + devcb_write16 m_out_cram_cb; + + u8 m_ready; + + offs_t m_address_s; + offs_t m_address_d; + u8 m_block_len; + u16 m_block_num; + bool m_align_s; + bool m_align_d; + u16 m_align; +}; + +DECLARE_DEVICE_TYPE(TSCONF_DMA, tsconfdma_device) +#endif // MAME_MACHINE_TSCONF_DMA_H diff --git a/src/mame/drivers/atm.cpp b/src/mame/drivers/atm.cpp index 7786ccd339e..1bf5e85ffb0 100644 --- a/src/mame/drivers/atm.cpp +++ b/src/mame/drivers/atm.cpp @@ -127,15 +127,15 @@ void atm_state::atm_mem(address_map &map) void atm_state::atm_io(address_map &map) { map.unmap_value_high(); - map(0x001f, 0x001f).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)).mirror(0xff00); - map(0x003f, 0x003f).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)).mirror(0xff00); - map(0x005f, 0x005f).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)).mirror(0xff00); - map(0x007f, 0x007f).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)).mirror(0xff00); - map(0x00fe, 0x00fe).rw(FUNC(atm_state::spectrum_port_fe_r), FUNC(atm_state::spectrum_port_fe_w)).select(0xff00); - map(0x00ff, 0x00ff).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)).mirror(0xff00); - map(0x4000, 0x4000).w(FUNC(atm_state::atm_port_7ffd_w)).mirror(0x3ffd); - map(0x8000, 0x8000).w("ay8912", FUNC(ay8910_device::data_w)).mirror(0x3ffd); - map(0xc000, 0xc000).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0x3ffd); + map(0x001f, 0x001f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)); + map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)); + map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)); + map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)); + map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(atm_state::spectrum_port_fe_r), FUNC(atm_state::spectrum_port_fe_w)); + map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)); + map(0x4000, 0x4000).mirror(0x3ffd).w(FUNC(atm_state::atm_port_7ffd_w)); + map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w)); + map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); } void atm_state::atm_switch(address_map &map) diff --git a/src/mame/drivers/pentagon.cpp b/src/mame/drivers/pentagon.cpp index cef525a20ee..61428d4e778 100644 --- a/src/mame/drivers/pentagon.cpp +++ b/src/mame/drivers/pentagon.cpp @@ -205,15 +205,15 @@ void pentagon_state::pentagon_mem(address_map &map) void pentagon_state::pentagon_io(address_map &map) { map.unmap_value_high(); - map(0x0000, 0x0000).w(FUNC(pentagon_state::pentagon_port_7ffd_w)).mirror(0x7ffd); // (A15 | A1) == 0 - map(0x001f, 0x001f).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)).mirror(0xff00); - map(0x003f, 0x003f).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)).mirror(0xff00); - map(0x005f, 0x005f).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)).mirror(0xff00); - map(0x007f, 0x007f).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)).mirror(0xff00); - map(0x00fe, 0x00fe).rw(FUNC(pentagon_state::spectrum_port_fe_r), FUNC(pentagon_state::spectrum_port_fe_w)).select(0xff00); - map(0x00ff, 0x00ff).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)).mirror(0xff00); - map(0x8000, 0x8000).w("ay8912", FUNC(ay8910_device::data_w)).mirror(0x3ffd); - map(0xc000, 0xc000).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0x3ffd); + map(0x0000, 0x0000).mirror(0x7ffd).w(FUNC(pentagon_state::pentagon_port_7ffd_w)); // (A15 | A1) == 0 + map(0x001f, 0x001f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)); + map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)); + map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)); + map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)); + map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(pentagon_state::spectrum_port_fe_r), FUNC(pentagon_state::spectrum_port_fe_w)); + map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)); + map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w)); + map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); } void pentagon_state::pentagon_switch(address_map &map) diff --git a/src/mame/drivers/scorpion.cpp b/src/mame/drivers/scorpion.cpp index e94e03609fc..95174090351 100644 --- a/src/mame/drivers/scorpion.cpp +++ b/src/mame/drivers/scorpion.cpp @@ -193,16 +193,16 @@ void scorpion_state::scorpion_mem(address_map &map) void scorpion_state::scorpion_io(address_map &map) { map.unmap_value_high(); - map(0x001f, 0x001f).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)).mirror(0xff00); - map(0x003f, 0x003f).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)).mirror(0xff00); - map(0x005f, 0x005f).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)).mirror(0xff00); - map(0x007f, 0x007f).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)).mirror(0xff00); - map(0x00fe, 0x00fe).rw(FUNC(scorpion_state::spectrum_port_fe_r), FUNC(scorpion_state::spectrum_port_fe_w)).select(0xff00); - map(0x00ff, 0x00ff).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)).mirror(0xff00); - map(0x4021, 0x4021).w(FUNC(scorpion_state::scorpion_port_7ffd_w)).mirror(0x3fdc); - map(0x8021, 0x8021).w("ay8912", FUNC(ay8910_device::data_w)).mirror(0x3fdc); - map(0xc021, 0xc021).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0x3fdc); - map(0x0021, 0x0021).w(FUNC(scorpion_state::scorpion_port_1ffd_w)).mirror(0x3fdc); + map(0x001f, 0x001f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)); + map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)); + map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)); + map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)); + map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(scorpion_state::spectrum_port_fe_r), FUNC(scorpion_state::spectrum_port_fe_w)); + map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)); + map(0x4021, 0x4021).mirror(0x3fdc).w(FUNC(scorpion_state::scorpion_port_7ffd_w)); + map(0x8021, 0x8021).mirror(0x3fdc).w("ay8912", FUNC(ay8910_device::data_w)); + map(0xc021, 0xc021).mirror(0x3fdc).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); + map(0x0021, 0x0021).mirror(0x3fdc).w(FUNC(scorpion_state::scorpion_port_1ffd_w)); } void scorpion_state::scorpion_switch(address_map &map) diff --git a/src/mame/drivers/spec128.cpp b/src/mame/drivers/spec128.cpp index c9fb9801b32..8a12f04b145 100644 --- a/src/mame/drivers/spec128.cpp +++ b/src/mame/drivers/spec128.cpp @@ -249,10 +249,10 @@ uint8_t spectrum_128_state::spectrum_128_ula_r() void spectrum_128_state::spectrum_128_io(address_map &map) { map(0x0000, 0xffff).rw(m_exp, FUNC(spectrum_expansion_slot_device::iorq_r), FUNC(spectrum_expansion_slot_device::iorq_w)); - map(0x0000, 0x0000).rw(FUNC(spectrum_128_state::spectrum_port_fe_r), FUNC(spectrum_128_state::spectrum_port_fe_w)).select(0xfffe); - map(0x0001, 0x0001).w(FUNC(spectrum_128_state::spectrum_128_port_7ffd_w)).select(0x7ffc); // (A15 | A1) == 0, note: reading from this port does write to it by value from data bus - map(0x8000, 0x8000).w("ay8912", FUNC(ay8910_device::data_w)).mirror(0x3ffd); - map(0xc000, 0xc000).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0x3ffd); + map(0x0000, 0x0000).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_port_fe_r), FUNC(spectrum_128_state::spectrum_port_fe_w)); + map(0x0001, 0x0001).select(0x7ffc).w(FUNC(spectrum_128_state::spectrum_128_port_7ffd_w)); // (A15 | A1) == 0, note: reading from this port does write to it by value from data bus + map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w)); + map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)); map(0x0001, 0x0001).r(FUNC(spectrum_128_state::spectrum_128_ula_r)); // .mirror(0xfffe); } diff --git a/src/mame/drivers/spectrum.cpp b/src/mame/drivers/spectrum.cpp index 7f945db26c1..621e1ddb9c2 100644 --- a/src/mame/drivers/spectrum.cpp +++ b/src/mame/drivers/spectrum.cpp @@ -509,14 +509,14 @@ The function decodes the ports appropriately */ void spectrum_state::spectrum_io(address_map &map) { map(0x0000, 0xffff).w(m_exp, FUNC(spectrum_expansion_slot_device::iorq_w)); - map(0x00, 0x00).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w)).select(0xfffe); - map(0x01, 0x01).r(FUNC(spectrum_state::spectrum_port_ula_r)).select(0xfffe); + map(0x00, 0x00).select(0xfffe).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w)); + map(0x01, 0x01).select(0xfffe).r(FUNC(spectrum_state::spectrum_port_ula_r)); } void spectrum_state::spectrum_clone_io(address_map &map) { map(0x0000, 0xffff).rw(m_exp, FUNC(spectrum_expansion_slot_device::iorq_r), FUNC(spectrum_expansion_slot_device::iorq_w)); - map(0x00, 0x00).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w)).select(0xfffe); + map(0x00, 0x00).select(0xfffe).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w)); map(0x01, 0x01).r(FUNC(spectrum_state::spectrum_clone_port_ula_r)); // .mirror(0xfffe); } diff --git a/src/mame/drivers/tsconf.cpp b/src/mame/drivers/tsconf.cpp new file mode 100644 index 00000000000..b727b91301d --- /dev/null +++ b/src/mame/drivers/tsconf.cpp @@ -0,0 +1,296 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/*************************************************************************** + + TS-Configuration (ZX Evolution) machine driver. + Implementation: Revision C / 5-bit VDAC + + Hobby computer ZX Evolution is Spectrum-compatible with extensions. + + Hardware (ZX Evolution): + - Z80 3.5 MHz (classic mode)/ 7 MHz (turbo mode without CPU wait circles)/ 14 MHz (mega turbo with CPU wait circles); + - 4 Mb RAM, 512Kb ROM; + - MiniITX board (172x170mm), 2 ZXBUS slots, power ATX or +5,+12V; + - Based on fpga (Altera EP1K50); + - Peripheral MCU ATMEGA128; + - PS/2 keyboard and mouse support; + - Floppy (WDC1793) Beta-disk compatible interface, IDE (one channel, up to 2 devices on master/slave mode), SD(HC) card, RS232; + - Sound: AY, Beeper, Covox (PWM); + - Real-time clock. + + Features (TS-Configuration): + - Resolutions: 360x288, 320x240, 320x200, 256x192 + - Hardware scrolled graphic planes + - 256 and 16 indexed colors per pixel + - Programmable color RAM with RGB555 color space and 256 cells + - Text mode with loadable font and hardware vertical scroll + - Up to 256 graphic screens + + - Up to 85 sprites per line + - Sprites sized from 8x8 to 64x64 pixels + - Up to 3 sprite planes + - Up to 2 tile planes with 8x8 pixels tiles + - Up to 16 palettes for sprites per line + - Up to 4 palettes for tiles per line for each tile plane + + - DRAM-to-Device, Device-to-DRAM and DRAM-to-DRAM DMA Controller + + Refs: + ZxEvo: http://nedopc.com/zxevo/zxevo_eng.php + Principal scheme (rev. C) :: http://nedopc.com/zxevo/zxevo_sch_revc.pdf + Montage scheme (rev. C) :: http://nedopc.com/zxevo/zxevo_mon_revc.pdf + TsConf: https://github.com/tslabs/zx-evo/blob/master/pentevo/docs/TSconf/tsconf_en.md + https://github.com/tslabs/zx-evo/raw/master/pentevo/docs/TSconf/TSconf.xls + FAQ-RUS: https://forum.tslabs.info/viewtopic.php?f=35&t=157 + ROM: https://github.com/tslabs/zx-evo/blob/master/pentevo/rom/bin/ts-bios.rom (validated on: 2021-12-14) + + HowTo: + # Use ts-bios.rom above. You also need tr-dos roms which simpliest(?) to get from pentagon. + # Create SD image "wc.img" + # Copy WC files from archive https://github.com/tslabs/zx-evo/blob/master/pentevo/soft/WC/wc.zip + # Tech Demos (currently *.spg only): http://prods.tslabs.info/index.php?t=4 + $ chdman createhd -i wc.img -o wc.chd -c none + $ mame tsconf -hard wc.chd + # BIOS Setup loads on fresh setup (return to BIOS: RShift+F3) + # Change "Reset To: BD boot.$c" + # Reset (F3) + # Enable keyboard: MAME Setup (Tab) > Keyboard Mode > AT Keyboard: Enabled + + TODO: + - Interrupts + - Sprites + - Sound + - ZX-Mode locks + - CPU frequency + - Timings + - Ram cache + - VDos + - Many more... + + ****************************************************************************/ + +#include "emu.h" +#include "includes/tsconf.h" + +TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_txt) +{ + u8 *m_row_location = &m_ram->pointer()[(m_regs[V_PAGE] << 14) + (tile_index / tilemap.cols() * 256)]; + u8 col = tile_index % tilemap.cols(); + u8 symbol = m_row_location[col]; + tileinfo.set(1, symbol, 0, 0); +} + +template +TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_16c) +{ + u8 col_offset = (tile_index % tilemap.cols()) << 1; + u16 row_offset = (((tile_index / tilemap.cols()) << 1) + Layer) * 64 * 2; + + u8 *tile_info_addr = &m_ram->pointer()[(m_regs[T_MAP_PAGE] << 14) + row_offset + col_offset]; + u8 hi = tile_info_addr[1]; + + u16 tile = ((u16(hi) & 0x0f) << 8) | tile_info_addr[0]; + tile = tile / tilemap.cols() * 64 * 8 + (tile % tilemap.cols()); + u8 pal = (BIT(m_regs[PAL_SEL], 4 + Layer * 2, 2) << 2) | BIT(hi, 4, 2); + if (BIT(hi, 6, 2)) + { + logerror("FIXME - FLIP Case\n"); + } + tileinfo.set(2 + Layer, tile, pal, 0); +} + +TILE_GET_INFO_MEMBER(tsconf_state::get_sprite_info_16c) +{ + tileinfo.set(4, tile_index, 0, 0); +} + +void tsconf_state::tsconf_mem(address_map &map) +{ + map(0x0000, 0x3fff).bankr("bank1").w(FUNC(tsconf_state::tsconf_bank_w<0>)); + map(0x4000, 0x7fff).bankr("bank2").w(FUNC(tsconf_state::tsconf_bank_w<1>)); + map(0x8000, 0xbfff).bankr("bank3").w(FUNC(tsconf_state::tsconf_bank_w<2>)); + map(0xc000, 0xffff).bankr("bank4").w(FUNC(tsconf_state::tsconf_bank_w<3>)); +} + +void tsconf_state::tsconf_io(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x0000).mirror(0x7ffd).w(FUNC(tsconf_state::tsconf_port_7ffd_w)); + map(0x001f, 0x001f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::status_r), FUNC(beta_disk_device::command_w)); + map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w)); + map(0x0057, 0x0057).mirror(0xff00).rw(FUNC(tsconf_state::tsconf_port_57_zctr_r), FUNC(tsconf_state::tsconf_port_57_zctr_w)); // spi config + map(0x0077, 0x0077).mirror(0xff00).rw(FUNC(tsconf_state::tsconf_port_77_zctr_r), FUNC(tsconf_state::tsconf_port_77_zctr_w)); // spi data + map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w)); + map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w)); + map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(tsconf_state::spectrum_port_fe_r), FUNC(tsconf_state::tsconf_port_fe_w)); + map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w)); + map(0x00af, 0x00af).select(0xff00).rw(FUNC(tsconf_state::tsconf_port_xxaf_r), FUNC(tsconf_state::tsconf_port_xxaf_w)); + map(0x8ff7, 0x8ff7).select(0x7000).w(FUNC(tsconf_state::tsconf_port_f7_w)); // 3:bff7 5:dff7 6:eff7 + map(0xbff7, 0xbff7).r(FUNC(tsconf_state::tsconf_port_f7_r)); +} + +void tsconf_state::tsconf_switch(address_map &map) +{ + map(0x0000, 0x3fff).r(FUNC(tsconf_state::beta_neutral_r)); // Overlap with next because we want real addresses on the 3e00-3fff range + map(0x3d00, 0x3dff).r(FUNC(tsconf_state::beta_enable_r)); + map(0x4000, 0xffff).r(FUNC(tsconf_state::beta_disable_r)); +} + +template +void tsconf_state::tsconf_bank_w(offs_t offset, u8 data) +{ + tsconf_state::ram_bank_write(Bank, offset, data); +} + +static const gfx_layout spectrum_charlayout = +{ + 8, 8, /* 8 x 8 characters */ + 96, /* 96 characters */ + 1, /* 1 bits per pixel */ + {0}, /* no bitplanes */ + /* x offsets */ + {STEP8(0, 1)}, + /* y offsets */ + {STEP8(0, 8)}, + 8 * 8 /* every char takes 8 bytes */ +}; + +static const gfx_layout tsconf_charlayout = +{ + 8, + 8, + 256, + 1, + {0}, + {STEP8(0, 1)}, + {STEP8(0, 8)}, + 8 * 8 +}; + +static const gfx_layout tsconf_tile_16cpp_layout = +{ + 8, + 8, + 64 * 64 * 8, + 4, + {STEP4(0, 1)}, + {STEP8(0, 4)}, + {STEP8(0, 256 * 8)}, + // Much more tiles when needed. Because tiles are in RAW formut but we don't know region properties. + 8 * 4 +}; + +static GFXDECODE_START(gfx_tsconf) + GFXDECODE_ENTRY("maincpu", 0x1fd00, spectrum_charlayout, 0xf7, 1) + GFXDECODE_ENTRY("maincpu", 0, tsconf_charlayout, 0xf7, 1) // TXT + GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 255) // T0 16cpp + GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 255) // T1 16cpp + GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 255) // Sprites 16cpp +GFXDECODE_END + +void tsconf_state::video_start() +{ + spectrum_128_state::video_start(); + + m_ts_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_txt)), TILEMAP_SCAN_ROWS, 8, 8, 128, 64); + m_ts_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<0>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); + m_ts_tilemap[1]->set_transparent_pen(0); + m_ts_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<1>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); + m_ts_tilemap[2]->set_transparent_pen(0); + m_ts_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_sprite_info_16c)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); + m_ts_tilemap[3]->set_transparent_pen(0); +} + +void tsconf_state::machine_start() +{ + save_item(NAME(m_regs)); + // TODO save'm'all! +} + +void tsconf_state::machine_reset() +{ + u8 *messram = m_ram->pointer(); + m_program = &m_maincpu->space(AS_PROGRAM); + + m_ram_0000 = nullptr; + + m_port_f7_ext = DISABLED; + + m_regs[V_CONFIG] = 0x00; + m_regs[V_PAGE] = 0x05; + m_regs[G_X_OFFS_L] = 0x00; + m_regs[G_X_OFFS_H] &= 0xfe; // xxxxxxx0 + m_regs[G_Y_OFFS_L] = 0x00; + m_regs[G_Y_OFFS_H] &= 0xfe; // xxxxxxx0 + m_regs[TS_CONFIG] &= 0x03; // 000000xx + m_regs[PAL_SEL] = 0x0f; + m_regs[PAGE0] = 0x00; + m_regs[PAGE1] = 0x05; + m_regs[PAGE2] = 0x02; + m_regs[PAGE3] = 0x00; + m_regs[FMAPS] &= 0xef; // xxx0xxxx + m_regs[SYS_CONFIG] = 0x00; + m_regs[MEM_CONFIG] = 0x04; + m_regs[HS_INT] = 0x01; // 00000001 + m_regs[VS_INT_L] = 0x00; // 00000001 + m_regs[VS_INT_H] = 0x00; // 0000xxx0 + // FDDVirt = 0x00; // 0000xxx0 + m_regs[INT_MASK] = 0x01; // xxxxx001 + // CacheConfig = 0x01; // xxxxx001 + + if (m_beta->started()) + m_beta->enable(); + + memset(messram, 0, 4096 * 1024); + + m_port_7ffd_data = 0; + + m_zctl_cs = 1; + m_zctl_di = 0xff; + + tsconf_update_bank1(); + + m_keyboard->write(0xff); + while (m_keyboard->read() != 0) { /* invalidate buffer */ } +} + +void tsconf_state::tsconf(machine_config &config) +{ + spectrum_128(config); + config.device_remove("exp"); + config.device_remove("palette"); + + //m_maincpu->set_clock(XTAL(14'000'000)); + m_maincpu->set_addrmap(AS_PROGRAM, &tsconf_state::tsconf_mem); + m_maincpu->set_addrmap(AS_IO, &tsconf_state::tsconf_io); + m_maincpu->set_addrmap(AS_OPCODES, &tsconf_state::tsconf_switch); + + m_ram->set_default_size("4096K"); + + GLUKRS(config, m_glukrs); + + TSCONF_DMA(config, m_dma, XTAL(14'000'000) / 2); + m_dma->in_mreq_callback().set(FUNC(tsconf_state::ram_read16)); + m_dma->out_mreq_callback().set(FUNC(tsconf_state::ram_write16)); + m_dma->in_spireq_callback().set(FUNC(tsconf_state::spi_read16)); + m_dma->out_cram_callback().set(FUNC(tsconf_state::cram_write16)); + + BETA_DISK(config, m_beta, 0); + SPI_SDCARD(config, m_sdcard, 0); + m_sdcard->spi_miso_callback().set(FUNC(tsconf_state::tsconf_spi_miso_w)); + + PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256); + m_screen->set_raw(X1_128_SINCLAIR / 2.5, 448, 0, 360, 320, 0, 288); + subdevice("gfxdecode")->set_info(gfx_tsconf); + RAM(config, m_cram).set_default_size("512").set_default_value(0); + + AT_KEYB(config, m_keyboard, pc_keyboard_device::KEYBOARD_TYPE::AT, 3); +} + +ROM_START(tsconf) + ROM_REGION(0x090000, "maincpu", ROMREGION_ERASEFF) // 16KB ROM + ROM_LOAD("ts-bios.rom", 0x010000, 0x10000, CRC(b060b0d9) SHA1(820d3539de115141daff220a3cb733fc880d1bab)) +ROM_END + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 2011, tsconf, spec128, 0, tsconf, spec_plus, tsconf_state, empty_init, "NedoPC, TS-Labs", "ZX Evolution TS-Configuration", MACHINE_NO_SOUND | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_TIMING ) diff --git a/src/mame/includes/spectrum.h b/src/mame/includes/spectrum.h index c9a9d153c29..e25dfc5c5b5 100644 --- a/src/mame/includes/spectrum.h +++ b/src/mame/includes/spectrum.h @@ -159,7 +159,7 @@ protected: uint8_t spectrum_clone_port_ula_r(); void spectrum_palette(palette_device &palette) const; - uint32_t screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + virtual uint32_t screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); DECLARE_WRITE_LINE_MEMBER(screen_vblank_spectrum); INTERRUPT_GEN_MEMBER(spec_interrupt); @@ -210,7 +210,8 @@ protected: optional_ioport m_io_joy2; void spectrum_UpdateBorderBitmap(); - void spectrum_UpdateScreenBitmap(bool eof = false); + virtual u16 get_border_color(); + virtual void spectrum_UpdateScreenBitmap(bool eof = false); inline unsigned char get_display_color(unsigned char color, int invert); inline void spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color); diff --git a/src/mame/includes/tsconf.h b/src/mame/includes/tsconf.h new file mode 100644 index 00000000000..d8700b3f7ae --- /dev/null +++ b/src/mame/includes/tsconf.h @@ -0,0 +1,191 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub +/***************************************************************************** + * + * includes/tsconfig.h + * + ****************************************************************************/ +#ifndef MAME_INCLUDES_TSCONF_H +#define MAME_INCLUDES_TSCONF_H + +#pragma once + +#include "machine/beta.h" +#include "machine/glukrs.h" +#include "machine/pckeybrd.h" +#include "machine/spi_sdcard.h" +#include "machine/tsconfdma.h" +#include "spectrum.h" +#include "tilemap.h" + +class tsconf_state : public spectrum_128_state +{ +public: + tsconf_state(const machine_config &mconfig, device_type type, const char *tag) + : spectrum_128_state(mconfig, type, tag), + m_p_rom(*this, "maincpu"), + m_bank1(*this, "bank1"), m_bank2(*this, "bank2"), m_bank3(*this, "bank3"), m_bank4(*this, "bank4"), + m_keyboard(*this, "pc_keyboard"), + m_beta(*this, BETA_DISK_TAG), + m_dma(*this, "dma"), + m_sdcard(*this, "sdcard"), + m_glukrs(*this, "glukrs"), + m_palette(*this, "palette"), + m_gfxdecode(*this, "gfxdecode"), + m_cram(*this, "cram") + { + } + + void tsconf(machine_config &config); + +protected: + virtual void video_start() override; + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + enum gluk_ext : u8 + { + CONF_VERSION = 0x00, + BOOTLOADER_VERSION = 0x01, + PS2KEYBOARDS_LOG = 0x02, + RDCFG = 0x03, + CONFIG = 0x0e, + SPIFL = 0x10, + + DISABLED = 0xff + }; + + enum tsconf_regs : u8 + { + V_CONFIG = 0x00, + V_PAGE = 0x01, + + G_X_OFFS_L = 0x02, + G_X_OFFS_H = 0x03, + G_Y_OFFS_L = 0x04, + G_Y_OFFS_H = 0x05, + + TS_CONFIG = 0x06, + PAL_SEL = 0x07, + + BORDER = 0x0f, + PAGE0 = 0x10, + PAGE1 = 0x11, + PAGE2 = 0x12, + PAGE3 = 0x13, + + FMAPS = 0x15, + T_MAP_PAGE = 0x16, + T0_G_PAGE = 0x17, + T1_G_PAGE = 0x18, + SG_PAGE = 0x19, + + DMAS_ADDRESS_L = 0x1a, + DMAS_ADDRESS_H = 0x1b, + DMAS_ADDRESS_X = 0x1c, + DMAD_ADDRESS_L = 0x1d, + DMAD_ADDRESS_H = 0x1e, + DMAD_ADDRESS_X = 0x1f, + + SYS_CONFIG = 0x20, + MEM_CONFIG = 0x21, + HS_INT = 0x22, + VS_INT_L = 0x23, + VS_INT_H = 0x24, + + DMA_WAIT_PORT_DEV = 0x25, + DMA_LEN = 0x26, + DMA_CTRL = 0x27, + DMA_NUM_L = 0x28, + INT_MASK = 0x2a, + DMA_NUM_H = 0x2c, + + T0_X_OFFSER_L = 0x40, + T0_X_OFFSER_H = 0x41, + T0_Y_OFFSER_L = 0x42, + T0_Y_OFFSER_H = 0x43, + T1_X_OFFSER_L = 0x44, + T1_X_OFFSER_H = 0x45, + T1_Y_OFFSER_L = 0x46, + T1_Y_OFFSER_H = 0x47 + }; + + DECLARE_VIDEO_START(tsconf); + TILE_GET_INFO_MEMBER(get_tile_info_txt); + template + TILE_GET_INFO_MEMBER(get_tile_info_16c); + TILE_GET_INFO_MEMBER(get_sprite_info_16c); + + // Changing this consider to revert 'virtual' in spectrum.h + u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override; + void spectrum_UpdateScreenBitmap(bool eof = false) override; + void tsconf_palette(palette_device &palette) const; + u16 get_border_color() override; + void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void tsconf_update_video_mode(); + rectangle get_resolution_info(); + + void tsconf_port_7ffd_w(u8 data); + void tsconf_port_fe_w(offs_t offset, u8 data); + u8 tsconf_port_xxaf_r(offs_t reg); + void tsconf_port_xxaf_w(offs_t reg, u8 data); + u8 tsconf_port_77_zctr_r(offs_t reg); + void tsconf_port_77_zctr_w(offs_t reg, u8 data); + u8 tsconf_port_57_zctr_r(offs_t reg); + void tsconf_port_57_zctr_w(offs_t reg, u8 data); + void tsconf_spi_miso_w(u8 data); + u8 tsconf_port_f7_r(offs_t offset); + void tsconf_port_f7_w(offs_t offset, u8 data); + + void tsconf_update_bank1(); + u8 beta_neutral_r(offs_t offset); + u8 beta_enable_r(offs_t offset); + u8 beta_disable_r(offs_t offset); + + void tsconf_io(address_map &map); + void tsconf_mem(address_map &map); + void tsconf_switch(address_map &map); + + template + void tsconf_bank_w(offs_t offset, u8 data); + void ram_bank_write(u8 bank, offs_t offset, u8 data); + void ram_page_write(u8 page, offs_t offset, u8 data); + void cram_write(u16 offset, u8 data); + void cram_write16(offs_t offset, u16 data); + void ram_write16(offs_t offset, u16 data); + u16 ram_read16(offs_t offset); + u16 spi_read16(); + + u8 m_regs[0x100]; + + address_space *m_program; + required_region_ptr m_p_rom; + required_memory_bank m_bank1; + required_memory_bank m_bank2; + required_memory_bank m_bank3; + required_memory_bank m_bank4; + + required_device m_keyboard; + + required_device m_beta; + required_device m_dma; + required_device m_sdcard; + u8 m_zctl_di; + u8 m_zctl_cs; + + required_device m_glukrs; + gluk_ext m_port_f7_ext; + u8 m_port_f7_gluk_reg; + + optional_device m_palette; + required_device m_gfxdecode; + tilemap_t *m_ts_tilemap[4]; + required_device m_cram; +}; + +/*----------- defined in drivers/tsconf.c -----------*/ + +INPUT_PORTS_EXTERN(tsconf); + +#endif // MAME_INCLUDES_TSCONF_H diff --git a/src/mame/machine/tsconf.cpp b/src/mame/machine/tsconf.cpp new file mode 100644 index 00000000000..98cf851d4aa --- /dev/null +++ b/src/mame/machine/tsconf.cpp @@ -0,0 +1,653 @@ +// license:BSD-3-Clause +// copyright-holders:Andrei I. Holub + +#include "emu.h" +#include "includes/tsconf.h" + +#define PAGE4K(_r) ((_r) << 14) + +#define W0_RAM (BIT(m_regs[MEM_CONFIG], 3)) +#define NW0_MAP (BIT(m_regs[MEM_CONFIG], 2)) +#define W0_WE (BIT(m_regs[MEM_CONFIG], 1)) +#define ROM128 (BIT(m_regs[MEM_CONFIG], 0)) + +#define VM static_cast(BIT(m_regs[V_CONFIG], 0, 2)) + +static constexpr rectangle resolution_info[4] = { + rectangle(52, 256 + 51, 48, 192 + 47), // 52|256|52 x 48-192-48 + rectangle(20, 320 + 19, 44, 200 + 43), // 20|320|20 x 44-200-44 + rectangle(20, 320 + 19, 24, 240 + 23), // 20|320|20 x 24-240-24 + rectangle(0, 360 - 1, 0, 288 - 1) // 0|360|0 x 0-288-0 +}; + +enum v_mode : u8 +{ + VM_ZX = 0, + VM_16C, + VM_256C, + VM_TXT +}; + +// https://github.com/tslabs/zx-evo/blob/master/pentevo/vdac/vdac1/cpld/top.v +static constexpr u8 pwm_to_rgb[32] = { + 0, 10, 21, 31, 42, 53, 63, 74, + 85, 95, 106, 117, 127, 138, 149, 159, + 170, 181, 191, 202, 213, 223, 234, 245, + 255, 255, 255, 255, 255, 255, 255, 255}; + +static constexpr rgb_t from_pwm(u16 pwm15) +{ + return rgb_t(pwm_to_rgb[BIT(pwm15, 10, 5)], pwm_to_rgb[BIT(pwm15, 5, 5)], pwm_to_rgb[BIT(pwm15, 0, 5)]); +} + +rectangle tsconf_state::get_resolution_info() +{ + rectangle info = resolution_info[BIT(m_regs[V_CONFIG], 6, 2)]; + if (VM == VM_TXT) + { + info.set_origin(0, 0); + info.set_width(info.width() << 1); + } + return info; +} + +void tsconf_state::tsconf_palette(palette_device &palette) const +{ + rgb_t colors[256] = {0}; + palette.set_pen_colors(0, colors); +} + +void tsconf_state::tsconf_update_bank1() +{ + + //W0_WE + if (NW0_MAP) + { + m_ROMSelection = m_regs[PAGE0]; + } + else + { + /* ROM: 0-SYS, 1-DOS, 2-128, 3-48 */ + m_ROMSelection = m_beta->started() && m_beta->is_active() ? ROM128 : (0x02 | ROM128); + m_ROMSelection |= (m_regs[PAGE0] & 0xfc); + } + + uint8_t *rom0; + if (W0_RAM) + { + rom0 = m_ram->pointer() + PAGE4K(m_ROMSelection); + m_bank1->set_base(rom0); + } + else + { + rom0 = &m_p_rom[0x10000 + PAGE4K(m_ROMSelection & 0x1f)]; + m_bank1->set_base(rom0); + } + m_ram_0000 = W0_WE ? rom0 : nullptr; +} + +void tsconf_state::tsconf_update_video_mode() +{ + rectangle resolution = resolution_info[3]; + u8 *messram = m_ram->pointer(); + switch (VM) + { + case VM_TXT: // Text Mode + resolution = get_resolution_info(); + m_gfxdecode->gfx(1)->set_source(messram + PAGE4K(m_regs[V_PAGE] ^ 0x01)); + break; + case VM_ZX: // Zx + { + m_screen_location = messram + ((m_port_7ffd_data & 8) ? PAGE4K(7) : PAGE4K(5)); + break; + } + default: + break; + } + + m_screen->configure(resolution.width(), resolution.height(), resolution, HZ_TO_ATTOSECONDS(50)); +} + +uint32_t tsconf_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (m_screen_bitmap.valid()) + { + // Border + if (m_border_bitmap.valid()) + { + if (BIT(m_regs[V_CONFIG], 5) || VM != VM_ZX) + { + copyscrollbitmap(bitmap, m_border_bitmap, 0, nullptr, 0, nullptr, cliprect); + } + } + + // Main Graphics + rectangle resolution = get_resolution_info(); + if (!BIT(m_regs[V_CONFIG], 5)) + { + if (VM == VM_ZX) + { + // Zx palette is stored at 0xf0. Adjust bitmaps colors. + for (auto y = cliprect.top(); y <= cliprect.bottom(); y++) + { + u16 *bm = &m_screen_bitmap.pix(y, 0); + for (auto x = cliprect.left(); x <= cliprect.right(); x++) + { + *bm++ |= 0xf0; + } + } + spectrum_state::screen_update_spectrum(screen, bitmap, cliprect); + } + else + { + copyscrollbitmap(bitmap, m_screen_bitmap, 0, nullptr, 0, nullptr, resolution); + } + } + // Tiles & Sprites + // TODO layers + if (!BIT(m_regs[V_CONFIG], 4)) + { + if (BIT(m_regs[TS_CONFIG], 5)) + { + m_ts_tilemap[1]->draw(screen, bitmap, resolution, 0); + } + if (BIT(m_regs[TS_CONFIG], 6)) + { + m_ts_tilemap[2]->draw(screen, bitmap, resolution, 0); + } + if (BIT(m_regs[TS_CONFIG], 7)) + { + draw_sprites(screen, bitmap, resolution); + } + } + } + return 0; +} + +void tsconf_state::spectrum_UpdateScreenBitmap(bool eof) +{ + if (!BIT(m_regs[V_CONFIG], 5)) + { + if (VM == VM_ZX) + { + spectrum_state::spectrum_UpdateScreenBitmap(eof); + } + else if (!eof) + { + u8 pal_offset = m_regs[PAL_SEL] << 4; + rectangle resolution = get_resolution_info(); + if (VM == VM_TXT) + { + u8 *messram = m_ram->pointer(); + u16 y = m_screen->vpos(); + u8 *font_location = messram + PAGE4K(m_regs[V_PAGE] ^ 0x01); + u8 *text_location = messram + PAGE4K(m_regs[V_PAGE]) + (y / 8 * 256); // OFFSETs + u16 *bm = &m_screen_bitmap.pix(y, 0); + for (auto x = 0; x < resolution.width() / 8; x++) + { + u8 char_x = *(font_location + (*text_location * 8) + (y % 8)); + u8 font_color = *(text_location + 128) & 0x0f; + u8 bg_color = (*(text_location + 128) & 0xf0) >> 4; + for (auto i = 7; i >= 0; i--) + { + *bm++ = (BIT(char_x, i) ? font_color : bg_color) + pal_offset; + } + text_location++; + } + } + else + { + if (m_screen->vpos() >= resolution.top()) + { + u16 y = m_screen->vpos() - resolution.top(); + u32 offset = ((y + ((m_regs[G_Y_OFFS_H] & 1) << 8) + m_regs[G_Y_OFFS_L]) * 512) + + ((m_regs[G_X_OFFS_H] & 1) << 8) + m_regs[G_X_OFFS_L]; + if (VM == VM_16C) + { + // FIXME wouldn't work for odd offsets + offset >>= 1; + } + u8 *video_location = &m_ram->pointer()[PAGE4K(m_regs[V_PAGE]) + offset]; + u16 *bm = &m_screen_bitmap.pix(m_screen->vpos(), resolution.left()); + for (auto x = resolution.left(); x <= resolution.right(); x++) + { + u8 pix = *video_location; + if (VM == VM_16C) + { + *bm++ = (pix >> 4) + pal_offset; + *bm++ = (pix & 0x0f) + pal_offset; + x++; + } + else + { + *bm++ = pix; + } + video_location++; + } + } + } + } + } +} + +u16 tsconf_state::get_border_color() +{ + return m_regs[BORDER]; +} + +void tsconf_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + //u8 *messram = m_ram->pointer(); + //u8 *sprites_location = messram + PAGE4K(m_regs[SG_PAGE]); + for (u8 i = 0; i < 85; i++) + { + logerror("Draw Sprites ... TODO\n"); + } +} + +void tsconf_state::ram_bank_write(u8 bank, offs_t offset, u8 data) +{ + offs_t machine_addr = PAGE4K(bank) + offset; + offs_t fmap_addr = BIT(m_regs[FMAPS], 0, 4) << 12; + if (BIT(m_regs[FMAPS], 4) && (machine_addr >= fmap_addr) && (machine_addr < (fmap_addr + 512))) + { + cram_write(machine_addr - fmap_addr, data); + } + else if (bank > 0 || (W0_WE && W0_RAM)) + { + ram_page_write(m_regs[PAGE0 + bank], offset, data); + } +} + +void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data) +{ + u32 ram_addr = PAGE4K(page) + offset; + if (ram_addr >= PAGE4K(m_regs[T_MAP_PAGE]) && ram_addr < (PAGE4K(m_regs[T_MAP_PAGE] + 1))) + { + //TODO invalidate sprites, not entire map + m_ts_tilemap[1]->mark_all_dirty(); + m_ts_tilemap[2]->mark_all_dirty(); + } + else + { + if (ram_addr >= PAGE4K(m_regs[T0_G_PAGE]) && ram_addr < PAGE4K(m_regs[T0_G_PAGE] + 8)) + { + m_ts_tilemap[1]->mark_all_dirty(); + } + if (ram_addr >= PAGE4K(m_regs[T1_G_PAGE]) && ram_addr < PAGE4K(m_regs[T1_G_PAGE] + 8)) + { + m_ts_tilemap[2]->mark_all_dirty(); + } + if (ram_addr >= PAGE4K(m_regs[SG_PAGE]) && ram_addr < PAGE4K(m_regs[SG_PAGE] + 8)) + { + m_ts_tilemap[3]->mark_all_dirty(); + } + } + + m_ram->write(ram_addr, data); +} + +u16 tsconf_state::ram_read16(offs_t offset) +{ + return ((m_ram->read(offset & 0xfffffffe)) << 8) | m_ram->read(offset | 1); +} + +void tsconf_state::ram_write16(offs_t offset, u16 data) +{ + m_ram->write(offset & 0xfffffffe, data >> 8); + m_ram->write(offset | 1, data & 0xff); +} + +u16 tsconf_state::spi_read16() +{ + return (tsconf_port_57_zctr_r(0) << 8) | tsconf_port_57_zctr_r(0); +} + +void tsconf_state::cram_write(u16 offset, u8 data) +{ + m_cram->write(offset, data); + u8 pen = offset >> 1; + rgb_t rgb = from_pwm((m_cram->read(offset | 1) << 8 | m_cram->read(offset & 0xfffe))); + m_palette->set_pen_color(pen, rgb); +}; + +void tsconf_state::cram_write16(offs_t offset, u16 data) +{ + cram_write(offset & 0xfffe, data >> 8); + cram_write(offset | 1, data & 0xff); +}; + +void tsconf_state::tsconf_port_7ffd_w(u8 data) +{ + /* disable paging */ + if (m_port_7ffd_data & 0x20) + return; + + /* store new state */ + m_port_7ffd_data = data; + m_regs[MEM_CONFIG] = (m_regs[MEM_CONFIG] & 0xfe) | BIT(data, 4); // ROM128 + m_regs[V_PAGE] = BIT(data, 3) ? 7 : 5; + + /* update memory */ + tsconf_update_bank1(); + tsconf_update_video_mode(); +} + +void tsconf_state::tsconf_port_fe_w(offs_t offset, u8 data) +{ + m_regs[BORDER] = (data & 0x07) | 0xf0; + spectrum_port_fe_w(offset, data); +} + +u8 tsconf_state::tsconf_port_xxaf_r(offs_t port) +{ + u8 nreg = port >> 8; + u8 data = 0xff; + + switch (nreg) + { + case V_CONFIG: + data = 0b01000011; // PWR_UP, !FDRVER, 5bit VDAC + break; + case PAGE2: + case PAGE3: + data = m_regs[nreg]; + break; + + case DMA_CTRL: // DMAStatus + data = m_dma->is_ready() ? 0x00 : 0x80; + break; + + case 0x30: // FRCnt0 + case 0x31: // FRCnt1 + case 0x32: // FRCnt2 + default: + logerror("'tsconf': unmapped reg read %02X\n", nreg); + break; + } + + //LOGWARN("'tsconf': reg read %02X = %02x\n", nreg, data); + return data; +} + +void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data) +{ + u8 nreg = port >> 8; + m_regs[nreg] = data; + + switch (nreg) + { + case V_CONFIG: + case V_PAGE: + case PAL_SEL: + tsconf_update_video_mode(); + break; + + case T_MAP_PAGE: + m_ts_tilemap[1]->mark_all_dirty(); + m_ts_tilemap[2]->mark_all_dirty(); + break; + + case T0_G_PAGE: + m_gfxdecode->gfx(2)->set_source(m_ram->pointer() + PAGE4K(data)); + m_ts_tilemap[1]->mark_all_dirty(); + break; + + case T0_X_OFFSER_L: + case T0_X_OFFSER_H: + case T0_Y_OFFSER_L: + case T0_Y_OFFSER_H: + m_ts_tilemap[1]->set_scrollx((m_regs[T0_X_OFFSER_H] << 8) | m_regs[T0_X_OFFSER_L]); + m_ts_tilemap[1]->set_scrolly((m_regs[T0_Y_OFFSER_H] << 8) | m_regs[T0_Y_OFFSER_L]); + break; + + case T1_G_PAGE: + m_gfxdecode->gfx(3)->set_source(m_ram->pointer() + PAGE4K(data)); + m_ts_tilemap[2]->mark_all_dirty(); + break; + + case T1_X_OFFSER_L: + case T1_X_OFFSER_H: + case T1_Y_OFFSER_L: + case T1_Y_OFFSER_H: + m_ts_tilemap[2]->set_scrollx((m_regs[T1_X_OFFSER_H] << 8) | m_regs[T1_X_OFFSER_L]); + m_ts_tilemap[2]->set_scrolly((m_regs[T1_Y_OFFSER_H] << 8) | m_regs[T1_Y_OFFSER_L]); + break; + + case SG_PAGE: + m_gfxdecode->gfx(4)->set_source(m_ram->pointer() + PAGE4K(data)); + m_ts_tilemap[3]->mark_all_dirty(); + break; + + case MEM_CONFIG: + m_port_7ffd_data = (m_port_7ffd_data & 0xef) | (ROM128 << 4); + tsconf_update_bank1(); + break; + + case PAGE0: + tsconf_update_bank1(); + break; + + case PAGE1: + m_bank2->set_base(m_ram->pointer() + PAGE4K(data)); + break; + + case PAGE2: + m_bank3->set_base(m_ram->pointer() + PAGE4K(data)); + break; + + case PAGE3: + m_bank4->set_base(m_ram->pointer() + PAGE4K(data)); + break; + + case BORDER: + spectrum_UpdateBorderBitmap(); + break; + + case DMAS_ADDRESS_L: + m_dma->set_saddr_l(data); + break; + + case DMAS_ADDRESS_H: + m_dma->set_saddr_h(data); + break; + + case DMAS_ADDRESS_X: + m_dma->set_saddr_x(data); + break; + + case DMAD_ADDRESS_L: + m_dma->set_daddr_l(data); + break; + + case DMAD_ADDRESS_H: + m_dma->set_daddr_h(data); + break; + + case DMAD_ADDRESS_X: + m_dma->set_daddr_x(data); + break; + + case DMA_LEN: + m_dma->set_block_len(data); + break; + + case DMA_NUM_L: + m_dma->set_block_num_l(data); + break; + + case DMA_NUM_H: + m_dma->set_block_num_h(data); + break; + + case DMA_CTRL: + m_dma->start_tx(((BIT(data, 7) << 3) | (data & 0x07)), BIT(data, 5), BIT(data, 4), BIT(data, 3)); + break; + + case SYS_CONFIG: + // 0 - 3.5MHz, 1 - 7MHz, 2 - 14MHz, 3 - reserved + switch (data & 0x03) + { + case 2: + m_maincpu->set_clock(X1); + break; + case 1: + m_maincpu->set_clock(X1 / 2); + break; + case 0: + default: + m_maincpu->set_clock(X1 / 4); + break; + } + break; + + case FMAPS: + case TS_CONFIG: + case G_X_OFFS_L: + case G_X_OFFS_H: + case G_Y_OFFS_L: + case G_Y_OFFS_H: + case HS_INT: + case VS_INT_L: + case VS_INT_H: + case INT_MASK: + break; + + default: + logerror("Unsupported reg write: %02X = %02x\n", nreg, data); + break; + } +} + +u8 tsconf_state::tsconf_port_f7_r(offs_t offset) +{ + // BFF7 + u8 data = 0xff; + if (m_port_f7_ext == PS2KEYBOARDS_LOG && m_port_f7_gluk_reg == 0xf0) + { + data = m_keyboard->read(); + } + else if (m_port_f7_ext != DISABLED) + { + data = m_glukrs->read(m_port_f7_gluk_reg); + } + + return data; +} + +void tsconf_state::tsconf_port_f7_w(offs_t offset, u8 data) +{ + auto m_l = offset >> 12; + if (m_l == 6) // EF + { + m_port_f7_ext = (data & 0x80) ? CONF_VERSION : DISABLED; + } + else if (m_port_f7_ext != DISABLED) + { + if (m_l == 5) // DF + { + // 0x0E..0xEF + m_port_f7_gluk_reg = data; + } + else if (m_l == 3) // BF + { + if (m_port_f7_gluk_reg == 0xf0) + { + u8 m_fx[0xf] = {0xff}; + m_port_f7_ext = static_cast(data); + switch (m_port_f7_ext) + { + case CONF_VERSION: + { + strcpy((char *)m_fx, "M.A.M.E."); + PAIR16 m_ver; + m_ver.w = ((21 << 9) | (12 << 5) | 15); + m_fx[0x0c] = m_ver.b.l; + m_fx[0x0d] = m_ver.b.h; + break; + } + case BOOTLOADER_VERSION: + case PS2KEYBOARDS_LOG: + break; + default: + logerror("Gluk extention not supported %x\n", m_port_f7_gluk_reg); + break; + } + for (u8 i = 0; i < 0xf; i++) + { + m_glukrs->write(0xf0 + i, m_fx[i]); + } + } + else + { + m_glukrs->write(m_port_f7_gluk_reg, data); + } + } + } +} + +void tsconf_state::tsconf_port_77_zctr_w(offs_t port, u8 data) +{ + m_sdcard->spi_ss_w(BIT(data, 0)); + m_zctl_cs = BIT(data, 1); +} + +u8 tsconf_state::tsconf_port_77_zctr_r(offs_t port) +{ + return 0x02 | !m_sdcard->get_card_present(); +} + +void tsconf_state::tsconf_port_57_zctr_w(offs_t port, u8 data) +{ + if (!m_zctl_cs) + { + for (u8 m = 0x80; m; m >>= 1) + { + m_sdcard->spi_clock_w(CLEAR_LINE); //0-S R + m_sdcard->spi_mosi_w(data & m ? 1 : 0); + m_sdcard->spi_clock_w(ASSERT_LINE); //1-L W + } + } +} + +u8 tsconf_state::tsconf_port_57_zctr_r(offs_t port) +{ + tsconf_port_57_zctr_w(0, 0xff); + return m_zctl_cs ? 0xff : m_zctl_di; +} + +void tsconf_state::tsconf_spi_miso_w(u8 data) +{ + m_zctl_di <<= 1; + m_zctl_di |= data; +} + +u8 tsconf_state::beta_neutral_r(offs_t offset) +{ + return m_program->read_byte(offset); +} + +u8 tsconf_state::beta_enable_r(offs_t offset) +{ + if (m_ROMSelection == 3) + { + if (m_beta->started() /*&& !m_beta->is_active()*/) + { + m_beta->enable(); + tsconf_update_bank1(); + } + } + + return m_program->read_byte(offset + 0x3d00); +} + +u8 tsconf_state::beta_disable_r(offs_t offset) +{ + if (m_beta->started() && m_beta->is_active()) + { + m_beta->disable(); + tsconf_update_bank1(); + } + + return m_program->read_byte(offset + 0x4000); +} diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 8dab36b88f8..81e061e9c9a 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -44078,6 +44078,9 @@ zx80 // 1980 Sinclair ZX-80 zx81 // 1981 Sinclair ZX-81 zx97 // +@source:tsconf.cpp +tsconf // ZX Evolution - TS-Configuration + @source:testpat.cpp tp1983 tp1985 diff --git a/src/mame/video/spectrum.cpp b/src/mame/video/spectrum.cpp index f16b55e86c1..c465921b587 100644 --- a/src/mame/video/spectrum.cpp +++ b/src/mame/video/spectrum.cpp @@ -266,6 +266,10 @@ void spectrum_state::spectrum_UpdateScreenBitmap(bool eof) } } +u16 spectrum_state::get_border_color() { + return m_port_fe_data & 0x07; +} + /* The code below is just a per-pixel 'partial update' for the border */ void spectrum_state::spectrum_UpdateBorderBitmap() @@ -278,7 +282,7 @@ void spectrum_state::spectrum_UpdateBorderBitmap() if (m_border_bitmap.valid()) { - uint16_t border = m_port_fe_data & 0x07; + uint16_t border = get_border_color(); //printf("update border from %d,%d to %d,%d\n", m_previous_border_x, m_previous_border_y, x, y); -- cgit v1.2.3