; ---------------------------------------------------------------------
;
;	the official Kickstart-game, part two !
;
;	code and comments by Martin Silbernagl 
;
;	last revision: 15/09/1988
;
; ---------------------------------------------------------------------

DMACONR		EQU	$DFF002
INTREQR		EQU	$DFF01E
INTENAR		EQU	$DFF01C
DIWSTRT		EQU	$DFF08E
DIWSTOP		EQU	$DFF090
DDFSTRT		EQU	$DFF092
DDFSTOP		EQU	$DFF094
DMACON		EQU	$DFF096
INTENA		EQU	$DFF09A
INTREQ		EQU	$DFF09C
BPL1PT		EQU	$DFF0E0
BPLCON0		EQU	$DFF100
BPLCON1		EQU	$DFF102
BPLCON2		EQU	$DFF104
BPL1MOD		EQU	$DFF108
BPL2MOD		EQU	$DFF10A
COLOR00		EQU	$DFF180

CIAA_PRA	EQU	$BFE001
CIAA_SDR	EQU	$BFEC01
CIAA_ICR	EQU	$BFED01
CIAA_CRA	EQU	$BFEE01
CIAA_CRB	EQU	$BFEF01

_LVOAllocMem		EQU	-$0c6	; exec LVOs
_LVOFreeMem		EQU	-$0d2
_LVOOpenLibrary		EQU	-$228
_LVOCloseLibrary	EQU	-$19e
_LVOOpen		EQU	-$01e	; dos LVOs
_LVOClose		EQU	-$024
_LVORead		EQU	-$02a
_LVOSeek		EQU	-$042
_LVODisplayAlert	EQU	-$05a	; intuition LVOs

START:
	MOVEM.L	D0-D7/A0-A6,-(A7)       ; Alle Register auf den Stack legen

	MOVEA.L	4,A6			; Adresse der exec-library holen
	MOVE.L	#40000,D0		; 40*200*5 bytes wollen wir
	MOVE.L	#$10002,D1		; CLEAR und CHIP soll es sein
	JSR	_LVOAllocMem(A6)	; Speicher holen
	TST.L	D0			; Speicher bekommen ?
	BNE.S	OK1			; wenn ja, dann nach OK1 springen
	MOVE.W	#0,ERRORN		; Fehler #0
	JSR	ERRORS			; Alert ausgeben
	JMP	END1			; Programm beenden
OK1:	MOVE.L	D0,TITLE_BASE		; Adresse des Speichers abspeichern

	MOVEA.L	4,A6			; ExecBase nach A6
	LEA	DOS_NAME,A1		; Name der Library nach A1
	MOVEQ	#0,D0			; Version Number 0
	JSR	_LVOOpenLibrary(A6)	; DOS-Library oeffnen
	TST.L	D0			; konnte sie nicht geoeffnet werden?
	BNE.S	OK2			; wenn doch, dann nach OK2 springen
	MOVE.W	#1,ERRORN		; Fehler #1
	JSR	ERRORS			; Alert ausgeben
	JMP	END2			; Programm beenden
OK2:	MOVE.L	D0,DOS_BASE		; Adresse der DOS-library speichern

 	LEA	TITLE_NAME,A0		; Name des Titelbildes
	MOVEA.L	TITLE_BASE,A5		; Adresse des Videospeichers
	MOVE.L	#320,D6			; gewuenschte Breite
	MOVE.L	#200,D7			; gewuenschte Hoehe
	JSR	LOAD_IFF		; IFF-Bild einladen

	LEA	IFF_COLORS,A0		; Adresse der Quellcolormap
	LEA	TITLE_CMAP,A1		; Adresse der Zielcolormap
	MOVEQ	#31,D0			; 32 mal kopieren
COPY_CMAP1:
	MOVE.W	(A0)+,(A1)+		; eine Farbe kopieren
	DBRA	D0,COPY_CMAP1		; Schleife machen

	MOVEQ	#61,D0			; Schleife 62 mal durchlaufen
	LEA	PAGE0,A0		; Basis des Zwischenspeichers nach A0
	LEA	8,A1			; Basis der Vektorentabelle nach A1
LOOP1:	MOVE.L	(A1)+,(A0)+		; jeweils einen Vektor kopieren
	DBRA	D0,LOOP1		; D0=-1? Wenn nicht, dann loop1

