4. How would a game do horizontal scrolling? This is a difficult question - but I'm trying to get you to think about the implications of the odd playfield->pixel correspondence, and the implications for game writing.
I modified the kernel code to use ASL commands to shift the bits in my playfield variable to the left. Since I didn't want the playfield to repeat itself twice on the screen, I added a second variable to the original kernel lesson sample.
The code only uses PF0 to draw the screen. The result is that the playfield scrolls horizontally from left to right, jumping the center and edges of the screen (everything else not drawned by PF0). The scrolling feels a lot like Vanguard. It's not smoothy like say, Chopper Command. I think for that you would need to use the HMOVE register with something other than the playfield, but that's ok for now.
On PCAEWIN it works fine, but on Z26 it draws some garbage at the top of the screen. Take a look at the code:
; 2600 for Newbies
; lesson 14 - playfield
; Question 4 - One way to do horizontal scrolling with the playfield.
processor 6502
include "vcs.h"
include "macro.h"
; OBJECTIVE: This variation of the lesson 14 kernel does horizontal scrolling with the playfield.
; Only PF0 is used. The program uses to variables to store the left and right side values
; of the playfield. These are declared below:
PATTERN_LEFT = $80
PATTERN_RIGHT = $82
TIMETOCHANGE = 20
SEG
ORG $F000
RESET
; Clear RAM and all TIA regs
LDX #0
LDA #0
CLEAR
STA 0,X
INX
BNE CLEAR
LDA #$45
STA COLUPF
LDY #0
; Here we assign the pattern values to our left and right side of the playfield.
; Try using different values.
LDA #$0
STA PATTERN_LEFT
LDA #$01
STA PATTERN_RIGHT
STARTOFFRAME
LDA #0
STA VBLANK
LDA #2
STA VSYNC
STA WSYNC
STA WSYNC
STA WSYNC
LDA #0
STA VSYNC
; 37 scanlines of vertical blank
LDX #0
VERTICALBLANK
STA WSYNC
INX
CPX #37
BNE VERTICALBLANK
; HANDLE A CHANGE IN THE PATTERN ONCE EVERY 20 FRAMES
; WRITE THE PATTERN TO PF1
INY
CPY #TIMETOCHANGE
BNE SCROLLCOMPLETE
LDY #0
; The following code uses arithmetic left shift commands (ASL) to make the scrolling happen.
; We shift the bits of the playfield variables to the left. Original bit 7 is shifted to the Carry.
; The program uses BCC to check if a bit was dropped. Dropped bits are inserted to the
; opposite pattern variable by the INC command. The INC command can mess up the pattern if
; the original bit 0 is turned on. To avoid this we shift everything to the left before incrementing.
SHIFTRIGHT
CLC
ASL PATTERN_RIGHT
BCC SHIFTLEFT
ASL PATTERN_LEFT
INC PATTERN_LEFT
BCC SCROLLCOMPLETE
INC PATTERN_RIGHT
JMP SCROLLCOMPLETE
SHIFTLEFT
ASL PATTERN_LEFT
BCC SCROLLCOMPLETE
INC PATTERN_RIGHT
SCROLLCOMPLETE
; DO 192 SCANLINES OF COLOR CHANGING (OUR PICTURE)
LDX #0
PICTURE
STX COLUPF
; Load the left pattern into PF1 register.
LDA PATTERN_LEFT
STA PF1
; Wait enough cycles before drawing right pattern.
SLEEP 20
; Load right pattern to PF1.
LDA PATTERN_RIGHT
STA PF1
STA WSYNC
INX
CPX #192
BNE PICTURE
LDA #%01000010
STA VBLANK
; 30 LINES OF OVERSCAN
LDX #0
OVERSCAN
STA WSYNC
INX
CPX #30
BNE OVERSCAN
JMP STARTOFFRAME
ORG $FFFA
INTERRUPTVECTORS
.WORD RESET
.WORD RESET
.WORD RESET
END
The tricky code is the bit shifting. Here is the pseudocode:
[color=blue]; Pseudocode:
;
; Clear Carry
; Shift bits in variable PATTERN_RIGHT to the left. Original bit 7 is shifted into the Carry.
;
; if no bit was dropped from PATTERN_RIGHT (Carry Clear) then
;
; Shift the bits in PATTERN_LEFT
; if no bit was dropped from PATTERN_LEFT then
;
; Scroll is complete. Continue program flow.
;
; else
;
; Insert dropped bit from left pattern into PATTERN_RIGHT (Using the INC command).
;
; end
;
; else
;
; Shift bits in PATTERN_LEFT
; Insert dropped bit from right pattern into PATTERN_LEFT.
; If no bit was dropped from PATTERN_LEFT then
;
; Scroll is complete.
;
; else
;
; Insert dropped bit from left pattern into PATTERN_RIGHT.
;
; end
;
; end[/color]
This translates to:
SHIFTRIGHT
CLC
ASL PATTERN_RIGHT
BCC SHIFTLEFT
ASL PATTERN_LEFT
INC PATTERN_LEFT
BCC SCROLLCOMPLETE
INC PATTERN_RIGHT
JMP SCROLLCOMPLETE
SHIFTLEFT
ASL PATTERN_LEFT
BCC SCROLLCOMPLETE
INC PATTERN_RIGHT
SCROLLCOMPLETE
I am sure there is a better way of doing this without so many BCC's and ASL's (perhaps getting rid of the JMP altogether).
question4.zip