;
; RM65-5102 CRT Controller (CRTC) Module Program ROM (R14B4-11)
;
;	Reformatted for CA65 Assembler
;	Chris Oddy December 2025
;
	.setcpu "6502"
;
			; *** Zero Page ***
BSTART	:= $DB
CURSOR	:= $DD
;
COLUMN	:= $F0
EQFLG	:= $F1
CRFLG	:= $F2
SAVA	:= $F3
SAVX	:= $F4
SMFLG	:= $F5
COMCOL	:= $F6
COMCR	:= $F7
;
			; *** CRT Variables ***
SCRMAX	:= $0347
ROWMAX	:= $0349
COLMAX	:= $034A
END	:= $034B
DLE	:= $034D
INCH	:= $034E
EFLG	:= $034F
GRAPH	:= $0350
INVERS	:= $0351
DSTARL	:= $0352
DSTARH	:= $0353
YSAV	:= $0354
XSAV	:= $0355
ASAV	:= $0356
AIM65	:= $0357
ROW	:= $0358
COL	:= $0359
TABLE	:= $035A
CURP2	:= $035B
ECHO	:= $035C
CMAX	:= $035E
PRFLG	:= $035F
XXX	:= $0360
YYY	:= $0361
XX2	:= $0362
XADDR	:= $0363
COL2	:= $0365
DBUFF	:= $0366
;
DILINK	:= $A406	; AIM Display Echo
CURPO2	:= $A415	; AIM Display Pointer
CURPOS	:= $A416	; AIM Printer Pointer
DIBUFF	:= $A438	; AIM Display Buffer
;
RS	:= $9800	; 6545 Base Address
;
STATUS	:= $9880	; Display Enable Status
;
			; *** Monitor Subroutines ***
COMIN	:= $E1A1	; Re-enter command interpreter
OUTDIS	:= $EF05	; Output A to display
;
			; *** ASCII Characters ***
CR	:= $0D
DELETE	:= $7F
;
	.org	$9800
;
RKWELL:	.byte	"COPYRIGHT 1981ROCKWELL INTERNATIONAL ;GET CURRENT ROW",CR
	.byte	" LDX ROWMAX ;GET #ROWS/SCREEN",CR
	.byte	" DEX ;DECR.",CR
	.byte	" CPX ROW ;CURRENT=LAST ?",CR
	.byte	" BEQ WRBLNK ;YES, JUST BLANK IT",CR
	.byte	" DEX ;ROWMAX-2 NOW",CR
	.byte	" STX ROW ;ROW=ROWMAX-2",CR
	.byte	" STY YSAV ;SAVE ORIGINAL ROW",CR
	.byte	" LDA COLMAX ;GET #COLS/SCREEN",CR
	.byte	" A"
;
MONENT:	jsr	INIT		; Initialisation Entry Point
	jmp	COMIN		; Re-enter command interpreter
;
INIT:	lda	TABLE
	cmp	#$04
	bcc	OKTAB
	bne	NOTOWN
	ldy	XADDR
	lda	XADDR+1
	jmp	SETUP
NOTOWN:	lda	#$01
OKTAB:	asl	a
	tax
	ldy	SIZE,x
	lda	SIZE+1,x
SETUP:	sta	BSTART+1
	sty	BSTART
;
	ldy	#$07
TABLES:	sty	RKWELL
	lda	(BSTART),y
	sta	RS+1
	lda	#$00
	sta	DLE,y
	dey
	bpl	TABLES
;
	ldy	#$0F
	ldx	#$07
NXPRM:	sty	RKWELL
	lda	MID8,x
	sta	RS+1
	dey
	dex
	bpl	NXPRM
;
	ldy	#$08
	ldx	#$03
NLSTB:	lda	(BSTART),y
	sta	SCRMAX,x
	iny
	lda	IVALS,x
	sta	ECHO,x
	dex
	bpl	NLSTB
	lda	#$90
	sta	DSTARH
	jsr	CALEND
;
WARM:	ldx	AIM65
	beq	NDAIM
	jsr	CRT
NDAIM:	jsr	CLRHOM
SKIPIT:	rts
;
USERQ:	bcc	SKIPIT
	pla
SKIPOA:	cmp	#$0A
	beq	SKIPIT
OUTD:	cld
	pha
	stx	XXX
	sty	YYY
	lda	PRFLG
	bne	SK3
	jsr	BSPACE
	jsr	BSPACE
	jsr	BSPACE
	lda	#$03
	sta	PRFLG
SK3:	tsx
	ldy	$0103,x
	cpy	#$D1
	bne	NASSM
	ldy	$0102,x
	cpy	#$09
	beq	DONE
