Better separation of driver and video code.

Gave Top Secret its own (1 line long) video update function.
This commit is contained in:
Zsolt Vasvari 2008-03-04 11:36:09 +00:00
parent 6ae0a85462
commit f1e2ccd4f1
3 changed files with 104 additions and 94 deletions

View File

@ -219,6 +219,10 @@
#include "exidy440.h"
/* constants */
#define MAIN_CPU_CLOCK (EXIDY440_MASTER_CLOCK / 8)
/* local variables */
static UINT8 exidy440_bank;
@ -994,7 +998,7 @@ INPUT_PORTS_END
static MACHINE_DRIVER_START( exidy440 )
/* basic machine hardware */
MDRV_CPU_ADD(M6809,EXIDY440_MAIN_CPU_CLOCK)
MDRV_CPU_ADD(M6809, MAIN_CPU_CLOCK)
MDRV_CPU_PROGRAM_MAP(exidy440_map,0)
MDRV_CPU_VBLANK_INT("main", exidy440_vblank_interrupt)
@ -1002,15 +1006,7 @@ static MACHINE_DRIVER_START( exidy440 )
MDRV_NVRAM_HANDLER(exidy440)
/* video hardware */
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_RAW_PARAMS(EXIDY440_PIXEL_CLOCK, EXIDY440_HTOTAL, EXIDY440_HBEND, EXIDY440_HBSTART, EXIDY440_VTOTAL, EXIDY440_VBEND, EXIDY440_VBSTART)
MDRV_PALETTE_LENGTH(256)
MDRV_VIDEO_START(exidy440)
MDRV_VIDEO_EOF(exidy440)
MDRV_VIDEO_UPDATE(exidy440)
MDRV_IMPORT_FROM(exidy440_video)
/* audio hardware */
MDRV_IMPORT_FROM(exidy440_audio)
@ -1023,9 +1019,7 @@ static MACHINE_DRIVER_START( topsecex )
MDRV_IMPORT_FROM(exidy440)
/* video hardware */
MDRV_SCREEN_MODIFY("main")
MDRV_SCREEN_RAW_PARAMS(EXIDY440_PIXEL_CLOCK, EXIDY440_HTOTAL, EXIDY440_HBEND, EXIDY440_HBSTART, EXIDY440_VTOTAL, EXIDY440_VBEND, TOPSECEX_VBSTART)
MDRV_IMPORT_FROM(topsecex_video)
MACHINE_DRIVER_END
@ -1933,7 +1927,6 @@ ROM_END
static DRIVER_INIT( exidy440 )
{
topsecex_yscroll = NULL;
showdown_bank_data[0] = showdown_bank_data[1] = NULL;
}

View File

@ -8,21 +8,6 @@
#define EXIDY440_MASTER_CLOCK (XTAL_12_9792MHz)
#define EXIDY440_MAIN_CPU_CLOCK (EXIDY440_MASTER_CLOCK / 8)
#define EXIDY440_PIXEL_CLOCK (EXIDY440_MASTER_CLOCK / 2)
#define EXIDY440_HTOTAL (0x1a0)
#define EXIDY440_HBEND (0x000)
#define EXIDY440_HBSTART (0x140)
#define EXIDY440_HSEND (0x178)
#define EXIDY440_HSSTART (0x160)
#define EXIDY440_VTOTAL (0x104)
#define EXIDY440_VBEND (0x000)
#define EXIDY440_VBSTART (0x0f0)
#define EXIDY440_VSEND (0x0f8)
#define EXIDY440_VSSTART (0x0f0)
/* Top Secret has a larger VBLANK area */
#define TOPSECEX_VBSTART (0x0ec)
/*----------- defined in drivers/exidy440.c -----------*/
@ -48,10 +33,6 @@ extern UINT8 *topsecex_yscroll;
INTERRUPT_GEN( exidy440_vblank_interrupt );
VIDEO_START( exidy440 );
VIDEO_EOF( exidy440 );
VIDEO_UPDATE( exidy440 );
READ8_HANDLER( exidy440_videoram_r );
WRITE8_HANDLER( exidy440_videoram_w );
READ8_HANDLER( exidy440_paletteram_r );
@ -61,3 +42,6 @@ WRITE8_HANDLER( exidy440_control_w );
READ8_HANDLER( exidy440_vertical_pos_r );
READ8_HANDLER( exidy440_horizontal_pos_r );
WRITE8_HANDLER( exidy440_interrupt_clear_w );
MACHINE_DRIVER_EXTERN( exidy440_video );
MACHINE_DRIVER_EXTERN( topsecex_video );

View File

