*
* miscellaneous assembler routines to use with semper.prg
* author     : Jan Kriesten
* last change: 12.04.1993
*

*** Globale Variablen:

	.EXPORT clip
		
	.IMPORT desk, vdi_myhandle

*** Globale Funktionen:

	;*** MYDIAL-Routinen:
	.IMPORT hide_mouse, show_mouse, rect2array, xywh2array
	.IMPORT myrc_intersect

	;*** Bibliotheksroutinen:
	.IMPORT vs_clip, vro_cpyfm, wind_update, itoa

***-----------------------------------------------------------------------------
*** Funktionsname:	get_tos
***		->	a0:	Zeiger Variable, wo TOS-Version gesichert werden soll
***		<-	nichts
***
*** Die Funktion holt die TOS-Version ber den _sysbase-Vektor des Betriebs-
*** systems.
***
get_tos:
		xdef		get_tos				; Funktion exportieren
		move.l		a3, -(sp)			; Register retten
		movea.l		a0, a3				; hierhin muž das Ergebnis
		
		pea			.get_tos			; aufzurufende Funktion
		move.w		#38, -(sp)			; Supexec (XBIOS 38)
		trap		#14					; XBIOS-Trap
		addq.l		#6, sp				; Stack aufr„umen

		movea.l		(sp)+, a3			; Register restaurieren
		rts								; und zurck

.get_tos:
		movea.l		($04f2), a0			; (_sysbase-Vektor)->OSHEADER-Struktur
		move.w		2(a0), (a3)			; TOS-Version sichern
		rts								; und zurck
		
***-----------------------------------------------------------------------------
*** Funktionsname:	do_bcd
***		->	d0: BCD-Zahl
***			a0:	Zeiger auf char[4], wo ASCII gesichert werden soll
***		<-	nichts
***
*** Die Funktion macht aus einer 3-stelligen BCD-Zahl einen ASCII-String.
***
do_bcd:
		xdef		do_bcd				; Funktion exportieren
		clr.w		6(a0)				; String nullterminiert

		move.b		d0, d1				; letzte BCD-Zahl nach d1
		and.w		#$000f, d1			; auf Wortl„nge erweitern
		add.w		#$30, d1			; das ist jetzt ASCII
		lsl.w		#8, d1				; das ist zweite Nachkomma
		move.w		d1, 2(a0)			; nach help
		
		lsr.w		#4, d0				; d0 ein Byte nach links
		move.b		d0, d1				; n„chstes Byte
		and.w		#$000f, d1			; auf Wortl„nge bringen
		add.w		#$30, d1			; das ist jetzt ASCII

		lsr.w		#4, d0				; d0 ein Byte nach links
		add			#$30, d0			; ebenfalls ASCII
		lsl.w		#8, d0				; das kommt ins high-Byte
		or.w		d0, d1				; in d1 vereinigen
		move.w		d1, (a0)			; nach help

		rts								; und zurck