NASSM:	pla
	pha
	sta	ASAV
	ldx	DLE
	beq	SPECAL
	dec	DLE
	beq	OUTIT
SPECAL:	cmp	#DELETE
	bne	N2DEL
	jsr	BSPACE
	bne	DONE
N2DEL:	and	#DELETE
	sta	ASAV
	ldx	EFLG
	beq	NESC
	dex
	beq	EFLQ1
	dex
	beq	EFLQ2
	jsr	CONVRT
	bne	DONE
EFLQ1:	cmp	#'='
	beq	INFLQ
	cmp	#'G'
	bne	NVALID
	jsr	GRPHON
NVALID:	dec	EFLG
	beq	DONE
EFLQ2:	sta	YSAV
INFLQ:	inc	EFLG
	bne	DONE
;
NESC:	cmp	#$20
	bcc	CNTL
OUTIT:	jsr	CHAR
	jmp	DONE
;
CNTL:	asl	a
	tax
	lda	JTBL,x
	sta	BSTART
	lda	JTBL+1,x
	sta	BSTART+1
	jsr	RDCUR
	jsr	INDIR
DONE:	pla
	ldx	XXX
	ldy	YYY
NOECHO:	rts
;
STEST:	jsr	CLRHOM
	jsr	RDCUR
	lda	#$00
	sta	BSTART
ROWOUT:	jsr	INCUR2
	lda	BSTART
	jsr	WRITE
	inc	BSTART
	lda	BSTART
	and	#$0F
	bne	ROWOUT
	lda	BSTART
	beq	HOMECU
	jsr	CARTN
	bne	ROWOUT
;
DELINE:	lda	ROW
	pha
	jsr	LNSTRT
LOOP:	inc	ROW
	ldx	ROW
	cpx	ROWMAX
	bne	COPY
	pla
	sta	ROW
	jmp	BLANK
COPY:	jsr	ADCOLS
	jsr	READLN
	jsr	SMAX2
	jsr	WRITLN
	beq	LOOP
;
CLINE:	jsr	LNSTRT
	jmp	WRBLNK
;
HOMECU:	lda	DSTARL
	sta	CURSOR
	lda	DSTARH
	sta	CURSOR+1
	ldx	#$00
	stx	ROW
ZERCOL:	stx	COL
	beq	XFR
;
CLRHOM:	jsr	HOMECU
;
CLREND:	jsr	WRITBL
	ldx	CURSOR
	cpx	END
	bne	CLREND
	lda	$DE
	and	#$DF
	cmp	END+1
	bne	CLREND
	rts
;
CURBCK:	jsr	RDCUR
	dec	COL
	bpl	NCOL1
	dec	ROW
	bpl	COL1
;
	jsr	ADCOLS
	jsr	TOPROW
COL1:	ldx	COLMAX
	dex
	stx	COL
;
NCOL1:	ldx	CURSOR
	bne	DDEC
	clc
	jsr	BOUND0
DDEC:	dec	CURSOR
XFR:	jmp	XFERCU
;
CURFWD:	jsr	CURFW2
	bcs	HOMECU
	rts
;
CURFW2:	jsr	RDCUR
	inc	COL2
	ldx	COL
	inx
	cpx	COLMAX
	bne	NTLCOL
	ldx	ROW
	inx
	cpx	ROWMAX
	bne	NTLROW
	sec
	rts
;
NTLROW:	ldx	#$FF
	stx	COL
	inc	ROW
NTLCOL:	inc	COL
INCUR:	jsr	INCUR2
	jsr	XFERCU
	clc
	rts
;
INSLIN:	jsr	LNSTRT
	ldy	ROW
	ldx	ROWMAX
	dex
	cpx	ROW
	beq	WRBLNK
	dex
	stx	ROW
	sty	YSAV
	lda	COLMAX
	asl	a
	sta	XSAV
	sec
	lda	END
	sbc	XSAV
	sta	CURSOR
	lda	END+1
	jsr	BOUND5
LOOP1:	jsr	READLN
	jsr	WRITLN
	ldx	ROW
	cpx	YSAV
	beq	WRBL2
	jsr	SMAX2
	jsr	CONTIN
	dec	ROW
	bpl	LOOP1

WRBL2:	jsr	SMAX2
WRBLNK:	ldx	#$00
	jsr	ZERCOL
;
BLANK:	ldx	#$00
BLANK1:	jsr	WRITBL
	inx
	cpx	COLMAX
	bne	BLANK1
	rts
;
CLREOL:	ldx	COL
	bpl	BLANK1
