;	DDF - Druckem mit DFonts
;	© 1990 Ebsche Hermesmann Junior (EHJ)

;	Aufruf: DDF <Filename>
;	<Filename> muß ein Textfile im 'DFONTS'-Format sein

ExecBase=4

;---EXEC-Funktionen
AllocMem=-198
FreeMem=-210
FindTask=-294
AddPort=-354
RemPort=-360
OpenLibrary=-552
CloseLibrary=-414
OpenDevice=-444
CloseDevice=-450
DoIO=-456

;---DOS-Funktionen
Open=-30
Close=-36
Read=-42
Write=-48
Output=-60
Lock=-84
Examine=-102
UnLock=-90

g:	move.b	#0,-1(a0,d0)	;Nullbyte an Filenamen anhängen
	subq.l	#1,d0		;D0 = Länge Filename (ohne 0)
	move.l	a0,a5		;Adresse Name und
	move.l	d0,d7		;Länge Name merken

;---Dos öffnen
	lea	DosName,a1	;'dos.library'
	moveq	#0,d0		;Version egal
	move.l	ExecBase,a6	;
	jsr	OpenLibrary(a6)	;öffnen
	move.l	d0,DosBase
	bne.s	w1		;weiter wenn ok, sonst

	rts			;zurück

;---Ausgabekanal holen
w1:	move.l	d0,a6		;DosBase nach A6
	jsr	Output(a6)	;Output holen
	move.l	d0,Outhd	;und merken
	beq	TUESS		;hat nicht geklappt

;---Überschrift ausgeben
	lea	Text1,a0
	bsr	Text

;---Suche ersten Buchstaben im Filenamen
	move.l	d7,d0		;Länge Filename nach D0
	beq	noName		;Länge = 0, Fehler

	move.l	a5,a0		;Filename ab (A0)
SuchNa:	cmp.b	#" ",(a0)+	;Space ?
	bne.s	NameDa		;nein, Name fängt an

	dbra	d0,SuchNa	;sonst weiter 1.Buchstaben suchen

	bra	noName 		;NUR Leerzeichen, Fehler

;---Name gefunden, Adresse merken
NameDa:	tst.b	-(a0)		;A0 auf ersten Buchstaben
	move.l	a0,Filename	;Adresse merken

;---PAR: öffnen
	sub.l	a1,a1		;Laufenden
	move.l	ExecBase,a6	;Task
	jsr	FindTask(a6)	;suchen
	move.l	d0,Reply+16	;und in Replyport eintragen
	lea	Reply,a1	;Replyport
	jsr	AddPort(a6)	;anmelden
	lea	IO,a1		;In I/O-Struktur
	move.l	#Reply,14(a1)	;Adresse Replyport eintragen
	moveq	#0,d0		;Keine
	moveq	#0,d1		;Flags
	moveq	#0,d2		;
	lea	PARName,a0	;'parallel.device'
	jsr	OpenDevice(a6)	;öffnen
	move.l	d0,PARhd	;D0 merken
	beq.s	holFIB		;geklappt, weiter, sonst

;---Parallel.Device konnte nicht geöffnet werden
	lea	Reply,a1	;Replyport
	jsr	RemPort(a6)	;wieder abmelden
	bra	noPAR		;und Fehler ausgeben

;---Speicher für FileInfoBlock und Filenamen reservieren
;---260 Bytes FileInfoBlock, 10 * 74 Bytes Filenamen
holFIB:	move.l	#1000,d0	;1000 Bytes
	bsr	Reservieren	;reservieren
	move.l	d0,FIB		;Header merken
	beq	noFree		;hat nicht geklappt, Fehler

	move.l	d0,a0		;Im RAM ab A0
	add.l	#260,a0		;A0 hinter FIB setzen
	lea	DFONTS,a1	;DFONTS ab (A1)
	moveq	#9,d7		;10 mal
	moveq	#74,d0		;je 74 Bytes
Loop2:	move.l	a0,(a1)+	;Adresse eintragen
	add.l	d0,a0		;nächste Adresse in A0
	dbra	d7,Loop2	;und Die eintragen

;---Filelänge holen
	move.l	Filename,d1	;Filelänge
	bsr	FileInfo	;(in D6) besorgen
	tst.b	d0		;Fehler ?
	bne	noFile		;ja, Fehler ausgeben

