;*******************************************************
;
; REVERSE TYPE
;
; RTYP  V1.3/83.10.21
;
; Geschreven door C.J.Havelaar
;
; Laatste wijziging 84.01.13
;
;*******************************************************
;
;
$TITLE('Reverse type  -  V1.4'),NOCONT,PL(70)
;
;
; Commando karakters
;
BREAK	EQU	003H		; ^C  break
DOWN	EQU	004H		; ^D (d of D) scrolling down (reverse)
CONT	EQU	011H		; ^Q (q of Q) continue
STOP	EQU	013H		; ^S (s of S) stop
UP	EQU	015H		; ^U (u of U) scrolling up (normaal)
;
;
; Konstanten
;
FCB	EQU	0005CH		; Startadres file control blok
CPM	EQU	00000H		; Warmboot entry cp/m
BDOS	EQU	00005H		; Bdos entry
;
; Ascii konstanten
;
TAB	EQU	 9		; Tabulator
LF	EQU	10		; Line feed
CR	EQU	13		; Carriage return
EOF	EQU	1AH		; End of file
;
; CP/M funktie konstanten
;
DICONF	EQU	 6		; Direct console I/O
PRINTF	EQU	 9		; Print funktie
OPENF	EQU	15		; Open file funktie
DMAF	EQU	26		; Set dma adres funktie
RRANDF	EQU	33		; Read random funktie
FILSF	EQU	35		; Bereken file grootte funktie
;
;
	ORG	00100H		; Start cp/m programma's
;
START:	JMP	RTYP		; Sla versie gegevens over
	DB	'**rtyp     CJH83.01.13 v1.4$'
	DW	0,0,0		; Reserve ruimte versie
;
;
	ORG	00120H		; Pointer ruimte terminal konstanten
				; Ingesteld voor een VT52 terminal
				;
REVLF:	DB	002H		; Aantal kar. rev. linefeed(scrolldown)
	DB	01BH		; Karakter string reverse linefeed
	DB	'I'
	DB	000H		; Reserve ruimte
	DW	0,0
DIRCUR:	DB	002H		; Aantal kar. direkte cursor besturing
	DB	01BH		; Kar. string dir. cursor besturing
	DB	'Y'
	DB	000H		; Reserve ruimte
	DW	0,0
OFFSL:	DB	020H		; Offset regel dir. cursor best.
OFFSC:	DB	020H		; Offset kolom dir. cursor best.
CHARW:	DB	80		; Aantal karakters per regel display
CHARH:	DB	24		; Aantal regels per display
;
;
;*******************************************************
;
; Hoofdprogramma.
;
;*******************************************************
;
;
RTYP:	LXI	SP,NWSTK	; Zet nieuwe stackpointer
	CALL	INIT		; Initialiseer pointers
	CALL	OPEN		; Open file
	CALL	RECCNT		; Haal record lengte file
	CALL	MEMREC		; Bereken vrije records van geheugen
	CALL	FILLM		; Zet file in geheugen
	JZ	CPM		; Keer terug indien file leeg
	JMP	TYPE		; Verzendt file naar het display
;
;
;-------------------------------------------------------
;
;
; Subroutines die de karakters van de file naar het display sturen.
;
;
; TYPE: verzendt de karakters uit het geheugen naar het display
;
; Entry: none
; Mod:	 all
; Exit:  none
;
TYPE:	LHLD	DMAAD		; Laad eindadres file +1
	DCX	H		; Korrigeer dit
	XCHG			; Eindadres in D,E
	LXI	H,STARTFL	; Start adres te displayen karakters
TYPE1:	MOV	A,M		; Karakter naar A voor test
	CPI	LF		; Is dat een line feed?
	JNZ	TYPE3		; Zo nee: spring
	XRA	A
	STA	CHARC		; Reset karakter teller
	CALL	DELAY		; Delay
	LDA	RLF		; Is de rev. line feed vlag geset?
	ANA	A
	JNZ	REVSCR		; Zo ja: ga verder in rev scroll
TYPE2:	LDA	CHARH		; Laad aantal regels/display
	MOV	B,A		; Bewaar dat in B
	INR	B		; Voor test
	LDA	LINC		; Laad regel teller
	CMP	B		; Is er al 1 display vol geschreven?
	JZ	TYPE3		; Zo ja: spring
	INR	A		; Zo nee: verhoog regel teller
	STA	LINC		; en berg deze op
TYPE3:	CALL	PCHAR		; Print karakter
	INX	H		; Verhoog ophaal adres
TYPE4:	CALL	CMPDH		; Zijn alle karakters verzonden?
	JNC	TYPE1		; Zo nee: verzendt volgende
	CALL	FILLM		; Laad indien aanwezig rest v.d. file
	JNZ	TYPE		; Verzendt karakters
	LDA	CHARH		; Test of file kleiner is dan aantal
	MOV	C,A		;  regels/display - 1
	INR	C
	LDA	LINC
	CMP	C
	JC	BRK		; Zo ja: keer terug naar cp/m
	CALL	ESTP		; Stop uitvoer, wacht op een down comm.
	LHLD	EOFAD		; Laad eindadres file
	JMP	REVSCR		; Ga verder in reverse mode
;
;
; REVSCR: verzendt de karakters uit het geheugen naar het display
;	  de file wordt echter van achteren naar voren doorlopen.
;
; Entry: H,L - adres karakter in file(blok)
; Mod:	 A,flags,B,C,H,L
; Exit:  D,E - eindadres file(blok)
;
REVSCR:	LDA	DFLAG		; Test of down commando is toegestaan
	ANA	A
	JNZ	TYPE2		; Keer terug indien geblokkeerd
	XRA	A		; Hef blokkering karakter print op
	STA	EOFFL
	LDA	CHARH		; Laad aantal regels/display
	MOV	C,A		; Bewaar dit in B
	INR	C		; Verhoog deze voor test
	LDA	LINC		; Laad regel teller
	CMP	C		; Is er al een display vol geschreven?
	PUSH	PSW
	CC	BSTP		; Zo nee: stop uitvoer en wacht op
	POP	PSW		;  een up commando
	JC	TYPE2		;  en keer terug naar type
	CALL	CURHOM		; Zet cursor linksboven op display
RSCR1:	DCX	H		; Verlaag adres
	LXI	D,STARTFL	; Start adres in D,E
	XCHG
	CALL	CMPDH		; Is begin file(blok) overschreden?
	XCHG
	PUSH	B		; Bewaar regeltelling
	CC	REVM		; Zo ja: laad nieuw fileblok
	POP	B
	JC	RSCR2		; Geen nieuw fileblok: print 1e regel
	MOV	A,M
	CPI	LF		; Zoek begin voorgaande regel
	JNZ	RSCR1
	DCR	C
	JNZ	RSCR1		; H,L = beginadres regel - 1
RSCR2:	PUSH	H		; Bewaar dit adres
	CALL	PUTRLF		; Print een reverse line feed
	INX	H		; Verhoog adres tot begin regel
RSCR3:	CALL	PCHAR		; Print karakter
RSCR3A:	INX	H
	MOV	A,M
	CPI	CR		; Karakter een car.return?
	JZ	RSCR3A		; Zo ja: sla deze over
	CPI	LF		; Einde regel?
	JNZ	RSCR3		; Zo nee: print volgende karakter
	MVI	E,CR		; Zo ja: print eerst een CR
	CALL	DCON
	POP	H		; Haal einde voorgaande regel terug
	XRA	A
	STA	CHARC		; Reset karakter teller
	LDA	RLF		; Laad rev line feed vlag
	ANA	A		; Is deze gereset?
	JZ	RSCR4		; Zo ja: ga verder met TYPE
	CALL	DELAY		; Delay
	LXI	D,STARTFL	; Start adres in D,E
	XCHG
	CALL	CMPDH		; Is begin overschreden?
	XCHG
	MVI	C,1		; Set lusteller voor 1 regel
	JNC	RSCR1		; Zo nee: print voorgaande regel
	CALL	BSTP		; Zo ja: stop uitvoer en wacht op een
				;  up commando
	LHLD	FBLOK		; Korrigeer ophaal record teller
	XCHG
	LHLD	RECCT
	DAD	D
	SHLD	RECCT
	LXI	H,STARTFL	; Begin adres file in H,L
	LDA	CHARH		; Laad aantal regels/display
	MOV	C,A		; Zet dat in C
	JMP	RSCR4A
