VTEMPFASM;
;	************************
;	***VIDEOTEXT-SOFTWARE***
;	************************
;
;	****EMPFANGSROUTINEN****
;
;	STAND: 11.11.89
;	ERSTELLT AUF KC85/3-EDAS1.4
;
;	G.REINHOLD
;	MOSKAUER STR. 3
;	RIBNITZ-DAMGARTEN
;	2590
;
;---------------------------------------
;
	ORG	0200H
;
;
RESET	IN	A,(PDB)
	RES	1,A
	OUT	(PDB),A	; H --> L
	SET	1,A
	OUT	(PDB),A ; L --> H
	RET
;
CLATCH	LD	HL,LATCH
	LD	(HL),0
	LD	DE,LATCH+1
	LD	BC,LLATCH
	LDIR
	RET
;
INIT	LD	A,4FH
 	OUT	(PSA),A	;BYTEEINGABE
  	IN	A,(PDA)	;ARDY=HIGH
	LD	A,0CFH	;BITBETRIEB
	OUT	(PSB),A
 	LD	A,5
 	OUT	(PSB),A	;BIT0,2=EINGANG
	LD	A,1
	OUT	(PDB),A	;RESETLTG.=L
	RET
;
;	ABFRAGE AUF ENDE BILDAUSTASTIMP.
;	ENDE BEI L-H-FLANKE
BAITST	IN	A,(PDB)
	BIT	0,A	;LOW ?
	JR	NZ,BAITST
BAIHT	IN	A,(PDB)
	BIT	0,A	;HIGH ?
	JR	Z,BAIHT
	CALL	RESET
	RET
;
;	ERMITTELN DER ANZAHL DER GESEN-
;	DETEN VT-ZEILEN PRO BAI
EZPBAI	LD	C,0
EZANF	IN	A,(PDB)
	BIT	0,A
	JR	NZ,EZANF ;LOW ?
	AND	04H
	LD	B,A
EZPB1	AND	04H	 ;BIT 2 TESTEN
	CP	B
	JR	Z,EZPB2
	LD	B,A	 ;FLANKE MERKEN
	INC	C	 ;DA FL.-WECHSEL
EZPB2	IN	A,(PDB)
	BIT	0,A
	JR	Z,EZPB1
 	LD	A,C
	LD	(AZPBAI),A
	RET
	;
EZPB	DI		;INT-SPERRE
	PUSH	BC
	PUSH	DE
EZPB4 	LD	D,10
	CALL	EZPBAI
	LD	E,A	;ANFANGSWERT
EZPB5	CALL	EZPBAI
	CP	E
	JR	NZ,EZPB4
	DEC	D
	JR	NZ,EZPB5
	LD	(AZPBAI),A
	POP	DE
	POP	BC
	EI		;INT-FREIGABE
	RET
;
;	42 BYTES AUS VT-INTERFACE HOLEN
INP42	LD	HL,(ZLATCH)
     	PUSH	BC
	LD	B,42
	LD	C,PDA
	INIR
 	POP	BC
	RET
;
;	GRUPPEN PRO BYTE
;	BIT0 - SCHUTZBIT       S0
;	BIT1 - INFORMATIONSBIT I0
;	BIT2 - SCHUTZBIT       S1
;	BIT3 - INFORMATIONSBIT I1
;	BIT4 - SCHUTZBIT       S2
;       BIT5 - INFORMATIONSBIT I2
;	BIT6 - SCHUTZBIT      S3
;	BIT7 - INFORMATIONSBIT I3
;
PARGR	LD	B,0FH	;PARIT. =1
	LD	A,(HL)
	AND	0A2H    ;BEST. VON S0
	JP	PE,PAR1
	BIT	0,(HL)  ;EMPF.-BIT=0 ?
	JR	Z,PARS1 ;JA-->S1 BEST.
	RES	0,B	;S0-FEHLER
	JR	PARS1
PAR1	BIT	0,(HL)	;EMPF.-BIT=1 ?
	JR	NZ,PARS1 ;JA--S1 BEST.
	RES	0,B	 ;S0-FEHLER
;
PARS1	LD	A,(HL)
	AND	08AH	;BEST. VON S1
	JP	PE,PAR2
	BIT	2,(HL)
	JR	Z,PARS2
	RES	1,B	;S1-FEHLER
	JR	PARS2