;
SMAX2:	jsr	CONTIN
CONTIN:	lda	CURSOR
	sec
	sbc	COLMAX
	jmp	BOUND1
;
CURDWN:	inc	ROW
	ldx	ROW
	cpx	ROWMAX
	beq	BOTROW
	jsr	ADCOLS
	bne	XFERCU
TOTOP:	jsr	CONTIN
BOTROW:	dec	ROW
	bne	TOTOP
	beq	XFERCU
;
CURUP:	dec	ROW
	bpl	UP2
TOPROW:	ldx	ROWMAX
	dex
	stx	ROW
TOBOT:	jsr	ADCOLS
	dex
	bpl	TOBOT
UP2:	jsr	CONTIN
;
XFERCU:	sec
	lda	CURSOR
	sbc	DSTARL
	lda	CURSOR+1
	tax
	sbc	DSTARH
	bpl	NOBIT
	txa
	ora	#$08
	bne	NOBIT2
NOBIT:	txa
NOBIT2:	ldx	INVERS
	beq	NOTSET
	ora	#$20
NOTSET:	ldx	#$0E
	jsr	S6545
	lda	CURSOR
	inx
S6545:	stx	RKWELL
	sta	RS+1
	rts
;
CARTN:	lda	AIM65
	beq	CLOOP
	lda	#$0D
	jsr	OUTDIS		; Output A to display
	lda	#$00
	sta	$AC01
CLOOP:	sta	CURP2
	sta	COL2
	inc	ROW
	jsr	RDCUR
	jsr	ADCOLS
	jsr	LNSTRT
	ldx	ROW
	cpx	ROWMAX
	bne	ZCOL
	dec	ROW
SCROLL:	clc
	lda	DSTARL
	adc	COLMAX
	sta	DSTARL
	lda	DSTARH
	adc	#$00
	and	#$97
	sta	DSTARH
	jsr	BLANK
	jsr	XDSTAR
	jsr	CONTIN
ZCOL:	ldx	#$00
	jmp	ZERCOL
;
VIDEO:	lda	INVERS
	eor	#$FF
	sta	INVERS
	jsr	XDSTAR
	jsr	RDCUR
	jmp	XFERCU
;
RDCUR:	ldx	#$0E
	jsr	R6545
	ora	#$90
	jsr	MASK
	inx
R6545:	stx	RKWELL
	lda	RS+1
	sta	CURSOR
	rts
;
LNSTRT:	sec
	lda	CURSOR
	sbc	COL
BOUND1:	sta	CURSOR
;
BOUND0:	lda	$DE
BOUND5:	sbc	#$00
	sta	$DE
	cmp	#$90
	bcs	SKCAR
	lda	#$97
	bne	MM2
;
ADCOLS:	clc
	lda	CURSOR
	adc	COLMAX
STCUR:	sta	CURSOR
INCMSB:	lda	CURSOR+1
	adc	#$00
MASK:	and	#$97
MM2:	sta	$DE
SKCAR:	rts
;
XDSTAR:	lda	DSTARH
	ora	#$20
	ldx	INVERS
	bne	STORE
	and	#$D7
STORE:	ldx	#$0C
	jsr	S6545
	inx
	lda	DSTARL
	jsr	S6545
;
CALEND:	clc
	lda	DSTARL
	adc	SCRMAX
	sta	END
	lda	DSTARH
	adc	SCRMAX+1
	and	#$D7
	sta	END+1
	rts
;
READLN:	ldx	#$00
READ1:	jsr	READ
	sta	DBUFF,x
	inx
	cpx	COLMAX
	bne	READ1
	rts
;
WRITLN:	ldx	#$00
WRIT1:	lda	DBUFF,x
	jsr	WRITE
	inx
WRIT2:	cpx	COLMAX
	bne	WRIT1
	rts
;
READ:	jsr	SDELAY
ENAB7:	ldx	STATUS
	bmi	ENAB7
	lda	(CURSOR),y
INCUR2:	pha
	inc	CURSOR
	bne	NOCA
	sec
	jsr	INCMSB
NOCA:	pla
	ldx	XX2
	rts
;
WRITE:	jsr	SDELAY
ENAB2:	ldx	STATUS
	bmi	ENAB2
	sta	(CURSOR),y
	bpl	INCUR2
;
SDELAY:	stx	XX2
	ldy	#$00
ENAB5:	ldx	STATUS
	bmi	ENAB5
DLY5:	ldx	STATUS
	bpl	DLY5
	rts
;
GRPHON:	jsr	B32CUR
	bne	GRTN
;
GRPHOF:	jsr	DCURS
GRTN:	sta	GRAPH
	rts
