** EXEHeader.asm	19/9/95
**
**			© 1995  Soyeb Aswat and NKH Software
**
**				Freeware
**
*******************************************************************************************************
*
*  Microsoft Windows New Executable 'NE' Examination utility
*
*******************************************************************************************************
**
** Open dos.library
** If open failed then
**   Print error message
**   Return
** Open file
** If open failed then
**   Print error message
**   Close dos.library
**   Return
** Seek to $18
**
** If (Current file pos word) < $40 then  ; Test if windows prog
**   Close file
**   Close dos.library
**   Return
**
** Seek to $3C          ; Goto start of win header
** Get word value
** Seek to word value above
**
** If (Current file pos word) <> 'NE' then ; Test if windows NE file
**   Close file
**   Close dos.library
**   Return
**
**  ;   Header length HeaderLen=(offset $20)+(Offset $20)-(WinHead)
**  ; WinHead=Start of windows header
** Allocate HeaderLen memory     ; Read in header
** Seek to WinHead
** Read HeaderLen bytes into buffer
**
** Print module name
**   Get address of resident-name table
**   Print first entry
** Print module description
**   Get address of non-resident name table
**   Print first entry
** Print linker version number (HEX)
** Print linker revision number (HEX)
** Print $0C flags data
**   Get word at $0C
**   If bit 0 set then SINGLE DATA
**   If bit 1 set then MULTIPLEDATA
**     else NOAUTODATA
**   If bit 11 set then self loading executable
**   If bit 15 set then file is a library module
** Print automatic data segment number
**   If 0 then print NOAUTODATA
**     else print segment number
** Print local heap size
**   If 0 then print No local allocation
**     else print heap size
** Print initial stack size
** Print CS:IP
** Print SS:SP
**   If SP=0 and DS=SS then SP= stacksize + data segment size (data seg size is in seg table)
**     else print SS:SP as normal
**
** Print offset to start of segment table
** Print number of entries in segment table
** Print contents of segment table
**   n=number of entries in segment table
**   REPEAT
**     Print segment number
**     Check offset 0 of each entry and
**	 If 0 then print "No data provided for this segment"
**	   else print size of segment in file
**     Print minimum allocation for this segment offset 6
**     Print flag meanings
**	 Print "Segment type"
**	 If bit 0 set then print DATA
**	   else print CODE
**	 If bit 1 set then print "Loader allocates memory for segment"
**	 If bit 2 set then print "Segment is loaded at load time"
**	 Print "Segment relocation"
**	 If bit 4 set then print "MOVEABLE"
**	   else print "FIXED"
**	 Print "Segment sharing"
**	 If bit 5 set then print "PURE or SHAREABLE"
**	   else print "IMPURE or NONSHAREABLE"
**	 Print "Segment load type"
**	 If bit 6 set then print "PRELOAD"
**	   else print "LOADONCALL"
**	 If bit 7 set then
**	   Print "Access type"
**	   If bit 0 set then print "READONLY"
**	     else print "EXECUTEONLY"
**	 If bit 8 set then print "Segment contains relocation data"
**	 If bit 12 set then print "Segment is discardable"
**     Decrement n
**     UNTIL n=0
**
** Print offset to resource table
** Print contents of resource table
**   Print rscAlignShift
**   Print rscTypes
**     REPEAT
**	 Print rtTypeID
**	   If rtTypeID < $8000 then 
**	     n=( rtTypeID + resource table base )
**	     Print n chars from above address+1
**	   If rtTypeID = $8000 + 1  then print "RT_CURSOR"
**	   If rtTypeID = $8000 + 2  then print "RT_BITMAP"
**	   If rtTypeID = $8000 + 3  then print "RT_ICON"
**	   If rtTypeID = $8000 + 4  then print "RT_MENU"
**	   If rtTypeID = $8000 + 5  then print "RT_DIALOG"
**	   If rtTypeID = $8000 + 6  then print "RT_STRING"
**	   If rtTypeID = $8000 + 7  then print "RT_FONTDIR"
**	   If rtTypeID = $8000 + 8  then print "RT_FONT"
**	   If rtTypeID = $8000 + 9  then print "RT_ACCELERATOR"
**	   If rtTypeID = $8000 + 10 then print "RT_RCDATA"
**	   If rtTypeID = $8000 + 12 then print "RT_GROUP_CURSOR"
**	   If rtTypeID = $8000 + 14 then print "RT_GROUP_ICON"
**	   If rtTypeID = $8000 + 16 then print "Version info?"
**	   ELSE Print "Unknown resource type",rtTypeID
**	 Print rtResourceCount
**	 Skip rtReserved (word)
**	 FOR n=1 to rtResourceCount
**	   Print rtNameInfo
**	     Print rnOffset
**	     Print rnLength
**	     Print rnFlags
**	       If bit 4 set then print "MOVEABLE"
**	       If bit 5 set then print "PURE"
**	       If bit 6 set then print "PRELOAD"
**	     Print rnID
**	       If rnID >= $8000 then print rnID-$8000
**	       ELSE
**		 n=( rnID + resource table base )
**	         Print n chars from above address+1
**	     Skip rnHandle (word)
**	     Skip rnUsage (word)
**	   END ; FOR
**	 UNTIL rscEndTypes ; ie. next byte = 0 ; REPEAT for printing rscTypes
**
** Print resident-name table
**   Get address of resident-name table
**   Skip first entry
**     Get length of string
**     Add to pointer
**     Add 2 to pointer to skip ordinal
**   WHILE next byte !=
**     Get length of string
**     Skip pointer past string
**     Print string
**     Print ordinal
**     END ; WHILE
**
** Print module-reference and imported-name tables
**   Print number of entries in module-reference table
**   Get address of imported-name table
**   FOR n=1 to number of entries in module-reference table
**     Get length of string
**     Get address of string
**     Print string
**     END ; FOR
**
** Print entry table
**   Test length of entry table
**   If length != 0 then
**     Get address of entry table
**     REPEAT
**	 Get number of entries in bundle
**	 Get bundle type
**	 Add 2 to pointer
**	 If bundle type = 0 then		; Null entry
**	   Print "Null entries : ",entries
**	   Add entries to entry counter.
**	 If bundle type = $FE then		; Constant pointer
**	   Print "Constant pointer"
**	   FOR n=1 to entries in bundle
**	     Print "Entry ",entry counter
**	     Print "Offset  :  ",EntryConstValue
**	     If bit 0 of EntryFixFlags = 1 then
**	       Print " Exported "
**	     If bit 1 of EntryFixFlags = 1 then
**	       Print "SINGLEDATA"
**	     Add 3 to pointer
**	     END ; FOR
**	 If bundle type = $FF then		; Movable segment
**	   Print "Movable segment records : ",entries in bundle," entries."
**	   FOR n=1 to entries in bundle
**	     Print "Entry ",entry counter
**	     Print "Segment : ",EntryMoveSegment
**	     Print "Offset  : ",EntryMoveOffset
**	     If bit 0 of EntryMoveFlags = 1 then
**	       Print " Exported "
**	     If bit 1 of EntryMoveFlags = 1 then
**	       Print " Global"
**	     Add 6 to pointer
**	     END ; FOR
**	 ELSE					; Fixed segment
**	   Print "Fixed segment records : ",entries in bundle," entries.    Segment : ",bundle type
**	   FOR n=1 to entries in bundle
**	     Print "Entry ",entry counter
**	     Print "Offset  : ",EntryFixOffset
**	     If bit 0 of EntryFixFlags = 1 then
**	       Print " Exported "
**	     If bit 1 of EntryFixFlags = 1 then
**	       Print "SINGLEDATA"
**	     Add 3 to pointer
**	     END ; FOR
**	 UNTIL next byte = 0
**
** Print segment relocations
**   Print "Segment relocations"
**   Initialize segment counter
**   Get address of segment table
**   Get number of entries in segment table
**   FOR n = 1 to entries in segment table
**     If this segment contains relocation data then
**	 Print "Relocations for segment ",segment counter
**	 Goto position of segment in file
**	 Move an extra segment length bytes
**	 Get intel word at that address (items in table)
**	 Allocate items in table * 8 bytes of ram
**	 If allocation UNsuccesful then
**	   Print "Out of memory"
**	   rts
**	 Read items in table * 8 bytes into allocated buffer
**	 If read failed then
**	   Print "Read from file failed!"
**	   rts
**	 Print "type    offset       target"
**	 FOR x = 1 to items in table
**	   If RelocAddrType = 0 then
**	     Print "LoByte  "
**	   If RelocAddrType = 2 then
**	     Print "Select  "
**	   If RelocAddrType = 3 then
**	     Print "PTR     "
**	   If RelocAddrType = 5 then
**	     Print "OFFS    "
**	   If RelocAddrType = 11 then
**	     Print "PTR-48  "
**	   If RelocAddrType = 13 then
**	     Print "OFFS-32 "
**	   else print "Unknown relocation type. Send me this file to df114@city.ac.uk read docs!!!!"
**	     rts
**
**	   Print RelocOffset
**	   If RelocType = 0 then		; Internal reference
**	     If RelocB4 = $FF then
**	       Print "Entry ",RelocB6
**	     else
**	       Print RelocB4,":",RelocB6		; Segment:Offset are the wrong way round!
**	   If RelocType = 1 then		; Imported ordinal
**	     (RelocB4 - 1)*2
**	     Add offset to mod-ref table
**	     Add that word to offset of imp-name table
**	     Print that byte many bytes at that addr+1
**	     Print ".",RelocB6
**	   If RelocType = 2 then		; Imported name
**	     (RelocB4 - 1)*2
**	     Add offset to mod-ref table
**	     Add that word to offset of imp-name table
**	     Print that byte many bytes at that addr+1
**	     Print "."
**	     RelocB6 + offset to imp-name table
**	     Print that byte many bytes at that addr+1
**	   If RelocType = 3 then		; OSFIXUP
**	     Print "OSFIXUP Send me this file to df114@city.ac.uk read docs!!!!"
**	     rts
**	   If RelocType = 5 then		; Additive?
**	     (RelocB4 - 1)*2
**	     Add offset to mod-ref table
**	     Add that word to offset of imp-name table
**	     Print that byte many bytes at that addr+1
**	     Print ".",RelocB6
**	   else
**	     Print "Unknown relocation type send me this file to df114@city.ac.uk read docs!!!!"
**
**	   Add 8 to pointer			; Skip to next entry in relocation table
**	   END ; FOR
**	 Deallocate memory just used
**	 Add 8 to pointer'			; Skip to next entry in segment table
**	 END ; FOR

** Close file
** Close dos.library
** Return


		INCLUDE  "work:languages/devpac/amiga.lib.inc"
**		INCLUDE  "exec/exec.i"
		INCLUDE  "dos/dos.i"
   
AbsExecBase	EQU	4
AnyMemoryType	EQU	0
NewLine		EQU	10
NULL		EQU	0

** Locations in the file

AutoDataSegNum		EQU	$0E
DataOffset		EQU	$00
DosHeaderValid		EQU	$18
EntryBndlNum		EQU	$00	; Entry table	Number of entries in this bundle
EntryBndlTyp		EQU	$01	;		Bundle type
EntryConstFlags		EQU	$00	;		Offset to flags for entry type constant
EntryConstValue		EQU	$01	;		Offset to value for entry type constant
EntryFixFlags		EQU	$00	;		Flags for fixed segment
EntryFixOffset		EQU	$01	;		Offset for fixed segment
EntryLength		EQU	$06	;	Length of entry table in entries (in windows header)
EntryMoveFlags		EQU	$00	;		Flags for movable segment
EntryMoveOffset		EQU	$04	;		Offset for movable segment
EntryMoveSeg		EQU	$03	;		Segment number for movable segment
EntryOffset		EQU	$04	;	Offset to entry table relative to start of windows header
FileFlags		EQU	$0C
FileSegLength		EQU	$02
ImpTableOffset		EQU	$2A
ImpNameOffset		EQU	$2A
InitCSIP		EQU	$14
InitLocalHeap		EQU	$10
InitSSSP		EQU	$18
InitStackSize		EQU	$12
LinkerRevisionNum	EQU	$02
LinkerVersionNum	EQU	$03
ModRefOffset		EQU	$28
ModTableEntries		EQU	$1E
NonResNamTabOffset	EQU	$2C
NonResNamTableSize	EQU	$20
rnFlags			EQU	$04
rnID			EQU	$06
rnLength		EQU	$02
rnOffset		EQU	$00
rscAlignShift		EQU	$00
RelocAddrType		EQU	$00
RelocB4			EQU	$04
RelocB6			EQU	$06
RelocOffset		EQU	$02
RelocType		EQU	$01
ResNameTabOffset	EQU	$26
RscTableOffset		EQU	$24
SegAllocSize		EQU	$06
SegFlags		EQU	$04
SegmentPos		EQU	$00
SegmentLen		EQU	$02
SegTableEntryNum	EQU	$1C
SegTableOffset		EQU	$22
ShiftCount		EQU	$32
WinHeaderOffset		EQU	$3C



** Temporary storage

TempStoreSize	EQU	256		; Size of the temporary storage buffer

DosBase		EQU	4*0
FileHandle	EQU	4*1
HeaderAddress	EQU	4*2
HeaderLen	EQU	4*3
HeaderOffset	EQU	4*4
OutputHandle	EQU	4*5
RelocBufferAddr	EQU	4*6
RelocBufferLen	EQU	4*7
StackEquation	EQU	4*8
TempBufferLen	EQU	4*9
TempBuffer	EQU	4*10		; *MUST* always be last!




		SECTION  code,CODE

