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? :P


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