Have you ever considered saving data into a pixel's color, but never understood what magical compression operations go on in the background?
Every pixel takes up 16 bits of storage, and this code lets you take advantage of that space.
'STORE A NUMBER FROM 0 TO 65535 (16 BITS) TO A PIXEL
DEF STORE X,Y,N
DIM PIXEL%[1]
PIXEL%[0]=N
GLOAD X,Y,1,1,PIXEL%,TRUE,TRUE
END
'RETRIEVE A NUMBER FROM A PIXEL
DEF UNSTORE(X,Y)
DIM PIXEL%[1]
GSAVE X,Y,1,1,PIXEL%,TRUE
RETURN PIXEL%[0]
END
Now, you could stop here, but we want to be able to make use of every single bit, allow larger numbers, and not have to worry about which pixel contains what data.
Using these two functions, we can construct a data structure.
Storing pixel to pixel, we will start from the bottom left hand corner of the graphics page, and work our way left to right, and then bottom to the top.
So our goal here is to have all the pixels work together to let you store any bit amount without worrying about the 0 TO 65535 (16 BIT) limitation.
Let's contruct a stack data structure:
'GLOBAL VARIABLES
VAR DATAX,DATAY=511,DATAP
DATAX is the x position of the current pixel
DATAY is the y position of the current pixel
DATAP is the bit position inside that current pixel
'PUSH SOME BITS ONTO THE GRAPHICS SCREEN
DEF PUSHDATA N,BITS
VAR I,D%
FOR I=1 TO BITS
D%=UNSTORE(DATAX,DATAY)
STORE DATAX,DATAY,D%*2+(N-2*FLOOR(N/2))
DATAP=DATAP+1
IF DATAP>15 THEN
DATAP=0
DATAX=DATAX+1
IF DATAX>511 THEN DATAX=0 DATAY=DATAY-1
ENDIF
N=N/2
NEXT
END
'POP SOME BITS OFF THE GRAPHICS SCREEN
DEF POPDATA(BITS)
VAR I,D%,N
FOR I=1 TO BITS
DATAP=DATAP-1
IF DATAP<0 THEN
DATAP=15
DATAX=DATAX-1
IF DATAX<0 THEN DATAX=511 DATAY=DATAY+1
ENDIF
D%=UNSTORE(DATAX,DATAY)
N=N*2+(D%-2*FLOOR(D%/2))
STORE DATAX,DATAY,D%/2
NEXT
RETURN N
END
So now we have a fully functional stack that is stored inside the graphics page, and can be loaded and saved along with a sprite page
Here is some test code
PUSHDATA 2147483648,31
PUSHDATA 2147483647,31
PUSHDATA 1,1
PUSHDATA 255,8
PUSHDATA 15,4
?POPDATA(4) 'BYTE
?POPDATA(8) 'CHARACTER
?POPDATA(1) 'BOOLEAN
?POPDATA(31) 'INTEGER
?POPDATA(31) 'OVERFLOWED INTEGER
The output should be 15, 255, 1, 2147483647, 0
Overflows work the exact same as they do in other programming languages
Keep in mind that if you are going to save and load this graphics page, you will also need to save the ending DATAX, DATAY, and DATAP variables, then load them along with the graphics page in order to ensure that the state of the stack remains the same.This is the algorithm used in Fractal Canvas to save each design along with directions on how to navigate to that design (screenshot)
10 Comment(s)12Me21Syntax HighlighterReceived for creating the code syntax highlighter on SBSNight PersonI like the quiet night and sleep late.Express YourselfIt might be faster to do something like:
DEF STORE X,Y,N
DIM PIXEL%[1]
PIXEL%[0]=N
GLOAD X,Y,1,1,PIXEL%,TRUE,TRUE
END
DEF UNSTORE(X,Y)
DIM PIXEL%[1]
GSAVE X,Y,1,1,PIXEL%,TRUE
RETURN PIXEL%[0]
END
We determined that it was faster for doing many values at once, but I'm not sure about single numbers.SimeonScholarReceived for knowing a great deal about programming topicsAchievementsAmazing PageHiddenAchievementsDrawingI like to draw!HobbiesOh my gosh you're right
Add RETURN PIXEL%[0] to UNSTORE, and this works much better
And it stores numbers up to 65535 (16 bits)
Wow thank you, ill see if I can implement this!SimeonScholarReceived for knowing a great deal about programming topicsAchievementsAmazing PageHiddenAchievementsDrawingI like to draw!HobbiesI'm certain there's a better algorithm for PUSHDATA and POPDATA, to update more than one bit at a time.
But as of right now this seems to be a really fast algorithm, and I'll figure that part out in the future.
Thanks so much for the help 12Me21!raimondzFirst WeekJoined in the very first week of SmileBASIC SourceWebsiteExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthNight PersonI like the quiet night and sleep late.Express YourselfI suggest that the method store and unstore should use an array and gload instead of gpset and gsave because graphic functions are slow.
Here is a performance comparison between those methods.
SimeonScholarReceived for knowing a great deal about programming topicsAchievementsAmazing PageHiddenAchievementsDrawingI like to draw!HobbiesThat's when drawing graphics in bulk, like filling a whole graphics page. I updated Fractal Canvas to do this because it was a big performance improvement, but it would not help in this situation because it only draws one or two pixels per function call.
Thanks for the suggestion!12Me21Syntax HighlighterReceived for creating the code syntax highlighter on SBSNight PersonI like the quiet night and sleep late.Express YourselfI recommend using >> and << instead of * and /, and writing some of the numbers in hexadecimal so they're more readable.SimeonScholarReceived for knowing a great deal about programming topicsAchievementsAmazing PageHiddenAchievementsDrawingI like to draw!HobbiesHexadecimal, i'll do that.
But >> and << have overflow protectors which I was trying to avoid for this12Me21Syntax HighlighterReceived for creating the code syntax highlighter on SBSNight PersonI like the quiet night and sleep late.Express YourselfOverflow protectors?SimeonScholarReceived for knowing a great deal about programming topicsAchievementsAmazing PageHiddenAchievementsDrawingI like to draw!HobbiesYeah they give you an overflow error when the number is too big
Same with MOD so I avoided that too12Me21Syntax HighlighterReceived for creating the code syntax highlighter on SBSNight PersonI like the quiet night and sleep late.Express YourselfAND does the same thing, so it's not possible for >> and << to cause problems here. And you should store integers in integer variables anyway.
DEF STORE X,Y,N DIM PIXEL%[1] PIXEL%[0]=N GLOAD X,Y,1,1,PIXEL%,TRUE,TRUE END DEF UNSTORE(X,Y) DIM PIXEL%[1] GSAVE X,Y,1,1,PIXEL%,TRUE RETURN PIXEL%[0] END
We determined that it was faster for doing many values at once, but I'm not sure about single numbers.