6502 Emulator Example Code

From CDOT Wiki
Revision as of 10:19, 4 March 2020 by Chris Tyler (talk | contribs) (Fill the Bitmapped Display)
Jump to: navigation, search

This is a collection of simple examples of 6502 code which will run in the 6502 Emulator. To use this code, copy and paste one of these programs into the text box of the emulator.

This code is Copyright ©2020 Seneca College of Applied Arts and Technology. Each of these programs is free software; you can redistribute them and/or modify them under the terms of the General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

Fill the Bitmapped Display

      lda #$00     ; set pointer at $10 to $0200
      sta $10
      lda #$02
      sta $11
      
      ldx #$06     ; max value for $11
      
      ldy #$00     ; index

      lda #$07     ; colour code

loop: sta ($10),y  ; store colour
      iny          ; increment index
      bne loop     ; branch until page done
      
      inc $11      ; increment high byte of pointer
      cpx $11      ; compare with max value
      bne loop     ; continue if not done 
      
      brk          ; done - return to debugger

Place a Message on the Character Display

Without using the ROM routines

 define SCREEN $f000
           ldy #$00
 
 char:     lda text,y
           beq done
           sta SCREEN,y
           iny
           bne char
 
 done:     brk
 
 text:
 dcb "6","5","0","2",32,"w","a","s",32,"h","e","r","e",".",00

Using the ROM routines

; ROM routines
define		SCINIT		$ff81 ; initialize/clear screen
define		CHRIN		$ffcf ; input character from keyboard
define		CHROUT		$ffd2 ; output character to screen
define		SCREEN		$ffed ; get screen size
define		PLOT		$fff0 ; get/set cursor coordinates

          jsr SCINIT
          ldy #$00

char:     lda text,y
          beq done
          jsr CHROUT
          iny
          bne char

done:     brk

text:
dcb "6","5","0","2",32,"w","a","s",32,"h","e","r","e",".",00

Type on the Screen

; let the user type on the first page of character screen
; has blinking cursor!
; does not use ROM routines
; backspace works (non-destructive), arrows/ENTER don't
 
next:     ldx #$00
idle:     inx
          cpx #$10
          bne check
          lda $f000,y
          eor #$80
          sta $f000,y

check:    lda $ff
          beq idle

          ldx #$00
          stx $ff

          cmp #$08 ; bs
          bne print

          lda $f000,y
          and #$7f
          sta $f000,y

          dey
          jmp next

print:    sta $f000,y
          iny
          jmp next

Place a Graphic on the Screen

 define WIDTH 	4 ; width of graphic
 define HEIGHT 	4 ; height of graphic
 
 
 	lda #$25	; create a pointer at $10
 	sta $10		;   which points to where
 	lda #$02	;   the graphic should be drawn
 	sta $11
 
 	lda #$00	; number of rows we've drawn
 	sta $12		;   is stored in $12
 
 	ldx #$00	; index for data
 	ldy #$00	; index for screen column
 
 draw:	lda data,x
 	sta ($10),y
 	inx
 	iny
 	cpy #WIDTH
 	bne draw
   
 	inc $12		; increment row counter
 
 	lda #HEIGHT	; are we done yet?
 	cmp $12
 	beq done	; ...exit if we are
 
 	lda $10		; load pointer
 	clc
 	adc #$20	; add 32 to drop one row
 	sta $10
 	lda $11	; carry to high byte if needed
 	adc #$00
 	sta $11
 
 	ldy #$00
 	beq draw
 
 done:	brk		; stop when finished
 
 data:
 dcb 00,03,03,00
 dcb 07,00,00,07
 dcb 07,00,00,07
 dcb 00,03,03,00

Etch-a-Sketchtm Style Drawing

 ; zero-page variable locations
 define  ROW		$20	; current row
 define	COL		$21	; current column
 define	POINTER		$10	; ptr: start of row
 define	POINTER_H	$11
 
 ; constants
 define	DOT		$01	; dot colour
 define	CURSOR		$04	; black colour
 
 
 	ldy #$00	; put help text on screen
 print:	lda help,y
 	beq setup
 	sta $f000,y
 	iny
 	bne print
 
 setup:	lda #$0f	; set initial ROW,COL
 	sta ROW
 	sta COL
 
 draw:	lda ROW		; ensure ROW is in range 0:31
 	and #$1f
 	sta ROW
 
 	lda COL		; ensure COL is in range 0:31
 	and #$1f
 	sta COL
 
 	ldy ROW		; load POINTER with start-of-row
 	lda table_low,y
 	sta POINTER
 	lda table_high,y
 	sta POINTER_H
 
 	ldy COL		; store CURSOR at POINTER plus COL
 	lda #CURSOR
 	sta (POINTER),y
 
 getkey:	lda $ff		; get a keystroke
 
 	ldx #$00	; clear out the key buffer
 	stx $ff
 
 	cmp #$43	; handle C or c
 	beq clear
 	cmp #$63
 	beq clear
 
 	cmp #$80	; if not a cursor key, ignore
 	bmi getkey
 	cmp #$84
 	bpl getkey
 
 	pha		; save A
 
 	lda #DOT	; set current position to DOT
 	sta (POINTER),y
 
 	pla		; restore A
 
 	cmp #$80	; check key == up
 	bne check1
 
 	dec ROW		; ... if yes, decrement ROW
 	jmp done
 
 check1:	cmp #$81	; check key == right
 	bne check2
 
 	inc COL		; ... if yes, increment COL
 	jmp done
 
 check2:	cmp #$82	; check if key == down
 	bne check3
 
 	inc ROW		; ... if yes, increment ROW
 	jmp done
 
 check3:	cmp #$83	; check if key == left
 	bne done
 
 	dec COL		; ... if yes, decrement COL
 	clc
 	bcc done
 
 clear:	lda table_low	; clear the screen
 	sta POINTER
 	lda table_high
 	sta POINTER_H
 
 	ldy #$00
 	tya
 
 c_loop:	sta (POINTER),y
 	iny
 	bne c_loop
 
 	inc POINTER_H
 	ldx POINTER_H
 	cpx #$06
 	bne c_loop
 
 done:	clc		; repeat
 	bcc draw
 
 
 ; these two tables contain the high and low bytes
 ; of the addresses of the start of each row
 
 table_high:
 dcb $02,$02,$02,$02,$02,$02,$02,$02
 dcb $03,$03,$03,$03,$03,$03,$03,$03
 dcb $04,$04,$04,$04,$04,$04,$04,$04
 dcb $05,$05,$05,$05,$05,$05,$05,$05,
 
 table_low:
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 dcb $00,$20,$40,$60,$80,$a0,$c0,$e0
 
 ; help message on character screen
 
 help:
 dcb "A","r","r","o","w",32,"k","e","y","s"
 dcb 32,"d","r","a","w",32,"/",32,"'","C","'"
 dcb 32,"k","e","y",32,"c","l","e","a","r","s"
 dcb 00

Additional Examples

Additional examples, as well as the source code for the emulator's ROM routines, are in a repository at https://github.com/ctyler/6502js-code