diff options
Diffstat (limited to 'src/mame/drivers/missile.c')
-rw-r--r-- | src/mame/drivers/missile.c | 1115 |
1 files changed, 1115 insertions, 0 deletions
diff --git a/src/mame/drivers/missile.c b/src/mame/drivers/missile.c new file mode 100644 index 00000000000..9cc74b36ac7 --- /dev/null +++ b/src/mame/drivers/missile.c @@ -0,0 +1,1115 @@ +/*************************************************************************** + + Atari Missile Command hardware + + Games supported: + * Missile Command + + Known issues: + * none at this time + +**************************************************************************** + + Horizontal sync chain: + + A J/K flip flop @ D6 counts the 1H line, and cascades into a + 4-bit binary counter @ D5, which counts the 2H,4H,8H,16H lines. + This counter cascades into a 4-bit BCD decade counter @ E5 + which counts the 32H,64H,128H,HBLANK lines. The counter system + rolls over after counting to 320. + + Pixel clock = 5MHz + HBLANK ends at H = 0 + HBLANK begins at H = 256 + HSYNC begins at H = 260 + HSYNC ends at H = 288 + HTOTAL = 320 + + Vertical sync chain: + + The HSYNC signal clocks a 4-bit binary counter @ A4, which counts + the 1V,2V,4V,8V lines. This counter cascades into a second 4-bit + binary counter @ B4 which counts the 16V,32V,64V,128V lines. The + counter system rolls over after counting to 256. + + if not flipped (V counts up): + VBLANK ends at V = 24 + VBLANK begins at V = 0 + VSYNC begins at V = 4 + VSYNC ends at V = 8 + VTOTAL = 256 + + if flipped (V counts down): + VBLANK ends at V = 0 + VBLANK begins at V = 24 + VSYNC begins at V = 20 + VSYNC ends at V = 16 + VTOTAL = 256 + + Interrupts: + + /IRQ connected to Q on flip-flop @ F7, clocked by SYNC which + indicates an instruction opcode fetch. Input to the flip-flop + (D) comes from a second flip-flop @ F7, which is clocked by + /16V or 16V depending on whether or not we are flipped. Input + to this second flip-flop is 32V. + + if not flipped (V counts up): + clock @ 0 -> 32V = 0 -> /IRQ = 0 + clock @ 32 -> 32V = 1 -> /IRQ = 1 + clock @ 64 -> 32V = 0 -> /IRQ = 0 + clock @ 96 -> 32V = 1 -> /IRQ = 1 + clock @ 128 -> 32V = 0 -> /IRQ = 0 + clock @ 160 -> 32V = 1 -> /IRQ = 1 + clock @ 192 -> 32V = 0 -> /IRQ = 0 + clock @ 224 -> 32V = 1 -> /IRQ = 1 + + if flipped (V counts down): + clock @ 208 -> 32V = 0 -> /IRQ = 0 + clock @ 176 -> 32V = 1 -> /IRQ = 1 + clock @ 144 -> 32V = 0 -> /IRQ = 0 + clock @ 112 -> 32V = 1 -> /IRQ = 1 + clock @ 80 -> 32V = 0 -> /IRQ = 0 + clock @ 48 -> 32V = 1 -> /IRQ = 1 + clock @ 16 -> 32V = 0 -> /IRQ = 0 + clock @ 240 -> 32V = 1 -> /IRQ = 1 + +**************************************************************************** + + CPU Clock: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | 1H + ___ ___ ___ ___ ___ ___ ___ + ___| |___| |___| |___| |___| |___| |___| | 2H + _______ _______ _______ + _______| |_______| |_______| |_______| 4H + _______ ___________ ___________ ___________ + |___| |___| |___| /(4H & /2H) + _ ___ ___ ___ + |_______| |___________| |___________| |_________ /Q on FF @ A7 + ___ ___ ___ + ___________| |___________| |___________| |_______ Q on FF @ B8 + + When V < 224, + ___ ___ ___ ___ ___ ___ ___ + ___| |___| |___| |___| |___| |___| |___| | Sigma-X = 2H + + When V >= 224, + ___ ___ ___ + ___________| |___________| |___________| |_______ Sigma-X = Q on FF @ B8 + +**************************************************************************** + + Modified from original schematics... + + MISSILE COMMAND + --------------- + HEX R/W D7 D6 D5 D4 D3 D2 D2 D0 function + ---------+-----+------------------------+------------------------ + 0000-01FF R/W D D D D D D D D 512 bytes working ram + + 0200-05FF R/W D D D D D D D D 3rd color bit region + of screen ram. + Each bit of every odd byte is the low color + bit for the bottom scanlines + The schematics say that its for the bottom + 32 scanlines, although the code only accesses + $401-$5FF for the bottom 8 scanlines... + Pretty wild, huh? + + 0600-063F R/W D D D D D D D D More working ram. + + 0640-3FFF R/W D D D D D D D D 2-color bit region of + screen ram. + Writes to 4 bytes each to effectively + address $1900-$ffff. + + 1900-FFFF R/W D D 2-color bit region of + screen ram + Only accessed with + LDA ($ZZ,X) and + STA ($ZZ,X) + Those instructions take longer + than 5 cycles. + + ---------+-----+------------------------+------------------------ + 4000-400F R/W D D D D D D D D POKEY ports. + ----------------------------------------------------------------- + 4008 R D D D D D D D D Game Option switches + ----------------------------------------------------------------- + 4800 R D Right coin + 4800 R D Center coin + 4800 R D Left coin + 4800 R D 1 player start + 4800 R D 2 player start + 4800 R D 2nd player left fire(cocktail) + 4800 R D 2nd player center fire " + 4800 R D 2nd player right fire " + ---------+-----+------------------------+------------------------ + 4800 R D D D D Horiz trackball displacement + if ctrld=high. + 4800 R D D D D Vert trackball displacement + if ctrld=high. + ---------+-----+------------------------+------------------------ + 4800 W D Unused ?? + 4800 W D screen flip + 4800 W D left coin counter + 4800 W D center coin counter + 4800 W D right coin counter + 4800 W D 2 player start LED. + 4800 W D 1 player start LED. + 4800 W D CTRLD, 0=read switches, + 1= read trackball. + ---------+-----+------------------------+------------------------ + 4900 R D VBLANK read + 4900 R D Self test switch input. + 4900 R D SLAM switch input. + 4900 R D Horiz trackball direction input. + 4900 R D Vert trackball direction input. + 4900 R D 1st player left fire. + 4900 R D 1st player center fire. + 4900 R D 1st player right fire. + ---------+-----+------------------------+------------------------ + 4A00 R D D D D D D D D Pricing Option switches. + 4B00-4B07 W D D D D Color RAM. + 4C00 W Watchdog. + 4D00 W Interrupt acknowledge. + ---------+-----+------------------------+------------------------ + 5000-7FFF R D D D D D D D D Program. + ---------+-----+------------------------+------------------------ + + + MISSILE COMMAND SWITCH SETTINGS (Atari, 1980) + --------------------------------------------- + + + GAME OPTIONS: + (8-position switch at R8) + + 1 2 3 4 5 6 7 8 Meaning + ------------------------------------------------------------------------- + Off Off Game starts with 7 cities + On On Game starts with 6 cities + On Off Game starts with 5 cities + Off On Game starts with 4 cities + On No bonus credit + Off 1 bonus credit for 4 successive coins + On Large trak-ball input + Off Mini Trak-ball input + On Off Off Bonus city every 8000 pts + On On On Bonus city every 10000 pts + Off On On Bonus city every 12000 pts + On Off On Bonus city every 14000 pts + Off Off On Bonus city every 15000 pts + On On Off Bonus city every 18000 pts + Off On Off Bonus city every 20000 pts + Off Off Off No bonus cities + On Upright + Off Cocktail + + + + PRICING OPTIONS: + (8-position switch at R10) + + 1 2 3 4 5 6 7 8 Meaning + ------------------------------------------------------------------------- + On On 1 coin 1 play + Off On Free play + On Off 2 coins 1 play + Off Off 1 coin 2 plays + On On Right coin mech * 1 + Off On Right coin mech * 4 + On Off Right coin mech * 5 + Off Off Right coin mech * 6 + On Center coin mech * 1 + Off Center coin mech * 2 + On On English + Off On French + On Off German + Off Off Spanish + On ( Unused ) + Off ( Unused ) + + -there are 2 different versions of the Super Missile Attack board. It's not known if + the roms are different. The SMA manual mentions a set 3(035822-03E) that will work + as well as set 2. Missile Command set 1 will not work with the SMA board. It would + appear set 1 and set 2 as labeled by mame are reversed. + +******************************************************************************************/ + +#include "driver.h" +#include "sound/pokey.h" + + +#define MASTER_CLOCK (10000000) + +#define PIXEL_CLOCK (MASTER_CLOCK/2) +#define HTOTAL (320) +#define HBSTART (256) +#define HBEND (0) +#define VTOTAL (256) +#define VBSTART (256) +#define VBEND (25) /* 24 causes a garbage line at the top of the screen */ + + +/************************************* + * + * Globals + * + *************************************/ + +static const UINT8 *writeprom; + +static emu_timer *irq_timer; +static emu_timer *cpu_timer; + +static UINT8 irq_state; +static UINT8 ctrld; +static UINT8 flipscreen; +static UINT8 madsel_delay; +static UINT16 madsel_lastpc; + + + +/************************************* + * + * VBLANK and IRQ generation + * + *************************************/ + +INLINE int scanline_to_v(int scanline) +{ + /* since the vertical sync counter counts backwards when flipped, + this function returns the current effective V value, given + that video_screen_get_vpos() only counts forward */ + return flipscreen ? (256 - scanline) : scanline; +} + + +INLINE int v_to_scanline(int v) +{ + /* same as a above, but the opposite transformation */ + return flipscreen ? (256 - v) : v; +} + + +INLINE void schedule_next_irq(int curv) +{ + /* IRQ = /32V, clocked by /16V ^ flip */ + /* When not flipped, clocks on 0, 64, 128, 192 */ + /* When flipped, clocks on 16, 80, 144, 208 */ + if (flipscreen) + curv = ((curv - 32) & 0xff) | 0x10; + else + curv = ((curv + 32) & 0xff) & ~0x10; + + /* next one at the start of this scanline */ + timer_adjust(irq_timer, video_screen_get_time_until_pos(0, v_to_scanline(curv), 0), curv, attotime_zero); +} + + +static TIMER_CALLBACK( clock_irq ) +{ + int curv = param; + + /* assert the IRQ if not already asserted */ + irq_state = (~curv >> 5) & 1; + cpunum_set_input_line(0, 0, irq_state ? ASSERT_LINE : CLEAR_LINE); + + /* force an update while we're here */ + video_screen_update_partial(0, v_to_scanline(curv)); + + /* find the next edge */ + schedule_next_irq(curv); +} + + +static UINT32 get_vblank(void *param) +{ + int v = scanline_to_v(video_screen_get_vpos(0)); + return v < 24; +} + + + +/************************************* + * + * Machine setup + * + *************************************/ + +static TIMER_CALLBACK( adjust_cpu_speed ) +{ + int curv = param; + + /* starting at scanline 224, the CPU runs at half speed */ + if (curv == 224) + cpunum_set_clock(0, MASTER_CLOCK/16); + else + cpunum_set_clock(0, MASTER_CLOCK/8); + + /* scanline for the next run */ + curv ^= 224; + timer_adjust(cpu_timer, video_screen_get_time_until_pos(0, v_to_scanline(curv), 0), curv, attotime_zero); +} + + +static offs_t missile_opbase_handler(offs_t address) +{ + /* offset accounts for lack of A15 decoding */ + int offset = address & 0x8000; + address &= 0x7fff; + + /* RAM? */ + if (address < 0x4000) + { + opcode_base = opcode_arg_base = videoram - offset; + return ~0; + } + + /* ROM? */ + else if (address >= 0x5000) + { + opcode_base = opcode_arg_base = memory_region(REGION_CPU1) - offset; + return ~0; + } + + /* anything else falls through */ + return address; +} + + +static MACHINE_START( missile ) +{ + /* initialize globals */ + writeprom = memory_region(REGION_PROMS); + flipscreen = 0; + + /* set up an opcode base handler since we use mapped handlers for RAM */ + memory_set_opbase_handler(0, missile_opbase_handler); + opcode_base = opcode_arg_base = videoram; + + /* create a timer to speed/slow the CPU */ + cpu_timer = timer_alloc(adjust_cpu_speed); + timer_adjust(cpu_timer, video_screen_get_time_until_pos(0, v_to_scanline(0), 0), 0, attotime_zero); + + /* create a timer for IRQs and set up the first callback */ + irq_timer = timer_alloc(clock_irq); + irq_state = 0; + schedule_next_irq(-32); + + /* setup for save states */ + state_save_register_global(irq_state); + state_save_register_global(ctrld); + state_save_register_global(flipscreen); + state_save_register_global(madsel_delay); + state_save_register_global(madsel_lastpc); +} + + +static MACHINE_RESET( missile ) +{ + cpunum_set_input_line(0, 0, CLEAR_LINE); + irq_state = 0; +} + + + +/************************************* + * + * VRAM access override + * + *************************************/ + +INLINE int get_madsel(void) +{ + UINT16 pc = activecpu_get_previouspc(); + + /* if we're at a different instruction than last time, reset our delay counter */ + if (pc != madsel_lastpc) + madsel_delay = 0; + + /* MADSEL signal disables standard address decoding and routes + writes to video RAM; it is enabled if the IRQ signal is clear + and the low 5 bits of the fetched opcode are 0x01 */ + if (!irq_state && (cpu_readop(pc) & 0x1f) == 0x01) + { + /* the MADSEL signal goes high 5 cycles after the opcode is identified; + this effectively skips the indirect memory read. Since this is difficult + to do in MAME, we just ignore the first two positive hits on MADSEL + and only return TRUE on the third or later */ + madsel_lastpc = pc; + return (++madsel_delay >= 4); + } + madsel_delay = 0; + return 0; +} + + +INLINE offs_t get_bit3_addr(offs_t pixaddr) +{ + /* the 3rd bit of video RAM is scattered about various areas + we take a 16-bit pixel address here and convert it into + a video RAM address based on logic in the schematics */ + return (( pixaddr & 0x0800) >> 1) | + ((~pixaddr & 0x0800) >> 2) | + (( pixaddr & 0x07f8) >> 2) | + (( pixaddr & 0x1000) >> 12); +} + + +static void write_vram(offs_t address, UINT8 data) +{ + static const UINT8 data_lookup[4] = { 0x00, 0x0f, 0xf0, 0xff }; + offs_t vramaddr; + UINT8 vramdata; + UINT8 vrammask; + + /* basic 2 bit VRAM writes go to addr >> 2 */ + /* data comes from bits 6 and 7 */ + /* this should only be called if MADSEL == 1 */ + vramaddr = address >> 2; + vramdata = data_lookup[data >> 6]; + vrammask = writeprom[(address & 7) | 0x10]; + videoram[vramaddr] = (videoram[vramaddr] & vrammask) | (vramdata & ~vrammask); + + /* 3-bit VRAM writes use an extra clock to write the 3rd bit elsewhere */ + /* on the schematics, this is the MUSHROOM == 1 case */ + if ((address & 0xe000) == 0xe000) + { + vramaddr = get_bit3_addr(address); + vramdata = -((data >> 5) & 1); + vrammask = writeprom[(address & 7) | 0x18]; + videoram[vramaddr] = (videoram[vramaddr] & vrammask) | (vramdata & ~vrammask); + + /* account for the extra clock cycle */ + activecpu_adjust_icount(-1); + } +} + + +static UINT8 read_vram(offs_t address) +{ + offs_t vramaddr; + UINT8 vramdata; + UINT8 vrammask; + UINT8 result = 0xff; + + /* basic 2 bit VRAM reads go to addr >> 2 */ + /* data goes to bits 6 and 7 */ + /* this should only be called if MADSEL == 1 */ + vramaddr = address >> 2; + vrammask = 0x11 << (address & 3); + vramdata = videoram[vramaddr] & vrammask; + if ((vramdata & 0xf0) == 0) + result &= ~0x80; + if ((vramdata & 0x0f) == 0) + result &= ~0x40; + + /* 3-bit VRAM reads use an extra clock to read the 3rd bit elsewhere */ + /* on the schematics, this is the MUSHROOM == 1 case */ + if ((address & 0xe000) == 0xe000) + { + vramaddr = get_bit3_addr(address); + vrammask = 1 << (address & 7); + vramdata = videoram[vramaddr] & vrammask; + if (vramdata == 0) + result &= ~0x20; + + /* account for the extra clock cycle */ + activecpu_adjust_icount(-1); + } + return result; +} + + + +/************************************* + * + * Video update + * + *************************************/ + +static VIDEO_UPDATE( missile ) +{ + int x, y; + + /* draw the bitmap to the screen, looping over Y */ + for (y = cliprect->min_y; y <= cliprect->max_y; y++) + { + UINT16 *dst = (UINT16 *)bitmap->base + y * bitmap->rowpixels; + + int effy = flipscreen ? ((256+24 - y) & 0xff) : y; + UINT8 *src = &videoram[effy * 64]; + UINT8 *src3 = NULL; + + /* compute the base of the 3rd pixel row */ + if (effy >= 224) + src3 = &videoram[get_bit3_addr(effy << 8)]; + + /* loop over X */ + for (x = cliprect->min_x; x <= cliprect->max_x; x++) + { + UINT8 pix = src[x / 4] >> (x & 3); + pix = ((pix >> 2) & 4) | ((pix << 1) & 2); + + /* if we're in the lower region, get the 3rd bit */ + if (src3 != NULL) + pix |= (src3[(x / 8) * 2] >> (x & 7)) & 1; + + dst[x] = pix; + } + } + return 0; +} + + + +/************************************* + * + * Global read/write handlers + * + *************************************/ + +static WRITE8_HANDLER( missile_w ) +{ + /* if we're in MADSEL mode, write to video RAM */ + if (get_madsel()) + { + write_vram(offset, data); + return; + } + + /* otherwise, strip A15 and handle manually */ + offset &= 0x7fff; + + /* RAM */ + if (offset < 0x4000) + videoram[offset] = data; + + /* POKEY */ + else if (offset < 0x4800) + pokey1_w(offset & 0x0f, data); + + /* OUT0 */ + else if (offset < 0x4900) + { + flipscreen = ~data & 0x40; + coin_counter_w(0, data & 0x20); + coin_counter_w(1, data & 0x10); + coin_counter_w(2, data & 0x08); + set_led_status(1, ~data & 0x04); + set_led_status(0, ~data & 0x02); + ctrld = data & 1; + } + + /* color RAM */ + else if (offset >= 0x4b00 && offset < 0x4c00) + palette_set_color_rgb(Machine, offset & 7, pal1bit(~data >> 3), pal1bit(~data >> 2), pal1bit(~data >> 1)); + + /* watchdog */ + else if (offset >= 0x4c00 && offset < 0x4d00) + watchdog_reset(); + + /* interrupt ack */ + else if (offset >= 0x4d00 && offset < 0x4e00) + { + if (irq_state) + { + cpunum_set_input_line(0, 0, CLEAR_LINE); + irq_state = 0; + } + } + + /* anything else */ + else + logerror("%04X:Unknown write to %04X = %02X\n", activecpu_get_pc(), offset, data); +} + + +static READ8_HANDLER( missile_r ) +{ + UINT8 result = 0xff; + + /* if we're in MADSEL mode, read from video RAM */ + if (get_madsel()) + return read_vram(offset); + + /* otherwise, strip A15 and handle manually */ + offset &= 0x7fff; + + /* RAM */ + if (offset < 0x4000) + result = videoram[offset]; + + /* ROM */ + else if (offset >= 0x5000) + result = memory_region(REGION_CPU1)[offset]; + + /* POKEY */ + else if (offset < 0x4800) + result = pokey1_r(offset & 0x0f); + + /* IN0 */ + else if (offset < 0x4900) + { + if (ctrld) /* trackball */ + { + if (!flipscreen) + result = ((readinputport(5) << 4) & 0xf0) | (readinputport(4) & 0x0f); + else + result = ((readinputport(7) << 4) & 0xf0) | (readinputport(6) & 0x0f); + } + else /* buttons */ + result = readinputport(0); + } + + /* IN1 */ + else if (offset < 0x4a00) + result = readinputport(1); + + /* IN2 */ + else if (offset < 0x4b00) + result = readinputport(2); + + /* anything else */ + else + logerror("%04X:Unknown read from %04X\n", activecpu_get_pc(), offset); + return result; +} + + + +/************************************* + * + * Main CPU memory handlers + * + *************************************/ + +/* complete memory map derived from schematics (implemented above) */ +static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0xffff) AM_READWRITE(missile_r, missile_w) AM_BASE(&videoram) +ADDRESS_MAP_END + + + +/************************************* + * + * Port definitions + * + *************************************/ + +static INPUT_PORTS_START( missile ) + PORT_START /* IN0 */ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_COCKTAIL + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN3 ) + + PORT_START /* IN1 */ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x18, IP_ACTIVE_HIGH, IPT_SPECIAL ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_TILT ) + PORT_SERVICE( 0x40, IP_ACTIVE_LOW ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_vblank, 0) + + PORT_START /* IN2 */ + PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("R10:1,2") + PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x03, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Free_Play ) ) + PORT_DIPNAME( 0x0c, 0x00, "Right Coin" ) PORT_DIPLOCATION("R10:3,4") + PORT_DIPSETTING( 0x00, "*1" ) + PORT_DIPSETTING( 0x04, "*4" ) + PORT_DIPSETTING( 0x08, "*5" ) + PORT_DIPSETTING( 0x0c, "*6" ) + PORT_DIPNAME( 0x10, 0x00, "Center Coin" ) PORT_DIPLOCATION("R10:5") + PORT_DIPSETTING( 0x00, "*1" ) + PORT_DIPSETTING( 0x10, "*2" ) + PORT_DIPNAME( 0x60, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("R10:6,7") + PORT_DIPSETTING( 0x00, DEF_STR( English ) ) + PORT_DIPSETTING( 0x20, DEF_STR( French ) ) + PORT_DIPSETTING( 0x40, DEF_STR( German ) ) + PORT_DIPSETTING( 0x60, DEF_STR( Spanish ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("R10:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_START /* IN3 */ + PORT_DIPNAME( 0x03, 0x00, "Cities" ) PORT_DIPLOCATION("R8:1,2") + PORT_DIPSETTING( 0x02, "4" ) + PORT_DIPSETTING( 0x01, "5" ) + PORT_DIPSETTING( 0x03, "6" ) + PORT_DIPSETTING( 0x00, "7" ) + PORT_DIPNAME( 0x04, 0x04, "Bonus Credit for 4 Coins" ) PORT_DIPLOCATION("R8:3") + PORT_DIPSETTING( 0x04, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x08, 0x00, "Trackball Size" ) PORT_DIPLOCATION("R8:4") + PORT_DIPSETTING( 0x00, "Large" ) + PORT_DIPSETTING( 0x08, "Mini" ) + PORT_DIPNAME( 0x70, 0x70, "Bonus City" ) PORT_DIPLOCATION("R8:5,6,7") + PORT_DIPSETTING( 0x10, "8000" ) + PORT_DIPSETTING( 0x70, "10000" ) + PORT_DIPSETTING( 0x60, "12000" ) + PORT_DIPSETTING( 0x50, "14000" ) + PORT_DIPSETTING( 0x40, "15000" ) + PORT_DIPSETTING( 0x30, "18000" ) + PORT_DIPSETTING( 0x20, "20000" ) + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPNAME( 0x80, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("R8:8") + PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Cocktail ) ) + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE PORT_COCKTAIL + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE PORT_COCKTAIL +INPUT_PORTS_END + + +static INPUT_PORTS_START( suprmatk ) + PORT_START /* IN0 */ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_COCKTAIL + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN3 ) + + PORT_START /* IN1 */ + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x18, IP_ACTIVE_HIGH, IPT_SPECIAL ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_TILT ) + PORT_SERVICE( 0x40, IP_ACTIVE_LOW ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(get_vblank, 0) + + PORT_START /* IN2 */ + PORT_DIPNAME( 0x03, 0x00, DEF_STR( Coinage ) ) PORT_DIPLOCATION("R10:1,2") + PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x03, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Free_Play ) ) + PORT_DIPNAME( 0x0c, 0x00, "Right Coin" ) PORT_DIPLOCATION("R10:3,4") + PORT_DIPSETTING( 0x00, "*1" ) + PORT_DIPSETTING( 0x04, "*4" ) + PORT_DIPSETTING( 0x08, "*5" ) + PORT_DIPSETTING( 0x0c, "*6" ) + PORT_DIPNAME( 0x10, 0x00, "Center Coin" ) PORT_DIPLOCATION("R10:5") + PORT_DIPSETTING( 0x00, "*1" ) + PORT_DIPSETTING( 0x10, "*2" ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("R10:6") + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0xc0, 0x40, "Game" ) PORT_DIPLOCATION("R10:7,8") + PORT_DIPSETTING( 0x00, "Missile Command" ) + PORT_DIPSETTING( 0x40, "Easy Super Missile Attack" ) + PORT_DIPSETTING( 0x80, "Reg. Super Missile Attack" ) + PORT_DIPSETTING( 0xc0, "Hard Super Missile Attack" ) + + PORT_START /* IN3 */ + PORT_DIPNAME( 0x03, 0x00, "Cities" ) PORT_DIPLOCATION("R8:1,2") + PORT_DIPSETTING( 0x02, "4" ) + PORT_DIPSETTING( 0x01, "5" ) + PORT_DIPSETTING( 0x03, "6" ) + PORT_DIPSETTING( 0x00, "7" ) + PORT_DIPNAME( 0x04, 0x04, "Bonus Credit for 4 Coins" ) PORT_DIPLOCATION("R8:3") + PORT_DIPSETTING( 0x04, DEF_STR( No ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPNAME( 0x08, 0x00, "Trackball Size" ) PORT_DIPLOCATION("R8:4") + PORT_DIPSETTING( 0x00, "Large" ) + PORT_DIPSETTING( 0x08, "Mini" ) + PORT_DIPNAME( 0x70, 0x70, "Bonus City" ) PORT_DIPLOCATION("R8:5,6,7") + PORT_DIPSETTING( 0x10, "8000" ) + PORT_DIPSETTING( 0x70, "10000" ) + PORT_DIPSETTING( 0x60, "12000" ) + PORT_DIPSETTING( 0x50, "14000" ) + PORT_DIPSETTING( 0x40, "15000" ) + PORT_DIPSETTING( 0x30, "18000" ) + PORT_DIPSETTING( 0x20, "20000" ) + PORT_DIPSETTING( 0x00, DEF_STR( None ) ) + PORT_DIPNAME( 0x80, 0x00, DEF_STR( Cabinet ) ) PORT_DIPLOCATION("R8:8") + PORT_DIPSETTING( 0x00, DEF_STR( Upright ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Cocktail ) ) + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE PORT_COCKTAIL + + PORT_START /* FAKE */ + PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE PORT_COCKTAIL +INPUT_PORTS_END + + + +/************************************* + * + * Sound interfaces + * + *************************************/ + +static struct POKEYinterface pokey_interface = +{ + { 0 }, + input_port_3_r +}; + + + +/************************************* + * + * Machine driver + * + *************************************/ + +static MACHINE_DRIVER_START( missile ) + + /* basic machine hardware */ + MDRV_CPU_ADD(M6502, MASTER_CLOCK/8) + MDRV_CPU_PROGRAM_MAP(main_map,0) + + MDRV_MACHINE_START(missile) + MDRV_MACHINE_RESET(missile) + MDRV_WATCHDOG_VBLANK_INIT(8) + + /* video hardware */ + MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER) + MDRV_PALETTE_LENGTH(8) + + MDRV_SCREEN_ADD("main", 0) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) + MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART) + + MDRV_VIDEO_UPDATE(missile) + + /* sound hardware */ + MDRV_SPEAKER_STANDARD_MONO("mono") + + MDRV_SOUND_ADD(POKEY, MASTER_CLOCK/8) + MDRV_SOUND_CONFIG(pokey_interface) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) +MACHINE_DRIVER_END + + + +/************************************* + * + * ROM definitions + * + *************************************/ + +ROM_START( missile ) + ROM_REGION( 0x8000, REGION_CPU1, 0 ) + ROM_LOAD( "035820.02", 0x5000, 0x0800, CRC(7a62ce6a) SHA1(9a39978138dc28fdefe193bfae1b226391e471db) ) + ROM_LOAD( "035821.02", 0x5800, 0x0800, CRC(df3bd57f) SHA1(0916925d3c94d766d33f0e4badf6b0add835d748) ) + ROM_LOAD( "035822.02", 0x6000, 0x0800, CRC(a1cd384a) SHA1(a1dd0953423750a0fbc6e3dccbf2ca64ef5a1f54) ) + ROM_LOAD( "035823.02", 0x6800, 0x0800, CRC(82e552bb) SHA1(d0f22894f779c74ceef644c9f03d840d9545efea) ) + ROM_LOAD( "035824.02", 0x7000, 0x0800, CRC(606e42e0) SHA1(9718f84a73c66b4e8ef7805a7ab638a7380624e1) ) + ROM_LOAD( "035825.02", 0x7800, 0x0800, CRC(f752eaeb) SHA1(0339a6ce6744d2091cc7e07675e509b202b0f380) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "035826.01", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + + +ROM_START( missile2 ) + ROM_REGION( 0x8000, REGION_CPU1, 0 ) + ROM_LOAD( "35820-01.h1", 0x5000, 0x0800, CRC(41cbb8f2) SHA1(5dcb58276c08d75d36baadb6cefe30d4916de9b0) ) + ROM_LOAD( "35821-01.jk1", 0x5800, 0x0800, CRC(728702c8) SHA1(6f25af7133d3ec79029117162649f94e93f36e0e) ) + ROM_LOAD( "35822-01.kl1", 0x6000, 0x0800, CRC(28f0999f) SHA1(eb52b11c6757c8dc3be88b276ea4dc7dfebf7cf7) ) + ROM_LOAD( "35823-01.mn1", 0x6800, 0x0800, CRC(bcc93c94) SHA1(f0daa5d2835a856e2038612e755dc7ded28fc923) ) + ROM_LOAD( "35824-01.np1", 0x7000, 0x0800, CRC(0ca089c8) SHA1(7f69ee990fd4fa1f2fceca7fc66fcaa02e4d2314) ) + ROM_LOAD( "35825-01.r1", 0x7800, 0x0800, CRC(428cf0d5) SHA1(03cabbef50c33852fbbf38dd3eecaf70a82df82f) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "035826.01", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + + +ROM_START( suprmatk ) + ROM_REGION( 0x9000, REGION_CPU1, 0 ) + ROM_LOAD( "035820.02", 0x5000, 0x0800, CRC(7a62ce6a) SHA1(9a39978138dc28fdefe193bfae1b226391e471db) ) + ROM_LOAD( "035821.02", 0x5800, 0x0800, CRC(df3bd57f) SHA1(0916925d3c94d766d33f0e4badf6b0add835d748) ) + ROM_LOAD( "035822.02", 0x6000, 0x0800, CRC(a1cd384a) SHA1(a1dd0953423750a0fbc6e3dccbf2ca64ef5a1f54) ) + ROM_LOAD( "035823.02", 0x6800, 0x0800, CRC(82e552bb) SHA1(d0f22894f779c74ceef644c9f03d840d9545efea) ) + ROM_LOAD( "035824.02", 0x7000, 0x0800, CRC(606e42e0) SHA1(9718f84a73c66b4e8ef7805a7ab638a7380624e1) ) + ROM_LOAD( "035825.02", 0x7800, 0x0800, CRC(f752eaeb) SHA1(0339a6ce6744d2091cc7e07675e509b202b0f380) ) + ROM_LOAD( "e0.rom", 0x8000, 0x0800, CRC(d0b20179) SHA1(e2a9855899b6ff96b8dba169e0ab83f00a95919f) ) + ROM_LOAD( "e1.rom", 0x8800, 0x0800, CRC(c6c818a3) SHA1(b9c92a85c07dd343d990e196d37b92d92a85a5e0) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "035826.01", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + + +ROM_START( sprmatkd ) + ROM_REGION( 0x8000, REGION_CPU1, 0 ) + ROM_LOAD( "035820.sma", 0x5000, 0x0800, CRC(75f01b87) SHA1(32ed71b6a869d7b361f244c384bbe6f407f6c6d7) ) + ROM_LOAD( "035821.sma", 0x5800, 0x0800, CRC(3320d67e) SHA1(5bb04b985421af6309818b94676298f4b90495cf) ) + ROM_LOAD( "035822.sma", 0x6000, 0x0800, CRC(e6be5055) SHA1(43912cc565cb43256a9193594cf36abab1c85d6f) ) + ROM_LOAD( "035823.sma", 0x6800, 0x0800, CRC(a6069185) SHA1(899cd8b378802eb6253d4bca7432797168595d53) ) + ROM_LOAD( "035824.sma", 0x7000, 0x0800, CRC(90a06be8) SHA1(f46fd6847bc9836d11ea0042df19fbf33ddab0db) ) + ROM_LOAD( "035825.sma", 0x7800, 0x0800, CRC(1298213d) SHA1(c8e4301704e3700c339557f2a833e70f6a068d5e) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "035826.01", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + + +/* + +Missile Combat bootlegs by 'Videotron' + +1x 6502A (main) +1x AY-3-8912 (sound) +1x oscillator 10000 + +PCB is marked: "VIDEOTRON BOLOGNA 002" + +*/ + +ROM_START( mcombat ) + ROM_REGION( 0x8000, REGION_CPU1, 0 ) + ROM_LOAD( "002-0-0.10a", 0x5000, 0x0800, CRC(589b81de) SHA1(06f18a837cedb0da5464dfaa04f92bd035db3752) ) + ROM_LOAD( "002-1-1.9a", 0x5800, 0x0800, CRC(08796a78) SHA1(e5aabe775889752ad1581098fcbf52ff1fa03b3b) ) + ROM_LOAD( "002-2-2.8a", 0x6000, 0x0800, CRC(59ab750c) SHA1(4555c27ddeb22ba895610a9c516fe574664a6f4b) ) + ROM_LOAD( "002-3-3.7a", 0x6800, 0x0800, CRC(3295cc3f) SHA1(2be0d492bd791df19d138d5bfe956361ee461989) ) + ROM_LOAD( "002-4-4.6a", 0x7000, 0x0800, CRC(aac71e95) SHA1(7daf115eb2cdde69b7c4de1e1a6ee68cd2fd0f2c) ) + ROM_LOAD( "002-5-5.5a", 0x7800, 0x0800, CRC(1b9a16e2) SHA1(03fb292bb6f815724b2fc4b2f561398000367373) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "mmi6331.6f", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + + +ROM_START( mcombata ) + ROM_REGION( 0x8000, REGION_CPU1, 0 ) + ROM_LOAD( "002-0-0.10a", 0x5000, 0x0800, CRC(589b81de) SHA1(06f18a837cedb0da5464dfaa04f92bd035db3752) ) + ROM_LOAD( "002-1-1.9a", 0x5800, 0x0800, CRC(08796a78) SHA1(e5aabe775889752ad1581098fcbf52ff1fa03b3b) ) + ROM_LOAD( "002-2-2.8a", 0x6000, 0x0800, CRC(59ab750c) SHA1(4555c27ddeb22ba895610a9c516fe574664a6f4b) ) + ROM_LOAD( "3.bin", 0x6800, 0x0800, CRC(ddbfda20) SHA1(444daaa76751853f67a7c0e5bf620ae5623d2105) ) + ROM_LOAD( "4.bin", 0x7000, 0x0800, CRC(e3b5428d) SHA1(ac9eb459df68a117a49e92fbc5ed88faaf46a395) ) + ROM_LOAD( "002-5-5.5a", 0x7800, 0x0800, CRC(1b9a16e2) SHA1(03fb292bb6f815724b2fc4b2f561398000367373) ) + + ROM_REGION( 0x0020, REGION_PROMS, 0 ) + ROM_LOAD( "mmi6331.6f", 0x0000, 0x0020, CRC(86a22140) SHA1(2beebf7855e29849ada1823eae031fc98220bc43) ) +ROM_END + +/************************************* + * + * Driver initialization + * + *************************************/ + +static DRIVER_INIT( suprmatk ) +{ + int i; + UINT8 *rom = memory_region(REGION_CPU1); + + for (i = 0; i < 0x40; i++) + { + rom[0x7CC0+i] = rom[0x8000+i]; + rom[0x5440+i] = rom[0x8040+i]; + rom[0x5B00+i] = rom[0x8080+i]; + rom[0x5740+i] = rom[0x80C0+i]; + rom[0x6000+i] = rom[0x8100+i]; + rom[0x6540+i] = rom[0x8140+i]; + rom[0x7500+i] = rom[0x8180+i]; + rom[0x7100+i] = rom[0x81C0+i]; + rom[0x7800+i] = rom[0x8200+i]; + rom[0x5580+i] = rom[0x8240+i]; + rom[0x5380+i] = rom[0x8280+i]; + rom[0x6900+i] = rom[0x82C0+i]; + rom[0x6E00+i] = rom[0x8300+i]; + rom[0x6CC0+i] = rom[0x8340+i]; + rom[0x7DC0+i] = rom[0x8380+i]; + rom[0x5B80+i] = rom[0x83C0+i]; + rom[0x5000+i] = rom[0x8400+i]; + rom[0x7240+i] = rom[0x8440+i]; + rom[0x7040+i] = rom[0x8480+i]; + rom[0x62C0+i] = rom[0x84C0+i]; + rom[0x6840+i] = rom[0x8500+i]; + rom[0x7EC0+i] = rom[0x8540+i]; + rom[0x7D40+i] = rom[0x8580+i]; + rom[0x66C0+i] = rom[0x85C0+i]; + rom[0x72C0+i] = rom[0x8600+i]; + rom[0x7080+i] = rom[0x8640+i]; + rom[0x7D00+i] = rom[0x8680+i]; + rom[0x5F00+i] = rom[0x86C0+i]; + rom[0x55C0+i] = rom[0x8700+i]; + rom[0x5A80+i] = rom[0x8740+i]; + rom[0x6080+i] = rom[0x8780+i]; + rom[0x7140+i] = rom[0x87C0+i]; + rom[0x7000+i] = rom[0x8800+i]; + rom[0x6100+i] = rom[0x8840+i]; + rom[0x5400+i] = rom[0x8880+i]; + rom[0x5BC0+i] = rom[0x88C0+i]; + rom[0x7E00+i] = rom[0x8900+i]; + rom[0x71C0+i] = rom[0x8940+i]; + rom[0x6040+i] = rom[0x8980+i]; + rom[0x6E40+i] = rom[0x89C0+i]; + rom[0x5800+i] = rom[0x8A00+i]; + rom[0x7D80+i] = rom[0x8A40+i]; + rom[0x7A80+i] = rom[0x8A80+i]; + rom[0x53C0+i] = rom[0x8AC0+i]; + rom[0x6140+i] = rom[0x8B00+i]; + rom[0x6700+i] = rom[0x8B40+i]; + rom[0x7280+i] = rom[0x8B80+i]; + rom[0x7F00+i] = rom[0x8BC0+i]; + rom[0x5480+i] = rom[0x8C00+i]; + rom[0x70C0+i] = rom[0x8C40+i]; + rom[0x7F80+i] = rom[0x8C80+i]; + rom[0x5780+i] = rom[0x8CC0+i]; + rom[0x6680+i] = rom[0x8D00+i]; + rom[0x7200+i] = rom[0x8D40+i]; + rom[0x7E40+i] = rom[0x8D80+i]; + rom[0x7AC0+i] = rom[0x8DC0+i]; + rom[0x6300+i] = rom[0x8E00+i]; + rom[0x7180+i] = rom[0x8E40+i]; + rom[0x7E80+i] = rom[0x8E80+i]; + rom[0x6280+i] = rom[0x8EC0+i]; + rom[0x7F40+i] = rom[0x8F00+i]; + rom[0x6740+i] = rom[0x8F40+i]; + rom[0x74C0+i] = rom[0x8F80+i]; + rom[0x7FC0+i] = rom[0x8FC0+i]; + } +} + + +/************************************* + * + * Game drivers + * + *************************************/ + +GAME( 1980, missile, 0, missile, missile, 0, ROT0, "Atari", "Missile Command (set 1)", GAME_SUPPORTS_SAVE ) +GAME( 1980, missile2, missile, missile, missile, 0, ROT0, "Atari", "Missile Command (set 2)", GAME_SUPPORTS_SAVE ) +GAME( 1981, suprmatk, missile, missile, suprmatk, suprmatk, ROT0, "Atari + Gencomp", "Super Missile Attack (for set 2)", GAME_SUPPORTS_SAVE ) +GAME( 1981, sprmatkd, missile, missile, suprmatk, 0, ROT0, "Atari + Gencomp", "Super Missile Attack (not encrypted)", GAME_SUPPORTS_SAVE ) + +/* the bootlegs are on different hardware and don't work */ +GAME( 198?, mcombat, missile, missile, missile, 0, ROT0, "[Atari] (Videotron bootleg)", "Missile Combat (Videotron bootleg, set 1)", GAME_NOT_WORKING ) +GAME( 198?, mcombata, missile, missile, missile, 0, ROT0, "[Atari] (Videotron bootleg)", "Missile Combat (Videotron bootleg, set 2)", GAME_NOT_WORKING ) |