MAIN:
	MOVE.L	#MAIN,$0020		; MAIN to Priv._Viol._Vektor
	MOVE.W	#$2700,SR		; Supervisor=1, Interruptlevel=7
	ADDA.L	#6,A7			; A7 auf alten Inhalt zuruecksetzen

	MOVE.L	A7,ADR7			; Inhalt von A7 zwischenspeichern
	LEA	STACK,A7		; Supervisor-Stackptr. neu setzten

	MOVE.W	INTENAR,INTENA_BUF	; Int-Kontrollregister zwischenspeichern
	MOVE.W	DMACONR,DMACON_BUF	; DMA-Kontrollregister zwischenspeichern

START_OVER:
	MOVE.L	#MAIN_LOOP,MAIN_JMP+2	; Vektor der Hauptschleife zuruecksetzen
	MOVE.L	#PORTS,$68		; Vektor Int.-Level 2 auf PORTS umbiegen
	MOVE.L	#VERTB,$6C		; Vektor Int.-Level 3 auf VERTB umbiegen
	MOVE.W	#$7fff,INTENA		; Alle Ints. ausschalten
	MOVE.W	#$C028,INTENA		; PORTS- und VERB-Int. erlauben
	MOVE.W	#$7fff,DMACON		; Alle DMA ausschalten
	MOVE.W	#$8300,DMACON		; DMAEN und BPLEN anschalten
	MOVE.B	#$88,CIAA_ICR		; SP Interrupt des CIA_A erlaubt
	MOVE.W	#$2000,SR		; Supervisor=1, Interruptlevel=0

	LEA	TITLE_CMAP,A0		; Adresse der Quellcolormap
	LEA	COLOR00,A1		; Basisadresse der Farbregister
	MOVEQ	#31,D0			; 32 mal kopieren
COPY_CMAP2:
	MOVE.W	(A0)+,(A1)+		; eine Farbe kopieren
	DBRA	D0,COPY_CMAP2		; Schleife machen

	MOVE.W	#$5200,BPLCON0		; 5 Bitplanes und Colorburst
	MOVE.W	#$0000,BPLCON1		; Scrollregister auf Null setzen
	MOVE.W	#$0000,BPLCON2		; Prioritaeten normal setzen

	MOVE.W	#0,BPL1MOD		; kein Modulo setzen
	MOVE.W	#0,BPL2MOD		; kein Modulo setzen

	MOVE.W	#$2c81,DIWSTRT		; linke, obere Ecke setzen
	MOVE.W	#$f4c1,DIWSTOP		; rechte, untere Ecke setzen
	MOVE.W	#$0038,DDFSTRT		; data-fetch-start definieren
	MOVE.W	#$00d0,DDFSTOP		; data-fetch-start definieren

MAIN_LOOP:
	NOP				; Hier steht spaeter das Hauptpgm.
MAIN_JMP:
	JMP	MAIN_LOOP		; Hauptschleife



; ---------------------------------------------------------------------
;
; Ab hier wird das Betriebssystem (exec usw.) wieder eingeschaltet.
;
; ---------------------------------------------------------------------

ENDING:
	MOVE.W	#$2700,SR		; auf hoechste Int. Ebene setzen
	ORI.W	#$8000,INTENA_BUF	; Set-Bit im Zwischenspeicher setzen
	MOVE.W	#$7fff,INTENA		; alle Ints. verbieten
	MOVE.W	INTENA_BUF,INTENA	; alte Interrupts setzen

	ORI.W	#$8000,DMACON_BUF	; Set-Bit im Zwischenspeicher setzen
	MOVE.W	#$7fff,DMACON		; alle Ints. verbieten
	MOVE.W	DMACON_BUF,DMACON	; alte Interrupts setzen

	MOVEQ	#61,D0			; 62 Werte kopieren
	LEA	PAGE0,A0		; Basis des Zwischenspeichers nach A0
	LEA	8,A1			; Basis der Vektorentabelle nach A1
LOOP2:
	MOVE.L	(A0)+,(A1)+		; jeweils einen Vektor kopieren
	DBRA	D0,LOOP2		; D0=-1? Wenn nicht, dann loop2

	MOVEA.L	ADR7,A7			; alten Stackpointer wieder holen

	MOVE.W	#$0000,SR		; Supervisor=0, Interruptlevel=0
END3:
	MOVEA.L	4,A6			; Basis der exec-Library holen
	MOVEA.L	DOS_BASE,A1		; Pointer auf DOS-Library holen
	JSR	_LVOCloseLibrary(A6)	; Bibliothek schliessen
END2:
	MOVEA.L	4,A6			; Basis der exec-Library holen
	MOVEA.L	TITLE_BASE,A1		; Basis nach A1 holen
	MOVE.L	#40000,D0		; Groesse nach D0
	JSR	_LVOFreeMem(A6)		; Speicher freigeben
