;; This example demonstrates hardware scrolling using the CRTC. ;; ;; This example will function on CPC, CPC+ and KC Compact and ALL CRTC ;; variants. ;; ;; The rate of horizontal scroll is a minimum of 2 CRTC characters. ;; This is equivalent to: ;; - 4 pixels in mode 0 ;; - 8 pixels in mode 1 ;; - 16 pixels in mode 2 ;; ;; The rate of vertical scroll is a minimum of a CRTC character line (the number ;; of scanlines in the CRTC line is defined using register 9 of the CRTC). ;; With 8 scanlines per CRTC character line this is equivalent to 8 scanlines. ;; ;; The horizontal scroll rate can be improved to scroll by: ;; This is equivalent to: ;; - 2 pixels in mode 0 ;; - 4 pixels in mode 1 ;; - 8 pixels in mode 2 ;; ;; Using register 3 of the CRTC. Another example will demonstrate this method. ;; ;; The vertical scroll rate can be improved to scroll by a single scanline at a time, ;; by using register 5 of the CRTC. Another example will demonstrate this method. ;; ;; It is very difficult to scroll the screen pixel by pixel using hardware alone ;; on the standard CPC hardware. If you want pixel scrolling using the hardware, ;; then please use the CPC+ enhancements. ;; ;; Hardware scrolling is made by changing the start address ;; of the display. ;; ;; Use the following keys: ;; Q - scroll screen up ;; A - scroll screen down ;; O - scroll screen to left ;; P - scroll screen to right ;; NOTE position of this code is not important org &4000 nolist .km_read_key equ &bb1b .mc_wait_flyback equ &bd19 .scr_set_mode equ &bc0e .txt_output equ &bb5a ;; set the screen mode ld a,1 call scr_set_mode ld bc,24*40 ld d,' ' .l1 inc d ld a,d cp &7f jr nz,no_char_reset ld d,' ' .no_char_reset ld a,d call txt_output dec bc ld a,b or c jr nz,l1 .loop ;; wait for vsync ;; ;; (synchronises scroll with the screen refresh; as a result it ;; updates at a constant rate and is smooth) call mc_wait_flyback ;; check if any keys are pressed (they will update the scroll offset) call check_keys ;; set the scroll offset ld hl,(scroll_offset) call set_offset ;; loop jp loop ;;---------------------------------------------------------------------- .check_keys ;; test if any key has been pressed call km_read_key ret nc ;; A = code of the key that has been pressed ;; ;; check the codes we are using and handle appropiatly. cp 'Q' ; Q jp z,scroll_up cp 'q' jp z,scroll_up cp 'A' ; A jp z,scroll_down cp 'a' jp z,scroll_down cp 'O' ; O jp z,scroll_left cp 'o' jp z,scroll_left cp 'P' ; P jp z,scroll_right cp 'p' jp z,scroll_right ret ;;---------------------------------------------------------------------- .scroll_up ;; get the current scroll offset ld hl,(scroll_offset) ;; update it ;; ;; NOTE: ;; - 40 is the number of CRTC characters in a CRTC character row ;; and it is identical to the value written to CRTC register 1 (Horizontal Displayed). ;; ;; - If you change the width of the display (using register 1), then you must ;; change this to the same value for the scroll to operate correctly. ld bc,40 or a sbc hl,bc ;; ensure scroll offset is in range &000-&3ff ld a,h and &3 ld h,a ;; store new scroll offset. It is now ready to be written to the CRTC. ld (scroll_offset),hl ret ;;---------------------------------------------------------------------- .scroll_down ;; get current scroll offset ld hl,(scroll_offset) ;; update it ;; ;; NOTE: ;; - 40 is the number of CRTC characters in a CRTC character row ;; and it is identical to the value written to CRTC register 1 (Horizontal Displayed). ;; ;; - If you change the width of the display (using register 1), then you must ;; change this to the same value for the scroll to operate correctly. ld bc,40 add hl,bc ;; ensure scroll offset is in range &000-&3ff ld a,h and &3 ld h,a ;; store new scroll offset. It is now ready to be written to the CRTC. ld (scroll_offset),hl ret ;;---------------------------------------------------------------------- .scroll_left ;; get current scroll offset ld hl,(scroll_offset) ;; update it dec hl ;; ensure scroll offset is in range &000-&3ff ld a,h and &3 ld h,a ;; store new scroll offset. It is now ready to be written to the CRTC. ld (scroll_offset),hl ret ;;---------------------------------------------------------------------- .scroll_right ;; get current scroll offset ld hl,(scroll_offset) ;; update it inc hl ;; ensure scroll offset is in range &000-&3ff ld a,h and &3 ld h,a ;; store new scroll offset. It is now ready to be written to the CRTC. ld (scroll_offset),hl ret ;;---------------------------------------------------------------------- ;; ;; HL = scroll offset in CRTC character units .set_offset ld bc,&bc0c ;; select CRTC register 12 out (c),c ld b,&bd ;; B = I/O address for CRTC register write ;; combine with scroll base ld a,(scroll_base) or h out (c),a ld bc,&bc0d ;; select CRTC register 13 out (c),c ld b,&bd ;; B = I/O address for CRTC register write out (c),l ret ;;---------------------------------------------------------------------- ;; high byte of the screen base address ;; &00 -> screen uses &0000-&3fff ;; &10 -> screen uses &4000-&7fff ;; &20 -> screen uses &8000-&bfff ;; &30 -> screen uses &c000-&ffff .scroll_base defb &30 ;; the scroll offset in CRTC character units .scroll_offset defw 0