For those curious, here's the source code I used to compile the patch. Compiled using NASM for windows:
bits 32
return_from_patch equ 0x428866
exit_from_timer equ 0x428db5
execution_speed equ 0x46dcd4
frame_skip equ 0x46dcd8
last_tick equ 0x46dd04
timer_id equ 0x467a78
timer_interval equ 0x46da98
timer_interval_2 equ 0x467c14
timer_type equ 0x46e584
exit_flag equ 0x4489d0
timer_proc equ 0x428820
settimer_ptr equ 0x4412bc
sound_freq equ 0x472350
sound_interval equ 0x470eb8
sound_ptr equ 0x472340
sound_buffer_size equ 0x4722c0
ms_fraction equ 0x473b34
previous_divisor equ 0x473b38
keep_tick equ 0x473b3c
sound_fraction equ 0x473b40
sound_deficit equ 0x473b44
org 0x428bbc
jmp 0x428d8c
patch_entry:
mov al, [timer_type]
test al, al
je .skip_clear_timer_id
xor ebx, ebx
mov [timer_id], ebx
.skip_clear_timer_id:
mov ah, [exit_flag]
test ah, ah
jne near exit_from_timer
test al, al
je near return_from_patch
push edx
; init variables when execution speed changes
mov eax, [execution_speed]
cmp eax, [previous_divisor]
je .skip_set_divisor
xor edx, edx
mov [ms_fraction], edx
mov [sound_fraction], edx
mov [sound_deficit], edx
mov [previous_divisor], eax
call esi
mov [keep_tick], eax
.skip_set_divisor:
; compute tick interval
compute_tick_interval:
mov ebx, [execution_speed]
mov eax, 0x683
imul dword [frame_skip]
div ebx
test edx, edx
jz .skip_fraction
add edx, [ms_fraction]
cmp edx, ebx
jl .skip_inc
inc eax
sub edx, ebx
.skip_inc:
mov [ms_fraction], edx
.skip_fraction:
mov [timer_interval], eax
mov [timer_interval_2], eax
push eax ; save time_interval
; compute timer delta
compute_timer_delta:
add eax, [keep_tick]
mov [keep_tick], eax
push eax ; save next_tick
call esi
mov edx, eax
pop eax ; restore next_tick
sub eax, edx
jg .positive_interval
mov eax, 1
.positive_interval:
; set timer
push byte 0
push byte 0
push dword timer_proc
push byte 0
push eax
call [settimer_ptr]
mov [timer_id], eax
; compute sound interval
compute_sound_interval:
pop eax ; restore time_interval
imul dword [sound_freq]
mov ebx, 0x7d0
div ebx
test edx, edx
jz .skip_fraction
add edx, [sound_fraction]
cmp edx, ebx
jl .skip_inc
inc eax
sub edx, ebx
.skip_inc:
mov [sound_fraction], edx
.skip_fraction:
add eax, [sound_deficit] ; take into account frame-skipping
cdq
div dword [frame_skip]
mov [sound_deficit], edx
add eax,eax ; sound intervals have a 2-byte resolution
mov edx, [sound_buffer_size]
cmp eax, edx
jle .sound_interval_ok
mov eax, edx
.sound_interval_ok:
mov [sound_interval], eax
mov word [sound_ptr], 0
pop edx
jmp return_from_patch