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:
BBDUMPBBLIST
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 CODEindicates text which must be typed exactly as shown.
CODEindicates optional text, which may be typed as shown or omitted.
Bold italicnames a required argument; a value must be supplied.
Regular italicnames 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  /1dump bytes
/BEbig-endian
/C:startstart address
/CP:ncode page to use for non-Unicode text
/D  or  /4dump doublewords (four-byte integers)
/E:endend address
/F:nnumeric base for values 16
/Hdisplay headers
/Iinclude a final summary line
/Jhighlight alternate lines
/K:nbytes per line
/LElittle-endian
/M:maxmaximum number of bytes to display
/ML:linesmaximum number of lines to dump
/N:flagsdisable features
/Ppage output
/Q  or  /8dump quadwords (eight-byte integers)
/UCuppercase hexadecimal addresses and values
/W  or  /2dump words (two-byte integers)
/Xuse control pictures for ASCII control characters
/Z:charset the replacement character0xB7
handlea handle returned by @BALLOC or @BLOAD

/F:n lets you specify the numeric base for displaying values. Legal values are:

/F:O  or  /F:8octal
/F:D  or  /F:10decimal
/F:S  or  /F:+signed decimal
/F:H  or  /F:16hexadecimal (the default)

Addresses are always shown in hexadecimal.


/N:flags disables features:

8do not show dashes between bytes of UTF-8 characters
Cno highlight
Ido not display the address field
Lomit the blank line at the end
Tdo 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:

bbytes
wwords
ddoublewords
qquadwords
kthousands of bytes
Kkilobytes (210 or 1,024 bytes)
mmillions of bytes
Mmegabytes (220 or 1,048,576 bytes)
gbillions of bytes
Ggigabytes (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

/Bbare bones (handles only)
/O:keyssort buffers
/Ppage 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:

Asort by the buffer’s address (handle)
-Areverse sort by buffer address
Ssort by buffer size
-Sreverse sort by buffer size
Tsort by creation time
-Treverse 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]

sizethe 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:

kthousands of bytes
Kkilobytes (1,024 bytes)
mmillions of bytes
Mmegabytes (1,048,576 bytes)
gbillions of bytes
Ggigabytes (1,073,741,824 bytes)

rem   Allocate a 5-kilobyte buffer:
set bbuf=%@balloc[5K]

See also: @BFREE, @BFREEALL.



@BFILL — Fills a binary buffer with a repeating value.

Syntax:
%@BFILL[handle,size,value,offset,count,flags]

handlea handle returned by @BALLOC
offsetthe starting offset, in bytes, from the start of the buffer; defaults to 0
sizethe size of the value to store: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer; defaults to 1
valuethe value to store
countthe maximum number of times to store the value; defaults to filling the entire buffer
flagsbitmapped:
      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]

handlea handle returned by @BALLOC
flags1: 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]

See also: @BALLOC, @BFREEALL.



@BFREEALL — Releases all binary buffers.

Syntax:
%@BFREEALL[]

@BFREEALL does not take any arguments. It returns the number of buffers freed.

See also: @BALLOC, @BFREE.



@BLOAD — Loads data from a file into a binary buffer.

Syntax:
%@BLOAD[filename]

filenamethe 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]

bbuf1the handle to the binary buffer with the first series of bytes; required
offset1the offset of the first series within bbuf1; defaults to 0
bbuf2the handle to the binary buffer with the second series of bytes; defaults to bbuf1
offset2the offset of the second series within bbuf2; defaults to 0
sizethe 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_bbufthe handle of the binary buffer to copy from
src_offsetthe location within the source buffer to copy from
dest_bbufthe handle of the binary buffer to copy to; defaults to src_bbuf
dest_offsetthe location within the destination buffer to copy to
sizethe 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]

handlea handle returned by @BALLOC
offsetthe starting offset, in bytes, from the start of the buffer
wordssizethe size of the value to return: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer
operationone 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
fmtthe format in which to return the value
flagsbitmapped:
     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.

0unsigned decimal (the default)
1signed decimal
2hexadecimal with a leading 0x
3hexadecimal without any prefix
4octal

Operation-specific notes:



@BPEEKX — Like @BPEEK, but supports oddball word sizes and big-endian data.

Syntax:
@BPEEKX[handle,offset,wordsize,fmt,flags]

handlea handle returned by @BALLOC
offsetthe starting offset, in bytes, from the start of the buffer
wordssizethe size of the value to return: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer
fmtthe format in which to return the value
flagsbitmapped:
     1: big-endian

The optional fmt parameter specifies the format for the returned value:

0unsigned decimal (the default)
1signed decimal
2hexadecimal with a leading 0x
3hexadecimal without any prefix
4octal

See also: @BPOKEX.



@BPOKEX — Like @BPOKE, but supports oddball word sizes and big-endian data.

Syntax:
@BPOKEX[handle,offset,wordsize,value,flags]

handlea handle returned by @BALLOC
offsetthe starting offset, in bytes, from the start of the buffer
wordsizethe size of the value to store: 1 a byte, 2 a word, 4 a doubleword, 8 a 64-bit integer
valuethe value to store
flagsbitmapped:
     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]

bbufa binary buffer handle returned by @BALLOC
offsetthe byte offset within the buffer to start filling; defaults to 0
countthe 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]

bbufa binary buffer handle returned by @BALLOC
filenamethe file to save to; will be overwritten if it exists
startthe starting address within the buffer; defaults to 0
lenthe 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:

490BBUF_ERROR_UNKNOWNA Windows function failed, but I don’t know why.
491BBUF_ERROR_FILE_TOO_BIGThe maximum file size is 8 MB (x86) or 1GB (x64).
492BBUF_ERROR_FILE_IS_EMPTYThe file does not contain any data.
493BBUF_ERROR_UNEXPECTED_EOF@BLOAD was not able to read the entire file.

See also: @BLOAD and @BSAVE.



_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.


BytesBitsUnsigned DecimalSigned DecimalHexadecimalOctal
18255-128 … 1270xFF0o377
21665535-32768 … 327670xFFFF0o177777
32416777215-8388608 … 83886070xFFFFFF0o77777777
4324294967295-2147483648 … 21474836470xFFFFFFFF0o37777777777
5401099511627775-549755813888 … 5497558138870xFFFFFFFFFF0o17777777777777
648281474976710655-140737488355328 … 1407374883553270xFFFFFFFFFFFF0o7777777777777777
75672057594037927935-36028797018963968 … 360287970189639670xFFFFFFFFFFFFFF0o3777777777777777777
86418446744073709551615-9223372036854775808 … 92233720368547758070xFFFFFFFFFFFFFFFF0o1777777777777777777777

(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

timetime in seconds, or (with a trailing M) milliseconds
linesnumber 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 Cturns off paging, and scrolls continuously
Esc or Ctrl-Caborts the current command
/scrolls half a screen, or half of lines
1 to 9scrolls 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.