END1:
	MOVEM.L	(A7)+,D0-D7/A0-A6	; Alle Register vom Stack
	RTS				; Und das Pgm beenden


; ---------------------------------------------------------------------
;
; Die Routine Ports wird angesprungen, wenn der CIA_A einen Interrupt
; fordert. Dies kann unter anderem dann geschehen, wenn von der Tas-
; tatur ein Byte gesendet wird.
;
; ---------------------------------------------------------------------

PORTS:					; Server von Interrupt-Level 2
	MOVE.W	#$0008,INTREQ		; Interrupt-Bit wieder zuruecksetzen
	MOVEM.L	D0-D2/A0,-(A7)		; D0-D2 und A0 auf den Stack

	MOVE.B	CIAA_ICR,D2		; Inhalt des Interrupt Controllers
	BTST	#3,D2			; SP Bit gesetzt ?
	BEQ	END_PORTS		; wenn nicht, kein Interrupt fuer uns
	MOVE.B	CIAA_SDR,D0		; Inhalt Serielles Datenregister
	ORI.B	#64,CIAA_CRA		; Serial-Port auf Output setzen
	MOVEQ	#60,D1			; Schleife 60 mal durchlaufen
KBRD_LOW:
	CLR.B	CIAA_SDR		; Auf Null setzen
	DBRA	D1,KBRD_LOW		; Schleife machen
	NOT.B	D0			; Erhaltene Daten invertieren
	ROR.B	#1,D0			; Bits in richtige Reihenfolge bringen
	AND.B	#$BF,CIAA_CRA		; Serial-Port auf Input setzen

	CMP.B	#$F9,D0			; Letzter Keycode schlecht ?
	BNE.S	LAST_GOOD		; wenn nicht, dann nach last_good
	BRA	END_PORTS		; sonst den Interrupt beenden
LAST_GOOD:

	TST.B	PASS_CNT		; Password schon eingegeben ?
	BEQ.S	PLUS_PASS		; wenn ja, dann nach plus_pass
	CMP.B	#$7f,D0			; Eine losgelassene Taste ?
	BHI	REGULAR_KEYS		; wenn ja, dann nach regular_keys
	MOVEA.L	PASS_PTR,A0		; Zeiger auf akt. Buchstaben
	CMP.B	(A0)+,D0		; gedr. Taste gleich (A0) ?
	BEQ.S	NEXT_OK			; wenn ja, dann nach next_ok
	MOVE.B	#14,PASS_CNT		; wenn nicht, Zaehler zuruecksetzen
	MOVE.L	#PASS_WORD,PASS_PTR	; Zeiger zuruecksetzen
	BRA	REGULAR_KEYS		; und beenden
NEXT_OK:
	MOVE.L	A0,PASS_PTR		; neue Adr. zurueckschreiben
	SUBQ.B	#1,PASS_CNT		; Zaehler erniedrigen
	BNE	END_PORTS		; Zaehler versch. Null -> end_ports

PLUS_PASS:
	LEA	PASS_KEY_TABLE,A0	; Adresse der Sprungtabelle nach A0
	MOVEQ	#0,D1			; D1 auf 32-Bit 0 setzen
	MOVE.B	D0,D1			; Key-Code kopieren
	LSL.W	#2,D1			; Inhalt von D1 vervierfachen
	MOVEA.L	0(A0,D1),A0		; Zeiger auf Adresse der Routine
	JMP	(A0)			; zur berechneten Key-Routine springen

RK:					; kuerzeres Label fuer REGULAR_KEYS
	NOP				; steht nur zur Zierde hier
REGULAR_KEYS:
	LEA	KEY_TABLE,A0		; Adresse der Sprungtabelle nach A0
	MOVEQ	#0,D1			; D1 auf 32-Bit 0 setzen
	MOVE.B	D0,D1			; Key-Code kopieren
	LSL.W	#2,D1			; Inhalt von D1 vervierfachen
	MOVEA.L	0(A0,D1),A0		; Zeiger auf Adresse der Routine
	JMP	(A0)			; zur berechneten Key-Routine springen

EP:					; kuerzeres Label fuer END_PORTS
	NOP				; steht auch hier nur zur Zierde
END_PORTS:
	MOVEM.L	(A7)+,D0-D2/A0		; D0-D2 und A0 vom Stack holen
	RTE				; return to where we came from

PASS_PTR:	DC.L	PASS_WORD
PASS_CNT:	DC.B	14
SHIFT:		DC.B	0
PASS_WORD:
	DC.B	$13,$12,$20,$22,$40,$27,$17,$33,$27,$21,$14,$20,$13,$14
		; r   e   a   d       k   i   c   k   s   t   a   r   t
	EVEN

