Classic Computer Magazine Archive A.N.A.L.O.G. ISSUE 66 / NOVEMBER 1988 / PAGE 10



Atari
Streamers


by Brad Timmins

Atari Streamers is a machine-language utility which uses player-missile graphics to create fine-scrolling vertical-character displays. Excluding inverse characters (which are automatically unshifted), displays can be made up of any string of characters desired-that is, uppercase, lowercase and graphics characters in either single- or double-line resolution. Even custom-character sets can be displayed.
    Atari Streamers has two entry points. The first entry point copies your string of characters into player-missile memory. It is called by the USR statement:

X=USR(1536,PMADDRESS,
STRINGADDRESS,FONT,LENGTH),

    PMADDRESS is the address of the player you wish to put your character display in. STRINGADDRESS is the address of the string of characters that will be copied to player memory. The best way to store your character display is to define it as a string variable, and then use the ADR function to find its address. FONT is the address of the character set you wish to use. It should be set to 57344,which is the ROM address for the normal character set,but if you have an altered character set in memory, or if you wish to use the international character set (found only on the XL and XE computers), simply substitute the address of the character set you wish to display. The international character set is located at 52224. The last value, LENGTH, is the length of your string of characters. In double-line resolution, strings can be a maximum of 16 characters long. In singleline resolution, strings can be up to 32 characters long.

Excluding inverse
characters, displays
 can be made up of
any string of
characters desired.

    The second entry point of the routine will move everything in the player specified one byte up or one byte down with wraparound. It is called by the USR statement:

X=USR(1677,PMADDRESS,DIRECT10N)

    PMADDRESS is the address of the player you wish to move. DIRECTION is the direction you wish to move the player in. If DIRECTION equals zero, everything in the player will be moved up by one. If DIRECTION equals one, everything in the player will be moved down by one. When this routine is used in combination with the horizontal-position registers, you can easily move your character displays anywhere on screen and over any graphics mode.
    The demo program displays and moves all four players in double-line resolution (if you wish to change the demo program to display in single-line resolution, substitute the lines in the REM statements). The four missiles are also displayed as a single player. This is not difficult since the missiles are mapped exactly the same way the players are mapped. The only difference is that the missiles have individual horizontal and collision registers. If you're going to combine the four missiles into a single player in your own program, remember to line them up in the correct order-that is, missile three, missile two, missile one, missile zero. They should be spaced two resolution lines apart. Poke location 623 with 17 to give all players priority over all playfields and to give all missiles their own color. You can change the missiles' color by poking to location 711.

Listing 1:
BASIC


SN 1 REM ATARI STREAMERS
XQ 2 REM BY BRAD TIMMINS
XW 3 REM Substitute the lines in REM
RL 4 REM statements for single-line
FH 5 REM resolution Players.
IR 6 REM COPYRIGHT 1988 BY ANALOG COMPUTI
   NG
AX 50 DIM P0$(16),P1$(16),P2$(16),P3$(16)
   ,MI$(16),CL$(16)
TW 51 REM DIM P0$(32),P1$(32),P2$(32),P3$
   (32),MI$(32),CL$(32)
DQ 60 ? CHRS(125):SETCOLOR 2,0,10:SETCOLO
   R 4,0,10
PX 70 GOSUB 500
TJ 80 A=PEEK(106)-8:REM A=PEEK(106)-16
FB 90 POKE 54279,A:PMBASE=256*A
EG 100 MISSILE=PMBASE+384:PM0=MISSILE+128
   :PM1=PM0+128:PM2=PM1+128:PM3=PM2+128
ZU 101 REM MISSILE=PMBASE+768:PM0=MISSILE
   +256:PM1=PM0+256:PM2=PM1+256:PM3=PM2+2
   56
IW 110 FONT=57344:REM ROM character set
LG 120 POKE 559,46:REM POKE 559,62
GM 130 POKE 53277,3:POKE 752,1:POKE 623,1
   7
UY 135 REM Position Players
JT 140 POKE 53248,60:POKE 53249,61:POKE 5
   3250,195:POKE 53251,196
RJ 144 REM Position Missiles
LM 145 POKE 53255,122:POKE 53254,124:POKE
   53253,126:POKE 53252,128
CN 150 POKE 704,128:POKE 705,134:POKE 706
   ,128:POKE 707,134:POKE 711,128
HI 155 REM Define a string of spaces
KT 156 REM the length of the players,
JG 157 REM to clear out Player-missile
MG 158 REM memory.
FC 160 CL$="                 "
J5 161 REM CLS="                        
          "
QX 180 FOR T=0 TO 4
WJ 190 X=USR(1536,MISSILE+(T*128),ADR(CL$
   ),FONT,16)