;---Filelänge im RAM reservieren
	cmp.l	#65000,d6	;Filelänge > 65000 ?
	bgt	noDFF		;dann Fehler

	move.l	d6,d0		;Filelänge
	bsr	Reservieren	;reservieren
	move.l	d0,Puffer	;Ab 'Puffer' im Speicher
	beq	noFree		;hat nicht geklappt

	move.l	d6,Laenge	;Pufferlänge merken

;---File öffnen und in Puffer einlesen
	move.l	Filename,d1	;File
	bsr	OpenFile	;öffnen
	move.l	Filehd,d1	;Header nach D1
	beq	noFile		;D1 = 0, dann Fehler

	move.l	d6,d3		;Gesamtes File
	move.l	Puffer,d2	;in Puffer
	move.l	DosBase,a6
	jsr	Read(a6)	;einlesen
	cmp.l	d3,d0		;Wirklich alle Bytes gelesen ?
	bne	noFile		;nein, Fehler

;---File schließen
	bsr	CloseFile

;---Testen, ob '##DFONTS' in Titelzeile
	move.l	Puffer,a5	;Pufferanfang ab (A5)
	cmp.l	#"##DF",(a5)+	;'##DF' ?
	bne	noDFF		;nein, kein DFonts-File

	cmp.l	#"ONTS",(a5)+	;'ONTS' ?
	bne	noDFF		;nein, kein DFonts-File

;---In Titelzeile steht '##DFONTS'
	moveq	#0,d7		;D7 (Fontzähler) löschen
	lea	DFONTS,a0	;ab (A0) Adressen, wo die
nextFo:	move.l	(a0)+,a1	;Fontnamen eingetragen werden
	tst.b	(a5)+		;Linefeed überlesen
	cmp.b	#"#",(a5)+	;'#' ?
	bne.s	wDF		;nein, weiter

	cmp.b	#"#",(a5)+	;'#' ?
	bne.s	wDF		;nein, weiter

;---Pfadnamen der DFonts einlesen
FoKop:	cmp.b	#"#",(a5)	;'#' ?
	beq.s	nFont		;ja, weiter

	move.b	(a5)+,(a1)+	;sonst Byte kopieren
	bra.s	FoKop		;und das Nächste

nFont:	move.b	#0,(a1)		;Nullbyte anhängen
	tst.b	(a5)+		;Linefeed überlesen
	addq.b	#1,d7		;Anzahl DFonts erhöhen
	cmp.b	#10,d7		;schon 11 DFonts ?
	blt.s	nextFo		;nein, weiter

	tst.b	(a5)+		;Linefeed überlesen
wDF:	tst.b	d7		;Gibt's DFonts ?
	beq	noDFF		;nein, Fehler

;---Filelängen der DFonts holen
	tst.b	-(a5)		;Aktuelle Pufferadresse in A5
	move.b	d7,FontAnz+1	;Anzahl merken
	subq.b	#1,d7		;-1 für Loop
	moveq	#0,d4		;In D4 Gesamtlänge
	lea	DFONTS,a4	;Filenamen ab (A4)
	lea	Laengen,a3	;Längen ab (A3)
FoLoop:	move.l	(a4)+,Filename	;Filename nach D1
	bsr	FileInfo	;Länge nach D6 holen
	tst.b	d0
	bne	noFile		;hat nicht geklappt

	add.l	d6,d4		;Länge zu D4 addieren
	move.l	d6,(a3)+	;Länge merken
	dbra	d7,FoLoop	;Nächste Länge holen

;---Speicher reservieren
	move.l	d4,d0		;Gesamtlänge
	bsr	Reservieren	;reservieren
	move.l	d0,FontRAM	;im Speicher ab 'FontRAM'
	beq	noFree		;hat nicht geklappt

;---Alle Files einlesen
	move.l	d4,DFLaenge	;Gesamtlänge merken
	move.w	FontAnz,d7	;Anzahl
	subq.b	#1,d7		;-1 für Loop
	move.l	FontRAM,a3	;RAM ab (A3)
	lea	Laengen,a2	;Filelängen ab (A2)
	lea	DFONTS,a4	;Filenamen ab (A4)
FoLoo2:	move.l	(a4)+,d1	;File
	bsr	OpenFile	;öffnen
	move.l	Filehd,d1	;Header merken
	beq	noFile		;hat nicht geklappt

	move.l	a3,d2		;Ab RAM-Adresse A3
	move.l	(a2)+,d3	;Länge D3
	jsr	Read(a6)	;einlesen
	cmp.l	d3,d0		;Wirklich D3-Bytes gelesen ?
	bne	noFile		;nein, Fehler

	add.l	d3,a3		;Länge zu RAM-Adresse
	bsr	CloseFile	;File schließen
	dbra	d7,FoLoo2	;und Nächstes holen

	lea	Text10,a0	;'Auf geht's'
	bsr	Text		;ausgeben

