/*************************************************************************** The Game Room Lethal Justice hardware ***************************************************************************/ #include "emu.h" #include "cpu/tms34010/tms34010.h" #include "includes/lethalj.h" #define BLITTER_SOURCE_WIDTH 1024 #define BLITTER_DEST_WIDTH 512 #define BLITTER_DEST_HEIGHT 512 /************************************* * * Compute X/Y coordinates * *************************************/ INLINE void get_crosshair_xy(running_machine &machine, int player, int *x, int *y) { static const char *const gunnames[] = { "LIGHT0_X", "LIGHT0_Y", "LIGHT1_X", "LIGHT1_Y" }; const rectangle &visarea = machine.primary_screen->visible_area(); int width = visarea.max_x + 1 - visarea.min_x; int height = visarea.max_y + 1 - visarea.min_y; *x = ((input_port_read_safe(machine, gunnames[player * 2], 0x00) & 0xff) * width) / 255; *y = ((input_port_read_safe(machine, gunnames[1 + player * 2], 0x00) & 0xff) * height) / 255; } /************************************* * * Gun input handling * *************************************/ READ16_HANDLER( lethalj_gun_r ) { lethalj_state *state = space->machine().driver_data(); UINT16 result = 0; int beamx, beamy; switch (offset) { case 4: case 5: /* latch the crosshair position */ get_crosshair_xy(space->machine(), offset - 4, &beamx, &beamy); state->m_gunx = beamx; state->m_guny = beamy; state->m_blank_palette = 1; break; case 6: result = state->m_gunx / 2; break; case 7: result = state->m_guny + 4; break; } /* logerror("%08X:lethalj_gun_r(%d) = %04X\n", cpu_get_pc(&space->device()), offset, result); */ return result; } /************************************* * * video startup * *************************************/ VIDEO_START( lethalj ) { lethalj_state *state = machine.driver_data(); /* allocate video RAM for screen */ state->m_screenram = auto_alloc_array(machine, UINT16, BLITTER_DEST_WIDTH * BLITTER_DEST_HEIGHT); /* predetermine blitter info */ state->m_blitter_base = (UINT16 *)machine.region("gfx1")->base(); state->m_blitter_rows = machine.region("gfx1")->bytes() / (2*BLITTER_SOURCE_WIDTH); } /************************************* * * Memory maps * *************************************/ static TIMER_CALLBACK( gen_ext1_int ) { cputag_set_input_line(machine, "maincpu", 0, ASSERT_LINE); } static void do_blit(lethalj_state *state) { int dsty = (INT16)state->m_blitter_data[1]; int srcx = (UINT16)state->m_blitter_data[2]; int srcy = (UINT16)(state->m_blitter_data[3] + 1); int width = (UINT16)state->m_blitter_data[5]; int dstx = (INT16)state->m_blitter_data[6]; int height = (UINT16)state->m_blitter_data[7]; int y; /* logerror("blitter data = %04X %04X %04X %04X %04X %04X %04X %04X\n", state->m_blitter_data[0], state->m_blitter_data[1], state->m_blitter_data[2], state->m_blitter_data[3], state->m_blitter_data[4], state->m_blitter_data[5], state->m_blitter_data[6], state->m_blitter_data[7]); */ /* loop over Y coordinates */ for (y = 0; y <= height; y++, srcy++, dsty++) { /* clip in Y */ if (dsty >= 0 && dsty < BLITTER_DEST_HEIGHT/2) { UINT16 *source = state->m_blitter_base + (srcy % state->m_blitter_rows) * BLITTER_SOURCE_WIDTH; UINT16 *dest = state->m_screenram + (dsty + (state->m_vispage ^ 1) * 256) * BLITTER_DEST_WIDTH; int sx = srcx; int dx = dstx; int x; /* loop over X coordinates */ for (x = 0; x <= width; x++, sx++, dx++) if (dx >= 0 && dx < BLITTER_DEST_WIDTH) { int pix = source[sx % BLITTER_SOURCE_WIDTH]; if (pix) dest[dx] = pix; } } } } WRITE16_HANDLER( lethalj_blitter_w ) { lethalj_state *state = space->machine().driver_data(); /* combine the data */ COMBINE_DATA(&state->m_blitter_data[offset]); /* blit on a write to offset 7, and signal an IRQ */ if (offset == 7) { if (state->m_blitter_data[6] == 2 && state->m_blitter_data[7] == 2) state->m_vispage ^= 1; else do_blit(state); space->machine().scheduler().timer_set(attotime::from_hz(XTAL_32MHz) * ((state->m_blitter_data[5] + 1) * (state->m_blitter_data[7] + 1)), FUNC(gen_ext1_int)); } /* clear the IRQ on offset 0 */ else if (offset == 0) cputag_set_input_line(space->machine(), "maincpu", 0, CLEAR_LINE); } /************************************* * * video update * *************************************/ void lethalj_scanline_update(screen_device &screen, bitmap_t *bitmap, int scanline, const tms34010_display_params *params) { lethalj_state *state = screen.machine().driver_data(); UINT16 *src = &state->m_screenram[(state->m_vispage << 17) | ((params->rowaddr << 9) & 0x3fe00)]; UINT16 *dest = BITMAP_ADDR16(bitmap, scanline, 0); int coladdr = params->coladdr << 1; int x; /* blank palette: fill with white */ if (state->m_blank_palette) { for (x = params->heblnk; x < params->hsblnk; x++) dest[x] = 0x7fff; if (scanline == screen.visible_area().max_y) state->m_blank_palette = 0; return; } /* copy the non-blanked portions of this scanline */ for (x = params->heblnk; x < params->hsblnk; x++) dest[x] = src[coladdr++ & 0x1ff] & 0x7fff; }