; Allocate temporary storage buffer

	move.l	d0,d2			; Save length of command line argument
	move.l	a0,a2			; Save pointer to command line argument

	move.l	AbsExecBase,a6		; Get exec base address
	move.l	#TempStoreSize,d0	; Allocate Temp store bytes of ram
	add.l	d2,d0			; Add length of command line argument
	move.l	d0,d3			; Save buffer length
	move.l	#AnyMemoryType,d1	; Any type of memory
	jsr	_LVOAllocMem(a6)	; Allocate the memory
	tst.l	d0			; Was memory allocated?
	beq	TempBufNoAlloc		; Temp buffer was not allocated
	move.l	d0,a5			; Store address in a5

	move.l	d3,TempBufferLen(a5)	; Save length of temp buffer

; Open dos.library

	clr.l	d0			; d0 = any version
	lea	DosLibName,a1		; a0 = * "dos.library"
	jsr	_LVOOpenLibrary(a6)	; Open dos.library
	tst.l	d0			; Did dos lib open OK?
	beq	DosNotOpen		; Goto dos lib not opened OK
	move.l	d0,DosBase(a5)		; Save dos base address
	move.l	d0,a6			; Put dos base address in a6

	jsr	_LVOOutput(a6)		; Get output handle
	move.l	d0,OutputHandle(a5)	; Save output handle

; Open file

	lea	TempBuffer(a5),a0	; Get address of temp buffer
	move.l	a0,a4			; Save a copy of buffer address
	subq.l	#1,d2			; Get the right length of filename
	
ReadFileName
	move.b	(a2)+,(a0)+		; Get a command line character
	
	dbeq	d2,ReadFileName		; Loop until all characters read
	move.b	#NULL,-(a0)		; Terminate string with null

	move.l	a4,d1			; And place in d1 (argument)
	move.l	#MODE_OLDFILE,d2	; Open file for reading
	jsr	_LVOOpen(a6)		; Open file
	tst.l	d0			; Did file open OK?
	beq	FileNotOpenOK		; Goto file not open error
	move.l	d0,FileHandle(a5)	; Save open file handle

; Seek to is dos header a valid windows header?

	move.l	#DosHeaderValid,d2	; Position to go to
	bsr	SeekTo			; Seek

; If (current file position word) < $40 then quit

	bsr	ReadIntelWord		; Read word at position
	cmp.w	#$40,d2			; Is less than $40?
	blt	NotWindowsEXE		; Goto wrong file type error

; Seek to offset to windows header

	move.l	#WinHeaderOffset,d2	; Position to go to
	bsr	SeekTo			; Seek there

; Get word value

	bsr	ReadIntelWord		; Read word at that position
	clr.l	d4			; Clear scratch register
	move.w	d2,d4			; d4 = offset to start of header
	move.l	d4,d2			; Clear high word
	move.l	d2,HeaderOffset(a5)	; Save offset

; Seek to word value above

	bsr	SeekTo			; Seek to start of header

; If (current file pos word) <> "NE" then quit

	bsr	ReadIntelWord		; Get word at start of header
	cmp.w	#$454E,d2		; Is it "NE"? The code $454E is "EN"
					; because ReadWord reverses the bytes
	bne	NotWindowsEXE		; Quit if not New Executable

; HeaderLen = (bytes in non-resident name table)+(offset to non-resident name table)-(WinHeaderOffset)

	move.l	#NonResNamTableSize,d2	; Offset $20
	add.l	d4,d2			; Add base
	bsr	SeekTo			; Seek to $20
	bsr	ReadIntelWord		; Read word
	clr.l	d5			; Clear scratch register
	move.w	d2,d5			; Move ($20) to d5
	move.l	#NonResNamTabOffset,d2	; Offset $2C
	add.l	d4,d2			; Add base
	bsr	SeekTo			; Seek to $2C
	bsr	ReadIntelWord		; Read low word at $2C
	move.w	d2,d6			; Save word
	bsr	ReadIntelWord		; Read high word at $2C
	swap	d2			; Place high byte in correct position
	move.w	d6,d2			; Construct longword
	add.l	d2,d5			; d5 = (offset $20)+(offset$2C)
	sub.l	d4,d5			; d5 = ($20)+($2C)-(WinHeaderOffset)
	move.l	d5,HeaderLen(a5)	; Store HeaderLen

;	bra	CloseFileAndDosLib;testing

; Allocate HeadLen bytes of memory

	move.l	d5,d0			; Put HeadLen into d0
	move.l	#AnyMemoryType,d1	; Any memory type
	move.l	AbsExecBase,a6		; Get ExecBase
	jsr	_LVOAllocMem(a6)	; Allocate the memory
	tst.l	d0			; Was memory allocated?
	beq	MemoryNotAllocated	; Goto not enough memory error
	move.l	d0,a4			; Store address of allocated memory
	move.l	d0,HeaderAddress(a5)	; Store alloced mem addr permanantly

; Seek to start of win header

	move.l	DosBase(a5),a6		; Get dos lib base address
	move.l	d4,d2			; Get win header base address
	bsr	SeekTo			; Goto start of header

; Read above bytes into buffer

	move.l	FileHandle(a5),d1	; Get file handle
	move.l	a4,d2			; Put memory block address in d2
	move.l	d5,d3			; HeadLen bytes to be read
	jsr	_LVORead(a6)		; Read header into buffer
	cmp.l	d5,d0			; Was whole header read?
	bne	ReadFailed		; Goto read failed


** Main section (prints everything) *******************************************************************

	bsr	PrintFileDetails	; Prints details about the whole file

	bsr	PrintSegmentTable	; Print the segment table

	bsr	PrintResourceTable	; Well isn't it obvious?	Print resource table

	bsr	PrintResNameTable	; Print resident name table

	bsr	PrintModImpTables	; Print module-reference and imported-name tables

	bsr	PrintNonResNameTable	; Print non-resident name table

	bsr	PrintEntryTable		; Print the entry table

	bsr	PrintRelocTabs		; Print segment relocation tables

******************************************************************************************************

; Clean up before returning to dos

	move.l	AbsExecBase,a6		; Get exec base
	move.l	a6,a4			; Keep copy of exec base
	move.l	HeaderAddress(a5),a1	; Get address of header
	move.l	HeaderLen(a5),d0	; Get headers length
	jsr	_LVOFreeMem(a6)		; Free memory

	lea	FinishMSG,a0		; Get address of closing message
	move.l	FinishMSGLen,d3		; Get length of finish message
	bra	CloseFileAndDosLibPrintMSG	; Print closing message cleanup and return to dos


*******************************************************************************************************
*******************************************************************************************************
*******************************************************************************************************
*******************************************************************************************************

**----------------------------------------
**
** Print file details
**
**----------------------------------------

PrintFileDetails

; Print module name							Print module name

	lea	ModuleNameMSG,a0	; Get address of message
	move.l	ModuleNameMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.w	ResNameTabOffset(a4),d0	; Get offset to res nam table	  Get address of res nam table
	rol.w	#8,d0			; Position bytes correctly
	lea	(a4,d0.w),a0		; Get address of entry table
	clr.l	d3			; Clear length of module name	  Print first entry
	move.b	(a0)+,d3		; Get length of message
	bsr	PrintMSG		; Print module name

; Print module description						Print module description

	lea	ModuleDescribeMSG,a0	; Get address of message
	move.l	ModuleDescribeMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	NonResNamTabOffset(a4),d0	; Get offset to non res nam table	  Get address of non res nam table
	rol.w	#8,d0			; Position bytes correctly
	swap	d0			; Get low word
	rol.w	#8,d0			; Position bytes correctly
	sub.l	HeaderOffset(a5),d0	; Get offset to non-res table
	lea	(a4,d0.w),a0		; Get address of entry table
	clr.l	d3			; Clear length of module name	  Print first entry
	move.b	(a0)+,d3		; Get length of message
	bsr	PrintMSG		; Print module name

; Print linker version number

	lea	VersionNumMSG,a0	; Get address of message
	move.l	VersionNumMSGLen,d3	; Get message length
	bsr	PrintMSG		; Print message
	
	move.b	LinkerVersionNum(a4),d3	; Get linker version number
	bsr	ConvertBin2ASCII	; Convert to ASCII digits
	move.b	#"$",TempBuffer(a5)	; Put $ for hexadecimal numbe r
	move.b	d0,TempBuffer+1(a5)	; Store Hi digit for printing
	move.b	d1,TempBuffer+2(a5)	; Store Lo digit for printing
	move.b	#NewLine,TempBuffer+3(a5)	; New line
	move.l	#4,d3			; 4 characters to be printed
	lea	TempBuffer(a5),a0	; Get address of string
	bsr	PrintMSG		; Print the MSG

; Print linker revision number

	lea	RevisionNumMSG,a0	; Get address of message
	move.l	RevisionNumMSGLen,d3	; Get message length
	bsr	PrintMSG		; Print message
	
	move.b	LinkerRevisionNum(a4),d3; Get linker revision number
	bsr	ConvertBin2ASCII	; Convert to ASCII digits
	move.b	#"$",TempBuffer(a5)	; Put $ for hexadecimal number
	move.b	d0,TempBuffer+1(a5)	; Store Hi digit for printing
	move.b	d1,TempBuffer+2(a5)	; Store Lo digit for printing
	move.b	#NewLine,TempBuffer+3(a5)	; New line
	move.l	#4,d3			; 4 characters to be printed
	lea	TempBuffer(a5),a0	; Get address of string
	bsr	PrintMSG		; Print the MSG

; Print $0C flags data

	lea	ExecutableTypeMSG,a0	; Get address of message
	move.l	ExecutableTypeMSGLen,d3	; Get message length
	bsr	PrintMSG		; Print message

	lea	NormalExecutableMSG,a0	; Get address of normal executable message
	move.l	NormalExecutableMSGLen,d3	; Get length of message
	
	btst	#7,FileFlags+1(a4)	; Test bit 15 of file flags
	beq	NormalExecutable	; If bit is zero then normal executable
	
	lea	LibraryModuleMSG,a0	; File is a library module
	move.l	LibraryModuleMSGLen,d3	; Get length of above message

NormalExecutable
	bsr	PrintMSG		; Print file type message

	lea	FileDataModelMSG,a0	; Get address of message
	move.l	FileDataModelMSGLen,d3	; Get message length
	bsr	PrintMSG		; Print message

	lea	SingleDataModelMSG,a0	; Get address of message
	move.l	SingleDataModelMSGLen,d3	; Get message length

	btst	#0,FileFlags(a4)	; Test bit 0 of $0C
	bne	PrintDataModel		; If set then file is SINGLEDATA

	lea	MultipleDataModelMSG,a0	; Get address of message
	move.l	MultipleDataModelMSGLen,d3	; Get message length

	btst	#1,FileFlags(a4)	; Test bit 1 of $0C
	bne	PrintDataModel		; If set then file is MULTIPLEDATA
	
	lea	NoAutoDataModelMSG,a0	; Get address of message
	move.l	NoAutoDataModelMSGLen,d3	; Get message length

PrintDataModel
	bsr	PrintMSG		; Print message

	lea	IsSelfLoadingMSG,a0	; Get address of message
	move.l	IsSelfLoadingMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	NoMSG,a0		; Get address of message
	move.l	NoMSGLen,d3		; Get length of message

	btst	#3,FileFlags+1(a4)	; Test if self loading EXE
	beq	NotSelfLoading		; Jump if not self loading EXE
	lea	YesMSG,a0		; Else executable is self loading
	move.l	YesMSGLen,d3		; Get length of message

NotSelfLoading
	bsr	PrintMSG		; Print the message

; Print auto data segment number. If file is NOAUTODATA then print that

	lea	AutoDataSegMSG,a0	; Get address of message
	move.l	AutoDataSegMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	NoAutoDataModelMSG,a0	; Get address of message
	move.l	NoAutoDataModelMSGLen,d3	; Get message length
	btst	#3,FileFlags+1(a4)	; Test if self loading EXE
	bne	PrintAutoSegNum		; If it is then print the message

	lea	AutoDataSegNum(a4),a3	; Get pointer to number
	bsr	PrePrintSingleIntelWord	; Prepare the number

PrintAutoSegNum
	bsr	PrintMSG		; Print the message

; Print initial local heap size, if 0 then print no local allocation

	lea	InitLocalHeapMSG,a0	; Get address of message
	move.l	InitLocalHeapMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	InitLocalHeap(a4),a3	; Get address of number
	lea	NoLocalHeapMSG,a0	; Get no Alloc message address
	move.l	NoLocalHeapMSGLen,d3	; Get message length
	tst.w	(a3)			; Is there a heap?
	beq	NoLocalHeap		; If no local heap then print message

	bsr	PrePrintSingleIntelWord	; Prepare heap size for printing

NoLocalHeap
	bsr	PrintMSG
	
; Print initial stack size

	lea	InitStackSizeMSG,a0	; Get address of message
	move.l	InitStackSizeMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	InitStackSize(a4),a3	; Get address of number
	bsr	PrePrintSingleIntelWord	; Prepare the stack size for printing
	bsr	PrintMSG		; Print the stack size

; Print CS:IP

	lea	InitCSIPMSG,a0		; Get address of message
	move.l	InitCSIPMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	InitCSIP(a4),a3		; Get address of number
	bsr	PrintSegOffset		; Print CS:IP

; Print SS:SP if SP=0 and SS=DS then SP= stacksize + data segment size

	lea	StackAddressMSG,a0	; Get address of message
	move.l	StackAddressMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	InitSSSP(a4),a3		; Get address of SS:SP

;		Note the output below and that of MAPWIN etc. does not agree so I have decided to
;		remove it for the moment. See docs!

