added novag tv interface peripheral [hap, Achim]

This commit is contained in:
hap 2024-03-23 19:03:46 +01:00
parent ea1b40a9f7
commit a4cf1316fa
5 changed files with 270 additions and 0 deletions

View File

@ -3212,6 +3212,8 @@ if (BUSES["RS232"]~=null) then
MAME_DIR .. "src/devices/bus/rs232/loopback.h",
MAME_DIR .. "src/devices/bus/rs232/mboardd.cpp",
MAME_DIR .. "src/devices/bus/rs232/mboardd.h",
MAME_DIR .. "src/devices/bus/rs232/nss_tvinterface.cpp",
MAME_DIR .. "src/devices/bus/rs232/nss_tvinterface.h",
MAME_DIR .. "src/devices/bus/rs232/null_modem.cpp",
MAME_DIR .. "src/devices/bus/rs232/null_modem.h",
MAME_DIR .. "src/devices/bus/rs232/patchbox.cpp",

View File

@ -0,0 +1,246 @@
// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Achim
/*******************************************************************************
Novag Super System Peripheral: TV Interface
It's meant to be connected either like: PC -> Distributor -> TV Interface, or
like: chesscomputer -> Distributor -> TV Interface. But the distributor is only
for converting to/from RS-232/TTL voltage, so MAME can ignore it.
It expects a baud rate of 9600, 8 data bits, 1 stop bit, no parity.
Hardware notes:
- PCB label: 100122 REV C
- Hitachi HD63A03RP @ 4.9152MHz
- 8KB ROM (27C64A), 4KB RAM (2*UM6116-3)
- TMT TM6310 CGA chip, 14.318MHz XTAL, 8KB CG ROM (27C64A, only 2KB used)
TODO:
- dump/add English version
- Currently, MAME only has CGA emulation on ISA cards, but this thing is not an
ISA card, nor compatible with IBM CGA standard. So if MAME ever adds a more
generic CGA device, use that.
*******************************************************************************/
#include "emu.h"
#include "nss_tvinterface.h"
#include "cpu/m6800/m6801.h"
#include "video/cgapal.h"
#include "video/mc6845.h"
#include "emupal.h"
#include "screen.h"
namespace {
//-------------------------------------------------
// initialization
//-------------------------------------------------
class nss_tvinterface_device : public device_t, public device_rs232_port_interface
{
public:
nss_tvinterface_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual void input_txd(int state) override { m_rx_state = state ? 1 : 0; }
private:
required_device<hd6303r_cpu_device> m_maincpu;
required_device<mc6845_device> m_crtc;
required_device<palette_device> m_palette;
required_device<screen_device> m_screen;
required_shared_ptr<u8> m_vram;
required_region_ptr<u8> m_cg_rom;
u8 m_rx_state = 0;
void palette(palette_device &palette) const;
MC6845_UPDATE_ROW(crtc_update_row);
u8 cga_sync_r();
void cga_mode_control_w(u8 data);
void cga_color_select_w(u8 data);
void unknown_w(u8 data);
void main_map(address_map &map);
u8 p2_r();
void p2_w(u8 data);
};
nss_tvinterface_device::nss_tvinterface_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, NSS_TVINTERFACE, tag, owner, clock),
device_rs232_port_interface(mconfig, *this),
m_maincpu(*this, "maincpu"),
m_crtc(*this, "crtc"),
m_palette(*this, "palette"),
m_screen(*this, "screen"),
m_vram(*this, "vram"),
m_cg_rom(*this, "cg_rom")
{ }
void nss_tvinterface_device::device_start()
{
save_item(NAME(m_rx_state));
}
//-------------------------------------------------
// CGA video
//-------------------------------------------------
void nss_tvinterface_device::palette(palette_device &palette) const
{
for (int i = 0; i < 16; i++)
palette.set_pen_color(i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2]);
}
MC6845_UPDATE_ROW(nss_tvinterface_device::crtc_update_row)
{
const pen_t *pen = m_palette->pens();
for (int x = 0; x < x_count; x++)
{
u16 offset = (ma + x) << 1 & 0x7ff;
u8 chr = m_vram[offset];
u8 data = m_cg_rom[((ra << 8 | chr) & 0x7ff) | 0x1000];
u8 attr = m_vram[offset | 1];
u8 fg = attr & 0xf;
u8 bg = attr >> 4 & 0xf;
for (int xi = 0; xi < 8; xi++)
bitmap.pix(y, x << 3 | xi) = BIT(data, xi ^ 7) ? pen[fg] : pen[bg];
}
}
u8 nss_tvinterface_device::cga_sync_r()
{
return (m_crtc->vsync_r() * 9) | m_crtc->hsync_r();
}
void nss_tvinterface_device::cga_mode_control_w(u8 data)
{
// only uses textmode
}
void nss_tvinterface_device::cga_color_select_w(u8 data)
{
// does not use 2bpp palette
}
//-------------------------------------------------
// internal i/o
//-------------------------------------------------
void nss_tvinterface_device::unknown_w(u8 data)
{
}
u8 nss_tvinterface_device::p2_r()
{
// P23: serial in
return m_rx_state << 3;
}
void nss_tvinterface_device::p2_w(u8 data)
{
// P24: serial out
output_rxd(BIT(~data, 4));
}
void nss_tvinterface_device::main_map(address_map &map)
{
map(0x8000, 0x87ff).ram().share(m_vram);
map(0xa3bd, 0xa3bd).portr("IN.0");
map(0xa3be, 0xa3be).w(FUNC(nss_tvinterface_device::unknown_w));
map(0xa3d0, 0xa3d0).mirror(0x0006).w(m_crtc, FUNC(mc6845_device::address_w));
map(0xa3d1, 0xa3d1).mirror(0x0006).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xa3d8, 0xa3d8).w(FUNC(nss_tvinterface_device::cga_mode_control_w));
map(0xa3d9, 0xa3d9).w(FUNC(nss_tvinterface_device::cga_color_select_w));
map(0xa3da, 0xa3da).r(FUNC(nss_tvinterface_device::cga_sync_r));
map(0xc000, 0xc7ff).ram();
map(0xe000, 0xffff).rom();
}
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
static INPUT_PORTS_START( nss_tvinterface )
PORT_START("IN.0")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Select")
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Change")
INPUT_PORTS_END
ioport_constructor nss_tvinterface_device::device_input_ports() const
{
return INPUT_PORTS_NAME(nss_tvinterface);
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void nss_tvinterface_device::device_add_mconfig(machine_config &config)
{
// basic machine hardware
HD6303R(config, m_maincpu, 4.9152_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &nss_tvinterface_device::main_map);
m_maincpu->in_p2_cb().set(FUNC(nss_tvinterface_device::p2_r));
m_maincpu->out_p2_cb().set(FUNC(nss_tvinterface_device::p2_w));
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(14.318181_MHz_XTAL/2, 472, 0, 320, 260, 0, 200);
m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update));
MC6845(config, m_crtc, 14.318181_MHz_XTAL/16);
m_crtc->set_screen(m_screen);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
m_crtc->set_update_row_callback(FUNC(nss_tvinterface_device::crtc_update_row));
PALETTE(config, m_palette, FUNC(nss_tvinterface_device::palette), 16);
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
ROM_START(nss_tvinterface)
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD("tvgr_011091", 0xe000, 0x2000, CRC(0ff64cec) SHA1(d35881111cdf8e85a843e3b085447d07244d8d70) )
ROM_REGION( 0x2000, "cg_rom", 0 )
ROM_LOAD("cg_930", 0x0000, 0x2000, CRC(98287b9d) SHA1(b20d7856e4739bafcd66434adf9881824f8a611b) )
ROM_END
const tiny_rom_entry *nss_tvinterface_device::device_rom_region() const
{
return ROM_NAME(nss_tvinterface);
}
} // anonymous namespace
DEFINE_DEVICE_TYPE_PRIVATE(NSS_TVINTERFACE, device_rs232_port_interface, nss_tvinterface_device, "nss_tvinterface", "Novag Super System TV Interface")