PASS_KEY_TABLE:
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $00-$0f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $10-$1f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $20-$2f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $30-$3f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $40-$4f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,HE	; $50-$5f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $60-$6f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $70-$7f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $80-$8f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $90-$9f
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $a0-$af
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $b0-$bf
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $c0-$cf
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $d0-$df
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $e0-$ef
	DC.L	RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK,RK	; $f0-$ff
	
KEY_TABLE:
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $00-$0f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $10-$1f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $20-$2f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $30-$3f
	DC.L	EP,EP,EP,EP,EP,ES,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $40-$4f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $50-$5f
	DC.L	SD,SD,SD,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $60-$6f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $70-$7f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $80-$8f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $90-$9f
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $a0-$af
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $b0-$bf
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $c0-$cf
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $d0-$df
	DC.L	SU,SU,SU,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $e0-$ef
	DC.L	EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP,EP	; $f0-$ff



; ---------------------------------------------------------------------
;
; Ab hier stehen die Routinen, die durch einen Tastendruck aufgerufen
; werden, auch wenn noch kein Password eingegeben wurde.
;
; ---------------------------------------------------------------------

ES:					; Wird bei esc (=$45) aufgerufen
	JMP	ENDING			; beenden

SD:					; Wird bei Shift down aufgerufen
	ADDQ.B	#1,SHIFT		; Shift-Zaehler um eins erhoehen
	JMP	END_PORTS		; und zurueck

SU:					; Wird bei Shift release aufgerufen
	SUBQ.B	#1,SHIFT		; Shift-Zaehler um eins erniedrigen
	JMP	END_PORTS		; und zurueck

DE:					; wird bei del (=$46) augerufen
	MOVE.L	#START_OVER,MAIN_JMP+2	; Vektor der Hauptschleife verbiegen
	JMP	END_PORTS		; und zurueck

; ---------------------------------------------------------------------
;
; Ab hier stehen die Routinen, die durch einen Tastendruck aufgerufen
; werden, aber nur wenn das Password eingegeben wurde.
;
; ---------------------------------------------------------------------

HE:					; wird durch Help down aufgerufen
	BCHG	#1,CIAA_PRA		; Led-Status umschalten
	JMP	END_PORTS		; Ruecksprung



; ---------------------------------------------------------------------
;
; Ab hier steht der Vertical-Blanking-Interrupt des Titelbildes.
; Der Vertb-Int. wird am aAnfang jedes Videobildes aufgerufen
;
; ---------------------------------------------------------------------

VERTB:
	MOVE.W	#$0020,INTREQ		; Request-Bit loeschen

	MOVEM.L	D0-D1/A0,-(A7)		; Register auf den Stack legen

	MOVEQ	#4,D0			; 5 Bitmapointer sind zu setzen
	MOVE.L	TITLE_BASE,D1		; Adresse des Titelbildes
	LEA	BPL1PT,A0		; Adresse des ersten Registers
SET_TITLE:
	MOVE.L	D1,(A0)+		; Adresse der Plane setzen
	ADDI.L	#8000,D1		; eine Plane dazuaddieren
	DBRA	D0,SET_TITLE		; naechste plane setzen

	MOVEM.L	(A7)+,D0-D1/A0		; Register vom Stack holen
	RTE



; ---------------------------------------------------------------------
;
; Ab hier steht die Fehlerausgaberoutine
;
; ---------------------------------------------------------------------

ERRORS:
	MOVEA.L	4,A6			; ExecBase nach A6
	LEA	INTUI_NAME,A1		; Name der Library nach A1
	MOVEQ	#0,D0			; Version Number 0
	JSR	_LVOOpenLibrary(A6)	; Intuition-Library oeffnen
	TST.L	D0			; Nicht moeglich zu oeffnen ?
	BNE.S	OK_ERR			; wenn doch, dann ok_err
	RTS
OK_ERR:
	MOVE.L	D0,INTUI_BASE		; Adresse abspeichern
	MOVEA.L	D0,A6			; Adresse kopieren
	MOVEQ	#0,D0			; Alert Nummer 0
	MOVE.W	ERRORN,D2		; Nummer des Alerts holen	
	LSL.L	#2,D2			; D2 auf Word-Offset bringen
	LEA	ALERTS,A1		; Adresse der Vektor-table nach A1
	ADDA.L	D2,A1			; Adresse des Vektors nach A1
	MOVEA.L	(A1),A0			; Adresse des Strings nach A0
	MOVE.L	#24,D1			; Hoehe = 24 Punkte
	JSR	_LVODisplayAlert(A6)	; Display it !
	MOVEA.L	INTUI_BASE,A1		; intuition's Basis holen
	MOVEA.L	4,A6			; exec's Basis holen		
	JSR	_LVOCloseLibrary(A6)	; Bibliothek schliessen
	RTS



