forge Documentation

display-list-interrupts

Display List Interrupts

Note: This is an advanced topic.

Display list interrupts (normally called DLI) are a way to modify display registers at certain vertical positions on the screen.

What Are DLIs?

DLIs allow you to change display hardware registers during screen rendering, enabling effects that would otherwise be impossible with a single set of register values.

Uses for DLIs

You can use DLIs to:

  • Display more colors in the image - By changing color registers (registers from $D012 to $D01A)
  • Split Player/Missile graphics - Move players/missiles to different horizontal positions (registers from $D000 to D007)
  • Change scrolling position - Modify screen scrolling during display
  • Change screen width - Adjust screen width mid-frame
  • Modify P/M width - Change Player/Missile width settings
  • Create color gradients - Change colors line-by-line for gradient effects

FORGE DLI Support

FORGE allows you to specify one or more DLI routines, activate one or deactivate all DLI by using the DLI statement.

Defining a DLI

DLI SET name = op1, op2, ... / DLIS.

Setups a new DLI with the given name and performing the op operations.

Each operation is of the form:

  • data INTO address
  • data WSYNC INTO address

Where:

  • data is one constant byte or the name of a DATA BYTE array
  • address is a memory location to modify

Array-Based DLIs

If data is a DATA array, the first element (at index 0) will be used at the first line with DLI active in the screen, the second element at the second active line, etc.

WSYNC

The WSYNC word advances one line in the display area (this is done by writing to the WSYNC ANTIC register), so the value is set in the next screen line. You can put the WSYNC word multiple times to advance more than one line. This allows one DLI to modify multiple lines at the screen.

Multiple INTO Operations

Multiple INTO words can be used to write more than one register with the same value.

Abbreviations

  • INTO can be abbreviated to I.
  • WSYNC can be abbreviated to W.

Important Notes

  • You can specify any number of operations, but as each one takes some time you could see display artifacts if you use too many.
  • By defining a DLI you are simply giving it a name, you need to activate the DLI afterwards.
  • You can split a DLI definition over multiple lines, just like DATA by ending a line with a comma and starting the next line with DLI =

Enabling a DLI

DLI name / DL.

This statement enables the DLI with the given name, the DLI must be defined before in the program.

This setups the OS DLI pointer to the named DLI and activates the interrupt bit in the display processor (the ANTIC chip), but does not activate on which lines the DLI must be called.

To define on which lines the DLI is active you must modify the Display List, see the examples below.

Custom Machine Code DLIs

You can also pass the name of a DATA BYTE array with a custom machine language routine to the DLI statement, the routine must begin with a PHA and end with PLA and RTI.

Disabling a DLI

DLI / DL.

This statement simply disables the DLI, returning the display to the original state.

Display List Modification

To activate DLIs on specific screen lines, you must modify the Display List. The Display List address is stored at memory location 560 (DPEEK(560)).

To enable a DLI on a specific line, you need to set bit 7 (add 128) to the display list instruction byte for that line.

Example:

' Enable DLI on line 11 (offset 16 in display list)
POKE DPEEK(560) + 16, 130  ' 2 + 128 = 130

Examples

Example 1: Simple Background Color Change

This is the most basic example of a DLI that simply changes the background color at the middle of the screen:

' Define the DLI: set background color to $24 = dark red.
DLI SET d1 = $24 INTO $D01A
' Setups screen
GRAPHICS 0
' Alter the Display List, adds a DLI at line 11 on the screen
POKE DPEEK(560) + 16, 130
' Activate DLI
DLI d1
' Wait for any key
? "Press a Key" : GET K
' Disable the DLI
DLI

Example 2: Multiple Color Changes

The next example shows how you can use a DLI to change multiple values in the screen:

' An array with color values
DATA Colors() BYTE = $24,$46,$68
' Define the DLI: set background color from the Color() array
' and text back color with value $8A in the same line and then
' the black in to the next line.
DLI SET d2 = Colors INTO $D01A,
DLI        = $8A INTO $D018,
DLI        = $00 WSYNC INTO $D018
' Setups screen
GRAPHICS 0
' Adds DLI at three lines:
POKE DPEEK(560) + 13, 130
POKE DPEEK(560) + 16, 130
POKE DPEEK(560) + 19, 130
' Activate DLI
DLI d2
' Wait for any key
? "Press a Key" : GET K
' Disable the DLI
DLI

Example 3: Player/Missile Movement

The final example shows how you can move multiple P/M using one DLI:

' Player shapes, positions and colors
DATA p1() BYTE = $E7,$81,$81,$E7
DATA p2() BYTE = $18,$3C,$3C,$18
DATA pos() BYTE = $40,$60,$80,$A0
DATA c1() BYTE = $28,$88,$C8,$08
DATA c2() BYTE = $2E,$80,$CE,$06
' Our DLI writes the position and colors to Player 1 and Player 2
DLI SET d3 = pos INTO $D000 INTO $D001,
DLI        = c1 INTO $D012, c2 INTO $D013
GRAPHICS 0 : PMGRAPHICS 2
' Setup our 4 DLI and Players
FOR I = 8 TO 20 STEP 4
  POKE DPEEK(560) + I, 130
  MOVE ADR(p1), PMADR(0)+I*4+5,4
  MOVE ADR(p2), PMADR(1)+I*4+5,4
NEXT
' Activate DLI
DLI d3
? "Press a Key"
REPEAT
  PAUSE
  pos(0) = pos(0) + 2
  pos(1) = pos(1) + 1
  pos(2) = pos(2) - 1
  pos(3) = pos(3) - 2
UNTIL KEY()
DLI

Useful Registers

This is a table of some useful registers to change during a DLI:

AddressRegister
$D000Player 0 horizontal pos.
$D001Player 1 horizontal pos.
$D002Player 2 horizontal pos.
$D003Player 3 horizontal pos.
$D004Missile 0 horizontal pos.
$D005Missile 1 horizontal pos.
$D006Missile 2 horizontal pos.
$D007Missile 3 horizontal pos.
$D012Color of player/missile 0
$D013Color of player/missile 1
$D014Color of player/missile 2
$D015Color of player/missile 3
$D016Color register 0
$D017Color register 1
$D018Color register 2
$D019Color register 3
$D01AColor of background

Best Practices

  1. Keep DLI routines short - Long DLI routines can cause display artifacts
  2. Test thoroughly - DLIs can be timing-sensitive
  3. Disable when done - Always disable DLIs when your program exits
  4. Use arrays for multiple lines - Arrays make it easy to change multiple lines
  5. Document your DLIs - Note which lines they affect and what they do

Troubleshooting

DLI not activating:

  • Check that you've modified the Display List correctly
  • Verify the DLI is enabled with DLI name
  • Ensure the DLI is defined before it's enabled

Display artifacts:

  • Reduce the number of operations in the DLI
  • Check timing - some operations may be too slow
  • Verify register addresses are correct

Colors not changing:

  • Check that you're writing to the correct color register
  • Verify the graphics mode supports the color changes
  • Ensure the DLI is actually being called (check Display List)

Related Topics