PAR2	BIT	2,(HL)
	JR	NZ,PARS2
	RES	1,B	;S1-FEHLER
;
PARS2	LD	A,(HL)
	AND	02AH	;BEST. VON S2
	JP	PE,PAR3
	BIT	4,(HL)
	JR	Z,PARS3
	RES	2,B	;S2-FEHLER
	JR	PARS3
PAR3	BIT	4,(HL)
	JR	NZ,PARS3
	RES	2,B	;S2-FEHLER
;
PARS3	LD	A,(HL)
	AND	0BFH	;BEST. VON S3
	JP	PE,PAR4
	BIT	6,(HL)
	JR	Z,PAREND
	RES	3,B	;S3-FEHLER
PAR4	BIT	6,(HL)
	JR	NZ,PAREND
	RES	,B
PAREND	LD	A,B
	RET
;
;	DEKODIEREN EINES HAMMING-
;	KODIERTEN HALBBYTES :
;
;	PE:(HL)=VOLLST. BYTE MIT SI'S
;	PA:(HL)=DEKODIERTE TETRADE,
;		RECHTSBUENDIG MIT KORRI-
;		GIERTEN EINBITFEHLERN
;	   (HL)FF WENN, MEHRFACHFEHLER
;
DEKB	CALL	PARGR	;PAR. ERRRECHNEN
	CP	0FH	;I.O. ?
	JR	Z,TSCH
;
FES0	EQU	06H
FES1	EQU	05H
FES2	EQU	03H
FES3	EQU	07H
;
	CP	FES0
	JR	Z,TSCH
	CP	FES1
	JR	Z,TSCH
	CP	FES2
	JR	Z,TSCH
	CP	FES3
	JR	Z,TSCH
;
FEI0	EQU	00H
FEI1	EQU	01H
FEI2	EQU	02H
FEI3	EQU	04H
;
	CP	FEI0
	JR	Z,KORR0
	CP	FEI1
	JR	Z,KORR1
	CP	FEI2
	JR	Z,KORR2
	CP	FEI3
	JR	Z,KORR3
	LD	(HL),0FFH  ;BYTE = FF
	LD	A,(HL)
	SCF		   ;CY=1
	RET
;
KORR0	BIT	1,(HL)
	JR	NZ,KRES0
	SET	1,(HL)
	JR	TSCH
KRES0	RES	1,(HL)
	JR	TSCH
;
KORR1	BIT	3,(HL)
	JR	NZ,KRES1
	SET	3,(HL)
	JR	TSCH
KRES1	RES	3,(HL)
	JR	TSCH
;
KORR2	BIT	5,(HL)
	JR	NZ,KRES2
	SET	5,(HL)
	JR	TSCH
KRES2	RES	5,(HL)
	JR	TSCH
;
KORR3	BIT	7,(HL)
	JR	NZ,KRES3
	SET	7,(HL)
	JR	TSCH
KRES3	RES	7,(HL)
;
TSCH	LD	A,(HL)  ;RECHTSBUENDIG
	LD	B,0	;SCHIEBEN
	RLCA
	RL	B	;2^3
	RLCA
	RLCA
	RL	B	;2^2
	RLCA
	RLCA
	RL	B	;2^1
	RLCA
	RLCA
	RL	B	;2^0
	LD	(HL),B	;EINTRAGEN
	LD	A,B
	SCF
	CCF		;CY=0
	RET
;
;	ZURECHTSCHIEBEN VON MAGAZIN-
;	UND REIHENADRESSE
;	PE:HL  =MAGAZINNR.+ BIT0-REIHE
;	PA:HL  =MAGAZINNR.AUS 3 BIT
;	   HL+1=REIHENNR.AUS 5 BIT
;
MAGREI	LD	A,(HL)
	INC	HL
	RRCA	     ;4 BIT NACH RECHTS
	RRCA
	RRCA
	RRCA
	RL	(HL)
	RRCA	     ;4 BIT NACH RECHTS
	RRCA
	RRCA
	RRCA
	AND	07H
	DEC	HL
	LD	(HL),A
	RET
