Language…
8 users online: cozyduck, Dark Mario Bros, Firstnamebutt, Golden Yoshi, Isikoro, Pink Gold Peach, qantuum,  Ringo - Guests: 240 - Bots: 367
Users: 64,795 (2,377 active)
Latest user: mathew

Abusing the Extra Property Byte

I'm editing a sprite where it's range of speeds vary depending on the Extra Property Byte, making several different sprites that more or less use the same code but behave differently because of the differently referenced tables. I may not be doing it right though, and I'm most certainly overworking it; I'm getting a 'positive branch too long' error with my 'expert handiwork' that you can see here:

Code
	LDA $157C,x
	BEQ Right
	LDA $7FAB28,x
	CMP #$00
	BEQ ATbl1
	LDA $7FAB28,x
	CMP #$01
	BEQ BTbl1
	LDA $7FAB28,x
	CMP #$02
	BEQ CTbl1
	LDA $7FAB28,x
	CMP #$03
	BEQ DTbl1
	LDA $7FAB28,x
	CMP #$04
	BEQ ETbl1
	LDA $7FAB28,x
	CMP #$05
	BEQ FTbl1
	LDA $7FAB28,x
	CMP #$06
	BEQ GTbl1
AfterCmp1:
	EOR #$FF
	INC A
	STA $1626;,y
	LDA $1626;,y
	BRA SetSpeed
Right:
	LDA $7FAB28,x
	CMP #$00
	BEQ ATbl2
	LDA $7FAB28,x
	CMP #$01
	BEQ BTbl2
	LDA $7FAB28,x
	CMP #$02
	BEQ CTbl2
	LDA $7FAB28,x
	CMP #$03
	BEQ DTbl2
	LDA $7FAB28,x
	CMP #$04
	BEQ ETbl2
	LDA $7FAB28,x
	CMP #$05
	BEQ FTbl2
	LDA $7FAB28,x
	CMP #$06
	BEQ GTbl2
SetSpeed:
	STA $B6,x
	LDA $7F998F
	BNE UpdatePos
	BRA Moving

ATbl1:
	LDA Tbl1R,y	
	JMP AfterCmp1

BTbl1:
	LDA Tbl2R,y	
	JMP AfterCmp1

CTbl1:
	LDA Tbl3R,y
	JMP AfterCmp1

DTbl1:
	LDA Tbl4R,y
	JMP AfterCmp1

ETbl1:
	LDA Tbl5R,y
	JMP AfterCmp1

FTbl1:
	LDA Tbl6R,y
	JMP AfterCmp1

GTbl1:
	LDA Tbl7R,y
	JMP AfterCmp1

ATbl2:
	LDA Tbl1R,y	
	JMP SetSpeed

BTbl2:
	LDA Tbl2R,y	
	JMP SetSpeed

CTbl2:
	LDA Tbl3R,y
	JMP SetSpeed

DTbl2:
	LDA Tbl4R,y
	JMP SetSpeed

ETbl2:
	LDA Tbl5R,y
	JMP SetSpeed

FTbl2:
	LDA Tbl6R,y
	JMP SetSpeed

GTbl2:
	LDA Tbl7R,y
	JMP SetSpeed


I haven't really gotten around to editing the other tables yet since I was gonna do that after testing it but these are all the tables nonetheless:

Code
Tbl1R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl2R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl3R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl4R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl5R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl6R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl7R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11


As you can see, it's a complete mess. Knowing how I can check the Extra Property Byte without being so messy (and whether or not I'm even doing it right) would be a godsend to me at this point. I'm a complete and utter noob when it comes to ASM so you might have to explain it in layman's terms. Thanks in advance though.
Yeah that's a mess indeed. Those endless if ... else if ... else if chains don't really look nice, one of those branches must be pointing to a label located more than 127 bytes after it (branching instruction can only target a range of -128/+127 bytes).

Maybe it's that BRA Moving, in that case replacing it with JMP Moving should work around that, since JMP can target any address within a bank.

Anyway, if I'm understanding what you want to do, I can think of a better way of handling that:
- multiply $7FAB28,x by 9, which is the length of each speed table;
- then add Y to the result, which is what you want to index each table by;
- then index Tbl1R (because it points to the start of all tables) by what you got above;
- after that, check if you need the negative value in order to move left;
- finally, update the sprite speed;

Translated into assembly, it would more or less look like this:

Code
	LDA $7FAB28,x
	ASL A	 		;\ multiply that by 9
	ASL A			; | by doing n<<3+n (= n*8+n = n*9) where n is $7FAB28,x
	ASL A			; |
	CLC			; |
	ADC $7FAB28,x		;/
	STY $00			;\ A += Y
	CLC			; | .. or you can just add the RAM address where you got Y from
	ADC $00			;/
	PHX			; preserve X
	TAX
	LDA Tbl1R,x
	PLX			; get X back because we need it
	PHY			; (assuming you want to preserve Y, here it's preserved)
	LDY $157C,x
	BNE .not_right
	EOR #$FF		; A = -A
	INC A			;
	STA $1626		;\ part of your code, maybe you want to index this by X
	;LDA $1526		;/ you don't need to reload A, it's already there
.not_right
	PLY			; (assuming you want to preserve Y, here it's restored)
	STA $B6,x		; update sprite X speed
	LDA $7F998F		;\ part of your code
	BNE UpdatePos		;/
	BRA Moving		; use JMP if you get "positive branch too long" on this line

Tbl1R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl2R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl3R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl4R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl5R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl6R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
Tbl7R:  db $00,$11,$13,$15,$15,$13,$11,$11,$11
A slightly off-topic tip for you, for future reference:
Originally posted by SchwerMuta
Code
LDA $7FAB28,x
CMP #$00
BEQ ATbl1
LDA $7FAB28,x
CMP #$01
BEQ BTbl1
LDA $7FAB28,x
CMP #$02
BEQ CTbl1
...

I'm pretty sure that neither CMP nor BEQ modify the accumulator, so you only need one LDA:
Code
LDA $7FAB28,x
CMP #$00
BEQ ATbl1
CMP #$01
BEQ BTbl1
CMP #$02
BEQ CTbl1
...

This change alone would shrink your original code by 48 bytes, although you'll probably be better off using Lui's code in this case, since it's a lot shorter and more efficient.
GradientToolLevelMusic UtilitySM64 Clean ROM verifierHQX VirtualDub FilterImoSPC2 (Alpha)Music Section SPC PlayerEmbeddable SPC Player for SMWCYouTube EmbedderJSRomcleanJS Address ConverterLazyHDMA
After a little tweaking, I got it to work and it runs very magnificently, and you have my thanks! I just have one little question for my grand adventure into further ASM learning. I was taught that LDA $addr,x means to load that address indexed by the X register. I noticed that when I left out the ,x out of LDA $7FAB28,x then it would load from a slightly different position, but it works as expected with it tacked on. I don't even know what the X register contains at this point as it seems to be out of the scope of the sprite itself. Should I always have it on regardless of what the X register contains? Or are there periods where I should leave it out or pull from the stack before doing something like that?

In sprites, as far as I know, the X register holds the current sprite slot. (That is, when the game is running the code for that sprite). So, by doing that while in a sprite:

Code
LDA $7FAB28,x


You're loading the extra property byte from the current sprite. By doing that (again, while in a sprite):

Code
LDA $7FAB28


You may be loading the extra property byte of some other sprite.