'
'      *** BINDUMP - a universal binary dumper ***
'
' Sometimes I need to check a textfile with a binary viewer
'   whether or not it contains a Carriage Return (0x0D).
'
' This small program can do so, the -c parameter generates
'   colored output.
'
' We read the target program in chunks of 16 bytes instead of
' reading it into memory completely, to avoid memory overflow
'             problems with really large files.
'
' PvE, February 2010 - GPL.
' -------------------------------------------------------------------

' Chunks of 16 bytes
CONST Chunk_Size = 16

' Declare as 'int' to avoid compiler warnings with FORMAT
DECLARE byte, counter TYPE int
DECLARE Use_Color, Mem_Block, dim

' Parse arguments to program
SPLIT ARGUMENT$ BY " " TO arg$ SIZE dim
IF dim < 2 THEN
    PRINT "Usage: bindump [-c] <file.txt>"
    END
ENDIF

' Determines if we use colored output
Use_Color = FALSE

' This is the memory area which will be printed
Mem_Block = MEMORY(Chunk_Size)

' Get parameter
IF EQUAL(arg$[1], "-c") AND dim IS 3 THEN
    Use_Color = TRUE
    prog$ = arg$[2]
ELSE prog$ = arg$[1]

' Check if file exists
IF FILELEN(prog$) < 0 THEN
    PRINT "ERROR: file not found!"
    END
END IF

OPEN prog$ FOR READING AS file

' Walk through file until end
WHILE NOT(ENDFILE(file)) DO

    ' Reset memory area to clean previous data
    FOR i = 0 TO Chunk_Size - 1
        POKE Mem_Block + i, 0
    NEXT

    ' Set File Pointer to next position
    SEEK file OFFSET counter*Chunk_Size

    ' Perform a binary read into our memory area
    GETBYTE Mem_Block FROM file SIZE Chunk_Size

    ' Print the current memory address
    IF Use_Color THEN COLOR FG TO RED
    PRINT "[";
    IF Use_Color THEN COLOR FG TO YELLOW
    PRINT counter * Chunk_Size FORMAT "%08x"
    IF Use_Color THEN COLOR FG TO RED
    PRINT "] ";

    ' Dump binary values as hex on screen
    FOR i = 0 TO Chunk_Size - 1
        byte = PEEK(Mem_Block + i)
        IF Use_Color THEN COLOR FG TO GREEN
        PRINT byte FORMAT "%02x "
    NEXT

    ' Dump binary values as character on screen
    FOR i = 0 TO Chunk_Size - 1
        byte = PEEK(Mem_Block + i)
        IF Use_Color THEN COLOR FG TO CYAN
        IF byte > 31 THEN PRINT CHR$(byte);
        ELSE PRINT ".";
    NEXT

    ' Next line and chunk
    PRINT
    counter = counter + 1

WEND

' Reset and close all
IF Use_Color THEN COLOR RESET

CLOSE FILE file
FREE Mem_Block