Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
Laaca

Homepage

Czech republic,
20.05.2020, 23:15
 

Freepascal and binary files? (Developers)

Does anybody know whether is possible to somehow include files with binary data into Freepascal sources?
It would be nice for things like bundled fonts, icons etc.
In windows environment is it called "ressources" and the special mechanism is established but I mean something different.
Something like:

============================================================
Procedure DefineMyMouseCursor;
{$LINK cursor.bmp}
end;

...
begin
SetCursorShape(@DefineMyMouseCursor);
end.

---
DOS-u-akbar!

RayeR

Homepage

CZ,
21.05.2020, 01:46

@ Laaca
 

Freepascal and binary files?

I don't know how in FP but in C you can easily use some Bin2H convertor that create a header file with static array definition like const Byte bitmap[32]={0x10, 0x12, ...} and include that generated file in your source (#include "cursor.h"). So if FP can include other files that you can generate during build process you can do it the same way...

---
DOS gives me freedom to unlimited HW access.

Laaca

Homepage

Czech republic,
21.05.2020, 10:36

@ RayeR
 

Freepascal and binary files?

Sure, I wrote similar converter few years ago. It is OK for small data sizes. But for bigger data sizes it is not ideal because it slowes down the compilation.


In Turbopascal is it possible with the help of utility BINOBJ.
See bellow the explanation how to do it in TP.


3. The BINOBJ Utility
=======================

A utility program called BINOBJ.EXE has been added to convert any
file to an .OBJ file so it can be linked into a pascal program as
a "procedure." This is useful if you have a binary data file that
must reside in the code segment or is too large to make into a
typed constant array. For example, you can use BINOBJ with the
Graph unit to link the graphics driver or font files directly
into your .EXE file. Then, to use your graph program, you need
only have the .EXE file (see the example BGILINK.PAS).

BINOBJ takes three parameters:

   BINOBJ  <source[.BIN]>  <destination[.OBJ]>  <public name>

where source is the binary file to convert, destination is the
name of the .OBJ to be produced, and public name is the name of
the procedure as it will be declared in your pascal program.

The following example, the procedure ShowScreen, takes a pointer
as a parameter and moves 4000 bytes of data to screen memory. The
file called MENU.DTA contains the image of the main menu screen
(80 * 25 * 2 = 4000 bytes).

Here's a simple (no error-checking) version of MYPROG.PAS:

   program MyProg;

   uses Crt;

   procedure ShowScreen(ScreenData : Pointer);
   { Display a screenful of data--no error-checking! }
   var
     ScreenSegment: Word;

   begin
     if (Lo(LastMode) = 7) then      { Mono? }
       ScreenSegment := $B000
     else
       ScreenSegment := $B800;
     Move(ScreenData^,               { From pointer }
      Ptr(ScreenSegment, 0)^,        { To video memory }
      4000);                         { 80 * 25 * 2 }
   end;

   var
     MenuP : Pointer;
     MenuF : file;
   begin
     Assign(MenuF, 'MENU.DTA');      { Open screen data file }
     Reset(MenuF, 1);
     GetMem(MenuP, 4000);            { Allocate buffer on heap }
     BlockRead(MenuF, MenuP^, 4000); { Read screen data }
     Close(MenuF);
     ShowScreen(MenuP);              { Display screen }
   end.


The screen data file (MENU.DTA) is opened and then read into a
buffer on the heap. Both MYPROG.EXE and MENU.DTA must be present
at run-time for this program to work. You can use BINOBJ to
convert MENU.DTA to an .OBJ file (MENUDTA.OBJ) and tell it to
associate the data with a procedure called MenuData. Then you can
declare the fake external procedure MenuData, which actually
contains the screen data. Once you link in the .OBJ file with the
$L compiler directive, MenuData will be 4000 bytes long and
contain your screen data. First, run BINOBJ on MENU.DTA:

   binobj MENU.DTA MENUDTA MenuData

The first parameter, MENU.DTA, shows a familiar file of screen
data; the second, MENUDTA, is the name of the .OBJ file to be
created (since you didn't specify an extension, .OBJ will be
added). The last parameter, MenuData, is the name of the external
procedure as it will be declared in your program. Now that you've
converted MENU.DTA to an .OBJ file, here's what the new
MYPROG.PAS looks like:

   program MyProg;

   uses Crt;

   procedure ShowScreen(ScreenData : Pointer);
   { Display a screenful of data--no error checking! }
   var
     ScreenSegment: Word;
   begin
     if (Lo(LastMode) = 7) then             { Mono? }
       ScreenSegment := $B000
     else
       ScreenSegment := $B800;
     Move(ScreenData^,                      { From pointer }
      Ptr(ScreenSegment, 0)^,               { To video memory }
      4000);                                { 80 * 25 * 2 }
   end;

   procedure MenuData; external;
   {$L MENUDTA.OBJ }
   begin
     ShowScreen(@MenuData);                 { Display screen }
   end.

Notice that ShowScreen didn't change at all, and that the ADDRESS
of your procedure is passed using the @ operator.

---
DOS-u-akbar!

Rugxulo

Homepage

Usono,
21.05.2020, 02:27

@ Laaca
 

Freepascal and binary files?

> Does anybody know whether is possible to somehow include files with binary
> data into Freepascal sources?
> It would be nice for things like bundled fonts, icons etc.

Not sure what you're asking here. Clearly you know more about (Turbo) Pascal than I do. I feel like I'm telling you what you already know.

Classic Pascal didn't allow including constant data. (EDIT: The only aggregate data allowed by J&W was strings like "const Msg = 'Hello!';".) TP extended the const keyword for initialized (writable) constant data. So just initialize a constant array. (Or is that too tedious? Do you want an automated way? Not sure offhand what tools would simplify that or what other alternatives exist.)

Obviously, if you bundle binary data, it makes the data harder to modify with third-party tools or reuse with other programs. Often people resort to WAD/PAK/ZIP archives to hold multiple files. (Yes, I realize tons of external files is annoying. I also think a super-bloated .EXE is bad, too. Code and data should "mostly" be kept separated.)

There's also a good FPC wiki article on file handling in Pascal with modern Delphi niceties (TStringList, TFileStream, TMemoryStream).

marcov

21.05.2020, 12:25

@ Laaca
 

Freepascal and binary files?

> Does anybody know whether is possible to somehow include files with binary
> data into Freepascal sources?
> It would be nice for things like bundled fonts, icons etc.
> In windows environment is it called "ressources" and the special mechanism
> is established but I mean something different.

Since Delphi uses resources, Free Pascal has generalized them. Since go32v2 uses an internal linker, it might simply support linking .res files. (using {$R x.res} )

The library to access them is fcl-res, which has an own CHM file. Or see it online here: https://www.freepascal.org/docs-html/current/fclres/index.html

It seems to be able to generate Coff .o's.

It won't work for 16-bit targets (msdos,win16) afaik.

I don't have much experience with all of this though. I use them on Windows of course, but afaik I retrieve them over winapi.

Several array generators exist too (bin2obj and data2inc)

Laaca

Homepage

Czech republic,
21.05.2020, 17:30

@ marcov
 

Freepascal and binary files?

> Since Delphi uses resources, Free Pascal has generalized them. Since go32v2
> uses an internal linker, it might simply support linking .res files. (using
> {$R x.res} )
>
> The library to access them is fcl-res, which has an own CHM file. Or see it
> online here:
> https://www.freepascal.org/docs-html/current/fclres/index.html
>

OK, it seems to be complicated.
Maybe the most elegant solution would be some encoder/decoder which can convert Binary data into 7-bit ASCII set (like email algorithms like BASE64?) and such 7-bit data save like PCHAR or ANSISTRING strings.

---
DOS-u-akbar!

marcov

22.05.2020, 13:17

@ Laaca
 

Freepascal and binary files?

>
> OK, it seems to be complicated.
> Maybe the most elegant solution would be some encoder/decoder which can
> convert Binary data into 7-bit ASCII set (like email algorithms like
> BASE64?) and such 7-bit data save like PCHAR or ANSISTRING strings.

Look at fpc/packages/fcl-base/examples/b64enc.pp followed by data2inc to encoding it as string.

Rugxulo

Homepage

Usono,
31.05.2020, 18:50

@ Laaca
 

Freepascal and binary files?

> Does anybody know whether is possible to somehow include files with binary
> data into Freepascal sources?
>
> Procedure DefineMyMouseCursor;
> {$LINK cursor.bmp}
> end;

Bas de Reuver's old Urthwurm DOS game used his own homegrown tool (makedata.pas) to convert .PCX to data for TP.

CandyMan

11.06.2020, 12:29

@ Laaca
 

Freepascal and binary files?

You can use FASM as below.

Cursor1.ASM file:
 
        format  MS COFF
        public  Cursor
section '.text' executable
Cursor  file    "cursor.bmp"

in PAS file:

procedure Cursor; external {$IFDEF FPC}name 'Cursor'{$ENDIF};
{$L Cursor1.O}

Laaca

Homepage

Czech republic,
12.06.2020, 07:37

@ CandyMan
 

Freepascal and binary files?

> You can use FASM as below.
>
> Cursor1.ASM file:
>  
> format  MS COFF
> public  Cursor
> section '.text' executable
> Cursor  file    "cursor.bmp"
>

> in PAS file:
>
> procedure Cursor; external {$IFDEF FPC}name 'Cursor'{$ENDIF};
> {$L Cursor1.O}
>


