it is not possible to delete the high-memory with one memset-command
poke(0x8000,1) poke(0xffff,1) ?peek(0x8000)--1 ?peek(0xffff)--1 memset(0x8000,2,0x8000) ?peek(0x8000)-- still 1 / should 2 ?peek(0xffff)-- still 1 / should 2 memset(0x8000,2,0x7fff) -- ?peek(0x8000)--2 ?peek(0xffff)--1
the first memset is ignored, because 0x8000 is -1
this is true, but I wouldn't consider it a bug. 0x8000 is -32000 or so, and memsetting a length of -32000 doesn't make sense.
(I suppose you could argue that memset should treat its input as an unsigned integer? but it's nice how pico8 just has one numeric type, without special cases like this)
edit: I changed my mind, see my later comment
Hm, I suppose you could argue that memset should treat its inputs as unsigned integers. After all, the addresses are already conceptually unsigned, despite technically being negative... the manual lists the 0x8000 region as if it were after 0x6000, which is how I think of it too (I assume most people do).
I've changed my mind -- I support this change (although it doesn't seem high-priority). It's easy to work around (e.g.
memset(0x8000,0,0x4000) memset(0xc000,0,0x4000)) but it could be nice to remove this common pitfall. Hopefully people aren't relying on
memset(addr,val,-100) to be a no-op?
If this is changed, some other length APIs should be changed too (
peek()'s length argument,
ord()'s length argument. others?)
On the subject of treating values differently for lengths, that would match with other programming languages that allow manual memory operations using size_t and such. I don't think it matter much though. I actually don't think zero-ing all of upper memory makes much sense, given that use of upper memory only makes sense if you either need to smuggle more data into your cart or need to store data that will be transferred quickly into the other engine sections. In both cases a memcpy of 0x4000 or less makes more sense.
"the manual lists the 0x8000 region as if it were after 0x6000, which is how I think of it too (I assume most people do)."
I would be really surprised if that wasn't real. Having to make functions like memset do loopy emulations of contiguous engine memory would be soooo much work while just having the memory actually be laid out the way the manual says it is would be dead simple under the hood.
You can move the map to the 0x8000-0xffff region to create a 256x128 map. When you want to use this map-content, you cant' just copy maps from the lower part.
I created a "object"-based map-struckture, but for faster handling, it is "drawn" to the upper memory block. First step is than to delete the "map", then "draw" the object into it.
Ultimately this sort of thing always comes down to arbitrary choices.
One project I worked on had a DMA controller that would transfer up to, and including, 64k of data at a time. Unsigned 16-bit lengths of 1-65535 were accepted as-is, and 0 was inferred to mean 65536, not 0, because if the length is 0, you should instead just not initiate a transfer at all. Laughs were had by all when someone failed to catch rare zero-length DMAs and it wiped the entire contents of remote RAM, randomly hard-crashing the entire machine with no debuggability remaining. Good times.
In this case, even if we were to convince zep to treat the second arg as unsigned, he'd have to say you can't do a full 64k in one go, because the existing behavior is that a 0-length memset is a valid no-op and can't be reassigned to 64k. But that's fine, there's no reason you'd ever do a full 64k on PICO-8, since you'd clobber all of the "hardware" registers.
[Please log in to post a comment]