Direct page issues...

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Direct page issues...

Post by gnarlyWarlock »

Hello. I'm trying to update my HDMA table in WRAM ($7FA100), however.....

Code: Select all

modGradient:
	.EQU COUNT 		1
	php
	phb
	phd	;push flags, bank and dp register, since we're tinkering with them
	lda #$7F
	pha
	plb	;got the new WRAM data bank (where the HDMA table is)
	rep #$20
	lda #$A100 ;direct page of the WRAM location
	tcd
	sep #$20
	.REPT 6
		ldx COUNT
		dea
		stx COUNT
		.REDEF COUNT COUNT+2
	.ENDR
	pld
	plb
	plp
	rts
I've got genuinely no idea why it isn't updating the table. Here's my initialization code (though I don't think it's relevant)...Also, $A100+COUNT does exactly what I want it to do. So....that's why I suspect something's wrong with my direct page address...

Code: Select all

InitHDMA:
	.EQU FREERAM 	$7FA100 ;initialize HDMA table in WRAM
	ldx #$0F
LVL1_HDMAINIT:
	lda.w LVL1BLUE, X
	sta FREERAM, X
	dex
	bpl LVL1_HDMAINIT
	rts
LVL1BLUE:
	.db $4F,$29	;the table will be modified continuously via modGradient, needa put it in WRAM
	.db $04,$2A
	.db $04,$2B
	.db $04,$2D
	.db $04,$2E
	.db $04,$2F
	.db $04,$30
	.db $00	
Please help, thanks
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: Direct page issues...

Post by Khaz »

Are you using ca65? ca65 has some kind of messed-up direct page behaviour that I can never remember exactly what it is, since I use WLA. As far as I can tell your code should be working.
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Re: Direct page issues...

Post by gnarlyWarlock »

Khaz wrote:Are you using ca65? ca65 has some kind of messed-up direct page behaviour that I can never remember exactly what it is, since I use WLA. As far as I can tell your code should be working.
Yeah, I am using WLA; I'm aware of ca65's issues from browsing the forum's earlier posts. Really sucks when I don't get what's happening lol
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: Direct page issues...

Post by Khaz »

Oh, okay. Well, uh, I've never used REPT or REDEF myself... I pretty much just write all my code out literally.

OH WAIT. I think this is your problem:

ldX
deA
stX
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: Direct page issues...

Post by 93143 »

You can't access bank $7F with direct page. It's always in bank $00.
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Re: Direct page issues...

Post by gnarlyWarlock »

Khaz wrote:Oh, okay. Well, uh, I've never used REPT or REDEF myself... I pretty much just write all my code out literally.

OH WAIT. I think this is your problem:

ldX
deA
stX
Lol yep I've noticed that right after I submit my original code and fixed it - I thought it had something to do with differences between the accumulator and x register addressing, but that made no sense so I changed it back.

As for the above post, If that's the actual issue, then what is the purpose of direct paging, assuming it can only address the 0 bank? In other words (I'm pretty new so please pardon the amateur questions) what's in the 0 bank? VRAM, dedicated hardware registers or what? What can I possibly use direct paging with?
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: Direct page issues...

Post by Khaz »

gnarlyWarlock wrote:As for the above post, If that's the actual issue, then what is the purpose of direct paging, assuming it can only address the 0 bank? In other words (I'm pretty new so please pardon the amateur questions) what's in the 0 bank? VRAM, dedicated hardware registers or what? What can I possibly use direct paging with?
Yeah I shoulda remembered that. The zero bank has a lot of useful stuff actually, namely the lowest $2000 of WRAM (which is mirrored in every bank from $00 to $3F (in LOROM)) and access to all your hardware registers, both of which can benefit greatly from some extra speed. Personally I've crammed almost all my game variables and the main "object list" inside that lowest $2000, the rest of WRAM I use for huge tables and other things that are not really time-sensitive. I mostly use direct page to iterate through my list of objects in game.

Others around here have more experience than me and I'm sure could list all kinds of other clever uses for it.
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Re: Direct page issues...

Post by gnarlyWarlock »

