The 0x5600+ area doesn't get reset properly when a new cartridge is loaded, or the current one is run again. Pretty easy to replicate, but here's a demo:
poke(0x5600,unpack(split"5,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,7,7,0,0,0,0,7,7,7,0,0,0,0,0,7,5,7,0,0,0,0,0,5,2,5,0,0,0,0,0,5,0,5,0,0,0,0,0,5,5,5,0,0,0,0,4,6,7,6,4,0,0,0,1,3,7,3,1,0,0,0,7,1,1,1,0,0,0,0,0,4,4,4,7,0,0,0,5,7,2,7,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,3,3,0,0,0,5,5,0,0,0,0,0,0,2,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,5,5,0,0,0,0,0,0,10,31,10,31,10,0,0,0,2,7,1,6,7,2,0,0,5,4,2,1,5,0,0,0,6,6,3,5,7,0,0,0,1,1,0,0,0,0,0,0,2,1,1,1,2,0,0,0,2,4,4,4,2,0,0,0,4,21,14,21,4,0,0,0,0,2,7,2,0,0,0,0,0,0,0,0,2,1,0,0,0,0,7,0,0,0,0,0,0,0,0,0,1,0,0,0,4,2,2,2,1,0,0,0,7,5,5,5,7,0,0,0,2,3,2,2,7,0,0,0,7,4,7,1,7,0,0,0,7,4,6,4,7,0,0,0,5,5,7,4,4,0,0,0,7,1,7,4,7,0,0,0,1,1,7,5,7,0,0,0,7,4,4,4,4,0,0,0,7,5,7,5,7,0,0,0,7,5,7,4,4,0,0,0,0,1,0,1,0,0,0,0,0,2,0,2,1,0,0,0,4,2,1,2,4,0,0,0,0,7,0,7,0,0,0,0,1,2,4,2,1,0,0,0,3,4,6,0,2,0,0,0,6,9,13,1,14,0,0,0,0,3,6,5,7,0,0,0,1,3,5,5,7,0,0,0,0,2,1,1,3,0,0,0,4,6,5,5,7,0,0,0,0,6,5,3,6,0,0,0,2,1,3,1,1,0,0,0,0,6,5,7,4,3,0,0,1,3,5,5,5,0,0,0,1,0,1,1,1,0,0,0,2,0,2,2,2,1,0,0,1,5,5,3,5,0,0,0,1,1,1,1,2,0,0,0,0,15,21,21,21,0,0,0,0,3,5,5,5,0,0,0,0,6,5,5,3,0,0,0,0,6,5,7,1,1,0,0,0,6,5,7,4,4,0,0,0,3,1,1,1,0,0,0,0,3,1,2,3,0,0,0,1,3,1,1,2,0,0,0,0,5,5,5,6,0,0,0,0,9,9,5,2,0,0,0,0,17,21,21,30,0,0,0,0,5,2,2,5,0,0,0,0,5,5,7,4,3,0,0,0,3,2,1,3,0,0,0,3,1,1,1,3,0,0,0,1,2,2,2,4,0,0,0,3,2,2,2,3,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,7,0,0,0,1,2,0,0,0,0,0,0,6,5,7,5,5,0,0,0,7,5,3,5,7,0,0,0,6,1,1,1,6,0,0,0,3,5,5,5,3,0,0,0,7,1,3,1,7,0,0,0,7,1,3,1,1,0,0,0,6,1,13,9,6,0,0,0,5,5,7,5,5,0,0,0,1,1,1,1,1,0,0,0,6,4,4,4,3,0,0,0,5,5,3,5,5,0,0,0,1,1,1,1,7,0,0,0,17,27,21,17,17,0,0,0,9,11,13,9,9,0,0,0,6,9,9,9,6,0,0,0,7,5,7,1,1,0,0,0,6,9,9,9,6,12,0,0,7,5,3,5,5,0,0,0,6,1,7,4,3,0,0,0,7,2,2,2,2,0,0,0,5,5,5,5,6,0,0,0,17,17,10,10,4,0,0,0,17,17,21,27,17,0,0,0,5,5,2,5,5,0,0,0,5,5,7,2,2,0,0,0,7,4,2,1,7,0,0,0,6,2,3,2,6,0,0,0,2,2,2,2,2,0,0,0,3,2,6,2,3,0,0,0,0,10,5,0,0,0,0,0,0,2,5,2,0,0,0,0,127,127,127,127,127,0,0,0,85,42,85,42,85,0,0,0,65,127,93,93,62,0,0,0,62,99,99,119,62,0,0,0,17,68,17,68,17,0,0,0,4,60,28,30,16,0,0,0,28,46,62,62,28,0,0,0,54,62,62,28,8,0,0,0,28,54,119,54,28,0,0,0,28,28,62,28,20,0,0,0,28,62,127,42,58,0,0,0,62,103,99,103,62,0,0,0,127,93,127,65,127,0,0,0,56,8,8,14,14,0,0,0,62,99,107,99,62,0,0,0,8,28,62,28,8,0,0,0,0,0,85,0,0,0,0,0,62,115,99,115,62,0,0,0,8,28,127,62,34,0,0,0,62,28,8,28,62,0,0,0,62,119,99,99,62,0,0,0,0,5,82,32,0,0,0,0,0,17,42,68,0,0,0,0,62,107,119,107,62,0,0,0,127,0,127,0,127,0,0,0,85,85,85,85,85,0,0,0,14,4,30,45,38,0,0,0,17,33,33,37,2,0,0,0,12,30,32,32,28,0,0,0,8,30,8,36,26,0,0,0,78,4,62,69,38,0,0,0,34,95,18,18,10,0,0,0,30,8,60,17,6,0,0,0,16,12,2,12,16,0,0,0,34,122,34,34,18,0,0,0,30,32,0,2,60,0,0,0,8,60,16,2,12,0,0,0,2,2,2,34,28,0,0,0,8,62,8,12,8,0,0,0,18,63,18,2,28,0,0,0,60,16,126,4,56,0,0,0,2,7,50,2,50,0,0,0,15,2,14,16,28,0,0,0,62,64,64,32,24,0,0,0,62,16,8,8,16,0,0,0,8,56,4,2,60,0,0,0,50,7,18,120,24,0,0,0,122,66,2,10,114,0,0,0,9,62,75,109,102,0,0,0,26,39,34,115,50,0,0,0,60,74,73,73,70,0,0,0,18,58,18,58,26,0,0,0,35,98,34,34,28,0,0,0,12,0,8,42,77,0,0,0,0,12,18,33,64,0,0,0,125,121,17,61,93,0,0,0,62,60,8,30,46,0,0,0,6,36,126,38,16,0,0,0,36,78,4,70,60,0,0,0,10,60,90,70,48,0,0,0,30,4,30,68,56,0,0,0,20,62,36,8,8,0,0,0,58,86,82,48,8,0,0,0,4,28,4,30,6,0,0,0,8,2,62,32,28,0,0,0,34,34,38,32,24,0,0,0,62,24,36,114,48,0,0,0,4,54,44,38,100,0,0,0,62,24,36,66,48,0,0,0,26,39,34,35,18,0,0,0,14,100,28,40,120,0,0,0,4,2,6,43,25,0,0,0,0,0,14,16,8,0,0,0,0,10,31,18,4,0,0,0,0,4,15,21,13,0,0,0,0,4,12,6,14,0,0,0,62,32,20,4,2,0,0,0,48,8,14,8,8,0,0,0,8,62,34,32,24,0,0,0,62,8,8,8,62,0,0,0,16,126,24,20,18,0,0,0,4,62,36,34,50,0,0,0,8,62,8,62,8,0,0,0,60,36,34,16,8,0,0,0,4,124,18,16,8,0,0,0,62,32,32,32,62,0,0,0,36,126,36,32,16,0,0,0,6,32,38,16,12,0,0,0,62,32,16,24,38,0,0,0,4,62,36,4,56,0,0,0,34,36,32,16,12,0,0,0,62,34,45,48,12,0,0,0,28,8,62,8,4,0,0,0,42,42,32,16,12,0,0,0,28,0,62,8,4,0,0,0,4,4,28,36,4,0,0,0,8,62,8,8,4,0,0,0,0,28,0,0,62,0,0,0,62,32,40,16,44,0,0,0,8,62,48,94,8,0,0,0,32,32,32,16,14,0,0,0,16,36,36,68,66,0,0,0,2,30,2,2,28,0,0,0,62,32,32,16,12,0,0,0,12,18,33,64,0,0,0,0,8,62,8,42,42,0,0,0,62,32,20,8,16,0,0,0,60,0,62,0,30,0,0,0,8,4,36,66,126,0,0,0,64,40,16,104,6,0,0,0,30,4,30,4,60,0,0,0,4,62,36,4,4,0,0,0,28,16,16,16,62,0,0,0,30,16,30,16,30,0,0,0,62,0,62,32,24,0,0,0,36,36,36,32,16,0,0,0,20,20,20,84,50,0,0,0,2,2,34,18,14,0,0,0,62,34,34,34,62,0,0,0,62,34,32,16,12,0,0,0,62,32,60,32,24,0,0,0,6,32,32,16,14,0,0,0,0,21,16,8,6,0,0,0,0,4,30,20,4,0,0,0,0,0,12,8,30,0,0,0,0,28,24,16,28,0,0,0,8,4,99,16,8,0,0,0,8,16,99,4,8,0,0,0")) function _update60() if btnp(5) then poke(0x5f58,peek(0x5f58)^^0x81) end end function _draw() cls(1) print("∧"..tostr(stat(1)),0,0,7) for i=0,14,2 do rectfill(0,9+i*8,127,16+i*8,2) end for i=0,239 do print(chr(i+16),(i<112 and 2 or 0)+8*(i%16),10+8*(i\16),6) end end |
Run once, and toggle between fonts with X. If you completely remove the first line of code, this still works. If you reload the cart and completely remove the first line of code before running it even once, this still works.
Before being designated as the custom font block, 0x5600+ was part of the 0x4300+ general use region; it continues to still serve in that role. The general use region does not get reset and can be used to pass data between carts with load(), this is a known undocumented feature.
If this is for backwards compatibility, I can understand, but I'm not happy about it. I feel like there should be a bit flag set for this persistent behavior, because even the current, officially recommended #font_snippet cart has a bug right now. It can generate fonts with data from the sprite sheet and memory blended together, if they don't happen to have the same number of glyphs in them. I'd recommend fixing that cart to memset the whole region blank, at the very least.
I'd also recommend resetting the 0x5600 area in splore, just so that each game loaded from blank gets a fresh set of glyphs by default. We were talking in the discord about this, and the worry is that a bug in which characters get set in the custom font could make everyone's experience look different, based on what games they've played before.
I think the manual should also recommend resetting the area with a memset in your own code, if you plan to do anything with custom fonts. Otherwise, debugging font adjustments could show something different than what's actually being updated.
> I'd also recommend resetting the 0x5600 area in splore
I would definitely agree with this. Any RAM expected to be persistent between runs should still be initialized when coming directly from Splore, since that is guaranteed not to be "between runs", but more like a fresh boot.
As for resetting it the rest of the time... it's unfortunate, but that RAM is indeed just user ram which can be repurposed. I think it needs to work the way it does. I'm pretty sure you can work around it by detecting the circumstances, whereas someone who needs it not to be reset would have no way to work around it being reset for them.
Yeah, agreed with both points. I think the custom font section in the manual should say something about always initializing the area with memset(0x5600,0,0x800) if you plan to use fonts though, because of the legacy behavior. For debugging purposes if nothing else, as in normal usage you should assume that nothing currently in memory will persist.
I'm leaving this up as a documentation bug because of that.
[Please log in to post a comment]