# Raster Interrupt Speed Tricks

7

nathanielbabiak 2020-12-04 21:50 (Edited)

### Raster Interrupt Speed Tricks - Disclaimer

Caution! Syntactic (within-same-line) speed optimizations are discussed frequently on this console. But, there's a 99% chance algorithmic (not syntactic) improvements will provide an order-of-magnitude speed improvement vs. doing any of these! These are only recommended for use within raster interrupts (not even VBL interrupts require them).

### Raster Interrupt Speed Tricks

Non-zero values (int and float) evaluate to true, these are smaller and faster, for example with `12.34` (or any variable replacing `12.34`):

• Replace `IF X<>0 THEN` with `IF X THEN`
• Replace `IF X<>0 AND Y<>0 THEN` with `IF X*Y THEN`
• Replace `IF X=0 OR Y=0 THEN` with `IF X*Y=0 THEN`
• Replace `IF X < 0 OR X>= 12.34 THEN` with `IF INT(X/12.34) THEN`
• Replace `IF X>= 0 AND X< 12.34 THEN` with `IF INT(X/12.34)=0 THEN`

There's two non-zero evaluation tricks if you're sure `X` and `Y` will always have matching signs:

• Replace `IF X<>0 OR Y<>0 THEN` with `IF X+Y THEN`
• Replace `IF X=0 AND Y=0 THEN` with `IF X+Y=0 THEN`

There's a few more non-zero evaluation tricks when `X` and, for example `1234` (or any variable replacing `1234`), are integers:

• Replace `IF (X AND %001)=%001 THEN` with `IF X AND %001 THEN`
• Replace `IF (X AND %010)=%010 THEN` with `IF X AND %010 THEN`
• Replace `IF (X AND %100)=%100 THEN` with `IF X AND %100 THEN`
• Replace `IF X<=-1234 OR X>=1234 THEN` with `IF X\1234 THEN`
• Replace `IF X> -1234 AND X<1234 THEN` with `IF X\1234=0 THEN`

You can store evaluations per-raster-line in an array to save a single clock cycle:

• Replace `IF RASTER=64 THEN` with `IF LOOKUP(RASTER) THEN` (after running `DIM GLOBAL LOOKUP(127)` and `LOOKUP(64)=1` elsewhere in your code)

If you're only performing one instruction occasionally per-raster-line, note that some instructions perform a graceful exit when executed with unrealistic arguments (for example `COPY SRC, 0 TO DST`), so the above tip can be shortened further (depending on the number of nonzero `LOOKUP()` entries and your specific instruction):

• Replace `IF LOOKUP(RASTER) THEN COPY SRC, 40 TO DST` with `COPY SRC, LOOKUP(RASTER) TO DST` (after initializing the values of the `LOOKUP()` array elsewhere in your code)

If you're performing various raster tricks on continuous sequences of `RASTER` scanlines, don't use either `switch-case` structure described below (they're too slow), instead change raster subprograms within the raster interrupt itself. Try this:

• `SUB RASTER1 \\ [first trick, upper screen] \\ IF LOOKUP(RASTER) THEN ON RASTER CALL RASTER2 \\ END SUB`
• `SUB RASTER2 \\ [second trick, middle screen] \\ IF LOOKUP(RASTER) THEN ON RASTER CALL RASTER3 \\ END SUB`
• `SUB RASTER3 \\ [third trick, bottom screen] \\ END SUB`
• `ON VBL CALL RASTER_RESET`
• `SUB RASTER_RESET \\ ON RASTER CALL RASTER1 \\ END SUB`

### Keywords from C

This `switch-case` structure requires few tokens, but it's slow:

``````IF X=0 THEN
CALL X0
ELSE IF X=1 THEN
CALL X1
ELSE IF X=2 THEN
CALL X2
ELSE IF X=3 THEN
CALL X3
ELSE IF X=4 THEN
CALL X4
ELSE IF X=5 THEN
CALL X5
ELSE IF X=6 THEN
CALL X6
ELSE IF X=7 THEN
CALL X7
END IF``````

This `switch-case` structure is much faster, but requires more tokens:

``````IF X<4 THEN
IF X<2 THEN
IF X<1 THEN CALL X0 ELSE CALL X1
ELSE
IF X<3 THEN CALL X2 ELSE CALL X3
END IF
ELSE
IF X<6 THEN
IF X<5 THEN CALL X4 ELSE CALL X5
ELSE
IF X<7 THEN CALL X6 ELSE CALL X7
END IF
END IF``````

### Goto

In small projects, using `GOTO` can be much easier to read than avoiding it, but it's harder to maintain nonlooped code, so avoid `GOTO` in large projects. In the vast majority of instances you think you need it, the algorithm isn't coherent. There's one instance where `GOTO` is common: implementing the C keywords `continue[(n)]` and `break[(n)]`.

### Small Declaration

If an algorithm needs more than 3 new variable names, this is smaller than declaring one variable per-line. It's slower only because of overhead, otherwise the same speed O(n).

``````DECLARE:
DATA 0, 0, 0, 0, 0, 0, 0, 0
READ Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7``````

Single-command if-then statements are smaller (and sometimes faster too) when written on a single line like this:

• `IF TEST1 THEN CALL FOO`
• `IF TEST1 THEN CALL FOO ELSE CALL BAR`
• `IF TEST1 THEN CALL FOO ELSE IF TEST2 THEN CALL BAR ELSE CALL ZOT`

### Loops

This loop is small but slow:

``````FOR X=0 TO 7
TEXT 0,X,"-"
NEXT X``````

This unrolled loop is fast but large:

``````TEXT 0,0,"-"
TEXT 0,1,"-"
TEXT 0,2,"-"
TEXT 0,3,"-"
TEXT 0,4,"-"
TEXT 0,5,"-"
TEXT 0,6,"-"
TEXT 0,7,"-"``````

### Misc. Stuff

• `X = ASC( CHR\$( X ) )` will convert an 8-bit value from unsigned to signed.
• Additional ROM space may be mimicked (with sequential access only) using `DATA` commands, containing strings of hex-values, use `VAL("0X"+VALUE\$)` to retrieve up to three bytes at a time.

### Short-Circuit Evaluation

LowRes NX supports a limited format for short-circuit evaluations. If you have evaluations `A`, `B`, and `C`, you can replace:

``IF A AND B AND C THEN CALL ALL_TRUE ELSE CALL SOME_FALSE``

With:

``IF A THEN IF B THEN IF C THEN CALL ALL_TRUE ELSE CALL SOME_FALSE``

moechofe 2020-12-05 07:29

good stuff

nathanielbabiak 2022-06-30 01:30

Thanks moechofe!

nathanielbabiak 2022-06-30 01:30

Many changes over the past two years - this update covers all the nuance I've learned pushing the system to its limits!

Hope it helps anybody who sees this!