;
;	KOPFZEILE SUCHEN
SKOPF	CALL	RESET
      	CALL	EZPBAI
	CALL	RESET
 	IN	A,(PDA)	  ;LEEREINGABE
	LD	HL,LATCH
	LD	(ZLATCH),HL
	LD	A,(AZPBAI)
	LD	E,A	  ;ZEILEN/BAI
	INC	E
SKOPF1	DEC	E
	JR	Z,SKOPF2  ;NEXT BAI
      	CALL	INP42
	LD	HL,(ZLATCH)
	CALL	DEKMR
	LD	(MAGAZ),A
	INC	HL
	LD	A,0
	CP	(HL)	   ;KOPFREIHE?
	JR	NZ,SKOPF1
	INC	HL
	CALL	DEKB
	LD	(SEIN),A
	INC	HL
	CALL	DEKB
	LD	(SZEHN),A
	CALL	NEXTZ
	SCF		;CY=1
	RET
SKOPF2	SCF
	CCF		;CY=0
 	RET
;
;	VERGLEICH OB RICHTIGE KOPFZ.
KOPFIO	LD	HL,XMAGAZ
	LD	A,(MAGAZ)
	CP	(HL)
	RET	NZ
	INC	HL
	LD	A,(SEIN)
	CP	(HL)
	RET	NZ
	INC	HL
	LD	A,(SZEHN)
	CP	(HL)
	RET
;
;	DIE RESTLICHEN ZUR TAFEL GEHOE-
;	RIGEN REIHEN EINLESEN
;	D.H. NOCH 31 ZEILEN
RREI	LD	D,31	;ZEAEHLER 1
	JR	RREI1
RREI2	CALL	RESET
	CALL	EZPBAI
	CALL	RESET
	IN	A,(PDA) ;LEEREINGABE
      	LD	A,(AZPBAI)
	LD	E,A	;ZAEHLER 2
	INC	E
RREI1	DEC	E
	JR	Z,RREI2
     	CALL	INP42
	CALL	NEXTZ
	DEC	D
	JR	NZ,RREI1
    	RET
;
RAMBEG	LD	HL,ANZPU
	LD	(ZEIAPU),HL
	RET
;
;	ZEICHENZAEHLER ERHOEHEN
ZEIINC	LD	A,(ZEICHZ)
	INC	A
	LD	(ZEICHZ),A
	RET
;	ZEILEN(REIHEN)ZAEHLER ERHOEHEN
;	FUER DIE 32 IN (ZLATCH) STEHEN-
;	DEN ZEILEN ZU JE 48 BYTES
ZLINC  	LD	A,(ZEILZ)
	INC	A
	LD	(ZEILZ),A
	RET
;	RAMZEIGER ERHOEHEN
LAINC	LD	HL,(ZLATCH)
	INC	HL
	LD	(ZLATCH),HL
	RET
;
;	8 LEERZEICHEN SCHREIBEN
SPACE8	LD	A,20H
	LD	B,8
SPACEL	CALL	WRASC
	DJNZ	SPACEL
	RET
;
WRASC	PUSH	HL
	LD	HL,(ZEIAPU)
	LD	(HL),A
	INC	HL
	LD	(ZEIAPU),HL
	POP	HL
	RET
;
RDASC	PUSH	HL
	LD	HL,(ZEIAPU)
	LD	A,(HL)
	POP	HL
	RET
;
WRNOP	PUSH	HL
	LD	HL,(ZEIAPU)
	INC	HL
	LD	(ZEIAPU),HL
	POP	HL
	RET
;
;	AUSGABE VON ZEICHEN AUF ANZPU
;	PARITAET: UNGERADE ANZAHL EINSEN
OUTAPU	CALL	RDASC
	BIT	7,A	;BITFEHLER?
	JR	Z,OUTAP2
	LD	A,(HL)
	AND	A
 	JP	PE,OUTAP1
	AND	07FH
	CALL	WRASC	;WRITE ASCII
	RET
;	FUER FEHLER SPACE AUSGEBEN
;	BIT7=1 ZUR KENNZEICHNUNG
OUTAP1	LD	A,0A0H
	CALL	WRASC
	RET
OUTAP2	CALL	WRNOP
	RET
;
;	ZLATCH AUF NAECHSTE ZEILE
NEXTZ	PUSH	AF	;WEGEN CY
	LD	HL,(ZLATCH)
	LD	BC,48
	ADD	HL,BC
	LD	(ZLATCH),HL
	POP	AF
	RET
