mirror of https://github.com/smartykit/apple1.git
155 lines
7.2 KiB
NASM
155 lines
7.2 KiB
NASM
|
; The WOZ Monitor for the Apple 1
|
|||
|
; Written by Steve Wozniak in 1976
|
|||
|
|
|||
|
|
|||
|
; Page 0 Variables
|
|||
|
|
|||
|
XAML = $24 ; Last "opened" location Low
|
|||
|
XAMH = $25 ; Last "opened" location High
|
|||
|
STL = $26 ; Store address Low
|
|||
|
STH = $27 ; Store address High
|
|||
|
L = $28 ; Hex value parsing Low
|
|||
|
H = $29 ; Hex value parsing High
|
|||
|
YSAV = $2A ; Used to see if hex value is given
|
|||
|
MODE = $2B ; $00=XAM, $7F=STOR, $AE=BLOCK XAM
|
|||
|
|
|||
|
|
|||
|
; Other Variables
|
|||
|
|
|||
|
IN = $0200 ; Input buffer to $027F
|
|||
|
KBD = $D010 ; PIA.A keyboard input
|
|||
|
KBDCR = $D011 ; PIA.A keyboard control register
|
|||
|
DSP = $D012 ; PIA.B display output register
|
|||
|
DSPCR = $D013 ; PIA.B display control register
|
|||
|
|
|||
|
.org $FF00
|
|||
|
.export RESET
|
|||
|
|
|||
|
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 #'_'+$80 ; "_"?
|
|||
|
BEQ BACKSPACE ; Yes.
|
|||
|
CMP #$9B ; ESC?
|
|||
|
BEQ ESCAPE ; Yes.
|
|||
|
INY ; Advance text index.
|
|||
|
BPL NEXTCHAR ; Auto ESC if > 127.
|
|||
|
ESCAPE: LDA #'\'+$80 ; "\".
|
|||
|
JSR ECHO ; Output it.
|
|||
|
GETLINE: LDA #$8D ; 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 <20>1<EFBFBD>.
|
|||
|
STA IN,Y ; Add to text buffer.
|
|||
|
JSR ECHO ; Display character.
|
|||
|
CMP #$8D ; 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=BLOK XAM
|
|||
|
BLSKIP: INY ; Advance text index.
|
|||
|
NEXTITEM: LDA IN,Y ; Get character.
|
|||
|
CMP #$8D ; CR?
|
|||
|
BEQ GETLINE ; Yes, done this line.
|
|||
|
CMP #'.'+$80 ; "."?
|
|||
|
BCC BLSKIP ; Skip delimiter.
|
|||
|
BEQ SETMODE ; Yes. Set STOR mode.
|
|||
|
CMP #':'+$80 ; ":"?
|
|||
|
BEQ SETSTOR ; Yes. Set STOR mode.
|
|||
|
CMP #'R'+$80 ; "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 hex.
|
|||
|
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<53>s.
|
|||
|
DEX ; Done 4 shifts?
|
|||
|
BNE HEXSHIFT ; No, loop.
|
|||
|
INY ; Advance text index.
|
|||
|
BNE NEXTHEX ; Always taken. Check next char 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 STOR 1 for XAM & BLOCK XAM
|
|||
|
LDA L ; LSD<53>s of hex data.
|
|||
|
STA (STL,X) ; Store at current <20>store index<65>.
|
|||
|
INC STL ; Increment store index.
|
|||
|
BNE NEXTITEM ; Get next item. (no carry).
|
|||
|
INC STH ; Add carry to <20>store index<65> 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 ; <20>store index<65>.
|
|||
|
STA XAML-1,X ; And to <20>XAM index<65>.
|
|||
|
DEX ; Next of 2 bytes.
|
|||
|
BNE SETADR ; Loop unless X=0.
|
|||
|
NXTPRNT: BNE PRDATA ; NE means no address to print.
|
|||
|
LDA #$8D ; CR.
|
|||
|
JSR ECHO ; Output it.
|
|||
|
LDA XAMH ; <20>Examine index<65> high-order byte.
|
|||
|
JSR PRBYTE ; Output it in hex format.
|
|||
|
LDA XAML ; Low-order <20>examine index<65> byte.
|
|||
|
JSR PRBYTE ; Output it in hex format.
|
|||
|
LDA #':'+$80 ; ":".
|
|||
|
JSR ECHO ; Output it.
|
|||
|
PRDATA: LDA #$A0 ; Blank.
|
|||
|
JSR ECHO ; Output it.
|
|||
|
LDA (XAML,X) ; Get data byte at <20>examine index<65>.
|
|||
|
JSR PRBYTE ; Output it in hex format.
|
|||
|
XAMNEXT: STX MODE ; 0->MODE (XAM mode).
|
|||
|
LDA XAML
|
|||
|
CMP L ; Compare <20>examine index<65> to hex data.
|
|||
|
LDA XAMH
|
|||
|
SBC H
|
|||
|
BCS TONEXTITEM ; Not less, so no more data to output.
|
|||
|
INC XAML
|
|||
|
BNE MOD8CHK ; Increment <20>examine index<65>.
|
|||
|
INC XAMH
|
|||
|
MOD8CHK: LDA XAML ; Check low-order <20>examine index<65> 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 #'0'+$80 ; Add "0".
|
|||
|
CMP #$BA ; Digit?
|
|||
|
BCC ECHO ; Yes, output it.
|
|||
|
ADC #$06 ; Add offset for letter.
|
|||
|
ECHO: BIT DSP ; bit (B7) cleared yet?
|
|||
|
BMI ECHO ; No, wait for display.
|
|||
|
STA DSP ; Output character. Sets DA.
|
|||
|
RTS ; Return.
|
|||
|
|
|||
|
NMI: RTI ; simple Interrupt Service Routine(ISR)
|
|||
|
IRQ: RTI ; simple Interrupt Service Routine(ISR)
|