;	tst.w	(a3)			; Is SP=0?
;	bne	NormalStack		; If not then print normally
;	clr.l	d0			; Clear d0 for later use
;	move.w	InitSSSP+2(a4),d0	; Get SS
;	cmp.w	AutoDataSegNum(a4),d0	; Is SS=DS?
;	bne	NormalStack		; If not then print normally
;
;	lea	StackEquation(a5),a3	; Temporary equation holder
;	clr.l	d1			; Clear d1 for later use
;	move.b	InitSSSP+3(a4),d1	; Get high byte of SS
;	move.b	d1,$03(a3)		; Save SS high for later printing
;	lsl.w	#8,d1			; Position high byte correctly
;	move.b	InitSSSP+2(a4),d1	; Get low byte of SS
;	move.b	d1,$02(a3)		; Save SS low for later printing
;	subq.w	#1,d1			; Decrement it
;	lsl.l	#3,d1			; Multiply by segment table entry size (8 bytes)
;	move.b	SegTableOffset+1(a4),d0	; Get high byte of seg table offset
;	lsl.w	#8,d0			; Position high byte correctly
;	move.b	SegTableOffset(a4),d0	; Get low byte of seg table offset
;	add.l	d0,d1			; Add offset to start of segment table
;	move.b	SegAllocSize+1(a4,d1),d0; Get high byte of segment allocation size
;	lsl.w	#8,d0			; Position high byte correctly
;	move.b	SegAllocSize(a4,d1),d0	; Get low byte of segment allocation size
;	move.b	InitStackSize+1(a4),d1	; Get high byte of stack size
;	lsl.w	#8,d1			; Position high byte correctly
;	move.b	InitStackSize(a4),d1	; Get low byte of stack size
;	add.w	d0,d1			; d1=SP
;	move.b	d1,$00(a3)		; Save low byte of SP
;	lsr.w	#8,d1			; Get high byte of SP
;	move.b	d1,$01(a3)		; Save high byte of SP
;
NormalStack
	bsr	PrintSegOffset		; Print SS:SP
	rts				; Finish printing file data


**--------------------------------------------
**
** Print segment table
**
**--------------------------------------------

; Print offset to start of segment table

PrintSegmentTable
	lea	SegTableOffsetMSG,a0	; Get address of message		Print offset to start of segment table
	move.l	SegTableOffsetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print message

	lea	SegTableOffset(a4),a3	; Get address of offset
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	bsr	PrintMSG		; Print the number

; Print number of entries in segment table

	lea	SegTableEntryNumMSG,a0	; Get address of message		Print number of entries in segment table
	move.l	SegTableEntryNumMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print message

	lea	SegTableEntryNum(a4),a3	; Get address of number of entries
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	bsr	PrintMSG		; Print the number

; Print contents of segment table

	clr.l	d0			; Clear d0
	move.w	SegTableOffset(a4),d6	; Get offset to table			d6=offset to seg table this is for later
	rol.w	#8,d6			; Position high byte correctly
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	move.w	SegTableEntryNum(a4),d7	; Get number of entries			d7=n this is for the FOR later
	rol.w	#8,d7			; Position high byte correctly
;	subq.w	#1,d7			; Segment number starts with 1

	move.w	#1,d5			; Counter for segment number
	
PrintSegmentTableEntry			;					REPEAT
	lea	SegmentNumberMSG,a0	; Get address of message		  Print segment number
	move.l	SegmentNumberMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.w	d5,d0			; d0=segment number for printing
	move.b	d0,StackEquation(a4)	; Put low byte of seg num for printing
	lsr.w	#8,d0			; Get high byte
	move.b	d0,StackEquation+1(a4)	; Put high byte of seg num for printing
	lea	StackEquation(a4),a3	; Get address of number for printing
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	bsr	PrintMSG		; Print the number

	lea	NoDataInSegmentMSG,a0	; Get address of message		  Check offset 0 of each entry and
	move.l	NoDataInSegmentMSGLen,d3; Get length of message
	tst.w	DataOffset(a4,d6)	; Is there any data?
	beq	NoDataInSegment		; Print message	if 0			    If 0 then print "No data provided for this segment"

	lea	FileSegLengthMSG,a0	; Get address of message		      else print size of segment in file
	move.l	FileSegLengthMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	SixtyFourKMSG,a0	; Get address of message
	move.l	SixtyFourKMSGLen,d3	; Get length of message
	lea	FileSegLength(a4,d6),a3	; Get address of number
	tst.w	(a3)			; Is it zero? Which means 64k allocated
	beq	NoDataInSegment		; If 64k size then print that
	bsr	PrePrintSingleIntelWord	; Prepare file segment length for printing

NoDataInSegment
	bsr	PrintMSG		; Print message

MinAllocForSegment
	lea	MinAllocForSegMSG,a0	; Get address of message		  Print minimum allocation for this segment
	move.l	MinAllocForSegMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	SixtyFourKMSG,a0	; Get address of message
	move.l	SixtyFourKMSGLen,d3	; Get length of message
	lea	SegAllocSize(a4,d6),a3	; Get address of number
	tst.w	(a3)			; Is it zero? Which means 64k allocated
	beq	AllocWholeSegment	; If 64k size then print that
	bsr	PrePrintSingleIntelWord	; Prepare file segment length for printing

AllocWholeSegment
	bsr	PrintMSG		; Print message

	lea	SegmentTypeMSG,a0	; Get address of message	Print "Segment type"
	move.l	SegmentTypeMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	lea	DataMSG,a0		; Get address of message	If bit 0 of flag set then segment is type data
	move.l	DataMSGLen,d3		; Get length of message
	btst	#0,SegFlags(a4,d6)	; Test bit 0 of segment flags
	bne	PrintSegmentType	; If set then print type data
	lea	CodeMSG,a0		; Get address of message	  else print type code
	move.l	CodeMSGLen,d3		; Get length of message

PrintSegmentType
	bsr	PrintMSG		; Print the message

	btst	#1,SegFlags(a4,d6)	; Test bit 1 of seg flags	If bit 1 set then print "Loader allocates mem..."
	beq	NoLoaderAllocation	; If zero then no allocation
	lea	LoaderAllocMSG,a0	; Get address of message
	move.l	LoaderAllocMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

NoLoaderAllocation

	btst	#2,SegFlags(a4,d6)	; Test bit 2 of seg flags	If bit 2 set then print "Segment is loaded..."
	beq	SegmentNotLoaded	; If zero then segment not loaded
	lea	SegmentLoadedMSG,a0	; Get address of message
	move.l	SegmentLoadedMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

SegmentNotLoaded

	lea	MoveableMSG,a0		; Get address of message	If bit 4 of flag set then segment is moveable
	move.l	MoveableMSGLen,d3	; Get length of message
	btst	#4,SegFlags(a4,d6)	; Test bit 4 of segment flags
	bne	PrintSegmentReloc	; If set then print type moveable
	lea	FixedMSG,a0		; Get address of message	  else print type fixed
	move.l	FixedMSGLen,d3		; Get length of message

PrintSegmentReloc
	bsr	PrintMSG		; Print the message

	lea	ShareMSG,a0		; Get address of message	If bit 5 of flag set then segment is pure or sharable
	move.l	ShareMSGLen,d3		; Get length of message
	btst	#5,SegFlags(a4,d6)	; Test bit 5 of segment flags
	bne	PrintSegmentSharing	; If set then print type shareable
	lea	NonShareMSG,a0		; Get address of message	  else print type non shareable
	move.l	NonShareMSGLen,d3	; Get length of message

PrintSegmentSharing
	bsr	PrintMSG		; Print the message

	lea	PreLoadMSG,a0		; Get address of message	If bit 6 of flag set then preload segment
	move.l	PreLoadMSGLen,d3	; Get length of message
	btst	#6,SegFlags(a4,d6)	; Test bit 6 of segment flags
	bne	PrintSegmentLoadType	; If set then print type preload
	lea	LoadOnCallMSG,a0	; Get address of message	  else print type load on call
	move.l	LoadOnCallMSGLen,d3	; Get length of message

PrintSegmentLoadType
	bsr	PrintMSG		; Print the message

	btst	#7,SegFlags(a4,d6)	; Test bit 7 of segment flags	If bit 7 set then
	beq	RandomAccess		; Random access
	lea	ReadOnlyMSG,a0	; Get address of message
	move.l	ReadOnlyMSGLen,d3	; Get length of message
	btst	#0,SegFlags(a4,d6)	; Test bit 0 of segment flags	  If bit 0 set then print "READONLY"
	bne	ReadOnlySegment		; Print "READONLY" if data seg
	lea	ExecuteOnlyMSG,a0	; Get address of message	    else print "EXECUTEONLY"
	move.l	ExecuteOnlyMSGLen,d3	; Get length of message

ReadOnlySegment
	bsr	PrintMSG		; Print the message

RandomAccess				; Come here for no access restrictions

	btst	#0,SegFlags+1(a4,d6)	; Test bit 8 of segment flags	If bit 8 set then print "Segment contains relocation data"
	beq	NoRelocation		; Jump if bit not set
	lea	SegRelocationMSG,a0	; Get address of message
	move.l	SegRelocationMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
NoRelocation

	btst	#0,SegFlags+1(a4,d6)	; Test bit 8 of segment flags	If bit 8 set then print "Segment contains relocation data"
	beq	NoDiscard		; Jump if bit not set
	lea	SegDiscardMSG,a0	; Get address of message
	move.l	SegDiscardMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
NoDiscard


	addq.l	#8,d6			; Bump to next entry
	addq.w	#1,d5			; Increment the segment counter
	subq.w	#1,d7			; Decrement the loop counter
	bne	PrintSegmentTableEntry	; Loop if not zero
	rts				; Finish printing segment table


**---------------------------------------
**
** Print resource table
**
**---------------------------------------

PrintResourceTable
	lea	RscTableOffsetMSG,a0	; Get address of message	; Print offset to resource table
	move.l	RscTableOffsetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	RscTableOffset(a4),a3	; Get pointer to offset
	move.w	(a3),d7			; Save offset of resource table
	rol.w	#8,d7			; Swap bytes for intel word
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	bsr	PrintMSG		; Print the number

; Print contents of resource table

	lea	rscAlignShiftMSG,a0	; Get address of message	;   Print rscAlignShift
	move.l	rscAlignShiftMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	rscAlignShift(a4,d7.w),a3	; Get pointer to shift count
	move.w	(a3),d4			; Get shift count
	rol.w	#8,d4			; Position bytes correctly
	cmp.w	#31,d4			; Check validity
	bgt	NoResourceTable		; Jump if out of bounds
	bsr	PrePrintSingleIntelWord	; Prepare number for printing
	bsr	PrintMSG		; Print the number
	move.w	d7,d6			; Get pointer to table
	addq.w	#2,d6			; Increment pointer in

; Print rscTypes

PrintrscTypes								;     REPEAT
	lea	ResourceTypeMSG,a0	; Get address of message		  Print "Resource type : "
	move.l	ResourceTypeMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	clr.l	d0			; Put d0 to zero
	move.w	(a4,d6.w),d0		; Get rtTypeID
	rol.w	#8,d0			; Position bytes correctly
 	move.l	d0,a0			; Get offset of string			  If rtTypeID < $8000 then
	add.w	d7,a0			; Add offset of resource table
	clr.l	d3			; Clear d3
	add.l	a4,a0			; Add base of header
	move.b	(a0)+,d3		; Get length of name
	cmp.w	#$8000,d0		; Compare with $8000			    n=(rtTypeID+resource table base)
	blt	PrintTherscType		; Print if less than			    Print n chars from above address+1

	lea	RT_CursorMSG,a0		; Get address of message		  If rtTypeID = $8000 + 1  then print "RT_CURSOR"
	move.l	RT_CursorMSGLen,d3	; Get length of message
	cmp.w	#$8000+1,d0		; Compare with $8000+1
	beq	PrintTherscType		; Print if equal

	lea	RT_BitmapMSG,a0		; Get address of message		  If rtTypeID = $8000 + 2  then print "RT_BITMAP"
	move.l	RT_BitmapMSGLen,d3	; Get length of message
	cmp.w	#$8000+2,d0		; Compare with $8000+2
	beq	PrintTherscType		; Print if equal

	lea	RT_IconMSG,a0		; Get address of message		  If rtTypeID = $8000 + 3  then print "RT_ICON"
	move.l	RT_IconMSGLen,d3	; Get length of message
	cmp.w	#$8000+3,d0		; Compare with $8000+3
	beq	PrintTherscType		; Print if equal

	lea	RT_MenuMSG,a0		; Get address of message		  If rtTypeID = $8000 + 4  then print "RT_MENU"
	move.l	RT_MenuMSGLen,d3	; Get length of message
	cmp.w	#$8000+4,d0		; Compare with $8000+4
	beq	PrintTherscType		; Print if equal

	lea	RT_DialogMSG,a0		; Get address of message		  If rtTypeID = $8000 + 5  then print "RT_DIALOG"
	move.l	RT_DialogMSGLen,d3	; Get length of message
	cmp.w	#$8000+5,d0		; Compare with $8000+5
	beq	PrintTherscType		; Print if equal

	lea	RT_StringMSG,a0		; Get address of message		  If rtTypeID = $8000 + 6  then print "RT_STRING"
	move.l	RT_StringMSGLen,d3	; Get length of message
	cmp.w	#$8000+6,d0		; Compare with $8000+6
	beq	PrintTherscType		; Print if equal

	lea	RT_FontDirMSG,a0	; Get address of message		  If rtTypeID = $8000 + 7  then print "RT_FONTDIR"
	move.l	RT_FontDirMSGLen,d3	; Get length of message
	cmp.w	#$8000+7,d0		; Compare with $8000+7
	beq	PrintTherscType		; Print if equal

	lea	RT_FontMSG,a0		; Get address of message		  If rtTypeID = $8000 + 8  then print "RT_FONT"
	move.l	RT_FontMSGLen,d3	; Get length of message
	cmp.w	#$8000+8,d0		; Compare with $8000+8
	beq	PrintTherscType		; Print if equal

	lea	RT_AcceleratorMSG,a0	; Get address of message		  If rtTypeID = $8000 + 9  then print "RT_ACCELERATOR"
	move.l	RT_AcceleratorMSGLen,d3	; Get length of message
	cmp.w	#$8000+9,d0		; Compare with $8000+9
	beq	PrintTherscType		; Print if equal

	lea	RT_RCDataMSG,a0		; Get address of message		  If rtTypeID = $8000 + 10 then print "RT_RCDATA"
	move.l	RT_RCDataMSGLen,d3	; Get length of message
	cmp.w	#$8000+10,d0		; Compare with $8000+10
	beq	PrintTherscType		; Print if equal

	lea	RT_Group_CursorMSG,a0	; Get address of message		  If rtTypeID = $8000 + 12 then print "RT_GROUP_CURSOR"
	move.l	RT_Group_CursorMSGLen,d3; Get length of message
	cmp.w	#$8000+12,d0		; Compare with $8000+12
	beq	PrintTherscType		; Print if equal

	lea	RT_Group_IconMSG,a0	; Get address of message		  If rtTypeID = $8000 + 14 then print "RT_GROUP_ICON"
	move.l	RT_Group_IconMSGLen,d3	; Get length of message
	cmp.w	#$8000+14,d0		; Compare with $8000+14
	beq	PrintTherscType		; Print if equal

	lea	RT_VersionInfoMSG,a0	; Get address of message		  If rtTypeID = $8000 + 16 then print "Version info?"
	move.l	RT_VersionInfoMSGLen,d3	; Get length of message
	cmp.w	#$8000+16,d0		; Compare with $8000+16
	beq	PrintTherscType		; Print if equal

	lea	RT_UnkRscTypeMSG,a0	; Get address of message		  ELSE Print "Unknown resource type",rtTypeID
	move.l	RT_UnkRscTypeMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	(a4,d6.w),a3		; Get address of number
	bsr	PrePrintSingleIntelWord	; Prepare number for printing