;
B32CUR:	lda	#$60
	bne	CMODE
;
DCURS:	lda	#$00
	beq	CMODE
BLKCUR:	lda	#$20
CMODE:	ldx	#$0A
	jmp	S6545
;
INSTOQ:	lda	INCH
	eor	#$FF
	sta	INCH
	rts
;
ESC:	ldx	#$01
	stx	EFLG
	rts
;
DELCHR:	jsr	RDEOL
	inx
	jsr	WRIT1
	jmp	WRITBL
;
CONVRT:	jsr	HOMECU
	lda	YSAV
	sec
	sbc	#$20
	tay
	beq	ROWZ
	cpy	ROWMAX
	bcc	ADDCOL
	ldy	ROWMAX
	dey
ADDCOL:	jsr	ADCOLS
	inc	ROW
	dey
	bne	ADDCOL
ROWZ:	sty	EFLG
	lda	ASAV
	sec
	sbc	#$20
	tax
	cpx	COLMAX
	bcc	DKCOL
	ldx	COLMAX
	dex
DKCOL:	stx	COL
	lda	CURSOR
	clc
	adc	COL
	jsr	STCUR
	jmp	XFERCU
;
DLESC:	lda	#$01
	sta	DLE
	rts
;
RDEOL:	ldx	COL
	jsr	READ1
	jsr	RDCUR
	ldx	COL
	rts
;
CRT:	dex
	bne	CRT2
	lda	#$73
	bne	PL65
AIMD:	lda	#$04
	sta	$AC01
	lda	#$05
	ldx	#$EF
	bne	STDEST
CRT2:	lda	#$77
PL65:	ldx	#$99
STDEST:	sta	DILINK
	stx	DILINK+1
DONE2:	rts
;
DEELET:	lda	CURP2
	cmp	#$14
	bcc	LTN20
	lda	#$13
LTN20:	sta	CURPO2
	lda	CURP2
	beq	DEL2
	lda	COL2
	cmp	CMAX
	beq	DEL2
	dec	CURP2
DEL2:	lda	#$E8
	sta	$0105,x
	dec	COL2
	lda	#$04
	sta	$0104,x
	lda	CURP2
	sta	$0103,x
BSPACE:	jsr	CURBCK
WRITBL:	lda	#$20
	jmp	WRITE
;
CHAR:	ldx	GRAPH
	beq	NOGRPH
	lda	ASAV
	ora	#$80
	sta	ASAV
NOGRPH:	ldx	AIM65
	beq	STCH00
	jsr	RDCUR
	tsx
ONOFF:	lda	$0108,x
	cmp	#$EC
	bne	TAPECK
	lda	$0107,x
	cmp	#$CF
	bne	TAPECK
	inc	CURPO2
	dec	PRFLG
	bpl	NOINS
TAPECK:	lda	$A412
	cmp	#$54
	bne	DELCK
	jmp	SCR0
;
DELCK:	lda	$0105,x
	ldy	$0104,x
	cmp	#$E7
	bne	STORE2
	cpy	#CRFLG
	beq	DEELET
CKMSQ:	cpy	#$B7
	bne	STORE2
	ldy	YYY
	cpy	#$72
	beq	EMSQ
	cpy	#$3B
	bne	SCR0
	ldy	#$03
	sty	PRFLG
EMSQ:	jsr	CARTN
	bne	SCR0
STORE2:	lda	ASAV
	ldy	CURPO2
	iny
	cpy	#$14
	bcc	LT20
	ldy	#$13
LT20:	sty	CURPO2
	ldy	CURP2
	cpy	#$3B
	bcs	STCH00
	sta	DIBUFF,y
	inc	CURP2
;
STCH00:	jsr	RDCUR
	ldx	INCH
	beq	NOINS
	jsr	RDEOL
	lda	ASAV
	jsr	WRITE
	dec	COLMAX
	jsr	WRIT2
	inc	COLMAX
	bne	SCR2
NOINS:	ldx	AIM65
	beq	SCR0
	ldx	CURP2
	cpx	CMAX
	bne	SCR0
	ldx	#$3A
	stx	YYY
	stx	CURP2
	ldx	#$12
	stx	CURPOS
	ldx	COL2
	inx
	cpx	CMAX
	beq	SCR0
	dec	COL2
	jsr	CURBCK
SCR0:	lda	ASAV
	jsr	WRITE
;
SCR2:	jsr	CURFW2
	bcc	NOTSCR
	jsr	INCUR
	jmp	SCROLL
