Skip to content

Commit

Permalink
mtu130: Implement mirroring of bfcx, implement lightpen
Browse files Browse the repository at this point in the history
  • Loading branch information
galibert committed Oct 28, 2022
1 parent 3b0c710 commit 28d2fc3
Showing 1 changed file with 155 additions and 10 deletions.
165 changes: 155 additions & 10 deletions src/mame/misc/mtu130.cpp
Expand Up @@ -13,7 +13,6 @@
// - MTUTAPE, a kind of digital tape?
// - MTUNET, some proprietary network
// - Sound on user via cb2, it's weird
// - Light pen, need working demo code

// Implemented extension boards:
// - DATAMOVER, a 68k-based board, used by BASIC 1.5 to accelerate floating point operations
Expand All @@ -22,9 +21,6 @@
// - PROGRAMMOVER, a z80-based board
// - MultI-O, an i/o board

// Probable bug somewhere making the BASIC (light pen, game) demos
// fail in the demonstration disk.

#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "imagedev/floppy.h"
Expand Down Expand Up @@ -99,7 +95,10 @@ class mtu130_state : public driver_device
m_id(*this, "id"),
m_keyboard(*this, "K%X", 0L),
m_keyboard_meta(*this, "KM"),
m_jumpers(*this, "jumpers")
m_jumpers(*this, "jumpers"),
m_lightpen_w(*this, "lightpen_w"),
m_lightpen_x(*this, "lightpen_x"),
m_lightpen_y(*this, "lightpen_y")
{ }

void mtu130(machine_config &config);
Expand Down Expand Up @@ -166,13 +165,23 @@ class mtu130_state : public driver_device
required_ioport_array<16> m_keyboard;
required_ioport m_keyboard_meta;
required_ioport m_jumpers;
required_ioport m_lightpen_w;
required_ioport m_lightpen_x;
required_ioport m_lightpen_y;

memory_interface *m_maincpu_intf;

emu_timer *m_timer_lightpen_hit;

int m_lightpen_hit_x, m_lightpen_hit_y;

uint16_t m_dma_adr;
u8 m_keyboard_col;
u8 m_dac_level;
u8 m_id_adr;

u8 m_lightpen_status, m_lightpen_low, m_lightpen_high;

bool m_dma_direction;
bool m_video_unblank;
bool m_video_bw;
Expand All @@ -189,6 +198,15 @@ class mtu130_state : public driver_device
void dma_adr_w(u8 data);
DECLARE_WRITE_LINE_MEMBER(dma_drq_w);

TIMER_CALLBACK_MEMBER(lightpen_hit);
void lightpen_trigger(int state);
u8 lightpen_status_r();
u8 lightpen_low_r();
u8 lightpen_high_r();
void lightpen_clear_w(u8);

void tape_w(u8);

void keyboard_col_clear_w(u8);
void user_cb2_w(int line);
void sys1_pb_w(u8 data);
Expand Down Expand Up @@ -345,6 +363,11 @@ void mtu130_state::machine_start()
m_video_unblank = true;
m_video_bw = true;
m_fdc_irq_enabled = false;
m_lightpen_hit_x = 0;
m_lightpen_hit_y = 0;
m_lightpen_status = 0;
m_lightpen_low = 0;
m_lightpen_high = 0;

save_item(NAME(m_dma_adr));
save_item(NAME(m_dma_direction));
Expand All @@ -354,6 +377,13 @@ void mtu130_state::machine_start()
save_item(NAME(m_video_unblank));
save_item(NAME(m_video_bw));
save_item(NAME(m_fdc_irq_enabled));
save_item(NAME(m_lightpen_hit_x));
save_item(NAME(m_lightpen_hit_y));
save_item(NAME(m_lightpen_status));
save_item(NAME(m_lightpen_low));
save_item(NAME(m_lightpen_high));

m_timer_lightpen_hit = timer_alloc(FUNC(mtu130_state::lightpen_hit), this);

m_fdc->set_rate(500000);
m_io_view.select(1);
Expand Down Expand Up @@ -554,6 +584,110 @@ void mtu130_state::keyboard_col_clear_w(u8)
m_keyboard_col = 0;
}

u8 mtu130_state::lightpen_status_r()
{
return m_lightpen_status;
}

