/*──────────────────────────────────────────────────────────────┐
│HexLoad: HEX-Dateien (auch nicht-zusammenhängend) laden │
│Codepage: UTF-8 ohne BOM, Zeilenenden: LF, Tabweite: 8 │
└──────────────────────────────────────────────────────────────*/
#include "peps.h"
/* GLOBAL */
MEMAREA *areas; // sortierte (!) Speicherbereiche
long LoadOffset;
FILE *InFile;
bool Verbose;
BYTE buffer[0x200000]; // maximal können 2 MiB verarbeitet werden
// Kann mehrfach aufgerufen werden.
// Das Initialisieren des PEPS muss voraus gehen,
// außer bei FileToFile-Operationen
//void InitBuffer(long size) {
// if (buffer) return;
// TargetSize=size;
// buffer = malloc(TargetSize);
//}
// Vorgefundenen Speicherblock hinzufügen,
// dabei versuchen die Anzahl der tatsächlichen Blöcke zu minimieren.
// Kommt auch mit Überlappungen zurecht!
// Es muss a < e gelten! Null-Blöcke sind nicht erlaubt.
void AddArea(long a, long e) {
MEMAREA *p,*q,**pp=&areas;
if (a<e) for(;;) { // EVL durchgehen
p=*pp;
if (!p || e < p->a) { // Kein Block ODER Bereich liegt davor?
q = malloc(sizeof(MEMAREA)); // Neuer Block
*pp = q; // fontal einfügen
q->next = p;
q->a = a; // abspeichern
q->e = e;
break; // Schleife beenden
}
if (e >= p->a && a <= p->e) { // Überlappt oder schmiegt sich an?
if (p->a > a) p->a = a; // Anfang ausdehnen (kann Vorgänger nicht berühren)
if (p->e < e) {
p->e = e; // Ende ausdehnen
while ((q = p->next)) { // Folgeblöcke abtesten
if (q->a <= e) { // Berührt oder überlappt nächsten Block?
if (q->e > e) p->e = q->e; // ja, anhängen (je nachdem was länger ist)
p->next = q->next; // <q> auskoppeln
free(q); // Folgeblock verschlingen (Okklusion)
}else break; // nein, Suche abbrechen
}
}
break; // Schleife beenden
}
pp=&p->next; // Zeiger auf vorhergehenden Anker setzen
}
}
// EVL löschen
void ClearAreas() {
MEMAREA *p;
while ((p=areas)) {
areas=p->next;
free(p);
}
}
// Bytes aus Speicherbereich hinzufügen, bei <p>==NULL aus globalem InFile
// a = Zieladresse, LoadOffset wird zusätzlich berücksichtigt
void AddBytes(const BYTE*p, long a, long len) {
long e;
a += LoadOffset; // kann negativ werden
e = a + len;
// Clipping
if (e<0) return; // komplett außerhalb (davor)
if (a>sizeof(buffer)) return; // komplett außerhalb (dahinter)
if (a<0) { // kann passieren bei negativem LoadOffset
a=-a; // Überhang (Betrag)
if (p) p+=a;
else fseek(InFile,a,SEEK_CUR); // vorspulen
a=0;
}
if ((unsigned long)e>sizeof(buffer)) e=sizeof(buffer);
// Daten schaufeln
len = e-a; // Länge nach dem Clipping
if (len<=0) return; // nichts! (sollte nicht vorkommen)
if (p) memcpy(buffer+a,p,len);
else fread(buffer+a,1,len,InFile);
// Bereich hinzufügen
AddArea(a,e);
}
void LoadObjModule() {
rprintf(4);
}
// Hexziffer in Nibble umwandeln; <c> muss gültiges Hexzeichen sein
static BYTE nibble(char c) {
if (!isxdigit(c)) DoExit(6);
c&=0x1F; // '0'..'9' -> 0x10..0x19, 'A'..'F', 'a'..'f' --> 0x01..0x06 (erschlägt Kleinbuchstaben)
c-=0x10;
if (c<0) c+=0x10+10-1;
return c;
}
// Hex-Zahl (2 Zeichen) einlesen
static BYTE htoi(const char *str) {
return nibble(str[0])<<4|nibble(str[1]);
}
void LoadIntel() {
long Segment=0, UpperLBA=0;
char buf[600]; // Textzeile
rprintf(5);
buf[sizeof buf-1]=0; // Muss da stehen bleiben
while (fgets(buf,sizeof(buf)-1,InFile)) { // 1 Zeile lesen
char *start;
BYTE CheckSum;
int i;
BYTE Data[260]; // 4 Byte Header, max. 255 Datenbytes, 1 Byte Prüfsumme
#define Length (Data[0]) // … der Daten (ab Data+4)
#define RecordAdr ((Data[1]<<8)|Data[2]) // tatsächlich Big-Endian
#define RecordType (Data[3])
if (buf[sizeof(buf)-1]) DoExit(11); // Zeile zu lang
start=strchr(buf,':');
if (!start) continue; // ungültige, eher leere Zeile ignorieren
start++;
CheckSum = 0;
Length = 0; // Optimizer ruhig stellen
for (i=0; i<(int)Length+5; i++) {
CheckSum += Data[i] = htoi(start);
start+=2;
}
if (CheckSum) DoExit(9);
switch (RecordType) {
case 4: //ELADRRECORD, Extended Linear Address Record
/* 18.12.1997 (aMay) */
UpperLBA = (long)(Data[4]<<8 | Data[5])<<16;// bis 4 GiByte
break;
case 3: //STARTRECORD
case 2: //EADRRECORD
Segment = (long)(Data[4]<<8 | Data[5])<<4; // bis 1 MiByte
break;
case 0: //DATARECORD
/* 18.12.97 aMay */
/* Extended Linear Address Record berücksichtigen! */
AddBytes(Data+4,RecordAdr+Segment+UpperLBA,Length);
break;
}
#undef Length
#undef RecordAdr
#undef RecordType
}
}
void LoadMotorola() {
char buf[600]; // Textzeile
rprintf(10);
buf[sizeof(buf)-1]=0; // darf nicht überschrieben werden, sonst Zeile zu lang!
while (fgets(buf,sizeof(buf)-1,InFile)) {
char *start;
int i;
BYTE CheckSum;
BYTE Data[258]; // RecordType, Länge, max. 255 Datenbytes, Prüfsumme = 258 Bytes
#define RecordType (Data[0])
#define Length (Data[1]) // inklusive Adresse, exklusive Prüfsumme
if (buf[sizeof(buf)-1]) DoExit(11);
start=strchr(buf,'S');
if (!start) continue; // ungültige, eher leere Zeile ignorieren
*start = '0'; // Zweistellige Hexzahl draus machen
CheckSum = 0xFF;
Length = 0; // Optimizer ruhig stellen
for (i=0; i<(int)Length+3; i++) {
CheckSum += Data[i] = htoi(start);
start+=2;
}
if (CheckSum!=RecordType) DoExit(12);
switch (RecordType) {
/*
case 0: //MFIRSTRECORD
Data[Length+1] = 0;
printf(" %s ", Data+2); // wozu das??
break;
*/
case 1: //MDATA16RECORD, 16-bit-Adresse
AddBytes(Data+4,Data[2]<<8|Data[3],Length-3);
break;
case 2: //MDATA24RECORD, 24-bit-Adresse (reicht bis 16 MiByte)
AddBytes(Data+5,(long)Data[2]<<16|Data[3]<<8|Data[4],Length-4);
break;
}
}
}
void LoadBinary() {
long Size;
fseek(InFile,0,SEEK_END); // Hoppla, unter Linux kommt da keine Dateilänge 'raus!
Size=ftell(InFile); // Deshalb eher umständlich
rprintf(41, Size, Size);
fseek(InFile,0,SEEK_SET);
AddBytes(NULL,0,Size);
}
Vorgefundene Kodierung: UTF-8 | 0
|