summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/octopus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/octopus.cpp')
-rw-r--r--src/mame/drivers/octopus.cpp1047
1 files changed, 0 insertions, 1047 deletions
diff --git a/src/mame/drivers/octopus.cpp b/src/mame/drivers/octopus.cpp
deleted file mode 100644
index 7b9f7686b27..00000000000
--- a/src/mame/drivers/octopus.cpp
+++ /dev/null
@@ -1,1047 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/***************************************************************************
-
-Hilger Analytical AB6089 Mk. 1 (LSI Octopus)
-
-2013-07-26 Skeleton driver.
-
-http://computers.mcbx.netne.net/8bit/hilger/index.htm
-
-Below is an extract from the page:
-
-The computer has 2 CPUs: Z80 and 8088. Most circuits are dated 1985-1986, display circuitry is made by Signetics.
-Mainboard was manufactured by LSI Computers Ltd. under part numbers: 15000SS100 and 15000P4100. All steel parts
-of casing are grounded by wires. It's graphics card works in pass-through mode: It takes picture from mainboard's
-TTL output and adds image to it, then it puts it to monitor. Its ROM is prepared for hard disk and some type of
-network, yet no HDD controller nor network interfaces are present inside - it seems that they were added as
-expansion cards.
-
-UPDATE: It's re-branded LSI Octopus computer, a very well-expandable machine which was designed to "grow with a
-company". First stage was a computer which could be used even with TV set. As requirements increased, Octopus
-could be equipped with hard disk controller, network adapter, multi-terminal serial port card to act as a terminal
-server or even CPU cards to run concurrent systems. There were even tape backup devices for it. Octopus could run
-CP/M, MP/M (concurrent - multitasking-like OS, even with terminals), or even MS-DOS - CP/M or MP/M could be used
-with Z80 or 8080. There was also LSI ELSIE system, a concurrent DOS. Last British LSI machines were 386 computers
-which could be used as servers for Octopus computers.
-
-Manufacturer Hilger Analytical / LSI Computers Ltd.
-
-Origin UK
-Year of unit 1986?
-Year of introduction 1985
-End of production ?
-CPU Z80, 8088
-Speed 8MHz (8088) or 6MHz (Z80)
-RAM 128kB or 256kB, expandable to 768kB
-ROM 16kB (Basic)
-Colors: ??
-Sound: Speaker. Beeps :)
-OS: CP/M 80 or 86
-MP/M 80 o 86
-Concurrent CP/M
-LSI ELSIE
-MS-DOS
-Text display: SCN2674B CRTC, SCB2675C for attributes
-Graphics: ?? (option board, ROM is dumped)
-
-Media: Two internal 5.25" floppy disk drives, DS DD, 96tpi.
-Probably hard disk
-
-Power supply:
-Built-in switching power supply.
-
-I/O: Serial port
-2 parallel ports
-
-Video TTL Output
-Composite video output
-
-Possible upgrades: Many
-
-Software accessibility:
-Dedicated: Impossible.
-CP/M - Good
-DOS - Good.
-
-It won't take XT nor AT keyboard, but pinout is quite similar. UPDATE: I saw a few photos of keyboard.
-It's another Z80 computer! It has an EPROM, simple memory and CPU.
-
-After powering on, it should perform POST writing:
-
-TESTING...
- Main Processor
- PROM
- DMA Controllers
- RAM
- Interrupts
- Floppy Discs
- Hard Disc Controller (optionally - if installed)
-
-Waiting for hard Disc... (Optionally - if installed)
-
-Firmware versions:
-
-SYSTEM 18B (or other)
-GRAPHICS 4 (if graphic card installed)
-
-And probably it should boot or display:
-
-Insert System Disk.
-
-Or maybe:
-
-Nowhere to boot from.
-
-Load options:
- Floppy
- Pro Network
- Winchester
-Enter selection:
-
-This information was gained by studying boot ROM of the machine.
-
-It's a very rare computer. It has 2 processors, Z80 and 8088, so it can run both MS-DOS and CP/M.
-
-****************************************************************************/
-
-#include "emu.h"
-
-#include "cpu/i86/i86.h"
-#include "cpu/z80/z80.h"
-#include "imagedev/floppy.h"
-#include "machine/am9517a.h"
-#include "machine/bankdev.h"
-#include "machine/clock.h"
-#include "machine/i8251.h"
-#include "machine/i8255.h"
-#include "machine/mc146818.h"
-#include "machine/octo_kbd.h"
-#include "machine/pic8259.h"
-#include "machine/pit8253.h"
-#include "machine/ram.h"
-#include "machine/wd_fdc.h"
-#include "machine/z80sio.h"
-#include "sound/spkrdev.h"
-#include "video/scn2674.h"
-
-#include "bus/centronics/ctronics.h"
-#include "bus/centronics/comxpl80.h"
-#include "bus/centronics/epson_ex800.h"
-#include "bus/centronics/epson_lx800.h"
-#include "bus/centronics/epson_lx810l.h"
-#include "bus/centronics/printer.h"
-
-#include "screen.h"
-#include "softlist.h"
-#include "speaker.h"
-
-
-class octopus_state : public driver_device
-{
-public:
- octopus_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_subcpu(*this, "subcpu"),
- m_crtc(*this, "crtc"),
- m_vram(*this, "vram"),
- m_fontram(*this, "fram"),
- m_dma1(*this, "dma1"),
- m_dma2(*this, "dma2"),
- m_pic1(*this, "pic_master"),
- m_pic2(*this, "pic_slave"),
- m_rtc(*this, "rtc"),
- m_fdc(*this, "fdc"),
- m_floppy0(*this, "fdc:0"),
- m_floppy1(*this, "fdc:1"),
- m_kb_uart(*this, "keyboard"),
- m_pit(*this, "pit"),
- m_ppi(*this, "ppi"),
- m_speaker(*this, "speaker"),
- m_serial(*this, "serial"),
- m_parallel(*this, "parallel"),
- m_z80_bankdev(*this, "z80_bank"),
- m_ram(*this, "ram"),
- m_dswa(*this, "DSWA"),
- m_current_dma(-1),
- m_speaker_active(false),
- m_beep_active(false),
- m_z80_active(false)
- { }
-
- void octopus(machine_config &config);
-
-private:
- virtual void machine_reset() override;
- virtual void machine_start() override;
- virtual void video_start() override;
- SCN2674_DRAW_CHARACTER_MEMBER(display_pixels);
- DECLARE_READ8_MEMBER(vram_r);
- DECLARE_WRITE8_MEMBER(vram_w);
- DECLARE_READ8_MEMBER(get_slave_ack);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq);
- DECLARE_READ8_MEMBER(bank_sel_r);
- DECLARE_WRITE8_MEMBER(bank_sel_w);
- DECLARE_READ8_MEMBER(dma_read);
- DECLARE_WRITE8_MEMBER(dma_write);
- DECLARE_WRITE_LINE_MEMBER(dma_hrq_changed);
- DECLARE_READ8_MEMBER(system_r);
- DECLARE_WRITE8_MEMBER(system_w);
- DECLARE_READ8_MEMBER(cntl_r);
- DECLARE_WRITE8_MEMBER(cntl_w);
- DECLARE_READ8_MEMBER(gpo_r);
- DECLARE_WRITE8_MEMBER(gpo_w);
- DECLARE_READ8_MEMBER(vidcontrol_r);
- DECLARE_WRITE8_MEMBER(vidcontrol_w);
- DECLARE_READ8_MEMBER(z80_io_r);
- DECLARE_WRITE8_MEMBER(z80_io_w);
- IRQ_CALLBACK_MEMBER(x86_irq_cb);
- DECLARE_READ8_MEMBER(rtc_r);
- DECLARE_WRITE8_MEMBER(rtc_w);
- DECLARE_READ8_MEMBER(z80_vector_r);
- DECLARE_WRITE8_MEMBER(z80_vector_w);
- DECLARE_READ8_MEMBER(parallel_r);
- DECLARE_WRITE8_MEMBER(parallel_w);
- DECLARE_READ8_MEMBER(video_latch_r);
- DECLARE_WRITE8_MEMBER(video_latch_w);
-
- DECLARE_WRITE_LINE_MEMBER(spk_w);
- DECLARE_WRITE_LINE_MEMBER(spk_freq_w);
- DECLARE_WRITE_LINE_MEMBER(beep_w);
- DECLARE_WRITE_LINE_MEMBER(serial_clock_w);
- DECLARE_WRITE_LINE_MEMBER(parallel_busy_w) { m_printer_busy = state; }
- DECLARE_WRITE_LINE_MEMBER(parallel_slctout_w) { m_printer_slctout = state; }
-
- DECLARE_WRITE_LINE_MEMBER(dack0_w) { m_dma1->hack_w(state ? 0 : 1); } // for all unused DMA channel?
- DECLARE_WRITE_LINE_MEMBER(dack1_w) { if(!state) m_current_dma = 1; else if(m_current_dma == 1) m_current_dma = -1; } // HD
- DECLARE_WRITE_LINE_MEMBER(dack2_w) { if(!state) m_current_dma = 2; else if(m_current_dma == 2) m_current_dma = -1; } // RAM refresh
- DECLARE_WRITE_LINE_MEMBER(dack3_w) { m_dma1->hack_w(state ? 0 : 1); }
- DECLARE_WRITE_LINE_MEMBER(dack4_w) { m_dma1->hack_w(state ? 0 : 1); }
- DECLARE_WRITE_LINE_MEMBER(dack5_w) { if(!state) m_current_dma = 5; else if(m_current_dma == 5) m_current_dma = -1; } // Floppy
- DECLARE_WRITE_LINE_MEMBER(dack6_w) { m_dma1->hack_w(state ? 0 : 1); }
- DECLARE_WRITE_LINE_MEMBER(dack7_w) { m_dma1->hack_w(state ? 0 : 1); }
-
- enum
- {
- BEEP_TIMER = 100
- };
-
- void octopus_io(address_map &map);
- void octopus_mem(address_map &map);
- void octopus_sub_io(address_map &map);
- void octopus_sub_mem(address_map &map);
- void octopus_vram(address_map &map);
-
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- required_device<cpu_device> m_maincpu;
- required_device<cpu_device> m_subcpu;
- required_device<scn2674_device> m_crtc;
- required_shared_ptr<uint8_t> m_vram;
- required_shared_ptr<uint8_t> m_fontram;
- required_device<am9517a_device> m_dma1;
- required_device<am9517a_device> m_dma2;
- required_device<pic8259_device> m_pic1;
- required_device<pic8259_device> m_pic2;
- required_device<mc146818_device> m_rtc;
- required_device<fd1793_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<i8251_device> m_kb_uart;
- required_device<pit8253_device> m_pit;
- required_device<i8255_device> m_ppi;
- required_device<speaker_sound_device> m_speaker;
- required_device<z80sio_device> m_serial;
- required_device<centronics_device> m_parallel;
- required_device<address_map_bank_device> m_z80_bankdev;
- required_device<ram_device> m_ram;
- required_ioport m_dswa;
-
- uint8_t m_hd_bank; // HD bank select
- uint8_t m_fd_bank; // Floppy bank select
- uint8_t m_z80_bank; // Z80 bank / RAM refresh
- int8_t m_current_dma; // current DMA channel (-1 for none)
- uint8_t m_current_drive;
- uint8_t m_cntl; // RTC / FDC control (PPI port B)
- uint8_t m_gpo; // General purpose outputs (PPI port C)
- uint8_t m_vidctrl;
- bool m_speaker_active;
- bool m_beep_active;
- bool m_speaker_level;
- bool m_z80_active;
- bool m_rtc_address;
- bool m_rtc_data;
- uint8_t m_prev_cntl;
- uint8_t m_rs232_vector;
- uint8_t m_rs422_vector;
- bool m_printer_busy;
- bool m_printer_slctout;
- uint8_t m_char_latch_r;
- uint8_t m_attr_latch_r;
- uint8_t m_char_latch_w;
- uint8_t m_attr_latch_w;
-
- emu_timer* m_timer_beep;
-};
-
-
-void octopus_state::octopus_mem(address_map &map)
-{
- map(0x00000, 0xcffff).bankrw("main_ram_bank");
- map(0xd0000, 0xdffff).ram().share("vram");
- map(0xe0000, 0xe3fff).noprw();
- map(0xe4000, 0xe5fff).ram().share("fram");
- map(0xe6000, 0xe7fff).rom().region("chargen", 0);
- map(0xe8000, 0xfbfff).noprw();
- map(0xfc000, 0xfffff).rom().region("user1", 0);
-}
-
-void octopus_state::octopus_io(address_map &map)
-{
- map.unmap_value_high();
- map(0x00, 0x0f).rw(m_dma1, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
- map(0x10, 0x1f).rw(m_dma2, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
- map(0x20, 0x20).portr("DSWA");
- map(0x21, 0x2f).rw(FUNC(octopus_state::system_r), FUNC(octopus_state::system_w));
- map(0x31, 0x33).rw(FUNC(octopus_state::bank_sel_r), FUNC(octopus_state::bank_sel_w));
- map(0x50, 0x51).rw(m_kb_uart, FUNC(i8251_device::read), FUNC(i8251_device::write));
- // 0x70-73: HD controller
- map(0x80, 0x83).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
- map(0xa0, 0xa0).rw(m_serial, FUNC(z80sio_device::da_r), FUNC(z80sio_device::da_w));
- map(0xa1, 0xa1).rw(m_serial, FUNC(z80sio_device::ca_r), FUNC(z80sio_device::ca_w));
- map(0xa2, 0xa2).rw(m_serial, FUNC(z80sio_device::db_r), FUNC(z80sio_device::db_w));
- map(0xa3, 0xa3).rw(m_serial, FUNC(z80sio_device::cb_r), FUNC(z80sio_device::cb_w));
- map(0xb0, 0xb1).rw(m_pic1, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
- map(0xb4, 0xb5).rw(m_pic2, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
- map(0xc0, 0xc7).rw(m_crtc, FUNC(scn2674_device::read), FUNC(scn2674_device::write));
- map(0xc8, 0xc8).rw(FUNC(octopus_state::vidcontrol_r), FUNC(octopus_state::vidcontrol_w));
- map(0xc9, 0xca).rw(FUNC(octopus_state::video_latch_r), FUNC(octopus_state::video_latch_w));
- // 0xcf: mode control
- map(0xd0, 0xd3).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write));
- map(0xe0, 0xe4).rw(FUNC(octopus_state::z80_vector_r), FUNC(octopus_state::z80_vector_w));
- map(0xf0, 0xf1).rw(FUNC(octopus_state::parallel_r), FUNC(octopus_state::parallel_w));
- map(0xf8, 0xff).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write));
-}
-
-
-void octopus_state::octopus_sub_mem(address_map &map)
-{
- map(0x0000, 0xffff).rw(m_z80_bankdev, FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
-}
-
-void octopus_state::octopus_sub_io(address_map &map)
-{
- map.unmap_value_high();
- map(0x0000, 0xffff).rw(FUNC(octopus_state::z80_io_r), FUNC(octopus_state::z80_io_w));
-}
-
-void octopus_state::octopus_vram(address_map &map)
-{
- map(0x0000, 0xffff).rw(FUNC(octopus_state::vram_r), FUNC(octopus_state::vram_w));
-}
-
-/* Input ports */
-static INPUT_PORTS_START( octopus )
- PORT_START("DSWA")
- PORT_DIPNAME( 0x03, 0x02, "Number of floppy drives" ) PORT_DIPLOCATION("SWA:1,2")
- PORT_DIPSETTING( 0x00, "None" )
- PORT_DIPSETTING( 0x01, "1 Floppy" )
- PORT_DIPSETTING( 0x02, "2 Floppies" )
- PORT_DIPSETTING( 0x03, "Not used" )
- PORT_DIPNAME( 0x04, 0x00, "Quad drives" ) PORT_DIPLOCATION("SWA:3")
- PORT_DIPSETTING( 0x00, "Disabled" )
- PORT_DIPSETTING( 0x04, "Enabled" )
- PORT_DIPNAME( 0x38, 0x00, "Winchester drive type" ) PORT_DIPLOCATION("SWA:4,5,6")
- PORT_DIPSETTING( 0x00, "None" )
- PORT_DIPSETTING( 0x08, "RO201" )
- PORT_DIPSETTING( 0x10, "RO202" )
- PORT_DIPSETTING( 0x18, "Reserved" )
- PORT_DIPSETTING( 0x20, "RO204" )
- PORT_DIPSETTING( 0x28, "Reserved" )
- PORT_DIPSETTING( 0x30, "RO208" )
- PORT_DIPSETTING( 0x38, "Reserved" )
- PORT_DIPNAME( 0x40, 0x00, DEF_STR( Unused ) ) PORT_DIPLOCATION("SWA:7")
- PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x40, DEF_STR( On ) )
- PORT_DIPNAME( 0x80, 0x80, "Colour monitor connected" ) PORT_DIPLOCATION("SWA:8")
- PORT_DIPSETTING( 0x00, DEF_STR( No ) )
- PORT_DIPSETTING( 0x80, DEF_STR( Yes ) )
-INPUT_PORTS_END
-
-void octopus_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch(id)
- {
- case BEEP_TIMER: // switch off speaker
- m_beep_active = false;
- break;
- }
-}
-
-WRITE8_MEMBER(octopus_state::vram_w)
-{
- m_vram[offset] = m_char_latch_w;
- m_vram[offset+0x1000] = m_attr_latch_w;
-}
-
-READ8_MEMBER(octopus_state::vram_r)
-{
- m_char_latch_r = m_vram[offset];
- m_attr_latch_r = m_vram[offset+0x1000];
- return m_vram[offset];
-}
-
-WRITE_LINE_MEMBER(octopus_state::fdc_drq)
-{
- // TODO
-}
-
-READ8_MEMBER(octopus_state::bank_sel_r)
-{
- switch(offset)
- {
- case 0:
- return m_hd_bank;
- case 1:
- return m_fd_bank;
- case 2:
- return m_z80_bank;
- }
- return 0xff;
-}
-
-WRITE8_MEMBER(octopus_state::bank_sel_w)
-{
- switch(offset)
- {
- case 0:
- m_hd_bank = data;
- logerror("HD bank = %i\n",data);
- break;
- case 1:
- m_fd_bank = data;
- logerror("Floppy bank = %i\n",data);
- break;
- case 2:
- m_z80_bank = data;
- m_z80_bankdev->set_bank(m_z80_bank & 0x0f);
- logerror("Z80/RAM bank = %i\n",data);
- break;
- }
-}
-
-// System control
-// 0x20: read: System type, write: Z80 NMI
-// 0x21: read: bit5=SLCTOUT from parallel interface, bit6=option board parity fail, bit7=main board parity fail
-// write: parity fail reset
-// ports 0x20 and 0x21 read out the DIP switch configuration (the firmware function to get system config simply does IN AX,20h)
-// 0x28: write: Z80 enable
-WRITE8_MEMBER(octopus_state::system_w)
-{
- logerror("SYS: System control offset %i data %02x\n",offset+1,data);
- switch(offset)
- {
- case 7: // enable Z80, halt 8088
- m_subcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
- m_z80_active = true;
- break;
- }
-}
-
-READ8_MEMBER(octopus_state::system_r)
-{
- uint8_t val = 0x00;
- switch(offset)
- {
- case 0:
- val = 0x1f;
- if(m_printer_slctout)
- val |= 0x20;
- return val; // do bits 0-4 mean anything? Language DIPs?
- }
-
- return 0xff;
-}
-
-// Any I/O cycle relinquishes control of the bus
-READ8_MEMBER(octopus_state::z80_io_r)
-{
- z80_io_w(space,offset,0);
- return 0x00;
-}
-
-WRITE8_MEMBER(octopus_state::z80_io_w)
-{
- m_subcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_z80_active = false;
-}
-
-// Z80 vector for RS232 and RS422
-READ8_MEMBER(octopus_state::z80_vector_r)
-{
- switch(offset)
- {
- case 0:
- return m_rs232_vector;
- case 4:
- return m_rs422_vector;
- default:
- return 0xff;
- }
- return 0xff;
-}
-
-WRITE8_MEMBER(octopus_state::z80_vector_w)
-{
- switch(offset)
- {
- case 0:
- m_rs232_vector = data;
- logerror("RS232 vector set to %02x\n",data);
- break;
- case 4:
- m_rs422_vector = data;
- logerror("RS422 vector set to %02x\n",data);
- break;
- default:
- logerror("Read invalid vector port 0x%02x\n",0xe0 + offset);
- }
-}
-
-// RTC data and I/O - PPI port A
-// bits 0-3 of RTC/FDC control go to control lines of the MC146818
-// The technical manual does not mention what is connected to each bit
-// This is an educated guess, based on the BIOS code
-// bit 0 = ? (Pulsed low after writing to an RTC register)
-// bit 1 = PPI Port A strobe?
-// bit 2 = Data strobe?
-// bit 3 = Address strobe?
-READ8_MEMBER(octopus_state::rtc_r)
-{
- uint8_t ret = 0xff;
-
- if(m_rtc_data)
- ret = m_rtc->read(1);
- else if(m_rtc_address)
- ret = m_rtc->read(0);
-
- return ret;
-}
-
-WRITE8_MEMBER(octopus_state::rtc_w)
-{
- if(m_rtc_data)
- m_rtc->write(1,data);
- else if(m_rtc_address)
- m_rtc->write(0,data);
-}
-
-// RTC/FDC control - PPI port B
-// bits0-3: RTC control lines
-// bit4-5: write precomp.
-// bit6-7: drive select
-READ8_MEMBER(octopus_state::cntl_r)
-{
- return m_cntl;
-}
-
-WRITE8_MEMBER(octopus_state::cntl_w)
-{
- m_cntl = data;
-
- if((m_cntl & 0x08) && !(m_prev_cntl & 0x08))
- {
- m_rtc_address = true;
- m_rtc_data = false;
- }
- if((data & 0x04) && !(m_prev_cntl & 0x04))
- {
- m_rtc_address = false;
- m_rtc_data = true;
- }
- m_ppi->pc4_w(data & 0x02);
- m_prev_cntl = m_cntl;
- m_current_drive = (data & 0xc0) >> 6;
- switch(m_current_drive)
- {
- case 1:
- m_fdc->set_floppy(m_floppy0->get_device());
- m_floppy0->get_device()->mon_w(0);
- break;
- case 2:
- m_fdc->set_floppy(m_floppy1->get_device());
- m_floppy1->get_device()->mon_w(0);
- break;
- }
- logerror("Selected floppy drive %i (%02x)\n",m_current_drive,data);
-}
-
-// General Purpose Outputs - PPI port C
-// bit 2 - floppy side select
-// bit 1 - parallel data I/O (0 = output)
-// bit 0 - parallel control I/O (0 = output)
-READ8_MEMBER(octopus_state::gpo_r)
-{
- return m_gpo;
-}
-
-WRITE8_MEMBER(octopus_state::gpo_w)
-{
- m_gpo = data;
- switch(m_current_drive)
- {
- case 1:
- m_floppy0->get_device()->ss_w((data & 0x04) >> 2);
- break;
- case 2:
- m_floppy1->get_device()->ss_w((data & 0x04) >> 2);
- break;
- default:
- logerror("Attempted to set side on unknown drive %i\n",m_current_drive);
- }
-}
-
-// Video control register
-// bit 0 - video dot clock - 0=17.6MHz, 1=16MHz
-// bit 2 - floppy DDEN line
-// bit 3 - floppy FCLOCK line - 0=1MHz, 1=2MHz
-// bits 4-5 - character width - 0=10 dots, 1=6 dots, 2=8 dots, 3=9 dots
-// bit 6 - cursor mode (colour only) - 0=inverse cursor, 1=white cursor (normal)
-// bit 7 - 1=monochrome mode, 0=colour mode
-// Is bit 7 writable, or just mirrors DIP switch setting? Tech manual is unclear.
-READ8_MEMBER(octopus_state::vidcontrol_r)
-{
- return m_vidctrl;
-}
-
-WRITE8_MEMBER(octopus_state::vidcontrol_w)
-{
- m_fdc->dden_w(BIT(data, 2));
- m_fdc->set_unscaled_clock(16_MHz_XTAL / (BIT(data, 3) ? 16 : 8));
-
- if (((m_vidctrl ^ data) & 0x31) != 0)
- {
- unsigned dots = 4 + ((data & 0x30) >> 3);
- if ((data & 0x30) == 0)
- dots = 10;
- else if ((data & 0x30) == 0x30)
- dots = 9;
-
- auto dotclk = BIT(data, 0) ? 16_MHz_XTAL : 17.6_MHz_XTAL;
-
- m_crtc->set_character_width(dots);
- m_crtc->set_unscaled_clock(dotclk / dots);
- }
-
- m_vidctrl = data;
-}
-
-// Sound hardware
-// Sound level provided by i8253 timer 2
-// Enabled by /DTR signal from i8251
-// 100ms beep triggered by pulsing /CTS signal low on i8251
-WRITE_LINE_MEMBER(octopus_state::spk_w)
-{
- m_speaker_active = !state;
- m_speaker->level_w(((m_speaker_active || m_beep_active) && m_speaker_level) ? 1 : 0);
-}
-
-WRITE_LINE_MEMBER(octopus_state::spk_freq_w)
-{
- m_speaker_level = state;
- m_speaker->level_w(((m_speaker_active || m_beep_active) && m_speaker_level) ? 1 : 0);
-}
-
-WRITE_LINE_MEMBER(octopus_state::beep_w)
-{
- if(!state) // active low
- {
- m_beep_active = true;
- m_speaker->level_w(((m_speaker_active || m_beep_active) && m_speaker_level) ? 1 : 0);
- m_timer_beep->adjust(attotime::from_msec(100));
- }
-}
-
-WRITE_LINE_MEMBER(octopus_state::serial_clock_w)
-{
- m_serial->rxca_w(state);
- m_serial->txca_w(state);
-}
-
-// Parallel Centronics port
-// 0xf0 : data
-// 0xf1 : control
-// bit 2 = INIT? On boot, bits 0 and 1 are set high, bit 2 is set low then high again, all other bits are set low
-// can generate interrupts - tech manual suggests that Strobe, Init, Ack, and Busy can trigger an interrupt (IRQ14)
-READ8_MEMBER(octopus_state::parallel_r)
-{
- switch(offset)
- {
- case 0:
- return 0;
- case 1:
- return m_printer_busy ? 0x01 : 0x00; // correct? Tech manual doesn't explain which bit is which
- }
- return 0xff;
-}
-
-WRITE8_MEMBER(octopus_state::parallel_w)
-{
- switch(offset)
- {
- case 0: // data
- if(!(m_gpo & 0x02)) // parallel data direction
- {
- m_parallel->write_data0(BIT(data,0));
- m_parallel->write_data1(BIT(data,1));
- m_parallel->write_data2(BIT(data,2));
- m_parallel->write_data3(BIT(data,3));
- m_parallel->write_data4(BIT(data,4));
- m_parallel->write_data5(BIT(data,5));
- m_parallel->write_data6(BIT(data,6));
- m_parallel->write_data7(BIT(data,7));
- }
- break;
- case 1: // control (bit order unknown?)
- if(!(m_gpo & 0x01)) // parallel control direction
- {
- m_parallel->write_init(BIT(data,2));
- m_pic2->ir6_w(!BIT(data,2));
- }
- break;
- }
-}
-
-READ8_MEMBER(octopus_state::dma_read)
-{
- uint8_t byte;
- address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
- if(m_current_dma == -1)
- return 0;
- byte = prog_space.read_byte((m_fd_bank << 16) + offset);
- return byte;
-}
-
-WRITE8_MEMBER(octopus_state::dma_write)
-{
- address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
- if(m_current_dma == -1)
- return;
- prog_space.write_byte((m_fd_bank << 16) + offset, data);
-}
-
-WRITE_LINE_MEMBER( octopus_state::dma_hrq_changed )
-{
- m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
-
- /* Assert HLDA */
- m_dma2->hack_w(state);
-}
-
-// Any interrupt will also give bus control back to the 8088
-IRQ_CALLBACK_MEMBER(octopus_state::x86_irq_cb)
-{
- uint8_t vector;
- m_subcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_z80_active = false;
- vector = m_pic1->inta_cb(device,irqline);
- if(vector == 0x61) // if we have hit a serial comms IRQ, then also have the Z80SIO/2 acknowledge the interrupt
- vector = m_serial->m1_r();
- return vector;
-}
-
-void octopus_state::machine_start()
-{
- m_timer_beep = timer_alloc(BEEP_TIMER);
- m_vidctrl = 0xff;
-
- // install RAM
- m_maincpu->space(AS_PROGRAM).install_readwrite_bank(0x0000,m_ram->size()-1,"main_ram_bank");
- m_maincpu->space(AS_PROGRAM).nop_readwrite(m_ram->size(),0xcffff);
-}
-
-void octopus_state::machine_reset()
-{
- m_subcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); // halt Z80 to start with
- m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_z80_active = false;
- m_current_dma = -1;
- m_current_drive = 0;
- m_rtc_address = true;
- m_rtc_data = false;
- membank("main_ram_bank")->set_base(m_ram->pointer());
- m_kb_uart->write_dsr(1); // DSR is used to determine if a keyboard is connected? If DSR is high, then the CHAR_OUT BIOS function will not output to the screen.
-}
-
-void octopus_state::video_start()
-{
- m_vram.allocate(0x10000);
-}
-
-READ8_MEMBER(octopus_state::video_latch_r)
-{
- if(offset & 0x01)
- return m_attr_latch_r;
- else
- return m_char_latch_r;
-}
-
-WRITE8_MEMBER(octopus_state::video_latch_w)
-{
- if(offset & 0x01)
- m_attr_latch_w = data;
- else
- m_char_latch_w = data;
-}
-
-SCN2674_DRAW_CHARACTER_MEMBER(octopus_state::display_pixels)
-{
- // Attributes:
- // - common bits
- // b7 : blink
- // b3 : underline
- // - Monochrome
- // b6 : GP1 (general purpose)
- // b5 : reverse video
- // b4 : GP2 (general purpose)
- // b2 : High intensity
- // b1 : Grey background
- // b0 : Blank (TODO)
- // - Colour
- // b6,5,4 : background colour (RGB)
- // b2,1,0 : foreground colour (RGB)
- if(!lg)
- {
- uint8_t tile = m_vram[address & 0x0fff];
- uint8_t attr = m_vram[(address & 0x0fff) + 0x1000];
- uint8_t data = m_fontram[(tile * 16) + linecount];
- rgb_t fg,bg;
- if(m_dswa->read() & 0x80) // monochrome or colour mode is selected by switch 8 of system DIP switches
- {
- // colour (is the background at half intensity?)
- bg.set_r((attr & 0x40) ? 0x7f : 0x00);
- bg.set_g((attr & 0x20) ? 0x7f : 0x00);
- bg.set_b((attr & 0x10) ? 0x7f : 0x00);
- fg.set_r((attr & 0x04) ? 0xff : 0x00);
- fg.set_g((attr & 0x02) ? 0xff : 0x00);
- fg.set_b((attr & 0x01) ? 0xff : 0x00);
- }
- else
- {
- // monochrome
- if(attr & 0x02)
- fg = 0xffffff;
- else
- fg = 0x7f7f7f;
- if(attr & 0x04)
- bg = 0x7f7f7f;
- else
- bg = 0x000000;
-
- if(attr & 0x20) // reverse video
- data = ~data;
- }
- if(ul && (attr & 0x08))
- data = 0xff;
- if(blink && (attr & 0x80))
- data = 0x00;
- if(cursor && !blink)
- {
- bool inverse = true;
-
- if(!(m_dswa->read() & 0x80)) // not available in monochrome mode
- inverse = false;
- if(m_vidctrl & 0x40) // not enabled
- inverse = false;
- if(inverse)
- data = ~data;
- else
- data = 0xff;
- }
- for (int z=0;z<8;z++)
- bitmap.pix32(y,x + z) = BIT(data,z) ? fg : bg;
- }
-}
-
-READ8_MEMBER( octopus_state::get_slave_ack )
-{
- if (offset==7)
- return m_pic2->acknowledge();
-
- return 0x00;
-}
-
-static void octopus_floppies(device_slot_interface &device)
-{
- device.option_add("525dd", FLOPPY_525_DD);
-}
-
-static void keyboard(device_slot_interface &device)
-{
- device.option_add("octopus", OCTOPUS_KEYBOARD);
-}
-
-void octopus_centronics_devices(device_slot_interface &device)
-{
- device.option_add("pl80", COMX_PL80);
- device.option_add("ex800", EPSON_EX800);
- device.option_add("lx800", EPSON_LX800);
- device.option_add("lx810l", EPSON_LX810L);
- device.option_add("ap2000", EPSON_AP2000);
- device.option_add("printer", CENTRONICS_PRINTER);
-}
-
-void octopus_state::octopus(machine_config &config)
-{
- /* basic machine hardware */
- I8088(config, m_maincpu, 24_MHz_XTAL / 3); // 8MHz
- m_maincpu->set_addrmap(AS_PROGRAM, &octopus_state::octopus_mem);
- m_maincpu->set_addrmap(AS_IO, &octopus_state::octopus_io);
- m_maincpu->set_irq_acknowledge_callback(FUNC(octopus_state::x86_irq_cb));
-
- Z80(config, m_subcpu, 24_MHz_XTAL / 4); // 6MHz
- m_subcpu->set_addrmap(AS_PROGRAM, &octopus_state::octopus_sub_mem);
- m_subcpu->set_addrmap(AS_IO, &octopus_state::octopus_sub_io);
-
- AM9517A(config, m_dma1, 24_MHz_XTAL / 6); // 4MHz
- m_dma1->out_hreq_callback().set(m_dma2, FUNC(am9517a_device::dreq0_w));
- m_dma1->in_memr_callback().set(FUNC(octopus_state::dma_read));
- m_dma1->out_memw_callback().set(FUNC(octopus_state::dma_write));
- //m_dma1->in_ior_callback<0>().set_nop();
- //m_dma1->in_ior_callback<1>().set_nop(); // HDC
- //m_dma1->in_ior_callback<2>().set_nop(); // RAM Refresh
- //m_dma1->in_ior_callback<3>().set_nop();
- //m_dma1->out_iow_callback<0>().set_nop();
- //m_dma1->out_iow_callback<1>().set_nop(); // HDC
- //m_dma1->out_iow_callback<2>().set_nop(); // RAM Refresh
- //m_dma1->out_iow_callback<3>().set_nop();
- m_dma1->out_dack_callback<0>().set(FUNC(octopus_state::dack0_w));
- m_dma1->out_dack_callback<1>().set(FUNC(octopus_state::dack1_w));
- m_dma1->out_dack_callback<2>().set(FUNC(octopus_state::dack2_w));
- m_dma1->out_dack_callback<3>().set(FUNC(octopus_state::dack3_w));
-
- AM9517A(config, m_dma2, 24_MHz_XTAL / 6); // 4MHz
- m_dma2->out_hreq_callback().set(FUNC(octopus_state::dma_hrq_changed));
- m_dma2->in_memr_callback().set(FUNC(octopus_state::dma_read));
- m_dma2->out_memw_callback().set(FUNC(octopus_state::dma_write));
- //m_dma2->in_ior_callback<0>().set_nop();
- m_dma2->in_ior_callback<1>().set(m_fdc, FUNC(fd1793_device::data_r)); // FDC
- //m_dma2->in_ior_callback<2>().set_nop();
- //m_dma2->in_ior_callback<3>().set_nop();
- //m_dma2->out_iow_callback<0>().set_nop();
- m_dma2->out_iow_callback<1>().set(m_fdc, FUNC(fd1793_device::data_w)); // FDC
- //m_dma2->out_iow_callback<2>().set_nop();
- //m_dma2->out_iow_callback<3>().set_nop();
- m_dma2->out_dack_callback<0>().set(FUNC(octopus_state::dack4_w));
- m_dma2->out_dack_callback<1>().set(FUNC(octopus_state::dack5_w));
- m_dma2->out_dack_callback<2>().set(FUNC(octopus_state::dack6_w));
- m_dma2->out_dack_callback<3>().set(FUNC(octopus_state::dack7_w));
-
- PIC8259(config, m_pic1, 0);
- m_pic1->out_int_callback().set_inputline(m_maincpu, 0);
- m_pic1->in_sp_callback().set_constant(1);
- m_pic1->read_slave_ack_callback().set(FUNC(octopus_state::get_slave_ack));
-
- PIC8259(config, m_pic2, 0);
- m_pic2->out_int_callback().set(m_pic1, FUNC(pic8259_device::ir7_w));
- m_pic2->in_sp_callback().set_constant(0);
-
- // RTC (MC146818 via i8255 PPI)
- I8255(config, m_ppi, 0);
- m_ppi->in_pa_callback().set(FUNC(octopus_state::rtc_r));
- m_ppi->in_pb_callback().set(FUNC(octopus_state::cntl_r));
- m_ppi->in_pc_callback().set(FUNC(octopus_state::gpo_r));
- m_ppi->out_pa_callback().set(FUNC(octopus_state::rtc_w));
- m_ppi->out_pb_callback().set(FUNC(octopus_state::cntl_w));
- m_ppi->out_pc_callback().set(FUNC(octopus_state::gpo_w));
-
- MC146818(config, m_rtc, 32.768_kHz_XTAL);
- m_rtc->irq().set(m_pic2, FUNC(pic8259_device::ir2_w));
-
- // Keyboard UART
- I8251(config, m_kb_uart, 0);
- m_kb_uart->rxrdy_handler().set("pic_slave", FUNC(pic8259_device::ir4_w));
- m_kb_uart->dtr_handler().set(FUNC(octopus_state::spk_w));
- m_kb_uart->rts_handler().set(FUNC(octopus_state::beep_w));
- rs232_port_device &keyboard_port(RS232_PORT(config, "keyboard_port", keyboard, "octopus"));
- keyboard_port.rxd_handler().set(m_kb_uart, FUNC(i8251_device::write_rxd));
- clock_device &keyboard_clock_rx(CLOCK(config, "keyboard_clock_rx", 9600 * 64));
- keyboard_clock_rx.signal_handler().set(m_kb_uart, FUNC(i8251_device::write_rxc));
- clock_device &keyboard_clock_tx(CLOCK(config, "keyboard_clock_tx", 1200 * 64));
- keyboard_clock_tx.signal_handler().set(m_kb_uart, FUNC(i8251_device::write_txc));
-
- FD1793(config, m_fdc, 16_MHz_XTAL / 8);
- m_fdc->intrq_wr_callback().set(m_pic1, FUNC(pic8259_device::ir5_w));
- m_fdc->drq_wr_callback().set(m_dma2, FUNC(am9517a_device::dreq1_w));
- FLOPPY_CONNECTOR(config, "fdc:0", octopus_floppies, "525dd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", octopus_floppies, "525dd", floppy_image_device::default_floppy_formats);
- SOFTWARE_LIST(config, "fd_list").set_original("octopus");
-
- PIT8253(config, m_pit, 0);
- m_pit->set_clk<0>(4.9152_MHz_XTAL / 2); // DART channel A
- m_pit->out_handler<0>().set(FUNC(octopus_state::serial_clock_w)); // being able to write both Rx and Tx clocks at one time would be nice
- m_pit->set_clk<1>(4.9152_MHz_XTAL / 2); // DART channel B
- m_pit->out_handler<1>().set(m_serial, FUNC(z80sio_device::rxtxcb_w));
- m_pit->set_clk<2>(4.9152_MHz_XTAL / 2); // speaker frequency
- m_pit->out_handler<2>().set(FUNC(octopus_state::spk_freq_w));
-
- SPEAKER(config, "mono").front_center();
- SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50);
-
- Z80SIO(config, m_serial, 16_MHz_XTAL / 4); // clock rate not mentioned in tech manual
- m_serial->out_int_callback().set(m_pic1, FUNC(pic8259_device::ir1_w));
- m_serial->out_txda_callback().set("serial_a", FUNC(rs232_port_device::write_txd));
- m_serial->out_txdb_callback().set("serial_b", FUNC(rs232_port_device::write_txd));
- m_serial->out_rtsa_callback().set("serial_a", FUNC(rs232_port_device::write_rts));
- m_serial->out_rtsb_callback().set("serial_b", FUNC(rs232_port_device::write_rts));
-
- rs232_port_device &serial_a(RS232_PORT(config, "serial_a", default_rs232_devices, nullptr));
- serial_a.rxd_handler().set(m_serial, FUNC(z80sio_device::rxa_w));
- serial_a.cts_handler().set(m_serial, FUNC(z80sio_device::ctsa_w)).invert();
- //serial_a.ri_handler().set(m_serial, FUNC(z80sio_device::ria_w)).invert();
- rs232_port_device &serial_b(RS232_PORT(config, "serial_b", default_rs232_devices, nullptr));
- serial_b.rxd_handler().set(m_serial, FUNC(z80sio_device::rxb_w));
- serial_b.cts_handler().set(m_serial, FUNC(z80sio_device::ctsb_w)).invert();
- //serial_b.ri_handler().set(m_serial, FUNC(z80sio_device::rib_w)).invert();
-
- CENTRONICS(config, m_parallel, octopus_centronics_devices, "printer");
- m_parallel->busy_handler().set(FUNC(octopus_state::parallel_busy_w));
- m_parallel->select_handler().set(FUNC(octopus_state::parallel_slctout_w));
- // TODO: Winchester HD controller (Xebec/SASI compatible? uses TTL logic)
-
- /* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_raw(16_MHz_XTAL, 918, 0, 729, 350, 0, 325);
- //screen.set_raw(17.6_MHz_XTAL, 1008, 0, 792, 348, 0, 319);
- screen.set_screen_update("crtc", FUNC(scn2674_device::screen_update));
-
- SCN2674(config, m_crtc, 16_MHz_XTAL / 9); // dot clock and character width are both selectable
- m_crtc->intr_callback().set("pic_slave", FUNC(pic8259_device::ir0_w));
- m_crtc->set_character_width(9);
- m_crtc->set_display_callback(FUNC(octopus_state::display_pixels));
- m_crtc->set_addrmap(0, &octopus_state::octopus_vram);
- m_crtc->set_screen("screen");
-
- ADDRESS_MAP_BANK(config, "z80_bank").set_map(&octopus_state::octopus_mem).set_options(ENDIANNESS_LITTLE, 8, 32, 0x10000);
-
- RAM(config, "ram").set_default_size("256K").set_extra_options("128K,512K,768K");
-}
-
-/* ROM definition */
-ROM_START( octopus )
- ROM_REGION( 0x4000, "user1", 0 )
- ROM_LOAD( "octopus_main_prom", 0x0000, 0x4000, CRC(b5b4518d) SHA1(41b8729c4c9074914fd4ea181c8b6d4805ee2b93) )
-
- // This rom was on the graphics card (yes, it has slots)
- ROM_REGION( 0x2000, "chargen", 0 )
- ROM_LOAD( "octopus_gfx_card", 0x0000, 0x2000, CRC(b2386534) SHA1(5e3c4682afb4eb222e48a7203269a16d26911836) )
-ROM_END
-
-/* Driver */
-
-// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-COMP( 1986, octopus, 0, 0, octopus, octopus, octopus_state, empty_init, "Digital Microsystems", "LSI Octopus", MACHINE_NOT_WORKING)