Khaz wrote:
gnarlyWarlock wrote:As for the above post, If that's the actual issue, then what is the purpose of direct paging, assuming it can only address the 0 bank? In other words (I'm pretty new so please pardon the amateur questions) what's in the 0 bank? VRAM, dedicated hardware registers or what? What can I possibly use direct paging with?
Yeah I shoulda remembered that. The zero bank has a lot of useful stuff actually, namely the lowest $2000 of WRAM (which is mirrored in every bank from $00 to $3F (in LOROM)) and access to all your hardware registers, both of which can benefit greatly from some extra speed. Personally I've crammed almost all my game variables and the main "object list" inside that lowest $2000, the rest of WRAM I use for huge tables and other things that are not really time-sensitive. I mostly use direct page to iterate through my list of objects in game.

Others around here have more experience than me and I'm sure could list all kinds of other clever uses for it.
http://wiki.superfamicom.org/snes/show/ ... M+Tutorial in this tutorial it says it can address the first 64K of memory...I should've noticed that. Makes much more sense now. So, I suppose when you say it's mirrored, I assume WRAM is identical in banks 00-3F... cool, fair enough.

Thank you very much for clarifying that for me!
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Re: Direct page issues...

Post by gnarlyWarlock »

I hope someone sees this, because yet again, the official documentation isn't clear

I'm quoting the SNES Dev Manual, page 2-21-1
The WRAM (8K-Byte) is mapped to address (0000~1FFF) of banks (00~3F), (80~BF) and 7E> This is the WRAM used as common bank. This 8K-bytes can be accessd from any bank described above...This is the WRAM used as the common bank. This 8k-Bytes can be accessed from any bank described above...
Now:

Code: Select all

	.EQU FREERAM 	$7EA100 ;initialize HDMA table in WRAM	
	ldx #$10
LVL1_HDMAINIT:
	lda.w LVL1BLUE, X 
	sta FREERAM, X
	dex
	bpl LVL1_HDMAINIT
	rts
works fine; I put #$A100 into $4302 and #$7E into $4304, start HDMA and everything's groovy. HOWEVER, that same code with FREERAM = $A100, and stz $4304 : it doesn't work. -_-".

Also, in my modGradient subroutine, if I do indeed load the table to #$7FA100, looking at the documentation, I'd assume I can direct page to it (lda #$A100, tcd, and rock and roll). That doesn't work. wtf??

ALSO, IF I put LVL1BLUE into another bank (lets say, bank 1, and try to lda.w $8000+LVL1BLUE, X), it can't find the table; the table has to be in the same bank as this subroutine.

Please help me out, the header's attached, on which I have yet ANOTHER question: I define having 8 ROM banks, and each ROM bank is $8000; does that mean my ROM is necessarily in banks $00-$08, from CPU's reference point?
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: Direct page issues...

Post by 93143 »

gnarlyWarlock wrote:works fine; I put #$A100 into $4302 and #$7E into $4304, start HDMA and everything's groovy. HOWEVER, that same code with FREERAM = $A100, and stz $4304 : it doesn't work. -_-".
Of course not. $A100 isn't in the bottom $2000 bytes (8 kilobytes) of the bank, meaning it's not in the WRAM mirror. In bank $00, $A100 is a ROM location.
Also, in my modGradient subroutine, if I do indeed load the table to #$7FA100, looking at the documentation, I'd assume I can direct page to it (lda #$A100, tcd, and rock and roll). That doesn't work. wtf??
Why would you assume that? Like I said, you can't use direct page to access anything outside bank $00, and it's only $7E0000-$7E1FFF that's mirrored to $0000-$1FFF in banks $00-$3F and $80-$BF. You can't access any of bank $7F via direct page, ever, and that also goes for the upper $E000 bytes (ie: most) of bank $7E.
ALSO, IF I put LVL1BLUE into another bank (lets say, bank 1, and try to lda.w $8000+LVL1BLUE, X), it can't find the table; the table has to be in the same bank as this subroutine.
Two things: First, the increment is not $8000; it's $10000. Banks are always $10000 bytes; it's just that they aren't always 100% ROM (the banks you're using are 50% ROM and 50% WRAM/MMIO/reserved areas). Second, by using lda.w, you're probably forcing 16-bit addressing, which causes the assembler to ignore the top byte (ie: the bank byte) of the operand. Try lda.l.

Or just try to arrange your code to minimize long accesses, because they're slow. Keep in mind that the data bank (the bank used for 16-bit addressing of data) does not have to be the same as the program bank (the bank the program counter is currently in), so you can access data that's in a different bank from the code doing the accessing without having to use long addresses. Of course, if you only have a handful of accesses to do in a particular bank, it's probably faster to use 24-bit addressing than to change the data bank just for that...

