;Kodieren eines Tracks ins MFM-Format

 include "exec/types.i"


CALLSYS	MACRO
	jsr _LVO\1(a6)
	ENDM
LINKSYS	MACRO
	move.l a6,-(a7)
	move.l \2,a6
	jsr _LVO\1(a6)
	move.l (a7)+,a6
	ENDM
XLIB	MACRO
	XREF _LVO\1
	ENDM

 XREF _AbsExecBase

 XLIB OpenLibrary
 XLIB CloseLibrary

;------------------------------------------------
;Graphics-Library

 XLIB OwnBlitter
 XLIB DisownBlitter

 STRUCTURE	global,0
	APTR	GfxBase
	APTR	Puffer1
	APTR	Puffer2
	WORD	TrackNum
	LABEL	global_size

SektorLang		EQU	$200
SyncWort		EQU	$4489
SektorMax		EQU	11

;------------------------------------------------
;Eigene Puffer eintagen

DecodeDat		EQU $50000  ;Zeiger auf unkodierte Datenpuffer
CodeDat		EQU $60000  ;Zeiger auf kodierte Datenpuffer 
TrackNummer		EQU 10      ;eigene Tracknummer

main:
	move.l	_AbsExecBase,a6
	lea	-global_size(a7),a7	;Platz im Staple für
				;die Struktur
	move.l	a7,a5		;Zeiger auf Struktur

	lea	GfxName,a1		;Zeiger auf Namen der Lib.
	clr.l	d0		;Verion
	CALLSYS	OpenLibrary		;Gfx-Lib öffnen
	move.l	d0,GfxBase(a5)
	beq	1$		;Fehler, nicht geöffnet

	move.l	#DecodeDat,Puffer1(a5)	;Zeiger auf Puffer für
				;kodierte Daten
	move.l	#CodeDat,Puffer2(a5)	;Zeiger auf Puffer für
				;nicht kodierte Daten

	LINKSYS	OwnBlitter,GfxBase(a5)	;Funktion: OwnBlitter

	move.l	Puffer1(a5),a0	;Zeiger auf Puffer 1
	move.l	Puffer2(a5),a1	;Zeiger auf Puffer 2
	move.w	#TrackNummer,TrackNum(a5)
	bsr	CodeTrack		;Track kodieren

	LINKSYS	DisownBlitter,GfxBase(a5) ;Funktion: DisownBlitter

	move.l	GfxBase(a5),a1	;Zeiger auf GfxLib.
	CALLSYS	CloseLibrary	;Library schließen

1$:	lea	global_size(a7),a7	;Staple wieder freigeben
	rts


;------------------------------------------------
;Track codieren
;>= A0 = Zeiger auf Quelle
;>= A1 = Zeiger auf Ziehl

CodeTrack:
	movem.l	d2-d3/a2-a3,-(a7)	;Register löschen
	move.l	a0,a2		;Zeiger auf Quelle
	move.l	a1,a3		;Zeiger auf Ziehl
	move.w	#SektorMax,d2	;11 Sektoren
	clr.w	d3		;Sektornummer
1$:	move.l	a2,a0		;Quelle
	move.l	a3,a1		;Ziehl
	move.w	d3,d0		;Sektornummer
	bsr	ErstellBlock	;Blockerstellen
	add.l	#$440,a3		;Zeiger auf Ziehl + $440
	add.l	#$200,a2		;Zeiger auf Quelle + $200
	addq.w	#1,d3		;Sektornummer +1
	subq.w	#1,d2		;Zähler -1
	bne	1$		;weiter, wenn nicht Null
	movem.l	(a7)+,d2-d3/a2-a3	;Register zurückholen
	rts
;------------------------------------------------
;Block kodieren und Header erstellen
;>= A0 = Unkodierte Daten (Quelle)
;>= A1 = Datenpuffer für kodierte Daten (Ziehl)
;>= D0 = Sektornummer / Position im Track

ErstellBlock:
	movem.l	a2-a3,-(a7)		;Register retten
	move.l	a0,a2		;Zeiger auf Quelle
	move.l	a1,a3		;Zeiger auf Ziehl
	move.l	d0,d1		;Sektornummer
	move.l	a3,a0		;Zeiger auf Ziehl
	bsr	ErstellHeader	;Header erstellen
	move.w	#SektorLang,d0	;Sektorlänge nach D0
	movea.l	a2,a0		;Zeiger auf Quelle
	lea	$40(a3),a1		;Zeiger hinter Header
	bsr	CodeBlock		;Block kodieren
	lea	$40(a3),A0		;Zeiger hinter Header
	move.w	#$400,D1		;Anzahl der Bytes
	bsr	PruefSumme		;Datenprüfsumme bilden
	lea	$38(a3),A0		;Offset für Prüfsumme
	bsr	CodeLWort		;Summe eintagen
	movem.l	(a7)+,a2-a3		;Register zurückholen
	rts

;------------------------------------------------
;Header mit allen Einträgen neu erstellen
;>= D0 = Position auf dem Track
;>= D1 = Sektornummer
;>= A0 = Zeiger auf Header

