;******************************************************
;*										    *
;*		  DPaint Unpack von Maik Trinkner		    *
;*           Gartenstr. 28   /  7121 Löchgau    	    *
;*			        07143/7817				    *	
;*										    *	
;*		    oder Karlsruhe  0721/606509		    *	
;*										    *
;******************************************************

; Dieses Programm läd ein DPaint Bild von der Diskette und
; entpackt dies. Dabei bleiben die Zeilen der Bitplanes 
; ineinander verschachtelt, d.h:
; In Speicher steht zuerst die 1.Zeile der 1.Bitplane. Dann
; die 1.Zeile der 2.Bitplane, dann die 3.Zeile der 3.Plane usw.
; Erst danach folgt die 2.Zeile der 1.Bitplane usw.
;
; Achtung: Das Programm läd die Quelldatei an die Adresse $40000
;          und legt die entpackten Bitplanes nach $60000,
;          ohne den Speicher vorher zu belegen
;          (würde Probleme geben)

; Hier sind einige der benötigten Labels

ExecBase=4		
OpenWindow=-30
OpenLibrary=-408

Dpaint_Unpack:

; Zuerst das Ausgabe Window öffnen (Beschreibung siehe dort )
; Zudem wird die DOS - Library geöffnet
; Ist Rückgabewert = $ffff dann Programmende wegen Fehler

	bsr		WindowOpen	
	cmp.l	#$ffff,d0		
	beq		Ende1
Error1:

; Anfangstext ausgeben (' Source : ')

	bsr		TypeErklaerung
	bsr		TypeLoad

; Auf Eingabe des Namens der Grafik warten 
; Falls Rückgabewert = $ffe1 heißt das, daß nur RETURN gedrückt 
; wurde. Dann Programmende

	bsr		InputName			
	cmp.w	#$ffe1,d0			
	beq		GoOn2		

; Angegebenes File suchen und laden. Falls es nicht exestiert
; erneut nach dem Dateinamen fragen

	bsr		LoadFile	
	beq		GoOn1	
	bsr.l	TypeMenu1		
	bra		Error1		

GoOn1:

; Nach dem Laden des angegebenen Files wird getestet, ob es sich
; um eine Datei im IFF - Format handelt. Wenn nicht wieder zum
; Programmanfang 

	bsr		CheckIFF	
	cmp.l	#$ffff,d0	
	bne		GoOn3	
	bsr.l	TypeMenu1
	bra		Error1	
GoON3:			

; File decrunchen

	bsr		DeCruncher	

; Endadresse des Files retten und nach 'Destination ' Name fragen
; Wurde hier nur RETURN gedrückt, bricht das Programm hier ab !

	move.l	a1,FileEnde
	bsr		TypeMenu2		
	bsr		Inputname	
	cmp.w	#$ffe1,d0	
	beq		GoOn2	

; Wurde der Zielname eingeben wird das File wieder abgespeichert
; Falls hier ein Fehler auftritt, wird eine Fehlermeldung 
; ausgegeben

	bsr		SaveFile	
	beq		GoOn2	
	bsr		SaveError		
GoOn2:

; Programmende. Text 'Hit RETURN to EXIT' ausgeben !

	bsr		TypeMenu3	
	bsr		Wait				

; komplettes System wieder zurückgeben -> Window + DOS schließen

AXNEnde:		
	move.l	4,a6
	bsr		WindowClose		

; Fehlerflag löschen (für DOS) und Programmende 

Ende1:
	moveq	#0,d0
	rts

;--------------------------------------------------------------------
;                  Unterprogramm  Fenster öffnen
;--------------------------------------------------------------------

; Zuerst wird die DOS - Library geöffnet. Tritt ein Fehler auf, 
; wird das Programm abgebrochen (sollte eigentlich nie vorkommen)
; Dann wird die DOSBASIS in 'DosBase' gesichert.

WindowOpen:
		move.l 	ExecBase,a6
		lea 		DosName,a1
		move.w	#0,d0	

