diff options
Diffstat (limited to 'src/mame/video/tunhunt.c')
-rw-r--r-- | src/mame/video/tunhunt.c | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/src/mame/video/tunhunt.c b/src/mame/video/tunhunt.c new file mode 100644 index 00000000000..934451be5d1 --- /dev/null +++ b/src/mame/video/tunhunt.c @@ -0,0 +1,412 @@ +/************************************************************************* + + Atari Tunnel Hunt hardware + +*************************************************************************/ + +#include "driver.h" + +extern UINT8 tunhunt_control; +extern UINT8 *tunhunt_ram; + +/****************************************************************************************/ + +/* Video Hardware Addresses */ + +/* Square Generator (13 bytes each) */ +#define LINEV 0x1403 // LINES VERTICAL START +#define LINEVS 0x1483 // LINES VERT STOP +#define LINEH 0x1083 // LINES HORIZ START +#define LINEC 0x1283 // LINE COLOR, 4 BITS D0-D3 +#define LINESH 0x1203 // LINES SLOPE 4 BITS D0-D3 (signed) +/* LINESH was used for rotation effects in an older version of the game */ + +/* Shell Object0 */ +#define SHEL0H 0x1800 // SHELL H POSITON (NORMAL SCREEN) +#define SHL0V 0x1400 // SHELL V START(NORMAL SCREEN) +#define SHL0VS 0x1480 // SHELL V STOP (NORMAL SCREEN) +#define SHL0ST 0x1200 // SHELL VSTRETCH (LIKE MST OBJ STRECTH) +#define SHL0PC 0x1280 // SHELL PICTURE CODE (D3-D0) + +/* Shell Object1 (see above) */ +#define SHEL1H 0x1A00 +#define SHL1V 0x1401 +#define SHL1VS 0x1481 +#define SHL1ST 0x1201 +#define SHL1PC 0x1281 + +/* Motion Object RAM */ +#define MOBJV 0x1C00 // V POSITION (SCREEN ON SIDE) +#define MOBVS 0x1482 // V STOP OF MOTION OBJECT (NORMAL SCREEN) +#define MOBJH 0x1402 // H POSITON (SCREEN ON SIDE) (VSTART - NORMAL SCREEN) +#define MOBST 0x1082 // STARTING LINE FOR RAM SCAN ON MOBJ +#define VSTRLO 0x1202 // VERT (SCREEN ON SIDE) STRETCH MOJ OBJ +#define MOTT 0x2C00 // MOTION OBJECT RAM (00-0F NOT USED, BYT CLEARED) +#define MOBSC0 0x1080 // SCAN ROM START FOR MOBJ (unused?) +#define MOBSC1 0x1081 // (unused?) + +static tilemap *fg_tilemap; + +/****************************************************************************************/ + +WRITE8_HANDLER( tunhunt_videoram_w ) +{ + videoram[offset] = data; + tilemap_mark_tile_dirty(fg_tilemap, offset); +} + +WRITE8_HANDLER( tunhunt_mott_w ) +{ + if( spriteram[offset]!=data ) + { + spriteram[offset] = data; + dirtybuffer[offset>>4] = 1; + } +} + +static TILE_GET_INFO( get_fg_tile_info ) +{ + int attr = videoram[tile_index]; + int code = attr & 0x3f; + int color = attr >> 6; + int flags = color ? TILE_FORCE_LAYER0 : 0; + + SET_TILE_INFO(0, code, color, flags); +} + +VIDEO_START( tunhunt ) +{ + /* + Motion Object RAM contains 64 lines of run-length encoded data. + We keep track of dirty lines and cache the expanded bitmap. + With max RLE expansion, bitmap size is 256x64. + */ + dirtybuffer = auto_malloc(64); + + memset( dirtybuffer, 1, 64 ); + tmpbitmap = auto_bitmap_alloc( 256, 64, machine->screen[0].format ); + + fg_tilemap = tilemap_create(get_fg_tile_info, tilemap_scan_cols, + TILEMAP_TYPE_PEN, 8, 8, 32, 32); + + tilemap_set_transparent_pen(fg_tilemap, 0); + tilemap_set_scrollx(fg_tilemap, 0, 64); +} + +PALETTE_INIT( tunhunt ) +{ + /* Tunnel Hunt uses a combination of color proms and palette RAM to specify a 16 color + * palette. Here, we manage only the mappings for alphanumeric characters and SHELL + * graphics, which are unpacked ahead of time and drawn using MAME's drawgfx primitives. + */ + + /* AlphaNumerics (1bpp) + * 2 bits of hilite select from 4 different background colors + * Foreground color is always pen#4 + * Background color is mapped as follows: + */ + + /* alpha hilite#0 */ + colortable[0] = 0x0; /* background color#0 (transparent) */ + colortable[1] = 0x4; /* foreground color */ + + /* alpha hilite#1 */ + colortable[2] = 0x5; /* background color#1 */ + colortable[3] = 0x4; /* foreground color */ + + /* alpha hilite#2 */ + colortable[4] = 0x6; /* background color#2 */ + colortable[5] = 0x4; /* foreground color */ + + /* alpha hilite#3 */ + colortable[6] = 0xf; /* background color#3 */ + colortable[7] = 0x4; /* foreground color */ + + /* shell graphics; these are either 1bpp (2 banks) or 2bpp. It isn't clear which. + * In any event, the following pens are associated with the shell graphics: + */ + colortable[0x8] = 0; + colortable[0x9] = 4;//1; + colortable[0xa] = 2; + colortable[0xb] = 4; +} + +/* +Color Array Ram Assignments: + Location + 0 Blanking, border + 1 Mot Obj (10) (D), Shell (01) + 2 Mot Obj (01) (G), Shell (10) + 3 Mot Obj (00) (W) + 4 Alpha & Shell (11) - shields + 5 Hilight 1 + 6 Hilight 2 + 8-E Lines (as normal) background + F Hilight 3 +*/ +static void update_palette(running_machine *machine) +{ +// const UINT8 *color_prom = memory_region( REGION_PROMS ); +/* + The actual contents of the color proms (unused by this driver) + are as follows: + + D11 "blue/green" + 0000: 00 00 8b 0b fb 0f ff 0b + 00 00 0f 0f fb f0 f0 ff + + C11 "red" + 0020: 00 f0 f0 f0 b0 b0 00 f0 + 00 f0 f0 00 b0 00 f0 f0 +*/ + int color; + int shade; + int i; + int red,green,blue; + + for( i=0; i<16; i++ ) + { + color = paletteram[i]; + shade = 0xf^(color>>4); + + color &= 0xf; /* hue select */ + switch( color ) + { + default: + case 0x0: red = 0xff; green = 0xff; blue = 0xff; break; /* white */ + case 0x1: red = 0xff; green = 0x00; blue = 0xff; break; /* purple */ + case 0x2: red = 0x00; green = 0x00; blue = 0xff; break; /* blue */ + case 0x3: red = 0x00; green = 0xff; blue = 0xff; break; /* cyan */ + case 0x4: red = 0x00; green = 0xff; blue = 0x00; break; /* green */ + case 0x5: red = 0xff; green = 0xff; blue = 0x00; break; /* yellow */ + case 0x6: red = 0xff; green = 0x00; blue = 0x00; break; /* red */ + case 0x7: red = 0x00; green = 0x00; blue = 0x00; break; /* black? */ + + case 0x8: red = 0xff; green = 0x7f; blue = 0x00; break; /* orange */ + case 0x9: red = 0x7f; green = 0xff; blue = 0x00; break; /* ? */ + case 0xa: red = 0x00; green = 0xff; blue = 0x7f; break; /* ? */ + case 0xb: red = 0x00; green = 0x7f; blue = 0xff; break; /* ? */ + case 0xc: red = 0xff; green = 0x00; blue = 0x7f; break; /* ? */ + case 0xd: red = 0x7f; green = 0x00; blue = 0xff; break; /* ? */ + case 0xe: red = 0xff; green = 0xaa; blue = 0xaa; break; /* ? */ + case 0xf: red = 0xaa; green = 0xaa; blue = 0xff; break; /* ? */ + } + + /* combine color components with shade value (0..0xf) */ + #define APPLY_SHADE( C,S ) ((C*S)/0xf) + red = APPLY_SHADE(red,shade); + green = APPLY_SHADE(green,shade); + blue = APPLY_SHADE(blue,shade); + + palette_set_color( machine,i,MAKE_RGB(red,green,blue) ); + } +} + +static void draw_motion_object(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ +/* + * VSTRLO 0x1202 + * normally 0x02 (gameplay, attract1) + * in attract2 (with "Tunnel Hunt" graphic), decrements from 0x2f down to 0x01 + * goes to 0x01 for some enemy shots + * + * MOBSC0 0x1080 + * MOBSC1 0x1081 + * always 0x00? + */ +// int skip = tunhunt_ram[MOBST]; + int x0 = 255-tunhunt_ram[MOBJV]; + int y0 = 255-tunhunt_ram[MOBJH]; + int scalex,scaley; + int line,span; + int x,span_data; + int color; + int count; + const UINT8 *source; + + for( line=0; line<64; line++ ) + { + if( dirtybuffer[line] ) + { + dirtybuffer[line] = 0; + x = 0; + source = &spriteram[line*0x10]; + for( span=0; span<0x10; span++ ) + { + span_data = source[span]; + if( span_data == 0xff ) break; + color = ((span_data>>6)&0x3)^0x3; + count = (span_data&0x1f)+1; + while( count-- && x < 256 ) + { + *BITMAP_ADDR16(tmpbitmap, line, x++) = machine->pens[color]; + } + } + while( x<256 ) + { + *BITMAP_ADDR16(tmpbitmap, line, x++) = machine->pens[0]; + } + } /* dirty line */ + } /* next line */ + + switch( tunhunt_ram[VSTRLO] ) + { + case 0x01: + scaley = (1<<16)*0.33; /* seems correct */ + break; + + case 0x02: + scaley = (1<<16)*0.50; /* seems correct */ + break; + + default: + scaley = (1<<16)*tunhunt_ram[VSTRLO]/4; /* ??? */ + break; + } + scalex = (1<<16); + + copyrozbitmap( + bitmap,tmpbitmap, + -x0*scalex,/* startx */ + -y0*scaley,/* starty */ + scalex,/* incxx */ + 0,0,/* incxy,incyx */ + scaley,/* incyy */ + 0, /* no wraparound */ + cliprect, + TRANSPARENCY_PEN,machine->pens[0], + 0 /* priority */ + ); +} + +static void draw_box(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect) +{ +/* + This is unnecessarily slow, but the box priorities aren't completely understood, + yet. Once understood, this function should be converted to use fillbitmap with + rectangular chunks instead of BITMAP_ADDR. + + Tunnels: + 1080: 00 00 00 01 e7 18 ae 51 94 6b 88 77 83 7c 80 7f x0 + 1480: 00 f0 17 00 22 22 5b 5b 75 75 81 81 86 86 89 89 y0 + 1400: 00 00 97 ff f1 f1 b8 b8 9e 9e 92 92 8d 8d 8a 8a y1 + 1280: 07 03 00 07 07 0c 0c 0d 0d 0e 0e 08 08 09 09 0a palette select + + Color Bars: + 1080: 00 00 00 01 00 20 40 60 80 a0 c0 e0 01 2a 50 7a x0 + 1480: 00 f0 00 00 40 40 40 40 40 40 40 40 00 00 00 00 y0 + 1400: 00 00 00 ff ff ff ff ff ff ff ff ff 40 40 40 40 y1 + 1280: 07 03 00 01 07 06 04 05 02 07 03 00 09 0a 0b 0c palette select + ->hue 06 02 ff 60 06 05 03 04 01 06 02 ff d2 00 c2 ff +*/ + int span,x,y; + int color; +// rectangle bbox; + int z; + int x0,y0,y1; + + for( y=0; y<256; y++ ) + { + if (0xff-y >= cliprect->min_y && 0xff-y <= cliprect->max_y) + for( x=0; x<256; x++ ) + { + color = 0; + z = 0; + for( span=3; span<16; span++ ) + { + x0 = tunhunt_ram[span+0x1080]; + y0 = tunhunt_ram[span+0x1480]; + y1 = tunhunt_ram[span+0x1400]; + + if( y>=y0 && y<=y1 && x>=x0 && x0>=z ) + { + color = tunhunt_ram[span+0x1280]&0xf; + z = x0; /* give priority to rightmost spans */ + } + } + if (x >= cliprect->min_x && x <= cliprect->max_x) + *BITMAP_ADDR16(bitmap, 0xff-y, x) = machine->pens[color]; + } + } +} + +/* "shell" graphics are 16x16 pixel tiles used for player shots and targeting cursor */ +static void draw_shell(running_machine *machine, + mame_bitmap *bitmap, + const rectangle *cliprect, + int picture_code, + int hposition, + int vstart, + int vstop, + int vstretch, + int hstretch ) +{ + if( hstretch ) + { + int sx,sy; + for( sx=0; sx<256; sx+=16 ) + { + for( sy=0; sy<256; sy+=16 ) + { + drawgfx( bitmap, machine->gfx[1], + picture_code, + 0, /* color */ + 0,0, /* flip */ + sx,sy, + cliprect, + TRANSPARENCY_PEN,0 ); + } + } + } + else + /* + vstretch is normally 0x01 + + targeting cursor: + hposition = 0x78 + vstart = 0x90 + vstop = 0x80 + + during grid test: + vstretch = 0xff + hposition = 0xff + vstart = 0xff + vstop = 0x00 + + */ + drawgfx( bitmap, machine->gfx[1], + picture_code, + 0, /* color */ + 0,0, /* flip */ + 255-hposition-16,vstart-32, + cliprect, + TRANSPARENCY_PEN,0 ); +} + +VIDEO_UPDATE( tunhunt ) +{ + update_palette(machine); + + draw_box(machine, bitmap, cliprect); + + draw_motion_object(machine, bitmap, cliprect); + + draw_shell(machine, bitmap, cliprect, + tunhunt_ram[SHL0PC], /* picture code */ + tunhunt_ram[SHEL0H], /* hposition */ + tunhunt_ram[SHL0V], /* vstart */ + tunhunt_ram[SHL0VS], /* vstop */ + tunhunt_ram[SHL0ST], /* vstretch */ + tunhunt_control&0x08 ); /* hstretch */ + + draw_shell(machine, bitmap, cliprect, + tunhunt_ram[SHL1PC], /* picture code */ + tunhunt_ram[SHEL1H], /* hposition */ + tunhunt_ram[SHL1V], /* vstart */ + tunhunt_ram[SHL1VS], /* vstop */ + tunhunt_ram[SHL1ST], /* vstretch */ + tunhunt_control&0x10 ); /* hstretch */ + + tilemap_draw(bitmap, cliprect, fg_tilemap, 0, 0); + return 0; +} |