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