#include "emu.h" #include "includes/othldrby.h" #define VIDEORAM_SIZE 0x1c00 #define SPRITERAM_START 0x1800 #define SPRITERAM_SIZE (VIDEORAM_SIZE - SPRITERAM_START) /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ INLINE void get_tile_info( running_machine &machine, tile_data *tileinfo, int tile_index, int plane ) { othldrby_state *state = machine.driver_data(); UINT16 attr; tile_index = 2 * tile_index + 0x800 * plane; attr = state->m_vram[tile_index]; SET_TILE_INFO( 1, state->m_vram[tile_index + 1], attr & 0x7f, 0); tileinfo->category = (attr & 0x0600) >> 9; } static TILE_GET_INFO( get_tile_info0 ) { get_tile_info(machine, tileinfo, tile_index, 0); } static TILE_GET_INFO( get_tile_info1 ) { get_tile_info(machine, tileinfo, tile_index, 1); } static TILE_GET_INFO( get_tile_info2 ) { get_tile_info(machine, tileinfo, tile_index, 2); } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ VIDEO_START( othldrby ) { othldrby_state *state = machine.driver_data(); state->m_bg_tilemap[0] = tilemap_create(machine, get_tile_info0, tilemap_scan_rows, 16, 16, 32, 32); state->m_bg_tilemap[1] = tilemap_create(machine, get_tile_info1, tilemap_scan_rows, 16, 16, 32, 32); state->m_bg_tilemap[2] = tilemap_create(machine, get_tile_info2, tilemap_scan_rows, 16, 16, 32, 32); state->m_vram = auto_alloc_array(machine, UINT16, VIDEORAM_SIZE); state->m_buf_spriteram = auto_alloc_array(machine, UINT16, 2 * SPRITERAM_SIZE); state->m_buf_spriteram2 = state->m_buf_spriteram + SPRITERAM_SIZE; tilemap_set_transparent_pen(state->m_bg_tilemap[0], 0); tilemap_set_transparent_pen(state->m_bg_tilemap[1], 0); tilemap_set_transparent_pen(state->m_bg_tilemap[2], 0); state->save_pointer(NAME(state->m_vram), VIDEORAM_SIZE); state->save_pointer(NAME(state->m_buf_spriteram), 2 * SPRITERAM_SIZE); } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE16_HANDLER( othldrby_videoram_addr_w ) { othldrby_state *state = space->machine().driver_data(); state->m_vram_addr = data; } READ16_HANDLER( othldrby_videoram_r ) { othldrby_state *state = space->machine().driver_data(); if (state->m_vram_addr < VIDEORAM_SIZE) return state->m_vram[state->m_vram_addr++]; else { popmessage("GFXRAM OUT OF BOUNDS %04x", state->m_vram_addr); return 0; } } WRITE16_HANDLER( othldrby_videoram_w ) { othldrby_state *state = space->machine().driver_data(); if (state->m_vram_addr < VIDEORAM_SIZE) { if (state->m_vram_addr < SPRITERAM_START) tilemap_mark_tile_dirty(state->m_bg_tilemap[state->m_vram_addr / 0x800], (state->m_vram_addr & 0x7ff) / 2); state->m_vram[state->m_vram_addr++] = data; } else popmessage("GFXRAM OUT OF BOUNDS %04x", state->m_vram_addr); } WRITE16_HANDLER( othldrby_vreg_addr_w ) { othldrby_state *state = space->machine().driver_data(); state->m_vreg_addr = data & 0x7f; /* bit 7 is set when screen is flipped */ } WRITE16_HANDLER( othldrby_vreg_w ) { othldrby_state *state = space->machine().driver_data(); if (state->m_vreg_addr < OTHLDRBY_VREG_SIZE) state->m_vreg[state->m_vreg_addr++] = data; else popmessage("%06x: VREG OUT OF BOUNDS %04x", cpu_get_pc(&space->device()), state->m_vreg_addr); } /*************************************************************************** Display refresh ***************************************************************************/ static void draw_sprites( running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect, int priority ) { othldrby_state *state = machine.driver_data(); int offs; for (offs = 0; offs < SPRITERAM_SIZE; offs += 4) { int x, y, color, code, sx, sy, flipx, flipy, sizex, sizey, pri; pri = (state->m_buf_spriteram[offs] & 0x0600) >> 9; if (pri != priority) continue; flipx = state->m_buf_spriteram[offs] & 0x1000; flipy = 0; color = (state->m_buf_spriteram[offs] & 0x01fc) >> 2; code = state->m_buf_spriteram[offs + 1] | ((state->m_buf_spriteram[offs] & 0x0003) << 16); sx = (state->m_buf_spriteram[offs + 2] >> 7); sy = (state->m_buf_spriteram[offs + 3] >> 7); sizex = (state->m_buf_spriteram[offs + 2] & 0x000f) + 1; sizey = (state->m_buf_spriteram[offs + 3] & 0x000f) + 1; if (flip_screen_get(machine)) { flipx = !flipx; flipy = !flipy; sx = 246 - sx; sy = 16 - sy; } for (y = 0; y < sizey; y++) { for (x = 0; x < sizex; x++) { drawgfx_transpen(bitmap,cliprect,machine.gfx[0], code + x + sizex * y, color, flipx,flipy, (sx + (flipx ? (-8*(x+1)+1) : 8*x) - state->m_vreg[6]+44) & 0x1ff,(sy + (flipy ? (-8*(y+1)+1) : 8*y) - state->m_vreg[7]-9) & 0x1ff,0); } } } } SCREEN_UPDATE( othldrby ) { othldrby_state *state = screen->machine().driver_data(); int layer; flip_screen_set(screen->machine(), state->m_vreg[0x0f] & 0x80); for (layer = 0; layer < 3; layer++) { if (flip_screen_get(screen->machine())) { tilemap_set_scrollx(state->m_bg_tilemap[layer], 0, state->m_vreg[2 * layer] + 59); tilemap_set_scrolly(state->m_bg_tilemap[layer], 0, state->m_vreg[2 * layer + 1] + 248); } else { tilemap_set_scrollx(state->m_bg_tilemap[layer], 0, state->m_vreg[2 * layer] - 58); tilemap_set_scrolly(state->m_bg_tilemap[layer], 0, state->m_vreg[2 * layer+1] + 9); } } bitmap_fill(screen->machine().priority_bitmap, cliprect, 0); bitmap_fill(bitmap, cliprect, 0); for (layer = 0; layer < 3; layer++) tilemap_draw(bitmap, cliprect, state->m_bg_tilemap[layer], 0, 0); draw_sprites(screen->machine(), bitmap, cliprect, 0); for (layer = 0; layer < 3; layer++) tilemap_draw(bitmap, cliprect, state->m_bg_tilemap[layer], 1, 0); draw_sprites(screen->machine(), bitmap, cliprect, 1); for (layer = 0; layer < 3; layer++) tilemap_draw(bitmap, cliprect, state->m_bg_tilemap[layer], 2, 0); draw_sprites(screen->machine(), bitmap, cliprect, 2); for (layer = 0; layer < 3; layer++) tilemap_draw(bitmap, cliprect, state->m_bg_tilemap[layer], 3, 0); draw_sprites(screen->machine(), bitmap, cliprect, 3); return 0; } SCREEN_EOF( othldrby ) { othldrby_state *state = machine.driver_data(); /* sprites need to be delayed two frames */ memcpy(state->m_buf_spriteram, state->m_buf_spriteram2, SPRITERAM_SIZE * sizeof(state->m_buf_spriteram[0])); memcpy(state->m_buf_spriteram2, &state->m_vram[SPRITERAM_START], SPRITERAM_SIZE * sizeof(state->m_buf_spriteram[0])); }