Quick note: I didn't figure out most of the format of SB files. Trinitro21 did most of the work figuring out the file structure, and the footer was thanks to code plutooo had for smilehax. I just wrote this document, which sums everything we know.
DISCLAIMER: This is not 100% correct and may change at any time.
By the way, me and Trinitro21 (triangle) wrote an API to download programs from the SmileBASIC servers. It can also display GRPs as PNGs. It's available at http://sbapi.me/
SmileBASIC has its own format for storing its files. There are 2 main types of files, TXT and DAT. Both have a common header and a footer, but DAT files have a secondary header after the common header to store metadata like how many dimensions it has, how large each dimension is, and what type of data it stores.
All files are stored in SmileBASIC's ExtData archive stored on the SD card. The default folder is stored as ### in the ExtData, and filenames are prefixed with T or B, for Text (TXT) and Binary (DAT), respectively.
The shared part of every SB file is the common header. This contains information such as the username of who wrote it, how large the data stored is, and when it was last modified. The common header is 80 bytes long, but 16 bytes at the end are always zero, so it's assumed it's reserved. All values are little-endian.
Offset | Size (bytes) | Description
&H00 | 2 | Always &H0100, the magic number
&H02 | 1 | File type (00 = TXT, 01 = DAT)
&H04 | 1 | Zlib compression (0 = no, 1 = yes)
&H06 | 1 | Icon shown in the project browser. For TXT files, 00 = TXT and 01 = PRG. For DAT, 00 = DAT and 02 = GRP
&H08 | 4 | 32-bit value storing the size of the file, not including the common header or the footer
&H0C | 2 | 16-bit value storing the year the file was last modified
&H0E | 1 | 8-bit value storing the month the file was last modified
&H0F | 1 | 8-bit value storing the day of the month the file was last modified
&H10 | 1 | 8-bit value storing the hour the file was last modified
&H11 | 1 | 8-bit value storing the minute the file was last modified
&H12 | 1 | 8-bit value storing the second the file was last modified
&H13 | 1 | Unknown, might be part of datetime
&H14 | 18 | The first author's (the original uploader) NNID. This one isn't shown in the project browser
&H26 | 18 | The second author's (the last editor) NNID. This one is displayed in the project browser
&H38 | 4 | The first author's user ID. Used for controlling the blacklist editable in the project download area
&H3C | 4 | The second author's user ID
DAT Secondary Header
TXT and PRG files just put the text after the footer. The DAT and GRP files need more information, which is why they have a secondary header. This secondary header stores information for SB to parse the file properly.
Offset | Size (bytes) | Description
&H50 | 8 | Always "PCBN0001", magic number for the DAT header
&H58 | 1 | Data type (03 = 16 bit unsigned (colors as RGBA5551, used for GRPs), 04 = Signed 32 bit integers (int%), 05 = 64-bit double (real#))
&H5A | 1 | Number of dimensions (1-4)
&H5C | 4 | 32-bit value storing the size of the first dimension
&H60 | 4 | 32-bit value storing the size of the second dimension if applicable
&H64 | 4 | 32-bit value storing the size of the third dimension if applicable
&H68 | 4 | 32-bit value storing the size of the fourth dimension if applicable
Afterwords, the data is stored in row-major order (https://en.wikipedia.org/wiki/Row-_and_column-major_order).
The footer is a 20 byte HMAC-SHA1 hash of the header and data using this HMAC key:
The footer must be valid in order to download or upload a program/project, not having a valid footer will cause an error when doing either of these.