Source file: /~heha/hs/dos/dosmisc.zip/SRC/NEWBEEP.ASM

;Programm NEWBEEP.COM (17.02.99), noch leidlich kurz im Speicher...
;Leitet den Pieps der Standardausgabe auf eine gängige Soundkarte um.
;
;Dieses Programm ist möglichst VOR dem Start von Windows zu laden,
;z.B. in der AUTOEXEC.BAT. Dieses Programm läuft auch auf 8086-Urgestein.
;
;Neu: korrekte Windows-Unterstützung und RELEASB
;(ansonsten bleibt die DOS-Box "auf ewig" Besitzer der Soundkarte)
;Der ReleaSB-Teil muß ggf. an den aktuell verwendeten VxD angepaßt werden!
;Hier: SoundBlaster und kompatible Karten/VxDs
;Die Art des Installations-Checks ist hier ziemlich simpel gehalten.
;
;henrik.haftmann@e-technik.tu-chemnitz.de
;http://www.tu-chemnitz.de/~heha/hs_freeware/freew.htm

	IDEAL				;Turbo Assembler (Borland) erforderlich
	MODEL	tiny
	CODESEG
		org	0
SegStart:
		org	58h		;irgendwie wollte 38h nicht mehr:-(
ISRBase:
VSBPDEntry	dd	?
CurVM		dw	?
TCount		db	?
SndData		db      25 dup (?)
		org	100h
start:		mov	dx,offset Text0
		mov	ah,9
		int	21h			;Meldung
		mov	si,81h
		cld
scancl:		lodsb
		cmp	al,'?'
		je	help
		cmp	al,'h'
		je	help
		cmp	al,'H'
		je	help
		cmp	al,0dh
		jne	scancl

		mov	ax,3510h
		int	21h			;Get Int10
		mov	[word ptr OldInt10],bx
		mov	[word ptr OldInt10+2],es
		mov	dx,es
		mov	cx,bx
		mov	ax,3508h
		int	21h			;Get Int8
		mov	[word ptr OldInt8],bx
		mov	[word ptr OldInt8+2],es

		cmp	cx,offset NewInt10-ISRA+ISRBASE
		jne	newinst
		cmp	bx,offset NewInt8-ISRA+ISRBASE
		jne	newinst
		mov	cx,es
		cmp	cx,dx
		jne	newinst

		lds	dx,[es:offset OldInt10-ISRA+ISRBASE]
		mov	ax,2510h
		int	21h
		lds	dx,[es:offset OldInt8-ISRA+ISRBASE]
		mov	al,8
		int	21h
		mov	ah,49h
		int	21h		;den Speicher ab es freigeben
		push	cs
		pop	ds
		mov	dx,offset Text3
		mov	ah,9
		int	21h			;Removed...
		mov	ax,4C01h
		int	21h

help:		mov	dx,offset TextH
		mov	ah,9
		int	21h			;Meldung
		mov	ax,4c00h
		int	21h			;Ende

newinst:
		call	DetectAdlib
		jnc	SBOK			;wenn kein Fehler
		mov	dx,offset Text1
		mov	ah,9
		int	21h			;Fehlertext
		mov	ax,4Cffh
		int	21h
SBOK:
;Falls man doch in einer DOS-Box das TSR startet, wäre bereits beim Laden
;die Soundkarte dauerhaft bis zum nächsten Pieps blockiert - deshalb
;hier "enteisen"
	xor	bx,bx
	mov	ax,1683h	;Get Current VM ID =>BX
	int	2Fh
	mov	[CurVM],bx	;0 bedeutet: kein Windows
	call	ReleaSB
		cld
		push	cs
		pop	es
		mov	si,offset ISRA
		mov	di,offset ISRBase
		mov	cx,(ISRE-ISRA+1)/2
		rep	movsw

		mov	dx,offset NewInt10-ISRA+ISRBASE
		mov	ax,2510h
		int	21h			;Set Int10
		mov	dx,offset NewInt8-ISRA+ISRBASE
		mov	ax,2508h
		int	21h			;Set Int8

		mov	es,[2ch]	;Segment Environment
		mov	ah,49h
		int	21h		;ENV-Speicher ab es freigeben
		mov	dx,offset Text2
		mov	ah,9
		int	21h			;alles OK
		mov	dx,((ISRE-ISRA)+(ISRBase-SegStart)+15)/16 ;Paragrafen
		mov	ax,3100h
		int	21h			;TSR

;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;  Residenter Bereich (wird vorkopiert)
;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

ISRA:

;VSBPDEntry
	dd	0
;CurVM
	dw	0
;TCount
	db	0
;SndData
	dw	2001h, 8120h, 8123h
	dw	1040h, 0043h, 0f360h
	dw	0f363h, 7780h, 7b83h
	dw	00C0h, 98A0h, 31B0h
	db	0FFh			;Abschluß!


proc NewInt10
	pushf
	 cmp	ax,0E07h
	 je	@@Sound		;TTY CHR 7
	popf
		db	0eah		;jmp far
OldInt10	dd	0

@@Sound:
	 sti
	 push	si ax bx
	  xor	bx,bx
	  mov	ax,1683h	;Get Current VM ID =>BX
	  int	2Fh
	  mov	[cs:CurVM],bx	;0 bedeutet: kein Windows
	  call	AdlibReset		;Globalreset
	  mov	si,offset SndData
	  cld
@@l:	  SEGCS	lodsw
	  cmp	al,0ffh
	  je	@@2
	  call	AdlibOutAX
	  jmp	@@l		;Komplette Programmierung!
@@2:	  mov	[cs:TCount],36	;Zähler
	 pop	bx ax si
	popf
	iret
endp NewInt10


proc NewInt8	;Nach einiger Zeit Globalreset ausführen
	pushf
	 cmp	[cs:TCount],0
	 je	@@Nix
	 dec	[cs:TCount]
	 jnz	@@Nix
;Neu: Weil das Port-Trapping von VADLIBD.386 VM-bezogen wirkt, muß diese
;umgeschalten werden.
	 cmp	[cs:CurVM],0	;Windows?
	 jz	@@dos		;blankes DOS!
PUSHSTATE
P286				;Mit VMs kann man sogar 386 voraussetzen!
	 pusha
	  mov	ax,1683h
	  int	2Fh
	  cmp	bx,[cs:CurVM]
	  jz	@@vmok		;gleiche VM - nicht umschalten!
	  mov	bx,[cs:CurVM]
	  mov	cx,3		;Wait_For_STI or Wait_Not_Crit
	  xor	dx,dx
	  xor	si,si		;kein Boost
	  mov	di,offset ResAndFree-ISRA+ISRBASE
	  push	es cs
	   pop	es		;ES:DI=Callback-Adresse
	   mov	ax,1685h
	   int	2Fh
	  pop	es
	 popa
	 jmp	@@Nix		;der Int2F wird's schon machen
@@vmok:	 popa
POPSTATE
@@dos:	 call	AdlibReset		;Globalreset
	 call	ReleaSB
;Danach Soundkarte wieder freigeben - ist ganz praktisch
@@Nix:	popf
		db	0eah		;jmp far
OldInt8		dd	0
endp NewInt8

proc ResAndFree far
;AdLib rücksetzen und Soundkarte freigeben; IRET-Routine für Int2F/1685
	call	AdlibReset
	call	ReleaSB
	iret
endp ResAndFree


;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;   Residente Unterprogramme
;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

proc In388cx	;Port 388 cx-mal einlesen
	push	ax dx
	 mov	dx,388h
@@l:	 in	al,dx
	 loop	@@l
	pop	dx ax
	ret
endp In388cx

proc AdlibReset	;Allgemeines Rücksetzen der AdLib-Soundkanäle
	push	ax
	 mov	ax,0FFh		;255 Schleifenläufe!
@@l:	 call	AdlibOutAX
	 dec	al
	 jnz	@@l
	pop	ax
	ret
endp AdlibReset

proc AdlibOutAX
;al nach 388 und ah nach 389 ausgeben
	push	ax cx dx
	 mov	dx,388h
	 out	dx,al
	 mov	cx,6		;6mal
	 call	In388cx
	 mov	dx,389h
	 mov	al,ah
	 out	dx,al
	 mov	cx,23h		;23h-mal
	 call	In388cx
	pop	dx cx ax
	ret
endp AdlibOutAX

proc ReleaSB
;SoundBlaster-Karte (VSBPD.386) "freischalten" für andere VMs
;Muß in der besitzenden VM gerufen werden
;PE: [CurVM], PA: -, VR: Flags
	cmp	[cs:CurVM],0
	jz	@@nosb		;Kein Windows!
PUSHSTATE
P286
	pusha
	push	es
	 xor	di,di
	 mov	es,di
	 mov	bx,292Dh	;VSBPD_Device_ID
	 mov	ax,1684h	;Get Devive API Entry Point
	 int	2Fh
	 mov	ax,es
	 mov	[word HIGH cs:VSBPDEntry],ax	;Byte-Geizhals!
	 mov	[word LOW cs:VSBPDEntry],di
	 or	ax,di
	 jz	@@nosb		;Kein VSBPD.386
	 mov	ax,0220h	;{übliche Basisadresse}
	 mov	bx,0003h	;{AdLib und DSP freigeben}
	 mov	dx,0002h	;{Funktionsnummer "Release"}
	 call	[cs:VSBPDEntry]
	pop	es
	popa
POPSTATE
@@nosb:	ret
endp ReleaSB


ISRE:
;Ende residenter Teil!

;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
;	Transiente Unterprogramme
;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

proc DetectAdlib	;mit ax=??
;sucht eine AdLib-kompatible Soundkarte
	call	AdlibReset	;Globalreset
	mov	ax,6004h
	call	AdlibOutAX
	mov	ax,8004h
	call	AdlibOutAX
	mov	dx,388h
	in	al,dx
	and	al,0E0h
	jnz	@@e

	mov	ax,0ff02h
	call	AdlibOutAX
	mov	ax,2104h
	call	AdlibOutAX
	mov	cx,14000	;ganz schön oft!
	call	In388cx
	in	al,dx
	push	ax
	 mov	ax,6004h
	 call	AdlibOutAX
	 mov	ax,4
	 call	AdlibOutAX
	pop	ax
	and	al,0E0h
	cmp	al,0C0h
	jne	@@e
	ret
@@e:	stc			;carry als Meldungsflag
	ret
endp DetectAdlib


Text0	db	'NEWBEEP 1.1 (haftmann#software)$'
Text1	db	': Soundkarte nicht gefunden!',13,10,'$'
Text2	db	' installiert, Speicherbedarf 384 Bytes.',13,10,'$'
Text3	db	' vom Speicher entfernt.',13,10,'$'
TextH	db	' Aufgemöbeltes Programm zur Umleitung von',13,10
	db	'PC-Speaker-Piepsern auf den Soundblaster o.ä. (AdLib-FM-Chips).',13,10,10
	db	'Außer /h oder /? für diese Hilfe keine Parameter!',13,10,10
	db	'Sollte wider Erwarten die Deinstallation durch Wiederaufruf nicht',13,10
	db	'funktionieren, hat sich eine andere TSR in den INT08 oder INT10',13,10
	db	'eingeklinkt. Dazu: *Neues NEWBEEP entfernen, *Stör-TSR raushauen,',13,10
	db	'*altes NEWBEEP entfernen. [1.1: Windows-kompatible Version mit ReleaSB]',13,10,'$'

	end	start
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded