Tables confusion

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
andylatham82
Posts: 10
Joined: Tue Jul 11, 2017 10:20 am

Re: Tables confusion

Post by andylatham82 »

There's no need really. Using .w just tells WLA that you want to use the absolute-addressed version of the instruction, so it can use a full 16-bit operand. Using direct page would be slightly faster, but unless you want to figure out how to tell WLA to only use the bottom half of the label, you'd need to use page zero, and unless your data bank is a HiROM region (it shouldn't be), page zero is in shadow RAM, so you'd have to spend more effort loading the table into RAM at boot. Furthermore, you'd need to be sure the direct page register was pointing at page zero before using this subroutine, since in general it's not.

Less trouble to just use absolute addressing.
I haven't got a clue what most of that means, but I'll just take it as read that I should use LDA.w anytime I run into trouble!

I've reorganised the code to now be like this:

Code: Select all

; TABLE EXAMPLE.
 
.include ".\SNESfiles\Header.inc"		; Include SNES header information.
.include ".\SNESfiles\Snes_Init.asm"	; Include SNES initialisation code.
 
; Needed to satisfy interrupt definition in "Header.inc".
VBlank:
RTI
 
.bank 0
.section "MainCode"

Start:					; Start of the program.

	Snes_Init			; Initialize the SNES. This resets the SNES to a known state.
	
	STZ $19

	LDX $19				; Mario's power-up state.
	LDA.w Table,x		; Load the table, indexed by power-up ($19)
	STA $09				; get the value into $9.
	RTL					 ; Return

Table:
	.db $08,$1C,$24,$48	; Table of timer values. Value can't go beyond #$FF unless in 16-bit mode.
	;	 00  01  02  03
 
; Loop forever.
Forever:
	JMP Forever

.ends
Thanks for the help with this everyone :)
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Tables confusion

Post by 93143 »

Two things.

First, .w (stands for word) is only useful when you want an instruction to use a 16-bit operand and WLA refuses to take any subtler hints. If you want to insist on an 8-bit operand, use .b (byte). For 24-bit, use .l (long).

Second, where is rtl taking you? Unless Snes_Init pushes the PBR value followed by Forever to the stack, this code will not do what you expect. Note also that even without rtl, your table is still not out of the way of the code; that terminator loop is code too and should be in sequence with the rest.
User avatar
andylatham82
Posts: 10
Joined: Tue Jul 11, 2017 10:20 am

Re: Tables confusion

Post by andylatham82 »

93143 wrote:First, .w (stands for word) is only useful when you want an instruction to use a 16-bit operand and WLA refuses to take any subtler hints. If you want to insist on an 8-bit operand, use .b (byte). For 24-bit, use .l (long).
Should it be possible for me to use LDA.b in my example?
Second, where is rtl taking you? Unless Snes_Init pushes the PBR value followed by Forever to the stack, this code will not do what you expect. Note also that even without rtl, your table is still not out of the way of the code; that terminator loop is code too and should be in sequence with the rest.
Ahh that makes sense. To be honest I wondered if a return was necessary at all in the main code. In a higher level language I'd put a return in at the end of the main function, but is one not needed in assembly?

I've rewritten the code to take the table outside the rest of the code properly (see below). Is this correct now?

Code: Select all

; TABLE EXAMPLE.
 
.include ".\SNESfiles\Header.inc"		; Include SNES header information.
.include ".\SNESfiles\Snes_Init.asm"	; Include SNES initialisation code.
 
; Needed to satisfy interrupt definition in "Header.inc".
VBlank:
RTI
 
.bank 0
.section "MainCode"

Start:					; Start of the program.

	Snes_Init			; Initialize the SNES. This resets the SNES to a known state.
	
	STZ $19

	LDX $19				; Mario's power-up state.
	LDA.w Table,x		; Load the table, indexed by power-up ($19)
	STA $09				; get the value into $9.
 
; Loop forever.
Forever:
	JMP Forever
	
Table:
	.db $08,$1C,$24,$48	; Table of timer values. Value can't go beyond #$FF unless in 16-bit mode.
	;    00  01  02  03

.ends

93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Tables confusion

Post by 93143 »

andylatham82 wrote:Should it be possible for me to use LDA.b in my example?
Sure, but it will get you the same error you were complaining about before. The location of your data table simply doesn't fit in a byte.

What the suffix does in this case is force WLA to pick a particular opcode. lda in the context of lda label,x can mean any of three opcodes: B5, BD, and BF, which take one-, two-, and three-byte operands respectively, corresponding to the direct-page, absolute, and long addressing modes. I have no idea why it thought you wanted direct-page addressing with a 16-bit label...
In a higher level language I'd put a return in at the end of the main function, but is one not needed in assembly?
In a higher level language, that return is to pass control back to the operating system. The SNES doesn't have an operating system, and in any case you aren't passing control anywhere at that point, because you want the program to continue into the terminator loop.
Is this correct now?
Should be.
User avatar
andylatham82
Posts: 10
Joined: Tue Jul 11, 2017 10:20 am

Re: Tables confusion

Post by andylatham82 »

93143 wrote:Sure, but it will get you the same error you were complaining about before. The location of your data table simply doesn't fit in a byte.
Yeah I did try it and got the same error. Now, is it possible to specify where in RAM the table gets stored? Whether it's in an address that can be described by a byte or a word, I feel like it would be good practice to control where it is located.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: Tables confusion

Post by 93143 »

andylatham82 wrote:Now, is it possible to specify where in RAM the table gets stored?
Of course, but currently you aren't storing it in RAM.

Like I said, the SNES doesn't have an OS - it starts in ROM, and everything in your program is read/executed directly from its initial location in ROM unless you explicitly copy it to RAM and then explicitly use the version in RAM. If you're leaving your table in ROM, as is usually good practice for uncompressed constant data, the best way to control where it goes is to put it in a separate section and FORCE the starting address of that section.

It is, however, not quite that simple. Further discussion along these lines leads us straight into one of the biggest initial hurdles for SNES n00bs: the memory map. And since I really need to get to bed...
User avatar
andylatham82
Posts: 10
Joined: Tue Jul 11, 2017 10:20 am

Re: Tables confusion

Post by andylatham82 »

Ah I had forgotten that the table would be part of the ROM! My notes tell me that ROM memory addresses start at $8000, so that explains the address of the table being up in the 8000's. This makes things more clear for me, thanks! :)
creaothceann
Posts: 611
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Tables confusion

Post by creaothceann »

Where ROM starts depends on where the cartridge is mapped into the memory map (this is fixed), and what the cartridge does with the address on the main address bus (depends on how the cartridge is wired).

If you use higan/bsnes you can see this info in the manifest viewer.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Post Reply