Author Topic: 16x16 sprites?  (Read 4187 times)

0 Members and 1 Guest are viewing this topic.

Offline matthias1992

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 408
  • Rating: +33/-5
    • View Profile
16x16 sprites?
« on: July 03, 2010, 10:43:56 am »
hey there!

I slightly modified the spirte routine from Ti asm in 28 days to support hardware keycode control. The point is if i wanted to display a 16x16 sprite (x,y) then what should I change? I do understand how to make a (8x#) sprite, you just need to modify B for that but how can I make the sprite wider?

Thanks in advance!
Code: [Select]
.nolist
#include "ti83plus.inc"
#define ProgStart $9D95
.list
.org ProgStart - 2
.db t2ByteTok, tAsmCmp
B_CALL(_RunIndicOff)
B_CALL(_GrBufClr)
Show:
    CALL    PutSpr
    B_CALL(_GrBufCpy)
KeyLoop:
LD A, $FD
OUT (1), A
IN A, (1)
CP %10111111
RET Z
LD A, $FE
OUT (1), A
IN A, (1)
CP %11111110
JP Z, MoveDown
CP %11111101
JP Z, MoveLeft
CP %11110111
JP Z, MoveUp
JR      NZ, KeyLoop
; Move sprite right
CALL    PutSpr          ; Erase sprite
LD      HL, xpos
INC     (HL)
JR      Show            ; Draw sprite at new location
MoveLeft:
; Move sprite left
CALL    PutSpr
LD      HL, xpos
DEC     (HL)
JR      Show
MoveUp:
; Move sprite up
CALL    PutSpr
LD      HL, ypos
DEC     (HL)
JR      Show
MoveDown:
CALL    PutSpr
LD      HL, ypos
INC     (HL)
JR      Show
ypos:   .DB     0
xpos:   .DB     0
sprite:
.DB     %10000001
.DB     %11000011
.DB     %01100110
.DB     %00111100
.DB     %00111100
.DB     %01100110
.DB     %11000011
.DB     %10000001
PutSpr:
LD      DE, (ypos)
LD      IX, sprite
LD      B, 8
ClipSprXOR:
; D = xpos
; E = ypos
; B = height
; IX = image address
; Start by doing vertical clipping
    LD     A, %11111111         ; Reset clipping mask
    LD     (clip_mask), A
    LD     A, E                 ; If ypos is negative
    OR     A                    ; try clipping the top
    JP     M, ClipTop           ;
    SUB    64                   ; If ypos is >= 64
    RET    NC                   ; sprite is off-screen
    NEG                         ; If (64 - ypos) > height
    CP     B                    ; don't need to clip
    JR     NC, VertClipDone     ;
    LD     B, A                 ; Do bottom clipping by
    JR     VertClipDone         ; setting height to (64 - ypos)
ClipTop:
    LD     A, B                 ; If ypos <= -height
    NEG                         ; sprite is off-screen
    SUB    E                    ;
    RET    NC                   ;
    PUSH   AF
    ADD    A, B                 ; Get the number of clipped rows
    LD     E, 0                 ; Set ypos to 0 (top of screen)
    LD     B, E                 ; Advance image data pointer
    LD     C, A                 ;
    ADD    IX, BC               ;
    POP    AF
    NEG                         ; Get the number of visible rows
    LD     B, A                 ; and set as height
VertClipDone:
; Now we're doing horizontal clipping
    LD     C, 0                 ; Reset correction factor
    LD     A, D
    CP     -7                   ; If 0 > xpos >= -7
    JR     NC, ClipLeft         ; clip the left side
    CP     96                   ; If xpos >= 96
    RET    NC                   ; sprite is off-screen
    CP     89                   ; If 0 <= xpos < 89
    JR     C, HorizClipDone     ; don't need to clip
ClipRight:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindRightMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindRightMask
    LD     (clip_mask), A
    LD     A, D
    JR     HorizClipDone
ClipLeft:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindLeftMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindLeftMask
    CPL
    LD     (clip_mask), A
    LD     A, D
    ADD    A, 96                ; Set xpos so sprite will "spill over"
    LD     C, 12                ; Set correction
HorizClipDone:
; A = xpos
; E = ypos
; B = height
; IX = image address
; Now we can finally display the sprite.
    LD     H, 0
    LD     D, H
    LD     L, E
    ADD    HL, HL
    ADD    HL, DE
    ADD    HL, HL
    ADD    HL, HL
    LD     E, A
    SRL    E
    SRL    E
    SRL    E
    ADD    HL, DE
    LD     DE, PlotSScreen
    ADD    HL, DE
    LD     D, 0                 ; Correct graph buffer address
    LD     E, C                 ; if clipping the left side
    SBC    HL, DE               ;
    AND    7
    JR     Z, _Aligned
    LD     C, A
    LD     DE, 11
_RowLoop:
    PUSH   BC
    LD     B, C
    LD     A, (clip_mask)       ; Mask out the part of the sprite
    AND    (IX)                 ; to be horizontally clipped
    LD     C, 0
_ShiftLoop:
    SRL    A
    RR     C
    DJNZ   _ShiftLoop
    XOR    (HL)
    LD     (HL), A
    INC    HL
    LD     A, C
    XOR    (HL)
    LD     (HL), A
    ADD    HL, DE
    INC    IX
    POP    BC
    DJNZ   _RowLoop
    RET
_Aligned:
    LD     DE, 12
_PutLoop:
    LD     A, (IX)
    XOR    (HL)
    LD     (HL), A
    INC    IX
    ADD    HL, DE
    DJNZ   _PutLoop
    RET
clip_mask:      .DB     0
.end
.end
« Last Edit: July 03, 2010, 11:29:39 am by matthias1992 »
MASM xxxxxxxxxx aborted | SADce ====:::::: 40% -Halted until further notice| XAOS =====::::: 50% -Units done| SKYBOX2D engine ========== 100% -Pre-alpha done. Need to  document it and extend |

~Those who dream by day are cognizant of much more than those who dream by night only. -Sir Edgar Allen Poe-

Offline matthias1992

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 408
  • Rating: +33/-5
    • View Profile
Re: 16x16 sprites?
« Reply #1 on: July 03, 2010, 12:11:39 pm »
And here is yet another problem, I am trying to make this in a manner that every time + is pressed the next sprite is drawn and every time I press - the previous one is drawn. C is the counter of the sprites and checked if it is z, if it is the program is aborted (becuase you can't do -1 sprite) and if it is >255 9the maximum of 8 bits) it should also be aborted. P.s. I know C is already used elsewere, that is likely to screw it up but i tried to insert a cntr byte by doing:
Code: [Select]
cntr: .db 0but then every time I did this:
Code: [Select]
LD cntr, Cor this
Code: [Select]
LD (cntr), Cit threw a error saying: "unrecognized argument"

This is my source:
Code: [Select]
.nolist
#include "ti83plus.inc"
#define ProgStart $9D95
.list
.org ProgStart - 2
.db t2ByteTok, tAsmCmp
ypos:   .DB     0
xpos:   .DB     0
clip_mask:      .DB     0
B_CALL(_RunIndicOff)
B_CALL(_GrBufClr)
LD C, $0001
PUSH BC
Show:
    CALL    PutSpr
    B_CALL(_GrBufCpy)
KeyLoop:
LD A, $FD
OUT (1), A
IN A, (1)
CP %10111111
RET Z
CP %11111101
JP Z, NextSpr
CP %11111011
JP Z, PrevSpr
LD A, $FE
OUT (1), A
IN A, (1)
CP %11111110
JP Z, MoveDown
CP %11111101
JP Z, MoveLeft
CP %11110111
JP Z, MoveUp
JR      NZ, KeyLoop
; Move sprite right
CALL    PutSpr          ; Erase sprite
LD      HL, xpos
INC     (HL)
JR      Show            ; Draw sprite at new location
MoveLeft:
; Move sprite left
CALL    PutSpr
LD      HL, xpos
DEC     (HL)
JR      Show
MoveUp:
; Move sprite up
CALL    PutSpr
LD      HL, ypos
DEC     (HL)
JR      Show
MoveDown:
CALL    PutSpr
LD      HL, ypos
INC     (HL)
JR      Show
NextSpr:
POP BC
        LD A, C
        OR A
        RET Z
        CP 255
        RET Z
INC C
CALL PutSpr
PrevSpr:
POP BC
        LD A, C
        OR A
        RET Z
        CP 255
        RET Z
DEC C
CALL PutSpr
PutSpr:
PUSH BC
LD      DE, (ypos)
LD A, C
CP 1
LD IX, Spr1
CP 2
LD IX, Spr2
LD      B, 8
ClipSprXOR:
; D = xpos
; E = ypos
; B = height
; IX = image address
; Start by doing vertical clipping
    LD     A, %11111111         ; Reset clipping mask
    LD     (clip_mask), A
    LD     A, E                 ; If ypos is negative
    OR     A                    ; try clipping the top
    JP     M, ClipTop           ;
    SUB    64                   ; If ypos is >= 64
    RET    NC                   ; sprite is off-screen
    NEG                         ; If (64 - ypos) > height
    CP     B                    ; don't need to clip
    JR     NC, VertClipDone     ;
    LD     B, A                 ; Do bottom clipping by
    JR     VertClipDone         ; setting height to (64 - ypos)
ClipTop:
    LD     A, B                 ; If ypos <= -height
    NEG                         ; sprite is off-screen
    SUB    E                    ;
    RET    NC                   ;
    PUSH   AF
    ADD    A, B                 ; Get the number of clipped rows
    LD     E, 0                 ; Set ypos to 0 (top of screen)
    LD     B, E                 ; Advance image data pointer
    LD     C, A                 ;
    ADD    IX, BC               ;
    POP    AF
    NEG                         ; Get the number of visible rows
    LD     B, A                 ; and set as height
VertClipDone:
; Now we're doing horizontal clipping
    LD     C, 0                 ; Reset correction factor
    LD     A, D
    CP     -7                   ; If 0 > xpos >= -7
    JR     NC, ClipLeft         ; clip the left side
    CP     96                   ; If xpos >= 96
    RET    NC                   ; sprite is off-screen
    CP     89                   ; If 0 <= xpos < 89
    JR     C, HorizClipDone     ; don't need to clip
ClipRight:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindRightMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindRightMask
    LD     (clip_mask), A
    LD     A, D
    JR     HorizClipDone
ClipLeft:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindLeftMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindLeftMask
    CPL
    LD     (clip_mask), A
    LD     A, D
    ADD    A, 96                ; Set xpos so sprite will "spill over"
    LD     C, 12                ; Set correction
HorizClipDone:
; A = xpos
; E = ypos
; B = height
; IX = image address
; Now we can finally display the sprite.
    LD     H, 0
    LD     D, H
    LD     L, E
    ADD    HL, HL
    ADD    HL, DE
    ADD    HL, HL
    ADD    HL, HL
    LD     E, A
    SRL    E
    SRL    E
    SRL    E
    ADD    HL, DE
    LD     DE, PlotSScreen
    ADD    HL, DE
    LD     D, 0                 ; Correct graph buffer address
    LD     E, C                 ; if clipping the left side
    SBC    HL, DE               ;
    AND    7
    JR     Z, _Aligned
    LD     C, A
    LD     DE, 11
_RowLoop:
    PUSH   BC
    LD     B, C
    LD     A, (clip_mask)       ; Mask out the part of the sprite
    AND    (IX)                 ; to be horizontally clipped
    LD     C, 0
_ShiftLoop:
    SRL    A
    RR     C
    DJNZ   _ShiftLoop
    XOR    (HL)
    LD     (HL), A
    INC    HL
    LD     A, C
    XOR    (HL)
    LD     (HL), A
    ADD    HL, DE
    INC    IX
    POP    BC
    DJNZ   _RowLoop
    RET
_Aligned:
    LD     DE, 12
_PutLoop:
    LD     A, (IX)
    XOR    (HL)
    LD     (HL), A
    INC    IX
    ADD    HL, DE
    DJNZ   _PutLoop
    RET
Spr1:
.DB     %10000001
.DB     %11000011
.DB     %01100110
.DB     %00111100
.DB     %00111100
.DB     %01100110
.DB     %11000011
.DB     %10000001
Spr2:
.DB     %11111111
.DB     %10000001
.DB     %10000001
.DB     %10000001
.DB     %10000001
.DB     %10000001
.DB     %10000001
    .DB     %11111111
.end
.end
MASM xxxxxxxxxx aborted | SADce ====:::::: 40% -Halted until further notice| XAOS =====::::: 50% -Units done| SKYBOX2D engine ========== 100% -Pre-alpha done. Need to  document it and extend |

~Those who dream by day are cognizant of much more than those who dream by night only. -Sir Edgar Allen Poe-

Offline simplethinker

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 695
  • Rating: +16/-5
  • snjwffl
    • View Profile
Re: 16x16 sprites?
« Reply #2 on: July 03, 2010, 01:17:56 pm »
P.s. I know C is already used elsewere, that is likely to screw it up but i tried to insert a cntr byte by doing:
Code: [Select]
cntr: .db 0but then every time I did this:
Code: [Select]
LD cntr, Cor this
Code: [Select]
LD (cntr), Cit threw a error saying: "unrecognized argument"
The reason that's not working is that the only 8-bit register you can store into/from an immediate address is A.  One way you can get around this is by making "cntr" two bytes instead of one, and then using "ld (cntr), BC".


I also see a few issues with your code, so let's try and tackle them one at a time :)  (The cool thing is that one of them sort of fixes itself and doesn't actually cause a visible problem XD)

- The first is where you put xpos, ypo, and clip_mask.  Although in this case it isn't a problem, under most circumstances it could lead to quite annoying behavior :D
  It's best to put variables like this either at the end of your code or at least somewhere it won't be executed (in the Asm28days example, notice that ypos/xpos/sprite are skipped because of the jr's).  The reason for this is that a db/dw directive will actually insert the numbers into the code.  Even though the programmer knows they just want to use those locations as storage, the processor will still try and execute it as code.  In your case the three consecutive $00's are executed, but since this is the opcode for 'nop' nothing happens.

- The next issue are those "push BC"'s you have.  When you use "call", the address of where to return to is pushed onto the same stack as when you push/pop the 16-bit registers.  This means that when you use "ret", whatever is at the top of the stack is popped and used as the address to return to.  There are a couple places where this will cause a problem:
  1) When running through "KeyLoop", you have BC at the top of the stack so when it gets to the "ret z" it starts executing code starting at the value of BC, which is probably not even part of the program.  You need to be careful when using the stack and make sure there aren't any conflicts with call/ret. 
  2) In PutSpr, the first line is a "push BC" and I don't see any "pop BC"'s before the first ret, so weird things are going to happen there as well.
  I think the best way to fix these problems for your program is to just use some memory location for "cntr" instead of the stack.

I hope this helps ;D  I'm not sure if I got all the bugs, but my computer is being mean to me today so I can't test this on an emulator.
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the Internet, we know this is not true." -- Professor Robert Silensky



Chip's Challenge: ħ%