Why can't I add more RAM tiles?

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
Post Reply
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Why can't I add more RAM tiles?

Post by Artcfox »

I'm trying to use cuzebox to determine the maximum number of RAM tiles I can have in my mode 3 scrolling game.

In my Makefile I have:

Code: Select all

KERNEL_DIR = ../../../kernel
KERNEL_OPTIONS  = -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSCROLLING=1 -DSOUND_MIXER=1 -DSOUND_CHANNEL_5_ENABLE=0
KERNEL_OPTIONS += -DMAX_SPRITES=24 -DRAM_TILES_COUNT=30 -DSCREEN_TILES_V=28 -DSCREEN_TILES_H=28
KERNEL_OPTIONS += -DOVERLAY_LINES=0 -DVRAM_TILES_V=32

LDFLAGS += -Wl,--section-start,.noinit=0x800100 -Wl,--section-start,.data=0x800500
And looking at the memory display of cuzebox:
why_cant_i_add_more_ram_tiles.png
why_cant_i_add_more_ram_tiles.png (36.11 KiB) Viewed 6594 times
It looks like near the end I still have 512 bytes free, but if I add just 1 more to -DRAM_TILES_COUNT, then I get garbage all over the screen when I'm moving the sprites.

Other info which might help:

For my tileset:

Code: Select all

Unique tiles found: 19
Total size (tiles + maps): 4578 bytes
For my sprites:

Code: Select all

File exported successfully!
Unique tiles found: 123
Total size (tiles + maps): 8054 bytes
Are those two blue squares near the end not really free memory?
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Why can't I add more RAM tiles?

Post by Artcfox »

Here's what it looks like when my Makefile is defined with fewer RAM tiles, -DRAM_TILES_COUNT=20:

Code: Select all

KERNEL_DIR = ../../../kernel
KERNEL_OPTIONS  = -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSCROLLING=1 -DSOUND_MIXER=1 -DSOUND_CHANNEL_5_ENABLE=0
KERNEL_OPTIONS += -DMAX_SPRITES=12 -DRAM_TILES_COUNT=20 -DSCREEN_TILES_V=28 -DSCREEN_TILES_H=28
KERNEL_OPTIONS += -DOVERLAY_LINES=0 -DVRAM_TILES_V=32

LDFLAGS += -Wl,--section-start,.noinit=0x800100 -Wl,--section-start,.data=0x800500
why_cant_i_add_more_ram_tiles2.png
why_cant_i_add_more_ram_tiles2.png (23.35 KiB) Viewed 6593 times
I can see there are a lot more blocks free near the end, so I would think that I could shrink that space in the first post even further, but there seems to be some limiting factor if I go above -DRAM_TILES_COUNT=30.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Why can't I add more RAM tiles?

Post by Jubatian »

Could you try to reproduce this with a program which is available in source? Such as the SuperMarioDemo on Master?

That demo has 38 RAM tiles by the way, and it doesn't seem to have problems with it. I tried to experience with it, but I couldn't find out how to add more sprites to see what happens when the RAM tile limit is exhausted (I never used the Mode 3 sprite interface, so as of now it is cryptic to me. I only worked on the back-end, not caring much about what it does).
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Why can't I add more RAM tiles?

Post by Artcfox »

I couldn't reproduce it using the SuperMarioDemo, because that demo doesn't use as many sprites to eat all the RAM tiles. However, I was able to change my Makefile to this just fine:

Code: Select all

KERNEL_DIR = ../../../kernel
KERNEL_OPTIONS  = -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSCROLLING=1 -DSOUND_MIXER=1 -DSOUND_CHANNEL_5_ENABLE=0
KERNEL_OPTIONS += -DMAX_SPRITES=23 -DRAM_TILES_COUNT=39 -DSCREEN_TILES_V=28 -DSCREEN_TILES_H=28
KERNEL_OPTIONS += -DVRAM_TILES_V=32
I could increase the RAM_TILES_COUNT to 39, as long as I decreased the MAX_SPRITES down to 23. I checked this against older versions of the kernel, like from mid 2015 (before any of the hardcore optimization work), and I saw the same corruption with a MAX_SPRITES greater than 17, and a RAM_TILES_COUNT of 39.

So my best guess is that I'm being limited by the blitter. I tried setting RT_ALIGNED=1, and changing the LDFLAGS to:

Code: Select all

LDFLAGS += -Wl,--section-start,.noinit=0x800100 -Wl,--section-start,.data=0x800D00
and then I was able to set MAX_SPRITES=24, but the RAM_TILES_COUNT needs to be limited to 32. Anything beyond 32 again causes corruption.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Why can't I add more RAM tiles?

Post by Jubatian »

Artcfox wrote: Wed Mar 28, 2018 11:29 am(...) I checked this against older versions of the kernel, like from mid 2015 (before any of the hardcore optimization work), and I saw the same corruption with a MAX_SPRITES greater than 17, and a RAM_TILES_COUNT of 39.
I was very cautious to leave everything above the blitter as-is, apparently I succeeded with it. That is, I successfully preserved the bug :P