; ---------------------------------------------------------------------
;
; Ab hier steht der IFF-loader
;
; ---------------------------------------------------------------------

LOAD_IFF:				; A0=Name A5=Ziel D6=X D7=Y
	JSR	OPEN_IFF		; oeffne das file
	JSR	READ_LONG		; lese ein Langwort nach D0
	CMP.L	#"FORM",D0		; FORM-Chunk?
	BEQ.S	FORM_FOUND		; wenn ja, dann weitermachen
	MOVEQ	#2,D0			; Fehler Nummer 2
	JMP	IFF_ERROR		; und ausgeben
FORM_FOUND:
	JSR	READ_LONG		; FORM-Laenge ueberlesen
	JSR	READ_LONG		; lese ein Langwort nach D0
	CMP.L	#"ILBM",D0		; ILBM-Chunk?
	BEQ.S	ILBM_FOUND		; wenn ja, dann weitermachen
	MOVEQ	#3,D0			; Fehler Nummer 3
	JMP	IFF_ERROR		; und ausgeben
ILBM_FOUND:
	JSR	READ_LONG		; lese ein Langwort nach D0
	CMP.L	#"BMHD",D0		; BMHD-Chunk?
	BEQ.S	BMHD_FOUND		; wenn ja, dann weitermachen
	JSR	READ_LONG		; Laenge des aktuellen Chunks
	JSR	SKIP_DATA		; aktuellen Chunk ueberspringen
	BRA.S	ILBM_FOUND		; nochmal versuchen
BMHD_FOUND:
	JSR	READ_LONG		; Laenge des Chunks lesen
	LEA	BMHD,A0			; Adresse des Header-Datenfeldes
	JSR	READ_DATA		; Chunk lesen
	MOVE.W	(A0),D2			; Breite aus dem Chunk lesen
	CMP.W	D6,D2			; Bild so breit wie gewuenscht?
	BEQ.S	IFF_X_OK		; wenn ja, dann weiter
	MOVEQ	#4,D0			; Fehler Nummer 4
	JMP	IFF_ERROR		; Alert ausgeben
IFF_X_OK:
	MOVE.W	2(A0),D2		; Hoehe aus dem Chunk lesen
	CMP.W	D7,D2			; Bild so hoch wie gewuenscht?
	BEQ.S	IFF_Y_OK		; wenn ja, dann weiter
	MOVEQ	#5,D0			; Fehler Nummer 5
	JMP	IFF_ERROR		; Alert ausgeben
IFF_Y_OK:
	JSR	READ_LONG		; lese ein Langwort nach D0
	CMP.L	#"CMAP",D0		; CMAP-Chunk?
	BEQ.S	CMAP_FOUND		; wenn ja, dann weitermachen
	JSR	READ_LONG		; Laenge des aktuellen Chunks
	JSR	SKIP_DATA		; aktuellen Chunk ueberspringen
	BRA.S	IFF_Y_OK		; nochmal versuchen
CMAP_FOUND:
	JSR	READ_LONG		; Laenge des Chunks lesen
	LEA	CMAP,A0			; Adresse der Colormap
	JSR	READ_DATA		; Chunk lesen
	MOVEQ	#31,D0			; 32 Werte zu konvertieren
	LEA	IFF_COLORS,A2		; Adresse des Ziels
DO_COLORS:
	MOVE.B	(A0)+,D1		; R-Wert holen
	LSL.W	#4,D1			; R-Wert konvertieren
	MOVE.B	(A0)+,D1		; G-Wert holen
	MOVE.B	(A0)+,D2		; B-Wert holen
	LSR.B	#4,D2			; B-Wert konvertieren
	OR.B	D2,D1			; B-Wert kopieren
	MOVE.W	D1,(A2)+		; Farbwert schreiben
	DBRA	D0,DO_COLORS		; Schleife
SEEK_BODY:
	JSR	READ_LONG		; lese ein Langwort nach D0
	CMP.L	#"BODY",D0		; BODY-Chunk?
	BEQ.S	BODY_FOUND		; wenn ja, dann weitermachen
	JSR	READ_LONG		; Laenge des aktuellen Chunks
	JSR	SKIP_DATA		; aktuellen Chunk ueberspringen
	BRA.S	SEEK_BODY		; nochmal versuchen
BODY_FOUND:

	JSR	READ_LONG		; Chunk-Laenge ueberlesen
	MOVE.B	PLANES,D4		; Anzahl der Planes nach D4
	EXT.W	D4			; auf word bringen
	SUBQ.W	#1,D4			; D4=Schleifenzaehler
	LSR.L	#3,D6			; D6=Bytes pro Zeile
	MOVE.W	D7,D5			; Hoehe kopieren
	MULU	D6,D5			; D5=Bytes pro Plane
	SUBQ.W	#1,D7			; D7=Schleifenzaehler

	CMP.B	#1,COMP			; komprimiertes Format?
	BEQ	IFF_COMP		; wenn ja, nach iff-comp springen
		
	MOVE.L	D6,D0			; Bytes pro Zeile kopieren
UN_DO_IT:
	MOVE.L	D4,D3			; Schleifenzehler kopieren
	MOVEA.L	A5,A0			; Zieladresse kopieren
UN_ONE_LINE:
	JSR	READ_DATA		; Zeile lesen
	ADD.L	D5,A0			; eine plane weiter gehen
	DBRA	D3,UN_ONE_LINE		; alle planes durchgehen
	CMP.B	#1,MASK			; Maskenplane verwendet?
	BNE.S	UN_NO_MASK		; wenn nicht, naechsten Teil auslassen
	JSR	SKIP_DATA		; Maskenplane ueberspringen
UN_NO_MASK:
	ADDA.L	D0,A5			; eine Zeile weiter gehen
	DBRA	D7,UN_DO_IT		; alle Zeilen abarbeiten
	JMP	CLOSE_IFF		; file schliessen und zurueck
IFF_COMP:
	MOVEA.L	A5,A1			; Zieladresse kopieren
	MOVE.L	D4,D3			; Schleifenzaehler kopieren
PK_ONE_LINE:
	MOVEQ	#0,D2			; Zaehler fuer Bytes pro Zeile
	MOVEA.L	A1,A0			; Zieladresse kopieren
PK_ONE_PLANE:
	JSR	READ_BYTE		; Pack-Byte lesen
	TST.L	D0			; Flags setzen
	BMI.S	PACKED			; wenn neg., dann gepackt
	ADDQ.L	#1,D0			; lese n+1 Bytes
	JSR	READ_DATA		; Daten uebernehmen
	ADDA.L	D0,A0			; Neue Adresse berechnen
	ADD.L	D0,D2			; "Bytes pro Zeile"-Zaehler erhoehen
BACK_FROM_PACK:
	CMP.W	D6,D2			; Zeile fertig?
	BNE.S	PK_ONE_PLANE		; wenn nicht, nochmal wiederholen
	BRA.S	PK_NEXT			; naechsten Teil ueberspringen
	CMP.B	#1,MASK			; Maskenplane verwenden
	BNE.S	PK_NEXT			; wenn nicht, naechsten Teil auslassen
PACKED:
	NEG.L	D0			; Vorzeichen von D0 aendern
	ADD.L	D0,D2			; Zaehler um n-1 erhoehen
	ADDQ.L	#1,D2			; "Bytes pro Zeile"-Zaehler um 1 erhoehen
	MOVE.L	D0,D1			; D0 retten
	JSR	READ_BYTE		; Wert lesen, der kopiert werden soll
PK_COPY_LOOP:
	MOVE.B	D0,(A0)+		; Wert kopieren
	DBRA	D1,PK_COPY_LOOP		; D1+1 mal kopieren
	BRA.S	BACK_FROM_PACK		; ansonsten normal weiter machen
PK_NEXT:
	ADDA.L	D5,A1			; eine Plane dazu addieren
	DBRA	D3,PK_ONE_LINE		; naechste Linie einlesen
MASKING:
	CMP.B	#1,MASK			; Maskenplane verwendet?
	BNE.S	PK_NO_MASK		; wenn nicht, naechsten Teil auslassen
	MOVEQ	#0,D2			; Zaehler fuer Bytes pro Zeile
MSK_ONCE:
	JSR	READ_BYTE		; Pack-Byte lesen
	TST.L	D0			; Flags setzen
	BMI.S	MSK_PACKED		; wenn neg., dann gepackt
	ADDQ.L	#1,D0			; ueberspringe n+1 Bytes
	JSR	SKIP_DATA		; Daten ueberspringen
MSK_BACK:
	ADD.L	D0,D2			; "Bytes pro Zeile"-Zaehler erhoehen
	CMP.W	D6,D2			; Zeile fertig?
	BNE.S	MSK_ONCE		; wenn nicht, nochmal wiederholen
	BRA.S	PK_NO_MASK		; naechsten Teil ueberspringen
