16bit table indexing problem

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: 16bit table indexing problem

Post by koitsu »

Re: concerns over ldy #$00:

It's being assembled correctly, or was at the time of that post. You can clearly see the results being $A0 00 00 which is correct (16-bit load of $0000 into Y).

Once again (is this the 5th or 6th time? I've lost track) we're back at the need for generated assembly listings and why using an assembler that generates ones properly is important, especially when learning.

Furthermore, and I don't know why this isn't being discussed: forcing the size using .w does not guarantee that the code will function correctly. For example, telling someone to "just use .w" is just as error-prone (if not more so!) than letting the assembler make its own educated guess. For example, take this code (and I'll include the machine language for it because it's important here):

Code: Select all

E2 20     sep #$20
          ;
          ; Programmer does something else here, using 8-bit accumulator, and forgets that it's 8-bit.
          ; Programmer has been taught "to use .w when referring to 16-bit values or addresses"
          ;
A9 00 00  lda.w #$0000
8D 28 EA  sta.w $ea28
But during run-time, this code gets executed as the following:

Code: Select all

E2 20     sep #$20
A9 00     lda #$00
00 8D     brk $8d
28        plp
EA        nop
I don't think WLA DX is going to dynamically change the size of the operands ($00 vs. $00 00) if you do lda #$00 vs. lda #$0000 or even lda #0 (that's a good example of an ambiguous one) -- that's what using .b/w is for -- instead it (very likely) keys off of what the accumulator size is per SEP/REP. I'd check, but there's no way in hell I'm going to bother trying to use assembly listings in WLA DX after what I've experienced this past week.

TL;DR -- Listings generated by the assembler: important. Programmer understanding what their code does, and understanding the processor: equally as important. Forcing sizes using .b/w/l can result in bad learned behaviour. In other words: aren't sure if your code is generated correctly? Look at the listing. Aren't sure if it's executing correctly? Use a debugger. (And for those wondering how we used to debug code on the SNES during the early 90s when there was no such thing as an emulator -- we stared at our code until we found the bug. Really. At least on the IIGS we had GSBug which is still one of my favourite debuggers, only rivalled by SoftIce).
93143
Posts: 1715
Joined: Fri Jul 04, 2014 9:31 pm

Re: 16bit table indexing problem

Post by 93143 »

I didn't mean to imply that it should be standard practice in all cases. For absolute or long addresses with small numerical values, it might be wise, because you know what addressing mode you want and the assembler is likely to screw it up.

But if you're using immediate values, yes, it's probably better to hold off on using length-forcing suffixes until it's clear you need them.
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: 16bit table indexing problem

Post by koitsu »

Nod, understood, and agreed. My post was mainly for psycopathicteen.

The issues here are compounded by the fact that WLA DX has awful documentation (both in organisation and grammar/phrasing), which just makes things even harder for someone new. I often brag about ORCA/M (Apple IIGS assembler) because its documentation is remarkably good (I can't tell you how many times during my IIGS days the docs saved me pain). Merlin 8/16's documentation (also Apple IIGS) is pretty good too. And so was x816s'.

All this makes me wonder if I could find Norman Yen (x816 author) and ask him to release the source for it so Win32 (rather than DOS) binaries could be built. It was written in Turbo Pascal, which could very easily be ported to C.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: 16bit table indexing problem

Post by Drew Sebastino »

koitsu wrote:
Espozo wrote:Just wondering because, like I said, the loading and storing approach didn't work, I wonder, how does the table actually get loaded into ram? The table is 7 bytes long, so does it fill the register and 7 after it with information? How can the processor even hold the table if it can only hold 16 bits? (I'm sure my way of thinking things is way off.)
What do you think the loop in build_metasprite is for? I'm starting to get the impression someone gave you a bunch of code you don't understand (how it works). Did someone give you this code? If so, it might be better to discuss with them this type of question, since they're the author. This is exactly why taking code snippets from people + using them (without understanding them) is a Bad Practise(tm) (that's my opinion).
I don't remember exactly how the code came to be, but I know the answer lies in the SNES Programming Help thread. If I remember correctly, it's part of a much more complicated (and useful) code psychopathicteen wrote that I edited a bit for me. I don't know exactly what's going on, but I think I have a fairly good idea. (Accumulator should be 8 bit, and X and Y should be 16 bit.)

Code: Select all

	ldy #$00		;says 0 sprites have been made yet
	ldx #MetaspriteTable	;where MetaspriteTable is in Bank0?
	sty YTemp		;store y to YTemp
	stx XTemp		;store x to XTemp
	jsr start_metasprite	;jump to start_metasprite to build a metasprite

Code: Select all

.BANK 0 SLOT 0
.ORG 0
.SECTION "MetaspriteCode"

start_metasprite:
	php		;no clue
	rep #$10	;prepares to make the accumulator 8bit by crearing the processor status bits?
	sep #$20	;makes the accumulator 8bit?
	ldy YTemp	;load #$00 into Y, as this offsets the Sprite Buffer and no sprites have been made yet
	ldx XTemp	;the value of where the table starts is being loaded into X

build_metasprite:
	lda $00,x		;I'm not sure why we are loading $00, (I looked in a memory editor and it is 0) but we are offseting $00 by X, to see where we are in the table
	beq metasprite_done	;If the number in the table was 0, (designed to mean there are no more sprites in the metasprite) then jump to metasprite_done to jump back to the main code.
	inx			;increase x by 1 to look at the next byte in the table (sprite x position)
	lda $00,x		;we are offseting $00 by X, to see where we are in the table
	sta SpriteBuf1,y	;storing the byte (for sprite y position) in SpriteBuf, offset by y (y gets incremented by 4 because each sprite has 4 bytes)
	inx			;increase x by 1 to look at the next byte in the table (sprite y position)
	lda $00,x		;we are offseting $00 by X, to see where we are in the table
	sta SpriteBuf1+1,y	;storing the byte (for sprite y position) in SpriteBuf, offset by y (y gets incremented by 4 because each sprite has 4 bytes)
	inx			;increase x by 1 to look at the next byte in the table (to see if there is another sprite in the metasprite)
	iny			;y gets incremented by 4 because each sprite has 4 bytes
	iny
	iny
	iny
	bra build_metasprite	;go back to build_metasprite to potentially build another sprite in the metasprite

metasprite_done:
	plp		;no clue
	rts		;jump back to the main code

.ENDS
I think the problem resides with the fact of how I'm storing X and Y when I jump to the metasprite building code and how I'm loading it when I get there, because like I said, if I just get rid of the storing and loading into XTemp and YTemp, it works fine. (X and Y are supposed to be 16 bit.)