NOTSCR:	rts
;
INDIR:	jmp	(BSTART)
;
ENTRY:	bcs	ASOUT
	ldx	#$00
	stx	SMFLG
	inx
	stx	COMCR
	rts
;
ASOUT:	cld
	stx	SAVX
	ldx	#$28
	stx	COMCOL
	pla
	sta	SAVA
	cmp	#$20
	bcc	NO
	cmp	#$5E
	bcc	N1
NO:	ldx	#$01
	stx	CRFLG
	ldx	SMFLG
	bpl	SKIP
	asl	SMFLG
SKIP:	rts
;
N1:	ldx	SMFLG
	bpl	N1A
	jmp	NEXT
N1A:	cmp	#$3D
	bne	N6
	ldx	CRFLG
	beq	N2
	jsr	CRLF
	stx	COMCR
	inx
	stx	EQFLG
	jmp	R1
N2:	ldx	EQFLG
	bne	N3
CRSP:	jmp	NEXT
N3:	lsr	EQFLG
	jmp	R1
N6:	ldx	CRFLG
	beq	N10
	cmp	#$3B
	bne	N8
	lda	$29
	bne	NOTZ
	jsr	CRLF
	lda	#$80
	sta	SMFLG
	sta	COMCR
	bne	SEMI
NOTZ:	lsr	CRFLG
	ldx	#$01
	stx	SMFLG
	bne	R1
NC:	ldx	COLUMN
	cpx	#$22
	bcc	SP1
	txa
	adc	#$02
	sta	COMCOL
SP1:	ldx	COLUMN
	cpx	COMCOL
	beq	N7
	jsr	SPACE
	jmp	SP1
N7:	lda	#$3B
	jsr	NEXT
	jmp	NN
N8:	ldx	COLUMN
	cpx	#$0C
	bcs	N9
	lda	COMCR
	cmp	#$80
	bne	SKCR
	asl	COMCR
	beq	N9
SKCR:	lsr	CRFLG
	jsr	COUNT
NN:	lda	SAVA
	jmp	NEXT
N9:	jsr	RESET
N10:	lda	SAVA
	ldx	SMFLG
	beq	NEXT
	lsr	SMFLG
	cmp	#$2E
	bne	NC
	jsr	RESET
SEMI:	lda	#$3B
	bne	NEXT
SPACE:	lda	#$20
NEXT:	ldx	COLUMN
	cpx	#$47
	bcs	IN1
	jsr	OUTD
	pha
	jsr	INDR2
	pla
IN1:	inc	COLUMN
R1:	ldx	SAVX
	rts
;
CRLF:	lda	#$0D
	jsr	OUTD
	jsr	INDR2
	ldx	#$00
	stx	COLUMN
	stx	CRFLG
	rts
;
RESET:	jsr	CRLF
	lda	$33
	jsr	NUMA
	lda	$32
	jsr	NUMA
COUNT:	jsr	SPACE
	ldx	COLUMN
	cpx	#$0C
	bne	COUNT
	rts
;
NUMA:	pha
	lsr	a
	lsr	a
	lsr	a
	lsr	a
	jsr	NOUT
	pla
	and	#$0F
NOUT:	clc
	adc	#$30
	cmp	#$3A
	bcc	LT10
	adc	#$06
LT10:	bne	NEXT
INDR2:	jmp	(ECHO)
;
T25806:	.byte	$6C,$50,$59,$59,$1F,$02,$19,$1C
	.byte	$50,$19,$07,$D0
	
T22725:	.byte	$6C,$48,$55,$59,$1A,$02,$16,$18
	.byte	$48,$16,$06,$30
;
T16405:	.byte	$36,$28,$2D,$55,$1A,$02,$10,$15
	.byte	$28,$10,$02,$80
T25406:	.byte	$36,$28,$2C,$55,$1F,$02,$19,$1C
	.byte	$28,$19,$03,$E8
;
SIZE:	.word	T25806,T22725,T25406,T16405
MID8:	.byte	$30,$09,$00,$0A,$90,$00,$90,$00
IVALS:	.byte	$09,$9A,$3B,$03
;
JTBL:	.word	DONE2,CLINE,CLREOL,CLRHOM,CLREND
	.word	CLRHOM,CLREND,DONE2,CURBCK,CURFWD
	.word	CURDWN,CURUP,DONE2,CARTN,HOMECU
	.word	HOMECU,DLESC,DONE2,DONE2,INSTOQ,DELCHR
	.word	INSLIN,DELINE,DCURS,BLKCUR,AIMD
	.word	DONE2,ESC,B32CUR,GRPHOF,STEST
BLAST:	.word	VIDEO
;
	.byte	$42,$4F
