diff --git a/apple1/wozmon.s b/apple1/wozmon.s index 853b2ac..06ca5c6 100644 --- a/apple1/wozmon.s +++ b/apple1/wozmon.s @@ -1,259 +1,158 @@ -;------------------------------------------------------------------------- -; -; The WOZ Monitor for the Apple 1 -; Written by Steve Wozniak 1976 -; -;------------------------------------------------------------------------- +; Wozniak Apple1 Monitor -; .CR 6502 -; .OR $FF00 -; .TF WOZMON.HEX,HEX,8 +.org $FF00 ; Rom Start -;------------------------------------------------------------------------- -; Memory declaration -;------------------------------------------------------------------------- +;******* Hardware 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 +DSP = $D012 ; Video I/O +DSPCR = $D013 -IN = $0200,$027F ; Input buffer +KBD = $D010 ; Keyboard I/O +KBDCR = $D011 -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 +;********* Zero Page Variables ********* -; 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. +XAML = $24 +XAMH = $25 +STL = $26 +STH = $27 +L = $28 +H = $29 +YSAV = $2A +MODE = $2B -;------------------------------------------------------------------------- -; Constants -;------------------------------------------------------------------------- +;******** $200-$27F Text Buffer ********* -BS = $DF ; Backspace key, arrow left key -CR = $8D ; Carriage Return -ESC = $9B ; ESC key -PROMPT = $DC ; Prompt character +IN = $0200 -;------------------------------------------------------------------------- -; 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. -;------------------------------------------------------------------------- +;******** Listing ************* -RESET: CLD ; Clear decimal arithmetic mode +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. + 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 + STY DSPCR ; postitive edge sense/output mode. +NOTCR: CMP #$DF ; "<-"? + BEQ BACKSAPCE ; Yes. + CMP #$9B ; ESC? + BEQ ESCAPE ; Yes. + INY ; Advance text index. + BPL NEXTCHAR ; Auto ESC if > 127. +ESCAPE: LDA #$DC ; "\". + JSR ECHO ; Output it. +GETLINE: LDA #$8D ; CR. + JSR ECHO ; Output it. + LDY #$01 ; Initiallize text index. +BACKSPACE: DEY ; Backup text index. + BMI GETLINE ; Beyond start of line, reinitialize +NEXTCHAR: LDA KBDCR ; Key ready? + BPL NEXTCHAR ; Loop until ready. + LDA KBD ; Load character. B7 shoul be '1' + 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 A ; Leaves $7B if setting STOR mode. +SETMODE: STA MODE ; $00 = XAM, $7B = STOR, $A3 = BLOK XAM +BLSKIP: INY ; Advance text index. +NEXTITEM: LDA IN,Y ; Get character. + CMP #$8D ; CR? + BEQ GETLINE ; Yes, done this line. + CMP #$A3 ; "."? + BCC BLSKIP ; Skip delimiter. + BEQ SETMODE ; Set BLOCK XAM mode. + CMP #$BA ; ":"? + BEQ SETSTOR ; Yes, set STOR mode. + CMP #$D2 ; "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 NOHEX ; No, character not hex. +DIG: ASL A + ASL A ; Hex digit to MSD of A. + ASL A ; + ASL A ; + LDX #$04 ; Shift count. +HEXSHIFT: ASL A ; Hex digit left, MSDB 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 #$8D ; 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 #$BA ; ":". + JSR ECHO ; Output it. +PRDATA: LDA #$A0 ; 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 ; Comapre '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 A + LSR A + LSR A ; MSD to LSD position. + LSR A + JSR PRHEX ; Output hex digit. + PLA ; Restore A. +PRHEX: AND #$0F ; Make LSD for hex print. + ORA #$B0 ; 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. -; 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 A ; 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 A - ASL A ; Hex digit to MSD of A - ASL A - ASL A - - LDX #4 ; Shift count -HEXSHIFT: ASL A ; 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 A - LSR A - LSR A ; MSD to LSD position - LSR A - 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 \ No newline at end of file +.byte $0000 +.byte $F000 NMI +.byte $FF00 RESET +.byte $0000 IRQ