Log In  

Cart #28897 | 2016-09-20 | Code ▽ | Embed ▽ | No License

64 values of save data ain't enough for you? Try using this! These functions will allow you to save up to 2,048* values in persistent data! Anyone's free to use it in their own projects; I'm personally releasing this under CC4-BY-SA to allow works using these functions to be sold.

*If you only accepted ON and OFF as acceptable values.

Here's a comprehensive manual on how to use these functions:


                 Pico-8 Binary Functions Set

                                             PRGM ver. 1.1.1
Created by A-zu-ra                         MANUAL ver. 1.1.2


This function set includes functions that will:
  - Convert a given integer into a 16-item table of
    binary values
  - Read a portion of the generated 16-item table
  - Insert a given table into another table at any position
  - Converts a given table of binary values into an integer

Through these functions, you can essentially use one integer
to serve multiple purposes. This document will not only
cover how the functions work, but also how to apply them in
the context of Pico-8's persistent data.

Included with this function set is a brief test program
showcasing all of the functions in action.

    INT COUNT increments once a frame in both whole number
    and decimal and is a base for all of the functions in
    the test.

    BIN START is the START variable of binread.
    BIN RANGE is the RANGE variable of binread.

    BIN TO INT tests reconversion of binary back to integer.
    BIN TO DEC tests reconversion of binary back to decimal.
    B2I + B2D is the values of BIN TO INT and BIN TO DEC
    as a single value.

    RANGE B2I is the integer value of binread.
    INSERT B2I is the integer value of binread inserted into
    another table via binins.
    RANGE B2D and INSERT B2D work the same as RANGE B2I and
    INSERT B2I, but for the decimal subset.

The bottom of the function test contains the RAW BINARY of
the integer, as well as the range of binread and starting
point of binins visualized. In the test code is a section
VALUES!, so feel free to experiment with the values to get
a better feel of how things go together.