ErstellHeader:
	movem.l	d2-d3/a2,-(a7)	;Register Retten
	move.l	a0,a2		;Zeiger auf Header
	move.l	d0,d2		;Position im Track
	move.l	d1,d3		;Sektornummer
	bsr	LoescheHeader	;Header mi $AA füllen
	move.l	a2,a0		;Zeiger auf Header
	move.l	d2,d0		;Position im Track
	move.l	d3,d1		;Sektornummer
	bsr	NeuerHeader		;Header erstellen
	movem.l	(a7)+,d2-d3/a2	;Register zurückholen
	rts			;Rücksprung

;------------------------------------------------
;Header löschen
;>= A0 = Zeiger auf Header

LoescheHeader:
	move.l	d2,-(a7)		;Register retten
	clr.w	d2		;Zähler
1$:	clr.l	d0		;Null
	bsr	CodeLWort		;Null eintragen
	addq.w	#1,d2		;Zähler +1
	cmp.w	#8,d2		;löschen beenden ?
	bne.s	1$		;nein, weiter
	move.l	(a7)+,d2		;Register zurückholen
	rts

;------------------------------------------------
;Header neu berechnen und Infoteil neu eintragen

;>= D0 = Position auf dem Track
;>= D1 = Sektornummer
;>= D2 = Tracknummer;>= A0 = Zeiger auf den Sektor

NeuerHeader:
	movem.l	d2-d3/a2,-(a7)
	move.l	d0,d2		;Position auf dem Track
	move.l	d1,d3		;Sektornummer
	move.l	a0,a2		;Zeiger auf den Sektor
	clr.l	d0		;$aaaaaaaa eintagen
	bsr	CodeLWort		;$aa vor Sync eintragen
	move.w	#SyncWort,4(a2)	;Sync eintragen
	move.w	#SyncWort,6(a2)
	move.w	TrackNum(a5),d0	;Tracknummer holen
	ori.w	#$ff00,d0		;DOS-Erkennung 
	swap	d0		;auf richtige Position
	move.w	d3,d0		;Sektornummer
	lsl.w	#8,d0		;an richtige Stelle
	move.w	#SektorMax,d1	;Sektoranzahl = 11
	sub.w	d2,d1		;Sektoren bis Lücke
	move.b	d1,d0		;Anzahl eintragen
	lea	8(a2),a0		;Zeiger auf Headerposition
	bsr	CodeLWort		;Header eintragen
	lea	8(a2),a0		;Zeiger auf Headerposition
	moveq.l	#$28,d1		;40 Bytes
	bsr	PruefSumme		;Prüfsumme bilden
	lea	48(a2),a0		;Zeiger auf Summenposition
	bsr	CodeLWort		;Summe eintagen
	movem.l	(a7)+,d2-d3/a2	;Register zurückholen
	rts			;Rücksprung
;------------------------------------------------
;Datenblock kodieren
;>= D0 = Länge der Quelle
;>= A0 = Zeiger auf Quelle
;>= A1 = Zeiger auf Ziehl

CodeBlock:
	movem.l	d2-d3/a2-a3,-(a7)	;Register retten
	move.l	a0,a2		;Zeiger auf Quelle
	move.l	a1,a3		;Zeiger auf Ziehl
	clr.l	d2		;D2 löschen
	move.w	d0,d2		;Blocklänge nach D2
	move.w	d0,d1		;Blocklänge nach D1
	lsl.w	#2,d1
	ori.w	#8,d1		;Wert für Bitterstart
	bsr	WartBlit		;Warten bis Blitter fertig
	bsr	BlitterCode		;Block kodieren
	movea.l	a3,a0		;Zeiger codierten Block
	bsr	Randsetzen		;Ränder neu erstellen
	adda.l	d2,a0		;Zeiger auf 1. Lücke
	bsr	Randsetzen		;Ränder neu erstellen
	adda.l	d2,a0		;Zeiger auf Blockende
	bsr	Randsetzen		;Ränger neu erstellen
	movem.l	(a7)+,d2-d3/a2-a3	;Register zurückholen
	rts			;Rücksprung
;------------------------------------------------
;>= A0 = Quelle
;>= A1 = Ziehl
;>= D0 = Länge der Quelle
;>= D1 = Blitter-Startwert

