;; Mode 2 pixel by pixel software scroll
;;
;; hard-wired to work with characters 8 pixels wide and 8 tall, uses system font from ROM
;;
;; Assembles with MAXAM.
;;
;; Code written by Kev Thacker. 

.scr_set_mode equ &bc0e
.kl_l_rom_enable equ &b906
.kl_l_rom_disable equ &b909
.kl_u_rom_disable equ &b903
;; this program must not be located in range &0000-&3fff,
;; because we need to access the lower rom, and the lower rom
;; is paged into this memory range.
org &4000
nolist

;;-------------------------------------------------------------------------------------
;; set video mode (and clear screen)
ld a,2
call scr_set_mode

;;-------------------------------------------------------------------------------------
;; copy system font from operating system ROM

;; enable lower ROM (ROM data is readable in range &0000-&3fff)
call kl_l_rom_enable

ld hl,&3900		;; start of font pixel data in lower ROM
ld de,font_data				;; address to copy to
ld bc,&4000-&3900		;; length of font pixel data
ldir

;; disable lower rom now we are done with it 
call kl_l_rom_disable

;; disable upper rom because we will be reading/writing screen memory
;; and we don't want to read upper rom contents by mistake
call kl_u_rom_disable

;;-------------------------------------------------------------------------------------

call initialise_scroller

;;-------------------------------------------------------------------------------------


.main_loop
ld b,&f5
.ll1 in a,(c)
rra
jr nc,ll1
halt
halt
halt
call scroll_message
jp main_loop

.initialise_scroller
ld hl,scroll_text
ld a,(hl)
jr sm2

.scroll_message ld a,0 ;current bit counter value
dec a   ;counts number of bits to scroll before updating 
   ;column buffer
and 7   ;make sure it loops 7..0 and repeats
ld (scroll_message+1),a ;store bit counter
jr nz,scroll_block ;scroll block in memory (or on-screen)

.sm1 ld hl,scroll_text ;current position in scroller message
inc hl   ;update position pointer
ld a,(hl)  ;get character at address
or a   ;is value zero?? (end of scroll message marker)
jr nz,sm2
ld hl,scroll_text ;return position pointer to start of scroll message
ld a,(hl)  ;get character at new position in scroll message

.sm2 ld (sm1+1),hl ;store position pointer
sub ' '   ;first character in font file
ld l,a   ;calculate offset from start of font file
ld h,0
add hl,hl  ;x2
add hl,hl  ;x4
add hl,hl  ;x8 (no of bytes occupied by character)
ld de,font_data ;start of first character's data in memory
add hl,de
ld de,column_buffer ;address to put data

ldi   ;poke column of character data into buffer
ldi
ldi
ldi
ldi
ldi
ldi
ldi   ;number of LDI's = height of character

.scroll_block
ld b,8				;; char height
ld hl,&c000+79			;; rightmost position of scroller on-screen
ld de,&800+79		;; increment for next line (80 bytes wide screen, standard 640x200 screen)
ld ix,column_buffer
.pixel_scroll
rl (ix+0)
inc ix
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
dec hl
rl (hl)
add hl,de
dec b
jp nz,pixel_scroll
ret

;; stores one column of font for scrolling
;; note this is modified in scroller
.column_buffer defs 8

.scroll_text defb "THIS IS A TOTALLY AMAZING, SUPER SMOOTH, PIXEL PERFECT FANTASTIC PIXEL SCROLL ...........                                   ",0

;; font data copied from OS rom
.font_data equ $+1