;
;	ERRECHNEN CURSORPOSITION
;	AUS DER REIHENNUMMER
ERCUPO	PUSH	HL
	PUSH	BC
	CP	24	  ;>23 ?
	JR	C,ERCUP1
	LD	A,23
ERCUP1	LD	B,A
	LD	DE,40	;40 ZEICH/ZEILE
	LD	HL,ANZPU
ERCUP2	ADD	HL,DE
	DJNZ	ERCUP2
	LD	(ZEIAPU),HL
	POP	BC
	POP	HL
	RET
;
;	42 BYTE NACH ANZPU SCHAFFEN
LOADAP	LD	HL,(ZLATCH)
	CALL	OUTAPU
	CALL	LAINC	;(LATCH)+1
  	CALL	ZEIINC
	CP	42
	JR	NZ,LOADAP
	LD	HL,(ZLATCH)
	LD	BC,6
	ADD	HL,BC
	LD	(ZLATCH),HL
	RET
;
;	MAGAZ. UND REIHENNR. DEKOD.
;	HL ZEIGT AUF 1.BYTE
DEKMR	CALL	DEKB
	INC	HL
	CALL	DEKB
	DEC	HL
	CALL	MAGREI
	LD	(MAGAZ),A
	RET
;
;	SEITENNUMMER DEKODIEREN
DEKSEI	CALL	DEKB
	LD	(SEIN),A   ;SEITEN-EINER
	INC	HL
	CALL	DEKB
	LD	(SZEHN),A  ;SEIT.-ZEHNER
	INC	HL
	RET
;
;	SUBCODES UND STEUERBITS DEKOD.
;	AUS BYTE 5 BIS 10
DEKSS	LD	A,(SBEIN)
	CP	0FFH
	JR	NZ,DEKS1
	CALL	DEKB
	LD	(SBEIN),A  ;SUB-EINER
DEKS1	INC	HL
	LD	A,(SBZEHN)
	CP	0FFH
	JR	NZ,DEKS2
	CALL	DEKB
	AND	07H
	LD	(SBZEHN),A ;SUB-ZEHNER
	LD	A,(HL)
	AND	08H
	RRCA
	RRCA
	RRCA
	LD	(CCC4),A   ;C4
DEKS2	INC	HL
	LD	A,(SBHUND)
	CP	0FFH
	JR	NZ,DEKS3
	CALL	DEKB
	LD	(SBHUND),A ;HUNDERTER
DEKS3	INC	HL
	LD	A,(SBTAU)
	CP	0FFH
	JR	NZ,DEKS4
	CALL	DEKB
	AND	03H
	LD	(SBTAU),A  ;TAUSENDER
	LD	A,(HL)
	AND	0CH
	RRCA
	RRCA
	LD	(C5C6),A
DEKS4	INC	HL
	LD	A,(C7C10)
	CP	0FFH
	JR	NZ,DEKS5
	CALL	DEKB
	LD	(C7C10),A
DEKS5	INC	HL
	LD	A,(C11C14)
	CP	0FFH
	JR	NZ,DEKS6
	CALL	DEKB
	LD	(C11C14),A
DEKS6	INC	HL	;ERSTES INFBYTE
	RET
;
;	SUBCODES UND STEUERBITS
;	MIT FEHLER LADEN
CLRSS	PUSH	HL
	PUSH	BC
       	LD	HL,SBTAU
	LD	B,8
CLRSS1	LD	(HL),0FFH
	INC	HL
	DJNZ	CLRSS1
	POP	BC
	POP	HL
	RET
;
;	UBERNAHME AUS ZLATCH NACH ANZPU
;	MIT DEKODIERUNG UND FEHLERKORR.
;	ANZPU HAT FORMAT 24*40
;	ERSTE 4 BYTE SCHON DEKODIERT
DEKKO	LD	A,1
	LD	(ZEILZ),A ;1.REIHE
	LD	HL,LATCH
	INC	HL
	INC	HL
	INC	HL
	INC	HL
;	NOCH 6 BYTES DEKODIEREN
	CALL	CLRSS
	CALL	DEKSS
	LD	(ZLATCH),HL
	LD	A,10	;SCHON 10.ZEICH.
	LD	(REIMZ),A
 	CALL	RAMBEG	;(ZEIAPU)=ANZPU
 	CALL	SPACE8