; OpenLibrary: d0=0 : Modus      /  a1=Zeiger auf den Library Namen

		jsr 		OpenLibrary(a6)		

; Auf Fehler testen.

		cmp.l 	#0,d0		
		beq 		WindowFehler	
		move.l	d0,DosBase	

; Fenster öffnen ('CON - Fenster': d.h: bei der Tastatureingabe
; wird der Text erst nach einem abschließenden RETURN übergeben)

		move.l 	d0,a6
		move.l	#Fenstername,d1	
		move.l	#1005,d2	
		jsr 		OpenWindow(a6)

; Wie üblich Fehler abfangen

		cmp.l	#0,d0	
		beq 		WindowFehler	

; kein Fehler -> Windowhandle retten und Anfangstext ausgeben

		move.l 	d0,Window		
		move.l	d0,d1	
		move.l	#Text0,d2			
		move.l	#Text0Ende-Text0,d3
		jsr		-48(a6)
		move.w	#0,d0	
		rts			

; Ist ein Fehler beim Window öffnen aufgetreten, dann hierher und
; Flag für Programmende setzen

WindowFehler:
		move.l	#$ffff,d0
		rts

;--------------------------------------------------------------------
;      Unterprogramm zum schließen des geöffneten Fensters
;--------------------------------------------------------------------

WindowClose:
		move.l	DosBase,a6	
		move.l 	Window,d1	
		jsr 		-36(a6)	

; und DOS - Library schließen

		move.l	4,a6	
		move.l	DosBase,a1	
		jsr		-414(a6)	
		rts				

;-------------------------------------------------------------------
;        Windowstruktur und sonstige Speicher
;-------------------------------------------------------------------

; Speicher für die DOS Basis und der Name der DoS-Library

DosBase:		dc.l		0
DosName:		dc.b	"dos.library",0
even

; Zwischenspeicher für das Window Handle

Window:		dc.l 0	

; Puffer für die Texteingabe (Siehe Input !)

Buffer:	blk.b	80,0				;Eingabepuffer

even

; Hier stehen die Texte, die im Window ausgegeben werden
; 'CON:50/10/350/100/ .... ' -> Größe und Position des Fensters
; Die Zahlen: $0a             -> Cursor in die nächste Zeile
;	         $0c             -> Fenster löschen
;             $0d			-> Cursor ins linke obere Eck
; 		    $9b,"3;33;40m"	-> Schriftfarbe und Art wählen
; 		    $9b,$30,$20,$70	-> Cursor unsichtbar
;		    $9b,$20,$70	-> Cursor wieder sichtbar


Fenstername:	dc.b	"CON:50/10/350/150/      Trinkner'sches Utility 1      ",0
even
Text0:		dc.b	$0c,$0d,$9b,"3;33;40m"
			dc.b	"            DPaint Unpack V 1.0  ",$0a
			dc.b	"      written by M.Trinkner in  1989",$0a
			dc.b	$9b,"0;1;0",$6d
Text0Ende:	dc.b	0
even

Text2:		dc.b	$0a,$0a,"Source:       "
Text2Ende:	dc.b	0
even
Text3:		dc.b	$0a,"          Hit RETURN to Exit !!",$9b,$30,$20,$70
Text3Ende:	dc.b	0
even

Text4:		dc.b	"Destination:  "
Text4Ende:	dc.b	0
even

Text7:		dc.b	"         DOS - ERROR !!! ",$0a,$0b
Text7Ende:	dc.b	0
even

Text8:		dc.b	$0a,"     Only IFF Files please !! ",$0a
			dc.b	"            Hit RETURN    ",$9b,$30,$20,$70
Text8Ende:	dc.b	0
even

Text9:		dc.b	$9b,$20,$70	
Text9Ende:	dc.b	0
even