DC 191 REM X=USR(1536,MISSILE+(T*256),ADR
   (CL$),FONT,32)
JY 200 NEXT T
YM 205 REM Define Strings
ID 210 P0$="   Streamers":P1$=P0$:P2$=P0$
   :P3$=P0$:MI$="     Atari"
RD 215 REM copy strings to Player memory
MV 220 X=USR(1536,PM0,ADR(P0$),FONT,12)
OO 230 X=USR(1536,PM1,ADR(P1$),FONT,12)
QH 240 X=USR(1536,PM2,ADR(P2$),FONT,12)
SA 250 X=USR(1536,PM3,ADR(P3$),FONT,12)
JQ 251 X=USR(1536,MISSILE,ADR(MI$),FONT,1
   0)
PX 255 REM Shift Players ONE and THREE
IC 256 REM down by one to create a
JC 257 REM shading effect.
KL 270 X=USR(1677,PM1,1)
LZ 290 X=USR(1677,PM3,1)
GL 295 FOR T=1 TO 500:NEXT T
VK 300 REM Move Missile and Players zero
IJ 305 REM and TWO
HI 306 FOR T=1 TO 250:NEXT T
SS 307 FOR I=1 TO 128:REM FORI=0 TO 255
IO 310 X=USR(1677,PM0,0)
KA 320 X=USR(1677,PM2,0)
CH 330 X=USR(1677,MISSILE,1):POKE 711,1
HK 340 NEXT I:GOTO 306
JO 495 REM *****ATARI STREAMERS*****
TN 496 REM MACHINE LANGUAGE SUBROUTINE
EQ 500 FOR A=1536 TO 1766:READ B:POKE A,B
   :NEXT A
ZQ 505 RETURN
WW 510 DATA 104,104,133,284,104,133,203,1
   04,133,206,104,133,205,104,141,230,6,1
   04,141,229,6
TG 520 DATA 104,104,141,227,6,169,0,141,2
   28,6,169,32,141,231,6,173,47,2,201,62,
   240
GX 530 DATA 5,169,16,141,231,6,172,228,6,
   177,205,41,127,201,31,176,4,9,64,208,7
IK 540 DATA 201,95,176,3,56,233,32,141,22
   5,6,169,0,141,226,6,162,3,24,14,225,6
BM 550 DATA 46,226,6,202,208,247,24,173,2
   25,6,109,229,6,133,207,173,226,6,109,2
   30,6
PD 560 DATA 133,208,162,0,160,8,161,207,1
   29,203,230,207,230,203,136,208,245,238
   ,228,6,173
JQ 570 DATA 228,6,205,231,6,240,7,205,227
   ,6,240,2,208,164,96,104,104,133,204,13
   3,206
AQ 580 DATA 104,133,203,133,205,104,162,2
   55,160,255,173,47,2,201,62,240,4,162,1
   27,160,126
PM 590 DATA 104,201,1,240,19,160,0,177,20
   5,141,225,6,230,203,177,203,145,205,20
   0,202,208
VL 600 DATA 248,240,27,138,168,177,205,14
   1,225,6,136,177,203,141,226,6,138,168,
   173,226,6
YF 610 DATA 145,205,136,136,202,208,239,1
   38,168,173,225,6,145,205,96,0,0,0,0,0,
   0
XG 620 DATA 0,224,2,225,2,0

Listing 2

 ORG 1536
 ;
------------------------------
 
;ATARI STREAMERS ML SUBROUTINE
 
;WRITTEN FOR THE MACRO ASSEMBLER
 ;
----------------------------------
 
;THIS ROUTINE WILL TAKE A CHARACTER
 
;STRING AND COPY IT TO PLAYER
 
;MISSILE MEMORY.
 
;----------------------------------

 
;ZERO PAGE EQUATES
PLAYER: = 203
STRING: = 205
CHRGET: = 207
MOVEP: = 203
MP: = 205

 PLA ;GET UNUSED BYTE
 PLA ;GET MSB OF PLAYER ADDRESS
 STA PLAYER+1
 PLA ;GET LSB OF PLAYER ADDRESS
 STA PLAYER
 PLA ;GET MSB OF STRING
 STA STRING+1
 PLA ;GET LSB OF STRING
 STA STRING
 PLA ;GET MSB OF CHARACTER SET
 STA CHSET+1
 PLA ;GET LSB OF CHARACTER SET
 STA CHSET
 PLA ;GET UNUSED MSB OF LENGTH
 PLA ;GET LSB OF LENGTH
 STA LENGTH

 ;INIT. VALUES

 LDA #0
 STA COUNT
 LDA #32
 STA MAX

 ;TEST FOR SINGLE OR DOUBLE LINE
 ;RESOLUTION.

 LDA 559
 CMP #62
  BEQ GETSTR
 LDA #16
 STA MAX
 ;----------------------------------
 ;GET ATASCII CHARACTER FROM STRING
 ;AND CONVERT IT TO FIND ITS CORRECT
 ;ORDER IN MEMORY.
 ;---------------------------------
