diff --git a/src/emu/video/mc6845.c b/src/emu/video/mc6845.c index b3587157b57..8811c51ca50 100644 --- a/src/emu/video/mc6845.c +++ b/src/emu/video/mc6845.c @@ -52,7 +52,9 @@ struct _mc6845_t UINT16 cursor; UINT16 light_pen; - emu_timer *display_enable_changed_timer; + emu_timer *de_changed_timer; + emu_timer *hsync_timer; + emu_timer *vsync_timer; UINT8 cursor_state; /* 0 = off, 1 = on */ UINT8 cursor_blink_count; @@ -63,6 +65,8 @@ struct _mc6845_t UINT16 last_vert_total; UINT16 last_max_x; UINT16 last_max_y; + UINT16 last_hsync_pos; + UINT16 last_vsync_pos; UINT16 current_ma; /* the MA address currently drawn */ int has_valid_parameters; }; @@ -70,8 +74,12 @@ struct _mc6845_t static void mc6845_state_save_postload(void *param); static void configure_screen(mc6845_t *mc6845, int postload); -static void update_timer(mc6845_t *mc6845); -static TIMER_CALLBACK( display_enable_changed_timer_cb ); +static void update_de_changed_timer(mc6845_t *mc6845); +static void update_hsync_timer(mc6845_t *mc6845); +static void update_vsync_timer(mc6845_t *mc6845); +static TIMER_CALLBACK( de_changed_timer_cb ); +static TIMER_CALLBACK( vsync_timer_cb ); +static TIMER_CALLBACK( hsync_timer_cb ); static void mc6845_state_save_postload(void *param) @@ -140,6 +148,7 @@ void mc6845_register_w(mc6845_t *mc6845, UINT8 data) break; case 2: mc6845->horiz_sync_pos = data; + call_configure_screen = TRUE; break; case 3: mc6845->sync_width = data & 0x0f; @@ -158,6 +167,7 @@ void mc6845_register_w(mc6845_t *mc6845, UINT8 data) break; case 7: mc6845->vert_sync_pos = data & 0x7f; + call_configure_screen = TRUE; break; case 8: mc6845->intl_skew = data & 0x03; @@ -215,13 +225,20 @@ static void configure_screen(mc6845_t *mc6845, int postload) UINT16 max_x = mc6845->horiz_disp * mc6845->intf->hpixels_per_column - 1; UINT16 max_y = mc6845->vert_disp * (mc6845->max_ras_addr + 1) - 1; + /* determine the syncing positions */ + UINT16 hsync_pos = mc6845->horiz_sync_pos * mc6845->intf->hpixels_per_column; + UINT16 vsync_pos = mc6845->vert_sync_pos * (mc6845->max_ras_addr + 1); + /* update only if screen parameters changed, unless we are coming here after loading the saved state */ if (postload || (horiz_total != mc6845->last_horiz_total) || (vert_total != mc6845->last_vert_total) || - (max_x != mc6845->last_max_x) || (max_y != mc6845->last_max_y)) + (max_x != mc6845->last_max_x) || (max_y != mc6845->last_max_y) || + (hsync_pos != mc6845->last_hsync_pos) || (vsync_pos != mc6845->last_vsync_pos)) { /* update the screen only if we have valid data */ - if ((mc6845->horiz_total > 0) && (max_x < horiz_total) && (mc6845->vert_total > 0) && (max_y < vert_total)) + if ((horiz_total > 0) && (max_x < horiz_total) && + (vert_total > 0) && (max_y < vert_total) && + (hsync_pos < horiz_total) && (vsync_pos < vert_total)) { rectangle visarea; @@ -232,8 +249,8 @@ static void configure_screen(mc6845_t *mc6845, int postload) visarea.max_x = max_x; visarea.max_y = max_y; - if (LOG) logerror("M6845 config screen: HTOTAL: %x VTOTAL: %x MAX_X: %x MAX_Y: %x FPS: %f\n", - horiz_total, vert_total, max_x, max_y, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); + if (LOG) logerror("M6845 config screen: HTOTAL: %x VTOTAL: %x MAX_X: %x MAX_Y: %x HSYNC: %x VSYNC: %x FPS: %f\n", + horiz_total, vert_total, max_x, max_y, hsync_pos, vsync_pos, 1 / ATTOSECONDS_TO_DOUBLE(refresh)); video_screen_configure(mc6845->intf->scrnum, horiz_total, vert_total, &visarea, refresh); @@ -246,8 +263,12 @@ static void configure_screen(mc6845_t *mc6845, int postload) mc6845->last_vert_total = vert_total; mc6845->last_max_x = max_x; mc6845->last_max_y = max_y; + mc6845->last_hsync_pos = hsync_pos; + mc6845->last_vsync_pos = vsync_pos; - update_timer(mc6845); + update_de_changed_timer(mc6845); + update_hsync_timer(mc6845); + update_vsync_timer(mc6845); } } } @@ -262,19 +283,17 @@ static int is_display_enabled(mc6845_t *mc6845) } -static void update_timer(mc6845_t *mc6845) +static void update_de_changed_timer(mc6845_t *mc6845) { - INT16 next_y; - UINT16 next_x; - attotime duration; - - if (mc6845->has_valid_parameters && (mc6845->display_enable_changed_timer != 0)) + if (mc6845->has_valid_parameters && (mc6845->de_changed_timer != NULL)) { + INT16 next_y; + UINT16 next_x; + attotime duration; + + /* we are in a display region, get the location of the next blanking start */ if (is_display_enabled(mc6845)) { - /* we are in a display region, - get the location of the next blanking start */ - /* normally, it's at end the current raster line */ next_y = video_screen_get_vpos(mc6845->intf->scrnum); next_x = mc6845->last_max_x + 1; @@ -291,10 +310,10 @@ static void update_timer(mc6845_t *mc6845) next_y = -1; } } + + /* we are in a blanking region, get the location of the next display start */ else { - /* we are in a blanking region, - get the location of the next display start */ next_x = 0; next_y = (video_screen_get_vpos(mc6845->intf->scrnum) + 1) % mc6845->last_vert_total; @@ -309,19 +328,71 @@ static void update_timer(mc6845_t *mc6845) else duration = attotime_never; - timer_adjust_oneshot(mc6845->display_enable_changed_timer, duration, 0); + timer_adjust_oneshot(mc6845->de_changed_timer, duration, 0); } } -static TIMER_CALLBACK( display_enable_changed_timer_cb ) +static void update_hsync_timer(mc6845_t *mc6845) +{ + if (mc6845->has_valid_parameters && (mc6845->hsync_timer != NULL)) + { + UINT16 next_y; + + /* we are before the HSYNC position, we trigger on the current line */ + if (video_screen_get_hpos(mc6845->intf->scrnum) < mc6845->last_hsync_pos) + next_y = video_screen_get_vpos(mc6845->intf->scrnum); + + /* trigger on the next line */ + else + next_y = (video_screen_get_vpos(mc6845->intf->scrnum) + 1) % mc6845->last_vert_total; + + /* if the next line is not in the visible region, go to the beginning of the screen */ + if (next_y > mc6845->last_max_y) + next_y = 0; + + timer_adjust_oneshot(mc6845->hsync_timer, video_screen_get_time_until_pos(mc6845->intf->scrnum, next_y, mc6845->last_hsync_pos), 0); + } +} + + +static void update_vsync_timer(mc6845_t *mc6845) +{ + if (mc6845->has_valid_parameters && (mc6845->vsync_timer != NULL)) + timer_adjust_oneshot(mc6845->vsync_timer, video_screen_get_time_until_pos(mc6845->intf->scrnum, mc6845->last_vsync_pos, 0), 0); +} + + +static TIMER_CALLBACK( de_changed_timer_cb ) { mc6845_t *mc6845 = ptr; /* call the callback function -- we know it exists */ - mc6845->intf->display_enable_changed(mc6845->machine, mc6845, is_display_enabled(mc6845)); + mc6845->intf->on_de_changed(mc6845->machine, mc6845, is_display_enabled(mc6845)); - update_timer(mc6845); + update_de_changed_timer(mc6845); +} + + +static TIMER_CALLBACK( vsync_timer_cb ) +{ + mc6845_t *mc6845 = ptr; + + /* call the callback function -- we know it exists */ + mc6845->intf->on_vsync(mc6845->machine, mc6845); + + update_vsync_timer(mc6845); +} + + +static TIMER_CALLBACK( hsync_timer_cb ) +{ + mc6845_t *mc6845 = ptr; + + /* call the callback function -- we know it exists */ + mc6845->intf->on_hsync(mc6845->machine, mc6845); + + update_hsync_timer(mc6845); } @@ -477,10 +548,18 @@ static void *mc6845_start(running_machine *machine, const char *tag, const void mc6845->machine = machine; mc6845->intf = static_config; - /* create the timer if the user is interested in getting display enable - notifications */ - if (mc6845->intf && mc6845->intf->display_enable_changed) - mc6845->display_enable_changed_timer = timer_alloc(display_enable_changed_timer_cb, mc6845); + /* create the timers for the various pin notifications */ + if (mc6845->intf) + { + if (mc6845->intf->on_de_changed) + mc6845->de_changed_timer = timer_alloc(de_changed_timer_cb, mc6845); + + if (mc6845->intf->on_hsync) + mc6845->hsync_timer = timer_alloc(hsync_timer_cb, mc6845); + + if (mc6845->intf->on_vsync) + mc6845->vsync_timer = timer_alloc(vsync_timer_cb, mc6845); + } /* register for state saving */ state_save_combine_module_and_tag(unique_tag, "mc6845", tag); diff --git a/src/emu/video/mc6845.h b/src/emu/video/mc6845.h index 9f2a17b0910..bf6098ee9ba 100644 --- a/src/emu/video/mc6845.h +++ b/src/emu/video/mc6845.h @@ -28,6 +28,33 @@ typedef struct _mc6845_interface mc6845_interface; #define R6545 r6545_get_info +/* callback definitions */ +typedef void * (*mc6845_begin_update_func)(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect); +#define MC6845_BEGIN_UPDATE(name) void *name(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect) + +typedef void (*mc6845_update_row_func)(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, + const rectangle *cliprect, UINT16 ma, UINT8 ra, + UINT16 y, UINT8 x_count, INT8 cursor_x, void *param); +#define MC6845_UPDATE_ROW(name) void name(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, \ + const rectangle *cliprect, UINT16 ma, UINT8 ra, \ + UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) + +typedef void (*mc6845_end_update_func)(running_machine *machine, mc6845_t *mc6845, + mame_bitmap *bitmap, const rectangle *cliprect, void *param); +#define MC6845_END_UPDATE(name) void name(running_machine *machine, mc6845_t *mc6845, \ + mame_bitmap *bitmap, const rectangle *cliprect, void *param) + +typedef void (*mc6845_on_de_changed_func)(running_machine *machine, mc6845_t *mc6845, int display_enabled); +#define MC6845_ON_DE_CHANGED(name) void name(running_machine *machine, mc6845_t *mc6845, int display_enabled) + +typedef void (*mc6845_on_hsync_func)(running_machine *machine, mc6845_t *mc6845); +#define MC6845_ON_HSYNC(name) void name(running_machine *machine, mc6845_t *mc6845) + +typedef void (*mc6845_on_vsync_func)(running_machine *machine, mc6845_t *mc6845); +#define MC6845_ON_VSYNC(name) void name(running_machine *machine, mc6845_t *mc6845) + + +/* interface */ struct _mc6845_interface { int scrnum; /* screen we are acting on */ @@ -37,23 +64,25 @@ struct _mc6845_interface /* if specified, this gets called before any pixel update, optionally return a pointer that will be passed to the update and tear down callbacks */ - void * (*begin_update)(running_machine *machine, mc6845_t *mc6845, - mame_bitmap *bitmap, const rectangle *cliprect); + mc6845_begin_update_func begin_update; /* this gets called for every row, the driver must output x_count * hpixels_per_column pixels. cursor_x indicates the character position where the cursor is, or -1 if there is no cursor on this row */ - void (*update_row)(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, - const rectangle *cliprect, UINT16 ma, UINT8 ra, - UINT16 y, UINT8 x_count, INT8 cursor_x, void *param); + mc6845_update_row_func update_row; /* if specified, this gets called after all row updating is complete */ - void (*end_update)(running_machine *machine, mc6845_t *mc6845, - mame_bitmap *bitmap, const rectangle *cliprect, void *param); + mc6845_end_update_func end_update; - /* if specified, this gets called for every change of the disply enable (DT pin 18) */ - void (*display_enable_changed)(running_machine *machine, mc6845_t *mc6845, int display_enabled); + /* if specified, this gets called for every change of the disply enable pin (pin 18) */ + mc6845_on_de_changed_func on_de_changed; + + /* if specified, this gets called when the HSYNC pin is asserted (pin 39) */ + mc6845_on_hsync_func on_hsync; + + /* if specified, this gets called when the VSYNC pin is asserted (pin 40) */ + mc6845_on_vsync_func on_vsync; }; diff --git a/src/mame/drivers/nyny.c b/src/mame/drivers/nyny.c index d610c29a8ec..d94dc98fdfb 100644 --- a/src/mame/drivers/nyny.c +++ b/src/mame/drivers/nyny.c @@ -288,7 +288,7 @@ static WRITE8_HANDLER( flipscreen_w ) } -static void *nyny_begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect) +static MC6845_BEGIN_UPDATE( begin_update ) { /* create the pens */ offs_t i; @@ -303,8 +303,7 @@ static void *nyny_begin_update(running_machine *machine, mc6845_t *mc6845, mame_ } -static void nyny_update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, - UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) +static MC6845_UPDATE_ROW( update_row ) { UINT8 cx; @@ -373,7 +372,7 @@ INLINE void shift_star_generator(void) } -static void nyny_end_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, void *param) +static MC6845_END_UPDATE( end_update ) { /* draw the star field into the bitmap */ int y; @@ -409,7 +408,7 @@ static void nyny_end_update(running_machine *machine, mc6845_t *mc6845, mame_bit } -static void nyny_display_enable_changed(running_machine *machine, mc6845_t *mc6845, int display_enabled) +static MC6845_ON_DE_CHANGED( display_enable_changed ) { TTL74123_A_w(0, display_enabled); } @@ -417,13 +416,15 @@ static void nyny_display_enable_changed(running_machine *machine, mc6845_t *mc68 static const mc6845_interface mc6845_intf = { - 0, /* screen we are acting on */ - CRTC_CLOCK, /* the clock (pin 21) of the chip */ - 8, /* number of pixels per video memory address */ - nyny_begin_update, /* before pixel update callback */ - nyny_update_row, /* row update callback */ - nyny_end_update, /* after pixel update callback */ - nyny_display_enable_changed /* call back for display state changes */ + 0, /* screen we are acting on */ + CRTC_CLOCK, /* the clock (pin 21) of the chip */ + 8, /* number of pixels per video memory address */ + begin_update, /* before pixel update callback */ + update_row, /* row update callback */ + end_update, /* after pixel update callback */ + display_enable_changed, /* callback for display state changes */ + NULL, /* HSYNC callback */ + NULL /* VSYNC callback */ }; diff --git a/src/mame/drivers/r2dtank.c b/src/mame/drivers/r2dtank.c index 446915938d9..58b045ae00e 100644 --- a/src/mame/drivers/r2dtank.c +++ b/src/mame/drivers/r2dtank.c @@ -322,7 +322,7 @@ static WRITE8_HANDLER( flipscreen_w ) } -static void *begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect) +static MC6845_BEGIN_UPDATE( begin_update ) { /* create the pens */ offs_t i; @@ -337,8 +337,7 @@ static void *begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitma } -static void update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, - UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) +static MC6845_UPDATE_ROW( update_row ) { UINT8 cx; @@ -387,7 +386,7 @@ static void update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap * } -static void display_enable_changed(running_machine *machine, mc6845_t *mc6845, int display_enabled) +static MC6845_ON_DE_CHANGED( display_enable_changed ) { TTL74123_A_w(0, display_enabled); } @@ -401,7 +400,9 @@ static const mc6845_interface mc6845_intf = begin_update, /* before pixel update callback */ update_row, /* row update callback */ 0, /* after pixel update callback */ - display_enable_changed /* call back for display state changes */ + display_enable_changed, /* callback for display state changes */ + NULL, /* HSYNC callback */ + NULL /* VSYNC callback */ }; diff --git a/src/mame/drivers/spiders.c b/src/mame/drivers/spiders.c index 78046fc5b20..bb229a27183 100644 --- a/src/mame/drivers/spiders.c +++ b/src/mame/drivers/spiders.c @@ -434,7 +434,7 @@ static WRITE8_HANDLER( flipscreen_w ) } -static void *begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect) +static MC6845_BEGIN_UPDATE( begin_update ) { /* create the pens */ offs_t i; @@ -449,8 +449,7 @@ static void *begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitma } -static void update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, - UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) +static MC6845_UPDATE_ROW( update_row ) { UINT8 cx; @@ -509,7 +508,7 @@ static void update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap * } -static void display_enable_changed(running_machine *machine, mc6845_t *mc6845, int display_enabled) +static MC6845_ON_DE_CHANGED( display_enable_changed ) { TTL74123_A_w(0, display_enabled); } @@ -523,7 +522,9 @@ static const mc6845_interface mc6845_intf = begin_update, /* before pixel update callback */ update_row, /* row update callback */ 0, /* after pixel update callback */ - display_enable_changed /* call back for display state changes */ + display_enable_changed, /* callback for display state changes */ + NULL, /* HSYNC callback */ + NULL /* VSYNC callback */ }; diff --git a/src/mame/drivers/ssingles.c b/src/mame/drivers/ssingles.c index a06c4252534..f53eaa6b095 100644 --- a/src/mame/drivers/ssingles.c +++ b/src/mame/drivers/ssingles.c @@ -47,8 +47,7 @@ static const UINT8 ssingles_colors[NUM_PENS*3]= 0x00,0x00,0x00, 0xff,0x00,0xff, 0x80,0x00,0x80, 0x40,0x00,0x40 }; -static void update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, - UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) +static MC6845_UPDATE_ROW( update_row ) { int cx,x; UINT32 tile_address; @@ -92,6 +91,8 @@ static const mc6845_interface mc6845_intf = NULL, update_row, NULL, + NULL, + NULL, NULL }; diff --git a/src/mame/video/madalien.c b/src/mame/video/madalien.c index bf342c2f6ae..0b7a02ab438 100644 --- a/src/mame/video/madalien.c +++ b/src/mame/video/madalien.c @@ -404,7 +404,9 @@ static const mc6845_interface mc6845_intf = NULL, /* before pixel update callback */ NULL, /* row update callback */ NULL, /* after pixel update callback */ - NULL /* call back for display state changes */ + NULL, /* callback for display state changes */ + NULL, /* HSYNC callback */ + NULL /* VSYNC callback */ }; diff --git a/src/mame/video/qix.c b/src/mame/video/qix.c index 6f9b4d80062..c63f46e2481 100644 --- a/src/mame/video/qix.c +++ b/src/mame/video/qix.c @@ -19,20 +19,9 @@ * *************************************/ -static void qix_display_enable_changed(running_machine *machine, mc6845_t *mc6845, int display_enabled); - -static void *qix_begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect); - -static void qix_update_row(running_machine *machine, - mc6845_t *mc6845, - mame_bitmap *bitmap, - const rectangle *cliprect, - UINT16 ma, - UINT8 ra, - UINT16 y, - UINT8 x_count, - INT8 cursor_x, - void *param); +static MC6845_BEGIN_UPDATE( begin_update ); +static MC6845_UPDATE_ROW( update_row ); +static MC6845_ON_DE_CHANGED( display_enable_changed ); @@ -67,7 +56,7 @@ static VIDEO_START( qix ) * *************************************/ -static void qix_display_enable_changed(running_machine *machine, mc6845_t *mc6845, int display_enabled) +static MC6845_ON_DE_CHANGED( display_enable_changed ) { qix_state *state = machine->driver_data; @@ -335,7 +324,7 @@ static WRITE8_HANDLER( qix_mc6845_register_w ) * *************************************/ -static void *qix_begin_update(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect) +static MC6845_BEGIN_UPDATE( begin_update ) { qix_state *state = machine->driver_data; @@ -353,8 +342,8 @@ static void *qix_begin_update(running_machine *machine, mc6845_t *mc6845, mame_b } -static void qix_update_row(running_machine *machine, mc6845_t *mc6845, mame_bitmap *bitmap, const rectangle *cliprect, - UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) +static MC6845_UPDATE_ROW( update_row ) + { qix_state *state = machine->driver_data; UINT16 x; @@ -460,13 +449,15 @@ ADDRESS_MAP_END static const mc6845_interface mc6845_intf = { - 0, /* screen we are acting on */ - QIX_CHARACTER_CLOCK, /* the clock (pin 21) of the chip */ - 8, /* number of pixels per video memory address */ - qix_begin_update, /* before pixel update callback */ - qix_update_row, /* row update callback */ - 0, /* after pixel update callback */ - qix_display_enable_changed /* call back for display state changes */ + 0, /* screen we are acting on */ + QIX_CHARACTER_CLOCK, /* the clock (pin 21) of the chip */ + 8, /* number of pixels per video memory address */ + begin_update, /* before pixel update callback */ + update_row, /* row update callback */ + NULL, /* after pixel update callback */ + display_enable_changed, /* callback for display state changes */ + NULL, /* HSYNC callback */ + NULL /* VSYNC callback */ };