Wer hat nicht schon einmal ein Programm geschrieben, das gewisse Hilfsdateien benötigt? Sollen z.B. Bilder angezeigt werden, müssen sie erst mühselig von Diskette nachgeladen werden.
MAKE_OBJ.TTP schafft hier Abhilfe. Es macht aus normalen Dateien linkfähige Objektdateien im weit verbreiteten DR-Format. Somit können beliebige Daten direkt ins Programm integriert werden. Dies können z.B. Bilder, Zeichensätze, Ressourcen oder ähnliches sein. Der Phantasie sind keine Grenzen gesetzt. solange man den Aufbau der Dateien kennt. Die erzeugten Objektdateien müssen dann nur noch zum Hauptprogramm hinzugelinkt werden.
Dem Programm wird eine Kommandozeile übergeben, die folgendes Format hat: PFAD SYMBOLNAME. PFAD ist der komplette Name der zu bearbeitenden Datei, z.B. B:\ORDNER\NAME.EXT. SYMBOLNAME ist ein maximal 8 Zeichen langer Name, der in die Symboltabelle eingetragen wird. Achtung: Groß-/Kleinschreibung beachten! MAKE_OBJ.TTP erzeugt dann eine Datei namens B:\ORDNER\NAME.O. Das Anhängen der Extension 'O' erledigt übrigens die Funktion set_ext(..). Als erstes wird überprüft, ob die Kommandozeile dem erwarteten Format entspricht. Danach wird die zu bearbeitende Datei geöffnet, deren Größe ermittelt und entsprechend viel Speicher reserviert. Die Daten werden eingelesen und die Datei geschlossen. danach eine neue Datei erzeugt, und der Objekt-Header. die Daten und die Symboltabelle geschrieben. Objekt-Header und Symboltabelle sind schon vordefiniert, da sich die Daten bis auf den Symbolnamen und die .Länge des Databereichs nicht ändern.
Daran schließen sich noch eine ganze Menge Nullen an. Die Datei wird geschlossen und der reservierte Speicher wieder freigegeben. Um die Arbeitsweise von MAKE_OBJ.TTP zu verdeutlichen, nun zu einem kleinen Beispiel. DEMO1.C zeigt, wie man ein im Programm integriertes Bild (im Screen-Format) anzeigen kann. Natürlich muß die Bilddatei vorher mit MAKE_OBJ.TTP bearbeitet werden. Man übergibt dem Programm den kompletten Pfad der Datei (z. B. "B:\MY_PIC.DOO") und den gewünschten Symbolnamen (in unserem Fall "BILD"). MAKE_OBJ.TTP erzeugt dann eine Objektdatei mit dem Namen "B:\MY_PIC.O". Diese Datei wird später zum Hauptprogramm "hinzugelinkt”.
Zum Listing ist eigentlich nicht viel zu sagen. Als erstes deklarieren Sie "BILD" als "extern long". Man muß jetzt nur noch die Adresse des Bildschirmes ermitteln, und pic die Adresse des Bildes im Speicher zuweisen. Danach lassen sich die Bilddaten direkt auf den Bildschirm kopieren. Will man Resource-Dateien ins Programm einbinden, gestaltet sich die Sache schon etwas komplizierter. Im DEMO2.C werden zwei Ressourcen gleichzeitig angesprochen.
Man muß dabei nichts anderes tun. als die Funktion rsrc_load(..). die man im Normalfall benutzen würde, durch rsrc_init(..) zu ersetzen. Übrigens kann dann rsrc_free() wegfallen. Die Adressen der Objektbäume, freien Strings etc. können wie üblich über die Funktion rsrc_gaddr(..) ermittelt werden. Bestehende Programme muß man also nur geringfügig ändern. Als Demonstration legen Sie zwei Resourcefiles an ("RSCA.RSC" und "RSCB.RSC"), wobei jeweils ein Objektbaum. dessen Aufbau beliebig ist. erstellt wird. Den ersten nennen wir TREE1. den zweiten TREE2. Verwendet man wie hier mehrere Resource-Dateien. muß man natürlich darauf achten, daß man nicht zweimal den gleichen Namen an verschiedene Objekte vergibt.
Beide Dateien werden nun mit "MAKE_OBJ.TTP" bearbeitet. Aufruf: 'RSCA.RSC RSCA' bzw. 'RSCB.RSC RSCB' Die Hauptarbeit erledigt also die Funktion rsrc_init(..). Ihr übergibt man die Anfangsadresse der zu bearbeitenden Resource-Datei (rsrc_init(&RSCA)). Rsh zeigt dann automatisch auf den Resource-Header.
Nun wird in global[9] die Größe der Ressource, die in rsh_rssize steht, geschrieben, danach in global[7] und global [8] die Adresse der Datei, und in global[5] und global[6] die Adresse einer Tabelle mit den Anfangsadressen der Objektbäume. Der Anfang dieser Tabelle steht wiederum im Header (rsh_trindex). In rsh_trindex steht der Beginn dieser Tabelle relativ zum Anfang der Resource-Datei. Man muß also nur noch ‘rsh hinzuaddieren' [das erledigt das Makro add_ptr(..)] und ptr zuweisen. Diese Zeilen sind notwendig, damit später die Funktion rsrc_gaddr(..) richtig arbeiten kann. Ptr zeigt also jetzt auf den ersten Eintrag der Tabelle. Hier könnte z.B. eine 36 stehen, was bedeuten würde, daß der erste Objektbaum ab Byte Nummer 36 in der Resource-Datei zu finden ist. Wir addieren wieder ‘rsh’, um die wirkliche Adresse zu erhalten. Dies geschieht innerhalb einer Schleife, in der alle Bäume durchlaufen werden. Analoges passiert mit den freien Strings und den freien Images. Anschließend werden für alle Objekte nach dem gleichen Prinzip mit dem Makro add_rsh(..) die Zeiger z.B. auf Texte etc. gesetzt und die Koordinaten mittels rsrc_obfix(..) angepaßt.
/********************************\
| Von Ralf Plamitzer |
| Dresdenerstr. 7 |
| 6120 Michelstadt |
| TURBO C 2.0 |
| |
| (c) MAXON Computer GmbH 1390 |
| Macht aus beliebigen Dateien |
| linkbare Objektdateien im |
| DR-Format. |
| Beispielaufruf: |
| B:\ORDNER\FILE.EXT SYMBOL |
| erzeugt: B:\ORDNER\FILE.O |
\********************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ext.h>
typedef struct
{
int branch; /* Immer 0x601A */
long tlen; /* Länge Textsegment (0) */
long dlen; /* Länge Datensegment */
long blen; /* Länge BSS */
long slen; /* Länge Symb.tab. (14) */
char reserved[10];
}OHEADER;
typedef struct {
char name[8]; /* Symbolname */
int typ; /* Bei uns immer 0xA400 */
long fill; /* Immer null */
} SYM;
OHEADER oh = {
0x601A,0L,0L,0L,0x0EL,0,0,0,0,0,0,
0,0,0,0 } ;
SYM sym = { "12345678",0xA400,0L };
void set_ext(char *name,char *ext)
{
char *c;
if((c = strrchr(name,'.')) == NULL)
return;
*++c = '\0';
strcat(name,ext);
}
int main(int argc,char *argv[])
{
FILE *file;
char *buf,path[128];
if(argc != 3)
return (1);
strcpy(path,argv[1]);
if ((file = fopen (path,"rb")) == NULL)
return(1);
if ((oh.dlen = filelength(file->Handle)) % 2)
oh.dlen++;
if ((buf = malloc(oh.dlen)) == NULL)
{
fclose(file);
return(1);
}
fread(buf,oh.dlen,1,file);
fclose(file);
set_ext(path,"O");
if((file = fopen(path,"wb")) == NULL)
{
free(buf);
return(1);
}
strncpy(sym.name,argv[2],8);
fwrite(&oh,sizeof(OHEADER),1,file);
fwrite(buf,oh.dlen,1,file);
fwrite(&sym,sizeof(SYM),1,file);
memset(buf,0,oh.dlen);
fwrite(buf,oh.dlen,1,file);
fclose(file);
free(buf);
return(0);
}
Listing: So werden in das DR-Format gewandelt.