The embedded files can then be accessed just like regular memory pointers (or as arrays, with IncArray).
incfile.bi
Code: Select all
#IFNDEF INCFILE_BI
#DEFINE INCFILE_BI
#MACRO IncFileEx(label, file, sectionName, attr)
#if __FUNCTION__ <> "__FB_MAINPROC__"
Dim label As Const Ubyte Ptr = Any
Dim label##_len As Uinteger = Any
#if __FB_DEBUG__
asm jmp .LT_END_OF_FILE_##label##_DEBUG_JMP
#else
' Switch to/Create the specified section
#if attr = ""
asm .section sectionName
#else
asm .section sectionName, attr
#endif
#endif
' Assign a label to the beginning of the file
asm .LT_START_OF_FILE_##label#:
asm __##label##__start = .
' Include the file
asm .incbin ##file
' Mark the end of the the file
asm __##label##__len = . - __##label##__start
asm .LT_END_OF_FILE_##label:
' Pad it with a NULL Integer (harmless, yet useful for text files)
asm .LONG 0
#if __FB_DEBUG__
asm .LT_END_OF_FILE_##label##_DEBUG_JMP:
#else
' Switch back to the .text (code) section
asm .section .text
asm .balign 16
#endif
asm .LT_SKIP_FILE_##label:
asm mov dword ptr [label], offset .LT_START_OF_FILE_##label#
asm mov dword ptr [label##_len], offset __##label##__len
#else
Extern "c"
Extern label As Ubyte Ptr
Extern label##_len As Uinteger
End Extern
#if __FB_DEBUG__
asm jmp .LT_END_OF_FILE_##label##_DEBUG_JMP
#else
' Switch to/create the specified section
#if attr = ""
asm .section sectionName
#else
asm .section sectionName, attr
#endif
#endif
' Assign a label to the beginning of the file
asm .LT_START_OF_FILE_##label#:
asm __##label##__start = .
' Include the file
asm .incbin ##file
' Mark the end of the the file
asm __##label##__len = . - __##label##__start
asm .LT_END_OF_FILE_##label:
' Pad it with a NULL Integer (harmless, yet useful for text files)
asm .LONG 0
asm label:
asm .int .LT_START_OF_FILE_##label#
asm label##_len:
asm .int __##label##__len
#if __FB_DEBUG__
asm .LT_END_OF_FILE_##label##_DEBUG_JMP:
#else
' Switch back to the .text (code) section
asm .section .text
asm .balign 16
#endif
asm .LT_SKIP_FILE_##label:
#endif
#endmacro
#macro IncFile(label, file)
IncFileEx(label, file, .data, "") 'Use the .data (storage) section (SHARED)
#endmacro
#endif
IncFile(label, filename)
creates a variable named "label" that points to the file contents, stores the file in the .data section, the length of the contents is stored in another variable called "label_len".
IncFileEx(label, filename, section_name, attr)
same as the above, but lets you specify a name for the section to store data in and the attributes of the section (can be 0 for default).
I hope some one finds it useful :)
Change log:
* Fixed some glitches and replaced LEA instruction with MOV (OFFSET).
* Now works inside functions once more.
* removed all x86 run-time initialization code (all except the jump for debug mode), replaced by compile-time assembler directives. [ If used at module leve ]
* removed the SHARE parameter altogether..
* IncFile Automatically decides whether to declare the variable as SHARED or not, based on the context. (__FB_MAINPROC__ trick)
* Support for debug builds.
* Now skips updating the variables if not needed.
* IncFileEx now allows you to specify section attributes.
* Added the 'share' parameter.
* fixed a small glitch with the "attr" parameter.
[22-1-2009] IncArray() macro
Code: Select all
#IFNDEF __INCARRAY_BI__
#DEFINE __INCARRAY_BI__
#macro IncArray(name, filename)
#if __FUNCTION__ <> "__FB_MAINPROC__"
#error "IncArray() cannot be used within a function."
' just to avoid extra pointless errors and keep things cleaner
dim label() as ubyte
#else
extern "c"
extern name() alias #name as ubyte
end extern
asm
#IF __FB_DEBUG__
jmp .LT_END_OF_FILE_##name##_DEBUG_JMP
#ELSE
.section .data
#ENDIF
.balign 1
__##name##__start = .
.incbin filename
__##name##__len = . - __##name##__start
.long 0 ' add one null int as padding
.globl ##name
.balign 4
##name:
.int __##name##__start 'data
.int __##name##__start 'ptr
.int __##name##__len 'size
.int 1 'element_len
.int 1 'dimensions
' dimTB
.int __##name##__len 'elements
.int 0 'lbound
.int __##name##__len-1 'ubound
.LT_END_OF_FILE_##name##_DEBUG_JMP:
.section .text
.balign 16
End asm
#undef Name##size
#endif
#endmacro
#ENDIF '__INCARRAY_BI__
- the macro builds an array descriptor using assembler directives, then imports the generated array using the "extern" statement.
- due to a bug in the FB preprocessor, the array's name must begin with an underscore (_test) [ FIXED, Not needed anymore ]
- this will not work with debug builds. (maybe if you build an object file separately) [ Read below ]
- you can use IncArrayEx() to specify the data-type of your array elements, the file will be divided into logical UDTs in memory just like normal arrays (variable-length strings are not supported)
- you cannot redim the generated array
- 0 instructions used, no executable code added to your application.
- [UPDATE] This should work in debug builds now, once this bug gets fixed.
- fixed some glitches with data-type alignment, now works as expected.
- [22-1-2009] support for datatypes other than byte has been removed, assembler started spewing errors recently, probably due to a recent change in the emitter.
Code: Select all
#include "incarray.bi"
IncArray(myFile, "test.bas")
print "File size: " & ubound(myFile) - lbound(myFile) + 1
print "Listing file contents:"
for i as integer = lbound(myFile) to ubound(myFile)
print chr(myFile(i));
next