diff options
Diffstat (limited to 'src/mame/acorn/bbcbp.cpp')
| -rw-r--r-- | src/mame/acorn/bbcbp.cpp | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/src/mame/acorn/bbcbp.cpp b/src/mame/acorn/bbcbp.cpp new file mode 100644 index 00000000000..5ffad0078d3 --- /dev/null +++ b/src/mame/acorn/bbcbp.cpp @@ -0,0 +1,933 @@ +// license:BSD-3-Clause +// copyright-holders:Gordon Jefferyes, Nigel Barnes +/****************************************************************************** + + BBC Model B+ + + ANB51 - BBC Model B+ 64K + ANB52 - BBC Model B+ 64K with Econet + ANB53 - BBC Model B+ 64K with Disc interface + ANB54 - BBC Model B+ 64K with Disc and Econet interfaces + ANB55 - BBC Model B+ 128K with Disc interface + + Econet + + AEH25 - Econet X25 Gateway + + Acorn Business Computer + + ABC110 - 64K, 10MB HDD, Z80, CP/M 2.2 + ABC210/ACW443 - 4096K, 20MB HDD, 32016, PanOS + ABC310 - 1024K, 10MB HDD, 80286, DOS 3.1/GEM + + TODO: + - Cambridge Workstation has a Tube switch to disable internal co-processor. + +******************************************************************************/ + +#include "emu.h" +#include "bbc.h" +#include "acorn_serproc.h" +#include "bbc_kbd.h" + +#include "machine/tms6100.h" +#include "machine/wd_fdc.h" +#include "sound/tms5220.h" + +#include "formats/uef_cas.h" +#include "formats/csw_cas.h" + +#include "softlist_dev.h" +#include "speaker.h" + +#include "bbc.lh" + + +namespace { + +class bbcbp_state : public bbc_state +{ +public: + bbcbp_state(const machine_config &mconfig, device_type type, const char *tag) + : bbc_state(mconfig, type, tag) + , m_view_shadow(*this, "view_shadow") + , m_view_paged(*this, "view_paged") + , m_kbd(*this, "kbd") + , m_sn(*this, "sn") + , m_vsp(*this, "vsp") + , m_wdfdc(*this, "wdfdc") + , m_adlc(*this, "mc6854") + , m_statid(*this, "STATID") + { } + + void bbcbp(machine_config &config); + void bbcbp128(machine_config &config); + void abc110(machine_config &config); + void acw443(machine_config &config); + void abc310(machine_config &config); + void cfa3000bp(machine_config &config); + void econx25(machine_config &config); + +protected: + virtual void machine_start() override ATTR_COLD; + +private: + memory_view m_view_shadow; + memory_view m_view_paged; + required_device<bbc_kbd_device> m_kbd; + required_device<sn76489a_device> m_sn; + optional_device<tms5220_device> m_vsp; + optional_device<wd1770_device> m_wdfdc; + required_device<mc6854_device> m_adlc; + required_ioport m_statid; + + void bbcbp_fetch(address_map &map) ATTR_COLD; + void bbcbp_mem(address_map &map) ATTR_COLD; + void econx25_mem(address_map &map) ATTR_COLD; + + void trigger_reset(int state); + + uint8_t fetch_r(offs_t offset); + void romsel_w(offs_t offset, uint8_t data); + uint8_t paged_r(offs_t offset); + void paged_w(offs_t offset, uint8_t data); + void drive_control_w(uint8_t data); + + uint8_t sysvia_pa_r(); + void sysvia_pa_w(uint8_t data); + void update_sdb(); + uint8_t sysvia_pb_r(); + void sysvia_pb_w(uint8_t data); + + uint8_t m_sdb = 0x00; +}; + + +void bbcbp_state::machine_start() +{ + bbc_state::machine_start(); + + save_item(NAME(m_sdb)); +} + + +void bbcbp_state::bbcbp_fetch(address_map &map) +{ + map(0x0000, 0xffff).r(FUNC(bbcbp_state::fetch_r)); +} + + +void bbcbp_state::bbcbp_mem(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x7fff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write)); // 0000-7FFF Regular RAM + map(0x3000, 0x7fff).view(m_view_shadow); // 3000-7FFF 20K Shadow RAM + m_view_shadow[0](0x3000, 0x7fff).lr8(NAME([this] (offs_t offset) { return m_ram->pointer()[offset + 0xb000]; })); + m_view_shadow[0](0x3000, 0x7fff).lw8(NAME([this] (offs_t offset, uint8_t data) { m_ram->pointer()[offset + 0xb000] = data; })); + map(0x8000, 0xbfff).rw(FUNC(bbcbp_state::paged_r), FUNC(bbcbp_state::paged_w)); // 8000-BFFF Paged ROM/RAM + map(0x8000, 0xafff).view(m_view_paged); // 8000-AFFF 12K Paged RAM + m_view_paged[0](0x8000, 0xafff).lr8(NAME([this] (offs_t offset) { return m_ram->pointer()[offset + 0x8000]; })); + m_view_paged[0](0x8000, 0xafff).lw8(NAME([this] (offs_t offset, uint8_t data) { m_ram->pointer()[offset + 0x8000] = data; })); + map(0xc000, 0xffff).rw(FUNC(bbcbp_state::mos_r), FUNC(bbcbp_state::mos_w)); // C000-FBFF OS ROM + map(0xfc00, 0xfcff).rw(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::fred_r), FUNC(bbc_1mhzbus_slot_device::fred_w)); // FC00-FCFF FRED Address Page + map(0xfd00, 0xfdff).rw(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::jim_r), FUNC(bbc_1mhzbus_slot_device::jim_w)); // FD00-FDFF JIM Address Page + map(0xfe00, 0xfeff).lr8(NAME([]() { return 0xfe; })).nopw(); // FE00-FEFF SHEILA Address Page + map(0xfe00, 0xfe00).mirror(0x06).rw(m_crtc, FUNC(hd6845s_device::status_r), FUNC(hd6845s_device::address_w)); // FE00-FE07 6845 CRTC Video controller + map(0xfe01, 0xfe01).mirror(0x06).rw(m_crtc, FUNC(hd6845s_device::register_r), FUNC(hd6845s_device::register_w)); + map(0xfe08, 0xfe09).mirror(0x06).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write)); // FE08-FE0F 6850 ACIA Serial controller + map(0xfe10, 0xfe17).rw("serproc", FUNC(acorn_serproc_device::read), FUNC(acorn_serproc_device::write)); // FE10-FE17 Serial ULA Serial system chip + map(0xfe18, 0xfe1f).lr8(NAME([this]() { econet_int_enable(0); return m_statid->read(); })); // R: FE18-FE1F INTOFF/STATID ECONET Interrupt Off / ID No. + map(0xfe18, 0xfe1f).lw8(NAME([this](uint8_t data) { econet_int_enable(0); })); // W: FE18-FE1F INTOFF ECONET Interrupt Off + map(0xfe20, 0xfe2f).lr8(NAME([this]() { econet_int_enable(1); return 0xfe; })); // R: FE20-FE2F INTON ECONET Interrupt On + map(0xfe20, 0xfe2f).w(FUNC(bbcbp_state::video_ula_w)); // W: FE20-FE2F Video ULA Video system chip + map(0xfe30, 0xfe3f).w(FUNC(bbcbp_state::romsel_w)); // W: FE30-FE3F 84LS161 Paged ROM selector + map(0xfe40, 0xfe4f).mirror(0x10).m(m_sysvia, FUNC(via6522_device::map)); // FE40-FE5F 6522 VIA SYSTEM VIA + map(0xfe60, 0xfe6f).mirror(0x10).m(m_uservia, FUNC(via6522_device::map)); // FE60-FE7F 6522 VIA USER VIA + map(0xfe80, 0xfe83).w(FUNC(bbcbp_state::drive_control_w)); // FE80-FE83 1770 FDC Drive control register + map(0xfe84, 0xfe9f).rw(m_wdfdc, FUNC(wd1770_device::read), FUNC(wd1770_device::write)); // FE84-FE9F 1770 FDC Floppy disc controller + map(0xfea0, 0xfea3).mirror(0x1c).rw(m_adlc, FUNC(mc6854_device::read), FUNC(mc6854_device::write)); // FEA0-FEBF 68B54 ADLC ECONET controller + map(0xfec0, 0xfec3).mirror(0x1c).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)); // FEC0-FEDF uPD7002 Analogue to digital converter + map(0xfee0, 0xfeff).rw(m_tube, FUNC(bbc_tube_slot_device::host_r), FUNC(bbc_tube_slot_device::host_w)); // FEE0-FEFF Tube ULA Tube system interface +} + + +void bbcbp_state::econx25_mem(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x7fff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write)); // 0000-7FFF Regular RAM + map(0x3000, 0x7fff).view(m_view_shadow); // 3000-7FFF 20K Shadow RAM + m_view_shadow[0](0x3000, 0x7fff).lr8(NAME([this] (offs_t offset) { return m_ram->pointer()[offset + 0xb000]; })); + m_view_shadow[0](0x3000, 0x7fff).lw8(NAME([this] (offs_t offset, uint8_t data) { m_ram->pointer()[offset + 0xb000] = data; })); + map(0x8000, 0xbfff).rw(FUNC(bbcbp_state::paged_r), FUNC(bbcbp_state::paged_w)); // 8000-BFFF Paged ROM/RAM + map(0x8000, 0xafff).view(m_view_paged); // 8000-AFFF 12K Paged RAM + m_view_paged[0](0x8000, 0xafff).lr8(NAME([this] (offs_t offset) { return m_ram->pointer()[offset + 0x8000]; })); + m_view_paged[0](0x8000, 0xafff).lw8(NAME([this] (offs_t offset, uint8_t data) { m_ram->pointer()[offset + 0x8000] = data; })); + map(0xc000, 0xffff).rw(FUNC(bbcbp_state::mos_r), FUNC(bbcbp_state::mos_w)); // C000-FBFF OS ROM + map(0xfc00, 0xfcff).rw(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::fred_r), FUNC(bbc_1mhzbus_slot_device::fred_w)); // FC00-FCFF FRED Address Page + map(0xfd00, 0xfdff).rw(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::jim_r), FUNC(bbc_1mhzbus_slot_device::jim_w)); // FD00-FDFF JIM Address Page + map(0xfe00, 0xfeff).lr8(NAME([]() { return 0xfe; })).nopw(); // FE00-FEFF SHEILA Address Page + map(0xfe00, 0xfe00).mirror(0x06).rw(m_crtc, FUNC(hd6845s_device::status_r), FUNC(hd6845s_device::address_w)); // FE00-FE07 6845 CRTC Video controller + map(0xfe01, 0xfe01).mirror(0x06).rw(m_crtc, FUNC(hd6845s_device::register_r), FUNC(hd6845s_device::register_w)); + map(0xfe08, 0xfe09).mirror(0x06).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write)); // FE08-FE0F 6850 ACIA Serial controller + map(0xfe10, 0xfe17).rw("serproc", FUNC(acorn_serproc_device::read), FUNC(acorn_serproc_device::write)); // FE10-FE17 Serial ULA Serial system chip + map(0xfe18, 0xfe1f).lr8(NAME([this]() { econet_int_enable(0); return m_statid->read(); })); // R: FE18-FE1F INTOFF/STATID ECONET Interrupt Off / ID No. + map(0xfe18, 0xfe1f).lw8(NAME([this](uint8_t data) { econet_int_enable(0); })); // W: FE18-FE1F INTOFF ECONET Interrupt Off + map(0xfe20, 0xfe2f).lr8(NAME([this]() { econet_int_enable(1); return 0xfe; })); // R: FE20-FE2F INTON ECONET Interrupt On + map(0xfe20, 0xfe2f).w(FUNC(bbcbp_state::video_ula_w)); // W: FE20-FE2F Video ULA Video system chip + map(0xfe30, 0xfe3f).w(FUNC(bbcbp_state::romsel_w)); // W: FE30-FE3F 84LS161 Paged ROM selector + map(0xfe40, 0xfe4f).mirror(0x10).m(m_sysvia, FUNC(via6522_device::map)); // FE40-FE5F 6522 VIA SYSTEM VIA + map(0xfe60, 0xfe6f).mirror(0x10).m(m_uservia, FUNC(via6522_device::map)); // FE60-FE7F 6522 VIA USER VIA + map(0xfea0, 0xfea3).mirror(0x1c).rw(m_adlc, FUNC(mc6854_device::read), FUNC(mc6854_device::write)); // FEA0-FEBF 68B54 ADLC ECONET controller + map(0xfec0, 0xfec3).mirror(0x1c).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)); // FEC0-FEDF uPD7002 Analogue to digital converter + map(0xfee0, 0xfeff).rw(m_tube, FUNC(bbc_tube_slot_device::host_r), FUNC(bbc_tube_slot_device::host_w)); // FEE0-FEFF Tube ULA Tube system interface +} + + +uint8_t bbcbp_state::fetch_r(offs_t offset) +{ + switch (offset & 0xf000) + { + case 0xa000: + // Code executing from sideways RAM between 0xa000-0xafff will access the shadow RAM (if selected) + if (m_vdusel && m_paged_ram) + m_view_shadow.select(0); + else + m_view_shadow.disable(); + break; + + case 0xc000: + case 0xd000: + // Access shadow RAM if VDU drivers and shadow RAM selected + if (m_vdusel) + m_view_shadow.select(0); + else + m_view_shadow.disable(); + break; + + default: + m_view_shadow.disable(); + break; + } + return m_maincpu->space(AS_PROGRAM).read_byte(offset); +} + +void bbcbp_state::romsel_w(offs_t offset, uint8_t data) +{ + // the BBC Model B+ addresses all 16 ROM sockets and extra 12K of RAM at 0x8000 and 20K of shadow RAM at 0x3000 + switch (offset & 0x07) + { + case 0x00: + m_paged_ram = BIT(data, 7); + if (m_paged_ram) + m_view_paged.select(0); + else + m_view_paged.disable(); + + m_romsel = data & 0x0f; + break; + + case 0x04: + // the video display should now use this flag to display the shadow RAM memory + m_vdusel = BIT(data, 7); + setvideoshadow(m_vdusel); + break; + } + + // pass ROMSEL to internal expansion board + if (m_internal && m_internal->overrides_rom()) + m_internal->romsel_w(offset, data); +} + +uint8_t bbcbp_state::paged_r(offs_t offset) +{ + uint8_t data; + + if (m_internal && m_internal->overrides_rom()) + { + data = m_internal->paged_r(offset); + } + else + { + // 32K sockets + if (m_rom[m_romsel & 0x0e] && m_rom[m_romsel & 0x0e]->present()) + data = m_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14); + else + data = m_region_rom->base()[offset + (m_romsel << 14)]; + } + + return data; +} + +void bbcbp_state::paged_w(offs_t offset, uint8_t data) +{ + if (m_internal && m_internal->overrides_rom()) + { + m_internal->paged_w(offset, data); + } + else + { + // 32K sockets + if (m_rom[m_romsel & 0x0e]) + m_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data); + } +} + + +uint8_t bbcbp_state::sysvia_pa_r() +{ + update_sdb(); + + return m_sdb; +} + +void bbcbp_state::sysvia_pa_w(uint8_t data) +{ + m_sdb = data; + + update_sdb(); +} + + +void bbcbp_state::update_sdb() +{ + uint8_t const latch = m_latch->output_state(); + + // speech + if (m_vsp) + { + m_vsp->combined_rsq_wsq_w(bitswap<2>(latch, 1, 2)); + switch (bitswap<2>(~latch, 1, 2)) + { + case tms5200_device::RS: + m_sdb = m_vsp->status_r(); + break; + case tms5200_device::WS: + m_vsp->data_w(m_sdb); + break; + } + } + + // keyboard + m_sdb = m_kbd->read(m_sdb); +} + + +uint8_t bbcbp_state::sysvia_pb_r() +{ + uint8_t data = 0xff; + + if (m_analog) + { + data &= ~0x30; + data |= m_analog->pb_r(); + } + + if (m_vsp) + { + data &= ~0xc0; + data |= m_vsp->intq_r() << 6; + data |= m_vsp->readyq_r() << 7; + } + + return data; +} + +void bbcbp_state::sysvia_pb_w(uint8_t data) +{ + m_latch->write_nibble_d3(data); + + if (m_analog) + { + m_analog->pb_w(data & 0x30); + } + + update_sdb(); +} + + +void bbcbp_state::drive_control_w(uint8_t data) +{ + // Bit Meaning + // ----------------- + // 7,6 Not used + // 5 Reset drive controller chip. (0 = reset controller, 1 = no reset) + // 4 Interrupt Enable (0 = enable int, 1 = disable int) + // 3 Double density select (0 = double, 1 = single) + // 2 Side select (0 = side 0, 1 = side 1) + // 1 Drive select 1 + // 0 Drive select 0 + + floppy_image_device *floppy = nullptr; + + // bit 0, 1: drive select + if (BIT(data, 0)) floppy = m_wdfdc->subdevice<floppy_connector>("0")->get_device(); + if (BIT(data, 1)) floppy = m_wdfdc->subdevice<floppy_connector>("1")->get_device(); + m_wdfdc->set_floppy(floppy); + + // bit 2: side select + if (floppy) + floppy->ss_w(BIT(data, 2)); + + // bit 3: density + m_wdfdc->dden_w(BIT(data, 3)); + + // bit 4: disable NMI (S5 wire link not fitted) + + // bit 5: reset + m_wdfdc->mr_w(BIT(data, 5)); +} + + +void bbcbp_state::trigger_reset(int state) +{ + m_maincpu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE); + + if (!state) + { + if (m_uservia) m_uservia->reset(); + if (m_adlc) m_adlc->reset(); + if (m_wdfdc) m_wdfdc->reset(); + if (m_1mhzbus) m_1mhzbus->reset(); + if (m_tube) m_tube->reset(); + if (m_internal) m_internal->reset(); + } +} + + +static INPUT_PORTS_START(bbc_statid) + PORT_START("STATID") + PORT_DIPNAME(0xff, 0xfe, "Econet ID") PORT_DIPLOCATION("S23:1,2,3,4,5,6,7,8") + PORT_DIPSETTING( 0x00, "0" ) PORT_DIPSETTING( 0x01, "1" ) PORT_DIPSETTING( 0x02, "2" ) PORT_DIPSETTING( 0x03, "3" ) PORT_DIPSETTING( 0x04, "4" ) + PORT_DIPSETTING( 0x05, "5" ) PORT_DIPSETTING( 0x06, "6" ) PORT_DIPSETTING( 0x07, "7" ) PORT_DIPSETTING( 0x08, "8" ) PORT_DIPSETTING( 0x09, "9" ) + PORT_DIPSETTING( 0x0a, "10" ) PORT_DIPSETTING( 0x0b, "11" ) PORT_DIPSETTING( 0x0c, "12" ) PORT_DIPSETTING( 0x0d, "13" ) PORT_DIPSETTING( 0x0e, "14" ) + PORT_DIPSETTING( 0x0f, "15" ) PORT_DIPSETTING( 0x10, "16" ) PORT_DIPSETTING( 0x11, "17" ) PORT_DIPSETTING( 0x12, "18" ) PORT_DIPSETTING( 0x13, "19" ) + PORT_DIPSETTING( 0x14, "20" ) PORT_DIPSETTING( 0x15, "21" ) PORT_DIPSETTING( 0x16, "22" ) PORT_DIPSETTING( 0x17, "23" ) PORT_DIPSETTING( 0x18, "24" ) + PORT_DIPSETTING( 0x19, "25" ) PORT_DIPSETTING( 0x1a, "26" ) PORT_DIPSETTING( 0x1b, "27" ) PORT_DIPSETTING( 0x1c, "28" ) PORT_DIPSETTING( 0x1d, "29" ) + PORT_DIPSETTING( 0x1e, "30" ) PORT_DIPSETTING( 0x1f, "31" ) PORT_DIPSETTING( 0x20, "32" ) PORT_DIPSETTING( 0x21, "33" ) PORT_DIPSETTING( 0x22, "34" ) + PORT_DIPSETTING( 0x23, "35" ) PORT_DIPSETTING( 0x24, "36" ) PORT_DIPSETTING( 0x25, "37" ) PORT_DIPSETTING( 0x26, "38" ) PORT_DIPSETTING( 0x27, "39" ) + PORT_DIPSETTING( 0x28, "40" ) PORT_DIPSETTING( 0x29, "41" ) PORT_DIPSETTING( 0x2a, "42" ) PORT_DIPSETTING( 0x2b, "43" ) PORT_DIPSETTING( 0x2c, "44" ) + PORT_DIPSETTING( 0x2d, "45" ) PORT_DIPSETTING( 0x2e, "46" ) PORT_DIPSETTING( 0x2f, "47" ) PORT_DIPSETTING( 0x30, "48" ) PORT_DIPSETTING( 0x31, "49" ) + PORT_DIPSETTING( 0x32, "50" ) PORT_DIPSETTING( 0x33, "51" ) PORT_DIPSETTING( 0x34, "52" ) PORT_DIPSETTING( 0x35, "53" ) PORT_DIPSETTING( 0x36, "54" ) + PORT_DIPSETTING( 0x37, "55" ) PORT_DIPSETTING( 0x38, "56" ) PORT_DIPSETTING( 0x39, "57" ) PORT_DIPSETTING( 0x3a, "58" ) PORT_DIPSETTING( 0x3b, "59" ) + PORT_DIPSETTING( 0x3c, "60" ) PORT_DIPSETTING( 0x3d, "61" ) PORT_DIPSETTING( 0x3e, "62" ) PORT_DIPSETTING( 0x3f, "63" ) PORT_DIPSETTING( 0x40, "64" ) + PORT_DIPSETTING( 0x41, "65" ) PORT_DIPSETTING( 0x42, "66" ) PORT_DIPSETTING( 0x43, "67" ) PORT_DIPSETTING( 0x44, "68" ) PORT_DIPSETTING( 0x45, "69" ) + PORT_DIPSETTING( 0x46, "70" ) PORT_DIPSETTING( 0x47, "71" ) PORT_DIPSETTING( 0x48, "72" ) PORT_DIPSETTING( 0x49, "73" ) PORT_DIPSETTING( 0x4a, "74" ) + PORT_DIPSETTING( 0x4b, "75" ) PORT_DIPSETTING( 0x4c, "76" ) PORT_DIPSETTING( 0x4d, "77" ) PORT_DIPSETTING( 0x4e, "78" ) PORT_DIPSETTING( 0x4f, "79" ) + PORT_DIPSETTING( 0x50, "80" ) PORT_DIPSETTING( 0x51, "81" ) PORT_DIPSETTING( 0x52, "82" ) PORT_DIPSETTING( 0x53, "83" ) PORT_DIPSETTING( 0x54, "84" ) + PORT_DIPSETTING( 0x55, "85" ) PORT_DIPSETTING( 0x56, "86" ) PORT_DIPSETTING( 0x57, "87" ) PORT_DIPSETTING( 0x58, "88" ) PORT_DIPSETTING( 0x59, "89" ) + PORT_DIPSETTING( 0x5a, "90" ) PORT_DIPSETTING( 0x5b, "91" ) PORT_DIPSETTING( 0x5c, "92" ) PORT_DIPSETTING( 0x5d, "93" ) PORT_DIPSETTING( 0x5e, "94" ) + PORT_DIPSETTING( 0x5f, "95" ) PORT_DIPSETTING( 0x60, "96" ) PORT_DIPSETTING( 0x61, "97" ) PORT_DIPSETTING( 0x62, "98" ) PORT_DIPSETTING( 0x63, "99" ) + PORT_DIPSETTING( 0x64, "100" ) PORT_DIPSETTING( 0x65, "101" ) PORT_DIPSETTING( 0x66, "102" ) PORT_DIPSETTING( 0x67, "103" ) PORT_DIPSETTING( 0x68, "104" ) + PORT_DIPSETTING( 0x69, "105" ) PORT_DIPSETTING( 0x6a, "106" ) PORT_DIPSETTING( 0x6b, "107" ) PORT_DIPSETTING( 0x6c, "108" ) PORT_DIPSETTING( 0x6d, "109" ) + PORT_DIPSETTING( 0x6e, "110" ) PORT_DIPSETTING( 0x6f, "111" ) PORT_DIPSETTING( 0x70, "112" ) PORT_DIPSETTING( 0x71, "113" ) PORT_DIPSETTING( 0x72, "114" ) + PORT_DIPSETTING( 0x73, "115" ) PORT_DIPSETTING( 0x74, "116" ) PORT_DIPSETTING( 0x75, "117" ) PORT_DIPSETTING( 0x76, "118" ) PORT_DIPSETTING( 0x77, "119" ) + PORT_DIPSETTING( 0x78, "120" ) PORT_DIPSETTING( 0x79, "121" ) PORT_DIPSETTING( 0x7a, "122" ) PORT_DIPSETTING( 0x7b, "123" ) PORT_DIPSETTING( 0x7c, "124" ) + PORT_DIPSETTING( 0x7d, "125" ) PORT_DIPSETTING( 0x7e, "126" ) PORT_DIPSETTING( 0x7f, "127" ) PORT_DIPSETTING( 0x80, "128" ) PORT_DIPSETTING( 0x81, "129" ) + PORT_DIPSETTING( 0x82, "130" ) PORT_DIPSETTING( 0x83, "131" ) PORT_DIPSETTING( 0x84, "132" ) PORT_DIPSETTING( 0x85, "133" ) PORT_DIPSETTING( 0x86, "134" ) + PORT_DIPSETTING( 0x87, "135" ) PORT_DIPSETTING( 0x88, "136" ) PORT_DIPSETTING( 0x89, "137" ) PORT_DIPSETTING( 0x8a, "138" ) PORT_DIPSETTING( 0x8b, "139" ) + PORT_DIPSETTING( 0x8c, "140" ) PORT_DIPSETTING( 0x8d, "141" ) PORT_DIPSETTING( 0x8e, "142" ) PORT_DIPSETTING( 0x8f, "143" ) PORT_DIPSETTING( 0x90, "144" ) + PORT_DIPSETTING( 0x91, "145" ) PORT_DIPSETTING( 0x92, "146" ) PORT_DIPSETTING( 0x93, "147" ) PORT_DIPSETTING( 0x94, "148" ) PORT_DIPSETTING( 0x95, "149" ) + PORT_DIPSETTING( 0x96, "150" ) PORT_DIPSETTING( 0x97, "151" ) PORT_DIPSETTING( 0x98, "152" ) PORT_DIPSETTING( 0x99, "153" ) PORT_DIPSETTING( 0x9a, "154" ) + PORT_DIPSETTING( 0x9b, "155" ) PORT_DIPSETTING( 0x9c, "156" ) PORT_DIPSETTING( 0x9d, "157" ) PORT_DIPSETTING( 0x9e, "158" ) PORT_DIPSETTING( 0x9f, "159" ) + PORT_DIPSETTING( 0xa0, "160" ) PORT_DIPSETTING( 0xa1, "161" ) PORT_DIPSETTING( 0xa2, "162" ) PORT_DIPSETTING( 0xa3, "163" ) PORT_DIPSETTING( 0xa4, "164" ) + PORT_DIPSETTING( 0xa5, "165" ) PORT_DIPSETTING( 0xa6, "166" ) PORT_DIPSETTING( 0xa7, "167" ) PORT_DIPSETTING( 0xa8, "168" ) PORT_DIPSETTING( 0xa9, "169" ) + PORT_DIPSETTING( 0xaa, "170" ) PORT_DIPSETTING( 0xab, "171" ) PORT_DIPSETTING( 0xac, "172" ) PORT_DIPSETTING( 0xad, "173" ) PORT_DIPSETTING( 0xae, "174" ) + PORT_DIPSETTING( 0xaf, "175" ) PORT_DIPSETTING( 0xb0, "176" ) PORT_DIPSETTING( 0xb1, "177" ) PORT_DIPSETTING( 0xb2, "178" ) PORT_DIPSETTING( 0xb3, "179" ) + PORT_DIPSETTING( 0xb4, "180" ) PORT_DIPSETTING( 0xb5, "181" ) PORT_DIPSETTING( 0xb6, "182" ) PORT_DIPSETTING( 0xb7, "183" ) PORT_DIPSETTING( 0xb8, "184" ) + PORT_DIPSETTING( 0xb9, "185" ) PORT_DIPSETTING( 0xba, "186" ) PORT_DIPSETTING( 0xbb, "187" ) PORT_DIPSETTING( 0xbc, "188" ) PORT_DIPSETTING( 0xbd, "189" ) + PORT_DIPSETTING( 0xbe, "190" ) PORT_DIPSETTING( 0xbf, "191" ) PORT_DIPSETTING( 0xc0, "192" ) PORT_DIPSETTING( 0xc1, "193" ) PORT_DIPSETTING( 0xc2, "194" ) + PORT_DIPSETTING( 0xc3, "195" ) PORT_DIPSETTING( 0xc4, "196" ) PORT_DIPSETTING( 0xc5, "197" ) PORT_DIPSETTING( 0xc6, "198" ) PORT_DIPSETTING( 0xc7, "199" ) + PORT_DIPSETTING( 0xc8, "200" ) PORT_DIPSETTING( 0xc9, "201" ) PORT_DIPSETTING( 0xca, "202" ) PORT_DIPSETTING( 0xcb, "203" ) PORT_DIPSETTING( 0xcc, "204" ) + PORT_DIPSETTING( 0xcd, "205" ) PORT_DIPSETTING( 0xce, "206" ) PORT_DIPSETTING( 0xcf, "207" ) PORT_DIPSETTING( 0xd0, "208" ) PORT_DIPSETTING( 0xd1, "209" ) + PORT_DIPSETTING( 0xd2, "210" ) PORT_DIPSETTING( 0xd3, "211" ) PORT_DIPSETTING( 0xd4, "212" ) PORT_DIPSETTING( 0xd5, "213" ) PORT_DIPSETTING( 0xd6, "214" ) + PORT_DIPSETTING( 0xd7, "215" ) PORT_DIPSETTING( 0xd8, "216" ) PORT_DIPSETTING( 0xd9, "217" ) PORT_DIPSETTING( 0xda, "218" ) PORT_DIPSETTING( 0xdb, "219" ) + PORT_DIPSETTING( 0xdc, "220" ) PORT_DIPSETTING( 0xdd, "221" ) PORT_DIPSETTING( 0xde, "222" ) PORT_DIPSETTING( 0xdf, "223" ) PORT_DIPSETTING( 0xe0, "224" ) + PORT_DIPSETTING( 0xe1, "225" ) PORT_DIPSETTING( 0xe2, "226" ) PORT_DIPSETTING( 0xe3, "227" ) PORT_DIPSETTING( 0xe4, "228" ) PORT_DIPSETTING( 0xe5, "229" ) + PORT_DIPSETTING( 0xe6, "230" ) PORT_DIPSETTING( 0xe7, "231" ) PORT_DIPSETTING( 0xe8, "232" ) PORT_DIPSETTING( 0xe9, "233" ) PORT_DIPSETTING( 0xea, "234" ) + PORT_DIPSETTING( 0xeb, "235" ) PORT_DIPSETTING( 0xec, "236" ) PORT_DIPSETTING( 0xed, "237" ) PORT_DIPSETTING( 0xee, "238" ) PORT_DIPSETTING( 0xef, "239" ) + PORT_DIPSETTING( 0xf0, "240" ) PORT_DIPSETTING( 0xf1, "241" ) PORT_DIPSETTING( 0xf2, "242" ) PORT_DIPSETTING( 0xf3, "243" ) PORT_DIPSETTING( 0xf4, "244" ) + PORT_DIPSETTING( 0xf5, "245" ) PORT_DIPSETTING( 0xf6, "246" ) PORT_DIPSETTING( 0xf7, "247" ) PORT_DIPSETTING( 0xf8, "248" ) PORT_DIPSETTING( 0xf9, "249" ) + PORT_DIPSETTING( 0xfa, "250" ) PORT_DIPSETTING( 0xfb, "251" ) PORT_DIPSETTING( 0xfc, "252" ) PORT_DIPSETTING( 0xfd, "253" ) PORT_DIPSETTING( 0xfe, "254" ) + PORT_DIPSETTING( 0xff, "255" ) +INPUT_PORTS_END + + +static INPUT_PORTS_START(bbcbp) + PORT_INCLUDE(bbc_config) + PORT_INCLUDE(bbc_statid) +INPUT_PORTS_END + +static INPUT_PORTS_START(abc) + PORT_INCLUDE(bbc_statid) +INPUT_PORTS_END + + +static void bbc_floppies(device_slot_interface &device) +{ + device.option_add("525sssd", FLOPPY_525_SSSD); + device.option_add("525sd", FLOPPY_525_SD); + device.option_add("525qd", FLOPPY_525_QD); + device.option_add("35dd", FLOPPY_35_DD); +} + + +static const char *const bbc_sample_names[] = +{ + "*bbc", + "motoroff", + "motoron", + nullptr +}; + + +/*************************************************************************** + + BBC Model B+ + +****************************************************************************/ + +void bbcbp_state::bbcbp(machine_config &config) +{ + M6512(config, m_maincpu, 16_MHz_XTAL / 8); + m_maincpu->set_addrmap(AS_PROGRAM, &bbcbp_state::bbcbp_mem); + m_maincpu->set_addrmap(AS_OPCODES, &bbcbp_state::bbcbp_fetch); + config.set_perfect_quantum(m_maincpu); + + INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set_inputline(m_maincpu, M6502_IRQ_LINE); + m_irqs->output_handler().append(m_internal, FUNC(bbc_internal_slot_device::irq6502_w)); + + RAM(config, m_ram).set_default_size("64K"); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(16_MHz_XTAL, 1024, 0, 640, 312, 0, 256); + m_screen->set_screen_update("crtc", FUNC(hd6845s_device::screen_update)); + + PALETTE(config, m_palette).set_entries(16); + + SAA5050(config, m_trom, 12_MHz_XTAL / 2); + + HD6845S(config, m_crtc, 16_MHz_XTAL / 8); + m_crtc->set_screen("screen"); + m_crtc->set_show_border_area(false); + m_crtc->set_char_width(8); + m_crtc->set_reconfigure_callback(FUNC(bbcbp_state::crtc_reconfigure)); + m_crtc->set_update_row_callback(FUNC(bbcbp_state::crtc_update_row)); + m_crtc->out_de_callback().set(FUNC(bbcbp_state::de_changed)); + m_crtc->out_hsync_callback().set(FUNC(bbcbp_state::hsync_changed)); + m_crtc->out_vsync_callback().set(FUNC(bbcbp_state::vsync_changed)); + + config.set_default_layout(layout_bbc); + + LS259(config, m_latch); + m_latch->q_out_cb<0>().set([this](int state) { if (!state) m_sn->write(m_sdb); }); + m_latch->q_out_cb<3>().set(m_kbd, FUNC(bbc_kbd_device::write_kb_en)); + m_latch->q_out_cb<6>().set_output("capslock_led"); + m_latch->q_out_cb<7>().set_output("shiftlock_led"); + + MOS6522(config, m_sysvia, 16_MHz_XTAL / 16); + m_sysvia->readpa_handler().set(FUNC(bbcbp_state::sysvia_pa_r)); + m_sysvia->writepa_handler().set(FUNC(bbcbp_state::sysvia_pa_w)); + m_sysvia->readpb_handler().set(FUNC(bbcbp_state::sysvia_pb_r)); + m_sysvia->writepb_handler().set(FUNC(bbcbp_state::sysvia_pb_w)); + m_sysvia->cb2_handler().set([this](int state) { if (state) m_crtc->assert_light_pen_input(); }); + m_sysvia->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>)); + + BBC_KBD(config, m_kbd, 16_MHz_XTAL / 16); + m_kbd->ca2_handler().set(m_sysvia, FUNC(via6522_device::write_ca2)); + m_kbd->rst_handler().set(FUNC(bbcbp_state::trigger_reset)); + + SPEAKER(config, "mono").front_center(); + + SN76489A(config, m_sn, 16_MHz_XTAL / 4); + m_sn->add_route(ALL_OUTPUTS, "mono", 1.0); + + TMS5220(config, m_vsp, 640000); + m_vsp->add_route(ALL_OUTPUTS, "mono", 0.5); + + TMS6100(config, "vsm", 0); + m_vsp->m0_cb().set("vsm", FUNC(tms6100_device::m0_w)); + m_vsp->m1_cb().set("vsm", FUNC(tms6100_device::m1_w)); + m_vsp->addr_cb().set("vsm", FUNC(tms6100_device::add_w)); + m_vsp->data_cb().set("vsm", FUNC(tms6100_device::data_line_r)); + m_vsp->romclk_cb().set("vsm", FUNC(tms6100_device::clk_w)); + + SAMPLES(config, m_samples); + m_samples->set_channels(1); + m_samples->set_samples_names(bbc_sample_names); + m_samples->add_route(ALL_OUTPUTS, "mono", 1.0); + + CASSETTE(config, m_cassette); + m_cassette->set_formats(bbc_cassette_formats); + m_cassette->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED); + m_cassette->set_interface("bbc_cass"); + + acia6850_device &acia(ACIA6850(config, "acia")); + acia.txd_handler().set("serproc", FUNC(acorn_serproc_device::write_txd)); + acia.rts_handler().set("serproc", FUNC(acorn_serproc_device::write_rtsi)); + acia.irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>)); + + acorn_serproc_device &serproc(ACORN_SERPROC(config, "serproc", 16_MHz_XTAL / 13)); + serproc.rxc_handler().set("acia", FUNC(acia6850_device::write_rxc)); + serproc.txc_handler().set("acia", FUNC(acia6850_device::write_txc)); + serproc.rxd_handler().set("acia", FUNC(acia6850_device::write_rxd)); + serproc.dcd_handler().set("acia", FUNC(acia6850_device::write_dcd)); + serproc.ctso_handler().set("acia", FUNC(acia6850_device::write_cts)); + serproc.dout_handler().set("rs423", FUNC(rs232_port_device::write_txd)); + serproc.rtso_handler().set("rs423", FUNC(rs232_port_device::write_rts)); + serproc.casmo_handler().set(FUNC(bbcbp_state::cassette_motor)); + serproc.casin_handler("cassette", FUNC(cassette_image_device::input)); + serproc.casout_handler("cassette", FUNC(cassette_image_device::output)); + + rs232_port_device &rs423(RS232_PORT(config, "rs423", default_rs232_devices, nullptr)); + rs423.rxd_handler().set("serproc", FUNC(acorn_serproc_device::write_din)); + rs423.cts_handler().set("serproc", FUNC(acorn_serproc_device::write_ctsi)); + + MOS6522(config, m_uservia, 16_MHz_XTAL / 16); + m_uservia->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write)); + m_uservia->readpb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_r)); + m_uservia->writepb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_w)); + m_uservia->writepb_handler().append(m_internal, FUNC(bbc_internal_slot_device::latch_fe60_w)); + m_uservia->ca2_handler().set("printer", FUNC(centronics_device::write_strobe)); + m_uservia->cb1_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb1)); + m_uservia->cb2_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb2)); + m_uservia->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>)); + + centronics_device ¢ronics(CENTRONICS(config, "printer", centronics_devices, "printer")); + centronics.ack_handler().set(m_uservia, FUNC(via6522_device::write_ca1)); + output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out")); + centronics.set_output_latch(latch); + + upd7002_device &upd7002(UPD7002(config, "upd7002", 16_MHz_XTAL / 16)); + upd7002.set_get_analogue_callback(FUNC(bbcbp_state::get_analogue_input)); + upd7002.set_eoc_callback(m_sysvia, FUNC(via6522_device::write_cb1)); + + BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr); + m_analog->lpstb_handler().set(m_sysvia, FUNC(via6522_device::write_cb2)); + m_analog->lpstb_handler().append([this](int state) { if (state) m_crtc->assert_light_pen_input(); }); + + WD1770(config, m_wdfdc, 16_MHz_XTAL / 2); + m_wdfdc->intrq_wr_callback().set(FUNC(bbcbp_state::fdc_intrq_w)); + m_wdfdc->drq_wr_callback().set(FUNC(bbcbp_state::fdc_drq_w)); + + FLOPPY_CONNECTOR(config, "wdfdc:0", bbc_floppies, "525qd", bbc_state::floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "wdfdc:1", bbc_floppies, "525qd", bbc_state::floppy_formats).enable_sound(true); + + MC6854(config, m_adlc); + m_adlc->out_txd_cb().set("network", FUNC(econet_device::host_data_w)); + m_adlc->out_irq_cb().set(FUNC(bbcbp_state::adlc_irq_w)); + //m_adlc->out_rts_cb(). + + econet_device &econet(ECONET(config, "network", 0)); + econet.clk_wr_callback().set(m_adlc, FUNC(mc6854_device::txc_w)); + econet.clk_wr_callback().append(m_adlc, FUNC(mc6854_device::rxc_w)); + econet.data_wr_callback().set(m_adlc, FUNC(mc6854_device::set_rx)); + ECONET_SLOT(config, "econet", "network", econet_devices); + + BBC_1MHZBUS_SLOT(config, m_1mhzbus, 16_MHz_XTAL / 16, bbc_1mhzbus_devices, nullptr); + m_1mhzbus->add_route(ALL_OUTPUTS, "mono", 1.0); + m_1mhzbus->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>)); + m_1mhzbus->nmi_handler().set(FUNC(bbcbp_state::bus_nmi_w)); + + BBC_TUBE_SLOT(config, m_tube, bbc_tube_devices, nullptr); + m_tube->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<4>)); + + BBC_USERPORT_SLOT(config, m_userport, bbc_userport_devices, nullptr); + m_userport->cb1_handler().set(m_uservia, FUNC(via6522_device::write_cb1)); + m_userport->cb2_handler().set(m_uservia, FUNC(via6522_device::write_cb2)); + + BBC_ROMSLOT32(config, m_rom[0x02], bbc_rom_devices, nullptr); // IC35 32K socket + BBC_ROMSLOT32(config, m_rom[0x04], bbc_rom_devices, nullptr); // IC44 32K socket + BBC_ROMSLOT32(config, m_rom[0x06], bbc_rom_devices, nullptr); // IC57 32K socket + BBC_ROMSLOT32(config, m_rom[0x08], bbc_rom_devices, nullptr); // IC62 32K socket + BBC_ROMSLOT32(config, m_rom[0x0a], bbc_rom_devices, nullptr); // IC68 32K socket + + BBC_INTERNAL_SLOT(config, m_internal, 16_MHz_XTAL, bbcbp_internal_devices, nullptr); + m_internal->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<5>)); + m_internal->nmi_handler().set(FUNC(bbcbp_state::bus_nmi_w)); + + SOFTWARE_LIST(config, "cass_ls").set_original("bbc_cass").set_filter("A,B"); + SOFTWARE_LIST(config, "rom_ls").set_original("bbc_rom").set_filter("B+"); + SOFTWARE_LIST(config, "flop_ls_b").set_original("bbcb_flop"); + SOFTWARE_LIST(config, "flop_ls_b_orig").set_original("bbcb_flop_orig"); + SOFTWARE_LIST(config, "hdd_ls").set_original("bbc_hdd").set_filter("B"); +} + + +void bbcbp_state::bbcbp128(machine_config &config) +{ + bbcbp(config); + + m_ram->set_default_size("128K"); + + BBC_ROMSLOT32(config, m_rom[0x00], bbc_rom_devices, "ram").set_fixed_ram(true); + BBC_ROMSLOT32(config, m_rom[0x0c], bbc_rom_devices, "ram").set_fixed_ram(true); +} + + +void bbcbp_state::cfa3000bp(machine_config &config) +{ + bbcbp(config); + + // no floppy drives + m_wdfdc->subdevice<floppy_connector>("0")->set_default_option(nullptr); + m_wdfdc->subdevice<floppy_connector>("1")->set_default_option(nullptr); + + // keyboard + m_userport->set_default_option("cfa3000kbd").set_fixed(true); + + // option board + m_1mhzbus->set_default_option("cfa3000opt").set_fixed(true); + + // analogue dials/sensors + m_analog->set_default_option("cfa3000a").set_fixed(true); + + config.device_remove("cass_ls"); + config.device_remove("flop_ls_b"); + config.device_remove("flop_ls_b_orig"); +} + + +/*************************************************************************** + + Acorn Business Computers + +****************************************************************************/ + +void bbcbp_state::abc110(machine_config &config) +{ + bbcbp(config); + + ABC_KBD(config.replace(), m_kbd, 16_MHz_XTAL / 16); + m_kbd->ca2_handler().set(m_sysvia, FUNC(via6522_device::write_ca2)); + m_kbd->rst_handler().set(FUNC(bbcbp_state::trigger_reset)); + + // single floppy drive + m_wdfdc->subdevice<floppy_connector>("1")->set_default_option(nullptr); + + // Acorn Z80 co-processor + m_tube->set_default_option("z80w").set_fixed(true); + + // Acorn Winchester Disc 10MB + m_1mhzbus->set_default_option("awhd").set_fixed(true); +} + + +void bbcbp_state::acw443(machine_config &config) +{ + abc110(config); + + // 32016 co-processor + m_tube->set_default_option("32016l").set_fixed(true); + + // Acorn Winchester Disc 20MB + m_1mhzbus->set_default_option("awhd").set_fixed(true); + + SOFTWARE_LIST(config, "flop_ls_32016").set_original("bbc_flop_32016"); +} + + +void bbcbp_state::abc310(machine_config &config) +{ + abc110(config); + + // Acorn 80286 co-processor + m_tube->set_default_option("80286").set_fixed(true); + + // Acorn Winchester Disc 10MB + m_1mhzbus->set_default_option("awhd").set_fixed(true); + + // Acorn Mouse + m_userport->set_default_option("m512mouse"); +} + + +/*************************************************************************** + + Econet X25 Gateway + +****************************************************************************/ + +void bbcbp_state::econx25(machine_config &config) +{ + bbcbp(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &bbcbp_state::econx25_mem); + + // Econet X25 Gateway co-processor + m_tube->set_default_option("x25").set_fixed(true); + + // fdc and speech not fitted + config.device_remove("wdfdc"); + config.device_remove("vsm"); + config.device_remove("vsp"); + + subdevice<centronics_device>("printer")->set_default_option(nullptr); + + config.device_remove("cass_ls"); + config.device_remove("flop_ls_b"); + config.device_remove("flop_ls_b_orig"); +} + + +ROM_START(bbcbp) + // page 0 00000 SWRAM (B+ 128K only) // page 8 20000 IC62 32K IN PAGE 9 + // page 1 04000 SWRAM (B+ 128K only) // page 9 24000 IC62 + // page 2 08000 IC35 32K IN PAGE 3 // page 10 28000 IC68 32K IN PAGE 11 + // page 3 0c000 IC35 // page 11 2c000 IC68 + // page 4 10000 IC44 32K IN PAGE 5 // page 12 30000 SWRAM (B+ 128K only) + // page 5 14000 IC44 ADFS // page 13 34000 SWRAM (B+ 128K only) + // page 6 18000 IC57 32K IN PAGE 7 // page 14 38000 IC71 32K IN PAGE 15 + // page 7 1c000 IC57 DDFS // page 15 3C000 IC71 BASIC + ROM_REGION(0x44000, "rom", ROMREGION_ERASEFF) + ROM_LOAD("bpos2.ic71", 0x3c000, 0x8000, CRC(9f356396) SHA1(ea7d3a7e3ee1ecfaa1483af994048057362b01f2)) + //ROM_LOAD("adfs130.rom", 0x14000, 0x4000, CRC(d3855588) SHA1(301fd05c475a629c4bec70510d4507256a5b00d8)) // not fitted as standard + ROM_LOAD("ddfs223.rom", 0x1c000, 0x4000, CRC(7891f9b7) SHA1(0d7ed0b0b3852cb61970ada1993244f2896896aa)) + + ROM_REGION(0x4000, "mos", 0) + ROM_COPY("rom", 0x40000, 0, 0x4000) + + ROM_REGION(0x40000, "vsm", ROMREGION_ERASE00) + ROM_LOAD("cm62024.bin", 0x3c000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6)) +ROM_END + + +#define rom_bbcbp128 rom_bbcbp + + +ROM_START(abc110) + // page 0 00000 // page 8 20000 IC62 32K IN PAGE 9 + // page 1 04000 IC71 selectable with link S13 // page 9 24000 IC62 + // page 2 08000 IC35 32K IN PAGE 3 // page 10 28000 IC68 32K IN PAGE 11 + // page 3 0c000 IC35 // page 11 2c000 IC68 + // page 4 10000 IC44 32K IN PAGE 5 // page 12 30000 + // page 5 14000 IC44 DDFS // page 13 34000 + // page 6 18000 IC57 32K IN PAGE 7 // page 14 38000 + // page 7 1c000 IC57 ADFS // page 15 3C000 IC71 BASIC + ROM_REGION(0x44000, "rom", ROMREGION_ERASEFF) + ROM_SYSTEM_BIOS(0, "200", "MOS2.00") + ROMX_LOAD("mos200.rom", 0x40000, 0x4000, CRC(5e88f994) SHA1(76235ff15d736f5def338f73ac7497c41b916505), ROM_BIOS(0)) + ROMX_LOAD("basic200.rom", 0x3c000, 0x4000, CRC(79434781) SHA1(4a7393f3a45ea309f744441c16723e2ef447a281), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "123stor", "MOS1.23 + ViewStore") + ROMX_LOAD("mos123stor.rom", 0x3c000, 0x8000, CRC(4e84f452) SHA1(145ee54f04b3eb4d0e5afaabe21915be48db3c54), ROM_BIOS(1)) // rom 15 3C000 ViewStore + ROM_SYSTEM_BIOS(2, "123", "MOS1.23") + ROMX_LOAD("mos123.rom", 0x40000, 0x4000, CRC(90d31d08) SHA1(42a01892cf8bd2ada4db1c8b36aff80c85eb5dcb), ROM_BIOS(2)) + ROMX_LOAD("basic200.rom", 0x3c000, 0x4000, CRC(79434781) SHA1(4a7393f3a45ea309f744441c16723e2ef447a281), ROM_BIOS(2)) + + ROM_SYSTEM_BIOS(3, "120", "MOS1.20") + ROMX_LOAD("mos120.rom", 0x40000, 0x4000, CRC(0a1e83a0) SHA1(21dc3a94eef7c003b194686730fb461779f44925), ROM_BIOS(3)) + ROMX_LOAD("basic200.rom", 0x3c000, 0x4000, CRC(79434781) SHA1(4a7393f3a45ea309f744441c16723e2ef447a281), ROM_BIOS(3)) + + //ROM_LOAD("ddfs223.rom", 0x14000, 0x4000, CRC(7891f9b7) SHA1(0d7ed0b0b3852cb61970ada1993244f2896896aa)) + ROM_LOAD("acwddfs225.rom", 0x14000, 0x4000, CRC(7d0f9016) SHA1(bdfe44c79e18142d747436627e71a362a04cf746)) + ROM_LOAD("adfs130.rom", 0x1c000, 0x4000, CRC(d3855588) SHA1(301fd05c475a629c4bec70510d4507256a5b00d8)) + + ROM_REGION(0x4000, "mos", 0) + ROM_COPY("rom", 0x40000, 0, 0x4000) + + ROM_REGION(0x40000, "vsm", ROMREGION_ERASE00) + ROM_LOAD("cm62024.bin", 0x3c000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6)) +ROM_END + + +#define rom_abc310 rom_abc110 + + +ROM_START(acw443) + // page 0 00000 // page 8 20000 IC62 32K IN PAGE 9 + // page 1 04000 IC71 selectable with link S13 // page 9 24000 IC62 ADFS + // page 2 08000 IC35 32K IN PAGE 3 // page 10 28000 IC68 BASIC + // page 3 0c000 IC35 DNFS // page 11 2c000 IC68 unused OS? + // page 4 10000 IC44 32K IN PAGE 5 // page 12 30000 + // page 5 14000 IC44 ACW DFS // page 13 34000 + // page 6 18000 IC57 32K IN PAGE 7 // page 14 38000 + // page 7 1c000 IC57 TERMINAL // page 15 3C000 IC71 selectable with link S13 + ROM_REGION(0x44000, "rom", ROMREGION_ERASEFF) + ROM_SYSTEM_BIOS(0, "210", "MOS2.10") + ROMX_LOAD("acwmos210.rom", 0x40000, 0x4000, CRC(168d6753) SHA1(dcd01d8f5f6e0cd92ae626ca52a3db71abf5d282), ROM_BIOS(0)) + + ROM_SYSTEM_BIOS(1, "200", "MOS2.00") + ROMX_LOAD("mos200.rom", 0x40000, 0x4000, CRC(5e88f994) SHA1(76235ff15d736f5def338f73ac7497c41b916505), ROM_BIOS(1)) + + ROM_LOAD("dnfs120-201666.rom", 0x0c000, 0x4000, CRC(8ccd2157) SHA1(7e3c536baeae84d6498a14e8405319e01ee78232)) + ROM_LOAD("acwddfs225.rom", 0x14000, 0x4000, CRC(7d0f9016) SHA1(bdfe44c79e18142d747436627e71a362a04cf746)) + ROM_LOAD("acwterminal.rom", 0x1c000, 0x4000, CRC(81afaeb9) SHA1(6618ed9158776b4b8aa030957bd19ba77e4a993c)) + ROM_LOAD("adfs130.rom", 0x24000, 0x4000, CRC(d3855588) SHA1(301fd05c475a629c4bec70510d4507256a5b00d8)) + ROM_LOAD("basic200.rom", 0x28000, 0x4000, CRC(79434781) SHA1(4a7393f3a45ea309f744441c16723e2ef447a281)) + + ROM_REGION(0x4000, "mos", 0) + ROM_COPY("rom", 0x40000, 0, 0x4000) + + ROM_REGION(0x40000, "vsm", ROMREGION_ERASE00) + ROM_LOAD("cm62024.bin", 0x3c000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6)) + + DISK_REGION("1mhzbus:awhd:scsi:0:acb4000a:image") + DISK_IMAGE("acw_panos14", 0, BAD_DUMP SHA1(9b9bad7197c9b1193342d9d60fe3f7a465afd99a)) // NEC D5126 with clean Panos 1.4 installation +ROM_END + + +ROM_START(econx25) + // page 0 00000 // page 8 20000 IC62 BASIC + // page 1 04000 IC71 selectable with link S13 // page 9 24000 IC62 unused OS + // page 2 08000 IC35 32K IN PAGE 3 // page 10 28000 IC68 32K IN PAGE 11 + // page 3 0c000 IC35 // page 11 2c000 IC68 + // page 4 10000 IC44 32K IN PAGE 5 // page 12 30000 + // page 5 14000 IC44 // page 13 34000 + // page 6 18000 IC57 32K IN PAGE 7 // page 14 38000 + // page 7 1c000 IC57 ANFS // page 15 3C000 IC71 selectable with link S13 + ROM_REGION(0x44000, "rom", ROMREGION_ERASEFF) + ROM_LOAD("0246,201_01_x25os.rom", 0x40000, 0x4000, CRC(8b652337) SHA1(6a5c7ace255c8ac96c983d5ba67084fbd71ff61e)) + ROM_LOAD("2201,248_03_anfs.rom", 0x1c000, 0x4000, CRC(744a60a7) SHA1(c733b108d74cf3b1c5de395335236800a7c9c0d8)) + ROM_LOAD("0201,241_01_bpos2.rom", 0x20000, 0x8000, CRC(9f356396) SHA1(ea7d3a7e3ee1ecfaa1483af994048057362b01f2)) + // X25 TSI is in IC37 which is supposed to take a speech PHROM, so not sure where this is mapped + ROM_LOAD("0246,215_02_x25tsi_v0.51.rom", 0x0c000, 0x4000, CRC(71dd84e4) SHA1(bbfa892fdcc6f753dda5134ecb97cc7c42b959c2)) + + ROM_REGION(0x4000, "mos", 0) + ROM_COPY("rom", 0x40000, 0, 0x4000) +ROM_END + + +ROM_START(cfa3000bp) + // page 0 00000 SWRAM (B+ 128K only) // page 8 20000 IC62 32K IN PAGE 9 + // page 1 04000 SWRAM (B+ 128K only) // page 9 24000 IC62 + // page 2 08000 IC35 32K IN PAGE 3 // page 10 28000 IC68 32K IN PAGE 11 + // page 3 0c000 IC35 // page 11 2c000 IC68 + // page 4 10000 IC44 32K IN PAGE 5 // page 12 30000 SWRAM (B+ 128K only) + // page 5 14000 IC44 // page 13 34000 SWRAM (B+ 128K only) + // page 6 18000 IC57 32K IN PAGE 7 // page 14 38000 IC71 32K IN PAGE 15 + // page 7 1c000 IC57 // page 15 3C000 IC71 BASIC + ROM_REGION(0x44000, "rom", ROMREGION_ERASEFF) + ROM_LOAD("bpos2.ic71", 0x3c000, 0x8000, CRC(9f356396) SHA1(ea7d3a7e3ee1ecfaa1483af994048057362b01f2)) + ROM_SYSTEM_BIOS(0, "40", "Issue 4") + ROMX_LOAD("cfa3000_3.rom", 0x14000, 0x4000, CRC(4f246cd5) SHA1(6ba9625248c585deed5c651a889eecc86384a60d), ROM_BIOS(0)) + ROMX_LOAD("cfa3000_4.rom", 0x1c000, 0x4000, CRC(ca0e30fd) SHA1(abddc7ba6d16855ebda2ef55fe8662bc545ae755), ROM_BIOS(0)) + ROMX_LOAD("cfa3000_s.rom", 0x24000, 0x4000, CRC(71fd4c8a) SHA1(5bad70ee55403bc0191f6b189c9b6e5effdbca4c), ROM_BIOS(0)) + + // link S13 set for BASIC to take low priority ROM numbers 0/1 + ROM_COPY("rom", 0x3c000, 0x4000, 0x4000) + ROM_FILL(0x3c000, 0x4000, 0xff) + + ROM_REGION(0x4000, "mos", 0) + ROM_COPY("rom", 0x40000, 0, 0x4000) + + ROM_REGION(0x40000, "vsm", ROMREGION_ERASE00) + ROM_LOAD("cm62024.bin", 0x3c000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6)) +ROM_END + + +#define rom_ltmpbp rom_bbcbp + +} // anonymous namespace + + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1985, bbcbp, 0, bbcb, bbcbp, bbcbp, bbcbp_state, init_bbc, "Acorn Computers", "BBC Micro Model B+ 64K", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1985, bbcbp128, bbcbp, 0, bbcbp128, bbcbp, bbcbp_state, init_bbc, "Acorn Computers", "BBC Micro Model B+ 128K", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1985, abc110, bbcbp, 0, abc110, abc, bbcbp_state, init_bbc, "Acorn Computers", "ABC 110", MACHINE_NOT_WORKING ) +COMP( 1985, acw443, bbcbp, 0, acw443, abc, bbcbp_state, init_bbc, "Acorn Computers", "ABC 210/Cambridge Workstation", MACHINE_NOT_WORKING ) +COMP( 1985, abc310, bbcbp, 0, abc310, abc, bbcbp_state, init_bbc, "Acorn Computers", "ABC 310", MACHINE_NOT_WORKING ) +COMP( 1986, econx25, bbcbp, 0, econx25, bbcbp, bbcbp_state, init_bbc, "Acorn Computers", "Econet X25 Gateway", MACHINE_NOT_WORKING ) + +// Industrial +COMP( 1985, ltmpbp, bbcbp, 0, bbcbp, abc, bbcbp_state, init_ltmp, "Lawrie T&M Ltd.", "LTM Portable (B+)", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 198?, cfa3000bp, bbcbp, 0, cfa3000bp, bbcbp, bbcbp_state, init_cfa, "Tinsley Medical Instruments", "Henson CFA 3000 (B+)", MACHINE_NOT_WORKING ) |