;---Umwandeln ab Puffer (A5)
	move.l	a5,d0		;D0 = Aktuelle Adresse
	sub.l	Puffer,d0	;- Pufferanfang
	move.l	Laenge,d7	;Länge
	sub.l	d0,d7		;- Länge von 'DFONTS' etc.
	subq.l	#1,d7		;- 1 für Loop

;---Testen, ob '**0' - '**9' im Text
DrLoop:	move.b	(a5)+,d0	;Drei
	move.b	(a5)+,d1	;Bytes
	move.b	(a5)+,d2	;holen
	cmp.b	#"*",d0		;'*' in D0 ?
	bne	weiter		;nein, normal weiter

	cmp.b	#"*",d1		;'*' in D1 ?
	bne	weiter		;nein, weiter

	cmp.b	#"0",d2		;'0' in D2 ?
	bmi	weiter		;nein, kleiner, weiter

	cmp.b	#"9",d2		;'9' in D2 ?
	bgt	weiter		;nein, größer, weiter

;---'0' - '9' in dezimal umrechnen
	sub.b	#48,d2		;ASCII in dezimal wandeln
	moveq	#0,d3		;D3 löschen
	move.b	d2,d3		;Dezimalzahl nach D3

;---Zahl größer als überhaupt vorhandene Anzahl DFonts ?
	cmp.b	FontAnz+1,d3	;D3 < Anzahl Fonts ?
	blt.s	NrOK		;dann weiter, sonst

	moveq	#0,d3		;Font0 setzen

;---DFont zum Drucker schicken
NrOK:	tst.b	d3		;Font0 ?
	beq.s	wNr		;dann weiter

	subq.b	#1,d3		;D3 - 1 für Loop
	move.l	FontRAM,a3	;FontRAM ab A3
	lea	Laengen,a1	;Längen ab (A1)
Loop1:	add.l	(a1)+,a3	;RAM = RAM + Länge
	dbra	d3,Loop1

	move.l	(a1),d6		;D6 = Länge
	bra.s	toPAR		;Font zum Drucker

;---Font0 gewünscht
wNr:	move.l	FontRAM,a3	;RAM-Adresse
	move.l	Laengen,d6	;Länge

;---File zum Drucker schicken
toPAR:	bsr	Print		;D6 Bytes ab A3 zum Drucker schicken

;---Bytezähler um 3 Bytes ('**1') verringern
	subq.l	#3,d7
	tst.l	d7		;D7 jetzt 0 ?
	beq	DasWars		;dann war's das

	bra.s	nixDF		;sonst weiter

weiter:	subq.l	#3,a5		;Puffer wieder 3 Bytes zurücksetzen

;---Ein Byte umwandeln (Ä Ö Ü @ ä ö ü ß )
nixDF:	move.b	(a5)+,d0	;Byte holen
	cmp.b	#10,d0		;Linefeed ?
	beq.s	OK		;dann OK

	cmp.b	#13,d0		;RETURN ?
	bne.s	Ae

	move.b	#10,d0		;dann Linefeed
	bra.s	OK

Ae:	cmp.b	#196,d0		;Ä ?
	bne.s	Oe

	move.b	#91,d0
	bra.s	OK

Oe:	cmp.b	#214,d0		;Ö ?
	bne.s	Ue

	move.b	#92,d0
	bra.s	OK

Ue:	cmp.b	#220,d0		;Ü ?
	bne.s	Sz

	move.b	#93,d0
	bra.s	OK

Sz:	cmp.b	#223,d0		;ß ?
	bne.s	Aek

	move.b	#126,d0
	bra.s	OK

Aek:	cmp.b	#228,d0		;ä ?
	bne.s	Oek

	move.b	#123,d0
	bra.s	OK

Oek:	cmp.b	#246,d0		;ö ?
	bne.s	Uek

	move.b	#124,d0
	bra.s	OK

Uek:	cmp.b	#252,d0		;ü ?
	bne.s	Gr126

	move.b	#125,d0
	bra.s	OK

Gr126:	cmp.b	#126,d0		;> 126 ?
	bpl.s	Nicht		;dann nicht drucken

	cmp.b	#32,d0		;< 32 ?
	bmi.s	Nicht		;dann nicht drucken

