File "xdata.inc"
Path: /program cloner/inc/xdata.inc
File size: 6.65 KB
MIME-type:
Charset: utf-8
'--------------------------------------------------------------------------------
' An 'ExeData' is a chunk of data at the end of an executable, it can be added
' at runtime. Its structure is: [CHUNK OF DATA][CHUNK SIZE][CHUNK DESC][MAGIC]
' where:
' - CHUNK OF DATA is any blob of data, text or binary
' - CHUNK SIZE is the hexadecimal length (on 8 bytes) of this blob of data
' - CHUNK DESC is a descriptor (on 3 bytes) of this blob of data, it can be
' anything such as: JPG, CFG, TXT, WAV etc.
' - MAGIC is the ExeData magic value: "{ExDt}"
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
TYPE ExeData
address AS DWORD
length AS DWORD
desc AS ASCIIZ * 4
END TYPE
'--------------------------------------------------------------------------------
$EXEDATA_MAGIC = "{ExDt}"
'--------------------------------------------------------------------------------
GLOBAL sharedData() AS STRING ' when packaging a custom widget
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB ParseExeData(BYVAL file AS STRING, BYREF ExDt() AS ExeData)
' Parse an executable and fill the info of its ExeData() parts
LOCAL a AS STRING
LOCAL i, n AS LONG
IF NOT Exist(file) THEN EXIT SUB ELSE a = GetFile(file)
' LogMe "<Parsing ExeData of file "+file+" ("+FORMAT$(LEN(a),"#,")+" Bytes)"
WHILE RIGHT$(a, LEN($EXEDATA_MAGIC)) = $EXEDATA_MAGIC
INCR n
IF ISFALSE ARRAYATTR(ExDt(),0) THEN ' Array not DIMensioned
DIM ExDt(1 TO 1)
ELSE
REDIM PRESERVE ExDt(1 TO UBOUND(ExDt)+1)
END IF
i = UBOUND(ExDt)
a = LEFT$(a, -LEN($EXEDATA_MAGIC)) ' magic value
ExDt(i).desc = RIGHT$(a, 3) + $NUL
a = LEFT$(a, -3) ' descriptor (3 Bytes)
ExDt(i).length = VAL("&H0"+RIGHT$(a,8))
a = LEFT$(a, - (ExDt(i).length + 8)) ' length (8 Bytes)
ExDt(i).address = LEN(a) + 1
' LogMe "- Found a chunk of data, of type '"+ExDt(i).desc _
' +"', at address "+FORMAT$(ExDt(i).address,"#,")+" (" _
' +"length: "+FORMAT$(ExDt(i).length,"#,")+" Bytes)"
WEND
FOR i = 1 TO UBOUND(ExDt) \ 2 ' sort 'ExeData' array
IF i = UBOUND(ExDt) / 2 THEN EXIT FOR
SWAP ExDt(i).desc, ExDt(UBOUND(ExDt)-i+1).desc
SWAP ExDt(i).length, ExDt(UBOUND(ExDt)-i+1).length
SWAP ExDt(i).address, ExDt(UBOUND(ExDt)-i+1).address
NEXT
' LogMe FORMAT$(n)+" chunk(s) of data found>"
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION ClearExeData(BYVAL file AS STRING) AS STRING
' Return the 'exe' part of an executable, w/o any of its ExeData
LOCAL a AS STRING
LOCAL ln AS DWORD
IF NOT Exist(file) THEN EXIT FUNCTION ELSE a = GetFile(file)
' LogMe "<Clearing ExeData from file "+file+" ("+FORMAT$(LEN(a),"#,")+" Bytes)"
WHILE RIGHT$(a, LEN($EXEDATA_MAGIC)) = $EXEDATA_MAGIC
a = LEFT$(a, - (LEN($EXEDATA_MAGIC) + 3)) ' remove magic value + 3B descriptor
ln = VAL("&H0"+RIGHT$(a,8))
a = LEFT$(a, - (ln + 8)) ' remove 8B length + data blob
WEND
FUNCTION = a
' LogMe "Done. Clean file is "+FORMAT$(LEN(a),"#,")+" Bytes>"
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION FindExeData(BYVAL desc AS STRING, BYREF ExDt() AS ExeData, _
OPTIONAL BYVAL start AS LONG) AS LONG
' Return the ExeData() index containing descriptor 'desc' ; or 0 if not found
LOCAL st, i AS LONG
IF start > 1 THEN st = start ELSE st = 1
FUNCTION = 0
FOR i = st TO UBOUND(ExDt)
IF TRIM$(UCASE$(ExDt(i).desc)) = TRIM$(UCASE$(desc)) THEN
FUNCTION = i
EXIT FUNCTION
END IF
NEXT
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION GetExeData(BYVAL file AS STRING, BYREF ExDtElt AS ExeData) AS STRING
' Return the ExeData(i) part (data chunk) from the executable 'file'
LOCAL a AS STRING
IF NOT Exist(file) THEN EXIT FUNCTION ELSE a = GetFile(file)
IF ExDtElt.address + ExDtElt.length > LEN(a) THEN EXIT FUNCTION ' out-of-bound
FUNCTION = MID$(a, ExDtElt.address, ExDtElt.length)
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION AddExeData(src AS STRING, desc AS STRING, chunk AS STRING) AS STRING
' Add 'chunk' data of type 'desc' to the exe (or data) 'src' and return the result
LOCAL a, d AS STRING
IF LEN(src) < %MAX_PATH AND MID$(src, 2, 2) = ":\" THEN
IF NOT Exist(src) THEN EXIT FUNCTION ELSE a = GetFile(src)
' LogMe "<Adding ExeData to file "+src+" ("+FORMAT$(LEN(a),"#,")+" Bytes)"
ELSE
a = src
' LogMe "<Adding ExeData to unnamed executable ("+FORMAT$(LEN(a),"#,")+" Bytes)"
END IF
' LogMe "- Trying to add a chunk of data, of type '"+desc _
' +"' and length "+FORMAT$(LEN(chunk),"#,")+" Bytes"
IF LEN(chunk) = 0 OR LEN(desc) > 3 THEN ' empty chunk or illegal descriptor
FUNCTION = a
' LogMe "Failed. Original file unchanged>"
EXIT FUNCTION
END IF
a += chunk
a += HEX$(LEN(chunk),8)
a += SPACE$(3-LEN(TRIM$(desc))) + TRIM$(desc)
a += $EXEDATA_MAGIC
FUNCTION = a
' LogMe "Done. New file is "+FORMAT$(LEN(a),"#,")+" Bytes>"
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB SetFile(dat AS STRING, file AS STRING)
LOCAL ff AS LONG
KILL file
ff = FREEFILE
OPEN file FOR BINARY ACCESS WRITE LOCK READ AS #ff
PUT$ #ff, dat
CLOSE #ff
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION GetFile(file AS STRING) AS STRING
LOCAL ff AS LONG
LOCAL aa AS STRING
IF NOT Exist(file) THEN EXIT FUNCTION
ff = FREEFILE
OPEN file FOR BINARY ACCESS READ LOCK WRITE AS #ff
GET$ #ff, LOF(#ff), aa
CLOSE #ff
FUNCTION = aa
END FUNCTION
'--------------------------------------------------------------------------------