gigatron/rom/Apps/Apple-1/a1basic/xwoz.txt
2025-01-28 19:17:01 +03:00

658 lines
26 KiB
Plaintext

\;======================================
\; ** ENHANCED WOZMON EXTENSION **
\; MINI-ASSEMBLER AND DISASSEMBLER
\; FOR THE APPLE 1 COMPUTER
\; BASED ON THE CODE OF STEVE WOZNIAK
\; AND ALLEN BAUM, 1976/1977
\; MANUALLY AND LOVINGLY ADAPTED BY THE
\; HAND OF MICHAEL T. BARRY, 2020
\; MODIFICATIONS MADE IN 2020 ARE
\; FREE TO USE WITH ATTRIBUTION
\; <<< 6502 FOREVER!! >>>
\;======================================
\XAML EQU $14
\XAMH EQU $15
\STL EQU $16
\STH EQU $17
\L EQU $18 ;($35 ON A2)
\H EQU $19
\YSAV EQU $1A ;($34 ON A2)
\MODE EQU $1B ;($31 ON A2)
\;
\FORMAT EQU $05
\LENGTH EQU $06
\FMT EQU $07
\LMNEM EQU $08
\RMNEM EQU $09
\PCL EQU $0A
\PCH EQU $0B
\A1L EQU $0C
\A1H EQU $0D
\A2L EQU $0E
\A2H EQU $0F
\A4L EQU $12
\A4H EQU $13
\;
\IN EQU $0200
\;
\KBD EQU $D010
\KBDCR EQU $D011
\DSP EQU $D012
\DSPCR EQU $D013
\
\ESCAPE EQU $3F1A
\;
\ ORG $3BAE
\;======================================
\LIST: ; ($FE5E ON A2)
3BAE:A9 14 \ LDA #20 ; DISASSEM 20 INSTR
\LIST1:
3BB0:48 \ PHA ; STACK LOOP COUNTER
3BB1:20 21 3D \ JSR INSTDSP ; DISASSEM ONE INSTR
3BB4:20 E5 3D \ JSR PCADJ ; UPDATE VIRTUAL PC
3BB7:85 0A \ STA PCL ;
3BB9:84 0B \ STY PCH ;
3BBB:68 \ PLA ; UPDATE LOOP COUNTER
3BBC:38 \ SEC ;
3BBD:E9 01 \ SBC #1 ;
3BBF:D0 EF \ BNE LIST1 ; LOOP FOR 20 INSTRS
\CMDLINE:
3BC1:20 AC 3D \ JSR GETLNZ ; INPUT A FRESH LINE
3BC4:8A \ TXA ; NULL INPUT?
3BC5:D0 03 \ BNE CMDLIN2 ;
3BC7:4C 1A 3F \ JMP ESCAPE ; YES: BACK TO WOZMON
\CMDLIN2:
3BCA:A0 00 \ LDY #0 ; START AT 1ST CHAR
3BCC:20 F4 3D \ JSR GETNUM ; PARSE OPTIONAL ADDR
3BCF:48 \ PHA ;
3BD0:8A \ TXA ; EMPTY ADDR FIELD?
3BD1:F0 07 \ BEQ CMDLIN3 ; YES: USE DEFAULT PC
\A1PCLP:
3BD3:B5 0C \ LDA A1L,X ; ASSUMES X=1
3BD5:95 0A \ STA PCL,X ; COPY FROM A1 TO PC
3BD7:CA \ DEX ;
3BD8:10 F9 \ BPL A1PCLP ;
\CMDLIN3:
3BDA:68 \ PLA ;
3BDB:C9 05 \ CMP #$05 ; 'L' COMMAND?
3BDD:F0 CF \ BEQ LIST ; YES: DISASSEMBLE
3BDF:C9 99 \ CMP #$99 ; ' ' COMMAND?
3BE1:F0 04 \ BEQ ASSEM ; YES: ASM AT CURR PC
3BE3:C9 93 \ CMP #$93 ; ':' COMMAND?
3BE5:D0 76 \ BNE FORM8A ; NO: ERROR
\ASSEM:
3BE7:A9 03 \ LDA #3 ; # OF CHARS IN MNEM
3BE9:85 0D \ STA A1H ;
\NXTMN:
3BEB:20 D4 3D \ JSR GETNSP ; GET A MNEM CHAR
\NXTM:
3BEE:0A \ ASL ;
3BEF:E9 BE \ SBC #$BE ; SUBTRACT OFFSET
3BF1:C9 C2 \ CMP #$C2 ; LEGAL CHAR?
3BF3:90 68 \ BCC FORM8A ; NO
3BF5:0A \ ASL ; COMPRESS/LT-JUSTIFY
3BF6:0A \ ASL ;
3BF7:A2 04 \ LDX #4 ;
\NXTM2:
3BF9:0A \ ASL ; DO 5 24-BIT SHIFTS
3BFA:26 12 \ ROL A4L ;
3BFC:26 13 \ ROL A4H ;
3BFE:CA \ DEX ;
3BFF:10 F8 \ BPL NXTM2 ;
3C01:C6 0D \ DEC A1H ; DONE WITH 3 CHARS?
3C03:F0 F4 \ BEQ NXTM2 ; YES: ONE LAST SHIFT
3C05:10 E4 \ BPL NXTMN ; NO
; \FORM1:
3C07:A2 05 \ LDX #5 ; 5 CHARS IN ADR MODE
; \FORM2:
3C09:20 D4 3D \ JSR GETNSP ; GET 1ST CHR OF ADDR
3C0C:84 1A \ STY YSAV ;
3C0E:DD 74 3E \ CMP CHR1,X ; 1ST CHR MATCH PATT?
3C11:D0 13 \ BNE FORM3 ; NO
3C13:20 D4 3D \ JSR GETNSP ; YES: GET 2ND CHAR
3C16:DD 7A 3E \ CMP CHR2,X ; MATCHES 2ND HALF?
3C19:F0 0D \ BEQ FORM5 ; YES
3C1B:BD 7A 3E \ LDA CHR2,X ; NO: IS 2ND HALF 0?
3C1E:F0 07 \ BEQ FORM4 ; YES
3C20:C9 A4 \ CMP #$A4 ; NO: 2ND HALF OPT?
3C22:F0 03 \ BEQ FORM4 ; YES
3C24:A4 1A \ LDY YSAV ;
\FORM3:
3C26:18 \ CLC ; CLEAR BIT-NO MATCH
\FORM4:
3C27:88 \ DEY ; BACK UP 1 CHAR
\FORM5:
3C28:26 07 \ ROL FMT ; FORM FORMAT BYTE
3C2A:E0 03 \ CPX #3 ; TIME TO CHECK ADDR?
3C2C:D0 0D \ BNE FORM7 ; NO
3C2E:20 F4 3D \ JSR GETNUM ; YES: PARSE IT
3C31:A5 0F \ LDA A2H ;
3C33:F0 01 \ BEQ FORM6 ; HIGH-ORDER BYTE 0?
3C35:E8 \ INX ; NO: INCR FOR 2-BYTE
\FORM6:
3C36:86 18 \ STX L ; STORE LENGTH
3C38:A2 03 \ LDX #3 ; RELOAD FMT INDEX
3C3A:88 \ DEY ; BACK UP 1 CHAR
\FORM7:
3C3B:86 0D \ STX A1H ; SAVE INDEX
3C3D:CA \ DEX ; DONE W/FMT CHECK?
3C3E:10 C9 \ BPL FORM2 ; NO
3C40:A5 07 \ LDA FMT ; YES: PUT LENGTH
3C42:0A \ ASL ; IN LOW BITS
3C43:0A \ ASL ;
3C44:05 18 \ ORA L ;
3C46:C9 20 \ CMP #$20 ;
3C48:B0 06 \ BCS FORM8 ;
3C4A:A6 18 \ LDX L ;
3C4C:F0 02 \ BEQ FORM8 ;
3C4E:09 80 \ ORA #$80 ;
\FORM8:
3C50:85 07 \ STA FMT ;
3C52:84 1A \ STY YSAV ;
3C54:B9 00 02 \ LDA IN,Y ; GET NEXT NONBLANK
3C57:C9 BB \ CMP #";" ; START OF COMMENT?
3C59:F0 04 \ BEQ TRYNEXT ; YES
3C5B:C9 8D \ CMP #CR ; CR?
\FORM8A:
3C5D:D0 2C \ BNE ERR2 ; NO: ERROR
\TRYNEXT: ; ($F55C ON A2)
3C5F:A5 0D \ LDA A1H ; GET TRIAL OPCODE
3C61:20 DB 3C \ JSR INSDS2 ; GET FMT+LEN FOR IT
3C64:AA \ TAX ;
3C65:BD C0 3E \ LDA MNEMR,X ; GET LOWER MNEM BYTE
3C68:C5 12 \ CMP A4L ; MATCH?
3C6A:D0 13 \ BNE NEXTOP ; NO: TRY NEXT OPCODE
3C6C:BD 80 3E \ LDA MNEML,X ; GET UPPER MNEM BYTE
3C6F:C5 13 \ CMP A4H ; MATCH?
3C71:D0 0C \ BNE NEXTOP ; NO: TRY NEXT OPCODE
3C73:A5 07 \ LDA FMT ;
3C75:A4 05 \ LDY FORMAT ; GET TRIAL FORMAT
3C77:C0 9D \ CPY #$9D ; IS IT RELATIVE?
3C79:F0 20 \ BEQ REL ; YES
3C7B:C5 05 \ CMP FORMAT ; SAME FORMAT?
3C7D:F0 37 \ BEQ FINDOP ; YES
\NEXTOP:
3C7F:C6 0D \ DEC A1H ; NO: TRY NEXT OPCODE
3C81:D0 DC \ BNE TRYNEXT ;
3C83:E6 07 \ INC FMT ; NO MORE: TRY LEN=2
3C85:C6 18 \ DEC L ; WAS L=2 ALREADY?
3C87:F0 D6 \ BEQ TRYNEXT ; NO: KEEP TRYING
\ERR:
3C89:A4 1A \ LDY YSAV ; YES: UNREC. INST
\ERR2:
3C8B:98 \ TYA ;
3C8C:AA \ TAX ;
3C8D:20 E0 3D \ JSR CROUT ;
3C90:20 CB 3D \ JSR PRXBL ; PRINT '^' BELOW THE
3C93:A9 DE \ LDA #"^" ; LAST PARSED CHAR
3C95:20 EF 3F \ JSR ECHO ; TO SHOW ERR POSN
3C98:4C C1 3B \ JMP CMDLINE ; NEXT COMMAND LINE
\REL:
3C9B:E9 81 \ SBC #$81 ; YES: IS FMT COMPAT
3C9D:4A \ LSR ; W/RELATIVE MODE?
3C9E:D0 E9 \ BNE ERR ; NO: ERROR OUT
3CA0:A4 0F \ LDY A2H ;
3CA2:A6 0E \ LDX A2L ; DOUBLE DECREMENT
3CA4:D0 01 \ BNE REL2 ;
3CA6:88 \ DEY ;
\REL2:
3CA7:CA \ DEX ;
3CA8:8A \ TXA ;
3CA9:18 \ CLC ;
3CAA:E5 0A \ SBC PCL ; CALC ADDR-PC-2
3CAC:85 0E \ STA A2L ;
3CAE:10 01 \ BPL REL3 ;
3CB0:C8 \ INY ;
\REL3:
3CB1:98 \ TYA ;
3CB2:E5 0B \ SBC PCH ;
3CB4:D0 D3 \ BNE ERR ; ERROR IF TOO FAR
\FINDOP:
3CB6:A4 06 \ LDY LENGTH ;
\FNDOP2:
3CB8:B9 0D 00 \ LDA A1H,Y ; MOVE INST TO (PC)
3CBB:91 0A \ STA (PCL),Y ;
3CBD:88 \ DEY ;
3CBE:10 F8 \ BPL FNDOP2 ;
3CC0:A9 01 \ LDA #1 ; DISASSEMBLE RESULT
3CC2:4C B0 3B \ JMP LIST1 ; BACK TO CMD LINE
\;= 92 ================================
\INSDS1: ; ($F882 ON A2)
3CC5:A6 0A \ LDX PCL ; PRINT PCL,H
3CC7:A4 0B \ LDY PCH ;
3CC9:20 E0 3D \ JSR CROUT ;
3CCC:20 91 3D \ JSR PRNTYX ;
3CCF:A0 00 \ LDY #0 ;
3CD1:A9 AD \ LDA #"-" ; PRINT '-'
3CD3:20 EF 3F \ JSR ECHO ;
3CD6:20 C9 3D \ JSR PR3BL ; PRINT 3 BLANKS
3CD9:A1 0A \ LDA (PCL,X) ; GET OPCODE
\INSDS2: ; ($F88E ON A2)
3CDB:A8 \ TAY ;
3CDC:4A \ LSR ; EVEN/ODD TEST
3CDD:90 0B \ BCC IEVEN ;
3CDF:4A \ LSR ; BIT 1 TEST
3CE0:09 80 \ ORA #$80 ; (BECAUSE ROR BUG)
3CE2:B0 15 \ BCS INVLD ; XXXXXX11 INVALID OP
3CE4:C9 A2 \ CMP #$A2 ;
3CE6:F0 11 \ BEQ INVLD ; OPCODE $89 INVALID
3CE8:29 87 \ AND #$87 ; MASK BITS
\IEVEN: ; ($F89B ON A2)
3CEA:4A \ LSR ; LSB->C FOR L/R TEST
3CEB:AA \ TAX ;
3CEC:BD 22 3E \ LDA FMT1,X ; GET FMT INDEX BYTE
3CEF:90 04 \ BCC RTMSKZ ; R/L H-BYTE ON CARRY
3CF1:4A \ LSR ;
3CF2:4A \ LSR ;
3CF3:4A \ LSR ;
3CF4:4A \ LSR ;
\RTMSKZ:
3CF5:29 0F \ AND #$0F ;
3CF7:D0 04 \ BNE GETFMT ;
\INVLD:
3CF9:A0 80 \ LDY #$80 ; SUB $80 FOR INVALID
3CFB:A9 00 \ LDA #0 ; SET PRINT FMT INDEX
\GETFMT: ; ($F8A9 ON A2)
3CFD:AA \ TAX ;
3CFE:BD 66 3E \ LDA FMT2,X ; INDX INTO FMT TABLE
3D01:85 05 \ STA FORMAT ; SAVE FOR ADR FLD
3D03:29 03 \ AND #$03 ; MASK FOR 2-BIT LEN
3D05:85 06 \ STA LENGTH ;
3D07:98 \ TYA ; OPCODE
3D08:29 8F \ AND #$8F ; MASK: 1XXX1010 TEST
3D0A:AA \ TAX ; SAVE IT
3D0B:98 \ TYA ; OPCODE TO A AGAIN
3D0C:A0 03 \ LDY #$03 ;
3D0E:E0 8A \ CPX #$8A ;
3D10:F0 0B \ BEQ MNNDX3 ;
\MNNDX1:
3D12:4A \ LSR ;
3D13:90 08 \ BCC MNNDX3 ; FORM IDX INTO MNEM
3D15:4A \ LSR ;
\MNNDX2:
3D16:4A \ LSR ; 1 1XXX1010>00101XXX
3D17:09 20 \ ORA #$20 ; 2 XXXYYY01>00111XXX
3D19:88 \ DEY ; 3 XXXYYY10>00110XXX
3D1A:D0 FA \ BNE MNNDX2 ; 4 XXXYY100>00100XXX
3D1C:C8 \ INY ; 5 XXXXX000>000XXXXX
\MNNDX3:
3D1D:88 \ DEY ;
3D1E:D0 F2 \ BNE MNNDX1 ;
3D20:60 \ RTS ;
\;= 120 ================================
\INSTDSP: ; ($F8D0 ON A2)
3D21:20 C5 3C \ JSR INSDS1 ; GEN FMT, LEN BYTES
3D24:48 \ PHA ; SAVE MNEM TABLE IDX
\PRNTOP:
3D25:B1 0A \ LDA (PCL),Y ;
3D27:20 DC 3F \ JSR PRBYTE ;
3D2A:A2 01 \ LDX #1 ; PRINT 2 BLANKS
\PRNTBL:
3D2C:20 CB 3D \ JSR PRXBL ;
3D2F:C4 06 \ CPY LENGTH ; PRINT INSTRUCTION
3D31:C8 \ INY ; IN A 12 CHAR FIELD
3D32:90 F1 \ BCC PRNTOP ;
3D34:A2 03 \ LDX #3 ; MNEM CHAR COUNT
3D36:C0 04 \ CPY #4 ;
3D38:90 F2 \ BCC PRNTBL ;
3D3A:68 \ PLA ; RECOVER MNEM INDEX
3D3B:A8 \ TAY ;
3D3C:B9 80 3E \ LDA MNEML,Y ;
3D3F:85 08 \ STA LMNEM ; FETCH 3-CHAR MNEM
3D41:B9 C0 3E \ LDA MNEMR,Y ; PACKED IN 2-BYTES
3D44:85 09 \ STA RMNEM ;
\PRMN1:
3D46:A9 00 \ LDA #0 ;
3D48:A0 05 \ LDY #5 ;
\PRMN2:
3D4A:06 09 \ ASL RMNEM ; SHIFT 5 BITS OF
3D4C:26 08 \ ROL LMNEM ; CHARACTER INTO A
3D4E:2A \ ROL ; (CLEARS CARRY)
3D4F:88 \ DEY ;
3D50:D0 F8 \ BNE PRMN2 ;
3D52:69 BF \ ADC #"?" ; ADD "?" OFFSET
3D54:20 EF 3F \ JSR ECHO ; SEND A CHAR OF MNEM
3D57:CA \ DEX ;
3D58:D0 EC \ BNE PRMN1 ;
3D5A:20 C9 3D \ JSR PR3BL ; PRINT 3 BLANKS
3D5D:A4 06 \ LDY LENGTH ;
3D5F:A2 06 \ LDX #6 ; CNT FOR 6 FMT BITS
\PRADR1:
3D61:E0 03 \ CPX #3 ;
3D63:F0 1C \ BEQ PRADR5 ; IF X=3 THEN ADDR
\PRADR2:
3D65:06 05 \ ASL FORMAT ;
3D67:90 0E \ BCC PRADR3 ;
3D69:BD 73 3E \ LDA CHR1-1,X ;
3D6C:20 EF 3F \ JSR ECHO ;
3D6F:BD 79 3E \ LDA CHR2-1,X ;
3D72:F0 03 \ BEQ PRADR3 ;
3D74:20 EF 3F \ JSR ECHO ;
\PRADR3:
3D77:CA \ DEX ;
3D78:D0 E7 \ BNE PRADR1 ;
3D7A:60 \ RTS ;
\PRADR4:
3D7B:88 \ DEY ;
3D7C:30 E7 \ BMI PRADR2 ;
3D7E:20 DC 3F \ JSR PRBYTE ;
\PRADR5:
3D81:A5 05 \ LDA FORMAT ;
3D83:C9 E8 \ CMP #$E8 ; HANDLE REL ADR MODE
3D85:B1 0A \ LDA (PCL),Y ; SPECIAL (SND TARGET
3D87:90 F2 \ BCC PRADR4 ; ADDR, NOT OFFSET)
3D89:20 E8 3D \ JSR PCADJ3 ;
3D8C:AA \ TAX ; PCL,H+OFFSET+1
3D8D:E8 \ INX ; TO A,Y
3D8E:D0 01 \ BNE PRNTYX ; +1 TO Y,X
3D90:C8 \ INY ;
\PRNTYX:
3D91:98 \ TYA ;
\PRNTAX:
3D92:20 DC 3F \ JSR PRBYTE ; PRINT BRANCH TARGET
3D95:8A \ TXA ;
3D96:4C DC 3F \ JMP PRBYTE ;
\;= 48 ================================
\NOTACR:
3D99:C9 9B \ CMP #ESC ; ESC?
3D9B:F0 0A \ BEQ CANCEL ; YES: START OVER
3D9D:20 EF 3F \ JSR ECHO ; PRINT CHAR
3DA0:C9 DF \ CMP #"_" ;
3DA2:F0 12 \ BEQ BCKSPC ;
3DA4:E8 \ INX ;
3DA5:10 12 \ BPL NXTCHAR ; 128 CHARS MAX
\CANCEL:
3DA7:A9 DC \ LDA #"\" ;
3DA9:20 EF 3F \ JSR ECHO ;
\GETLNZ: ; ($FD67 ON A2)
3DAC:20 E0 3D \ JSR CROUT ; FRESH LINE
\GETLINE:
3DAF:A9 A1 \ LDA #"!" ; PROMPT CHAR
3DB1:20 EF 3F \ JSR ECHO ;
3DB4:A2 01 \ LDX #1 ;
\BCKSPC:
3DB6:CA \ DEX ;
3DB7:30 EE \ BMI CANCEL ;
\NXTCHAR:
3DB9:2C 11 D0 \ BIT KBDCR ; WAIT FOR KEY PRESS
3DBC:10 FB \ BPL NXTCHAR ; NO KEY YET
3DBE:AD 10 D0 \ LDA KBD ; LOAD CHAR
3DC1:9D 00 02 \ STA IN,X ; STORE IN BUFFER
3DC4:C9 8D \ CMP #CR ; CR?
3DC6:D0 D1 \ BNE NOTACR ; NO: KEEP GOING
3DC8:60 \ RTS ; YES: X=BUFLEN
\;= 11 ================================
\PR3BL: ; ($F948 ON A2)
3DC9:A2 03 \ LDX #3 ; BLANK COUNT
\PRXBL:
3DCB:A9 A0 \ LDA #" " ; LOAD A SPACE CHAR
3DCD:20 EF 3F \ JSR ECHO ; PRINT IT
3DD0:CA \ DEX ;
3DD1:D0 F8 \ BNE PRXBL ; LOOP UNTIL COUNT=0
3DD3:60 \ RTS ;
\;= 9 ================================
\GETNSP: ; ($F634 ON A2)
3DD4:B9 00 02 \ LDA IN,Y ;
3DD7:C8 \ INY ;
3DD8:C9 A0 \ CMP #" " ; SKIP OVER SPACES
3DDA:F0 F8 \ BEQ GETNSP ;
3DDC:60 \ RTS ;
\;= 3 ================================
\XMON: ;
3DDD:4C C1 3B \ JMP CMDLINE ;
\;= 5 ================================
\CROUT: ; ($FD8E ON A2)
3DE0:A9 8D \ LDA #CR ;
3DE2:4C EF 3F \ JMP ECHO ;
\;= 15 ================================
\PCADJ: ; ($F953 ON A2)
3DE5:38 \ SEC ; 0=1-BYTE, 1=2-BYTE,
3DE6:A5 06 \ LDA LENGTH ; 2=3-BYTE INST
\PCADJ3:
3DE8:A4 0B \ LDY PCH ;
3DEA:AA \ TAX ; TEST DISPLCMNT SIGN
3DEB:10 01 \ BPL PCADJ4 ; (FOR REL BRANCH)
3DED:88 \ DEY ; EXT NEG BY DEC PCH
\PCADJ4:
3DEE:65 0A \ ADC PCL ; PCL + LEN(DSPL) + 1
3DF0:90 01 \ BCC PCADJ5 ; TO A (PCL),
3DF2:C8 \ INY ; CARRY TO Y (PCH)
\PCADJ5:
3DF3:60 \ RTS ;
\;= 46 ================================
\GETNUM: ; ($FFA7 ON A2)
3DF4:A2 00 \ LDX #0 ; CLEAR VALID # FLAG
3DF6:86 0E \ STX A2L ; CLEAR A2
3DF8:86 0F \ STX A2H ;
3DFA:F0 15 \ BEQ NXTCHAR ;
\DIG: ; ($FF8A ON A2)
3DFC:A2 03 \ LDX #3 ;
3DFE:0A \ ASL ;
3DFF:0A \ ASL ; GOT HEX DIGIT,
3E00:0A \ ASL ; SHIFT INTO A2
3E01:0A \ ASL ;
\NXTBIT:
3E02:0A \ ASL ;
3E03:26 0E \ ROL A2L ;
3E05:26 0F \ ROL A2H ;
3E07:CA \ DEX ; LEAVE X=$FF IF DIG
3E08:10 F8 \ BPL NXTBIT ;
\NXTBAS:
3E0A:B5 0F \ LDA A2H,X ; COPY A2 TO A1
3E0C:95 0D \ STA A1H,X ;
\NXTBS2:
3E0E:E8 \ INX ;
3E0F:F0 F9 \ BEQ NXTBAS ;
\NXTCHAR: ; ($FFAD ON A2)
3E11:B9 00 02 \ LDA IN,Y ; GET CHAR
3E14:C8 \ INY ; ADVANCE INDEX
3E15:49 B0 \ EOR #$B0 ;
3E17:C9 0A \ CMP #10 ; DECIMAL DIGIT?
3E19:90 E1 \ BCC DIG ; YES: ACCUMULATE
3E1B:69 88 \ ADC #$88 ;
3E1D:C9 FA \ CMP #$FA ; 'A'-'F'
3E1F:B0 DB \ BCS DIG ; YES: ACCUMULATE
3E21:60 \ RTS ; NO: RETURN WITH
\ ; X=0: NO NUMBER
\ ; X=1: NUMBER
\;= 222 ================================
\FMT1: ; ($F962 ON A2)
\; FMT1 BYTES: XXXXXXY0 INSTRS
\; IF Y=0 THEN LEFT HALF BYTE
\; IF Y=1 THEN RIGHT HALF BYTE
\; (X=INDEX)
3E22:04 20 54 30 0D 80 04 90 03 22 54 33 0D 80 04 90
3E32:04 20 54 33 0D 80 04 90 04 20 54 3B 0D 80 04 90
3E42:00 22 44 33 0D C8 44 00 11 22 44 33 0D C8 44 A9
3E52:01 22 44 33 0D 80 04 90 01 22 44 33 0D 80 04 90
\; $ZZXXXY01 INSTRS
3E62:26 31 87 9A
\FMT2: ; ($F9A6 ON A2)
\; ERR IMM ZP ABS IMP ACC (ZP,X) (ZP),Y
\; ZP,X ABS,X ABS,Y (ABS) ZP,Y REL
3E66:00 21 81 82 00 00 59 4D 91 92 86 4A 85 9D
\CHR1: ; ($F9B4 ON A2)
\; ",),#($"
3E74:AC A9 AC A3 A8 A4
\CHR2: ; ($F9BA ON A2)
\; "Y",0,"X$$",0
3E7A:D9 00 D8 A4 A4 00
\MNEML: ; ($F9C0 ON A2)
\; MNEML IS OF FORM:
\; (A) XXXXX000
\; (B) XXXYY100
\; (C) 1XXX1010
\; (D) XXXYYY10
\; (E) XXXYYY01
\; (X=INDEX)
3E80:1C 8A 1C 23 5D 8B 1B A1 9D 8A 1D 23 9D 8B 1D A1
3E90:00 29 19 AE 69 A8 19 23 24 53 1B 23 24 53 19 A1
3EA0:00 1A 5B 5B A5 69 24 24 AE AE A8 AD 29 00 7C 00
3EB0:15 9C 6D 9C A5 69 29 53 84 13 34 11 A5 69 23 A0
\MNEMR:
3EC0:D8 62 5A 48 26 62 94 88 54 44 C8 54 68 44 E8 94
3ED0:00 B4 08 84 74 B4 28 6E 74 F4 CC 4A 72 F2 A4 8A
3EE0:00 AA A2 A2 74 74 74 72 44 68 B2 32 B2 00 22 00
3EF0:1A 1A 26 26 72 72 88 C8 C4 CA 26 48 44 44 A2 C8
\;======================================
\; WOZMON
\RESET:
3F00:D8 \ CLD ; CLEAR DECIMAL MODE
3F01:58 \ CLI ; ENABLE INTERRUPTS
3F02:A0 7F \ LDY #$7F ; DSP DIRECTION MASK
3F04:8C 12 D0 \ STY DSP ; (DDR MODE ASSUMED)
3F07:A9 A7 \ LDA #$A7 ; KBD & DSP CTRL MASK
3F09:8D 11 D0 \ STA KBDCR ; ENABLE IRQS, SET
3F0C:8D 13 D0 \ STA DSPCR ; CA1,CB1 FOR POS
\ ; EDGE SENSE/OUT MODE
\NOTCR:
3F0F:C9 DF \ CMP #BS ; BACKSPACE KEY?
3F11:F0 13 \ BEQ BACKSP ;
3F13:C9 9B \ CMP #ESC ; ESC KEY?
3F15:F0 03 \ BEQ ESCAPE ;
3F17:C8 \ INY ; ADVANCE TEXT INDEX
3F18:10 0F \ BPL NXTCHR ; ESC IF LINE TOO BIG
\ESCAPE:
3F1A:A9 DC \ LDA #PROMPT ; PRINT PROMPT CHAR
3F1C:20 EF 3F \ JSR ECHO ;
\GETLIN:
3F1F:A9 8D \ LDA #CR ; PRINT CR
3F21:20 EF 3F \ JSR ECHO ;
3F24:A0 01 \ LDY #1 ; START NEW LINE
\BACKSP:
3F26:88 \ DEY ; BACK UP INDEX
3F27:30 F6 \ BMI GETLIN ; REINIT IF EMPTY
\NXTCHR:
3F29:AD 11 D0 \ LDA KBDCR ; WAIT FOR KEY PRESS
3F2C:10 FB \ BPL NXTCHR ; NO KEY YET
3F2E:AD 10 D0 \ LDA KBD ; LOAD CHAR
3F31:99 00 02 \ STA IN,Y ; ADD TO TEXT BUFFER
3F34:20 EF 3F \ JSR ECHO ; PRINT CHAR
3F37:C9 8D \ CMP #CR ;
3F39:D0 D4 \ BNE NOTCR ;
3F3B:A0 FF \ LDY #$FF ;
3F3D:A9 00 \ LDA #0 ; DEFAULT MODE IS XAM
3F3F:AA \ TAX ;
\STSTOR:
3F40:0A \ ASL ;
\STMODE:
3F41:85 1B \ STA MODE ; SET MODE FLAGS
\BLSKIP:
3F43:C8 \ INY ; ADVANCE TEXT INDEX
\NXTITM:
3F44:B9 00 02 \ LDA IN,Y ; GET CHAR
3F47:C9 8D \ CMP #CR ;
3F49:F0 D4 \ BEQ GETLIN ; DONE IF CR
3F4B:C9 AE \ CMP #"." ;
3F4D:90 F4 \ BCC BLSKIP ; IGNORE CHAR < "."
3F4F:F0 F0 \ BEQ STMODE ; SET BLOCK XAM MODE
3F51:C9 BA \ CMP #":" ;
3F53:F0 EB \ BEQ STSTOR ; SET STOR MODE
3F55:C9 D2 \ CMP #"R" ;
3F57:F0 3B \ BEQ RUN ; RUN THE PROGRAM
3F59:86 18 \ STX L ; CLEAR INPUT VALUE
3F5B:86 19 \ STX H ;
3F5D:84 1A \ STY YSAV ; SAVE Y FOR COMPARE
3F5F:B9 00 02 \ LDA IN,Y ; GET CHR FOR HEX TST
3F62:49 B0 \ EOR #$B0 ; MAP DIGITS TO 0-9
3F64:C9 0A \ CMP #10 ; DECIMAL DIGIT?
3F66:90 06 \ BCC DIG ;
3F68:69 88 \ ADC #$88 ; "A"-"F" -> $FA-FF
3F6A:C9 FA \ CMP #$FA ; HEX LETTER?
3F6C:90 11 \ BCC NOTHEX ;
\DIG:
3F6E:0A \ ASL ;
3F6F:0A \ ASL ;
3F70:0A \ ASL ;
3F71:0A \ ASL ;
3F72:A2 04 \ LDX #4 ;
\HXSHIF:
3F74:0A \ ASL ;
3F75:26 18 \ ROL L ;
3F77:26 19 \ ROL H ;
3F79:CA \ DEX ;
3F7A:D0 F8 \ BNE HXSHIF ;
3F7C:C8 \ INY ;
3F7D:D0 E0 \ BNE NXTHEX ;
\NOTHEX:
3F7F:C4 1A \ CPY YSAV ;
3F81:F0 97 \ BEQ ESCAPE ;
3F83:24 1B \ BIT MODE ;
3F85:50 10 \ BVC NOTSTO ;
3F87:A5 18 \ LDA L ;
3F89:81 16 \ STA (STL,X) ;
3F8B:E6 16 \ INC STL ;
3F8D:D0 B5 \ BNE NXTITM ;
3F8F:E6 17 \ INC STH ;
\TONEXT:
3F91:4C 44 3F \ JMP NXTITM ;
\RUN: ; RUN USER'S PROGRAM
3F94:6C 14 00 \ JMP (XAML)
\NOTSTO:
3F97:30 2B \ BMI XAMNXT
3F99:A2 02 \ LDX #2 ; COPY 2 BYTES
\SETADR:
3F9B:B5 17 \ LDA L-1,X
3F9D:95 15 \ STA STL-1,X
3F9F:95 13 \ STA XAML-1,X
3FA1:CA \ DEX
3FA2:D0 F7 \ BNE SETADR
\NXTPRN: ; PRINT ADDR AND DATA
3FA4:D0 14 \ BNE PRDATA
3FA6:A9 8D \ LDA #$8D
3FA8:20 EF 3F \ JSR ECHO
3FAB:A5 15 \ LDA XAMH
3FAD:20 DC 3F \ JSR PRBYTE
3FB0:A5 14 \ LDA XAML
3FB2:20 DC 3F \ JSR PRBYTE
3FB5:A9 BA \ LDA #":"
3FB7:20 EF 3F \ JSR ECHO
\PRDATA:
3FBA:A9 A0 \ LDA #" "
3FBC:20 EF 3F \ JSR ECHO
3FBF:A1 14 \ LDA (XAML,X)
3FC1:20 DC 3F \ JSR PRBYTE
3FC4:86 1B \ STX MODE
3FC6:A5 14 \ LDA XAML
3FC8:C5 18 \ CMP L
3FCA:A5 15 \ LDA XAMH
3FCC:E5 19 \ SBC H
3FCE:B0 C1 \ BCS TONEXT
3FD0:E6 14 \ INC XAML
3FD2:D0 02 \ BNE MD8CHK
3FD4:E6 15 \ INC XAMH
\MD8CHK:
3FD6:A5 14 \ LDA XAML
3FD8:29 07 \ AND #$07
3FDA:10 C8 \ BPL NXTPRN
\PRBYTE:
3FDC:48 \ PHA ; PRINT A AS HEX BYTE
3FDD:4A \ LSR ; (DESTRUCTIVE)
3FDE:4A \ LSR
3FDF:4A \ LSR
3FE0:4A \ LSR
3FE1:20 E5 3F \ JSR PRHEX
3FE4:68 \ PLA
\PRHEX:
3FE5:29 0F \ AND #$0F ; PRINT A AS HEX DIG
3FE7:09 B0 \ ORA #"0"
3FE9:C9 BA \ CMP #"9"+1
3FEB:90 02 \ BCC ECHO
3FED:69 06 \ ADC #6
\ECHO:
3FEF:2C 12 D0 \ BIT DSP ; PRINT A AS ASCII
3FF2:30 FB \ BMI ECHO
3FF4:8D 12 D0 \ STA DSP
3FF7:60 \ RTS
\;
3FF8:FF FF 00 0F 00 FF 00 00
\;
\; THE FOLLOWING PATCHES ADAPT THE
\; ABOVE CODE FOR TESTING ON AN
\; ORIGINAL APPLE ][
3DB9:AD 00 C0
3DBE:2C 10 C0
3F29:AD 00 C0
3F2E:2C 10 C0
3FEF:4C ED FD