Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ussr/juku: Convert to memory_view, add mouse & fix timer #13205

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
126 changes: 65 additions & 61 deletions src/mame/ussr/juku.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,32 @@
and T to boot from tape/disk/network

TODO:
- E5103 (Juss) and IBM AT keyboard layouts?
- Work out how the floppy interface really works?
- Tape? (split up to E5101 batch as tape only?)
- Separate FDC 1791, 1792 and 1793 versions
- И41 (=Multibus-1) compatibility?
- Network?
- Ramdisk?
- Memory extensions?
- Mouse!

***************************************************************************/

#include "emu.h"

#include "jukumouse.h"

#include "cpu/i8085/i8085.h"
#include "imagedev/floppy.h"
#include "machine/74148.h"
#include "machine/bankdev.h"
#include "machine/i8251.h"
#include "machine/i8255.h"
#include "machine/pic8259.h"
#include "machine/pit8253.h"
#include "machine/wd_fdc.h"
#include "sound/spkrdev.h"

#include "emuopts.h"
#include "screen.h"
#include "softlist_dev.h"
#include "speaker.h"
Expand Down Expand Up @@ -80,7 +83,11 @@ class juku_state : public driver_device
juku_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_bank(*this, "bank"),
m_rom(*this, "maincpu"),
m_exp(*this, "expcart"),
m_ram(*this, "ram"),
m_ext(*this, "ext%u", 0U),
m_mode(*this, "mode"),
m_pic(*this, "pic"),
m_pit(*this, "pit%u", 0U),
m_pio(*this, "pio%u", 0U),
Expand All @@ -91,7 +98,8 @@ class juku_state : public driver_device
m_keys(*this, "COL.%u", 0U),
m_key_special(*this, "SPECIAL"),
m_screen(*this, "screen"),
m_speaker(*this, "speaker")
m_speaker(*this, "speaker"),
m_mouse(*this, "mouse")
{ }

void juku(machine_config &config);
Expand All @@ -102,7 +110,11 @@ class juku_state : public driver_device

private:
required_device<i8080a_cpu_device> m_maincpu;
required_device<address_map_bank_device> m_bank;
required_region_ptr<uint8_t> m_rom;
optional_region_ptr<uint8_t> m_exp;
required_shared_ptr<uint8_t> m_ram;
optional_shared_ptr_array<uint8_t, 1> m_ext;
memory_view m_mode;
required_device<pic8259_device> m_pic;
required_device_array<pit8253_device, 3> m_pit;
required_device_array<i8255_device, 2> m_pio;
Expand All @@ -114,6 +126,7 @@ class juku_state : public driver_device
required_ioport m_key_special;
required_device<screen_device> m_screen;
required_device<speaker_sound_device> m_speaker;
optional_device<juku_mouse_device> m_mouse;

int32_t m_width, m_height, m_hbporch, m_vbporch;

Expand All @@ -126,10 +139,7 @@ class juku_state : public driver_device

uint8_t m_fdc_cur_cmd;

std::unique_ptr<uint8_t[]> m_ram;

void mem_map(address_map &map) ATTR_COLD;
void bank_map(address_map &map) ATTR_COLD;
void io_map(address_map &map) ATTR_COLD;

void pio0_porta_w(uint8_t data);
Expand Down Expand Up @@ -163,25 +173,9 @@ class juku_state : public driver_device

void juku_state::mem_map(address_map &map)
{
map(0x0000, 0xffff).m(m_bank, FUNC(address_map_bank_device::amap8));
}

void juku_state::bank_map(address_map &map)
{
// memory mode 0
map(0x00000, 0x03fff).rom().region("maincpu", 0);
map(0x00000, 0x03fff).bankw("ram_0000");
map(0x04000, 0x0ffff).bankrw("ram_4000");
// memory mode 1
map(0x10000, 0x1ffff).bankrw("ram_0000");
map(0x1d800, 0x1ffff).bankr("rom_d800");
// memory mode 2
map(0x20000, 0x23fff).bankrw("ram_0000");
map(0x24000, 0x2bfff).rom().region("extension", 0);
map(0x2c000, 0x2ffff).bankrw("ram_c000");
map(0x2d800, 0x2ffff).bankr("rom_d800");
// memory mode 3
map(0x30000, 0x3ffff).bankrw("ram_0000");
map(0x0000, 0xffff).ram().share(m_ram);
map(0x0000, 0x7fff).ram().share(m_ext[0]);
map(0x0000, 0xffff).view(m_mode);
}

