1 // license:BSD-3-Clause
2 // copyright-holders:Nigel Barnes
3 /**********************************************************************
4 
5     Acorn ANC04 Z80 2nd processor
6 
7     http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC04_Z802ndproc.html
8 
9 **********************************************************************/
10 
11 
12 #include "emu.h"
13 #include "tube_z80.h"
14 #include "softlist_dev.h"
15 
16 
17 //**************************************************************************
18 //  DEVICE DEFINITIONS
19 //**************************************************************************
20 
21 DEFINE_DEVICE_TYPE(BBC_TUBE_Z80, bbc_tube_z80_device, "bbc_tube_z80", "Acorn Z80 2nd Processor")
22 DEFINE_DEVICE_TYPE(BBC_TUBE_Z80W, bbc_tube_z80w_device, "bbc_tube_z80w", "Acorn Z80 2nd Processor (Winchester)")
23 
24 
25 //-------------------------------------------------
26 //  ADDRESS_MAP( tube_z80_mem )
27 //-------------------------------------------------
28 
tube_z80_mem(address_map & map)29 void bbc_tube_z80_device::tube_z80_mem(address_map &map)
30 {
31 	map(0x0000, 0xffff).rw(FUNC(bbc_tube_z80_device::mem_r), FUNC(bbc_tube_z80_device::mem_w));
32 }
33 
34 //-------------------------------------------------
35 //  ADDRESS_MAP( tube_z80_fetch )
36 //-------------------------------------------------
37 
tube_z80_fetch(address_map & map)38 void bbc_tube_z80_device::tube_z80_fetch(address_map &map)
39 {
40 	map(0x000, 0xffff).r(FUNC(bbc_tube_z80_device::opcode_r));
41 }
42 
43 //-------------------------------------------------
44 //  ADDRESS_MAP( tube_z80_io )
45 //-------------------------------------------------
46 
tube_z80_io(address_map & map)47 void bbc_tube_z80_device::tube_z80_io(address_map &map)
48 {
49 	map(0x00, 0x07).mirror(0xff00).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
50 }
51 
52 //-------------------------------------------------
53 //  ROM( tube_z80 )
54 //-------------------------------------------------
55 
56 ROM_START( tube_z80 )
57 	ROM_REGION(0x1000, "rom", 0)
58 	ROM_SYSTEM_BIOS(0, "120", "Z80 v1.20")
59 	ROMX_LOAD("z80_120.rom", 0x0000, 0x1000, CRC(315bfc20) SHA1(069077df498599a9c880d4ec9f4bc53fcc602d82), ROM_BIOS(0))
60 ROM_END
61 
ROM_START(tube_z80w)62 ROM_START( tube_z80w )
63 	ROM_REGION(0x1000, "rom", 0)
64 	ROM_SYSTEM_BIOS(0, "200", "Z80 v2.00") /* supplied with Acorn Business Computer */
65 	ROMX_LOAD("z80_200.rom", 0x0000, 0x1000, CRC(84672c3d) SHA1(47211cead3a1b0f9830dcdef8e54e29522c69bf8), ROM_BIOS(0))
66 ROM_END
67 
68 //-------------------------------------------------
69 //  device_add_mconfig - add device configuration
70 //-------------------------------------------------
71 
72 void bbc_tube_z80_device::device_add_mconfig(machine_config &config)
73 {
74 	Z80(config, m_z80, 12_MHz_XTAL / 2);
75 	m_z80->set_addrmap(AS_PROGRAM, &bbc_tube_z80_device::tube_z80_mem);
76 	m_z80->set_addrmap(AS_OPCODES, &bbc_tube_z80_device::tube_z80_fetch);
77 	m_z80->set_addrmap(AS_IO, &bbc_tube_z80_device::tube_z80_io);
78 	m_z80->set_irq_acknowledge_callback(FUNC(bbc_tube_z80_device::irq_callback));
79 
80 	TUBE(config, m_ula);
81 	m_ula->pnmi_handler().set_inputline(m_z80, INPUT_LINE_NMI);
82 	m_ula->pirq_handler().set_inputline(m_z80, INPUT_LINE_IRQ0);
83 
84 	/* software lists */
85 	SOFTWARE_LIST(config, "flop_ls_z80").set_original("bbc_flop_z80");
86 }
87 
88 //-------------------------------------------------
89 //  rom_region - device-specific ROM region
90 //-------------------------------------------------
91 
device_rom_region() const92 const tiny_rom_entry *bbc_tube_z80_device::device_rom_region() const
93 {
94 	return ROM_NAME( tube_z80 );
95 }
96 
device_rom_region() const97 const tiny_rom_entry *bbc_tube_z80w_device::device_rom_region() const
98 {
99 	return ROM_NAME( tube_z80w );
100 }
101 
102 //**************************************************************************
103 //  LIVE DEVICE
104 //**************************************************************************
105 
106 //-------------------------------------------------
107 //  bbc_tube_z80_device - constructor
108 //-------------------------------------------------
109 
bbc_tube_z80_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)110 bbc_tube_z80_device::bbc_tube_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
111 	: device_t(mconfig, type, tag, owner, clock)
112 	, device_bbc_tube_interface(mconfig, *this)
113 	, m_z80(*this, "z80")
114 	, m_ula(*this, "ula")
115 	, m_rom(*this, "rom")
116 	, m_rom_enabled(true)
117 {
118 }
119 
bbc_tube_z80_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)120 bbc_tube_z80_device::bbc_tube_z80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
121 	: bbc_tube_z80_device(mconfig, BBC_TUBE_Z80, tag, owner, clock)
122 {
123 }
124 
bbc_tube_z80w_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)125 bbc_tube_z80w_device::bbc_tube_z80w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
126 	: bbc_tube_z80_device(mconfig, BBC_TUBE_Z80W, tag, owner, clock)
127 {
128 }
129 
130 //-------------------------------------------------
131 //  device_start - device-specific startup
132 //-------------------------------------------------
133 
device_start()134 void bbc_tube_z80_device::device_start()
135 {
136 	m_ram = std::make_unique<uint8_t[]>(0x10000);
137 	memset(m_ram.get(), 0xff, 0x10000);
138 
139 	/* register for save states */
140 	save_pointer(NAME(m_ram), 0x10000);
141 }
142 
143 //-------------------------------------------------
144 //  device_reset - device-specific reset
145 //-------------------------------------------------
146 
device_reset()147 void bbc_tube_z80_device::device_reset()
148 {
149 	m_rom_enabled = true;
150 }
151 
152 
153 //**************************************************************************
154 //  IMPLEMENTATION
155 //**************************************************************************
156 
host_r(offs_t offset)157 uint8_t bbc_tube_z80_device::host_r(offs_t offset)
158 {
159 	return m_ula->host_r(offset);
160 }
161 
host_w(offs_t offset,uint8_t data)162 void bbc_tube_z80_device::host_w(offs_t offset, uint8_t data)
163 {
164 	m_ula->host_w(offset, data);
165 }
166 
167 
opcode_r(offs_t offset)168 uint8_t bbc_tube_z80_device::opcode_r(offs_t offset)
169 {
170 	if (!machine().side_effects_disabled())
171 	{
172 		if (offset == 0x0066 && m_z80->input_state(INPUT_LINE_NMI))
173 			m_rom_enabled = true;
174 		else if (offset >= 0x8000)
175 			m_rom_enabled = false;
176 	}
177 	return m_z80->space(AS_PROGRAM).read_byte(offset);
178 }
179 
180 
mem_r(offs_t offset)181 uint8_t bbc_tube_z80_device::mem_r(offs_t offset)
182 {
183 	uint8_t data;
184 
185 	if (m_rom_enabled && (offset < 0x1000))
186 		data = m_rom->base()[offset & 0xfff];
187 	else
188 		data = m_ram[offset];
189 
190 	return data;
191 }
192 
mem_w(offs_t offset,uint8_t data)193 void bbc_tube_z80_device::mem_w(offs_t offset, uint8_t data)
194 {
195 	m_ram[offset] = data;
196 }
197 
198 
199 //-------------------------------------------------
200 //  irq vector callback
201 //-------------------------------------------------
202 
IRQ_CALLBACK_MEMBER(bbc_tube_z80_device::irq_callback)203 IRQ_CALLBACK_MEMBER(bbc_tube_z80_device::irq_callback)
204 {
205 	return 0xfe;
206 }
207