(nw) split llc into llc1 and llc2, as they are completely different.

This commit is contained in:
Robbbert 2020-06-19 23:20:07 +10:00
parent 240f1381ce
commit 580718db09
7 changed files with 506 additions and 493 deletions

View File

@ -2128,10 +2128,8 @@ files {
MAME_DIR .. "src/mame/includes/huebler.h",
MAME_DIR .. "src/mame/drivers/jtc.cpp",
MAME_DIR .. "src/mame/drivers/kramermc.cpp",
MAME_DIR .. "src/mame/drivers/llc.cpp",
MAME_DIR .. "src/mame/includes/llc.h",
MAME_DIR .. "src/mame/machine/llc.cpp",
MAME_DIR .. "src/mame/video/llc.cpp",
MAME_DIR .. "src/mame/drivers/llc1.cpp",
MAME_DIR .. "src/mame/drivers/llc2.cpp",
MAME_DIR .. "src/mame/drivers/nanos.cpp",
MAME_DIR .. "src/mame/drivers/pcm.cpp",
MAME_DIR .. "src/mame/drivers/vcs80.cpp",

View File

@ -2,7 +2,7 @@
// copyright-holders:Miodrag Milanovic, Robbbert
/******************************************************************************
LLC driver by Miodrag Milanovic
LLC1 driver by Miodrag Milanovic
17/04/2009 Preliminary driver.
@ -29,37 +29,68 @@
The user instructions of the monitor (in German) are here:
http://www.jens-mueller.org/jkcemu/llc1.html
LLC2:
The BEL character plays a short tune.
In the monitor, it is case sensitive, most commands are uppercase,
but some are lowercase.
To start Basic, the command is b. To quit basic, use BYE.
Inside Basic, it is not case-sensitive.
ToDo:
- LLC1: Get good dump of monitor rom, has a number of bad bytes
- LLC1: In Basic, pressing enter several times causes the start
of the line to be shifted 1 or 2 characters to the right.
- LLC1: Go command crashes
- LLC2: Keyboard is incomplete
- Lots of other things
*******************************************************************************/
#include "emu.h"
#include "includes/llc.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "machine/z80ctc.h"
#include "machine/z80pio.h"
#include "machine/keyboard.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "llc1.lh"
class llc1_state : public driver_device
{
public:
llc1_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_p_chargen(*this, "chargen")
, m_vram(*this, "videoram")
, m_digits(*this, "digit%u", 0U)
{ }
void llc1(machine_config &config);
private:
void machine_start() override;
void machine_reset() override;
void kbd_put(u8 data);
u8 llc1_port1_a_r();
u8 llc1_port2_a_r();
u8 llc1_port2_b_r();
void llc1_port1_a_w(u8 data);
void llc1_port1_b_w(u8 data);
u32 screen_update_llc1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void io_map(address_map &map);
void mem_map(address_map &map);
u8 m_term_status;
u8 m_llc1_key;
u8 m_porta;
u8 m_term_data;
required_device<z80_device> m_maincpu;
required_region_ptr<u8> m_p_chargen;
required_shared_ptr<u8> m_vram;
output_finder<8> m_digits;
};
/* Address maps */
void llc_state::llc1_mem(address_map &map)
void llc1_state::mem_map(address_map &map)
{
map(0x0000, 0x07ff).rom(); // Monitor ROM
map(0x0800, 0x13ff).rom(); // BASIC ROM
@ -67,7 +98,7 @@ void llc_state::llc1_mem(address_map &map)
map(0x1c00, 0x1fff).ram().share("videoram"); // Video RAM
}
void llc_state::llc1_io(address_map &map)
void llc1_state::io_map(address_map &map)
{
map.global_mask(0xff);
map.unmap_value_high();
@ -76,25 +107,6 @@ void llc_state::llc1_io(address_map &map)
map(0xF8, 0xFB).rw("z80ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
void llc_state::llc2_mem(address_map &map)
{
map(0x0000, 0x3fff).bankrw("bank1");
map(0x4000, 0x5fff).bankrw("bank2");
map(0x6000, 0xbfff).bankrw("bank3");
map(0xc000, 0xffff).bankrw("bank4");
}
void llc_state::llc2_io(address_map &map)
{
map.global_mask(0xff);
map.unmap_value_high();
map(0xE0, 0xE3).w(FUNC(llc_state::llc2_rom_disable_w));
map(0xE4, 0xE7).rw("z80pio2", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
map(0xE8, 0xEB).rw("z80pio1", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
map(0xEC, 0xEC).w(FUNC(llc_state::llc2_basic_enable_w));
map(0xF8, 0xFB).rw("z80ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
/* Input ports */
static INPUT_PORTS_START( llc1 )
PORT_START("X4") // out F4,BF
@ -126,15 +138,11 @@ static INPUT_PORTS_START( llc1 )
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED) // does nothing
INPUT_PORTS_END
static INPUT_PORTS_START( llc2 )
INPUT_PORTS_END
void llc_state::kbd_put(u8 data)
void llc1_state::kbd_put(u8 data)
{
static constexpr uint8_t s1[16]={0x40, 0x1e, 0x12, 0x1b, 0x19, 0x14, 0x15, 0x1d, 0x16, 0x17, 0x1c, 0x3c, 0x3f, 0x3d, 0x3e, 0x10}; // 0x20 to 0x2F
static constexpr uint8_t s2[7] ={0x1a, 0x11, 0x7c, 0x13, 0x7b, 0x1f, 0x00}; // 0x3A to 0x40
static constexpr uint8_t s3[6] ={0x5c, 0x00, 0x5b, 0x7e, 0x00, 0x5e}; // 0x5B to 0x60
static constexpr u8 s1[16]={0x40, 0x1e, 0x12, 0x1b, 0x19, 0x14, 0x15, 0x1d, 0x16, 0x17, 0x1c, 0x3c, 0x3f, 0x3d, 0x3e, 0x10}; // 0x20 to 0x2F
static constexpr u8 s2[7] ={0x1a, 0x11, 0x7c, 0x13, 0x7b, 0x1f, 0x00}; // 0x3A to 0x40
static constexpr u8 s3[6] ={0x5c, 0x00, 0x5b, 0x7e, 0x00, 0x5e}; // 0x5B to 0x60
m_term_data = data;
@ -151,19 +159,144 @@ void llc_state::kbd_put(u8 data)
m_term_status = 0xff;
}
// LLC1 BASIC keyboard
u8 llc1_state::llc1_port2_b_r()
{
u8 retVal = 0;
if (m_term_status)
{
retVal = m_term_status;
m_term_status = 0;
}
else
retVal = m_term_data;
return retVal;
}
u8 llc1_state::llc1_port2_a_r()
{
return 0;
}
// LLC1 Monitor keyboard
u8 llc1_state::llc1_port1_a_r()
{
u8 data = 0;
if (!BIT(m_porta, 4))
data = ioport("X4")->read();
if (!BIT(m_porta, 5))
data = ioport("X5")->read();
if (!BIT(m_porta, 6))
data = ioport("X6")->read();
if (data & 0xf0)
data = (data >> 4) | 0x80;
data |= (m_porta & 0x70);
// do not repeat key
if (data & 15)
{
if (data == m_llc1_key)
data &= 0x70;
else
m_llc1_key = data;
}
else
if ((data & 0x70) == (m_llc1_key & 0x70))
m_llc1_key = 0;
return data;
}
void llc1_state::llc1_port1_a_w(u8 data)
{
m_porta = data;
}
void llc1_state::llc1_port1_b_w(u8 data)
{
static u8 count = 0, digit = 0;
if (data == 0)
{
digit = 0;
count = 0;
}
else
count++;
if (count == 1)
{
if (digit < 8)
m_digits[digit] = data & 0x7f;
}
else
if (count == 3)
{
count = 0;
digit++;
}
}
void llc1_state::machine_reset()
{
m_term_status = 0;
m_llc1_key = 0;
}
void llc1_state::machine_start()
{
m_digits.resolve();
save_item(NAME(m_term_status));
save_item(NAME(m_llc1_key));
save_item(NAME(m_porta));
save_item(NAME(m_term_data));
}
u32 llc1_state::screen_update_llc1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
u8 y,ra,chr,gfx,inv;
u16 sy=0,ma=0,x;
for (y = 0; y < 16; y++)
{
for (ra = 0; ra < 8; ra++)
{
u16 *p = &bitmap.pix16(sy++);
for (x = ma; x < ma + 64; x++)
{
inv = (m_vram[x] & 0x80) ? 0xff : 0;
chr = m_vram[x] & 0x7f;
/* get pattern of pixels for that character scanline */
gfx = m_p_chargen[ chr | (ra << 7) ] ^ inv;
/* Display a scanline of a character (8 pixels) */
*p++ = BIT(gfx, 7);
*p++ = BIT(gfx, 6);
*p++ = BIT(gfx, 5);
*p++ = BIT(gfx, 4);
*p++ = BIT(gfx, 3);
*p++ = BIT(gfx, 2);
*p++ = BIT(gfx, 1);
*p++ = BIT(gfx, 0);
}
}
ma+=64;
}
return 0;
}
static const z80_daisy_config llc1_daisy_chain[] =
{
{ "z80ctc" },
{ nullptr }
};
static const z80_daisy_config llc2_daisy_chain[] =
{
{ "z80pio1" },
{ "z80ctc" },
{ nullptr }
};
/* F4 Character Displayer */
static const gfx_layout llc1_charlayout =
{
@ -178,38 +311,18 @@ static const gfx_layout llc1_charlayout =
8 /* every char takes 8 x 1 bytes */
};
static const gfx_layout llc2_charlayout =
{
8, 8, /* 8 x 8 characters */
256, /* 256 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 bytes */
};
static GFXDECODE_START( gfx_llc1 )
GFXDECODE_ENTRY( "chargen", 0x0000, llc1_charlayout, 0, 1 )
GFXDECODE_END
static GFXDECODE_START( gfx_llc2 )
GFXDECODE_ENTRY( "chargen", 0x0000, llc2_charlayout, 0, 1 )
GFXDECODE_END
/* Machine driver */
void llc_state::llc1(machine_config &config)
void llc1_state::llc1(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, XTAL(3'000'000));
m_maincpu->set_daisy_config(llc1_daisy_chain);
m_maincpu->set_addrmap(AS_PROGRAM, &llc_state::llc1_mem);
m_maincpu->set_addrmap(AS_IO, &llc_state::llc1_io);
MCFG_MACHINE_START_OVERRIDE(llc_state, llc1 )
MCFG_MACHINE_RESET_OVERRIDE(llc_state, llc1 )
m_maincpu->set_addrmap(AS_PROGRAM, &llc1_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &llc1_state::io_map);
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -217,7 +330,7 @@ void llc_state::llc1(machine_config &config)
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(64*8, 16*8);
screen.set_visarea(0, 64*8-1, 0, 16*8-1);
screen.set_screen_update(FUNC(llc_state::screen_update_llc1));
screen.set_screen_update(FUNC(llc1_state::screen_update_llc1));
screen.set_palette("palette");
GFXDECODE(config, "gfxdecode", "palette", gfx_llc1);
@ -225,13 +338,13 @@ void llc_state::llc1(machine_config &config)
config.set_default_layout(layout_llc1);
z80pio_device& pio1(Z80PIO(config, "z80pio1", XTAL(3'000'000)));
pio1.in_pa_callback().set(FUNC(llc_state::llc1_port1_a_r));
pio1.out_pa_callback().set(FUNC(llc_state::llc1_port1_a_w));
pio1.out_pb_callback().set(FUNC(llc_state::llc1_port1_b_w));
pio1.in_pa_callback().set(FUNC(llc1_state::llc1_port1_a_r));
pio1.out_pa_callback().set(FUNC(llc1_state::llc1_port1_a_w));
pio1.out_pb_callback().set(FUNC(llc1_state::llc1_port1_b_w));
z80pio_device& pio2(Z80PIO(config, "z80pio2", XTAL(3'000'000)));
pio2.in_pa_callback().set(FUNC(llc_state::llc1_port2_a_r));
pio2.in_pb_callback().set(FUNC(llc_state::llc1_port2_b_r));
pio2.in_pa_callback().set(FUNC(llc1_state::llc1_port2_a_r));
pio2.in_pb_callback().set(FUNC(llc1_state::llc1_port2_b_r));
z80ctc_device& ctc(Z80CTC(config, "z80ctc", XTAL(3'000'000)));
// timer 0 irq does digit display, and timer 3 irq does scan of the
@ -242,76 +355,27 @@ void llc_state::llc1(machine_config &config)
ctc.zc_callback<1>().set("z80ctc", FUNC(z80ctc_device::trg3));
generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
keyboard.set_keyboard_callback(FUNC(llc_state::kbd_put));
keyboard.set_keyboard_callback(FUNC(llc1_state::kbd_put));
}
void llc_state::llc2(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, XTAL(3'000'000));
m_maincpu->set_daisy_config(llc2_daisy_chain);
m_maincpu->set_addrmap(AS_PROGRAM, &llc_state::llc2_mem);
m_maincpu->set_addrmap(AS_IO, &llc_state::llc2_io);
MCFG_MACHINE_RESET_OVERRIDE(llc_state, llc2 )
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(50);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(64*8, 32*8);
screen.set_visarea(0, 64*8-1, 0, 32*8-1);
screen.set_screen_update(FUNC(llc_state::screen_update_llc2));
screen.set_palette("palette");
GFXDECODE(config, "gfxdecode", "palette", gfx_llc2);
PALETTE(config, "palette", palette_device::MONOCHROME);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.15);
z80pio_device& pio1(Z80PIO(config, "z80pio1", XTAL(3'000'000)));
pio1.in_pa_callback().set(K7659_KEYBOARD_TAG, FUNC(k7659_keyboard_device::read));
pio1.in_pb_callback().set(FUNC(llc_state::llc2_port1_b_r));
pio1.out_pb_callback().set(FUNC(llc_state::llc2_port1_b_w));
z80pio_device& pio2(Z80PIO(config, "z80pio2", XTAL(3'000'000)));
pio2.in_pa_callback().set(FUNC(llc_state::llc2_port2_a_r));
Z80CTC(config, "z80ctc", XTAL(3'000'000));
K7659_KEYBOARD(config, K7659_KEYBOARD_TAG, 0);
/* internal ram */
RAM(config, RAM_TAG).set_default_size("64K");
}
/* ROM definition */
ROM_START( llc1 )
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_REGION( 0x1400, "maincpu", 0 )
//ROM_LOAD( "llc1-monitor.rom", 0x0000, 0x0800, BAD_DUMP CRC(0e81378d) SHA1(0fbb6eca016d0f439ea1c9aa0cb0affb5f49ea69) )
ROM_LOAD( "llc1mon.bin", 0x0000, 0x0800, BAD_DUMP CRC(e291dd63) SHA1(31a71bef84f7c164a270d0895cb645e078e9c6f2) )
ROM_LOAD( "llc1mon.bin", 0x0000, 0x0800, BAD_DUMP CRC(e291dd63) SHA1(31a71bef84f7c164a270d0895cb645e078e9c6f2) )
ROM_LOAD( "llc1_tb1.bin", 0x0800, 0x0400, CRC(0d9d4039) SHA1(b515e385af57f4faf3a9f7b4a1edd59a1c1ea260) )
ROM_LOAD( "llc1_tb2.bin", 0x0c00, 0x0400, CRC(28bfea2a) SHA1(a68a8b87bfc931627ddd8d124b153e511477fbaf) )
ROM_LOAD( "llc1_tb3.bin", 0x1000, 0x0400, CRC(fe5e3132) SHA1(cc3b191e41f5772a4b86b8eb0ebe6fce67872df6) )
ROM_FILL(0x23b, 1, 0x00) // don't reboot when typing into the monitor
ROM_FILL(0x2dc, 1, 0x0f) // fix display of AF in the reg command
ROM_REGION(0x0400, "chargen",0)
ROM_LOAD ("llc1_zg.bin", 0x0000, 0x0400, CRC(fa2cd659) SHA1(1fa5f9992f35929f656c4ce55ed6980c5da1772b) )
ROM_END
ROM_START( llc2 )
ROM_REGION( 0x12000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "scchmon_91.bin", 0x0000, 0x1000, CRC(218d8236) SHA1(b8297272cc79751afc2eb8688d99b40691346dcb) )
ROM_LOAD( "gsbasic.bin", 0x10000, 0x2000, CRC(78a5f388) SHA1(e7b475b98dce36b24540ad11eb89046ddb4f02af) )
ROM_REGION(0x0800, "chargen",0)
ROM_LOAD ("llc2font.bin", 0x0000, 0x0800, CRC(ce53e55d) SHA1(da23d93f14a8a1f8d82bb72470a96b0bfd81ed1b) )
ROM_REGION( 0x0400, "chargen", 0 )
ROM_LOAD ("llc1_zg.bin", 0x0000, 0x0400, CRC(fa2cd659) SHA1(1fa5f9992f35929f656c4ce55ed6980c5da1772b) )
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1984, llc1, 0, 0, llc1, llc1, llc_state, init_llc1, "SCCH", "LLC-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW)
COMP( 1984, llc2, llc1, 0, llc2, llc2, llc_state, init_llc2, "SCCH", "LLC-2", 0 )
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1984, llc1, 0, 0, llc1, llc1, llc1_state, empty_init, "SCCH", "LLC-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE )

305
src/mame/drivers/llc2.cpp Normal file
View File

@ -0,0 +1,305 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic, Robbbert
/******************************************************************************
LLC driver by Miodrag Milanovic
17/04/2009 Preliminary driver.
July 2012, updates by Robbbert
Very little info available on these computers.
LLC2:
The BEL character plays a short tune.
In the monitor, it is case sensitive, most commands are uppercase,
but some are lowercase.
To start Basic, the command is b. To quit basic, use BYE.
Inside Basic, it is not case-sensitive.
ToDo:
- LLC2: Keyboard is incomplete
- Lots of other things
*******************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "machine/k7659kb.h"
#include "machine/ram.h"
#include "machine/z80ctc.h"
#include "machine/z80pio.h"
#include "sound/spkrdev.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
class llc2_state : public driver_device
{
public:
llc2_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_speaker(*this, "speaker")
, m_vram(*this, "videoram")
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_p_chargen(*this, "chargen")
{ }
void llc2(machine_config &config);
void init_llc2();
private:
void machine_start() override;
void machine_reset() override;
void llc2_rom_disable_w(u8 data);
void llc2_basic_enable_w(u8 data);
u8 llc2_port1_b_r();
u8 llc2_port2_a_r();
void llc2_port1_b_w(u8 data);
u32 screen_update_llc2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void io_map(address_map &map);
void mem_map(address_map &map);
bool m_rv;
optional_device<speaker_sound_device> m_speaker;
optional_shared_ptr<u8> m_vram;
required_device<z80_device> m_maincpu;
optional_device<ram_device> m_ram;
required_region_ptr<u8> m_p_chargen;
};
/* Address maps */
void llc2_state::mem_map(address_map &map)
{
map(0x0000, 0x3fff).bankrw("bank1");
map(0x4000, 0x5fff).bankrw("bank2");
map(0x6000, 0xbfff).bankrw("bank3");
map(0xc000, 0xffff).bankrw("bank4");
}
void llc2_state::io_map(address_map &map)
{
map.global_mask(0xff);
map.unmap_value_high();
map(0xE0, 0xE3).w(FUNC(llc2_state::llc2_rom_disable_w));
map(0xE4, 0xE7).rw("z80pio2", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
map(0xE8, 0xEB).rw("z80pio1", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
map(0xEC, 0xEC).w(FUNC(llc2_state::llc2_basic_enable_w));
map(0xF8, 0xFB).rw("z80ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
/* Input ports */
static INPUT_PORTS_START( llc2 )
INPUT_PORTS_END
/* Driver initialization */
void llc2_state::init_llc2()
{
m_vram.set_target( m_ram->pointer() + 0xc000,m_vram.bytes());
}
void llc2_state::machine_reset()
{
address_space &space = m_maincpu->space(AS_PROGRAM);
u8 *ram = m_ram->pointer();
space.unmap_write(0x0000, 0x3fff);
membank("bank1")->set_base(memregion("maincpu")->base());
space.unmap_write(0x4000, 0x5fff);
membank("bank2")->set_base(ram + 0x4000);
space.unmap_write(0x6000, 0xbfff);
membank("bank3")->set_base(ram + 0x6000);
space.install_write_bank(0xc000, 0xffff, "bank4");
membank("bank4")->set_base(ram + 0xc000);
}
void llc2_state::llc2_rom_disable_w(u8 data)
{
address_space &mem_space = m_maincpu->space(AS_PROGRAM);
u8 *ram = m_ram->pointer();
mem_space.install_write_bank(0x0000, 0xbfff, "bank1");
membank("bank1")->set_base(ram);
mem_space.install_write_bank(0x4000, 0x5fff, "bank2");
membank("bank2")->set_base(ram + 0x4000);
mem_space.install_write_bank(0x6000, 0xbfff, "bank3");
membank("bank3")->set_base(ram + 0x6000);
mem_space.install_write_bank(0xc000, 0xffff, "bank4");
membank("bank4")->set_base(ram + 0xc000);
}
void llc2_state::llc2_basic_enable_w(u8 data)
{
address_space &mem_space = m_maincpu->space(AS_PROGRAM);
if (BIT(data, 1))
{
mem_space.unmap_write(0x4000, 0x5fff);
membank("bank2")->set_base(memregion("maincpu")->base() + 0x4000);
}
else
{
mem_space.install_write_bank(0x4000, 0x5fff, "bank2");
membank("bank2")->set_base(m_ram->pointer() + 0x4000);
}
}
u8 llc2_state::llc2_port1_b_r()
{
return 0;
}
void llc2_state::llc2_port1_b_w(u8 data)
{
m_speaker->level_w(BIT(data, 6));
m_rv = BIT(data, 5);
}
u8 llc2_state::llc2_port2_a_r()
{
return 0; // bit 2 low or hangs on ^Z^X^C sequence
}
void llc2_state::machine_start()
{
save_item(NAME(m_rv));
}
u32 llc2_state::screen_update_llc2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
u8 y,ra,chr,gfx,inv, inv1=m_rv ? 0xff : 0;
u16 sy=0,ma=0,x;
for (y = 0; y < 32; y++)
{
for (ra = 0; ra < 8; ra++)
{
inv = 0;
u16 *p = &bitmap.pix16(sy++);
for (x = ma; x < ma + 64; x++)
{
chr = m_vram[x];
if (chr==0x11) // inverse on
{
inv=0xff;
chr=0x0f; // must not show
}
else
if (chr==0x10) // inverse off
inv=0;
/* get pattern of pixels for that character scanline */
gfx = m_p_chargen[ (chr << 3) | ra ] ^ inv ^ inv1;
/* Display a scanline of a character (8 pixels) */
*p++ = BIT(gfx, 7);
*p++ = BIT(gfx, 6);
*p++ = BIT(gfx, 5);
*p++ = BIT(gfx, 4);
*p++ = BIT(gfx, 3);
*p++ = BIT(gfx, 2);
*p++ = BIT(gfx, 1);
*p++ = BIT(gfx, 0);
}
}
ma+=64;
}
return 0;
}
static const z80_daisy_config llc2_daisy_chain[] =
{
{ "z80pio1" },
{ "z80ctc" },
{ nullptr }
};
/* F4 Character Displayer */
static const gfx_layout llc2_charlayout =
{
8, 8, /* 8 x 8 characters */
256, /* 256 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
8*8 /* every char takes 8 bytes */
};
static GFXDECODE_START( gfx_llc2 )
GFXDECODE_ENTRY( "chargen", 0x0000, llc2_charlayout, 0, 1 )
GFXDECODE_END
/* Machine driver */
void llc2_state::llc2(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, XTAL(3'000'000));
m_maincpu->set_daisy_config(llc2_daisy_chain);
m_maincpu->set_addrmap(AS_PROGRAM, &llc2_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &llc2_state::io_map);
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(50);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(64*8, 32*8);
screen.set_visarea(0, 64*8-1, 0, 32*8-1);
screen.set_screen_update(FUNC(llc2_state::screen_update_llc2));
screen.set_palette("palette");
GFXDECODE(config, "gfxdecode", "palette", gfx_llc2);
PALETTE(config, "palette", palette_device::MONOCHROME);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.15);
z80pio_device& pio1(Z80PIO(config, "z80pio1", XTAL(3'000'000)));
pio1.in_pa_callback().set(K7659_KEYBOARD_TAG, FUNC(k7659_keyboard_device::read));
pio1.in_pb_callback().set(FUNC(llc2_state::llc2_port1_b_r));
pio1.out_pb_callback().set(FUNC(llc2_state::llc2_port1_b_w));
z80pio_device& pio2(Z80PIO(config, "z80pio2", XTAL(3'000'000)));
pio2.in_pa_callback().set(FUNC(llc2_state::llc2_port2_a_r));
Z80CTC(config, "z80ctc", XTAL(3'000'000));
K7659_KEYBOARD(config, K7659_KEYBOARD_TAG, 0);
/* internal ram */
RAM(config, RAM_TAG).set_default_size("64K");
}
/* ROM definition */
ROM_START( llc2 )
ROM_REGION( 0x6000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "scchmon_91.bin", 0x0000, 0x1000, CRC(218d8236) SHA1(b8297272cc79751afc2eb8688d99b40691346dcb) )
ROM_LOAD( "gsbasic.bin", 0x4000, 0x2000, CRC(78a5f388) SHA1(e7b475b98dce36b24540ad11eb89046ddb4f02af) )
ROM_REGION( 0x0800, "chargen", 0 )
ROM_LOAD ("llc2font.bin", 0x0000, 0x0800, CRC(ce53e55d) SHA1(da23d93f14a8a1f8d82bb72470a96b0bfd81ed1b) )
ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1984, llc2, llc1, 0, llc2, llc2, llc2_state, init_llc2, "SCCH", "LLC-2", MACHINE_SUPPORTS_SAVE )

View File

@ -1,78 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic, Robbbert
/*****************************************************************************
*
* includes/llc.h
*
****************************************************************************/
#ifndef MAME_INCLUDES_LLC_H
#define MAME_INCLUDES_LLC_H
#pragma once
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "machine/k7659kb.h"
#include "machine/ram.h"
#include "machine/z80ctc.h"
#include "machine/z80pio.h"
#include "sound/spkrdev.h"
class llc_state : public driver_device
{
public:
llc_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_speaker(*this, "speaker")
, m_p_videoram(*this, "videoram")
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_p_chargen(*this, "chargen")
, m_digits(*this, "digit%u", 0U)
{ }
void llc1(machine_config &config);
void llc2(machine_config &config);
void init_llc2();
void init_llc1();
private:
void llc2_rom_disable_w(uint8_t data);
void llc2_basic_enable_w(uint8_t data);
void kbd_put(u8 data);
uint8_t llc1_port1_a_r();
uint8_t llc1_port2_a_r();
uint8_t llc1_port2_b_r();
void llc1_port1_a_w(uint8_t data);
void llc1_port1_b_w(uint8_t data);
uint8_t llc2_port1_b_r();
uint8_t llc2_port2_a_r();
void llc2_port1_b_w(uint8_t data);
DECLARE_MACHINE_START(llc1);
DECLARE_MACHINE_RESET(llc1);
DECLARE_MACHINE_RESET(llc2);
uint32_t screen_update_llc1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
uint32_t screen_update_llc2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void llc1_io(address_map &map);
void llc1_mem(address_map &map);
void llc2_io(address_map &map);
void llc2_mem(address_map &map);
bool m_rv;
uint8_t m_term_status;
uint8_t m_llc1_key;
uint8_t m_porta;
uint8_t m_term_data;
optional_device<speaker_sound_device> m_speaker;
optional_shared_ptr<uint8_t> m_p_videoram;
required_device<z80_device> m_maincpu;
optional_device<ram_device> m_ram;
required_region_ptr<u8> m_p_chargen;
output_finder<8> m_digits;
};
#endif // MAME_INCLUDES_LLC_H

View File

@ -1,185 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic, Robbbert
/***************************************************************************
LLC driver by Miodrag Milanovic
17/04/2009 Preliminary driver.
****************************************************************************/
#include "emu.h"
#include "includes/llc.h"
// LLC1 BASIC keyboard
uint8_t llc_state::llc1_port2_b_r()
{
uint8_t retVal = 0;
if (m_term_status)
{
retVal = m_term_status;
m_term_status = 0;
}
else
retVal = m_term_data;
return retVal;
}
uint8_t llc_state::llc1_port2_a_r()
{
return 0;
}
// LLC1 Monitor keyboard
uint8_t llc_state::llc1_port1_a_r()
{
uint8_t data = 0;
if (!BIT(m_porta, 4))
data = ioport("X4")->read();
if (!BIT(m_porta, 5))
data = ioport("X5")->read();
if (!BIT(m_porta, 6))
data = ioport("X6")->read();
if (data & 0xf0)
data = (data >> 4) | 0x80;
data |= (m_porta & 0x70);
// do not repeat key
if (data & 15)
{
if (data == m_llc1_key)
data &= 0x70;
else
m_llc1_key = data;
}
else
if ((data & 0x70) == (m_llc1_key & 0x70))
m_llc1_key = 0;
return data;
}
void llc_state::llc1_port1_a_w(uint8_t data)
{
m_porta = data;
}
void llc_state::llc1_port1_b_w(uint8_t data)
{
static uint8_t count = 0, digit = 0;
if (data == 0)
{
digit = 0;
count = 0;
}
else
count++;
if (count == 1)
{
if (digit < 8)
m_digits[digit] = data & 0x7f;
}
else
if (count == 3)
{
count = 0;
digit++;
}
}
void llc_state::init_llc1()
{
}
MACHINE_RESET_MEMBER(llc_state,llc1)
{
m_term_status = 0;
m_llc1_key = 0;
}
MACHINE_START_MEMBER(llc_state,llc1)
{
m_digits.resolve();
}
/* Driver initialization */
void llc_state::init_llc2()
{
m_p_videoram.set_target( m_ram->pointer() + 0xc000,m_p_videoram.bytes());
}
MACHINE_RESET_MEMBER(llc_state,llc2)
{
address_space &space = m_maincpu->space(AS_PROGRAM);
space.unmap_write(0x0000, 0x3fff);
membank("bank1")->set_base(memregion("maincpu")->base());
space.unmap_write(0x4000, 0x5fff);
membank("bank2")->set_base(memregion("maincpu")->base() + 0x4000);
space.unmap_write(0x6000, 0xbfff);
membank("bank3")->set_base(memregion("maincpu")->base() + 0x6000);
space.install_write_bank(0xc000, 0xffff, "bank4");
membank("bank4")->set_base(m_ram->pointer() + 0xc000);
}
void llc_state::llc2_rom_disable_w(uint8_t data)
{
address_space &mem_space = m_maincpu->space(AS_PROGRAM);
uint8_t *ram = m_ram->pointer();
mem_space.install_write_bank(0x0000, 0xbfff, "bank1");
membank("bank1")->set_base(ram);
mem_space.install_write_bank(0x4000, 0x5fff, "bank2");
membank("bank2")->set_base(ram + 0x4000);
mem_space.install_write_bank(0x6000, 0xbfff, "bank3");
membank("bank3")->set_base(ram + 0x6000);
mem_space.install_write_bank(0xc000, 0xffff, "bank4");
membank("bank4")->set_base(ram + 0xc000);
}
void llc_state::llc2_basic_enable_w(uint8_t data)
{
address_space &mem_space = m_maincpu->space(AS_PROGRAM);
if (data & 0x02)
{
mem_space.unmap_write(0x4000, 0x5fff);
membank("bank2")->set_base(memregion("maincpu")->base() + 0x10000);
}
else
{
mem_space.install_write_bank(0x4000, 0x5fff, "bank2");
membank("bank2")->set_base(m_ram->pointer() + 0x4000);
}
}
uint8_t llc_state::llc2_port1_b_r()
{
return 0;
}
void llc_state::llc2_port1_b_w(uint8_t data)
{
m_speaker->level_w(BIT(data, 6));
m_rv = BIT(data, 5);
}
uint8_t llc_state::llc2_port2_a_r()
{
return 0; // bit 2 low or hangs on ^Z^X^C sequence
}

View File

@ -491,7 +491,8 @@ lft.cpp
lg-dvd.cpp
lilith.cpp
lisa.cpp
llc.cpp
llc1.cpp
llc2.cpp
lms46.cpp
lola8a.cpp
lviv.cpp

View File

@ -1,92 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic, Robbbert
/***************************************************************************
LLC driver by Miodrag Milanovic
17/04/2009 Preliminary driver.
****************************************************************************/
#include "emu.h"
#include "includes/llc.h"
uint32_t llc_state::screen_update_llc1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t y,ra,chr,gfx,inv;
uint16_t sy=0,ma=0,x;
for (y = 0; y < 16; y++)
{
for (ra = 0; ra < 8; ra++)
{
uint16_t *p = &bitmap.pix16(sy++);
for (x = ma; x < ma + 64; x++)
{
inv = (m_p_videoram[x] & 0x80) ? 0xff : 0;
chr = m_p_videoram[x] & 0x7f;
/* get pattern of pixels for that character scanline */
gfx = m_p_chargen[ chr | (ra << 7) ] ^ inv;
/* Display a scanline of a character (8 pixels) */
*p++ = BIT(gfx, 7);
*p++ = BIT(gfx, 6);
*p++ = BIT(gfx, 5);
*p++ = BIT(gfx, 4);
*p++ = BIT(gfx, 3);
*p++ = BIT(gfx, 2);
*p++ = BIT(gfx, 1);
*p++ = BIT(gfx, 0);
}
}
ma+=64;
}
return 0;
}
uint32_t llc_state::screen_update_llc2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t y,ra,chr,gfx,inv, inv1=m_rv ? 0xff : 0;
uint16_t sy=0,ma=0,x;
for (y = 0; y < 32; y++)
{
for (ra = 0; ra < 8; ra++)
{
inv = 0;
uint16_t *p = &bitmap.pix16(sy++);
for (x = ma; x < ma + 64; x++)
{
chr = m_p_videoram[x];
if (chr==0x11) // inverse on
{
inv=0xff;
chr=0x0f; // must not show
}
else
if (chr==0x10) // inverse off
inv=0;
/* get pattern of pixels for that character scanline */
gfx = m_p_chargen[ (chr << 3) | ra ] ^ inv ^ inv1;
/* Display a scanline of a character (8 pixels) */
*p++ = BIT(gfx, 7);
*p++ = BIT(gfx, 6);
*p++ = BIT(gfx, 5);
*p++ = BIT(gfx, 4);
*p++ = BIT(gfx, 3);
*p++ = BIT(gfx, 2);
*p++ = BIT(gfx, 1);
*p++ = BIT(gfx, 0);
}
}
ma+=64;
}
return 0;
}