Erklaerung:	dc.b	$0c,$0d,$9b,"3;33;40m"
			dc.b	"            DPaint Unpack V 1.0  ",$0a
			dc.b	"      written by M.Trinkner in 1989",$0a
			dc.b	$9b,"3;31;40",$6d,$0a,$0a
			dc.b "Dieses Programm lädt ein File des Grafik",$0a
			dc.b	"Programmes DPaint und erzeugt daraus ein ",$0a
			dc.b	"File, das nur noch die rohen Bitplanes ",$0a
			dc.b	"enthält. Grafiken werden also entpackt.",$0a
			dc.b	"Dadurch ist es einfacher sie in eigene ",$0a
			dc.b	"Programme einzubinden.",$0a
			dc.b	"Bei Bedienfehlern wird erneut nach dem",$0a
			dc.b	"Sourcenamen gefragt, oder das Programm ",$0a
			dc.b	"abgebrochen. Fehlbedienung ist somit ",$0a
			dc.b	"ausgeschlossen !! ",$0a,$0a
			dc.b	"              Press RETURN  "
			dc.b	$9b,"0;31;40",$6d
 		     dc.b	$9b,$30,$20,$70

ErklaerungE:	dc.b	0
even


;---------------------------------------------------------------------
;       ClearWindow + Anfangstext ausgeben
;---------------------------------------------------------------------

TypeMenu1:
	move.l	#Text0,d2		
	move.l	#Text0Ende-Text0,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;     Erklärungstext am Anfang ausdrucken und auf RETURN warten
;---------------------------------------------------------------------

TypeErklaerung:
	move.l	#Erklaerung,d2		
	move.l	#ErklaerungE-Erklaerung,d3		
	bsr		Print
	bsr		Wait
	move.l	#Text0,d2		
	move.l	#Text0Ende-Text0,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;         Text " Destination:  " ausgeben
;---------------------------------------------------------------------

TypeMenu2:
	move.l	#Text4,d2		
	move.l	#Text4Ende-Text4,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;         Text " DOS ERROR !!  " ausgeben
;---------------------------------------------------------------------

SaveError:
	move.l	#Text7,d2	
	move.l	#Text7Ende-Text7,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;         Text " Hit any key to EXIT   " ausgeben
;---------------------------------------------------------------------

TypeMenu3:
	move.l	#Text3,d2	
	move.l	#Text3Ende-Text3,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;        allgemeine Printfunktion
;---------------------------------------------------------------------
; d2 -> Textanfang                  d3 -> Textlänge

Print:
	move.l	DosBase,a6	
	move.l	Window,d1		
	jsr		-48(a6)	
	rts

;---------------------------------------------------------------------
;       Text 'Source: ' ausgeben
;---------------------------------------------------------------------

TypeLoad:
	move.l	#Text2,d2		
	move.l	#Text2Ende-Text2,d3		
	bsr		Print
	rts

;---------------------------------------------------------------------
;        Auf RETURN warten
;---------------------------------------------------------------------

; Kurzbeschreibung: Die READ Funktion wartet solange bis RETURN 
; gedrückt wurde. Der eingegebene Text wird in diesem Fall ignoriert
; da nur das RETURN wichtig ist.

Wait:
	move.l	DosBase,a6
	move.l	Window,d1
	move.l	#Buffer,d2
	move.l	#40,d3	
	jsr		-42(a6)		
	rts

;---------------------------------------------------------------------
;          Stringeingabe der Source-/Destination Namens
;---------------------------------------------------------------------

; Kurzbeschreibung: Die Input Funktion wartet auf eine Tastatureingabe
; abgeschlossen mit RETURN (-> CON: Fenster !!). Der eingelesene 
; Text wird ab dem mit BUFFER bezeichneten Speicherbereich abgelegt
; (als ASCII Text natürlich.)

InputName:
	move.l	DosBase,a6
	move.l	Window,d1
	move.l	#Buffer,d2	
	move.l	#40,d3	
	jsr		-42(a6)	

; Wurde nur RETURN gedrückt, dann Flag für Programmende setzen

	lea		Buffer,a0	
	move.b	(a0),d0		
	cmp.b	#$0a,d0
	bne		Search		
	move.w	#$ffe1,d0		
	rts