I am pretty sure it is not the blitter, the bug is above that. You should have a working system with SPRITES_AUTO_PROCESS set zero (that is, if you ditched the traditional sprite management of Mode 3 and used it the "Mode 74 way").

What you may try is just setting SPRITES_VSYNC_PROCESS zero, and modifying the game to use RestoreBackground() and ProcessSprites() around the WaitVsync() function. If the bug comes from a hazard (you are writing the sprites array when the VSync interrupt strikes), this should eliminate it. It would be good to know if this is the case since such problems are very difficult to track down.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Why can't I add more RAM tiles?

Post by Artcfox »

Ha!

Thank you so much, that fixed it completely!

All I had to do was set:

Code: Select all

KERNEL_DIR = ../../../kernel
KERNEL_OPTIONS  = -DVIDEO_MODE=3 -DINTRO_LOGO=0 -DSCROLLING=1 -DSOUND_MIXER=1 -DSOUND_CHANNEL_5_ENABLE=0
KERNEL_OPTIONS += -DMAX_SPRITES=24 -DRAM_TILES_COUNT=40 -DSCREEN_TILES_V=28 -DSCREEN_TILES_H=28
KERNEL_OPTIONS += -DVRAM_TILES_V=32 -DRT_ALIGNED=0 -DSPRITES_VSYNC_PROCESS=0

LDFLAGS += -Wl,--section-start,.noinit=0x800100 -Wl,--section-start,.data=0x800500
And wrap WaitVsync:

Code: Select all

    ProcessSprites();
    WaitVsync(1);
    RestoreBackground();
(It doesn't work with RT_ALIGNED=1, all the sprites vanish.)

And now I can use 40 RAM tiles, with 24 sprites, with no corruption! :D

So it would seem like this should become the default recommended method to use rather than call WaitVsync(1) the old way. Are there any downsides, or does this just make it so nothing interrupts user code?
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Why can't I add more RAM tiles?

Post by Jubatian »

I checked it from the PM, for me the same, SPRITES_VSYNC_PROCESS does the fix, with RT_ALIGNED set (I kept it that way as I got it that way). I think you just forgot to adjust the .data start in the Makefile.

It seems like at this point the game has a blitting bottleneck, that is, it runs out of VBlank time. So the bug is most likely an interrupt hazard occurring somehow, possibly related to the management of the VRAM related to the sprites.

Yes, I would recommend using SPRITES_VSYNC_PROCESS zero, CONTROLLERS_VSYNC_READ zero, and if it was carried ofer from FoaD, then also to move ProcessMusic out of the VSync interrupt. These all call for trouble somewhere down the road (Audio can also produce a weird mess, I did the change in FoaD especially since I experienced it happening: FoaD does nothing in its VSync interrupt).
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Why can't I add more RAM tiles?

Post by Artcfox »

What did you use for a data start? I copied the LDFLAGS line from a comment for using RT_ALIGNED in the kernel's code (videoMode3.def.h)

When I set CONTROLLERS_VSYNC_READ zero, what do I need to add to get controller input back in my game? Is this the correct order?

Code: Select all

    ProcessSprites();
    WaitVsync(1);
    RestoreBackground();
    ReadControllers();
For ProcessMusic, I see that's an a .s file. Would I need to change the kernel to remove it from the VSync interrupt? And then how would I still get music to work? Call it like I did ReadControllers() above?
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Why can't I add more RAM tiles?

Post by Jubatian »

Artcfox wrote: Wed Mar 28, 2018 1:26 pmWhat did you use for a data start? I copied the LDFLAGS line from a comment for using RT_ALIGNED in the kernel's code (videoMode3.def.h)
You have to calculate it by the number of RAM tiles you have (the location for .data is after the VRAM and the RAM tiles, so if you increase the RAM tile count, for each RAM tile, you have to add 64).
Artcfox wrote: Wed Mar 28, 2018 1:26 pmWhen I set CONTROLLERS_VSYNC_READ zero, what do I need to add to get controller input back in my game? Is this the correct order?
You can have it anywhere, ideally read the controllers before processing them for the lowest latency. It doesn't matter a lot, though, I don't think it can actually have any notable hazard.
Artcfox wrote: Wed Mar 28, 2018 1:26 pmFor ProcessMusic, I see that's an a .s file. Would I need to change the kernel to remove it from the VSync interrupt? And then how would I still get music to work? Call it like I did ReadControllers() above?
As of now you would have to tweak the kernel to have it that way, it would go the way you describe. Remove ProcessMusic from the VSync interrupt, and call it yourself. It will work as long as you are not losing frames (so it might not be a good idea, in FoaD it was straightforward since that game is designed in such a manner that it is impossible to lose frames). So you either might happen to experience hazards (in FoaD it manifested in occasional loud 1 frame noise bursts), or have your music slowing down (frequency of notes will stay, only envelopes are affected).
Post Reply