Quelltext /~heha/basteln/PC/hh_vts/hh_vts.zip/VTD_LPT/VL.PAS

program vl;
{Videotext über LPT auslesen}
{$G+}
uses crt;
function ReadByte:Byte; assembler;
{PE: DX=Portadresse LPT, VR: AX}
 asm	mov al,$10; out dx,al	;{TAKT=L	 0   1   0   0   0   0 }
	inc	dx
	in	al,dx	;{Low-Nibble 3x21 0xxx}
	dec	dx
	add	ax,ax
	add	al,al
	shl	ax,3	;{AH=xxxx 3210}
	mov al,$14; out dx,al	;{TAKT=H	 0   1   0   1   0   0 }
	mov al,$10; out dx,al	;{TAKT=L	 0   1   0   0   0   0 }
	inc	dx
	in	al,dx	;{High-Nibble 7x65 4xxx}
	dec	dx
	add	ax,ax	;{AX=xxx3 2107 x654 xxxx}
	add	al,al	;{AX=xxx3 2107 654x xxxx}
	shl	ax,3	;{AH=3210 7654}
	mov al,$14; out dx,al	;{TAKT=H	 0   1   0   1   0   0 }
	xchg	al,ah
	ror	al,4
 end;

const
 IOA: Word=$378;
 IRQ: Byte=7;
 Stat: Byte=0;
 Pref: Byte=0;
type
 TVTLine=record
  case integer of
   0: (data: array[0..43] of Byte);
   1: (ch: array[0..43] of Char);
   2: (siz: Byte;		{Länge der Struktur (44=2Ch)}
       vsy: Byte;		{umlaufende Nummer der Vertikalaustastlücke}
       mag: Byte;		{Magazin (Hunderter), hamming-kodiert}
       lin: Byte;		{Zeilennummer, hamming-kodiert}
       txt: array[0..39] of Byte);	{eine Videotext-Zeile, mit Parität}
 end;

var
 Buffer: array[0..599] of TVTLine; {1s Puffer bei 12 Zeilen pro Halbbild}
const
 BufWr: Word=ofs(Buffer);
 BufRd: Word=ofs(Buffer);	{Ausgangspunkt: leerer Puffer}

procedure ReadRAM; assembler;	{		RSR RDR /OE TKT QRY RCV}
 asm	mov	dx,[IOA]
	mov al,$06; out dx,al	;{Abfr. Zähler   0   0   0   1   1   0 }
	mov al,$02; out dx,al	;{TAKT=L	 0   0   0   0   1   0 }
	mov al,$06; out dx,al	;{TAKT=H	 0   0   0   1   1   0 }
	mov al,$24; out dx,al	;{/OE aktiv	 1   0   0   1   0   0 }
	mov al,$04; out dx,al	;{kein RSR	 1   0   0   1   0   0 }
	inc	dx
	in	al,dx
	dec	dx
	add	ax,ax
	add	al,al
	shr	ax,5
	and	al,0Fh
	jz	@@nf		;{kein Fehler}
	test	al,3
	jnz	@@nf
	or	[Stat],1	;{Fehler aufgetaucht}
@@nf:	mov	ah,al
	shr	ah,2		;{tabellenfreie Konversion}
	sub	al,ah		;{Zeilen:=Nibble - Nibble div 3}
	jz	@@e
	mov	ch,al
	mov	bl,al
	shl	bl,4		;{High-Nibble = Zeilen pro Austastlücke}
	mov	bh,[Pref]
	mov al,$02; out dx,al	;{TAKT=L	 0   0   0   0   1   0 }
	mov al,$06; out dx,al	;{TAKT=H	 0   0   0   1   1   0 }
	mov	di,[BufWr]
@@l2:	inc	bl		;{Low-Nibble = aktuelle Zeile in Lücke}
	mov	[di],bx
	add	di,2
	mov	cl,42
@@l1:	call	ReadByte
	mov	[di],al
	inc	di
	dec	cl
	jnz	@@l1
	cmp	di,OFFSET Buffer + TYPE Buffer
	jc	@@1
	mov	di,OFFSET Buffer
@@1:	cmp	di,[BufRd]
	jnz	@@2
	or	[Stat],80h	;{Puffer gerade voll}
	jmp	@@3
@@2:	test	[Stat],80h
	jz	@@3
	or	[Stat],40h	;{Pufferüberlauf}
	mov	[BufRd],di	;{Lesezeiger zwangsweise vorrücken}
@@3:	dec	ch
	jnz	@@l2
	mov	[BufWr],di
@@e:	mov al,$2C; out dx,al	;{Reset RAM-Zä.	 1   0   1   1   0   0 }
	mov al,$0C; out dx,al	;{/OE aus	 0   0   1   1   0   0 }
	mov al,$0D; out dx,al	;{Empfangsbereit 0   0   1   1   0   1 }
	inc	[Pref]
 end;

