applesoft-lite/wozmon.s

184 lines
4.8 KiB
ArmAsm

; Apple I Monitor ROM
; Steve Wozniak
; 1976
; --------------------------------------------------------
.setcpu "6502"
.segment "MONITOR"
.export ECHO
; --------------------------------------------------------
; Zero page variables
XAML := $24
XAMH := $25
STL := $26
STH := $27
L := $28
H := $29
YSAV := $2A
MODE := $2B
; I/O locations
IN := $0200 ; Input buffer is $0200 to $027F
KBD := $D010 ; Keyboard data
DSP := $D012 ; Display data
KBDCR := $D011 ; Keyboard control register
DSPCR := $D013 ; Display control register
; ASCII codes
CR = $0D | $80 ; Carriage return
ESC = $1B | $80 ; Escape
SLASH = '\' | $80 ; \
UNDERSC = '_' | $80 ; Underscore (acts as backspace)
DOT = '.' | $80 ; .
COLON = ':' | $80 ; :
R = 'R' | $80 ; "R"
SPACE = ' ' | $80 ; blank
ZERO = '0' | $80 ; "0"
; --------------------------------------------------------
RESET: cld ; Clear decimal arithmetic mode
cli
ldy #$7F ; Mask for DSP data direction register
sty DSP ; Set it up
lda #$A7 ; KBD and DSP control register mask
sta KBDCR ; Enable interrupts, set CA1, CB1 for
sta DSPCR ; positive edge sense/output mode
NOTCR: cmp #UNDERSC ; Backspace?
beq BACKSPACE ; Yes
cmp #ESC ; ESC?
beq ESCAPE ; Yes
iny ; Advance text index
bpl NEXTCHAR ; Auto ESC if > 127
ESCAPE: lda #SLASH ; "\"
jsr ECHO ; Output it
GETLINE:
lda #CR ; CR
jsr ECHO ; Output it
ldy #$01 ; Initialize text index
BACKSPACE:
dey ; Back up text index
bmi GETLINE ; Beyond start of line, reinitialize
NEXTCHAR:
lda KBDCR ; Key ready?
bpl NEXTCHAR ; Loop until ready
lda KBD ; Load character. B7 should be '1'
sta IN,y ; Add to text buffer
jsr ECHO ; Display character
cmp #CR ; CR?
bne NOTCR ; No
ldy #$FF ; Reset text index
lda #$00 ; For XAM mode
tax ; 0 -> x
SETSTOR:
asl ; Leaves $7B if setting STOR mode
SETMODE:
sta MODE ; $00 = XAM, $7B = STOR, $AE = BLOCK XAM
BLSKIP: iny ; Advance text index
NEXTITEM:
lda IN,y ; Get character
cmp #CR ; CR?
beq GETLINE ; Yes, done this line
cmp #DOT ; "."?
bcc BLSKIP ; Skip delimiter
beq SETMODE ; Set BLOCK XAM mode
cmp #COLON ; ":"?
beq SETSTOR ; Yes, set STOR mode
cmp #R ; "R"?
beq RUN ; Yes, run user program
stx L ; $00 -> L
stx H ; and H
sty YSAV ; Save Y for comparison
NEXTHEX:
lda IN,y ; Get character for hex test
eor #$B0 ; Map digits to $0-9
cmp #$0A ; Digit?
bcc DIG ; Yes
adc #$88 ; Map letter "A"-"F" to $FA-FF
cmp #$FA ; Hex letter?
bcc NOTHEX ; No, character not hext
DIG: asl
asl ; Hex digit to MSD of A
asl
asl
ldx #$04 ; Shift count
HEXSHIFT:
asl ; Hex digit left, MSB to carry
rol L ; Rotate into LSD
rol H ; Rotate into MSD's
dex ; Done 4 shifts?
bne HEXSHIFT ; No, loop
iny ; Advance text index
bne NEXTHEX ; Always taken. Check next character for hex
NOTHEX:
cpy YSAV ; Check if L, H empty (no hex digits)
beq ESCAPE ; Yes, generate ESC sequence
bit MODE ; Test MODE byte
bvc NOTSTOR ; B6 = 0 for STOR, 1 for XAM and BLOCK XAM
lda L ; LSD's of hex data
sta (STL,x) ; Store at current 'store index'
inc STL ; Increment store index
bne NEXTITEM ; Get next item (no carry)
inc STH ; Add carry to 'store index' high order
TONEXTITEM:
jmp NEXTITEM ; Get next command item
RUN: jmp (XAML) ; Run at current XAM index
NOTSTOR:
bmi XAMNEXT ; B7=0 for XAM, 1 for BLOCK XAM
ldx #$02 ; Byte count
SETADR: lda L-1,x ; Copy hex data to
sta STL-1,x ; 'store index'
sta XAML-1,x ; And to 'XAM index'
dex ; Next of 2 bytes
bne SETADR ; Loop unless X=0
NXTPRNT:
bne PRDATA ; NE means no address to print
lda #CR ; CR
jsr ECHO ; Output it
lda XAMH ; 'Examine index' high-order byte
jsr PRBYTE ; Output it in hex format
lda XAML ; Low-order 'examine index' byte
jsr PRBYTE ; Output it in hex format
lda #COLON ; ":"
jsr ECHO ; Output it
PRDATA: lda #SPACE ; Blank
jsr ECHO ; Output it
lda (XAML,x) ; Get data byte at 'examine index'
jsr PRBYTE ; Output it in hex format
XAMNEXT:
stx MODE ; 0 -> MODE (XAM mode)
lda XAML
cmp L ; Compare 'examine index' to hex data
lda XAMH
sbc H
bcs TONEXTITEM ; Not less, so no more data to output
inc XAML
bne MOD8CHK ; Increment 'examine index'
inc XAMH
MOD8CHK:
lda XAML ; Check low-order 'examine index' byte
and #$07 ; For MOD 8 = 0
bpl NXTPRNT ; Always taken
PRBYTE: pha ; Save A for LSD
lsr
lsr
lsr ; MSD to LSD position
lsr
jsr PRHEX ; Output hex digit
pla ; Restore A
PRHEX: and #$0F ; Mask LSD for hex print
ora #ZERO ; Add "0"
cmp #$BA ; Digit?
bcc ECHO ; Yes, output it
adc #$06 ; Add offset for letter
ECHO: bit DSP ; DA bit (B7) cleared yet?
bmi ECHO ; No, wait for display
sta DSP ; Output character. Sets DA.
rts ; Return
; --------------------------------------------------------
.word $0000 ; (unused)
.addr $0F00 ; (NMI vector)
.addr RESET ; (RESET vector)
.addr $0000 ; (IRQ vector)