Page 1 of 1
[New!] Rotate that sprite!
Posted: Thu 24 Nov, 2005 11:11 am
by kv83
===General===
Please do not discuss in this topic. If you feel to discuss an entry, have a question or anything else open a new topic. This topic should only have this starting post, the entries and the result. All other posts will deleted. If you have question or want to discuss the entries, go
to this thread.
===Description===
We have a sprite which has fixed width and height of 8x8 pixels. The sprite is not compressed or whatever. A sample sprite (of my Indy project) is below:
Code: Select all
Sprite:
.db 00011000
.db 00111100
.db 00011000
.db 00100100
.db 00111100
.db 00011000
.db 00100100
.db 00100100
Your routine should be able to rotate that sprite 90° Clockwise or 90° Not-clockwise. So your routine should accept two inputs; A (16-bit) sprite pointer and a flag or variable how to rotate the sprite. Whether you store the sprite in the same space as it was in, create a temp. storage in saferam or plot it direct onto screen (with additional variables for x and y) is up to you. As example, when rotating the sample sprite 90° Clockwise the sprite should be like this:
Code: Select all
.db 00000000
.db 00000000
.db 11011010
.db 00110111
.db 00110111
.db 11011010
.db 00000000
.db 00000000
===Conditions===
Your routine should meet the following conditions:
- The routine may only use a, bc, de, hl, ix and the array given. It may also use optional an additional array (whether in the prog self or the saferam3) to store the new sprite. The stack may be used aswell.
- SMC is allowed.
- The routine should be well documented.
- You should state how much size your routine needs.
- The routine should be in z80 for the TI-83(+) series.
===Deadline===
You have 4 weeks time. Until 22th of December.
===How to particpate?===
Just post your source in here if you are finished. A sample program and/or screenshot is welcome but not required. If you update your routine, you have to edit your post, instead of posting it again. The smallest routine wins (or someone comes up with a fair system to judge both).
===Current list===
CoBB: 20 bytes
tr1p1ea: 21 bytes
Jim E: 26 bytes
===Winner ===
===Change log===
Posted: Thu 24 Nov, 2005 11:56 am
by CoBB
First try:
Code: Select all
; Rotate: rotates an 8x8 sprite
; Input: DE - pointer to right after the last byte of the sprite
; HL - pointer to an 8-byte temporary buffer
; IXL - number of clockwise turns to perform
; Output: the sprite is rotated in its place and
; a copy of the result stays in the buffer
; provided as well
; Size: 28 bytes
Rotate:
ld c,8
R_loop:
dec de
ld a,(de)
push hl
ld b,8
R_inloop:
rla
rl (hl)
inc hl
djnz R_inloop
pop hl
dec c
jr nz,R_loop
ld c,8
push hl
ldir
pop hl
dec ixl
jr nz,Rotate
ret
Second try:
Code: Select all
; Rotate: rotates an 8x8 sprite
; Input: DE - pointer to the sprite
; HL - pointer to an 8-byte destination buffer
; IX - R_cw for clockwise, R_acw for anti-clockwise
; Output: the rotated sprite in the destination buffer
; Size: 25 bytes
Rotate:
ld c,8
R_loop:
ld a,(de)
inc de
push hl
ld b,8
R_inloop:
jp (ix)
R_cw:
rra
rr (hl)
jr R_skip
R_acw:
rla
rl (hl)
R_skip:
inc hl
djnz R_inloop
pop hl
dec c
jr nz,R_loop
ret
Third try (combining the second one with tr1p1ea's solution):
Code: Select all
; Rotate: rotates an 8x8 sprite
; Input: DE - pointer to the sprite
; H - high byte of the destination buffer
; IX - R_cw for clockwise, R_acw for anti-clockwise
; B - number of rows to rotate (8)
; Output: the rotated sprite at H*256+1
; Size: 20 bytes
Rotate:
ld a,(de)
inc de
ld l,8
R_inloop:
jp (ix)
R_cw:
rra
rr (hl)
jr R_skip
R_acw:
rla
rl (hl)
R_skip:
dec l
jr nz,R_inloop
djnz Rotate
ret
Posted: Thu 24 Nov, 2005 4:15 pm
by Jim e
I technically haven't tested this but I think my math is right.
1st TRY:
Code: Select all
:--------------------------------------------
;Rotate tile by James Montelongo
;input:
;DE = 8x8 tile
;HL = 8 bytes buffer
;A = $17 equals Clockwise
; $1F equals Counter Clockwise
;
;Output:
; Rotates a tile 90° left or right into a buffer
;
;Size: 26 Bytes
:Tstates: ~2900
rotate:
ld (rotloop),a
xor $09
ld (rotloop+2),a
ld c,8
rotbigloop:
ld a,(de)
inc de
push hl
ld b,8
rotloop:
rra
rl (hl)
inc hl
djnz rotloop
pop hl
dec c
jr nz,rotbigloop
ret
2nd TRY:
Code: Select all
:--------------------------------------------
;Rotate tile by James Montelongo
;input:
;DE = 8xB tile
;HL = 10 byte buffer(page aligned)
;B = Height
;IX = $1F1E equals Clockwise
; $1716 equals Counter Clockwise
;
;Output:
; Rotates a tile 90° left or right at H*256+1
; ie If buffer is at $8000 the tile is rotated
; in $8001.
;
;Size: 17 Bytes
Rotate:
ld (R_inloop+1),ix
rotateloop:
ld a,(de)
inc de
ld l,9
R_inloop:
rl (hl)
rla
dec l
jr nz,R_inloop
djnz rotateloop
ret
Why do i get this feeling CoBB will swoop in with a 16 byte routine?
Pseudo cheating:(not quite cause it doesn't TRULY save mem.)
Code: Select all
:--------------------------------------------
;Rotate tile by James Montelongo
;input:
;DE = 8xB tile
;HL = 10 byte buffer(page aligned)
;B = Height
;C = 9
;IX = $1F1E equals Clockwise
; $1716 equals Counter Clockwise
;
;Output:
; Rotates a tile 90° left or right at H*256+1
; ie If buffer is at $8000 the tile is rotated
; in $8001.
;
;Size: 16 Bytes
Rotate:
ld (R_inloop+1),ix
rotateloop:
ld a,(de)
inc de
ld l,c
R_inloop:
rl (hl)
rla
dec l
jr nz,R_inloop
djnz rotateloop
ret
Posted: Thu 24 Nov, 2005 5:52 pm
by tr1p1ea
1st try (updated):
Code: Select all
;--------------------------------------------------
; RotateSprite by tr1p1ea - 20 bytes
;--------------------------------------------------
; Rotates an 8x8 sprite
;
; Input: de = SpriteData
; hl = TempBuffer (page aligned)
; b = # of rows to rotate (usually 8)
; a = Direction to rotate. CW = $17, CCW = $1F
;
; Output: TempBuffer = rotated sprite
;
; Remarks: TempBuffer must be page aligned.
; For example equate it to $8B00
;
RotateSprite:
ld (RotateSprite_Loop2),a
dec a
ld (RotateSprite_Loop2 + 2),a
RotateSprite_Loop1:
ld a,(de)
inc de
ld l,8
RotateSprite_Loop2:
rla
rr (hl)
dec l
jr nz,RotateSprite_Loop2
djnz RotateSprite_Loop1
ret
2nd try:
Code: Select all
;--------------------------------------------------
; RotateSprite by tr1p1ea - 19 bytes
;--------------------------------------------------
; Rotates an 8x8 sprite
;
; Input: de = SpriteData (page aligned) - 1
; hl = TempBuffer (page aligned)
; c = # of 90 deg turns clockwise
;
; Output: de + 1 = rotated sprite
;
; Remarks: SpriteData and TempBuffer must be
; page aligned. For example equate
; to $8700 and $8800
;
RotateSprite:
ld b,8
RotateSprite_Loop1:
inc de
ld a,(de)
ld l,8
RotateSprite_Loop2:
rra
rr (hl)
dec l
jr nz,RotateSprite_Loop2
djnz RotateSprite_Loop1
ex de,hl
dec c
jr nz,RotateSprite
ret
3rd try *Exploitatively deleted*
Posted: Sun 27 Nov, 2005 6:35 am
by Dwedit
My crappy first attempt: 28 bytes, output buffer must be pre-cleared
Only rotates clockwise
This could be easily modified to XOR draw over the output buffer
Code: Select all
rotate:
;ix = input
;hl = output
ld de,-8
ld bc,$0101
loop1:
ld a,(ix)
and c
jr z,noplot
ld a,(hl)
or b
ld (hl),a
noplot:
inc hl
rlc c
jr nc,loop1
add hl,de
inc ix
rlc b
jr nc,loop1
ret
Small modification to bring the size down to 23 bytes:
(still doesn't rotate counterclockwise)
Code: Select all
rotate:
;de = input
;hl = output
ld bc,$0101
loop0:
push hl
loop1:
ld a,(de)
and c
jr z,noplot
ld a,(hl)
or b
ld (hl),a
noplot:
inc hl
rlc c
jr nc,loop1
pop hl
inc de
rlc b
jr nc,loop0
ret
Posted: Sun 27 Nov, 2005 7:00 am
by h4x0r
This is ridiculous code of course, as are the other entries. Since the inputs are not specified, the cost to fill the required input registers should also be counted (i.e. the cost for mine is 11 bytes). Then people might be motivated to write compact code rather than try to bend the rules. B=8 for example is not a valid thing to have as a parameter, but I have assumed it is okay for the contest as the entry currently listed as winning uses it.
Code: Select all
;==================================================
; ROTATE BY H4X0R - 17 BYTES
;==================================================
; ROTATES AN 8X8 SPRITE CLOCKWISE OR, AS THEY SAY,
; "NOT CLOCKWISE"
;
; INPUTS:
; DE -> SPRITE
; HL -> 8 BYTES TEMP AT $xx01 (L need not be set)
; B = NUMBER OF ROWS TO ROTATE (I.E. 8)
; IX = $0F1E (CW) OR $0716 (CCW)
;
; OUTPUTS:
; ROTATED SPRITE AT THE INPUT $xx01
ROTATE:
LD (ROTATE_SELFMOD + 1),IX
ROTATELOOP:
LD A,(DE)
INC DE
LD L,9
ROTATE_SELFMOD:
SET 7,C
SRA L
JR NZ,ROTATE_SELFMOD
DJNZ ROTATELOOP
RET
Posted: Wed 07 Dec, 2005 5:49 am
by Spencer
Code: Select all
;Spencer's Crazy In Place Rotate
;I always go left, suckers!
;30 bytes
;35 bytes with user
;========================
;a - $23 for ccw (inc hl)
; - $2B for cw (dec hl)
;hl - data for ccw
;hl - data+7 for cw
;========================
rotate_sprite8:
ld (hax1),a
ld (hax2),a
ld c,8
_ol_sprite8:
ld b,8
ld d,h
ld e,l
_il_sprite8:
rl (hl)
hax1:
inc hl
rla
djnz _il_sprite8
push af
ex de,hl
dec c
jr nz,_ol_sprite8
ld b,8
_rebuild_loop:
pop af
ld (hl),a
hax2:
inc hl
djnz _rebuild_loop
ret
Take 2:
Code: Select all
;==========================================
;Spencer's Not-so-crazy Rotater.
;32 bytes with user input.
;It's not like Jim E's
;==========================================
;hl - data [data+7]
;de - buffer+7 [buffer]
;a - $23
; [- $2B]
;Use backeted inputs for cw, non-bracketed
;for ccw. Must have a sizable buffer, as it
;overrotates 48 bytes.
;==========================================
rotate_sprite8:
ld (_hax1),a
ld b,$38
xor b
ld (_hax2),a
ld c,l
_ol_sprite8:
ld a,1
ld l,c
_il_sprite8:
rl (hl)
rla
_hax1:
inc hl
jr nc,_il_sprite8
ld (de),a
_hax2:
dec de
djnz _ol_sprite8
ret