;	INFBYTES DER KOPFREIHE NACH
;	ANZPU SCHAFFEN
DEKKO1	LD	A,10
	LD	(ZEICHZ),A
	CALL	LOADAP
	LD	A,0	;DA REIHENANFANG
	LD	(ZEICHZ),A
;	WEITERE KOPFREIHEN WERDEN
;	UEBERSPRUNGEN, BZW. ZUR FEHLER-
;	KORREKTUR DER ERSTEN VERWENDET
DEKKO3	CALL	ZLINC	;ZEILE+1
	CP	33	; >32?
	JR	NC,DEKKO5
	LD	HL,(ZLATCH)
	CALL	DEKMR
	LD	A,(HL)
	CP	0FFH	;FEHLER IN MAG?
	CALL	Z,NEXTZ
	JR	Z,DEKKO3
	INC	HL
	LD	A,(HL)
	CP	0FFH	;F. IN REIHE?
	CALL	Z,NEXTZ
	JR	Z,DEKKO3
	CP	0	  ;KOPFREIHE?
	JR	NZ,DEKKO2 ;>23?
;	BIS HIER, FEHLERFREIE KOPFZEILE
	INC	HL
	CALL	DEKSEI
	LD	A,(SEIN)
	CP	0FFH	;F. IN SEINER?
	CALL	Z,NEXTZ
	JR	Z,DEKKO3
	LD	A,(SZEHN)
	CP	0FFH	;F. IN SZEHNER?
	CALL	Z,NEXTZ
	JR	Z,DEKKO3
;	SEITENEINER UND ZEHNER SIND AUCH
;	FEHLERFREI, NUN TEST OB GESUCHTE
;	TAFEL VORLIEGT
	EX	DE,HL
	LD	HL,XMAGAZ
	LD	A,(MAGAZ)
	CP	(HL)
	JR	NZ,DEKKO5
	INC	HL
	LD	A,(SEIN)
	CP	(HL)
	JR	NZ,DEKKO5
	INC	HL
	LD	A,(SZEHN)
	CP	(HL)
	JR	NZ,DEKKO5
	EX	DE,HL
;	KORREKTUR SUBCODES/STEUERBITS
	CALL	DEKSS
	LD	(ZLATCH),HL
;	KORREKTUR DER INF-BYTES
	CALL	RAMBEG	;ZEIAPU AUF BEG.
	CALL	SPACE8	;8 LEERZEICHEN
	JR	DEKKO1
;	KEINE KOPFZEILE, REST DER TAFEL
;	IN DEKTA VERARBEITEN
DEKKO2	CP	24 	  ;REIHENNR>23 ?
	CALL	NC,NEXTZ  ;DA FEHLER
	JR	NC,DEKKO3
	LD	(AKTZN),A
	RET
;	ABBRUCH VON DEKTA, WENN 2 KOPF-
;	REIHEN NACHEINANDER GESENDET
;	WURDEN Z.B. UNTERTITEL(TAFEL150)
DEKKO5	LD	A,80H
	LD	(AKTZN),A
	LD	(ZEILZ),A
	RET
;
;	UEBERNAHME REIHE 1-23 NACH ANZPU
;	(ZLATCH)=1.BYTE DER 1.INF-REIHE
;	(ZEILZ)=ANZAHL DER BEREITS ANA-
;	LYSIERTEN RAM-ZEILEN ZU 48 BYTE
;	(AKTZN)=DEKOD.AKTUELLE REIHENNR.
;	MAGAZIN UND REIHENNR. DER AKT.
;	REIHE SIND BEREITS DEKODIERT
DEKTA	LD	A,(AKTZN)
DEKTA2	CP	24	 ;REHENNR>23 ?
 	CALL	NC,NEXTZ ;DA FEHLER
 	JR	NC,DEKTA1
	LD	(REIMZ),A ;REINR.MERKEN
	CALL	ERCUPO	;CURSORPOSITION
	CALL	LAINC	;MAGAZIN
	CALL	ZEIINC
	CALL	LAINC	;REIHE
	CALL	ZEIINC
	CALL	LOADAP	;REIHE -> ANZPU
