Just a sandbox to get a better understanding of what happens when you change the map width (0x5f57) and the map address (0x5F56)
Upper memory 0x8000-0xFFFF is fully initialized to 53 (blue square sprite)
Arrow keys to move the camera
X / O to change the map width
pause menu to change what X/O changes between map width and map address.
Title says it all.
Problem is the same on firefox and safari on Mac, and on safari on iPhone.
Embed arrow still works, so you can still get the cart's id from it and view the game's code in pico-8's editor.
I've spent two hours fixing a nasty bug. The image above is essentially the bug I was trying to fix, except all the steps were spread in three functions, and took a good minute of playing on average before everything aligned just right (or just wrong depending on how you look at it) for it to seemingly randomly occur.
Can you figure out why t[2] is not 8 in the end ?
Hint : Lua arrays and # operator are cursed.
Ideally, I'd like the game to crash at t[i]=8 if possible. Anyone knows if you can add some sanity checks to all array accesses ?
A lot of old games save space by using the same data for multiple purposes. I’ve seen code used as graphics, code inside graphics, graphics containing map data, and was daydreaming what parts of pico8 could be interesting to use as double purpose.
The game thumbnail seems very promising : 128x128 32 Colors is 10Kb worth which is pretty big for pico8.
There ´s nohing in the api related to it, just a keyboard shortcut to save the current screen to it. It’s hidden when using the built in editor, but you can see it when viewing a .p8 file.
I’m a newbie in lua, and don’t know if it’s a valid lua section, or maybe a type of multi line named comment designed for documentation for example.
Or maybe it’s just part of the .p8 format and never passed to the interpreter ?
If there’s a way in code to interact with it, I’d love to know.
Or maybe the source code is somehow in the scope of the program and can be opened and parsed ?
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 ?