;---Byte in Ausgabepuffer und drucken
OK:	move.b	d0,Byte		;D0 in Ausgabepuffer
Nicht:	bsr	Print1		;Byte ausgeben

;---Testen, ob linke Maustaste gedrückt wird - Abbruch
	btst	#6,$bfe001	;Taste gedrückt ?
	beq.s	DasWars		;dann Programm beenden

	dbra	d7,DrLoop	;sonst nächstes Byte holen

;---Zum Schluß ein Linefeed und Programm beenden
DasWars:
	move.b	#10,Byte	;Linefeed
	bsr	Print1		;zum Schluß ausgeben

;---Programm beenden
Ende:	move.l	DFLaenge,d0	;Gesamtlänge DFont-RAM
	beq.s	Ende2		;ist 0, NICHT freigeben

	move.l	FontRAM,a1	;FontRAM
	bsr	Freigeben	;freigeben

Ende2:	move.l	Laenge,d0	;Länge 'Puffer' im RAM
	beq.s	Ende3		;0 ?, dann NICHT freigeben

	move.l	Puffer,a1	;Puffer
	bsr	Freigeben	;freigeben

Ende3:	tst.l	FIB		;Gibt's 'n FileInfoBlock ?
	beq.s	Ende4		;nein, weiter

	move.l	FIB,a1		;FileInfoBlock/Filenamen
	move.l	#1000,d0	;1000 Bytes
	bsr	Freigeben	;freigeben

Ende4:	bsr	CloseFile	;File schließen (falls noch offen)

	bsr	ClosePAR	;PAR: schließen (falls offen)

TUESS:	move.l	DosBase,a1	;Doslibrary
	move.l	ExecBase,a6
	jmp	CloseLibrary(a6);schließen und PRG beenden
;---------------
;FEHLERMELDUNGEN
;---------------
;---Kein Filename angegeben
noName:	move.b	#1,PARhd	;muß <> 0 sein für ClosePAR
	lea	Text2,a0

;---Text ab (A0) ausgeben und Programm beenden
TxtOut:	bsr	Text
	bra.s	Ende

;---Parallel.Device wurde nicht geöffnet
noPAR:	lea	Text4,a0
	bra.s	TxtOut

;---Nicht genug Speicher
noFree:	lea	Text6,a0
	bra.s	TxtOut

;---File nicht gefunden/geöffnet
noFile:	lea	Text5,a0
	bra.s	TxtOut

;---File ist kein DFonts-File
noDFF:	lea	Text3,a0
	bra.s	TxtOut
;----------------------------------------------
;UP - Text ausgeben, Adresse ab (A0)
;----------------------------------------------
Text:	move.l	a0,a2		;Adresse nach A2
Kopie:	move.b	(a0)+,d3	;Byte aus (A0) nach D3
	bne.s	Kopie		;kopieren bis Nullbyte

	tst.b	-(a0)		;zurück auf's Nullbyte
	sub.l	a2,a0		;Ende Text - Anfang
	move.l	a0,d3		;= Länge Text nach D3
	move.l	a2,d2		;Textpuffer ab D2
	move.l	Outhd,d1	;Text im CLI-Fenster
	move.l	DosBase,a6
	jmp	Write(a6)	;ausgeben und zurück
;-------------------
;UP - PAR: schließen
;-------------------
ClosePAR:
	move.l	PARhd,d0	;Header nach D0
	beq.s	Close2		;weiter, wenn vorhanden

	rts			;sonst zurück

Close2:	lea	Reply,a1	;Replyport
	move.l	ExecBase,a6
	jsr	RemPort(a6)	;abmelden
	lea	IO,a1
	jmp	CloseDevice(a6)	;Device schließen und zurück
;------------------------------
;UP - 1 Byte über PAR: ausgeben
;------------------------------
Print1:	lea	IO,a1		;I/O-Struktur ab (A1)
	move.w	#3,28(a1)	;WRITE (schreibe) eintragen
	move.l	#1,36(a1)	;1 Byte
	move.l	#Byte,40(a1)	;ab Adresse 'Byte'
	move.l	ExecBase,a6
	jmp	DoIO(a6)	;ausgeben
;----------------------------------
;UP - Mehr Bytes über PAR: ausgeben
;----------------------------------
Print:	lea	IO,a1
	move.w	#3,28(a1)
	move.l	d6,36(a1)	;D6 Bytes
	move.l	a3,40(a1)	;ab A3
	move.l	ExecBase,a6
	jmp	DoIO(a6)	;ausgeben
