Speeding Up The Player-Missile Demo
Larry Isaacs, Raleigh, NC
Chris Crawford's article1 on the inner workings of some of the player-missile graphics was very interesting. I'm sure all those who tried the demo program noticed the difference in speed between horizontal movement and vertical movement. This provides a very good example of the difference between the execution speed of machine language' and the execution speed of BASIC.
Horizontal movement of the "player" requires only a POKE statement. The function of the POKE statement is roughly equivalent to a single machine language instruction. This allows it to execute fairly fast. On the other hand, vertical movement of the "player" isn't nearly as simple. A FOR...NEXT statement is needed to move some data in memory. Also, vertical movement requires a more complex POKE statement. This POKE statement not only takes longer to execute, but is executed 7 times. These factors result in noticeably slower vertical movement than horizontal movement. If this FOR... NEXT loop could be replaced with some machine language, vertical movement could be brought to seemingly the same speed as horizontal movement.
The program in Listing 1 will illustrate this point. This program is a duplication of Chris Crawford's original demo with modifications for upward movement of the "player" to be done with the aid of machine language. Downward movement is still done with the FOR... NEXT loop to give a comparison. With this program you will find that it takes around three seconds to move the "player" from the bottom of the screen to the top. It will take around 17 seconds to move the "player" back to the bottom again. If the downward movement is too slow to bear, use the program in Listing 2. It has machine language for both upward and downward movement.
The machine language routines do not contain any absolute addressing, so they are relocateable. This means you can further modify the demo programs and the routines will still work. For those familiar with assembly language, here is the code for the two routines.
UP | PLA | DOWN | PLA |
PLA | PLA | ||
STA $CC | STA $CC | ||
PLA | PLA | ||
STA $CB | STA $CB | ||
LDY #$01 | LDY #$06 | ||
UPLOOP | LDA ($CB),Y | DNLOOP | LDA ($CB),Y |
DEY | INY | ||
STA ($CB),Y | STA ($CB),Y | ||
INY | DEY | ||
INY | DEY | ||
CPY #$07 | CPY #$FF | ||
BNE UPLOOP | BNE DNLOOP | ||
RTS | RTS |
As illustrated by this example, where the speed of an operation is concerned, it is faster to use machine language. However, it may not always be better to use machine language, and using it probably won't be easier than using BASIC.
Listing 1
1 GOSUB 1000 : REM Load machine code 10 SETCOLOR 2, 0, 0 : X = 120 : Y = 48 : REM Set background color and player position 20 A = PEEK (106) - 8 : POKE 54279, A : PMBASE = 256 * A : REM Set player-missile address 30 POKE 559, 46 : POKE 53277, 3 : REM Enable PM graphics with 2-line resolution 40 POKE 53248, X : REM Set horizontal position 50 FOR I = PMBASE + 512 TO PMBASE + 640 : POKE I, O : NEXT I : REM Clear out player first 60 POKE 704, 216 : REM Set color to screen 70 FOR I = PMBASE + 512 + Y TO PMBASE + 516 + Y : READ A : POKE I, A : NEXT I : REM Draw player80 DATA 153, 189, 255, 189, 153 90 REM Now comes the motion routine 100 A = STICK(0) : IF A = 15 THEN GOTO 100 110 IF A = 11 THEN X = X - 1 : POKE 53248, X 120 IF A = 7 THEN X = X + 1 : POKE 53248, X 130 IF A = 13 THEN FOR I = 6 TO 0 STEP -1 : POKE PMBASE + 512 + Y + I, PEEK(PMBASE + 511 + Y + I) : NEXT I : Y = Y + 1 140 IF A = 14 THEN D = USR(UP, PMBASE + 511 + Y) : Y = Y - 1 150 GOTO 100 1000 DIM UPCODE$ (22) : UP = ADR(UPCODE$) 1010 FOR I = 1 TO 5 : READ A : NEXT I : REM Skip player data 1020 FOR I = UP TO UP+20 1030 READ BYTE : POKE I, BYTE 1040 NEXT I : RESTORE : RETURN 1050 REM Move player up code 1060 DATA 104, 104, 133, 204, 104, 133, 203 1070 DATA 160, 1, 177, 203, 136, 145, 203 1080 DATA 200, 200, 192, 7, 208, 245, 96
Listing 2
1 GOSUB 1000 : GOSUB 1100 : REM Load machine code 10 SETCOLOR 2, 0, 0 : X = 120 : Y = 48 : REM Set background color and player position 20 A = PEEK(106) - 8 : POKE 54279, A : PMBASE = 256 * A : REM Set player-missile address 30 POKE 559, 46 : POKE 53277, 3 : REM Enable PM graphics with 2-line resolution 40 POKE 53248, X : REM Set horizontal position 50 FOR I = PMBASE + 512 TO PMBASE + 640 : POKE I, 0 : NEXT I : REM Clear out player first 60 POKE 704, 216 : REM Set color to green 70 FOR I = PMBASE + 512 + Y TO PMBASE + 516 + Y : READ A : POKE I, A : NEXT I : REM Draw player 80 DATA 153, 189, 255, 189, 153 90 REM Now comes the motion routine 100 A = STICK(0) : IF A = 15 THEN GOTO 100 110 IF A = 11 THEN X = X - 1 : POKE 53248, X : GOTO 100 120 IF A = 7 THEN X = X + 1 : POKE 53248, X : GOTO 100 130 IF A = 13 THEN D = USR(DOWN, PMBASE + 511 + Y) : Y = Y + 1 : GOTO 100 140 IF A = 14 THEN D = USR(UP, PMBASE + 511 + Y) : Y = Y - 1 150 GOTO 100 1000 DIM UPC0DE$(22) : UP = ADR(UPCODE$) 1010 FOR I = 1 TO 5 : READ A : NEXT I : REM Skip player data 1020 FOR I = UP TO UP + 20 1030 READ BYTE : POKE I, BYTE 1040 NEXT I : RETURN 1050 REM Move player up code 1060 DATA 104, 104, 133, 204, 104, 133, 203 1070 DATA 160, 1, 177, 203, 136, 145, 203 1080 DATA 200, 200, 192, 7, 208, 245, 96 1100 DIM DOWNCODE$(22) : DOWN = ADR(DOWNCODE $) 1120 FOR I = DOWN TO DOWN + 20 1130 READ BYTE : POKE I, BYTE 1140 NEXT I : RESTORE : RETURN 1150 REM Move player down code 1160 DATA 104, 104, 133, 204, 104, 133, 203 1170 DATA 160, 6, 177, 203, 200, 145, 203 1180 DATA 136, 136, 192, 255, 208, 245, 96