;;----------------------------------------------------------------------------------------------------- ;; ;; This example demonstrates: ;; SCR NEXT BYTE, SCR PREV BYTE, SCR NEXT LINE, SCR PREV LINE ;; for moving around the screen using screen addresses ;; ;; SCR GET LOCATION to get address of top-left of screen (accounts for scrolling ;; and if screen location has changed (e.g. with SCR SET BASE) ;; ;; SCR PIXELS, SCR WRITE, SCR READ for accessing screen in a way that ;; works with upper roms enabled org &8000 ;; turn off listing; remove for pasmo assembler nolist scr_set_mode equ &bc0e txt_output equ &bb5a mc_wait_flyback equ &bd19 km_test_key equ &bb1e scr_next_byte equ &bc20 scr_prev_byte equ &bc23 scr_next_line equ &bc26 scr_prev_line equ &bc29 scr_get_location equ &bc0b scr_pixels equ &bc5c kl_l_rom_enable equ &b906 kl_l_rom_disable equ &b909 ram_lam equ &0020 ;; for the indirections you need to have lower rom enabled ;; before you call them to call the default functions! ind_scr_write equ &bde8 ind_scr_read equ &bde5 spr_height equ 16 spr_width_bytes equ 8 ;;------------------------- start: ;; set mode to 0 xor a call scr_set_mode ;; write some chars to the screen ;; so we can see that restoring background works for sprites ld bc,24*20 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 call scr_get_location or h ld h,a ;; HL = screen address of top-left of screen ld (scr_addr),hl ;; copy screen behind sprite to a buffer ld hl,(scr_addr) ld b,spr_height ld c,spr_width_bytes ld de,buffer call scr_to_mem ;; put sprite onto screen ld hl,(scr_addr) ld b,spr_height ld c,spr_width_bytes ld de,sprite_data call mem_to_scr ;;------------------------- main_loop: ;; wait for VSYNC call mc_wait_flyback ;; restore screen ld hl,(scr_addr) ld b,spr_height ld c,spr_width_bytes ld de,buffer call mem_to_scr ;; check keys call do_keys ;; scr_addr has potentially been updated ;; copy new screen behind sprite to a buffer ld hl,(scr_addr) ld b,spr_height ld c,spr_width_bytes ld de,buffer call scr_to_mem ;; put sprite onto screen ld hl,(scr_addr) ld b,spr_height ld c,spr_width_bytes ld de,sprite_data call mem_to_scr jp main_loop ;;----------------------------------------------------------------------------------------------------- ;; use firmware method SCR_PIXELS to write to ram write_method_1: ld b,a ld c,&ff call scr_pixels ret ;;----------------------------------------------------------------------------------------------------- ;; writing always goes to RAM regardless of ROM enabled state write_method_2: ld (hl),a ret ;;----------------------------------------------------------------------------------------------------- ;; HL = screen address ;; DE = address of data ;; B = height in lines ;; C = width in bytes ;; width/2 for mode 0 ;; width/4 for mode 1 ;; width/8 for mode 2 mem_to_scr: m2s_height_loop: push bc push hl m2s_width_loop: push bc ld a,(de) ;; pixels inc de ;;call write_method_1 call write_method_2 ;; increment screen address for next byte to right call scr_next_byte pop bc dec c jr nz,m2s_width_loop ;; restore screen address of start of line pop hl ;; go down to next line call scr_next_line pop bc djnz m2s_height_loop ret ;;----------------------------------------------------------------------------------------------------- ;; use SCR READ indirection read_method_1: ;; enable lower rom to allow indirection to work call kl_l_rom_enable push af ;; read pixels ld c,&ff call ind_scr_read ;; write them ld (de),a inc de pop af ;;restore lower rom state call kl_l_rom_disable ret ;;----------------------------------------------------------------------------------------------------- read_method_2: rst 4 ;; ram lam ld (de),a inc de ret ;;----------------------------------------------------------------------------------------------------- ;; copy a section of screen to a buffer ;; HL = screen address ;; B = height in lines ;; C = width in bytes ;; width/2 for mode 0 ;; width/4 for mode 1 ;; width/8 for mode 2 scr_to_mem: s2m_height_loop: push bc push hl s2m_width_loop: push bc ;;call read_method_1 call read_method_2 ;; increment screen address for next byte to right call scr_next_byte pop bc dec c jr nz,s2m_width_loop ;; restore screen address of start of line pop hl ;; go down to next line call scr_next_line pop bc djnz s2m_height_loop ret ;;----------------------------------------------------------------------------------------------------- ;; check keyboard ;; ;; cursor keys do_keys: ld a,0*8+0 call km_test_key jr nz,move_up ld a,0*8+1 call km_test_key jr nz,move_right ld a,0*8+2 call km_test_key jr nz,move_down ld a,1*8+0 call km_test_key jr nz,move_left ret ;;----------------------------------------------------------------------------------------------------- move_up: ld hl,(scr_addr) call scr_prev_line ld (scr_addr),hl ret ;;----------------------------------------------------------------------------------------------------- move_down: ld hl,(scr_addr) call scr_next_line ld (scr_addr),hl ret ;;----------------------------------------------------------------------------------------------------- move_left: ld hl,(scr_addr) call scr_prev_byte ld (scr_addr),hl ret ;;----------------------------------------------------------------------------------------------------- move_right: ld hl,(scr_addr) call scr_next_byte ld (scr_addr),hl ret ;;----------------------------------------------------------------------------------------------------- ;; background behind sprite that needs to be restored to screen to erase sprite buffer: defs spr_height*spr_width_bytes ;;----------------------------------------------------------------------------------------------------- ;; sprite pixels sprite_data: defs spr_height*spr_width_bytes,&ff ;;----------------------------------------------------------------------------------------------------- ;; screen address of sprite scr_addr: defw 0