(I know I'm probably frustrating you by this point...)
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: 16bit table indexing problem

Post by psycopathicteen »

It looks like it should work. Post the latest ROM so I can trace it in a debugger and figure out what's wrong.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: 16bit table indexing problem

Post by Drew Sebastino »

Thank you. I'm literally dumbfounded. MetaspriteTest1 yields the correct result, while MetaspriteTest2 doesn't, which is the one that uses XTemp and YTemp. The metasprite routine for both is Metasprite and Metasprite2 respectively. If you have any questions, don't hesitate to ask.
MetaspriteDemo.rar
(3.83 MiB) Downloaded 538 times
Edit: I accidentally increased Y by one more than I should have in Metasprite2, so just get rid of one of them after you download it. It still doesn't work though...
psycopathicteen
Posts: 3140
Joined: Wed May 19, 2010 6:12 pm

Re: 16bit table indexing problem

Post by psycopathicteen »

I just learned something new. WLA is a total piece of crap.
0082ea ldy #$0000 A:0000 X:0000 Y:0000 S:1fff D:0000 DB:00 nvMxdiZC V:230 H: 30
0082ed ldx #$8401 A:0000 X:0000 Y:0000 S:1fff D:0000 DB:00 nvMxdiZC V:230 H: 54
0082f0 sty $1808 [001808] A:0000 X:8401 Y:0000 S:1fff D:0000 DB:00 NvMxdizC V:230 H: 78
0082f3 stx $180a [00180a] A:0000 X:8401 Y:0000 S:1fff D:0000 DB:00 NvMxdizC V:230 H: 118
0082f6 jsr $820e [00820e] A:0000 X:8401 Y:0000 S:1fff D:0000 DB:00 NvMxdizC V:230 H: 158
00820e php A:0000 X:8401 Y:0000 S:1ffd D:0000 DB:00 NvMxdizC V:230 H: 204
00820f rep #$10 A:0000 X:8401 Y:0000 S:1ffc D:0000 DB:00 NvMxdizC V:230 H: 226
008211 sep #$20 A:0000 X:8401 Y:0000 S:1ffc D:0000 DB:00 NvMxdizC V:230 H: 248
008213 ldy $08 [000008] A:0000 X:8401 Y:0000 S:1ffc D:0000 DB:00 NvMxdizC V:230 H: 270
008215 ldx $0a [00000a] A:0000 X:8401 Y:0000 S:1ffc D:0000 DB:00 nvMxdiZC V:230 H: 302
008217 lda $00,x [000000] A:0000 X:0000 Y:0000 S:1ffc D:0000 DB:00 nvMxdiZC V:230 H: 334
008219 beq $822e [00822e] A:0000 X:0000 Y:0000 S:1ffc D:0000 DB:00 nvMxdiZC V:230 H: 364
00822e plp A:0000 X:0000 Y:0000 S:1ffc D:0000 DB:00 nvMxdiZC V:230 H: 386
00822f rts A:0000 X:0000 Y:0000 S:1ffd D:0000 DB:00 NvMxdizC V:230 H: 414
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: 16bit table indexing problem

Post by Drew Sebastino »

Wait a minute, did it load from the completely wrong register from what I stored in? Both were defined as XTemp and YTemp... I guess I'm not completely crazy after all! :roll: I guess this would explain how it got the number 0 and exited the routine. (I guess it's time to switch to a new assembler?)
Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: 16bit table indexing problem

Post by Sik »

That's about as bad as that time I tried to use asmx and it somehow managed to rotate the order of the bytes in an entire 16 byte block (inevitably resulting in a crash for obvious reasons).
tomaitheous
Posts: 592
Joined: Thu Aug 28, 2008 1:17 am
Contact:

Re: 16bit table indexing problem

Post by tomaitheous »

psycopathicteen wrote:I just learned something new. WLA is a total piece of crap.
It's a secret to everybody.
__________________________
http://pcedev.wordpress.com
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: 16bit table indexing problem

Post by koitsu »

