Language…
10 users online: crocodileman94, Faro, Gabriel Yanni, KaidenThelens, khiptune,  Losoall, Lusix, RichardDS90, Squiggs, YouFailMe - Guests: 62 - Bots: 147
Users: 55,661 (2,419 active)
Latest user: valentarising

Sprite Programming [Legacy]

Hmmm, you're right. I used to use $13 myself until someone told me one day to use $14 because sprites will always animate regardless of $9D.
That is a pretty good tutorial. But it still doesn't change the fact that ASM can be ANNOYING to do. Edit: level up.
YOUR layout has been removed.

I do non-kaizo beta tests!
Check my profile for more details.

A Mario and Luigi Story: The Universe's Star Demo 2:
50%
Status: Dead until I regain interest. Link to hack thread.

ASM isn't annoying. The only thing that's annoying is debugging and fixing odd problems.

If it's not annoying for other people, there shouldn't be a valid reason why it should be annoying to you.
Really good tutorial, it has covered so many things I've been wondering!

Just one thing, can you cover how to give different behavoir to sprites "depending on their x position"?


Waluigi needs his own game, he doesn't even have character!
...
Currently working on Waluigi's Treasure Hunt.
Hmm, that should be something good to cover in the tutorial.

There are 16 possible sprite (X) positions on one screen. If you want to check what position it is on, $E4,x will hold it's position on screen.

16 positions can be too much though, you can make 8 possible values (0, 1, 2, 3, 4, 5, 6, 7), 4 possible values (0, 1, 2, 3) and 2 possible values (0, 1) by dividing $E4,x and storing it somewhere. You put this code in the INIT routine:

LDA $E4,x
LSR ; position x8
LSR ; position x4
STA $1594,x ; store somewhere

Now $1594,x can either be 0, 1, 2 or 3 based on it's position. Even though there are 16 positions on screen, it will go like this:

0 1 2 3 4 5 6 7 8 9 A B C D E F | 0 1 2 3 4 5 6 7 8 9 A B C D E F
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 | 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3

$1594,x (or whatever you stored to) will contain these values, and you can branch to different codes and do different stuff based on what the value in that address is.
Originally posted by The Heavenly Muncher
words

I found some inaccurancies in this.
First, $E4,x is $00-$F0 at the start, so you'd need four more LSRs.
Second, you missed the 0s at the position tables. A screen isn't 15 tiles.
The rest seems correct, though.
<blm> zsnes users are the flatearthers of emulation
Just a headsup, you forgot to make a "SlotsFull" label at the "Making A Sprite Spawn A Custom Sprite" lesson.

Speaking of that, it spawn normal sprites, not custom. Coulf you write how to spawn custom sprites to?



Also, your jump rouitine for the boss is broken.
The boss will rise a short distance for one frame and plummet the next.
This works better (I think ^^;):
Code
LDA $1594,x
CMP #$10               ;Number of frames to jump          
BEQ TIME_TO_JUMP
BCC TIME_TO_JUMP
BRA SHARED

RESET:
LDA #$80            ;Number of frames until next jump (minus "Number
                    ;of frames to jump).
STA $1594,x
BRA SHARED

TIME_TO_JUMP:
BEQ RESET
LDA #$C0
STA $AA,x
JSL $01802A
LDA #$01
STA $1DFA

SHARED:
DEC $1594,x         ;This isn't needed if you use a sprite table that
                    ;decreases itself each frame.
RTS

Waluigi needs his own game, he doesn't even have character!
...
Currently working on Waluigi's Treasure Hunt.
Crap.. bplaced.net is down :/ I might have to move everything somewhere else.

Also, maybe I will add a few more things to the tutorial soon.
Yes!!! I've created a moving coin that is worth 10 coins, thanks to this tutorial!
the genorator file I made (the one that this tutor did) will not even insert in spiret tool. In my sprites.txt I put it as below

00 firebar.cfg
01 crab.cfg
02 egg.cfg
03 beezo_carryable.cfg
d2 10 coins to cape.cfg this is the genorator (I just cald it this)

whene I insert the sprites in sprite tool it seys..... couldent open sprite d2 10 coins to cape.cfg

when I open the cgf file in the cfg editor it seys that its not a supported cfg file.

hI put both the 10 coins to cape.asm and cfg file in the genorators folder. HELP!!!


Don't put a space in the .cfg file. I thought I covered that in the tutorial.
I made the actionless blue mushroom, yet when i play the lvel, the screen just goes black. HELP!
Originally posted by SomeGuy
I made the actionless blue mushroom, yet when i play the lvel, the screen just goes black. HELP!

We are incapable of knowing what the problem is unless you post the code.

World Community Grid: Thread | Team
 

