/*************************************************************************** Atari Tank 8 video emulation ***************************************************************************/ #include "emu.h" #include "includes/tank8.h" PALETTE_INIT( tank8 ) { int i; /* allocate the colortable */ machine.colortable = colortable_alloc(machine, 0x0a); colortable_palette_set_color(machine.colortable, 8, MAKE_RGB(0x00, 0x00, 0x00)); colortable_palette_set_color(machine.colortable, 9, MAKE_RGB(0xff, 0xff, 0xff)); for (i = 0; i < 8; i++) { colortable_entry_set_value(machine.colortable, 2 * i + 0, 8); colortable_entry_set_value(machine.colortable, 2 * i + 1, i); } /* walls */ colortable_entry_set_value(machine.colortable, 0x10, 8); colortable_entry_set_value(machine.colortable, 0x11, 9); /* mines */ colortable_entry_set_value(machine.colortable, 0x12, 8); colortable_entry_set_value(machine.colortable, 0x13, 9); } static void set_pens(tank8_state *state, colortable_t *colortable) { if (*state->m_team & 0x01) { colortable_palette_set_color(colortable, 0, MAKE_RGB(0xff, 0x00, 0x00)); /* red */ colortable_palette_set_color(colortable, 1, MAKE_RGB(0x00, 0x00, 0xff)); /* blue */ colortable_palette_set_color(colortable, 2, MAKE_RGB(0xff, 0xff, 0x00)); /* yellow */ colortable_palette_set_color(colortable, 3, MAKE_RGB(0x00, 0xff, 0x00)); /* green */ colortable_palette_set_color(colortable, 4, MAKE_RGB(0xff, 0x00, 0xff)); /* magenta */ colortable_palette_set_color(colortable, 5, MAKE_RGB(0xe0, 0xc0, 0x70)); /* puce */ colortable_palette_set_color(colortable, 6, MAKE_RGB(0x00, 0xff, 0xff)); /* cyan */ colortable_palette_set_color(colortable, 7, MAKE_RGB(0xff, 0xaa, 0xaa)); /* pink */ } else { colortable_palette_set_color(colortable, 0, MAKE_RGB(0xff, 0x00, 0x00)); /* red */ colortable_palette_set_color(colortable, 2, MAKE_RGB(0xff, 0x00, 0x00)); /* red */ colortable_palette_set_color(colortable, 4, MAKE_RGB(0xff, 0x00, 0x00)); /* red */ colortable_palette_set_color(colortable, 6, MAKE_RGB(0xff, 0x00, 0x00)); /* red */ colortable_palette_set_color(colortable, 1, MAKE_RGB(0x00, 0x00, 0xff)); /* blue */ colortable_palette_set_color(colortable, 3, MAKE_RGB(0x00, 0x00, 0xff)); /* blue */ colortable_palette_set_color(colortable, 5, MAKE_RGB(0x00, 0x00, 0xff)); /* blue */ colortable_palette_set_color(colortable, 7, MAKE_RGB(0x00, 0x00, 0xff)); /* blue */ } } WRITE8_HANDLER( tank8_video_ram_w ) { tank8_state *state = space->machine().driver_data(); state->m_video_ram[offset] = data; tilemap_mark_tile_dirty(state->m_tilemap, offset); } static TILE_GET_INFO( tank8_get_tile_info ) { tank8_state *state = machine.driver_data(); UINT8 code = state->m_video_ram[tile_index]; int color = 0; if ((code & 0x38) == 0x28) { if ((code & 7) != 3) color = 8; /* walls */ else color = 9; /* mines */ } else { if (tile_index & 0x010) color |= 1; if (code & 0x80) color |= 2; if (tile_index & 0x200) color |= 4; } SET_TILE_INFO(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); } VIDEO_START( tank8 ) { tank8_state *state = machine.driver_data(); state->m_helper1 = machine.primary_screen->alloc_compatible_bitmap(); state->m_helper2 = machine.primary_screen->alloc_compatible_bitmap(); state->m_helper3 = machine.primary_screen->alloc_compatible_bitmap(); state->m_tilemap = tilemap_create(machine, tank8_get_tile_info, tilemap_scan_rows, 16, 16, 32, 32); /* VBLANK starts on scanline #256 and ends on scanline #24 */ tilemap_set_scrolly(state->m_tilemap, 0, 2 * 24); } static int get_x_pos(tank8_state *state, int n) { return 498 - state->m_pos_h_ram[n] - 2 * (state->m_pos_d_ram[n] & 128); /* ? */ } static int get_y_pos(tank8_state *state, int n) { return 2 * state->m_pos_v_ram[n] - 62; } static void draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect) { tank8_state *state = machine.driver_data(); int i; for (i = 0; i < 8; i++) { UINT8 code = ~state->m_pos_d_ram[i]; int x = get_x_pos(state, i); int y = get_y_pos(state, i); drawgfx_transpen(bitmap, cliprect, machine.gfx[(code & 0x04) ? 2 : 3], code & 0x03, i, code & 0x10, code & 0x08, x, y, 0); } } static void draw_bullets(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect) { tank8_state *state = machine.driver_data(); int i; for (i = 0; i < 8; i++) { rectangle rect; int x = get_x_pos(state, 8 + i); int y = get_y_pos(state, 8 + i); x -= 4; /* ? */ rect.min_x = x; rect.min_y = y; rect.max_x = rect.min_x + 3; rect.max_y = rect.min_y + 4; if (rect.min_x < cliprect->min_x) rect.min_x = cliprect->min_x; if (rect.min_y < cliprect->min_y) rect.min_y = cliprect->min_y; if (rect.max_x > cliprect->max_x) rect.max_x = cliprect->max_x; if (rect.max_y > cliprect->max_y) rect.max_y = cliprect->max_y; bitmap_fill(bitmap, &rect, (i << 1) | 0x01); } } static TIMER_CALLBACK( tank8_collision_callback ) { tank8_set_collision(machine, param); } SCREEN_UPDATE( tank8 ) { tank8_state *state = screen->machine().driver_data(); set_pens(state, screen->machine().colortable); tilemap_draw(bitmap, cliprect, state->m_tilemap, 0, 0); draw_sprites(screen->machine(), bitmap, cliprect); draw_bullets(screen->machine(), bitmap, cliprect); return 0; } SCREEN_EOF( tank8 ) { tank8_state *state = machine.driver_data(); int x; int y; const rectangle &visarea = machine.primary_screen->visible_area(); tilemap_draw(state->m_helper1, &visarea, state->m_tilemap, 0, 0); bitmap_fill(state->m_helper2, &visarea, 8); bitmap_fill(state->m_helper3, &visarea, 8); draw_sprites(machine, state->m_helper2, &visarea); draw_bullets(machine, state->m_helper3, &visarea); for (y = visarea.min_y; y <= visarea.max_y; y++) { int _state = 0; const UINT16* p1 = BITMAP_ADDR16(state->m_helper1, y, 0); const UINT16* p2 = BITMAP_ADDR16(state->m_helper2, y, 0); const UINT16* p3 = BITMAP_ADDR16(state->m_helper3, y, 0); if (y % 2 != machine.primary_screen->frame_number() % 2) continue; /* video display is interlaced */ for (x = visarea.min_x; x <= visarea.max_x; x++) { UINT8 index; /* neither wall nor mine */ if ((p1[x] != 0x11) && (p1[x] != 0x13)) { _state = 0; continue; } /* neither tank nor bullet */ if ((p2[x] == 8) && (p3[x] == 8)) { _state = 0; continue; } /* bullets cannot hit mines */ if ((p3[x] != 8) && (p1[x] == 0x13)) { _state = 0; continue; } if (_state) continue; if (p3[x] != 8) { index = ((p3[x] & ~0x01) >> 1) | 0x18; if (1) index |= 0x20; if (0) index |= 0x40; if (1) index |= 0x80; } else { int sprite_num = (p2[x] & ~0x01) >> 1; index = sprite_num | 0x10; if (p1[x] == 0x11) index |= 0x20; if (y - get_y_pos(state, sprite_num) >= 8) index |= 0x40; /* collision on bottom side */ if (x - get_x_pos(state, sprite_num) >= 8) index |= 0x80; /* collision on right side */ } machine.scheduler().timer_set(machine.primary_screen->time_until_pos(y, x), FUNC(tank8_collision_callback), index); _state = 1; } } }