APPLE-1-ReplicaDue/ASM/woz_monitor_dasm.asm

259 lines
11 KiB
NASM

; dasm woz_monitor_masm.asm -orom.o -lrom.lst -srom.sym
;-------------------------------------------------------------------------
;
; The WOZ Monitor for the Apple 1
; Written by Steve Wozniak 1976
;
;-------------------------------------------------------------------------
processor 6502
org $FF00
;-------------------------------------------------------------------------
; Memory declaration
;-------------------------------------------------------------------------
XAML equ $24 ;Last "opened" location Low
XAMH equ $25 ;Last "opened" location High
STL equ $26 ;Store address Low
STH equ $27 ;Store address High
L equ $28 ;Hex value parsing Low
H equ $29 ;Hex value parsing High
YSAV equ $2A ;Used to see if hex value is given
MODE equ $2B ;$00=XAM, $7F=STOR, $AE=BLOCK XAM
IN equ $0200,$027F ;Input buffer
KBD equ $D010 ;PIA.A keyboard input
KBDCR equ $D011 ;PIA.A keyboard control register
DSP equ $D012 ;PIA.B display output register
DSPCR equ $D013 ;PIA.B display control register
; KBD b7..b0 are inputs, b6..b0 is ASCII input, b7 is constant high
; Programmed to respond to low to high KBD strobe
; DSP b6..b0 are outputs, b7 is input
; CB2 goes low when data is written, returns high when CB1 goes high
; Interrupts are enabled, though not used. KBD can be jumpered to IRQ,
; whereas DSP can be jumpered to NMI.
;-------------------------------------------------------------------------
; Constants
;-------------------------------------------------------------------------
BS equ $DF ;Backspace key, arrow left key
CR equ $8D ;Carriage Return
ESC equ $9B ;ESC key
PROMPT equ $5C ;Prompt character \
;-------------------------------------------------------------------------
; Let's get started
;
; Remark the RESET routine is only to be entered by asserting the RESET
; line of the system. This ensures that the data direction registers
; are selected.
;-------------------------------------------------------------------------
RESET cld ;Clear decimal arithmetic mode
cli
ldy #%01111111 ;Mask for DSP data direction reg
sty DSP ;(DDR mode is assumed after reset)
lda #%10100111 ;KBD and DSP control register mask
sta KBDCR ;Enable interrupts, set CA1, CB1 for
sta DSPCR ;positive edge sense/output mode.
; Program falls through to the GETLINE routine to save some program bytes
; Please note that Y still holds $7F, which will cause an automatic Escape
;-------------------------------------------------------------------------
; The GETLINE process
;-------------------------------------------------------------------------
NOTCR cmp #BS ;Backspace key?
beq BACKSPACE ;Yes
cmp #ESC ;ESC?
beq ESCAPE ;Yes
iny ;Advance text index
bpl NEXTCHAR ;Auto ESC if line longer than 127
ESCAPE lda #PROMPT ;Print prompt character
jsr ECHO ;Output it.
GETLINE lda #CR ;Send CR
jsr ECHO
ldy #0+1 ;Start a new input line
BACKSPACE dey ;Backup text index
bmi GETLINE ;Oops, line's empty, reinitialize
NEXTCHAR lda KBDCR ;Wait for key press
bpl NEXTCHAR ;No key yet!
lda KBD ;Load character. B7 should be '1'
sta IN,Y ;Add to text buffer
jsr ECHO ;Display character
cmp #CR
bne NOTCR ;It's not CR!
; Line received, now let's parse it
ldy #-1 ;Reset text index
lda #0 ;Default mode is XAM
tax ;X=0
SETSTOR asl ;Leaves $7B if setting STOR mode
SETMODE sta MODE ;Set mode flags
BLSKIP iny ;Advance text index
NEXTITEM lda IN,Y ;Get character
cmp #CR
beq GETLINE ;We're done if it's CR!
cmp #"."
bcc BLSKIP ;Ignore everything below "."!
beq SETMODE ;Set BLOCK XAM mode ("." = $AE)
cmp #":"
beq SETSTOR ;Set STOR mode! $BA will become $7B
cmp #"R"
beq RUN ;Run the program! Forget the rest
stx L ;Clear input value (X=0)
stx H
sty YSAV ;Save Y for comparison
; Here we're trying to parse a new hex value
NEXTHEX lda IN,Y ;Get character for hex test
eor #$B0 ;Map digits to 0-9
cmp #9+1 ;Is it a decimal digit?
bcc DIG ;Yes!
adc #$88 ;Map letter "A"-"F" to $FA-FF
cmp #$FA ;Hex letter?
bcc NOTHEX ;No! Character not hex
DIG asl
asl ;Hex digit to MSD of A
asl
asl
ldx #4 ;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
NOTHEX cpy YSAV ;Was at least 1 hex digit given?
beq ESCAPE ;No! Ignore all, start from scratch
bit MODE ;Test MODE byte
bvc NOTSTOR ;B6=0 is STOR, 1 is XAM or BLOCK XAM
; STOR mode, save LSD of new hex byte
lda L ;LSD's of hex data
sta (STL,X) ;Store current 'store index'(X=0)
inc STL ;Increment store index.
bne NEXTITEM ;No carry!
inc STH ;Add carry to 'store index' high
TONEXTITEM jmp NEXTITEM ;Get next command item.
;-------------------------------------------------------------------------
; RUN user's program from last opened location
;-------------------------------------------------------------------------
RUN jmp (XAML) ;Run user's program
;-------------------------------------------------------------------------
; We're not in Store mode
;-------------------------------------------------------------------------
NOTSTOR bmi XAMNEXT ;B7 = 0 for XAM, 1 for BLOCK XAM
; We're in XAM mode now
ldx #2 ;Copy 2 bytes
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
; Print address and data from this address, fall through next bne.
NXTPRNT bne PRDATA ;NE means no address to print
lda #CR ;Print CR first
jsr ECHO
lda XAMH ;Output high-order byte of address
jsr PRBYTE
lda XAML ;Output low-order byte of address
jsr PRBYTE
lda #":" ;Print colon
jsr ECHO
PRDATA lda #" " ;Print space
jsr ECHO
lda (XAML,X) ;Get data from address (X=0)
jsr PRBYTE ;Output it in hex format
XAMNEXT stx MODE ;0 -> MODE (XAM mode).
lda XAML ;See if there's more to print
cmp L
lda XAMH
sbc H
bcs TONEXTITEM ;Not less! No more data to output
inc XAML ;Increment 'examine index'
bne MOD8CHK ;No carry!
inc XAMH
MOD8CHK lda XAML ;If address MOD 8 = 0 start new line
and #%00000111
bpl NXTPRNT ;Always taken.
;-------------------------------------------------------------------------
; Subroutine to print a byte in A in hex form (destructive)
;-------------------------------------------------------------------------
PRBYTE pha ;Save A for LSD
lsr
lsr
lsr ;MSD to LSD position
lsr
jsr PRHEX ;Output hex digit
pla ;Restore A
; Fall through to print hex routine
;-------------------------------------------------------------------------
; Subroutine to print a hexadecimal digit
;-------------------------------------------------------------------------
PRHEX and #%00001111 ;Mask LSD for hex print
ora #"0" ;Add "0"
cmp #"9"+1 ;Is it a decimal digit?
bcc ECHO ;Yes! output it
adc #6 ;Add offset for letter A-F
; Fall through to print routine
;-------------------------------------------------------------------------
; Subroutine to print a character to the terminal
;-------------------------------------------------------------------------
ECHO bit DSP ;DA bit (B7) cleared yet?
bmi ECHO ;No! Wait for display ready
sta DSP ;Output character. Sets DA
rts
;-------------------------------------------------------------------------
; Vector area
;-------------------------------------------------------------------------
dc.w $0000 ;Unused, what a pity
NMI_VEC dc.w $0F00 ;NMI vector
RESET_VEC dc.w RESET ;RESET vector
IRQ_VEC dc.w $0000 ;IRQ vector
;-------------------------------------------------------------------------