dcb "INIT"
RTL

dcb "MAIN"
BRA GET_DRAW_INFo
RTL
;===================================
; GRAPHICS ROUTINE HERE
;===================================

SPR_T1 dcb $0C,$1C
SPR_T2 dcb $01,$02

GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC SPR_T1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA SPR_T2,y ; |
STA $186C,x ; |
ON_SCREEN_Y DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /
LDA $00
STA $0300,y

LDA $01
STA $0301,y

LDA #$24
STA $0302,y

LDA #%00000110
ORA $64
STA $0303,y

INY
INY
INY
INY

LDY #$02 ; This means the tile drawn is 16x16.
LDA #$00 ; The number of tiles I wrote - 1.

JSL $01B7B3

RTS


There is the code
First of all, the code looks kind of scrambled.
When using codes that never, ever has to to changed, you JSR to them.

When you build your code, JSR from the main routine to the sprite code.
Then, at the very begginning of your sprite code, write: "JSR GET_DRAW_INFO", then put that routine last.

It's important that you JSR and not branch in the beginning, otherwhise the code have to end with an RTL, and every return in the graphics routine ends with RTS.
This caused the crash.

I think that this should work:
Code
dcb "INIT"
RTL

dcb "MAIN"
JSR Routine
RTL
;===================================
; GRAPHICS ROUTINE HERE
;===================================

Routine:
JSR GET_DRAW_INFO

LDA $00
STA $0300,y

LDA $01
STA $0301,y

LDA #$24
STA $0302,y

LDA #%00000110
ORA $64
STA $0303,y

INY
INY
INY
INY

LDY #$02 ; This means the tile drawn is 16x16.
LDA #$00 ; The number of tiles I wrote - 1.

JSL $01B7B3

RTS 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; $B760 - graphics routine helper - shared
; sets off screen flags and sets index to OAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


SPR_T1 dcb $0C,$1C
SPR_T2 dcb $01,$02

GET_DRAW_INFO: 
STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X: 
LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /

ON_SCREEN_LOOP: 
LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC SPR_T1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA SPR_T2,y ; |
STA $186C,x ; |
ON_SCREEN_Y: 
DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID: 
PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /




Waluigi needs his own game, he doesn't even have character!
...
Currently working on Waluigi's Treasure Hunt.
Originally posted by deffon1993
dcb "MAIN"
JSR Routine
RTL

Wrong. Change this to this or the tables will break:
Originally posted by deffon1993
dcb "MAIN"
PHB
PHK
PLB
JSR Routine
PLB
RTL

<blm> zsnes users are the flatearthers of emulation
May I ask what use is the ORA $64 in setting YXPPCCCT? Noobish tells me it's simply to set the PP, which can obviously just be done yourself. What use is it? Why? He says it's fine to not use it, so what makes this "easier"?

World Community Grid: Thread | Team
 
Let's play the what did I do wrong game.
dcb "INIT" RTL dcb "MAIN" PHB PHK PLB JSR Routine PLB RTL ;=================================== ; GRAPHICS ROUTINE HERE ;=================================== Routine: JSR GET_DRAW_INFO LDA $00 STA $0300,y LDA $01 STA $0301,y LDA #$24 STA $0302,y LDA #%00000110 ORA $64 STA $0303,y INY INY INY INY LDY #$02 ; This means the tile drawn is 16x16. LDA #$00 ; The number of tiles I wrote - 1. JSL $01B7B3 RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $B760 - graphics routine helper - shared ; sets off screen flags and sets index to OAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SPR_T1 dcb $0C,$1C SPR_T2 dcb $01,$02 GET_DRAW_INFO: STZ $186C,x ; reset sprite offscreen flag, vertical STZ $15A0,x ; reset sprite offscreen flag, horizontal LDA $E4,x ; \ CMP $1A ; | set horizontal offscreen if necessary LDA $14E0,x ; | SBC $1B ; | BEQ ON_SCREEN_X ; | INC $15A0,x ; / ON_SCREEN_X: LDA $14E0,x ; \ XBA ; | LDA $E4,x ; | REP #$20 ; | SEC ; | SBC $1A ; | mark sprite invalid if far enough off screen CLC ; | ADC.W #$0040 ; | CMP.W #$0180 ; | SEP #$20 ; | ROL A ; | AND #$01 ; | STA $15C4,x ; / BNE INVALID ; LDY #$00 ; \ set up loop: LDA $1662,x ; | AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice BEQ ON_SCREEN_LOOP ; | else, go through loop once INY ; / ON_SCREEN_LOOP: LDA $D8,x ; \ CLC ; | set vertical offscreen if necessary ADC SPR_T1,y ; | PHP ; | CMP $1C ; | (vert screen boundry) ROL $00 ; | PLP ; | LDA $14D4,x ; | ADC #$00 ; | LSR $00 ; | SBC $1D ; | BEQ ON_SCREEN_Y ; | LDA $186C,x ; | (vert offscreen) ORA SPR_T2,y ; | STA $186C,x ; | ON_SCREEN_Y: DEY ; | BPL ON_SCREEN_LOOP ; / LDY $15EA,x ; get offset to sprite OAM LDA $E4,x ; \ SEC ; | SBC $1A ; | $00 = sprite x position relative to screen boarder STA $00 ; / LDA $D8,x ; \ SEC ; | SBC $1C ; | $01 = sprite y position relative to screen boarder STA $01 ; / RTS ; return INVALID: PLA ; \ return from *main gfx routine* subroutine... PLA ; | ...(not just this subroutine) RTS ; /