; sonst muß der eingegebene Text konvertiert werden in ein Format,
; das die LOAD bzw. SAVE Routine versteht. Dabei wird einfach der
; Text ab BUFFER nach dem abschließenden RETURN (= $0a ) 
; durchsucht. Dieses $0a wird dann in $00 umgewandelt. ( Die LOAD
; Routine verlangt den Filenamen mit einer abschließenden Null )

Search:
	lea		Buffer,a0	
Search0A:
	move.b	(a0),d0	
	cmp.b	#$0a,d0	
	beq		Found0A		
	add.l	#1,a0	
	bra		Search0A		
Found0A:
	move.b	#$00,(a0)		
	rts
	
;---------------------------------------------------------------------
;	      Unterprogramm um ein File von Disk zu laden
;---------------------------------------------------------------------

; Zwischenspeicher des Filehandles

FileHandle:		dc.l		0

; Benötigte Funktionen

Open=-30
Read=-42
Close=-36

; File öffnen. Der Filename aus BUFFER von der Tastatureingabe
; 1005 - Mode OLD d.h: File nur lesen
; Tritt ein Fehler auf (File nicht gefunden) -> Fehlerflag setzen
 
LoadFile:
	move.l	DosBase,a6	
	move.l	#Buffer,d1		
	move.l	#1005,d2		
	jsr		Open(a6)		
	move.l	d0,FileHandle	
	bne		LoadOk		
	move.l	#$ffff,d0			
	rts						

; War das Öffnen der Datei erfolgreich, dann wird sie jetzt and
; die Adresse $40000 geladen

LoadOk:
	move.l	DosBase,a6	
	move.l	FileHandle,d1	
	move.l	#$40000,d2
	move.l	#$60000-$40000,d3
	jsr		Read(a6)	

; Bei Lesefehler "DOS ERROR" ausgeben, und erneuter Programmstart

	cmp.l	#-1,d0	
	beq		LoadError	

; Sonst File wieder schließen und zurück ins Hauptprogramm

	move.l	DosBase,a6	
	move.l	FileHandle,d1	
	jsr		Close(a6)
	clr.l	d0	
	rts				

; Fehlerbehandlung, falls ein Fehler aufgetreten ist
; d.h: 'DOS-ERROR' ausgeben, auf RETURN warten und erneuter
; Programmstart

LoadError:
	move.l	DosBase,a6	
	move.l	FileHandle,d1
	jsr		Close(a6)		
	move.l	#$ffff,d0
	rts				
	
;---------------------------------------------------------------------
;   Unterprogramm, um das generierte File wieder abzuspeichern
;---------------------------------------------------------------------

; Filehandle für das zu sichernde File

SaveHandle:		dc.l		0
FileEnde:			dc.l		0
Write=-48

; File auf der Diskette (oder Festplatte,RAM, ...) öffnen
; Diesmal mit Mode new also neues File anlegen (1006)

SaveFile:
	move.l	DosBase,a6	
	move.l	#Buffer,d1
	move.l	#1006,d2		
	jsr		Open(a6)		

; Auf Fehler testen

	move.l	d0,SaveHandle	
	bne		SaveOk		
	move.l	#$ffff,d0		
	rts	

; Hier wird die generierte Grafik auf Diskette gespeichert.
; Anfangsadresse $60000    Endadresse in FileEnde

SaveOk:
	move.l	DosBase,a6	
	move.l	SaveHandle,d1	
	move.l	#$60000,d2	
	move.l	FileEnde,d3	
	sub.l	#$60000,d3	
	jsr		Write(a6)		

; Erneut auf eventuellen Fehler testen

	cmp.l	#-1,d0	
	beq		SaveFehler

; und das File wieder schließen

	move.l	DosBase,a6	
	move.l	SaveHandle,d1	
	jsr		Close(a6)	
	clr.l	d0
	rts					

; Fehlerbehandlung der Speicherroutine (s.o.)

SaveFehler:
	move.l	DosBase,a6	
	move.l	SaveHandle,d1	
	jsr		Close(a6)	
	move.l	#$ffff,d0	
	rts		

