Skip to content

Commit df30fcf

Browse files
committed
added clipped gfx_RotatedScaledSprite
1 parent 6c0c574 commit df30fcf

File tree

2 files changed

+305
-65
lines changed

2 files changed

+305
-65
lines changed

src/graphx/graphx.asm

Lines changed: 232 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
include '../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
;-------------------------------------------------------------------------------
149154
LcdSize := ti.lcdWidth*ti.lcdHeight
@@ -4867,35 +4872,67 @@ dv_shr_8_times_width_plus_width := $-3
48674872

48684873
;-------------------------------------------------------------------------------
48694874
gfx_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
;-------------------------------------------------------------------------------
48834903
gfx_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
;-------------------------------------------------------------------------------
51585343
gfx_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

Comments
 (0)