PrintTherscType
	bsr	PrintMSG		; Print the message
	addq.w	#2,d6			; Increment pointer

	lea	rtResourceCountMSG,a0	; Get address of message		Print rtResourceCount
	move.l	rtResourceCountMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
	lea	(a4,d6.w),a3		; Get address of rtResourceCount
	move.w	(a3),d5
	bsr	PrePrintSingleIntelWord	; Prepare word for printing
	bsr	PrintMSG		; Print the number

	addq.w	#6,d6			; Increment pointer			Skip rtReserved (longword)

;	move.w	(a3),d5			; d5 = rtResourceCount			FOR n-1 to rtResourceCount
	rol.w	#8,d5			; Position the bytes right

PrintrtNameInfo								;	  Print rtNameInfo
	lea	rnOffsetMSG,a0		; Get address of message		    Print rnOffset
	move.l	rnOffsetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	clr.l	d0			; Clear d0
	move.w	rnOffset(a4,d6.w),d0	; Get rnOffset
	rol.w	#8,d0			; Position the bytes correctly
	lsl.l	d4,d0			; Shift to size
	bsr	PrintMotoRegNum		; Print the number

	lea	rnLengthMSG,a0		; Get address of message	;	    Print rnLength
	move.l	rnLengthMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	clr.l	d0			; Clear d0
	move.w	rnLength(a4,d6.w),d0	; Get rnOffset
	rol.w	#8,d0			; Position the bytes correctly
	lsl.l	d4,d0			; Shift to size
	bsr	PrintMotoRegNum		; Print the number

; Print rnFlags									    Print rnFlags

	lea	rnFlagsMSG,a0		; Get address of message		      Print "Resource flags"
	move.l	rnFlagsMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	btst	#4,rnFlags(a4,d6.w)	; Test bit 4 of rnFlags			      If bit 4 set then print "MOVEABLE"
	beq	rnFlagsNotMoveable	; Jump if flag not set
	lea	rnFlagsMoveableMSG,a0	; Get address of message
	move.l	rnFlagsMoveableMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
rnFlagsNotMoveable
	btst	#5,rnFlags(a4,d6.w)	; Test bit 6 of rnFlags			      If bit 5 set then print "PURE"
	beq	rnFlagsNotPure		; Jump if flag not set
	lea	rnFlagsPureMSG,a0	; Get address of message
	move.l	rnFlagsPureMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
rnFlagsNotPure
	btst	#6,rnFlags(a4,d6.w)	; Test bit 6 of rnFlags			      If bit 6 set then print "PRELOAD"
	beq	PrintrnID		; Jump if flag not set
	lea	rnFlagsPreloadMSG,a0	; Get address of message
	move.l	rnFlagsPreloadMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

PrintrnID								;	    Print rnID
	lea	rnIDMSG,a0		; Get address of message		      Print "Resource ID is"
	move.l	rnIDMSGLen,d3		; Get length of message
	bsr	PrintMSG		; Print the message
	move.w	rnID(a4,d6.w),d0	; Get rnID				      If rnID >= $8000 then print rnID-$8000
	bclr	#7,d0			; Clear MSBit of intel word
	lea	StackEquation(a5),a3	; Get temporary address
	move.w	d0,(a3)			; Store ID
	bsr	PrePrintSingleIntelWord	; Prepare the word for printing
	btst	#7,rnID+1(a4,d6.w)	; Test bit 15 of rnID
	bne	EndFORrnNameInfo	; Jump if set
	lea	rnID(a4,d6.w),a0	; Get rnID address				ELSE
	clr.l	d0			; Clear scratch register			  x=(rnID+resource table base)
	move.l	d0,d3			; Clear d3 also					  Print x chars from above table
	move.w	(a0),d0			; Get offset
	rol.w	#8,d0			; Position bytes correctly
	move.l	d0,a0			; Get address of string
	add.w	d7,a0			; Add base of resource table
	add.l	a4,a0			; Add base of header
	move.b	(a0)+,d3		; Get length of string

EndFORrnNameInfo
	bsr	PrintMSG		; Print the message
	add.w	#12,d6			; Skip to next entry			      Skip to next entry
	subq.w	#1,d5			; Decrement n FOR loop
	bne	PrintrtNameInfo		; Loop if not zero		;	    END ; FOR
	tst.w	(a4,d6.w)		; Test next byte
	bne	PrintrscTypes		; Loop if not zero		;	  UNTIL rscEndTypes ; ie. next byte = 0
NoResourceTable
	rts				; End of printing


**------------------------------------------
**
** Print resident-name table
**
**------------------------------------------

PrintResNameTable
	lea	ResNamTableMSG,a0	; Get address of message	Print resident-name table
	move.l	ResNamTableMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	clr.l	d7			; Clear d7			  Get address of resident-name table
	move.w	ResNameTabOffset(a4),d7	; Get offset
	rol.w	#8,d7			; Position bytes correctly
	add.l	a4,d7			; Get address of table
	move.l	d7,a0			; Put in address register	  Skip first entry
	move.b	(a0)+,d3		; Get length of module		    Get length of string
	add.l	d3,a0			; Skip past name		    Add to pointer
	addq.l	#2,a0			; Skip ordinal			    Add 2 to pointer to skip ordinal
PrintResNamTabString
	tst.b	(a0)			; Test next byte		  WHILE next byte !=0
	beq	ResNamTabFinished	; Jump if 0
	move.l	a0,d7			; Save pointer
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d7,a0			; Get pointer			    Get length of string
	move.b	(a0)+,d3		; Get length of string
	move.l	a0,d7			; Save pointer
	add.l	d3,d7			; Add string length		    Skip pointer past string
	bsr	PrintMSG		; Print the string		    Print string
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d7,a3			; Put pointer in a3		    Print ordinal
	bsr	PrePrintSingleIntelWord	; Prepare the number
	bsr	PrintMSG		; Print the number
	addq.l	#2,d7			; Skip past ordinal
	move.l	d7,a0			; Get pointer
	bra	PrintResNamTabString	; Loop				    END ; WHILE

ResNamTabFinished
	rts				; Return


**--------------------------------------------------
**
** Print module-reference and imported-name tables
**
**--------------------------------------------------

PrintModImpTables
	lea	ModTableEntriesMSG,a0	; Get address of message	Print module-reference and imported-name tables
	move.l	ModTableEntriesMSGLen,d3; Get length of message		  Print number of entries in module-reference table
	bsr	PrintMSG		; Print the message
	lea	ModTableEntries(a4),a3	; Point to entries in mod tab
	move.w	(a3),d7			; Get number of entries
	rol.w	#8,d7			; Position bytes correctly
	bsr	PrePrintSingleIntelWord	; Prepare for printing
	bsr	PrintMSG		; Print the number
	clr.l	d6			; Clear d6			  Get address of imported-name table
	move.w	ImpTableOffset(a4),d6	; Get offset to imp tab
	rol.w	#8,d6			; Position the bytes correctly
	add.l	a4,d6			; Add base of header
	addq.w	#1,d7			; Add extra 1
PrintModRefStrings							; FOR n=1 to number of entries in module-reference table
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d6,a0			; Get pointer			    Get length of string
	move.b	(a0)+,d3		; Get length of string
	move.l	a0,d6			; Save pointer			    Get address of string
	add.l	d3,d6			; Skip past string
	bsr	PrintMSG		; Print string			    Print string
	lea	NewLineMSG,a0		; Get address of message
	move.l	NewLineMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	subq.w	#1,d7			; Decrement counter		    END ; FOR
	bne	PrintModRefStrings	; Loop
	rts				; Finished


**------------------------------------------
**
** Print non-resident name table
**
**------------------------------------------

PrintNonResNameTable
	lea	NonResNamTableMSG,a0	; Get address of message	Print resident-name table
	move.l	NonResNamTableMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	clr.l	d7			; Clear d7			  Get address of resident-name table
	move.l	NonResNamTabOffset(a4),d7	; Get offset
	rol.w	#8,d7			; Position bytes correctly
	swap	d7			; swap register halves
	rol.w	#8,d7			; Position bytes correctly
	sub.l	HeaderOffset(a5),d7	; Get address of table
	add.l	a4,d7			; Add offset to table
	move.l	d7,a0			; Put in address register	  Skip first entry
	move.b	(a0)+,d3		; Get length of module		    Get length of string
	add.l	d3,a0			; Skip past name		    Add to pointer
	addq.l	#2,a0			; Skip ordinal			    Add 2 to pointer to skip ordinal
PrintNonResNamTabString
	tst.b	(a0)			; Test next byte		  WHILE next byte !=0
	beq	NonResNamTabFinished	; Jump if 0
	move.l	a0,d7			; Save pointer
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d7,a0			; Get pointer			    Get length of string
	move.b	(a0)+,d3		; Get length of string
	move.l	a0,d7			; Save pointer
	add.l	d3,d7			; Add string length		    Skip pointer past string
	bsr	PrintMSG		; Print the string		    Print string
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d7,a3			; Put pointer in a3		    Print ordinal
	bsr	PrePrintSingleIntelWord	; Prepare the number
	bsr	PrintMSG		; Print the number
	addq.l	#2,d7			; Skip past ordinal
	move.l	d7,a0			; Get pointer
	bra	PrintNonResNamTabString	; Loop				    END ; WHILE

NonResNamTabFinished
	rts				; Return


**---------------------------------------------
**
** Print entry table
**
**---------------------------------------------

PrintEntryTable							;	Print entry table
	lea	EntryTableMSG,a0	; Get address of message
	move.l	EntryTableMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	tst.w	EntryLength(a4)		; Test number			  Test length of entry table
	beq	EntryTableFinished	; Quit if 0		
	clr.l	d5			; Clear d5
	moveq.l	#1,d6			; Initialize entry counter	  If length != 0 then
	move.w	EntryOffset(a4),d7	; Get offset			    Get address of entry table
	rol.w	#8,d7			; Position bytes correctly
PrintEntryTableBundles						;	    REPEAT
	move.b	EntryBndlNum(a4,d7.w),d5; Get number of entries		      Get number of entries in bundle
	move.b	EntryBndlTyp(a4,d7.w),d4; Get entry type		      Get bundle type
	addq.w	#2,d7			; Add 2 to pointer		      Add 2 to pointer
	tst.b	d4			; Is d4 = 0 ?			      If bundle type = 0 then	; Null entries
	beq	EntryZeroBundle		; Branch if 0
	cmp.b	#$FE,d4			; Is d4 = $FE			      If bundle type = $FE then	; Constant pointer
	beq	EntryConstBundle	; Jump if $FE
	cmp.b	#$FF,d4			; Is d4 = $FF
	beq	EntryMoveBundle		; Jump if $FF			      If bundle type = $FF then	; Movable segment

; Print fixed segment records						      ELSE

	lea	EntryFixSegRecrMSG,a0	; Get address of message		Print "Fixed segment records : "
	move.l	EntryFixSegRecrMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	d5,d3			; Move byte for printing
	bsr	PrintByte		; Print a byte number			,entries in bundle,
	lea	EntryEntriesSegMSG,a0	; Get address of message		" entries.    Segment : "
	move.l	EntryEntriesSegMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	d4,d3			; Move byte for printing		,bundle type
	bsr	PrintByte		; Print the number
