BBufStuff plugin for Take Command / TCC / TCC/LE
beta version 0.66.4 2025-06-13
Charles Dye
Purpose:
This plugin adds new functions to help work with binary buffers.
@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.
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:
| New Commands: | ||||
|---|---|---|---|---|
BBDUMP | BBLIST | |||
| New Functions: | ||||
@BALLOC | @BFILL | @BFREE | @BFREEALL | @BLOAD |
@BMEMCMP | @BMEMCPY | @MODVAL | @BPEEKX | @BPOKEX |
@BRANDFILL | @BSAVE | |||
| New Variables: | ||||
_BBLASTERR | _BLOADSIZE | |||
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 | |
/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 | ✔ |
/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) |
/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.
/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]
| size | the size of the new buffer; required |
@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 two 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) |
rem Allocate a 5-kilobyte buffer:
set bbuf=%@balloc[5K]
@BFILL — Fills a binary buffer
with a repeating value.
Syntax:
%@BFILL[handle,size,value,offset,count,flags]
| handle | a handle returned by @BALLOC |
| 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.
@BFREE — Releases a binary
buffer.
Syntax:
%@BFREE[handle,flags]
| handle | a handle returned by @BALLOC |
| flags | 1: do not verify handle against list |
This plugin replaces TCC’s internal @BFREE function to
add one new feature:
• If the handle is not found
in this plugin’s list of binary buffers, @BFREE will fail
with an error message. This safety feature prevents you from freeing anything
other than binary buffers, or from freeing buffers which have already been
freed. You can disable this check with the optional ,1 parameter;
e.g. to free a buffer which was allocated before this plugin was
loaded.
rem Free the buffer named in BBUF:
set rv=%@bfree[%bbuf,1]
@BFREEALL — Releases all binary
buffers.
Syntax:
%@BFREEALL[]
@BFREEALL does not take any arguments. It returns the number
of buffers 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.
(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 series 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 |
| 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 |
| 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 |
| 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[bbuf,offset,count]
| bbuf | a binary buffer handle returned by @BALLOC |
| 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[bbuf,filename,start,len]
| bbuf | a binary buffer handle returned by @BALLOC |
| 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.
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.
Word Size Ranges:
@BFILL, @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
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.