+ fprintf (fOut, ":00000001FF\n");
+
+ fclose (fOut);
+}
+
+int relocate() {
+ struct SYMBOL *symbol;
+ struct REFERENCE *reference;
+ char *from, *to;
+ int length=segments[GSINIT]._size +
+ segments[CSEG]._size +
+ segments[XINIT]._size;
+ int unresolved=0;
+
+ // first check if it will fit
+ if (length > 0xffff) {
+ fprintf (stderr, "error: code segment exceeds 0xffff\n");
+ fatalErrors++;
+ }
+
+ // resolve reverences
+ for (reference=references; reference; reference=reference->next) {
+ if (!reference->resolved && !findSymbolByName(reference->name)) {
+ unresolved++;
+ }
+ }
+ if (unresolved) {
+ // first scan the libraries
+ return unresolved;
+ }
+
+ // GSFINAL starts at --code-loc ( -b CSEG = 0x1234 )
+ if (segments[CSEG].start & 1) {
+ fprintf (stderr, "*** error: code doesn't start at "
+ "an even address: %04x\n", segments[CSEG].start);
+ exit (1);
+ }
+ segments[GSFINAL].start=segments[CSEG].start;
+ memset(gsfinalImage, 0xff, CODESIZE);
+
+ // copy gsinit to gsfinal
+ from = gsinitImage;
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
+ memcpy(to, from, segments[GSINIT]._size);
+ segments[GSINIT].start=segments[GSFINAL].start;
+ segments[GSFINAL]._size += segments[GSINIT]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // append cseg to gsfinal
+ from=csegImage;
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
+ memcpy(to, from, segments[CSEG]._size);
+ segments[CSEG].start=segments[GSFINAL].start+segments[GSFINAL]._size;
+ segments[GSFINAL]._size += segments[CSEG]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // append xinit to gsfinal
+ from=xinitImage;
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
+ memcpy(to, from, segments[XINIT]._size);
+ segments[XINIT].start=segments[GSFINAL].start+segments[GSFINAL]._size;
+ segments[GSFINAL]._size += segments[XINIT]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // XISEG is located after XSEG
+ if (segments[XSEG].start & 1) {
+ fprintf (stderr, "*** warning: xdata doesn't start at "
+ "an even address: %04x\n", segments[XSEG].start);
+ }
+ if (segments[XSEG]._size & 1) {
+ segments[XSEG]._size++;
+ }
+
+ segments[XISEG].start=segments[XSEG].start +
+ segments[XSEG]._size;
+
+ // now relocate the defined symbols
+ for (symbol=symbols; symbol; symbol=symbol->next) {
+ if (!symbol->absolute) {
+ symbol->address += symbol->segment->start;
+ }
+ }
+ // and the references
+ for (reference=references; reference; reference=reference->next) {
+ symbol=findSymbolByName(reference->name);
+ if (!reference->resolved && !symbol && reference->how!=ABS_PC) {
+ // this reference isn't resolved after all
+ fprintf (stderr, "*** %s:%d undefined symbol %s\n",
+ reference->module->name, reference->lineno,
+ reference->name);
+ fatalErrors++;
+ } else {
+ reference->address +=
+ reference->module->offset[reference->segment->id]+
+ reference->segment->start;
+ reference->pc +=
+ reference->module->offset[reference->segment->id]+
+ reference->segment->start;
+ switch (reference->how)
+ {
+ case REL_FF: {
+ int rel8 = symbol->address-(reference->pc & ~1);
+ if (rel8<-256 || rel8>256) {
+ fprintf (stderr,
+ "rel8 target for %s is out of range in module %s:%d\n",
+ reference->name, reference->module->name,
+ reference->lineno);
+ fatalErrors++;
+ }
+ gsfinalImage[reference->address]=rel8/2;
+ break;
+ }
+ case REL_FFFF: {
+ int rel16 = symbol->address-(reference->pc & ~1);
+ if (rel16<-65536 || rel16>65534) {
+ fprintf (stderr,
+ "rel16 target for %s is out of range in module %s:%d\n",
+ reference->name, reference->module->name,
+ reference->lineno);
+ fatalErrors++;
+ }
+ gsfinalImage[reference->address]=(rel16/2)>>8;
+ gsfinalImage[reference->address+1]=rel16/2;
+ break;
+ }
+ case DIR_70FF:
+ gsfinalImage[reference->address] =
+ (gsfinalImage[reference->address]&~0x70) +
+ ((symbol->address>>4)&0x70);
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
+ case ABS_FFFF:
+ gsfinalImage[reference->address] = symbol->address>>8;
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
+ case ABS_FF:
+ gsfinalImage[reference->address] = symbol->address;
+ break;
+ case ABS_PC:
+ {
+ unsigned int address=
+ (gsfinalImage[reference->address]<<8) +
+ gsfinalImage[reference->address+1];
+ address += reference->module->offset[reference->segment->id];
+ address += segments[reference->segment->id].start;
+ gsfinalImage[reference->address] = address>>8;
+ gsfinalImage[reference->address+1] = address;
+ };
+ break;
+ default:
+ fprintf (stderr, "unsupported reference mode %d.\n",
+ reference->how);
+ fatalErrors++;
+ }
+ }
+ }
+ return 0;