EntryPrintFixSeg							;	FOR n=1 to entries in bundle
	bsr	PrintEntryNumber	; Print entry				  Print "Entry ",entry counter
	lea	EntryFixOffsetMSG,a0	; Get address of message		  Print "Offset : ",EntryFixOffset
	move.l	EntryFixOffsetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	EntryFixOffset(a4,d7.w),a3	; Get address of offset
	bsr	PrePrintSingleIntelWord	; Prepare num for printing
	subq.l	#1,d3			; No new line
	bsr	PrintMSG		; Print number
	btst	#0,EntryFixFlags(a4,d7.w)	; Test flag			  If bit 0 of EntryFixFlags = 1 then
	beq	EntryFixNotExported	; Jump if 0
	bsr	PrintEntryExported	; Print exported			    Print Exported
EntryFixNotExported
	btst	#1,EntryFixFlags(a4,d7.w)	; Test flag			  If bit 1 of EntryFixFlags = 1 then
	beq	EntryFixNotGlobal	; Jump if 0
	lea	SingleDataModelMSG,a0	; Get address of message		    Print "SINGLEDATA"
	move.l	SingleDataModelMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
EntryFixNotGlobal
	addq.w	#3,d7			; Add 3 to pointer			  Add 3 to pointer
	addq.l	#1,d6			; Increment entry number		  END ; FOR
	subq.b	#1,d5			; Decrement number of entries in bundle
	bne	EntryPrintFixSeg	; Loop
	bra	EntryFinished		; Finished

; Print null entry bundles

EntryZeroBundle
	lea	EntryNullEntriesMSG,a0	; Get address of message		Print "Null entries : "
	move.l	EntryNullEntriesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	d5,d3			; Get number of entries			,entries
	bsr	PrintByte		; Print the number
	add.l	d5,d6			; Add entries to counter		Add entries to entry counter
	bra	EntryFinished		; Null entries done

; Constant pointer

EntryConstBundle
	lea	EntryConstantMSG,a0	; Get address of message		Print "Constant records : "
	move.l	EntryConstantMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	d5,d3			; Move byte for printing
	bsr	PrintByte		; Print a byte number			,entries in bundle,
	lea	EntryEntriesMSG,a0	; Get address of message		" entries."
	move.l	EntryEntriesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
EntryPrintConstSeg							;	FOR n=1 to entries in bundle
	bsr	PrintEntryNumber	; Print entry				  Print "Entry ",entry counter
	lea	EntryFixOffsetMSG,a0	; Get address of message		  Print "Offset : ",EntryConstValue
	move.l	EntryFixOffsetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	EntryConstValue(a4,d7.w),a3	; Get address of offset
	bsr	PrePrintSingleIntelWord	; Prepare num for printing
	subq.l	#1,d3			; No new line
	bsr	PrintMSG		; Print number
	btst	#0,EntryConstFlags(a4,d7.w)	; Test flag			  If bit 0 of EntryFixFlags = 1 then
	beq	EntryConstNotExported	; Jump if 0
	bsr	PrintEntryExported	; Print exported			    Print Exported
EntryConstNotExported
	btst	#1,EntryConstFlags(a4,d7.w)	; Test flag			  If bit 1 of EntryFixFlags = 1 then
	beq	EntryConstNotGlobal	; Jump if 0
	lea	SingleDataModelMSG,a0	; Get address of message		    Print "SINGLEDATA"
	move.l	SingleDataModelMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
EntryConstNotGlobal
	addq.w	#3,d7			; Add 3 to pointer			  Add 3 to pointer
	addq.l	#1,d6			; Increment entry number		  END ; FOR
	subq.b	#1,d5			; Decrement number of entries in bundle
	bne	EntryPrintConstSeg	; Loop
	bra	EntryFinished		; Finished

; Print moveable segment record

EntryMoveBundle
	lea	EntryMoveRecrMSG,a0	; Get address of message		Print "Movable segment records : "
	move.l	EntryMoveRecrMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	d5,d3			; Move byte for printing
	bsr	PrintByte		; Print a byte number			,entries in bundle,
	lea	EntryEntriesMSG,a0	; Get address of message		Print "entries"
	move.l	EntryEntriesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
EntryPrintMoveSeg							;	FOR n=1 to entries in bundle
	bsr	PrintEntryNumber	; Print entry				  Print "Entry ",entry counter
	lea	EntryMoveSegMSG,a0	; Get address of message		  Print "Segment : ",EntryMoveSeg
	move.l	EntryMoveSegMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.b	EntryMoveSeg(a4,d7.w),d3; Get address of offset
	bsr	PrintByte		; Prepare num for printing
	lea	EntryMoveOffsetMSG,a0	; Get address of message		  Print "Offset : ",EntryMoveOffset
	move.l	EntryMoveOffsetMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
	lea	EntryMoveOffset(a4,d7.w),a3	; Get address of offset
	bsr	PrePrintSingleIntelWord	; Prepare num for printing
	subq.l	#1,d3			; No new line
	bsr	PrintMSG		; Print number
	btst	#0,EntryMoveFlags(a4,d7.w)	; Test flag			  If bit 0 of EntryFixFlags = 1 then
	beq	EntryMoveNotExported	; Jump if 0
	bsr	PrintEntryExported	; Print exported			    Print Exported
EntryMoveNotExported
	btst	#1,EntryFixFlags(a4,d7.w)	; Test flag			  If bit 1 of EntryFixFlags = 1 then
	beq	EntryMoveNotGlobal	; Jump if 0
	lea	GlobalMSG,a0		; Get address of message		    Print "GLOBAL"
	move.l	GlobalMSGLen,d3		; Get length of message
	bsr	PrintMSG		; Print the message
EntryMoveNotGlobal
	addq.w	#6,d7			; Add 6 to pointer			  Add 6 to pointer
	addq.l	#1,d6			; Increment entry number		  END ; FOR
	subq.b	#1,d5			; Decrement number of entries in bundle
	bne	EntryPrintMoveSeg	; LoopEntryFinished
EntryFinished
	tst.b	(a4,d7.w)		; Is next byte = 0			UNTIL next byte = 0
	bne	PrintEntryTableBundles	; Loop
EntryTableFinished
	rts				; Finished

PrintEntryNumber
	lea	EntryNumberMSG,a0	; Get address of message		Print "Entry : "
	move.l	EntryNumberMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	d6,d0			; Get entry counter			,entry counter
	rol.w	#8,d0			; Convert to intel form
	swap	d0			; Swap register halves
	rol.w	#8,d0			; Convert to intel form
	move.l	d0,StackEquation(a5)	; Put number for printing
	lea	StackEquation(a5),a3	; Get address of number
	lea	TempBuffer(a5),a1	; Get address of printing buffer
	move.l	a1,a0			; Make a copy of buffer address
	move.b	#"$",(a1)+		; Put $ for hexadecimal
	addq.l	#2,a3			; Bump pointer to segment number
	bsr	PrePrintIntelWord	; Print the segment number
	move.b	#":",(a1)+		; Character in between seg and offset
	subq.l	#4,a3			; Bump pointer back to offset
	bsr	PrePrintIntelWord	; Print the offset number
	move.l	#10,d3			; Length of string
	bra	PrintMSG		; Print string

PrintEntryExported
	lea	EntryExportedMSG,a0	; Get address of message		Print "Exported"
	move.l	EntryExportedMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	rts				; Return


**----------------------------------------------
**
** Print relocation tables
**
**----------------------------------------------

PrintRelocTabs				;					Print segment relocations
	lea	PrintRelocationMSG,a0	; Get address of message		  Print "Segment relocations"
	move.l	PrintRelocationMSGLen,d3; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	#1,d7			; d7=segment counter			  Initialize segment counter
	move.w	SegTableOffset(a4),d5	; Get seg table offset			  Get address of segment table
	rol.w	#8,d5			; d5=Pointer in seg table
	move.w	SegTableEntryNum(a4),d6	; Get seg table entries			  Get number of entries in segment table
	rol.w	#8,d6			; d6=Seg table entries (n)
SearchSegTab4Reloc			;					  FOR n=1 to entries in segment table
	btst	#0,SegFlags+1(a4,d5.w)	; Test bit 8 of segment flags		    If this segment contains relocation data
	beq	NoRelocInThisSeg	; Jump if no relocations
	lea	RelocForSegMSG,a0	; Get address of message		      Print "Relocations for segment "
	move.l	RelocForSegMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.w	d7,d0			; Get temp copy of seg num		      ,segment counter
	rol.w	#8,d0			; Make intel word
	lea	StackEquation(a5),a3	; Get temporary address
	move.w	d0,(a3)			; Save number
	bsr	PrePrintSingleIntelWord	; Prepare for printing
	bsr	PrintMSG		; Print the number
	clr.l	d2			; Clear d2 for later
	move.l	d2,d0			; Clear d0 for later too
	move.b	ShiftCount(a4),d0	; Get shift count			      Goto position of segment in file
	move.w	SegmentPos(a4,d5.w),d2	; Get position of segment
	rol.w	#8,d2			; Position bytes correctly
	lsl.l	d0,d2			; Shift pos by sector size
	move.w	SegmentLen(a4,d5.w),d0	; Get length of segment			      Move an extra segment length bytes
	rol.w	#8,d0			; Position bytes correctly
	add.l	d0,d2			; Add the length
	bsr	SeekTo			; Goto that position
	bsr	ReadIntelWord		; Get length of buffer			      Get intel word at that address (items in table)
	clr.l	d3			; Clear d0				      Allocate items in table * 8 bytes of ram
	move.w	d2,d3			; Get length of buffer
	move.l	d3,d4			; d4=number of entries counter (x)
	lsl.l	#3,d3			; Multiply by 8
	move.l	d3,d0			; Save copy of length
	move.l	d3,RelocBufferLen(a5)	; Save permanent copy of buffer len
	move.l	#AnyMemoryType,d1	; Any memory type
	move.l	AbsExecBase,a6		; Get address of exec base
	jsr	_LVOAllocMem(a6)	; Allocate the memory
	move.l	DosBase(a5),a6		; Get dos.library pointer
	tst.l	d0			; Was memory allocated?
	bne	RelocBufferOK		; Jump if OK

	lea	OutOfMemMSG,a0		; Get address of message		      If allocation UNsuccesful then
	move.l	OutOfMemMSGLen,d3	; Get length of message				Print "Out of memory"
	bsr	PrintMSG		; Print the message
	rts				; Return					rts

RelocBufferOK
	move.l	d0,a4			; a4=address of reloc buffer		      Read items in table * 8 bytes into allocates buffer
	move.l	d0,RelocBufferAddr(a5)	; Keep permanent copy of buffer addr
	move.l	d0,d2			; Get address of buffer
	move.l	FileHandle(a5),d1	; Get file handle
	jsr	_LVORead(a6)		; Get relocation table
	cmp.l	d0,d3			; Check return value			      If read failed then
	beq	RelocReadOK		; Jump if ok
	lea	RelocReadFailedMSG,a0	; Get address of message			Print "Read from file failed"
	move.l	RelocReadFailedMSGLen,d3; Get length of message

RelocError
	bsr	PrintMSG		; Print the message
	move.l	HeaderAddress(a5),a4	; Get address of header
	move.l	RelocBufferAddr(a5),a1	; Get address of buffer
	move.l	RelocBufferLen(a5),d0	; Get length of buffer
	move.l	AbsExecBase,a6		; Get address of exec base
	jsr	_LVOFreeMem(a6)		; Allocate the memory
	move.l	DosBase(a5),a6		; Get dos.library pointer
	rts				; Finished					rts

RelocReadOK
	lea	TypeOffsTargetMSG,a0	; Get address of message		      Print "type    offset    target"
	move.l	TypeOffsTargetMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

PrintRelocItem				;					      FOR x = 1 to items in table
	lea	LoByteMSG,a0		; Get address of message			If RelocAddrType = 0 then
	move.l	LoByteMSGLen,d3		; Get length of message				  Print "LoByte "
	cmp.b	#0,RelocAddrType(a4)	; Is it = 0?
	beq	RelocTypeFound		; Print reloc type
	lea	SelectMSG,a0		; Get address of message			If RelocAddrType = 2 then
	move.l	SelectMSGLen,d3		; Get length of message				  Print "Select "
	cmp.b	#2,RelocAddrType(a4)	; Is it = 2?
	beq	RelocTypeFound		; Print reloc type
	lea	PtrMSG,a0		; Get address of message			If RelocAddrType = 3 then
	move.l	PtrMSGLen,d3		; Get length of message				  Print "PTR    "
	cmp.b	#3,RelocAddrType(a4)	; Is it = 3?
	beq	RelocTypeFound		; Print reloc type
	lea	OffsMSG,a0		; Get address of message			If RelocAddrType = 5 then
	move.l	OffsMSGLen,d3		; Get length of message				  Print "OFFS   "
	cmp.b	#5,RelocAddrType(a4)	; Is it = 5?
	beq	RelocTypeFound		; Print reloc type
	lea	Ptr48MSG,a0		; Get address of message			If RelocAddrType = 11 then
	move.l	Ptr48MSGLen,d3		; Get length of message				  Print "PTR-48 "
	cmp.b	#11,RelocAddrType(a4)	; Is it = 11?
	beq	RelocTypeFound		; Print reloc type
	lea	Offs32MSG,a0		; Get address of message			If RelocAddrType = 13 then
	move.l	Offs32MSGLen,d3		; Get length of message				  Print "OFFS-32 "
	cmp.b	#13,RelocAddrType(a4)	; Is it = 13?
	beq	RelocTypeFound		; Print reloc type

	lea	RelocTypeUnknMSG,a0	; Get address of message			else print "Unknown relocation type. Send me this file to df114@city.ac.uk read docs!!!!"
	move.l	RelocTypeUnknMSGLen,d3	; Get length of message
	bra	RelocError		; Finish					  rts

