1 // license:BSD-3-Clause 2 // copyright-holders:Fabio Priuli 3 #ifndef MAME_BUS_MEGADRIVE_MD_SLOT_H 4 #define MAME_BUS_MEGADRIVE_MD_SLOT_H 5 6 #pragma once 7 8 #include "softlist_dev.h" 9 10 /*************************************************************************** 11 TYPE DEFINITIONS 12 ***************************************************************************/ 13 14 #define MD_ADDR(a) (rom_bank_map[((a << 1) / 0x10000) & 0x3f] * 0x10000 + ((a << 1) & 0xffff))/2 15 16 /* PCB */ 17 enum 18 { 19 SEGA_STD = 0, 20 21 // Cart + Slot Expansion 22 SEGA_SK, /* Sonic & Knuckles pass-through cart */ 23 24 // Cart + SVP 25 SEGA_SVP, /* Virtua Racing */ 26 27 // Cart + NVRAM 28 SEGA_SRAM, SEGA_FRAM, 29 HARDBALL95, /* Hardball 95 uses different sram start address */ 30 XINQIG, /* Xin Qigai Wangzi uses different sram start address and has no valid header */ 31 BEGGARP, /* Beggar Prince uses different sram start address + bankswitch tricks */ 32 WUKONG, /* Legend of Wukong uses different sram start address + bankswitch trick for last 128K of ROM */ 33 STARODYS, /* Star Odyssey */ 34 35 // EEPROM 36 SEGA_EEPROM, /* Wonder Boy V / Evander Holyfield's Boxing / Greatest Heavyweights of the Ring / Sports Talk Baseball / Megaman */ 37 NBA_JAM, /* NBA Jam */ 38 NBA_JAM_ALT, /* NBA Jam */ 39 NBA_JAM_TE, /* NBA Jam TE / NFL Quarterback Club */ 40 NFL_QB_96, /* NFL Quarterback Club '96 */ 41 C_SLAM, /* College Slam / Frank Thomas Big Hurt Baseball */ 42 EA_NHLPA, /* NHLPA Hockey 93 / Rings of Power */ 43 BRIAN_LARA, /* Brian Lara Cricket 96 */ 44 PSOLAR, /* Pier Solar (STM95 EEPROM) */ 45 46 // J-Cart 47 CM_JCART, /* Pete Sampras Tennis */ 48 CODE_MASTERS, /* Micro Machines 2 / Military (J-Cart + SEPROM) */ 49 CM_MM96, /* Micro Machines 96 (J-Cart + SEPROM, diff I2C model) */ 50 51 // Various 52 SSF2, /* Super Street Fighter 2 */ 53 CM_2IN1, /* CodeMasters 2in1 : Psycho Pinball + Micro Machines */ 54 GAME_KANDUME, /* Game no Kandume Otokuyou */ 55 RADICA, /* Radica TV games.. these probably should be a separate driver since they are a separate 'console' */ 56 57 TILESMJ2, /* 16 Mahjong Tiles II */ 58 BUGSLIFE, /* A Bug's Life */ 59 CHINFIGHT3, /* Chinese Fighters 3 */ 60 ELFWOR, /* Linghuan Daoshi Super Magician */ 61 KAIJU, /* Pokemon Stadium */ 62 KOF98, /* King of Fighters '98 */ 63 KOF99, /* King of Fighters '99 */ 64 LIONK2, /* Lion King 2 */ 65 LIONK3, /* Lion King 3, Super Donkey Kong 99, Super King Kong 99 */ 66 MC_PIRATE, /* Super 19 in 1, Super 15 in 1, 12 in 1 and a few more multicarts */ 67 MJLOVER, /* Mahjong Lover */ 68 CJMJCLUB, /* Super Mahjong Club */ 69 POKEMONA, /* Pocket Monster Alt Protection */ 70 REALTEC, /* Whac a Critter/Mallet legend, Defend the Earth, Funnyworld/Ballonboy */ 71 REDCLIFF, /* Romance of the Three Kingdoms - Battle of Red Cliffs, already decoded from .mdx format */ 72 REDCL_EN, /* The encoded version... */ 73 ROCKMANX3, /* Rockman X3 */ 74 SBUBBOB, /* Super Bubble Bobble */ 75 SMB, /* Super Mario Bros. */ 76 SMB2, /* Super Mario Bros. 2 */ 77 SMW64, /* Super Mario World 64 */ 78 SMOUSE, /* Smart Mouse */ 79 SOULBLAD, /* Soul Blade */ 80 SQUIRRELK, /* Squirrel King */ 81 TEKKENSP, /* Tekken Special */ 82 TOPFIGHTER, /* Top Fighter 2000 MK VIII */ 83 84 // when loading from fullpath, we need to treat SRAM in custom way 85 SEGA_SRAM_FULLPATH, 86 SEGA_SRAM_FALLBACK 87 }; 88 89 90 // ======================> device_md_cart_interface 91 92 class device_md_cart_interface : public device_interface 93 { 94 friend class base_md_cart_slot_device; 95 public: 96 // construction/destruction 97 virtual ~device_md_cart_interface(); 98 99 // reading and writing read(offs_t offset)100 virtual uint16_t read(offs_t offset) { return 0xffff; } 101 virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) {} read_a13(offs_t offset)102 virtual uint16_t read_a13(offs_t offset) { return 0xffff; } write_a13(offs_t offset,uint16_t data)103 virtual void write_a13(offs_t offset, uint16_t data) {} read_a15(offs_t offset)104 virtual uint16_t read_a15(offs_t offset) { return 0xffff; } write_a15(offs_t offset,uint16_t data)105 virtual void write_a15(offs_t offset, uint16_t data) {} 106 read_test()107 virtual int read_test() { return 0; } // used by Virtua Racing test 108 109 // this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly write_tmss_bank(offs_t offset,uint16_t data)110 virtual void write_tmss_bank(offs_t offset, uint16_t data) { device().logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); }; 111 112 virtual void rom_alloc(size_t size, const char *tag); 113 virtual void nvram_alloc(size_t size); get_rom_base()114 virtual uint16_t* get_rom_base() { return m_rom; }; get_nvram_base()115 virtual uint16_t* get_nvram_base() { return &m_nvram[0]; }; get_rom_size()116 virtual uint32_t get_rom_size() { return m_rom_size; }; get_nvram_size()117 virtual uint32_t get_nvram_size() { return m_nvram.size()*sizeof(uint16_t); }; set_bank_to_rom(const char * banktag,uint32_t offset)118 virtual void set_bank_to_rom(const char *banktag, uint32_t offset) {}; 119 save_nvram()120 void save_nvram() { device().save_item(NAME(m_nvram)); } 121 122 void rom_map_setup(uint32_t size); 123 uint32_t get_padded_size(uint32_t size); 124 125 protected: 126 device_md_cart_interface(const machine_config &mconfig, device_t &device); 127 128 int m_nvram_start, m_nvram_end; 129 int m_nvram_active, m_nvram_readonly; 130 131 // when loading from fullpath, we create NVRAM even if not set in the header 132 // however in this case we access it only if the game turn it on 133 // the variable below is basically needed to track this... 134 int m_nvram_handlers_installed; 135 136 // internal state 137 public: // FIXME: this needs to be public because the S&K "lock-on" cart is implemented in a really dodgy way 138 uint16_t *m_rom; 139 protected: 140 uint32_t m_rom_size; 141 std::vector<uint16_t> m_nvram; 142 143 uint8_t rom_bank_map[128]; // 64K chunks of rom 144 }; 145 146 147 // ======================> base_md_cart_slot_device 148 149 class base_md_cart_slot_device : public device_t, 150 public device_image_interface, 151 public device_single_card_slot_interface<device_md_cart_interface> 152 { 153 public: 154 // construction/destruction 155 virtual ~base_md_cart_slot_device(); 156 157 // image-level overrides 158 virtual image_init_result call_load() override; 159 virtual void call_unload() override; 160 image_type()161 virtual iodevice_t image_type() const noexcept override { return IO_CARTSLOT; } is_readable()162 virtual bool is_readable() const noexcept override { return true; } is_writeable()163 virtual bool is_writeable() const noexcept override { return false; } is_creatable()164 virtual bool is_creatable() const noexcept override { return false; } must_be_loaded()165 virtual bool must_be_loaded() const noexcept override { return m_must_be_loaded; } is_reset_on_load()166 virtual bool is_reset_on_load() const noexcept override { return true; } 167 168 // slot interface overrides 169 virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; 170 get_type()171 int get_type() { return m_type; } 172 173 image_init_result load_list(); 174 image_init_result load_nonlist(); 175 static int get_cart_type(const uint8_t *ROM, uint32_t len); 176 177 void setup_custom_mappers(); 178 void setup_nvram(); set_must_be_loaded(bool _must_be_loaded)179 void set_must_be_loaded(bool _must_be_loaded) { m_must_be_loaded = _must_be_loaded; } 180 void file_logging(uint8_t *ROM, uint32_t rom_len, uint32_t nvram_len); 181 save_nvram()182 void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); } 183 184 // reading and writing 185 virtual uint16_t read(offs_t offset); 186 virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); 187 virtual uint16_t read_a13(offs_t offset); 188 virtual void write_a13(offs_t offset, uint16_t data); 189 virtual uint16_t read_a15(offs_t offset); 190 virtual void write_a15(offs_t offset, uint16_t data); write_tmss_bank(offs_t offset,uint16_t data)191 virtual void write_tmss_bank(offs_t offset, uint16_t data) { if (m_cart) m_cart->write_tmss_bank(offset, data); }; 192 read_test()193 virtual int read_test() { if (m_cart) return m_cart->read_test(); else return 0; } // used by Virtua Racing test 194 195 // TODO: this only needs to be public because megasvp copies rom into memory region, so we need to rework that code... 196 //private: 197 198 int m_type; 199 device_md_cart_interface* m_cart; 200 bool m_must_be_loaded; 201 202 protected: 203 base_md_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 204 205 // device-level overrides 206 virtual void device_start() override; 207 208 // device_image_interface implementation get_software_list_loader()209 virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); } 210 211 }; 212 213 // ======================> md_cart_slot_device 214 215 class md_cart_slot_device : public base_md_cart_slot_device 216 { 217 public: 218 // construction/destruction 219 template <typename T> md_cart_slot_device(machine_config const & mconfig,char const * tag,device_t * owner,T && opts,char const * dflt)220 md_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) 221 : md_cart_slot_device(mconfig, tag, owner, (uint32_t)0) 222 { 223 option_reset(); 224 opts(*this); 225 set_default_option(dflt); 226 set_fixed(false); 227 } 228 229 md_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); image_interface()230 virtual const char *image_interface() const noexcept override { return "megadriv_cart"; } file_extensions()231 virtual const char *file_extensions() const noexcept override { return "smd,bin,md,gen"; } 232 }; 233 234 // ======================> pico_cart_slot_device 235 236 class pico_cart_slot_device : public base_md_cart_slot_device 237 { 238 public: 239 // construction/destruction 240 template <typename T> pico_cart_slot_device(machine_config const & mconfig,char const * tag,device_t * owner,T && opts,char const * dflt)241 pico_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) 242 : pico_cart_slot_device(mconfig, tag, owner, (uint32_t)0) 243 { 244 option_reset(); 245 opts(*this); 246 set_default_option(dflt); 247 set_fixed(false); 248 } 249 pico_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); image_interface()250 virtual const char *image_interface() const noexcept override { return "pico_cart"; } file_extensions()251 virtual const char *file_extensions() const noexcept override { return "bin,md"; } 252 }; 253 254 // ======================> copera_cart_slot_device 255 256 class copera_cart_slot_device : public base_md_cart_slot_device 257 { 258 public: 259 // construction/destruction 260 template <typename T> copera_cart_slot_device(machine_config const & mconfig,char const * tag,device_t * owner,T && opts,char const * dflt)261 copera_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) 262 : copera_cart_slot_device(mconfig, tag, owner, (uint32_t)0) 263 { 264 option_reset(); 265 opts(*this); 266 set_default_option(dflt); 267 set_fixed(false); 268 } 269 copera_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); image_interface()270 virtual const char *image_interface() const noexcept override { return "copera_cart"; } file_extensions()271 virtual const char *file_extensions() const noexcept override { return "bin,md"; } 272 }; 273 274 275 // device type definition 276 DECLARE_DEVICE_TYPE(MD_CART_SLOT, md_cart_slot_device) 277 DECLARE_DEVICE_TYPE(PICO_CART_SLOT, pico_cart_slot_device) 278 DECLARE_DEVICE_TYPE(COPERA_CART_SLOT, copera_cart_slot_device) 279 280 281 /*************************************************************************** 282 DEVICE CONFIGURATION MACROS 283 ***************************************************************************/ 284 285 #define MDSLOT_ROM_REGION_TAG ":cart:rom" 286 287 #endif // MAME_BUS_MEGADRIVE_MD_SLOT_H 288