Questions about SNES programming

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

Moderator: Moderators

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

Re: Questions about SNES programming

Post by koitsu » Tue Jul 30, 2019 3:52 pm

People here are hemming and hawing over direct page -- please do not listen to them especially if you are starting with the SNES. This is a case where highly experienced people can't step back and think about the bigger picture. Instead, set D=$0000 (i.e. rep #$20 / lda #$0000 / tcd) and do not change it. DP (or what you know as zero page on 6502) will behave exactly how you're used to. Moving it is known to cause "complications" with assemblers, which has been discussed at length in other threads.

User avatar
SusiKette
Posts: 110
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

Re: Questions about SNES programming

Post by SusiKette » Mon Sep 09, 2019 3:15 am

Can someone explain this bit of code:

Code: Select all

...
PHB                  ; Here Data Bank is $01 and pushed to stack (only value in stack atm)
LDA #$0000
STA $0000C4 [0000C4]
LDA #$1D3A
LDX #$00C4
TXY
INY
MVN $00,$00    ; Data Bank changes to $00, value in stack is still $01
PLB                  ; Here the value at stack changes to $00, Data Bank is still $00
INC $3C [00003C]       ; Stack is empty now, Data Bank is $00
...
Shouldn't the Data Bank value be returned to $01 at PLB? Why does it change to $00? I found this while using Mesen-S. Although, I don't thing this could be an emulation error. It would seem like something like this could break the program, but the game still works just fine. This code is from Akumajou Dracula (or Super Castlevania IV iirc).

Now that I'm posting here, can people give me some practical MVP and MVN. I know what each parameter do, but I don't know practical uses for them, so I don't know how to properly use them in a code. Can these instructions be used to clear RAM?

creaothceann
Posts: 220
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Questions about SNES programming

Post by creaothceann » Mon Sep 09, 2019 3:43 am

Afaik using DMA would be faster than using MVN/MVP, and doesn't use the CPU registers for its operation.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10

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

Re: Questions about SNES programming

Post by 93143 » Mon Sep 09, 2019 6:23 am

creaothceann wrote:Afaik using DMA would be faster than using MVN/MVP, and doesn't use the CPU registers for its operation.
There are a couple of cases where DMA isn't useful.

1) during active display, while using HDMA. There is a crash bug in the launch version of the hardware that can be triggered if DMA and HDMA are used at the same time. Technically it can be worked around if you know the timing, but not in every situation, and definitely not by a beginner; even for experienced coders the safe way to go is to simply not mix DMA and HDMA. If you mess it up, your game will randomly hard lock on a rev. 1 CPU, so it's best not to try it.

2) for WRAM to WRAM copying. You'd think you could do this, because there's WRAM access on both buses, but you'd be wrong - the WRAM is not actually dual-ported and cannot provide a read from one address and take a write to a different address at the same time. So don't DMA from WRAM to WMDATA, or vice versa, because it will not work.

(Technically I suppose you could use SRAM in the cartridge as a temporary data buffer; DMA from WMDATA to SRAM and then from SRAM back to WMDATA. Or if you've got a bunch of VRAM free you could go from WRAM to VMDATAL/H and then back out to WRAM, assuming this is happening during VBlank or forced blank. It would still be way faster than block move... but honestly I'd expect WRAM-to-WRAM transfers to be pretty rare anyway.)

nocash
Posts: 1199
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: Questions about SNES programming

Post by nocash » Mon Sep 09, 2019 7:27 am