;-------------------
;UP - FileInfo holen
;-------------------
FileInfo:
	lea	Text8,a0	;'Lese '
	bsr	Text		;ausgeben
	move.l	Filename,a0	;Filenamen
	bsr	Text		;ausgeben
	lea	Text9,a0	;Linefeed
	bsr	Text		;ausgeben
	move.l	Filename,d1	;Leselock
	moveq	#-2,d2		;auf Filenamen
	move.l	DosBase,a6
	jsr	Lock(a6)	;holen
	move.l	d0,d5		;und in D5 merken
	beq.s	RET1		;hat nicht geklappt

	move.l	d0,d1		;Lock nach D1
	move.l	FIB,d2		;FileInfoBlock
	jsr	Examine(a6)	;einlesen
	tst.l	d0
	beq.s	RET2		;hat nicht geklappt

	move.l	FIB,a0		;Aus 124.Langwort im FIB
	move.l	124(a0),d6	;Filelänge nach D6 holen
	move.l	d5,d1		;Lock
	jsr	UnLock(a6)	;freigeben
	moveq	#0,d0		;Alles klar
	rts			;und zurück

RET2:	move.l	d5,d1		;Lock
	jsr	UnLock(a6)	;freigeben
RET1:	moveq	#1,d0		;FehlerFlag setzen
	rts			;und zurück
;--------------------------------
;UP - File öffnen, Filename in D1
;--------------------------------
OpenFile:
	move.l	#1005,d2	;Modus 'OLD'
	move.l	DosBase,a6
	jsr	Open(a6)	;File öffnen
	move.l	d0,Filehd	;Header merken
	rts			;und zurück
;------------------------------------
;UP - File schließen - falls geöffnet
;------------------------------------
CloseFile:
	move.l	Filehd,d1	;Fileheader vorhanden ?
	beq.s	CloRET		;nein, zurück, sonst

	move.l	DosBase,a6	;File
	jsr	Close(a6)	;schließen
	clr.l	Filehd		;Fileheader löschen
CloRET:	rts			;und zurück
;---------------------------------------
;UP - Speicher reservieren, Anzahl in D0
;---------------------------------------
Reservieren:
	move.l	#$10000,d1	;irgendwo im RAM
	move.l	ExecBase,a6
	jmp	AllocMem(a6)	;D0 Bytes reservieren
;----------------------------------------------------
;UP - Speicher freigeben, Anzahl in D0, Adresse in A1
;----------------------------------------------------
Freigeben:
	move.l	ExecBase,a6
	jmp	FreeMem(a6)
;----------------------------------------------------
DosBase:	dc.l	0	;Dosbasis
Outhd:		dc.l	0	;Ausgabekanal (CLI-Fenster)
FIB:		dc.l	0	;FileInfoBlock im RAM
Filename:	dc.l	0	;Aktueller Filename
Filehd:		dc.l	0	;Aktueller Fileheader
Puffer:		dc.l	0	;Puffer für Textfile
Laenge:		dc.l	0	;Länge des Textfile-Puffers
FontRAM:	dc.l	0	;Puffer für ALLE DFont-Files
DFONTS:		blk.l	10,0	;Adressen der Filenamen
Laengen:	blk.l	10,0	;Längen der DFont-Files
DFLaenge:	dc.l	0	;Länge aller DFont-Files
PARhd:		dc.l	0	;Flag für 'PAR: geöffnet'
IO:		blk.l	20,0	;I/O für Parallel-Device
Reply:		blk.l	8,0	;Replyport
FontAnz:	dc.w	0	;Anzahl DFonts im Textfile
Byte:		dc.b	0	;Ausgabebyte

Text1:		dc.b	10,$9b,"1mDDF"
		dc.b	$9b,"0m - Drucken mit DFonts - "
		dc.b	"© 1990 by EHJ",10,10,0
Text2:		dc.b	"Aufruf: DDF <Filename>",10,10,0
Text3:		dc.b	"File ist ",$9b,"1mKEIN "
		dc.b	$9b,"0m'DFonts'-File !",10,10,0
Text4:		dc.b	"Kann 'parallel.device' "
		dc.b	"nicht öffnen !",10,10,0
Text5:		dc.b	"Kann File nicht finden oder "
		dc.b	"öffnen !",10,10,0
Text6:		dc.b	"Nicht genug Speicher !",10,10,0
Text8:		dc.b	"Lese ",0
Text9:		dc.b	10,0
Text10:		dc.b	10,"Auf geht's...",10,10,0
DosName:	dc.b	"dos.library",0
PARName:	dc.b	"parallel.device",0
