

;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­                                                                   ­­
;  ­­                        WaitAnyKey V1.00                           ­­
;  ­­                                                                   ­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­                                                                   ­­
;  ­­      Copyright 1990      Roger Fischlin                           ­­
;  ­­                          Steigerwaldweg 6                         ­­
;  ­­                          D-6450 Hanau 7                           ­­
;  ­­                          Germany                                  ­­
;  ­­                                                                   ­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­                                                                   ­­
;  ­­  This program is FREEWARE. It's still copyrighted by the author.  ­­
;  ­­                                                                   ­­
;  ­­                                                                   ­­
;  ­­  This program can be freely distributed if :                      ­­
;  ­­  1. the name of  the author  and  the  copyright  remark  remain  ­­
;  ­­     unchanged.                                                    ­­
;  ­­  2. you don't gain any profit by distributing it !                ­­
;  ­­                                                                   ­­
;  ­­                                                                   ­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;  ­­ This  program  ist  PC  relative and  100 %  PURE (set P flag) !  ­­
;  ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­





	incdir	"ram:include/"

	include	"exec/exec_lib.i"
	include	"exec/memory.i"
	include	"libraries/dos.i"
	include	"libraries/dos_lib.i"
	include	"libraries/dosextens.i"


	IFND	DOSTRUE
DOSTRUE	equ	-1
	ENDC
	IFND	DOSFALSE
DOSFALSE	equ	0
	ENDC




; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                               Macro                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


DOS	macro			; der  alte  Macro  muß  ersetzt
	move.l	a5,a6		; werden, da ja die DOS-Library-Base
	jsr	_LVO\1(a6)		; an anderer Stelle (a5) vermerkt ist.
	endm


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                     DOS-Library öffnen                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

_main	lea.l	DosName(pc),a1		; DOS-Library
	moveq.l	#33,d0		; ab Kickstart 1.2
	CALLEXEC	OpenLibrary		; öffnen
	move.l	d0,a5
	tst.l	d0
	beq.s	.Error		; Fehler !
	bsr	MAIN		; Hauptprogramm ausführen
	move.l	d0,-(sp)
	move.l	a5,a1		; DOS-Library wieder schließen
	CALLEXEC	CloseLibrary
	move.l	(sp)+,d0
	rts

.Error	moveq.l	#20,d0
	rts

DosName	DOSNAME


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          Hauptprogramm                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

MAIN	move.l	#DOSTRUE,d0
	bsr	GoRAW		; CON in RAW-Modus umwandeln
.Loop	DOS	Input
	subq.l	#2,sp		; Puffer (2 Byte) anlegen
	move.l	d0,d1
	move.l	sp,d2
	moveq.l	#1,d3
	DOS	Read		; 1 Zeichen lesen (=auf ein Tastendruck warten)
	addq.l	#2,sp		; Stack wieder korrigieren
	DOS	Input
	move.l	d0,d1
	moveq.l	#1,d2		; noch weitere Zeichen im Puffer ?
	DOS	WaitForChar
	tst.l	d0	
	bne.s	.Loop		; gegebenenfalls weitere Zeichen auslesen
				; sonst stören sie bei der späteren Eingabe
	move.l	#DOSFALSE,d0
	bsr	GoRAW		; zurück in CON-Modus
	moveq.l	#0,d0
	rts


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                            GoRAW                                ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ Enthält D0 DOSTRUE (-1) ,versetzt GoRAW die Console in den RAW- ­­
; ­­ Modus bei DOSFALSE (0) hingen versetzt GoRAW die Console zurück ­­
; ­­ in den CON-Modus. Bei einem Fehler ist d0 0.                    ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

	IFND	ACTION_SCREEN_MODE
ACTION_SCREEN_MODE	equ	994
	ENDC

GoRAW	movem.l	d7/a2-a5,-(sp)		; Register retten
	move.l	d0,d7		; Modus retten
	sub.l	a1,a1
	CALLEXEC	FindTask		; Zeiger auf eigenen Task
	move.l	d0,a0
	move.l	pr_ConsoleTask(a0),a2	; ID der zugehörigen Console

	sub.l	a0,a0		; Reply-Port erzeugen
	moveq.l	#0,d0
	bsr	CreatePort
	tst.l	d0		; Fehler ?
	beq	.Label1
	move.l	d0,a3		; Zeiger auf Reply-Port retten

	bsr	CreatePacket		; StandardPacket erzeugen
	tst.l	d0		; Fehler ?
	beq.s	.Label2
	move.l	d0,a4
	move.l	a3,sp_Pkt+dp_Port(a4)	; Reply-Port eintragen

	move.l	d7,sp_Pkt+dp_Arg1(a4)	; Modus eintragen
	move.l	#ACTION_SCREEN_MODE,sp_Pkt+dp_Type(a4)	

	move.l	a4,a1		; Zeiger auf Packet
	move.l	a2,a0		; Zeiger auf Port
	CALLEXEC	PutMsg

.Label5	move.l	a3,a0		; auf Reply warten
	CALLEXEC	WaitPort	

	move.l	a3,a0		; Reply-Message holen
	CALLEXEC	GetMsg
	tst.l	d0		; doch keine Message ?
	beq.s	.Label5
	moveq.l	#1,d0		; kein Fehler

.Label3	move.l	d0,-(sp)
	move.l	a4,a0
	bsr	DeletePacket		; Standard-Packet löschen
	move.l	(sp)+,d0

.Label2	move.l	d0,-(sp)
	move.l	a3,a0
	bsr	DeletePort		; Reply-Port löschen
	move.l	(sp)+,d0

.Label1	movem.l	(sp)+,d7/a2-a5
	rts




; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           CreatePacket                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CreatePacket erzeugt ein StandardPacket,Message- und DosPacket- ­­
; ­­ Teil werden verbunden. In d0/a0 wird er Zeiger zurückgeben,bzw. ­­
; ­­ 0 bei einen Fehler.                                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


CreatePacket	moveq.l	#sp_SIZEOF,d0		; Speicher für StandardPacket reservieren
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.Label1
	move.l	d0,a0	
	lea.l	sp_Pkt(a0),a1		; Zeiger auf Packet-Teil
	move.l	a1,sp_Msg+LN_NAME(a0)	; Node-Namen muß auf Packet-Teil zeigen
	move.l	a0,sp_Pkt+dp_Link(a0)	; DosPacket-Link muß auf Message-Teil zeigen
.Label1	rts	

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           DeletePacket                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ DeletePacket  löscht ein   zuvor   mit  CreatePacket  erzeugtes ­­
; ­­ StandardPacket. Als Parameter  wird  in A0 der  Zeiger auf  das ­­
; ­­ StandardPacket erwartet.                                        ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

DeletePacket	moveq.l	#0,d0
	cmp.l	d0,a0		; 0-Zeiger abfangen !
	beq.s	.NIL
	move.l	a0,a1
	moveq.l	#sp_SIZEOF,d0		; Speicher freigeben
	CALLEXEC	FreeMem
.NIL	rts


; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          CreatePort                             ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CreatePort erzeugt einen  funktionsfähigen   Msg-Port  des Typs ­­
; ­­ PA_SIGNAL mit der Priorität von D0.A0 zeigt auf den Port-Namen, ­­
; ­­ der nicht kopiert  wird. Falls A0 0  ist, wird er nicht in  die ­­
; ­­ Liste öffentlicher  Ports   aufgenommen.  Als SigTask wird  der ­­
; ­­ eigene eingetragen. Der Funktionswert in D0 ist  der Zeiger auf ­­
; ­­ auf den Port oder bei einem Fehler 0 .                          ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­


CreatePort	move.l	a2,-(sp)
	movem.l	d0/a0,-(sp)		; retten
	moveq.l	#MP_SIZE,d0		; Speicher für Port reservieren
	move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
	CALLEXEC	AllocMem
	tst.l	d0
	beq.s	.NoMem
	move.l	d0,a2
	moveq.l	#-1,d0		; Signal belegen
	CALLEXEC	AllocSignal
	move.b	d0,MP_SIGBIT(a2)
	bmi.s	.FreeMem		; kein Signal 
	movem.l	(sp)+,d0/a0
	move.b	d0,MP+LN_PRI(a2)	; Priorität eintragen
	move.b	#NT_MSGPORT,LN_TYPE(a2)
	move.l	a0,MP+LN_NAME(a2)	; Name
	sub.l	a1,a1
	CALLEXEC	FindTask
	move.l	d0,MP_SIGTASK(a2)	; eigener Task als Signal-Empfänger
	lea.l	MP_MSGLIST(a2),a0
	move.b	#NT_MESSAGE,LH_TYPE(a0)	; Messages werden verwaltet
	bsr	NewList
	tst.l	MP+LN_NAME(a2)		; öffentlicher Port ?
	beq.s	.Private
	move.l	a2,a1
	CALLEXEC	AddPort		; Port in allgemeine Liste eintragen
.Private	move.l	a2,d0
	move.l	(sp)+,a2
	rts

.FreeMem	move.l	a2,a1
	moveq.l	#MP_SIZE,d0		; Speicher freigeben
	CALLEXEC	FreeMem
.NoMem	addq.l	#8,sp
	move.l	(sp)+,a2
	moveq.l	#0,d0		; Fehler !
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                            NewList                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ NewList initialisiert eine LIST-Struktur, A0 muß auf die LIST-  ­­
; ­­ Struktur zeigen.                                                ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

NewList	move.l	a0,LH_HEAD(a0)		; LH_HEAD muß auf LH_TAIL zeigen
	addq.l	#LH_TAIL,(a0)
	clr.l	LH_TAIL(a0)		; LH_TAIL muß auf  0 zeigen
	move.l	a0,LH_TAILPRED(a0)
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                         DeletePort                              ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ DeletePort löscht einen zuvor mit CreatePort erzeugten MsgPort. ­­
; ­­ Als Parameter wird in A0 der Zeiger auf den Port erwartet.Noch  ­­
; ­­ ausstehende Messages werden zuvor reply-t.                      ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

DeletePort	move.l	a2,-(sp)
	move.l	a0,a2		; Zeiger retten
	CALLEXEC	Forbid		; Multitasking unterbinden
.Loop	move.l	a2,a0
	CALLEXEC	GetMsg		; Msg holen
	tst.l	d0		; keine (weitere) Message mehr
	beq.s	.AllReplied
	move.l	d0,a1
	CALLEXEC	ReplyMsg		; Message reply-en
	bra.s	.Loop
.AllReplied	move.l	MP+LN_NAME(a2),d0	; öffentlicher Port ?
	beq.s	.Private
	move.l	a2,a1
	CALLEXEC	RemPort		; entfernen
.Private	move.b	MP_SIGBIT(a2),d0
	CALLEXEC	FreeSignal		; Signal freigeben
	move.l	a2,a1		; Speicher freigeben
	moveq.l	#MP_SIZE,d0
	CALLEXEC	FreeMem
	CALLEXEC	Permit		; Multitasking wieder erlauben
	move.l	(sp)+,a2
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                           CLIText                               ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ CLIText gibt den mit einem $00-Byte  abgeschlossen Text (Zeiger ­­
; ­­ in A0) im CLI-Window aus.                                       ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

CLIText	movem.l	d2/d3,-(sp)		; Register retten
	move.l	a0,d2		; Zeiger nach D2
	moveq.l	#-1,d3		; Länge ermitteln
.Label	addq.l	#1,d3
	tst.b	(a0)+
	bne.s	.Label
	DOS	Output		; Handle fürs CLI-Fenster
	move.l	d0,d1
	DOS	Write		; Text ausgeben
	movem.l	(sp)+,d2/d3
	rts

; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­                          GetLong                                ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
; ­­ GetLong übersetzt den ASCII-String (Zeiger in A0)  in ein Long- ­­
; ­­ Word, welches in D0 zurückgeben wird. Anschließend zeigt A0 auf ­­                                                      ­­
; ­­ das erste Zeichen nach der Zalh im String.  Enthält D1  0, trat ­­
; ­­ kein Fehler auf. 1 signalisiert einen Überlauf, -1 zeigt  einen ­­
; ­­ Fehler im Aufbau  an. Unterstützt werden  das  dezimale und das ­­
; ­­ hexadezimale ("$")  Zahlensystem.                               ­­
; ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

GetLong	movem.l	d3-d3/a1-a3,-(sp)	; Register retten
	bsr.s	.Main
	movem.l	(sp)+,d3-d3/a1-a3
	rts

.Main	moveq.l	#0,d0		; Register löschen
	moveq.l	#0,d1
	moveq.l	#0,d2
.Label1	move.b	(a0)+,d3		; Spaces und Tabs überlesen
	cmp.b	#" ",d3
	beq.s	.Label1
	cmp.b	#9,d3
	beq.s	.Label1

	cmp.b	#"$",d3		; hexadezimal ?
	beq	.Hex
	cmp.b	#"-",d3		; negativ ?
	beq.s	.Negativ
	cmp.b	#"9",d3		; Ziffer ?
	bhi	.Fehler
	cmp.b	#"0"-1,d3
	bhi	.Dezimal

.Fehler	subq.l	#1,a0		; ^Fehler
	moveq.l	#-1,d1		; Fehlercode
	rts

.Negativ	tst.b	d2		; teste,ob bereits ein "-"
	bne.s	.Fehler
	moveq.l	#1,d2		; Flag für negativ seten
	bra	.Label1




.Dezimal	subq.l	#1,a0		; A0 auf erste Ziffer setzen
	move.l	a0,a1		; A1 ^erstes Ziffer
.Label_D2	move.b	(a0)+,d3		; nächste Zeiffer holen 
	cmp.b	#"9",d3		; wiederhole, bis Zahlenende
	bhi.s	.Label_D3		; erreicht wird.
	cmp.b	#"0"-1,d3
	bhi.s	.Label_D2

.Label_D3	lea.l	.Data10(pc),a2		; Zeiger auf 10'er-Potenzen
	subq.l	#1,a0		; A0 ^letzte Ziffer+1
	move.l	a0,a3		; A3 ^letzte Ziffer+1 

.Label_D5	move.l	(a2)+,d4		; Stellenzahl holen
	beq.s	.Overflow		; Longwordgrenze überschritten ?
	moveq.l	#0,d3		; D3 löschen
	move.b	-(a3),d3		; vorherige Ziffer holen
	sub.b	#"0"+1,d3		; und in Zahl umwandeln (1 abziehen wegen DBRA-Schleife)
	bmi.s	.D_Zero		; Ziffer "0" abfangen
.Label_D4	add.l	d4,d0		; Stellenzahl so oft wie Ziffer addieren
	dbra	d3,.Label_D4
.D_Zero	cmp.l	a3,a1		; Zahlenanfang erreicht ?
	bne.s	.Label_D5

.Vorzeichen	tst.b	d2		; negatives Vorzeichen ?
	beq.s	.NotNegative
	tst.l	d0		; Ist die Zahl größer als ein Longint ?
	bmi	.Overflow
	neg.l	d0		; negativieren
.NotNegative	moveq.l	#0,d1		; keine Fehler
	rts

.Data10	dc.l	1
	dc.l	10
	dc.l	100
	dc.l	1000
	dc.l	10000
	dc.l	100000
	dc.l	1000000
	dc.l	10000000
	dc.l	100000000
	dc.l	1000000000
	dc.l	0

.Overflow	moveq.l	#1,d1		; Überfluß (Zahl zu groß !)
	rts
		




.Hex	move.b	(a0)+,d3		; erste Stelle OK ?
	bsr.s	.Nibble
	bmi	.Fehler		; Fehler !


	lea.l	-1(a0),a1		; A1 ^ erste Ziffer
.Label_H2	move.b	(a0)+,d3
	bsr.s	.Nibble		; in Hexa-Ziffer übersetzen 
	bpl.s	.Label_H2
	subq.l	#1,a0		; A0 ^letzte Ziffer+1
	move.l	a0,a2		; A2 ^letzte Ziffer+1
	moveq.l	#0,d1
.Label_H3	move.b	-(a2),d3		; vorherige Ziffer
	bsr	.Nibble
	lsl.l	d1,d4		; Nibble an richtige Position schieben
	add.l	d4,d0		; zum Ergebnis addieren
	addq.l	#4,d1
	cmp.b	#32,d1		; 32. Bit erreicht ?
	bhi	.Overflow		; wenn ja, Overflow !
	cmp.l	a2,a1		; Zahlenanfang erreicht ?
	bne.s	.Label_H3
	bra	.Vorzeichen

.Nibble	moveq.l	#0,d4
	cmp.b	#"a"-1,d3		; Ziffer d3 -> Zahl d4
	bls.s	.N1		; Upcase
	cmp.b	#"f",d3
	bhi.s	.N_Error
	sub.b	#"a"-"A",d3
.N1	sub.b	#"0",d3
	cmp.b	#9,d3		; Ziffer ?
	bls.s	.Ziffer
	sub.b	#"@"-"9",d3		; Buchstabe
	cmp.b	#$f,d3
	bhi.s	.N_Error
.Ziffer	move.b	d3,d4
	rts
.N_Error	moveq.l	#-1,d4		; Fehler !
	rts
	