RSCR4:	LDA	CHARH		; Bereken nu het het beginadres van
	MOV	C,A		;  de regel die onderaan het display
	INR	C		;  moet worden geprint
RSCR4A:	XCHG
	LHLD	DMAAD
	DCX	H
	XCHG
	DCX	H		; Verlaag adres voor lus test
RSCR5:	INX	H
	CALL	CMPDH		; Is einde file(blok) overschreden?
	JNC	RSCR6		; Zo nee: spring
	PUSH	B		; Bewaar lusteller
	CALL	FILLM		; Laad volgende blok
	POP	B
	LHLD	DMAAD		; Laad nieuwe begin en eindadres
	DCX	H
	XCHG
	LXI	H,STARTFL
RSCR6:	MOV	A,M		; Zoek de linefeeds
	CPI	LF
	JNZ	RSCR5
	DCR	C
	JNZ	RSCR5		; H,L = beginadres regel
	CALL	CURDWN		; Zet cursor rechtsonderaan op display
	MVI	E,CR
	CALL	DCON		; Print een car.return
	XCHG			; Bewaar ophaal adres in D,E
	LHLD	DMAAD		; Laad eindadres file(blok)
	DCX	H		; Korrigeer dit
	XCHG
	JMP	TYPE4		; Ga verder in normale mode
;
;
; PCHAR: print een karakter op het display.
;	 test keyboard op input en houdt de telling van karakters op
;	 een regel bij.
;
; Entry: H,L - current adres
; Mod:	 A,flags,C
; Exit:  none
;
PCHAR:	PUSH	D		; Bewaar adres
	LDA	EOFFL		; Test of kar. mogen worden geprint
	ANA	A
	JNZ	PCHAR4		; Spring indien geblokkeerd
	MOV	A,M		; Karakter naar A
	CPI	EOF		; Is dat een eof karakter ?
	JNZ	PCHAR1		; Zo nee: print karakter
	MVI	A,1		; Zo ja: blokkeer karakter print
	STA	EOFFL
	SHLD	EOFAD		;  en bewaar eof adres
	JMP	PCHAR4		;  en print eof niet
PCHAR1:	CPI	CR		; Is dat een CR ?
	JZ	PCHAR4		; Zo ja: sla deze over
	CPI	LF		; Is dat een LF ?
	JNZ	PCHAR2		; Zo nee: spring
	MVI	E,CR		; Zo ja: print eerst een CR
	CALL	DCON
PCHAR2:	LDA	CHARW		; Laad aant. kar/regel
	MOV	C,A		; Bewaar dat in C
	LDA	CHARC		; Laad karakter telling
	INR	A		; Verhoog karakter teller
	MOV	B,A		; Bewaar deze in B
	MOV	A,M		; Karakter in A
	CPI	TAB		; Is dat een tab ?
	MOV	A,B		; Karakter telling alvast in A
	JNZ	PCHAR3		; Zo nee: spring
	ADI	8		; Expandeer tab
	ANI	0F8H
PCHAR3:	STA	CHARC		; Berg telling op
	CMP	C		; Regel te lang?
	JNC	PCHAR4		; Zo ja: print karakter niet
	JZ	PCHAR4
	MVI	E,0FFH		; Vlag voor console input
	CALL	DCON		; Test console
	ANA	A		; Is er een karakter ontvangen?
	CNZ	COMMAND		; Zo ja: verwerk commando
	MOV	E,M		; Karakter in E voor verzending
	CALL	DCON		; Verzendt karakter
PCHAR4:	POP	D
	RET
;
;
;-------------------------------------------------------
;
;
; Subroutines die de file of stukken van de file in het geheugen zet.
;
;
; FILLM: zet de file in het geheugen
;	 wanneer de file te groot is, gebeurt dit in blokken.
;
; Entry: none
; Mod:	 all
; Exit:  zf = 1 indien file leeg
;
FILLM:	LHLD	RCCNT		; Test of file leeg is
	MOV	A,L
	ORA	H
	RZ			; Zo ja: keer terug
	LHLD	MXRECM		; Aantal records geheugen in H,L
	XCHG			; Records in D,E
	LHLD	RCCNT		; Aantal records file in D,E
	CALL	CMPDH		; Vergelijk deze
	JNC	FILLM1		; Spring als file in geheugen past
	CALL	SUBDH		; Verlaag file met geheugenlengte
	SHLD	RCCNT		; Berg rest lengte file op
	XCHG			; Aantal records geheugen in H,L
	JMP	FILLM2
FILLM1:	PUSH	H		; Bewaar record lengte file
	LXI	H,0
	SHLD	RCCNT		; Reset record count file lengte
	POP	H
FILLM2:	SHLD	FBLOK		; Bewaar fileblok t.b.v. REVM
FILLM3:	SHLD	CNT
	LHLD	RECCT		; Laad record teller
	XCHG			; Teller naar D,E
	LXI	H,STARTFL	; Start adres in H,L
	CALL	STDMA		; Set dma adres
	XCHG			; Ophaal counter naar H,L
FILLM4:	SHLD	FCB+33		; Zet waarde in file control blok
	XCHG			; Ophaal counter terug naar D,E
	CALL	RRAND		; Laad record
	LHLD	DMAAD		; Laad oude dma adres
	LXI	B,128		; Verhoog dit
	DAD	B
	CALL	STDMA		; Set nieuwe dma adres
	LHLD	RECCT		; Verhoog ophaal counter
	INX	H
	SHLD	RECCT
	LHLD	CNT		; Verlaag lus teller
	DCX	H
	SHLD	CNT
	MOV	A,L		; Test of deze 0 is
	ORA	H
	LHLD	RECCT		; Laad alvast ophaal counter
	JNZ	FILLM4		; Geen 0: laad volgende record
	MVI	E,0FFH		; Gooi event. ingetikt kar. tijdens
	CALL	DCON		;  laden van records weg
	XRA	A
	INR	A		; Reset zf
	RET
;
;
; REVM: test of er nog voorgaande blokken van een file zijn
;	zo ja, dan worden deze geladen
;
; Entry: none
; Mod:	 all
; Exit:  H,L - eindadres fileblok
;	 D,E - startadres fileblok
;	 csf = 1 indien geen voorgaand blok aanwezig
;
REVM:	PUSH	D		; Bewaar begin en eindadres
	PUSH	H
	LHLD	FBLOK		; Laad waarde geladen file(blok)
	XCHG			; Waarde naar D,E
	LHLD	RECCT		; Verlaag ophaal record teller
	CALL	SUBDH		; Verlaag record teller met file(blok)
	SHLD	RECCT		; Berg uitkomst op
	MOV	A,L		; Is deze 0?
	ORA	H
	POP	H		; Haal eerst adressen terug
	POP	D
	JNZ	REVM2		; Zo nee: spring
REVM1:	STC			; Zo ja: set carry; er zijn geen voor-
	RET			;  gaande fileblokken meer
REVM2:	LHLD	DMAAD		; Verplaats nu eerst het 1e record van
	XCHG			;  het huidige blok achter het werkge-
	LXI	H,STARTFL	;  heugen
	LXI	B,128
REVM3:	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCX	B
	MOV	A,C
	ORA	B
	JNZ	REVM3
	LHLD	FBLOK		; Laad waarde geladen file(blok)
	XCHG
	LHLD	RCCNT		; Verhoog oude recordteller met blok
	DAD	D
	SHLD	RCCNT
	LHLD	MXRECM		; Aantal records geheugen
	SHLD	FBLOK		; Set nieuwe waarde file(blok)
	XCHG
	LHLD	RECCT		; Verlaag ophaal rec. teller tot
	CALL	SUBDH		;  voorgaande blok
	SHLD	RECCT
	XCHG			; Aantal te laden records in H,L
	CALL	FILLM3		; Laad voorgaande file(blok)
	LHLD	DMAAD		; Nieuwe karakter adres in H,L
	DCX	H
	LXI	D,STARTFL	; Beginadres werkruimte in D,E
	ANA	A		; Reset csf
	RET
;
;
;-------------------------------------------------------
;
;
; Subroutines die de commando's verwerken.
;
;
; COMMAND: test of ontvangen karakter een commando is
;
; Entry: A - commando karakter
; Mod:	 A,flags
; Exit:  none
;
COMMAND:CPI	BREAK		; Break commando?
	JZ	BRK		; Zo ja: keer terug naar cp/m
	CPI	'0'		; Karakter kleiner dan ascii 0?
	JC	COMM1		; Zo ja: spring
	CPI	'9'+1		; Karakter groter dan ascii 9?
	JC	SETDLY		; Kar. een cijfer: spring
COMM1:	ANI	01FH		; Verwijder de drie msbits
	CPI	DOWN		; Reverse commando?
	JZ	SETRLF		; Zo ja: set reverse line feed vlag
	CPI	UP		; Normale scroll mode commando?
	JZ	RESRLF		; Zo ja: reset rev line feed vlag
	CPI	STOP		; Stop commando?
	JZ	STP		; Zo ja: stop
	RET			; Keer terug. Kar. is geen commando
;
;
; BRK: break zet de cursor linksonder op display en keert
;	terug naar cp/m
;
; Entry: none
; Mod:	 all
; Exit:  none
;
BRK:	CALL	CURDWN		; Zet cursor linksonder
	JMP	CPM		; en keer terug naar cp/m
;
;
; SETRLF: set de reverse line feed vlag
;
; Entry: none
; Mod:	 A
; Exit:  none
;
SETRLF:	MVI	A,1
	STA	RLF
	RET
;
;
; RESRLF: reset de reverse line feed vlag
;
; Entry: none
; Mod:	 A
; Exit:  none
;
RESRLF:	XRA	A
	STA	RLF
	RET
;
;
; SETDLY: set de delay pointer
;
; Entry: A - ascii cijfer
; Mod:	 A,flags
; Exit:	 none
;
SETDLY:	ANI	0FH		; Maak van kar. een hexgetal
	PUSH	H
	MVI	L,0		; Clear L
	MOV	H,A		; Getal naar H
	DAD	H		; *2
	DAD	H		; *4
	DAD	H		; *8
	DAD	H		; *16
	INX	H		; Indien getal nul is!
	SHLD	DLY		; Berg pointer op
	POP	H
	RET
;
;
; STP: stop de uitvoer naar het display
;
; Entry: none
; Mod:	 A,flags
; Exit:  none
;
STP:	PUSH	B		; Bewaar registers
	PUSH	D
	PUSH	H
STP1:	MVI	E,0FFH
	CALL	DCON		; Test op input
	ANA	A		; Karakter ontvangen?
	JZ	STP1		; Zo nee: test op input
	MOV	C,A		; Bewaar commando in C
	ANI	01FH
	CPI	STOP		; Weer een stop commando?
	JZ	STP1		; Zo ja: negeer dit
	MOV	A,C		; Zo nee: commando weer in A
	CALL	COMMAND		; Verwerk commando
	CPI	CONT		; Karakter om verder te gaan?
	JNZ	STP1		; Zo nee: test op input
	POP	H
	POP	D
	POP	B
	RET
;
;
; BSTP: stopt uitvoer wanneer met reverse scrolling de file
;	geheel is doorlopen. Wacht op een up commando om
;	verder te gaan of op een break commando.
;
; Entry: none
; Mod:	 A,flags
; Exit:  none
;
BSTP:	PUSH	B		; Bewaar registers
	PUSH	D
	PUSH	H
BSTP1:	MVI	E,0FFH
	CALL	DCON		; Test op input
	ANA	A		; Karakter ontvangen?
	JZ	BSTP1		; Zo nee: test op input
	MOV	C,A		; Bewaar commando in C
	ANI	01FH
	CPI	STOP		; Is het een stop commando
	JZ	BSTP1		; Zo ja: negeer dit
	MOV	A,C		; Zo nee: verwerk commando
	CALL	COMMAND
	MOV	A,C
	ANI	01FH
	CPI	UP		; Is het een up commando?
	JNZ	BSTP1		; Zo nee: test op input
	POP	H
	POP	D
	POP	B
	RET
;
;
; ESTP: stopt de uitvoer wanneer de gehele file is doorlopen.
;	Wacht op een down commando om verder te gaan of een
;	break commando
;
; Entry: none
; Mod:	 A,flags
; Exit:  none
;
ESTP:	PUSH	B		; Bewaar registers
	PUSH	D
	PUSH	H
ESTP1:	MVI	E,0FFH
	CALL	DCON		; Test op input
	ANA	A		; Karakter ontvangen?
	JZ	ESTP1		; Zo nee: test op input
	MOV	C,A		; Bewaar commando in C
	ANI	01FH
	CPI	STOP		; Is het een stop commando?
	JZ	ESTP1		; Zo ja: negeer dit
	MOV	A,C		; Zo nee: verwerk commando
	CALL	COMMAND
	MOV	A,C
	ANI	01FH
	CPI	DOWN		; Is het een down commando?
	JNZ	ESTP1		; Zo nee: test op input
	POP	H
	POP	D
	POP	B
	RET
;
;
;-------------------------------------------------------
;
;
; Subroutine die de intialisatie verzorgt na het opstarten.
;
;
; INIT: initialiseert pointers en vult het file control blok vanaf
;	de filenaam met nullen.
;
; Entry: none
; Mod:	 all
; Exit:  none
;
INIT:	LXI	H,FCB+12	; Eerste te resetten adres van fcb
	LXI	D,FCB+35	; Laatste te resetten adres van fcb
INIT1:	MVI	M,0		; Reset byte
	INX	H
	CALL	CMPDH		; Zijn alle bytes gereset?
	JNC	INIT1		; Zo nee: reset volgende
	XRA	A
	STA	RLF		; Reset rev line feed vlag
	STA	CHARC		; Reset karakter teller
	STA	DFLAG		; Reset down commando vlag
	STA	EOFFL		; Reset blokering karakter print
	INR	A
	STA	LINC		; Set regelteller
	LXI	H,0
	SHLD	RECCT		; Clear record teller
	MVI	A,'2'
	CALL	SETDLY		; Set delaypointer op snelheid 2
	LDA	REVLF		; Laad pointer string reverse lf
	ANA	A		; Is deze nul?
	JNZ	INIT2		; Zo ja, spring
	MVI	A,1
	STA	DFLAG		; Set down commando vlag
INIT2:	LDA	DIRCUR		; Laad pointer string dir. cur. best.
	ANA	A		; Is deze nul?
	JNZ	INIT3		; Zo nee, spring
	MVI	A,1
	STA	DFLAG		; Set down commando vlag
INIT3:	LDA	CHARW		; Laad aant. kar/regel
	CPI	32		; Is dit kleiner dan 32?
	JC	INIT4		; Zo ja: outp. foutm.
	LDA	CHARH		; Laad aant. regels/display
	CPI	16		; Is dit kleiner dan 16?
	RNC			; Zo ja: outp. foutm.
INIT4:	LXI	D,ERTERM	; Adres fout melding in D,E
	CALL	PRSTRG		; Output foutmelding
	JMP	CPM		; en keer terug naar cp/m
	RET
;
;
;-------------------------------------------------------
;
;
; Subroutines die gebruik maken van de direkte cursor besturing van
; de terminal en van de reverse linefeed functie.
;
;
; PUTRLF: print een reverse line feed op het display
;
; Entry: none
; Mod:	 A,flags,B,C
; Exit:  none
;
PUTRLF:	PUSH	D		; Bewaar adressen
	PUSH	H
	LXI	H,REVLF		; String rev lf in H,L
	MOV	C,M		; Aantal karakters string in C
PRLF1:	INX	H
	MOV	E,M		; Karakter in E voor verzending
	PUSH	B		; Bewaar teller
	CALL	DCON		; Print karakter
	POP	B
	DCR	C		; Verlaag teller
	JNZ	PRLF1		; Indien geen nul, verzendt volg. kar.
	POP	H		; Haal adressen terug
	POP	D
	RET
;
;
; CURHOM: zet de cursor links bovenaan op het display
;
; Entry: none
; Mod:	 A,flags,D,E
; Exit:	 none
;
CURHOM:	PUSH	H		; Bewaar registers
	PUSH	B
	CALL	CURDIR		; Verzendt string dir.cur.adressering
	LXI	H,OFFSL		; H,L adres regel offset
	MOV	E,M
	CALL	DCON		; Verzendt regel offset
	LXI	H,OFFSC		; H,L adres kolom offset
	MOV	E,M
	CALL	DCON		; Verzendt kolom offset
	POP	B		; Haal register terug
	POP	H
	RET
;
;
; CURDWN: zet de cursor links onderaan op het display
;
; Entry: none
; Mod:	 A,flags,D,E
; Exit:  none
;
CURDWN:	PUSH	H		; Bewaar registers
	CALL	CURDIR		; Verzendt string dir.cur.adressering
	LXI	H,OFFSL		; H,L adres regel offset
	MOV	C,M		; Offset in C
	LDA	CHARH		; Aantal regels/display in A
	DCR	A		; min 1
	ADD	C		; Tel offset hierbij op
	MOV	E,A
	CALL	DCON		; Verzendt regel + offset
	LXI	H,OFFSC		; H,L adres kolom offset
	MOV	E,M
	CALL	DCON		; Verzendt kolom offset
	POP	H		; Haal registers terug
	RET
;
;
; CURDIR: verzendt de string voor de direkte cursor adressering
;
; Entry: none
; Mod:	 A,flags,D,E
; Exit:  none
;
CURDIR:	PUSH	H		; Bewaar registers
	PUSH	B
	LXI	H,DIRCUR	; H,L adrespointer string dir.cur.adr.
	MOV	C,M		; Pointer in C
CURD1:	INX	H		; Verzendt string
	MOV	E,M
	PUSH	B
	CALL	DCON
	POP	B
	DCR	C
	JNZ	CURD1
	POP	B		; Haal registers terug
	POP	H
	RET
;
;
;-------------------------------------------------------
;
;
; Algemene subroutines.
;
;
; MEMREC: berekent hoeveel records van 128 bytes er in het geheugen
;	  passen.
;
; Entry: none
; Mod:	 A,flags,H,L
; Exit:  none
;
MEMREC:	LHLD	00006H		; Startadres bdos in H,L
	MOV	A,L		; Deel dit door 128
	ANI	080H
	PUSH	PSW
	MOV	A,H
	RAL
	MOV	L,A
	MVI	A,0
	ADC	A
	MOV	H,A
	POP	PSW
	RLC
	ADD	L
	SUI	LGPRM		; Trek hiervan het aantal records af
	MOV	L,A		;  wat het programma lang is
	MOV	A,H
	SBI	0
	MOV	H,A
	DCX	H		; - 1, voor reserve buffer
	SHLD	MXRECM		; Berg resultaat op
	RET
;
;
; DELAY: voegt een wachttijd in tussen de verzending van regels
;
; Entry: none
; Mod:	 A,flags
; Exit:  none
;
DELAY:	PUSH	H
	LHLD	DLY		; Laad delay pointer
DELAY1:	DCX	H		; Verlaag deze
	MOV	A,L
	ORA	H		; Is pointer nul?
	JNZ	DELAY1		; Nee: wacht
	POP	H
	RET
;
;
; CMPDH: vergelijkt twee getallen c.q. adressen
;
; Entry: H,L - eerste getal
;	 D,E - tweede getal
; Mod:	 A,flags
; Exit:  csf = 0 indien H,L < = D,E
;	 csf = 1 indien H,L >   D,E
;
CMPDH:	MOV	A,E		; Vergelijk lsbytes
	SUB	L
	MOV	A,D		; Vergelijk msbytes
	SBB	H
	RET
;
;
; SUBDH: trekt D,E af van H,L
;
; Entry: D,E - aftrektal
;	 H,L - getal
; Mod:	 A,flags,H,L
; Exit:  H,L - uitkomst
;	 D,E - aftrektal
;
SUBDH:	MOV	A,L		; Trek lsbyte af
	SUB	E
	MOV	L,A
	MOV	A,H		; Trek msbyte af
	SBB	D
	MOV	H,A
	RET
;
;
;-------------------------------------------------------
;
;
; CP/M funktie subroutines.
;
;
; DCON: direkte console I/O
;
; Entry: E = 0FFH voor input
;	 E = karkter voor output
; Mod:	 A,flags,B,C,D,E
; Exit:  bij input: A = 00 er wacht geen karakter
;		    A <> 0 ontvangen karakter
;
DCON:	PUSH	H		; Bewaar H,L
	MVI	C,DICONF	; Direkte console funktie in C
	CALL	BDOS		; Voer funktie uit
	POP	H
	RET