RelocTypeFound
	bsr	PrintMSG		; Print reloc type
	lea	RelocOffset(a4),a3	; Get address of reloc offset			Print RelocOffset
	bsr	PrePrintSingleIntelWord	; Prepare for printing
	subq.l	#1,d3			; No newline
	bsr	PrintMSG		; Print the number
	lea	SixBlankSpacesMSG,a0	; Get address of message
	move.l	SixBlankSpacesMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message

	tst.b	RelocType(a4)		; Is it 0					If RelocType = 0 then		Internal reference
	beq	RelocInternalReference	; Jump if true
	cmp.b	#1,RelocType(a4)	; Is it 1					If RelocType = 1 then		Imported ordinal
	beq	RelocImportedOrdinal	; Jump if true
	cmp.b	#2,RelocType(a4)	; Is it 2					If RelocType = 2 then		Imported name
	beq	RelocImportedName	; Jump if true
	cmp.b	#3,RelocType(a4)	; Is it 3					If RelocType = 3 then		OSFIXUP
	beq	RelocOSFIXUP		; Jump if true
	cmp.b	#5,RelocType(a4)	; Is it 5					If RelocType = 5 then		Additive?
	beq	RelocAdditive		; Jump if true

	lea	RelocTypeUnknMSG,a0	; Get address of message			else
	move.l	RelocTypeUnknMSGEnd,d3	; Get length of message				  Print "Unknown relocation type send me this file to df114@city.ac.uk read docs!!!!"
	bra	RelocError		; Finish					  rts

RelocInternalReference			;						If RelocType = 0 then		Internal reference
	cmp.b	#$FF,RelocB4(a4)	; Is segment movable?				  If RelocB4 = $FF then
	bne	RelocInternalFixed	; Jump if fixed segment
	lea	EntryMSG,a0		; Get address of message			    Print "Entry "
	move.l	EntryMSGLen,d3		; Get length of message
	bsr	PrintMSG		; Print the message
	lea	RelocB6(a4),a3		; Get pointer to entry				    ,RelocB6
	bsr	PrePrintSingleIntelWord	; Print the number
	bra	RelocItemPrinted	; Done
RelocInternalFixed
	move.l	RelocB4(a4),d0		; Get number					  else
	swap	d0			; Swap register halves				    Print RelocB4,":",RelocB6	Segment:Offset are the wrong way round
	rol.w	#8,d0			; Position bytes correctly
	swap	d0			; Swap register halves
	rol.w	#8,d0			; Form number correctly
	bsr	PrintMotoRegNum		; Print the number
	bra	RelocItemPrinted	; Done

RelocImportedOrdinal			;						If RelocType = 1 then
	move.l	HeaderAddress(a5),a3	; Get address of header
	clr.l	d0			; Clear d0
	move.l	d0,d1			; Clear d1
	move.b	RelocB4(a4),d0		; Get RelocB4					  (RelocB4 - 1)*2
	subq.b	#1,d0			; RelocB4-1
	lsl.w	#1,d0			; (RelocB4-1)*2
	move.w	ModRefOffset(a3),d1	; Get offset to mod-ref table			  Add offset to mod-ref table
	rol.w	#8,d1			; Position bytes correctly
	add.l	d0,d1			; Add numbers
	move.w	(a3,d1),d1		; Get offset into imp-nam table
	rol.w	#8,d1			; Position bytes correctly
	move.w	ImpNameOffset(a3),d0	; Get offset to imp-nam table			  Add that word to offset of imp-name table
	rol.w	#8,d0			; Position bytes correctly
	add.l	d0,d1			; Add the numbers
	lea	(a3,d1),a0		; Get address of string				  Print that byte many bytes at that addr+1
	move.b	(a0)+,d3		; Get length of string
	bsr	PrintMSG		; Print the string
	lea	FullStopMSG,a0		; Get address of message			  Print "."
	move.l	FullStopMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	RelocB6(a4),a3		; Get address of number				  ,RelocB6
	bsr	PrePrintSingleIntelWord	; Prepare for printing
	bsr	PrintMSG		; Print the number
	bra	RelocItemPrinted	; Done

RelocImportedName			;						If RelocType = 2 then		; Imported name
	move.l	HeaderAddress(a5),a3	; Get address of header
	clr.l	d0			; Clear d0
	move.l	d0,d1			; Clear d1
	move.b	RelocB4(a4),d0		; Get RelocB4					  (RelocB4 - 1)*2
	subq.b	#1,d0			; RelocB4-1
	lsl.w	#1,d0			; (RelocB4-1)*2
	move.w	ModRefOffset(a3),d1	; Get offset to mod-ref table			  Add offset to mod-ref table
	rol.w	#8,d1			; Position bytes correctly
	add.l	d0,d1			; Add numbers
	move.w	(a3,d1),d1		; Get offset into imp-nam table
	rol.w	#8,d1			; Position bytes correctly
	move.w	ImpNameOffset(a3),d0	; Get offset to imp-nam table			  Add that word to offset of imp-name table
	rol.w	#8,d0			; Position bytes correctly
	add.l	d0,d1			; Add the numbers
	lea	(a3,d1),a0		; Get address of string				  Print that byte many bytes at that addr+1
	move.b	(a0)+,d3		; Get length of string
	bsr	PrintMSG		; Print the string
	lea	FullStopMSG,a0		; Get address of message			  Print "."
	move.l	FullStopMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	move.l	HeaderAddress(a5),a3	; Get address of header
	clr.l	d0			; Clear d0
	move.l	d0,d1			; Clear d1
	move.b	RelocB6(a4),d0		; Get RelocB6					  RelocB6 + offset to imp-name table
	move.w	ImpNameOffset(a3),d1	; Get offset to imp-nam table
	rol.w	#8,d1			; Position bytes correctly
	add.l	d0,d1			; Add the numbers
	lea	(a3,d1),a0		; Get address of string				  Print that byte many bytes at that addr+1
	move.b	(a0)+,d3		; Get length of string
	bsr	PrintMSG		; Print the string
	lea	NewLineMSG,a0		; Get address of message
	move.l	NewLineMSG,d3		; Get length of message
	bsr	PrintMSG		; Print the message
	bra	RelocItemPrinted	; Done

RelocOSFIXUP				;						If RelocType = 3 then		OSFIXUP
	lea	RelocTypeUnknMSG,a0	; Get address of message			  Print "OSFIXUP Send me this file to df114@city.ac.uk read docs!!!!"
	move.l	RelocTypeUnknMSGLen,d3	; Get length of message
	bra	RelocError		; Finished					  rts

RelocAdditive
	move.l	HeaderAddress(a5),a3	; Get address of header
	clr.l	d0			; Clear d0
	move.l	d0,d1			; Clear d1
	move.b	RelocB4(a4),d0		; Get RelocB4					  (RelocB4 - 1)*2
	subq.b	#1,d0			; RelocB4-1
	lsl.w	#1,d0			; (RelocB4-1)*2
	move.w	ModRefOffset(a3),d1	; Get offset to mod-ref table			  Add offset to mod-ref table
	rol.w	#8,d1			; Position bytes correctly
	add.l	d0,d1			; Add numbers
	move.w	(a3,d1),d1		; Get offset into imp-nam table
	rol.w	#8,d1			; Position bytes correctly
	move.w	ImpNameOffset(a3),d0	; Get offset to imp-nam table			  Add that word to offset of imp-name table
	rol.w	#8,d0			; Position bytes correctly
	add.l	d0,d1			; Add the numbers
	lea	(a3,d1),a0		; Get address of string				  Print that byte many bytes at that addr+1
	move.b	(a0)+,d3		; Get length of string
	bsr	PrintMSG		; Print the string
	lea	FullStopMSG,a0		; Get address of message			  Print "."
	move.l	FullStopMSGLen,d3	; Get length of message
	bsr	PrintMSG		; Print the message
	lea	RelocB6(a4),a3		; Get address of number				  ,RelocB6
	bsr	PrePrintSingleIntelWord	; Prepare for printing
	bsr	PrintMSG		; Print the number

RelocItemPrinted
	addq.l	#8,a4			; Add 8						Add 8 to pointer			; Skip to next entry in relocation table
	subq.w	#1,d4			; Decrement num of entries
	tst.w	d4
	bne	PrintRelocItem		; Loop						END ; FOR

	move.l	RelocBufferAddr(a5),a1	; Get address of reloc buffer		      Deallocate memory just used
	move.l	RelocBufferLen(a5),d0	; Get length of reloc buffer
	move.l	AbsExecBase,a6		; Get exec base
	jsr	_LVOFreeMem(a6)		; Free the memory
	move.l	DosBase(a5),a6		; Restore dos.library pointer
	move.l	HeaderAddress(a5),a4	; Get address of header
NoRelocInThisSeg
	addq.w	#8,d5			; Add 8 to pointer			      Add 8 to pointer'			; Skip to next entry in segment table
	addq.w	#1,d7			; Increment segment counter
	subq.w	#1,d6			; Decrement number of segments
	tst.w	d6			; Are we finished?
	bne	SearchSegTab4Reloc	; Loop					      END ; FOR
	rts				; Finished

*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrintByte		PrintByte(Number)
**				   d3
**
** Print the byte held in d3
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrintByte
	lea	TempBuffer(a5),a0	; Get address of temp buffer
	bsr	ConvertBin2ASCII	; Convert number to ASCII
	move.b	#"$",(a0)		; Put a $ sign
	move.b	d0,1(a0)		; Put high nibble
	move.b	d1,2(a0)		; Put low nibble
	move.l	#3,d3			; Three characters to print
	bra	PrintMSG		; Print the number

**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrintMotoRegNum	PrintMotoRegNum(Number)
**					 d0
**
** Prints the normal format number in d0 in segment:offset form
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrintMotoRegNum
	rol.w	#8,d0			; Convert to intel form
	swap	d0			; Swap register halves
	rol.w	#8,d0			; Convert to intel form
	move.l	d0,StackEquation(a5)	; Put number for printing
	lea	StackEquation(a5),a3	; Get address of number
	bra	PrintSegOffset		; Print the number



**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrintSegOffset	PrintSegOffset(*Number)
**					a3
**
** Prints a segment and offset number as pointed to by a3
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrintSegOffset
	lea	TempBuffer(a5),a1	; Get address of printing buffer
	move.l	a1,a0			; Make a copy of buffer address
	move.b	#"$",(a1)+		; Put $ for hexadecimal
	addq.l	#2,a3			; Bump pointer to segment number
	bsr	PrePrintIntelWord	; Print the segment number
	move.b	#":",(a1)+		; Character in between seg and offset
	subq.l	#4,a3			; Bump pointer back to offset
	bsr	PrePrintIntelWord	; Print the offset number
	move.b	#NewLine,(a1)+		; New line
	move.l	#11,d3			; Length of string
	bra	PrintMSG		; Print string




**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrePrintIntelWord	PrePrintIntelWord(*Number,*PrintBuffer)
**					    a3		a1
**
** Puts the ASCII codes for a word into a string ready to be printed. a3 points to the number and
** a1 points to the number itself in Intel format.
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrePrintIntelWord
	move.b	1(a3),d3		; Get high byte of number
	bsr	ConvertBin2ASCII	; Get ASCII codes
	move.b	d0,(a1)+		; Put high nibble
	move.b	d1,(a1)+		; Put low nibble
	move.b	(a3),d3			; Get low byte of number
	bsr	ConvertBin2ASCII	; Get ASCII codes
	move.b	d0,(a1)+		; Put high nibble
	move.b	d1,(a1)+		; Put low nibble
	addq.l	#2,a3			; Increment pointer past number
	rts				; Return



**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrePrintSingleIntelWord	*Buffer , Length = PrePrintSingleIntelWord(*Number)
**				  a0	    d3					a3
**
** Prepares a single Intel format word for printing. It return a pointer to the print buffer and has
** the length in d3 ready for a call to PrintMSG.
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrePrintSingleIntelWord
	lea	TempBuffer(a5),a1	; Get address of temporary buffer
	move.l	a1,a0			; Keep a temporary copy of buffer address
	move.b	#"$",(a1)+		; Put $ for hex number
	bsr	PrePrintIntelWord	; Put number
	move.b	#NewLine,(a1)+		; Put new line character
	move.l	#6,d3			; 6 characters to be printed
	rts				; Finished

**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** ReadIntelWord  d2 = ReadIntelWord
**
** Read an Intel backward format word from current position in file and
** returns it as a proper Motorola word
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

ReadIntelWord
	move.l	FileHandle(a5),d1	; Get file handle
	lea	TempBuffer(a5),a0	; Get address of temp buffer
	move.l	a0,d2			; Put temp buffer address in d2
	move.l	#2,d3			; Two bytes or word to be checked
	jsr	_LVORead(a6)		; Read word for checking
	cmp.l	#2,d0			; Read OK?
	bne	ReadFailed		; Goto read failed error
	move.w	TempBuffer(a5),d2	; Get word
	rol.w	#8,d2			; Swap high and low byte
	rts				; Return word



**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** SeekTo   SeekTo(Position)
**			d2
**
** Seeks to the indicated position in the file. If operation unsuccesful
** the return address is POPed from the stack and an error printed.
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

SeekTo
	move.l	FileHandle(a5),d1	; Move file handle to d1
	move.l	#OFFSET_BEGINNING,d3	; Seek from beginning of file
	jsr	_LVOSeek(a6)		; Seek
	cmp.l	#-1,d0			; Was seek succesful?
	beq	SeekNotSuccesful	; Goto error if unsuccesful   
	rts				; Completed succesfully

