- int tm = (Pico32x.regs[0x30 / 2] & 0x0f00) >> 8;
- if (tm == 0)
- return; // TODO: verify
-
- Pico32x.pwm_irq_sample_cnt += pwm_line_samples;
- if (Pico32x.pwm_irq_sample_cnt >= (tm << 16)) {
- Pico32x.pwm_irq_sample_cnt -= tm << 16;
- Pico32x.sh2irqs |= P32XI_PWM;
- p32x_update_irls();
+ int cnt, i;
+
+ cycles *= 3;
+
+ // since we run things in async fashion, allow pwm to lag behind
+ // but don't allow our "queue" to be infinite
+ cnt = pwm_smp_expect - pwm_smp_cnt;
+ if (cnt <= 0 || cnt * pwm_cycles < OSC_NTSC/7*3 / 60 / 2) {
+ pwm_cycle_counter += cycles;
+ while (pwm_cycle_counter > pwm_cycles) {
+ pwm_cycle_counter -= pwm_cycles;
+ pwm_smp_expect++;
+ }
+ }
+
+ // WDT timers
+ for (i = 0; i < 2; i++) {
+ void *pregs = Pico32xMem->sh2_peri_regs[i];
+ if (PREG8(pregs, 0x80) & 0x20) { // TME
+ timer_cycles[i] += cycles;
+ cnt = PREG8(pregs, 0x81);
+ while (timer_cycles[i] >= timer_tick_cycles[i]) {
+ timer_cycles[i] -= timer_tick_cycles[i];
+ cnt++;
+ }
+ if (cnt >= 0x100) {
+ int level = PREG8(pregs, 0xe3) >> 4;
+ int vector = PREG8(pregs, 0xe4) & 0x7f;
+ elprintf(EL_32X, "%csh2 WDT irq (%d, %d)",
+ i ? 's' : 'm', level, vector);
+ sh2_internal_irq(&sh2s[i], level, vector);
+ cnt &= 0xff;
+ }
+ PREG8(pregs, 0x81) = cnt;
+ }