BBufStuff plugin for Take Command / TCC / TCC/LE
beta version 0.70.2 2026-05-08
Charles Dye
Purpose:
This plugin adds new functions to help work with binary buffers.
@BPEEKX and @BPOKEX
are like @BPEEK and @BPOKE, but with support for
unusual word sizes and big-endian data.
@BSAVE and @BLOAD
provide a quick way to save and restore binary buffers to and from files.
@BMEMCPY and @BMEMCMP
let you easily copy and compare series of bytes, without having to write
batch-file loops. @BFILL and
@BRANDFILL let you fill binary buffers,
or part of a binary buffer, with repeated values or with random bytes, again
without batch loops. @BFIND searches for
a series of numeric values in a binary buffer; @BFINDSTR
searches for a string of characters.
The BBDUMP command gives you an easy
but flexible way to display binary buffers to standard output as
hexadecimal. BBLIST lists currently
allocated binary buffers.
Installation:
To use this plugin, copy BBufStuff.dll and
BBufStuff.chm to some known location on your hard
drive. (If you are still using the 32-bit version of Take Command, take
BBufStuff-x86.dll instead of
BBufStuff.dll.) Load the .DLL file with a
PLUGIN /L command, for example:
plugin /l c:\bin\tcmd\test\bbufstuff.dll
If you copy these files to a subdirectory named PlugIns within your Take Command program directory, the plugin will be loaded automatically when TCC starts.
Plugin Features:
Syntax Note:
The syntax definitions in the following text use these conventions for clarity:
BOLD CODE | indicates text which must be typed exactly as shown. |
CODE | indicates optional text, which may be typed as shown or omitted. |
| Bold italic | names a required argument; a value must be supplied. |
| Regular italic | names an optional argument. |
| ellipsis… | after an argument means that more than one may be given. |
Examples are shown in a gray box:
rem This is an example:
set bbuf=%@balloc[256]
set rv=%@brandfill[%bbuf]
bbdump /h %bbuf
Some options take an argument. These are shown with a colon between the option and its
argument: /A:arg
If you like, you may substitute an equals sign for the colon: /A=arg
This is handy if the arg is a filename, and you want to use tab completion to
enter the filename.
Or you can omit the colon: /Aarg
New Commands:
BBDUMP — Dump a binary buffer to
standard output as hex.
Syntax:
BBDUMP /B /BE /C: /CP: /D /E: /F: /H /I /J /K: /LE /M: /ML: /N: /P /Q /UC /W /X /Z: handle…
/B or /1 | dump bytes | ✔ |
/BE | big-endian | |
/C:start | start address | |
/CP:n | code page to use for non-Unicode text | |
/CR | use CR line ends | |
/CRLF | use CR/LF line ends | ✔ |
/D or /4 | dump doublewords (four-byte integers) | |
/E:end | end address | |
/F:n | numeric base for values | 16 |
/H | display headers | |
/I | include a final summary line | |
/J | highlight alternate lines | |
/K:n | bytes per line | |
/LE | little-endian | ✔ |
/LF | use LF line ends | |
/M:max | maximum number of bytes to display | |
/ML:lines | maximum number of lines to dump | |
/N:flags | disable features | |
/P | page output | |
/Q or /8 | dump quadwords (eight-byte integers) | |
/UC | uppercase hexadecimal addresses and values | |
/W or /2 | dump words (two-byte integers) | |
/X | use control pictures for ASCII control characters | |
/Z:char | set the replacement character | 0xB7 |
| handle | a handle returned by @BALLOC or @BLOAD |
/F:n
lets you specify the numeric base for displaying values. Legal values are:
/F:O or /F:8 | octal |
/F:D or /F:10 | decimal |
/F:S or /F:+ | signed decimal |
/F:H or /F:16 | hexadecimal (the default) |
Addresses are always shown in hexadecimal.
8 | do not show dashes between bytes of UTF-8 characters |
C | no highlight |
I | do not display the address field |
L | omit the blank line at the end |
T | do not display the text field (i.e. characters) |
U | do not display non-ASCII characters in the text field |
/C:start,
/E:end, and
/M:max let you specify a start
address, an end address, and a maximum number of bytes to dump. You can
enter these values as decimal, or hexadecimal with a leading 0x.
You may give none, one, or any combination of these options.
/C:, /E:, and /M: values are
all in bytes by default. You can append one of the following letters:
b | bytes |
w | words |
d | doublewords |
q | quadwords |
k | thousands of bytes |
K | kilobytes (210 or 1,024 bytes) |
m | millions of bytes |
M | megabytes (220 or 1,048,576 bytes) |
g | billions of bytes |
G | gigabytes (230 or 1,073,741,824 bytes) |
Note that k K m M g and G are case-sensitive.
If you don’t give any of these suffixes, the value is in bytes — even if you are displaying words or doublewords. There are no alignment checks; you can dump misaligned data if you wish.
/C: and /E: allow you to pass a negative number to
specify the address as an offset from the end of the buffer, e.g. /C:-1K
to dump only the last kilobyte of the buffer. /M: does not allow
negative numbers.
/K:n
lets you specify the number of bytes to display per line. If you don’t
give any /K:, the command will pick its own value based on the
console width (if output is to the console), or a default line width of
100 characters if output is redirected. Again, this value is in bytes,
even if you are displaying data as words or doublewords. The value
n must be between 8 and 80, and a multiple of 8.
/K:0 sets the line length based on the console width, even
in cases where BBDUMP normally would not do so: when output
is redirected or piped, e.g. piping to LIST.
/ML:lines
lets you set a maximum number of data lines to dump. Any header or summary lines
are not counted.
/CP:n
specifies the code page to use for non-Unicode text. If you do not specify any
/CP:n, the default behavior is to show
only ASCII characters. (Binary buffers, after all, are often used for things
other than text….)
/Z:char
lets you specify the replacement character, which is shown in the text
field in place of control characters. The default is normally a middle dot
· You may give either a literal character or a character value. All
three of the following are equivalent:
• /Z:* | (literal character) |
• /Z:42 | (decimal value) |
• /Z:0x2a | (hexadecimal value) |
Your replacement character may not be alphanumeric or a control
character. /Z by itself will use a space as the replacement
character.
rem Load and dump a file:
set bbuf=%@bload[build.txt]
bbdump /hh /i /x %bbuf
set rv=%@bfree[%bbuf] & unset bbuf
BBLIST — List currently
allocated binary buffers.
Syntax:
BBLIST /B /O:keys /P
/B | bare bones (handles only) | |
/O:keys | sort buffers | |
/P | page output |
While this plugin is loaded, it will track binary buffers being allocated and
freed. BBLIST will display the current list of binary buffers known
to the plugin. Binary buffers that are allocated or freed while this plugin is
not loaded are not tracked and will not be listed.
/O: can sort by several criteria.
The available sort keys are:
A | sort by the buffer’s address (handle) |
-A | reverse sort by buffer address |
S | sort by buffer size |
-S | reverse sort by buffer size |
T | sort by creation time |
-T | reverse sort by creation time |
These can be combined, e.g. /O:ST to sort by size first,
then by creation time. If you type /O by itself, BBLIST
will sort by size first, then by creation time.
New Functions:
@BALLOC — Allocates a new binary
buffer.
Syntax:
%@BALLOC[size,comment]
| size | the size of the new buffer; required |
| comment | an optional description |
@BALLOC returns a handle to the new buffer, which you will use
in subsequent buffer operations.
This plugin replaces TCC’s internal @BALLOC function to
add three new features:
• The handle it returns will be remembered
for later use. You can use BBLIST to list
all currently allocated binary buffers, and @BFREEALL
to free them all at once.
• The size may optionally be followed by a letter to indicate scale. Note that case is significant:
k | thousands of bytes |
K | kilobytes (1,024 bytes) |
m | millions of bytes |
M | megabytes (1,048,576 bytes) |
g | billions of bytes |
G | gigabytes (1,073,741,824 bytes) |
• You can supply a comment
to associate with the new buffer. BBLIST
displays these comments, and @BBINFO[handle,7]
returns them.
rem Allocate a 5-kilobyte buffer:
set bbuf=%@balloc[5K]
@BBHANDLE — Returns handles of
known binary buffers.
Syntax:
%@BBHANDLE[n]
| n | which handle to return |
This function can be used to iterate through binary buffers known to this
plugin. Only buffers created by @BALLOC and
@BLOAD in this plugin, in the current
shell, will be returned. Buffers created by TCC’s internal @BALLOC
function will not be returned.
n is a zero-based index. If it’s negative
or not given, @BBHANDLE returns the current count of known binary
buffers. If it’s greater than or equal to the current count,
@BBHANDLE returns an empty string. Otherwise, @BBHANDLE
returns the nth handle in the list, as
provided by @BALLOC or @BLOAD.
for /l %i in ( 0, 1, %@dec[%@bbhandle[]] ) echo %i - %@bbhandle[%i]
@BBINFO — Returns information about
a binary buffer.
Syntax:
%@BBINFO[handle,n]
| handle | a handle returned by @BALLOC or @BLOAD |
| n | which info to return: |
0: the buffer size in bytes | |
1: the buffer’s address (decimal) | |
2: the buffer’s address (hex) | |
3: the time the buffer was created (local) | |
4: the time the buffer was created (UTC) | |
5: the time the buffer was created (Unix) | |
7: buffer comment (empty string if none) |
If @BBINFO cannot retrieve the requested information, it will return
a single dash -.
@BFILL — Fills a binary buffer
with a repeating value.
Syntax:
%@BFILL[handle,size,value,offset,count,flags]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer; defaults to 0 |
| size | the size of the value to store: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer; defaults to 1 |
| value | the value to store |
| count | the maximum number of times to store the value; defaults to filling the entire buffer |
| flags | bitmapped: |
1: big-endian |
The handle is required; all other parameters are
optional. If you do not supply any of the other options, @BFILL will
fill the entire buffer with zeros.
If the value begins with either a + or
- sign, it will be treated as a signed decimal integer. If
it begins with anything else, it’s unsigned. Either way, the
value must fall within the range
specified by the size parameter.
@BFIND — Searches for a series of
values in a binary buffer.
Syntax:
%@BFIND[handle,offset,value1 value2 value3…]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer; defaults to 0 |
value1 value2 value3… | may be decimal or hexadecimal with a leading 0x |
Values may be separated with spaces, commas, or semicolons. You must give at least one value to search for. In addition to values, you can also include:
(B) or (1) | the following values are bytes (the default) |
(W) or (2) | the following values are words |
(D) or (4) | the following values are doublewords |
(Q) or (8) | the following values are quadwords |
@BFIND returns the offset of the first match starting from
offset, or -1 if no match is found.
See also: @BFINDSTR,
which searches for a string of characters.
@BFINDSTR — Searches for a
string in a binary buffer.
Syntax:
%@BFIND[handle,offset,encoding,string]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer; defaults to 0 |
| encoding | ANSI or A, OEM or O, UTF8, UTF16, or CPnnn; defaults to ANSI |
| string | the text to search for |
This is a byte-for-byte search. The string in the binary buffer must match the search string exactly — case, spacing, punctuation, everything.
@BFINDSTR returns the offset of the first match starting from
offset, or -1 if no match is found.
See also: @BFIND, which
searches for a series of numeric values.
@BFREE — Releases a binary
buffer.
Syntax:
%@BFREE[handle]
| handle | a handle returned by @BALLOC or @BLOAD |
@BFREE behaves the same as TCC’s internal @BFREE
function, but it also tracks freed buffer handles. If you try to @BFREE
a buffer which has already been @BFREEd, you will get a “Bad
buffer handle” error message. (Re-freeing memory which has already been
freed is a good way to cause a crash.)
@BFREE returns the size (in bytes) of the freed buffer.
rem Free the buffer named in BBUF:
set rv=%@bfree[%bbuf,1]
See also: @BALLOC,
@BLOAD, and @BFREEALL.
@BFREEALL — Releases all binary
buffers.
Syntax:
%@BFREEALL[]
@BFREEALL does not take any arguments. It returns the number
of buffers freed.
@BFREEALL only knows about binary buffers created by
@BALLOC and @BLOAD
in this plugin. Binary buffers that were allocated while this plugin was
not loaded (e.g. by TCC’s internal @BALLOC function)
are not tracked and will not be freed.
@BLOAD — Loads data from a file
into a binary buffer.
Syntax:
%@BLOAD[filename]
| filename | the file to load into a binary buffer |
This function allocates a new binary buffer of the same size as the file,
loads the named file into it, and returns the handle of the new buffer.
The number of bytes loaded — i.e. the file size —
is available through _BLOADSIZE.
If any error occurs while allocating the buffer or reading the file,
@BLOAD returns 0; the Windows error code is in
_BBLASTERR.
The maximum file size that @BLOAD will load is eight megabytes
in x86 TCC, or one gigabyte in x64 TCC.
When you are finished with the buffer, free it with with
@BFREE.
(You could of course do the same thing with @FILESIZE,
@BALLOC, @FILEOPEN, @BREAD, and
@FILECLOSE. This function just spares you the tedium.)
rem Load a file into a buffer and display it:
set bbuf=%@bload[build.txt]
bbdump %bbuf
set rv=%@bfree[%bbuf]
See also: @BSAVE.
@BMEMCMP — Compares two series of
bytes in binary buffers.
Syntax:
%@BMEMCMP[bbuf1,offset1,bbuf2,offset2,size]
| bbuf1 | the handle to the binary buffer with the first series of bytes; required |
| offset1 | the offset of the first series within bbuf1; defaults to 0 |
| bbuf2 | the handle to the binary buffer with the second series of bytes; defaults to bbuf1 |
| offset2 | the offset of the second series within bbuf2; defaults to 0 |
| size | the number of bytes to compare; defaults to all from offset1 to the end of buf1 |
@BMEMCMP compares two series of bytes. Both series may be in the
same buffer, or they can be in two different buffers.
@BMEMCMP returns 0 if the two blocks are identical,
or nonzero if they differ.
After parsing and validating its arguments, this function just calls memcmp().
@BMEMCPY — Copies a series of
bytes in binary buffers.
Syntax:
%@BMEMCPY[src_bbuf,src_offset,dest_bbuf,dest_offset,size]
| src_bbuf | the handle of the binary buffer to copy from |
| src_offset | the location within the source buffer to copy from |
| dest_bbuf | the handle of the binary buffer to copy to; defaults to src_bbuf |
| dest_offset | the location within the destination buffer to copy to |
| size | the number of bytes to copy |
@BMEMCPY copies a series of bytes. It can copy within a single
buffer, or from one buffer to another.
After parsing and validating its arguments, this function just calls memcpy().
@BMODVAL — Modifies a value in
a binary buffer.
Syntax:
%@BMODVAL[handle,offset,wordsize,operation,value,fmt,flags]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer |
| wordssize | the size of the value to return: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer |
| operation | one of: |
AND or &: logical-ANDs the value in the buffer with value | |
OR or |: logical-ORs the value in the buffer with value | |
XOR: logical-XORs the value in the buffer with value | |
ADD or +: adds value to the value in the buffer | |
SUBTRACT or -: subtracts value from the value in the buffer | |
SHL or <<: shifts the value in the buffer left value bits | |
SHR or >>: shifts the value in the buffer right value bits | |
| fmt | the format in which to return the value |
| flags | bitmapped: |
1: big-endian |
@BMODVAL reads a value from a binary buffer, performs the requested
operation on it, writes the new value back to the binary buffer, and returns the
new value in the specified format.
If the value begins with either a +
or - sign, the value is treated as a
signed value; otherwise it’s unsigned. Either way, the value
must fall within the range specified by the
wordsize parameter.
The optional fmt parameter specifies the format for the returned value. If you
are ignoring @BMODVAL’s return value, then its format doesn’t matter.
0 | unsigned decimal (the default) |
1 | signed decimal |
2 | hexadecimal with a leading 0x |
3 | hexadecimal without any prefix |
4 | octal |
Operation-specific notes:
ADDandSUBTRACTdo not check for overflow/underflow. If the resulting value does not fit in the specified wordsize,@BMODVAL’s behavior is undefined.- For
SHLandSHR, value is the number of bits to shift. It must not be greater than 8 * wordsize, or you’ll get an error message.
@BPEEKX — Like @BPEEK, but supports
oddball word sizes and big-endian data.
Syntax:
@BPEEKX[handle,offset,wordsize,fmt,flags]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer |
| wordssize | the size of the value to return: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer |
| fmt | the format in which to return the value |
| flags | bitmapped: |
1: big-endian |
The optional fmt parameter specifies the format for the returned value:
0 | unsigned decimal (the default) |
1 | signed decimal |
2 | hexadecimal with a leading 0x |
3 | hexadecimal without any prefix |
4 | octal |
See also: @BPOKEX.
@BPOKEX — Like @BPOKE, but supports
oddball word sizes and big-endian data.
Syntax:
@BPOKEX[handle,offset,wordsize,value,flags]
| handle | a handle returned by @BALLOC or @BLOAD |
| offset | the starting offset, in bytes, from the start of the buffer |
| wordsize | the size of the value to store: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer |
| value | the value to store |
| flags | bitmapped: |
1: big-endian |
If the value begins with either a +
or - sign, the value is treated as a
signed value; otherwise it’s unsigned. Either way, the value
must fall within the range specified by the
wordsize parameter.
Returns 0 for success.
See also: @BPEEKX.
@BRANDFILL — Fills a binary buffer
with random bytes.
Syntax:
%@BRANDFILL[handle,offset,count]
| handle | a binary buffer handle returned by @BALLOC or @BLOAD |
| offset | the byte offset within the buffer to start filling; defaults to 0 |
| count | the maximum number of bytes to write; defaults to the end of the buffer |
@BSAVE — Saves data from a binary
buffer to a file.
Syntax:
%@BSAVE[handle,filename,start,len]
| handle | a binary buffer handle returned by @BALLOC or @BLOAD |
| filename | the file to save to; will be overwritten if it exists |
| start | the starting address within the buffer; defaults to 0 |
| len | the maximum number of bytes to save; defaults to all through the end of the buffer |
@BSAVE returns the number of bytes written to the file. If
any error occurs while saving the file, @BSAVE returns 0;
the Windows error code is in _BBLASTERR.
See also: @BLOAD.
@BSIZE — Returns the size of a
binary buffer.
Syntax:
%@BSIZE[handle]
| handle | a binary buffer handle returned by @BALLOC or @BLOAD |
Returns the size of a binary buffer in bytes. If the handle
is not valid, or if it was freed by @BFREE,
this function returns -1.
@BSIZE behaves the same as TCC’s internal @BSIZE
function, but includes a check for @BFREEd buffers.
New Variables:
_BBLASTERR — Returns the last
error code from @BLOAD or @BSAVE.
Syntax:
%_BBLASTERR
If the function call was successful, _BBLASTERR returns 0.
If it failed, this variable returns a Windows error code;
pass this value to @ERRTEXT or LOOKUPERRORS for
more information.
In addition to the standard Windows error codes, this variable might also return:
| 490 | BBUF_ERROR_UNKNOWN | A Windows function failed, but I don’t know why. |
| 491 | BBUF_ERROR_FILE_TOO_BIG | The maximum file size is 8 MB (x86) or 1GB (x64). |
| 492 | BBUF_ERROR_FILE_IS_EMPTY | The file does not contain any data. |
| 493 | BBUF_ERROR_UNEXPECTED_EOF | @BLOAD was not able to read the entire file. |
_BLOADSIZE — Returns the number
of bytes loaded by @BLOAD.
Syntax:
%_BLOADSIZE
See also: @BLOAD.
Reference Information:
| Word Size Ranges | Including the odd word sizes. |
| Paging Options | Supported in several commands. |
| The Highlight Variable | Choose your colors. |
| Startup Message | And how to suppress it. |
| Changes | Slow march of progress, or just another bug hunt? |
| Status and Licensing |
Word Size Ranges:
@BFILL, @BFIND,
@BMODVAL, and @BPOKEX
permit some odd word sizes for their values. Here are the ranges for different word sizes,
in a variety of different formats.
| Bytes | Bits | Unsigned Decimal | Signed Decimal | Hexadecimal | Octal |
|---|---|---|---|---|---|
| 1 | 8 | 255 | -128 … 127 | 0xFF | 0o377 |
| 2 | 16 | 65535 | -32768 … 32767 | 0xFFFF | 0o177777 |
| 3 | 24 | 16777215 | -8388608 … 8388607 | 0xFFFFFF | 0o77777777 |
| 4 | 32 | 4294967295 | -2147483648 … 2147483647 | 0xFFFFFFFF | 0o37777777777 |
| 5 | 40 | 1099511627775 | -549755813888 … 549755813887 | 0xFFFFFFFFFF | 0o17777777777777 |
| 6 | 48 | 281474976710655 | -140737488355328 … 140737488355327 | 0xFFFFFFFFFFFF | 0o7777777777777777 |
| 7 | 56 | 72057594037927935 | -36028797018963968 … 36028797018963967 | 0xFFFFFFFFFFFFFF | 0o3777777777777777777 |
| 8 | 64 | 18446744073709551615 | -9223372036854775808 … 9223372036854775807 | 0xFFFFFFFFFFFFFFFF | 0o1777777777777777777777 |
(The table above is very wide. You may have to enlarge your browser window, or reduce the font size, to see the whole thing. Sorry ’bout that.)
Paging Options:
BBDUMP and BBLIST
both have a /P option to page output. This option supports two suboptions:
/P:time,lines
| time | time in seconds, or (with a trailing M) milliseconds |
| lines | number of lines to display before pausing |
Both time and lines are optional. The colon is not required, but you must use the comma if you want to specify lines.
rem Scroll every five seconds:
bbdump %bbuf /p:5
rem Display ten lines at a time:
bbdump %bbuf /p:,10
rem Display twenty lines at a time, and
rem scroll every 2.5 seconds:
bbdump %bbuf /p:2500m,20
At the “Press a key to continue” prompt, most keys will advance by another screenful (or lines). But a few keys behave differently:
| A or C | turns off paging, and scrolls continuously |
| Esc or Ctrl-C | aborts the current command |
| / | scrolls half a screen, or half of lines |
| 1 to 9 | scrolls that many lines, e.g. 3 scrolls three lines |
Highlight Variable:
BBDUMP features highlighted output
when use use /H, /I, or /J. You can
customize this feature by setting an environment variable Highlight:
rem Disable highlight:
set highlight=none
rem Set the highlight foreground:
set highlight=bright cyan
rem Set both foreground and background:
set highlight=bri whi on blu
rem Numbers are also supported:
set highlight=46
If the Highlight environment variable is not defined, the plugin will
check the registry for a value named Highlight of type REG_SZ.
The plugin will search, in this order:
| • HKEY_CURRENT_USER\Software\JPPlugins\BBufStuff | (affects this plugin only) |
| • HKEY_CURRENT_USER\Software\JPPlugins | (affects several of my plugins) |
You can also use /NC to disable highlighting.
Startup Message:
This plugin displays an informational line when it initializes. The
message will be suppressed in transient or pipe shells. You can disable it
for all shells by defining an environment variable named NOLOADMSG,
for example:
set /e /u noloadmsg=1
Changes:
| Version: | Date: | Changes: |
|---|---|---|
| 0.70.2 | 2026-05-08 | Added @BSIZE
(the same as TCC’s, but with a check for @BFREEd buffers.) |
| 0.70.1 | 2026-05-08 | Added a hack to prevent re-freeing
binary buffers which have already been freed. Removed the flags
argument to @BFREE. |
| 0.70.0 | 2026-05-07 | Added @BBHANDLE. |
| 0.69.0 | 2026-05-06 | Added support for binary buffer comments. Many other changes and optimizations. |
| 0.68.0 | 2026-05-06 | Added @BFIND and
@BFINDSTR. |
| 0.67.0 | 2026-05-04 | Added @BBINFO. BBDUMP, BBLIST: Handles
are formatted for display by BBufHandleToString(). |
| 0.66.8 | 2026-04-24 | Supports binary numbers
prefixed with 0B. Added this Changes page, and reorganized the .CHM help file to put all the miscellaneous help topics under Reference Info. |
Status and Licensing:
Consider this beta software. It may well have issues. Try it at your own risk. If you find a problem, you can report it in the JP Software support forum.
BBufStuff is currently licensed only for testing purposes. I may make binaries and source code available under some free license once I consider it ready for use.
Download:
You can download the current version of this plugin from https://charlesdye.net/dl/bbufstuff.zip.