procedure EOI(IRQ:Byte); assembler; {Spezifischer IRQ, auch für "hohe" IRQs}
 asm	mov	al,[IRQ]
	cmp	al,$0F
	ja	@@e
	or	al,$60
	test	al,$08
	jz	@@1
	and	al,$67
	out	$A0,al
	mov	al,$62
@@1:	out	$20,al
@@e:
 end;

function HookIrq(IRQ:Byte; P:Pointer):Pointer; assembler;
 asm	mov	al,[IRQ]
	cmp	al,$0F
	ja	@@e
	add	al,$08
	cmp	al,$10
	jc	@@1
	add	al,$60	{Hohe IRQ 70..77}
@@1:	mov	ah,35h
	int	21h	{GetIntVect ES:BX}
	push	ds
	 lds	dx,[P]
	 mov	ah,25h
	 int	21h
	pop	ds
	mov	dx,es
	xchg	bx,ax
@@e:
 end;

procedure UnmaskIrq(IRQ:Byte); assembler;
 asm	mov	cl,[IRQ]
	cmp	cl,$0F
	ja	@@e
	mov	ch,$FE
	rol	ch,cl
	test	cl,$08
	jnz	@@hi
	in	al,$21
	and	al,ch
	out	$21,al
	jmp	@@e
@@hi:	in	al,$A1
	and	al,ch
	out	$A1,al
@@e:
 end;

procedure MaskIrq(IRQ:Byte); assembler;
 asm	mov	cl,[IRQ]
	cmp	cl,$0F
	ja	@@e
	mov	ch,$01
	rol	ch,cl
	test	cl,$08
	jnz	@@hi
	in	al,$21
	or	al,ch
	out	$21,al
	jmp	@@e
@@hi:	in	al,$A1
	or	al,ch
	out	$A1,al
@@e:
 end;

const
 Sema:Byte=0;	{Bit 0: Sperre, Bit 7: Anforderung}

function GetLine(var vl:TVTLine):Boolean; assembler;
{liest Zeile nach vl; ist keine vorhanden, dann sofortige Rückkehr mit FALSE}
 asm	inc	[Sema]
	mov	si,[BufRd]
	cmp	si,[BufWr]
	jnz	@@ok
	test	[Stat],80h	{Genau voll?}
	stc
	jz	@@e		{Genau leer und kann nichts lesen!}
@@ok:	cld
	les	di,[vl]
	mov	cx,TYPE TVTLine / 2
	rep	movsw
	cmp	si,OFFSET Buffer + TYPE Buffer
	jc	@@1
	mov	si,OFFSET Buffer
@@1:	mov	[BufRd],si
	and	[Stat],7Fh	{Nicht mehr voll; CY=0}
@@e:	mov	al,1
	sbb	al,0		{BOOLEAN-Meldung}

	dec	[Sema]
	jns	@@nrq
	and	[Sema],7Fh
	push	ax
	 inc	[Sema]
	 call	ReadRAM		{ebenfalls "kritisch"}
	 dec	[Sema]
	pop	ax
@@nrq:
 end;

procedure Tick; assembler;
 asm	mov	al,0A0h
	out	43h,al
	mov	al,2
	out	42h,al
 end;

procedure ISR; interrupt;
 begin
{  Inc(Pref);}
  Tick;
{  asm sti end;}
  if Sema=0 then begin
   Inc(Sema);
   asm sti end;
{   Write('*',Sema);}
   ReadRAM;
   asm cli end;
   Dec(Sema);
  end else begin
   Sema:=Sema or $80;
  end;
  EOI(IRQ);
 end;

procedure SetCharImg;
{zunächst ohne separierte Grafik wegen fehlender Umlaute}
 procedure GenChar8x8(Code:Integer; var Buf); assembler;
  asm	mov	ah,byte ptr Code
	les	di,Buf
	cld
	xor	al,al
	test	ah,1 shl 6
	jnz	@@sep		;{Separierte Grafik}
	call	@@22		;{Oberes Drittel: 3 Scanzeilen}
	call	@@2
	call	@@221		;{Mittleres Drittel: 2 Scanzeilen}
	call	@@221		;{Unteres Drittel: 3 Scanzeilen}
	call	@@2
	jmp	@@e

@@221:	shr	ah,2
@@22:	call	@@2
@@2:	test	ah,1
	jz	@@2a
	or	al,$F0
@@2a:	test	ah,2
	jz	@@2b
	or	al,$F
@@2b:	stosb
	xor	al,al
	ret
@@111:
	shr	ah,2
@@11:	call	@@1
@@1:	test	ah,1
	jz	@@1a
	or	al,$60
@@1a:	test	ah,2
	jz	@@2b
	or	al,$6
	jmp	@@2b
@@sep:
	call	@@11		;{Oberes Drittel}
	stosb			;{Leerzeile}
	call	@@111		;{Mittleres Drittel}
	stosb			;{Leerzeile}
	call	@@111		;{Unteres Drittel}
