Fix clock-coupled buzzer timing and HALT idle-cycle behavior - #40
Fix clock-coupled buzzer timing and HALT idle-cycle behavior#40andressbarajas wants to merge 1 commit into
Conversation
- **File:** `lib/source/hw/evmu_buzzer.c` - **Issue:** `EvmuBuzzer_setTone()` used a fixed quartz `/6` cycle time and only rebuilt PCM when `T1LR/T1LC` changed, so Timer1 audio pitch ignored live `OCR` clock selection and divider changes. - **Fix:** Derive PCM playback frequency from the current system clock via `EvmuClock_systemTicksPerCycle()`, keep one Timer1 cycle per PCM sample, and treat `OCR` writes as tone-affecting so active PWM audio re-buffers immediately when the VMU clock changes. HALT-mode timers inherited the previous instruction's cycle count - **File:** `lib/source/hw/evmu_cpu.c`, `lib/source/hw/evmu_timers.c` - **Issue:** While `PCON.HALT` was set, `EvmuCpu_secs()` correctly advanced the halted CPU loop by one system cycle at a time, but `EvmuCpu_cycles()` still returned the last decoded instruction's `cc` value. Timer0, Timer1, and the Base Timer therefore ran at an opcode-dependent speed while halted, which skewed BIOS clock updates for software that sleeps in `HALT` loops such as the `CCSakura*.vms` titles. - **Fix:** Make `EvmuCpu_cycles()` report a single cycle whenever the CPU is halted or held so timer advancement matches the halted CPU time step. Also add a conservative HALT-only batching path in the CPU update loop so high-clock titles do not spin one host-side iteration per emulated cycle while waiting for timer/interrupt wakeups.
|
Changing the buzzer behavior required gui frontend changes. I had AI generate a summary of those changes: The core contract changed from: “buzzer PCM is effectively always at one fixed rate” “buzzer PCM is a 1-cycle waveform with a dynamic source sample rate” A good shareable pattern is: // Open host audio once at a fixed output rate. // Frontend-owned playback state. AudioState s = {0}; void refresh_step() { // Call this after each emulator update, or whenever the core says pcmChanged. } // Audio callback fills host stream at fixed HOST_RATE. } Open the host audio device at one fixed output rate. libevmu buzzer output is now:
Frontend must:
|
Buzzer PCM timing was hardcoded to quartz
/6lib/source/hw/evmu_buzzer.cEvmuBuzzer_setTone()used a fixed quartz/6cycle time and only rebuilt PCM whenT1LR/T1LCchanged, so Timer1 audio pitch ignored liveOCRclock selection and divider changes.EvmuClock_systemTicksPerCycle(), keep one Timer1 cycle per PCM sample, and treatOCRwrites as tone-affecting so active PWM audio re-buffers immediately when the VMU clock changes.HALT-mode timers inherited the previous instruction's cycle count
lib/source/hw/evmu_cpu.c,lib/source/hw/evmu_timers.cPCON.HALTwas set,EvmuCpu_secs()correctly advanced the halted CPU loop by one system cycle at a time, butEvmuCpu_cycles()still returned the last decoded instruction'sccvalue. Timer0, Timer1, and the Base Timer therefore ran at an opcode-dependent speed while halted, which skewed BIOS clock updates for software that sleeps inHALTloops such as theCCSakura*.vmstitles.EvmuCpu_cycles()report a single cycle whenever the CPU is halted or held so timer advancement matches the halted CPU time step. Also add a conservative HALT-only batching path in the CPU update loop so high-clock titles do not spin one host-side iteration per emulated cycle while waiting for timer/interrupt wakeups. Without batching the game POPMUSIC*.VMS would have intense slowdown during gameplay. This was because the CF oscillator was being used and causing a lot of looping during halts.