@@ -779,13 +779,13 @@ gfx_FillRectangle_NoClip:
779779; None
780780 ld iy , 0
781781 add iy , sp
782+ ld bc , (iy + 9 ) ; bc = width
783+ ld a , b
784+ or a , c
785+ ret z ; make sure width is not 0
782786 ld a , (iy + 12 ) ; a = height
783787 or a , a
784788 ret z ; make sure height is not 0
785- ld bc , (iy + 9 ) ; bc = width
786- sbc hl , hl
787- adc hl , bc
788- ret z ; make sure width is not 0
789789 ld hl , (iy + 3 ) ; hl = x coordinate
790790 ld e , (iy + 6 ) ; e = y coordinate
791791_FillRectangle_NoClip:
@@ -894,13 +894,13 @@ gfx_Rectangle_NoClip:
894894; None
895895 ld iy , 0
896896 add iy , sp
897+ ld bc , (iy + 9 ) ; bc = width
898+ ld a , b
899+ or a , c
900+ ret z ; abort if width == 0
897901 ld a , (iy + 12 ) ; a = height
898902 or a , a
899903 ret z ; abort if height == 0
900- ld bc , (iy + 9 ) ; bc = width
901- sbc hl , hl
902- adc hl , bc
903- ret z ; abort if width == 0
904904 push bc
905905 call _HorizLine_NoClip_NotDegen_StackXY ; draw top horizontal line
906906 ; hl = &buf[y][x+width-1]
@@ -930,30 +930,22 @@ gfx_HorizLine:
930930 ld de , ti.lcdHeight
931931smcWord _YMax
932932 sbc hl , de ; subtract maximum y
933- ld de , ti.lcdHeight ; add y bounds span
933+ ld de , ti.lcdHeight
934934smcWord _YSpan
935- add hl , de
935+ add hl , de ; add y bounds span
936936 ret nc ; return if not within y bounds
937- ld hl , (iy + 9 )
938937 ld de , (iy + 3 )
939- add hl , de
940- push hl
941938 ld hl , 0
942939smcWord _XMin
943- call _Maximum ; get minimum x
944- ex ( sp ) , hl
945- ld de , ti.lcdWidth
946- smcWord _XMax
947- call _Minimum ; get maximum x
948- pop de
949- scf
950- sbc hl , de
951- ret c
952- inc hl
953- push hl
954- pop bc ; bc = length
940+ ld bc , ti.lcdWidth
941+ smcWord _XSpan
942+ call _ClipInterval
955943 ex de , hl
956- jr _HorizLine_NoClip_NotDegen_StackY
944+ ; Check for empty interval
945+ ld a , b
946+ or a , c
947+ jr nz , _HorizLine_NoClip_NotDegen_StackY
948+ ret
957949
958950;-------------------------------------------------------------------------------
959951gfx_HorizLine_NoClip:
@@ -968,8 +960,8 @@ gfx_HorizLine_NoClip:
968960 add iy , sp
969961 ld bc , (iy + 9 ) ; bc = length
970962_HorizLine_NoClip_StackXY:
971- sbc hl , hl
972- adc hl , bc
963+ ld a , b
964+ or a , c
973965 ret z ; abort if length == 0
974966_HorizLine_NoClip_NotDegen_StackXY:
975967 ld hl , (iy + 3 ) ; hl = x
@@ -1015,23 +1007,14 @@ smcWord _XMax
10151007smcWord _XSpan
10161008 add hl , de ; add x bounds span
10171009 ret nc ; return if not within x bounds
1018- ld hl , (iy + 9 )
10191010 ld de , (iy + 6 )
1020- add hl , de
1021- push hl
10221011 ld hl , 0
10231012smcWord _YMin
1024- call _Maximum ; get minimum y
1025- ex ( sp ) , hl
1026- ld de , ti.lcdHeight
1027- smcWord _YMax
1028- call _Minimum ; get maximum y
1029- pop de
1030- ld a , l
1031- sub a , e
1032- ret c ; return if not within y bounds
1033- ld b , a
1034- jr _VertLine_NoClip_MaybeDegen_StackX ; jump to unclipped version
1013+ ld bc , ti.lcdHeight
1014+ smcWord _YSpan
1015+ call _ClipInterval
1016+ ld b , c
1017+ jr _VertLine_NoClip_StackX ; jump to unclipped version
10351018
10361019;-------------------------------------------------------------------------------
10371020gfx_VertLine_NoClip:
@@ -1968,8 +1951,8 @@ gfx_FillCircle_NoClip:
19681951 lea hl , ix - 9
19691952 ld sp , hl
19701953 ld bc , (ix + 12 )
1971- sbc hl , hl
1972- adc hl , bc ; carry won't be set since HL is zero here
1954+ ld a , c
1955+ or a , a
19731956 jr z , _FillCircle_NoClip.ResetStack
19741957 ld (ix - 6 ) , bc
19751958 sbc hl , hl
@@ -6647,6 +6630,65 @@ _Minimum:
66476630 add hl , de
66486631 ret
66496632
6633+ ;-------------------------------------------------------------------------------
6634+ _ClipInterval:
6635+ ; Clips an interval represented as start, length
6636+ ; Inputs:
6637+ ; HL : Start of the clip region
6638+ ; DE : Start of the interval to clip
6639+ ; BC : Length of the clip region
6640+ ; (IY+9) : Length of the interval to clip
6641+ ; Carry flag is set
6642+ ; Outputs:
6643+ ; DE : Start of the clipped interval
6644+ ; BC : Size of the clipped interval (less than or equal to input BC)
6645+ ; Returns to the caller's caller if the interval is culled,
6646+ ; but may return an empty interval in edge cases
6647+ ; Reject negative-length intervals
6648+ bit 7 , (iy + 11 )
6649+ jr nz , .cull
6650+ ; Check if the interval starts in the clip region [start, end),
6651+ ; and calculate the length until the end of the clip region
6652+ ; Carry flag is set
6653+ sbc hl , de
6654+ add hl , bc
6655+ inc hl
6656+ jr nc , .clip_start
6657+ ld bc , (iy + 9 )
6658+ .clip_end:
6659+ ; DE : clipped interval start
6660+ ; BC : unclipped interval length
6661+ ; HL : length until the end of the clip region
6662+ ; Return the minimum of the two lengths in BC
6663+ or a , a
6664+ sbc hl , bc
6665+ ret nc
6666+ add hl , bc
6667+ push hl
6668+ pop bc
6669+ ret
6670+
6671+ .clip_start:
6672+ ; Restore the original coordinates and swap them
6673+ ; Carry flag is clear
6674+ sbc hl , bc
6675+ add hl , de
6676+ ex de , hl
6677+ ; Check if the clip region starts inside the interval (start, end],
6678+ ; and calculate the length until the end of the interval
6679+ or a , a
6680+ sbc hl , de
6681+ push bc
6682+ ld bc , (iy + 9 )
6683+ add hl , bc
6684+ pop bc
6685+ jr c , .clip_end
6686+ .cull:
6687+ ; Return to the caller's caller
6688+ pop bc
6689+ ret
6690+
6691+
66506692;-------------------------------------------------------------------------------
66516693_ClipRegion:
66526694; Calculates the new coordinates given the clip and inputs
0 commit comments