I am working on my first ever game, a gltich themed breakout, based on the Squashy from Pico8 Zine#1 and I am now working on making the glitch effects that will be part of the gameplay. What I have now is a way to add a static noise through pget and pset and this kinda corrupted VHS by using random values over x06000 with memcpy.
Memcpy is great for making random glitch effects. But what if we want to, for example, take something from a particular part of the screen and paste it another place we have chosen. Right now I am just doing a trial and error of values and if I get close, I call it a day... but I think there has to be a better way.
Basically, I am wondering if there is a way to find exact memory address of particular screen coordinates? Some kind of a map perhaps of x,y coordinates and memory values? Or even better... a formula that we can use to input x,y of source and destination that would return the memory values we can use memcpy on.
I am pretty sure that there has to be a some kind of underlying math that translates one to the other, but I am a noob, so don't even know where to start trying to back-engineer it.
Would such a map be possible, or would the memory values change depending on color of each pixel for example?
With help from @TRASEVOL_DOG and after repeatedly POKEing at Pico8 memory I got the first part of the puzzle - finding the exact memory value(v) for a pixel at x,y.
0x6000 corresponds to the pixel at 0,0. Each +1 to the value after 0x6000 moves the the pixel on the screen two pixels to the right. It moves it two pixels because of computer science concepts I don't understand. For time being, let's just assume this is how it is. So: 0x6001 is 2,0. 0x6002 is 4,0 and so on... After the value reached the end of the screen (127 on x axis, so after adding 63 to the screen memory value) it moves down one line and back to the leftmost pixel. So 0,1 is 0x6040 (or 0x6000 +64).
From that we can see that it requires 64 to be added to the beginning of screen memory (0x6000) to change Y by +1. From that we can create a formula that returns the screen memory value(v):
v = 0x6000 + y*64 + flr(x/2)
Sure, it only let's us access even pixels on X axis, but it is much better than just stabbing in the dark with memcpy or poke. If anyone has an idea on how to access each pixel, feel free to expand the formula.
Anyway, from that we can easily calculate length for things like memcpy, so we can easily copy exact length as (long as what we want is lines) and paste it wherever we need it. For something like copying rectangles it would be easier to copy all the lines containing the rectangle needed to spare place in a sprite sheet and use sspr to paste it in the place we need. It would be possible to memcpy multiple lines to create a rectangle as well. It would be a bit more messy, but it might be faster(?). I will try to come up with a function/formula for this approach soon.
That's it for now. All feedback welcome.
Edit: Blokatt beat me to it!
Also keep in mind that you can run into trouble with non-integer Y values. The graphics API truncates x and y, but if you're doing the address math manually, you can easily multiply 64 by a fractional value and end up at some random horizontal position by accident. You can ignore X's fraction, but definitely use FLR(Y).
Thanks Felice, I will definitely keep that in mind! I plan on using this formula mostly to get value from x,y but I will make sure I have flr(y) when calculating the other way around.
@Blokatt, is there a way to incorporate the right pixel into the value formula, so it works for both left and right pixel?
so you're there:
addr = 0x6000+flr(y)*64+x/2
mem = peek(addr)
then you have :
(1) mem = left_pixel + right_pixel*16
(2) left_pixel = mem%16
(3) right_pixel=flr(mem/16) (or (mem-left)/16, same result here)
to change a single pixel you extract the one you want to keep with (2) or (3), then set the one you want (while also putting back the one you keep) using (1):
poke (addr, left_pixel + new_right_pixel16) for the right one
poke (addr, new_left_pixel + right_pixel16) for the left one
well, while I was at it, I wrote this:
function zonecpy(sx,sy,dx,dy,w,h) if (sx+w>128) w=128-sx if (dx+w>128) w=128-dx if (sy+h>128) h=128-sy if (dy+h>128) h=128-dy w = w/2 sad = 0x6000+flr(sy)*64+sx/2 dad = 0x6000+flr(dy)*64+dx/2 for y=1,h do memcpy(dad,sad,w) sad+=64 dad+=64 end end
copies a memory block of size (w,h) from (sx,sy) to (dx,dy)
the block is cropped at the left and bottom screen edges and rounded on an even width, then copied line by line. this is directly from screen to screen, you could get an infinite mirror effect if the source and destination overlap. if you end up using sspr, you'll be able to flip or stretch the block or change its palette when drawing it back. (just remove 0x6000 from 'dad' to copy to sprite mem)
hope that'll help, have fun :)
[Please log in to post a comment]