**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** ConvertBin2ASCII	d0,d1 = ConvertBin2ASCII (binary number)
**							d3
**
** Converts an 8-digit binary number to two ASCII hexadecimal digits.
**
** d0 = high digit bits 4-7
** d1 = low digit bits 0-3
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

ConvertBin2ASCII
	move.b	d3,d0			; Get low nibble
	and.b	#$0F,d0			; Blank out high nibble
	bsr	ConvertNumber		; Convert the nibble
	move.b	d0,d1			; Store low nibble in d1
	move.b	d3,d0			; Get high nibble
	lsr.b	#4,d0			; Position it correctly
ConvertNumber
	add.b	#$30,d0			; Add ASCII "0"
	cmp.b	#$3A,d0			; Is number < 10 ?
	blt	ConversionComplete	; If yes then conversion complete
	add.b	#$07,d0			; Add to ASCII "A"
ConversionComplete
	rts				; Conversion completed


**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
**
** PrintMSG	PrintMSG (*MSG,Length)
**			   a0	d3
**
** Prints a given message to standard out.
**
**+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

PrintMSG
	move.l	DosBase(a5),a6		; Get dos base address
	move.l	a0,d2			; Put message pointer in d2
	move.l	OutputHandle(a5),d1	; Move output handle to d1
	jsr	_LVOWrite(a6)		; Print message
	rts				; Print complete



**=====================================================================================================
**
** Error handlers
**
**=====================================================================================================


FileNotOpenOK
	move.l	FileNotOpenMSGLen,d3	; Get length of message
	lea	FileNotOpenMSG,a0	; Get pointer to error message
	bra	PrintErrorAndReturnToDos; Print error message

MemoryNotAllocated
	move.l	MemoryNotAllocatedMSGLen,d3	; Get length message
	lea	MemoryNotAllocatedMSG,a0	; Get pointer to error message
	bra	CloseFileAndDosLibPrintMSG	; Print error message

NotWindowsEXE
	move.l	NotWindowsEXEMSGLen,d3		; Get length message
	lea	NotWindowsEXEMSG,a0		; Get pointer to error message
	bra	CloseFileAndDosLibPrintMSG	; Print error message

ReadFailed
	move.l	ReadFailedMSGLen,d3		; Get length message
	lea	ReadFailedMSG,a0		; Get pointer to error message
	addq.l	#4,sp				; POP return address from stack
	bra	CloseFileAndDosLibPrintMSG	; Print error message

SeekNotSuccesful
	move.l	SeekNotSuccesMSGLen,d3		; Get length message
	lea	SeekNotSuccesMSG,a0		; Get pointer to error message
	addq.l	#4,sp				; POP return address from stack
	bra	CloseFileAndDosLibPrintMSG	; Print error message


CloseFileAndDosLibPrintMSG
	move.l	a0,a3			; Save message pointer
	move.l	FileHandle(a5),d1	; Get file handle
	move.l	DosBase(a5),a6		; Get dos lib base address
	jsr	_LVOClose(a6)		; Close file
	move.l	a3,a0			; Get message pointer

PrintErrorAndReturnToDos
	bsr	PrintMSG		; Print error message

	move.l	a6,a1			; Pointer to dos.library
	move.l	AbsExecBase,a6		; Get exec base address
	jsr	_LVOCloseLibrary(a6)	; Close dos.library

	move.l	a5,a1			; Free temporary storage memory
	move.l	TempBufferLen(a5),d0	; Get length of temporary buffer
	jsr	_LVOFreeMem(a6)		; Free the memory

	moveq.l	#0,d0			; Return code = 0

	rts				; Return to DOS


DosNotOpen
	move.l	a5,a1			; Free temporary storage memory
	move.l	TempBufferLen(a5),d0	; Get size of memory block
	jsr	_LVOFreeMem(a6)		; Free the memory

	move.l	#20,d0			; Error code = 20 not open
	rts				; Exit


TempBufNoAlloc
	move.l	#30,d0			; Error code = 30 buffer not allocated
	rts				; Exit




**=====================================================================================================
**
**    The wonderful data section
**
**=====================================================================================================


;		SECTION	data,DATA


DosLibName
	dc.b	"dos.library",NULL
FileName
	dc.b	"TaskMan.exe",NULL



** Error messages

FileNotOpenMSGLen
	dc.l	FileNotOpenMSGEnd-FileNotOpenMSG
FinishMSGLen
	dc.l	FinishMSGEnd-FinishMSG
MemoryNotAllocatedMSGLen
	dc.l	MemoryNotAllocatedMSGEnd-MemoryNotAllocatedMSG
NotWindowsEXEMSGLen
	dc.l	NotWindowsEXEMSGEnd-NotWindowsEXEMSG
ReadFailedMSGLen
	dc.l	ReadFailedMSGEnd-ReadFailedMSG
SeekNotSuccesMSGLen
	dc.l	SeekNotSuccesMSGEnd-SeekNotSuccesMSG

FileNotOpenMSG
	dc.b	"File did not open succesfully.",NewLine
FileNotOpenMSGEnd
FinishMSG
	dc.b	NewLine,"Program completed succesfully.",NewLine
FinishMSGEnd
MemoryNotAllocatedMSG
	dc.b	"Memory not allocated, not enough memory perhaps?",NewLine,NULL
MemoryNotAllocatedMSGEnd
NotWindowsEXEMSG
	dc.b	"This is not a windows NE file.",NewLine
NotWindowsEXEMSGEnd
ReadFailedMSG
	dc.b	"Read operation failed.",NewLine
ReadFailedMSGEnd
SeekNotSuccesMSG
	dc.b	"Seek operation unsuccesful",NewLine
SeekNotSuccesMSGEnd




** Data printing messages

AccessTypeMSGLen
	dc.l	AccessTypeMSGEnd-AccessTypeMSG
AutoDataSegMSGLen
	dc.l	AutoDataSegMSGEnd-AutoDataSegMSG
CodeMSGLen
	dc.l	CodeMSGEnd-CodeMSG
DataMSGLen
	dc.l	DataMSGEnd-DataMSG
EntryMSGLen
	dc.l	EntryMSGEnd-EntryMSG
EntryConstantMSGLen
	dc.l	EntryConstantMSGEnd-EntryConstantMSG
EntryEntriesMSGLen
	dc.l	EntryEntriesMSGEnd-EntryEntriesMSG
EntryEntriesSegMSGLen
	dc.l	EntryEntriesSegMSGEnd-EntryEntriesSegMSG
EntryExportedMSGLen
	dc.l	EntryExportedMSGEnd-EntryExportedMSG
EntryFixOffsetMSGLen
	dc.l	EntryFixOffsetMSGEnd-EntryFixOffsetMSG
EntryFixSegRecrMSGLen
	dc.l	EntryFixSegRecrMSGEnd-EntryFixSegRecrMSG
EntryMoveOffsetMSGLen
	dc.l	EntryMoveOffsetMSGEnd-EntryMoveOffsetMSG
EntryMoveRecrMSGLen
	dc.l	EntryMoveRecrMSGEnd-EntryMoveRecrMSG
EntryMoveSegMSGLen
	dc.l	EntryMoveSegMSGEnd-EntryMoveSegMSG
EntryNullEntriesMSGLen
	dc.l	EntryNullEntriesMSGEnd-EntryNullEntriesMSG
EntryNumberMSGLen
	dc.l	EntryNumberMSGEnd-EntryNumberMSG
EntryTableMSGLen
	dc.l	EntryTableMSGEnd-EntryTableMSG
ExecutableTypeMSGLen
	dc.l	ExecutableTypeMSGEnd-ExecutableTypeMSG
ExecuteOnlyMSGLen
	dc.l	ExecuteOnlyMSGEnd-ExecuteOnlyMSG
FileDataModelMSGLen
	dc.l	FileDataModelMSGEnd-FileDataModelMSG
FileSegLengthMSGLen
	dc.l	FileSegLengthMSGEnd-FileSegLengthMSG
FixedMSGLen
	dc.l	FixedMSGEnd-FixedMSG
FullStopMSGLen
	dc.l	FullStopMSGEnd-FullStopMSG
GlobalMSGLen
	dc.l	GlobalMSGEnd-GlobalMSG
InitCSIPMSGLen
	dc.l	InitCSIPMSGEnd-InitCSIPMSG
InitLocalHeapMSGLen
	dc.l	InitLocalHeapMSGEnd-InitLocalHeapMSG
InitStackSizeMSGLen
	dc.l	InitStackSizeMSGEnd-InitStackSizeMSG
IsSelfLoadingMSGLen
	dc.l	IsSelfLoadingMSGEnd-IsSelfLoadingMSG
LibraryModuleMSGLen
	dc.l	LibraryModuleMSGEnd-LibraryModuleMSG
LoaderAllocMSGLen
	dc.l	LoaderAllocMSGEnd-LoaderAllocMSG
LoadOnCallMSGLen
	dc.l	LoadOnCallMSGEnd-LoadOnCallMSG
LoByteMSGLen
	dc.l	LoByteMSGEnd-LoByteMSG
MinAllocForSegMSGLen
	dc.l	MinAllocForSegMSGEnd-MinAllocForSegMSG
ModTableEntriesMSGLen
	dc.l	ModTableEntriesMSGEnd-ModTableEntriesMSG
ModuleDescribeMSGLen
	dc.l	ModuleDescribeMSGEnd-ModuleDescribeMSG
ModuleNameMSGLen
	dc.l	ModuleNameMSGEnd-ModuleNameMSG
MoveableMSGLen
	dc.l	MoveableMSGEnd-MoveableMSG
MultipleDataModelMSGLen
	dc.l	MultipleDataModelMSGEnd-MultipleDataModelMSG
NewLineMSGLen
	dc.l	NewLineMSGEnd-NewLineMSG
NoMSGLen
	dc.l	NoMSGEnd-NoMSG
NoAutoDataModelMSGLen
	dc.l	NoAutoDataModelMSGEnd-NoAutoDataModelMSG
NoDataInSegmentMSGLen
	dc.l	NoDataInSegmentMSGEnd-NoDataInSegmentMSG
NoLocalHeapMSGLen
	dc.l	NoLocalHeapMSGEnd-NoLocalHeapMSG
NonResNamTableMSGLen
	dc.l	NonResNamTableMSGEnd-NonResNamTableMSG
NonShareMSGLen
	dc.l	NonShareMSGEnd-NonShareMSG
NormalExecutableMSGLen
	dc.l	NormalExecutableMSGEnd-NormalExecutableMSG
OffsMSGLen
	dc.l	OffsMSGEnd-OffsMSG
Offs32MSGLen
	dc.l	Offs32MSGEnd-Offs32MSG
OutOfMemMSGLen
	dc.l	OutOfMemMSGEnd-OutOfMemMSG
PreLoadMSGLen
	dc.l	PreLoadMSGEnd-PreLoadMSG
PrintRelocationMSGLen
	dc.l	PrintRelocationMSGEnd-PrintRelocationMSG
PtrMSGLen
	dc.l	PtrMSGEnd-PtrMSG
Ptr48MSGLen
	dc.l	Ptr48MSGEnd-Ptr48MSG
ReadOnlyMSGLen
	dc.l	ReadOnlyMSGEnd-ReadOnlyMSG
RelocForSegMSGLen
	dc.l	RelocForSegMSGEnd-RelocForSegMSG
RelocReadFailedMSGLen
	dc.l	RelocReadFailedMSGEnd-RelocReadFailedMSG
RelocTypeUnknMSGLen
	dc.l	RelocTypeUnknMSGEnd-RelocTypeUnknMSG
ResNamTableMSGLen
	dc.l	ResNamTableMSGEnd-ResNamTableMSG
ResourceTypeMSGLen
	dc.l	ResourceTypeMSGEnd-ResourceTypeMSG
RevisionNumMSGLen
	dc.l	RevisionNumMSGEnd-RevisionNumMSG
rnFlagsMSGLen
	dc.l	rnFlagsMSGEnd-rnFlagsMSG
rnFlagsMoveableMSGLen
	dc.l	rnFlagsMoveableMSGEnd-rnFlagsMoveableMSG
rnFlagsPreloadMSGLen
	dc.l	rnFlagsPreloadMSGEnd-rnFlagsPreloadMSG
rnFlagsPureMSGLen
	dc.l	rnFlagsPureMSGEnd-rnFlagsPureMSG
rnIDMSGLen
	dc.l	rnIDMSGEnd-rnIDMSG
rnOffsetMSGLen
	dc.l	rnOffsetMSGEnd-rnOffsetMSG
rnLengthMSGLen
	dc.l	rnLengthMSGEnd-rnLengthMSG
rscAlignShiftMSGLen
	dc.l	rscAlignShiftMSGEnd-rscAlignShiftMSG
RscTableOffsetMSGLen
	dc.l	RscTableOffsetMSGEnd-RscTableOffsetMSG
RT_AcceleratorMSGLen
	dc.l	RT_AcceleratorMSGEnd-RT_AcceleratorMSG
RT_BitmapMSGLen
	dc.l	RT_BitmapMSGEnd-RT_BitmapMSG
RT_CursorMSGLen
	dc.l	RT_CursorMSGEnd-RT_CursorMSG
RT_DialogMSGLen
	dc.l	RT_DialogMSGEnd-RT_DialogMSG
RT_FontMSGLen
	dc.l	RT_FontMSGEnd-RT_FontMSG
RT_FontDirMSGLen
	dc.l	RT_FontDirMSGEnd-RT_FontDirMSG
RT_Group_CursorMSGLen
	dc.l	RT_Group_CursorMSGEnd-RT_Group_CursorMSG
RT_Group_IconMSGLen
	dc.l	RT_Group_IconMSGEnd-RT_Group_IconMSG
