Printing to screen without kernal

Basic and Machine Language

Moderator: Moderators

Post Reply
TNT
Vic 20 Hobbyist
Posts: 121
Joined: Wed Apr 29, 2009 5:46 am

Printing to screen without kernal

Post by TNT »

Here is the code I use for printing in my Infocom interpreter. It's faster than kernal, uses less zero page locations, is portable accross multiple C= computers, and allows custom screen sizes.

Code: Select all

	subroutine
prChar
	cmp	#$20
	bcc	.ctrl			; cr/del/home
	tax

	ldy	kzp_cursorx
SWptchB
	cpy	#SCR_WIDTH
	bcs	.line
.0
	lda	.table-32,x		; poke code
	ora	kzp_reverse		; reverse mode
	inc	kzp_cursorx		; bump column

.putc
	sta	(kzp_cursoraddr),y

	ldx	kzp_cursoraddr+1
	txa
	eor	#>SCREEN^>COLORMEM
	sta	kzp_cursoraddr+1
	lda	scr_txcolor
	sta	(kzp_cursoraddr),y
	stx	kzp_cursoraddr+1
	rts

;	wrap to next line

.line
	pha
	jsr	.nline
	sty	kzp_cursorx		; x=0
	jsr	SetCursorRow		; fix kzp_cursoraddr
	pla
	tax
	bpl	.0			; print it (branch always taken)

;	increment line

.nline
	ldx	kzp_cursory
	inx				; next line
SHptch1
	cpx	#SCR_HEIGHT
	bcc	.noscr			; still on screen, just exit
	jsr	ScrollScreen
SHptch2
	ldx	#SCR_HEIGHT-1		; move to first column on last row
.noscr
	ldy	#0
.x
	rts

;	cr/del/home

.ctrl
	cmp	#13			; return?
	bne	.del

	jsr	.nline			; increment line
	sty	kzp_reverse		; reverse off
	beq	plotxy			; set cursor position

.del
	cmp	#20			; backspace?
	bne	.home

	ldy	kzp_cursorx		; first column?
	bne	.del1			; no, easy

	ldx	kzp_cursory		; first row?
	beq	.x			; yes, nothing to do

	dex				; else move to previous line
	jsr	SetCursorRow
SWptchC
	ldy	#SCR_WIDTH		; last column +1, decremented very soon

.del1
	dey				; previous column
	sty	kzp_cursorx
	lda	#$20			; print space
	bne	.putc

.home
	ldx	#0		; move to 0,0
	ldy	#0

plotxy
	sty	kzp_cursorx
SetCursorRow
	lda	Scr_lo,x
	sta	kzp_cursoraddr
	lda	Scr_hi,x
	sta	kzp_cursoraddr+1

	stx	kzp_cursory
	rts


;	poke codes for chars 20..7f

.table	HEX	202122232425262728292a2b2c2d2e2f	; [20,3f] as is
	HEX	303132333435363738393a3b3c3d3e3f
	HEX	404142434445464748494a4b4c4d4e4f	; [40,5f] as is
	HEX	505152535455565758595a1b5c1d5e6f	; exc: 5b>1b, 5d>1d, 5f>6f
	HEX	000102030405060708090a0b0c0d0e0f	; [60,7f] & 1f
	HEX	101112131415161718191a1b5d1d1e1f	; exc: 7c>5d


	subroutine
ScrollScreen
	ldx	#0
SWptchD
.1
	ldy	#SCR_WIDTH-1
SHptch3
	cpx	#SCR_HEIGHT-1
	beq	.4

	lda	Scr_lo,x
	sta	.3+1
	lda	Scr_hi,x
	sta	.3+2
	inx
	lda	Scr_lo,x
	sta	.2+1
	lda	Scr_hi,x
	sta	.2+2

.2
	lda	$1234,y			; copy line up
.3
	sta	$1234,y
	dey
	bpl	.2
	bmi	.1			; continue with next line

.4
	lda	Scr_lo,x		; clear last line
	sta	.5+1
	lda	Scr_hi,x
	sta	.5+2
	lda	#" "
.5
	sta	$1234,y
	dey
	bpl	.5
	rts
Notes:
  • Values used at labels SWptchXX and SHptchXX are modified when the screen size is configured.
  • It only supports printing chars $20-$7f + $0d (return), $14 (backspace) and $13 (home) as that's all I need.
  • Because of the above reverse flag need to be set separately. It's easy to add them by using $80-$8f for colors and $90/$91 for reverse off/on.
  • It prints colors, but doesn't scroll them. That's easy to add if needed.


Here is the code which builds Scr_lo/Scr_hi tables for VIC-20

Code: Select all

;	build table for row addresses

	lda	#0
	ldy	#>SCREEN
	tax
.1
	sta	Scr_lo,x
	pha
	tya
	sta	Scr_hi,x
	pla
	clc
	adc	w
	bcc	.2
	iny
.2
	inx
	cpx	#32
	bcc	.1
w holds screen width in chars, routine always calculates addresses for 32 lines even if less are used.
Post Reply