1 // license:BSD-3-Clause 2 // copyright-holders:Miodrag Milanovic 3 #pragma once 4 5 #ifndef __EMU_H__ 6 #error Dont include this file directly; include emu.h instead. 7 #endif 8 9 #ifndef MAME_EMU_DISLOT_H 10 #define MAME_EMU_DISLOT_H 11 12 //************************************************************************** 13 // TYPE DEFINITIONS 14 //************************************************************************** 15 16 class get_default_card_software_hook 17 { 18 // goofy "hook" to pass to device_slot_interface::get_default_card_software 19 public: 20 get_default_card_software_hook(const std::string &path, std::function<bool(util::core_file &, std::string&)> &&get_hashfile_extrainfo); 21 22 // accesses the image file to be scrutinized by get_default_card_software(); is 23 // nullptr in the case of images loaded by software list image_file()24 util::core_file::ptr &image_file() { return m_image_file; } 25 26 // checks to see if image is of the specified "file type" (in practice, file extension) is_filetype(const char * candidate_filetype)27 bool is_filetype(const char *candidate_filetype) const { return !core_stricmp(m_file_type.c_str(), candidate_filetype); } 28 29 // extra info from hashfile 30 bool hashfile_extrainfo(std::string &extrainfo); 31 32 private: 33 util::core_file::ptr m_image_file; 34 std::string m_file_type; 35 std::function<bool(util::core_file &, std::string&)> m_get_hashfile_extrainfo; 36 bool m_called_get_hashfile_extrainfo; 37 bool m_has_hash_extrainfo; 38 std::string m_hash_extrainfo; 39 }; 40 41 42 /// \brief Base class for configurable slot devices 43 class device_slot_interface : public device_interface 44 { 45 public: 46 class slot_option 47 { 48 public: 49 slot_option(char const *name, device_type const &devtype, bool selectable); 50 name()51 char const *name() const { return m_name; } devtype()52 device_type const &devtype() const { return m_devtype; } selectable()53 bool selectable() const { return m_selectable; } default_bios()54 char const *default_bios() const { return m_default_bios; } machine_config()55 std::function<void (device_t *)> const &machine_config() const { return m_machine_config; } input_device_defaults()56 input_device_default const *input_device_defaults() const { return m_input_device_defaults; } clock()57 u32 clock() const { return m_clock; } 58 default_bios(char const * default_bios)59 slot_option &default_bios(char const *default_bios) { m_default_bios = default_bios; return *this; } machine_config(Object && cb)60 template <typename Object> slot_option &machine_config(Object &&cb) { m_machine_config = std::forward<Object>(cb); return *this; } input_device_defaults(input_device_default const * dev_inp_def)61 slot_option &input_device_defaults(input_device_default const *dev_inp_def) { m_input_device_defaults = dev_inp_def; return *this; } clock(u32 clock)62 slot_option &clock(u32 clock) { m_clock = clock; return *this; } clock(XTAL clock)63 slot_option &clock(XTAL clock) { clock.validate(std::string("Configuring slot option ") + m_name); m_clock = clock.value(); return *this; } 64 65 private: 66 // internal state 67 char const *const m_name; 68 device_type const m_devtype; 69 bool const m_selectable; 70 char const *m_default_bios; 71 std::function<void (device_t *)> m_machine_config; 72 input_device_default const *m_input_device_defaults; 73 u32 m_clock; 74 }; 75 76 virtual ~device_slot_interface(); 77 78 /// \brief Set whether slot is fixed 79 /// 80 /// Allows a slot to be configured as fixed. Fixed slots can only 81 /// be configured programmatically. Options for fixed slots are not 82 /// user-selectable. By default, slots are not fixed. 83 /// \param [in] fixed True to mark the slot as fixed, or false to 84 /// mark it user-configurable. 85 /// \sa fixed set_fixed(bool fixed)86 void set_fixed(bool fixed) { m_fixed = fixed; } 87 88 /// \brief Set the default option 89 /// 90 /// Set the default option the slot. The corresponding card device 91 /// will be loaded if no other option is selected by the user or 92 /// programmatically. 93 /// \param [in] option The name of the default option. This must be 94 /// correspond to an option added using #option_add or 95 /// #option_add_internal, or be nullptr to not load any card 96 /// device by default. The string is not copied and must remain 97 /// valid for the lifetime of the device (or until another default 98 /// option is configured). 99 /// \sa default_option set_default_option(const char * option)100 void set_default_option(const char *option) { m_default_option = option; } 101 102 /// \brief Clear options 103 /// 104 /// This removes all previously added options. option_reset()105 void option_reset() { m_options.clear(); } 106 107 /// \brief Add a user-selectable option 108 /// 109 /// Adds an option that may be selected by the user via the command 110 /// line or other configureation methods. 111 /// \param [in] option The name used to select the option. This 112 /// will also be used as the tag when instantiating the card. It 113 /// must be a valid device tag, and should be terse but 114 /// descriptive. The string is copied when the option is added. 115 /// \param [in] devtype Device type of the option. The device type 116 /// description is used in the user interface. 117 /// \return A reference to the added option for additional 118 /// configuration. 119 slot_option &option_add(char const *option, const device_type &devtype); 120 121 /// \brief Add an internal option 122 /// 123 /// Adds an option that may only be selected programmatically. This 124 /// is most often used for options used for loading software. 125 /// \param [in] option The name used to select the option. This 126 /// will also be used as the tag when instantiating the card. It 127 /// must be a valid device tag. The string is copied when the 128 /// option is added. 129 /// \param [in] devtype Device type of the option. The device type 130 /// description is used in the user interface. 131 /// \return A reference to the added option for additional 132 /// configuration. 133 slot_option &option_add_internal(const char *option, const device_type &devtype); 134 set_option_default_bios(const char * option,const char * default_bios)135 void set_option_default_bios(const char *option, const char *default_bios) { config_option(option)->default_bios(default_bios); } set_option_machine_config(const char * option,T && machine_config)136 template <typename T> void set_option_machine_config(const char *option, T &&machine_config) { config_option(option)->machine_config(std::forward<T>(machine_config)); } set_option_device_input_defaults(const char * option,const input_device_default * default_input)137 void set_option_device_input_defaults(const char *option, const input_device_default *default_input) { config_option(option)->input_device_defaults(default_input); } 138 139 /// \brief Returns whether the slot is fixed 140 /// 141 /// Fixed slots can only be configured programmatically. Slots are 142 /// not fixed by default. 143 /// \return True if the slot is fixed, or false if it is 144 /// user-configurable. 145 /// \sa set_fixed fixed()146 bool fixed() const { return m_fixed; } 147 148 /// \brief Returns true if the slot has user-selectable options 149 /// 150 /// Returns true if the slot is not marked as fixed and has at least 151 /// one user-selectable option (added using #option_add rather than 152 /// #option_add_internal). Returns false if the slot is marked as 153 /// fixed, all options are internal, or there are no options. 154 /// \return True if the slot has user-selectable options, or false 155 /// otherwise. 156 bool has_selectable_options() const; 157 default_option()158 const char *default_option() const { return m_default_option; } option_list()159 const std::unordered_map<std::string, std::unique_ptr<slot_option>> &option_list() const { return m_options; } 160 const slot_option *option(const char *name) const; get_default_card_software(get_default_card_software_hook & hook)161 virtual std::string get_default_card_software(get_default_card_software_hook &hook) const { return std::string(); } get_card_device()162 device_t *get_card_device() const { return m_card_device; } set_card_device(device_t * dev)163 void set_card_device(device_t *dev) { m_card_device = dev; } slot_name()164 const char *slot_name() const { return device().tag() + 1; } option_set(const char * tag,const device_type & devtype)165 slot_option &option_set(const char *tag, const device_type &devtype) { m_default_option = tag; m_fixed = true; return option_add_internal(tag, devtype); } 166 167 protected: 168 device_slot_interface(machine_config const &mconfig, device_t &device); 169 virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD; set_default_clock(u32 clock)170 void set_default_clock(u32 clock) { m_default_clock = clock; } 171 172 private: 173 // internal state 174 std::unordered_map<std::string, std::unique_ptr<slot_option>> m_options; 175 u32 m_default_clock; 176 char const *m_default_option; 177 bool m_fixed; 178 device_t *m_card_device; 179 180 slot_option *config_option(char const *option); 181 }; 182 183 184 /// \brief Base class for slots that accept a single card interface 185 /// 186 /// Performs basic validity checks to ensure the configured card (if 187 /// any) implements the required interface. 188 template <typename Card> 189 class device_single_card_slot_interface : public device_slot_interface 190 { 191 public: get_card_device()192 Card *get_card_device() const { return dynamic_cast<Card *>(device_slot_interface::get_card_device()); } 193 194 protected: device_single_card_slot_interface(machine_config const & mconfig,device_t & device)195 device_single_card_slot_interface(machine_config const &mconfig, device_t &device) : 196 device_slot_interface(mconfig, device) 197 { 198 } 199 interface_validity_check(validity_checker & valid)200 virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD 201 { 202 device_slot_interface::interface_validity_check(valid); 203 device_t *const card(device_slot_interface::get_card_device()); 204 if (card && !dynamic_cast<Card *>(card)) 205 { 206 osd_printf_error( 207 "Card device %s (%s) does not implement %s\n", 208 card->tag(), 209 card->name(), 210 typeid(Card).name()); 211 } 212 } 213 interface_pre_start()214 virtual void interface_pre_start() override ATTR_COLD 215 { 216 device_slot_interface::interface_pre_start(); 217 device_t *const card(device_slot_interface::get_card_device()); 218 if (card && !dynamic_cast<Card *>(card)) 219 { 220 throw emu_fatalerror( 221 "slot '%s' card device %s (%s) does not implement %s\n", 222 device().tag(), 223 card->tag(), 224 card->name(), 225 typeid(Card).name()); 226 } 227 } 228 }; 229 230 typedef device_interface_iterator<device_slot_interface> slot_interface_iterator; 231 232 #endif // MAME_EMU_DISLOT_H 233