MSK_PACKED:
	MOVEQ	#1,D0			; Laenge nach D0
	JSR	SKIP_DATA		; ein Byte ueberlesen
	BRA.S	MSK_BACK		; normal weiter machen
PK_NO_MASK:
	ADD.L	D6,A5			; eine Zeile weiter gehen
	DBRA	D7,IFF_COMP		; naechste Zeile bearbeiten
	JMP	CLOSE_IFF		; file schliessen und dann zurueck

READ_LONG:
	MOVE.L	A0,-(A7)		; A0 auf den Stack legen
	MOVEQ	#4,D0			; ein Langwort lesen
	LEA	LONG_B,A0		; Adresse des Buffers
	JSR	READ_DATA		; Langwort in den Buffer lesen
	MOVE.L	LONG_B,D0		; Langwort nach D0 holen
	MOVEA.L	(A7)+,A0		; A0 vom Stack holen
	RTS				; zurueck
LONG_B:	DC.L	0			; hier kommt das Langw. hinein

READ_BYTE:
	MOVE.L	A0,-(A7)		; A0 auf den Stack legen
	MOVEQ	#1,D0			; ein Langwort lesen
	LEA	BYTE_B,A0		; Adresse des Buffers
	JSR	READ_DATA		; Langwort in den Buffer lesen
	MOVE.B	BYTE_B,D0		; Langwort nach D0 holen
	EXT.W	D0			; D0 vorzeichenrichtig auf Word bringen
	EXT.L	D0			; D0 vorzeichenrichtig auf Long bringen
	MOVEA.L	(A7)+,A0		; A0 vom Stack holen
	RTS				; zurueck
BYTE_B:	DC.W	0			; hier kommt das Langw. hinein

READ_DATA:				; A0=Ziel D0=Laenge
	MOVEM.L	D0-D4/A0-A1/A6,-(A7)	; Register auf den Stack
	MOVE.L	FILE,D1			; Adresse des file-handles
	MOVE.L	A0,D2			; Zieladresse des Reads
	MOVE.L	D0,D3			; Anzahl der zu lesenden Bytes
	MOVE.L	D0,D4			; Kopie der Anzahl machen
	MOVEA.L	DOS_BASE,A6		; DOS-Base nach A6
	JSR	_LVORead(A6)		; und lesen
	CMP.L	D4,D0			; gewuenschte Anzahl gelesen?
	BEQ.S	READ_DATA_OK		; wenn ja, dann weiter
	MOVEM.L	(A7)+,D0-D4/A0-A1/A6	; Register auf den Stack
	ADDQ.L	#4,A7			; Eine Ebene vom Stack nehmen
	MOVEQ	#7,D0			; Error #7
	JMP	IFF_ERROR		; -> zwei Ebenen zurueck -> Hauptprg.
READ_DATA_OK:
	MOVEM.L	(A7)+,D0-D4/A0-A1/A6	; Register auf den Stack
	RTS	

SKIP_DATA:				; A0=Ziel D0=Laenge
	MOVEM.L	D0-D3/A0-A1/A6,-(A7)	; Register auf den Stack
	MOVE.L	FILE,D1			; Adresse des file-handles
	MOVE.L	D0,D2			; Anz. der zu ueberlesenden Bytes
	MOVEQ	#0,D3			; Von der aktuellen r/w-position aus
	MOVEA.L	DOS_BASE,A6		; DOS-Base nach A6
	JSR	_LVOSeek(A6)		; Bytes ueberlesen
	CMPI.L	#-1,D0			; gewuenschte Anzahl ueberlesen?
	BNE.S	SKIP_DATA_OK		; wenn ja, dann weiter
	MOVEM.L	(A7)+,D0-D3/A0-A1/A6	; Register auf den Stack
	ADDQ.L	#4,A7			; Eine Ebene vom Stack nehmen
	MOVEQ	#7,D0			; Error #7
	JMP	IFF_ERROR		; -> zwei Ebenen zurueck -> Hauptprg.
SKIP_DATA_OK:
	MOVEM.L	(A7)+,D0-D3/A0-A1/A6	; Register auf den Stack
	RTS	