void juku_state::io_map(address_map &map)
Expand Down Expand Up @@ -645,18 +639,35 @@ void juku_state::pio0_portc_w(uint8_t data)
floppy->ss_w(BIT(data, 6));
}

m_bank->set_bank(data & 0x03);
m_mode.select(data & 0b11);
}

void juku_state::machine_start()
{
m_ram = std::make_unique<uint8_t []>(0x10000);

membank("rom_d800")->set_base(memregion("maincpu")->base() + 0x1800);

membank("ram_0000")->set_base(&m_ram[0x0000]);
membank("ram_4000")->set_base(&m_ram[0x4000]);
membank("ram_c000")->set_base(&m_ram[0xc000]);
// map memory modes
m_mode[0].install_rom(0x0000, 0x3fff, &m_rom[0x0000]);
m_mode[0].install_writeonly(0x0000, 0x3fff, &m_ram[0x0000]);
m_mode[0].install_ram(0x4000, 0xffff, &m_ram[0x4000]);
m_mode[1].install_ram(0x0000, 0xd7ff, &m_ram[0x0000]);
m_mode[1].install_rom(0xd800, 0xffff, &m_rom[0x1800]);
m_mode[1].install_writeonly(0xd800, 0xffff, &m_ram[0xd800]);
m_mode[2].install_ram(0x0000, 0x3fff, &m_ram[0x0000]);
// optional BASIC expansion cartridge
m_mode[2].install_rom(0x4000, 0xbfff, &m_exp[0x0000]);
//m_mode[2].install_ram(0x4000, 0xbfff, &m_ext[0][0x0000]);
// no info on programs actually using extra 32kb "memory window"
m_mode[2].install_writeonly(0x4000, 0xbfff, &m_ext[0][0x0000]);
// could also refer to usual ram (specs not clear)
//m_mode[2].install_writeonly(0x4000, 0xbfff, &m_ram[0x4000]);
m_mode[2].install_ram(0xc000, 0xd7ff, &m_ram[0xc000]);
m_mode[2].install_rom(0xd800, 0xffff, &m_rom[0x1800]);
m_mode[2].install_writeonly(0xd800, 0xffff, &m_ram[0xd800]);
// could as well disable the view, but for coherence
m_mode[3].install_ram(0x0000, 0xffff, &m_ram[0x0000]);

// check if mouse is plugged
if (m_mouse.found() && strcmp(mconfig().options().mouse_device(), "none") != 0)
m_maincpu->space(AS_IO).install_read_handler(0x80, 0x80, read8smo_delegate(*m_mouse, FUNC(juku_mouse_device::mouse_port_r)));

// register for save states
save_item(NAME(m_width));
Expand All @@ -671,12 +682,11 @@ void juku_state::machine_start()
save_item(NAME(m_beep_state));
save_item(NAME(m_beep_level));
save_item(NAME(m_fdc_cur_cmd));
save_pointer(NAME(m_ram), 0x10000);
}

