VBL, DLI

Two routines GetIntVec and SetIntVec are dedicated to handle VBL, DLI interrupts. The presence of OS is required for proper operation (disable ROM only by $DEFINE ROMOFF)

GetIntVec

GetIntVec(iVBLI, pointer);  // pobranie adresu programu obsługi przerwań VBLI ($0222)
GetIntVec(iVBLD, pointer);  // pobranie adresu programu obsługi przerwań VBLD ($0224)
GetIntVec(iDLI, pointer);   // pobranie adresu programu obsługi przerwań DLI ($0200)
var oldVBL: pointer;

begin

GetIntVec(iVBL, oldVBL);

end.

SetIntVec

SetIntVec(iVBLI, pointer);  // ustanowienie adresu programu obsługi przerwań VBLI ($0222)
SetIntVec(iVBLD, pointer);  // ustanowienie adresu programu obsługi przerwań VBLD ($0224)
SetIntVec(iDLI, pointer);   // ustanowienie adresu programu obsługi przerwań DLI ($0200)
procedure newVBL; interrupt; assembler;
asm

 jmp xitvbv

end;


begin

SetIntVec(iVBL, @newVBL);

end.

The VBL interrupt is terminated by jumping to the XITVBV address ($E462) which will restore the value of the A X Y CPU6502 registers.

If we have disabled ROM by {$define romoff} and are using routines placed in memory $C000..$FFFF we must take care to set PORTB properly.

procedure newVBL; interrupt; assembler;
asm

 dec portb

 jsr user_proc_c000_ffff

 inc portb

 jmp xitvbv

end;



```delphi
procedure newVBL; interrupt; assembler;
asm

 jmp sysvbv

end;


begin

SetIntVec(iVBLI, @newVBL);

end.

We terminate the VBLDI (VBL immediate) interrupt by jumping to the SYSVBV address ($E45F) which will continue handling the VBL interrupt.

If we have disabled ROM by {$define romoff} and are using routines placed in memory $C000..$FFFF we must take care to set PORTB properly.

procedure newVBL; interrupt; assembler;
asm

 dec portb

 jsr user_proc_c000_ffff

 inc portb

 jmp sysvbv

end;


## IRQ - TIMER1, TIMER2, TIMER4

Two routines `GetIntVec` and `SetIntVec` are dedicated to handle **IRQ** - **TIMER1**, **TIMER2**, **TIMER4** interrupts. The presence of OS is required for proper operation (disable ROM only by [$DEFINE ROMOFF](/composition/#romoff))

### GetIntVec

    GetIntVec(iTIM1, pointer);  // getting the address of the TIMER 1 interrupt handler ($0210)
    GetIntVec(iTIM2, pointer);  // getting the address of the TIMER 2 interrupt handler ($0212)
    GetIntVec(iTIM4, pointer);  // getting the address of the TIMER 4 interrupt handler ($0214)

```delphi
var oldIRQ: pointer;

begin

GetIntVec(iTIM4, oldIRQ);

end.

SetIntVec

SetIntVec(iTIM1, pointer);  // establishing the address of the TIMER 1 interrupt handler ($0210)
SetIntVec(iTIM2, pointer);  // establishing the address of the TIMER 2 interrupt handler ($0212)
SetIntVec(iTIM4, pointer);  // establishing the address of the TIMER 4 interrupt handler ($0214)
procedure irq; assembler; interrupt;
asm

 pla

end;

begin

SetIntVec(iTIM4, @irq, 0, 28);

repeat until keypressed;

SetIntVec(iTIM4, oldIRQ);

end.

When the system executes a jump to an interrupt service routine, it puts the contents of the accumulator on the stack beforehand; keep this in mind and end the interrupt service with PLA.

Additional parameters are required to trigger a new IRQ interrupt, such as the choice of base clock clock_base = [0,1] and frequency rate = [6.255]. Values of rate less than 6 will cause the system to slow down severely, up to a possible suspension.

SetIntVec(iTIM1, pointer, clock_base, rate);
SetIntVec(iTIM2, pointer, clock_base, rate);
SetIntVec(iTIM4, pointer, clock_base, rate);