u8 mtu130_state::lightpen_low_r()
{
return m_lightpen_low;
}

u8 mtu130_state::lightpen_high_r()
{
return m_lightpen_high;
}

void mtu130_state::lightpen_clear_w(u8)
{
m_lightpen_status &= ~8;
}

void mtu130_state::lightpen_trigger(int state)
{
if(state && m_lightpen_w->read()) {
m_lightpen_hit_x = m_lightpen_x->read();
m_lightpen_hit_y = m_lightpen_y->read();
m_timer_lightpen_hit->adjust(m_screen->time_until_pos(m_lightpen_hit_y, m_lightpen_hit_x + 120));
}
}

TIMER_CALLBACK_MEMBER(mtu130_state::lightpen_hit)
{
if(m_lightpen_status & 8)
return;

// aaaa aaaa .ppp ...s (a = address, p = pixel, s = skew)
// The os-provided coordinates decoding routine cannot generate x >= 474
static const uint16_t x_to_address[480] = {
0x0261, 0x0271, 0x0300, 0x0310, 0x0320, 0x0330, 0x0340, 0x0350, 0x0360, 0x0370,
0x0301, 0x0311, 0x0421, 0x0431, 0x0440, 0x0450, 0x0460, 0x0470, 0x0400, 0x0410,
0x0420, 0x0430, 0x0540, 0x0550, 0x0560, 0x0570, 0x0501, 0x0511, 0x0521, 0x0531,
0x0541, 0x0551, 0x0660, 0x0670, 0x0700, 0x0710, 0x0720, 0x0730, 0x0740, 0x0750,
0x0760, 0x0770, 0x0801, 0x0811, 0x0821, 0x0831, 0x0840, 0x0850, 0x0860, 0x0870,
0x0800, 0x0810, 0x0820, 0x0830, 0x0940, 0x0950, 0x0960, 0x0970, 0x0901, 0x0911,
0x0921, 0x0931, 0x0a41, 0x0a51, 0x0a61, 0x0a71, 0x0a00, 0x0a10, 0x0a20, 0x0a30,
0x0a40, 0x0a50, 0x0a60, 0x0a70, 0x0c00, 0x0c10, 0x0c20, 0x0c30, 0x0c40, 0x0c50,
0x0c61, 0x0c71, 0x0d00, 0x0d10, 0x0d20, 0x0d30, 0x0d40, 0x0d50, 0x0d60, 0x0d70,
0x0d01, 0x0d11, 0x0e21, 0x0e31, 0x0e40, 0x0e50, 0x0e60, 0x0e70, 0x0e00, 0x0e10,
0x0e20, 0x0e30, 0x0f40, 0x0f50, 0x0f60, 0x0f70, 0x0f01, 0x0f11, 0x0f21, 0x0f31,
0x0f41, 0x0f51, 0x1060, 0x1070, 0x1100, 0x1110, 0x1120, 0x1130, 0x1140, 0x1150,
0x1160, 0x1170, 0x1201, 0x1211, 0x1221, 0x1231, 0x1240, 0x1250, 0x1260, 0x1270,
0x1200, 0x1210, 0x1220, 0x1230, 0x1340, 0x1350, 0x1360, 0x1370, 0x1301, 0x1311,
0x1321, 0x1331, 0x1441, 0x1451, 0x1461, 0x1471, 0x1400, 0x1410, 0x1420, 0x1430,
0x1440, 0x1450, 0x1460, 0x1470, 0x1600, 0x1610, 0x1620, 0x1630, 0x1640, 0x1650,
0x1661, 0x1671, 0x1700, 0x1710, 0x1720, 0x1730, 0x1740, 0x1750, 0x1760, 0x1770,
0x1701, 0x1711, 0x1821, 0x1831, 0x1840, 0x1850, 0x1860, 0x1870, 0x1800, 0x1810,
0x1820, 0x1830, 0x1940, 0x1950, 0x1960, 0x1970, 0x1901, 0x1911, 0x1921, 0x1931,
0x1941, 0x1951, 0x1a60, 0x1a70, 0x1b00, 0x1b10, 0x1b20, 0x1b30, 0x1b40, 0x1b50,
0x1b60, 0x1b70, 0x1c01, 0x1c11, 0x1c21, 0x1c31, 0x1c40, 0x1c50, 0x1c60, 0x1c70,
0x1c00, 0x1c10, 0x1c20, 0x1c30, 0x1d40, 0x1d50, 0x1d60, 0x1d70, 0x1d01, 0x1d11,
0x1d21, 0x1d31, 0x1e41, 0x1e51, 0x1e61, 0x1e71, 0x1e00, 0x1e10, 0x1e20, 0x1e30,
0x1e40, 0x1e50, 0x1e60, 0x1e70, 0x2000, 0x2010, 0x2020, 0x2030, 0x2040, 0x2050,
0x2061, 0x2071, 0x2100, 0x2110, 0x2120, 0x2130, 0x2140, 0x2150, 0x2160, 0x2170,
0x2101, 0x2111, 0x2221, 0x2231, 0x2240, 0x2250, 0x2260, 0x2270, 0x2200, 0x2210,
0x2220, 0x2230, 0x2340, 0x2350, 0x2360, 0x2370, 0x2301, 0x2311, 0x2321, 0x2331,
0x2341, 0x2351, 0x2460, 0x2470, 0x2500, 0x2510, 0x2520, 0x2530, 0x2540, 0x2550,
0x2560, 0x2570, 0x2601, 0x2611, 0x2621, 0x2631, 0x2640, 0x2650, 0x2660, 0x2670,
0x2600, 0x2610, 0x2620, 0x2630, 0x2740, 0x2750, 0x2760, 0x2770, 0x2701, 0x2711,
0x2721, 0x2731, 0x2841, 0x2851, 0x2861, 0x2871, 0x2800, 0x2810, 0x2820, 0x2830,
0x2840, 0x2850, 0x2860, 0x2870, 0x2a00, 0x2a10, 0x2a20, 0x2a30, 0x2a40, 0x2a50,
0x2a61, 0x2a71, 0x2b00, 0x2b10, 0x2b20, 0x2b30, 0x2b40, 0x2b50, 0x2b60, 0x2b70,
0x2b01, 0x2b11, 0x2c21, 0x2c31, 0x2c40, 0x2c50, 0x2c60, 0x2c70, 0x2c00, 0x2c10,
0x2c20, 0x2c30, 0x2d40, 0x2d50, 0x2d60, 0x2d70, 0x2d01, 0x2d11, 0x2d21, 0x2d31,
0x2d41, 0x2d51, 0x2e60, 0x2e70, 0x2f00, 0x2f10, 0x2f20, 0x2f30, 0x2f40, 0x2f50,
0x2f60, 0x2f70, 0x3001, 0x3011, 0x3021, 0x3031, 0x3040, 0x3050, 0x3060, 0x3070,
0x3000, 0x3010, 0x3020, 0x3030, 0x3140, 0x3150, 0x3160, 0x3170, 0x3101, 0x3111,
0x3121, 0x3131, 0x3241, 0x3251, 0x3261, 0x3271, 0x3200, 0x3210, 0x3220, 0x3230,
0x3240, 0x3250, 0x3260, 0x3270, 0x3400, 0x3410, 0x3420, 0x3430, 0x3440, 0x3450,
0x3461, 0x3471, 0x3500, 0x3510, 0x3520, 0x3530, 0x3540, 0x3550, 0x3560, 0x3570,
0x3501, 0x3511, 0x3621, 0x3631, 0x3640, 0x3650, 0x3660, 0x3670, 0x3600, 0x3610,
0x3620, 0x3630, 0x3740, 0x3750, 0x3760, 0x3770, 0x3701, 0x3711, 0x3721, 0x3731,
0x3741, 0x3751, 0x3860, 0x3870, 0x3900, 0x3910, 0x3920, 0x3930, 0x3940, 0x3950,
0x3960, 0x3970, 0x3a01, 0x3a11, 0x3a21, 0x3a31, 0x3a40, 0x3a50, 0x3a60, 0x3a70,
0x3a00, 0x3a10, 0x3a20, 0x3a30, 0x3b40, 0x3b50, 0x3b60, 0x3b70, 0x3b01, 0x3b11,
0x3b21, 0x3b31, 0x3c41, 0x3c51, 0x3c61, 0x3c71, 0x3c00, 0x3c10, 0x3c20, 0x3c30,
0x3c40, 0x3c50, 0x3c60, 0x3c70, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};

uint16_t base = x_to_address[m_lightpen_hit_x];
if(!base)
return;

uint16_t pixel = (base >> 4) & 7;
uint16_t skew = base & 1;
uint16_t address = (base >> 8) + 60*m_lightpen_hit_y;

m_lightpen_status = pixel | 8;
m_lightpen_low = address & 0xff;
m_lightpen_high = ((address >> 8) & 0x3f) | (skew ? 0x80 : 0x00);
}

