new to snes environment, have some questions.

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
new to snes environment, have some questions.
by on (#216123)
I'm now getting the desire to get serious with learning to write for the snes. But I have a few questions as to understanding how the RAM/ROM works.

I know 6502, I've hacked many games which a lot of people know, and I've now written 2 games from scratch for the NES. Just wanted to give that brief background on my coding/writing history.

1. Is the snes ram really $0-$1FFF? I ask because, I know the NES ram is $0-$7FF. Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?

2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?

4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

Thank you all for reading!
Re: new to snes environment, have some questions.
by on (#216125)
infidelity wrote:
I know 6502, I've hacked many games which a lot of people know, and I've now written 2 games from scratch for the NES.
Take a look at this then.

infidelity wrote:
1. Is the snes ram really $0-$1FFF?
See anomie's memmap.txt.

(His regs.txt is an excellent hardware reference.)

infidelity wrote:
Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?
Sprite data is in OAM (Object Attribute Memory), which is accessed via a set of PPU registers.

infidelity wrote:
2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?
Graphics are either stored uncompressed in ROM and transferred to VRAM, or are decoded into WRAM and transferred to VRAM, or decoded directly to VRAM.

infidelity wrote:
3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?
The CPU loads the 16-bit reset vector from $00:$FFFC, which is in cartridge address space. The memory mapper or address bus wiring may route that to any ROM location, but it mostly goes to either $FFFC or $7FFC.

infidelity wrote:
4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?
Depends if you're using HiROM/LoROM/etc.
Re: new to snes environment, have some questions.
by on (#216127)
infidelity wrote:
1. Is the snes ram really $0-$1FFF?

RAM on the Super NES is $7E0000-$7FFFFF. The $7E0000-$7E1FFF region gets mirrored to $0000-$1FFF of banks $00-$3F and $80-$BF.

infidelity wrote:
Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?

Shadow OAM can be placed anywhere in $7E0000-$7FFFFF. Because DMA on Super NES is much more flexible than DMA on NES, there is no need for alignment to a 256-byte page, though it cannot cross a 65536-byte bank.

infidelity wrote:
2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

Like the Game Boy and Genesis, the Super NES uses CHR RAM. The only consoles I know of that use CHR ROM are NES and Neo Geo. (Atari 7800 is a borderline example; if you're interested, ask in Other Retro Dev.)

infidelity wrote:
3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?

Super NES uses $FFE4-$FFFF, as it has separate sets of vectors for 6502 emulation mode (not used much past the boot sequence) and native mode.

infidelity wrote:
4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

The internal header goes immediately prior to the vectors, based on whatever offset in the ROM image corresponds to $00FFB0-$00FFDF in the CPU address space. In mode $20/$30 ("LoROM"), it goes at $007FB0-$007FDF in the ROM image. In mode $21/$31 ("HiROM"), it goes at $00FFB0-$00FFDF in the ROM image.
Re: new to snes environment, have some questions.
by on (#216149)
infidelity wrote:
Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

No. The S-PPU can't access the cartridge. All graphics data needs to be transferred to the 64 KB VRAM (which the CPU can access only via a port, as it is not on the A bus) before it can be used. As said, DMA is far more flexible on the SNES, and far more bandwidth is available, so this isn't as onerous as it would be on the NES.

VRAM and OAM can be targeted with DMA at any point during VBlank (which is bigger than on NES, at least for NTSC, because the useless overscan has been trimmed and NMI fires after just 224 lines by default) or forced blank (which can be used to extend VBlank like in Star Fox, which can comfortably update its 224x192 4bpp framebuffer in three frames and could probably do it in two if it had to, or to create a black bar on the screen like in Mario Kart, which uploads OAM data in between the top and bottom halves of the display). CGRAM can be addressed during VBlank, forced blank, or HBlank, and is (like most other PPU registers) a great target for HDMA.

Also, the SNES has a raster IRQ that can be set to trigger at a horizontal position every line, at a vertical position every frame, or at a horizontal position on a particular line every frame. HDMA is better for a lot of things, but the IRQ can be very useful too. The use of forced blank described above is a good example, because the NMI can't be moved except by switching overscan on and off.

Quote:
I'm a little fuzzy on header/no header.

That's got nothing to do with the official Nintendo header. A "headered" ROM is one that has a Super Magicom (or other?) copier header before the actual copy of the ROM, and is thus slightly larger than the actual game; by convention the extension for a ROM with a Super Magicom header is .smc. An "unheadered" ROM has no copier header and is thus the correct size; the correct extension for an unheadered ROM is .sfc. These file extension conventions are not universal and should not be relied on. If the ROM is a multiple of 32 KB, it's unheadered. Modern emulators and flash carts do not use the copier headers, so there's no point including one unless you're going to be using a Super Magicom or something to run it.
Re: new to snes environment, have some questions.
by on (#216151)
93143 wrote:
That's got nothing to do with the official Nintendo header. A "headered" ROM is one that has a Super Magicom (or other?) copier header before the actual copy of the ROM, and is thus slightly larger than the actual game; by convention the extension for a ROM with a Super Magicom header is .smc. An "unheadered" ROM has no copier header and is thus the correct size; the correct extension for an unheadered ROM is .sfc. These file extension conventions are not universal and should not be relied on. If the ROM is a multiple of 32 kB, it's unheadered.

I think he's talking about $FFB0 through $FFDF ("ROM Registration Data", using official Nintendo terminology). People colloquially call this a "header" or "cartridge header". Quoting him again, emphasis mine:

infidelity wrote:
4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

Talking to the OP again: 93143 is talking about the 512-byte SMC header (for files ending in .swc or .smc) for Super Magicom / Super Wild Card copiers, which is at the start of the file (i.e. 512 byte header followed by the actual ROM). You don't need this to make a ROM. Stick to just the raw data and name your ROM with a .sfc file extension and you should be fine. If the assembler you're using forces you to make a file with an SMC header, then that file format is documented -- just ask if/when you get there.

Also, re: "goes from 0 to $FFFF": don't make a 64KByte ROM (or smaller like we used to do back in the day). You'll get publicly chastised by some emulator authors for doing so, usually authors who weren't around doing snesdev using copiers and floppy disks. ;-) Make your ROM 512KBytes (4mbits), even if you use way less space than that. Unused space will compress well with .zip or other formats.
Re: new to snes environment, have some questions.
by on (#216152)
Given the wording of "header/no header", I figured he might be confused about the distinction between copier headers and ROM registration data. I was when I started - I deliberately used .smc on my first attempts because I wasn't sure which "header" Neviksti's starter kit was constructing and including. (It was the ROM registration data, of course. You have to go back a fair ways to find example code that includes a copier header; the Anthrox mode split demo is an example.)

It may be worth noting that while some emulators and flash carts do rely on the ROM registration data, the SNES itself does not. The only header data the SNES cares about is the vectors.
Re: new to snes environment, have some questions.
by on (#216153)
koitsu wrote:
don't make a 64KByte ROM (or smaller like we used to do back in the day). You'll get publicly chastised by some emulator authors for doing so

To the contrary, I think 32/64/128/256kb ROMs are fine if that's the only space you actually need; I'm not aware of any current emulators that would have problems with that. 512kb is reasonable for e.g. an actual gamedev project though, since it's hard to predict how much stuff you'll be throwing in there over the course of development and it's easy to just give yourself a decent amount of space right off the bat.

I've even made working ROMs as small as 256 bytes that loaded and ran just fine in bsnes/higan (other emulators needed some padding), although there is virtually no realistic scenario where anyone would actually have a reason to attempt to do this :P
Re: new to snes environment, have some questions.
by on (#216160)
Revenant wrote:
To the contrary, I think 32/64/128/256kb ROMs are fine if that's the only space you actually need; I'm not aware of any current emulators that would have problems with that. 512kb is reasonable for e.g. an actual gamedev project though, since it's hard to predict how much stuff you'll be throwing in there over the course of development and it's easy to just give yourself a decent amount of space right off the bat.

The problem was not with emulators, it was with emulator authors.
Re: new to snes environment, have some questions.
by on (#216165)
I'm not sure why that's important.
Re: new to snes environment, have some questions.
by on (#216196)
Thank you everyone for all the info!

I was doing some testing with the JML & JSL, very cool! I learned how to correctly set the desired address, and the bank number, and was able to return properly with the RTL, again that's so cool how that works! And also a first, I wanted to clear all of the $0000-$1FFF snes ram. So I set X & Y as 16 bit values, while A was at 8 bit. I then loaded 00 into A, then I loaded Y as #$1FFF, then I did STA'Y to $0000 (which at the start, stores 00 into $1FFF, then I DEY, and BNE back to my STA'Y. Using bsnes, I stepped through a couple times to make sure it was working, then when I clicked Run, the code worked! Y was down to 0000, and all the ram was wiped! :-)

Very fun stuff!

However I got lazy and didn't read up on what snes address does ppu rendering, (nes uses $2000) so I was unable to have my NMI fire up, my reset vector I had to deliberately insert a brk, to trip the NMI. :-/

All I'm doing is testing commands right now, to get a feel of the system.

Oh, am I wiping the stack with my code? I don't know where the stack is in the snes.

Thanks, this is becoming fun to toy around with! :-)
Re: new to snes environment, have some questions.
by on (#216199)
infidelity wrote:
Oh, am I wiping the stack with my code? I don't know where the stack is in the snes.

Yes. The 6502 confines the stack to $0100-$01ff, but the 65816 allows it to be anywhere in bank $00. Most games tend to put it at $1fff, or $01ff like NES.

You initialize the stack pointer just like on NES, but this time you'll want to do it with X as a 16-bit register.
Code:
ldx #$1fff
txs

Alternatively, you can use A instead, like so:
Code:
lda #$1fff
tcs         ; or "tas" in some assemblers
Re: new to snes environment, have some questions.
by on (#216337)
Thanks for that info! :-)

I have 2 questions with CGRAM.

1: Are you able to set the desired CGRAM address via $2121, by writing to it twice like you would on the NES for $2006?

2: I've written 2 bytes to $00-$01 of CGRAM. The first byte is fine, but no matter what I put for a 2nd byte, it's always increased by 80? Any ideas?

Thanks! :-)
Re: new to snes environment, have some questions.
by on (#216341)
infidelity wrote:
1: Are you able to set the desired CGRAM address via $2121, by writing to it twice like you would on the NES for $2006?

No. $2121 (CGADD) is essentially an "index" register into CGRAM. You write a single 8-bit value (0 to 255), depending on what colour index you wish to start at. The address (internally) auto-increments when you've written to $2122 twice (keep reading). This is a write-only register.

$2122 (CGDATA) is a double-write register, similar to how the NES's $2006 works (but for a different purpose). It's a 15-bit value, but you write the lower 8 bits first, followed by the upper 7. The order of the data is (when represented by a 15-bit value): 0BBBBBGGGGGRRRRR (B = blue, G = green, R = red). You can only write to this during VBlank, HBlank, or if forced blanking is set. How this data is used depends on what BG mode you're using ($2105). This is a write-only register. Example which would store a bright purple colour (%0111110000011111) in CG-RAM location 6, assuming mode 0:

Code:
sep #$20     ; 8-bit accumulator
lda #6       ; Colour index 6
sta $2121
lda #$1f     ; $7c1f = %0111110000011111 = bright purple
sta $2122
lda #$7c
sta $2122

infidelity wrote:
2: I've written 2 bytes to $00-$01 of CGRAM. The first byte is fine, but no matter what I put for a 2nd byte, it's always increased by 80? Any ideas?

Sounds like a bug in your understanding of how the registers work, or a general bug in your program. I don't know how your determined "it's always increased by 80". If you're using bsnes-plus then you should know that some registers and memory is "pre-seeded" with values, so that may be what you're seeing (this still means your program is buggy :-) ).

Start here: https://wiki.superfamicom.org/writing-y ... es-program
Re: new to snes environment, have some questions.
by on (#216342)
Regarding your second question, are you saying that you're writing two 8-bit values to $2122 after setting $2121 to zero, and the top bit of the resulting 16-bit colour value is being flipped? If so, it might be a quirk of the emulator, because the top bit is a dummy bit. I don't think it's even stored; fullsnes says it's PPU2 open bus when read (via $213B). The values in CGRAM are 15-bit BGR triplets with no extra information.
Re: new to snes environment, have some questions.
by on (#216432)
OK I see now what's happening. In bsnes when I view the CGRAM, using the addresses $000 & $001, the address showing me only .421|8421 is $001. So when I write the 2nd byte to $2122, then that's the one with the leftmost bit unused.

And I was also able to direct $2121 wherever I wanted it to start within the CGRAM to write the palette color! :-)

Very exciting so far for me!

Now I need to learn CHR-RAM, this feature I've never done on the NES, I've only worked with CHR-ROM. Any helpful tips would be grear! Can't believe I'm getting all this. :-)
Re: new to snes environment, have some questions.
by on (#216435)
Get familiar with general purpose DMA. It'll make transferring data from ROM (or RAM space, ex. banks $7E/7F) to PPU RAM easier. Stick with mode 0 for starters -- get some graphics/text up on two different backgrounds, then try playing with the BG scroll registers. This is pretty much what I did in my old iNFiNiTY demo that came with my old SNES docs -- I still think that demo works as a nice "introduction" primer for people getting started. It's not perfect, but it's good enough.

Off-topic and IMO, but the SNES has all the things you wish the NES had. I feel lucky that back in the early 90s I started with the SNES and learned NES stuff several years later; the SNES really spoiled me. :P
Re: new to snes environment, have some questions.
by on (#216449)
Thanks for those tips! Much appreciated! :-)

I'm so impressed from a coding perspective, with how much more can be done with the snes. I've worked with the nes since 2005, and I'm just at the point where I feel comfortable now to tackle the snes, since I've had success with nes romhacks, and coded 2 games from scratch. But I'll definitely follow what you suggested. Thank you again! :-)
Re: new to snes environment, have some questions.
by on (#216516)
Hmm, I'm having an issue getting data to be stored within the VRAM. Using bsnes, when I view the Memory Viewer to see the VRAM, nothing is getting stored to it, yet the bytes I want to be read, are read? I'm obviously missing a step or doing something wrong. :-/

Code:
LDA #$80
STA $2115     ;increase VRAM address

;trying to make it so bytes get stored at $0000 in VRAM
STZ $2116     ;VRAM address low byte
STZ $2117     ;VRAM address hi byte

LDA #$01
STA $4300     ;Make DMA write 1 byte to $2118 then $2119

LDA #$18
STA $4301     ;Write to $2118 & $2119

;I want to load my tileset, which is located at $E000 within my 01 bank, and the size is 2000 bytes
LDA #$00
STA $4302     ;low byte for my tiles
LDA #$E0
STA $4303     ;hi byte for my tiles
LDA #$01
STA $4304     ;bank id
LDA #$00
STA $4305     ;low byte of how many bytes to load
LDA #$20
STA $4306     ;hi byte of how many bytes to load

LDA #$01
STA $420B     ;start DMA


So once all of that is done, I can see my entire 2000 byte set of tiles loaded from the 01 bank, (all of my code is in the 00 bank) but when I view the Memory Viewer for the VRAM, it is all 00's. :-/
Re: new to snes environment, have some questions.
by on (#216518)
- Are you sure the accumulator/memory width is 8 bits? As the code is written that is the assumption, but it would assemble just fine in 16 bit mode and then all the register writes will put an extra zero at the next address, possibly messing things up.

- Is the system in vblank or forced blanking when DMA is started (and for the duration of the transfer)? If not VRAM is tied up by the PPUs and the writes “won’t bite”.
Re: new to snes environment, have some questions.
by on (#216521)
A is 8-bit. I'm not sure regarding vblank, this is still new to me. Is the routine at least correct looking? And with me loading $2000 bytes, what snes registers do I need to set correctly for vblank? Thanks!
Re: new to snes environment, have some questions.
by on (#216525)
The code looks correct to me. (In fact, even if A were 16-bit, it looks like it would still happen to work anyway because of the order things are set in, so I think we can rule that out as the cause.)

Vertical blank, or vblank for short, is the span of time between each frame being drawn to the screen. During this time, the PPU isn't reading from VRAM, and it can be freely modified.

NMI is triggered at the start of vblank, so normally you would do stuff like this within your NMI routine. However, vblank is a fairly limited amount of time -- at most, you could transfer a bit under 6 KB of data per vblank via DMA, on NTSC consoles. As it happens, 0x2000 bytes is 8 KB, so it's too much to fit in a single vblank. Doing this during vblank would require splitting up the DMA.

Forced blank is another option. This simply turns off rendering, so VRAM can be modified freely as much as you want without worrying about time running out. The consequence, however, is that the screen is black while forced blanking is on. Thus, this is normally used while loading levels.
Re: new to snes environment, have some questions.
by on (#216530)
Edit: didn't see post where OP said accumulator is 8-bit. I'll leave the below content here anyway.

I think 16-bit accumulator could break operational behaviour of this code. The big one is how stz $2116 / stz $2117 would result in (operationally) $00 --> $2116, $00 --> $2117, $00 --> $2117, $00 --> $2118, which I think could skew the subsequent DMA transfer results. I don't know what a 2nd write to $2117 would do, same with the subsequent write to $2118. No I'm not going to go look at emulator source code. Really depends on how the "flip-flop latch" thing is done in the hardware. This subject should not de-rail the main purpose of the thread.

There are similar "hmms" in the later parts of the code for the same reason, but as I worked them out, it seems they might actually work by total luck (solely due to the values being written and in the order the MMIO regs are being written to).

OP should get in the habit of checking accum/index sizes when posting code/asking for help. If you aren't sure, generate a code listing in your assembler -- it should be pretty obvious when you have the wrong thing -- else step-trace in a realtime debugger (CPU flags m (accum) and x (index): 0 = 16-bit, 1 = 8-bit). This is a common struggle point with the 65816 in general (read: common mistake/source of issues) so don't feel bad.

The rest of the advice about when this code is run (in VBlank/NMI handler vs. not) and concern over transfer size (while within VBlank) is absolutely correct.

I would make sure the source data you expect to be read really is within $01E000 -- emulator debugger should make this easy. The SNES's mode 20 (LoROM) memory map can often confuse people since sort of a "32KB bank" mode (byte 0 of ROM starts at $008000, byte 65536 ends up at $018000, etc.).

Otherwise the code looks OK.

Are you using a proper SNES initialisation routine, BTW? Many of the MMIO registers need to be initialised at reset. Attached are the recommend values. Things that say "VRAM Data", "OAM Data", and "CG Data" shouldn't be written to.

(2018/08/29 Edit: attachments removed.)
Re: new to snes environment, have some questions.
by on (#216542)
Oh yeah, one more thing: All addresses and lengths on the PPU are specified in 16-bit words. 0x2000 bytes = 0x1000 words, “byte address” 0x6000 = “word address” 0x3000, and so on.
Re: new to snes environment, have some questions.
by on (#216544)
Optiroc wrote:
Oh yeah, one more thing: All addresses and lengths on the PPU are specified in 16-bit words. 0x2000 bytes = 0x1000 words, “byte address” 0x6000 = “word address” 0x3000, and so on.

It's true that VRAM addresses represent a number of words rather than bytes, so it's something to keep in mind for when you set $2116/$2117 to choose the start of where to transfer to.

However, they are correct in setting $4305/$4306 to $00 and $20, because DMA counts in bytes rather than transfer units.
Re: new to snes environment, have some questions.
by on (#216644)
Ok, I'm away from my laptop till tonight, but I'm making progress.

I redid the snes initialization routine, then after that (using DMA) I was able to load and store palettes into the CGRAM.

After that, again using DMA, I was able to load and store my tileset at address $0000 in VRAM.

Then, I started reading up on how the tile maps coexist within the VRAM, and you have to set addresses for them. So I was able to create addresses for the 4 BG layers, starting at $A000, then the following 3 are at $B000, $C000, $D000.

Then manually, I started inserting one tile id into each of the 4 tile maps. I haven't messed with the properties of palettes, priority, flip, but with all 4 BG modes enabled, I was able to see the 4 tiles on 4 different bg's on screen! :-)

I'll post my code tonight, to see if there is stuff that is not needed, or missing.

But, with all of that said, I do have a question regarding the 2bpp/4bpp graphics.

I'm using 2bpp tile graphics. Now again this is all new to me, so I may have done this wrong. I used YY-CHR, to copy a tileset from an NES rom, and I pasted it within my SNES test rom. Now, when the tileset is injected into the VRAM, the 2bpp mode shows my tiles as "every-other", meaning from left to right, 1 8x8 tile is present, the next is blank, the next 8x8 tile is present, the next is blank. This goes on and on. But within 4bpp mode, my tilset looks correctly like it should, all together.

What am I missing/doing wrong with the gfx?

Thanks! :-)
Re: new to snes environment, have some questions.
by on (#216648)
infidelity wrote:
I'm using 2bpp tile graphics. Now again this is all new to me, so I may have done this wrong. I used YY-CHR, to copy a tileset from an NES rom, and I pasted it within my SNES test rom. Now, when the tileset is injected into the VRAM, the 2bpp mode shows my tiles as "every-other", meaning from left to right, 1 8x8 tile is present, the next is blank, the next 8x8 tile is present, the next is blank. This goes on and on. But within 4bpp mode, my tilset looks correctly like it should, all together.

What am I missing/doing wrong with the gfx?

The graphics you've created is 4bpp tile data (albeit only using the first 2 planes). In VRAM 4bpp tiles is laid out exactly like that – two 2bpp tiles back to back. 8bpp tiles are laid out as four 2bpp tiles in sequence (although you don't see these used too often).

So I suppose you need to fiddle with the save/export settings of the tool you're using to make sure you export 2bpp data.
Re: new to snes environment, have some questions.
by on (#216652)
The 2bpp option may be called "Game Boy" in the tool you use.
Re: new to snes environment, have some questions.
by on (#216653)
I know I've seen a window in yy-chr, where you are able to change the bpp view.

So am I correct with this thinking...

Open snes rom, change the view to 2bpp, paste the tiles I want into the snes rom, and while the view is still set at 2bpp, I then save the rom?

Thanks! :-)
Re: new to snes environment, have some questions.
by on (#216664)
Excellent! I changed it to 2bpp GameBoy, saved the gfx, and when I loaded up bsnes, 2bpp displayed correctly. :-)
Re: new to snes environment, have some questions.
by on (#216726)
Is there a program that can take an NES palette id, and concert it to snes bits? I've wasted hours trying to mimic the colors from the nes. Idk if there's already a conversion table on the Internet? Thanks!
Re: new to snes environment, have some questions.
by on (#216731)
Do you want exact or good enough? For good enough, you could take the RGB values out of an image built with an NES palette generation tool and convert them from 8bpc to 5bpc.
Re: new to snes environment, have some questions.
by on (#216734)
Find any emulator that uses .pal files (example: FCEUX; see Palettes\ directory). Here is the file format. Pick one that you think best represents the NES. Nice and easy.
Re: new to snes environment, have some questions.
by on (#216740)
I'd like to do exact nes colors on the snes. Also the palette viewer in bsnes displays incorrect colors when creating the colors. If I try designing a color by watching the main game screen, I'll get an incorrect color block in the viewer. If I try creating a color within the palette viewer, then the main screen shows an incorrect color. I tried eyeballing it but that is taking a long time for me to do.

I will try what you two just suggested. Thanks for the help/guidance!
Re: new to snes environment, have some questions.
by on (#216748)
If you really want "exact" color matching to where a user can't ABX the difference between pixels from the NES and Super NES on the same monitor even if he tries, you'll need to dive into the pit that is NTSC: Never The Same Color.

You claim that colors look right on a flat screen but look wrong in detailed pixel art but vice versa. One problem you might be running into is that colors of adjacent pixels mix in occasionally nonintuitive ways. This is in part due to the limited bandwidth of the NTSC chroma subcarrier and the shortcuts taken by the NES and Super NES to generate an NTSC-compatible signal with little silicon. They might even be mixing slightly differently on NES and Super NES or even between resets on the same console. And because you mentioned emulators, you might also be seeing the effect of your TV and computer monitor being set to different brightness, contrast, or color (saturation, tint) settings.

For "exact", you'll probably need a setup involving an oscilloscope to determine which Super NES RGB triplet's output waveform after NTSC encoding has a center level, phase, and amplitude (after low pass filtering) closest to each of the distinct NES colors. And you'll want to look at these waveforms after low pass filtering in order to take into account the difference between the NES's square wave chroma waveform and the Super NES S-ENC/S-RGB's presumably sinusoid chroma waveform.


EDIT: Expanded the lead sentence to clarify how I had interpreted the word "exact" in infidelity's prior post
Re: new to snes environment, have some questions.
by on (#216759)
I remember hearing talk about how the NES's square color carrier has some kind of slew rate distortion where $1x and $2x colors get hue shifted because the saturation is higher than $0x and $3x colors. Is that caused by the NES's circuitry, or because of the TV's circuitry, and if the former, how much specific math do we know about it?
Re: new to snes environment, have some questions.
by on (#216761)
Results from NewRisingSun show that $3x gets shifted even more than $2x. The highest brightnesses are shifted "up" the rainbow, so to speak. Thus it appears not to be slew rate (delay based on difference from old level) as much as output impedance (delay based on amount of current flowing through the chip).
Re: new to snes environment, have some questions.
by on (#216763)
Note: my reply is off topic.

tepples, you have been blessed with an extremely brilliant mind. You understand deeply about: NES color, SNES color, and NES music; how to tackle the conveluded, to me at least, task that infidelity must follow to accomplish exact NES colors on a SNES; valid_left and visible_left scrolling wisdom. Sometimes your posts impress me so much; my brain is just overloaded; keep up the good work. :)
Re: new to snes environment, have some questions.
by on (#216765)
@infidelity -- ignore all of the above hemming and hawing over NTSC subcarriers, adjacent pixels, saturation/tint, chroma waveforms, colour carriers, etc.. Don't think about that stuff right now -- it's extremely complicated and you will spend way too much time trying to comprehend it vs. staying the course. It's just another example of how quickly a thread can de-rail, despite everyone's positive intentions. (The info is relevant and valid, but it's complete overkill to try and learn right now)

You can certainly get similar or identical colours to the NES on the SNES, though there may be some slight variances given RGB vs. NTSC. The RGB values you're looking for are in those .pal files. Stay focused! :-)

This thread is one of the most enjoyable I've read in years. It's almost like seeing myself back in the early 90s when I was writing my SNES docs. I've told this story before somewhere, but I still remember the very first time I got text up on the screen in mode 0, followed by multi-coloured text, followed by multiple panning backgrounds. Hours and hours and hours of assembling + copying file to floppy + shoving it into an MGH + waiting + rinse lather repeat. That feeling of accomplishment you have? I remember it vividly -- it's worth it. Never forget that feeling.

Keep it up!
Re: new to snes environment, have some questions.
by on (#216809)
Thanks koitsu! I haven't had a chance to get back to my test rom, I work 55/60 hours a week, so my free time is extremely limited, but tonight I should he able to get back to toying around. :-) I've been thinking about getting back to it alot this week. It's very exciting stuff! And from all he palette responses, I'm hoping get to get "near" the nes colors. Because what I'm doing right now is seeing how the bg layers look when I insert the tiles, and I want them to match color-wise how they appear on the nes. So I've been altering the bits via hex, but I've wasted so much time, so I'll grab the .pal you referenced and see if that helps in me setting the correct sets of bits.

I want to get that down before I venture to the other awesome functions of the system. :-)
Re: new to snes environment, have some questions.
by on (#216834)
I'll try to explain the .pal file stuff and why it's a bit tricky (read: why you can't just take a raw .pal file and use it for CGRAM data on the SNES), but I'll provide a useful resource.

NES emulator .pal files are intended for emulators running on PCs/systems offering at minimum 24-bits colour. Most today are 32-bit.

The .pal file is formatted like this:

Byte 0 = Palette entry/colour #0 red
Byte 1 = Palette entry/colour #0 blue
Byte 2 = Palette entry/colour #0 green
Byte 3 = Palette entry/colour #1 red
Byte 4 = Palette entry/colour #1 blue
Byte 5 = Palette entry/colour #1 green
...going all the way up to palette entry/colour #63.

A byte per colour (red, green, blue) means that each colour is 8 bits in depth (range: 0 to 255). 8*3 = 24-bit total colour range.

SNES CGRAM, as you've learned, only offers 5-bit colour per red, green, and blue (re: %0BBBBBGGGGGRRRRR). 5*3 = 15-bit total colour range.

I want to be clear about something, because I know some reader (and possibly you) will misunderstand: the NES is not a "24-bit colour depth" system! I don't even want to talk about the "bit depth" of the colours on the NES: it's complicated because of how NTSC works and all that jazz (the stuff I said don't focus on, haha :P). The .pal files are intended for emulators as I said. This is also why in some emulators, instead of using a .pal file, they actually offer real-time NES colour calculation through formulas (some sliders/stuff can adjust it) (FCEUX for example has such: Config -> Palette -> NTSC Color Emulation). It's complicated. That's also why there's a bunch of different .pal files -- everyone thinks the NES's palette/colours look different. NTSC is responsible for a large amount of this, along with huge variances in TVs, plus everyone's TV's "hue" and "tint" knobs were set differently, etc... Everyone sees (and remembers) something a bit different.

So you might be wondering: how can you convert 24-bit RGB colour ranges (like in a .pal file) to the SNES's 15-bit colour range? You can, but there's going to be some loss of "quality", obviously. The Super Famicom Development Wiki actually talks about this exact thing, and how to do it. It gives very clear/excellent examples and formulas, with real values: https://wiki.superfamicom.org/palettes

Don't worry about converting 15-bit colour to 24-bit colour -- what you're interested in is the other way around.

Wrapping your brain around this shouldn't be too bad.
Re: new to snes environment, have some questions.
by on (#216839)
Thank you again koitsu, I have a .pal file, but I cant seem to view the colors R,G,B values within any emulator? It just (which I already know) shows the 8-bit value used for it, from #$00-#$3F.

I don't know what i'm supposed to use exactly to view the file properly?


EDIT, oooh I think I got it figured out, i'm using a hex editor to view the .pal file. And, the values that have A-F in them, I think I figured out how to decipher that to decimal form, and perform the formula, I'm through the first 5 colors of the nes palette, and the colors are matching on the snes palette viewer! I'll report back!
Re: new to snes environment, have some questions.
by on (#216840)
Yes, the .pal files are binary (as I described). You use a hex editor or a tool that can dump a binary file into text in a format you might want.

For things like this, I honestly prefer just a tool that can dump it into some raw ASCII like $a1 $b2 $e0 $74 $22 or whatever. Some assembler suites even come with tools that do this for you. Seeing the data in ASCII as hex values can make your job of comprehending the data easier. An old DOS tool I used for this was called bin2db.exe which literally dumped a raw binary file into ASCII .db $xx statements.

The more you get into game development (esp. on the SNES), the more you are going to find that there is an extensive lack of tools to work with/manipulate data (esp. palettes/colours, images/CHR data, map data, ROM transfer, etc.). There were some back in the early 90s for MS-DOS, but these don't work on present-day systems. I still keep them around though. Most people now just write their own in some other language of their choice. I've complained about this before -- and please don't let this derail the subject of the thread -- but lack of tools is still a tremendous problem.

Some old DOS tools I have from the SNES days:

Code:
1996-11-16  13:04             5,952 BIN2DB.EXE
1997-04-16  18:00             3,157 CHR2PCX.DOC
1997-04-16  18:00            88,806 CHR2PCX.EXE
1996-11-16  08:16            18,960 GFXCONV.EXE
1993-07-12  17:30            37,845 GIF2SNES.EXE
1993-11-24  13:05            47,630 GIF2SOPT.EXE
1997-12-24  09:20            40,960 GRAPHICS.RAW
1993-08-05  09:30             9,025 IPS.EXE
1995-07-16  18:03            10,581 PATCHMK.EXE
1997-04-16  18:00             3,523 PCX2CHR.DOC
1997-12-30  15:57           150,016 PCX2CHR.EXE
1998-03-07  16:22             7,328 readchar.exe
1984-12-13  17:51            14,054 SGIF.EXE
1995-04-11  14:47             8,913 SGR.EXE
1996-01-01  11:39            11,185 SNESTL12.DOC
1999-01-11  16:27            23,978 SNESTL12.EXE
1980-01-14  10:22            15,775 TLAYER.EXE
1980-01-14  06:28                48 TLAYER.PAL
1980-01-15  06:55             7,439 TLAYER.TXT
1997-04-24  11:13            11,288 TRACER.DOC
1997-04-24  11:08            12,432 TRACER.EXE
1996-01-02  08:34            38,447 TSF.EXE
1996-01-02  08:34            19,968 TSF2.EXE
1994-07-18  18:40            55,834 UCON.EXE
1995-11-08  15:15            18,337 UCON14.DOC
1999-01-11  16:23            93,126 VGS.EXE
1997-04-10  17:10            40,766 x816.doc
1997-04-09  10:40            84,672 X816.EXE
Re: new to snes environment, have some questions.
by on (#216851)
Yeah I still have the DOS tools form yore. I'm thinking that I might just have to set up my P133/Win95 box that I did my SNES work on back in the day in a permanent fashion if I'm going to do solid SNES work. And Find a copy of VS C++ 6.0 and back port my new tools to it...

I wonder if VirtualBox works with a USB disk drive and can support win95 VM... hmmm
EDIT : It does, bit of a pain to get it "just so" but seems to work fine ;)
Re: new to snes environment, have some questions.
by on (#216866)
Got the .pal values converted. A little darker than what i'm used to, but I still like it! :-)

https://imgur.com/a/3gIQ5

Now to further expand my learning of the system. :-)
Re: new to snes environment, have some questions.
by on (#216873)
Looks awesome! And yeah, they'll look slightly different due to the whole SNES RGB vs. NES HSV (hue/saturation/value/luma) aspect.

Nice chart, BTW. For readers: the SNES colour hex values shown are in low-byte-high-byte ordering, i.e. the order they'd be written to via $2122. I only mention this because when I first glanced them, I was like "$f75e?! That has the MSB set! No no no... oh, wait, he wrote them in L/H order..." :-)
Re: new to snes environment, have some questions.
by on (#216874)
Thanks! :-D yeah took me about 2 hours with all the conversions, my laptop gets a bit finicky, and different values would pop up when I was typing, so I just really took my time with them. :-)

I just inserted a working joy pad routine, and can see all the buttons functioning within the RAM. :-)

So my next thing I'm trying to get going, is getting sprites to be displayed. I'm trying to manually insert them via the memory viewer for the OAM, but nothing is happening. I'm assuming I'm missing a register to enable or something?

Having a blast with this thus far! :-)
Re: new to snes environment, have some questions.
by on (#216875)
Im really late to the topic :( but earlier you said something about no way to see RGB values for a nes palette.
and i wanted to show that the Nestopia emulator lets you see those 0 to 255 numbers on any individual color like this:

Image
Re: new to snes environment, have some questions.
by on (#216882)
I must've overlooked that with Nestopia! That's what I was trying to find, thanks for showing that! I was able to convert the default fceux.pal file to snes values, now to just get sprites to display on screen.

And how come I can't get my imgur uploads to display within the thread? I'm using the [ /img ] brackets, so weird...

Anyway, back to figuring out the sprites.
Re: new to snes environment, have some questions.
by on (#216886)
For sprites, there's a tutorial on that suited for people who are familiar with NES sprites and are trying SNES: https://wiki.superfamicom.org/how-to-display-sprites

More specific details about the OAM format and general use, including some MMIO registers for OAM access and "when" it's OK to update OAM: https://wiki.superfamicom.org/sprites

And don't forget about general purpose DMA for all of this (palette, OAM, etc.).

In general:

You write to $2101 to select the CHR data address in PPU RAM for the sprites, and the sprite sizes (bits 7-5). Bits 4-0 for the former are a bit confusing and too much to cover here. Bit 2 should always be 0, by the way.

You write to $2102 and $2103 (or just a 16-bit write to $2102) to define where in OAM memory you want to write to (via $2104). Bits 8-0 define the address, and bit 15 has to do with OAM priority shifting. Bits 9-14 are unused/set them to 0.

$2104 is write-only an 8-bit double-write register (i.e. it's like $2122 but for OAM).

$2102 through $2014 can only be written do during VBlank or forced blank; so your NMI handler should do your OAM updates.

$2138 is identical to $2104, but for reading OAM data.

Which graphics mode you're in also plays a role with regards to sprite visibility. There's 2 bits (thus range 0-3) in the OAM data that control if the sprite in question should be displayed in front of or behind some backgrounds (and which BG number matters). This is a complicated topic too because of how many "layers" there are, and gets even more complicated when you start getting into main vs. sub screens or "windowing", as well as interlaced modes.

I've attached a screenshot from the official manual which depicts background vs. sprite ordering, as well as register descriptions and PPU RAM layout. I'm pretty sure there are better documents describing the BG/OBJ layering, though. And the PPU RAM layout document will probably confuse the hell out of you -- think back to earlier in this thread about the term "word", because it's used heavily.

Oh, and I'll include a couple pages about $213e too -- specifically bits 7 and 6 ("time over" and "range over"). As someone who did NES stuff, you'll probably understand them, re: too many sprites per scanline.

Edit: forgot to mention: like the NES, sprites with lower index numbers have higher priority (will be shown atop) than those with higher index numbers

(2018/08/29 Edit: attachments removed.)
Re: new to snes environment, have some questions.
by on (#216887)
(2018/08/29 Edit: attachments removed.)
Re: new to snes environment, have some questions.
by on (#216888)
(2018/08/29 Edit: attachments removed.)
Re: new to snes environment, have some questions.
by on (#216891)
Quote:
$2102 through $2014 can only be written do during VBlank or forced blank

EDIT/DELETE: You mean $2102 through $2104, right? I wrote a whole post based on the premise that you meant $2114, but I suspect said premise was faulty, so I've removed it...
Re: new to snes environment, have some questions.
by on (#216914)
In my own words:

OBJ CHR RAM, or sprite tile memory

OBJ CHR RAM is in VRAM. It consists of two windows, each 256 tiles or 4K words or 8 KiB in size. At any given moment, the sprite unit can see 512 tiles: 256 from the first window and 256 from the second.

PPU port $2101 contains four bits that control the starting position of these windows. The first begins at an 8K word boundary: $0000, $2000, $4000, or $6000. The second is 4K, 8K, 12K, or 16K words ($1000, $2000, $3000, or $4000) higher, with wraparound from $7FFF to $0000. Thus there are 16 possibilities:

$0000 and $1000, $2000, $3000, or $4000
$2000 and $3000, $4000, $5000, or $6000
$4000 and $5000, $6000, $7000, or $0000
$6000 and $7000, $0000, $1000, or $2000

For example, when these are set to $4000 and $6000, OBJ tiles 0-255 come from $4000-$4FFF, and OBJ tiles 256-511 come from $6000-$6FFF.

With careful programming, it should be possible to address 768 tiles, some of which appear only in the top of the screen, some in the bottom, and some throughout. You might store tiles used throughout in $4000-$4FFF, tiles used on top in $5000-$5FFF, and tiles used on bottom in $6000-$6FFF. Then set $2101 during vertical blanking to use $4000 and $5000, and set an HVIRQ or HDMA to change $2101 to use $4000 and $6000 part-way down the screen.

Tiles in both OBJ CHR data and 4bpp BG CHR data are 16 words apart. Slivers (8x1-pixel rows) within a tile are 1 word apart, and pairs of bit planes within a sliver are 8 words apart. Thus row Y (0-7) of a given tile whose base address is X ($0000-$7FF0) has its four bit planes arranged as follows:

0: Word X+Y, low byte
1: Word X+Y, high byte
2: Word X+Y+8, low byte
3: Word X+Y+8, high byte

The horizontal position of a sprite is a 9-bit two's complement signed quantity: 0-255 if the corresponding X bit in high OAM is 0, or -256 to -1 if the X bit in high OAM is true. There is a hardware bug where a sprite at X=-256 still counts toward the limit of 32 sprites on a scanline, just as if it were at X=0. It's better to fully hide such sprites by parking them at Y=225, just below the visible portion of the screen (usually Y=1 to 224).

A sprite larger than 8x8 pixels is displayed using consecutive tile numbers (horizontally) and tile numbers 16 apart (vertically).

Layer priority

Layer priority from front to back in modes 0 and 1:

BG3 tiles with tilemap priority 1 (if in mode 1 with HUD in front enabled)
Priority 3 sprites
BG1 tiles with tilemap priority 1
BG2 tiles with tilemap priority 1
Priority 2 sprites
BG1 tiles with tilemap priority 0
BG2 tiles with tilemap priority 0
Priority 1 sprites
BG3 tiles with tilemap priority 1
BG4 tiles with tilemap priority 1
Priority 0 sprites
BG3 tiles with tilemap priority 0
BG4 tiles with tilemap priority 0
Backdrop

Layer priority from front to back in modes 2 through 7:

Priority 3 sprites
BG1 tiles with tilemap priority 1
Priority 2 sprites
BG2 tiles with tilemap priority 1
Priority 1 sprites
BG1 tiles with tilemap priority 0
Priority 0 sprites
BG2 tiles with tilemap priority 0
Backdrop

The background priority stack is split into two half-stacks. In modes 0 and 1, BG1 and BG2 are in the top half-stack, and BG3 and BG4 are in the bottom (except with HUD in front in mode 1). In particular, BG3 cannot normally be placed between BG1 and BG2, though this can be faked with windowing or color math. In modes 2 through 6, tilemap priority directly chooses a half-stack. Mode 7 has tilemap priority 0.

Priority between sprites is determined before comparing them against backgrounds. This means that if a sprite with a lower OAM index and a lower priority value overlaps a sprite with a higher OAM index and higher priority, the low-index sprite is visible in the overlap area. This can cause the low-index sprite to "cut out" portions the high-index sprite, letting the background show through.

Capacity of the sprite unit

For each scanline, the S-PPU considers up to 32 lowest-index sprites overlapping the line, not counting sprites in X=-255 through X=-width. (Due to a hardware bug, sprites with X=-256 are counted.) Among these 32, called the in-range set, up to 34 slivers are displayed, not counting slivers to the left or right of the screen. There is a hardware bug in the overflow behavior when the 32 sprites have more than 34 slivers. The slivers chosen are those of the highest-index sprites among the in-range set. This causes a visible difference if at least one sprite is 32x32 pixels or larger, or if at least three sprites are 16x16 pixels or larger.

If more than 32 sprites or 34 slivers are in range on a given line, the S-PPU sets flags in port $213E for the remainder of that frame and clears them to 0 at the end of vertical blanking. It sets bit 6 for too many sprites and bit 7 for too many slivers.

Your software can use these flags to trigger reshuffling of sprites within OAM, so that excess sprites flicker instead of dropping out entirely. If your software fills OAM from front to back each frame, this can be done by drawing game objects in a pseudorandom order. Or if sprite-to-sprite priority is not important for your software, you can use hardware-accelerated reshuffling. Set bit 7 to $2103 to true, and during vertical blanking, write an OAM index to bits 7-1 of $2102 that varies from one frame to the next. This moves sprites X through 127 to the front of the sprite stack and sprites 0 through X-1 to the back, as if their OAM index were 128 through X+127.
Re: new to snes environment, have some questions.
by on (#216922)
tepples wrote:
Then set $2101 during vertical blanking to use $4000 and $5000, and set an HVIRQ or HDMA to change $2101 to use $4000 and $6000 part-way down the screen.

HDMA is not recommended for this. Sprite graphics are pulled from VRAM during HBlank, and changing the OBJ data offsets with HDMA would interrupt this process, likely resulting in glitching. I believe this may be what's occurring in First Try by Magical, which I have confirmed uses HDMA for this (look at the right hand side of the screen, about halfway down, once the mountain shows up - after a few seconds there's a flickery bit).

I've tried using an HV-IRQ to ensure that the write to $2101 happens mid-scanline, while the PPU is scanning OAM, so that when it goes to look for the actual graphics after the line is finished, it picks up all of them from the new VRAM locations. This seems to work without glitches on real hardware, even with a fully-loaded 34-tile line.

I haven't thoroughly exercised this trick myself yet, but supposedly there's at least one commercial game that changes $2101 mid-screen, so I hope my results aren't a fluke.

Quote:
It's better to fully hide such sprites by parking them at Y=225, just below the visible portion of the screen (usually Y=1 to 224).

Unless you're using 64x64 sprites (which you usually won't be) on NTSC (EDIT: or 32x32 on PAL), in which case VBlank the gap between the last displayed line and the maximum Y coordinate is too short to hide the whole sprite and it will wrap around to the top of the screen. Generally hiding sprites with Y is better, but watch out for this edge case.
Re: new to snes environment, have some questions.
by on (#216923)
Wow, I cannot thank you all for the abundance of information with the OAM!

However I'm having an issue. For some reason I cannot move any of the 128 sprites? Currently I set all of the Y positions to E0. But with doing that, I still have a random sprite at the upper left of the screen? I cannot seem to move them?

When I have the Sprite Viewer open, I can see the 128 sprites, i'm able to edit all of the 4 bytes for those 128 sprites, and see the changes. But nothing appears on screen?

I have $212C set to enable sprites, and BG 1 enabled. And for $2101, I do LDA #$01 STA $2101.

Now, all these tests are all within my reset vector, i'm not trying to run any type of program, everything is me testing things with the system. So right now I don't have anything being written & stored into the OAM, I'm simply editing them through the Memory Viewer on the fly.

What am I missing, doing wrong? Thank you everyone!

Image
Re: new to snes environment, have some questions.
by on (#216924)
Maybe I'm misunderstanding you, but:

I haven't used this feature of the debugger, but my guess is that if you change sprite details in the Sprite Viewer, you won'tsee changes in real-time, only after the next VBlank completes. That's how the console works.

It could also be a quirk/bug in the debugger. The debugger has had a long history of this type of stuff (I say that without negative judgement); there are always edge cases that have to be looked at. "Wait, do we want this actually be reflected visually on-screen immediately or only when the console actually reads from OAM + renders sprites?" What the behaviour *should* be vs. what the user *wants* are often two different things. For stuff like this, filing a GitHub Issues to ask devinacker is usually the best choice of action; he's super cool and nice.

The "Auto-update" checkbox means to automatically update the contents of the Sprite Viewer window when underlying 65816 code issues changes to OAM (and probably PPU RAM data for CHR).

In short: you need to start writing code.
Re: new to snes environment, have some questions.
by on (#216925)
93143 wrote:
Quote:
It's better to fully hide such sprites by parking them at Y=225, just below the visible portion of the screen (usually Y=1 to 224).

Unless you're using 64x64 sprites (which you usually won't be) on NTSC, in which case VBlank is too short to hide the whole sprite

All sprite size combinations including 64x64 also have 32x32 or smaller, and a 32x32 sprite at Y=225 occupies lines 225-255 (invisible) and 0 (also invisible). The wraparound problem with 32x32 and 64x64 mode comes not on NTSC but on PAL, where 239-line mode is expected. But again, you usually won't be using 64x64 anyway.
Re: new to snes environment, have some questions.
by on (#216927)
Right. I had confused myself slightly.

Still, the fact that you can make 64x64 sprites fit on NTSC by downsizing them doesn't really address the issue, because (a) you have to remember to do that, which is really the only reason anybody mentions the sprite-wrapping issue at all as it's easy to work around, and (b) if you have to change both the main coordinate and the high-table data, you might just as well use X.
Re: new to snes environment, have some questions.
by on (#216986)
Ok, I think I got the sprites working! I have $800 in ram, as the region that loads the sprites that are stored into OAM.

But I'm facing another weird issue. I was able to select the base in vram where the 1st OAM set of sprite tiles is located. I forget the address, but I have it set to 01. Which makes the first oam address in vram to $4000, and the 2nd OAM address $6000. My sprite tiles are at $4000.

So all of that was working perfectly. But I decided to shift code out of the reset vector, (again all I've been doing is testing code to see results, I'm not building a game or demo yet) and have it run within the NMI instead.

Now, I set $4200 I think, (I'm at work) with 80, to enable an NMI, I have that code at the end of my reset vector, then I have an infinite jmp.

The NMI address kicks on, and within that I have my sprite OAM being loaded and stored, and a functional joypad routine. I do not know if I'm supposed to have all the pushes and pulls of the stack like the NES does at the beginning and end of its NMI, I don't have that.

So what happens is, my OAM base for vram is only pointing at $0000 & $2000? I even alter the bits for the base addresses manually while the code is being ran, but the addresses do not change when I view the vram viewer?

Any ideas?

Thanks everyone! :-)
Re: new to snes environment, have some questions.
by on (#216991)
Yes, you need the pushes. In fact, you may need even more pushes than on NES because of more registers: B for data bank and D for frame pointer/direct page being the big ones.
Re: new to snes environment, have some questions.
by on (#216995)
OK I'll add them. And do you think that's the reason why I can't alter the base addresses for my OAM locations in vram?
Re: new to snes environment, have some questions.
by on (#217005)
We wouldn't have any way of knowing that without looking at full source code + putting in the time for a full debugging session. That's all you right now, esp. since you had it working. ;-)
Re: new to snes environment, have some questions.
by on (#217011)
Ok. :-) What I have so far...
Code:
;initialize snes
008000 sei                    A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nv1BdIzc V:  0 H: 46 F: 0
008001 clc                    A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nv1BdIzc V:  0 H: 50 F: 0
008002 xce                    A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nv1BdIzc V:  0 H: 53 F: 0
008003 jml $808007   [808007] A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMXdIzC V:  0 H: 57 F: 0
808007 rep #$10               A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMXdIzC V:  0 H: 65 F: 0
808009 sep #$20               A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  0 H: 70 F: 0
80800b lda #$8f               A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  0 H: 76 F: 0
80800d sta $2100     [002100] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H: 80 F: 0
808010 stz $2101     [002101] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H: 87 F: 0
808013 stz $2102     [002102] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H: 95 F: 0
808016 stz $2103     [002103] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:102 F: 0
808019 stz $2105     [002105] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:110 F: 0
80801c stz $2106     [002106] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:117 F: 0
80801f stz $2107     [002107] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:125 F: 0
808022 stz $2108     [002108] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:132 F: 0
808025 stz $2109     [002109] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:150 F: 0
808028 stz $210a     [00210a] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:157 F: 0
80802b stz $210b     [00210b] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:165 F: 0
80802e stz $210c     [00210c] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:172 F: 0
808031 stz $210d     [00210d] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:180 F: 0
808034 stz $210d     [00210d] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:187 F: 0
808037 stz $210e     [00210e] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:195 F: 0
80803a stz $210e     [00210e] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:202 F: 0
80803d stz $210f     [00210f] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:210 F: 0
808040 stz $210f     [00210f] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:217 F: 0
808043 stz $2110     [002110] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:225 F: 0
808046 stz $2110     [002110] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:232 F: 0
808049 stz $2111     [002111] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:240 F: 0
80804c stz $2111     [002111] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:247 F: 0
80804f stz $2112     [002112] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:255 F: 0
808052 stz $2112     [002112] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:262 F: 0
808055 stz $2113     [002113] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:270 F: 0
808058 stz $2113     [002113] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:277 F: 0
80805b stz $2114     [002114] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:285 F: 0
80805e stz $2114     [002114] A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:292 F: 0
808061 lda #$80               A:008f X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:300 F: 0
808063 sta $2115     [002115] A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:304 F: 0
808066 stz $2116     [002116] A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:311 F: 0
808069 stz $2117     [002117] A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:319 F: 0
80806c stz $211a     [00211a] A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:326 F: 0
80806f stz $211b     [00211b] A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  0 H:333 F: 0
808072 lda #$01               A:0080 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:  0 F: 0
808074 sta $211b     [00211b] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:  4 F: 0
808077 stz $211c     [00211c] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 12 F: 0
80807a stz $211c     [00211c] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 19 F: 0
80807d stz $211d     [00211d] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 27 F: 0
808080 stz $211d     [00211d] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 34 F: 0
808083 stz $211e     [00211e] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 42 F: 0
808086 sta $211e     [00211e] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 49 F: 0
808089 stz $211f     [00211f] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 57 F: 0
80808c stz $211f     [00211f] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 64 F: 0
80808f stz $2120     [002120] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 72 F: 0
808092 stz $2120     [002120] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 79 F: 0
808095 stz $2121     [002121] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 87 F: 0
808098 stz $2123     [002123] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H: 94 F: 0
80809b stz $2124     [002124] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:102 F: 0
80809e stz $2125     [002125] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:109 F: 0
8080a1 stz $2126     [002126] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:117 F: 0
8080a4 stz $2127     [002127] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:124 F: 0
8080a7 stz $2128     [002128] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:132 F: 0
8080aa stz $2129     [002129] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:149 F: 0
8080ad stz $212a     [00212a] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:157 F: 0
8080b0 stz $212b     [00212b] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:164 F: 0
8080b3 stz $212c     [00212c] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:172 F: 0
8080b6 stz $212d     [00212d] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:179 F: 0
8080b9 stz $212e     [00212e] A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:187 F: 0
8080bc lda #$30               A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:194 F: 0
8080be sta $2130     [002130] A:0030 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:198 F: 0
8080c1 stz $2131     [002131] A:0030 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:206 F: 0
8080c4 lda #$e0               A:0030 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  1 H:213 F: 0
8080c6 sta $2132     [002132] A:00e0 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:217 F: 0
8080c9 stz $2133     [002133] A:00e0 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:225 F: 0
8080cc stz $4200     [004200] A:00e0 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:232 F: 0
8080cf lda #$ff               A:00e0 X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:240 F: 0
8080d1 sta $4201     [004201] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:244 F: 0
8080d4 stz $4202     [004202] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:251 F: 0
8080d7 stz $4203     [004203] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:259 F: 0
8080da stz $4204     [004204] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:266 F: 0
8080dd stz $4205     [004205] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:274 F: 0
8080e0 stz $4206     [004206] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:281 F: 0
8080e3 stz $4207     [004207] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:289 F: 0
8080e6 stz $4208     [004208] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:296 F: 0
8080e9 stz $4209     [004209] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:304 F: 0
8080ec stz $420a     [00420a] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:311 F: 0
8080ef stz $420b     [00420b] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:319 F: 0
8080f2 stz $420c     [00420c] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:326 F: 0
8080f5 stz $420d     [00420d] A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  1 H:333 F: 0

;here i'm loading and storing to CGRAM using DMA
8080f8 lda #$00               A:00ff X:0000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  2 H:  0 F: 0
8080fa sta $2121     [002121] A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIZC V:  2 H:  4 F: 0
8080fd lda #$01               A:0000 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIZC V:  2 H: 12 F: 0
8080ff ldx #$ce00             A:0001 X:0000 Y:0000 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 16 F: 0
808102 ldy #$0200             A:0001 X:ce00 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V:  2 H: 22 F: 0
808105 stx $4302     [004302] A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 28 F: 0
808108 sta $4304     [004304] A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 37 F: 0
80810b sty $4305     [004305] A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 44 F: 0
80810e stz $4300     [004300] A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 53 F: 0
808111 lda #$22               A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 61 F: 0
808113 sta $4301     [004301] A:0022 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 65 F: 0
808116 lda #$01               A:0022 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 72 F: 0
808118 sta $420b     [00420b] A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 76 F: 0

;here i'm loading 2bpp bg tiles into VRAM using DMA
80811b lda #$80               A:0001 X:ce00 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  2 H: 84 F: 0
80811d sta $2115     [002115] A:0080 X:ce00 Y:0200 S:01ff D:0000 DB:00 NvMxdIzC V:  5 H:127 F: 0
808120 ldx #$0000             A:0080 X:ce00 Y:0200 S:01ff D:0000 DB:00 NvMxdIzC V:  5 H:144 F: 0
808123 stx $2116     [002116] A:0080 X:0000 Y:0200 S:01ff D:0000 DB:00 nvMxdIZC V:  5 H:150 F: 0
808126 lda #$01               A:0080 X:0000 Y:0200 S:01ff D:0000 DB:00 nvMxdIZC V:  5 H:159 F: 0
808128 ldx #$d000             A:0001 X:0000 Y:0200 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:163 F: 0
80812b ldy #$1000             A:0001 X:d000 Y:0200 S:01ff D:0000 DB:00 NvMxdIzC V:  5 H:169 F: 0
80812e stx $4302     [004302] A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:175 F: 0
808131 sta $4304     [004304] A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:184 F: 0
808134 sty $4305     [004305] A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:192 F: 0
808137 lda #$01               A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:201 F: 0
808139 sta $4300     [004300] A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:205 F: 0
80813c lda #$18               A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:212 F: 0
80813e sta $4301     [004301] A:0018 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:216 F: 0
808141 lda #$01               A:0018 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:224 F: 0
808143 sta $420b     [00420b] A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:228 F: 0

;here im loading 4bpp sprite gfx into VRAM using DMA
808146 lda #$80               A:0001 X:d000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V:  5 H:235 F: 0
808148 sta $2115     [002115] A:0080 X:d000 Y:1000 S:01ff D:0000 DB:00 NvMxdIzC V: 30 H:162 F: 0
80814b ldx #$2000             A:0080 X:d000 Y:1000 S:01ff D:0000 DB:00 NvMxdIzC V: 30 H:170 F: 0
80814e stx $2116     [002116] A:0080 X:2000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:176 F: 0
808151 lda #$01               A:0080 X:2000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:185 F: 0
808153 ldx #$e000             A:0001 X:2000 Y:1000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:189 F: 0
808156 ldy #$2000             A:0001 X:e000 Y:1000 S:01ff D:0000 DB:00 NvMxdIzC V: 30 H:195 F: 0
808159 stx $4302     [004302] A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:201 F: 0
80815c sta $4304     [004304] A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:210 F: 0
80815f sty $4305     [004305] A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:217 F: 0
808162 lda #$01               A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:226 F: 0
808164 sta $4300     [004300] A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:230 F: 0
808167 lda #$18               A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:238 F: 0
808169 sta $4301     [004301] A:0018 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:242 F: 0
80816c lda #$01               A:0018 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:249 F: 0
80816e sta $420b     [00420b] A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:253 F: 0

;this code i think i'm doing incorrectly, i think i was tyring to set the addresses in vram for BG's 1-4... the more i look at this, i feel this is incorrect....
808171 lda #$00               A:0001 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 30 H:261 F: 0
808173 sta $2105     [002105] A:0000 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIZC V: 80 H: 95 F: 0
808176 lda #$0f               A:0000 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIZC V: 80 H:102 F: 0
808178 sta $2106     [002106] A:000f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:106 F: 0
80817b lda #$51               A:000f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:114 F: 0
80817d sta $2107     [002107] A:0051 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:118 F: 0
808180 lda #$58               A:0051 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:125 F: 0
808182 sta $2108     [002108] A:0058 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:129 F: 0
808185 lda #$60               A:0058 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:147 F: 0
808187 sta $2109     [002109] A:0060 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:151 F: 0
80818a lda #$68               A:0060 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:158 F: 0
80818c sta $210a     [00210a] A:0068 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:162 F: 0
80818f stz $210b     [00210b] A:0068 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:170 F: 0
808192 lda #$1f               A:0068 X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:177 F: 0
808194 sta $212c     [00212c] A:001f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:181 F: 0
808197 sta $212d     [00212d] A:001f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:189 F: 0
80819a lda #$0f               A:001f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:196 F: 0
80819c sta $2100     [002100] A:000f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:200 F: 0

;my routine to wipe out snes ram $0000-$1FFF
80819f rep #$10               A:000f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:208 F: 0
8081a1 ldy #$1fff             A:000f X:e000 Y:2000 S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:213 F: 0
8081a4 lda #$00               A:000f X:e000 Y:1fff S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:219 F: 0
8081a6 sta $0000,y   [001fff] A:0000 X:e000 Y:1fff S:01ff D:0000 DB:00 nvMxdIZC V: 80 H:223 F: 0
8081a9 dey                    A:0000 X:e000 Y:1fff S:01ff D:0000 DB:00 nvMxdIZC V: 80 H:233 F: 0
8081aa bne $81a6     [8081a6] A:0000 X:e000 Y:1ffe S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:236 F: 0
8081a6 sta $0000,y   [001ffe] A:0000 X:e000 Y:1ffe S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:242 F: 0
8081a9 dey                    A:0000 X:e000 Y:1ffe S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:251 F: 0
8081aa bne $81a6     [8081a6] A:0000 X:e000 Y:1ffd S:01ff D:0000 DB:00 nvMxdIzC V: 80 H:255 F: 0
8081ac sta $0000     [000000] A:0000 X:e000 Y:0000 S:01ff D:0000 DB:00 nvMxdIZC V: 81 H:121 F: 0

;my preperation for OAM at $800 in RAM, have all Y positions set to #$E0
8081af ldy #$0000             A:0000 X:e000 Y:0000 S:01ff D:0000 DB:00 nvMxdIZC V: 81 H:129 F: 0
8081b2 lda #$e0               A:0000 X:e000 Y:0000 S:01ff D:0000 DB:00 nvMxdIZC V: 81 H:145 F: 0
8081b4 sta $0801,y   [000801] A:00e0 X:e000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V: 81 H:149 F: 0
8081b7 iny                    A:00e0 X:e000 Y:0000 S:01ff D:0000 DB:00 NvMxdIzC V: 81 H:159 F: 0
8081b8 iny                    A:00e0 X:e000 Y:0001 S:01ff D:0000 DB:00 nvMxdIzC V: 81 H:162 F: 0
8081b9 iny                    A:00e0 X:e000 Y:0002 S:01ff D:0000 DB:00 nvMxdIzC V: 81 H:166 F: 0
8081ba iny                    A:00e0 X:e000 Y:0003 S:01ff D:0000 DB:00 nvMxdIzC V: 81 H:169 F: 0
8081bb cpy #$0200             A:00e0 X:e000 Y:0004 S:01ff D:0000 DB:00 nvMxdIzC V: 81 H:173 F: 0
8081be bne $81b4     [8081b4] A:00e0 X:e000 Y:0004 S:01ff D:0000 DB:00 NvMxdIzc V: 81 H:179 F: 0

;enable nmi, infinte loop at end of reset vector
8081c0 lda #$81               A:00e0 X:e000 Y:0200 S:01ff D:0000 DB:00 nvMxdIZC V: 81 H:288 F: 0
8081c2 sta $4200     [004200] A:0081 X:e000 Y:0200 S:01ff D:0000 DB:00 NvMxdIzC V: 81 H:292 F: 0
8081c5 jmp $81c5     [8081c5] A:0081 X:e000 Y:0200 S:01ff D:0000 DB:00 NvMxdIzC V: 81 H:299 F: 0

;nmi routine
;load OAM table from RAM to OAM with DMA
008230 rep #$10               A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:229 H: 47 F: 0
008232 sep #$20               A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:229 H: 53 F: 0
008234 lda #$00               A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIZC V:229 H: 58 F: 0
008236 sta $2102     [002102] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIZC V:229 H: 62 F: 0
008239 lda #$00               A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIZC V:229 H: 70 F: 0
00823b sta $2103     [002103] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIZC V:229 H: 74 F: 0
00823e ldy #$0400             A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIZC V:229 H: 81 F: 0
008241 sty $4300     [004300] A:0000 X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H: 87 F: 0
008244 stz $4302     [004302] A:0000 X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H: 96 F: 0
008247 lda #$08               A:0000 X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:104 F: 0
008249 sta $4303     [004303] A:0008 X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:108 F: 0
00824c lda #$7e               A:0008 X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:115 F: 0
00824e sta $4304     [004304] A:007e X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:119 F: 0
008251 ldy #$0220             A:007e X:0000 Y:0400 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:127 F: 0
008254 sty $4305     [004305] A:007e X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:133 F: 0
008257 lda #$01               A:007e X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:152 F: 0
008259 sta $420b     [00420b] A:0001 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:156 F: 0

;joypad routine
00825c rep #$32               A:0001 X:0000 Y:0220 S:01fb D:0000 DB:00 nvMxdIzC V:229 H:163 F: 0
00825e lda $4218     [004218] A:0001 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIzC V:232 H:270 F: 0
008261 tax                    A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:279 F: 0
008262 and #$000f             A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:282 F: 0
008265 beq $826a     [00826a] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:288 F: 0
00826a stx $a7       [0000a7] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:294 F: 0
00826c txa                    A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:302 F: 0
00826d eor $a9       [0000a9] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:305 F: 0
00826f and $a7       [0000a7] A:7fff X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIzC V:232 H:313 F: 0
008271 sta $ab       [0000ab] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:321 F: 0
008273 lda $ad       [0000ad] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:328 F: 0
008275 sta $af       [0000af] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:232 H:336 F: 0
008277 lda $421a     [00421a] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H:  4 F: 0
00827a tax                    A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 13 F: 0
00827b and #$000f             A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 17 F: 0
00827e beq $8283     [008283] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 23 F: 0
008283 stx $ad       [0000ad] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 28 F: 0
008285 txa                    A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 36 F: 0
008286 eor $af       [0000af] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 40 F: 0
008288 and $ad       [0000ad] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 48 F: 0
00828a sta $b1       [0000b1] A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:233 H: 56 F: 0

;rti
00828c rti                    A:0000 X:0000 Y:0220 S:01fb D:0000 DB:00 nvmxdIZC V:237 H: 86 F: 0


For some reason, I'm only able to have my OAM base address load correctly if it is constantly read within my reset vector? It doesn't work in my NMI.
Re: new to snes environment, have some questions.
by on (#217038)
Thoughts? :-)
Re: new to snes environment, have some questions.
by on (#217075)
Yes, I have many thoughts, but it will take me literally hours to reverse-engineer that disassembly dump and break it all down, especially without actual graphical data. I remember sprites being particularly annoying/painful/quirky -- I'm having to remember things from 25 years ago and my memory is not what it used to be -- particularly with the "hows" of OAM specification via $2102/2103 and data via $2014. Something in the back of my mind says "are you sure this is identical to PPU RAM methodology?" despite what I said before.

I just started a new job last Monday, so that kind of has priority right now. I wrote up a very long reply last night, but in the end opted to not post it because I felt it was too premature. I am hoping someone else has the time/cycles to look at this in the meantime. There are minor things I noticed *not* relating to OAM/OBJ, but didn't want to get you sidetracked.
Re: new to snes environment, have some questions.
by on (#217078)
Oh I wasn't looking for anyone to reverse engineer or anything like that with the code! I just wanted to know if I'm using the addresses correctly.
Re: new to snes environment, have some questions.
by on (#217081)
Most of my brain "broke" when I was trying to figure out all the DMA parameters vs. the addresses you were transferring from vs. the sizes for OBJ/OAM vs. the format of the data vs. how the MMIO registers are actually accessed.

Page A-3 (I attached it earlier) is frustrating because it's easy to overlook things like how 4 bytes of data are per-sprite (not including X-loc MSB and large/size specifier) when on the left it's showing the indexes as incrementing by 1 (because, again: things are in words / 16-bits).

This, combined with (and I'm not sure I have the right to talk badly about this) good-yet-bad resources on sprites (two examples: https://wiki.superfamicom.org/snes-sprites and https://github.com/michielvoo/SNES/wiki/Sprites), none of which actually cover doing this with DMA in NMI... well... point is, it's obviously a neglected subject. The more I read that 2nd link the more things from 25 years ago "trickled back" into my mind, but nothing definitively came forth. Like I can't explain why the MMIO register model used there writes to $2103 before $2102, and there's some additional math being applied to the sprite index/offset (*2, maybe due to the fact that two 16-bit words represent data for a sprite?). Then there's nocash's resource which talks about how $2102/2103 are re-set at the start of VBlank (note the "Caution" part). This is all stuff that's new to me vs. when I last worked with sprites 25 years ago.

In short: there is no terse way for me to summarise what went through my mind when reviewing that dump of code vs. what the behaviour of the console is.
Re: new to snes environment, have some questions.
by on (#217303)
I appreciate all of your guidance and info koitsu! I ran I to another issue with BG layers.

I'm trying to do another test from scratch, to see if I'm understanding the proper usage of the systems addresses.

I'm unable to have all 4 bg layers appear at once, I think it's $212C that enables/disables all 4.

Now, I have my tileset in vram, starting at $0000. This tileset contains all the tiles of want to use for the 4 bg layers.

So my 4 bg base addresses are all pointing to $0000 in vram.

My tilemaps for all 4 bg layers are in is order, $4000 for bg1, $6000 for bg2, $8000 for bg3, $A000 for bg4.

Using bsnes's debugger, I'm able to view the tilemaps, they correctly displays the vrams base addresses, and tile map addresses.

When I go to the tilemap location for bg1, I manually insert a tile I'd using the hex editor. I see the tile display on the main screen.

I do this for the other 3 tile map addresses, and nothing gets displayed. Bg1 I put the tile I'd at $4000, bg2 at $6002, bg3 at $8004, and bg4 at $A006.

Now here's the thing, the tilemap viewer in bsnes, actually let's you view all 4 bag's tilemaps. And when I view all 4 tilemaps, I see the individual tile that I placed of all 4 bg layers.

What am I missing, or doing wrong? Thanks!
Re: new to snes environment, have some questions.
by on (#217305)
Are you in BG mode 0?

You could also post your source and/or ROM.
Re: new to snes environment, have some questions.
by on (#217306)
I'm at work now. I believe I'm in mode 0 from the STZ'S I did in my initialization of all the systems addresses.
Re: new to snes environment, have some questions.
by on (#217353)
This is my code, so again my tilemaps for all 4 BG's display the tile I place, but the main screen only shows BG1 on, when I have $212C set to enable all 4 BG layers....

Code:
;snes initialize
008000 sei
008001 clc
008002 xce
008003 rep #$18
008005 ldx #$1fff
008008 txs
008009 jml $80800d
80800d sep #$30
80800f lda #$8f
808011 sta $2100
808014 stz $2101
808017 stz $2102
80801a stz $2103
80801d stz $2105
808020 stz $2106
808023 stz $2107
808026 stz $2108
808029 stz $2109
80802c stz $210a
80802f stz $210b
808032 stz $210c
808035 stz $210d
808038 stz $210d
80803b lda #$ff
80803d sta $210e
808040 sta $2110
808043 sta $2112
808046 sta $2114
808049 lda #$07
80804b sta $210e
80804e sta $2110
808051 sta $2112
808054 sta $2114
808057 stz $210f
80805a stz $210f
80805d stz $2111
808060 stz $2111
808063 stz $2113
808066 stz $2113
808069 lda #$80
80806b sta $2115
80806e stz $2116
808071 stz $2117
808074 stz $211a
808077 stz $211b
80807a lda #$01
80807c sta $211b
80807f stz $211c
808082 stz $211c
808085 stz $211d
808088 stz $211d
80808b stz $211e
80808e sta $211e
808091 stz $211f
808094 stz $211f
808097 stz $2120
80809a stz $2120
80809d stz $2121
8080a0 stz $2123
8080a3 stz $2124
8080a6 stz $2125
8080a9 stz $2126
8080ac stz $2127
8080af stz $2128
8080b2 stz $2129
8080b5 stz $212a
8080b8 stz $212b
8080bb sta $212c
8080be stz $212d
8080c1 stz $212e
8080c4 stz $212f
8080c7 lda #$30
8080c9 sta $2130
8080cc stz $2131
8080cf lda #$e0
8080d1 sta $2132
8080d4 stz $2133
8080d7 stz $4200
8080da lda #$ff
8080dc sta $4201
8080df stz $4202
8080e2 stz $4203
8080e5 stz $4204
8080e8 stz $4205
8080eb stz $4206
8080ee stz $4207
8080f1 stz $4208
8080f4 stz $4209
8080f7 stz $420a
8080fa stz $420b
8080fd stz $420c
808100 stz $420d
808103 cli

;wipe out snes $0000-$1FFF
808104 rep #$10
808106 ldy #$1fff
808109 lda #$00
80810b sta $0000,y
80810e dey
80810f bpl $810b

;enable sprites, & all 4 BG layers, and back up value to $0800 RAM
808111 lda #$1f
808113 sta $212c
808116 sta $0800

;BG 1-2 tile data location ($0000 VRAM)
;BG 3-4 tile data location ($0000 VRAM)
808119 lda #$00
80811b sta $210b
80811e lda #$00
808120 sta $210c

;sprite register??
808123 lda #$00
808125 sta $2101

;prepare OAM buffer at $200-$2FF, and set all Y positions to #$E0
808128 sep #$10
80812a ldy #$00
80812c lda #$e0
80812e sta $0201,y
808131 iny
808132 iny
808133 iny
808134 iny
808135 cpy #$00
808137 bne $812e

;store OAM buffer from $200-$2FF to OAM $0000-$00FF via DMA
808139 rep #$10
80813b sep #$20
80813d lda #$00
80813f sta $2102
808142 lda #$00
808144 sta $2103
808147 ldy #$0400
80814a sty $4300
80814d stz $4302
808150 lda #$02
808152 sta $4303
808155 lda #$7e
808157 sta $4304
80815a ldy #$0100
80815d sty $4305
808160 lda #$01
808162 sta $420b

;store OAM buffer from $200-$2FF to OAM $0100-$01FF via DMA
808165 lda #$80
808167 sta $2102
80816a lda #$00
80816c sta $2103
80816f ldy #$0400
808172 sty $4300
808175 stz $4302
808178 lda #$02
80817a sta $4303
80817d lda #$7e
80817f sta $4304
808182 ldy #$0100
808185 sty $4305
808188 lda #$01
80818a sta $420b

;set BG 1-4 tile map locations
80818d lda #$20
80818f sta $2107
808192 lda #$30
808194 sta $2108
808197 lda #$40
808199 sta $2109
80819c lda #$50
80819e sta $210a

;turn on brightness to full
8081a1 lda #$0f
8081a3 sta $2100

;infinite loop to brigtness full address
8081a6 jmp $81a1
Re: new to snes environment, have some questions.
by on (#217367)
Again: don't have linear time (i.e. hours) to allocate to this, but I did notice you're enabling main ***and*** sub screens on all your BGs (or most of them), but I haven't looked to see what screen add/sub settings you're using. I wasn't sure why you were tinkering with those registers (esp. sub screen) at all.
Re: new to snes environment, have some questions.
by on (#217401)
I'll rework the initi, because I was able to have 4bg layers before. Thanks for your info! :-)
Re: new to snes environment, have some questions.
by on (#217488)
I'm having one hell of a time trying to write to the oam without using dma. I wanted to write specifically to $0100, so I set $2102 00, $2103 to 01, and then I picked a random value as FF, and wrote that to $2104. Nothing happens. :-/
Re: new to snes environment, have some questions.
by on (#217489)
Are you writing in F/VBlank?
Re: new to snes environment, have some questions.
by on (#217490)
I'm not sure. I'm just doing the test right at the very beginning of the NMI. It's the only code I have running, then I end with an RTI.
Re: new to snes environment, have some questions.
by on (#217492)
You have to write two bytes minimum to OAM or CGRAM before it shows up in the actual memory. There's a word buffer.
Re: new to snes environment, have some questions.
by on (#217493)
So if X,Y are 16 bits, and I want the order of bytes stored to oam are 88,FF, I'd do LDY #$FF88 STA $2104

Am I understanding that correctly?
Re: new to snes environment, have some questions.
by on (#217497)
For OAM, both the even byte and the odd byte have to be stored to the same address, one after the other.
Re: new to snes environment, have some questions.
by on (#217499)
In other words, you can't use 16-bit writes, because then the top byte will go to $2105. Writing $FF88 to $2104 as a 16-bit value would set all four BG layers to 16x16 tile size, set the BG3 priority bit, and put the PPU in Mode 7, and OAM would still be blank.

More importantly, did you mean STY and not STA?
Re: new to snes environment, have some questions.
by on (#217509)
93143 wrote:
More importantly, did you mean STY and not STA?


Yes, STY, sorry I had a typo.

And I got the oam to write without dma, the info on the write register being a word helped!
Re: new to snes environment, have some questions.
by on (#217515)
infidelity wrote:
And I got the oam to write without dma, the info on the write register being a word helped!

From my previous post:
koitsu wrote:
$2104 is write-only an 8-bit double-write register (i.e. it's like $2122 but for OAM).

FeelsBadMan. By "8-bit double-write", that means the MMIO register itself is a single address (ex. $2104), not a pair of addresses (ex. $2104 + $2105), and that it requires you to write twice to it (low byte first, then high byte). It's just like MMIO register $2122 in this respect. A "full 16-bit address" would be like $2116 and $2117 (for PPU RAM access), where you can do rep #$10 ldx #$1234 stx $2116 to write $34 to $2116 and $12 to $2117.

The SNES has a few "inconsistencies" like this (some MMIOs are 8-bit and double-write, others are two MMIO registers in sequence to make life easier when using 16-bit registers), so you really have to read the documentation slowly/clearly. This is one reason why I really don't like the Super Famicom Development Wiki's format of MMIO register descriptions:

Code:
2104  wb++--
        dddddddd

2116  wl++?-
2117  wh++?-
        aaaaaaaa aaaaaaaa

2122  ww+++-
        -bbbbbgg gggrrrrr

Cryptic shit. Sorry, but my SNES docs were much more clear:

Code:
|rwd2?|Address|Title & Explanation                                           |
||||||-----------------------------------------------------------------------|
||||||                                                                       |
||||||__  ?: Don't know what the statistics on this register are             |
|||||____ 2: 2 byte (1 word) length register                                 |
||||_____ d: Double-byte write required when writing to this register        |
|||______ w: Writable register                                               |
||_______ r: Readable register                                               |

|----------------------------------------------------------------------------|
|rwd2?|Address|Title & Explanation                                           |
|----------------------------------------------------------------------------|
...
| wd  |$2104  |OAM data register [OAMDATA]                                   |
|     |       |???????? ????????                                             |
...
| w 2 |$2116  |Video port address [VMADDL/VMADDH]                            |
|     |       |???????? ????????                                             |
...
| wd  |$2122  |Colour data register [CGDATA]                                 |
|     |       |xxxxxxxx              x: Value of colour.                     |

This all should help explain why bits 4 and 2-0 of $43x0 are so incredibly important. And you'll find other docs online that document these wrong as well (such as saying %010 is the same as %000 -- no!). Hell, even I got mine wrong back in the 90s. Sticking to general DMA:

Code:
| w   |$43x0  |DMA Control register [DMAPX]                                  |
|     |       |vh0cbaaa              v: 0 = CPU memory -> PPU.               |
|     |       |                         1 = PPU -> CPU memory.               |
|     |       |                      h: For HDMA only:                       |
|     |       |                         0 = Absolute addressing.             |
|     |       |                         1 = Indirect addressing.             |
|     |       |                      c: 0 = Auto address inc/decrement.      |
|     |       |                         1 = Fixed address (for VRAM, etc.).  |
|     |       |                      b: 0 = Automatic increment.             |
|     |       |                         1 = Automatic decrement.             |
|     |       |                      a: Transfer type:
|     |       |                         000 = 1 address write twice: LH.     |
|     |       |                         001 = 2 addresses: LH.               |
|     |       |                         010 = 1 address write once.          |
|     |       |                         011 = 2 addresses write twice: LLHH  |
|     |       |                         100 = 4 addresses: LHLH              |

Here's another one, more clear than mine, but still wrong (%010 is not the same as %000!)
Code:
$43x0: AB0CDEEE    DMA Setup Register [DMAPx]
         A -- Transfer Direction (0==CPU -> PPU, 1==PPU -> CPU)
         B -- HDMA Addressing Mode (0==Absolute, 1==Indirect)
         C -- CPU addr Auto inc/dec selection (0==Increment, 1==Decrement)
         D -- CPU addr Auto inc/dec enable (0==Enable, 1==Disable (fixed))
         E -- DMA Transfer Word Select
            For DMA: (B0-B3 are the source data bytes, $21XX is PPU destination)
               000 == Write 1 byte, B0->$21xx
               001 == Write 2 bytes, B0->$21xx B1->$21XX+1
               010 == Identical to 000
               011 == Write 4 bytes, B0->$21XX B1->$21XX B2->$21XX+1 B3->$21XX+1
               100 == Write 4 bytes, B0->$21XX B1->$21XX+1 B2->$21XX+2 B3->$21XX+3

What it should have said:
Code:
               010 == Write 2 bytes, B0->$21xx B0->$21xx (i.e. same byte, written twice)
Re: new to snes environment, have some questions.
by on (#217542)
koitsu wrote:
(i.e. same byte, written twice)


Are you sure about this part? My understanding (based on higan) is that the A-bus address is always updated after every byte written regardless of transfer type.

(Which, given that regular DMA size is measured in bytes and not "transfer units", means that it would be equivalent to %000 for regular DMA, but not HDMA)
Re: new to snes environment, have some questions.
by on (#217545)
Revenant wrote:
koitsu wrote:
(i.e. same byte, written twice)


Are you sure about this part? My understanding (based on higan) is that the A-bus address is always updated after every byte written regardless of transfer type.

(Which, given that regular DMA size is measured in bytes and not "transfer units", means that it would be equivalent to %000 for regular DMA, but not HDMA)

Honestly, I'm not sure. Quoting official documentation:

(2018/08/29 Edit: attachments removed.)

The description for %010 means one of two things:

a) Write a single byte to the destination address two times (ex. B0->$21xx B0->$21xx)
b) Write a single byte to the destination address and destination address+1 (ex. B0->$21xx B0->$21xx+1)

From the diagrams we can tell:

* There is a difference between %000 and %010 ("1-ADDRESS" vs. "1-ADDRESS (WRITE TWICE)")
* The same description is used for HDMA (but with additional specification of L,L for low byte, low byte)
* The description for general DMA %010 is a little vague, but HDMA helps gives us a slightly better idea.

Conclusion: if the %010 description meant (b), then it would have been listed as "2-ADDRESS" (since that is certainly the terminology used to refer to writing to multiple (sequential) destination addresses).

I have several revisions of manuals (not just the popular one that circulates), across ~3 years, and they all denote %010 the above way.

Going back to "Grog's Guide to DMA and HDMA" as a comparison:

Code:
$43x0: AB0CDEEE    DMA Setup Register [DMAPx]
         A -- Transfer Direction (0==CPU -> PPU, 1==PPU -> CPU)
         B -- HDMA Addressing Mode (0==Absolute, 1==Indirect)
         C -- CPU addr Auto inc/dec selection (0==Increment, 1==Decrement)
         D -- CPU addr Auto inc/dec enable (0==Enable, 1==Disable (fixed))
         E -- DMA Transfer Word Select
            For DMA: (B0-B3 are the source data bytes, $21XX is PPU destination)
               000 == Write 1 byte, B0->$21xx
               001 == Write 2 bytes, B0->$21xx B1->$21XX+1
               010 == Identical to 000
               011 == Write 4 bytes, B0->$21XX B1->$21XX B2->$21XX+1 B3->$21XX+1
               100 == Write 4 bytes, B0->$21XX B1->$21XX+1 B2->$21XX+2 B3->$21XX+3

            For HDMA: (B0-B3 are the source data bytes, $21XX is PPU destination)
               000 == Write 1 byte, B0->$21xx
               001 == Write 2 bytes, B0->$21XX, B1->$21XX+1
               010 == Write 2 bytes, B0->$21XX, B1->$21XX
               011 == Write 4 bytes, B0->$21XX, B1->$21XX B2->$21XX+1 B3->$21XX+1
               100 == Write 4 bytes, B0->$21XX, B1->$21XX+1, B2->$21XX+2, B3->$21XX+3

The description of %010 here claims %010 is the same as %000, yet HDMA's %010 writes two (different) bytes to the same destination ("1-ADDRESS")... except the official documentation clearly says L,L not L,H. That would mean the same source byte.

Super Famicom Development Wiki says this -- and documents even more modes that aren't in the official documentation:

Code:
43x0 rwb++++
        da-ifttt
        d        = Transfer Direction.^
         a       = HDMA Addressing Mode.^^
           i     = DMA Address Increment.^^^
            f    = DMA Fixed Transfer.^^^^

        ttt  = Transfer Mode.
            000 => 1 register write once             (1 byte:  p               )
            001 => 2 registers write once            (2 bytes: p, p+1          )
            010 => 1 register write twice            (2 bytes: p, p            )
            011 => 2 registers write twice each      (4 bytes: p, p,   p+1, p+1)
            100 => 4 registers write once            (4 bytes: p, p+1, p+2, p+3)
            101 => 2 registers write twice alternate (4 bytes: p, p+1, p,   p+1)
            110 => 1 register write twice            (2 bytes: p, p            )
            111 => 2 registers write twice each      (4 bytes: p, p,   p+1, p+1)

p in this context is the first individual byte read from the source. So, B0->$21xx B0->$21xx. This could also (to me) be represented as what Nintendo said: "1-ADDRESS (WRITE TWICE) L,L".

I don't know of any games which use %010 off the top of my head (do I look like I sit around disassembling every commercial game and analysing their DMA params? Haha :-) ), but it's safe to say we can't trust emulator source code, and everyone's documentation is either inconsistent or wrong (including my own).

Possible to test on hardware? Absolutely! Should it be tested on hardware? Absolutely!
Re: new to snes environment, have some questions.
by on (#217546)
I used HDMA mode 2 in my PPU bus activity program to adjust the vertical scrolling for the offset-per-tile layer.
Re: new to snes environment, have some questions.
by on (#217562)
I'll have to recheck my routine for $2104, I'm doing a double write, but it's storing at 2 addresses in oam, but I'm able to load a table for the values I want. There's a lot for me to digest and understand correctly, a bit overwhelmed a points, but as long as I get the results I'm trying to accomplish, I'll know I'm on the right track and continously study what's going on, that is giving me my desired results.

I have another question regarding "WAI"

Is that 1 byte opcode the same as what the NES uses for cpu cycles (LDA $2002, DEX, BPL back to DEX)? I want to know examples of how to use WAI properly.
Re: new to snes environment, have some questions.
by on (#217563)
koitsu wrote:
I don't know of any games which use %010 off the top of my head (do I look like I sit around disassembling every commercial game and analysing their DMA params? Haha :-) ), but it's safe to say we can't trust emulator source code, and everyone's documentation is either inconsistent or wrong (including my own).

Possible to test on hardware? Absolutely! Should it be tested on hardware? Absolutely!

I don't know why I somehow failed to remember this in my last post (other than it being somewhat late at night), but the last demo I wrote/released uses %010 for CGRAM color gradients. Presumably, so does every other game that uses HDMA to perform color gradient effects. So yes, it writes two different bytes.

My interpretation of the official documentation's "1-ADDRESS (WRITE TWICE)" is that it's only supposed to describe which type of register it's designed to write to. It clearly also states that it "transfers" two bytes, not just performs two writes. (Likewise, "L" and "H" are clearly referring to register addresses, not source bytes.)
Re: new to snes environment, have some questions.
by on (#217579)
infidelity wrote:
I have another question regarding "WAI"

Is that 1 byte opcode the same as what the NES uses for cpu cycles (LDA $2002, DEX, BPL back to DEX)? I want to know examples of how to use WAI properly.

With NMI-on-VBlank enabled, you can use wai in your main loop to effectively wait for VBlank to finish (e.g. wai / lda #1 would sit and wait for NMI to occur, then after rti in your NMI routine, the next instruction run would be lda #1). Technically it waits for any interrupt (NMI, IRQ, ABORT, or RESET (not that the latter matters)). It's quicker, easier, faster (cycle-wise) and more precise (timing-wise) than polling $4210 and watching bit 7 (akin to the above loop on the NES) but it depends on what your needs are.

If you don't have a 65816 instruction manual by now, then get it. Pages 192-202 (Chapter 13) and page 420 (opcode description) are useful.
Re: new to snes environment, have some questions.
by on (#217581)
Revenant wrote:
I don't know why I somehow failed to remember this in my last post (other than it being somewhat late at night), but the last demo I wrote/released uses %010 for CGRAM color gradients. Presumably, so does every other game that uses HDMA to perform color gradient effects. So yes, it writes two different bytes.

Respectfully, this description is no better than any of the existing documentation. :\ Which is it?

a) B0->$21xx B0->$21xx (e.g. byte 0 of source written to $21xx, followed by byte 0 of source written to $21xx)
b) B0->$21xx B1->$21xx (e.g. byte 0 of source written to $21xx, followed by byte 1 of source written to $21xx)

If you're using it for CGRAM data (ex. writes to $2122) then it's almost certainly (b), which means that yes, the very last paragraph of my previous post is incorrect.

Regardless, %010 is not the same as %000 (re: Grog's guide). Meanwhile, the Super Famicom Development Wiki doesn't bother to explain what p is, when if (b) is true, then p refers to the destination address only -- and that the source address is effectively always incrementing by 1 (which would correlate with what you said earlier, re: A-bus address always incrementing). It's like whoever wrote this was trying to be terse through implication (and it's described differently in two different parts of the site -- here we are again with an example of why wikis are not inherently better for documentation).

Overall, I actually prefer the nomenclature from Grog's guide since it makes it clearer what source data is going to what destination. This thread is a good example of why denoting both is important. Without both, the programmer doesn't know how to format the data that's used as the source.

Revenant wrote:
My interpretation of the official documentation's "1-ADDRESS (WRITE TWICE)" is that it's only supposed to describe which type of register it's designed to write to. It clearly also states that it "transfers" two bytes, not just performs two writes. (Likewise, "L" and "H" are clearly referring to register addresses, not source bytes.)

It's subjective. Two writes to a single MMIO register still technically is "transferring" two bytes of data. What matter is *which* two bytes it's transferring (from the source). Case in point: %001 is described "2 BYTE", "2-ADDRESS (VRAM etc.) L,H" -- two different source bytes are transferred, to two different destination addresses (i.e. B0->$21xx, B1->$21xx+1).

Nintendo's documentation has always been unclear/vague in this regard, but what we have in the community is still not crystal clear to programmers. I mean we can sit here and debate what's what 'til the cows come home, but this thread acts as solid proof that it's not clear to programmers. And without clear/concise examples that can be referenced in the existing documentation, the situation doesn't improve. (To this, please do not tell me "Well it's a wiki, go fix it yourself")
Re: new to snes environment, have some questions.
by on (#217585)
Revenant wrote:
the last demo I wrote/released uses %010 for CGRAM color gradients. Presumably, so does every other game that uses HDMA to perform color gradient effects.

I use %x11, so that I can set both the address and the colour with one channel. This method wastes a write because the address gets hit twice, but unfortunately (p, p+1, p+1) is not an available HDMA pattern.

Sadly, (p, p, p, p) isn't available either, so if you want to do >8 consecutive colours you have to use regular DMA in an IRQ...
Re: new to snes environment, have some questions.
by on (#217590)
koitsu wrote:
Respectfully, this description is no better than any of the existing documentation. :\ Which is it?

a) B0->$21xx B0->$21xx (e.g. byte 0 of source written to $21xx, followed by byte 0 of source written to $21xx)
b) B0->$21xx B1->$21xx (e.g. byte 0 of source written to $21xx, followed by byte 1 of source written to $21xx)

The latter.

Quote:
Two writes to a single MMIO register still technically is "transferring" two bytes of data.

Sure, but given that there is literally no register that requires/expects you to always write the same value to it twice at a time (versus several registers that are 16-bit write-twice), I think it's pretty obvious that "2 bytes" in Nintendo's docs means the same thing for that mode that it does for every other multiple-byte mode, w/r/t reading data from the source address.

The misinformation about %010 being the same as %000 probably just stemmed from people only testing it with regular DMA, where it is functionally identical since you're measuring the source data size in bytes instead of scanlines.
Re: new to snes environment, have some questions.
by on (#217597)
Revenant wrote:
The latter.

Awesome -- thank you!

Revenant wrote:
Sure, but given that there is literally no register that requires/expects you to always write the same value to it twice at a time (versus several registers that are 16-bit write-twice), I think it's pretty obvious that "2 bytes" in Nintendo's docs means the same thing for that mode that it does for every other multiple-byte mode, w/r/t reading data from the source address.

The misinformation about %010 being the same as %000 probably just stemmed from people only testing it with regular DMA, where it is functionally identical since you're measuring the source data size in bytes instead of scanlines.

Could I ask for you to expand on this, particularly the 2nd paragraph? I don't see how in general DMA mode %010 is identical to %000. Sorry if I sound like a broken record, but B0->$21xx and B0->$21xx B1->$21xx are most certainly not the same.
Re: new to snes environment, have some questions.
by on (#217615)
With HDMA, it matters because it changes the number of bytes that are transferred per scanline (from 1 byte to 2). With regular DMA, $43x5/43x6 measure the total transfer size in bytes regardless of which transfer mode you use, so those two modes end up doing basically the same thing. That's why I think some early documentation had that mistake, just because the difference isn't apparent unless you're using one of them with HDMA instead of regular DMA.
Re: new to snes environment, have some questions.
by on (#217668)
I'm still having stack issues. Within my NMI, the RTI is not returning back to bank $80 which I set it to. It keeps going to bank $A5? :-/

Code:
008200 jml $808204   [808204] A:0081 X:8000 Y:2000 S:01fb D:0000 DB:00 NvMxdIzC V:257 H: 10 F: 1
808204 rep #$30               A:0081 X:8000 Y:2000 S:01fb D:0000 DB:00 NvMxdIzC V:257 H: 18 F: 1
808206 lda #$8200             A:0081 X:8000 Y:2000 S:01fb D:0000 DB:00 NvmxdIzC V:257 H: 24 F: 1
808209 pha                    A:8200 X:8000 Y:2000 S:01fb D:0000 DB:00 NvmxdIzC V:257 H: 30 F: 1
80820a phx                    A:8200 X:8000 Y:2000 S:01f9 D:0000 DB:00 NvmxdIzC V:257 H: 37 F: 1
80820b phy                    A:8200 X:8000 Y:2000 S:01f7 D:0000 DB:00 NvmxdIzC V:257 H: 45 F: 1
80820c phd                    A:8200 X:8000 Y:2000 S:01f5 D:0000 DB:00 NvmxdIzC V:257 H: 52 F: 1
80820d phb                    A:8200 X:8000 Y:2000 S:01f3 D:0000 DB:00 NvmxdIzC V:257 H: 60 F: 1
80820e rep #$10               A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 NvmxdIzC V:257 H: 65 F: 1
808210 sep #$20               A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 NvmxdIzC V:257 H: 71 F: 1
808212 lda #$00               A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 NvMxdIzC V:257 H: 76 F: 1
808214 sta $2102     [002102] A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 nvMxdIZC V:257 H: 80 F: 1
808217 sta $2103     [002103] A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 nvMxdIZC V:257 H: 88 F: 1
80821a ldy #$0400             A:8200 X:8000 Y:2000 S:01f2 D:0000 DB:00 nvMxdIZC V:257 H: 95 F: 1
80821d sty $4300     [004300] A:8200 X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:101 F: 1
808220 stz $4302     [004302] A:8200 X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:110 F: 1
808223 lda #$02               A:8200 X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:118 F: 1
808225 sta $4303     [004303] A:8202 X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:122 F: 1
808228 lda #$7e               A:8202 X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:129 F: 1
80822a sta $4304     [004304] A:827e X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:133 F: 1
80822d ldy #$0100             A:827e X:8000 Y:0400 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:151 F: 1
808230 sty $4305     [004305] A:827e X:8000 Y:0100 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:157 F: 1
808233 lda #$01               A:827e X:8000 Y:0100 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:166 F: 1
808235 sta $420b     [00420b] A:8201 X:8000 Y:0100 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:170 F: 1
808238 sep #$10               A:8201 X:8000 Y:0100 S:01f2 D:0000 DB:00 nvMxdIzC V:257 H:177 F: 1
80823a lda #$80               A:8201 X:0000 Y:0000 S:01f2 D:0000 DB:00 nvMXdIzC V:259 H: 29 F: 1
80823c sta $2102     [002102] A:8280 X:0000 Y:00fc S:01f2 D:0000 DB:00 NvMXdIzC V:259 H: 33 F: 1
80823f lda #$00               A:8280 X:0000 Y:00fc S:01f2 D:0000 DB:00 NvMXdIzC V:259 H: 40 F: 1
808241 sta $2103     [002103] A:8200 X:0000 Y:00fc S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 44 F: 1
808244 ldy #$00               A:8200 X:0000 Y:00fc S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 52 F: 1
808246 ldx #$00               A:8200 X:0000 Y:0000 S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 56 F: 1
808248 lda $81fc,x   [0081fc] A:8200 X:0000 Y:0000 S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 60 F: 1
80824b sta $2104     [002104] A:8200 X:0000 Y:0000 S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 68 F: 1
80824e inx                    A:8200 X:0000 Y:0000 S:01f2 D:0000 DB:00 nvMXdIZC V:259 H: 75 F: 1
80824f lda $81fc,x   [0081fd] A:8200 X:0001 Y:0000 S:01f2 D:0000 DB:00 nvMXdIzC V:259 H: 79 F: 1
808252 sta $2104     [002104] A:82e0 X:0001 Y:0000 S:01f2 D:0000 DB:00 NvMXdIzC V:259 H: 87 F: 1
808255 inx                    A:82e0 X:0001 Y:0000 S:01f2 D:0000 DB:00 NvMXdIzC V:259 H: 94 F: 1
808256 cpx #$04               A:82e0 X:0002 Y:00fc S:01f2 D:0000 DB:00 nvMXdIzC V:259 H: 98 F: 1
808258 bne $825c     [80825c] A:82e0 X:0002 Y:00fc S:01f2 D:0000 DB:00 NvMXdIzc V:259 H:102 F: 1
80825c iny                    A:82e0 X:0002 Y:00fc S:01f2 D:0000 DB:00 NvMXdIzc V:259 H:107 F: 1
80825d iny                    A:82e0 X:0002 Y:00fd S:01f2 D:0000 DB:00 NvMXdIzc V:259 H:111 F: 1
80825e cpy #$fe               A:82e0 X:0002 Y:00fe S:01f2 D:0000 DB:00 NvMXdIzc V:259 H:114 F: 1
808260 bne $8248     [808248] A:82e0 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:118 F: 1
808262 lda #$00               A:82e0 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:122 F: 1
808264 sta $2102     [002102] A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:126 F: 1
808267 pha                    A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:134 F: 1
808268 lda #$01               A:8200 X:0002 Y:00fe S:01f1 D:0000 DB:00 nvMXdIZC V:259 H:149 F: 1
80826a sta $2103     [002103] A:8201 X:0002 Y:00fe S:01f1 D:0000 DB:00 nvMXdIzC V:259 H:153 F: 1
80826d pla                    A:8201 X:0002 Y:00fe S:01f1 D:0000 DB:00 nvMXdIzC V:259 H:161 F: 1
80826e sta $2104     [002104] A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:168 F: 1
808271 sta $2104     [002104] A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:175 F: 1
808271 sta $2104     [002104] A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:175 F: 1
808274 plb                    A:8200 X:0002 Y:00fe S:01f2 D:0000 DB:00 nvMXdIZC V:259 H:183 F: 1
808275 pld                    A:8200 X:0002 Y:00fe S:01f3 D:0000 DB:00 nvMXdIZC V:259 H:190 F: 1
808276 ply                    A:8200 X:0002 Y:00fe S:01f5 D:0000 DB:00 nvMXdIZC V:259 H:199 F: 1
808277 plx                    A:8200 X:0002 Y:0000 S:01f6 D:0000 DB:00 nvMXdIZC V:259 H:206 F: 1
808278 pla                    A:8200 X:0020 Y:0000 S:01f7 D:0000 DB:00 nvMXdIzC V:259 H:213 F: 1
808279 rti                    A:8200 X:0020 Y:0000 S:01f8 D:0000 DB:00 nvMXdIZC V:259 H:220 F: 1

here is the issue, it's going to bank $A5???
a58200 inx                    A:8200 X:0020 Y:0000 S:01fc D:0000 DB:00 Nvmxdizc V:259 H:233 F: 1
Re: new to snes environment, have some questions.
by on (#217670)
infidelity wrote:
008200 jml $808204 [808204] A:0081 X:8000 Y:2000 S:01fb D:0000 DB:00 NvMxdIzC V:257 H: 10 F: 1
[...]
808279 rti A:8200 X:0020 Y:0000 S:01f8 D:0000 DB:00 nvMXdIZC V:259 H:220 F: 1
Your stack use is unbalanced. Make sure you pull and push the same number of bytes in every possible execution path.
Re: new to snes environment, have some questions.
by on (#217675)
Thank You!

I used the bsnes debugger and stepped through my NMI, turns out it had to deal with how I had my REP's & SEP's placed near the beginning and end of my NMI. I made it so when the NMI starts (before pushing everything) that I set A,X,Y to 8-bits. Then, at the end of the NMI (before pulling everything) I make sure to set A,X,Y to 8-bits again, then when I watch the stack address during pulling, it matched the address it was before the pushing, resulting in going back to my reset vector infinite loop. :-)
Re: new to snes environment, have some questions.
by on (#217678)
You should instead set them all to 16-bit before pushing/popping to make sure that the upper bytes of A/X/Y aren't destroyed whenever an interrupt occurs.

e: especially if X/Y were already 16-bit when the interrupt occurs, because setting the index registers to 8-bit will destroy the upper bytes automatically.
Re: new to snes environment, have some questions.
by on (#217682)
I suggest getting familiar with php and plp. Revenant's advice is highly applicable alongside that.
Re: new to snes environment, have some questions.
by on (#217696)
Ooooh, ok. Thank you both for that info! I'll add that today and step through to watch the stack. :-)
Re: new to snes environment, have some questions.
by on (#217827)
I've got another question regarding loading long. Are you able to load a ROM value long, with X and Y? Opcodes I heavily used were B9####(LDA'Y) & BD####(LDA'X)

Can I do this with using long, reading values from other banks that other banks, that my loading code is currently not in?
Re: new to snes environment, have some questions.
by on (#217835)
http://www.6502.org/tutorials/65c816opcodes.html#5.17
https://wiki.nesdev.com/w/images/7/76/Programmanual.pdf pg52 etc.
Re: new to snes environment, have some questions.
by on (#217836)
I also recommend http://oxyron.de/html/opcodes816.html as a quick cheat sheet, especially if you're already familiar with the original 6502 instructions. It lists all opcodes in a table along with their addressing mode and cycle count, plus notes about which flags they affect, etc.
Re: new to snes environment, have some questions.
by on (#217847)
As I said in a previous post on the previous page:

Quote:
If you don't have a 65816 instruction manual by now, then get it. ...

Said manual is easy to understand and goes over all the addressing modes. There is also an opcode breakdown in Chapter 13 that makes it easier to remember what opcode supports what addressing mode.

In short: yes, there are 24-bit long indexed addressing modes, and yes you can use them to access anything in the entire 24-bit address space of the 65816. But I'm not going to go into the rest because I'm going to make you get the manual and read it. :-) Make sure you understand the B register (bank; sometimes called DB (data bank)) as well (relates to 16-bit addressing). Don't confuse this with the upper vs. lower bytes of the 16-bit accumulator (which are often called "A" and "B", hence xba opcode).

Next, be aware that different assemblers use different syntax for long addressing. Refer to your assembler documentation for how. And most use [] (brackets, not parenthesis!) for indirect long addressing, but again, it depends on the assembler.

Finally, if you're using WLA DX, you may need to get familiar with using the .b and .w and .l suffixes on opcodes, ex. lda.b vs. lda.w vs. lda.l, to tell the assembler what addressing mode / "operand length" you want to use (8-bit vs. 16-bit vs. 24-bit). You can also put those suffixes on the end of the operand, but that tends to look incredibly gross/ugly. There's docs on that here and here (look up .8bit, .16bit, .24bit in Section 2, and ESPECIALLY see Section 14.5). Sometimes it can figure it out on its own, other times it cannot -- and when it can't, or picks the wrong one, you'll need assembly listings to figure it out (or step through the code in a debugger and see that it's using the wrong opcode/addressing mode).