RTS

Originally posted by SomeGuy
Let's play the what did I do wrong game.

*KAWD*
How about placing in line breaks instead of merely setting the color to 1970s-green?


My blue hushroom asm file will not work. when I insert it with sprite tool it seys that it can not open the asm file. Here is the code.
--------------------------
blue mushroom
--------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; sprite initialization JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcb "INIT"
RTL

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main sprite JSL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


dcb "MAIN"
RTL
JSR GRAPHICS ROUTINE HERE
JSR GET_DRAW_INFO




;===================================
; GRAPHICS ROUTINE HERE
;===================================

LDA $00
STA $0300,y

LDA $01
STA $0301,y

LDA #$24
STA $0302,y

LDA #%00000110
ORA $64
STA $0303,y

PHX ;
LDX $15E9
LDA $15F6,x

PLX ;
ORA $64
STA $0303,y

INY
INY
INY
INY

LDY #$02 ;
LDA #$00 ;

JSL $01B7B3

RTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET_DRAW_INFO
; This is a helper for the graphics routine. It sets off screen flags, and sets up
; variables. It will return with the following:
;
; Y = index to sprite OAM ($300)
; $00 = sprite x position relative to screen boarder
; $01 = sprite y position relative to screen boarder
;
; It is adapted from the subroutine at $03B760
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SPR_T1 dcb $0C,$1C
SPR_T2 dcb $01,$02

GET_DRAW_INFO STZ $186C,x ; reset sprite offscreen flag, vertical
STZ $15A0,x ; reset sprite offscreen flag, horizontal
LDA $E4,x ; \
CMP $1A ; | set horizontal offscreen if necessary
LDA $14E0,x ; |
SBC $1B ; |
BEQ ON_SCREEN_X ; |
INC $15A0,x ; /

ON_SCREEN_X LDA $14E0,x ; \
XBA ; |
LDA $E4,x ; |
REP #$20 ; |
SEC ; |
SBC $1A ; | mark sprite invalid if far enough off screen
CLC ; |
ADC.W #$0040 ; |
CMP.W #$0180 ; |
SEP #$20 ; |
ROL A ; |
AND #$01 ; |
STA $15C4,x ; /
BNE INVALID ;

LDY #$00 ; \ set up loop:
LDA $1662,x ; |
AND #$20 ; | if not smushed (1662 & 0x20), go through loop twice
BEQ ON_SCREEN_LOOP ; | else, go through loop once
INY ; /
ON_SCREEN_LOOP LDA $D8,x ; \
CLC ; | set vertical offscreen if necessary
ADC SPR_T1,y ; |
PHP ; |
CMP $1C ; | (vert screen boundry)
ROL $00 ; |
PLP ; |
LDA $14D4,x ; |
ADC #$00 ; |
LSR $00 ; |
SBC $1D ; |
BEQ ON_SCREEN_Y ; |
LDA $186C,x ; | (vert offscreen)
ORA SPR_T2,y ; |
STA $186C,x ; |
ON_SCREEN_Y DEY ; |
BPL ON_SCREEN_LOOP ; /

LDY $15EA,x ; get offset to sprite OAM
LDA $E4,x ; \
SEC ; |
SBC $1A ; | $00 = sprite x position relative to screen boarder
STA $00 ; /
LDA $D8,x ; \
SEC ; |
SBC $1C ; | $01 = sprite y position relative to screen boarder
STA $01 ; /
RTS ; return

INVALID PLA ; \ return from *main gfx routine* subroutine...
PLA ; | ...(not just this subroutine)
RTS ; /

----------------------------------------------------------------------
Can some one cheack over this code because I have no clue what whent wrong.

side note. ice guy the links you posted with your totorial are broken (the site seys that the pages are not avalable) (sigh) please make shure that your links work so i can see what you have done!!!!!

(WYEdit: Got rid of the unnecessary line breaks at the end.)