summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2020-07-10 02:41:24 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2020-07-10 02:41:24 +1000
commit700d95e88f665f7ba0029ccb31684206432d92ee (patch)
treedaf5cc0b15123465e19a5480cdf616cf3ba55a7f
parentbe6924832da5675e8aa4f7cb3f901e4d9e2d4300 (diff)
llc2: cleanup, added cassette
-rw-r--r--src/mame/drivers/llc2.cpp189
1 files changed, 93 insertions, 96 deletions
diff --git a/src/mame/drivers/llc2.cpp b/src/mame/drivers/llc2.cpp
index bd0b6d896c0..b22de1b0774 100644
--- a/src/mame/drivers/llc2.cpp
+++ b/src/mame/drivers/llc2.cpp
@@ -2,24 +2,21 @@
// copyright-holders:Miodrag Milanovic, Robbbert
/******************************************************************************
- LLC driver by Miodrag Milanovic
+LLC2 driver by Miodrag Milanovic
- 17/04/2009 Preliminary driver.
+2009-04-17 Preliminary driver.
- July 2012, updates by Robbbert
+2012-07-?? Updates by Robbbert
- Very little info available on these computers.
+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.
- 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
+ToDo:
+- Unofficial expansions
+- Need software
*******************************************************************************/
@@ -31,6 +28,7 @@
#include "machine/ram.h"
#include "machine/z80ctc.h"
#include "machine/z80pio.h"
+#include "imagedev/cassette.h"
#include "sound/spkrdev.h"
#include "emupal.h"
#include "screen.h"
@@ -47,6 +45,10 @@ public:
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_p_chargen(*this, "chargen")
+ , m_cass(*this, "cassette")
+ , m_ctc(*this, "ctc")
+ , m_bankr(*this, "bankr%u", 0U)
+ , m_bankw(*this, "bankw%u", 0U)
{ }
void llc2(machine_config &config);
@@ -56,42 +58,46 @@ public:
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 rom_disable_w(u8 data);
+ void basic_enable_w(u8 data);
+ u8 port1b_r();
+ u8 port2a_r();
+ void port1b_w(u8 data);
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void io_map(address_map &map);
void mem_map(address_map &map);
bool m_rv;
required_device<speaker_sound_device> m_speaker;
- optional_shared_ptr<u8> m_vram;
+ required_shared_ptr<u8> m_vram;
required_device<z80_device> m_maincpu;
required_device<ram_device> m_ram;
required_region_ptr<u8> m_p_chargen;
+ required_device<cassette_image_device> m_cass;
+ required_device<z80ctc_device> m_ctc;
+ required_memory_bank_array<2> m_bankr;
+ required_memory_bank_array<2> m_bankw;
};
/* 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");
+ map(0x0000, 0x3fff).bankr("bankr0").bankw("bankw0");
+ map(0x4000, 0x5fff).bankr("bankr1").bankw("bankw1");
+ map(0x6000, 0xbfff).ram();
+ map(0xc000, 0xffff).ram().share("videoram");
}
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));
+ map(0xE0, 0xE3).w(FUNC(llc2_state::rom_disable_w));
+ map(0xE4, 0xE7).rw("pio2", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
+ map(0xE8, 0xEB).rw("pio1", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
+ map(0xEC, 0xEC).w(FUNC(llc2_state::basic_enable_w));
+ map(0xF8, 0xFB).rw("ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
/* Input ports */
@@ -102,74 +108,53 @@ INPUT_PORTS_END
/* Driver initialization */
void llc2_state::init_llc2()
{
- m_vram.set_target( m_ram->pointer() + 0xc000,m_vram.bytes());
+ u8 *r = m_ram->pointer();
+ u8 *m = memregion("maincpu")->base();
+
+ m_bankr[0]->configure_entry(0, r);
+ m_bankr[0]->configure_entry(1, m);
+ m_bankw[0]->configure_entry(0, r);
+ m_bankr[1]->configure_entry(0, r+0x4000);
+ m_bankr[1]->configure_entry(1, m+0x4000);
+ m_bankw[1]->configure_entry(0, r+0x4000);
}
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);
+ m_bankr[0]->set_entry(1);
+ m_bankw[0]->set_entry(0);
+ m_bankr[1]->set_entry(0);
+ m_bankw[1]->set_entry(0);
}
-void llc2_state::llc2_rom_disable_w(u8 data)
+void llc2_state::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);
-
+ m_bankr[0]->set_entry(0);
}
-void llc2_state::llc2_basic_enable_w(u8 data)
+void llc2_state::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);
- }
-
+ m_bankr[1]->set_entry(BIT(data, 1));
}
-u8 llc2_state::llc2_port1_b_r()
+u8 llc2_state::port1b_r()
{
- return 0;
+ u8 data = 0xfd;
+
+ if (m_cass->input() > 0.03)
+ data |= 0x02;
+
+ return data;
}
-void llc2_state::llc2_port1_b_w(u8 data)
+void llc2_state::port1b_w(u8 data)
{
+ m_cass->output(BIT(data, 0) ? -1.0 : +1.0);
m_speaker->level_w(BIT(data, 6));
m_rv = BIT(data, 5);
}
-u8 llc2_state::llc2_port2_a_r()
+u8 llc2_state::port2a_r()
{
return 0; // bit 2 low or hangs on ^Z^X^C sequence
}
@@ -179,7 +164,7 @@ 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)
+u32 llc2_state::screen_update(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;
@@ -222,15 +207,16 @@ u32 llc2_state::screen_update_llc2(screen_device &screen, bitmap_ind16 &bitmap,
return 0;
}
-static const z80_daisy_config llc2_daisy_chain[] =
+static const z80_daisy_config daisy_chain[] =
{
- { "z80pio1" },
- { "z80ctc" },
+ { "ctc" },
+ { "pio1" },
+ { "pio2" },
{ nullptr }
};
/* F4 Character Displayer */
-static const gfx_layout llc2_charlayout =
+static const gfx_layout charlayout =
{
8, 8, /* 8 x 8 characters */
256, /* 256 characters */
@@ -244,15 +230,15 @@ static const gfx_layout llc2_charlayout =
};
static GFXDECODE_START( gfx_llc2 )
- GFXDECODE_ENTRY( "chargen", 0x0000, llc2_charlayout, 0, 1 )
+ GFXDECODE_ENTRY( "chargen", 0x0000, 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);
+ Z80(config, m_maincpu, 12_MHz_XTAL / 4);
+ m_maincpu->set_daisy_config(daisy_chain);
m_maincpu->set_addrmap(AS_PROGRAM, &llc2_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &llc2_state::io_map);
@@ -262,7 +248,7 @@ void llc2_state::llc2(machine_config &config)
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_screen_update(FUNC(llc2_state::screen_update));
screen.set_palette("palette");
GFXDECODE(config, "gfxdecode", "palette", gfx_llc2);
@@ -270,17 +256,28 @@ void llc2_state::llc2(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
- SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.15);
+ SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);
- z80pio_device& pio1(Z80PIO(config, "z80pio1", XTAL(3'000'000)));
+ z80pio_device& pio1(Z80PIO(config, "pio1", 12_MHz_XTAL / 4));
+ pio1.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
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));
+ pio1.in_pb_callback().set(FUNC(llc2_state::port1b_r));
+ pio1.out_pb_callback().set(FUNC(llc2_state::port1b_w));
+
+ z80pio_device& pio2(Z80PIO(config, "pio2", 12_MHz_XTAL / 4));
+ pio2.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+ pio2.in_pa_callback().set(FUNC(llc2_state::port2a_r));
- z80pio_device& pio2(Z80PIO(config, "z80pio2", XTAL(3'000'000)));
- pio2.in_pa_callback().set(FUNC(llc2_state::llc2_port2_a_r));
+ Z80CTC(config, m_ctc, 12_MHz_XTAL / 4);
+ m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+ m_ctc->set_clk<0>(12_MHz_XTAL / 8);
+ m_ctc->set_clk<1>(12_MHz_XTAL / 8);
+ m_ctc->set_clk<2>(50); // comes from deep in the video section, assumed to be 50Hz
+ m_ctc->zc_callback<2>().set(m_ctc, FUNC(z80ctc_device::trg3));
- Z80CTC(config, "z80ctc", XTAL(3'000'000));
+ CASSETTE(config, m_cass);
+ m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
+ m_cass->add_route(ALL_OUTPUTS, "mono", 0.05);
K7659_KEYBOARD(config, K7659_KEYBOARD_TAG, 0);
@@ -291,11 +288,11 @@ void llc2_state::llc2(machine_config &config)
/* ROM definition */
ROM_START( llc2 )
ROM_REGION( 0x6000, "maincpu", ROMREGION_ERASEFF )
- ROM_LOAD( "scchmon_91.bin", 0x0000, 0x1000, CRC(218d8236) SHA1(b8297272cc79751afc2eb8688d99b40691346dcb) )
+ ROM_LOAD( "scchmon_91.d35", 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_LOAD ("llc2font.d17", 0x0000, 0x0800, CRC(ce53e55d) SHA1(da23d93f14a8a1f8d82bb72470a96b0bfd81ed1b) )
ROM_END