====== Text scrolling with the VIC ======
By Monte Carlos
====Introduction====
Text scrollers are done by moving one or more lines of the screen left or right and
adding new characters at the border. They are using the simplest mode the grafic chip of the c64 offers, namely the text mode.
See http://codebase64.org/doku.php?id=base:built_in_screen_modes for more information on the c64
grafics modes.\\
A memory area is associated with the textscreen, the grafic chip displays. (The memory area
for the textscreen lies at $0400(1024) after switching on the computer and has 1000 bytes)
A scroller can be done by simply peeking a value from the textscreen and poking this value
at the byte associated with the neighbour character and doing this consecutively for the whole textline.
**Example:**
{{:base:textscroll_peekpoke.jpg?400}}
====== Scrolling ======
==== Hardscroll in one direction ====
In the following example, the text is scrolled left and a new character is
inserted at the rightmost screenposition.
screen = $0400
ldx #38
ldy #0
scroll:
lda screen+1,y
sta screen,y
iny
dex
bpl scroll
lda newchar
sta screen+39
Next example is the code for moving text left to right.
screen = $0400
ldy #38
scroll:
lda screen,y
sta screen+1,y
dey
bpl scroll
lda newchar
sta screen
A common pitfall is to move the bytes in the wrong order.
Say you want to scroll the string **commodore**.
Then, after the transfer, it looks like **ommodore ** if you move
first the o, then the first m, then the second m etc.
Contrary you get **eeeeeeeee** if you start moving the e, then
the now overwritten r, then the now overwritten o.
===Bigger scrollers===
See [[Bigger letters]] for information about how to assemble
characters to bigger letters in a way so that each character represents only a
part of the letter.
The only difference to 1x1 text scroller like described above is,
that you have to scrolll more than one line.\\
For example scrolling n lines looks like this:
screen = $0400
ldx #38
ldy #0
scroll:
lda screen+1,y
sta screen,y
lda screen+41,y
sta screen+40,y
...
lda screen+((n-1)*40)+1,y
sta screen+((n-1)*40),y
lda screen+(n*40)+1,y
sta screen+(n*40),y
iny
dex
bpl scroll
lda newchar
sta screen+39
lda newchar+1
sta screen+40+39
...
lda newchar+n-1
sta screen+((n-1)*40)+39
lda newchar+n
sta screen+(n*40)+39
The charset memory may not contain latin symbols. It can also hold parts of
scenery for games. The characters then represent small
parts of the background which is build up by these characters
like a puzzle. This way the scenery can be easily scrolled like text.
==== Bidirectionall hardscroll ====
Of course it is possible to write extra code to scroll left and to scroll right.
(See the examples above)
But this isn't necessary, if we use speedcode for the textscrolling and the y register
to temporarily save the characters at the destination positions (Speedcode basics: See article by Cruzer/CML:[[base:speedcode]]).
Look at the following example:
lda screen,x
sty screen
ldy screen+1,x
sta screen+1
lda screen+2,x
sty screen+2
...
If the routine is started with x=0, the text is scrolled right.
If the routine if started with x=2, the text is scrolled left.
Is is also possible to use exactly the same routine for 4 or 8 ways scrolling (See article and homepage by Malcolm Bamber: [[base:4_ways_scroll]],[[http://www.dark-well.pwp.blueyonder.co.uk/]]).
Care must be taken for the characters at the screen borders. Extra code has to be
added for each direction to supply the new characters scrolling into the visible area.
This extra code is much smaller than the core routine and so we save approximately 7/8
of the memory compared to 8 scroll routines for each direction.
If we do not use speedcode for the scrolling, things get a little more complicated
and the stack has to be used to temporaly save characters which may become overwritten.
LDX #39
LDY #39; for left scrolling
LDX #39
LDY #37; for right scrolling
LDA SCRLADR,Y
STA TMP1
LDA SCRLADR-1,Y
PHA
S
LDA TMP1
STA SCRLADR-1,X
PLA
STA TMP1
LDA SCRLADR-2,Y
PHA
DEY
DEX
BNE S
PLA
====== Softscroll ======
==== Role of $d016 ====
The code above enables you to scroll a text in 8 pixel steps.
If you want to do a smooth scroll two pixel steps or 1 pixel steps
are desirable.
This is done using the soft-scroll register $d016 (for a detailed description look: https://sh.scs-trc.net/vic/).
If you want to scroll left you start with $x7 in $d016 and decrease that value
every frame. After 8 times you reset this register to its start value and
move all characters one byte backwards using the according one of above scroll routines.
==== Example code ====
What follows is the perhaps shortest routine
for bidirectional soft scrolling (only $6d bytes long),
from which above code is taken from:
*= $1000
Q = 2
XPIXSHIFT = 4
TMP1 = 5
TEXTADR = 6
SCRLADR = $0400
JSR $E544
SEI
TEXTRESTART
LDA #TEXT
STA TEXTADR+1
LOOP INC $d012
BNE LOOP
DESTSTART = *+1
LDX #39;39
SRCSTART = *+1
LDY #39;37
XPIXSHIFTADD
DEC XPIXSHIFT
LDA XPIXSHIFT
AND #7
STA $D016
CMP XPIXSHIFT
STA XPIXSHIFT
BEQ LOOP
LDA SCRLADR,Y
STA TMP1
LDA SCRLADR-1,Y
PHA
S
LDA TMP1
STA SCRLADR-1,X
PLA
STA TMP1
LDA SCRLADR-2,Y
PHA
DEY
DEX
BNE S
PLA
GETNEWCHAR
;TEXTADR = *+1
LDA (TEXTADR,X)
BEQ TEXTRESTART
INY
BMI *+4
LDX #$27
NOBEGIN INC TEXTADR
BNE *+4
INC TEXTADR+1
TAY
BMI DIRCHANGE
STA SCRLADR,X
BPL LOOP
;---------------------------------------
DIRCHANGE LDA XPIXSHIFTADD
EOR #$20
STA XPIXSHIFTADD
LDX DESTSTART
LDY SRCSTART
DEX
INY
STX SRCSTART
STY DESTSTART
BNE LOOP
;---------------------------------------
TEXT .TEXT " THIS SCROLLER CAN"
.TEXT " SCROLL IN FORWARD"
.TEXT " AND BACKWARD DIREC"
.TEXT "TION! "
.TEXT " "
.TEXT " "
.BYTE $FF
.TEXT "WON GNILLORCS MORF "
.TEXT "TFEL OT THGIR ... . "
.TEXT " "
.TEXT " "
.BYTE $FF,0