It might be a good idea to study up on the SNES memory map; once you get it, everything makes way more sense.
I define having 8 ROM banks, and each ROM bank is $8000; does that mean my ROM is necessarily in banks $00-$08, from CPU's reference point?
You mean $00-$07, right? It certainly should be (unless there's an assembler option I'm not aware of), but for a ROM that small you should also be able to find the data in $40-$47, $80-$87, and $C0-$C7. Since you're using LoROM, I wouldn't bother with the $40+ and $C0+ ranges - if you're using some variant of HiROM they allow access to all $10000 bytes of a ROM bank, but if you aren't, the only practical difference is that you can't access MMIO or the RAM mirror with 16-bit addressing in those banks. $80+ is useful for FastROM purposes, but that's out of scope so I'll leave off here.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Direct page issues...

Post by AWJ »

gnarlyWarlock wrote:I hope someone sees this, because yet again, the official documentation isn't clear
You're suffering from a fundamental misunderstanding. Direct page is limited to accessing the first 64K of the CPU address space. Not the first 64K of RAM, not the first 64K of ROM, but the first 64K of the address space. The 65816 doesn't "know" anything about RAM or ROM, it only knows addresses.

That means that direct page can access the following areas:

Code: Select all

000000-001FFF: WRAM (first 8k bytes only)
002100-0021FF: B bus (S-PPU registers, etc.)
004000-0043FF: S-CPU registers (HDMA, etc.)
008000-00FFFF: ROM (first 32k bytes if Mode 20; second 32k bytes if Mode 21)
Plus any cartridge-specific special registers (DSP, SuperFX, SA-1, etc.)

Direct page addressing adds the the 8-bit operand, the 16-bit direct page register, and possibly an index register, then ANDs the sum with $FFFF to get the effective address. The data bank register (the one you access with PHB/PLB) is completely ignored, it's treated as always zero. Only the addressing modes that take a 16-bit address use the data bank register.
HOWEVER, that same code with FREERAM = $A100, and stz $4304 : it doesn't work. -_-".
It doesn't work because $00A100 is ROM. You can't write anything there.
ALSO, IF I put LVL1BLUE into another bank (lets say, bank 1, and try to lda.w $8000+LVL1BLUE, X), it can't find the table; the table has to be in the same bank as this subroutine.
It can't find it because the data bank is pointing to the bank your subroutine is in, not the one your table is in. Absolute indexed addressing does use the data bank register.
I define having 8 ROM banks, and each ROM bank is $8000; does that mean my ROM is necessarily in banks $00-$08, from CPU's reference point?
Address space banks and ROM "banks" are distinct but related concepts. I assume your ROM is Mode 20 because you're talking about $8000 banks. In that case, the first ROM bank (the first $8000 bytes) is visible in address space banks 00 and 80. The second $8000 bytes is visible in banks 01 and 81. The third $8000 bytes is visible in banks 02 and 82, et cetera. If you have 256 KB of ROM then the last $8000 bytes will be visible in banks 07 and 87.
gnarlyWarlock
Posts: 18
Joined: Fri Jul 24, 2015 1:30 pm

Re: Direct page issues...

Post by gnarlyWarlock »

Thank you guys so much. It's always the simple stupid mistakes that get me, and I seriously JUST realized $A100 isn't in $0000-$1FFF LOL. The info on the memory map is incredibly useful though, thanks. I couldn't understand the nomenclature they use for the different ROM types (There's Modes 20, 21, 25; however, I still have a fairly weak grasp of the concepts of LoROM and HiROM, though I presume the prefixes indicate size (???)). I have been wondering how to load in the full 24 bit address and haven't realized that I can designate it by lda.l. But yeah the bank information is incredibly useful.

However, on that last part AWJ mentioned dp addresses all of bank 0...well then, if I have my data stored at offset $1000 (still in WRAM) and I transfer that to the page register, and alter the data @ that offset, in bank 0, will the WRAM in banks $00-$3F be altered immediately, as well as $7F, or is it going to take a few clock cycles to synchronize them together? In other words, is the WRAM in all those banks the same exact space of physical memory that we're altering, or are there multiple copies of the same exact pool of memory? In the documentation it does say the SNES has 8k fast WRAM, and then an extra 120k, so a total of 128k. Well, If WRAM is just one pool, lets say banks $7E and $7F are fully dedicated to WRAM, then 16^4*2 = 131k. So what happens with that extra 3k of memory?
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Direct page issues...