;
;
; PRSTRG: verzendt een string naar het display.
;
; Entry: D,E - beginadres string
; Mod:	 all
; Exit:  none
;
PRSTRG:	MVI	C,PRINTF	; Printfunktie in C
	JMP	BDOS		; Print string
;
;
; OPEN: opent een file
;
; Entry: none
; Mod:	 all
; Exit:  A - <> 0FFH indien openen is gelukt
;	      = 0FFH indien openen is mislukt
;
OPEN:	LDA	080H		; Haal eerste karakter uit line buf.
	ANA	A		; Is er een file naam opgegeven?
	PUSH	PSW
	LXI	D,USE		; Zo nee: display gebruiksaanwijzing
	CZ	PRSTRG
	POP	PSW
	JZ	CPM		; en keer terug naar cp/m
	MVI	C,OPENF		; Open funktie in C
	LXI	D,FCB		; Startadres file contr. blok in D,E
	CALL	BDOS		; Open file
	CPI	0FFH		; Is openen gelukt?
	RNZ			; Zo ja: keer terug
	LXI	D,NOINP		; Zo nee: meldt dat op het display
	CALL	PRSTRG
	JMP	CPM		; en keer terug naar cp/m
;
;
; STDMA: set het dma adres
;
; Entry: H,L - dma adres
; Mod:	 A,flags,B,C,H,L
; Exit:  none
;
STDMA:	PUSH	D		; Bewaar D,E
	SHLD	DMAAD		; Bewaar een copy van dma adres
	XCHG			; Adres naar D,E
	MVI	C,DMAF		; Set dma funktie in C
	CALL	BDOS		; Set dma adres
	POP	D		; Haal D,E terug
	RET
;
;
; RRAND: laad een random record
;
; Entry: none
; Mod:	 A,flags,B,C,H,L
; Exit:  none
;
RRAND:	PUSH	D		; Bewaar D,E
	MVI	C,RRANDF	; Read random funktie in C
	LXI	D,FCB		; Start adres file control blok in D,E
	CALL	BDOS		; Laad record
	POP	D
	RET
;
;
; RECCNT: haalt het aantal records van een file.
;
; Entry: none
; Mod:	 all
; Exit:  none
;
RECCNT:	MVI	C,FILSF		; File grootte funktie in C
	LXI	D,FCB		; Startadres file contr. blok in D,E
	CALL	BDOS		; Bereken aantal records
	LHLD	FCB+33		; Aantal records in H,L
	SHLD	RCCNT		; Berg aantal records op
	RET
;
;
;-------------------------------------------------------
;
;
; Ascii karakter strings.
;
USE:	DB	CR,LF,'++use: RTYP <filename>',CR,LF,'$'
NOINP:	DB	CR,LF,'--no input file present !',CR,LF,'$'
ERTERM:	DB	CR,LF,'!!Wrong terminal constants!!',CR,LF,LF,'$'
;
;
;
;
; Data area
;
MXRECM:	DS	2		; Max. aantal vrije records v. geheugen
RCCNT:	DS	2		; Aantal records van file
CNT:	DS	2		; Teller max. te laden records
FBLOK:	DS	2		; Rec. lengte geladen file(blok)
DMAAD:	DS	2		; Kopy dma adres
RECCT:	DS	2		; Record teller
RLF:	DS	1		; Reverse line feed vlag
DLY:	DS	2		; Delay pointer
CHARC:	DS	1		; Karakter teller
LINC:	DS	1		; Regelteller
DFLAG:	DS	1		; Blokkering down commando
EOFFL:	DS	1		; End of file vlag
EOFAD:	DS	2		; End of file adres
	DS	80		; Stack ruimte
NWSTK	EQU	$		; Nieuwe stackpointer
;
;
;
;
LGPRM	EQU	($+127)/128	; Lengte programma in rec. v. 128 bytes
;
STARTFL	EQU	LGPRM*100H/2	; Start vrije werkruimte
;
;
;
	END