SusiKette wrote:Can someone explain this bit of code:...
Can these instructions be used to clear RAM?
That memcopy instructions are intended to copy memory, not to clear it.
But, yes, they can be also used for clearing memory, and your example code seems to be doing that:
Setting the dest=src+1 will cause each byte to be overwritten by the previous byte (ie. by whatever was stored in the the first src byte) (when using the forward copy variant, I don't remember which one was doing that, mvn or mvp).
If your stack pointer is in the cleared area, then that will also affect the value being read by PLB opcode.

Anyways, dma will be faster, and even if you don't have dma, I would treat mvn/mvp rather as weird oddity, not as a useful feature.
Or maybe they can be useful in some cases, it's just that the parameters/syntax are kinda weird, making it difficult to get familar with those instructions (z80 and 80x86 have similar instructions, but I think they are much easier to use than mvn/mvp).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

User avatar
SusiKette
Posts: 110
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

Re: Questions about SNES programming

Post by SusiKette » Mon Sep 09, 2019 11:43 am

nocash wrote: If your stack pointer is in the cleared area, then that will also affect the value being read by PLB opcode.
Not sure why I didn't think of this.
creaothceann wrote: Afaik using DMA would be faster than using MVN/MVP, and doesn't use the CPU registers for its operation.
While I am a bit more familiar with DMAs than MVP/MVN, my current information on DMAs is mixed, so I don't know what information is correct.

Also, do SNES games compress graphics? I was unable to find the graphics from a SNES ROM with YY-CHR. If they do, what sort of methods are commonly used for that?

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

Re: Questions about SNES programming

Post by 93143 » Mon Sep 09, 2019 2:58 pm

...I just want to clarify that there is zero problem with using HDMA during an active frame and then regular DMA during VBlank after HDMA has ended for the frame. The bug triggers when an HDMA transfer starts immediately after a DMA ends, within a couple of microseconds, so it really only happens if you try to run both at the same time.

It's a shame, because the DMA controller was designed to allow HDMA to seamlessly interrupt DMA, so you could do stuff like transferring from cartridge to WRAM during active display while running automated raster effects. But you basically can't do that because of the risk.
SusiKette wrote:Also, do SNES games compress graphics? I was unable to find the graphics from a SNES ROM with YY-CHR. If they do, what sort of methods are commonly used for that?
Generally, yes they do. Methods are game-specific. Nowadays one might wish to use an advanced technique, like some variant of lz4, or a very simple technique like RLE. Or just store them uncompressed, if you don't care about ROM size. There are no commercial SNES games that would have exceeded the maximum practical cartridge size without compression; it was all about saving money.
Last edited by 93143 on Mon Sep 09, 2019 3:15 pm, edited 2 times in total.

User avatar
TmEE
Posts: 744
Joined: Wed Feb 13, 2008 9:10 am
Location: Estonia, Rapla city (50 and 60Hz compatible :P)
Contact:

Re: Questions about SNES programming

Post by TmEE » Mon Sep 09, 2019 3:03 pm

Most/all SNES games compress their GFX, there's no CHR-ROM that necessitates uncompressed GFX as on NES or NeoGeo. You could think of SNES and most other machines as NES with exclusive CHR-RAM and to save space games compress as much of their things as they can.

creaothceann
Posts: 220
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Questions about SNES programming

Post by creaothceann » Tue Sep 10, 2019 5:12 am

Though it's not like there are no ROMs that have no uncompressed graphics.

Just load a ZSNES or SNES9x 1.43 savestate into vSNES, then load the ROM and use the savestate's palette to look through the ROM.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10

tepples
Posts: 21936
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Questions about SNES programming

Post by tepples » Tue Sep 10, 2019 7:27 am

Games such as Super Mario All-Stars and Tetris & Dr. Mario have uncompressed graphics, and I assume this is for two reasons: to allow CHR DMA, and because compressing them wouldn't put the game below the next power of two ROM size.

User avatar
SusiKette
Posts: 110
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

Re: Questions about SNES programming

Post by SusiKette » Tue Sep 10, 2019 1:48 pm

Got the memory clear DMA working now.

Since there are some registers that are split into two byte sized registers, can you use a 16 bit register mode to write to both at once? For the "write twice" type registers, is there a latch that resets which one is written? Iirc, this was done by reading $2002 on NES.

Also, does the SNES have any use for the COP instruction?

tepples
Posts: 21936
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Questions about SNES programming

Post by tepples » Tue Sep 10, 2019 2:38 pm

If the low and high bytes are in consecutive addresses, such as VRAM address ($2116 and $2117), VRAM data ($2118 and $2119), and OAM address ($2102 and $2103), then yes, you can use a 16-bit write.
If the low and high bytes are in the same address, such as scroll position ($210D and $210D, $210E and $210E, $210F and $210F, ..., $2114 and $2114) or CGRAM data ($2122), then no, you cannot use a 16-bit write.

According to Fullsnes, writing to OAM address ($2102 or $2103) resets the first/second write latch for OAM data ($2104), and writing to CGRAM address ($2121) resets the first/second write latch for CGRAM data ($2122). Scroll registers appear to treat all writes as the second write, where the last value written gets written to low bits and the current value gets written to high bits. Mode 0-6 and mode 7 registers have separate "last value written" states, despite some of them sharing addresses, and the behavior of horizontal mode 0-6 scrolling registers differs slightly from vertical scrolling or mode 7 in part because the NES-style coarse/fine split is still present in the horizontal registers. Reading $213F resets both first/second read latches for horizontal and vertical beam position ($213C and $213D).

User avatar
SusiKette
Posts: 110
Joined: Fri Mar 16, 2018 1:52 pm
Location: Finland

Re: Questions about SNES programming

Post by SusiKette » Wed Sep 18, 2019 7:29 am

I ran into a compilation error that I can't seem to figure out. The code does compile, but ca65 thinks is that the "RegisterSetup" subroutine should be compiled in index register 8 bit mode, instead of 16 bit mode, and compiles it incorrectly. I can't find what causes this error. Here is the code to the current file: https://pastebin.com/SMWSBPhR

Post Reply