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

;Programm KeepVideoMode gegen das SetVideoMode03-Syndrom
;Aufruf: keepvm <programmname> <parameter>
;P.S.: Hiermit kann man auch Nicht-EXE-Programme mit MZ-Header
;ohne Umbenennung zum Abarbeiten bringen!

	include	prolog.asm
	mov	[parseg],ds
	;Kommandozeile abscannen
	cld
	mov	si,81h
	mov	di,80h
	mov	cl,[di]
sk1:	lodsb
	dec	cl
	cmp	al,0dh		;Ende?
	jz	help
	cmp	al,21h
	jc	sk1		;Trennzeichen
	cmp	al,'/'
	jz	sk11		;für gebräuchliches /?
	cmp	al,'?'
	jnz	sk41
help:	PRINT	msgH
	xor	ax,ax
	jmp	hlp
sk11:	cmp	[by si],'x'
	jz	sk13
	cmp	[by si],'X'
	jnz	sk1
sk13:	mov	[keepscr],ax	;Image retten!
	inc	si
	dec	cl
	jr	sk1

sk41:	dec	si
	inc	cl
sk4:	movsb			;um 1 Zeichen vorkopieren
	dec	cl		;immer restliche Zeichen mitzählen
	cmp	[byte si],21h
	jnc	sk4
	;80h steht Dateiname
	;SI= ^Parameter
	;DI= ^Ende Dateiname+1
	dec	si
	mov	[si],cl		;Abschlußzeichen
	;SI= ^Parameter MIT Anzahl Bytes

	mov	[byte di],0	;Endekennung
	mov	[parofs],si
	mov	sp,100h		;erst DEC, dann Schreiben! (wie Z80)

	test	[keepscr],-1
	jz	NoSave
	call	OpenTmp
	jc	errm
	call	SaveImg
	xchg	bx,ax
	jc	Errm

NoSave:
	ResizeM			;Speicherblockgröße verändern

	mov	ah,0fh
	int	10h
	call	GetLines	;ah=Zeilenzahl
	mov	[VM],ax

	mov	dx,80h
	mov	bx,offset params
	DOS	4b00h		;starten
	mov	bx,cs
	mov	ss,bx
	mov	sp,100h
	mov	ds,bx
	mov	es,bx
	mov	bl,al		;Exit- oder Errorcode
	jnc	bye
errm:
	PRINT	msgE
	mov	al,bl
	call	ahex
	jmp	Exi		;Kein CLS!

bye:	;bl=ExitCode
	push	bx
	mov	ah,0fh
	int	10h		;VM ermitteln
	mov	bl,al
	mov	ax,[VM]
	cmp	al,bl
	jz	vmok
	push	ax
	xor	ah,ah
	int	10h
	pop	ax
vmok:	cmp	al,4		;Der multiple Modus?
	jc	vmx1
	cmp	al,7
	jnz	EndMode00
vmx1:	xchg	al,ah
	cmp	al,27
	jz	Mo28
	cmp	al,32
	jz	mo28
	cmp	al,49
	jne	EndMode00
mo28:	push	ax
	int	10h		;Cursorpos
	pop	ax
	sub	dh,al		;CY=0 und Z=0: Cursor steht unter dem Fenster!
	jbe	noscroll
	push	ax
	mov	ah,8
	int	10h
	mov	bh,ah		;Attribut
	mov	al,dh		;Rollweite
	mov	cx,0
	call    GetLines
	mov	dh,ah
	mov	dl,79
	mov	ah,6
	int	10h		;rollen
	mov	ah,0fh
	int	10h		;Seite ermitteln
	mov	ah,3
	int	10h		;GetCursor
	pop	ax
	push	ax
	mov	dh,al
	mov	ah,2
	int	10h
	pop	ax
noscroll:
	cmp	al,27
	jz	Mode28
	cmp	al,32
	jz	Mode33
VGAMode:
	MOV	AX,1112h
	xor	bx,BX
	INT	10h
	MOV	AX,1200h
	MOV	BL,20h
	INT	10h
	mov	ax,0714h
	jr	em01
EndMode00:
	jr	EndMode
Mode28:
	mov	ax,1111h
	xor	bl,bl
	int	10h
	mov	ax,1202h
	mov	bl,30h
	int	10h
	mov	cx,0b14h
	mov	ah,1
	int	10h
	mov	dx,3d4h
	mov	ax,0d0eh
	jr	EM01
Mode33:
	mov	BH,2
	mov	AX,1130h
	int	10h		;Adresse Font14x8 erhalten nach es:bp
	inc	BP		;immer oben 1 Scanzeile weg
	mov	CX,100h
	mov	DX,0
	mov	BX,0E00h
	mov	AX,1110h
	int	10h
	mov	ax,0b09h	;unten auch noch 1 Zeile weg gibt 12 Zeilen
	call	pcrtc
	xor	ax,AX
	mov	ES,AX
	mov	[by es:484h],32
	mov	ax,LOW(33*12-1)*256+12h
	call	pcrtc
	mov	ax,0b14h
em01:
	call	pcrtc		;Underline-Bugfix nach RalfBrownIntList
EndMode:
	test	[keepscr],-1
	jz	noLoad
	call	GetImg
noload:
	pop	bx