inttobin(value, decimal)

    value     An integer within Pico-8's acceptable range
              (-32768 to 32767)
    decimal   A boolean that decides whether or not to pull
              from either whole number or decimal (0 or 1)

    RETURNS a table with 16 values of either 0 or 1

    This function takes an acceptable value that you give it
    and creates a 16-value table, each containing either a
    0 or a 1 in it. The following examples are formatted to
    be human readable; the order is reversed when the table
    is created (i.e. the first example below is, from the
    table's perspective, 0000100000000000).

    16        0000000000010000
    136       0000000010001000
    9570      0010010101100010
    -32768    1000000000000000
    -3530     1111001000110110


binread(table, start, range)

    table     A table generated via inttobin
    start     The starting point to read from
              (remember, tables are 1-indexed)
    range     How many values from the starting point
              to read from

    RETURNS a table with a number of values
    specified in range

    This function takes a table that is generated from
    inttobin and extracts a user specified portion of it.
    This function requires two more additional values: the
    starting point (so you can choose from a different
    section of the table), and a range (so you can extract
    larger values).

    Since the table has the binary values in reverse order,
    the function will appear to go from right to left when
    imagining the ranges in a human readable order. The
    following examples will hopefully give a better visual
    of this.

    Assume that table is {1, 1, 0, 0, 1, 1, 0, 0,
    1, 1, 0, 0, 1, 1, 0, 0}.

    (table, 1, 1)                   S
                     0011001100110011   bintoint: 1
    (table, 1, 5)               E   S
                     0011001100110011   bintoint: 19
    (table, 4, 7)          E     S   
                     0011001100110011   bintoint: 102
    (table, 9, 4)        E  S   
                     0011001100110011   bintoint: 3


binins(table, table2, start)

    table     The table you want to append values to
    table2    A table generated via inttobin or binread
    start     What point in the target table to start at

    RETURNS the target table with table2 appended to it,
    starting from the bit position specified by the user

    This function allows you to combine one table into
    another at any place. It's advised that you calculate
    the size of the table that you want to insert if you
    plan on using this function multiple times on one table.

    Much like the binread function, the function will appear
    to go from right to left when imagining the start point
    in a human readable order.

    Assume that the target table is empty.

    table2 = {1, 0, 0, 1} -- 1001
    (table, table2, 1)                   S
                          0000000000001001   bintoint: 9

    table2 = {1, 0, 1, 0, 1, 1} -- 110101
    (table, table2, 4)                S
                          0000000110101000   bintoint: 424

    table2 = {0, 1, 1, 0, 1} -- 10110
    (table, table2, 7)             S
                          0000010110000000   bintoint: 1408

    Remember to calculate your table sizes.

    table2 = {1, 0, 1, 1} -- 1101                YES
    table3 = {0, 1, 1} -- 110
    (table, table2, 3)            3    2
    (table, table3, 8)            S    S
                          0000001100110100   bintoint: 820
                          (Both tables added in with no

    Otherwise, calling the function again will overwrite
    those bits if the sizes conflict with the positioning.

    table2 = {1, 0, 1, 1} -- 1101                NO
    table3 = {0, 1, 1} -- 110
    (table, table2, 6)            3 2
    (table, table3, 8)            S S
                          0000001100100000   bintoint: 800
                          (Table 3 overwrites last two bits
                           of table 2)


bintoint(table, decimal)

    table     A table generated via inttobin, binread, or
    decimal   A boolean that decides whether or not to write
              to either whole number or decimal (0 or 1)

    RETURNS an integer representation of the binary table

    This function will take a binary table that you give it
    and convert it back into an integer.

    0000000000001000    8
    0000000001000010    66
    0000101000101000    2600
    1000100100001000    -30456


How to apply code in context with Pico-8 persistent data

-- Two 8-bit values (43 tokens)
c = {}
v = {6,6}
for i=1,#v do
f = bintoint(c,0)

(Throw f into persistent data via dset)

To adjust this for other equal bit values, replace B and
adjust the amount of items used in the v table:

for i=1,#v do

         #v  B   Max     Leftover bits
16-bit   1   16  65535*  None left over
15-bit   1   15  32767   1 bit
14-bit   1   14  16383   2 bits
13-bit   1   13  8191    3 bits
12-bit   1   12  4095    4 bits
11-bit   1   11  2047    5 bits
10-bit   1   10  1023    6 bits
9-bit    1   9   511     7 bits
8-bit    2   8   255     None left over
7-bit    2   7   127     2 bits
6-bit    2   6   63      4 bits
5-bit    3   5   31      1 bit
4-bit    4   4   15      None left over
3-bit    5   3   7       1 bit
2-bit    8   2   3       None left over
1-bit    16  1   1       None left over

*Any number past 32767 will be represented as a negative
 value counting towards 0.

-- Different size bit values (47 tokens)
d = {}
s = {5,8}
v = {31,255}
c = 1
for i=1,#v do
 c += s[i]
f = bintoint(d)

(Throw f into persistent data via dset)

To adjust this for other values and bit sizes, ensure that:
  - s and v have the same amount of items
  - the sum of all numbers in s is less than or equal to 16
  - the values in v are within the boundaries of the
    respective bit count specified in s


Version History

PROGRAM                                          TKN    BYTE

    v1.1.1                                       161     418
        Optimized inttobin function.

    v1.1.0                                       171     435
        inttobin and bintoint can now read from and write
        to decimal.

    v1.0.0                                       136     377
        Initial release.

*Token and byte values based on the functions alone;
 they do not factor in the included function test.


        Modified examples for applying code in context with
        Pico-8 persistent data to work with PRGM v1.1.1.

        Changed version number system.

        Added explanation of additional test functions,
        as well as new decimal option for inttobin and

        Removed mention of empty table generation in the
        function summary.

        Added bintoint readouts on binread and binins.

        Initial manual.

A brief on this function set:

  • inttobin(value, decimal) where you throw in any acceptable number from Pico-8, as well as an indicator to pull from either the whole number space or the decimal space, and it'll give you a binary table based on that number.
  • binread(table, start, range) where you throw in a binary table generated by inttobin, specify where to start extracting bits, as well as how many bits to extract, and it'll give you a new binary table of just what you selected.
  • binins(table, 2nd table, start) where you throw in two tables: a destination table and the binary table you want to insert, as well as where to insert the binary table, and it'll give you a new binary table with the desired binary table inserted in. Perfect for cramming in multiple values into one!
  • bintoint(table, decimal) where you throw in a binary table, as well as an indicator to write to either the whole number space or the decimal space, and it'll give you an integer based on that table. Essentially the final destination when you want to save (second-to-final if you want to use both the whole number space and the decimal space).

If there are any questions, suggestions, or bugs that I should be aware of, let me know :o
Also let me know if you use any of these functions in your own save data in your game!

Cart #28892 | 2016-09-20 | Code ▽ | Embed ▽ | No License

Cart #28536 | 2016-09-15 | Code ▽ | Embed ▽ | No License

P#28537 2016-09-15 01:51 ( Edited 2016-09-27 20:26)

What's the license on this? :P I assume we can use it, but..can we?

P#28855 2016-09-20 03:21 ( Edited 2016-09-20 07:21)

Oh, whoops
Forgot to check the CC license :o

Also yeah, anyone's free to use these functions in their game! I'll also be developing this further since there's a lot more that could be done with it. My next goal is to tap in to the decimal space so I can expand the functionality to use all 2,048 bits (256 bytes) of Pico-8's persistent data.

P#28874 2016-09-20 12:19 ( Edited 2016-09-20 16:19)

I had been wondering why you had said only 1,024 switches were possible. xD (That is until I started poking around and realized you weren't using that section.)

Would it be possible for me to be able to use it under a license allowing sale of games at pay-what-you-want with a minimum price of $0? The CC licensing on this site is for non-commercial use, but I have an idea and I would like to put it up on Itch.io and allow purchases.

P#28884 2016-09-20 15:23 ( Edited 2016-09-20 19:23)

That would be fine by me. I probably might opt for CC BY-SA so if anyone really wants to use these functions and sell their work, they'll be free to do so.

P#28890 2016-09-20 16:17 ( Edited 2016-09-20 20:17)

Version 1.1 is now available for use.

New to this version is the ability to read from and write to the decimal space.

The next version will focus on expanding that functionality so you can read from and write to both the whole number space and the decimal space. As of right now, you can only read from and write to one or the other, not both.

P#28895 2016-09-20 17:01 ( Edited 2016-09-20 21:01)

Umm ... ???

Isn't there already an ability in PICO to save more than 256-bytes of persistent data via CSTORE ?

P#28904 2016-09-20 18:03 ( Edited 2016-09-20 22:03)

Technically you could, but if you want to update your Pico-8 application, the save data you have for one version will be lost in the next version since you're writing directly to the cart itself (unless you do cart swapping and save to another cart instead).

I meant to make these functions around the use of persistent data so developers can get more out of the persistent data's 64 value limit; it's a given that these functions can only go so far if a developer legitimately needs more than 2,048 bits/256 bytes for their own save functionality.

P#28917 2016-09-20 21:26 ( Edited 2016-09-21 01:26)

Since a notepad program I'm working on will definitely need more than 256-bytes of data for storage of text, I will certainly be experimenting with CSTORE.

Perhaps there is an easy method of persistent data despite being a different program altogether. I'll look into it.

Curiously I wrote a comprehensive bit-to-byte program that saved values for small data on the Gameboy as it only had 16k SRAM.

I labeled the elements Coin, 4D, 8D, 16D, 32D, 64D, 128D, BYTE, WORD, and LONG.

Coin being HEADS or TAILS (boolean, 1-bit).
4D value 0-3, 2-bits
8D value 0-7, 3-bits
16D value 0-15, 4-bits
32D value 0-31, 5-bits
64D value 0-63, 6-bits
128D value 0-127, 7-bits
BYTE value 0-255, 8-bits
WORD 2-bytes, 16-bits
LONG 4-bytes, 32-bits

It would retrieve or set these values by reading and writing individual bits.

Nice to see someone writing similar code for PICO.

Your CC4-BY-SA contract I believe is the standard agreement for all uploaded carts, so I wouldn't worry about it. :)

P#28918 2016-09-20 21:53 ( Edited 2016-09-27 20:26)

My notepad program is complete (well, almost). But you can see it uses quite a bit more than just 256-bytes, a nice 8192 total and it doesn't touch your image tiles, mapper, audio, or music. You can find that fully working cart w source HERE:


P#29516 2016-09-27 16:26 ( Edited 2016-09-27 20:26)

[Please log in to post a comment]