/* Halley's Comet, 1986 Taito Halley's Comet was created by Fukio Mitsuji (MTJ), who also created Bubble Bobble, Rainbow Islands, Syvalion, etc. Issues: - Status reads from blitter RAM aren't well understood. They probably includes both completion and collision flags. - The blitter is missing many features, in particular certain sprites aren't erased properly. - It isn't known how many independent planes of graphics the blitter manages. The starfield, for example, probably involves at least two additional planes orthogonal to the sprites and scroll layer. - Background tiles inside the comet have wrong coordinates. - Score digits have wrong colors. - Blitter functions, especially those capable of screen warping, are unoptimized. - The starfields can probably be represented and rendered by two simple lists instead of costly bitmaps. - Ben Bero Beh has collision problems with the falling fireballs and a minor priority glitch with the "Elevator Action" baddies. * Halley's Comet's undocumented DIP switches only work if the player1 start button is depressed during boot-up. Special thanks to Phil Stroffolino for the creation of a solid framework, Jarek Burczynski for adding sound and providing awesome hand-drawn schematics, Jason MacFarlane for his continuous and selfless support. I'd never have come all this way without the invaluable videos and screen shots sent by Jason. To the Columbia crew and the forerunners who gave their lives to science and space exploration. Your bravery and devotion will not be forgotten. CPU: MC68B09EP Z80A(SOUND) Sound: YM2149F x 4 OSC: 19.968MHz 6MHz J1100021 sound daughterboard Z80A 6MHz 2016 A62-13 A62-14 YM2149 YM2149 YM2149 J1100018 sw1 sw2 sw3 sw4 A62-2 A62-15 68B09EP A62-1 A62-4 2016 YM2149 2016 J1100020 4116 4116 4116 4116 MB15511 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 MB15512 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 4116 MB15510 MB15510 2016 2016 J1100019 A62-9 A62-10 A26-13 A62-11 A62-12 A26-13 A62-5 A62-16 A26-13 A62-7 A62-8 HALLEY'S COMET Taito 1986 Pinout and DIP switch settings typed in by Pelle Einarsson, pelle@mensa.se NOTE: I had to guess the meaning of some Japanese text concerning the DIP switch settings, but I think I got it right. * = default settings T G PARTS SOLDER PARTS SOLDER ---------------------------------- --------------------------------------- GND 1 A GND GND 1 A GND GND 2 B GND 2 B GND 3 C GND 3 C GND 4 D GND 4 D Video GND 5 E Video GND Sound out+ 5 E Sound Out - Video sync 6 F Video sync Post 6 F Post Post 7 H Post 7 H Power on reset Video R 8 J Video R Coin sw A 8 J Coin sw B Video G 9 K Video G Coin counter A 9 K Coin counter B Video B 10 L Video B Coin lockout A 10 L Coin lockout B -5V 11 M -5V Service sw 11 M Tilt sw -5V 12 N -5V Select 1 12 N Select 2 +12V 13 P +12V 1P up 13 P 2P up +12V 14 R +12V 1P down 14 R 2P down +5V 15 S +5V 1P right 15 S 2P right +5V 16 T +5V 1P left 16 T 2P left +5V 17 U +5V 17 U +5V 18 V +5V 18 V 19 W 20 X H 1P shoot 21 Y 2p shoot -------- 1P hyperspace 22 Z 2P hyperspace 1 GND 2 GND 3 GND 4 GND 5 +5V 6 +5V 7 +5V 8 -5V 9 +13V (a typo?) DIP switch 1 Option 1-5 6 10 Post ---------------------------------------------- 11 +12V (single/dual controls?) *1-way off on 12 +12V 2-way off color test layout: (0,0) *ROT90 +------+-------+------+------+ | | | | | | White| Blue |Green | Red | 1 (brightest) | | | | | +------+-------+------+------+ | | | | | | | | | | 2 | | | | | +------+-------+------+------+ | | | | | | | | | | 3 | | | | | +------+-------+------+------+ | | | | | | | | | | 4 (darkest) | | | | | +------+-------+------+------+ */ //************************************************************************** // Compiler Directives #include "driver.h" #include "taitoipt.h" #include "deprecat.h" #include "cpu/m6809/m6809.h" #include "sound/ay8910.h" #define HALLEYS_DEBUG 0 //************************************************************************** // Driver Constants and Variables #define GAME_BENBEROB 0 #define GAME_HALLEYS 1 /* CAUTION: SENSITIVE VALUES */ #define SCREEN_WIDTH_L2 8 #define SCREEN_HEIGHT 256 #define VIS_MINX 0 #define VIS_MAXX 255 #define VIS_MINY 8 #define VIS_MAXY (255-8) #define MAX_LAYERS 6 #define MAX_SPRITES 256 #define MAX_SOUNDS 16 #define SP_2BACK 0x100 #define SP_ALPHA 0x200 #define SP_COLLD 0x300 #define BG_MONO 0x400 #define BG_RGB 0x500 #define PALETTE_SIZE 0x600 #define SCREEN_WIDTH (1 << SCREEN_WIDTH_L2) #define SCREEN_SIZE (SCREEN_HEIGHT << SCREEN_WIDTH_L2) #define SCREEN_BYTEWIDTH_L2 (SCREEN_WIDTH_L2 + 1) #define SCREEN_BYTEWIDTH (1 << SCREEN_BYTEWIDTH_L2) #define SCREEN_BYTESIZE (SCREEN_HEIGHT << SCREEN_BYTEWIDTH_L2) #define CLIP_SKIP (VIS_MINY * SCREEN_WIDTH + VIS_MINX) #define CLIP_W (VIS_MAXX - VIS_MINX + 1) #define CLIP_H (VIS_MAXY - VIS_MINY + 1) #define CLIP_BYTEW (CLIP_W << 1) static UINT16 *render_layer[MAX_LAYERS]; static UINT8 sound_fifo[MAX_SOUNDS]; static UINT8 *gfx_plane02, *gfx_plane13, *collision_list; static UINT8 *scrolly0, *scrollx0, *scrolly1, *scrollx1; static UINT32 *internal_palette, *alpha_table; static UINT8 *cpu1_base, *gfx1_base, *blitter_ram, *io_ram; static size_t blitter_ramsize, io_ramsize; static int game_id, blitter_busy, collision_count, stars_enabled, bgcolor, ffcount, ffhead, fftail; static int mVectorType, sndnmi_mask, firq_level; static emu_timer *blitter_reset_timer; static offs_t halleys_collision_detection; //************************************************************************** // MB1551x Blitter Functions static void blit(int offset) { /* The render layers can be converted to standard MAME bitmaps but I am not taking chances as long as the blitter has unknown draw modes which may go beyond MAME's capability. The function has grown tremendously as more features were added and become rather difficult to maintain. */ // status attributes #define ACTIVE 0x02 #define DECAY 0x10 #define RETIRE 0x80 // mode attributes #define IGNORE_0 0x01 #define MODE_02 0x02 #define COLOR_ON 0x04 #define MIRROR_X 0x08 #define MIRROR_Y 0x10 #define MODE_40 0x40 #define GROUP 0x80 // color attributes #define PENCOLOR 0x0f #define BANKBIT1 0x80 // code attributes #define COMMAND 0x0f #define BGLAYER 0x10 #define BANKBIT0 0x40 #define PLANE 0x80 // special draw commands #define EFX1 0x8 // draws to back?? #define HORIZBAR 0xe // draws 8-bit RGB horizontal bars #define STARPASS1 0x3 // draws the stars #define STARPASS2 0xd // modifies stars color #define TILEPASS1 0x5 // draws tiles(s1: embedded 8-bit RGB, s2: bit-packed pixel data) #define TILEPASS2 0xb // modifies tiles color/alpha // user flags #define FLIP_X 0x0100 #define FLIP_Y 0x0200 #define SINGLE_PEN 0x0400 #define RGB_MASK 0x0800 #define AD_HIGH 0x1000 #define SY_HIGH 0x2000 #define S1_IDLE 0x4000 #define S1_REV 0x8000 #define S2_IDLE 0x10000 #define S2_REV 0x20000 #define BACKMODE 0x40000 #define ALPHAMODE 0x80000 #define PPCD_ON 0x100000 // hard-wired defs and interfaces #define HALLEYS_SPLIT 0xf4 #define COLLISION_PORTA 0x67 #define COLLISION_PORTB 0x8b // short cuts #define XMASK (SCREEN_WIDTH-1) #define YMASK (SCREEN_HEIGHT-1) static const UINT8 penxlat[16]={0x03,0x07,0x0b,0x0f,0x02,0x06,0x0a,0x0e,0x01,0x05,0x09,0x0d,0x00,0x04,0x08,0x0c}; static const UINT8 rgbmask[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff}; static const UINT8 tyremap[ 8]={ 0, 5, 9,13,16,20,24,28}; UINT8 *param, *src_base; UINT16 *dst_base; int stptr, mode, color, code, y, x, h, w, src1, src2; int status, flags, group, command, bank, layer, pen0, pen1; int yclip, xclip, src_yskip, src_xskip, dst_skip, hclip, wclip, src_dy, src_dx; UINT32 *pal_ptr; UINT8 *src1_ptr, *src2_ptr; // esi alias, ebx alias UINT16 *dst_ptr; // edi alias void *edi; // scratch int eax, ebx, ecx, edx; // scratch UINT16 ax; UINT8 al, ah; // partial regs param = blitter_ram + offset; #if HALLEYS_DEBUG if (0) { logerror("%04x:[%04x]", activecpu_get_pc(), offset); for (ecx=0; ecx<16; ecx++) logerror(" %02x", param[ecx]); logerror("\n"); } #endif // init blitter controls stptr = (int)param[0x2]<<8 | (int)param[0x3]; mode = (int)param[0x5]; color = (int)param[0x6]; code = (int)param[0x7]; // update sprite status layer = (code>>3 & 2) | (code>>7 & 1); offset >>= 4; status = (stptr) ? cpu1_base[stptr] : ACTIVE; flags = mode; group = mode & GROUP; command = code & COMMAND; if (game_id == GAME_HALLEYS) { if (!layer) flags |= PPCD_ON; if (offset >= HALLEYS_SPLIT) flags |= AD_HIGH; else if (offset & 1) memcpy(param-0x10, param, 0x10); else group = param[0x15] & GROUP; // HACK: force engine flame in group zero to increase collision accuracy if (offset == 0x1a || offset == 0x1b) group = 0; } else if (offset & 1) memcpy(param-0x10, param, 0x10); // init draw parameters y = (int)param[0x8]; x = (int)param[0x9]; h = (int)param[0xa]; w = (int)param[0xb] + 1; if (!h) return; // translate source addresses src1 = (int)param[0xc]<<8 | (int)param[0xd]; src2 = (int)param[0xe]<<8 | (int)param[0xf]; flags |= src1 & (S1_IDLE | S1_REV); flags |= src2<<2 & (S2_IDLE | S2_REV); src1 &= 0x3fff; src2 &= 0x3fff; bank = ((code & BANKBIT0) | (color & BANKBIT1)) << 8; pal_ptr = internal_palette; // the crossroad of fate if (code & BGLAYER || command & 7) goto COMMAND_MODE; // reject off-screen objects if (flags & MIRROR_Y) { flags |= FLIP_Y; y -= (h - 1); } if (flags & MIRROR_X) { flags |= FLIP_X; x -= (w - 1); } if (y > VIS_MAXY || (y + h) <= VIS_MINY) return; if (x > VIS_MAXX || (x + w) <= VIS_MINX) return; // clip objects against the visible area yclip = y; xclip = x; hclip = h; wclip = w; src_yskip = src_xskip = dst_skip = 0; if (yclip < VIS_MINY) { src_yskip = VIS_MINY - yclip; yclip = VIS_MINY; hclip -= src_yskip; } if (yclip + hclip > VIS_MAXY+1) { hclip = VIS_MAXY+1 - yclip; } if (xclip < VIS_MINX) { src_xskip = VIS_MINX - xclip; xclip = VIS_MINX; wclip -= src_xskip; } if (xclip + wclip > VIS_MAXX+1) { wclip = VIS_MAXX+1 - xclip; } dst_skip = (yclip << SCREEN_WIDTH_L2) + xclip; // adjust orientations eax = 0; if (flags & (S1_REV | S2_REV)) { flags ^= FLIP_Y | FLIP_X; eax -= w * h - 8; } if (flags & FLIP_Y) { eax += w * (h - 1); src_yskip = -src_yskip; src_dy = (flags & FLIP_X) ? -w + wclip : -w - wclip; } else src_dy = (flags & FLIP_X) ? w + wclip : w - wclip; if (flags & FLIP_X) { eax += w - 1; src_xskip = -src_xskip; src_dx = -1; } else src_dx = 1; // calculate entry points and loop constants src1_ptr = gfx_plane02 + ((bank + src1)<<3) + eax; src2_ptr = gfx_plane13 + ((bank + src2)<<3) + eax; if (!(flags & (S1_IDLE | S2_IDLE))) { eax = src_yskip * w + src_xskip; src1_ptr += eax; src2_ptr += eax; } else src_dy = src_dx = 0; dst_ptr = render_layer[layer] + dst_skip; // look up pen values and set rendering flags pen0 = code>>3 & 0x10; pen1 = 0; if (command == EFX1) { flags |= BACKMODE; pen0 |= SP_2BACK; } if (src1 == src2) { flags |= SINGLE_PEN; eax = (UINT32)penxlat[color & PENCOLOR]; if (eax) pen1 = pen0 + eax; } else if (color & PENCOLOR) flags |= RGB_MASK; //-------------------------------------------------------------------------- #define BLOCK_WIPE_COMMON { \ eax = wclip<<1; \ ecx = hclip; \ edi = dst_ptr; \ do { memset((UINT8*)edi, 0, eax); edi = (UINT8*)edi + SCREEN_BYTEWIDTH; } while (--ecx); } //-------------------------------------------------------------------------- // multi-pen block or transparent blit if ((flags & (SINGLE_PEN | RGB_MASK | COLOR_ON)) == COLOR_ON) { if (!(flags & IGNORE_0)) BLOCK_WIPE_COMMON dst_ptr += wclip; ecx = wclip = -wclip; edx = src_dx; if (flags & PPCD_ON) goto COLLISION_MODE; al = ah = (UINT8)pen0; if (!(flags & BACKMODE)) { do { do { al |= *src1_ptr; src1_ptr += edx; al |= *src2_ptr; src2_ptr += edx; if (al & 0xf) { dst_ptr[ecx] = (UINT16)al; al = ah;} } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } else { do { do { al |= *src1_ptr; src1_ptr += edx; al |= *src2_ptr; src2_ptr += edx; if (al & 0xf) { dst_ptr[ecx] = (UINT16)al | SP_2BACK; al = ah; } } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } return; COLLISION_MODE: ax = 0; if (group) { do { do { al = *src1_ptr; src1_ptr += edx; al |= *src2_ptr; src2_ptr += edx; if (al & 0xf) { dst_ptr[ecx] = (UINT16)al | SP_COLLD; } // set collision flag on group one pixels } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } else { do { do { al = *src1_ptr; src1_ptr += edx; al |= *src2_ptr; src2_ptr += edx; if (al & 0xf) { ax |= dst_ptr[ecx]; dst_ptr[ecx] = (UINT16)al; } // combine collision flags in ax } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } // update collision list if object collided with the other group if (status & ACTIVE && ax & SP_COLLD) { collision_list[collision_count & (MAX_SPRITES-1)] = offset; collision_count++; #if HALLEYS_DEBUG popmessage("ID:%02x CC:%3d", offset, collision_count); #endif } } else //-------------------------------------------------------------------------- // multi-pen, RGB masked block or transparent blit if ((flags & (RGB_MASK | COLOR_ON)) == RGB_MASK + COLOR_ON) { if (!(flags & IGNORE_0)) BLOCK_WIPE_COMMON dst_ptr += wclip; ecx = wclip = -wclip; al = ah = (UINT8)pen0; ebx = rgbmask[color & PENCOLOR] | 0xffffff00; do { do { al |= *src1_ptr; src1_ptr += src_dx; al |= *src2_ptr; src2_ptr += src_dx; if (al & 0xf) { edx = (UINT32)al; al = ah; dst_ptr[ecx] = pal_ptr[edx] & ebx; } } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } else //-------------------------------------------------------------------------- // single-pen block or transparent blit if ((flags & (SINGLE_PEN | COLOR_ON)) == SINGLE_PEN + COLOR_ON) { if (!(flags & IGNORE_0)) BLOCK_WIPE_COMMON dst_ptr += wclip; ebx = hclip; ecx = wclip = -wclip; edx = src_dx; ax = (UINT16)pen1; do { do { if (*src1_ptr) dst_ptr[ecx] = ax; src1_ptr += edx; } while (++ecx); ecx = wclip; src1_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--ebx); } else //-------------------------------------------------------------------------- // transparent wipe if ((flags & (IGNORE_0 | COLOR_ON)) == IGNORE_0) { dst_ptr += wclip; wclip = -wclip; ecx = wclip; edx = src_dx; if (flags & PPCD_ON && !group) { // preserve collision flags when wiping group zero objects do { do { al = *src1_ptr; ah = *src2_ptr; src1_ptr += edx; src2_ptr += edx; if (al | ah) dst_ptr[ecx] &= SP_COLLD; } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } else { do { do { al = *src1_ptr; ah = *src2_ptr; src1_ptr += edx; src2_ptr += edx; if (al | ah) dst_ptr[ecx] = 0; } while (++ecx); ecx = wclip; src1_ptr += src_dy; src2_ptr += src_dy; dst_ptr += SCREEN_WIDTH; } while (--hclip); } } else //-------------------------------------------------------------------------- // block wipe if ((flags & (IGNORE_0 | COLOR_ON)) == 0) BLOCK_WIPE_COMMON //-------------------------------------------------------------------------- // End of Standard Mode return; //-------------------------------------------------------------------------- COMMAND_MODE: #define GFX_HI 0x10000 // reject illegal blits and adjust parameters if (command) { if (h > 8) return; if (y >= 0xf8) { y -= 0xf8; flags |= SY_HIGH; } else if (y >= 8) return; if (command != TILEPASS1) { h <<= 5; y <<= 5; } } // calculate entry points and loop constants if (flags & S1_IDLE) src_dx = 0; else src_dx = 1; if (flags & S1_REV ) src_dx = -src_dx; src_base = gfx1_base + bank; if (command == STARPASS1 || command == STARPASS2) layer = (layer & 1) + 4; dst_base = render_layer[layer]; //-------------------------------------------------------------------------- #define WARP_WIPE_COMMON { \ ebx = y + h; \ ecx = (x + w - SCREEN_WIDTH) << 1; \ for (edx=y; edx 0) { memset(dst_ptr, 0, ecx); eax = SCREEN_WIDTH - x; } else eax = w; \ memset(dst_ptr+x, 0, eax<<1); } } //-------------------------------------------------------------------------- // specialized block wipe if ((flags & (IGNORE_0 | COLOR_ON)) == 0) { // wipe star layer when the following conditions are met: if (!command && y == 0xff && h == 1) { y = 0; h = SCREEN_HEIGHT; dst_base = render_layer[(layer&1)+4]; WARP_WIPE_COMMON stars_enabled = ~layer & 1; } // wipe background and chain-wipe corresponding sprite layer when the command is zero else { WARP_WIPE_COMMON if (!command) { dst_base = render_layer[layer&1]; WARP_WIPE_COMMON } } } else //-------------------------------------------------------------------------- // gray shaded star map with 16x16 cells if (command == STARPASS1 && flags & COLOR_ON) { /* Each star map is generated by two data sets pointed by the second source address. The first 256-byte set has scattered bits to reflect the star population while the second 256-byte set appears to have random values. When the game runs the the star fields are updated a small portion at a time by a third data set containing gradient patterns which may indicate gray shades or alpha levels. Halley's Comet draws and clears the two star fields as if they are independent from the backgrounds, making it a total of four scrollable layers. However, only two pairs of scroll registers are in use and they affect the stars and the backgrounds together - possibly afterthoughts on the original Ben Bero Beh hardware. This algorithm is based on speculation and deemed inaccurate. */ #define RORB(R,N) ( ((R>>N)|(R<<(8-N))) & 0xff ) #define C2S(X,Y,O) ( (((Y+(O>>4))&YMASK)< 0xf8) return; if (code & PLANE) return; /* WARNING: UNEMULATED */ if (flags & IGNORE_0) { w=8; h=8; WARP_WIPE_COMMON } src1_ptr = src_base + src1; dst_ptr = render_layer[2] + (y << SCREEN_WIDTH_L2); src1_ptr += 8; edx = -8; if (x <= 0xf8) { dst_ptr += x; do { ax = (UINT16)src1_ptr[edx]; al = src1_ptr[edx+0x10000]; ax |= BG_RGB; if (al & 0x01) *dst_ptr = ax; if (al & 0x02) dst_ptr[1] = ax; if (al & 0x04) dst_ptr[2] = ax; if (al & 0x08) dst_ptr[3] = ax; if (al & 0x10) dst_ptr[4] = ax; if (al & 0x20) dst_ptr[5] = ax; if (al & 0x40) dst_ptr[6] = ax; if (al & 0x80) dst_ptr[7] = ax; dst_ptr += SCREEN_WIDTH; } while (++edx); } else { #define WARPMASK ((SCREEN_WIDTH<<1)-1) do { ecx = x & WARPMASK; ax = (UINT16)src1_ptr[edx]; al = src1_ptr[edx+0x10000]; ax |= BG_RGB; if (al & 0x01) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x02) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x04) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x08) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x10) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x20) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x40) dst_ptr[ecx] = ax; ecx++; ecx &= WARPMASK; if (al & 0x80) dst_ptr[ecx] = ax; dst_ptr += SCREEN_WIDTH; } while (++edx); #undef WARPMASK } } else //-------------------------------------------------------------------------- // RGB horizontal bar(foreground only) if (command == HORIZBAR && flags & COLOR_ON && !(layer & 1)) { #define WARP_LINE_COMMON { \ if (ecx & 1) { ecx--; *dst_ptr = (UINT16)eax; dst_ptr++; } \ dst_ptr += ecx; ecx = -ecx; \ while (ecx) { *(UINT32*)(dst_ptr+ecx) = eax; ecx += 2; } } src1_ptr = src_base + src1; src2_ptr = src_base + src2; hclip = y + h; if (!(flags & S2_IDLE)) { // double source mode src2_ptr += GFX_HI; wclip = x + w; w = 32; } else { // single source mode if (color & 4) src1_ptr += GFX_HI; wclip = 32; } for (xclip=x; xclip 0) { ecx = edx; dst_ptr = (UINT16*)edi; WARP_LINE_COMMON ecx = SCREEN_WIDTH - xclip; } else ecx = w; dst_ptr = (UINT16*)edi + xclip; WARP_LINE_COMMON } edi = src1_ptr; src1_ptr = src2_ptr; src2_ptr = (UINT8*)edi; } #undef WARP_LINE_COMMON } //-------------------------------------------------------------------------- } // end of blit() // draws Ben Bero Beh's color backdrop(verification required) static WRITE8_HANDLER( bgtile_w ) { int yskip, xskip, ecx; UINT16 *edi; UINT16 ax; cpu1_base[0x1f00+offset] = data; offset -= 0x18; if (offset >= 191) return; yskip = offset / 48; xskip = offset % 48; if (xskip > 43) return; yskip = yskip * 48 + 24; xskip = xskip * 5 + 2; edi = render_layer[2] + (yskip<>2&0x03) | BG_RGB; for (count=0; count<16; count++) { r = i << 4; g = r + count + BG_MONO; r += i; pal_ptr[g] = d; palette_set_color(machine, g, MAKE_RGB(r, r, r)); } } // 1280-1535: RGB for (d=0; d<256; d++) { j = d + BG_RGB; pal_ptr[j] = j; i = d>>6 & 0x03; r = d>>2 & 0x0c; r |= i; g = d & 0x0c; g |= i; b = d<<2 & 0x0c; b |= i; palette_set_color_rgb(machine, j, pal4bit(r), pal4bit(g), pal4bit(b)); } } static void halleys_decode_rgb(running_machine *machine, UINT32 *r, UINT32 *g, UINT32 *b, int addr, int data) { /* proms contain: 00 00 00 00 c5 0b f3 17 fd cf 1f ef df bf 7f ff 00 00 00 00 01 61 29 26 0b f5 e2 17 57 fb cf f7 */ int latch1_273, latch2_273; UINT8 *sram_189; UINT8 *prom_6330; int bit0, bit1, bit2, bit3, bit4; // the four 16x4-bit SN74S189 SRAM chips are assumed be the game's 32-byte palette RAM sram_189 = paletteram; // each of the three 32-byte 6330 PROM is wired to an RGB component output prom_6330 = memory_region(machine, "proms"); // latch1 holds 8 bits from the selected palette RAM address latch1_273 = sram_189[addr]; // latch2 holds another 8 bits from somewhere on the data bus in a bit-swapped manner(inaccurate) latch2_273 = (data>>4 & 0x0f)|(data<<1 & 0x10)|(data<<3 & 0x20)|(data<<5 & 0x40)|(data<<7 & 0x80); // data from latch1 and 2 are combined and then decoded through PROMs to form three 8-bit tripplets bit0 = latch1_273>>5 & 0x01; bit1 = latch1_273>>3 & 0x02; bit2 = latch1_273>>5 & 0x04; bit3 = latch1_273>>3 & 0x08; bit4 = latch2_273>>2 & 0x10; *r = prom_6330[0x00 + (bit0|bit1|bit2|bit3|bit4)]; bit2 = latch1_273>>0 & 0x04; bit3 = latch1_273>>0 & 0x08; bit4 = latch2_273>>3 & 0x10; *g = prom_6330[0x20 + (bit0|bit1|bit2|bit3|bit4)]; bit2 = latch1_273<<2 & 0x04; bit3 = latch1_273<<2 & 0x08; bit4 = latch2_273<<1 & 0x10; *b = prom_6330[0x40 + (bit0|bit1|bit2|bit3|bit4)]; } static WRITE8_HANDLER( halleys_paletteram_IIRRGGBB_w ) { UINT32 d, r, g, b, i, j; UINT32 *pal_ptr = internal_palette; paletteram[offset] = data; d = (UINT32)data; j = d | BG_RGB; pal_ptr[offset] = j; pal_ptr[offset+SP_2BACK] = j; pal_ptr[offset+SP_ALPHA] = j; pal_ptr[offset+SP_COLLD] = j; // 8-bit RGB format: IIRRGGBB i = d>>6 & 0x03; r = d>>2 & 0x0c; r |= i; r = r<<4 | r; g = d & 0x0c; g |= i; g = g<<4 | g; b = d<<2 & 0x0c; b |= i; b = b<<4 | b; palette_set_color(machine, offset, MAKE_RGB(r, g, b)); palette_set_color(machine, offset+SP_2BACK, MAKE_RGB(r, g, b)); palette_set_color(machine, offset+SP_ALPHA, MAKE_RGB(r, g, b)); palette_set_color(machine, offset+SP_COLLD, MAKE_RGB(r, g, b)); halleys_decode_rgb(machine, &r, &g, &b, offset, 0); palette_set_color(machine, offset+0x20, MAKE_RGB(r, g, b)); } static VIDEO_START( halleys ) { #define HALLEYS_Y0 0x8e #define HALLEYS_X0 0x9a #define HALLEYS_Y1 0xa2 #define HALLEYS_X1 0xa3 int dst, src, c; // create short cuts to scroll registers scrolly0 = io_ram + HALLEYS_Y0; scrollx0 = io_ram + HALLEYS_X0; scrolly1 = io_ram + HALLEYS_Y1; scrollx1 = io_ram + HALLEYS_X1; // fill alpha table for (src=0; src<256; src++) for (dst=0; dst<256; dst++) { c = (((src&0xc0)+(dst&0xc0))>>1) & 0xc0; c += (((src&0x30)+(dst&0x30))>>1) & 0x30; c += (((src&0x0c)+(dst&0x0c))>>1) & 0x0c; c += (((src&0x03)+(dst&0x03))>>1) & 0x03; alpha_table[(src<<8)+dst] = c | BG_RGB; } } static void copy_scroll_op(bitmap_t *bitmap, UINT16 *source, int sx, int sy) { //-------------------------------------------------------------------------- #define OPCOPY_COMMON { \ memcpy(edi, esi+sx, rcw); \ memcpy((UINT8*)edi+rcw, esi, CLIP_BYTEW-rcw); \ esi += SCREEN_WIDTH; \ edi += edx; } //-------------------------------------------------------------------------- UINT16 *esi, *edi; int rcw, bch, ecx, edx; sx = -sx & 0xff; sy = -sy & 0xff; if ((rcw = CLIP_W - sx) < 0) rcw = 0; else rcw <<= 1; if ((bch = CLIP_H - sy) < 0) bch = 0; esi = source + CLIP_SKIP + (sy << SCREEN_WIDTH_L2); edi = BITMAP_ADDR16(bitmap, VIS_MINY, VIS_MINX); edx = bitmap->rowpixels; // draw top split for (ecx=bch; ecx; ecx--) OPCOPY_COMMON esi = source + CLIP_SKIP; // draw bottom split for (ecx=CLIP_H-bch; ecx; ecx--) OPCOPY_COMMON #undef OPCOPY_COMMON } static void copy_scroll_xp(bitmap_t *bitmap, UINT16 *source, int sx, int sy) { //-------------------------------------------------------------------------- #define XCOPY_COMMON \ if (ecx) { \ if (ecx & 1) { ecx--; ax = *esi; esi++; if (ax) *edi = ax; edi++; } \ esi += ecx; edi += ecx; ecx = -ecx; \ while (ecx) { \ ax = esi[ecx]; \ bx = esi[ecx+1]; \ if (ax) edi[ecx] = ax; \ if (bx) edi[ecx+1] = bx; \ ecx += 2; } } //-------------------------------------------------------------------------- #define YCOPY_COMMON { \ esi = src_base + sx; ecx = rcw; XCOPY_COMMON \ esi = src_base; ecx = CLIP_W - rcw; XCOPY_COMMON \ src_base += SCREEN_WIDTH; \ edi += dst_adv; } //-------------------------------------------------------------------------- int rcw, bch, dst_adv; UINT16 *src_base, *esi, *edi; int ecx, edx; UINT16 ax, bx; sx = -sx & 0xff; sy = -sy & 0xff; if ((rcw = CLIP_W - sx) < 0) rcw = 0; if ((bch = CLIP_H - sy) < 0) bch = 0; src_base = source + CLIP_SKIP + (sy << SCREEN_WIDTH_L2); edi = BITMAP_ADDR16(bitmap, VIS_MINY, VIS_MINX); dst_adv = bitmap->rowpixels - CLIP_W; // draw top split for (edx=bch; edx; edx--) YCOPY_COMMON src_base = source + CLIP_SKIP; // draw bottom split for (edx=CLIP_H-bch; edx; edx--) YCOPY_COMMON #undef XCOPY_COMMON #undef YCOPY_COMMON } static void copy_fixed_xp(bitmap_t *bitmap, UINT16 *source) { UINT16 *esi, *edi; int dst_pitch, ecx, edx; UINT16 ax, bx; esi = source + CLIP_SKIP + CLIP_W; edi = BITMAP_ADDR16(bitmap, VIS_MINY, VIS_MINX + CLIP_W); dst_pitch = bitmap->rowpixels; ecx = -CLIP_W; edx = CLIP_H; do { do { ax = esi[ecx]; bx = esi[ecx+1]; if (ax) edi[ecx ] = ax; ax = esi[ecx+2]; if (bx) edi[ecx+1] = bx; bx = esi[ecx+3]; if (ax) edi[ecx+2] = ax; ax = esi[ecx+4]; if (bx) edi[ecx+3] = bx; bx = esi[ecx+5]; if (ax) edi[ecx+4] = ax; ax = esi[ecx+6]; if (bx) edi[ecx+5] = bx; bx = esi[ecx+7]; if (ax) edi[ecx+6] = ax; if (bx) edi[ecx+7] = bx; } while (ecx += 8); ecx = -CLIP_W; esi += SCREEN_WIDTH; edi += dst_pitch; } while (--edx); } static void copy_fixed_2b(bitmap_t *bitmap, UINT16 *source) { UINT16 *esi, *edi; int dst_pitch, ecx, edx; UINT16 ax, bx; esi = source + CLIP_SKIP + CLIP_W; edi = BITMAP_ADDR16(bitmap, VIS_MINY, VIS_MINX + CLIP_W); dst_pitch = bitmap->rowpixels; ecx = -CLIP_W; edx = CLIP_H; do { do { ax = esi[ecx]; bx = esi[ecx+1]; if (!(ax)) goto SKIP0; if (!(ax&SP_2BACK)) goto DRAW0; if (edi[ecx ]) goto SKIP0; DRAW0: edi[ecx ] = ax; SKIP0: ax = esi[ecx+2]; if (!(bx)) goto SKIP1; if (!(bx&SP_2BACK)) goto DRAW1; if (edi[ecx+1]) goto SKIP1; DRAW1: edi[ecx+1] = bx; SKIP1: bx = esi[ecx+3]; if (!(ax)) goto SKIP2; if (!(ax&SP_2BACK)) goto DRAW2; if (edi[ecx+2]) goto SKIP2; DRAW2: edi[ecx+2] = ax; SKIP2: ax = esi[ecx+4]; if (!(bx)) goto SKIP3; if (!(bx&SP_2BACK)) goto DRAW3; if (edi[ecx+3]) goto SKIP3; DRAW3: edi[ecx+3] = bx; SKIP3: bx = esi[ecx+5]; if (!(ax)) goto SKIP4; if (!(ax&SP_2BACK)) goto DRAW4; if (edi[ecx+4]) goto SKIP4; DRAW4: edi[ecx+4] = ax; SKIP4: ax = esi[ecx+6]; if (!(bx)) goto SKIP5; if (!(bx&SP_2BACK)) goto DRAW5; if (edi[ecx+5]) goto SKIP5; DRAW5: edi[ecx+5] = bx; SKIP5: bx = esi[ecx+7]; if (!(ax)) goto SKIP6; if (!(ax&SP_2BACK)) goto DRAW6; if (edi[ecx+6]) goto SKIP6; DRAW6: edi[ecx+6] = ax; SKIP6: if (!(bx)) continue; if (!(bx&SP_2BACK)) goto DRAW7; if (edi[ecx+7]) continue; DRAW7: edi[ecx+7] = bx; } while (ecx += 8); ecx = -CLIP_W; esi += SCREEN_WIDTH; edi += dst_pitch; } while (--edx); } static void filter_bitmap(bitmap_t *bitmap, int mask) { int dst_pitch; UINT32 *pal_ptr, *edi; int esi, eax, ebx, ecx, edx; pal_ptr = internal_palette; esi = mask | 0xffffff00; edi = (UINT32*)BITMAP_ADDR16(bitmap, VIS_MINY, VIS_MINX + CLIP_W); dst_pitch = bitmap->rowpixels >> 1; ecx = -(CLIP_W>>1); edx = CLIP_H; do { do { eax = edi[ecx]; if (eax & 0x00ff00ff) { ebx = eax; eax >>= 16; ebx &= 0xffff; eax = pal_ptr[eax]; ebx = pal_ptr[ebx]; eax &= esi; ebx &= esi; eax <<= 16; ebx |= eax; edi[ecx] = ebx; } } while (++ecx); ecx = -(CLIP_W>>1); edi += dst_pitch; } while (--edx); } static VIDEO_UPDATE( halleys ) { int i, j; if (stars_enabled) { copy_scroll_op(bitmap, render_layer[5], *scrollx0, *scrolly0); copy_scroll_xp(bitmap, render_layer[4], *scrollx1, *scrolly1); } else fillbitmap(bitmap, bgcolor, cliprect); #ifdef MAME_DEBUG if (input_port_read(screen->machine, "DEBUG")) copy_scroll_xp(bitmap, render_layer[3], *scrollx0, *scrolly0); // not used??? #endif copy_scroll_xp(bitmap, render_layer[2], *scrollx1, *scrolly1); copy_fixed_2b (bitmap, render_layer[1]); copy_fixed_xp (bitmap, render_layer[0]); // HALF-HACK: apply RGB filter when the following conditions are met i = io_ram[0xa0]; j = io_ram[0xa1]; if (io_ram[0x2b] && (i>0xc6 && i<0xfe) && (j==0xc0 || j==0xed)) filter_bitmap(bitmap, i); return 0; } static VIDEO_UPDATE( benberob ) { if (io_ram[0xa0] & 0x80) copy_scroll_op(bitmap, render_layer[2], *scrollx1, *scrolly1); else fillbitmap(bitmap, bgcolor, cliprect); copy_fixed_xp (bitmap, render_layer[1]); copy_fixed_xp (bitmap, render_layer[0]); return 0; } //************************************************************************** // Debug and Test Handlers #if HALLEYS_DEBUG static READ8_HANDLER( zero_r ) { return(0); } static READ8_HANDLER( debug_r ) { return(io_ram[offset]); } #endif //************************************************************************** // Interrupt and Hardware Handlers static INTERRUPT_GEN( halleys_interrupt ) { static int latch_delay = 0; UINT8 latch_data; switch (cpu_getiloops()) { case 0: /* How the custom chips handle sound latching is largely unknown. Halley's Comet dumps sound commands to register ff8a so rapidly the AY8910 core sometimes fails to reset itself and the music stops. Masking sound NMI is not enough to ensure successive writes are processed properly so it is advisable to queue sound commands or make the main CPU yield for a minimum of 600 Z80 cycles. Furthermore, soundlatch NMI interval should not be too much shorter than music IRQ's period(27306667ns), and must be longer in case of a reset(00). Current implementation is quite safe although not 100% foul-proof. */ if (latch_delay) latch_delay--; else if (ffcount) { ffcount--; latch_data = sound_fifo[fftail]; fftail = (fftail + 1) & (MAX_SOUNDS - 1); latch_delay = (latch_data) ? 0 : 4; soundlatch_w(machine, 0, latch_data); cpunum_set_input_line(machine, 1, INPUT_LINE_NMI, PULSE_LINE); } // clear collision list of this frame unconditionally collision_count = 0; break; // In Halley's Comet, NMI is used exclusively to handle coin input case 1: cpunum_set_input_line(machine, 0, INPUT_LINE_NMI, PULSE_LINE); break; // FIRQ drives gameplay; we need both types of NMI each frame. case 2: mVectorType = 1; cpunum_set_input_line(machine, 0, M6809_FIRQ_LINE, ASSERT_LINE); break; case 3: mVectorType = 0; cpunum_set_input_line(machine, 0, M6809_FIRQ_LINE, ASSERT_LINE); break; } } static INTERRUPT_GEN( benberob_interrupt ) { static int latch_delay = 0; UINT8 latch_data; switch (cpu_getiloops()) { case 0: if (latch_delay) latch_delay--; else if (ffcount) { ffcount--; latch_data = sound_fifo[fftail]; fftail = (fftail + 1) & (MAX_SOUNDS - 1); latch_delay = (latch_data) ? 0 : 4; soundlatch_w(machine, 0, latch_data); cpunum_set_input_line(machine, 1, INPUT_LINE_NMI, PULSE_LINE); } break; case 1: cpunum_set_input_line(machine, 0, INPUT_LINE_NMI, PULSE_LINE); break; case 2: case 3: // FIRQ must not happen when the blitter is being updated or it'll cause serious screen artifacts if (!blitter_busy) cpunum_set_input_line(machine, 0, M6809_FIRQ_LINE, ASSERT_LINE); else firq_level++; break; } } static READ8_HANDLER( vector_r ) { return(cpu1_base[0xffe0 + (offset^(mVectorType<<4))]); } static WRITE8_HANDLER( firq_ack_w ) { io_ram[0x9c] = data; if (firq_level) firq_level--; cpunum_set_input_line(machine, 0, M6809_FIRQ_LINE, CLEAR_LINE); } static WRITE8_HANDLER( sndnmi_msk_w ) { sndnmi_mask = data & 1; } static WRITE8_HANDLER( soundcommand_w ) { if (ffcount < MAX_SOUNDS) { ffcount++; sound_fifo[ffhead] = io_ram[0x8a] = data; ffhead = (ffhead + 1) & (MAX_SOUNDS - 1); } } static READ8_HANDLER( coin_lockout_r ) { // This is a hack, but it lets you coin up when COIN1 or COIN2 are signaled. // See NMI for the twisted logic that is involved in handling coin input : // 0x8599 : 'benberob' // 0x83e2 : 'halleys', 'halleysc', 'halleycj' // 0x83df : 'halley87' int inp = input_port_read(machine, "IN0"); int result = ((input_port_read(machine, "DSW4")) & 0x20) >> 5; if (inp & 0x80) result |= 0x02; if (inp & 0x40) result |= 0x04; return(result); } static READ8_HANDLER( io_mirror_r ) { static const char *const portnames[] = { "IN0", "IN1", "IN2", "IN3" }; return input_port_read(machine, portnames[offset]); } //************************************************************************** // Memory Maps static ADDRESS_MAP_START( readmem, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x0fff) AM_READ(blitter_r) AM_RANGE(0x1000, 0xefff) AM_READ(SMH_ROM) AM_RANGE(0xf000, 0xfeff) AM_READ(SMH_RAM) // work ram AM_RANGE(0xff66, 0xff66) AM_READ(collision_id_r) // HACK: collision detection bypass(Halley's Comet only) AM_RANGE(0xff71, 0xff71) AM_READ(blitter_status_r) AM_RANGE(0xff80, 0xff83) AM_READ(io_mirror_r) AM_RANGE(0xff90, 0xff90) AM_READ_PORT("IN0") // coin/start AM_RANGE(0xff91, 0xff91) AM_READ_PORT("IN1") // player 1 AM_RANGE(0xff92, 0xff92) AM_READ_PORT("IN2") // player 2 AM_RANGE(0xff93, 0xff93) AM_READ_PORT("IN3") // unused? AM_RANGE(0xff94, 0xff94) AM_READ(coin_lockout_r) AM_RANGE(0xff95, 0xff95) AM_READ_PORT("DSW1") // dipswitch 4 AM_RANGE(0xff96, 0xff96) AM_READ_PORT("DSW2") // dipswitch 3 AM_RANGE(0xff97, 0xff97) AM_READ_PORT("DSW3") // dipswitch 2 AM_RANGE(0xff00, 0xffbf) AM_READ(SMH_RAM) // I/O read fall-through AM_RANGE(0xffc0, 0xffdf) AM_READ(SMH_RAM) // palette read AM_RANGE(0xffe0, 0xffff) AM_READ(vector_r) ADDRESS_MAP_END static ADDRESS_MAP_START( writemem, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x0fff) AM_WRITE(blitter_w) AM_BASE(&blitter_ram) AM_SIZE(&blitter_ramsize) AM_RANGE(0x1f00, 0x1fff) AM_WRITE(bgtile_w) // background tiles?(Ben Bero Beh only) AM_RANGE(0x1000, 0xefff) AM_WRITE(SMH_ROM) AM_RANGE(0xf000, 0xfeff) AM_WRITE(SMH_RAM) // work ram AM_RANGE(0xff8a, 0xff8a) AM_WRITE(soundcommand_w) AM_RANGE(0xff9c, 0xff9c) AM_WRITE(firq_ack_w) AM_RANGE(0xff00, 0xffbf) AM_WRITE(SMH_RAM) AM_BASE(&io_ram) AM_SIZE(&io_ramsize) // I/O write fall-through AM_RANGE(0xffc0, 0xffdf) AM_WRITE(halleys_paletteram_IIRRGGBB_w) AM_BASE(&paletteram) AM_RANGE(0xffe0, 0xffff) AM_WRITE(SMH_ROM) ADDRESS_MAP_END static ADDRESS_MAP_START( sound_readmem, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x3fff) AM_READ(SMH_ROM) AM_RANGE(0x4000, 0x47ff) AM_READ(SMH_RAM) AM_RANGE(0x4801, 0x4801) AM_READ(ay8910_read_port_1_r) AM_RANGE(0x4803, 0x4803) AM_READ(ay8910_read_port_2_r) AM_RANGE(0x4805, 0x4805) AM_READ(ay8910_read_port_3_r) AM_RANGE(0x5000, 0x5000) AM_READ(soundlatch_r) AM_RANGE(0xe000, 0xefff) AM_READ(SMH_ROM) // space for diagnostic ROM ADDRESS_MAP_END static ADDRESS_MAP_START( sound_writemem, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x3fff) AM_WRITE(SMH_ROM) AM_RANGE(0x4000, 0x47ff) AM_WRITE(SMH_RAM) AM_RANGE(0x4800, 0x4800) AM_WRITE(ay8910_control_port_1_w) AM_RANGE(0x4801, 0x4801) AM_WRITE(ay8910_write_port_1_w) AM_RANGE(0x4802, 0x4802) AM_WRITE(ay8910_control_port_2_w) AM_RANGE(0x4803, 0x4803) AM_WRITE(ay8910_write_port_2_w) AM_RANGE(0x4804, 0x4804) AM_WRITE(ay8910_control_port_3_w) AM_RANGE(0x4805, 0x4805) AM_WRITE(ay8910_write_port_3_w) AM_RANGE(0xe000, 0xefff) AM_WRITE(SMH_ROM) ADDRESS_MAP_END //************************************************************************** // Port Maps static INPUT_PORTS_START( benberob ) PORT_START("DSW1") /* 0xff95 */ PORT_DIPNAME( 0x03, 0x03, DEF_STR( Bonus_Life ) ) /* code at 0xb00e */ PORT_DIPSETTING( 0x02, "Every 100k" ) PORT_DIPSETTING( 0x03, "100k 300k 200k+" ) PORT_DIPSETTING( 0x00, "100k 200k" ) PORT_DIPSETTING( 0x01, "150k 300k" ) PORT_DIPNAME( 0x04, 0x04, DEF_STR( Free_Play ) ) PORT_DIPSETTING( 0x04, DEF_STR( No ) ) PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) PORT_DIPNAME( 0x18, 0x08, DEF_STR( Lives ) ) PORT_DIPSETTING( 0x08, "3" ) PORT_DIPSETTING( 0x10, "4" ) PORT_DIPSETTING( 0x18, "5" ) PORT_DIPSETTING( 0x00, "Infinite (Cheat)" ) PORT_DIPUNKNOWN( 0x20, IP_ACTIVE_LOW ) PORT_DIPNAME( 0x40, 0x40, DEF_STR( Flip_Screen ) ) /* TO DO : confirm OFF/ON when screen flipping emulated */ PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, DEF_STR( Cabinet ) ) PORT_DIPSETTING( 0x80, DEF_STR( Upright ) ) PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ) ) PORT_START("DSW2") /* 0xff96 */ PORT_DIPNAME( 0x0f, 0x00, DEF_STR( Coin_A ) ) PORT_DIPSETTING( 0x0f, DEF_STR( 9C_1C ) ) PORT_DIPSETTING( 0x0e, DEF_STR( 8C_1C ) ) PORT_DIPSETTING( 0x0d, DEF_STR( 7C_1C ) ) PORT_DIPSETTING( 0x0c, DEF_STR( 6C_1C ) ) PORT_DIPSETTING( 0x0b, DEF_STR( 5C_1C ) ) PORT_DIPSETTING( 0x0a, DEF_STR( 4C_1C ) ) PORT_DIPSETTING( 0x09, DEF_STR( 3C_1C ) ) PORT_DIPSETTING( 0x08, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x01, DEF_STR( 1C_2C ) ) PORT_DIPSETTING( 0x02, DEF_STR( 1C_3C ) ) PORT_DIPSETTING( 0x03, DEF_STR( 1C_4C ) ) PORT_DIPSETTING( 0x04, DEF_STR( 1C_5C ) ) PORT_DIPSETTING( 0x05, DEF_STR( 1C_6C ) ) PORT_DIPSETTING( 0x06, DEF_STR( 1C_7C ) ) PORT_DIPSETTING( 0x07, DEF_STR( 1C_8C ) ) PORT_DIPNAME( 0xf0, 0x00, DEF_STR( Coin_B ) ) PORT_DIPSETTING( 0xf0, DEF_STR( 9C_1C ) ) PORT_DIPSETTING( 0xe0, DEF_STR( 8C_1C ) ) PORT_DIPSETTING( 0xd0, DEF_STR( 7C_1C ) ) PORT_DIPSETTING( 0xc0, DEF_STR( 6C_1C ) ) PORT_DIPSETTING( 0xb0, DEF_STR( 5C_1C ) ) PORT_DIPSETTING( 0xa0, DEF_STR( 4C_1C ) ) PORT_DIPSETTING( 0x90, DEF_STR( 3C_1C ) ) PORT_DIPSETTING( 0x80, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) ) PORT_DIPSETTING( 0x20, DEF_STR( 1C_3C ) ) PORT_DIPSETTING( 0x30, DEF_STR( 1C_4C ) ) PORT_DIPSETTING( 0x40, DEF_STR( 1C_5C ) ) PORT_DIPSETTING( 0x50, DEF_STR( 1C_6C ) ) PORT_DIPSETTING( 0x60, DEF_STR( 1C_7C ) ) PORT_DIPSETTING( 0x70, DEF_STR( 1C_8C ) ) PORT_START("DSW3") /* 0xff97 */ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Difficulty ) ) PORT_DIPSETTING( 0x01, DEF_STR( Easy ) ) PORT_DIPSETTING( 0x00, DEF_STR( Hard ) ) PORT_DIPNAME( 0x02, 0x00, "Use Both Buttons" ) PORT_DIPSETTING( 0x02, DEF_STR( No ) ) PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) PORT_DIPNAME( 0x0c, 0x0c, "Timer Speed" ) /* table at 0xb10e */ PORT_DIPSETTING( 0x0c, "Slowest" ) PORT_DIPSETTING( 0x08, "Slow" ) PORT_DIPSETTING( 0x04, "Fast" ) PORT_DIPSETTING( 0x00, "Fastest" ) PORT_DIPNAME( 0x10, 0x10, "Show Coinage" ) PORT_DIPSETTING( 0x00, DEF_STR( No ) ) PORT_DIPSETTING( 0x10, DEF_STR( Yes ) ) PORT_DIPNAME( 0x20, 0x20, "Show Year" ) PORT_DIPSETTING( 0x00, DEF_STR( No ) ) PORT_DIPSETTING( 0x20, DEF_STR( Yes ) ) PORT_DIPNAME( 0x40, 0x40, "No Hit (Cheat)" ) PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, "Maximum Credits" ) PORT_DIPSETTING( 0x80, "9" ) PORT_DIPSETTING( 0x00, "16" ) PORT_START("DSW4") /* 0xff94 - read by coin_lockout_r */ PORT_DIPUNUSED( 0x01, IP_ACTIVE_LOW ) PORT_DIPUNUSED( 0x02, IP_ACTIVE_LOW ) PORT_DIPUNUSED( 0x04, IP_ACTIVE_LOW ) PORT_DIPUNUSED( 0x08, IP_ACTIVE_LOW ) PORT_DIPUNUSED( 0x10, IP_ACTIVE_LOW ) PORT_DIPNAME( 0x20, 0x20, "Coin Slots" ) PORT_DIPSETTING( 0x00, "1" ) PORT_DIPSETTING( 0x20, "2" ) PORT_DIPUNUSED( 0x40, IP_ACTIVE_LOW ) PORT_DIPUNUSED( 0x80, IP_ACTIVE_LOW ) PORT_START("IN0") /* 0xff90 */ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_TILT ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_IMPULSE(12) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_START("IN1") /* 0xff91 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_START("IN2") /* 0xff92 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_START("IN3") /* 0xff93 */ INPUT_PORTS_END static INPUT_PORTS_START( halleys ) PORT_START("DSW1") /* 0xff95 */ TAITO_MACHINE_COCKTAIL_LOC(SW4) TAITO_COINAGE_JAPAN_OLD_LOC(SW4) PORT_START("DSW2") /* 0xff96 */ TAITO_DIFFICULTY_LOC(SW3) PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Bonus_Life ) ) PORT_DIPLOCATION("SW3:3,4") /* index of tables at 0x1a2f or 0x19b5 */ PORT_DIPSETTING( 0x00, "100k 600k 500k+" ) /* last bonus life at 5600k : max. 12 bonus lives */ PORT_DIPSETTING( 0x0c, "200k 800k 600k+" ) /* last bonus life at 6800k : max. 12 bonus lives */ PORT_DIPSETTING( 0x08, "200k 1000k 800k+" ) /* last bonus life at 9000k : max. 12 bonus lives */ PORT_DIPSETTING( 0x04, "200k 1200k 1000k+" ) /* last bonus life at 9200k : max. 10 bonus lives */ PORT_DIPNAME( 0x30, 0x30, DEF_STR( Lives ) ) PORT_DIPLOCATION("SW3:5,6") PORT_DIPSETTING( 0x20, "2" ) PORT_DIPSETTING( 0x30, "3" ) PORT_DIPSETTING( 0x10, "4" ) PORT_DIPSETTING( 0x00, "4 (No Points Bonus Lives)" ) /* code at 0xa509 or 0xa502 - 3 in the US manual */ PORT_DIPNAME( 0x40, 0x40, "Operation Data Recorder" ) PORT_DIPLOCATION("SW3:7") /* from the US manual - what is this ? */ PORT_DIPSETTING( 0x40, "Not fixed" ) PORT_DIPSETTING( 0x00, "When fixed" ) PORT_DIPUNUSED_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW3:8" ) /* From US manual : "DIP SW 2 is not used and all contacts should be set off." However, they enable debug features if you press START1 during the boot sequence. */ PORT_START("DSW3") /* 0xff97 */ PORT_DIPUNUSED_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW2:1" ) PORT_DIPNAME( 0x02, 0x02, "Free Play (Cheat)" ) PORT_DIPLOCATION("SW2:2") PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x1c, 0x1c, "Start Area (Cheat)" ) PORT_DIPLOCATION("SW2:3,4,5") PORT_DIPSETTING( 0x1c, "1 (Earth)" ) PORT_DIPSETTING( 0x18, "4 (Venus)" ) PORT_DIPSETTING( 0x14, "7 (Mercury)" ) PORT_DIPSETTING( 0x10, "10 (Sun)" ) PORT_DIPSETTING( 0x0c, "13 (Pluto)" ) /* spelled "Plato" */ PORT_DIPSETTING( 0x08, "16 (Neptune)" ) PORT_DIPSETTING( 0x04, "19 (Uranus)" ) PORT_DIPSETTING( 0x00, "22 (Saturn)" ) PORT_DIPUNUSED_DIPLOC( 0x20, IP_ACTIVE_LOW, "SW2:6" ) PORT_DIPNAME( 0x40, 0x40, "Invincibility (Cheat)") PORT_DIPLOCATION("SW2:7") PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, "Infinite Lives (Cheat)" ) PORT_DIPLOCATION("SW2:8") PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) /* From US manual : "Coin mechs system can be optioned by setting DIP SW 1. Position 6 on for single coin selector. Position 6 off for twin coin selector." */ PORT_START("DSW4") /* 0xff94 - read by coin_lockout_r */ PORT_DIPUNUSED_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW1:1" ) PORT_DIPUNUSED_DIPLOC( 0x02, IP_ACTIVE_LOW, "SW1:2" ) PORT_DIPUNUSED_DIPLOC( 0x04, IP_ACTIVE_LOW, "SW1:3" ) PORT_DIPUNUSED_DIPLOC( 0x08, IP_ACTIVE_LOW, "SW1:4" ) PORT_DIPUNUSED_DIPLOC( 0x10, IP_ACTIVE_LOW, "SW1:5" ) PORT_DIPNAME( 0x20, 0x20, "Coin Slots" ) PORT_DIPLOCATION("SW1:6") PORT_DIPSETTING( 0x00, "1" ) PORT_DIPSETTING( 0x20, "2" ) PORT_DIPUNUSED_DIPLOC( 0x40, IP_ACTIVE_LOW, "SW1:7" ) PORT_DIPUNUSED_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW1:8" ) PORT_START("IN0") /* 0xff90 */ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_TILT ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_IMPULSE(12) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_START("IN1") /* 0xff91 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_START("IN2") /* 0xff92 */ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_START("IN3") /* 0xff93 */ #ifdef MAME_DEBUG PORT_START("DEBUG") /* just to be safe */ PORT_DIPNAME( 0x01, 0x00, "Show Unused Layer" ) PORT_DIPSETTING( 0x00, DEF_STR( No ) ) PORT_DIPSETTING( 0x01, DEF_STR( Yes ) ) #endif INPUT_PORTS_END //************************************************************************** // Machine Definitions and Initializations static MACHINE_RESET( halleys ) { mVectorType = 0; firq_level = 0; blitter_busy = 0; collision_count = 0; stars_enabled = 0; bgcolor = get_black_pen(machine); fftail = ffhead = ffcount = 0; memset(io_ram, 0xff, io_ramsize); memset(render_layer[0], 0, SCREEN_BYTESIZE * MAX_LAYERS); } static const ay8910_interface ay8910_config = { AY8910_LEGACY_OUTPUT, AY8910_DEFAULT_LOADS, NULL, NULL, NULL, sndnmi_msk_w // port Bwrite }; static MACHINE_DRIVER_START( halleys ) MDRV_CPU_ADD("main", M6809, XTAL_19_968MHz/12) /* verified on pcb */ MDRV_CPU_PROGRAM_MAP(readmem, writemem) MDRV_CPU_VBLANK_INT_HACK(halleys_interrupt, 4) MDRV_CPU_ADD("audio", Z80, XTAL_6MHz/2) /* verified on pcb */ MDRV_CPU_PROGRAM_MAP(sound_readmem, sound_writemem) MDRV_CPU_PERIODIC_INT(irq0_line_hold, (double)6000000/(4*16*16*10*16)) MDRV_MACHINE_RESET(halleys) // video hardware MDRV_SCREEN_ADD("main", RASTER) MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) MDRV_SCREEN_SIZE(SCREEN_WIDTH, SCREEN_HEIGHT) MDRV_SCREEN_VISIBLE_AREA(VIS_MINX, VIS_MAXX, VIS_MINY, VIS_MAXY) MDRV_PALETTE_LENGTH(PALETTE_SIZE) MDRV_PALETTE_INIT(halleys) MDRV_VIDEO_START(halleys) MDRV_VIDEO_UPDATE(halleys) // sound hardware MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD("ay1", AY8910, XTAL_6MHz/4) /* verified on pcb */ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15) MDRV_SOUND_ADD("ay2", AY8910, XTAL_6MHz/4) /* verified on pcb */ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15) MDRV_SOUND_ADD("ay3", AY8910, XTAL_6MHz/4) /* verified on pcb */ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15) MDRV_SOUND_ADD("ay4", AY8910, XTAL_6MHz/4) /* verified on pcb */ MDRV_SOUND_CONFIG(ay8910_config) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15) MACHINE_DRIVER_END static MACHINE_DRIVER_START( benberob ) MDRV_IMPORT_FROM(halleys) MDRV_CPU_REPLACE("main", M6809, XTAL_19_968MHz/12) /* not verified but pcb identical to halley's comet */ MDRV_CPU_VBLANK_INT_HACK(benberob_interrupt, 4) MDRV_VIDEO_UPDATE(benberob) MACHINE_DRIVER_END //************************************************************************** // ROM Definitions ROM_START( benberob ) ROM_REGION( 0x10000, "main", 0 ) //MAIN PRG ROM_LOAD( "a26_01.31", 0x4000, 0x4000, CRC(9ed566ba) SHA1(15c042e727b00b1dc6f24c72226d1a361fc0fa58) ) ROM_LOAD( "a26_02.52", 0x8000, 0x4000, CRC(a563a033) SHA1(c2c4a73f190303b7101e7849a638d35a80e4c36b) ) ROM_LOAD( "a26_03.50", 0xc000, 0x4000, CRC(975849ef) SHA1(2724c3b7cca724bee5ae8331037529bfd8285011) ) ROM_REGION( 0x10000, "audio", 0 ) //SOUND ROM_LOAD( "a26_12.5", 0x0000, 0x4000, CRC(7fd728f3) SHA1(772c14d9254e43a56f1e67ad4dd5d7840df50e34) ) ROM_REGION( 0x20000, "gfx1", ROMREGION_DISPOSE ) //CHR ROM_LOAD( "a26_06.78", 0x00000, 0x4000, CRC(79ae2e58) SHA1(726dbaf01dcb330a8a7bd69578b67ec48db01ae1) ) ROM_LOAD( "a26_07.77", 0x04000, 0x4000, CRC(fe976343) SHA1(68b655d00b1e7e72ab81974b39033f6c130dc829) ) ROM_LOAD( "a26_04.80", 0x08000, 0x4000, CRC(77d10723) SHA1(fd284de30c7740c56e7192e0d73a6939b8386538) ) ROM_LOAD( "a26_05.79", 0x0c000, 0x4000, CRC(098eebcc) SHA1(3dd82d92273b4d1ebbe0f81f6d367c8bc642815f) ) ROM_LOAD( "a26_10.89", 0x10000, 0x4000, CRC(3d406060) SHA1(f02df4957ad7ba59ac14fd0134d856b2a80c9342) ) ROM_LOAD( "a26_11.88", 0x14000, 0x4000, CRC(4561836a) SHA1(6bd582ddb980a1c0b1ed4981118d5a9c862ff89c) ) ROM_LOAD( "a26_08.91", 0x18000, 0x4000, CRC(7e63059d) SHA1(01e1e805fa2e05058ebd83aae95e26879b4a275d) ) ROM_LOAD( "a26_09.90", 0x1c000, 0x4000, CRC(ebd9a16c) SHA1(0230892f451cac310d5ad0d328cea0556b96157f) ) ROM_REGION( 0x0060, "proms", 0 ) //COLOR (all identical!) ROM_LOAD( "a26_13.r", 0x0000, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26_13.g", 0x0020, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26_13.b", 0x0040, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_END ROM_START( halleys ) ROM_REGION( 0x10000, "main", 0 ) //MAIN PRG ROM_LOAD( "a62_01.30", 0x0000, 0x4000, CRC(a5e82b3e) SHA1(c16c6a6c23a579454b8a2be4b951c35b04f2a856) ) ROM_LOAD( "a62_02.31", 0x4000, 0x4000, CRC(25f5bcd3) SHA1(9d72afe866df363d2ac33dab3ed6c3913f4de12d) ) ROM_LOAD( "a62-15.52", 0x8000, 0x4000, CRC(e65d8312) SHA1(29870fe0dbb30d23970a8a816849dc5807d70675) ) ROM_LOAD( "a62_04.50", 0xc000, 0x4000, CRC(fad74dfe) SHA1(92c0d42c5e186bc07c168ad581e52a5ae340c2b2) ) ROM_REGION( 0x10000, "audio", 0 ) //SOUND ROM_LOAD( "a62_13.5", 0x0000, 0x2000, CRC(7ce290db) SHA1(e3c72ba5d97cb07f0f72d2765a068af6fb5cca29) ) ROM_LOAD( "a62_14.4", 0x2000, 0x2000, CRC(ea74b1a2) SHA1(7be3b9e9d51cfa753ce97e92f7eebd9723fe5821) ) ROM_REGION( 0x20000, "gfx1", ROMREGION_DISPOSE ) ROM_LOAD( "a62_12.78", 0x00000, 0x4000, CRC(c5834a7a) SHA1(4a24b3fa707cde89ad5a52d4e994412fcf28e81f) ) ROM_LOAD( "a62_10.77", 0x04000, 0x4000, CRC(3ae7231e) SHA1(277f12570001d82104c79d3d0a58a0b57ed18778) ) ROM_LOAD( "a62_08.80", 0x08000, 0x4000, CRC(b9210dbe) SHA1(f72f2307e9acd2dd622a3efce71bd334b68a9b60) ) ROM_LOAD( "a62-16.79", 0x0c000, 0x4000, CRC(1165a622) SHA1(6a0b4a3eadf157f89c69b5202bd4f895f92a3ef1) ) //bad? ROM_LOAD( "a62_11.89", 0x10000, 0x4000, CRC(d0e9974e) SHA1(6826cfb4fbf098ed7b9d8b00e2684d7c85a13c11) ) ROM_LOAD( "a62_09.88", 0x14000, 0x4000, CRC(e93ef281) SHA1(8bfe1ecce1c7107a5bd1b43b531594c8cfc0719d) ) ROM_LOAD( "a62_07.91", 0x18000, 0x4000, CRC(64c95e8b) SHA1(4c3320a764b13a5751c0019c9fafb899ea2f908f) ) ROM_LOAD( "a62_05.90", 0x1c000, 0x4000, CRC(c3c877ef) SHA1(23180b106e50b7a2a230c5e9948832e5631972ae) ) ROM_REGION( 0x0060, "proms", 0 ) //COLOR (all identical!) ROM_LOAD( "a26-13.109", 0x0000, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.110", 0x0020, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.111", 0x0040, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_END ROM_START( halleycj ) ROM_REGION( 0x10000, "main", 0 ) //MAIN PRG ROM_LOAD( "a62_01.30", 0x0000, 0x4000, CRC(a5e82b3e) SHA1(c16c6a6c23a579454b8a2be4b951c35b04f2a856) ) ROM_LOAD( "a62_02.31", 0x4000, 0x4000, CRC(25f5bcd3) SHA1(9d72afe866df363d2ac33dab3ed6c3913f4de12d) ) ROM_LOAD( "a62_03-1.52", 0x8000, 0x4000, CRC(e2fffbe4) SHA1(a10ced7103a26fd6753765bf11b00ca018f49a48) ) ROM_LOAD( "a62_04.50", 0xc000, 0x4000, CRC(fad74dfe) SHA1(92c0d42c5e186bc07c168ad581e52a5ae340c2b2) ) ROM_REGION( 0x10000, "audio", 0 ) //SOUND ROM_LOAD( "a62_13.5", 0x0000, 0x2000, CRC(7ce290db) SHA1(e3c72ba5d97cb07f0f72d2765a068af6fb5cca29) ) ROM_LOAD( "a62_14.4", 0x2000, 0x2000, CRC(ea74b1a2) SHA1(7be3b9e9d51cfa753ce97e92f7eebd9723fe5821) ) ROM_REGION( 0x20000, "gfx1", ROMREGION_DISPOSE ) //CHR ROM_LOAD( "a62_12.78", 0x00000, 0x4000, CRC(c5834a7a) SHA1(4a24b3fa707cde89ad5a52d4e994412fcf28e81f) ) ROM_LOAD( "a62_10.77", 0x04000, 0x4000, CRC(3ae7231e) SHA1(277f12570001d82104c79d3d0a58a0b57ed18778) ) ROM_LOAD( "a62_08.80", 0x08000, 0x4000, CRC(b9210dbe) SHA1(f72f2307e9acd2dd622a3efce71bd334b68a9b60) ) ROM_LOAD( "a62_06.79", 0x0c000, 0x4000, CRC(600be9ca) SHA1(a705b10be37ee93908b1bbaf806cfe7955aa3ffc) ) ROM_LOAD( "a62_11.89", 0x10000, 0x4000, CRC(d0e9974e) SHA1(6826cfb4fbf098ed7b9d8b00e2684d7c85a13c11) ) ROM_LOAD( "a62_09.88", 0x14000, 0x4000, CRC(e93ef281) SHA1(8bfe1ecce1c7107a5bd1b43b531594c8cfc0719d) ) ROM_LOAD( "a62_07.91", 0x18000, 0x4000, CRC(64c95e8b) SHA1(4c3320a764b13a5751c0019c9fafb899ea2f908f) ) ROM_LOAD( "a62_05.90", 0x1c000, 0x4000, CRC(c3c877ef) SHA1(23180b106e50b7a2a230c5e9948832e5631972ae) ) ROM_REGION( 0x0060, "proms", 0 ) //COLOR (all identical!) ROM_LOAD( "a26-13.109", 0x0000, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.110", 0x0020, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.111", 0x0040, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_END ROM_START( halleysc ) ROM_REGION( 0x10000, "main", 0 ) //MAIN PRG ROM_LOAD( "a62_01.30", 0x0000, 0x4000, CRC(a5e82b3e) SHA1(c16c6a6c23a579454b8a2be4b951c35b04f2a856) ) ROM_LOAD( "a62_02.31", 0x4000, 0x4000, CRC(25f5bcd3) SHA1(9d72afe866df363d2ac33dab3ed6c3913f4de12d) ) ROM_LOAD( "a62_03.52", 0x8000, 0x4000, CRC(8e90a97b) SHA1(9199628ad5353a88e4478a13c48df1ccb5d2b538) ) ROM_LOAD( "a62_04.50", 0xc000, 0x4000, CRC(fad74dfe) SHA1(92c0d42c5e186bc07c168ad581e52a5ae340c2b2) ) ROM_REGION( 0x10000, "audio", 0 ) //SOUND ROM_LOAD( "a62_13.5", 0x0000, 0x2000, CRC(7ce290db) SHA1(e3c72ba5d97cb07f0f72d2765a068af6fb5cca29) ) ROM_LOAD( "a62_14.4", 0x2000, 0x2000, CRC(ea74b1a2) SHA1(7be3b9e9d51cfa753ce97e92f7eebd9723fe5821) ) ROM_REGION( 0x20000, "gfx1", ROMREGION_DISPOSE ) //CHR ROM_LOAD( "a62_12.78", 0x00000, 0x4000, CRC(c5834a7a) SHA1(4a24b3fa707cde89ad5a52d4e994412fcf28e81f) ) ROM_LOAD( "a62_10.77", 0x04000, 0x4000, CRC(3ae7231e) SHA1(277f12570001d82104c79d3d0a58a0b57ed18778) ) ROM_LOAD( "a62_08.80", 0x08000, 0x4000, CRC(b9210dbe) SHA1(f72f2307e9acd2dd622a3efce71bd334b68a9b60) ) ROM_LOAD( "a62_06.79", 0x0c000, 0x4000, CRC(600be9ca) SHA1(a705b10be37ee93908b1bbaf806cfe7955aa3ffc) ) ROM_LOAD( "a62_11.89", 0x10000, 0x4000, CRC(d0e9974e) SHA1(6826cfb4fbf098ed7b9d8b00e2684d7c85a13c11) ) ROM_LOAD( "a62_09.88", 0x14000, 0x4000, CRC(e93ef281) SHA1(8bfe1ecce1c7107a5bd1b43b531594c8cfc0719d) ) ROM_LOAD( "a62_07.91", 0x18000, 0x4000, CRC(64c95e8b) SHA1(4c3320a764b13a5751c0019c9fafb899ea2f908f) ) ROM_LOAD( "a62_05.90", 0x1c000, 0x4000, CRC(c3c877ef) SHA1(23180b106e50b7a2a230c5e9948832e5631972ae) ) ROM_REGION( 0x0060, "proms", 0 ) //COLOR (all identical!) ROM_LOAD( "a26-13.109", 0x0000, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.110", 0x0020, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.111", 0x0040, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_END ROM_START( halley87 ) ROM_REGION( 0x10000, "main", 0 ) //MAIN PRG ROM_LOAD( "a62-17.30", 0x0000, 0x4000, CRC(fa2a58a6) SHA1(42cb587aad166ff74ece987f275aa7ad16d58300) ) ROM_LOAD( "a62-18.31", 0x4000, 0x4000, CRC(f3a078e6) SHA1(f8fa548b5814276d1ae2d575b9a5d3f0cc2f54fa) ) ROM_LOAD( "a62-19.52", 0x8000, 0x4000, CRC(e8bb695c) SHA1(066558ec48a38db03ae10ba873ff05ab5f911658) ) ROM_LOAD( "a62-20.50", 0xc000, 0x4000, CRC(59ed52cd) SHA1(059ee01610949a654741b853eed0235eabe0e313) ) ROM_REGION( 0x10000, "audio", 0 ) //SOUND ROM_LOAD( "a62_13.5", 0x0000, 0x2000, CRC(7ce290db) SHA1(e3c72ba5d97cb07f0f72d2765a068af6fb5cca29) ) ROM_LOAD( "a62_14.4", 0x2000, 0x2000, CRC(ea74b1a2) SHA1(7be3b9e9d51cfa753ce97e92f7eebd9723fe5821) ) ROM_REGION( 0x20000, "gfx1", ROMREGION_DISPOSE ) ROM_LOAD( "a62_12.78", 0x00000, 0x4000, CRC(c5834a7a) SHA1(4a24b3fa707cde89ad5a52d4e994412fcf28e81f) ) ROM_LOAD( "a62_10.77", 0x04000, 0x4000, CRC(3ae7231e) SHA1(277f12570001d82104c79d3d0a58a0b57ed18778) ) ROM_LOAD( "a62_08.80", 0x08000, 0x4000, CRC(b9210dbe) SHA1(f72f2307e9acd2dd622a3efce71bd334b68a9b60) ) ROM_LOAD( "a62_06.79", 0x0c000, 0x4000, CRC(600be9ca) SHA1(a705b10be37ee93908b1bbaf806cfe7955aa3ffc) ) ROM_LOAD( "a62_11.89", 0x10000, 0x4000, CRC(d0e9974e) SHA1(6826cfb4fbf098ed7b9d8b00e2684d7c85a13c11) ) ROM_LOAD( "a62_09.88", 0x14000, 0x4000, CRC(e93ef281) SHA1(8bfe1ecce1c7107a5bd1b43b531594c8cfc0719d) ) ROM_LOAD( "a62_07.91", 0x18000, 0x4000, CRC(64c95e8b) SHA1(4c3320a764b13a5751c0019c9fafb899ea2f908f) ) ROM_LOAD( "a62_05.90", 0x1c000, 0x4000, CRC(c3c877ef) SHA1(23180b106e50b7a2a230c5e9948832e5631972ae) ) ROM_REGION( 0x0060, "proms", 0 ) //COLOR (all identical!) ROM_LOAD( "a26-13.109", 0x0000, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.110", 0x0020, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_LOAD( "a26-13.111", 0x0040, 0x0020, CRC(ec449aee) SHA1(aa33e82b592276d5ffd540d9a73d1b48d7d4accf) ) ROM_END //************************************************************************** // Driver Initializations static void init_common(running_machine *machine) { UINT8 *buf, *rom; int addr, i; UINT8 al, ah, dl, dh; // allocate memory for unpacked graphics buf = auto_malloc(0x100000); gfx_plane02 = buf; gfx_plane13 = buf + 0x80000; // allocate memory for render layers buf = auto_malloc(SCREEN_BYTESIZE * MAX_LAYERS); for (i=0; i=0; i--) { al = rom[i]; ah = rom[i+0x10000]; gfx1_base[0xffff-i] = al; gfx1_base[0x1ffff-i] = ah; buf[0] = dl = (al & 1) | (ah<<2 & 4); dl <<= 1; buf[1] = dh = (al>>1 & 1) | (ah<<1 & 4); dh <<= 1; buf[0+0x80000] = dl; buf[1+0x80000] = dh; buf[2] = dl = (al>>2 & 1) | (ah & 4); dl <<= 1; buf[3] = dh = (al>>3 & 1) | (ah>>1 & 4); dh <<= 1; buf[2+0x80000] = dl; buf[3+0x80000] = dh; buf[4] = dl = (al>>4 & 1) | (ah>>2 & 4); dl <<= 1; buf[5] = dh = (al>>5 & 1) | (ah>>3 & 4); dh <<= 1; buf[4+0x80000] = dl; buf[5+0x80000] = dh; buf[6] = dl = (al>>6 & 1) | (ah>>4 & 4); dl <<= 1; buf[7] = dh = (al>>7 ) | (ah>>5 & 4); dh <<= 1; buf[6+0x80000] = dl; buf[7+0x80000] = dh; buf += 8; } } static DRIVER_INIT( benberob ) { game_id = GAME_BENBEROB; init_common(machine); blitter_reset_timer = timer_alloc(blitter_reset, NULL); } static DRIVER_INIT( halleys ) { game_id = GAME_HALLEYS; halleys_collision_detection = 0xb114; init_common(machine); } static DRIVER_INIT( halley87 ) { game_id = GAME_HALLEYS; halleys_collision_detection = 0xb10d; init_common(machine); } //************************************************************************** // Game Definitions GAME( 1984, benberob, 0, benberob, benberob, benberob, ROT0, "Taito", "Ben Bero Beh (Japan)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_COLORS | GAME_NO_COCKTAIL ) GAME( 1986, halleys, 0, halleys, halleys, halleys, ROT90, "Taito America Corporation (Coin-It license)", "Halley's Comet (US)", GAME_IMPERFECT_GRAPHICS | GAME_NO_COCKTAIL ) GAME( 1986, halleysc, halleys, halleys, halleys, halleys, ROT90, "Taito Corporation", "Halley's Comet (Japan, Newer)", GAME_IMPERFECT_GRAPHICS | GAME_NO_COCKTAIL ) GAME( 1986, halleycj, halleys, halleys, halleys, halleys, ROT90, "Taito Corporation", "Halley's Comet (Japan, Older)", GAME_IMPERFECT_GRAPHICS | GAME_NO_COCKTAIL ) GAME( 1986, halley87, halleys, halleys, halleys, halley87, ROT90, "Taito Corporation", "Halley's Comet '87", GAME_IMPERFECT_GRAPHICS | GAME_NO_COCKTAIL )