1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Commodore 64 CP/M cartridge emulation
6 
7     http://www.baltissen.org/newhtm/c64_cpm.htm
8 
9 **********************************************************************/
10 
11 /*
12 
13     TODO:
14 
15     - Z80 clock speed
16 
17 */
18 
19 #include "emu.h"
20 #include "cpm.h"
21 
22 
23 
24 //**************************************************************************
25 //  MACROS/CONSTANTS
26 //**************************************************************************
27 
28 #define Z80_TAG     "z80"
29 
30 
31 
32 //**************************************************************************
33 //  DEVICE DEFINITIONS
34 //**************************************************************************
35 
36 DEFINE_DEVICE_TYPE(C64_CPM, c64_cpm_cartridge_device, "c64_cpm", "C64 CP/M cartridge")
37 
38 
39 //-------------------------------------------------
40 //  ADDRESS_MAP( z80_mem )
41 //-------------------------------------------------
42 
z80_mem(address_map & map)43 void c64_cpm_cartridge_device::z80_mem(address_map &map)
44 {
45 	map(0x0000, 0xffff).rw(FUNC(c64_cpm_cartridge_device::dma_r), FUNC(c64_cpm_cartridge_device::dma_w));
46 }
47 
48 
49 //-------------------------------------------------
50 //  ADDRESS_MAP( z80_io )
51 //-------------------------------------------------
52 
z80_io(address_map & map)53 void c64_cpm_cartridge_device::z80_io(address_map &map)
54 {
55 	map(0x0000, 0xffff).rw(FUNC(c64_cpm_cartridge_device::dma_r), FUNC(c64_cpm_cartridge_device::dma_w));
56 }
57 
58 
59 //-------------------------------------------------
60 //  device_add_mconfig - add device configuration
61 //-------------------------------------------------
62 
device_add_mconfig(machine_config & config)63 void c64_cpm_cartridge_device::device_add_mconfig(machine_config &config)
64 {
65 	Z80(config, m_maincpu, 3000000);
66 	m_maincpu->set_addrmap(AS_PROGRAM, &c64_cpm_cartridge_device::z80_mem);
67 	m_maincpu->set_addrmap(AS_IO, &c64_cpm_cartridge_device::z80_io);
68 }
69 
70 
71 
72 //**************************************************************************
73 //  INLINE HELPERS
74 //**************************************************************************
75 
76 //-------------------------------------------------
77 //  update_signals -
78 //-------------------------------------------------
79 
update_signals()80 inline void c64_cpm_cartridge_device::update_signals()
81 {
82 	if (m_enabled)
83 	{
84 		m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
85 		m_slot->dma_w(ASSERT_LINE);
86 
87 		if (m_reset)
88 		{
89 			m_maincpu->reset();
90 			m_maincpu->set_state_int(Z80_PC, 0);
91 			m_reset = 0;
92 		}
93 	}
94 	else
95 	{
96 		m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
97 		m_slot->dma_w(CLEAR_LINE);
98 	}
99 
100 /*
101     // NOTE: the following is how it actually works once the Z80 core has been rewritten
102 
103     // C64 DMA
104     m_slot->dma_w(m_enabled ? ASSERT_LINE : CLEAR_LINE);
105 
106     // Z80 BUSRQ
107     int busrq = !(m_enabled & !m_ba) ? CLEAR_LINE : ASSERT_LINE;
108     m_maincpu->set_input_line(Z80_INPUT_LINE_BUSRQ, busrq);
109 
110     // Z80 WAIT
111     m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, m_enabled ? CLEAR_LINE : ASSERT_LINE);
112 */
113 }
114 
115 
116 
117 //**************************************************************************
118 //  LIVE DEVICE
119 //**************************************************************************
120 
121 //-------------------------------------------------
122 //  c64_cpm_cartridge_device - constructor
123 //-------------------------------------------------
124 
c64_cpm_cartridge_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)125 c64_cpm_cartridge_device::c64_cpm_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
126 	device_t(mconfig, C64_CPM, tag, owner, clock),
127 	device_c64_expansion_card_interface(mconfig, *this),
128 	m_maincpu(*this, Z80_TAG),
129 	m_enabled(0),
130 	m_ba(1), m_reset(0)
131 {
132 }
133 
134 
135 //-------------------------------------------------
136 //  device_start - device-specific startup
137 //-------------------------------------------------
138 
device_start()139 void c64_cpm_cartridge_device::device_start()
140 {
141 	// state saving
142 	save_item(NAME(m_enabled));
143 	save_item(NAME(m_ba));
144 }
145 
146 
147 //-------------------------------------------------
148 //  device_reset - device-specific reset
149 //-------------------------------------------------
150 
device_reset()151 void c64_cpm_cartridge_device::device_reset()
152 {
153 	m_enabled = 0;
154 	m_reset = 1;
155 
156 	update_signals();
157 }
158 
159 
160 //-------------------------------------------------
161 //  c64_cd_w - cartridge data write
162 //-------------------------------------------------
163 
c64_cd_w(offs_t offset,uint8_t data,int sphi2,int ba,int roml,int romh,int io1,int io2)164 void c64_cpm_cartridge_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
165 {
166 	if (!io1)
167 	{
168 		m_enabled = !BIT(data, 0);
169 
170 		update_signals();
171 	}
172 }
173 
174 
175 //-------------------------------------------------
176 //  c64_game_r - GAME read
177 //-------------------------------------------------
178 
c64_game_r(offs_t offset,int sphi2,int ba,int rw)179 int c64_cpm_cartridge_device::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
180 {
181 	if (m_ba != ba)
182 	{
183 		m_ba = ba;
184 
185 		update_signals();
186 	}
187 
188 	return 1;
189 }
190 
191 
192 //-------------------------------------------------
193 //  dma_r -
194 //-------------------------------------------------
195 
dma_r(offs_t offset)196 uint8_t c64_cpm_cartridge_device::dma_r(offs_t offset)
197 {
198 	uint8_t data = 0xff;
199 
200 	if (m_enabled)
201 	{
202 		offs_t addr = (offset + 0x1000) & 0xffff;
203 
204 		data = m_slot->dma_cd_r(addr);
205 	}
206 
207 	return data;
208 }
209 
210 
211 //-------------------------------------------------
212 //  dma_w -
213 //-------------------------------------------------
214 
dma_w(offs_t offset,uint8_t data)215 void c64_cpm_cartridge_device::dma_w(offs_t offset, uint8_t data)
216 {
217 	if (m_enabled)
218 	{
219 		offs_t addr = (offset + 0x1000) & 0xffff;
220 
221 		m_slot->dma_cd_w(addr, data);
222 	}
223 }
224