; ---------------------------------------------------------------------------
; Handle the (Pc) timer.
; ---------------------------------------------------------------------------
Timer_Install:
            Cli
            Call  Timer_Reset
            Mov   Ax,0
            Mov   Es,Ax
            Mov   Eax,[Es:08h*4]
            Mov   [Save08],Eax
            Mov   [Word Es:08h*4],Offset Int08
            Mov   [Word Es:08h*4+2],Cs
            Mov   Al,36h
            Out   43h,Al
            Mov   Ax,1193200/Timer_Freq
            Out   40h,Al
            Mov   Al,Ah
            Out   40h,Al
            Sti
            Ret
; ---------------------------------------------------------------------------
Timer_Restore:
            Mov   Al,36h
            Out   43h,Al
            Mov   Al,-1
            Out   40h,Al
            Jmp   @@1
@@1:        Out   40h,Al
            Cli
            Mov   Ax,0
            Mov   Es,Ax
            Mov   Eax,[Save08]
            Mov   [Es:08h*4],Eax
            Sti
            Ret
; ---------------------------------------------------------------------------
Timer_Reset:Push  Ds
            Push  Ax
            Mov   Ax,0
            Mov   [Timer_On+0],Al
            Mov   [Timer_On+1],Al
            Mov   [Timer_On+2],Al
            Mov   [Timer_On+3],Al
            Mov   Ds,[Iodirect]
            Mov   [0DC04h],Ax
            Mov   [0DC06h],Ax
            Mov   [0DD04h],Ax
            Mov   [0DD06h],Ax
            Pop   Ax
            Pop   Ds
            Ret
; ---------------------------------------------------------------------------
Timer_Start:Pushf
            Cli
            Push  Ds
            Push  Bx
            Push  Di
            Mov   [Timer_On+Bx],1
            Add   Bl,Bl
            Mov   Ds,[Iodirect]
            Mov   Di,[Timer_Addr+Bx]
            Mov   Bx,[Timer_Rate+Bx]
            Mov   [Di],Bx
            Pop   Di
            Pop   Bx
            Pop   Ds
            Popf
            Ret
; ---------------------------------------------------------------------------
Timer_Stop: Mov   [Timer_On+Bx],0
            Ret
; ---------------------------------------------------------------------------
Evendata
Callold   Dw    1
Sprite    Dw    1
TimerJmp  Dw    Timer_F1a,Timer_F1b,Timer_F2a,Timer_F2b

Align 10h
Int08:      Push  Ax
            Push  Ds
            Push  Si
            Push  Di
            Push  Bx
            Mov   Ds,[Iodirect]
            Xor   Bx,Bx

            Mov   [0DC0Dh],Bl     ; Should have been cleared on read.
            Mov   [0DD0Dh],Bl

            Mov   Ah,[0D011h]
            Mov   Bh,Ah
            Shl   Bh,1
            Mov   Al,[0D012h]
            Shr   Ah,7
            Inc   Ax
            Cmp   Ax,Raster_YMax
            Jbe   @@4
            Mov   Ax,0
@@4:        Mov   [0D012h],Al
            Shr   Ah,1
            Rcr   Bh,1
            Mov   [0D011h],Bh
            Cmp   Ax,[Raster]
            Jne   @@5
            Test  [Byte 0D01Ah],00000001b
            Je    @@5
            Test  [Byte 0D019h],00000001b
            Jne   @@5
            Test  [Flags],Flag_I
            Jne   @@5
            Or    [Byte 0D019h],10000001b
            Mov   [Word Next],Irqpatch

@@5:        Mov   Bx,0
@@0:        Cmp   [Timer_On+Bx],1
            Jne   @@1
            Mov   Si,Bx
            Mov   Di,[Timer_Addr+Bx+Si]
            Sub   [Word Di],Timer_Step
            Jnc   @@1
            Call  [TimerJmp+Si+Bx]
@@1:        Inc   Bl
            Cmp   Bl,4
            Jne   @@0
            Pop   Bx
            Pop   Di
            Pop   Si
            Pop   Ds
            Dec   [Callold]
            Je    @@3
            Mov   Al,60h
            Out   20h,Al
            Pop   Ax
            Dec   [Sprite]
            Jns   @@7
            Cmp   [Word Next],Nextpatch
            Jne   @@7
            Add   [Sprite],Timer_Freq/25
            Mov   [Word Next],Spritepatch
@@7:        Iret
@@3:        Mov   [Callold],Timer_Freq*100/1802
            Pop   Ax
            Cmp   [Word Next],Nextpatch
            Jne   @@6
            Cmp   [Wantrefresh],1
            Jne   @@6
            Dec   [Wantrefresh]
            Cmp   [Video_Lock],0
            Jne   @@6
            Mov   [Word Next],Refreshpatch
@@6:        Jmp   [Save08]

; ---------------------------------------------------------------------------
Timer_F1a:  Or    [Byte 0DC0Dh],00000001b
            Test  [Byte 0DC0Eh],00001000b
            Je    @@1
            Call  Timer_Stop
            And   [Byte 0DC0Eh],11111110b
            Mov   [Word Di],0
@@2:        Test  [Cia1_Imask],00000001b
            Je    @@3
            Or    [Byte 0DC0Dh],10000000b
            Test  [Flags],Flag_I
            Jne   @@3
            Mov   [Word Next],Irqpatch
@@3:        Ret
@@1:        Call  Timer_Start ; inaccurate
            Jmp   @@2
; ---------------------------------------------------------------------------
Timer_F1b:  Or    [Byte 0DC0Dh],00000010b
            Test  [Byte 0DC0Fh],00001000b
            Je    @@1
            Call  Timer_Stop
            And   [Byte 0DC0Fh],11111110b
            Mov   [Word Di],0
@@2:        Test  [Cia1_Imask],00000010b
            Je    @@3
            Or    [Byte 0DC0Dh],10000000b
            Test  [Flags],Flag_I
            Jne   @@3
            Mov   [Word Next],Irqpatch
@@3:        Ret
@@1:        Call  Timer_Start ; inaccurate
            Jmp   @@2
; ---------------------------------------------------------------------------
Timer_F2a:  Or    [Byte 0DD0Dh],00000001b
            Test  [Byte 0DD0Eh],00001000b
            Je    @@1
            Call  Timer_Stop
            And   [Byte 0DD0Fh],11111110b
            Mov   [Word Di],0
@@2:        Test  [Cia2_Imask],00000001b
            Je    @@3
            Or    [Byte 0DD0Dh],10000000b
            Mov   [Word Next],Nmipatch
@@3:        Ret
@@1:        Call  Timer_Start ; inaccurate
            Jmp   @@2
; ---------------------------------------------------------------------------
Timer_F2b:  Or    [Byte 0DD0Dh],00000010b
            Test  [Byte 0DD0Fh],00001000b
            Je    @@1
            Call  Timer_Stop
            And   [Byte 0DD0Fh],11111110b
            Mov   [Word Di],0
@@2:        Test  [Cia2_Imask],00000010b
            Je    @@3
            Or    [Byte 0DD0Dh],10000000b
            Mov   [Word Next],Nmipatch
@@3:        Ret
@@1:        Call  Timer_Start ; inaccurate
            Jmp   @@2
; ---------------------------------------------------------------------------
