Files
open-roms/src/mon_m65/bsmon.s
T

2941 lines
69 KiB
ArmAsm

; *******************************
; * BSM = Bit Shifter's Monitor *
; * for The MEGA65 10-Dec_2020 *
; * (adaped for the Open ROMs) *
; *******************************
; XXX adapt all the addresses/constants!
; ************************************************
; * Register storage for JMPFAR and JSRFAR calls *
; ************************************************
!addr Bank = 2
!addr PCH = 3
!addr PCL = 4
!addr SR = 5
!addr AC = 6
!addr XR = 7
!addr YR = 8
!addr ZR = 9
; *************************************
; * Used direct (zero) page addresses *
; *************************************
!addr BP = 10
!addr SPH = 11
!addr SPL = 12
; following variables overlap with the BASIC floating point area
; $59 - $5d : temporary floating point accumulator
; $5e - $62 : temporary floating point accumulator
; $63 - $69 : primary floating point accumulator
; $6a - $6f : secondary floating point accumulator
; A set of 32 bit variables also used as 32 bit pointer
!addr Long_AC = $59 ; 32 bit accumulator
!addr Long_CT = $5d ; 32 bit counter
!addr Long_PC = $61 ; 32 bit program counter
!addr Long_DA = $65 ; 32 bit data pointer
; Flags are used in BBR BBS instructions
!addr Adr_Flags = $69
!addr Mode_Flags = $6a
!addr Op_Code = $6b
!addr Op_Flag = $6c ; 7: two operands
; 6: long branch
; 5: 32 bit address
; 4: Q register
!addr Op_Size = $6d
!addr Dig_Cnt = $6e
!addr Buf_Index = $6f
; operating system variables
!addr MODE_80 = $d7 ; 80 column / 40 volumn flag
!addr IIRQ = $0314
!addr IBRK = $0316
!addr EXMON = $032e
; bottom of BASIC runtime stack
; should be a safe space
!addr X_Vector = $400 ; exit vector (ROM version dependent)
!addr Ix_Mne = $402 ; index to mnemonics table
!addr Op_Mne = $403 ; 3 bytes for mnemonic
!addr Op_Ix = $406 ; type of constant
!addr Op_Len = $407 ; length of operand
!addr Disk_Unit = $408 ; unit = device
!addr Disk_Track = $409 ; logical track 1 -> 255
!addr Disk_Sector = $40A ; logical sector 0 -> 255
!addr Disk_Status = $40B ; BCD value of status
!addr Mon_Data = $410 ; 40 bytes, buffer for hunt and filename
!addr Disk_Msg = $440 ; 40 bytes, disk status as text message
!addr EXIT_OLD = $cf2e ; exit address for ROM 910110
!addr EXIT = $cfa4 ; exit address for ROM 911001
!addr SETMSG = $ff90
!addr SECOND = $ff93
!addr TKSA = $ff96
!addr ACPTR = $ffa5
!addr CIOUT = $ffa8
!addr UNTALK = $ffab
!addr UNLSN = $ffae
!addr LISTEN = $ffb1
!addr TALK = $ffb4
!addr OPEN = $ffc0
!addr CLOSE = $ffc3
!addr STOP = $ffe1
; *******
Mon_Break
; *******
JSR PRIMM
!pet KEY_RETURN, "break",0 ; ; XXX what is '\a'?
JSR Print_Commands
; pull BP, Z, Y, X, A,SR,PCL,PCH
; 7 6 5 4 3 2 1 0
LDX #7
BIT EXIT ; version
BPL @loop
DEX
@loop PLA
STA PCH,X
DEX
BPL @loop
; decrement PC to point after BRK
LDA PCL
BNE @nopage
DEC PCH
@nopage DEC PCL
LDA $011d
BBR7 Bank,@bank
LDA $011f
@bank AND #15
STA Bank
BRA Mon_Start
; ******
Mon_Call
; ******
JSR Print_Commands
; clear register for monitor call
LDA #0
LDX #6
@loop STA AC,X
DEX
BPL @loop
; set default PC to "exit to BASIC"
LDA #<EXIT ; ROM 911110
LDX #>EXIT
BIT EXIT ; $20 (JSR) or $ff ?
BPL @store
LDA #<EXIT_OLD ; ROM 910111
LDX #>EXIT_OLD
@store STA PCL
STA X_Vector
STX PCH
STX X_Vector+1
; *******
Mon_Start
; *******
CLD
TSY
STY SPH
TSX
STX SPL
LDA #$c0
JSR SETMSG
CLI
+NOP
; **********
Mon_Register
; **********
JSR Reg_Text
; print Bank,PCH
LDY #0
@loopa LDA Bank,Y
JSR Print_Hex
INY
CPY #2
BCC @loopa
; print SR,PCL,A,X,Y,Z,BP
@loopb LDA Bank,Y
JSR Print_Hex_Blank
INY
CPY #9
BCC @loopb
; print 16 bit stack pointer
LDA SPH
JSR Print_Hex
LDA SPL
JSR Print_Hex_Blank
; print flags
LDY #8
LDA SR
@loopc ASL
PHA
LDA #'-'
BCC @flag
LDA #'1'
@flag JSR CHROUT
PLA
DEY
BNE @loopc
; **
Main
; **
JSR Print_CR
LDX #0
; read one line into buffer
; ****
Main_A
; ****
@loop JSR CHRIN
STA BUF,X
INX
CPX #80
BCS Mon_Error ; input too long
CMP #KEY_RETURN
BNE @loop
LDA #0
STA Buf_Index
STA BUF-1,X ; terminate buffer
@getcomm JSR Get_Char
BEQ Main
CMP #' '
BEQ @getcomm
; ********
Mon_Switch
; ********
LDX #24
@loop CMP Command_Char,X
BEQ Mon_Select
DEX
BPL @loop
; fall through to error routine if not found
; *******
Mon_Error
; *******
; put a question mark at the end of the text
JSR PRIMM
!pet KEY_ESC, "o",KEY_CRSR_RIGHT,'?',0
LDX #$f8 ; reset stack pointer
TXS
BRA Main
; ********
Mon_Select
; ********
STA VERCKK
CPX #22
LBCS Load_Save
TXA
ASL
TAX
JMP (Jump_Table,X)
; ************
Print_Commands
; ************
JSR PRIMM
!pet KEY_RETURN,KEY_YELLOW,KEY_RVS_ON,"commands: "
; **********
Command_Char
; **********
; 0123456789abcdef
!pet "abcdfghjmrtx@.>;?"
; *********
Cons_Prefix
; *********
!pet "$+&%'"
; **************
Load_Save_Verify
; **************
!pet "lsv",KEY_WHITE,0
RTS
; ********
Jump_Table
; ********
!word Mon_Assemble ; A
!word Mon_Bits ; B
!word Mon_Compare ; C
!word Mon_Disassemble ; D
!word Mon_Fill ; F
!word Mon_Go ; G
!word Mon_Hunt ; H
!word Mon_JSR ; J
!word Mon_Memory ; M
!word Mon_Register ; R
!word Mon_Transfer ; T
!word Mon_Exit ; X
!word Mon_DOS ; @
!word Mon_Assemble ; .
!word Mon_Set_Memory ; >
!word Mon_Set_Register ; ;
!word Mon_Help ; ?
!word Converter ; $
!word Converter ; +
!word Converter ; &
!word Converter ; %
; ******
Mon_Exit
; ******
JMP (X_Vector)
; *******
LAC_To_PC
; *******
; called from Mon_Set_Register, Mon_Go and Mon_JSR
; as the first instruction. The carry flag was set from
; the routine Got_LAC if an error occured.
; Notice that the Bank, PCH and PCL values are stored
; high to low, reverse to the standard order.
; Bank, PCH and PCL are part of a list, that is used by
; the routines FAR_JMP and FAR_JSR of the operating system
BCS @error
LDA Long_AC
STA Bank+2
LDA Long_AC+1
STA Bank+1
LDA Long_AC+2
STA Bank
@error RTS
; ********
LAC_To_LPC
; ********
PHX
LDX #3
@loop LDA Long_AC,X
STA Long_PC,X
DEX
BPL @loop
PLX
RTS
; ********
LAC_To_LCT
; ********
PHX
LDX #3
@loop LDA Long_AC,X
STA Long_CT,X
DEX
BPL @loop
PLX
RTS
; ********
LAC_To_LDA
; ********
PHX
LDX #3
@loop LDA Long_AC,X
STA Long_DA,X
DEX
BPL @loop
PLX
RTS
; **********
LAC_Plus_LCT
; **********
PHX
LDX #252 ; use ZP wrap around
CLC
@loop LDA Long_AC+4,X
ADC Long_CT+4,X
STA Long_AC+4,X
INX
BNE @loop
PLX
RTS
; ***********
LAC_Minus_LPC
; ***********
PHX
LDX #252 ; use ZP wrap around
SEC
@loop LDA Long_AC+4,X
SBC Long_PC+4,X
STA Long_CT+4,X
INX
BNE @loop
PLX
RTS
; *************
LAC_Compare_LPC
; *************
PHX
LDX #252 ; use ZP wrap around
SEC
@loop LDA Long_AC+4,X
SBC Long_PC+4,X
INX
BNE @loop
PLX
RTS
; *****
Inc_LAC
; *****
INW Long_AC
BNE @return
INW Long_AC+2
@return RTS
; *****
Dec_LAC
; *****
LDA Long_AC
ORA Long_AC+1
BNE @skip
DEW Long_AC+2
@skip DEW Long_AC
RTS
; *****
Inc_LPC
; *****
INW Long_PC
BNE @return
INW Long_PC+2
@return RTS
; *****
Dec_LDA
; *****
LDA Long_DA
ORA Long_DA+1
BNE @skip
DEW Long_DA+2
@skip DEW Long_DA
RTS
; ***
Fetch
; ***
PHZ
TYA
TAZ
BBS7 Long_PC+3,@banked ; trigger banked access
+NOP ; use LDA [Long_PC],Z
@banked LDA (Long_PC),Z
PLZ
AND #$ff
RTS
; ********
Mon_Memory
; ********
JSR Get_LAC ; get 1st. parameter
LDZ #16 ; default row count
BCS @row ; no address
JSR LAC_To_LPC ; Long_PC = start address
JSR Get_LAC ; Long_AC = end address
BCS @row ; not given
JSR LAC_Minus_LPC ; Long_CT = range
LBCC Mon_Error ; negative range -> error
LDX #4 ; 16 bytes / line
BBR7 MODE_80,@shift
DEX ; 8 bytes / line
@shift LSR Long_CT+1
ROR Long_CT
DEX
BNE @shift
LDZ Long_CT ; row count
INZ
@row JSR STOP
BEQ @exit
JSR Dump_Row
DEZ
BNE @row
@exit JMP Main
; ********
Print_Bits
; ********
PHZ
STA Long_DA
LDY #8
@loop LDA #'*'
BBS7 Long_DA,@set
LDA #'.'
@set JSR CHROUT
ASL Long_DA
DEY
BNE @loop
PLZ
RTS
; ******
Mon_Bits
; ******
JSR Get_LAC ; get 1st. parameter
BCS @lab
JSR LAC_To_LPC ; Long_PC = start address
@lab JSR Print_CR
LDA #KEY_WHITE
STA Long_DA+1
LDX #8
@row PHX
JSR Hex_LPC
LDZ #0
@col SEC
LDA #KEY_WHITE+KEY_LT_RED ; toggle colour
SBC Long_DA+1
STA Long_DA+1
JSR CHROUT
LDA [Long_PC],Z
JSR Print_Bits
CLC
TZA
ADC #8
TAZ
CMP #64
BCC @col
JSR Print_CR
JSR Inc_LPC
PLX
DEX
BNE @row
JMP Main
; **************
Mon_Set_Register
; **************
JSR Get_LAC ; get 1st. parameter
JSR LAC_To_PC
LDY #3
@loop JSR Get_LAC
BCS @exit
LDA Long_AC
STA Bank,Y
INY
CPY #9
BCC @loop
@exit JMP Main
; ************
Mon_Set_Memory
; ************
JSR Get_LAC ; get 1st. parameter
BCS @exit
JSR LAC_To_LPC ; Long_PC = row address
LDZ #0
@loop JSR Get_LAC
BCS @exit
LDA Long_AC
BBS7 Long_PC+3,@banked ; trigger banked access
+NOP ; use STA [Long_PC],Z
@banked STA (Long_PC),Z
INZ
CPZ #16
BBR7 MODE_80,@next
CPZ #8
@next BCC @loop
@exit JSR PRIMM
!pet KEY_ESC, "o"
!pet $91,$00
JSR Dump_Row
JMP Main
; ****
Mon_Go
; ****
; XXX to be rewritten for Open ROMs!
rts
; JSR Get_LAC ; get 1st. parameter
; JSR LAC_To_PC
; LDX SPL
; TXS
; JMP JMPFAR
; *****
Mon_JSR
; *****
; XXX to be rewritten for Open ROMs!
rts
; JSR Get_LAC ; get 1st. parameter
; JSR LAC_To_PC
; LDX SPL
; TXS
; JSR JSRFAR
; TSX
; STX SPL
; JMP Main
; **********
Dump_4_Bytes
; **********
JSR CHROUT ; colour
@loop BBS7 Long_PC+3,@banked ; trigger banked access
+NOP ; use LDA [Long_PC],Z
@banked LDA (Long_PC),Z
JSR Print_Hex_Blank
INZ
TZA
AND #3
BNE @loop
RTS
; **********
Dump_4_Chars
; **********
LDY #0
STY QTSW ; disable quote mode
JSR CHROUT ; colour
@loop BBS7 Long_PC+3,@banked ; trigger banked access
+NOP ; use LDA [Long_PC],Z
@banked LDA (Long_PC),Z
TAY
AND #%01100000
BNE @laba
LDY #'.'
@laba TYA
JSR CHROUT
INZ
TZA
AND #3
BNE @loop
RTS
; ******
Dump_Row
; ******
PHZ
JSR Print_CR
LDA #'>'
JSR CHROUT
JSR Hex_LPC
LDZ #0
LDX #2 ; 2 blocks in 80 columns
BBR7 MODE_80,@loop
DEX ; 1 block in 40 columns
@loop LDA #KEY_LT_RED
JSR Dump_4_Bytes
LDA #KEY_WHITE
JSR Dump_4_Bytes
DEX
BNE @loop
JSR PRIMM
!byte $3a,$12,$00 ; : reverse on
LDZ #0
LDX #2 ; 4 blocks in 80 columns
BBR7 MODE_80,@lchr
DEX ; 2 blocks in 40 columns
@lchr LDA #KEY_LT_RED
JSR Dump_4_Chars
LDA #KEY_WHITE
JSR Dump_4_Chars
DEX
BNE @lchr
TZA
JSR Add_LPC
PLZ
RTS
; **********
Mon_Transfer
; **********
JSR Param_Range ; Long_PC = source
LBCS Mon_Error ; Long_CT = count
JSR Get_LAC ; Long_AC = target
LBCS Mon_Error
LDZ #0
JSR LAC_Compare_LPC ; target - source
BCC @forward
; source < target: backward transfer
JSR LAC_Plus_LCT ; Long_AC = end of target
@lpback LDA [Long_DA],Z ; backward copy
STA [Long_AC],Z
JSR Dec_LDA
JSR Dec_LAC
JSR Dec_LCT
BPL @lpback
JMP Main
@forward LDA [Long_PC],Z ; forward copy
STA [Long_AC],Z
JSR Inc_LPC
JSR Inc_LAC
JSR Dec_LCT
BPL @forward
JMP Main
; *********
Mon_Compare
; *********
JSR Param_Range ; Long_PC = source
LBCS Mon_Error ; Long_CT = count
JSR Get_LAC ; Long_AC = target
LBCS Mon_Error
JSR Print_CR
LDZ #0
@loop LDA [Long_PC],Z
CMP [Long_AC],Z
BEQ @laba
JSR Hex_LPC
@laba JSR Inc_LAC
JSR Inc_LPC
JSR Dec_LCT
BPL @loop
JMP Main
; ******
Mon_Hunt
; ******
JSR Param_Range ; Long_PC = start
LBCS Mon_Error ; Long_CT = count
LDY #0
JSR Get_Char
CMP #KEY_APOSTROPHE
BNE @bin
JSR Get_Char ; string hunt
CMP #0
LBEQ Mon_Error ; null string
@lpstr STA Mon_Data,Y
INY
JSR Get_Char
BEQ @hunt
CPY #32 ;max. string length
BNE @lpstr
BRA @hunt
@bin JSR Got_LAC
@lpbin LDA Long_AC
STA Mon_Data,Y
INY
JSR Get_LAC
BCS @hunt
CPY #32 ;max. data length
BNE @lpbin
@hunt STY Long_DA ; hunt length
JSR Print_CR
@lpstart LDY #0
@lpins JSR Fetch
CMP Mon_Data,Y
BNE @next
INY
CPY Long_DA
BNE @lpins
JSR Hex_LPC ; match
@next JSR STOP
LBEQ Main
JSR Inc_LPC
JSR Dec_LCT
BPL @lpstart
JMP Main
; *******
Load_Save
; *******
; XXX to be rewritten for OpenROMs!
rts
; LDY Disk_Unit
; STY FA
; LDY #8
; STY SA
; LDY #0
; STY BA
; STY FNLEN
; STY FNBANK
; STY IOSTATUS
; LDA #>Mon_Data
; STA FNADR+1
; LDA #<Mon_Data
; STA FNADR
; @skip JSR Get_Char ; skip blanks
; LBEQ Mon_Error
; CMP #' '
; BEQ @skip
; CMP #KEY_QUOTE ; must be quote
; LBNE Mon_Error
; LDX Buf_Index
; @copyfn LDA BUF,X ; copy filename
; BEQ @do ; no more input
; INX
; CMP #KEY_QUOTE
; BEQ @unit ; end of filename
; STA (FNADR),Y ; store to filename
; INC FNLEN
; INY
; CPY #19 ; max = 16 plus prefix "@0:"
; BCC @copyfn
; JMP Mon_Error ; filename too long
; @unit STX Buf_Index ; update read position
; JSR Get_Char
; BEQ @do ; no more parameter
; JSR Get_LAC
; BCS @do
; LDA Long_AC ; unit #
; STA FA
; JSR Get_LAC
; BCS @do
; JSR LAC_To_LPC ; Long_PC = start address
; STA BA ; Bank
; JSR Get_LAC ; Long_AC = end address + 1
; BCS @load ; no end address -> load/verify
; JSR Print_CR
; LDX Long_AC ; X/Y = end address
; LDY Long_AC+1
; LDA VERCKK ; A = load/verify/save
; CMP #'S'
; LBNE Mon_Error ; must be Save
; LDA #0
; STA SA ; set SA for PRG
; LDA #Long_PC ; Long_PC = start address
; JSR SAVE
; @exit JMP Main
; @do LDA VERCKK
; CMP #'V' ; Verify
; BEQ @exec
; CMP #'L' ; Load
; LBNE Mon_Error
; LDA #0 ; 0 = LOAD
; @exec JSR LOAD ; A == 0 : LOAD else VERIFY
; BBR4 IOSTATUS,@exit
; LDA VERCKK
; LBEQ Mon_Error
; LBCS Main
; JSR PRIMM
; !pet " error",0
; JMP Main
; @load LDX Long_PC
; LDY Long_PC+1
; LDA #0 ; 0 = use X/Y as load address
; STA SA ; and ignore load address from file
; BRA @do
; ******
Mon_Fill
; ******
JSR Param_Range ; Long_PC = target
LBCS Mon_Error ; Long_CT = count
JSR Get_LAC ; Long_AC = fill byte
LBCS Mon_Error
JSR Print_CR
LDZ #0
@loop LDA Long_AC
STA [Long_PC],Z
JSR Inc_LPC
JSR Dec_LCT
BPL @loop
JMP Main
; **********
Mon_Assemble
; **********
JSR Get_LAC ; get 1st. parameter
LBCS Mon_Error
JSR LAC_To_LPC ; Long_PC = PC
@start LDX #0 ; mne letter counter
STX Long_DA+1 ; clear encoded MNE
STX Op_Flag ; 6:long branch 5:32 bit
STX Op_Ix ; operand byte index
STX Op_Len ; operand length
@getin JSR Get_Char
BNE @laba
CPX #0
LBEQ Main
@laba CMP #' '
BEQ @start ; restart after blank
; check for long branches
CPX #1
BNE @labb ; -> not 2nd. char
CMP #'B'
BNE @labb ; 2nd. char != 'B'
LDZ Op_Mne
CPZ #'L'
BNE @labb ; 1st. Char != 'L'
SMB6 Op_Flag ; flag long branch
DEX ; skip 'L'
@labb STA Op_Mne,X ; next mne character
INX
CPX #3
BNE @getin
; encode 3 letter mnemonic
@lpenc LDA Op_Mne-1,X
SEC
SBC #$3f ; offset
LDY #5 ; 5 bit code
@lpbit LSR
ROR Long_DA
ROR Long_DA+1
DEY
BNE @lpbit
DEX
BNE @lpenc
; find packed MNE code in table
LDX #90 ; # of mnemonics
LDA Long_DA
@lpfind CMP MNE_L,X ; compare left MNE
BNE @nxfind
LDY MNE_R,X
CPY Long_DA+1 ; compare right MNE
BEQ @found
@nxfind DEX
BPL @lpfind
JMP Mon_Error
@found STX Ix_Mne
; find 1st. opcode for this mnemonic
TXA
LDX #0
@lpopc CMP MNE_Index,X
BEQ @exopc
INX
BNE @lpopc
@exopc STX Op_Code
; check for BBR BBS RMB SMB
TXA
AND #7
CMP #7
BNE @labc
JSR Get_Char
CMP #'0'
LBCC Mon_Error
CMP #'8'
LBCS Mon_Error
ASL
ASL
ASL
ASL
ORA Op_Code
STA Op_Code
JSR Get_Char
CMP #' '
LBNE Mon_Error
; read operand
@labc LDA #0
@labd STA Mode_Flags
JSR Read_Number
LBCS Mon_Error
BEQ @labg ; no operand
LDA Long_AC+2
LBNE Mon_Error ; -> overflow
LDY #2 ; Y=2 word operand
LDA Long_AC+1
BNE @labf ; high byte not zero
DEY ; Y=1 byte operand
@labf LDX Op_Ix ; X = operand value #
TYA ; A = 1:byte or 2:word
STA Op_Len,X ; store operand length
INC Op_Ix ; ++index to operand value
TXA ; A = current index
BNE @labg ; -> at 2nd. byte
JSR LAC_To_LCT ; Long_CT = 1st. operand
@labg DEC Buf_Index ; back to delimiter
@lpnop JSR Get_Char ; get delimiter
LBEQ @adjust ; end of operand
CMP #' '
BEQ @lpnop
; immediate
CMP #'#'
BNE @lbra
LDA Mode_Flags
BNE @error
LDA #$80 ; immediate mode
BRA @labd
; left bracket
@lbra CMP #'['
BNE @indir
LDA Mode_Flags
BNE @error
SMB5 Op_Flag ; 32 bit mode
LDA #$40 ; ( flag
BRA @labd
; left parenthesis
@indir CMP #'('
BNE @comma
LDA Mode_Flags
BNE @error
LDA #$40 ; ( flag
BRA @labd
; comma
@comma CMP #','
BNE @stack
LDA Op_Ix ; operand value #
BEQ @error
LDX #4 ; outside comma
LDA Mode_Flags
BEQ @comma1 ; no flags yet
CMP #$78 ; ($nn,SP)
BEQ @comma1
CMP #$48 ; ($nn)
BEQ @comma1
LDX #$20 ; , inside comma
CMP #$40 ; (
BNE @error
@comma1 TXA
ORA Mode_Flags
JMP @labd
; stack relative
@stack CMP #'S'
BNE @rbra
JSR Get_Char
CMP #'P'
BNE @error
LDA Mode_Flags
CMP #$60 ; ($nn,
BNE @error
ORA #%00010000 ; SP flag
JMP @labd
; right bracket
@rbra CMP #']'
BNE @right
BBR5 Op_Flag,@error
LDA Op_Ix
LBEQ Mon_Error ; no value
LDA Mode_Flags
CMP #$40 ; (
LBNE Mon_Error
ORA #%00001000 ; )
JMP @labd
@error JMP Mon_Error
; right parenthesis
@right CMP #')'
BNE @X
LDA Op_Ix
LBEQ Mon_Error ; no value
LDA Mode_Flags
CMP #$40 ; (
BEQ @right1
CMP #$61 ; ($nn,X
BEQ @right1
CMP #$70 ; ($nn,SP
LBNE Mon_Error
@right1 ORA #%00001000 ; )
JMP @labd
@X CMP #'X'
BNE @Y
LDA Op_Ix
LBEQ Mon_Error
LDA Mode_Flags
CMP #$60
BEQ @X1
CMP #4
LBNE Mon_Error
@X1 ORA #%00000001
JMP @labd
; Y
@Y CMP #'Y'
BNE @Z
LDA Op_Ix
LBEQ Mon_Error
LDA Mode_Flags
CMP #$4c ; ($nn),
BEQ @Y1
CMP #4 ; $nn,
BEQ @Y1
CMP #$7c ; ($nn,SP),
LBNE Mon_Error
@Y1 ORA #%00000010 ; Y
JMP @labd
; Z
@Z CMP #'Z'
LBNE Mon_Error
LDA Op_Ix
LBEQ Mon_Error
LDA Mode_Flags
CMP #$4c ; $nn,
LBNE Mon_Error
ORA #%00000011 ; Z
JMP @labd
; BBR BBS RMB SMB two operands
@adjust LDA Ix_Mne
LDX Op_Ix ; # if values
BEQ @match ; -> no operand
DEX
BEQ @one ; -> one operand
DEX
LBNE Mon_Error ; -> error if more than 2
CMP #5 ; BBR
BEQ @BB
CMP #6 ; BBS
LBNE Mon_Error
@BB LDA Long_CT+1
LBNE Mon_Error
LDA #3 ; offset
JSR Branch_Target
LDA Op_Code
LDY Long_AC
LDX Long_CT
STX Long_AC
STY Long_AC+1
LDY #2
BRA @store
; one operand in Long_CT
@one LDX Long_CT
LDY Long_CT+1
STX Long_AC
STY Long_AC+1 ; Aval = operand
LDX #10
@lpbrain CMP BRAIN-1,X
BEQ @branch
DEX
BNE @lpbrain
BRA @match
; branch instruction
@branch LDA Mode_Flags
LBNE Mon_Error ; only value
LDA #2 ; branch offset
JSR Branch_Target
LDA Op_Code
LDY #1 ; short branch
BBR6 Op_Flag,@bran1
INY ; long branch
ORA #3
@bran1 BRA @store
; find opcode matching mnemonic and address mode
@match JSR Mode_Index
@lpmatch JSR Match_Mode
BEQ @okmat
LDA Op_Len
LBEQ Mon_Error
LDA Mode_Flags
LBMI Mon_Error
AND #%00111111
STA Mode_Flags
INC Op_Len
JSR Size_To_Mode
BRA @lpmatch
@okmat LDY Op_Len
TXA
; store instruction bytes
; -----------------------
; A = opcode
; Y = operand length
; Long_AC = operand value
@store STA Op_Code
STY Op_Size
INC Op_Size
BBR5 Op_Flag,@storen
LDA #$ea ; 32 bit prefix
LDZ #0
STA [Long_PC],Z ; store prefix
INZ
LDA Op_Code
STA [Long_PC],Z ; store opcode
INZ
LDA Long_AC
STA [Long_PC],Z ; store address
INC Op_Size
BRA @print
@storen PHY
PLZ ; Z = Y
BEQ @store1
@lpsto LDA Long_AC-1,Y
STA [Long_PC],Z
DEZ
DEY
BNE @lpsto
@store1 LDA Op_Code
STA [Long_PC],Z
@print JSR PRIMM
!pet 13,$91,"a ", KEY_ESC, "q",0
JSR Print_Code
INC Op_Size
LDA Op_Size
JSR Add_LPC
; print out command 'A' together with next address
; and put it into buffer too,
; for easy entry of next assembler instruction
JSR PRIMM
!pet KEY_RETURN,"a ",0
LDA #'A'
STA BUF
LDA #' '
STA BUF+1
LDY #2
LDX #2 ; 6 digits
LDA Long_PC,X
BNE @auto
DEX ; 4 digits
@auto PHX
LDA Long_PC,X
JSR A_To_Hex
STA BUF,Y
JSR CHROUT
INY
TXA
STA BUF,Y
JSR CHROUT
INY
PLX
DEX
BPL @auto
LDA #' '
STA BUF,Y
JSR CHROUT
INY
TYA
TAX
JMP Main_A
; ***********
Branch_Target
; ***********
DEW Long_AC
DEC
BNE Branch_Target
; Target - PC
SEC
LDA Long_AC
SBC Long_PC
STA Long_AC
LDA Long_AC+1
SBC Long_PC+1
STA Long_AC+1
RTS
; ********
Match_Mode
; ********
; find matching mnemonic and address mode
LDX Op_Code ; try this opcode
LDA Mode_Flags ; size and address mode
@loop CMP LEN_ADM,X
BEQ @return ; success ZF=1
; search for next opcode with same mnemonic
@next INX ; next opcode
BEQ @error
LDY MNE_Index,X
CPY Ix_Mne ; same mnemonic ?
BEQ @loop ; -> compare again
BRA @next
@error DEX ; X = $ff ZF=0
@return RTS
; ********
Mode_Index
; ********
LDA Mode_Flags
LDX #0
@loop CMP ADMODE,X
BEQ @found
INX
CPX #16
BCC @loop
TXA
RTS
@found STX Mode_Flags
; **********
Size_To_Mode
; **********
LDA Op_Len
LSR
ROR
ROR
ORA Mode_Flags
STA Mode_Flags
LDX #0
RTS
; *************
Mon_Disassemble
; *************
JSR Get_LAC ; get 1st. parameter
BCS @nopar
JSR LAC_To_LPC ; Long_PC = start address
JSR Get_LAC ; Long_AC = end address
BCC @range
@nopar LDA #32 ; disassemble 32 bytes
STA Long_CT
BRA @loop
@range JSR LAC_Minus_LPC ; Long_CT = range
LBCC Mon_Error ; -> negative
@loop JSR CR_Erase ; prepare empty line
JSR STOP
LBEQ Main
JSR Dis_Code ; disassemble one line
INC Op_Size
LDA Op_Size
JSR Add_LPC ; advance address
LDA Long_CT
SEC
SBC Op_Size
STA Long_CT
BCS @loop
JMP Main
; ******
Dis_Code
; ******
JSR PRIMM
!pet ". ",0
; ********
Print_Code
; ********
; print 24 bit address of instruction
JSR Hex_LPC ; 24 bit address
; read opcode and calculate length and address mode
LDY #0
STY Op_Flag ; clear flags
JSR Fetch ; fetch from (banked) address
; check for Q instructions
CMP #$42 ; NEG
BNE @nop
INY ; Y = 1
JSR Fetch
CMP #$42 ; NEG
BNE @nop
SMB4 Op_Flag ; Q flag
LDA #2
JSR Add_LPC ; skip NEG NEG
; check for 32 bit address mode
@nop LDY #0
JSR Fetch
STA Op_Code
TAX
CMP #$ea ; prefix ?
BNE @normal
INY
JSR Fetch ; opcode after prefix
AND #%00011111 ; identify ($nn),Z codes
CMP #%00010010
BNE @normal
SMB5 Op_Flag ; set extended flag
JSR Fetch
STA Op_Code ; code after prefix
TAX
@normal LDY LEN_ADM,X ; Y = length and address mode
TYA ; A = length and address mode
AND #15 ; A = address mode
TAX ; X = address mode
LDA ADMODE,X ; A = mode flags
STA Adr_Flags ; store
TYA ; A = length and address mode
AND #%11000000 ; mask instruction length
ASL ; rotate into lower two bits
ROL
ROL
STA Op_Size ; store
BBR5 Op_Flag,@norm1
INC Op_Size
@norm1
; print instruction and operand bytes
LDY #0
LDA #' '
BBR4 Op_Flag,@blpr
LDA #'*' ; print * for NEG NEG
@blpr JSR CHROUT
@lphex JSR Fetch
JSR Print_Hex_Blank
CPY #2
BEQ @long ; stop after 3 bytes
CPY Op_Size
INY
BCC @lphex
; fill up with blanks
@lpfill CPY #3
BCS @long
JSR PRIMM
!pet " ",0
INY
BRA @lpfill
; detect long branches
@long LDA #KEY_YELLOW
JSR CHROUT
LDX Op_Code
LDA LEN_ADM,X
CMP #%10100000 ; long branch mode
BNE @locate
SMB6 Op_Flag ; set long branch flag
LDA #'L'
JSR CHROUT
; locate mnemonic text
@locate LDX Op_Code ; X = opcode
LDY MNE_Index,X ; Y = index to mnemonic text
LDA MNE_L,Y ; A = packed left part
STA Long_AC+1
LDA MNE_R,Y ; A = packed right part
STA Long_AC
; unpack and print mnemonic text
LDX #3 ; 3 letters
@lpmne LDA #0
LDY #5 ; 5 bits per letter
@lplet ASL Long_AC
ROL Long_AC+1
ROL ; rotate letter into A
DEY
BNE @lplet ; next bit
ADC #$3f ; add offset (C = 0)
DEX
BEQ @lastc ; 3rd. character
TAZ ; remember
JSR CHROUT ; and print it
BRA @lpmne ; next letter
@lastc BBR4 Op_Flag,@lbra ; -> no Q
CMP #'A' ; LDA, STA, ORA
BEQ @Q3
CMP #'C' ; DEC, INC
BNE @Q4
CPZ #'E' ; DEC
BEQ @Q3
CPZ #'N' ; INC
BNE @Q4
@Q3 LDA #'Q' ; LDQ, STQ, ORQ, INQ, DEQ
JSR CHROUT
BRA @mne4
@Q4 JSR CHROUT
LDA #'Q' ; add Q as 4th. char
JSR CHROUT
BRA @mne5
@lbra JSR CHROUT ; 3rd. character
BBS6 Op_Flag,@mne5 ; long branch
; check for 4-letter bit instructions
LDA Op_Code
AND #15
CMP #7 ; RMB & SMB
BEQ @biti
CMP #15 ; BBR & BBS
BNE @mne4
SMB7 Op_Flag ; flag two operands
@biti LDA Op_Code
AND #%01110000
ASL
ROL
ROL
ROL
ROL
ORA #'0'
JSR CHROUT
BRA @mne5
@mne4 JSR Print_Blank
@mne5 JSR Print_Blank
LDA #KEY_WHITE
JSR CHROUT
; check for accumulator operand
LDA Op_Code
LDX #8
@lpaccu DEX
BMI @oper
CMP ACCUMODE,X
BNE @lpaccu
LDA #'A'
BBR4 Op_Flag,@accu
LDA #'Q'
@accu JSR CHROUT
JMP @return
; fetch and decode operand
@oper LDX Op_Size
LBEQ @return ; -> no operand
BBR7 Adr_Flags,@laba ; bit 7: immediate
LDA #'#'
BRA @labb
@laba BBR6 Adr_Flags,@labc ; bit 6: left (
LDA #'('
BBR5 Op_Flag,@labb
LDA #'['
@labb JSR CHROUT
@labc LDA #'$'
JSR CHROUT
; fetch operand to Long_AC
LDY #0
STY Long_AC+1
@lpfop INY
JSR Fetch
STA Long_AC-1,Y
CPY Op_Size
BCC @lpfop
; interpret address modes
LDX Op_Code
LDA LEN_ADM,X
AND #%00100000 ; branches
LBNE @rel
; print 16 bit operand hi/lo or 8 bit operand
BBR5 Op_Flag,@proper
LDA Long_AC+1
JSR Print_Hex ; [$nn],Z
LDA #']'
JSR CHROUT
BRA @labf
@proper LDY Op_Size
BBR7 Op_Flag,@lpoper
LDY #1
@lpoper LDA Long_AC-1,Y
JSR Print_Hex
DEY
BNE @lpoper
BBR5 Adr_Flags,@labe ; comma flag
LDA #','
JSR CHROUT
BBR4 Adr_Flags,@labd ; SP flag
LDA #'S'
JSR CHROUT
LDA #'P'
JSR CHROUT
@labd BBR0 Adr_Flags,@labe ; X flag
LDA #'X'
JSR CHROUT
@labe BBR3 Adr_Flags,@labf ; ) flag
LDA #')'
JSR CHROUT
@labf BBR4 Op_Flag,@comch ; not a Q instruction
LDA Adr_Flags
AND #3
CMP #1
BNE @return ; Q only with ,X
@comch BBR2 Adr_Flags,@labg ; , flag
LDA #','
JSR CHROUT
LDA Adr_Flags
AND #%00000011 ; $03
BEQ @labg
TAY
LDA Index_Char-1,Y
JSR CHROUT
; fetch 2nd. operand for BBR and BBS
@labg BBR7 Op_Flag,@return
LDA #','
JSR CHROUT
LDA #'$'
JSR CHROUT
LDY #2
JSR Fetch
STA Long_AC
LDA #0
STA Long_AC+1
DEY
STY Op_Size ; Op_Size = 1
LDA #3 ; offset for relative address
BRA @rela
@rel LDA #2 ; offset for relative address
@rela PHA
LDA Op_Size ; 1:short 2:long
LSR
ROR
AND Long_AC
BPL @labh
LDA #$ff ; backward branch
STA Long_AC+1
@labh PLX ; offset 2 or 3
@lpinw INW Long_AC
DEX
BNE @lpinw
CLC
LDA Long_AC
ADC Long_PC
PHA
LDA Long_AC+1
ADC Long_PC+1
TAX
PLA
JSR Print_XA_Hex
BBR7 Op_Flag,@return
INC Op_Size
@return RTS
; *****
Got_LAC
; *****
DEC Buf_Index
; *****
Get_LAC
; *****
JSR Read_Number
BCS @error ; illegal character
BEQ @noval ; no value
JSR Got_Char ; delimiter ?
BEQ @end ; end of input
CMP #' '
BEQ @ok
CMP #','
BEQ @ok
@error JMP Mon_Error ; stack is reset in Mon_Error
@noval SEC
RTS
@end DEC Buf_Index
@ok CLC
RTS
; *********
Read_Number
; *********
PHX
PHY
PHZ
LDA #0
STA Dig_Cnt ; count columns read
STA Long_AC ; clear result Long_AC
STA Long_AC+1
STA Long_AC+2
STA Long_AC+3
JSR Get_Glyph ; get 1st. character
BEQ @exit
CMP #KEY_APOSTROPHE ; character entry 'C
BNE @numeric
JSR Get_Char ; character after '
STA Long_AC
INC Dig_Cnt
BRA @exit
@numeric LDY #3 ; $ + % %
@prefix CMP Cons_Prefix,Y ; Y = base index
BEQ @digit ; -> valid prefix
DEY
BPL @prefix
INY ; Y = 0
DEC Buf_Index ; character is digit
@digit JSR Get_Char ; hex -> BCD
BEQ @exit ; ? : ; and zero terminate
CMP #'0'
BCC @exit
CMP #':'
BCC @valid ; 0-9
CMP #'A'
BCC @exit
CMP #'G'
BCS @exit
SBC #7 ; hex conversion
@valid SBC #'0'-1
CMP Num_Base,Y
BCS @error
PHA ; push digit
INC Dig_Cnt
CPY #1 ; decimal
BNE @laba
LDX #3 ; push Long_AC * 2
CLC
@push LDA Long_AC,X
ROL
PHA
DEX
BPL @push
@laba LDX Num_Bits,Y
@shift ASL Long_AC
ROL Long_AC+1
ROW Long_AC+2
BCS @error ; overflow
DEX
BNE @shift
CPY #1 ; decimal adjustment
BNE @labc
LDX #0
LDZ #3
CLC
@pull PLA
ADC Long_AC,X
STA Long_AC,X
INX
DEZ
BPL @pull
@labc PLA ; pull digit
CLC
ADC Long_AC
STA Long_AC
BCC @digit
INC Long_AC+1
BNE @digit
INW Long_AC+2
BNE @digit
@error SEC
BRA @return
@exit CLC
@return PLZ
PLY
PLX
LDA Dig_Cnt ; digits read
RTS
; *****
Hex_LPC
; *****
LDX Long_PC+3
BEQ @laba
LDA #KEY_YELLOW
JSR CHROUT
TXA
JSR Print_Hex
LDA Long_PC+2
JSR Print_Hex
LDA #KEY_WHITE
JSR CHROUT
BRA @labb
@laba LDA Long_PC+2
BEQ @labb
JSR Print_Hex
@labb LDX Long_PC+1
LDA Long_PC
; **********
Print_XA_Hex
; **********
PHA
TXA
JSR Print_Hex
PLA
; *************
Print_Hex_Blank
; *************
JSR Print_Hex
; *********
Print_Blank
; *********
LDA #' '
JMP CHROUT
; ******
Print_CR
; ******
LDA #13
JMP CHROUT
; ******
CR_Erase
; ******
JSR PRIMM
!pet KEY_RETURN, KEY_ESC, "q",0
RTS
; *******
Print_Hex
; *******
PHX
JSR A_To_Hex
JSR CHROUT
TXA
PLX
JMP CHROUT
; ******
A_To_Hex
; ******
PHA
JSR @nibble
TAX
PLA
LSR
LSR
LSR
LSR
@nibble AND #15
CMP #10
BCC @lab
ADC #6
@lab ADC #'0'
RTS
; *******
Get_Glyph
; *******
PHX
LDA #' '
@loop LDX Buf_Index
INC Buf_Index
CMP BUF,X
BEQ @loop
PLX ; fall through
; ******
Got_Char
; ******
DEC Buf_Index
; ******
Get_Char
; ******
PHX
LDX Buf_Index
INC Buf_Index
LDA BUF,X
CPX #1
PLX
BCC @regc
CMP #';' ; register
BEQ @return
CMP #'?' ; help
BEQ @return
@regc CMP #0
BEQ @return
CMP #':'
@return RTS
; *****
Dec_LCT
; *****
LDA Long_CT
ORA Long_CT+1
BNE @skip
DEW Long_CT+2
@skip DEW Long_CT
LDA Long_CT+3 ; set N flag
RTS
; *****
Add_LPC
; *****
CLC
ADC Long_PC
STA Long_PC
BCC Inc_LPC_Page_return
; **********
Inc_LPC_Page
; **********
INC Long_PC+1
BNE Inc_LPC_Page_return
INW Long_PC+2
Inc_LPC_Page_return
RTS
; *********
Param_Range
; *********
; read two (address) parameters
; Long_CT = difference (2nd. minus 1st.)
; Long_PC = 1st. parameter
; Long_DA = 2nd. parameter
; carry on exit flags error
JSR Get_LAC ; get 1st. parameter
BCS @error
JSR LAC_To_LPC ; Long_PC = 1st. address
JSR Get_LAC
BCS @error
JSR LAC_To_LDA ; Long_DA = 2nd. address
JSR LAC_Minus_LPC ; Long_CT = range
BCC @error
CLC
RTS
@error SEC
RTS
; *******
Converter
; *******
LDX #0
STX Buf_Index
JSR Get_LAC
LBCS Mon_Error
LDX #0
@loop PHX
JSR CR_Erase
LDA Cons_Prefix,X
JSR CHROUT
TXA
ASL
TAX
JSR (Conv_Tab,X)
PLX
INX
CPX #4
BCC @loop
JMP Main
Conv_Tab !word Print_Hexval
!word Print_Decimal
!word Print_Octal
!word Print_Dual
; ********
Print_Dual
; ********
LDX #24 ; digits
LDY #1 ; bits per digit
BRA Print_Octal_entry
; *********
Print_Octal
; *********
LDX #8 ; digits
LDY #3 ; bits per digit
Print_Octal_entry
JSR LAC_To_LCT
LDZ #0
STZ Long_PC
LDZ #'0'
PHY ; save start value
@loopa PLY ; reinitialise
PHY
LDA #0
@loopb ASL Long_CT
ROW Long_CT+1
ROL
DEY
BNE @loopb
CPX #1 ; print last character
BEQ @skip
ORA Long_PC
BEQ @next
@skip ORA #'0'
STZ Long_PC
JSR CHROUT
@next DEX
BNE @loopa
PLY ; cleanup stack
RTS
; **********
Print_Hexval
; **********
JSR LAC_To_LPC
LDA #0
STA Long_PC+3
BRA Print_BCD
; ***********
Print_Decimal
; ***********
; max $ffffff = 16777215 (8 digits)
JSR LAC_To_LCT
LDX #3 ; 4 BCD bytes = 8 digits
LDA #0
@clear STA Long_PC,X
DEX
BPL @clear
LDX #32 ; source bits
SED
@loop ASL Long_CT
ROL Long_CT+1
ROW Long_CT+2
LDA Long_PC
ADC Long_PC
STA Long_PC
LDA Long_PC+1
ADC Long_PC+1
STA Long_PC+1
LDA Long_PC+2
ADC Long_PC+2
STA Long_PC+2
LDA Long_PC+3
ADC Long_PC+3
STA Long_PC+3
DEX
BNE @loop
CLD
; *******
Print_BCD
; *******
LDA #0
STA Long_CT
LDZ #'0'
LDY #8 ; max. digits
@loopa LDX #3 ; 4 bytes
LDA #0
@loopb ASL Long_PC
ROL Long_PC+1
ROW Long_PC+2
ROL
DEX
BPL @loopb
CPY #1 ; print last character
BEQ @skip
ORA Long_CT
BEQ @next
@skip ORA #'0'
STZ Long_CT
CMP #$3a
BCC @print
ADC #6 ; + carry
@print JSR CHROUT
@next DEY
BNE @loopa
RTS
; ******
Mon_Disk
; ******
DEC Buf_Index
LDX Buf_Index
LDA BUF,X
BEQ Print_Disk_Status
STA Long_CT ; dir marker
LDY #$ff ; SA = 15
CMP #'$'
BNE @lab
LDY #$f0 ; SA = 0
@lab LDA FA
JSR LISTEN
TYA ; SA
JSR SECOND
@loop LDA BUF,X
BEQ @close
JSR CIOUT
INX
BRA @loop
@close JSR UNLSN
LDA Long_CT
CMP #'$'
BNE Print_Disk_Status
JMP Directory
; *************
Get_Disk_Status
; *************
LDA FA
JSR TALK
LDA #$6f
JSR TKSA
JSR ACPTR ; 1st. digit
STA Disk_Msg
ASL
ASL
ASL
ASL
STA Disk_Status ; BCD
JSR ACPTR ; 2nd. digit
STA Disk_Msg+1
AND #15
ORA Disk_Status
STA Disk_Status ; complete BCD number
LDY #1
@loop INY
JSR ACPTR
STA Disk_Msg,Y
CMP #' '
BCS @loop
LDA #0
STA Disk_Msg,Y
JSR UNTALK
LDA Disk_Status
RTS
; ***************
Print_Disk_Status
; ***************
JSR Get_Disk_Status
; ************
Print_Disk_Msg
; ************
JSR Print_CR
LDY #0
@loop LDA Disk_Msg,Y
BEQ @exit
JSR CHROUT
INY
BRA @loop
@exit JMP Print_CR
; @[u] : print disk status for unit u
; @[u],$[=pattern] : print directory
; @[u],command : send disk command and read status
; @[u],U1 mem track startsec [endsec] : read disk sector(s)
; @[u],U2 mem track startsec [endsec] : write disk sector(s)
; *****
Mon_DOS
; *****
LDX #8 ; default device
JSR Get_Glyph
CMP #'0'
BCC @unit
CMP #':'
BCS @unit
DEC Buf_Index
JSR Read_Number
BCS @unit
LDX Long_AC ; unit
CPX #4
LBCC Mon_Error
CPX #31
LBCS Mon_Error
@unit STX FA
DEC Buf_Index
@next JSR Get_Char
BEQ @status ; only @u
CMP #' '
BEQ @next
CMP #','
BEQ @next
CMP #'U' ; sector read/write
BEQ DOS_U
@status JSR Mon_Disk
JMP Main
; *******
Directory
; *******
LDA FA
JSR TALK
LDA #$60
STA SA
JSR TKSA
LDA #0
STA IOSTATUS
LDZ #6 ; load address, pseudo link, pseudo number
@loopb TAX ; X = previous byte
JSR ACPTR ; A = current byte
LDY IOSTATUS
BNE @exit
DEZ
BNE @loopb ; X/A = last read word
STX Long_AC
STA Long_AC+1
STZ Long_AC+2
STZ Long_AC+3
JSR Print_Decimal ; file size
JSR Print_Blank
@loopc JSR ACPTR ; print file entry
BEQ @cr
LDY IOSTATUS
BNE @exit
JSR CHROUT
BCC @loopc
@cr JSR Print_CR
JSR STOP
BEQ @exit
LDZ #4
BRA @loopb ; next file
@exit JMP UNTALK
; ***
DOS_U
; ***
JSR Get_Char
CMP #'1' ; U1: read
LBCC Mon_Error
CMP #'3' ; U2: write
LBCS Mon_Error
STA Mon_Data+1 ; U type
INC Buf_Index
JSR Get_LAC
LBCS Mon_Error
JSR LAC_To_LPC ; Long_PC = memory address
JSR Get_LAC
LBCS Mon_Error
LDA Long_AC
STA Disk_Track
JSR Get_LAC
LBCS Mon_Error
LDA Long_AC
STA Disk_Sector
JSR Get_LAC
JSR LAC_To_LCT ; Long_CT = sector count
DEW Long_CT ; Long_CT = -1 for single
JSR Open_Disk_Buffer
@loop LDA Mon_Data+1
LSR
BEQ @write
JSR Find_next_Sector
BNE @error
JSR Read_Sector
BRA @next
@write JSR Write_Sector
JSR Find_next_Sector
BNE @error
@next JSR Inc_LPC_Page
INC Disk_Sector
DEW Long_CT
BPL @loop
@error JSR Print_Disk_Msg
JSR Close_Disk_Buffer
JMP Main
; **************
Find_next_Sector
; **************
JSR Build_U_String
JSR Send_Disk_Command
JSR Get_Disk_Status
BEQ @return ; OK
CMP #$66 ; illegal track or sector
BNE @error ; error
LDA #0
STA Disk_Sector
INC Disk_Track ; try next track
JSR Build_U_String
JSR Send_Disk_Command
JSR Get_Disk_Status
BEQ @return
@error JSR Print_Disk_Msg
LDA Disk_Status
@return RTS
; ******************
Open_Command_Channel
; ******************
LDA FA
JSR LISTEN
LDA #$ff
JSR SECOND
LDY #0
STY IOSTATUS
RTS
; ******
Reset_BP
; ******
JSR Open_Command_Channel
@loop LDA BP_ZERO,Y
BEQ @end
JSR CIOUT
INY
BRA @loop
@end JMP UNLSN
; ***************
Send_Disk_Command
; ***************
JSR Open_Command_Channel
@loop LDA Mon_Data,Y
BEQ @end
JSR CIOUT
INY
BRA @loop
@end JMP UNLSN
; *********
Read_Sector
; *********
LDA FA
JSR TALK
LDA #$69 ; SA = 9
JSR TKSA
LDZ #0
STZ IOSTATUS
@loop JSR ACPTR
STA [Long_PC],Z
INZ
BNE @loop
JMP UNTALK
; **********
Write_Sector
; **********
JSR Reset_BP ; reset disk buffer pointer
LDA FA
JSR LISTEN
LDA #$69 ; SA = 9
JSR TKSA
LDZ #0
STZ IOSTATUS
@loop LDA [Long_PC],Z
JSR CIOUT
INZ
BNE @loop
JSR UNLSN
RTS
; ****
Set_TS
; ****
; Input A = track or sector
; X = string index
@100 CMP #100
BCC @10
INC Mon_Data,X
SBC #100
BRA @100
@10 CMP #10
BCC @1
INC Mon_Data+1,X
SBC #10
BRA @10
@1 ORA #'0'
STA Mon_Data+2,X
RTS
; @[u],U1 mem track startsec [endsec] : read disk sector(s)
; U1:CHANNEL DRIVE TRACK SECTOR
; ************
Build_U_String
; ************
LDX #14
@loop LDA U1,X
STA Mon_Data,X
DEX
CPX #2
BCS @loop
LDA #'U'
STA Mon_Data
LDA Disk_Track
LDX #7
JSR Set_TS
LDA Disk_Sector
LDX #11
JMP Set_TS
; **************
Open_Disk_Buffer
; **************
LDA #0
STA IOSTATUS
LDA FA
JSR LISTEN ; open fa,9,"#"
LDA #$f9 ; sa = 9
JSR SECOND
LDA #'#' ; open buffer
JSR CIOUT
JSR UNLSN
LDA IOSTATUS
LBNE Print_Disk_Status
RTS
; ***************
Close_Disk_Buffer
; ***************
LDA #0
STA IOSTATUS
LDA FA
JSR LISTEN ; open fa,9,"#"
LDA #$e9 ; sa = 9
JSR SECOND
JSR UNLSN
LDA IOSTATUS
LBNE Print_Disk_Status
RTS
; The 3 letter mnemonics are encoded as three 5-bit values
; and stored in a left byte MNE_L and a right byte MNE_R
; The 5 bit value is computed by subtracting $3f from the
; ASCII value, so '?'-> 0, '@'->1, 'A'->2, 'B'->3,'Z'->27
; For example "ADC" is encoded as 2, 5, 4
; ----------------
; 7654321076543210
; 00010
; 00101
; 00100
; 0
;
!set ENC_A = %00000010
!set ENC_B = %00000011
!set ENC_C = %00000100
!set ENC_D = %00000101
!set ENC_E = %00000110
!set ENC_F = %00000111
!set ENC_G = %00001000
!set ENC_H = %00001001
!set ENC_I = %00001010
!set ENC_J = %00001011
!set ENC_K = %00001100
!set ENC_L = %00001101
!set ENC_M = %00001110
!set ENC_N = %00001111
!set ENC_O = %00010000
!set ENC_P = %00010001
!set ENC_Q = %00010010
!set ENC_R = %00010011
!set ENC_S = %00011000
!set ENC_T = %00011001
!set ENC_U = %00011010
!set ENC_V = %00011011
!set ENC_W = %00011100
!set ENC_X = %00011101
!set ENC_Y = %00011110
!set ENC_Z = %00011111
!set ENC_ADC = ENC_A * 64 * 64 + ENC_D * 64 + ENC_C
!set ENC_AND = ENC_A * 64 * 64 + ENC_N * 64 + ENC_D
!set ENC_ASL = ENC_A * 64 * 64 + ENC_S * 64 + ENC_L
!set ENC_ASR = ENC_A * 64 * 64 + ENC_S * 64 + ENC_R
!set ENC_ASW = ENC_A * 64 * 64 + ENC_S * 64 + ENC_W
!set ENC_BBR = ENC_B * 64 * 64 + ENC_B * 64 + ENC_R
!set ENC_BBS = ENC_B * 64 * 64 + ENC_B * 64 + ENC_S
!set ENC_BCC = ENC_B * 64 * 64 + ENC_C * 64 + ENC_C
!set ENC_BCS = ENC_B * 64 * 64 + ENC_C * 64 + ENC_S
!set ENC_BEQ = ENC_B * 64 * 64 + ENC_E * 64 + ENC_Q
!set ENC_BIT = ENC_B * 64 * 64 + ENC_I * 64 + ENC_T
!set ENC_BMI = ENC_B * 64 * 64 + ENC_M * 64 + ENC_I
!set ENC_BNE = ENC_B * 64 * 64 + ENC_N * 64 + ENC_E
!set ENC_BPL = ENC_B * 64 * 64 + ENC_P * 64 + ENC_L
!set ENC_BRA = ENC_B * 64 * 64 + ENC_R * 64 + ENC_A
!set ENC_BRK = ENC_B * 64 * 64 + ENC_R * 64 + ENC_K
!set ENC_BSR = ENC_B * 64 * 64 + ENC_S * 64 + ENC_R
!set ENC_BVC = ENC_B * 64 * 64 + ENC_V * 64 + ENC_C
!set ENC_BVS = ENC_B * 64 * 64 + ENC_V * 64 + ENC_S
!set ENC_CLC = ENC_C * 64 * 64 + ENC_L * 64 + ENC_C
!set ENC_CLD = ENC_C * 64 * 64 + ENC_L * 64 + ENC_D
!set ENC_CLE = ENC_C * 64 * 64 + ENC_L * 64 + ENC_E
!set ENC_CLI = ENC_C * 64 * 64 + ENC_L * 64 + ENC_I
!set ENC_CLV = ENC_C * 64 * 64 + ENC_L * 64 + ENC_V
!set ENC_CMP = ENC_C * 64 * 64 + ENC_M * 64 + ENC_P
!set ENC_CPX = ENC_C * 64 * 64 + ENC_P * 64 + ENC_X
!set ENC_CPY = ENC_C * 64 * 64 + ENC_P * 64 + ENC_Y
!set ENC_CPZ = ENC_C * 64 * 64 + ENC_P * 64 + ENC_Z
!set ENC_DEC = ENC_D * 64 * 64 + ENC_E * 64 + ENC_C
!set ENC_DEW = ENC_D * 64 * 64 + ENC_E * 64 + ENC_W
!set ENC_DEX = ENC_D * 64 * 64 + ENC_E * 64 + ENC_X
!set ENC_DEY = ENC_D * 64 * 64 + ENC_E * 64 + ENC_Y
!set ENC_DEZ = ENC_D * 64 * 64 + ENC_E * 64 + ENC_Z
!set ENC_EOR = ENC_E * 64 * 64 + ENC_O * 64 + ENC_R
!set ENC_INC = ENC_I * 64 * 64 + ENC_N * 64 + ENC_C
!set ENC_INW = ENC_I * 64 * 64 + ENC_N * 64 + ENC_W
!set ENC_INX = ENC_I * 64 * 64 + ENC_N * 64 + ENC_X
!set ENC_INY = ENC_I * 64 * 64 + ENC_N * 64 + ENC_Y
!set ENC_INZ = ENC_I * 64 * 64 + ENC_N * 64 + ENC_Z
!set ENC_JMP = ENC_J * 64 * 64 + ENC_M * 64 + ENC_P
!set ENC_JSR = ENC_J * 64 * 64 + ENC_S * 64 + ENC_R
!set ENC_LDA = ENC_L * 64 * 64 + ENC_D * 64 + ENC_A
!set ENC_LDX = ENC_L * 64 * 64 + ENC_D * 64 + ENC_X
!set ENC_LDY = ENC_L * 64 * 64 + ENC_D * 64 + ENC_Y
!set ENC_LDZ = ENC_L * 64 * 64 + ENC_D * 64 + ENC_Z
!set ENC_LSR = ENC_L * 64 * 64 + ENC_S * 64 + ENC_R
!set ENC_MAP = ENC_M * 64 * 64 + ENC_A * 64 + ENC_P
!set ENC_NEG = ENC_N * 64 * 64 + ENC_E * 64 + ENC_G
!set ENC_NOP = ENC_N * 64 * 64 + ENC_O * 64 + ENC_P
!set ENC_ORA = ENC_O * 64 * 64 + ENC_R * 64 + ENC_A
!set ENC_PHA = ENC_P * 64 * 64 + ENC_H * 64 + ENC_A
!set ENC_PHP = ENC_P * 64 * 64 + ENC_H * 64 + ENC_P
!set ENC_PHW = ENC_P * 64 * 64 + ENC_H * 64 + ENC_W
!set ENC_PHX = ENC_P * 64 * 64 + ENC_H * 64 + ENC_X
!set ENC_PHY = ENC_P * 64 * 64 + ENC_H * 64 + ENC_Y
!set ENC_PHZ = ENC_P * 64 * 64 + ENC_H * 64 + ENC_Z
!set ENC_PLA = ENC_P * 64 * 64 + ENC_L * 64 + ENC_A
!set ENC_PLP = ENC_P * 64 * 64 + ENC_L * 64 + ENC_P
!set ENC_PLX = ENC_P * 64 * 64 + ENC_L * 64 + ENC_X
!set ENC_PLY = ENC_P * 64 * 64 + ENC_L * 64 + ENC_Y
!set ENC_PLZ = ENC_P * 64 * 64 + ENC_L * 64 + ENC_Z
!set ENC_RMB = ENC_R * 64 * 64 + ENC_M * 64 + ENC_B
!set ENC_ROL = ENC_R * 64 * 64 + ENC_O * 64 + ENC_L
!set ENC_ROR = ENC_R * 64 * 64 + ENC_O * 64 + ENC_R
!set ENC_ROW = ENC_R * 64 * 64 + ENC_O * 64 + ENC_W
!set ENC_RTI = ENC_R * 64 * 64 + ENC_T * 64 + ENC_I
!set ENC_RTS = ENC_R * 64 * 64 + ENC_T * 64 + ENC_S
!set ENC_SBC = ENC_S * 64 * 64 + ENC_B * 64 + ENC_C
!set ENC_SEC = ENC_S * 64 * 64 + ENC_E * 64 + ENC_C
!set ENC_SED = ENC_S * 64 * 64 + ENC_E * 64 + ENC_D
!set ENC_SEE = ENC_S * 64 * 64 + ENC_E * 64 + ENC_E
!set ENC_SEI = ENC_S * 64 * 64 + ENC_E * 64 + ENC_I
!set ENC_SMB = ENC_S * 64 * 64 + ENC_M * 64 + ENC_B
!set ENC_STA = ENC_S * 64 * 64 + ENC_T * 64 + ENC_A
!set ENC_STX = ENC_S * 64 * 64 + ENC_T * 64 + ENC_X
!set ENC_STY = ENC_S * 64 * 64 + ENC_T * 64 + ENC_Y
!set ENC_STZ = ENC_S * 64 * 64 + ENC_T * 64 + ENC_Z
!set ENC_TAB = ENC_T * 64 * 64 + ENC_A * 64 + ENC_B
!set ENC_TAX = ENC_T * 64 * 64 + ENC_A * 64 + ENC_X
!set ENC_TAY = ENC_T * 64 * 64 + ENC_A * 64 + ENC_Y
!set ENC_TAZ = ENC_T * 64 * 64 + ENC_A * 64 + ENC_Z
!set ENC_TBA = ENC_T * 64 * 64 + ENC_B * 64 + ENC_A
!set ENC_TRB = ENC_T * 64 * 64 + ENC_R * 64 + ENC_B
!set ENC_TSB = ENC_T * 64 * 64 + ENC_S * 64 + ENC_B
!set ENC_TSX = ENC_T * 64 * 64 + ENC_S * 64 + ENC_X
!set ENC_TSY = ENC_T * 64 * 64 + ENC_S * 64 + ENC_Y
!set ENC_TXA = ENC_T * 64 * 64 + ENC_X * 64 + ENC_A
!set ENC_TXS = ENC_T * 64 * 64 + ENC_X * 64 + ENC_S
!set ENC_TYA = ENC_T * 64 * 64 + ENC_Y * 64 + ENC_A
!set ENC_TYS = ENC_T * 64 * 64 + ENC_Y * 64 + ENC_S
!set ENC_TZA = ENC_T * 64 * 64 + ENC_Z * 64 + ENC_A
; ***
MNE_L
; ***
!byte <ENC_ADC, <ENC_AND, <ENC_ASL, <ENC_ASR, <ENC_ASW, <ENC_BBR, <ENC_BBS, <ENC_BCC
!byte <ENC_BCS, <ENC_BEQ, <ENC_BIT, <ENC_BMI, <ENC_BNE, <ENC_BPL, <ENC_BRA, <ENC_BRK
!byte <ENC_BSR, <ENC_BVC, <ENC_BVS, <ENC_CLC, <ENC_CLD, <ENC_CLE, <ENC_CLI, <ENC_CLV
!byte <ENC_CMP, <ENC_CPX, <ENC_CPY, <ENC_CPZ, <ENC_DEC, <ENC_DEW, <ENC_DEX, <ENC_DEY
!byte <ENC_DEZ, <ENC_EOR, <ENC_INC, <ENC_INW, <ENC_INX, <ENC_INY, <ENC_INZ, <ENC_JMP
!byte <ENC_JSR, <ENC_LDA, <ENC_LDX, <ENC_LDY, <ENC_LDZ, <ENC_LSR, <ENC_MAP, <ENC_NEG
!byte <ENC_NOP, <ENC_ORA, <ENC_PHA, <ENC_PHP, <ENC_PHW, <ENC_PHX, <ENC_PHY, <ENC_PHZ
!byte <ENC_PLA, <ENC_PLP, <ENC_PLX, <ENC_PLY, <ENC_PLZ, <ENC_RMB, <ENC_ROL, <ENC_ROR
!byte <ENC_ROW, <ENC_RTI, <ENC_RTS, <ENC_SBC, <ENC_SEC, <ENC_SED, <ENC_SEE, <ENC_SEI
!byte <ENC_SMB, <ENC_STA, <ENC_STX, <ENC_STY, <ENC_STZ, <ENC_TAB, <ENC_TAX, <ENC_TAY
!byte <ENC_TAZ, <ENC_TBA, <ENC_TRB, <ENC_TSB, <ENC_TSX, <ENC_TSY, <ENC_TXA, <ENC_TXS
!byte <ENC_TYA, <ENC_TYS, <ENC_TZA
; ***
MNE_R
; ***
!byte >ENC_ADC, >ENC_AND, >ENC_ASL, >ENC_ASR, >ENC_ASW, >ENC_BBR, >ENC_BBS, >ENC_BCC
!byte >ENC_BCS, >ENC_BEQ, >ENC_BIT, >ENC_BMI, >ENC_BNE, >ENC_BPL, >ENC_BRA, >ENC_BRK
!byte >ENC_BSR, >ENC_BVC, >ENC_BVS, >ENC_CLC, >ENC_CLD, >ENC_CLE, >ENC_CLI, >ENC_CLV
!byte >ENC_CMP, >ENC_CPX, >ENC_CPY, >ENC_CPZ, >ENC_DEC, >ENC_DEW, >ENC_DEX, >ENC_DEY
!byte >ENC_DEZ, >ENC_EOR, >ENC_INC, >ENC_INW, >ENC_INX, >ENC_INY, >ENC_INZ, >ENC_JMP
!byte >ENC_JSR, >ENC_LDA, >ENC_LDX, >ENC_LDY, >ENC_LDZ, >ENC_LSR, >ENC_MAP, >ENC_NEG
!byte >ENC_NOP, >ENC_ORA, >ENC_PHA, >ENC_PHP, >ENC_PHW, >ENC_PHX, >ENC_PHY, >ENC_PHZ
!byte >ENC_PLA, >ENC_PLP, >ENC_PLX, >ENC_PLY, >ENC_PLZ, >ENC_RMB, >ENC_ROL, >ENC_ROR
!byte >ENC_ROW, >ENC_RTI, >ENC_RTS, >ENC_SBC, >ENC_SEC, >ENC_SED, >ENC_SEE, >ENC_SEI
!byte >ENC_SMB, >ENC_STA, >ENC_STX, >ENC_STY, >ENC_STZ, >ENC_TAB, >ENC_TAX, >ENC_TAY
!byte >ENC_TAZ, >ENC_TBA, >ENC_TRB, >ENC_TSB, >ENC_TSX, >ENC_TSY, >ENC_TXA, >ENC_TXS
!byte >ENC_TYA, >ENC_TYS, >ENC_TZA
; *******
MNE_Index
; *******
; an index for all 256 opcodes, describing
; where to find the 3-letter mnemonic
!byte $0f,$31,$15,$46,$53,$31,$02,$3d
!byte $33,$31,$02,$55,$53,$31,$02,$05
!byte $0d,$31,$31,$0d,$52,$31,$02,$3d
!byte $13,$31,$22,$26,$52,$31,$02,$05
!byte $28,$01,$28,$28,$0a,$01,$3e,$3d
!byte $39,$01,$3e,$59,$0a,$01,$3e,$05
!byte $0b,$01,$01,$0b,$0a,$01,$3e,$3d
!byte $44,$01,$1c,$20,$0a,$01,$3e,$05
!byte $41,$21,$2f,$03,$03,$21,$2d,$3d
!byte $32,$21,$2d,$50,$27,$21,$2d,$05
!byte $11,$21,$21,$11,$03,$21,$2d,$3d
!byte $16,$21,$36,$4d,$2e,$21,$2d,$05
!byte $42,$00,$42,$10,$4c,$00,$3f,$3d
!byte $38,$00,$3f,$5a,$27,$00,$3f,$05
!byte $12,$00,$00,$12,$4c,$00,$3f,$3d
!byte $47,$00,$3b,$51,$27,$00,$3f,$05
!byte $0e,$49,$49,$0e,$4b,$49,$4a,$48
!byte $1f,$0a,$56,$4b,$4b,$49,$4a,$06
!byte $07,$49,$49,$07,$4b,$49,$4a,$48
!byte $58,$49,$57,$4a,$4c,$49,$4c,$06
!byte $2b,$29,$2a,$2c,$2b,$29,$2a,$48
!byte $4f,$29,$4e,$2c,$2b,$29,$2a,$06
!byte $08,$29,$29,$08,$2b,$29,$2a,$48
!byte $17,$29,$54,$2c,$2b,$29,$2a,$06
!byte $1a,$18,$1b,$1d,$1a,$18,$1c,$48
!byte $25,$18,$1e,$04,$1a,$18,$1c,$06
!byte $0c,$18,$18,$0c,$1b,$18,$1c,$48
!byte $14,$18,$35,$37,$1b,$18,$1c,$06
!byte $19,$43,$29,$23,$19,$43,$22,$48
!byte $24,$43,$30,$40,$19,$43,$22,$06
!byte $09,$43,$43,$09,$34,$43,$22,$48
!byte $45,$43,$3a,$3c,$34,$43,$22,$06
; ***
BRAIN
; ***
; index values for branch mnemonics
; BCC BCS BEQ BMI BNE BPL BRA BSR BVC BVS
!byte $07,$08,$09,$0b,$0c,$0d,$0e,$10,$11,$12
; *****
LEN_ADM
; *****
; a table of instruction length, flags
; and address mode for all 256 opcodes
; 7-6: operand length %00.. 0: implied
; %01.. 1: direct page, indirect
; %10.. 2: absolute, etc.
; %11.. 3: BBR and BBS
; 5: relative %0110 0000 $60 short branch
; %1010 0000 $a0 long branch
; 4:
; 3-0: index of address mode
; ( %11...... BBR BBS)
!byte $00,$44,$00,$00,$40,$40,$40,$40 ; $00
!byte $00,$41,$00,$00,$80,$80,$80,$c0 ; $08
!byte $60,$45,$46,$a0,$40,$47,$47,$40 ; $10
!byte $00,$88,$00,$00,$80,$87,$87,$c0 ; $18
!byte $80,$44,$8b,$84,$40,$40,$40,$40 ; $20
!byte $00,$41,$00,$00,$80,$80,$80,$c0 ; $28
!byte $60,$45,$46,$a0,$47,$47,$47,$40 ; $30
!byte $00,$88,$00,$00,$87,$87,$87,$c0 ; $38
!byte $00,$44,$00,$00,$40,$40,$40,$40 ; $40
!byte $00,$41,$00,$00,$80,$80,$80,$c0 ; $48
!byte $60,$45,$46,$a0,$47,$47,$47,$40 ; $50
!byte $00,$88,$00,$00,$00,$87,$87,$c0 ; $58
!byte $00,$44,$41,$a0,$40,$40,$40,$40 ; $60
!byte $00,$41,$00,$00,$8b,$80,$80,$c0 ; $68
!byte $60,$45,$46,$a0,$47,$47,$47,$40 ; $70
!byte $00,$88,$00,$00,$84,$87,$87,$c0 ; $78
!byte $60,$44,$4d,$a0,$40,$40,$40,$40 ; $80
!byte $00,$41,$00,$87,$80,$80,$80,$c0 ; $88
!byte $60,$45,$46,$a0,$47,$47,$48,$40 ; $90
!byte $00,$88,$00,$88,$80,$87,$87,$c0 ; $98
!byte $41,$44,$41,$41,$40,$40,$40,$40 ; $a0
!byte $00,$41,$00,$80,$80,$80,$80,$c0 ; $a8
!byte $60,$45,$46,$a0,$47,$47,$48,$40 ; $b0
!byte $00,$88,$00,$87,$87,$87,$88,$c0 ; $b8
!byte $41,$44,$41,$40,$40,$40,$40,$40 ; $c0
!byte $00,$41,$00,$80,$80,$80,$80,$c0 ; $c8
!byte $60,$45,$46,$a0,$40,$47,$47,$40 ; $d0
!byte $00,$88,$00,$00,$80,$87,$87,$c0 ; $d8
!byte $41,$44,$4d,$40,$40,$40,$40,$40 ; $e0
!byte $00,$41,$00,$80,$80,$80,$80,$c0 ; $e8
!byte $60,$45,$46,$a0,$81,$47,$47,$40 ; $f0
!byte $00,$88,$00,$00,$80,$87,$87,$c0 ; $f8
; ****
ADMODE
; ****
; printout flags for 16 address modes
; 76543210
; --------
; 7 x #
; 6 x (
; 5 x ,
; 4 x SP
; 3 x )
; 2 x ,
; 1/0 xx 01:X 10:Y 11:Z
!byte %00000000 ; 0 implicit/direct
!byte %10000000 ; 1 #$nn immediate
!byte %00000000 ; 2 ----------
!byte %00000000 ; 3 ----------
!byte %01101001 ; 4 ($nn,X) indirect X
!byte %01001110 ; 5 ($nn),Y indirect Y
!byte %01001111 ; 6 ($nn),Z indirect Z
!byte %00000101 ; 7 $nn,X indexed X
!byte %00000110 ; 8 $nn,Y indexed Y
!byte %00000101 ; 9 $nn,X indexed X
!byte %00000110 ; a $nn,Y ----------
!byte %01001000 ; b ($nnnn,X) JMP & JSR
!byte %01101001 ; c ($nn,X) ----------
!byte %01111110 ; d ($nn,SP),Y LDA & STA
!byte %00000000 ; e
!byte %00000100 ; f
; ASL INC ROL DEC LSR ROR NEG ASR
ACCUMODE !byte $0a,$1a,$2a,$3a,$4a,$6a,$42,$43
Num_Base !byte 16,10, 8, 2 ; hex, dec, oct, bin
Num_Bits !byte 4, 3, 3, 1 ; hex, dec, oct, bin
Index_Char !pet "xyz"
; 0123456789abcd
U1 !pet "u1:9 0 000 000",0 ; channel 9, drive, track, sector
BP_ZERO !pet "b-p 9 0",0 ; set buffer pointer to 0
; ******
Reg_Text
; ******
JSR PRIMM
!pet KEY_RETURN, " pc sr ac xr yr zr bp sp nvebdizc", KEY_RETURN, "; ", KEY_ESC, "q",0
RTS
; ******
Mon_Help
; ******
JSR PRIMM
!pet KEY_RETURN
!pet KEY_LT_RED,"a",KEY_WHITE,"ssemble - a address mnemonic operand",KEY_RETURN
!pet KEY_LT_RED,"b",KEY_WHITE,"itmaps - b [from [to]]",KEY_RETURN
!pet KEY_LT_RED,"c",KEY_WHITE,"ompare - c from to with",KEY_RETURN
!pet KEY_LT_RED,"d",KEY_WHITE,"isassemble - d [from [to]]",KEY_RETURN
!pet KEY_LT_RED,"f",KEY_WHITE,"ill - f from to fillbyte",KEY_RETURN
!pet KEY_LT_RED,"g",KEY_WHITE,"o - g [address]",KEY_RETURN
!pet KEY_LT_RED,"h",KEY_WHITE,"unt - h from to (string or bytes)",KEY_RETURN
!pet KEY_LT_RED,"j",KEY_WHITE,"sr - j address",KEY_RETURN
!pet KEY_LT_RED,"l",KEY_WHITE,"oad - l filename [uniy [address]]",KEY_RETURN
!pet KEY_LT_RED,"m",KEY_WHITE,"emory - m [from [to]]",KEY_RETURN
!pet KEY_LT_RED,"r",KEY_WHITE,"egisters - r",KEY_RETURN
!pet KEY_LT_RED,"s",KEY_WHITE,"ave - s filename unit from to",KEY_RETURN
!pet KEY_LT_RED,"t",KEY_WHITE,"ransfer - t from to target",KEY_RETURN
!pet KEY_LT_RED,"v",KEY_WHITE,"erify - v filename [unit [address]]",KEY_RETURN
!pet "e",KEY_LT_RED,"x",KEY_WHITE,"it - x",KEY_RETURN
!pet KEY_LT_RED,".",KEY_WHITE,"<dot> - . address mnemonic operand",KEY_RETURN
!pet KEY_LT_RED,">",KEY_WHITE,"<greater> - > address byte sequence",KEY_RETURN
!pet KEY_LT_RED,";",KEY_WHITE,"<semicolon> - ; register contents",KEY_RETURN
!pet KEY_LT_RED,"@",KEY_WHITE,"dos - @ [dos command]",KEY_RETURN
!pet KEY_LT_RED,"?",KEY_WHITE,"help - ?",KEY_RETURN
!pet 0
JMP Main