diff options
Diffstat (limited to 'src/mame/video/atarisy2.c')
-rw-r--r-- | src/mame/video/atarisy2.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/src/mame/video/atarisy2.c b/src/mame/video/atarisy2.c new file mode 100644 index 00000000000..906b69c93b6 --- /dev/null +++ b/src/mame/video/atarisy2.c @@ -0,0 +1,371 @@ +/*************************************************************************** + + Atari System 2 hardware + +****************************************************************************/ + +#include "driver.h" +#include "machine/atarigen.h" +#include "slapstic.h" +#include "atarisy2.h" + + + +/************************************* + * + * Globals we own + * + *************************************/ + +UINT16 *atarisy2_slapstic; + + + +/************************************* + * + * Statics + * + *************************************/ + +static emu_timer *yscroll_reset_timer; +static UINT32 playfield_tile_bank[2]; +static UINT32 videobank; +static UINT16 *vram; + + + +/************************************* + * + * Prototypes + * + *************************************/ + +static TIMER_CALLBACK( reset_yscroll_callback ); + + + +/************************************* + * + * Tilemap callbacks + * + *************************************/ + +static TILE_GET_INFO( get_alpha_tile_info ) +{ + UINT16 data = atarigen_alpha[tile_index]; + int code = data & 0x3ff; + int color = (data >> 13) & 0x07; + SET_TILE_INFO(2, code, color, 0); +} + + +static TILE_GET_INFO( get_playfield_tile_info ) +{ + UINT16 data = atarigen_playfield[tile_index]; + int code = playfield_tile_bank[(data >> 10) & 1] + (data & 0x3ff); + int color = (data >> 11) & 7; + SET_TILE_INFO(0, code, color, 0); + tileinfo->category = (~data >> 14) & 3; +} + + + +/************************************* + * + * Video system start + * + *************************************/ + +VIDEO_START( atarisy2 ) +{ + static const struct atarimo_desc modesc = + { + 1, /* index to which gfx system */ + 1, /* number of motion object banks */ + 1, /* are the entries linked? */ + 0, /* are the entries split? */ + 0, /* render in reverse order? */ + 0, /* render in swapped X/Y order? */ + 0, /* does the neighbor bit affect the next object? */ + 0, /* pixels per SLIP entry (0 for no-slip) */ + 0, /* pixel offset for SLIPs */ + 0, /* maximum number of links to visit/scanline (0=all) */ + + 0x00, /* base palette entry */ + 0x40, /* maximum number of colors */ + 15, /* transparent pen index */ + + {{ 0,0,0,0x07f8 }}, /* mask for the link */ + {{ 0 }}, /* mask for the graphics bank */ + {{ 0,0x07ff,0,0 }}, /* mask for the code index */ + {{ 0x0007,0,0,0 }}, /* mask for the upper code index */ + {{ 0,0,0,0x3000 }}, /* mask for the color */ + {{ 0,0,0xffc0,0 }}, /* mask for the X position */ + {{ 0x7fc0,0,0,0 }}, /* mask for the Y position */ + {{ 0 }}, /* mask for the width, in tiles*/ + {{ 0,0x3800,0,0 }}, /* mask for the height, in tiles */ + {{ 0,0x4000,0,0 }}, /* mask for the horizontal flip */ + {{ 0 }}, /* mask for the vertical flip */ + {{ 0,0,0,0xc000 }}, /* mask for the priority */ + {{ 0,0x8000,0,0 }}, /* mask for the neighbor */ + {{ 0 }}, /* mask for absolute coordinates */ + + {{ 0 }}, /* mask for the special value */ + 0, /* resulting value to indicate "special" */ + 0 /* callback routine for special entries */ + }; + + /* allocate banked memory */ + vram = auto_malloc(0x8000); + memset(vram, 0, 0x8000); + atarigen_alpha = &vram[0x0000]; + atarimo_0_spriteram = &vram[0x0c00]; + atarigen_playfield = &vram[0x2000]; + + /* initialize the playfield */ + atarigen_playfield_tilemap = tilemap_create(get_playfield_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8,8, 128,64); + + /* initialize the motion objects */ + atarimo_init(machine, 0, &modesc); + + /* initialize the alphanumerics */ + atarigen_alpha_tilemap = tilemap_create(get_alpha_tile_info, tilemap_scan_rows, TILEMAP_TYPE_PEN, 8,8, 64,48); + tilemap_set_transparent_pen(atarigen_alpha_tilemap, 0); + + /* reset the statics */ + yscroll_reset_timer = timer_alloc(reset_yscroll_callback); + videobank = 0; +} + + + +/************************************* + * + * Scroll/playfield bank write + * + *************************************/ + +WRITE16_HANDLER( atarisy2_xscroll_w ) +{ + UINT16 oldscroll = *atarigen_xscroll; + UINT16 newscroll = oldscroll; + COMBINE_DATA(&newscroll); + + /* if anything has changed, force a partial update */ + if (newscroll != oldscroll) + video_screen_update_partial(0, video_screen_get_vpos(0)); + + /* update the playfield scrolling - hscroll is clocked on the following scanline */ + tilemap_set_scrollx(atarigen_playfield_tilemap, 0, newscroll >> 6); + + /* update the playfield banking */ + if (playfield_tile_bank[0] != (newscroll & 0x0f) * 0x400) + { + playfield_tile_bank[0] = (newscroll & 0x0f) * 0x400; + tilemap_mark_all_tiles_dirty(atarigen_playfield_tilemap); + } + + /* update the data */ + *atarigen_xscroll = newscroll; +} + + +static TIMER_CALLBACK( reset_yscroll_callback ) +{ + tilemap_set_scrolly(atarigen_playfield_tilemap, 0, param); +} + + +WRITE16_HANDLER( atarisy2_yscroll_w ) +{ + UINT16 oldscroll = *atarigen_yscroll; + UINT16 newscroll = oldscroll; + COMBINE_DATA(&newscroll); + + /* if anything has changed, force a partial update */ + if (newscroll != oldscroll) + video_screen_update_partial(0, video_screen_get_vpos(0)); + + /* if bit 4 is zero, the scroll value is clocked in right away */ + if (!(newscroll & 0x10)) + tilemap_set_scrolly(atarigen_playfield_tilemap, 0, (newscroll >> 6) - video_screen_get_vpos(0)); + else + timer_adjust(yscroll_reset_timer, video_screen_get_time_until_pos(0, 0, 0), newscroll >> 6, attotime_zero); + + /* update the playfield banking */ + if (playfield_tile_bank[1] != (newscroll & 0x0f) * 0x400) + { + playfield_tile_bank[1] = (newscroll & 0x0f) * 0x400; + tilemap_mark_all_tiles_dirty(atarigen_playfield_tilemap); + } + + /* update the data */ + *atarigen_yscroll = newscroll; +} + + + +/************************************* + * + * Palette RAM write handler + * + *************************************/ + +WRITE16_HANDLER( atarisy2_paletteram_w ) +{ + static const int intensity_table[16] = + { + #define ZB 115 + #define Z3 78 + #define Z2 37 + #define Z1 17 + #define Z0 9 + 0, ZB+Z0, ZB+Z1, ZB+Z1+Z0, ZB+Z2, ZB+Z2+Z0, ZB+Z2+Z1, ZB+Z2+Z1+Z0, + ZB+Z3, ZB+Z3+Z0, ZB+Z3+Z1, ZB+Z3+Z1+Z0,ZB+ Z3+Z2, ZB+Z3+Z2+Z0, ZB+Z3+Z2+Z1, ZB+Z3+Z2+Z1+Z0 + }; + static const int color_table[16] = + { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xe, 0xf, 0xf }; + + int newword, inten, red, green, blue; + + COMBINE_DATA(&paletteram16[offset]); + newword = paletteram16[offset]; + + inten = intensity_table[newword & 15]; + red = (color_table[(newword >> 12) & 15] * inten) >> 4; + green = (color_table[(newword >> 8) & 15] * inten) >> 4; + blue = (color_table[(newword >> 4) & 15] * inten) >> 4; + palette_set_color(Machine, offset, MAKE_RGB(red, green, blue)); +} + + + +/************************************* + * + * Video RAM bank read/write handlers + * + *************************************/ + +READ16_HANDLER( atarisy2_slapstic_r ) +{ + int result = atarisy2_slapstic[offset]; + slapstic_tweak(offset); + + /* an extra tweak for the next opcode fetch */ + videobank = slapstic_tweak(0x1234) * 0x1000; + return result; +} + + +WRITE16_HANDLER( atarisy2_slapstic_w ) +{ + slapstic_tweak(offset); + + /* an extra tweak for the next opcode fetch */ + videobank = slapstic_tweak(0x1234) * 0x1000; +} + + + +/************************************* + * + * Video RAM read/write handlers + * + *************************************/ + +READ16_HANDLER( atarisy2_videoram_r ) +{ + return vram[offset | videobank]; +} + + +WRITE16_HANDLER( atarisy2_videoram_w ) +{ + int offs = offset | videobank; + + /* alpharam? */ + if (offs < 0x0c00) + { + COMBINE_DATA(&atarigen_alpha[offs]); + tilemap_mark_tile_dirty(atarigen_alpha_tilemap, offs); + } + + /* spriteram? */ + else if (offs < 0x1000) + { + /* force an update if the link of object 0 is about to change */ + if (offs == 0x0c03) + video_screen_update_partial(0, video_screen_get_vpos(0)); + atarimo_0_spriteram_w(offs - 0x0c00, data, mem_mask); + } + + /* playfieldram? */ + else if (offs >= 0x2000) + { + offs -= 0x2000; + COMBINE_DATA(&atarigen_playfield[offs]); + tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offs); + } + + /* generic case */ + else + { + COMBINE_DATA(&vram[offs]); + } +} + + + +/************************************* + * + * Main refresh + * + *************************************/ + +VIDEO_UPDATE( atarisy2 ) +{ + struct atarimo_rect_list rectlist; + mame_bitmap *mobitmap; + int x, y, r; + + /* draw the playfield */ + fillbitmap(priority_bitmap, 0, cliprect); + tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 0, 0); + tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 1, 1); + tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 2, 2); + tilemap_draw(bitmap, cliprect, atarigen_playfield_tilemap, 3, 3); + + /* draw and merge the MO */ + mobitmap = atarimo_render(machine, 0, cliprect, &rectlist); + for (r = 0; r < rectlist.numrects; r++, rectlist.rect++) + for (y = rectlist.rect->min_y; y <= rectlist.rect->max_y; y++) + { + UINT16 *mo = (UINT16 *)mobitmap->base + mobitmap->rowpixels * y; + UINT16 *pf = (UINT16 *)bitmap->base + bitmap->rowpixels * y; + UINT8 *pri = (UINT8 *)priority_bitmap->base + priority_bitmap->rowpixels * y; + for (x = rectlist.rect->min_x; x <= rectlist.rect->max_x; x++) + if (mo[x] != 0x0f) + { + int mopriority = mo[x] >> ATARIMO_PRIORITY_SHIFT; + + /* high priority PF? */ + if ((mopriority + pri[x]) & 2) + { + /* only gets priority if PF pen is less than 8 */ + if (!(pf[x] & 0x08)) + pf[x] = mo[x] & ATARIMO_DATA_MASK; + } + + /* low priority */ + else + pf[x] = mo[x] & ATARIMO_DATA_MASK; + + /* erase behind ourselves */ + mo[x] = 0x0f; + } + } + + /* add the alpha on top */ + tilemap_draw(bitmap, cliprect, atarigen_alpha_tilemap, 0, 0); + return 0; +} |