@ -8,7 +8,23 @@
#include "deprecat.h"
#include "exidy440.h"
#define SPRITE_COUNT 40
#define PIXEL_CLOCK (EXIDY440_MASTER_CLOCK / 2)
#define HTOTAL (0x1a0)
#define HBEND (0x000)
#define HBSTART (0x140)
#define HSEND (0x178)
#define HSSTART (0x160)
#define VTOTAL (0x104)
#define VBEND (0x000)
#define VBSTART (0x0f0)
#define VSEND (0x0f8)
#define VSSTART (0x0f0)
/* Top Secret has a larger VBLANK area */
#define TOPSECEX_VBSTART (0x0ec)
#define SPRITE_COUNT (0x28)
/* globals */
@ -28,7 +44,6 @@ static UINT8 firq_enable;
static UINT8 firq_select;
static UINT8 palettebank_io;
static UINT8 palettebank_vis;
static UINT8 is_topsecex;
/* function prototypes */
static void exidy440_update_firq(running_machine *machine);
@ -41,7 +56,7 @@ static void exidy440_update_firq(running_machine *machine);
*
*************************************/
VIDEO_START( exidy440 )
static VIDEO_START( exidy440 )
{
/* reset the system */
firq_enable = 0;
@ -51,15 +66,6 @@ VIDEO_START( exidy440 )
exidy440_firq_vblank = 0;
exidy440_firq_beam = 0;
/* if Top Secret, reset scroll position */
if (topsecex_yscroll != NULL)
{
is_topsecex = TRUE;
*topsecex_yscroll = 0;
}
else
is_topsecex = FALSE;
/* allocate a buffer for VRAM */
local_videoram = auto_malloc(256 * 256 * 2);
memset(local_videoram, 0, 256 * 256 * 2);
@ -70,6 +76,14 @@ VIDEO_START( exidy440 )
}
static VIDEO_START( topsecex )
{
VIDEO_START_CALL(exidy440);
*topsecex_yscroll = 0;
}
/*************************************
*
@ -293,15 +307,13 @@ static TIMER_CALLBACK( collide_firq_callback )
*
*************************************/
static void draw_sprites(bitmap_t *bitmap, const rectangle *cliprect, int scroll_offset)
static void draw_sprites(bitmap_t *bitmap, const rectangle *cliprect, int scroll_offset, int check_collision)
{
int i;
/* get a pointer to the palette to look for collision flags */
UINT8 *palette = &local_paletteram[palettebank_vis * 512];
/* start the count high for topsecret, which doesn't use collision flags */
int count = is_topsecex ? 128 : 0;
int count = 0;
/* draw the sprite images, checking for collisions along the way */
UINT8 *sprite = spriteram + (SPRITE_COUNT - 1) * 4;
@ -330,10 +342,10 @@ static void draw_sprites(bitmap_t *bitmap, const rectangle *cliprect, int scroll
for (y = 0; y < 16; y++, yoffs--, sy--)
{
/* wrap at the top and bottom of the screen */
if (sy >= EXIDY440_VBSTART)
sy -= (EXIDY440_VBSTART - EXIDY440_VBEND);
else if (sy < EXIDY440_VBEND)
sy += (EXIDY440_VBSTART - EXIDY440_VBEND);
if (sy >= VBSTART)
sy -= (VBSTART - VBEND);
else if (sy < VBEND)
sy += (VBSTART - VBEND);
/* stop if we get before the current scanline */
if (yoffs < cliprect->min_y)
@ -354,27 +366,27 @@ static void draw_sprites(bitmap_t *bitmap, const rectangle *cliprect, int scroll
int pen;
/* left pixel */
if (left && EXIDY440_HBEND >= 0 && currx < EXIDY440_HBSTART)
if (left && HBEND >= 0 && currx < HBSTART)
{
/* combine with the background */
pen = left | old[0];
*BITMAP_ADDR16(bitmap, yoffs, currx) = pen;
/* check the collisions bit */
if ((palette[2 * pen] & 0x80) && count++ < 128)
if (check_collision && (palette[2 * pen] & 0x80) && (count++ < 128))
timer_set(video_screen_get_time_until_pos(0, yoffs, currx), NULL, currx, collide_firq_callback);
}
currx++;
/* right pixel */
if (right && EXIDY440_HBEND >= 0 && currx < EXIDY440_HBSTART)
if (right && HBEND >= 0 && currx < HBSTART)
{
/* combine with the background */
pen = right | old[1];
*BITMAP_ADDR16(bitmap, yoffs, currx) = pen;
/* check the collisions bit */
if ((palette[2 * pen] & 0x80) && count++ < 128)
if (check_collision && (palette[2 * pen] & 0x80) && (count++ < 128))
timer_set(video_screen_get_time_until_pos(0, yoffs, currx), NULL, currx, collide_firq_callback);
}
currx++;
@ -394,7 +406,7 @@ static void draw_sprites(bitmap_t *bitmap, const rectangle *cliprect, int scroll
*
*************************************/
static void update_screen(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, int scroll_offset)
static void update_screen(bitmap_t *bitmap, const rectangle *cliprect, int scroll_offset, int check_collision)
{
int y, sy;
@ -403,15 +415,15 @@ static void update_screen(running_machine *machine, bitmap_t *bitmap, const rect
for (y = cliprect->min_y; y <= cliprect->max_y; y++, sy++)
{
/* wrap at the bottom of the screen */
if (sy >= EXIDY440_VBSTART)
sy -= (EXIDY440_VBSTART - EXIDY440_VBEND);
if (sy >= VBSTART)
sy -= (VBSTART - VBEND);
/* draw line */
draw_scanline8(bitmap, 0, y, (EXIDY440_HBSTART - EXIDY440_HBEND), &local_videoram[sy * 512], NULL, -1);
draw_scanline8(bitmap, 0, y, (HBSTART - HBEND), &local_videoram[sy * 512], NULL, -1);
}
/* draw the sprites */
draw_sprites(bitmap, cliprect, scroll_offset);
draw_sprites(bitmap, cliprect, scroll_offset, check_collision);
}
@ -422,13 +434,42 @@ static void update_screen(running_machine *machine, bitmap_t *bitmap, const rect
*
*************************************/
VIDEO_UPDATE( exidy440 )
static VIDEO_UPDATE( exidy440 )
{
/* redraw the screen */
if (is_topsecex)
update_screen(machine, bitmap, cliprect, *topsecex_yscroll);
else
update_screen(machine, bitmap, cliprect, 0);
update_screen(bitmap, cliprect, 0, TRUE);
/* generate an interrupt once/frame for the beam */
if (cliprect->max_y == machine->screen[screen].visarea.max_y)
{
int i;
int beamx = ((input_port_4_r(0) & 0xff) * (HBSTART - HBEND)) >> 8;
int beamy = ((input_port_5_r(0) & 0xff) * (VBSTART - VBEND)) >> 8;
/* The timing of this FIRQ is very important. The games look for an FIRQ
and then wait about 650 cycles, clear the old FIRQ, and wait a
very short period of time (~130 cycles) for another one to come in.
From this, it appears that they are expecting to get beams over
a 12 scanline period, and trying to pick roughly the middle one.
This is how it is implemented. */
attoseconds_t increment = attotime_to_attoseconds(video_screen_get_scan_period(0));
attotime time = attotime_sub(video_screen_get_time_until_pos(0, beamy, beamx), attotime_make(0, increment * 6));
for (i = 0; i <= 12; i++)
{
timer_set(time, NULL, beamx, beam_firq_callback);
time = attotime_add(time, attotime_make(0, increment));
}
}
return 0;
}
static VIDEO_UPDATE( topsecex )
{
/* redraw the screen */
update_screen(bitmap, cliprect, *topsecex_yscroll, FALSE);
return 0;
}
@ -437,35 +478,27 @@ VIDEO_UPDATE( exidy440 )
/*************************************
*
* Standard screen refresh callback
* Machine drivers
*
*************************************/
VIDEO_EOF( exidy440 )
{
/* generate an interrupt once/frame for the beam */
if (!is_topsecex)
{
attotime time;
attoseconds_t increment;
int beamx, beamy;
int i;
MACHINE_DRIVER_START( exidy440_video )
MDRV_VIDEO_ATTRIBUTES(VIDEO_ALWAYS_UPDATE)
MDRV_VIDEO_START(exidy440)
MDRV_VIDEO_UPDATE(exidy440)
MDRV_PALETTE_LENGTH(256)
beamx = ((input_port_4_r(0) & 0xff) * (EXIDY440_HBSTART - EXIDY440_HBEND)) >> 8;
beamy = ((input_port_5_r(0) & 0xff) * (EXIDY440_VBSTART - EXIDY440_VBEND)) >> 8;
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART)
MACHINE_DRIVER_END
/* The timing of this FIRQ is very important. The games look for an FIRQ
and then wait about 650 cycles, clear the old FIRQ, and wait a
very short period of time (~130 cycles) for another one to come in.
From this, it appears that they are expecting to get beams over
a 12 scanline period, and trying to pick roughly the middle one.
This is how it is implemented. */
increment = attotime_to_attoseconds(video_screen_get_scan_period(0));
time = attotime_sub(video_screen_get_time_until_pos(0, beamy, beamx), attotime_make(0, increment * 6));
for (i = 0; i <= 12; i++)
{
timer_set(time, NULL, beamx, beam_firq_callback);
time = attotime_add(time, attotime_make(0, increment));
}
}
}
MACHINE_DRIVER_START( topsecex_video )
MDRV_VIDEO_ATTRIBUTES(0)
MDRV_VIDEO_START(topsecex)
MDRV_VIDEO_UPDATE(topsecex)
MDRV_SCREEN_MODIFY("main")
MDRV_SCREEN_RAW_PARAMS(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, TOPSECEX_VBSTART)
MACHINE_DRIVER_END