/*************************************************************************** World Rally Video Hardware Functions to emulate the video hardware of the machine ***************************************************************************/ #include "emu.h" #include "includes/wrally.h" /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ /* Tile format ----------- Screen 0 & 1: (64*32, 16x16 tiles) Word | Bit(s) | Description -----+-FEDCBA98-76543210-+-------------------------- 0 | --xxxxxx xxxxxxxx | code 0 | xx------ -------- | not used? 1 | -------- ---xxxxx | color 1 | -------- --x----- | priority 1 | -------- -x------ | flip y 1 | -------- x------- | flip x 1 | ---xxxxx -------- | data used to handle collisions, speed, etc 1 | xxx----- -------- | not used? */ static TILE_GET_INFO( get_tile_info_wrally_screen0 ) { wrally_state *state = machine.driver_data(); int data = state->m_videoram[tile_index << 1]; int data2 = state->m_videoram[(tile_index << 1) + 1]; int code = data & 0x3fff; tileinfo->category = (data2 >> 5) & 0x01; SET_TILE_INFO(0, code, data2 & 0x1f, TILE_FLIPYX((data2 >> 6) & 0x03)); } static TILE_GET_INFO( get_tile_info_wrally_screen1 ) { wrally_state *state = machine.driver_data(); int data = state->m_videoram[(0x2000/2) + (tile_index << 1)]; int data2 = state->m_videoram[(0x2000/2) + (tile_index << 1) + 1]; int code = data & 0x3fff; tileinfo->category = (data2 >> 5) & 0x01; SET_TILE_INFO(0, code, data2 & 0x1f, TILE_FLIPYX((data2 >> 6) & 0x03)); } /*************************************************************************** Start/Stop the video hardware emulation. ***************************************************************************/ VIDEO_START( wrally ) { wrally_state *state = machine.driver_data(); state->m_pant[0] = tilemap_create(machine, get_tile_info_wrally_screen0,tilemap_scan_rows,16,16,64,32); state->m_pant[1] = tilemap_create(machine, get_tile_info_wrally_screen1,tilemap_scan_rows,16,16,64,32); tilemap_set_transmask(state->m_pant[0],0,0xff01,0x00ff); /* this layer is split in two (pens 1..7, pens 8-15) */ tilemap_set_transparent_pen(state->m_pant[1],0); } /*************************************************************************** Sprites ***************************************************************************/ /* Sprite Format ------------- Word | Bit(s) | Description -----+-FEDCBA98-76543210-+-------------------------- 0 | -------- xxxxxxxx | y position 0 | --xxxxxx -------- | not used? 0 | -x------ -------- | flipx 0 | x------- -------- | flipy 1 | xxxxxxxx xxxxxxxx | unknown 2 | ------xx xxxxxxxx | x position 2 | --xxxx-- -------- | sprite color (low 4 bits) 2 | -x------ -------- | shadows/highlights (see below) 2 | x------- -------- | not used? 3 | --xxxxxx xxxxxxxx | sprite code 3 | xx------ -------- | not used? For shadows/highlights, the tile color below the sprite will be set using a palette (from the 8 available) based on the gfx pen of the sprite. Only pens in the range 0x8-0xf are used. */ static void draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect, int priority) { wrally_state *state = machine.driver_data(); int i, px, py; const gfx_element *gfx = machine.gfx[0]; for (i = 6/2; i < (0x1000 - 6)/2; i += 4) { int sx = state->m_spriteram[i+2] & 0x03ff; int sy = (240 - (state->m_spriteram[i] & 0x00ff)) & 0x00ff; int number = state->m_spriteram[i+3] & 0x3fff; int color = (state->m_spriteram[i+2] & 0x7c00) >> 10; int attr = (state->m_spriteram[i] & 0xfe00) >> 9; int xflip = attr & 0x20; int yflip = attr & 0x40; int color_effect = (color & 0x10) >> 4; int high_priority = number >= 0x3700; color = color & 0x0f; if (high_priority != priority) continue; if (flip_screen_get(machine)) { sy = sy + 248; } if (!color_effect) { drawgfx_transpen(bitmap,cliprect,gfx,number, 0x20 + color,xflip,yflip, sx - 0x0f,sy,0); } else { /* get a pointer to the current sprite's gfx data */ const UINT8 *gfx_src = gfx_element_get_data(gfx, number % gfx->total_elements); for (py = 0; py < gfx->height; py++){ /* get a pointer to the current line in the screen bitmap */ int ypos = ((sy + py) & 0x1ff); UINT16 *srcy = BITMAP_ADDR16(bitmap, ypos, 0); int gfx_py = yflip ? (gfx->height - 1 - py) : py; if ((ypos < cliprect->min_y) || (ypos > cliprect->max_y)) continue; for (px = 0; px < gfx->width; px++){ /* get current pixel */ int xpos = (((sx + px) & 0x3ff) - 0x0f) & 0x3ff; UINT16 *pixel = srcy + xpos; int src_color = *pixel; int gfx_px = xflip ? (gfx->width - 1 - px) : px; /* get asociated pen for the current sprite pixel */ int gfx_pen = gfx_src[gfx->line_modulo*gfx_py + gfx_px]; /* pens 8..15 are used to select a palette */ if ((gfx_pen < 8) || (gfx_pen >= 16)) continue; if ((xpos < cliprect->min_x) || (xpos > cliprect->max_x)) continue; /* modify the color of the tile */ *pixel = src_color + (gfx_pen-8)*1024; } } } } } /*************************************************************************** Display Refresh ***************************************************************************/ SCREEN_UPDATE( wrally ) { wrally_state *state = screen->machine().driver_data(); /* set scroll registers */ if (!flip_screen_get(screen->machine())) { tilemap_set_scrolly(state->m_pant[0], 0, state->m_vregs[0]); tilemap_set_scrollx(state->m_pant[0], 0, state->m_vregs[1]+4); tilemap_set_scrolly(state->m_pant[1], 0, state->m_vregs[2]); tilemap_set_scrollx(state->m_pant[1], 0, state->m_vregs[3]); } else { tilemap_set_scrolly(state->m_pant[0], 0, 248 - state->m_vregs[0]); tilemap_set_scrollx(state->m_pant[0], 0, 1024 - state->m_vregs[1] - 4); tilemap_set_scrolly(state->m_pant[1], 0, 248 - state->m_vregs[2]); tilemap_set_scrollx(state->m_pant[1], 0, 1024 - state->m_vregs[3]); } /* draw tilemaps + sprites */ tilemap_draw(bitmap,cliprect,state->m_pant[1],TILEMAP_DRAW_OPAQUE,0); tilemap_draw(bitmap,cliprect,state->m_pant[0],TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER0,0); tilemap_draw(bitmap,cliprect,state->m_pant[0],TILEMAP_DRAW_CATEGORY(0) | TILEMAP_DRAW_LAYER1,0); tilemap_draw(bitmap,cliprect,state->m_pant[1],TILEMAP_DRAW_CATEGORY(1),0); tilemap_draw(bitmap,cliprect,state->m_pant[0],TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER0,0); draw_sprites(screen->machine(),bitmap,cliprect,0); tilemap_draw(bitmap,cliprect,state->m_pant[0],TILEMAP_DRAW_CATEGORY(1) | TILEMAP_DRAW_LAYER1,0); draw_sprites(screen->machine(),bitmap,cliprect,1); return 0; }