1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods
3 /*********************************************************************
4
5 cococart.h
6
7 CoCo/Dragon cartridge management
8
9 *********************************************************************/
10
11 #ifndef MAME_BUS_COCO_COCOCART_H
12 #define MAME_BUS_COCO_COCOCART_H
13
14 #pragma once
15
16 #include "softlist_dev.h"
17
18
19 /***************************************************************************
20 TYPE DEFINITIONS
21 ***************************************************************************/
22
23 // ======================> cococart_base_update_delegate
24
25 // direct region update handler
26 typedef delegate<void (u8 *)> cococart_base_update_delegate;
27
28
29 // ======================> cococart_slot_device
30 class device_cococart_interface;
31
32 class cococart_slot_device final : public device_t,
33 public device_single_card_slot_interface<device_cococart_interface>,
34 public device_image_interface
35 {
36 public:
37 // output lines on the CoCo cartridge slot
38 enum class line
39 {
40 CART, // connects to PIA1 CB1
41 NMI, // connects to NMI line on CPU
42 HALT, // connects to HALT line on CPU
43 SOUND_ENABLE // sound enable
44 };
45
46 // since we have a special value "Q" - we have to use a special enum here
47 enum class line_value
48 {
49 CLEAR,
50 ASSERT,
51 Q
52 };
53
54 // construction/destruction
55 template <typename T>
cococart_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock,T && opts,const char * dflt)56 cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
57 : cococart_slot_device(mconfig, tag, owner, clock)
58 {
59 option_reset();
60 opts(*this);
61 set_default_option(dflt);
62 set_fixed(false);
63 }
64 cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
65
cart_callback()66 auto cart_callback() { return m_cart_callback.bind(); }
nmi_callback()67 auto nmi_callback() { return m_nmi_callback.bind(); }
halt_callback()68 auto halt_callback() { return m_halt_callback.bind(); }
69
70 // device-level overrides
71 virtual void device_start() override;
72 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
73
74 // image-level overrides
75 virtual image_init_result call_load() override;
get_software_list_loader()76 virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
77
image_type()78 virtual iodevice_t image_type() const noexcept override { return IO_CARTSLOT; }
79
is_readable()80 virtual bool is_readable() const noexcept override { return true; }
is_writeable()81 virtual bool is_writeable() const noexcept override { return false; }
is_creatable()82 virtual bool is_creatable() const noexcept override { return false; }
must_be_loaded()83 virtual bool must_be_loaded() const noexcept override { return false; }
is_reset_on_load()84 virtual bool is_reset_on_load() const noexcept override { return true; }
image_interface()85 virtual const char *image_interface() const noexcept override { return "coco_cart"; }
file_extensions()86 virtual const char *file_extensions() const noexcept override { return "ccc,rom"; }
87
88 // slot interface overrides
89 virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
90
91 // reading and writing to $C000-$FFEF
92 u8 cts_read(offs_t offset);
93 void cts_write(offs_t offset, u8 data);
94
95 // reading and writing to $FF40-$FF5F
96 u8 scs_read(offs_t offset);
97 void scs_write(offs_t offset, u8 data);
98
99 // manipulation of cartridge lines
100 void set_line_value(line line, line_value value);
101 void set_line_delay(line line, int cycles);
102 line_value get_line_value(line line) const;
103
104 // hack to support twiddling the Q line
105 void twiddle_q_lines();
106
107 // cart base
108 u8 *get_cart_base();
109 u32 get_cart_size();
110 void set_cart_base_update(cococart_base_update_delegate update);
111
112 private:
113 // TIMER_POOL: Must be power of two
114 static constexpr int TIMER_POOL = 2;
115
116 struct coco_cartridge_line
117 {
118 emu_timer *timer[TIMER_POOL];
119 int timer_index;
120 int delay;
121 line_value value;
122 int line;
123 int q_count;
124 devcb_write_line * callback;
125 };
126
127 // configuration
128 coco_cartridge_line m_cart_line;
129 coco_cartridge_line m_nmi_line;
130 coco_cartridge_line m_halt_line;
131 public:
132 devcb_write_line m_cart_callback;
133 devcb_write_line m_nmi_callback;
134 devcb_write_line m_halt_callback;
135 private:
136 // cartridge
137 device_cococart_interface *m_cart;
138
139 // methods
140 void set_line(const char *line_name, coco_cartridge_line &line, line_value value);
141 void set_line_timer(coco_cartridge_line &line, line_value value);
142 void twiddle_line_if_q(coco_cartridge_line &line);
143 static const char *line_value_string(line_value value);
144 };
145
146 // device type definition
DECLARE_DEVICE_TYPE(COCOCART_SLOT,cococart_slot_device)147 DECLARE_DEVICE_TYPE(COCOCART_SLOT, cococart_slot_device)
148
149
150 // ======================> device_cococart_host_interface
151
152 // this is implemented by the CoCo root device itself and the Multi-Pak interface
153 class device_cococart_host_interface
154 {
155 public:
156 virtual address_space &cartridge_space() = 0;
157 };
158
159
160 // ======================> device_cococart_interface
161
162 class device_cococart_interface : public device_interface
163 {
164 public:
165 // construction/destruction
166 virtual ~device_cococart_interface();
167
168 virtual u8 cts_read(offs_t offset);
169 virtual void cts_write(offs_t offset, u8 data);
170 virtual u8 scs_read(offs_t offset);
171 virtual void scs_write(offs_t offset, u8 data);
172 virtual void set_sound_enable(bool sound_enable);
173
174 virtual u8 *get_cart_base();
175 virtual u32 get_cart_size();
176 void set_cart_base_update(cococart_base_update_delegate update);
177 virtual memory_region *get_cart_memregion();
178
179 protected:
180 virtual void interface_config_complete() override;
181 virtual void interface_pre_start() override;
182
183 device_cococart_interface(const machine_config &mconfig, device_t &device);
184
185 void cart_base_changed(void);
186
187 // accessors for containers
owning_slot()188 cococart_slot_device &owning_slot() { assert(m_owning_slot); return *m_owning_slot; }
host()189 device_cococart_host_interface &host() { assert(m_host); return *m_host; }
190
191 // CoCo cartridges can read directly from the address bus. This is used by a number of
192 // cartridges (e.g. - Orch-90, Multi-Pak interface) for their control registers, independently
193 // of the SCS or CTS lines
194 address_space &cartridge_space();
195 template <typename R>
install_read_handler(u16 addrstart,u16 addrend,R && rhandler)196 void install_read_handler(u16 addrstart, u16 addrend, R &&rhandler)
197 {
198 address_space &space(cartridge_space());
199 space.install_read_handler(addrstart, addrend, std::forward<R>(rhandler));
200 }
201 template <typename W>
install_write_handler(u16 addrstart,u16 addrend,W && whandler)202 void install_write_handler(u16 addrstart, u16 addrend, W &&whandler)
203 {
204 address_space &space(cartridge_space());
205 space.install_write_handler(addrstart, addrend, std::forward<W>(whandler));
206 }
207 template <typename R, typename W>
install_readwrite_handler(u16 addrstart,u16 addrend,R && rhandler,W && whandler)208 void install_readwrite_handler(u16 addrstart, u16 addrend, R &&rhandler, W &&whandler)
209 {
210 address_space &space(cartridge_space());
211 space.install_read_handler(addrstart, addrend, std::forward<R>(rhandler));
212 space.install_write_handler(addrstart, addrend, std::forward<W>(whandler));
213 }
214
215 // setting line values
216 void set_line_value(cococart_slot_device::line line, cococart_slot_device::line_value value);
set_line_value(cococart_slot_device::line line,bool value)217 void set_line_value(cococart_slot_device::line line, bool value) { set_line_value(line, value ? cococart_slot_device::line_value::ASSERT : cococart_slot_device::line_value::CLEAR); }
218
219 typedef cococart_slot_device::line line;
220 typedef cococart_slot_device::line_value line_value;
221
222 private:
223 cococart_base_update_delegate m_update;
224 cococart_slot_device * m_owning_slot;
225 device_cococart_host_interface * m_host;
226 };
227
228 #endif // MAME_BUS_COCO_COCOCART_H
229