View File

@ -0,0 +1,18 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*******************************************************************************
Novag Super System Peripheral: TV Interface
*******************************************************************************/
#ifndef MAME_BUS_RS232_NSS_TVINTERFACE_H
#define MAME_BUS_RS232_NSS_TVINTERFACE_H
#pragma once
#include "rs232.h"
DECLARE_DEVICE_TYPE(NSS_TVINTERFACE, device_rs232_port_interface)
#endif // MAME_BUS_RS232_NSS_TVINTERFACE_H

View File

@ -158,6 +158,7 @@ device_rs232_port_interface::~device_rs232_port_interface()
#include "keyboard.h"
#include "loopback.h"
#include "mboardd.h"
#include "nss_tvinterface.h"
#include "null_modem.h"
#include "patchbox.h"
#include "printer.h"
@ -178,6 +179,7 @@ void default_rs232_devices(device_slot_interface &device)
device.option_add("keyboard", SERIAL_KEYBOARD);
device.option_add("loopback", RS232_LOOPBACK);
device.option_add("mockingboard", SERIAL_MOCKINGBOARD_D);
device.option_add("nss_tvi", NSS_TVINTERFACE);
device.option_add("null_modem", NULL_MODEM);
device.option_add("patch", RS232_PATCH_BOX);
device.option_add("printer", SERIAL_PRINTER);

View File

@ -10,6 +10,8 @@ properly.
TODO:
- if/when MAME supports an exit callback, hook up power-off switch to that
- nsnova sometimes fails to detect Super System TV Interface when pressing New Game?
It should flash the screen on successful detection.
- unmapped reads from 0x3c/0x3d (primo/supremo) or 0x33/0x34 (nsnova)
- supremo unmapped writes to 0x2000/0x6000, always 0?
- is the 1st version of supremo(black plastic) the same ROM?