Max stack depth + OAM transfer

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
krzysiobal
Posts: 719
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland

Max stack depth + OAM transfer

Post by krzysiobal » Sun Jun 21, 2020 12:23 pm

I am improving the ROM for my micro sd flash cartridge. Currently I am using the internal 2K ROM plus few hundred bytes from additional WRAM at $6000-$7fff. I need to stop using WRAM because it will be needed for other purposes, so I have to save as much as I can. My minimum is:

1) 512 bytes is used as sector buffer for bytes read from micro sd card (sector with data)
2) 512 bytes is used as sector buffer for bytes read from micro sd card (sector containing FAT entries)
3) ~256 bytes are used as a data result the function that read single directory entry (4 bytes starting cluster, 1 byte type, 256 bytes filename - maximum FAT filename length is 256 characters
4) ~256 bytes are used as input variable to function that search for a directory entry with specified name
probably around 128 bytes are used by other variables
5) ~512 bytes are used as a temporary place in RAM to copy and execute code from that can't be run from ROM (responsible for self programming ROM), but that code does not use the functions from 3) and 4) so the buffer can be be in the same place
6) Around 256 bytes for variables

Questions:
1) Of course stack is also needed, but is there any tool that could automaticaly analyze my code and calculate maximum stack depth in pesimistic call-nesting? (I don't use recurrent functions)

2) I use just one sprite as an arrow, so wasting 256 bytes for OAM and using OAM_DMA is ridiculous.
2a) is it safe to just do:

Code: Select all

lda #0
sta OAMADDR
lda OAM
sta OAMDATA
lda OAM + 1
sta OAMDATA
lda OAM + 2
sta OAMDATA
lda OAM +3
sta OAMDATA
or are there any third party consoles that only support OAM DMA transfer?

2b) For the remaining unused 252 bytes of OAM, do I have to initialize them to zeros once? Or should I anyway refresh them every frame? Maybe it is good to declare 256 zero-byte array somewhere in ROM and make

Code: Select all

.SEGMENT "DATA"
OAM_ZEROS:
.REPEAT 256
.byte 0
.ENDREPEAT

LDA #>OAM_ZEROS
STA OAM_DMA
and then manually fill the 4 bytes like above?

lidnariq
Posts: 9418
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Max stack depth + OAM transfer

Post by lidnariq » Sun Jun 21, 2020 12:50 pm

krzysiobal wrote:
Sun Jun 21, 2020 12:23 pm
2) 512 bytes is used as sector buffer for bytes read from micro sd card (sector containing FAT entries)
You don't really need to store the whole 512b of FAT; instead you can convert the values you find there into an extent (effectively: clusters A through B on disk correspond to file offset C through D). It's just not that likely that you'll have a fragmented file but the fragments happen to be stored in the same sector of FAT.
2a) is it safe to just do:
lda #0
sta OAMADDR
On the 2C02G/H, writes to OAMADDR corrupt the contents of OAM RAM, regardless of what the current value of OAMADDR is. If you write to OAMADDR, you basically have to rewrite the entire contents of OAM.

However, you can rely on OAMADDR being 0 at the end of rendering.
2b) For the remaining unused 252 bytes of OAM, do I have to initialize them to zeros once? Or should I anyway refresh them every frame? Maybe it is good to declare 256 zero-byte array somewhere in ROM and make
You don't want them to be 0, because that'll place all 63 remaining sprites in the top-left corner of the screen - off the top of a normal NTSC TV, but visible on a PAL PPU.

If you ever disable rendering, you need to upload new OAM contents; for the PPUs I've experimented with, OAM DRAM seems to decay to every byte holding something in the $10 to $1F range. If you leave rendering enabled always, or don't care about OAM after you re-enable rendering (e.g. leave sprite rendering off), you can just fill OAM the once.

krzysiobal
Posts: 719
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland

Re: Max stack depth + OAM transfer

Post by krzysiobal » Mon Jun 22, 2020 8:34 am

lidnariq wrote:
Sun Jun 21, 2020 12:50 pm
You don't really need to store the whole 512b of FAT; instead you can convert the values you find there into an extent (effectively: clusters A through B on disk correspond to file offset C through D). It's just not that likely that you'll have a fragmented file but the fragments happen to be stored in the same sector of FAT.
Cool idea, thank you. But I alsso have save-state support (that is, transfering the content of WRAM into micro sd card after power reset). That involves need of finding first free cluster, and allocating it. And micro sd support only reading/writing whole sector, so even if I only changed 4 bytes in it, i still need to write back the whole sector, so basically I need to have it in uncompressed form anywa.
If you ever disable rendering, you need to upload new OAM contents; for the PPUs I've experimented with, OAM DRAM seems to decay to every byte holding something in the $10 to $1F range. If you leave rendering enabled always, or don't care about OAM after you re-enable rendering (e.g. leave sprite rendering off), you can just fill OAM the once.
I just need this single sprite as an arrow pointing the current entry, but rendering is disabled many times, for example when I load next page with filenames. Anyway, looks like that single arrow does not have to be sprite, but just single name-table background tile.

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

Re: Max stack depth + OAM transfer

Post by nocash » Tue Jun 23, 2020 11:30 pm

Do you really need the uncompressed 512 byte FAT sector, and the 512 byte DATA sector at the same time?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

User avatar
rainwarrior
Posts: 7818
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Max stack depth + OAM transfer

Post by rainwarrior » Wed Jun 24, 2020 3:27 pm

As a compromise you can fill only every Y byte of your OAM buffer with $FF and that makes the other 3 bytes or each group of 4 irrelevant and free for other use. Not quite as convenient as a big linear chunk of memory, but still plenty to use.

Though... if it's just for a pointer, do you really need a sprite at all? Maybe just turn sprites off and use the nametable for your cursor? Otherwise, like others said, I'd advise against trying to upload single bytes at a time to OAM. There are too many problems with that.

I don't have static code analysis tools, but there's a quick way to check the total stack depth of a running program in Mesen: Memory tools, then the Access Counters tab. You can scroll down to the stack page and see how far up it's been accessed.

Post Reply