***-----------------------------------------------------------------------------
*** Funktionsname:	normkey
***		->	d0:	kstate (aus evnt_multi)
***			d1: kreturn (aus evnt_multi)
***		<-	d0: normalisierten Tastaturcode
*** Die Funktion bereitet die Rckgabe von pks und pkr eines Evnt-Multi fr 
*** den Aufruf von nkc_tconv auf, die einen TOS-Key folgenden aussehens
*** erwartet:
***
***		Bit 0-7:		ASCII-Code
***		Bit 8-15:		nichts
***		Bit 16-23:		SCAN-Code
***		Bit 24-31:		Keyboard-State
***
*** Zudem werden beide Shift-Bits gesetzt, wenn nur einer gesetzt war, und das
*** CapsLock-Bit und das NKCC-reservierte Bit werden ausgeblendet
normkey:
		xdef		normkey				; Funktion exportieren
		move.w		d3, -(sp)			; Register retten
		move.w		d0, d3				; Keyboard-State nach d3

		;*** Keyboard-Return umwandeln:		
		move.w		d1, d0				; Keyboard-Return nach d1 kopieren
		andi.l		#$000000FF, d0		; Scancode ausblenden
		andi.l		#$0000FF00, d1		; dort den ASCII-Code ausblenden
		lsl.l		#8, d1				; der soll nach TOS-Manier in das obere Word
		or.l		d1, d0				; und wieder zusammensetzen;
		
		;*** Keyboard-State umwandeln:
		moveq.l		#24, d1				; um die Anzahl soll verschoben werden
		lsl.l		d1, d3				; d3 schieben
		or.l		d3, d0				; das fassen wir jetzt alles in d0 zusammen
		
		;*** NKCC aufrufen:
		import		nkc_tconv			; Funktionsadresse importieren
		jsr			nkc_tconv			; daraus jetzt den normalisierten Code

		;*** entsprechende Bits setzen/l”schen:
		andi.w		#$bfff, d0			; das von NKCC reservierte Bit wird ausgeblendet
		
		move.w		d0, d1				; nochmal nach d1 zum testen
		andi.w		#$0300, d1			; alles aužer NKF_RSH und NKF_LSH aublenden
		beq.b		no_or				; wenn keins von beiden gesetzt, dann kein or
		or.w		#$0300, d0			; sonst beide Shift-Codes setzen

no_or:
		andi.w		#$efff, d0			; CapsLock-Code ausblenden

		move.w		(sp)+, d3			; Stack restaurieren
		rts								; und zurck

***-------------------------------------------------------------------------------
*** Funktionsname:	scroll_area
***		->	a0:	Zeiger auf RECT fr den Bereich
***			d0:	delta
***		<-	nichts.
***
*** Die Funktion verschiebt den Bereich, auf den a0 zeigt um delta in 
*** vertikaler Richtung.
scroll_area:
		xdef		scroll_area			; Funktion exportieren
		move.l		d3, -(sp)			; Register retten
		move.l		a3, -(sp)			; "
		
		link.w		a4, #-64			; Lokale Variablen anlegen
				SMFDB	.EQU	-20		; Offsets der Variablen
				DMFDB	.EQU	-40		;
				XY		.EQU	-56		;
				DST		.EQU	-64		;
		move.l		d0, d3				; delta retten
		movea.l		a0, a3				; Zeiger auf RECT retten
		
		;*** Bildschirm sperren und Mauszeiger l”schen:
		moveq.l		#1, d0				; BEG_UPDATE
		jsr			wind_update			; AES-Funktion ausfhren
		jsr			hide_mouse			; MYDIAL: Mauszeiger verstecken

		clr.l		SMFDB(a4)			; Bildschirmadresse erzwingen
		clr.l		DMFDB(a4)			; "

		lea			XY(a4), a1			; dummy
		movea.l		a3, a0				; zu verschiebender Bereich
		jsr			rect2array			; in array wandeln

		lea			XY(a4), a0			; Adresse von xy nach a0
		move.l		(a0), 8(a0)			; xy[0], xy[1] hochkopieren
		move.l		4(a0), 12(a0)		; xy[2], xy[3] hochkopieren
				
		sub.w		d3, 10(a0)			; Clippingbereich berechnen
		sub.w		d3, 14(a0)			; "
		
		lea			DST(a4), a1			; dst-Adresse
		lea			8(a0), a0			; Scrollbereich
		jsr			array2rect			; in Array wandeln
		
		lea			DST(a4), a1			; dst-Adresse
		lea			desk, a0			; Desktop-Ausmaže
		jsr			myrc_intersect		; šberschneidung mit Desktop-Bereich
		
		tst.w		d0					; šberschneidung vorhanden?
		beq			sa_ende				; wenn nicht, dann Ende

		;*** Clipping setzen:
		lea			DST(a4), a0			; RECT fr das Clipping
		moveq.l		#1, d0				; TRUE (Clipping setzen)
		bsr			set_clip			; setzen ...
		
		pea			DMFDB(a4)			; Adresse des 2. MFDB-Blocks
		lea			SMFDB(a4), a1		; Adresse des 1. MFDB-Blocks
		lea			XY(a4), a0			; zu verschiebender Bereich
		moveq.l		#3, d1				; S_ONLY (Zielpixel = Quellpixel)
		move.w		vdi_myhandle, d0	; vdi-handle
		jsr			vro_cpyfm			; VDI-Funktion ausfhren
		addq.l		#4, sp				; Stack restaurieren
		