Wow! It is exactly what I had on my mind.
Anyway, I've managed to write own tiny implementation of BASE64 encoder and decoder as discused above.
So for smaller data I'll use the PChar strings in BASE64 and eventualy for large data your solution.

---
DOS-u-akbar!

Laaca

Homepage

Czech republic,
29.10.2021, 00:17

@ Laaca
 

Freepascal and binary files?

Sorry for exhuming this thread but I did some further investigation in this topic.
1) Create a file HELLO.TXT with content like that:
Hello world!<CR><LF>

2) Call this line: "LD -r -b binary -o HELLO.O HELLO.TXT"
(I tried the LD.EXE ver. 2.17 from FPC 3.2.0 and LD.EXE ver. 2.9.1 from FPC 1.0.10 -- both work)

3) Write this FPC code:

var start_ptr:pointer;external name '_binary_hello_txt_start';
    size_ptr:pointer;external name '_binary_hello_txt_size';
    {end_ptr:pointer;external name '_binary_hello_txt_end';}

    my_start:pointer;
    my_size:longint;
    p:pchar;

begin
{$L hello.o}
my_start:=@start_ptr;
my_size:=longint(@size_ptr);

p:=my_start;
p[my_size]:=#0;  {Yeah, I know, I am crippling the LF char}
write(p);
end.


4) Compile it and run.

__BUT__
It works perfectly with FPC 1.0.10 and with FPC 2.4.2
However it does NOT with FPC 3.2.0 and 3.0.4 !
Why???
The 3.x.y versions of FPC refuse to compile the source with this error message:
"Error - Failed reading coff file, invalid section index while reading hello.o"

Edit: Well, it does compile if I set the compile option "Call linker after".
But... Can I make it work even without this option?

---
DOS-u-akbar!

tkchia

Homepage

30.10.2021, 07:33
(edited by tkchia, 30.10.2021, 18:29)

@ Laaca
 

Freepascal and binary files?

Hello Laaca,

> __BUT__
> It works perfectly with FPC 1.0.10 and with FPC 2.4.2
> However it does NOT with FPC 3.2.0 and 3.0.4 !
> Why???
> The 3.x.y versions of FPC refuse to compile the source with this error
> message:
> "Error - Failed reading coff file, invalid section index while reading
> hello.o"

No idea what is happening, but apparently the compiler or linker does not like hello.o's contents. What I might do is to use Watcom's wdis (or some other disassembler) to dump hello.o to see what might be wrong...

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

Laaca

Homepage

Czech republic,
30.10.2021, 12:29

@ tkchia
 

Freepascal and binary files?

It seems to be some problem with the FPC internal linker. In the past the FPC created only the object files and the external utility (LD.EXE) was called to boil the final EXE.
But since some version it changed into own linker. In some platforms earlier in some later. Maybe DOS is linker internaly since FPC 3.0.0. Maybe.
And maybe the FPC internal linker is such valid but too simplistic object file like above mentioned HELLO.O

---
DOS-u-akbar!

tkchia

Homepage

30.10.2021, 19:01

@ Laaca
 

Freepascal and binary files?

Hello Laaca,

> And maybe the FPC internal linker is such valid but too simplistic object
> file like above mentioned HELLO.O

OK, I did a quick test with my MinGW32 ld which I happen to have installed on my Ubuntu box:

$ echo hello >hello.txt
$ x86_64-w64-mingw32-ld -r -b binary hello.txt -o hello.o
$ x86_64-w64-mingw32-objdump -x hello.o
...
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .data         00000010  0000000000000000  0000000000000000  00000064  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  1 .rdata        00000000  0000000000000000  0000000000000000  00000000  2**4
                  ALLOC, LOAD, READONLY, DATA
SYMBOL TABLE:
[  0](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 _binary_hello_txt_start
[  1](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000006 _binary_hello_txt_size
[  2](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000006 _binary_hello_txt_end


(The target platform is not the same as DJGPP COFF, but it is COFF and probably close enough for this quick and dirty test...)

The section index for the symbol _binary_hello_txt_size is -1. I guess -1 is used for absolute values that do not belong to any section.

My guess is that something similar was happening with your hello.o — and Free Pascal was complaining because it did not like the -1 section number.

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

Rugxulo

Homepage

Usono,
28.08.2022, 23:21

@ tkchia
 

Freepascal and binary files?

Unrelated to Pascal, but the upcoming C standard C23 will (apparently??) support #embed, see here for details.

I have not tried it (not sure GCC even has it yet!), but GCC 12.2 was silently uploaded for DJGPP last week. (We already had GCC 12.1.)

Back to index page
Thread view  Board view
22049 Postings in 2034 Threads, 396 registered users, 157 users online (0 registered, 157 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum