At the moment, we have 6 native functions to peek and poke the memory :
v=peek(addr, [n] ) you also have v=@addr that is equivalent to peek(addr,1) and peek(addr)
v=peek2(addr, [n] ) and v=%addr
v=peek4(addr, [n] ) and v=$addr
poke ( addr, [value,] [...] )
poke2( addr, [value,] [...] )
poke4( addr, [value,] [...] )
What could be a good extension of this ? The problem is not really the coding part, but rather coming up with conventions that fit well withing the pico8 universe...
poke3 seems like a simple addition, but what three bytes should be copied from the value ?
Pico8 is a little endian universe XXXX read from value ..... ignored [ pico8 numeric value ] [fraction ] [integer ] Byte0 Byte1 Byte2 Byte3 poke ..... ..... XXXXX ..... poke2 ..... ..... XXXXX XXXXX poke3 ????? XXXXX XXXXX ????? poke4 XXXXX XXXXX XXXXX XXXXX |
Since our standard pico8 numbers are 16.16 bits, we can't go further, poke5 wouldn't make sense.
What we could do is going in the other direction with powers of 2, poke_nibble(), poke_half_nibble() and poke_bit()
That's a whole new can of worm : what is the first bit of a byte ?
To me (It's a convention, feel free to disagree and argue) it makes sense that bits are ordered from least significant to most significant in a byte, in similar little endian spirit than the rest.
Each bit in memory would have an address : bit 0 would have the same address as the byte containing it, bit 1 would have 1/8 more that the previous bit, bit 7 would have 7/8 more.
This fits nicely with how the screen is memory mapped :
pixel_address=0x6000+(128*y+x)/2
second pixel of the 1st screen row would have address 0x6000.8
Here's what I propose :
peekn(byte_size,fractional_address, [n]) poken(byte_size,fractional_address,[value,] [...] ) Example uses : bs=1/8 -- bit size in bytes, or 0.125 in decimal 0x0.2 in hexa poken(4*bs,0x6000+(128*y+x)/2,color) -- same effect as pset(x,y,color) minus pal shenanigans poken(bs,0x5e00+idx*bs,1) -- treats cartdata spaces as 2048 flags and sets flag idx to 1 peekn(1,addr) -- equivalent to peek(addr) if addr is an integer peekn(2,addr) -- equivalent to peek2(addr) if addr is an integer peekn(4,addr) -- equivalent to peek4(addr) if addr is an integer |
Only the integer part and the three most significant bits for the fractional part of an address would be taken into account.
For the value, for byte_size between 1/8 and 2, only the least significant bits of the integer part would be taken into account, to stay in line with peek and peek2.
From 17*bs to 4, the most significant bits would count.
That would make poken(3,addr,value) write byte1, byte2 and byte3 from value to addr, addr+1 and addr+2.
Or we could drop compatibility with poke and have a more coherent scheme. I don't like the drawbacks of either solution... What would you wish for ?
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/85395/picocolordance_24.gif)
Newbie question here, but what is the difference between using poke
and memset
?
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](/media/82211/7_realshadowcaster.png)
@kozm0naut With poke you give all the values you want to write to memory. Memset writes a single value multiple times.
![](/gfx/set_like0.png)
![](/gfx/top_drop.png)
![](https://www.lexaloffle.com/bbs/files/32759/comovic.gif)
I probably had a similar goal.
But I didn't come up with the idea of poken()/peekn()
.
In my case, rather than extending poke()/peek()
, I created a function that performs bitwise operations to suit poke()/peek()
.
It stuffs bits of different lengths into the 1 byte needed for poke()
.
It also expands the 1 byte obtained from peek()
into a bit tuple of different lengths.
The bitshift argument allows it to support up to 4 bytes.
BPACK() [Pack with bit value. (different bit widths supported)]
BUNPACK() [The bit value slice and unpack]
For now I'm using it to save space in cartdata and sprite sheets.
[Please log in to post a comment]