From 4c2953d8efa42269dd3df3bdb0e309aa801c14c9 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Fri, 28 Nov 2008 22:58:24 +0000 Subject: [PATCH] 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) --- src/mame/drivers/stv.c | 34 +++++++++++------- src/mame/video/stvvdp2.c | 77 ++++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/src/mame/drivers/stv.c b/src/mame/drivers/stv.c index 63f7424167d..88f5cf4aab9 100644 --- a/src/mame/drivers/stv.c +++ b/src/mame/drivers/stv.c @@ -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,15 +2613,17 @@ 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) { - timer_adjust_oneshot(scan_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline+1, h_sync), scanline+1); + 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; - timer_adjust_oneshot(t1_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline+1, 0), 0); + if(stv_irq.timer_1) + timer_adjust_oneshot(t1_timer, video_screen_get_time_until_pos(machine->primary_screen, scanline+1, 0), 0); } timer_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,15 +2657,19 @@ 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*/ - timer_adjust_oneshot(vblank_out_timer,video_screen_get_time_until_pos(device->machine->primary_screen, 0, 0), 0); + 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*/ - timer_adjust_oneshot(scan_timer, video_screen_get_time_until_pos(device->machine->primary_screen, 0, h_sync), 0); + 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)*/ /* (NOTE: value shouldn't be at h_sync/v_sync position (will break shienryu))*/ diff --git a/src/mame/video/stvvdp2.c b/src/mame/video/stvvdp2.c index f80070dd7c1..383de3142f4 100644 --- a/src/mame/video/stvvdp2.c +++ b/src/mame/video/stvvdp2.c @@ -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); + /*VBLANK HBLANK ODD PAL */ + 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)