Espozo wrote:Wait a minute, did it load from the completely wrong register from what I stored in? Both were defined as XTemp and YTemp... I guess I'm not completely crazy after all! :roll: I guess this would explain how it got the number 0 and exited the routine. (I guess it's time to switch to a new assembler?)
The root cause of the bug is unknown (I have a couple theories -- I'll spend a little time testing them out tonight), and I could do some testing to see what the heck is going on, but I'm choosing not to. Purely for educational purposes for you -- the code:

Code: Select all

  rep #$10
  sep #$20
  ldy $180a
  ldx $1808
Should have assembled into:

Code: Select all

C2 10     rep #$10
E2 20     sep #$20
AC 0A 18  ldy $180a
AE 08 18  ldx $1808
But instead the assembler somehow decided the index register size was 8-bit (I think?) and came out with this, silently discarding the upper byte of the address entirely, and thus chose to "optimise" by using direct page addresses:

Code: Select all

C2 10     rep #$10
E2 20     sep #$20
A4 0A     ldy $0a     ; Effectively same as ldy $000a
A6 08     ldx $08     ; Effectively same as ldx $0008
I can tell it's using direct page because the opcodes+operands according to psychopathicteen's debugger output shows only 2 bytes used (if they were 16-bit absolute addresses, but wrong, they'd be 3 bytes).

Needless to say, $08 != $1808 and $0a != $180a. You didn't store your temporary values in direct page, you stored them in RAM (as the STX/STY lines clearly indicate), so the LDY/LDX statements here would result in incorrect values being loaded. Who knows what's in direct page at that point!

What's funny about all of this: this might explain why long, LONG ago, when I looked at some code someone wrote in WLA DX, I'd see what I considered "intermittent" usage of the .w modifier (meaning use at times where the assembler obviously should have gotten the right thing, thus was implied). That never sat well with me. Christ, I'm having horror flashbacks...
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 16bit table indexing problem

Post by tepples »

[benefit-of-the-doubt]
Was there lda #$1800 tad beforehand? Perhaps it's attempting to track D the same way it tracks bits 5-4 of P.
[/benefit-of-the-doubt]
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: 16bit table indexing problem

Post by koitsu »

You mean tcd? Nope, no where in that code. What psychopathicteen posted here is what literally got run. And if there was a tcd (earlier in the program), it wouldn't explain why STY/STX used absolute addressing while LDY/LDX didn't (since neither used the .w to force 16-bit addresses).

Good theory/thinking nonetheless!
User avatar
nicklausw
Posts: 376
Joined: Sat Jan 03, 2015 5:58 pm
Location: ...
Contact:

Re: 16bit table indexing problem

Post by nicklausw »

koitsu wrote:
nicklausw wrote:Visual Studio and a bunch of other crap is needed. Don't use the binaries given on Ville's website, as those are somewhat outdated (and some bug fixes along with improvements have been made since then).

By the assumption that you're using Windows, here's my binaries. Fresh off GitHub. Made them last month as I recall.

EDIT: just remembered I also compiled them for Ubuntu, so I'll put those there aswell. Zip = windows, Tar = Ubuntu.
The Windows binaries you provide in the zip are native 64-bit binaries -- they will not work on 32-bit operating systems. This is unlike the "unofficial" binary builds which are 32-bit. I can't use these binaries (I do not run a 64-bit OS). There's really no reason (that I can think of) for native 64-bit binaries for WLA DX on Windows (on *IX it's a different situation, as not everyone's OSes have 32-bit compatibility shims; for example my FreeBSD boxes are all pure 64-bit with absolutely no 32-bit binary support). Windows 64-bit OSes provide 32-bit compatibility shims by default, so 32-bit is a better choice there for something non-memory-intensive like 65xxx assemblers.

The only reason I'm bothering to try your binaries is to see if the listing generation stuff has been fixed. "And some bug fixes along with improvements have been made since then" isn't precise enough -- this is exactly what a ChangeLog or commit history is for. I wouldn't need to try the binaries if I could see that + know exactly what commit and/or branch your binaries were based off of. :-)
Update: Decided to download the newest sources and try out a 32-bit distribution of cygwin to see if it could compile it. It did, and I'd like you to test these binaries out.
Attachments
wla-dx-win32.zip
(1.57 MiB) Downloaded 388 times
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 16bit table indexing problem

Post by tepples »

koitsu wrote:You mean tcd?
Yes, a well-known synonym which I seem to remember came from WDC's datasheet. I use tad because it doesn't confuse "C" (BA) with "C" (bit 0 of P). Given the existence of xce (exchange carry with emulation); tcd looks like it could stand for "copy carry to decimal mode".

Is Cygwin needed, or would MinGW work as well? MinGW doesn't need quite as big of a C runtime DLL because it doesn't try to implement a huge swath of POSIX. Instead, it uses MSVC 6's DLL.
Post Reply