sa_ende:

		jsr			show_mouse			; MYDIAL: Mauszeiger zeigen
		clr.w		d0					; END_UPDATE
		jsr			wind_update			; AES-Funktion ausfhren

		unlk		a4					; Lokale Variablen entfernen		
		movea.l		(sp)+, a3			; Register restaurieren
		move.l		(sp)+, d3			; "

		rts

***-------------------------------------------------------------------------------
*** Funktionsname:	set_clip
***		->	a0:	Zeiger auf Clipping-Bereich
***			d0:	Clipflag
***		<-	nichts.
***
*** Die Funktion setzt das Clipping auf den Bereich a0
set_clip:
		xdef		set_clip			; Funktion exportieren
		move.l		d3, -(sp)			; Register retten
		move.l		a3, -(sp)			; "
		
		link.w		a4, #-16			; Lokale Variablen fr 2 RECTS
				XYWH	.EQU	-16		; Offsets der Variablen
				DEST	.EQU	-8		; 

		move.w		d0, d3				; Clipflag retten
		movea.l		a0, a3				; Zeiger auf RECT retten
		
		cmpa.l		#0, a3				; ist berhaupt ein Bereich angegeben
		bne			.size				; wenn ja, dann weiter bei .size
		
		;*** sonst Desktop nehmen:
		lea			DEST(a4), a1		; hier rein kopieren
		lea			desk, a0			; Desktop-Ausdehnung
		move.l		(a0), (a1)			; x, y kopieren
		move.l		4(a0), 4(a1)		; w, h kopieren
		
		bra			.cont1				; weiter bei .cont1

.size:
		;*** RECT nehmen:
		lea			DEST(a4), a1		; hier rein kopieren
		move.l		(a3), (a1)			; x, y kopieren
		move.l		4(a3), 4(a1)		; w, h kopieren
				
.cont1:
		;*** Werte in globaler Clipping-Variable sichern:
		lea			clip, a0			; Adresse der Clipping-Variable
		move.l		(a1), (a0)			; x, y kopieren
		move.l		4(a1), 4(a0)		; w, h kopieren
		
		;*** Desktop-šberschneidung bestimmen:
		lea			desk, a0			; Desktop-Bereich
		jsr			myrc_intersect		; bestimmen ...
		
		tst.w		d0					; im Desktop-Bereich?
		beq			.cont2				; wenn nicht, dann nichts zeichnen
		
		;*** in Array wandeln:
		lea			XYWH(a4), a1		; hier rein ...
		lea			DEST(a4), a0		; diese Koordinaten
		jsr			rect2array			; umwandeln
		
		bra			.clip				; Clipping setzen
		
.cont2:
		;*** nichts zeichnen:
		lea			XYWH(a4), a0		; hier rein ...
		clr.w		-(sp)				; 0
		clr.w		d2					; 0
		clr.w		d1					; 0
		clr.w		d0					; 0
		jsr			xywh2array			; umwandeln
		addq.l		#2, sp				; Stack aufr„umen
		
.clip:
		lea			XYWH(a4), a0		; Adresse vom Bereich
		move.w		d3, d1				; Clipflag (TRUE oder FALSE)
		move.w		vdi_myhandle, d0	; VDI-Handle
		jsr			vs_clip				; VDI-Funktion ausfhren
		
		unlk		a4					; Lokale Variablen entfernen
		movea.l		(sp)+, a3			; Register restaurieren
		move.l		(sp)+, d3			; "
		rts								;

***-------------------------------------------------------------------------------
*** Funktionsname:	array2rect
***		->	a0:	Ausgangsarray
***			a1:	Zielrect
***		<-	nichts.
***
*** Die Funktion wandelt ein Array in Rect
array2rect:
		xdef		array2rect			; Funktion exportieren
		move.w		(a0), d0			; array[0] nach d0
		move.w		4(a0), d1			; array[2] nach d1
		
		cmp.w		d0, d1				; Vergleichen, welches von beiden gr”žer
		bpl			.umgek1				; wenn positiv, dann war array[2] gr”žer

		;*** Kleineres nach rext.x, gr”žeres nach rect.w:		
		move.w		d1, (a1)			;
		move.w		d0, 4(a1)			;
		bra			.next1				;
.umgek1:
		move.w		d0, (a1)			;
		move.w		d1, 4(a1)			;
		
.next1:
		move.w		2(a0), d0			; array[1] nach d0
		move.w		6(a0), d1			; array[3] nach d1
		
		cmp.w		d0, d1				; Vergleichen, welches von beiden gr”žer
		bpl			.umgek2				; wenn positiv, dann war array[3] gr”žer

		;*** Kleineres nach rect.y, gr”žeres nach rect.h:		
		move.w		d1, 2(a1)			;
		move.w		d0, 6(a1)			;
		bra			.next2				;
.umgek2:
		move.w		d0, 2(a1)			;
		move.w		d1, 6(a1)			;
		
.next2:
		;*** rect.w korrigieren:
		move.w		(a1), d0			; rect.x holen
		sub.w		d0, 4(a1)			; rect.w - rect.x
		addi.w		#1, 4(a1)			; + 1
		
		;*** rect.h korrigieren:
		move.w		2(a1), d0			; rect.y holen
		sub.w		d0, 6(a1)			; rect.h - rect.y
		addi.w		#1, 6(a1)			; + 1
		
		rts								; und zurck ...

;-------------------------------------------------------------------------------
; select_file ruft Fileselctor auf;
;	-> a0:		Zeiger auf String mit/fr Pfad
;	   a1:		Zeiger auf String mit/fr Name
;	   Stack:	Zeiger auf String mit Label fr Fileselector
;	<- d0:		gedrckter Button (0: Abbruch, 1: OK)
;
select_file:
		xdef		select_file			; Funktion exportieren
		xref		tos					; Variable importieren
		xref		strlen				; Funktionen importieren
		xref		fsel_input			;
		xref		fsel_exinput		;
		
		move.l		a3, -(sp)			; Register retten

		move.l		a0, a3				; Adresse des Pfades retten
		link		a2, #-2				; Lokale Variable anlegen
				OKs			.EQU	-2	; Offset fr lokale Variable

		;*** Parameter fr Fileselector setzen:
		move.l		12(a2), -(sp)		; Label
		pea			OKs(a2)				; pbutton

		;*** fsel_exinput m”glich?
		cmpi.w		#$0140, tos			; tos >= 0x140?
		bpl			.exin				; wenn ja, dann ist es m”glich

.fselin:
		;*** nur fsel_input m”glich:
		jsr			fsel_input			; AES-Funktion ausfhren
		bra			.weiter				; weiter bei .weiter

.exin:
		;*** fsel_exinput m”glich:
		jsr			fsel_exinput		; AES-Funktion ausfhren

.weiter:
		addq.l		#8, sp				; Stack korrigieren
		
		;*** vom Pfad das *.* abschneiden:
		move.l		a3, a0				; Adresse des Pfades nach a0
		jsr			strlen				; und Stringl„nge ermitteln

		bra			.loop		
.while:
		subq.l		#1, d0				; Counter erniedrigen
.loop:
		cmpi.b		#'\', (a3, d0.l)	; ist das Zeichen ein Backslash?
		bne			.while				; wenn nein, dann weiter
		
		addq.l		#1, d0				; d0 + 1 muž auf 0 gesetzt werden
		clr.b		(a3, d0.l)			; Byte l”schen
		
		move.w		OKs(a2), d0			; Rckgabe des gedrckten Buttons

.sf_ende:
		unlk		a2					; Lokale Variablen entfernen
		move.l		(sp)+, a3			; Register restaurieren
		rts

;-------------------------------------------------------------------------------
; time_date holt Zeit und Datum in String;
;	-> a0:		Zeiger auf String fr Zeit (5 Byte)
;	   a1:		Zeiger auf String fr Datum (7Byte)
;	<- nichts.
;
time_date:
		xdef		time_date			; Funktion exportieren
		movem.l		a3/a4/d3, -(sp)		; Register retten
		
		movea.l		a0, a4				; šbergabe sichern
		movea.l		a1, a3
		
		*** Zeit und Datum holen:
		move.w		#23, -(sp)			; Gettime (XBIOS 32)
		trap		#14					; XBIOS-Trap
		addq.l		#2, sp				; Stack restaurieren
		
		move.l		d0, d3				; Rckgabe sichern

		;*** Zeit in String wandeln:
		move.w		#11, d1				; gleich 11 nach rechts schieben
		lsr.w		d1, d0				; in d0 Stunden.
		movea.l		a4, a0				; hierhin wandeln
		move.w		#10, d1				; Basis 10
		bsr			itoa				; wandeln

		tst.b		1(a2)				; ist Ergebnis nur 1-stellig?
		bne			.t1					; wenn nicht, dann weiter bei .t1

		move.b		(a4), 1(a4)			; an die Zweite Stelle schieben
		move.b		#32, (a4)			; Blank einfgen
		
.t1:		
		move.w		d3, d0				; jetzt Minuten wandeln
		lsr.w		#5, d0				; Sekunden ausblenden
		andi.w		#$003F, d0			; Stunden ausblenden
		lea			2(a4), a0			; hierhin wandeln
		move.w		#10, d1				; Basis 10
		bsr			itoa				; wandeln
		
		tst.b		3(a4)				; ist Ergebnis nur 1-stellig?
		bne			.t2					; wenn nicht, dann weiter bei .t2

		move.b		2(a4), 3(a4)		; an die Zweite Stelle schieben
		move.b		#48, 2(a4)			; Null einfgen

.t2:
		;*** Datum in String wandeln:
		swap.w		d3					; jetzt ist das Datum dran
		
		move.w		d3, d0				; in d0 wird gearbeitet
		andi.w		#$001F, d0			; Monat und Jahr ausblenden
		movea.l		a3, a0				; hierhin wandeln
		move.w		#10, d1				; Basis 10
		bsr			itoa				; wandeln

		tst.b		1(a3)				; ist Ergebnis nur 1-stellig?
		bne			.d1					; wenn nicht, dann weiter bei .d1

		move.b		(a3), 1(a3)			; an die Zweite Stelle schieben
		move.b		#48, (a3)			; Null einfgen
		
.d1:
		move.w		d3, d0				; jetzt Monat wandeln
		lsr.w		#5, d0				; Tag ausblenden
		andi.w		#$000F, d0			; Jahr ausblenden
		lea			2(a3), a0			; hierhin wandeln
		move.w		#10, d1				; Basis 10
		bsr			itoa				; wandeln
		
		tst.b		3(a3)				; ist Ergebnis nur 1-stellig?
		bne			.d2					; wenn nicht, dann weiter bei .d2

		move.b		2(a3), 3(a3)		; an die Zweite Stelle schieben
		move.b		#48, 2(a3)			; Null einfgen

.d2:
		move.w		d3, d0				; jetzt Jahr wandeln
		move.w		#9, d1				; um 9 verschieben
		lsr.w		d1, d0				; Monat und Tag ausblenden
		add.w		#80, d0				; + 80
		lea			4(a3), a0			; hierhin wandeln
		move.w		#10, d1				; Basis 10
		bsr			itoa				; wandeln
		
		move.b		#0, 4(a4)			; Strings mit Null enden lassen
		move.b		#0, 6(a3)
		
		movem.l		(sp)+, a3/a4/d3		; Register restaurieren
		rts								; und zurck ...

*****************************************************************************

		.DATA
		.EVEN

*****************************************************************************

		.BSS
		.EVEN

*** Globale Clipping-Variable:
clip:	ds.w	4

		.END