OPEN_IFF:
	MOVEM.L	D0-D2/A0-A1/A6,-(A7)	; Register auf den Stack retten
	MOVE.L	A0,D1			; Adresse des Namens nach D1
	MOVE.L	#1005,D2		; Modus = MODE_OLDFILE
	MOVE.L	DOS_BASE,A6		; Adresse der DOS-library
	JSR	_LVOOpen(A6)		; file oeffnen
	TST.L	D0			; kein Erfolg?
	BNE.S	OPEN_IFF_OK		; wenn doch, weitermachen
	MOVE.W	#6,ERRORN		; Fehler Nummer 6
	JSR	ERRORS			; Fehler ausgeben
	MOVEM.L	(A7)+,D0-D2/A0-A1/A6	; Register vom Stack holen
	ADDQ.L	#4,A7			; Stack manipulieren
	RTS				; -> zwei Ebenen zurueck -> Hauptprg.
OPEN_IFF_OK:
	MOVE.L	D0,FILE			; file-handle abspeichern
	MOVEM.L	(A7)+,D0-D2/A0-A1/A6	; Register vom Stack retten
	RTS				; Rueckkehr

CLOSE_IFF:
	MOVE.L	DOS_BASE,A6		; pointer auf die DOSch-library holen
	MOVE.L	FILE,D1			; file-handle nach D1 laden	
	JSR	_LVOClose(A6)		; file schliessen
	RTS				; zurueck

IFF_ERROR:				; D0=Fehlernummer
	MOVE.W	D0,ERRORN		; Fehlernummer 
	JSR	ERRORS			; und ausgeben
	JMP	CLOSE_IFF		; IFF-file schliessen

BMHD:
	DC.W	0,0			; Breite und Hoehe
	DC.W	0,0			; X- und Y-Position
PLANES:	DC.B	0			; Anzahl der Planes
MASK:	DC.B	0			; Art der Maske
COMP:	DC.B	0			; Komprimiert Ja/Nein
	DC.B	0			; Leerbyte
	DC.W	0			; Nummer der Hintergrundfarbe
	DC.B	0,0			; Verhaeltnis von Breite zu Hoehe
	DC.W	0,0			; screen-hoehe und screen-breite
CMAP:
	DS.B	96			; Platz fuer 96 R, G und B Werte
IFF_COLORS:
	DS.W	32			; Platz fuer 32 RGB-Werte


; ---------------------------------------------------------------------
;
; Ab hier stehen der Stack, unsere Variablen und Zwischenspeicher (Buffer)
;
; ---------------------------------------------------------------------

STACK_END:	DS.W	2048		; neuer Stack-Speicher
STACK:		DC.W	0		; oberes Stack-Ende
ADR7:		DC.L	0		; Zwischenspeicher fuer A7
PAGE0:		DS.L	62		; Zwischenspeicher der "Zeropage"
INTENA_BUF:	DC.W	0		; Zwischenspeicher des Int.-Registers
DMACON_BUF:	DC.W	0		; Zwischenspeicher des DMA-Kontrollreg.
INTUI_BASE:	DC.L	0		; Adresse der intuition-library
DOS_BASE:	DC.L	0		; Adresse der dos-library
TITLE_BASE:	DC.L	0		; Adresse unseres Speichers
FILE:		DC.L	0		; Adresse des File-Handles
TITLE_CMAP:	DS.W	32		; Platz fuer die Titelbildfarben
ERRORN:		DC.W	0		; Nummer der Fehlermeldung
ALERTS:		DC.L    ALERT0,ALERT1	; Adressen der Alert-Texte
		DC.L	ALERT2,ALERT3
		DC.L	ALERT4,ALERT5
		DC.L	ALERT6,ALERT7

DOS_NAME:	DC.B	"dos.library",0
GFX_NAME:	DC.B	"gfx.library",0	
INTUI_NAME:	DC.B	"intuition.library",0
TITLE_NAME:	DC.B	"Title.pic"
ALERT0:		DC.B	0,16,16,"Fehler #0: kann nicht genuegend CHIP-memory"
		DC.B	"bekommen !",0,0
ALERT1:		DC.B	0,16,16,"Fehler #1: kann DOS-library nicht oeffnen !",0,0
ALERT2:		DC.B	0,16,16,"Fehler #2: erster Chunk kein FORM-Chunk !",0,0
ALERT3:		DC.B	0,16,16,"Fehler #3: zweiter Chunk kein ILBM-Chunk !",0,0
ALERT4:		DC.B	0,16,16,"Fehler #4: IFF-Bild breiter als gewuenscht !",0,0
ALERT5:		DC.B	0,16,16,"Fehler #5: IFF-Bild hoeher als gewuenscht !",0,0
ALERT6:		DC.B	0,16,16,"Fehler #6: kann IFF-Bild nicht oeffnen !",0,0
ALERT7:		DC.B	0,16,16,"Fehler #7: IFF-file kuerzer als erwartet !",0,0

       END
