Atari
Streamers
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.
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