## Chronos

4
Posts
1
Topics
9
Following
A member registered May 05, 2015 · View creator page →

### Recent community posts

In Lua it's pretty simple -- just the 'not' keyword.

```if not btn(n) then
--True if btn n is NOT pressed
end```

So it's taken some time, but after using the brick-wall method (banging my head against it until it works) I've finally managed to get a working save-safe (mostly) efficient storage metod that can store up to 10 characters. 11 or more characters will cause an overflow, so I've taken the liberty of putting a sanity check in for that.

I wanted to stick to my original rules (1-53, 1 is capital 'A', 27 is lowercase 'a' and 53 is space), meaning I needed 6 bits per character; after doing a little tinkering with binary (specifically trying to come up with a way to handle bitflags for saves) I came up with a method that seems to be working, but has some overhead (2-4 bits) caused by  endianness that I'm not sure how to fix.

Anyway, here's the code (Size: 710)

```nums={3,34,44,41,40,41,45,48,9,9}
local fmt=string.format
--Size counting starts on next line
function combine(tab)
local out=0
if #tab > 10 then trace"Error: Input table too big."end
for i=1,#tab do
if tab[i] then
if tab[i]>53 then tab[i]=53 end
out=out+tab[i]
out=out<<6
end
end
return out
end
function bytify(num)
local out={}
local i=1
while num>0 do
out[i]=num & 0xFF
num=(num >> 8) // 1
i=i+1
end
return out
end
function rebuild(tab)
local out=0
for i=#tab,1,-1 do
if tab[i] then
out = (out << 8)
out = out + (tab[i]&0xFF)
end
end
return out
end
function retable(num)
local out={}
local i=0
while num>0 do
if num>0 then
out[i]=num&0x3F
num=(num>>6)//1
end
i=i+1
end
local n={}
for i=1,#out do
n[#out-(i-1)]=out[i]
end
return n
end
--Size counting stops at end of previous line
--Debug Stuff but shows how to use the code
trace("Starting name:\n "..table.concat(nums,','))
val1 = combine(nums)
trace("Integer out:\n "..fmt("%0X",val1))
val2 = bytify(val1)
trace("Bytes out:\n "..table.concat(val2,","))
val3 = rebuild(val2)
trace("Integer confirm:\n "..fmt("%0X",val3))
val4 = retable(val3)
trace("Confirm:\n "..table.concat(val4,','))
```

And a little proof that it's working (as best as I can make it work with my current skills):

This works in tandem with some of my above code (specifically this:

```ltrs="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
function str2num(str)
local s={}
for i=1,#str do
s[i]=ltrs:find(str:sub(i,i))
end
return s
end
```

to convert the name string into a table. I haven't done the opposite conversion yet, but it wouldn't be that difficult, and you could even forgo the string step altogether if you operated strictly on a table and used a "name()" function or equivalent to convert the table into a string for use in your game.

That certainly would be ideal, but unfortunately I'm not currently familiar or comfortable enough with binary operations to make it so. Even in its original PICO-8 form it could be taken from 128 bits down to the same 40. I know it's a terrible waste of space as it is now but I never pretended I really knew what I was doing with TIC-80 (or PICO-8 for that matter). Maybe one day it'll be that efficient but even if it's a jumping-off point for someone more skilled then it's done its job.

(6 edits)

Hello! I've been doing the beginnings of tinkering around with TIC-80 after having used PICO-8 for about a month, and while I was looking through the documentation I realized I had run into quite a problem -- PICO-8 gives you 63 values to store user data to, and TIC-80 only gives you 7. This lead to an interesting problem, because one of the things I've been tinkering around with fantasy consoles for is a mini-RPG, complete with name entry.

In PICO-8 it was simple -- since you could only use capital letters I saved each letter as a number 1 to 26, then reconstructed the name with those values.

With TIC-80, I was scratching my head... until an idea hit me: You get 32-bit integers, which give you 2147483647 possible positive values (if the variables are signed, which I assume they are). And since TIC-80 supports lowercase letters, you can range 1 to 52, 53 if you allow for spaces. I decided to store the letters, grouped together, into integers. Since splitting 2147483647 into groups of 2 digits gives 21 47 48 36 47, I can't use the 21 (or 42 if unsigned) at the start. So I store 2 sets of 4 letters in integers ranging from 0 (nothing) to 53,535,353.

Here's the code to do this if you want to replicate the functionality -- you'll just need to implement these into save/load functions.

```ltrs="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "
local flr=math.floor
--Convert 2 32-bit integers into one 8-character string
function num2str(v1,v2)
local n={0,0,0,0,0,0,0,0}
local v2=v2 or 0
local o=""
for i=8,5,-1 do
n[i]=v2%100
v2 = flr(v2/100)
end
for i=4,1,-1 do
n[i]=v1%100
v1 = flr(v1/100)
end
for i=1,8 do
local l=n[i]
if l>0 then
o=o..ltrs:sub(l,l)
end
end
return o
end
--Take a string (str) up to 8 chars and turn it into 2 integers
function str2num(str)
if #str>8 then error"String too long for str2num." end
local s={}
for i=1,#str do
s[i]=ltrs:find(str:sub(i,i))
end
local o={}
local t=""
local j=1
for i=1,#s do
t=t..s[i]
if i==4 then o[j]=flr(t*1) j=j+1 t="" end
end
if #s>4 then o[j]=flr(t*1) end
o[2]=o[2] or 0
return o
end
```

I'm sure there's a more efficient way to do this, but I'm used to the PICO-8 syntax. Also apologies for the variable shortening but that was a concession for the 64kb limit -- even though it would be best to do that after I was finished, for some reason I got into that mindset immediately and that's how I wrote it..

Variable 'o' is always "output", table 'n' are the numbers once split to turn into a string, table 's' is the opposite -- the numbers converted from their positions in the 'ltrs' string.

Hopefully people find this useful!

Edit Log:

There was an error being generated when you passed a 4-character string to str2num.

```    o[j]=flr(t*1)
```

became

```    if #s>4 then o[j]=flr(t*1) end
```

The above line was intended to write the value of 't' to the first number if the length was 1, 2, 3 or 4 characters and write to the second number in any other case. Thanks to not writing the logic properly 't' was trying to be converted from an empty string to a number and caused an error. This edit fixes that problem.

I need this game in my life. Reminds me of a PlayStation 2 game I owned forever ago called HSX: HyperSonic Xtreme. It was a Majesco bargain bin game but it took F-Zero-like gameplay and added a fully featured track editor where you could do a lot of crazy stuff. This feels like that, only better with things like tubes and pipes.

You've got a new fan. Keep up the great work!