Legal Interrupt Handling for Amiga Demos

OS Legal interrupts are so easy to add and have such a very tiny overhead that it is a real pity that so many people ignore them...

Hardware interrupts are set with AddIntServer and removed with RemIntServer.

The best way to show how to use interrupts on the Amiga is with an example (thanks Bjorn!). I've pessimised it slightly (to make it a little more readable) and fixed one bug!
INTB_VERTB  equ   5                 ; for vblank interrupt
INTB_COPER  equ   4                 ; for copper interrupt

CALL: MACRO
      jsr   _LVO1(a6)
      ENDM


SystemOff:
      move.l   GfxBase,a6
      sub.l    a1,a1
      CALL     LoadView             ;Get default view
      CALL     WaitTOF
      CALL     WaitTOF
      CALL     OwnBlitter           ;Claim ownership of blitter
      move.l   $4.w,a6
      CALL     Forbid               ;Forbid multitasking
      moveq.l  #INTB_VERTB,d0       ; INTB_COPER for copper interrupt
      lea      VBlankServer(pc),a1
      CALL     AddIntServer         ;Add my interrupt to system list
      rts

SystemOn:
      move.l   $4.w,a6
      moveq.l  #INTB_VERTB,d0       ;Change for copper interrupt.
      lea      VBlankServer(pc),a1
      CALL     RemIntServer         ;Remove my interrupt
      CALL     Permit               ;Permit multitasking
      move.l   GfxBase,a6
      CALL     DisownBlitter        ;Give blitter back
      move.l   MyView,a1
      CALL     LoadView             ;Load original view
      rts

IntLevel3:

      movem.l  d2-d7/a2-a4,-(sp)    ; all other registers can be trashed
      ...
      movem.l  (sp)+,d2-d7/a2-a4

;     If you set your interrupt to priority 10 or higher then
;     a0 must point at $dff000 on exit.

      moveq    #0,d0                ; must set Z flag on exit!
      rts                           ;Not rte!!!

VBlankServer:
      dc.l  0,0                     ;ln_Succ,ln_Pred
      dc.b  2,0                     ;ln_Type,ln_Pri
      dc.l  IntName                 ;ln_Name
      dc.l  0,IntLevel3             ;is_Data,is_Code

IntName:dc.b "Dexion & SAE IntLevel3",0     ; :-)
      EVEN
;------------------------------------------------------------------
where MyView is filled in immediately after graphics.library have been opened:
   ..
   move.l   GfxBase,a1
   move.l   gb_ActiView(a1),MyView
   ...

exec.library/AddIntServer()

   NAME
      AddIntServer -- add an interrupt server to a system server chain

   SYNOPSIS
      AddIntServer(intNum, interrupt)
        -168       D0-0:4      A1

      void AddIntServer(ULONG, struct Interrupt *);

   FUNCTION
      This function adds a new interrupt server to a given server chain.
      The node is located on the chain in a priority dependent position.
      If this is the first server on a particular chain, interrupts will
      be enabled for that chain.

      Each link in the chain will be called in priority order until the
      chain ends or one of the servers returns with the 68000's Z condition
      code clear (indicating non-zero).  Servers on the chain should return
      with the Z flag clear if the interrupt was specifically for that
      server, and no one else.  VERTB servers should always return Z set.
      (Take care with High Level Language servers, the language may not
      have a mechanism for reliably setting the Z flag on exit).

      Servers are called with the following register conventions:

          D0 - scratch
          D1 - scratch

          A0 - scratch
          A1 - server is_Data pointer (scratch)

          A5 - jump vector register (scratch)
          A6 - scratch

          all other registers must be preserved

   INPUTS
      intNum - the Paula interrupt bit number (0 through 14). Processor
        level seven interrupts (NMI) are encoded as intNum 15.
        The PORTS, COPER, VERTB, EXTER and NMI interrupts are
        set up as server chains.
      interrupt - pointer to an Interrupt structure.
        By convention, the LN_NAME of the interrupt structure must
        point a descriptive string so that other users may
        identify who currently has control of the interrupt.

   WARNING
      Some compilers or assemblers may optimize code in unexpected ways,
      affecting the conditions codes returned from the function.  Watch
      out for a "MOVEM" instruction (which does not affect the condition
      codes) turning into "MOVE" (which does).

   BUGS
      The graphics library's VBLANK server, and some user code, currently
      assume that address register A0 will contain a pointer to the custom
      chips. If you add a server at a priority of 10 or greater, you must
      compensate for this by providing the expected value ($DFF000).

exec.library/RemIntServer()

   NAME
      RemIntServer -- remove an interrupt server from a server chain

   SYNOPSIS
      RemIntServer(intNum, interrupt)
         -174        D0      A1

      void RemIntServer(ULONG,struct Interrupt *);

   FUNCTION
      This function removes an interrupt server node from the given
      server chain.

      If this server was the last one on this chain, interrupts for this
      chain are disabled.

   INPUTS
      intNum - the Paula interrupt bit (0..14)
      interrupt - pointer to an interrupt server node

   BUGS
      Before V36 Kickstart, the feature that disables the interrupt
      would not function.  For most server chains this does not
      cause a problem.


Main Menu