@@e:	end;
 var
  CharImg: array[0..1023] of Char;	{Zeichenbildtabelle}
  i: Integer;
  SP: PChar;
 begin
  SP:=CharImg;
  for i:=0 to 63 do begin
   GenChar8x8(i,SP^);
   Inc(SP,8);
  end;
  asm	mov	bx,0800h
	mov	cx,40h
	mov	dx,0A0h		{Zeichen von A0h..DFh}
	lea	ax,[CharImg]
	push	bp
	 mov	bp,ax
	 push	ss
	 pop	es
	 mov	ax,1110h
	 int	10h
	pop	bp
  end;
 end;

var
 OldInt7: Pointer;
 VTLine: TVTLine;
 i,m,z,x,y: Integer;
 C: Char;
 Str: String[40];
 Old0, Old2: Byte;		{Merker für Port-Zustände}
 OldExit: Pointer;
 Graf:Boolean;

procedure Finalizer; far;	{falls Laufzeitfehler oder Fatal-Abbruch}
 begin
  ExitProc:=OldExit;
  Port[IOA+2]:=Old2 and not $10;
  MaskIrq(IRQ);
  HookIrq(IRQ,OldInt7);
 end;

begin
 TextMode(C80+font8x8);
 SetCharImg;
 Old0:=Port[IOA];
 Old2:=Port[IOA+2] and $1F;	{nicht unbeabsichtigt tristate schalten!}
 OldExit:=ExitProc;
 ExitProc:=@Finalizer;		{Runtime-Fehler sicher "abfangen"}
 OldInt7:=HookIrq(IRQ,@ISR);
 UnmaskIrq(IRQ);
 EOI(IRQ);
 asm 	sti
	in	al,61h		{Lautsprecher aktivieren}
	or	al,3
	out	61h,al
 end;
 Port[IOA+2]:=Old2 or $10;
 Port[IOA]:=$0D;		{Empfangsbereit}
 Str[0]:=#40;
 WriteLn('STAT VSY LA LC M  Z Text     (ESC zum Beenden mit MODE CO80)');
 WriteLn('■■■■ ■■■ ■■ ■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■');
{Falls es gar nicht erst zu dieser Ausschrift kommt, liegt eine zu hohe
 Interruptfrequenz (mit Software-Selbsterregung:-) vor}
 y:=3;
 repeat
  if GetLine(VTLine) then begin
   GotoXY(1,y);
   m:=VTLine.mag shr 1 and 1 or VTLine.mag shr 2 and 2
     or VTLine.mag shr 3 and 4;
   z:=VTLine.mag shr 7 and 1
     or VTLine.lin shr 0 and 2
     or VTLine.lin shr 1 and 4
     or VTLine.lin shr 2 and 8
     or VTLine.lin shr 3 and 16;
   Graf:=false;
   for i:=0 to 39 do begin
    C:=Char(VTLine.txt[i] and $7F);
    if C<#32 then begin
     case C of
      #0..#7: Graf:=false;
      #16..#23: if (1<=z) and (z<=23) then Graf:=true;
     end;
     C:=' ';
    end else if Graf then case C of
     #32..#63: C:=Char(Byte(C)+$80);	{ab A0h}
     #96..#127: C:=Char(Byte(C)+$60);	{ab C0h}
    end else case C of
     '@': C:='';		{Ersetzungen für deutschen VT}
     '[': C:='Ä';
     '\': C:='Ö';
     ']': C:='Ü';
     '`': C:='°';
     '{': C:='ä';
     '|': C:='ö';
     '}': C:='ü';
     '~': C:='ß';
     '': C:='■';
    end;
    Str[i+1]:=C;
   end;
   if z in [25..30] then HighVideo;
   Write(Stat:4,VTLine.vsy:4,VTLine.siz shr 4:3,VTLine.siz and $0F:3,
     m:2,z:3,Str:41);
   NormVideo;
   Inc(y); if y>Hi(WindMax)+1 then y:=3;
  end else asm
	mov	ax,1680h
	int	2Fh		{Soft-Windows}
  end;
{  while Port[IOA+1] and $40 =0 do;
  write('*');
  while Port[IOA+1] and $40 <>0 do;}
 until keypressed;
 C:=ReadKey;
 case C of
  #0: readkey;
  #27: TextMode(CO80);
 end;
 Port[IOA]:=$2C;		{Stop}
 Port[IOA+2]:=Old2 and not $10;
 MaskIrq(IRQ);
 HookIrq(IRQ,OldInt7);
 ExitProc:=OldExit;
 Port[IOA+2]:=Old2;
 Port[IOA]:=Old0;
end.
Vorgefundene Kodierung: OEM (CP437)1
Umlaute falsch? - Datei sei ANSI-kodiert (CP1252)