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