GETSTR: LDY COUNT
 LDA (STRING),Y

 ;IF CHARACTER IS IN INVERSE,
 ;UNSHIFT IT.

 AND #127
Cl: CMP #31
  BCS C2

  ;GRAPHICS CHARACTER 0-31
  ;ADD 64 TO ITS VALUE.

 ORA #64
 BNE C3
C2: CMP #95
 BCS C3

  ;UPPERCASE CHARACTER 32-95
  ;SUBTRACT 32 FROM ITS VALUE

 SEC
 SBC #32

 ;LOWERCASE CHARACTER 96-127
 ;DO NOTHING. THEY ARE ALREADY
 ;IN THE CORRECT ORDER.

 ;STORE NEW CHARACTER VALUE IN TEMP.

C3: STA TEMP
 LDA #0
 STA TEMP+1
 ;-------------------------------
 ;MUTIPLI CHARACTER BY 8
 ;-------------------------------
 LDX #3
 CLC
C4: ASL TEMP
 ROL TEMP+1
 DEX
 BNE C4
 ;------------------------------
 ;ADD CHARACTER SET ADDRESS, AND
 ;PUT THE VALUE IN ZERO PAGE.
 ;------------------------------
 CLC
 LDA TEMP
 ADC CHSET
 STA CHRGET
 LDA TEMP+l
 ADC CHSET+1
 STA CHRGET+1
 ;---------------------------------
 ;COPY CHARACTER, FROM ITS ORIGINAL
 ;ADDRESS, TO PLAYER MEMORY.
 ;---------------------------------
 LDX #0
 LDY #8
CP1: LDA (CHRGET,X)
 STA (PLAYER,X)
 INC CHRGET
 INC PLAYER
 DEY
 BNE CP1
 INC COUNT
 LDA COUNT
 CMP MAX;
 BEQ RETURN
 CMP LENGTH
 BEQ RETURN
 BNE GETSTR;NOT DONE.CONTINUE LOOP.
RETURN: RTS;DONE.GO BACK TO BASIC.
 ;---------------------------------
 ;THIS ROUTINE WILL MOVE THE PLAYER
 ;UP OR DOWN WITH RAP.
 ;---------------------------------
 PLA ;GET UNUSED BYTE.
 PLA ;MSB OF PLAYER.
 STA MOVEP+1
 STA MP+1
 PLA ;LSB OF PLAYER.
 STA MOVEP
 STA MP
 PLA ;UNUSED MSB OF DIRECTION.

 ;SINGLE LINE RESOLUTION SETUP.

 LDX #255
  LDY #255

 ;TEST FOR DOUBLE OR SINGLE LINE
 ;RESOLUTION.

 LDA 559
 CMP #62
 BEQ S1

;DOUBLE LINE RESOLUTION SETUP.

 LDX #127
 LDY #126

 ;PULL LSB OF DIRECTION OFF STACK,AND
 ;FIND OUT THE DIRECTION TO MOVE.

S1: PLA
 CMP #l
 BEQ MDOWN
 ;---------------------------------
 ;MOVE PLAYER UP ONE BYTE AND RAP.
 ;---------------------------------
 LDY #0
 LDA (MP),Y
 STA TEMP
 INC MOVEP
UP: LDA (MOVEP),Y
 STA (MP),Y
 INY
 DEX
 BNE UP

 ;DONE.GO RAP LAST BYTE AROUND.

 BEQ 53
 ;----------------------------------
 ;MOVE PLAYER DOWN ONE BYTE AND RAP.
 ;----------------------------------
MDOWN: TXA
 TAY
 LDA (MP),Y
 STA TEMP
 DEY
S2: LDA (MOVEP),Y
 STA TEMP+1
 TXA
 TAY
 LDA TEMP+1
 STA (MP),Y
 DEY
 DEY
 DEX
 BNE S2
 ;-----------------------------
 ;RAP LAST BYTE AROUND AND EXIT
 ;ROUTINE.
 ;-----------------------------
 TXA
 TAY
S3: LDA TEMP
 STA (MP),Y
 RTS

 ;BYTE FIELD EQUATES

TEMP: DB 0,0
LENGTH: DB 0
COUNT: DB 0
CHSET: DB 0,0
MAX: DB 0