void juku_state::machine_reset()
{
m_bank->set_bank(0);
m_mode.select(0);
m_key_encoder->enable_input_w(0);
m_beep_state = 0;
m_beep_level = 0;
Expand All @@ -701,13 +711,7 @@ void juku_state::juku(machine_config &config)
I8080A(config, m_maincpu, 20_MHz_XTAL/10);
m_maincpu->set_addrmap(AS_PROGRAM, &juku_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &juku_state::io_map);
m_maincpu->in_inta_func().set("pic", FUNC(pic8259_device::acknowledge));

ADDRESS_MAP_BANK(config, m_bank);
m_bank->set_map(&juku_state::bank_map);
m_bank->set_data_width(8);
m_bank->set_addr_width(18);
m_bank->set_stride(0x10000);
m_maincpu->in_inta_func().set(m_pic, FUNC(pic8259_device::acknowledge));

// КР580ВН59
PIC8259(config, m_pic, 0);
Expand All @@ -721,30 +725,26 @@ void juku_state::juku(machine_config &config)
m_pit[0]->out_handler<0>().set(m_pit[1], FUNC(pit8253_device::write_clk0));
m_pit[0]->out_handler<0>().append(m_pit[0], FUNC(pit8253_device::write_gate1));
m_pit[0]->out_handler<0>().append(m_pit[0], FUNC(pit8253_device::write_gate2));
//m_pit[0]->out_handler<1>().set(, ); // HOR RTR
//m_pit[0]->out_handler<1>().append(, ); // HOR RTR
//m_pit[0]->out_handler<1>().set(?, ?); // HOR RTR

// КР580ВИ53 #2
PIT8253(config, m_pit[1], 0);
m_pit[0]->out_handler<2>().set(m_pit[1], FUNC(pit8253_device::write_clk1)); // H SYNC DSL
m_pit[0]->out_handler<2>().set(m_pit[1], FUNC(pit8253_device::write_clk1)); // HOR SYNC DSL
m_pit[0]->out_handler<2>().append(m_pit[1], FUNC(pit8253_device::write_clk2));
m_pit[1]->out_handler<0>().append(m_pit[1], FUNC(pit8253_device::write_gate1));
m_pit[1]->out_handler<0>().append(m_pit[1], FUNC(pit8253_device::write_gate2));
m_pit[1]->out_handler<1>().set(m_pic, FUNC(pic8259_device::ir5_w)); // VER RTR / FRAME INT

//m_pit[1]->out_handler<2>().append(m_pit[1], FUNC(pit8253_device::write_clk1)); // VERT SYNC DSL
//m_pit[1]->out_handler<2>().set(m_pit[1], FUNC(pit8253_device::write_clk1)); // VERT SYNC DSL
//m_pit[1]->out_handler<2>().append(m_pit[1], FUNC(pit8253_device::write_clk2));

// КР580ВИ53 #3
PIT8253(config, m_pit[2], 0);

m_pit[2]->set_clk<0>(16_MHz_XTAL/13); // 1.23 MHz
m_pit[2]->set_clk<1>(16_MHz_XTAL/8); // 2 MHz
m_pit[2]->set_clk<2>(16_MHz_XTAL/13); // 1.23 MHz

//m_pit[1]->out_handler<0>().append(...); // BAUD RATE
m_pit[1]->out_handler<1>().append(m_pit[2], FUNC(pit8253_device::write_clk2)); // ~49.92 Hz
//m_pit[2]->out_handler<0>().set(?, ?); // BAUD RATE
m_pit[2]->out_handler<1>().append(FUNC(juku_state::speaker_w)); // SOUND
//m_pit[1]->out_handler<2>().append(...); // SYNC BAUD RATE
//m_pit[2]->out_handler<2>().set(?, ?); // SYNC BAUD RATE

// КР580ВВ55A #1 (=КР580ИК55)
I8255A(config, m_pio[0]);
Expand All @@ -757,13 +757,13 @@ void juku_state::juku(machine_config &config)

// КР580ВВ51A
I8251(config, m_sio[0], 0);
m_sio[0]->rxrdy_handler().set("pic", FUNC(pic8259_device::ir2_w));
m_sio[0]->txrdy_handler().set("pic", FUNC(pic8259_device::ir3_w));
m_sio[0]->rxrdy_handler().set(m_pic, FUNC(pic8259_device::ir2_w));
m_sio[0]->txrdy_handler().set(m_pic, FUNC(pic8259_device::ir3_w));

// КР580ВВ51A (instead of FDC?)
I8251(config, m_sio[1], 0);
m_sio[1]->rxrdy_handler().set("pic", FUNC(pic8259_device::ir0_w));
m_sio[1]->txrdy_handler().set("pic", FUNC(pic8259_device::ir1_w));
m_sio[1]->rxrdy_handler().set(m_pic, FUNC(pic8259_device::ir0_w));
m_sio[1]->txrdy_handler().set(m_pic, FUNC(pic8259_device::ir1_w));

// Электроника МС 6105.1 "Колокольчик" (DEC VR201 analog)
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
Expand All @@ -778,6 +778,10 @@ void juku_state::juku(machine_config &config)
// К155ИВ1
TTL74148(config, m_key_encoder, 0);

// E4701 (joystick like mouse device)
JUKU_MOUSE(config, m_mouse);
m_mouse->int_handler().set(m_pic, FUNC(pic8259_device::ir6_w));

// КР1818ВГ93 (for E6502 disk drive)
KR1818VG93(config, m_fdc, 16_MHz_XTAL/16);
m_fdc->drq_wr_callback().set(FUNC(juku_state::fdc_drq_w));
Expand All @@ -796,8 +800,8 @@ ROM_START( juku )
ROM_DEFAULT_BIOS("3.43m_37")
ROM_REGION(0x4000, "maincpu", 0)

// Monitor 3.3 with Bootstrap 3.3, FDC 1791 from early 1985 prototype
// Does not seem to be compatible with JBASIC extension cartridge
// Monitor 3.3 with Bootstrap 3.3, FDC 1791 from early prototypes
// Does not seem to be compatible with JBASIC expansion cartridge
ROM_SYSTEM_BIOS(0, "jmon3.3", "Monitor/Bootstrap 3.3 \\w JBASIC")
ROMX_LOAD("jmon33.bin", 0x0000, 0x4000, CRC(ed22c287) SHA1(76407d99bf83035ef526d980c9468cb04972608c), ROM_BIOS(0))

Expand Down Expand Up @@ -826,7 +830,7 @@ ROM_START( juku )
ROM_SYSTEM_BIOS(5, "2.43m_43", "Tape/Disk \\w AT keyb (2.43m #0043)")
ROMX_LOAD("ekta43.bin", 0x0000, 0x4000, CRC(05678f9f) SHA1(a7419bfd8249871cc7dbf5c6ea85022d6963fc9a), ROM_BIOS(5))

ROM_REGION(0x8000, "extension", 0)
ROM_REGION(0x8000, "expcart", 0)

// EKTA JBASIC cartridge (buggy) seems similar to v1.1 from 14.09.1987.
// There is also a version with additional HEX$ directive for EKDOS.
Expand Down
118 changes: 118 additions & 0 deletions src/mame/ussr/jukumouse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// license:BSD-3-Clause
// copyright-holders:Märt Põder

#include "emu.h"
#include "jukumouse.h"

//#define VERBOSE 1
//#define LOG_OUTPUT_FUNC osd_printf_info

#include "logmacro.h"

// measured avg in heavy use 442-520, max ~1400Hz
static constexpr int MOUSE_RATE_HZ = 600;

DEFINE_DEVICE_TYPE(JUKU_MOUSE, juku_mouse_device, "juku_mouse", "Juku E510x mouse")

juku_mouse_device::juku_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, JUKU_MOUSE, tag, owner, clock),
m_mouse_x(*this, "MOUSE_X"),
m_mouse_y(*this, "MOUSE_Y"),
m_mouse_b(*this, "BUTTONS"),
m_int_handler(*this)
{
}

