trunk/src/mame/drivers/wmg.c
| r0 | r21558 | |
| 1 | /************************************************************** |
| 2 | * |
| 3 | * Williams Multigame (6-game version) driver, by Robbbert, |
| 4 | * 2007/2008. |
| 5 | * |
| 6 | * Thanks to assistance from Peale. |
| 7 | * |
| 8 | **************************************************************/ |
| 9 | |
| 10 | /********************************************************************************************************* |
| 11 | |
| 12 | Game numbers: |
| 13 | 0 = The Menu |
| 14 | 1 = robotron |
| 15 | 2 = joustr |
| 16 | 3 = stargate |
| 17 | 4 = bubbles |
| 18 | 5 = defender |
| 19 | 6 = splat |
| 20 | 7 = spare position (duplicate of bubbles) |
| 21 | |
| 22 | Some documents can be downloaded from http://www.multigame.com/williams.html |
| 23 | |
| 24 | Hardware features: |
| 25 | |
| 26 | There are 3 boards - the CPU board, the Sound board, and the Widget board. |
| 27 | |
| 28 | - The Sound board only has the new sound ROM. The sounds are selected via the bank number from C400. |
| 29 | |
| 30 | - The Widget board has the joysticks and buttons connected to it. These are steered to the correct |
| 31 | inputs by a custom-programmed large square XC9572 84-pin chip. This is also controlled by |
| 32 | the bank number from C400. |
| 33 | |
| 34 | - The CPU board has 3 components: |
| 35 | -- A DS1225AD 8k x 8 NVRAM. Like the other chips, it is banked, giving each game its own save area. |
| 36 | -- The new cpu ROM, containing code for the 6 games and the menu. Splat and Defender are slightly |
| 37 | modified to work properly on the Robotron hardware. Splat is converted from SC2 to SC1; while |
| 38 | Defender has the I/O devices remapped to suit the hardware. |
| 39 | -- A square custom-programmed 44-pin chip (number rubbed off), which performs all the bank-switching, |
| 40 | the special changes for Defender, the lock feature, and the sound cpu reset. It is not known |
| 41 | which square chip detects and acts on the P1+P2 reset. |
| 42 | |
| 43 | |
| 44 | Setting it up: |
| 45 | |
| 46 | When you first start WMG, you need to initialise the NVRAM properly. Do this by starting wmg, |
| 47 | pressing 1 to cycle through the games list, pressing 2 to run the game. When it says "FACTORY |
| 48 | SETTINGS RESTORED", press F3 to return to the menu. Repeat this procedure for all 6 games. |
| 49 | After that, quit wmg, then restart. On the Setup menu you can personalise the settings with |
| 50 | the 1 and 2 keys. The inputs default to be the same as on the original hardware. You may |
| 51 | change any input individually for each game. Note that the WMG hardware has the Flap and |
| 52 | Inviso buttons wired together. JOUST can be played by 2 players at the same time, player 1 |
| 53 | uses the left joystick and the Flap button, while player 2 uses the right joystick and the |
| 54 | Fire button. SPLAT would normally require 4 joysticks, but since the WMG only has 2, it is |
| 55 | limited to a one-player game. Cocktail mode is not supported, WMG must be played on an upright |
| 56 | only. After playing a game, returning to the menu will return to the place you left from. You |
| 57 | can force a return to the Setup by holding F1 and pressing F3. You can also clear out the |
| 58 | menu's NVRAM (not the game's NVRAM), by holding down L and pressing F3. |
| 59 | |
| 60 | ToDo: |
| 61 | |
| 62 | The game works perfectly. However the code is a bit of a bodge-job, originally for MisfitMAME 0.127.E, |
| 63 | then updated for HBMAME 0.148u1. It could do with a cleanup, and removal of the various hacks. Support |
| 64 | of save-state is also needed. |
| 65 | |
| 66 | |
| 67 | ***********************************************************************************************************/ |
| 68 | |
| 69 | #include "includes/williams.h" |
| 70 | #include "cpu/m6800/m6800.h" |
| 71 | #include "machine/nvram.h" |
| 72 | |
| 73 | #define MASTER_CLOCK (XTAL_12MHz) |
| 74 | #define SOUND_CLOCK (XTAL_3_579545MHz) |
| 75 | |
| 76 | class wmg_state : public williams_state |
| 77 | { |
| 78 | public: |
| 79 | wmg_state(const machine_config &mconfig, device_type type, const char *tag) |
| 80 | : williams_state(mconfig, type, tag) |
| 81 | , m_maincpu(*this, "maincpu") |
| 82 | , m_soundcpu(*this, "soundcpu") |
| 83 | , m_p_ram(*this, "nvram") |
| 84 | { } |
| 85 | |
| 86 | DECLARE_WRITE8_MEMBER(wmg_rombank_w); |
| 87 | DECLARE_MACHINE_RESET(wmg); |
| 88 | DECLARE_DRIVER_INIT(wmg); |
| 89 | UINT8 m_wmg_bank; |
| 90 | UINT8 m_wmg_def_bank; |
| 91 | UINT8 m_wmg_port_select; |
| 92 | UINT8 m_wmg_vram_bank; |
| 93 | DECLARE_READ8_MEMBER(wmg_nvram_r); |
| 94 | DECLARE_WRITE8_MEMBER(wmg_nvram_w); |
| 95 | DECLARE_READ8_MEMBER(wmg_pia_0_r); |
| 96 | DECLARE_WRITE8_MEMBER(wmg_def_rombank_w); |
| 97 | DECLARE_WRITE8_MEMBER(wmg_port_select_w); |
| 98 | DECLARE_WRITE8_MEMBER(wmg_sound_reset_w); |
| 99 | DECLARE_WRITE8_MEMBER(wmg_vram_select_w); |
| 100 | DECLARE_CUSTOM_INPUT_MEMBER(wmg_mux_r); |
| 101 | void wmg_def_install_io_space(address_space &space); |
| 102 | required_device<cpu_device> m_maincpu; |
| 103 | required_device<cpu_device> m_soundcpu; |
| 104 | required_shared_ptr<UINT8> m_p_ram; |
| 105 | }; |
| 106 | |
| 107 | |
| 108 | /************************************* |
| 109 | * |
| 110 | * NVRAM (8k x 8), banked |
| 111 | * |
| 112 | *************************************/ |
| 113 | READ8_MEMBER( wmg_state::wmg_nvram_r ) |
| 114 | { |
| 115 | return m_p_ram[offset+(m_wmg_bank<<10)]; |
| 116 | } |
| 117 | |
| 118 | WRITE8_MEMBER( wmg_state::wmg_nvram_w ) |
| 119 | { |
| 120 | m_p_ram[offset+(m_wmg_bank<<10)] = data; |
| 121 | } |
| 122 | |
| 123 | /************************************* |
| 124 | * |
| 125 | * Bankswitching |
| 126 | * |
| 127 | *************************************/ |
| 128 | |
| 129 | /* switches the banks around when given a game number. |
| 130 | The hardware has a lock feature, so that once a bank is selected, the next choice must be the menu */ |
| 131 | |
| 132 | WRITE8_MEMBER( wmg_state::wmg_rombank_w ) |
| 133 | { |
| 134 | address_space &space1 = m_maincpu->space(AS_PROGRAM); |
| 135 | UINT8 *RAM = memregion("maincpu")->base(); |
| 136 | |
| 137 | data &= 7; |
| 138 | |
| 139 | if ((!data) || (!m_wmg_bank)) // we must be going to/from the menu |
| 140 | { |
| 141 | m_wmg_bank = data; |
| 142 | wmg_def_rombank_w( space1, 0, 0); |
| 143 | memcpy( &RAM[0x10000], &RAM[(data << 16) + 0x20000], 0x9000 ); /* Gfx etc */ |
| 144 | membank("bank5")->set_entry(data); /* Code */ |
| 145 | membank("bank6")->set_entry(data); /* Sound */ |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | WRITE8_MEMBER( wmg_state::wmg_sound_reset_w ) |
| 150 | { |
| 151 | /* This resets the sound card when bit 0 is low */ |
| 152 | if (!BIT(data, 0)) m_soundcpu->reset(); |
| 153 | } |
| 154 | |
| 155 | WRITE8_MEMBER( wmg_state::wmg_vram_select_w ) |
| 156 | { |
| 157 | /* VRAM/ROM banking from bit 0 */ |
| 158 | m_wmg_vram_bank = BIT(data, 0); |
| 159 | membank("bank1")->set_entry(m_wmg_vram_bank); |
| 160 | |
| 161 | /* cocktail flip from bit 1 */ |
| 162 | m_cocktail = BIT(data, 1); |
| 163 | } |
| 164 | |
| 165 | void wmg_state::wmg_def_install_io_space(address_space &space) |
| 166 | { |
| 167 | williams_state *state = space.machine().driver_data<williams_state>(); |
| 168 | pia6821_device *pia_0 = space.machine().device<pia6821_device>("pia_0"); |
| 169 | pia6821_device *pia_1 = space.machine().device<pia6821_device>("pia_1"); |
| 170 | |
| 171 | /* this routine dynamically installs the memory mapped above from c000-cfff */ |
| 172 | space.install_write_bank (0xc000, 0xc00f, 0, 0, "bank4"); |
| 173 | space.install_write_handler (0xc010, 0xc01f, write8_delegate(FUNC(williams_state::defender_video_control_w),this)); |
| 174 | space.install_write_handler (0xc400, 0xc400, write8_delegate(FUNC(wmg_state::wmg_rombank_w),this)); |
| 175 | space.install_write_handler (0xc401, 0xc401, write8_delegate(FUNC(wmg_state::wmg_sound_reset_w),this)); |
| 176 | space.install_readwrite_handler(0xc804, 0xc807, read8_delegate(FUNC(wmg_state::wmg_pia_0_r),this), write8_delegate(FUNC(pia6821_device::write), pia_0)); |
| 177 | space.install_readwrite_handler(0xc80c, 0xc80f, read8_delegate(FUNC(pia6821_device::read), pia_1), write8_delegate(FUNC(pia6821_device::write), pia_1)); |
| 178 | space.install_write_handler (0xc900, 0xc9ff, write8_delegate(FUNC(wmg_state::wmg_vram_select_w),this)); |
| 179 | space.install_write_handler (0xca00, 0xca07, write8_delegate(FUNC(williams_state::williams_blitter_w),this)); |
| 180 | space.install_write_handler (0xcbff, 0xcbff, write8_delegate(FUNC(williams_state::williams_watchdog_reset_w),this)); |
| 181 | space.install_read_handler (0xcb00, 0xcbff, read8_delegate(FUNC(williams_state::williams_video_counter_r),this)); |
| 182 | space.install_readwrite_handler(0xcc00, 0xcfff, read8_delegate(FUNC(wmg_state::wmg_nvram_r), this), write8_delegate(FUNC(wmg_state::wmg_nvram_w),this)); |
| 183 | membank("bank4")->set_base(state->m_generic_paletteram_8); |
| 184 | } |
| 185 | |
| 186 | WRITE8_MEMBER( wmg_state::wmg_def_rombank_w ) |
| 187 | { |
| 188 | address_space &space1 = m_maincpu->space(AS_PROGRAM); |
| 189 | data &= 15; |
| 190 | if ((m_wmg_def_bank != data) && (m_wmg_bank == 5) && (data)) |
| 191 | { |
| 192 | m_wmg_def_bank = data; |
| 193 | |
| 194 | /* set bank address */ |
| 195 | switch (data) |
| 196 | { |
| 197 | /* pages 1,2,3,7 map to ROM banks */ |
| 198 | case 1: |
| 199 | case 2: |
| 200 | case 3: |
| 201 | space1.install_read_bank(0xc000, 0xcfff, 0, 0, "bank7"); |
| 202 | space1.unmap_write(0xc000, 0xcfff); |
| 203 | membank("bank7")->set_entry(data); |
| 204 | break; |
| 205 | |
| 206 | case 7: |
| 207 | space1.install_read_bank(0xc000, 0xcfff, 0, 0, "bank7"); |
| 208 | space1.unmap_write(0xc000, 0xcfff); |
| 209 | membank("bank7")->set_entry(4); |
| 210 | break; |
| 211 | |
| 212 | default: |
| 213 | printf("Unknown bank %X selected\n",data); |
| 214 | } |
| 215 | } |
| 216 | else |
| 217 | if ((m_wmg_def_bank != data) && (!data)) |
| 218 | { |
| 219 | /* page 0 is I/O space */ |
| 220 | m_wmg_def_bank = data; |
| 221 | wmg_def_install_io_space(space1); |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | |
| 226 | MACHINE_RESET_MEMBER( wmg_state, wmg ) |
| 227 | { |
| 228 | address_space &space1 = m_maincpu->space(AS_PROGRAM); |
| 229 | m_wmg_bank=0; |
| 230 | m_wmg_def_bank=8; |
| 231 | m_wmg_port_select=0; |
| 232 | m_wmg_vram_bank=0; |
| 233 | wmg_rombank_w( space1, 0, 0); |
| 234 | MACHINE_RESET_CALL_MEMBER(williams_common); |
| 235 | m_maincpu->reset(); |
| 236 | } |
| 237 | |
| 238 | /************************************* |
| 239 | * |
| 240 | * Input selector code |
| 241 | * |
| 242 | *************************************/ |
| 243 | |
| 244 | WRITE8_MEMBER( wmg_state::wmg_port_select_w ) |
| 245 | { |
| 246 | m_wmg_port_select = data | (m_wmg_bank << 1); |
| 247 | } |
| 248 | |
| 249 | CUSTOM_INPUT_MEMBER(wmg_state::wmg_mux_r) |
| 250 | { |
| 251 | UINT8 i; |
| 252 | const char *tag = (const char *)param; |
| 253 | |
| 254 | if (m_wmg_port_select) |
| 255 | for (i = 0; i < m_wmg_port_select; i++) |
| 256 | tag += strlen(tag) + 1; |
| 257 | |
| 258 | return ioport(tag)->read(); |
| 259 | } |
| 260 | |
| 261 | static const pia6821_interface wmg_muxed_pia_0_intf = |
| 262 | { |
| 263 | /*inputs : A/B,CA/B1,CA/B2 */ DEVCB_INPUT_PORT("IN0"), DEVCB_INPUT_PORT("IN1"), DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, |
| 264 | /*outputs: A/B,CA/B2 */ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_DRIVER_MEMBER(wmg_state, wmg_port_select_w), |
| 265 | /*irqs : A/B */ DEVCB_NULL, DEVCB_NULL |
| 266 | }; |
| 267 | |
| 268 | READ8_MEMBER( wmg_state::wmg_pia_0_r ) |
| 269 | { |
| 270 | /* if player presses P1 and P2 in a game, return to the menu. |
| 271 | Since there is no code in rom to handle this, it must be a hardware feature |
| 272 | which probably just resets the cpu. */ |
| 273 | |
| 274 | address_space &space1 = m_maincpu->space(AS_PROGRAM); |
| 275 | pia6821_device *pia_0 = space1.machine().device<pia6821_device>("pia_0"); |
| 276 | UINT8 data = pia_0->read(space1, offset); |
| 277 | |
| 278 | if ((m_wmg_bank) && (!offset) && ((data & 0x30) == 0x30)) // P1 and P2 pressed |
| 279 | { |
| 280 | wmg_rombank_w( space1, 0, 0); |
| 281 | m_maincpu->reset(); |
| 282 | } |
| 283 | |
| 284 | return data; |
| 285 | } |
| 286 | |
| 287 | /************************************* |
| 288 | * |
| 289 | * Address Map |
| 290 | * |
| 291 | *************************************/ |
| 292 | static ADDRESS_MAP_START( wmg_cpu1, AS_PROGRAM, 8, wmg_state ) |
| 293 | AM_RANGE(0x0000, 0x8fff) AM_READ_BANK("bank1") AM_WRITEONLY AM_SHARE("videoram") |
| 294 | AM_RANGE(0x9000, 0xbfff) AM_RAM |
| 295 | AM_RANGE(0xc000, 0xcfff) AM_ROMBANK("bank7") |
| 296 | AM_RANGE(0xd000, 0xffff) AM_ROMBANK("bank5") |
| 297 | AM_RANGE(0xd000, 0xd000) AM_WRITE(wmg_def_rombank_w) |
| 298 | ADDRESS_MAP_END |
| 299 | |
| 300 | static ADDRESS_MAP_START( wmg_cpu2, AS_PROGRAM, 8, wmg_state ) |
| 301 | AM_RANGE(0x0000, 0x007f) AM_RAM /* internal RAM */ |
| 302 | AM_RANGE(0x0080, 0x00ff) AM_RAM /* MC6810 RAM */ |
| 303 | AM_RANGE(0x0400, 0x0403) AM_MIRROR(0x8000) AM_DEVREADWRITE("pia_2", pia6821_device, read, write) |
| 304 | /* These next 2 are actually banked in CPU 1, but its not something Mame can handle very well. Placed here instead. */ |
| 305 | AM_RANGE(0xc000, 0xc00f) AM_MIRROR(0x03f0) AM_WRITEONLY AM_SHARE("paletteram") |
| 306 | AM_RANGE(0xd000, 0xefff) AM_RAM AM_SHARE("nvram") |
| 307 | AM_RANGE(0xf000, 0xffff) AM_ROMBANK("bank6") |
| 308 | ADDRESS_MAP_END |
| 309 | |
| 310 | /****************************************** |
| 311 | * |
| 312 | * Inputs, banked. One set for each game. |
| 313 | * |
| 314 | ******************************************/ |
| 315 | static INPUT_PORTS_START( wmg ) |
| 316 | PORT_START("IN0") |
| 317 | PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, wmg_state, wmg_mux_r, "IN000\0IN000\0IN100\0IN100\0IN202\0IN201\0IN300\0IN300\0IN400\0IN400\0IN500\0IN500\0IN602\0IN601\0IN400\0IN400") |
| 318 | |
| 319 | PORT_START("IN1") |
| 320 | PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, wmg_state, wmg_mux_r, "IN010\0IN010\0IN110\0IN110\0IN210\0IN210\0IN310\0IN310\0IN410\0IN410\0IN510\0IN510\0IN612\0IN611\0IN410\0IN410") |
| 321 | |
| 322 | PORT_START("IN2") |
| 323 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Auto Up") PORT_CODE(KEYCODE_F1) |
| 324 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Advance") PORT_CODE(KEYCODE_F2) |
| 325 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN3 ) |
| 326 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("High Score Reset") PORT_CODE(KEYCODE_9) |
| 327 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN1 ) |
| 328 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN2 ) |
| 329 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_TILT ) |
| 330 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 331 | |
| 332 | /* menu */ |
| 333 | PORT_START("IN000") |
| 334 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY PORT_NAME("Menu/Left/Up") |
| 335 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY PORT_NAME("Menu/Left/Down") |
| 336 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY PORT_NAME("Menu/Left/Left") |
| 337 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY PORT_NAME("Menu/Left/Right") |
| 338 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) |
| 339 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START2 ) |
| 340 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_8WAY PORT_NAME("Menu/Right/Up") |
| 341 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_8WAY PORT_NAME("Menu/Right/Down") |
| 342 | |
| 343 | PORT_START("IN010") |
| 344 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_8WAY PORT_NAME("Menu/Right/Left") |
| 345 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_8WAY PORT_NAME("Menu/Right/Right") |
| 346 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Menu/Fire") |
| 347 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Menu/Thrust") |
| 348 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Menu/Smart Bomb") |
| 349 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Menu/Hyperspace") |
| 350 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Menu/Reverse") |
| 351 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Menu/Inviso or Flap") |
| 352 | |
| 353 | /* robotron */ |
| 354 | PORT_START("IN100") |
| 355 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY PORT_NAME("Robotron/Left/Up") |
| 356 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY PORT_NAME("Robotron/Left/Down") |
| 357 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY PORT_NAME("Robotron/Left/Left") |
| 358 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY PORT_NAME("Robotron/Left/Right") |
| 359 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 360 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 361 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_8WAY PORT_NAME("Robotron/Right/Up") |
| 362 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_8WAY PORT_NAME("Robotron/Right/Down") |
| 363 | |
| 364 | PORT_START("IN110") |
| 365 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_8WAY PORT_NAME("Robotron/Right/Left") |
| 366 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_8WAY PORT_NAME("Robotron/Right/Right") |
| 367 | PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 368 | |
| 369 | /* joust */ |
| 370 | PORT_START("IN201") /* muxed into IN0 */ |
| 371 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_2WAY PORT_NAME("Joust/P1/Left") |
| 372 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_2WAY PORT_NAME("Joust/P1/Right") |
| 373 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Joust/P1/Flap") |
| 374 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 375 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 376 | PORT_BIT( 0xc8, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 377 | |
| 378 | PORT_START("IN202") /* muxed into IN0 */ |
| 379 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_2WAY PORT_NAME("Joust/P2/Left") |
| 380 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_2WAY PORT_NAME("Joust/P2/Right") |
| 381 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Joust/P2/Flap") |
| 382 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 383 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 384 | PORT_BIT( 0xc8, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 385 | |
| 386 | PORT_START("IN210") |
| 387 | PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 388 | |
| 389 | /* stargate */ |
| 390 | PORT_START("IN300") |
| 391 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Stargate/Fire") |
| 392 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Stargate/Thrust") |
| 393 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Stargate/Smart Bomb") |
| 394 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Stargate/Hyperspace") |
| 395 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 396 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 397 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Stargate/Reverse") |
| 398 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_2WAY PORT_NAME("Stargate/Down") |
| 399 | |
| 400 | PORT_START("IN310") |
| 401 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_2WAY PORT_NAME("Stargate/Up") |
| 402 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Stargate/Inviso") |
| 403 | PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 404 | |
| 405 | /* bubbles */ |
| 406 | PORT_START("IN400") |
| 407 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY PORT_NAME("Bubbles/Up") |
| 408 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY PORT_NAME("Bubbles/Down") |
| 409 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY PORT_NAME("Bubbles/Left") |
| 410 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY PORT_NAME("Bubble/Right") |
| 411 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 412 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 413 | PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 414 | |
| 415 | PORT_START("IN410") |
| 416 | PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 417 | |
| 418 | /* defender */ |
| 419 | PORT_START("IN500") |
| 420 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Defender/Fire") |
| 421 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Defender/Thrust") |
| 422 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Defender/Smart Bomb") |
| 423 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Defender/Hyperspace") |
| 424 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) |
| 425 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START1 ) |
| 426 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Defender/Reverse") |
| 427 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN) PORT_2WAY PORT_NAME("Defender/Down") |
| 428 | |
| 429 | PORT_START("IN510") |
| 430 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_2WAY PORT_NAME("Defender/Up") |
| 431 | PORT_BIT( 0xfe, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 432 | |
| 433 | /* splat - there are no P2 controls, so it can only be played by a single player */ |
| 434 | PORT_START("IN601") /* muxed into IN0 */ |
| 435 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Left/Up") |
| 436 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Left/Down") |
| 437 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Left/Left") |
| 438 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Left/Right") |
| 439 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) |
| 440 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START2 ) |
| 441 | PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Right/Up") |
| 442 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Right/Down") |
| 443 | |
| 444 | PORT_START("IN602") /* muxed into IN0 */ |
| 445 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) |
| 446 | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START2 ) |
| 447 | PORT_BIT( 0xcf, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 448 | |
| 449 | PORT_START("IN611") /* muxed into IN1 */ |
| 450 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Right/Left") |
| 451 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Splat/P1/Right/Right") |
| 452 | PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 453 | |
| 454 | PORT_START("IN612") /* muxed into IN1 */ |
| 455 | PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNKNOWN ) |
| 456 | INPUT_PORTS_END |
| 457 | |
| 458 | /************************************* |
| 459 | * |
| 460 | * Machine Driver |
| 461 | * |
| 462 | *************************************/ |
| 463 | static MACHINE_CONFIG_START( wmg, wmg_state ) |
| 464 | |
| 465 | /* basic machine hardware */ |
| 466 | MCFG_CPU_ADD("maincpu", M6809, MASTER_CLOCK/3/4) |
| 467 | MCFG_CPU_PROGRAM_MAP(wmg_cpu1) |
| 468 | |
| 469 | MCFG_CPU_ADD("soundcpu", M6808, SOUND_CLOCK) |
| 470 | MCFG_CPU_PROGRAM_MAP(wmg_cpu2) |
| 471 | |
| 472 | MCFG_MACHINE_START_OVERRIDE(williams_state,williams) |
| 473 | MCFG_MACHINE_RESET_OVERRIDE(wmg_state, wmg) |
| 474 | MCFG_NVRAM_ADD_0FILL("nvram") |
| 475 | |
| 476 | MCFG_TIMER_DRIVER_ADD("scan_timer", williams_state, williams_va11_callback) |
| 477 | MCFG_TIMER_DRIVER_ADD("240_timer", williams_state, williams_count240_callback) |
| 478 | |
| 479 | /* video hardware */ |
| 480 | MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE | VIDEO_ALWAYS_UPDATE) |
| 481 | |
| 482 | MCFG_SCREEN_ADD("screen", RASTER) |
| 483 | MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK*2/3, 512, 10, 304, 260, 7, 245) |
| 484 | MCFG_SCREEN_VISIBLE_AREA(6, 298-1, 7, 247-1) |
| 485 | MCFG_SCREEN_UPDATE_DRIVER(williams_state, screen_update_williams) |
| 486 | |
| 487 | MCFG_VIDEO_START_OVERRIDE(williams_state,williams) |
| 488 | |
| 489 | /* sound hardware */ |
| 490 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 491 | |
| 492 | MCFG_DAC_ADD("wmsdac") |
| 493 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) |
| 494 | |
| 495 | /* pia */ |
| 496 | MCFG_PIA6821_ADD("pia_0", wmg_muxed_pia_0_intf) |
| 497 | MCFG_PIA6821_ADD("pia_1", williams_pia_1_intf) |
| 498 | MCFG_PIA6821_ADD("pia_2", williams_snd_pia_intf) |
| 499 | MACHINE_CONFIG_END |
| 500 | |
| 501 | /************************************* |
| 502 | * |
| 503 | * Driver Initialisation |
| 504 | * |
| 505 | *************************************/ |
| 506 | DRIVER_INIT_MEMBER( wmg_state, wmg ) |
| 507 | { |
| 508 | UINT8 *RAM = memregion("maincpu")->base(); |
| 509 | UINT8 *ROM = memregion("soundcpu")->base(); |
| 510 | membank("bank5")->configure_entries(0, 8, &RAM[0x2d000], 0x10000); /* Code */ |
| 511 | membank("bank6")->configure_entries(0, 8, &ROM[0x10000], 0x1000); /* Sound */ |
| 512 | membank("bank7")->configure_entries(1, 4, &RAM[0x78000], 0x1000); /* Defender roms */ |
| 513 | // CONFIGURE_BLITTER(WILLIAMS_BLITTER_SC01, 0xc000); |
| 514 | m_blitter_config = WILLIAMS_BLITTER_SC01; |
| 515 | m_blitter_clip_address = 0xc000; |
| 516 | } |
| 517 | |
| 518 | /************************************* |
| 519 | * |
| 520 | * Roms |
| 521 | * |
| 522 | *************************************/ |
| 523 | ROM_START( wmg ) |
| 524 | ROM_REGION( 0xa0000, "maincpu", 0 ) |
| 525 | ROM_LOAD( "wmg.cpu", 0x20000, 0x80000, CRC(975516ec) SHA1(571aaf9bff8ebfc36448cd9394b47bcfae7d1b83) ) |
| 526 | |
| 527 | /* This little HACK! lets the menu boot up. |
| 528 | It patches a jump to some new code, which sets a few memory locations, and sets the stack pointer. |
| 529 | Then it jumps back to continue the main run. */ |
| 530 | |
| 531 | ROM_COPY( "maincpu", 0x2e0da, 0x2f800, 0x0001b ) |
| 532 | ROM_FILL( 0x2f81b, 1, 0x7e ) |
| 533 | ROM_FILL( 0x2f81c, 1, 0xe0 ) |
| 534 | ROM_FILL( 0x2f81d, 1, 0xba ) |
| 535 | ROM_FILL( 0x2e0b7, 1, 0x7e ) |
| 536 | ROM_FILL( 0x2e0b8, 1, 0xf8 ) |
| 537 | ROM_FILL( 0x2e0b9, 1, 0x00 ) |
| 538 | |
| 539 | ROM_REGION( 0x18000, "soundcpu", 0 ) |
| 540 | ROM_LOAD( "wmg.snd", 0x10000, 0x8000, CRC(1d08990e) SHA1(7bfb29426b3876f113e6ec3bc6c2fce9d2d1eb0c) ) |
| 541 | |
| 542 | ROM_REGION( 0x0400, "proms", 0 ) |
| 543 | ROM_LOAD( "decoder.4", 0x0000, 0x0200, CRC(e6631c23) SHA1(9988723269367fb44ef83f627186a1c88cf7877e) ) |
| 544 | ROM_LOAD( "decoder.6", 0x0200, 0x0200, CRC(83faf25e) SHA1(30002643d08ed983a6701a7c4b5ee74a2f4a1adb) ) |
| 545 | ROM_END |
| 546 | |
| 547 | |
| 548 | /******************************************************* |
| 549 | * |
| 550 | * Game Driver |
| 551 | * |
| 552 | *******************************************************/ |
| 553 | |
| 554 | GAME( 2001, wmg, 0, wmg, wmg, wmg_state, wmg, ROT0, "Clay Cowgill", "Williams 6in1 Multigame", 0 ) |