[New!] Rotate that sprite!

Moderator: MaxCoderz Staff

Locked
User avatar
kv83
Maxcoderz Staff
Posts: 2735
Joined: Wed 15 Dec, 2004 7:26 pm
Location: The Hague, Netherlands
Contact:

[New!] Rotate that sprite!

Post 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===
Last edited by kv83 on Fri 25 Nov, 2005 8:59 am, edited 2 times in total.
Image
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post 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
Last edited by CoBB on Fri 25 Nov, 2005 2:30 pm, edited 3 times in total.
User avatar
Jim e
Calc King
Posts: 2457
Joined: Sun 26 Dec, 2004 5:27 am
Location: SXIOPO = Infinite lives for both players
Contact:

Post 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
Last edited by Jim e on Fri 25 Nov, 2005 9:56 pm, edited 5 times in total.
Image
User avatar
tr1p1ea
Maxcoderz Staff
Posts: 4141
Joined: Thu 16 Dec, 2004 10:06 pm
Location: I cant seem to get out of this cryogenic chamber!
Contact:

Post 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*
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image
User avatar
Dwedit
Maxcoderz Staff
Posts: 579
Joined: Wed 15 Dec, 2004 6:06 am
Location: Chicago!
Contact:

Post 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
Last edited by Dwedit on Sun 27 Nov, 2005 7:01 am, edited 1 time in total.
You know your hexadecimal output routine is broken when it displays the character 'G'.
h4x0r
New Member
Posts: 1
Joined: Sun 27 Nov, 2005 6:47 am

Post 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
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post 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
Locked