BlitterCode:
	movem.l	d2-d3/a2-a4,-(a7)	;Register retten
	clr.l	d2		;D2 löschen
	move.w	d0,d2		;Länge des Blocks
	move.w	d1,d3		;Startwert für Blitter
	move.l	a0,a2		;Zeiger auf Quelle
	move.l	a1,a3		;Zeiger auf Ziehl
	bsr	BlitMask		;Makenworte setzen
	lea	$dff000,a4		;Chip-Basisadresse
	move.l	a2,$4C(A4)		;Zeiger auf Source B
	move.l	a2,$50(A4)		;Zeiger auf Source A
	move.l	a3,$54(A4)		;Zeiger auf Dest.
	move.w	#$1DB1,$40(A4)	;Blittercontrol 0
	move.w	#0,$42(A4)		;Blittercontrol 1
	move.w	d3,d0		;Startwert für Blitter
	bsr	StartBlit		;Blitter starten
	move.l	a3,$4C(A4)		;Zeiger auf Source B
	move.l	a2,$50(A4)		;Zeiger auf Source A
	move.l	a3,$54(A4)		;Zeiger auf Dest
	move.w	#$2d8c,$40(A4)	;Blittercontrol 0
	move.w	d3,d0		;Startwert für Blitter
	bsr	StartBlit		;Blitter starten
	move.l	a2,a0		;Zeiger auf Quelle
	move.l	a3,a1		;Zeiger auf Ziehl
	adda.l	D2,a0		;Zeiger auf Ende von Quelle
	subq.l	#2,a0		;Zeiger auf letztes Wort
	adda.l	D2,a1
	adda.l	D2,a1		;Zeiger auf Ende von Ziehl
	subq.l	#2,a1		;Zeiger auf letztes Wort
	move.l	a0,$4C(A4)		;Zeiger auf Source B
	move.l	a0,$50(A4)		;Zeiger auf Source A
	move.l	a1,$54(A4)		;Zeiger auf Dest.
	move.w	#$DB1,$40(A4)	;Bittercontrol 0
	move.w	#$1002,$42(A4)	;Blittercontrol
				;(rückwerts)
	move.w	d3,d0		;Startwert für Blitter
	bsr	StartBlit		;Blitter starten
	move.l	a2,a0		;Zeiger auf Quelle
	move.l	a3,a1		;Zeiger auf Ziehl
	adda.l	D2,a1		;Zeiger auf 2. Hälfte
	move.l	a1,$4C(A4)		;Zeiger auf Source B
	move.l	a0,$50(A4)		;Zeiger auf Source A
	move.l	a1,$54(A4)		;Zeiger auf Dest.
	move.w	#$1D8C,$40(A4)	;Blittercontrol 0
	move.w	#0,$42(A4)		;Blittercontrol 1
	move.w	d3,d0		;Startwert für Blitter
	bsr	StartBlit		;Blitter starten
	movem.l	(a7)+,d2-d3/a2-a4	;Register zurückholen
	rts			;Rücksprung

;------------------------------------------------
;Maskenregister für Blitter setzen

BlitMask:
	lea	$dff000,a0		;Chip-Basisadresse
	clr.l	d0		;D0 löschen
	lea	$44(a0),a1		;Zeiger auf 1. Maskword
	move.l	#-1,(a1)		;1. und 2. Maskwords setzen
	lea	$62(a0),a1		;Zeiger auf Modulu
	move.l	d0,(a1)+		;Blittermodulu löschen
	move.w	d0,(a1)+
	addq.l	#8,a1
	move.w	#$5555,(a1)		;Blitter Source C
	rts			;Rücksprung
;------------------------------------------------
;Blit start und auf Ende von Blitter warten
;>= D0 = Startwert

StartBlit:
	move.w d0,$dff058		;Blitter starten
	bsr	WartBlit		;Warten bis Blitter fertig
	rts			;Rücksprung
;------------------------------------------------
;Warten bis Blitter fertig

WartBlit:
	btst	#14,$dff002
	bne.s	WartBlit
	rts

;------------------------------------------------

;Langwort kodieren und in Puffer eintragen
;>= D0 = Langwort
;>= A0 = Zeiger auf Puffer

CodeLWort:     MOVEM.L D2-D3,-(A7)
               MOVE.L D0,D3
               LSR.L #1,D0
               BSR 1$
               MOVE.L D3,D0
               BSR 1$
               BSR Randsetzen
               MOVEM.L (A7)+,D2-D3
               RTS
1$:            ANDI.L #$55555555,D0
               MOVE.L D0,D2
               EORI.L #$55555555,D2
               MOVE.L D2,D1
               LSL.L #1,D2
               LSR.L #1,D1
               BSET #$1F,D1
               AND.L D2,D1
               OR.L D1,D0
               BTST #0,-1(A0)
               BEQ.S 2$
               BCLR #$1F,D0
2$:            MOVE.L D0,(A0)+
               RTS

;Ränder richtig setzten

Randsetzen:    MOVE.B (A0),D0
               BTST #0,-1(A0)
               BNE.S 4$
               BTST #6,D0
               BNE.S 6$
               BSET #7,D0
               BRA.S 5$
4$:            BCLR #7,D0
5$:            MOVE.B D0,(A0)
6$:            RTS

;------------------------------------------------
;Prüfsumme über Datenbereich ermitteln
;>= D1 = Anzahl der Bytes (muß immer durch 4 teilbar sein)
;>= A0 = Zeiger auf Puffer
;=> D0 = Prüfsumme

PruefSumme:	MOVE.L	D2,-(A7)
	LSR.W	#2,D1
	SUBQ.W	#1,D1
	MOVEQ	#0,D0
1$:	MOVE.L	(A0)+,D2
	EOR.L	D2,D0
	DBRA	D1,1$
	ANDI.L	#$55555555,D0
	MOVE.L	(A7)+,D2
	RTS

;------------------------------------------------

GfxName:	dc.b	'graphics.library',0

	END
