22include '../include/library.inc'
33;-------------------------------------------------------------------------------
44
5- library GRAPHX , 12
5+ library GRAPHX , 13
66
77;-------------------------------------------------------------------------------
88; no dependencies
@@ -144,6 +144,11 @@ library GRAPHX, 12
144144 export gfx_Ellipse_NoClip
145145 export gfx_FillEllipse
146146 export gfx_FillEllipse_NoClip
147+ ;-------------------------------------------------------------------------------
148+ ; v13 functions
149+ ;-------------------------------------------------------------------------------
150+ export gfx_RotatedScaledTransparentSprite
151+ export gfx_RotatedScaledSprite
147152
148153;-------------------------------------------------------------------------------
149154LcdSize := ti.lcdWidth * ti.lcdHeight
@@ -4867,35 +4872,67 @@ dv_shr_8_times_width_plus_width := $-3
48674872
48684873;-------------------------------------------------------------------------------
48694874gfx_RotatedScaledSprite_NoClip:
4870- ; Rotate and scale an image drawn directly to the screen buffer
4875+ ; Rotate and scale an unclipped sprite drawn directly to the screen buffer
48714876; Arguments:
4872- ; arg0 : Pointer to sprite struct input
4873- ; arg1 : Pointer to sprite struct output
4874- ; arg2 : Rotation angle as an integer
4875- ; arg3 : Scale factor (64 = 100%)
4877+ ; arg0 : Pointer to sprite
4878+ ; arg1 : X coordinate
4879+ ; arg2 : Y coordinate
4880+ ; arg3 : Rotation angle as an integer
4881+ ; arg4 : Scale factor (64 = 100%)
48764882; Returns:
4877- ; arg1 : Pointer to sprite struct output
4878- ld a , - 1 + _RotatedScaledSprite_NoClip.inner_opaque - _RotatedScaledSprite_NoClip.dsrs_jump_1
4883+ ; The size of the sprite after scaling
4884+ ld h , $ 21 ; ld hl, *
4885+ db $ FD ; ld h, * --> ld iyh, *
4886+ ;-------------------------------------------------------------------------------
4887+ gfx_RotatedScaledSprite:
4888+ ; Rotate and scale a clipped sprite drawn directly to the screen buffer
4889+ ; Arguments:
4890+ ; arg0 : Pointer to sprite
4891+ ; arg1 : X coordinate
4892+ ; arg2 : Y coordinate
4893+ ; arg3 : Rotation angle as an integer
4894+ ; arg4 : Scale factor (64 = 100%)
4895+ ; Returns:
4896+ ; The unclipped size of the sprite after scaling
4897+ ld h , $ CD ; call *
4898+ ld a , - 1 + _RSS_NC.inner_opaque - _RSS_NC.dsrs_jump_1
48794899 ; jr .inner_opaque_hijack \ inc l
4880- ld bc , ( $ 2C0018) or ((( - 1 + _RotatedScaledSprite_NoClip .inner_opaque_hijack - _RotatedScaledSprite_NoClip .dsrs_jump_2) and $ FF) shl 8 )
4881- jr _RotatedScaledSprite_NoClip
4900+ ld bc , ( $ 2C0018) or ((( - 1 + _RSS_NC .inner_opaque_hijack - _RSS_NC .dsrs_jump_2) and $ FF) shl 8 )
4901+ jr _RotatedScaledSprite
48824902;-------------------------------------------------------------------------------
48834903gfx_RotatedScaledTransparentSprite_NoClip:
4884- ; Rotate and scale an image drawn directly to the screen buffer
4904+ ; Rotate and scale an unclipped transparent sprite drawn directly to the screen buffer
48854905; Arguments:
4886- ; arg0 : Pointer to sprite struct input
4887- ; arg1 : Pointer to sprite struct output
4888- ; arg2 : Rotation angle as an integer
4889- ; arg3 : Scale factor (64 = 100%)
4906+ ; arg0 : Pointer to sprite
4907+ ; arg1 : X coordinate
4908+ ; arg2 : Y coordinate
4909+ ; arg3 : Rotation angle as an integer
4910+ ; arg4 : Scale factor (64 = 100%)
48904911; Returns:
4891- ; arg1 : Pointer to sprite struct output
4892- ld a , - 1 + _RotatedScaledSprite_NoClip.inner_transparent - _RotatedScaledSprite_NoClip.dsrs_jump_1
4912+ ; The size of the sprite after scaling
4913+ ld h , $ 21 ; ld hl, *
4914+ db $ FD ; ld h, * --> ld iyh, *
4915+ ;-------------------------------------------------------------------------------
4916+ gfx_RotatedScaledTransparentSprite:
4917+ ; Rotate and scale a clipped transparent sprite drawn directly to the screen buffer
4918+ ; Arguments:
4919+ ; arg0 : Pointer to sprite
4920+ ; arg1 : X coordinate
4921+ ; arg2 : Y coordinate
4922+ ; arg3 : Rotation angle as an integer
4923+ ; arg4 : Scale factor (64 = 100%)
4924+ ; Returns:
4925+ ; The unclipped size of the sprite after scaling
4926+ ld h , $ CD ; call *
4927+ ld a , - 1 + _RSS_NC.inner_transparent - _RSS_NC.dsrs_jump_1
48934928 ; push hl \ ld l, a \ inc l
48944929 ld bc , $ 2C6FE5
4895- _RotatedScaledSprite_NoClip:
4930+ _RotatedScaledSprite:
4931+ _RSS_NC:
48964932 ld iy , .dsrs_base_address
4897- ld (iy + (_RotatedScaledSprite_NoClip.dsrs_jump_1 - .dsrs_base_address)) , a
4898- ld (iy + (_RotatedScaledSprite_NoClip.dsrs_jump_2 - .dsrs_base_address - 1 )) , bc
4933+ ld (iy + (.dsrs_jump_1 - .dsrs_base_address)) , a
4934+ ld (iy + (.dsrs_jump_2 - .dsrs_base_address - 1 )) , bc
4935+ ld (iy + (.dsrs_clip_call - .dsrs_base_address)) , h
48994936 push ix
49004937 ; aligning ix with gfx_RotateScaleSprite allows for code sharing
49014938 ld ix , 3
@@ -4971,45 +5008,36 @@ _RotatedScaledSprite_NoClip:
49715008 jr nz , .hax
49725009 inc a ; hax for scale = 1?
49735010.hax:
4974- ld (iy + (.dsrs_size_1 - .dsrs_base_address)) , a ; write smc
5011+ ld b , a ; render height
5012+ ld c , a ; render width
5013+
5014+ ; changes from call * to ld hl, *
5015+ .dsrs_clip_call := $ + 0
5016+ call _RotatedScaled_ClipAdjust
5017+
5018+ ld (iy + (.dsrs_size_1 - .dsrs_base_address)) , c ; write smc
49755019
49765020 or a , a
49775021 sbc hl , hl
4978- ld l , a
5022+ ld l , c
49795023 ld de , ti.lcdWidth
49805024 ex de , hl
49815025 sbc hl , de
49825026 ld (iy + (.line_add - .dsrs_base_address)) , hl
49835027
4984- ld c , a
4985-
49865028 ; calculate y-loop offset for IX
49875029 ld hl , (iy + (.dsrs_cosf_0A - .dsrs_base_address))
4988- ; DE = HL * C
4989- ld e , l
4990- ld d , c
4991- ld l , d
4992- mlt hl
4993- mlt de
4994- ld a , d
4995- add a , l
4996- ld d , a
5030+ ; DE = HL * C(width)
5031+ call _set_DE_to_HL_mul_C
49975032 ld hl , (iy + (.dsrs_sinf_1_plus_offset_ix - .dsrs_base_address))
49985033 or a , a
4999- sbc hl , de
5034+ sbc.s hl , de ; make sure UHL is zero
50005035 ld (iy + (.dsrs_sinf_1_plus_offset_ix - .dsrs_base_address)) , hl
50015036
50025037 ; calculate y-loop offset for HL
50035038 ld hl , (iy + (.dsrs_sinf_0A - .dsrs_base_address))
5004- ; DE = HL * C
5005- ld e , l
5006- ld d , c
5007- ld l , d
5008- mlt hl
5009- mlt de
5010- ld a , d
5011- add a , l
5012- ld d , a
5039+ ; DE = HL * C(width)
5040+ call _set_DE_to_HL_mul_C
50135041 ld hl , (iy + (.dsrs_cosf_0A - .dsrs_base_address))
50145042 or a , a
50155043 sbc hl , de
@@ -5033,14 +5061,15 @@ _RotatedScaledSprite_NoClip:
50335061 ld ixh , c ; store return value
50345062 ex ( sp ) , ix ; smc = dxs start
50355063
5036- ld iyh , c ; size * scale / 64
5064+ ld iyh , b ; size * scale / 64
50375065
50385066 ld bc , 0 ; xs = (dxs + dyc) + (size * 128)
50395067.dsrs_size128_0_plus_dyc_0 := $ - 3
50405068 add ix , bc ; de = (dxs + dyc) + (size * 128)
50415069
50425070 ld bc , 0 ; ys = (dxc - dys) + (size * 128)
50435071.dsrs_size128_1_minus_dys_0 := $ - 3
5072+ .dsrs_base_address := .dsrs_size128_1_minus_dys_0
50445073 add hl , bc ; hl = (dxc - dys) + (size * 128)
50455074
50465075 call gfx_Wait
@@ -5087,7 +5116,6 @@ _RotatedScaledSprite_NoClip:
50875116 ; restore and increment dxc
50885117 ld bc , 0 ; smc = cosf
50895118.dsrs_cosf_1_plus_offset_hl := $ - 3
5090- .dsrs_base_address := .dsrs_cosf_1_plus_offset_hl
50915119 add hl , bc ; dxc += cosf
50925120
50935121 ; restore and increment dxs
@@ -5154,6 +5182,163 @@ smcByte _TransparentColor
51545182 pop ix
51555183 ret
51565184
5185+ ;-------------------------------------------------------------------------------
5186+ _rss_not_culled:
5187+ ; offscreen
5188+ ld a , iyl ; sprite out size (iyl/width should remain untouched)
5189+ lea hl , ix - 3
5190+ ld sp , hl
5191+ pop ix
5192+ ret
5193+ _RotatedScaled_ClipAdjust:
5194+ ; modified version of _ClipCoordinates
5195+ push iy
5196+ ld iyh , b ; height
5197+ ld iyl , c ; width
5198+ xor a , a
5199+ ld (ix + 13 ) , a ; width that was clipped
5200+ ld (ix + 14 ) , a ; height that was clipped
5201+ ; Clipping stuff
5202+ ; Arguments:
5203+ ; arg0 : Pointer to sprite structure
5204+ ; arg1 : X coordinate
5205+ ; arg2 : Y coordinate
5206+ ; Returns:
5207+ ; IYH: New sprite height
5208+ ; IYL: New sprite width
5209+ ; NC : If offscreen
5210+ ld bc , 0
5211+ smcWord _YMin
5212+ ld hl , (ix + 9 ) ; hl = y coordinate
5213+ sbc hl , bc
5214+ ex de , hl ; de = y coordinate relative to min y
5215+ ld a , ti.lcdHeight ; a = clip_height
5216+ smcByte _YSpan
5217+ ld c , iyh ; bc = height
5218+ sub a , c ; get difference between clip_height and height
5219+ sbc hl , hl
5220+ ld l , a
5221+ dec c ; bc = height - 1
5222+ jr nc , .nottaller
5223+ xor a , a
5224+ sbc hl , de ; is partially clipped both top and bottom?
5225+ jr nc , .yclip
5226+ sub a , e ; a = negated relative y
5227+ add hl , de ; use clip_height as the draw height, and clip top
5228+ jr .cliptop
5229+ .nottaller:
5230+ xor a , a
5231+ sbc hl , de ; is fully onscreen vertically?
5232+ jr nc , .yclipped
5233+ .yclip:
5234+ add hl , bc ; is partially clipped bottom?
5235+ ex de , hl ; e = new height - 1, hl = relative y
5236+ jr c , .clipbottom
5237+ sub a , l ; a = negated relative y
5238+ .cliptop:
5239+ add hl , bc ; is partially clipped top?
5240+ jr nc , _rss_not_culled
5241+ ex de , hl ; e = new height - 1
5242+ ld (ix + 14 ) , a ; store height that was clipped
5243+ ld (ix + 9 ) , 0 ; save min y coordinate
5244+ smcByte _YMin
5245+ .clipbottom:
5246+ inc e
5247+ ld iyh , e ; save new height
5248+ or a , a
5249+ .yclipped: ; <-- carry already cleared on this path
5250+ ld bc , 0
5251+ smcWord _XMin
5252+ ld hl , (ix + 9 ) ; hl = x coordinate
5253+ sbc hl , bc
5254+ ex de , hl ; de = x coordinate relative to min x
5255+ ld hl , ti.lcdWidth ; hl = clip_width
5256+ smcWord _XSpan
5257+ xor a , a
5258+ ld b , a
5259+ ld c , iyl ; bc = width
5260+ sbc hl , bc ; get difference between clip_width and width
5261+ dec c ; bc = width - 1
5262+ jr nc , .notwider
5263+ or a , a
5264+ sbc hl , de ; is partially clipped both left and right?
5265+ jr nc , .xclip
5266+ sub a , e ; a = negated relative x
5267+ add hl , de ; use clip_width as the draw width, and clip left
5268+ jr .clipleft
5269+ .notwider:
5270+ sbc hl , de ; is fully onscreen horizontally?
5271+ jr nc , .xclipped ; a = 0 for bytes to add per iteration
5272+ .xclip:
5273+ add hl , bc ; is partially clipped right?
5274+ ex de , hl ; e = new width - 1, hl = relative x
5275+ jr c , .clipright
5276+ sub a , l ; a = negated relative x
5277+ .clipleft:
5278+ add hl , bc ; is partially clipped left?
5279+ jr nc , _rss_not_culled ; return if offscreen
5280+ ld (ix + 13 ) , a ; store width that was clipped
5281+ ex de , hl ; e = new width - 1
5282+ ld hl , 0
5283+ smcWord _XMin
5284+ ld (ix + 6 ) , hl ; save min x coordinate
5285+ .clipright:
5286+ inc e
5287+ ld iyl , e ; save new width
5288+ .xclipped:
5289+ ; width and height are on the stack
5290+ ex ( sp ) , iy
5291+
5292+ ld bc , (ix + 13 )
5293+
5294+ ; Starting IX offset X
5295+ ld hl , (iy + (_RSS_NC.dsrs_cosf_0A - _RSS_NC.dsrs_base_address))
5296+ ; DE = HL * C(width)
5297+ call _set_DE_to_HL_mul_C
5298+ ld hl , (iy + (_RSS_NC.dsrs_size128_0_plus_dyc_0 - _RSS_NC.dsrs_base_address))
5299+ add hl , de
5300+ push hl
5301+
5302+ ; Starting HL offset X
5303+ ld hl , (iy + (_RSS_NC.dsrs_sinf_0A - _RSS_NC.dsrs_base_address))
5304+ ; DE = HL * C(width)
5305+ call _set_DE_to_HL_mul_C
5306+ ld hl , (iy + (_RSS_NC.dsrs_size128_1_minus_dys_0 - _RSS_NC.dsrs_base_address))
5307+ add hl , de
5308+ push hl
5309+
5310+ ld c , b
5311+
5312+ ; Starting HL offset Y
5313+ ld hl , (iy + (_RSS_NC.dsrs_cosf_0A - _RSS_NC.dsrs_base_address))
5314+ ; DE = HL * B(height)
5315+ call _set_DE_to_HL_mul_C
5316+ pop hl
5317+ add .s hl , de ; make sure UHL is zero
5318+ ld (iy + (_RSS_NC.dsrs_size128_1_minus_dys_0 - _RSS_NC.dsrs_base_address)) , hl
5319+
5320+ ; Starting IX offset Y
5321+ ld hl , (iy + (_RSS_NC.dsrs_sinf_1_plus_offset_ix - _RSS_NC.dsrs_base_address))
5322+ ; DE = HL * B(height)
5323+ call _set_DE_to_HL_mul_C
5324+ pop hl
5325+ add hl , de
5326+ ld (iy + (_RSS_NC.dsrs_size128_0_plus_dyc_0 - _RSS_NC.dsrs_base_address)) , hl
5327+
5328+ pop bc ; B = height, C = width
5329+ ret
5330+
5331+ _set_DE_to_HL_mul_C:
5332+ ld d , c
5333+ ld e , l
5334+ ld l , d
5335+ mlt hl
5336+ mlt de
5337+ ld a , d
5338+ add a , l
5339+ ld d , a
5340+ ret
5341+
51575342;-------------------------------------------------------------------------------
51585343gfx_RotateScaleSprite:
51595344; Rotate and scale an image using an output buffer
@@ -5245,14 +5430,7 @@ gfx_RotateScaleSprite:
52455430 ; calculate y-loop offset for IX
52465431 ld hl , (iy + (_smc_dsrs_cosf_0A - _smc_dsrs_base_address))
52475432 ; DE = HL * C
5248- ld e , l
5249- ld d , c
5250- ld l , d
5251- mlt hl
5252- mlt de
5253- ld a , d
5254- add a , l
5255- ld d , a
5433+ call _set_DE_to_HL_mul_C
52565434 ld hl , (ix - 3 ) ; _smc_dsrs_sinf_1_plus_offset_ix
52575435 or a , a
52585436 sbc.s hl , de ; make sure UHL is zero
@@ -5261,14 +5439,7 @@ gfx_RotateScaleSprite:
52615439 ; calculate y-loop offset for HL
52625440 ld hl , (iy + (_smc_dsrs_sinf_0A - _smc_dsrs_base_address))
52635441 ; DE = HL * C
5264- ld e , l
5265- ld d , c
5266- ld l , d
5267- mlt hl
5268- mlt de
5269- ld a , d
5270- add a , l
5271- ld d , a
5442+ call _set_DE_to_HL_mul_C
52725443 ld hl , (iy + (_smc_dsrs_cosf_0A - _smc_dsrs_base_address))
52735444 or a , a
52745445 sbc hl , de
0 commit comments