RT_IconMSGLen
	dc.l	RT_IconMSGEnd-RT_IconMSG
RT_MenuMSGLen
	dc.l	RT_MenuMSGEnd-RT_MenuMSG
RT_RCDataMSGLen
	dc.l	RT_RCDataMSGEnd-RT_RCDataMSG
RT_StringMSGLen
	dc.l	RT_StringMSGEnd-RT_StringMSG
RT_UnkRscTypeMSGLen
	dc.l	RT_UnkRscTypeMSGEnd-RT_UnkRscTypeMSG
RT_VersionInfoMSGLen
	dc.l	RT_VersionInfoMSGEnd-RT_VersionInfoMSG
rtResourceCountMSGLen
	dc.l	rtResourceCountMSGEnd-rtResourceCountMSG
SegDiscardMSGLen
	dc.l	SegDiscardMSGEnd-SegDiscardMSG
SegmentLoadedMSGLen
	dc.l	SegmentLoadedMSGEnd-SegmentLoadedMSG
SegmentLoadTypeMSGLen
	dc.l	SegmentLoadTypeMSGEnd-SegmentLoadTypeMSG
SegmentNumberMSGLen
	dc.l	SegmentNumberMSGEnd-SegmentNumberMSG
SegmentTypeMSGLen
	dc.l	SegmentTypeMSGEnd-SegmentTypeMSG
SegmentRelocMSGLen
	dc.l	SegmentRelocMSGEnd-SegmentRelocMSG
SegmentSharingMSGLen
	dc.l	SegmentSharingMSGEnd-SegmentSharingMSG
SegRelocationMSGLen
	dc.l	SegRelocationMSGEnd-SegRelocationMSG
SegTableEntryNumMSGLen
	dc.l	SegTableEntryNumMSGEnd-SegTableEntryNumMSG
SegTableOffsetMSGLen
	dc.l	SegTableOffsetMSGEnd-SegTableOffsetMSG
SelectMSGLen
	dc.l	SelectMSGEnd-SelectMSG
ShareMSGLen
	dc.l	ShareMSGEnd-ShareMSG
SingleDataModelMSGLen
	dc.l	SingleDataModelMSGEnd-SingleDataModelMSG
SixBlankSpacesMSGLen
	dc.l	SixBlankSpacesMSGEnd-SixBlankSpacesMSG
SixtyFourKMSGLen
	dc.l	SixtyFourKMSGEnd-SixtyFourKMSG
StackAddressMSGLen
	dc.l	StackAddressMSGEnd-StackAddressMSG
TypeOffsTargetMSGLen
	dc.l	TypeOffsTargetMSGEnd-TypeOffsTargetMSG
VersionNumMSGLen
	dc.l	VersionNumMSGEnd-VersionNumMSG
YesMSGLen
	dc.l	YesMSGEnd-YesMSG

AccessTypeMSG
	dc.b	"  Access type                       :    "
AccessTypeMSGEnd
AutoDataSegMSG
	dc.b	"Automatic data segment number     :    "
AutoDataSegMSGEnd
CodeMSG
	dc.b	"      CODE"
CodeMSGEnd
DataMSG
	dc.b	"      DATA"
DataMSGEnd
EntryMSG
	dc.b	"Entry "
EntryMSGEnd
EntryConstantMSG
	dc.b	NewLine,"Constant bundle  :  "
EntryConstantMSGEnd
EntryEntriesMSG
	dc.b	" entries.",NewLine
EntryEntriesMSGEnd
EntryEntriesSegMSG
	dc.b	" entries.   Segment : "
EntryEntriesSegMSGEnd
EntryExportedMSG
	dc.b	"    Exported    "
EntryExportedMSGEnd
EntryFixOffsetMSG
	dc.b	"   Offset : "
EntryFixOffsetMSGEnd
EntryFixSegRecrMSG
	dc.b	NewLine,"Fixed segment records : "
EntryFixSegRecrMSGEnd
EntryMoveOffsetMSG
	dc.b	"   Offset : "
EntryMoveOffsetMSGEnd
EntryMoveRecrMSG
	dc.b	NewLine,"Movable segment records : "
EntryMoveRecrMSGEnd
EntryMoveSegMSG
	dc.b	"   Segment : "
EntryMoveSegMSGEnd
EntryNullEntriesMSG
	dc.b	NewLine,"Null entries : "
EntryNullEntriesMSGEnd
EntryNumberMSG
	dc.b	NewLine,"    Entry "
EntryNumberMSGEnd
EntryTableMSG
	dc.b	NewLine,"Entry table  : ",NewLine
EntryTableMSGEnd
ExecutableTypeMSG
	dc.b	"Executable type                   :    "
ExecutableTypeMSGEnd
ExecuteOnlyMSG
	dc.b	"      EXECUTEONLY"
ExecuteOnlyMSGEnd
FileDataModelMSG
	dc.b	"Data model type                   :    "
FileDataModelMSGEnd
FileSegLengthMSG
	dc.b	"  Segment length in file            :    "
FileSegLengthMSGEnd
FixedMSG
	dc.b	"      FIXED"
FixedMSGEnd
FullStopMSG
	dc.b	"."
FullStopMSGEnd
GlobalMSG
	dc.b	"GLOBAL",NewLine
GlobalMSGEnd
InitCSIPMSG
	dc.b	"Initial CS:IP                     :    "
InitCSIPMSGEnd
InitLocalHeapMSG
	dc.b	"Initial local heap size           :    "
InitLocalHeapMSGEnd
InitStackSizeMSG
	dc.b	"Initial stack size                :    "
InitStackSizeMSGEnd
IsSelfLoadingMSG
	dc.b	"Self loading application?         :    "
IsSelfLoadingMSGEnd
LibraryModuleMSG
	dc.b	"Library module",NewLine
LibraryModuleMSGEnd
LoaderAllocMSG
	dc.b	"Loader allocates memory for segment.",NewLine
LoaderAllocMSGEnd
LoadOnCallMSG
	dc.b	"      LOADONCALL"
LoadOnCallMSGEnd
LoByteMSG
	dc.b	"    LoByte  "
LoByteMSGEnd
MinAllocForSegMSG
	dc.b	"  Minimum allocation for segment    :    "
MinAllocForSegMSGEnd
ModuleDescribeMSG
	dc.b	NewLine,"Module description                :    "
ModuleDescribeMSGEnd
ModuleNameMSG
	dc.b	NewLine,"Module name                       :    "
ModuleNameMSGEnd
ModTableEntriesMSG
	dc.b	"Entries in module reference table :    "
ModTableEntriesMSGEnd
MoveableMSG
	dc.b	"      MOVEABLE"
MoveableMSGEnd
MultipleDataModelMSG
	dc.b	"MULTIPLEDATA",NewLine
MultipleDataModelMSGEnd
NewLineMSG
	dc.b	NewLine
NewLineMSGEnd
NoMSG
	dc.b	"NO",NewLine
NoMSGEnd
NoAutoDataModelMSG
	dc.b	"NOAUTODATA",NewLine
NoAutoDataModelMSGEnd
NoDataInSegmentMSG
	dc.b	"No data provided for this segment.",NewLine
NoDataInSegmentMSGEnd
NoLocalHeapMSG
	dc.b	"No initial allocation",NewLine
NoLocalHeapMSGEnd
NonResNamTableMSG
	dc.b	NewLine,"  Non-resident name table :",NewLine
NonResNamTableMSGEnd
NonShareMSG
	dc.b	"      IMPURE"
NonShareMSGEnd
NormalExecutableMSG
	dc.b	"Normal executable",NewLine
NormalExecutableMSGEnd
OffsMSG
	dc.b	"    Offs    "
OffsMSGEnd
Offs32MSG
	dc.b	"    Offs-32 "
Offs32MSGEnd
OutOfMemMSG
	dc.b	NewLine,"Out of memory.",NewLine
OutOfMemMSGEnd
PreLoadMSG
	dc.b	"      PRELOAD"
PreLoadMSGEnd
PrintRelocationMSG
	dc.b	"Segment relocations",NewLine
PrintRelocationMSGEnd
PtrMSG
	dc.b	"    PTR     "
PtrMSGEnd
Ptr48MSG
	dc.b	"    PTR-48  "
Ptr48MSGEnd
ReadOnlyMSG
	dc.b	"      READONLY"
ReadOnlyMSGEnd
RelocForSegMSG
	dc.b	"  Relocations for segment : "
RelocForSegMSGEnd
RelocReadFailedMSG
	dc.b	"Read from file failed!"
RelocReadFailedMSGEnd
RelocTypeUnknMSG
	dc.b	"Unknown relocation type. Send me this file to df114@city.ac.uk read docs!!!!"
RelocTypeUnknMSGEnd
ResNamTableMSG
	dc.b	NewLine,"  Resident-name table :",NewLine
ResNamTableMSGEnd
ResourceTypeMSG
	dc.b	NewLine,NewLine,NewLine,"  Resource type                     :    "
ResourceTypeMSGEnd
RevisionNumMSG
	dc.b	"Linker revision number            :    "
RevisionNumMSGEnd
rnFlagsMSG
	dc.b	"    Resource attributes",NewLine
rnFlagsMSGEnd
rnFlagsMoveableMSG
	dc.b	"       MOVEABLE"
rnFlagsMoveableMSGEnd
rnFlagsPreloadMSG
	dc.b	"       PRELOAD "
rnFlagsPreloadMSGEnd
rnFlagsPureMSG
	dc.b	"       PURE"
rnFlagsPureMSGEnd
rnIDMSG
	dc.b	NewLine,"    Resource ID                           :    "
rnIDMSGEnd
rnLengthMSG
	dc.b	"    Resource length                       :    "
rnLengthMSGEnd
rnOffsetMSG
	dc.b	NewLine,"    Resource offset                       :    "
rnOffsetMSGEnd
rscAlignShiftMSG
	dc.b	"Resource align shift              :    "
rscAlignShiftMSGEnd
RscTableOffsetMSG
	dc.b	NewLine,"Offset to resource table          :    "
RscTableOffsetMSGEnd
RT_AcceleratorMSG
	dc.b	"RT_ACCELERATOR",NewLine
RT_AcceleratorMSGEnd
RT_BitmapMSG
	dc.b	"RT_BITMAP",NewLine
RT_BitmapMSGEnd
RT_CursorMSG
	dc.b	"RT_CURSOR",NewLine
RT_CursorMSGEnd
RT_DialogMSG
	dc.b	"RT_DIALOG",NewLine
RT_DialogMSGEnd
RT_FontMSG
	dc.b	"RT_FONT",NewLine
RT_FontMSGEnd
RT_FontDirMSG
	dc.b	"RT_FONTDIR",NewLine
RT_FontDirMSGEnd
RT_Group_CursorMSG
	dc.b	"RT_GROUP_CURSOR",NewLine
RT_Group_CursorMSGEnd
RT_Group_IconMSG
	dc.b	"RT_GROUP_ICON",NewLine
RT_Group_IconMSGEnd
RT_IconMSG
	dc.b	"RT_ICON",NewLine
RT_IconMSGEnd
RT_MenuMSG
	dc.b	"RT_MENU",NewLine
RT_MenuMSGEnd
RT_RCDataMSG
	dc.b	"RT_RCDATA",NewLine
RT_RCDataMSGEnd
RT_StringMSG
	dc.b	"RT_STRING",NewLine
RT_StringMSGEnd
RT_UnkRscTypeMSG
	dc.b	"Unknown resource type "
RT_UnkRscTypeMSGEnd
RT_VersionInfoMSG
	dc.b	"Version info?",NewLine
RT_VersionInfoMSGEnd
rtResourceCountMSG
	dc.b	"  Resource count                    :    "
rtResourceCountMSGEnd
SegDiscardMSG
	dc.b	"      DISCARDABLE"
SegDiscardMSGEnd
SegmentLoadedMSG
	dc.b	"Segment is loaded at load time."
SegmentLoadedMSGEnd
SegmentLoadTypeMSG
	dc.b	"  Segment loaded type               :    "
SegmentLoadTypeMSGEnd
SegmentNumberMSG
	dc.b	NewLine,NewLine,"Data for segment number : "
SegmentNumberMSGEnd
SegmentRelocMSG
	dc.b	"  Segment relocation                :    "
SegmentRelocMSGEnd
SegmentSharingMSG
	dc.b	"  Segment sharing                   :    "
SegmentSharingMSGEnd
SegmentTypeMSG
	dc.b	"  Segment flags:",NewLine
SegmentTypeMSGEnd
SegRelocationMSG
	dc.b	"      RELOCATIONS"
SegRelocationMSGEnd
SegTableEntryNumMSG
	dc.b	"Entries in segment table          :    "
SegTableEntryNumMSGEnd
SegTableOffsetMSG
	dc.b	"Offset to segment table           :    "
SegTableOffsetMSGEnd
SelectMSG
	dc.b	"    Select  "
SelectMSGEnd
ShareMSG
	dc.b	"      PURE"
ShareMSGEnd
SingleDataModelMSG
	dc.b	"SINGLEDATA",NewLine
SingleDataModelMSGEnd
SixBlankSpacesMSG
	dc.b	"      "
SixBlankSpacesMSGEnd
SixtyFourKMSG
	dc.b	"64k",NewLine
SixtyFourKMSGEnd
StackAddressMSG
	dc.b	"Initial SS:SP                     :    "
StackAddressMSGEnd
TypeOffsTargetMSG
	dc.b	"    type    offset     target",NewLine
TypeOffsTargetMSGEnd
VersionNumMSG
	dc.b	NewLine,"Linker version number             :    "
VersionNumMSGEnd
YesMSG
	dc.b	"YES",NewLine
YesMSGEnd


	END