;	HL ZEIGT JETZT AUF REIHENANFANG
DEKTA1	CALL	ZLINC	   ;RAMREIHE+1
	CP	33
	JR	NC,DTEND
;	MAGAZIN UND REIHENNR DER
;	NAECHSTEN REIHE BESTIMMEN
	LD	A,0
	LD	(ZEICHZ),A
	CALL	DEKMR
	LD	A,(XMAGAZ)
	CP	(HL)	;MAGAZIN OK?
	CALL	NZ,NEXTZ
	JR	NZ,DEKTA1
	INC	HL	;(HL)=REIHENNR.
 	LD	A,(REIMZ)
 	CP	(HL)
 	LD	A,(HL)
;	RETURN, WENN DIE REIHENNR.
;	KLEINER ALS DIE VORHERIGE IST
 	JR	C,DEKTA2
DTEND	RET
;
;	KOPFREIHE IN ANZPU LOESCHEN
CLRKO	PUSH	BC
	PUSH	DE
	PUSH	HL
	LD	HL,ANZPU
	LD	DE,ANZPU+1
	LD	BC,39
	LD	(HL),0A0H
	LDIR
	POP	HL
	POP	DE
	POP	BC
	RET
;
;	REIHE 1-23 IN ANZPU LOESCHEN
CLRTA	PUSH	BC
	PUSH	DE
	PUSH	HL
 	LD	HL,ANZPU+40
	LD	DE,ANZPU+41
	LD	BC,LANZPU-41
	LD	(HL),0A0H
	LDIR
	POP	HL
	POP	DE
	POP	BC
	RET
;
EMEND	EQU	$
;
;---------------------------------------
;
	ORG	1000H
;
;	VEREINBARUNGEN UND DEFINITIONEN
;	DER EMPFANGSROUTINEN
;
LATCH	EQU	$	;PUFFERANFANG
LLATCH	EQU	1536	;PUFFERLAENGE
	ORG	$+LLATCH
ANZPU	EQU	$	;CRT-PUFFER
LANZPU	EQU	1000	;25*40=1000
	ORG	$+LANZPU
PDA	EQU	04H	;DATEN-RAM
PDB	EQU	05H	;STEUERUNG
PSA	EQU	06H
PSB	EQU	07H
;
;
;	AREADY INKREMENT. ADRESSZAEHLER
;	PORT B 	BIT0 ABTASTEN-START
;		BIT1 ZAEHLER-RESET
;		BIT2 ZAEHLEN VT-ZEILEN
;		     PRO AUSTASTLUECKE
;
XMAGAZ	DEFB	0    ;GESUCHTES MAGAZIN
XEIN	DEFB	0    ;GES. SEITENEINER
XZEHN	DEFB	0    ;GES. SEITENZEHNER
AZPBAI	DEFB	0    ;ZEIL./AUSTASTL.
ZLATCH	DEFW	0    ;ZEIGER-LATCH
ZEIAPU	DEFB	0    ;ZEIGER-CRT-PUFFER
ZFEHL	DEFB	0    ;ZAEHLER-FEHLER
ZEILZ	DEFB	0    ;ZEILEN-ZAEHLER
ZEICHZ  DEFB	0    ;ZEICHEN-ZAEHLER
REIMZ	DEFB	0    ;REIHEN-MERKZELLE
AKTZN	DEFB	0    ;AKTUELLE ZEILENNR.
MAGAZ	DEFB	0    ;MAGAZIN-NR.
REIHE	DEFB	0    ;REIHEN-NR.
SEIN	DEFB	0    ;SEITEN-EINER
SZEHN	DEFB	0    ;SEITEN-ZEHNER
SBTAU	DEFB	0    ;SUBCODE-TAUSENDER
SBHUND	DEFB	0    ;SUBC.-HUNDERTER
SBZEHN	DEFB	0    ;SUBC.-ZEHNER
SBEIN	DEFB	0    ;SUBC.-EINER
C11C14	DEFB	0    ;MODUS/ALPHABET
C7C10	DEFB	0    ;SEITENSTEUERUNG
C5C6	DEFB	0    ;NACHRICHT./UNTERT.
CCC4	DEFB	0    ;SEITENLOESCHUNG
;
MZEND	EQU	$
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