diff --git a/src/emu/cpu/sh2/sh2.c b/src/emu/cpu/sh2/sh2.c index 70282c98c95..505d4b7560e 100644 --- a/src/emu/cpu/sh2/sh2.c +++ b/src/emu/cpu/sh2/sh2.c @@ -2173,6 +2173,7 @@ static CPU_RESET( sh2 ) memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16); memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17); sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0; + sh2->frc_remainder = 0; sh2->frc_base = 0; sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0; sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0; diff --git a/src/emu/cpu/sh2/sh2comn.c b/src/emu/cpu/sh2/sh2comn.c index c3e80888704..099d90a7016 100644 --- a/src/emu/cpu/sh2/sh2comn.c +++ b/src/emu/cpu/sh2/sh2comn.c @@ -64,7 +64,17 @@ static void sh2_timer_resync(sh2_state *sh2) UINT64 cur_time = sh2->device->total_cycles(); if(divider) - sh2->frc += (cur_time - sh2->frc_base) >> divider; + { + sh2->frc += (cur_time - sh2->frc_base) / (1 << divider); + sh2->frc_remainder += (cur_time - sh2->frc_base) % (1 << divider); + + if(sh2->frc_remainder >= divider) + { + sh2->frc_remainder-=divider; + sh2->frc++; + } + } + sh2->frc_base = cur_time; } @@ -119,6 +129,7 @@ static TIMER_CALLBACK( sh2_timer_callback ) if(frc == sh2->ocrb) sh2->m[4] |= OCFB; + /* FIXME: frc increments isn't stable! */ if(frc == 0x0000) sh2->m[4] |= OVF; @@ -127,7 +138,7 @@ static TIMER_CALLBACK( sh2_timer_callback ) sh2->m[4] |= OCFA; if(sh2->m[4] & 0x010000) - sh2->frc = 0; + sh2->frc = sh2->frc_remainder = 0; } sh2_recalc_irq(sh2); @@ -528,6 +539,7 @@ WRITE32_HANDLER( sh2_internal_w ) // printf("SH2.%s: TIER write %04x @ %04x\n", sh2->device->tag(), data >> 16, mem_mask>>16); sh2->m[4] = (sh2->m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2->m[4] & (ICF|OCFA|OCFB|OVF)); COMBINE_DATA(&sh2->frc); + sh2->frc_remainder = 0; if((mem_mask & 0x00ffffff) != 0) sh2_timer_activate(sh2); sh2_recalc_irq(sh2); @@ -988,6 +1000,7 @@ void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_callb device->save_pointer(NAME(sh2->m), 0x200/4); device->save_item(NAME(sh2->nmi_line_state)); device->save_item(NAME(sh2->frc)); + device->save_item(NAME(sh2->frc_remainder)); device->save_item(NAME(sh2->ocra)); device->save_item(NAME(sh2->ocrb)); device->save_item(NAME(sh2->icr)); diff --git a/src/emu/cpu/sh2/sh2comn.h b/src/emu/cpu/sh2/sh2comn.h index 9f2509a0146..99cef451114 100644 --- a/src/emu/cpu/sh2/sh2comn.h +++ b/src/emu/cpu/sh2/sh2comn.h @@ -127,6 +127,7 @@ typedef struct INT8 nmi_line_state; UINT16 frc; + UINT16 frc_remainder; UINT16 ocra, ocrb, icr; UINT64 frc_base;