Many improvements on the irq handling of the ST-V driver [Angelo Salese,Charles MacDonald]

* Fixed a bug with irq timings;
* Added ODD bit emulation;
* Fixed vblank period timings;
* Optimized a bit the whole interrupt routines,getting a 4x speed gain;
* Fixed an irq mask handling bug;
(This fixes at least Astra SuperStars and Pebble Beach booting,but the latter still fails the timer 1 irq routines...I need to check why)
This commit is contained in:
Angelo Salese 2008-11-28 22:58:24 +00:00
parent 1962ffeaf9
commit 4c2953d8ef
2 changed files with 79 additions and 32 deletions

View File

@ -195,6 +195,8 @@ static UINT16* scsp_regs;
static UINT16* sound_ram;
int stv_enable_slave_sh2;
/*VDP2 stuff*/
extern int get_vblank_duration(running_machine *machine);
/*SMPC stuff*/
static UINT8 NMI_reset;
static void system_reset(void);
@ -1332,9 +1334,9 @@ static WRITE32_HANDLER( stv_scu_w32 )
stv_irq.sound_req = (((stv_scu[40] & 0x0040)>>6) ^ 1);
stv_irq.smpc = (((stv_scu[40] & 0x0080)>>7)); //NOTE: SCU bug
stv_irq.pad = (((stv_scu[40] & 0x0100)>>8) ^ 1);
stv_irq.dma_end[0] = (((stv_scu[40] & 0x0200)>>9) ^ 1);
stv_irq.dma_end[2] = (((stv_scu[40] & 0x0200)>>9) ^ 1);
stv_irq.dma_end[1] = (((stv_scu[40] & 0x0400)>>10) ^ 1);
stv_irq.dma_end[2] = (((stv_scu[40] & 0x0800)>>11) ^ 1);
stv_irq.dma_end[0] = (((stv_scu[40] & 0x0800)>>11) ^ 1);
stv_irq.dma_ill = (((stv_scu[40] & 0x1000)>>12) ^ 1);
stv_irq.vdp1_end = (((stv_scu[40] & 0x2000)>>13) ^ 1);
stv_irq.abus = (((stv_scu[40] & 0x8000)>>15) ^ 1);
@ -1379,9 +1381,9 @@ static WRITE32_HANDLER( stv_scu_w32 )
stv_irq.sound_req = ((stv_scu[41] & 0x0040)>>6);
stv_irq.smpc = ((stv_scu[41] & 0x0080)>>7);
stv_irq.pad = ((stv_scu[41] & 0x0100)>>8);
stv_irq.dma_end[0] = ((stv_scu[41] & 0x0200)>>9);
stv_irq.dma_end[2] = ((stv_scu[41] & 0x0200)>>9);
stv_irq.dma_end[1] = ((stv_scu[41] & 0x0400)>>10);
stv_irq.dma_end[2] = ((stv_scu[41] & 0x0800)>>11);
stv_irq.dma_end[0] = ((stv_scu[41] & 0x0800)>>11);
stv_irq.dma_ill = ((stv_scu[41] & 0x1000)>>12);
stv_irq.vdp1_end = ((stv_scu[41] & 0x2000)>>13);
stv_irq.abus = ((stv_scu[41] & 0x8000)>>15);
@ -2611,14 +2613,16 @@ static TIMER_CALLBACK( hblank_in_irq )
// h = video_screen_get_height(machine->primary_screen);
// w = video_screen_get_width(machine->primary_screen);
TIMER_0_IRQ;
HBLANK_IN_IRQ;
TIMER_0_IRQ;
if((scanline+1) < v_sync)
if(scanline+1 < v_sync)
{
if(stv_irq.hblank_in || stv_irq.timer_0)
timer_adjust_oneshot(scan_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline+1, h_sync), scanline+1);
/*set the first Timer-1 event*/
cur_scan = scanline+1;
if(stv_irq.timer_1)
timer_adjust_oneshot(t1_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline+1, 0), 0);
}
@ -2631,7 +2635,7 @@ static TIMER_CALLBACK( timer1_irq )
TIMER_1_IRQ;
if((cur_point+1) < h_sync)
if((cur_point+1) < h_sync && stv_irq.timer_1)
{
timer_adjust_oneshot(t1_timer, video_screen_get_time_until_pos(machine->primary_screen, cur_scan, cur_point+1), cur_point+1);
}
@ -2653,14 +2657,18 @@ static TIMER_CALLBACK( vblank_out_irq )
static INTERRUPT_GEN( stv_interrupt )
{
// scanline = 0;
h_sync = video_screen_get_height(device->machine->primary_screen)/2;//horz
v_sync = video_screen_get_width(device->machine->primary_screen)-2;//vert
rectangle visarea = *video_screen_get_visible_area(device->machine->primary_screen);
h_sync = visarea.max_x+1;//horz
v_sync = visarea.max_y+1;//vert
VBLANK_IN_IRQ;
/*Next V-Blank-OUT event*/
if(stv_irq.vblank_out)
timer_adjust_oneshot(vblank_out_timer,video_screen_get_time_until_pos(device->machine->primary_screen, 0, 0), 0);
/*Set the first Hblank-IN event*/
if(stv_irq.hblank_in || stv_irq.timer_0 || stv_irq.timer_1)
timer_adjust_oneshot(scan_timer, video_screen_get_time_until_pos(device->machine->primary_screen, 0, h_sync), 0);
/*TODO: timing of this one (related to the VDP1 speed)*/

View File

@ -67,6 +67,9 @@ its not displayed because its priority value is 0.Left-over?
-scrolling is screen display wise,meaning that a scrolling value is masked with the
screen resolution size values;
-H-Blank bit is INDIPENDENT of the V-Blank bit...trying to fix enable/disable it during V-Blank period
causes wrong gameplay speed in Golden Axe:The Duel.
-Bitmaps uses transparency pens,examples are:
\-elandore's energy bars;
\-mausuke's foreground(the one used on the playfield)
@ -112,13 +115,18 @@ static UINT8* stv_vdp2_vram_dirty_8x8x8;
static UINT8* stv_vdp2_gfx_decode;
static int stv_vdp2_render_rbg0;
int stv_hblank,stv_vblank;
int stv_hblank,stv_vblank,stv_odd;
int horz_res,vert_res;
UINT32* stv_vdp2_cram;
static void stv_vdp2_dynamic_res_change(running_machine *machine);
UINT8 get_vblank(running_machine *machine);
UINT8 get_hblank(running_machine *machine);
int get_vblank_duration(running_machine *machine);
//int get_hblank_duration(running_machine *machine); //<- when we know that...
UINT8 get_odd_bit(running_machine *machine);
static void refresh_palette_data(running_machine *machine);
static int stv_vdp2_window_process(int x,int y);
static int stv_vdp2_apply_window_on_layer(rectangle *cliprect);
@ -5277,6 +5285,9 @@ UINT8 get_hblank(running_machine *machine)
return 0;
}
//int get_hblank_duration(running_machine *machine)
//...
UINT8 get_vblank(running_machine *machine)
{
static int cur_v;
@ -5289,6 +5300,43 @@ UINT8 get_vblank(running_machine *machine)
return 0;
}
/*some vblank lines measurements (according to Charles MacDonald)*/
int get_vblank_duration(running_machine *machine)
{
if(STV_VDP2_HRES & 4)
{
switch(STV_VDP2_HRES & 1)
{
case 0: return 45; //31kHz Monitor
case 1: return 82; //Hi-Vision Monitor
}
}
switch(STV_VDP2_VRES & 3)
{
case 0: return 39; //263-224
case 1: return 23; //263-240
case 2: return 7; //263-256
case 3: return 7; //263-256
}
return 0;
}
UINT8 get_odd_bit(running_machine *machine)
{
static int cur_v;
cur_v = video_screen_get_vpos(machine->primary_screen);
if(STV_VDP2_HRES & 4) //exclusive monitor mode makes this bit to be always 1
return 1;
if(cur_v % 2)
return 1;
else
return 0;
}
READ32_HANDLER ( stv_vdp2_regs_r )
{
// if (offset!=1) if(LOG_VDP2) logerror ("VDP2: Read from Registers, Offset %04x\n",offset);
@ -5298,25 +5346,12 @@ READ32_HANDLER ( stv_vdp2_regs_r )
case 0x4/4:
{
/*Screen Status Register*/
//rectangle visarea = *video_screen_get_visible_area(machine->primary_screen);
//stv_hblank = 0;
//stv_vblank = 0;
//h = video_screen_get_height(machine->primary_screen);
//w = video_screen_get_width(machine->primary_screen);
//cur_h = video_screen_get_hpos(machine->primary_screen);
//cur_v = video_screen_get_vpos(machine->primary_screen);
//popmessage("%d %d",cur_h,cur_v);
//if (cur_h > visarea.max_x)
stv_hblank = get_hblank(space->machine);
//if (cur_v > visarea.max_y)
stv_vblank = get_vblank(space->machine);
/*ODD bit*/
stv_hblank = get_hblank(space->machine);
stv_odd = get_odd_bit(space->machine);
/*VBLANK HBLANK ODD PAL */
stv_vdp2_regs[offset] = (stv_vblank<<19) | (stv_hblank<<18) | (1 << 17) | (0 << 16);
stv_vdp2_regs[offset] = (stv_vblank<<19) | (stv_hblank<<18) | (stv_odd << 17) | (0 << 16);
break;
}
case 0x8/4:
@ -5400,13 +5435,17 @@ VIDEO_START( stv_vdp2 )
/* & height / width not yet understood (docs-wise MUST be bigger than normal visible area)*/
static TIMER_CALLBACK( dyn_res_change )
{
UINT8 vblank_period;
rectangle visarea = *video_screen_get_visible_area(machine->primary_screen);
visarea.min_x = 0;
visarea.max_x = horz_res-1;
visarea.min_y = 0;
visarea.max_y = vert_res-1;
video_screen_configure(machine->primary_screen, horz_res*2, vert_res+2, &visarea, video_screen_get_frame_period(machine->primary_screen).attoseconds );
vblank_period = get_vblank_duration(machine);
// popmessage("%d",vblank_period);
// hblank_period = get_hblank_duration(machine->primary_screen);
video_screen_configure(machine->primary_screen, horz_res*2, (vert_res+vblank_period), &visarea, video_screen_get_frame_period(machine->primary_screen).attoseconds );
}
static void stv_vdp2_dynamic_res_change(running_machine *machine)