;############## Calcuzap by Patrick Davidson - graphics rendering routines ;############## Clear the screen (in black, of course!) Clear_Screen: ld hl,$D40000 ld (hl),0 ld de,$D40001 ld bc,320*240*2-1 ldir Display_Org: Display_Normal: Full_Window: ret ;############## Locate position of pixel in display memory ; B = X coordinate divided by 2 ; L = Y coordinate ; result in HL Get_Screen_Start: push de ld a,l ld hl,0 ld l,a push hl pop de add hl,hl add hl,hl add hl,de ; HL = 5 * Y add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ; HL = 160 * Y ld e,b add hl,de ; HL = 160 * Y + X add hl,hl add hl,hl ; HL = 640 * Y + 4 * X ld de,$D40000-(96*2) add hl,de pop de ret ;############## Erase rectangle ; B = X coordinate ; C = Y coordinate ; E = height ; D = width Erase_Rectangle: ld a,c Erase_Rectangle_A: cp 244 ret nc ; below the bottom, so exit sub 12 ld l,a jr nc,erase_no_top_clip add a,e ; A = remaining height ret nc ret z ld e,a ld l,0 jr erase_vertical_clip_done erase_no_top_clip: add a,e ; A = bottom Y coordinate + 1 cp 233 jr c,erase_vertical_clip_done ld a,232 sub l ld e,a erase_vertical_clip_done: ; E = final height, L = final Y coordinate call Get_Screen_Start ld c,e ; C = height push hl ld a,d ld (smc_Erase_Clipped_Loop+1),a add a,a add a,a ; A = width in bytes ld de,0 ld e,a ld hl,640 sbc hl,de ; HL = amount to skip between rows ex de,hl ; DE = amount to skip between rows pop hl xor a smc_Erase_Clipped_Loop: ld b,4 Erase_Clipped_Inner_Loop: ld (hl),a inc hl ld (hl),a inc hl ld (hl),a inc hl ld (hl),a inc hl djnz Erase_Clipped_Inner_Loop add hl,de dec c jr nz,smc_Erase_Clipped_Loop ret ;############## Draw a sprite ; B = X coordinate divided by 2 ; L = Y coordinate ; DE -> sprite (first byte is height in pixels, second byte is width in bytes, then packed pixels) Draw_Sprite_Packed: ld a,l cp 244 ret nc ; draw nothing if starting below the bottom sub 12 ; A = adjusted Y coordinate jr nc,draw_sprite_no_top_clip ld a,(de) add a,l sub 12 ; A = bottom Y coordinate (+1) ret c ret z push af ; push height inc de ld a,(de) ; A = width in double-pixels inc de ; DE -> start of sprite add a,a add a,a ; A = width in bytes push bc ld bc,0 ld c,a ; BC = width in bytes ld a,12 sub l ; A = number of lines cut ex de,hl loop_cut_top: add hl,bc dec a jr nz,loop_cut_top ex de,hl ld a,c ; A = width in bytes pop bc Ld l,0 ; New Y start is 0 jr draw_sprite_vertical_clip_done draw_sprite_no_top_clip: ld l,a ld a,(de) ; A = height push af ; push height inc de add a,l ; A = bottom Y coordinate cp 233 jr c,draw_sprite_no_bottom_clip pop af ld a,232 sub l push af draw_sprite_no_bottom_clip: ld a,(de) ; A = width in double-pixels inc de add a,a add a,a ; A = width in bytes draw_sprite_vertical_clip_done: ld (smc_draw_no_clip_loop+1),a call Get_Screen_Start ex de,hl ; DE -> location on screen, HL -> sprite push hl ; calculate skip length ld hl,320*2 ld bc,(smc_draw_no_clip_loop+1) sbc hl,bc ld (smc_draw_no_clip_skip+1),hl pop hl pop af smc_draw_no_clip_loop: ld bc,4 ; width to draw in bytes ldir ex de,hl smc_draw_no_clip_skip: ld bc,636 ; width to skip in bytes add hl,bc ex de,hl dec a jr nz,smc_draw_no_clip_loop ret Draw_Sprite_Flash: ld a,l cp 244 jp nc,flash_revert ; draw nothing if starting below the bottom sub 12 ; A = adjusted Y coordinate jr nc,flash_no_top_clip ld a,(de) add a,l sub 12 ; A = bottom Y coordinate (+1) ret c ret z push af ; push height inc de ld a,(de) ; A = width in double-pixels inc de ; DE -> start of sprite add a,a add a,a ; A = width in bytes push bc ld bc,0 ld c,a ; BC = width in bytes ld a,12 sub l ; A = number of lines cut ex de,hl flash_cut_top: add hl,bc dec a jr nz,flash_cut_top ex de,hl ld a,c ; A = width in bytes pop bc ld l,0 ; New Y start is 0 rrca jr flash_vertical_clip_done flash_no_top_clip: ld l,a ld a,(de) ; A = height push af ; push height inc de add a,l ; A = bottom Y coordinate cp 233 jr c,flash_no_bottom_clip pop af ld a,232 sub l push af flash_no_bottom_clip: ld a,(de) ; A = width in double-pixels inc de add a,a ; A = width in pixels flash_vertical_clip_done: ld (smc_flash_no_clip_loop+1),a push af call Get_Screen_Start ex de,hl ; DE -> location on screen, HL -> sprite pop af push hl ; calculate skip length ld hl,320*2 add a,a ; A = width in bytes ld bc,0 ld c,a sbc hl,bc ld (smc_flash_no_clip_skip+1),hl pop hl pop af smc_flash_no_clip_loop: ld b,4 ; width to draw in pixels ld c,a flash_loop: ld a,(hl) inc hl or (hl) inc hl ld a,0 jr z,flash_no_pixel ld a,-1 flash_no_pixel: ld (de),a inc de ld (de),a inc de djnz flash_loop ld a,c ex de,hl smc_flash_no_clip_skip: ld bc,636 ; width to skip in bytes add hl,bc ex de,hl dec a jr nz,smc_flash_no_clip_loop flash_revert: ld bc,Draw_Sprite_Packed ld (Draw_Sprite+1),bc ret