/*************************************************************************** Sega System 18 hardware ***************************************************************************/ #include "emu.h" #include "video/segaic16.h" #include "includes/genesis.h" #include "includes/segas16.h" /************************************* * * Debugging * *************************************/ #define DEBUG_VDP (0) /************************************* * * Video startup * *************************************/ VIDEO_START( system18 ) { segas1x_state *state = machine.driver_data(); int width, height; state->m_grayscale_enable = 0; state->m_vdp_enable = 0; state->m_vdp_mixing = 0; /* compute palette info */ segaic16_palette_init(0x800); /* initialize the tile/text layers */ segaic16_tilemap_init(machine, 0, SEGAIC16_TILEMAP_16B, 0x000, 0, 8); /* create the VDP */ system18_vdp_start(machine); /* create a temp bitmap to draw the VDP data into */ width = machine.primary_screen->width(); height = machine.primary_screen->height(); state->m_tmp_bitmap = auto_bitmap_alloc(machine, width, height, BITMAP_FORMAT_INDEXED16); state->save_item(NAME(state->m_grayscale_enable)); state->save_item(NAME(state->m_vdp_enable)); state->save_item(NAME(state->m_vdp_mixing)); state->save_item(NAME(*state->m_tmp_bitmap)); } /************************************* * * Miscellaneous setters * *************************************/ void system18_set_grayscale(running_machine &machine, int enable) { segas1x_state *state = machine.driver_data(); enable = (enable != 0); if (enable != state->m_grayscale_enable) { machine.primary_screen->update_partial(machine.primary_screen->vpos()); state->m_grayscale_enable = enable; // mame_printf_debug("Grayscale = %02X\n", enable); } } void system18_set_vdp_enable(running_machine &machine, int enable) { segas1x_state *state = machine.driver_data(); enable = (enable != 0); if (enable != state->m_vdp_enable) { machine.primary_screen->update_partial(machine.primary_screen->vpos()); state->m_vdp_enable = enable; #if DEBUG_VDP mame_printf_debug("VDP enable = %02X\n", enable); #endif } } void system18_set_vdp_mixing(running_machine &machine, int mixing) { segas1x_state *state = machine.driver_data(); if (mixing != state->m_vdp_mixing) { machine.primary_screen->update_partial(machine.primary_screen->vpos()); state->m_vdp_mixing = mixing; #if DEBUG_VDP mame_printf_debug("VDP mixing = %02X\n", mixing); #endif } } /************************************* * * VDP drawing * *************************************/ static void draw_vdp(device_t *screen, bitmap_t *bitmap, const rectangle *cliprect, int priority) { segas1x_state *state = screen->machine().driver_data(); int x, y; bitmap_t *priority_bitmap = screen->machine().priority_bitmap; for (y = cliprect->min_y; y <= cliprect->max_y; y++) { UINT16 *src = BITMAP_ADDR16(state->m_tmp_bitmap, y, 0); UINT16 *dst = BITMAP_ADDR16(bitmap, y, 0); UINT8 *pri = BITMAP_ADDR8(priority_bitmap, y, 0); for (x = cliprect->min_x; x <= cliprect->max_x; x++) { UINT16 pix = src[x]; if (pix != 0xffff) { dst[x] = pix; pri[x] |= priority; } } } } /************************************* * * Video update * *************************************/ SCREEN_UPDATE( system18 ) { segas1x_state *state = screen->machine().driver_data(); int vdppri, vdplayer; /* Current understanding of VDP mixing: mixing = 0x00: astorm: layer = 0, pri = 0x00 or 0x01 lghost: layer = 0, pri = 0x00 or 0x01 mixing = 0x01: ddcrew: layer = 0, pri = 0x00 or 0x01 or 0x02 mixing = 0x02: never seen mixing = 0x03: ddcrew: layer = 1, pri = 0x00 or 0x01 or 0x02 mixing = 0x04: astorm: layer = 2 or 3, pri = 0x00 or 0x01 or 0x02 mwalk: layer = 2 or 3, pri = 0x00 or 0x01 or 0x02 mixing = 0x05: ddcrew: layer = 2, pri = 0x04 wwally: layer = 2, pri = 0x04 mixing = 0x06: never seen mixing = 0x07: cltchitr: layer = 1 or 2 or 3, pri = 0x02 or 0x04 or 0x08 mwalk: layer = 3, pri = 0x04 or 0x08 */ vdplayer = (state->m_vdp_mixing >> 1) & 3; vdppri = (state->m_vdp_mixing & 1) ? (1 << vdplayer) : 0; #if DEBUG_VDP if (screen->machine().input().code_pressed(KEYCODE_Q)) vdplayer = 0; if (screen->machine().input().code_pressed(KEYCODE_W)) vdplayer = 1; if (screen->machine().input().code_pressed(KEYCODE_E)) vdplayer = 2; if (screen->machine().input().code_pressed(KEYCODE_R)) vdplayer = 3; if (screen->machine().input().code_pressed(KEYCODE_A)) vdppri = 0x00; if (screen->machine().input().code_pressed(KEYCODE_S)) vdppri = 0x01; if (screen->machine().input().code_pressed(KEYCODE_D)) vdppri = 0x02; if (screen->machine().input().code_pressed(KEYCODE_F)) vdppri = 0x04; if (screen->machine().input().code_pressed(KEYCODE_G)) vdppri = 0x08; #endif /* if no drawing is happening, fill with black and get out */ if (!segaic16_display_enable) { bitmap_fill(bitmap, cliprect, get_black_pen(screen->machine())); return 0; } /* if the VDP is enabled, update our tmp_bitmap */ if (state->m_vdp_enable) system18_vdp_update(state->m_tmp_bitmap, cliprect); /* reset priorities */ bitmap_fill(screen->machine().priority_bitmap, cliprect, 0); /* draw background opaquely first, not setting any priorities */ segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0 | TILEMAP_DRAW_OPAQUE, 0x00); segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 1 | TILEMAP_DRAW_OPAQUE, 0x00); if (state->m_vdp_enable && vdplayer == 0) draw_vdp(screen, bitmap, cliprect, vdppri); /* draw background again to draw non-transparent pixels over the VDP and set the priority */ segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 0, 0x01); segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_BACKGROUND, 1, 0x02); if (state->m_vdp_enable && vdplayer == 1) draw_vdp(screen, bitmap, cliprect, vdppri); /* draw foreground */ segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_FOREGROUND, 0, 0x02); segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_FOREGROUND, 1, 0x04); if (state->m_vdp_enable && vdplayer == 2) draw_vdp(screen, bitmap, cliprect, vdppri); /* text layer */ segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_TEXT, 0, 0x04); segaic16_tilemap_draw(screen, bitmap, cliprect, 0, SEGAIC16_TILEMAP_TEXT, 1, 0x08); if (state->m_vdp_enable && vdplayer == 3) draw_vdp(screen, bitmap, cliprect, vdppri); /* draw the sprites */ segaic16_sprites_draw(screen, bitmap, cliprect, 0); #if DEBUG_VDP if (state->m_vdp_enable && screen->machine().input().code_pressed(KEYCODE_V)) { bitmap_fill(bitmap, cliprect, get_black_pen(screen->machine())); update_system18_vdp(bitmap, cliprect); } if (vdp_enable && screen->machine().input().code_pressed(KEYCODE_B)) { FILE *f = fopen("vdp.bin", "w"); fwrite(state->m_tmp_bitmap->base, 1, state->m_tmp_bitmap->rowpixels * (state->m_tmp_bitmap->bpp / 8) * state->m_tmp_bitmap->height, f); fclose(f); } #endif return 0; }