void juku_mouse_device::device_start()
{
save_item(NAME(m_prev_mouse_y));
save_item(NAME(m_prev_mouse_x));
save_item(NAME(m_prev_byte));
m_mouse_timer = timer_alloc(FUNC(juku_mouse_device::poll_delta), this);
}

void juku_mouse_device::device_reset()
{
m_prev_mouse_y = 0;
m_prev_mouse_x = 0;
m_prev_byte = 0;
m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(MOUSE_RATE_HZ));
}

/*
* Calculate positive/negative delta from old and new relative value
*/
inline int delta(int o, int n)
{
if(o>n) {
if(o-n<128) return n-o;
else return n+255-o;
}
if(o<n) {
if(n-o<128) return n-o;
else return n-255-o;
}

return 0;
}

TIMER_CALLBACK_MEMBER( juku_mouse_device::poll_delta )
{
uint8_t buttons = m_mouse_b->read();
int x = m_mouse_x->read(), y = m_mouse_y->read();
int dx = delta(m_prev_mouse_x, x);
int dy = delta(m_prev_mouse_y, y);

if (dx != 0 || dy != 0 || (m_prev_byte & 0b11) != buttons) {
m_int_handler(CLEAR_LINE);
m_int_handler(ASSERT_LINE);
}
}

INPUT_PORTS_START( juku_mouse )
PORT_START("MOUSE_X")
PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_CODE(MOUSECODE_X) PORT_SENSITIVITY(23)

PORT_START("MOUSE_Y")
PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_CODE(MOUSECODE_Y) PORT_SENSITIVITY(23)

PORT_START("BUTTONS")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Left Button")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Right Button")
INPUT_PORTS_END

uint8_t juku_mouse_device::mouse_port_r()
{
// 7------- always 1
// -6------ always 0
// --5----- vertical active
// ---4---- vertical direction
// ----3--- horizontal active
// -----2-- horizontal direction
// ------1- left button
// -------0 right button

uint8_t data = 0b10000000 | m_mouse_b->read();
int x = m_mouse_x->read(), y = m_mouse_y->read();
int dx = delta(m_prev_mouse_x, x);
int dy = delta(m_prev_mouse_y, y);

if (dx != 0) {
data |= dx > 0 ? 0b00001000 : 0b00001100;
m_prev_mouse_x = x;
}

if (dy != 0) {
data |= dy > 0 ? 0b00110000 : 0b00100000;
m_prev_mouse_y = y;
}

m_prev_byte = data;

return data;
}

ioport_constructor juku_mouse_device::device_input_ports() const
{
return INPUT_PORTS_NAME( juku_mouse );
}
Loading
Loading