void mtu130_state::tape_w(u8)
{
logerror("tape_w\n");
}

void mtu130_state::map(address_map &map)
{
Expand All @@ -563,10 +697,10 @@ void mtu130_state::map(address_map &map)

map(0x0be00, 0x0bfff).view(m_io_view); // I/O dynamically overrides part of the main ram
m_io_view[1](0x0be00, 0x0bfff).unmaprw(); // Fully mask out the ram when active
m_io_view[1](0x0bfc3, 0x0bfc3).r(FUNC(mtu130_state::id_r));
m_io_view[1](0x0bfc3, 0x0bfc3).w(FUNC(mtu130_state::id_reset_w));
m_io_view[1](0x0bfc5, 0x0bfc5).w(FUNC(mtu130_state::keyboard_col_clear_w));
m_io_view[1](0x0bfc7, 0x0bfc7).w(FUNC(mtu130_state::id_reset_w));
m_io_view[1](0x0bfc0, 0x0bfc0).rw(FUNC(mtu130_state::lightpen_status_r), FUNC(mtu130_state::lightpen_clear_w)).mirror(4);
m_io_view[1](0x0bfc1, 0x0bfc1).rw(FUNC(mtu130_state::lightpen_low_r), FUNC(mtu130_state::keyboard_col_clear_w)).mirror(4);
m_io_view[1](0x0bfc2, 0x0bfc2).rw(FUNC(mtu130_state::lightpen_high_r), FUNC(mtu130_state::tape_w)).mirror(4);
m_io_view[1](0x0bfc3, 0x0bfc3).rw(FUNC(mtu130_state::id_r), FUNC(mtu130_state::id_reset_w)).mirror(4);
m_io_view[1](0x0bfc8, 0x0bfcb).rw(m_acia, FUNC(mos6551_device::read), FUNC(mos6551_device::write));
m_io_view[1](0x0bfd0, 0x0bfdf).m(m_user_6522, FUNC(via6522_device::map));
m_io_view[1](0x0bfe0, 0x0bfef).m(m_sys1_6522, FUNC(via6522_device::map));
Expand Down Expand Up @@ -626,6 +760,7 @@ void mtu130_state::mtu130(machine_config &config)
m_screen->set_screen_update(FUNC(mtu130_state::screen_update));
m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(m_sys2_6522, FUNC(via6522_device::write_ca2));
m_screen->screen_vblank().append(FUNC(mtu130_state::lightpen_trigger));

PALETTE(config, m_palette).set_entries(4);

Expand Down Expand Up @@ -686,6 +821,16 @@ static INPUT_PORTS_START(mtu130)
PORT_CONFSETTING(0x00, "FDC rom")
PORT_CONFSETTING(0x01, "ROM1 rom (aka rom F)")

PORT_START("lightpen_w")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1)
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)

PORT_START("lightpen_x")
PORT_BIT(0x1ff, 0x000, IPT_LIGHTGUN_X) PORT_MINMAX(0, 479) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15)

PORT_START("lightpen_y")
PORT_BIT(0x0ff, 0x000, IPT_LIGHTGUN_Y) PORT_MINMAX(0, 255) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15)

PORT_START("K0")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("RIGHT SHIFT")
Expand Down Expand Up @@ -832,7 +977,7 @@ ROM_START(mtu130)
// address 1 unused f
// address 2-6 vendor 00102
// address 7-b group 00000
// address c-f,0 user 00175 (used by BASIC 1.5 for system-locking)
// address c-f,0 user 00175 (used by BASIC 1.0 and 1.5 for system-locking)

ROM_LOAD("6301.u24", 0, 0x100, CRC(7ebc5451) SHA1(402bd7bf343d995bc9c857fe4f3a23e0a8e7bd1c))
ROM_END
Expand Down

0 comments on commit 28d2fc3

Please sign in to comment.