;Decodieren eines Tracks der im MFM-Format vorliegt

 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
	LABEL	global_size

SektorLang		EQU	$200
SyncWort		EQU	$4489
SektorMax		EQU	11

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

CodeDat		EQU $60000  ;Zeiger auf kodierte Datenpuffer 
DecodeDat		EQU $70000  ;Zeiger auf unkodierte Datenpuffer

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	#CodeDat,Puffer1(a5)	;Zeiger auf Puffer für
				;kodierte Daten
	move.l	#DecodeDat,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
	bsr	DecodeTrack		;Track dekodieren

	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

DecodeTrack:
	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.l	d3		;Sektorposition im Puffer
1$:	move.l	a2,a0		;Quelle
	move.w	#$440,d0
	mulu	d3,d0
	lea	8(a0,d0.L),a0	;Zeiger auf Header
	bsr	Header		;Header decodieren
	lsr.w	#8,d0		;Sektornummer
	move.w	d0,d1		;Sektornummer
	move.w	d3,d0		;Position im Puffer
	move.l	a2,a0		;Zeiger auf Quelle
	move.l	a3,a1		;Ziehl
	bsr	DecodeSektor	;Blockerstellen
	addq.w	#1,d3		;Sektorposition +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
;------------------------------------------------
;Sektor decodieren

;>= D0 = Sektorposition innerhalb des Puffers
;>= D1 = reale Sektornummer
;>= A0 = Zeiger auf Sektorpuffer
;>= A1 = Zeiger auf Puffer für decodierte Daten

DecodeSektor:
	move.l	d2,-(a7)		;Register retten
	move.l	#$440,d2		;Länge von kodier. Block
	mulu	d2,d0		;Offset für kodier. Bock
	move.l	#SektorLang,d2	;Länge des Sektors
	mulu	d2,d1		;Offset für unko. Sektor
	add.l	d0,a0		;Adresse für Trackpuffer
	add.l	#$40,a0		;Position hinter Header
	add.l	d1,a1		;Adresse für unko. Puffer
	move.w	#SektorLang,d0	;Sektorlänge	
	bsr	BlitSektor		;Sektor decodieren
	move.l	(a7)+,d2		;Register zurückholen
	rts			;Rücksprung

;------------------------------------------------
;>= D0 = Länge eines Sektors
;>= A0 = Zeiger auf Source
;>= A1 = Zeiger auf Dest

BlitSektor:
	movem.l	d2-d3/a2-a3,-(a7)	;Register retten
	move.l	d0,d2		;Länge eines Sektors
	move.l	a0,a2		;Zeiger auf Source
	move.l	a1,a3		;Zeiger auf Dest.
	lsl.w	#2,d0
	ori.w	#$0008,d0		;Startwert für Blitter
	move.w	d0,d3		;Wert merken
	bsr	WartBlit		;Warten bis Blitter bereit
	bsr	BlitMask		;Maskenworte setzen
	lea	$dff000,a0		;Chip-Basisadresse
	adda.l	d2,a2		;Zeiger auf Ende 1. Hälfte
	subq.l	#2,a2		;Zeiger auf letztes Wort
	move.l	a2,80(a0)		;Source A setzen
	adda.l	d2,a2		;Zeiger auf Ende 2. Hälfte
	move.l	a2,76(a0)		;Source B setzen
	adda.l	d2,a3		;Zeiger auf Ende von Ziehl
	subq.l	#2,a3		;Zeiger auf letzes Wort
	move.l	a3,84(a0)		;Dest. eintragen
	move.w	#$1dd8,64(a0)	;Blittercontrol 0
	move.w	#$0002,66(a0)	;Blittercontrol 1
				;(rückwerts)
	move.w	d3,d0		;Startwert für Blitter
	bsr	StartBlit		;Blitter starten
	movem.l	(a7)+,d2-d3/a2-a3	;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

;------------------------------------------------
;Blockheader decodieren

;>= A0 ist Zeiger auf Header
;=> D0 = Header

Header:	move.l	(a0)+,D0
	move.l	(a0)+,D1
	andi.l	#$55555555,d0
	andi.l	#$55555555,d1
	lsl.l	#1,D0
	or.l	D1,D0
	rts
;------------------------------------------------

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

	END
