Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- log2 is used to reverse 2^x this is basic math I wont explain this
- --]]
- local function log2(colour)
- return math.log(colour) / math.log(2)
- end
- --[[
- iterates through a 2D table, finding the longest row
- this is so we can calculate the full width and height of a 2D table, incase some rows have more columns than others
- --]]
- local function findLongest( t )
- local l = #t[1]
- for _,v in pairs( t ) do
- l = math.max( l, #v )
- end
- return l
- end
- --[[
- Creates a single byte from a colour and a true/false value
- a byte is 8 bits, we can store a colour in 4 bytes (a nibble) and a boolean in 1 bit
- this means that we have 3 spare bits in the nibble we're using to store the state,
- you could use this for other states if you wish
- --]]
- local function buildByte( color, state )
- --# turn the boolean into a number and then shift it 4 places to the left so its a high nibble
- --# so we have 00000001 to begin, but after shifting we have 00010000
- local high = bit.blshift(state == true and 1 or 0, 4)
- --# turn the colour into a number 0-15
- local low = log2( color )
- --# combine the low and high bits together into a byte
- return bit.bor( high, low )
- end
- --[[
- unpacks a single byte back into a colour and a true/false value
- --]]
- local function unpackByte( byte )
- --# shift the boolean value back into a range, so lets assume we have a byte that is colors.red and true
- --# the binary would be 00011110 performing this shift would make it 00000001 which is obviously what we
- --# want 'cause that's how we saved our boolean
- local high = bit.brshift( byte, 4)
- --# read the colour, assuming the same example with 00011110 applying a bitwise AND of 00001111 to it would
- --# result in 00001110 which is colors.red
- local low = bit.band( byte, 0xF )
- --# return the table in the form it was, converting the high bit back to a boolean by checking it its 00000001
- return { c = 2^low, s = high == 1 }
- end
- --[[
- Save the map to a file
- --]]
- function save(filename, map)
- --# open the file in binary writing mode
- local file = fs.open(filename, "wb")
- file.write(#map) --# height
- file.write(findLongest(map)) --# width
- --# iterate over the 2D table
- for _,row in pairs(map) do
- for _,col in pairs(row) do
- --# write out the byte
- file.write(buildByte(col.c, col.s))
- end
- --# make note that we dont make a newline here, newlines are useless in binary mode
- --# we will have to deal with this in `load`
- end
- --# done
- file.close()
- end
- --[[
- Load the map to a file
- --]]
- function load(filename)
- --# the map
- local map = {}
- --# open the file in binary read mode
- local file = fs.open(filename, "rb")
- --# read the width and height
- local height = file.read()
- local width = file.read()
- --# tracking information, `bc` is the number of bytes we've read
- local row, col, bc = 0,0,0
- --# read the file, 1 byte at a time
- for byte in file.read do
- --# calculate which row and column it belongs in
- row, col = (bc % height) + 1, (bc % width) + 1
- --# if there is no table for this row, make it
- map[row] = map[row] or {}
- --# unpack the byte into the row/column
- map[row][col] = unpackByte(byte)
- --# increment, we've read the byte
- bc = bc + 1
- end
- --# return the map and close the file, file.close returns nil, so you wont get a value from this
- return map, file.close()
- end
Advertisement
Add Comment
Please, Sign In to add comment