Source file: /~heha/vt/viewers/vt080.zip/RXSW/RXSW3.ASM

;RXSW: Satelliten-Receiver-Umschalter
;CTRL+ALT+U: Kanal hoch
;         J: Kanal runter
;         H: Kanalsteuerungs-Automatik
;Version 3 mit Auswertung der VT.INI, Sektion [RXSW3], Schlüssel schedule
;anstatt Patchen der .COM-Datei

	include	prolog.asm
	include	"asc2scan.asm"
REQfunc		equ	4b48h		;in AX
REQcode		equ	9879h		;in DX
ANScode		equ	8764h		;in AX; DX=Segmentadresse
ResPara		equ	(ISRBase-PSPOrg+ISRE-ISRA+0fh)/16

	org	5ch
ctrl0	db	?
ISRBase:	;FCB's überschreiben
ChIst	db	?
ChSoll	db	?
ChAuto	db	?
ChHDrv	db	?
TonL	db	?

	org	100h
	PRINT	Text0		;Meldung
	mov	[ctrl0],0e0h	;erst mal Standard laden
;Bit4 ist Int13BusyFlag
	call	LoadIst		;Istwert von Platte laden, 1..48
	call	InstChk		;ggf. ES auf Fremdroutine
	;nun ch=Statusregister:
	;Bit0..3: Deinstallation nicht möglich
	;Bit7: Noch nicht installiert
	JUMPS
	mov	si,81h
	cld
scancl:	lodsb
	cmp	al,'/'
	jz	scancl
	cmp	al,'-'
	jz	scancl
	cmp	al,' '
	jz	scancl
	cmp	al,'?'
	jz	help
	cmp	al,0dh
	jz	install
	BRES	al,bit 5
	cmp	al,'H'
	jz	help
	cmp	al,'U'
	jz	UnInst
	cmp	al,'D'
	jz	DisAb
	cmp	al,'E'
	jz	setab
	cmp	al,'S'
	jz	Stat2
	cmp	al,'Q'
	jz	quiet
	cmp	al,'I'
	jz	zahlen
scanc0:	jr	scancl		;weiter in Kommandozeile
	NOJUMPS
zahlen:
	push	cx
	 mov	di,ofs SwTab
	 test	ch,bit 7
	 jnz	v0
	 mov	di,ofs SwTab -ISRA+ISRBASE
v0:	 mov	cx,24
v2:	 push	cx
v1:	  lodsb
	  cmp	al,' '
	  je	v1
	  dec	si
	  mov	bl,10
	  call	inw
	  jc	te
	  stosb			;Zahl abspeichern
	 pop	cx
	 loop	v2
	pop	cx
	mov	al,[es:di-24]
	stosb			;25. Stunde wie 1. Stunde
	jr	scanc0
te:	mov	dx,ofs TextE
	jmp	TxtOut

quiet:	lodsb
	cmp	al,'-'
	jnz	sndoff
	bset	[es:ctrl0],bit 5 ;Tastaturpiepser ON
	jr	scanc0
sndoff:	dec	si
	bres	[es:ctrl0],bit 5
	jr	scanc0
help:	;Hilfe Option "H" oder "?"
	mov	dx,offset TextH
	jr	TXTOut


disab:	test	ch,80h
	mov	dx,ofs Text5
	jnz	TXTOut
	mov	dx,ofs Text4b
	jr	TXTOut

UnInst:	;Deinstallation(sversuch) Option "U"
	mov	dx,ofs Text5
	test	ch,80h
	jnz	TXTOut		;Wenn nicht nötig!
	and	ch,0fh
	jz	Raus
	PRINT	Text4b
	mov	dx,ofs Text4a
	bres	[es:Ctrl0],0e0h	;löschen (auch Tastatur sperren)
	jr	TXTOut

DisActiv:;Deaktivieren Option "D"
	test	ch,80h		;Schon installiert?
	mov	dx,ofs Text5
	jnz	TXTOut
	mov	dx,ofs Text4b
	jr	disab
	;Deinstallation
Raus:	lds	dx,[es:ofs OldInt09-ISRA+ISRBASE]
	DOS	2509h
	lds	dx,[es:ofs OldInt08-ISRA+ISRBASE]
	DOS	2508h
	lds	dx,[es:ofs OldInt17-ISRA+ISRBASE]
	DOS	2517h
	lds	dx,[es:ofs OldInt13-ISRA+ISRBASE]
	DOS	2513h
	DOS	49h		;den Speicher ab es freigeben
	push	cs
	pop	ds
	mov	dx,ofs Text3	;removed...

	;dx-adressierten Text ausgeben
TXTOut:	DOS	9		;Textausgabe
	;Programm beenden
LFOut:	PRINT	NL$
	DOS	4C00h

setab:	test	ch,80h
	mov	dx,ofs Text5
	jnz	TXTOut
	bset	[es:Ctrl0],bit 7 ;setzen
stat2:	;hier ist die Statusanzeige
	call	statmeld
	test	ch,80h
	jnz	sta1
	PRINT	Text6
sta1:	jr	lfout

proc InstChk
	;Installationscheck, ES=Zeiger auf installierte Routine oder n.a.!,
	;Bit7(CH)=0: Installationscheck erfolgreich, dann:
	;ES: Segmentadresse der residenten Routine
	;Bit0,1,2(CH)=0: Zeiger nicht von anderen verbogen
	;Di=0 wenn nicht installiert, ISRBASE-ISRA wenn installiert
	mov	ax,REQfunc	;
	mov	dx,REQcode
	int	17h
	xor	ch,ch
	mov	di,ISRBase-ISRA
	cmp	ax,ANScode	;gleich?
	jz	@@1
	or	ch,80h		;Z-Flag "retten"
	xor	di,di
	mov	dx,ds
@@1:	push	dx		;Segment der TSR
	;Segment retten
	DOS	3513h		;Get Int13
	SES	<OldInt13>,bx
	cmp	bx,ofs NewInt13-ISRA+ISRBASE
	jnz	@@13f
	mov	bx,es
	cmp	bx,dx
	je	@@13ok
@@13f:	bset	ch,bit 3	;ch <>0 wenn andere TSR stört
@@13OK:
	DOS	3517h		;Get Int17
	SES	<OldInt17>,bx
	cmp	bx,ofs NewInt17-ISRA+ISRBASE
	jnz	@@17f
	mov	bx,es
	cmp	bx,dx
	je	@@17ok
@@17f:	inc	ch		;ch <>0 wenn andere TSR stört
@@17OK:
	DOS	3508h
	SES	<OldInt08>,bx
	cmp	bx,ofs NewInt08-ISRA+ISRBASE
	jnz	@@08F
	mov	bx,es
	cmp	bx,dx
	je	@@08ok
@@08f:	bset	ch,bit 1
@@08ok:
	DOS	3509h
	SES	<OldInt09>,bx
	cmp	bx,ofs NewInt09-ISRA+ISRBASE
	jnz	@@09F
	mov	bx,es
	cmp	bx,dx
	je	@@09ok
@@09f:	bset	ch,bit 2
@@09ok:
	pop	es
	ret
	endp
proc LoadIst			;Istwert von Platte holen
	mov	bx,ofs SecBuf
	mov	cx,2		;Sektor 2, Zyl. 0
	mov	dx,80h		;Festplatte C: Kopf 0
	DRV	201h		;1 Sektor lesen
	jc	@@e		;Fehler ->Kanal 8 bleibt
	mov	al,[bx]
	mov	[ChHDrv+(ISRA-ISRBase)],al ;Platten-Istwert eintragen
	or	al,al
	jz	@@e
	cmp	al,49
	jnc	@@e		;AL ist nicht im Bereich 1..48
	mov	[ChIst+(ISRA-ISRBase)],al	;Sollte tatsächlicher Istwert sein!
	mov	[ChSoll+(ISRA-ISRBase)],al	;Sollte tatsächlicher Istwert sein!
	mov	[ChAuto+(ISRA-ISRBase)],al	;Sollte tatsächlicher Istwert sein!
@@e:	ret
endp

;═══════════════════════════════════════
ISRA:
	db	8		;mit Einschalt-Kanalnummer belegt!
	db	8
	db	8
	db	8		;Festplatten-Inhalt
	db	0		;Initialisierungswerte
NewInt17: ;Neue INT17-Routine
	cmp	ax,REQfunc      ;Installationscheck?
	jne	I17cont
	cmp	dx,REQcode
	jne	I17cont
	mov	ax,ANScode
	mov	dx,cs
	iret
I17cont:
	cmp	dx,0		;Schnittstelle 0?
	jnz	ToOld17
	xor	ah,ah		;Status: Drucker nicht bereit!
	iret

ToOld17: JMPF
OldInt17 dd	?

NewInt13:	;Neue Int13-Routine: setzt Reentranz-Flag.
	pushf
	 bset	[cs:ctrl0],bit 4 ;Setzt Int13Busy-Flag
	popf
	pushf
	 callf
OldInt13 dd	?
	pushf
	 bres	[cs:ctrl0],bit 4 ;Löscht Int13Busy-Flag
	popf
	sti
	retf	2

NewInt08:
	push	ax ds dx
	 mov	ax,40h		;DS=Bios-Segment
	 mov	ds,ax
	 mov	dx,[8]		;LPT1-Adresse holen
	 cmp	[wo 6ch],0	;Volle Stunde?
	 mov	al,[6eh]	;Stunde holen
	 LD	ds,cs		;DS=Eignes Segment
	 jnz	NoSw		;nein, nichts zu schalten
	 push	bx
	  mov	bx,ofs SwTab-ISRA+ISRBASE ;Schalttabelle adressieren
	  xlat			;Neue Kanalnummer holen
	 pop	bx
	 mov	[ChAuto],al
	 btst	[ctrl0],bit 0	;Auto-Modus?
	 jnz	NoSw		;nein, Schaltverbot!
	 mov	[ChSoll],al	;ja, auch zum Sollwert machen!
NoSw:
	 cmp	[TonL],1	;Läuft Ton?
	 jc	NoTon		;nein
	 dec	[TonL]		;Zeitzähler...
	 jnz	NoTon		;Nicht Null
	 in	al,61h		;Lautsprecher wieder ausschalten
	 and	al,not 3
	 out	61h,al
NoTon:
	 btst	[ctrl0],bit 7
	 jz	EndInt08	;Wenn abgeschaltet nichts tun!

	 in	al,dx
	 test	al,bit 1+bit 2	;Interessierende Bits
	 jz	NoBRes
	 bres	al,bit 1+bit 2	;abschalten (egal welches)
	 jr	OutEnd
NoBRes:
	 mov	ah,[ChSoll]
	 cmp	[ChIst],ah
	 jz	EndInt08	;Nichts zu tun
	 jc	IncIst		;Istwert zu klein -  emulieren
	 dec	[ChIst]
	 bset	al,bit 2	;-Bit
	 jr	OutEnd
IncIst:
	 inc	[ChIst]
	 bset	al,bit 1	;-Bit
OutEnd:	 out	dx,al		;Ausgabe
EndInt08:
	pop	dx ds ax
	pushf
	callf
OldInt08 dd	?		;EOI an INT-Controller ausgeben lassen
	sti
	push	ax bx cx dx ds es
	 LD	ds,cs
	 LD	es,cs
	 mov	al,[ChIst]
	 cmp	[ChHdrv],al	;Istwert auf Platte korrekt?
	 jz	wrerr		;ja, nichts tun
	 btst	[ctrl0],bit 4	;Int13Busy?
	 jnz	wrerr		;Kann (noch) nichts tun
	 mov	bx,ofs SecBuf-ISRA+ISRBase
	 mov	[bx],al		;ChIst als erstes Byte eintragen!
	 mov	cx,2		;Sektor 2 Zylinder 0
	 mov	dx,80h		;Laufwerk C: Kopf 0
	 DRV	301h		;1 Sektor schreiben
	 jc	wrerr
	 mov	al,[ChIst]
	 mov	[ChHdrv],al	;Kanal auf Platte angeglichen.
wrerr:	pop	es ds dx cx bx ax
	iret

;##########################################
NewInt09:
	push	ax ds		;Ansprung durch	Tastendruck
	 xor	ax,ax
	 mov	ds,ax
	 mov	al,[417h]	;Tastatur-Statusbyte, AUSNAHMSWEISE mit DS=0!
	 LD	ds,cs
	 btst	[ctrl0],bit 6	;Tastaturfunktion eingeschaltet?
	 jz	i09cont
	 not	al
	 and	al,00001100b	;nur noch Ctrl & Alt - Flag
	 jnz	i09cont
	 in	al,60h		;AL=Scan-Code der gedr.	Taste
	 cmp	al,16h		;HotKey "U" () gedrückt ?
	 jz	KP1
	 cmp	al,24h		;"J" ()
	 jz	KP2
	 cmp	al,23h		;"H" (auto)
	 jz	KP3
i09cont:
	pop	ds ax
	 JMPF
OldInt09 dd	?

KP1:	;HOCH-Funktion
	bset	[ctrl0],bit 0	;HAND-Bit setzen
	cmp	[ChSoll],48	;Maximal?
	jz	EndHot2		;Nicht stellen!
	inc	[ChSoll]	;Neue Soll-Kanalnummer
	mov	ax,900		;Tonhöhe
	jr	EndHotkey

KP2:	;RUNTER-Funktion
	bset	[ctrl0],bit 0	;HAND-Bit setzen
	cmp	[ChSoll],1	;Minimal?
	jz	EndHot2		;Nicht stellen!
	dec	[ChSoll]	;Neue Soll-Kanalnummer
	mov	ax,1000		;tieferer Ton
	jr	EndHotkey

KP3:	;AUTO-Funktion
	bres	[ctrl0],bit 0	;HAND-Bit löschen
	mov	al,[ChAuto]
	mov	[ChSoll],al	;kopieren
	mov	ax,800		;Höchster Ton
EndHotKey:
	call	Pieps
EndHot2:
	mov	al,20h		;EOI
	out	20h,al
	in	al,61h		;Zeichen abholen
	mov	ah,al
	or	al,80h
	out	61h,al		;Bit 7[61h] setzen
	xchg	al,ah
	out	61h,al		;auf alten Wert zurück
	pop	ds ax
	iret			;zurück zum Caller

proc Pieps	;Piepser (ES=40h, Tonhöhe AX, feste Länge 3 Ticks) sounden
		;und dabei Null Rechenzeit nehmen!
	btst	[ctrl0],bit 5	;Pieps ein?
	jz	@@e		;nein, schweigen
	push	ax
	 in	al,61h
	 or	al,3
	 out	61h,al
	 mov	al,0b6h
	 out	43h,al
	pop	ax
	out	42h,al
	xchg	al,ah
	out	42h,al
	xchg	ah,al		;AX unverändert
	mov	[TonL],3
@@e:	ret
	endp

;#########################################
;SchaltTabelle
SwTab	db	12,12,11,11,10,10,6,6,2,2,3,3	;vormittags
	db	7,5,4,4,8,13,9,9,22,22,28,28,12	;nachmittags

SecBuf	db	512 dup (?)	;Festplattensektor
ISRE:
;=== Ende residenter Code ===

proc Statmeld
	PRINT	TextS1
	test	ch,80h
	mov	dx,ofs Text5	;Nicht installiert
	jnz	@@x
	btst	[es:ctrl0],bit 7
	mov	dx,ofs Text4b
	jz	@@x		;deaktiviert
	btst	[es:ctrl0],bit 0
	mov	dx,ofs Text2
	jz	@@a
	mov	dx,ofs Text2a
@@a:	DOS	9
	PRINT	Text2b
	mov	al,[es:ChIst]
	xor	ah,ah
	call	axdez
	PRINT	Text2c
	mov	cx,24
	mov	si,ofs SwTab -ISRA+ISRBASE
@@l:	PRINT	Space
	seges	lodsb
	xor	ah,ah
	call	axdez
	loop	@@l
	mov	dx,ofs nl$
@@x:	DOS	9
@@e:	ret
	endp

	_OCHR
	_AXDEZ
	_ANUM
	_INW

Install:	test	ch,80h
		jn	z,stat2
	;ISR nach vorn schaufeln
		cld
		push	cs
		pop	es
		mov	si,ofs ISRA
		mov	di,ofs ISRBase
		mov	cx,(ISRE-ISRA+1)/2
		rep	movsw
		mov	di,ISRBASE-ISRA
	;Zeiger verbiegen
		mov	dx,ofs NewInt13-ISRA+ISRBASE
		DOS	2513h		;Set Int13
		mov	dx,ofs NewInt17-ISRA+ISRBASE
		DOS	2517h		;Set Int17
		mov	dx,ofs NewInt08-ISRA+ISRBASE
		DOS	2508h		;Set Int08
		mov	dx,ofs NewInt09-ISRA+ISRBASE
		DOS	2509h		;Set Int09
	;Environment freigeben
		mov	es,[2ch]	;Segment Environment
		DOS	49h		;ENV-Speicher ab es freigeben
	;Test des Hochladens
		mov	ax,cs
		mov	es,ax		;Eigenes Programm=Resident!
		cmp	ax,0a000h
		mov	dx,ofs Text1
		jc	NoHi		;unten
		mov	dx,ofs Text1a
NoHi:	;enabeln
	DOS	9
	PRINT	Text6a
	mov	al,[es:ChIst]
	xor	ah,ah
	call	axdez
	PRINT	Text6b
	mov	dx,ResPara
	DOS	3100h

;═══════════════════════════════════════
	_SCANTAB
macro dbd	str	;;definiere Bytes doppelt mit Backstep für LESS
	irpc	x,<str>
	 db	'&x&',8,'&x&'
	endm
	endm

macro dbu	str
	irpc	x,<str>
	 db	'_',8,'&x&'
	endm
	endm

Text0:	dbd	<RXSW3>
	db	' 02/01 (haftmann#software): $'
Text1a	db	'hoch'
Text1	db	'geladen, $'

Text6	db	'Hotkeys: CTRL+ALT+U[]/J[]/H[auto]$'
Text6a:	dbu	<Prüfe>
	db	' Receiver auf Kanal'
Space	db	' $'
Text6b	db	' !',nl,'$'
Text6d	db	' (Kein Piepsen)$'

Text2	db	'Automatik$'
Text2a	db	'Handwahl$'
Text2b	db	', Kanal $'
Text2c	db	nl,'Kanalliste:$'
TextE	db	'Kanalnummern fehlerhaft!$'

Text3	db	'vom Speicher entfernt.$'
Text4b	db	'deaktiviert.$'
Text4a	db	' (Andere TSR stahl Int08, 09, 13 oder 17)$'
TextS1	db	'Status: $'
Text5	db	'Noch nicht installiert!$'
TextH	db	'		++ FREEWARE ++',nl
	db	'(Satelliten-)Receiver-Umschalter für Videotext-Dekoder.',nl,10
	db	'Parameter:	- (keiner)	laden oder Statusanzeige',nl
	db	'		- d oder 0	RXSW deaktivieren',nl
	db	'		- e		.. aktivieren',nl
	db	'		- q{-}		Hotkeypiepse {einschalten}',nl
	db	'		- s		Status',nl
	db	'		- i<24 Zahlen>	Kanalnummern pro Stunde',nl
	db	'		- u		TSR entfernen',nl
	db	'		- ? oder h	diese Hilfe$'
NL$	db	nl,'$'
	endc
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded