;------------------------------------------------------------------------- ; ; 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 "\\" ;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 #%0111.1111 ;Mask for DSP data direction reg STY DSP ; (DDR mode is assumed after reset) LDA #%1010.0111 ;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 #%0000.0111 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 #%0000.1111 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 ;------------------------------------------------------------------------- .DA $0000 Unused, what a pity NMI_VEC .DA $0F00 NMI vector RESET_VEC .DA RESET RESET vector IRQ_VEC .DA $0000 IRQ vector ;------------------------------------------------------------------------- .LI OFF