;---------------------------------------------------------------------
;           Hier die eigentliche Entpack Routine
;---------------------------------------------------------------------

DeCruncher:

; Zuerst die Anfangsadresse der Ausgangsgrafik und die Zieladresse
; der entpackten Grafik setzen

unpack:
	lea		$4000e,a0
	lea		$60004,a1		

; Register a0 zeigt jetzt auf die Grafik Steuerdaten

	move.l	4(a0),d0

; Plus Länge dieser Daten. Jetzt zeigt A0 auf die Farbtabelle

	add.l	d0,a0
	add.l	#8,a0

PackLoop1:	
	move.l	4(a0),d0
	add.l	d0,a0
	add.l	#8,a0

; nach der Kennung "BODY" suchen. Diese ist das Kennzeichen für den
; Anfang der eigentlichen Grafikdaten

	move.l	#'BODY',d1
	cmp.l	(a0),d1
	bne		PackLoop1

; Grafik gefunden. Jetzt bestimmen wieviel Bytes diese Grafik lang ist

	add.l	#4,a0
	move.l	(a0),WievielBytes	
	add.l	#1,WievielBytes
	and.l	#$fffffffe,WievielBytes
	add.l	#4,a0	

; Jetzt die Grafik entpacken. Dabei werden einfach die gepackten NullBytes
; wieder zu richtigen Nullbytes gemacht.

	move.l	#0,d3
PackLoop3:	
	move.b	(a0)+,Count
	move.l	#0,d5
	move.b	Count,d5
	and.b	#$80,d5
	bne		PackLoopA
	move.l	#0,d4
	move.b	Count,d4

; Die gesammte Grafik wird von $40000 nach $60000 kopiert.
; Entpackt natürlich

PackLoop6:	
	move.b	(a0)+,(a1)+
	add.l	#1,d3
	dbf		d4,PackLoop6
	sub.l	#1,a0
	bra		PackLoopC

PackLoopA:	
	neg.b	Count
	move.l	#0,d0
	move.b	Count,d0
PackLoopB:	
	move.b	(a0),(a1)+
	dbf		d0,PackLoopB

; Test, ob bereits die gesammte Grafik fertig kopiert wurde

	add.l	#2,d3
PackLoopC:	
	move.l	WievielBytes,d1
	cmp.l	d3,d1
	ble		PackLoop5
	add.l	#1,a0
	bra		PackLoop3

; Ende -> Grafik fertig

PackLoop5:	

	rts

; Tabelle, die enthält, wo die Information über die Grafik liegen

WievielBytes:		dc.l	0
Count:			dc.b	0
even

;-------------------------------------------------------------------------
;  Dieses Unterprogramm testet das geladene File darauf, ob es überhaupt
;  ein IFF File ist.
;-------------------------------------------------------------------------

; Bei einer DPaint Grafik enthält das 1.Langword den ASCII Text
; "FORM" (siehe Literatur unter dem Stichwort IFF-Format)

CheckIFF:
	move.l	$40000,d0	
	cmp.l	#"FORM",d0	
	bne		IFFError	

; wurde die 1.Kennung gefunden, dann wird noch getestet, ob die 
; geladene IFF-Datei (um diese handelt es sich jetzt sicher) auch
; eine Grafik Datei ist. (Es gibt auch Sound und Textdateien)
; Die Kennung hierfür ist das Wort "ILBM".

	move.l	$40008,d0		
	cmp.l	#"ILBM",d0	
	bne		IFFError		
	clr.l	d0			
	rts				

; War das geladene File keine IFF Grafik Datei, wird der Text
; "kein IFF-File" ausgegeben, und das Programm erneut gestartet

IFFError:
	move.l	#Text8,d2		
	move.l	#Text8Ende-Text8,d3		
	bsr		Print
	move.l	DosBase,a6		
	move.l	Window,d1
	move.l	#Buffer,d2		
	move.l	#40,d3		
	jsr		-42(a6)		
	move.l	#Text9,d2		
	move.l	#Text9Ende-Text9,d3
	bsr		Print
	move.l	#$ffff,d0		
	rts	