Post by tepples »

The first nibble of the mode denotes the ROM speed.
  • Mode 2x is slow ROM, where ROM is accessed at 2.7 MHz. Slow ROM must be 200 ns or faster.
  • Mode 3x is fast ROM, which allows 3.6 MHz ROM reading in $80-$FF but needs 120 ns or faster ROMs. It provides a speed advantage for code or data tables in ROM but not for DMA copies from ROM, which always run at 2.7 MHz.
The second nibble of the mode denotes the way ROM banks are arranged in S-CPU address space.
  • Mode x0 is LoROM, where 32K of ROM occupies the second half of each bank from $80-$FF (mirrored to $00-$7D). LoROM can be up to 32 Mbit (4 MiB), with 128 banks of 32 KiB each.
  • Mode x1 is HiROM, where ROM occupies the whole bank $C0-$FF (mirrored to $40-$7D, and with the second half of each 64K bank mirrorred to $00-$3F and $80-$BF). HiROM can be up to 32 Mbit (4 MiB), with 64 banks of 64 KiB each.
  • Mode x5 is ExHiROM, which consists of one 32 Mbit (4 MiB) HiROM mapped to $C0-$FF and a second 8, 16, or 32 Mbit (1, 2, or 4 MiB) HiROM mapped to $40-$7D. It's mirrored as in HiROM, meaning the vectors come from the second ROM. ExHiROM can be up to 64 Mbit (8 MiB), with 128 banks of 64 KiB each, though the first half of the last two banks is inaccessible and the second half is accessible only through the mirrors at $3E and $3F. The second ROM is also always slow, making it useful for less frequently used code or data or as a DMA source.
The WRAM at the start of $00-$3F and $80-$BF is exactly the same physical memory as $7E0000-$7E1FFF. RAM access is always slow (2.7 MHz).
lets say banks $7E and $7F are fully dedicated to WRAM, then 16^4*2 = 131k. So what happens with that extra 3k of memory?
That's the 2.4% difference between 1000 bytes in a (metric) kilobyte and 1024 bytes in what is officially called a kibibyte (abbreviated KiB).
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Direct page issues...

Post by AWJ »

gnarlyWarlock wrote:However, on that last part AWJ mentioned dp addresses all of bank 0...well then, if I have my data stored at offset $1000 (still in WRAM) and I transfer that to the page register, and alter the data @ that offset, in bank 0, will the WRAM in banks $00-$3F be altered immediately, as well as $7F, or is it going to take a few clock cycles to synchronize them together? In other words, is the WRAM in all those banks the same exact space of physical memory that we're altering, or are there multiple copies of the same exact pool of memory? In the documentation it does say the SNES has 8k fast WRAM, and then an extra 120k, so a total of 128k. Well, If WRAM is just one pool, lets say banks $7E and $7F are fully dedicated to WRAM, then 16^4*2 = 131k. So what happens with that extra 3k of memory?
The SNES WRAM size is exactly $20000 bytes. The whole thing is mapped at $7E0000-$7FFFFF, and the first $2000 bytes are mirrored in banks 00-3F and 80-BF. The mirrors are all physically the same memory as each other and as $7E0000-7E1FFF. However, $7F0000-$7F1FFF is not a mirror, it's a separate chunk of RAM.
93143
Posts: 1371
Joined: Fri Jul 04, 2014 9:31 pm

Re: Direct page issues...

Post by 93143 »

gnarlyWarlock wrote:It's always the simple stupid mistakes that get me
It happens. Just last week I fixed a bug in a display engine test ROM I'd been working on, wherein I had tried to get an IRQ to fire on the 14th scanline by setting VTIME to $0014. Before that I had trouble with my IRQs sending the CPU all over everywhere, because I had defined my IRQ trampoline location as $1000 (so far so good) and then used $IRQ0 instead of IRQ0 to actually insert the value into the ROM...

Oh, and watch out for immediate value loads that don't actually have # in front. It's a perfectly valid expression, and depending on what's in the memory location you accidentally loaded from, it can be very difficult to diagnose the problem based solely on output. Your code might even work, for a while...

"BRK" redirects here. For other uses, see BRK (disambiguation). - Wikipedia
Post Reply