Date : Sun, 10 Feb 2002 22:19:20 -0000
From : "Rich Talbot-Watkins" <rich_tw@...>
Subject: Sample Firetrack-type-scrolling proggy
After all the recent discussion, this may be of interest to anyone
developing emulators and trying to get to the bottom of the Firetrack
scrolling... here's a little demo which should be small enough to type-in
(wow, a type-in listing... keeping the nostalgia alive!). It splits the
screen in two: the top 16 displayed character rows are a pixel-by-pixel
vertical scroll, the bottom 16 displayed character rows remain stationary:-
[typed in by hand, 'tis the only way I've got unfortunately, so sorry for
any typos that creep in]
10 MODE2
20 PROCdraw
30 PROCassemble
40 !addr=&B00:CALL&900
50 :
\\ just a crap demo screen so you can see what's going on....
60 DEF PROCdraw
70 VDU28,0,15,19,0,17,132,12,26,17,128
80 FOR N%=0 TO 15
90 COLOUR N%MOD7+1
100 COLOUR 128:PRINTTAB(N%,16+N%);N%;"_";
110 COLOUR 132:PRINTTAB(2,N%);N%+16;
120 NEXT
130 MOVE0,1023:DRAW1279,1023:DRAW1279,512:DRAW0,512:DRAW0,1023
140 ENDPROC
150 :
\\ wait for vsync
160 DEF FNvsync
170 [OPTN%:LDA&FE4D:AND#2:BEQP%-5:STA&FE4D:]
180 =N%
190 :
\\ set our timer to timeout in L% microseconds
200 DEF FNsetwait(L%)
210 [OPTN%:LDA#L%AND255:STA&FE44:LDA#L%DIV256:STA&FE45:]
220 =N%
230 :
\\ wait for our timer to timeout
240 DEF FNwait
250 [OPTN%:LDA&FE4D:AND#&40:BEQP%-5:STA&FE4D:]
260 =N%
270 :
\\ this macro either enables or disables display by
\\ changing all palette colours
280 DEF FNcols(B%)
290 FORC%=0TO7:IFB% D%=C%EOR7 ELSE D%=7
300 [OPTN%:LDA#C%*16+D%:STA&FE21:]
310 NEXT
320 =N%
330 :
340 DEF PROCassemble
350 addr=&70:line=&72
355 linetime%=64:REM 1 scanline rasterises in 64 microsecs
360 FOR N%=0 TO 2 STEP 2:P%=&900:[OPT N%
370 SEI
\\ set bits 4/5 of addressable latch for 10k screen
380 LDA#15:STA&FE42
390 LDX#12:STX&FE40:INX:STX&FE40
\\ initialise a few constant CRTC registers
400 LDA#3:STA&FE00:LDA#&88:STA&FE01
410 LDA#10:STA&FE00:LDA#32:STA&FE01
420 .loop
\\ wait until vsync, then blank all colours and set timer
\\ for four character rows time (top of visible screen)
430 OPT FNvsync \wait for vsync
440 OPT FNsetwait(linetime%*32-50) \-50 for fine tuning
450 OPT FNcols(0) \all colours off
460 OPT FNwait
\\ after four character rows, turn all colours back on
\\ (we deem this point to be the top of the visible screen),
\\ set timer to stop us sometime in the bottom half of scrn,
\\ setup R4/5/6/7 for this top half of the screen, and
\\ setup R12/13 for the bottom half of screen when recached
470 OPT FNsetwait(linetime%*138) \reasonably arbitrary
480 OPT FNcols(1) \colours back on
490 LDA#4:STA&FE00:LDA#15:STA&FE01 \crtc cycle=16 rows
500 LDA#5:STA&FE00:LDAline:STA&FE01 \plus these scanlines
510 LDA#6:STA&FE00:LDA#255:STA&FE01 \display always
520 LDA#7:STA&FE00:LDA#255:STA&FE01 \inhibit vsync this half
530 LDA#12:STA&FE00:LDA#6:STA&FE01 \bottom screen start
540 LDA#13:STA&FE00:LDA#0:STA&FE01 \ address is &3000
550 OPT FNwait
\\ now prepare to jiggle the addr and line variables to
\\ scroll the screen up by a line (this is effectively
\\ the bottom of the loop)
560 LDAline:CLC:ADC#1:CMP#8:BCCskip
570 LDAaddr:CLC:ADC#80:STAaddr
580 LDAaddr+1:ADC#0:CMP#&10:BCCP%+4
590 LDA#&B:STAaddr+1:LDA#0
600 .skip STAline
\\ we are currently rasterising the bottom half of screen,
\\ setup R4/5/6/7 for this bottom half, and R12/13 for
\\ the top half (next frame).
\\ NB As the VSync occurs midway through this CRTC update,
\\ the effects of changing R5 are effectively seen in the
\\ positioning of the 'top' screen next update.
610 LDA#4:STA&FE00:LDA#21:STA&FE01
620 LDA#5:STA&FE00
630 SEC:LDA#8:SBCline:STA&FE01
640 LDA#6:STA&FE00:LDA#16:STA&FE01 \16 lines in bottom screen
650 LDA#7:STA&FE00:LDA#18:STA&FE01
660 LDA#12:STA&FE00:LDAaddr+1:STA&FE01
670 LDA#13:STA&FE00:LDAaddr:STA&FE01
\\ that's it! vsync set to occur sometime this crtc
\\ update, which will be picked up next time round this loop
680 JMPloop
690 ]:NEXT
700 ENDPROC
This works perfectly on my BBC Master at home, I've not had a chance to try
it on any emulators. It's quite timing critical; the black palette fringe
inhibiting display at the top of the screen is set to occur in the side
border just before the appropriate screen line, so the visible number of
lines in the 'top' screen should be exactly 128. It is important that R3 is
set to &88 (line 400); changing the top 4 bits will move this fringe up and
down by scanline amounts - probably crucial in an emulator too.
The following changes might make the demo more useful for getting the timing
right:
290 FORC%=0TO7:IFB% D%=C%EOR7 ELSE D%=0
455 LDA#3:STA&FE21
485 LDA#7:STA&FE21
555 LDA#7:JMPskip
This stops the scrolling, and should display the 'masked' area at the very
top of the screen as white text on blue. The very top digit zero should
appear wholly in white on blue, whereas the underline next to it should be
in the first 'visible' scanline of the screen and should hence appear red.
As we are effectively displaying a 33-row screen here (but always masking up
to the first 8 scanlines), we see 7 lines of the digit zero repeated in row
16 too, just before the 'bottom' screen half begins.
Probably worth trying on a real Beeb first of all anyway in order to get a
feel for what should be going on....
All this to get blimmin' Firetrack working...!
cheers,
Rich