Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to embed binary data into DOS EXEs made in Turbo C?

I've set up a DOSBox development environment with Turbo C++ intending to make a game with my friends.

I'm using C code, and am wondering how I'd link binary data into the EXE. (All my previous experience with C is libGBA, sorry if that's not actually possible in the way I think it'd be.)

If it isn't possible, then what would be an alternative option for embedding binary data? (I don't really want to need a bunch of binary files in the game directory...)

Can't find much third party documentation for Turbo C, especially considering I'm using the other, supported, but not main language for my IDE which was last updated in the early 2000s after moving to another OS entirely.

like image 675
ScottBeebiWan Avatar asked Apr 16 '19 07:04

ScottBeebiWan


2 Answers

An easy solution used by programs such as self-extracting .zip files, is to simply append the data onto the end of the .exe file. The size of the .exe can be calculated from values in the header, which will give you the offset where the appended data begins. Here is an example C program that compiles with Borland Turbo C v2.01 (available as freeware) - note that I have omitted error checking for clarity:

#include <stdio.h>

int main(int argc, const char *argv[])
{
    FILE *fSelf;
    unsigned short lenFinalBlock, numBlocks;
    unsigned long offEnd;
    char trailing[256];
    int len;

    /* Open our own .exe file */
    fSelf = fopen(argv[0], "rb");

    /* Read part of the .exe header */
    fseek(fSelf, 2, SEEK_SET);
    fread(&lenFinalBlock, 2, 1, fSelf);
    fread(&numBlocks, 2, 1, fSelf);

    /* Calculate the size of the .exe from the header values */
    offEnd = numBlocks * 512;
    if (lenFinalBlock) offEnd -= 512 - lenFinalBlock;

    /* Jump to the end of the .exe and read what's there */
    fseek(fSelf, offEnd, SEEK_SET);

    /* Just read it as a string - you'd presumably be using
       some custom data format here instead */
    len = fread(trailing, 1, 256, fSelf);
    trailing[len] = 0;

    printf("Trailing data (%d bytes @ 0x%lX):\n%s", len, offEnd, trailing);

    fclose(fSelf);

    return 0;
}

Once compiled to trailing.exe you can use it like this:

C:\>trailing
Trailing data (0 bytes @ 0x2528):

I'm on Linux so I will append some example data using the shell:

$ echo Hello >> trailing.exe

Running it again shows it picking up the trailing data:

C:\>trailing
Trailing data (6 bytes @ 0x2528):
Hello
like image 192
Malvineous Avatar answered Oct 19 '22 06:10

Malvineous


It should be possible to use the BGIOBJ.EXE utility which is included with Turbo C++ to achieve what you want.

BGIOBJ can convert a binary file to an .obj file which then can be linked into the .exe file. Its primary purpose is to include BGI drivers and fonts in the .exe, but it shouldn't put any restrictions on the file (except for size).

Unfortunately I can't tell you exactly how to get the memory address where the file is loaded at run-time, but that shouldn't be too difficult. BGIOBJ supports parameters for public name, segment name and segment class so you can refer to these.

like image 1
idspispopd Avatar answered Oct 19 '22 07:10

idspispopd