Exi:	mov	al,bl
hlp:	mov	ah,4ch		;Programmende
	int	21h

pcrtc:	;CRT-Controller-Register programmieren
	;AL=Funktions-Adresse, AH=Ausgabe-Byte
	push	dx
	push	ax
	 mov	ah,12h
	 mov	bl,10h
	 int	10h		;{Get Monochrom-Bit to bit0(bh)}
	 mov	dx,3d4h		;{Color CRTC Base Address}
	 test	bh,1
	 jz	@@1
	 mov	dx,3b4h		;{Mono CRTC Base Address}
@@1:	pop	ax
	 cli
	 out	dx,al
	 inc	dx
	 xchg	al,ah
	 out	dx,al
	 sti
	pop	dx
	ret

GetLines:;ah=Zeilenzahl-1
	push	ds
	push	bx
	mov	bx,40h
	mov	ds,bx
	pop	bx
	mov	ah,[84h]	;Letzte Bildschirmzeile
	pop	ds
	ret

;-------------- Allgemeine UP-Sammlung ----------
ahex:	push	ax		;Werte erhalten
	mov	cl,4		;oberes Nibble auf Bit 3...0
	shr	al,cl		; schieben
	call	ahex1
	pop	ax
ahex1:	and	al,0fh
	add	al,90h		;Hex -> ASCII
	daa
	adc	al,40h
	daa
	mov	dl,al
	mov	ah,2
	int	21h
	ret

GetImg:	;GetImage
	mov	dx,[curso]
	mov	ah,2
	mov	bh,0
	int	10h		;Cursor setzen!
	mov	dx,ofs TmpFile
	DOS	3d00h		;öffnen
	jc	GI1
	push	ds
	mov	bx,ax
	mov	cx,[ImgLng]
	mov	ds,[keepscr]
	mov	dx,0		;Einschränkung
	DOS	3fh		;lesen
	pop	ds
	jc	GI1
	DOS	3eh		;schließen
	jc	GI1
	mov	dx,ofs TmpFile
	DOS	41h		;löschen
GI1:	ret

params	dw	0
parofs	dw	80h
parseg	dw	?

VM	dw	0
keepscr	dw	0		;Bilschirmswap-Segment
ImgLng	dw	?
curso	dw	?
msgE	db	'DOS-Fehler #$'
TmpFile	db	'C:/',60 dup(0)	;Temporäre Datei

ResEnd:	;Ab hier von Tochter überschreibbar

tmp$	db	'TEMP='
OpenTmp:;VR: AX, BX, DX
	;ES=Ptr Environment
	push	di si cx
	mov	es,[2ch]
	xor	di,di
	xor	ax,ax
	cld
lp3:	mov	cx,5		;Länge von TEMP=
	mov	si,offset tmp$
	repe	cmpsb		;Vergleichen
	je	lp2		;gleich
	dec	di
lp1:	scasb
	jnz	lp1
	scasb
	dec	di
	jnz	lp3
	push	ds
	pop	es
	jr	lp4

lp2:	mov	si,ofs TmpFile
	EX	ds,es
	xchg	si,di
lp5:	lodsb			;StrCopy
	stosb
	or	al,al
	jnz	lp5
	push	es
	pop	ds		;DS back!
	mov	[by di-1],'\'	;das Schlußzeichen wie intern
lp4:	mov	dx,ofs TmpFile
	mov	cx,0
	DOS	5ah		;Temporäre Datei erstellen
	mov	bx,ax
	pop	cx si di
	ret			;Mit oder ohne CY

SaveImg:
	push	ds bx		;Handle retten
	mov	ah,0fh
	int	10h
	push	ax
	mov	ah,3
	int	10h		;in bh noch die Seite
	mov	[curso],dx
	pop	ax
	mov	dx,0b000h
	cmp	al,7		;Hercules?
	jz	JHerc
	mov	dh,0b8h
JHerc:	mov	[keepscr],dx
	mov	ds,dx		;Fernes Segment...
	xchg	al,ah		;Zeichen pro Zeile
	call	GetLines
	or	ah,ah
	pushf
	inc	ah
	mul	ah		;Zeilenzahl
	popf
	jnz	lngok
	mov	ax,80*25
lngok:	shl	ax,1		;2 Bytes!
	mov	cx,ax
	mov	[es:ImgLng],cx
	mov	dx,0		;Nur Bildseite Null!! (Einschränkung)
	pop	bx
	DOS	40h		;write
	jc	SavI1
	cmp	ax,cx
	stc
	jnz	SavI1
	DOS	3eh		;close
SavI1:	pop	ds
	ret

msgH	db	'KeepVideoMode v1.33 (haftmann#software): Batch-Hilfsprogramm',nl
	db	'Gebrauch: keepvm programmname [parameter]',nl
	db	'stellt den Videomodus nach Programmausführung auf den vor dem Start.',nl
	db	'(Vollständiger Name mit Erweiterung notwendig!)',nl
	db	'In dieser Version bitte nur *ausführbare* Programme angeben, also z.B.',nl
	db	'KEINE Batch-Dateien!!!',nl
	db	'Option /X rettet Bildschirm-Text in temporärer Datei',nl
	db	'$'
;
	ENDC
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded