; da65 V2.17 - Git a6b04f6e ; Created: 2019-01-15 22:26:37 ; Input file: samson.rom ; Page: 1 ; ; recreated from original EPROM content ; with use of Elektor Computing #1, Junior Paperware #2, Junior Paperware #4 and several KIM Kenner listings ; uppercase labels reflect original nomenclature. Lowercase labels are made by me. .setcpu "6502" .org $F000 ; ---------------------------------------------------------------------------- ; Definition of char values ; CTRLC := $03 ; BREAK CHAR CTRL-C ESC := $1B ; ESCAPE CHARACTER SPACE := $20 ; SPACE CHARACTER ; ---------------------------------------------------------------------------- ; Zero page addresses ; RAMPTR := $006C ; RAMPOINTER cpyadr := $00C0 ; ADDR FOR COPY trchar := $00C2 ; HOLD CONTROL CHAR WHEN STARTING TRACER scratc := $00C3 ; SCRATCH BYTE FOR COUNTERS traadr := $00C4 ; TRACE ADDR OF LAST BRK/NMI/IRQ savef := $00C6 ; VALUE OF FLAG REGISTER FOR PROGRAM RUN saves := $00C7 ; VALUE OF STACK POINTER FOR PROGRAM RUN savea := $00C8 ; VALUE OF A REGISTER FOR PROGRAM RUN savey := $00C9 ; VALUE OF Y REGISTER FOR PROGRAM RUN savex := $00CA ; VALUE OF X REGISTER FOR PROGRAM RUN inword := $00CC ; CURRENT VALUE, UP TO 16 BIT ENTERED MONADR := $00CE ; ACTUAL MEMORY ADDRESS USED BY MONITOR calcbp := $00D1 ; REGISTER FOR BREAKPOINT CALCULATIONS MONVEC := $00D6 ; ADDRESS VECTOR USED BY MONITOR CLI L00FD := $00FD MEMLO := $00FE ; FLOPPY LOAD POINTER LO BYTE MEMHI := $00FF ; FLOPPY LOAD POINTER HI BYTE ; ---------------------------------------------------------------------------- ; Addresses in OS65D ; KPDO := $2325 ; OS65D: KEY PRESSED DURING OUTPUT AHOLD := $2363 ; OS65D: SAVE THE CHARACTER HERE OS65D := $2547 ; OS65D: RE-ENTRY POINT FOR KERNEL ; ---------------------------------------------------------------------------- ; Floppy Disk Controller ; DRA := $E000 ; FDC PIA (6821) DATA/DATA DIRECTION REGISTER A CRA := DRA+1 ; FDC PIA CONTROL REGISTER A DRB := DRA+2 ; FDC PIA DATA/DATA REGISTER B CRB := DRA+3 ; FDC PIA CONTROL REGISTER B CACIA := $E010 ; FDC ACIA (6850) CONTROL REGISTER DACIA := CACIA+1 ; FDC ACIA DATA REGISTER ; ---------------------------------------------------------------------------- ; IO on CPU Card ; VAPBD := $E100 ; VIA 1 ON CPU CARD, PORT B DATA VAPAD := VAPBD+01 ; PORT A DATA VAPBDD := VAPBD+02 ; PORT B DATA DIRECTION VAPADD := VAPBD+03 ; PORT A DATA DIRECTION VATACL := VAPBD+04 ; T1, LATCH LOW, COUNTER LOW VATACH := VAPBD+05 ; T1, COUNTER HIGH VATALL := VAPBD+06 ; T1, LATCH LOW VATALH := VAPBD+07 ; T1, LATCH HIGH VATBCL := VAPBD+08 ; T2, LATCH LOW, COUNTER LOW VATBCH := VAPBD+09 ; T2, COUNTER HIGH VASR := VAPBD+10 ; SHIFT REGISTER VAACR := VAPBD+11 ; AUXILARY CONTROL REGISTER VAPCR := VAPBD+12 ; PERIPHERAL CONTROL REGISTER VAIFR := VAPBD+13 ; INTERRUPT FLAG REGISTER VAIER := VAPBD+14 ; INTERRUPT ENABLE REGISTER VAPADN := VAPBD+15 ; PORT A DATA, NO HANDSHAKE VBPBD := VAPBD+16 ; VIA 2 ON CPU CARD, PORT B DATA VBPAD := VBPBD+01 ; PORT A DATA VBPBDD := VBPBD+02 ; PORT B DATA DIRECTION VBPADD := VBPBD+03 ; PORT A DATA DIRECTION VBTACL := VBPBD+04 ; T1, LATCH LOW, COUNTER LOW VBTACH := VBPBD+05 ; T1, COUNTER HIGH VBTALL := VBPBD+06 ; T1, LATCH LOW VBTALH := VBPBD+07 ; T1, LATCH HIGH VBTBCL := VBPBD+08 ; T2, LATCH LOW, COUNTER LOW VBTBCH := VBPBD+09 ; T2, COUNTER HIGH VBSR := VBPBD+10 ; SHIFT REGISTER VBACR := VBPBD+11 ; AUXILARY CONTROL REGISTER VBPCR := VBPBD+12 ; PERIPHERAL CONTROL REGISTER VBIFR := VBPBD+13 ; INTERRUPT FLAG REGISTER VBIER := VBPBD+14 ; INTERRUPT ENABLE REGISTER VBPADN := VBPBD+15 ; PORT A DATA, NO HANDSHAKE MOADR := VAPBD+48 ; MODEM ACIA (6551) DATA REG MOASR := MOADR+01 ; ACIA STATUS REG MOACMR := MOADR+02 ; ACIA COMMAND REG MOACTR := MOADR+03 ; ACIA CONTROL REG ; ---------------------------------------------------------------------------- ; VDU Card (with 6845 CRTC) ; AR := $E140 ; ADDRESS REGISTER OF THE CRT RFILE := AR+1 ; REGISTER FILE OF CRT VIDRAM := $E800 ; VIDEO RAM ADDRESS ; Video modes can be selected via PL6 on the CPU card, although Elektor documentation for Octopus says no ; PL6 is connected to PB5, 6 and 7 of VIA2 ; this allows for 8 modes, but the SAMMON only supports 4 modes and a later version (EC65.rom) only supports two modes ; In PL6 nomenclature this means: ; all versions: ; no jumper (all lines open) 80x24 ; 5-6 (PB5 on low) 64x24 ; only first SAMMON version: ; 3-4 (PB6 low) 48x12 ; 3-4, 5-6 (PB5 and PB6 low) 24x24 ; ---------------------------------------------------------------------------- ; Addresses in Scratch RAM (1k range E400-E7FF) ; brktbl := $E7AE ; THIS IS USED AS brkpoi-3 BECAUSE THE LOOPS FOR HANDLING START WITH 1 brkpno := $E7B0 ; NUMBER OF BREAKPOINTS brkpoi := $E7B1 ; BREAKPOINTTABLE, EACH ENTRY IS 3 BYTE: ADDR-LO, ADDR-HI, ORG OPCODE baddr1 := $E7C0 ; WORK STORAGE FOR FIRST 16 BIT VALUE baddr2 := $E7C2 ; WORK STORAGE FOR SECOND 16 BIT VALUE wrkbyt := $E7C4 ; WORK STORAGE FOR BYTE OPERATIONS brkvec := $E7C5 ; VECTOR FOR BREAK FUNCTION aciflg := $E7C7 ; IF >0 OUTPUT TO SERIAL cenflg := $E7C8 ; IF >0 OUTPUT TO CENTRONICS nmivec := $E7C9 ; NMI VECTOR irqvec := $E7CB ; IRQ VECTOR FLN := $E7CD ; FIRST LINE POINTER CLN := $E7CF ; FLN+2 CURRENT LINE POINTER LLN := $E7D1 ; CLN+2 LAST LINE POINTER SCRPTR := $E7D3 ; LLN+2 SLAVE SCREEN POINTER CURSOR := $E7D5 ; SCRPTR+2 CURRENT CURSOR INLINE := $E7D7 ; CURSOR+2 IN LINE OF WINDOW COL := $E7D8 ; INLINE+1 CURRENT COLUMN ESCFLG := $E7D9 ; COL+1 ESC FLAG TEMCOL := $E7DA ; ESCFLG+1 SLAVE COLUMN RAMBEG := $E7DB ; TEMCOL+1 THE REFRESH RAM STARTS HERE CHAPLN := $E7DD ; RAMBEG+2 CHARACTER/LINE LPSCR := $E7DE ; CHAPLN+1 LINES/SCREEN FORMAT := $E7DF ; LPSCR+1 SCREEN FORMAT INDEX := $E7E0 ; FORMAT+1 SOFTWARE STACK FOR CHAR. INPUT BUFFER := $E7E1 ; INDEX+1 TABLE := $E7E9 ; BUFFER+8 CRT FORMAT TABLE JMPVEC := $E7F5 ; TABLE+12 COMMAND ADDRESS POINTER CENFLG := $E7F7 ; JMPVEC+2 CENTRONICS FLAG DUPLEX := $E7F8 ; CENFLG+1 0=FULL, 1=HALF DUPLEX AUTOLF := $E7F9 ; DUPLEX+1 0=NO, 1=AUTO CRLF TO CENTRONICS NMIVEC := $E7FA ; AUTOLF+1 (NMI VECTOR); SEEMS NOT TO BE USED IRQVEC := $E7FC ; NMIVEC+2 (IRQ VECTOR); SEEMS NOT TO BE USED TRAPRO := $E7FE ; IRQVEC+2 PROCESSOR FLAG (NOT USED) ; ---------------------------------------------------------------------------- ; VIDEO HANDLER, OUTPUTS CHAR FROM A.HOLD VIDEO: pha txa pha tya pha lda AHOLD cmp #ESC bne CHECK sta ESCFLG VIDEND: pla tay pla tax pla rts ; ---------------------------------------------------------------------------- ; TEXT S65D S65D: .byte "S65D" ; ---------------------------------------------------------------------------- CHECK: jsr COMCOM bcs VALVEC lda COMADR,x sta TABLE+10 inx lda COMADR,x sta TABLE+11 jmp (TABLE+10) ; ---------------------------------------------------------------------------- VALVEC: jmp VALID ; ---------------------------------------------------------------------------- ; CARRIAGE RETURN RETURN: ldx #$00 stx COL jsr ADJUST jmp VIDEND ; ---------------------------------------------------------------------------- ; LINE FEED FEED: jsr CURDN jmp VIDEND ; ---------------------------------------------------------------------------- ; CLEAR SCREEN & HOME CURSOR CLRHOM: jsr HOME jsr ERTEOS jmp VIDEND ; ---------------------------------------------------------------------------- ; CURSOR LEFT LEFT: jsr CURLFT jmp VIDEND ; ---------------------------------------------------------------------------- ; HOME CURSOR HOCU: jsr HOME jmp VIDEND ; ---------------------------------------------------------------------------- ; CURSOR UP UP: jsr CURUP jmp VIDEND ; ---------------------------------------------------------------------------- ; CURSOR DOWN DOWN: jsr CURDN jmp VIDEND ; ---------------------------------------------------------------------------- ; CURSOR RIGHT RIGHT: jsr CURRGT jmp VIDEND ; ---------------------------------------------------------------------------- ; ERASE TO END OF LINE ERLNX: jsr ERTEOL jmp VIDEND ; ---------------------------------------------------------------------------- ; ERASE TO END OF SCREEN ERSCRX: jsr ERTEOS jmp VIDEND ; ---------------------------------------------------------------------------- ; DELETE THE CURRENT LINE DELLIN: ldx #$00 stx COL jsr ADJCUR jsr ERTEOL jmp VIDEND ; ---------------------------------------------------------------------------- ; FILTER < SPACE VALID: lda AHOLD cmp #SPACE bcs TOSCR jmp VIDEND ; ---------------------------------------------------------------------------- ; TRANSFER TO SCREEN TOSCR: jsr TVPUT jmp VIDEND ; ---------------------------------------------------------------------------- ; FIRST LINE UP FLNUP: sec lda FLN sbc CHAPLN sta FLN lda FLN+1 sbc #$00 and #$07 sta FLN+1 rts ; ---------------------------------------------------------------------------- ; CURRENT LINE UP CLNUP: sec lda CLN sbc CHAPLN sta CLN lda CLN+1 sbc #$00 and #$07 sta CLN+1 rts ; ---------------------------------------------------------------------------- ; LAST LINE UP LLNUP: sec lda LLN sbc CHAPLN sta LLN lda LLN+1 sbc #$00 and #$07 sta LLN+1 rts ; ---------------------------------------------------------------------------- ; FIRST LINE DOWN FLNDN: clc lda FLN adc CHAPLN sta FLN lda FLN+1 adc #$00 and #$07 sta FLN+1 rts ; ---------------------------------------------------------------------------- ; CURRENT LINE DOWN CLNDN: clc lda CLN adc CHAPLN sta CLN lda CLN+1 adc #$00 and #$07 sta CLN+1 rts ; ---------------------------------------------------------------------------- ; LAST LINE DOWN LLNDN: clc lda LLN adc CHAPLN sta LLN lda LLN+1 adc #$00 and #$07 sta LLN+1 rts ; ---------------------------------------------------------------------------- ; ADJUST THE LINE POINTERS ADJUST: ldy COL bpl ADSA dec INLINE bpl ADJU jsr FLNUP jsr FLNCRT jsr ERAFLN jsr LLNUP ldy #$00 sty INLINE ADJU: jsr CLNUP ldy CHAPLN dey sty COL jmp ADJCUR ; ---------------------------------------------------------------------------- ADSA: cpy CHAPLN bcc ADJCUR ldy #$00 sty COL inc INLINE ldy INLINE cpy LPSCR bcc ADJV jsr FLNDN jsr FLNCRT jsr LLNDN ldy LPSCR dey sty INLINE jsr ERALLN ADJV: jsr CLNDN ; MOVE CURSOR TO COL 0 ADJCUR: ldx #$00 stx CURSOR stx CURSOR+1 ldx INLINE beq ACURX ACURA: clc lda CHAPLN adc CURSOR sta CURSOR bcc ACURB inc CURSOR+1 ACURB: dex bne ACURA ACURX: clc lda FLN adc CURSOR sta CURSOR lda FLN+1 adc CURSOR+1 sta CURSOR+1 clc lda COL adc CURSOR sta CURSOR bcc ACURC inc CURSOR+1 ACURC: ldx #$0E lda CURSOR+1 stx AR sta RFILE inx lda CURSOR stx AR sta RFILE rts ; ---------------------------------------------------------------------------- ; FLN-->CRT FLNCRT: ldx #$0C lda FLN+1 stx AR sta RFILE inx lda FLN stx AR sta RFILE rts ; ---------------------------------------------------------------------------- ; COMPUTE RAM POINTER CRAMPT: clc lda SCRPTR adc RAMBEG sta RAMPTR lda SCRPTR+1 adc RAMBEG+1 and #$EF ora #$08 sta RAMPTR+1 clc lda RAMPTR adc TEMCOL sta RAMPTR bcc CRAMP inc RAMPTR+1 lda RAMPTR+1 and #$EF ora #$08 sta RAMPTR+1 CRAMP: rts ; ---------------------------------------------------------------------------- ; ERASE TO END OF LINE ERTEOL: ldx CLN ldy CLN+1 stx SCRPTR sty SCRPTR+1 ldy COL sty TEMCOL ldx #SPACE ldy #$00 EREOL: jsr CRAMPT EROLX: txa sta (RAMPTR),y inc TEMCOL inc RAMPTR bne EROXX inc RAMPTR+1 lda RAMPTR+1 and #$EF ora #$08 sta RAMPTR+1 EROXX: lda TEMCOL cmp CHAPLN bcc EROLX rts ; ---------------------------------------------------------------------------- ; CLEAR THE SCREEN ERTEOS: ldx INLINE inx cpx LPSCR beq ERTEOL jsr ERTEOL EREOS: clc lda SCRPTR adc CHAPLN sta SCRPTR lda SCRPTR+1 adc #$00 and #$07 sta SCRPTR+1 cmp LLN+1 bne EEOL lda SCRPTR cmp LLN beq EEOLB EEOL: sty TEMCOL jsr EREOL bcs EREOS EEOLB: sty TEMCOL beq EREOL ; ERASE THE FIRST LINE ERAFLN: ldy #$00 sty TEMCOL ldx #SPACE lda FLN sta SCRPTR lda FLN+1 sta SCRPTR+1 jmp EREOL ; ---------------------------------------------------------------------------- ; ERASE THE LAST LINE ERALLN: ldy #$00 sty TEMCOL ldx #SPACE lda LLN sta SCRPTR lda LLN+1 sta SCRPTR+1 jmp EREOL ; ---------------------------------------------------------------------------- ; PUT A CHARACTER ON THE SCREEN TVPUT: clc lda CLN adc RAMBEG sta RAMPTR lda CLN+1 adc RAMBEG+1 sta RAMPTR+1 ldy #$00 clc lda COL adc RAMPTR sta RAMPTR bcc TVX inc RAMPTR+1 lda RAMPTR+1 and #$EF ora #$08 sta RAMPTR+1 TVX: lda AHOLD sta (RAMPTR),y inc COL jmp ADJUST ; ---------------------------------------------------------------------------- ; CURSOR DOWN CURDN: inc INLINE jsr CLNDN ldy INLINE cpy LPSCR bcc CURDNX jsr FLNDN jsr FLNCRT jsr LLNDN jsr ERALLN ldy LPSCR dey sty INLINE CURDNX: jmp ADJCUR ; ---------------------------------------------------------------------------- ; CURSOR UP CURUP: dec INLINE jsr CLNUP ldy INLINE bpl CURUPX jsr FLNUP jsr FLNCRT jsr LLNUP jsr ERAFLN ldy #$00 sty INLINE CURUPX: jmp ADJCUR ; ---------------------------------------------------------------------------- ; CURSOR LEFT CURLFT: dec COL jmp ADJUST ; ---------------------------------------------------------------------------- ; CURSOR RIGHT CURRGT: inc COL jmp ADJUST ; ---------------------------------------------------------------------------- ; HOME CURSOR HOME: ldx #$00 stx INLINE stx COL ldx FLN stx CLN ldx FLN+1 stx CLN+1 jmp ADJUST ; ---------------------------------------------------------------------------- ; MASTER RESET OF THE MEMORY MAPPED VDU RESET: lda #$00 sta FLN sta FLN+1 sta CLN sta CLN+1 sta LLN sta LLN+1 sta COL sta INLINE ldx LPSCR dex RSA: clc lda CHAPLN adc LLN sta LLN bcc RSB inc LLN+1 RSB: dex bne RSA jsr CRTINT jsr HOME jsr ERTEOS jmp FLNCRT ; ---------------------------------------------------------------------------- ; SET THE CRT TIMING REGISTERS CRTINT: ldx #$00 CIA: stx AR lda BUFFER,x sta RFILE inx cpx #$10 bne CIA rts ; ---------------------------------------------------------------------------- ; COMPUTE THE COMMAND ADDRESS INDEX COMCOM: ldx #$00 ldy #$01 COMCOA: lda COMTAB,x cmp ESCFLG bne COMCOB lda COMTAB,y cmp AHOLD bne COMCOB clc bcc COMCOC COMCOB: inx inx iny iny cpx #$16 bcc COMCOA COMCOC: lda #$00 sta ESCFLG rts ; ---------------------------------------------------------------------------- ; COMMAND TABLE COMTAB: .dbyt $000D ; RETURN .dbyt $000A ; LINE FEED .dbyt $0008 ; BACKSPACE .dbyt $1B31 ; ESC-1 .dbyt $1B32 ; ESC-2 .dbyt $1B33 ; ESC-3 .dbyt $1B34 ; ESC-4 .dbyt $1B35 ; ESC-5 .dbyt $1B36 ; ESC-6 .dbyt $1B38 ; ESC-7 COTABA: .dbyt $0010 ; CTRL-P .dbyt $FFFF .dbyt $FFFF .dbyt $FFFF .dbyt $FFFF .dbyt $FFFF ; ---------------------------------------------------------------------------- ; COMMAND ADDRESS TABLE COMADR: .addr RETURN .addr FEED .addr LEFT .addr CLRHOM .addr CLRHOM .addr HOCU .addr ERSCRX .addr UP .addr DOWN .addr ERLNX .addr RIGHT .addr LFFFF .addr LFFFF .addr LFFFF .addr LFFFF .addr LFFFF ; ---------------------------------------------------------------------------- ; MOVE THE CRT FILE FROM ROM TO RAM MOVCRT: lda #VIDRAM sta RAMBEG stx RAMBEG+1 lda #$00 tay ldx FORMAT beq MCRTB MCRTA: clc adc #$12 dex bne MCRTA MCRTB: tax MCRTC: lda CRTINA,x sta BUFFER,y inx iny cpy #$12 bne MCRTC dey lda BUFFER,y sta LPSCR dey lda BUFFER,y sta CHAPLN rts ; ---------------------------------------------------------------------------- ; CRT TIMING TABLES ; 80 x 24 CRTINA: .byte $7F ; Horizontal total-1 = 128-1 .byte $50 ; Horizontal displayed = 80 char .byte $60 ; Horiz. sync. position = 96 char .byte $08 ; Vert/Horiz Sync width = 16/8 .byte $21 ; Vertical total -1 = 33 char lines .byte $06 ; Vert. total adjust = 6 * 64 micro sec .byte $18 ; Vertical displayed = 24 lines .byte $1C ; Vert. sync position = 29 char. lines .byte $00 ; Mode control .byte $08 ; Scan lines - 1 = 8 .byte $00 ; Cursor start .byte $09 ; Cursor end .byte $00 ; Display start (not needed) .byte $00 .byte $00 ; Cursor position (not needed) .byte $00 .byte $50 ; Characters/line .byte $18 ; Lines/screen ; 64 x 24 .byte $64 .byte $40 .byte $52 .byte $05 .byte $22 .byte $00 .byte $18 .byte $1C .byte $00 .byte $08 .byte $00 .byte $09 .byte $00 .byte $00 .byte $00 .byte $00 .byte $40 .byte $18 ; CRT TIMING TABLES#2, ONLY IN SAMSON ROM NOT IN EC65 ROM ; 48 x 12 CRTINB: .byte $46,$30,$3A,$05,$16,$0E,$0C,$12 .byte $00,$0C,$00,$09,$00,$00,$00,$00 .byte $30,$0C ; 24 x 24 .byte $38,$18,$26,$05,$22,$00 .byte $18,$1C,$00,$08,$00,$09,$00,$00 .byte $00,$00,$18,$18 ; ---------------------------------------------------------------------------- ; LOAD TRACK ZERO FROM DISK LOATR0: jsr INIDSK jsr BOOT rts ; ---------------------------------------------------------------------------- ; INIT FLOPPY CONTROLLER INIDSK: ldy #$00 sty CRA lda #$40 sta DRA lda #$04 sta CRA lda #$40 sta DRA ldx #$04 stx CRA sty CRB dey sty DRB stx CRB sty DRB rts ; ---------------------------------------------------------------------------- BOOT: lda #$FB bne TRKO STEPLO: lda #$02 bit DRA beq INDEXP lda #$FF TRKO: sta DRB jsr DUMMY and #$F7 sta DRB jsr DUMMY ora #$08 sta DRB ldx #$18 jsr FDELAY beq STEPLO INDEXP: ldx #$7F stx DRB jsr FDELAY ; WAIT FOR BEGIN OF INDEX HOLE INDBEG: lda DRA bmi INDBEG ; WAIT FOR END OF INDEX HOLE INDEND: lda DRA bpl INDEND lda #$03 sta CACIA lda #$58 sta CACIA jsr RBYTE sta MEMLO tax jsr RBYTE sta L00FD jsr RBYTE sta MEMHI ldy #$00 ; READ FULL PAGES FROM DISK, NUMBER OF PAGES IS IN MEMHI RPAGE: jsr RBYTE sta (L00FD),y iny bne RPAGE inc MEMLO dec MEMHI bne RPAGE stx MEMLO lda #$FF sta DRB rts ; ---------------------------------------------------------------------------- ; DELAY OF ABOUT 10ms FDELAY: ldy #$F8 FDELA: dey bne FDELA eor MEMHI,x dex bne FDELAY rts ; ---------------------------------------------------------------------------- ; READ BYTE FROM FLOPPY RBYTE: lda CACIA lsr a bcc RBYTE lda DACIA ; JUMPTARGET FOR DELAY DUMMY: rts ; ---------------------------------------------------------------------------- ; BOOT DISK, LOAD TRACK 0 AND JUMP TO TRACK 0 LOAD VECTOR bootds: jsr LOATR0 jmp (L00FD) ; ---------------------------------------------------------------------------- LF511: jsr prtcrlf jsr LF520 jsr LF5FE sta MONVEC sty MONVEC+1 clv rts ; ---------------------------------------------------------------------------- LF520: jsr prtadr lda (MONVEC,x) tay lsr a bcc LF534 lsr a bcs LF543 cmp #$22 beq LF543 and #$07 ora #$80 LF534: lsr a tax lda distab,x bcs LF53F lsr a lsr a lsr a lsr a LF53F: and #$0F bne LF547 LF543: ldy #$80 lda #$00 LF547: tax lda LF651,x sta $D2 and #$03 sta $D3 tya and #$8F tax tya ldy #$03 cpx #$8A beq LF567 LF55C: lsr a bcc LF567 lsr a LF560: lsr a ora #$20 dey bne LF560 iny LF567: dey bne LF55C pha LF56B: lda (MONVEC),y jsr prtbyt ldx #$01 LF572: jsr prtxspc cpy $D3 iny bcc LF56B ldx #$03 cpy #$04 bcc LF572 pla tay lda LF66B,y sta $D4 lda LF6AB,y sta $D5 LF58C: lda #$00 ldy #$05 LF590: asl $D5 rol $D4 rol a dey bne LF590 adc #$BF and #$7F jsr prtchr dex bne LF58C jsr prtada ldx #$06 LF5A7: cpx #$03 bne LF5BD ldy $D3 beq LF5BD LF5AF: lda $D2 cmp #$E8 lda (MONVEC),y bcs LF5D7 jsr prtbyt dey bne LF5AF LF5BD: asl $D2 bcc LF5D3 lda LF65E,x and #$7F jsr prtchr lda LF664,x beq LF5D3 and #$7F jsr prtchr LF5D3: dex bne LF5A7 rts ; ---------------------------------------------------------------------------- LF5D7: jsr LF601 tax inx bne LF5DF iny LF5DF: tya ; PRINT 16-BIT WORD A,X prtwrd: jsr prtbyt txa jmp prtbyt ; ---------------------------------------------------------------------------- ; MONITOR: PRINT CURRENT WORK ADDRESS prtadr: lda MONVEC+1 ldx MONVEC jsr prtwrd lda #$3A jsr prtchr ; NUMBER OF SPACE SEPARATORS prtada: ldx #$01 ; PRINT X SPACES prtxspc:lda #$20 jsr prtchr dex bne prtxspc rts ; ---------------------------------------------------------------------------- LF5FE: lda $D3 sec LF601: ldy MONVEC+1 tax bpl LF607 dey LF607: adc MONVEC bcc LF60C iny LF60C: rts ; ---------------------------------------------------------------------------- ; LOOKUP TABLE FOR DISASM, EXACT FUNCTION STILL UNCLEAR distab: .byte $40,$02,$45,$03,$D0,$08,$40,$09 .byte $30,$22,$45,$33,$D0,$08,$40,$09 .byte $40,$02,$45,$33,$D0,$08,$40,$09 .byte $40,$02,$45,$B3,$D0,$08,$40,$09 .byte $00,$22,$44,$33,$D0,$8C,$44,$00 .byte $11,$22,$44,$33,$D0,$8C,$44,$9A .byte $10,$22,$44,$33,$D0,$08,$40,$09 .byte $10,$22,$44,$33,$D0,$08,$40,$09 .byte $62,$13,$78,$A9 LF651: .byte $00,$21,$81,$82,$00,$00,$59,$4D .byte $91,$92,$86,$4A,$85 LF65E: .byte $9D,$AC,$A9,$AC,$A3,$A8 LF664: .byte $A4,$D9,$00,$D8,$A4,$A4,$00 LF66B: .byte $1C,$8A,$1C,$23,$5D,$8B,$1B,$A1 .byte $9D,$8A,$1D,$23,$9D,$8B,$1D,$A1 .byte $00,$29,$19,$AE,$69,$A8,$19,$23 .byte $24,$53,$1B,$23,$24,$53,$19,$A1 .byte $00,$1A,$5B,$5B,$A5,$69,$24,$24 .byte $AE,$AE,$A8,$AD,$29,$00,$7C,$00 .byte $15,$9C,$6D,$9C,$A5,$69,$29,$53 .byte $84,$13,$34,$11,$A5,$69,$23,$A0 LF6AB: .byte $D8,$62,$5A,$48,$26,$62,$94,$88 .byte $54,$44,$C8,$54,$68,$44,$E8,$94 .byte $00,$B4,$08,$84,$74,$B4,$28,$6E .byte $74,$F4,$CC,$4A,$72,$F2,$A4,$8A .byte $00,$AA,$A2,$A2,$74,$74,$74,$72 .byte $44,$68,$B2,$32,$B2,$00,$22,$00 .byte $1A,$1A,$26,$26,$72,$72,$88,$C8 .byte $C4,$CA,$26,$48,$44,$44,$A2,$C8 ; ---------------------------------------------------------------------------- ; CALLED BY NMI; JUMPS VIA nmivec in RAM nmifnc: jmp (nmivec) ; ---------------------------------------------------------------------------- ; CALLED BY IRQ; JUMPS VIA irqvec in RAM irqfnc: jmp (irqvec) ; ---------------------------------------------------------------------------- ; INIT CENTRONICS OUTPUT INICEN: lda #$FF sta VAPBDD lda #$A0 ora VAPCR sta VAPCR lda VBPBDD and #$E7 sta VBPBDD rts ; ---------------------------------------------------------------------------- ; INIT VIA FOR PARALLEL KEYBOARD INPUT INIKBD: lda #$01 ora VAACR sta VAACR lda VAPCR ora #$01 sta VAPCR lda #$00 sta VAPADD rts ; ---------------------------------------------------------------------------- ; RECEIVE CHAR FROM KEYBOARD RECCHA: lda VAIFR and #$02 beq RECCHA ; LOAD CHAR FROM KEYBOARD W/O STROBE INPUT1: lda VAPAD and #$7F sta AHOLD rts ; ---------------------------------------------------------------------------- ; READ CONFIG JUMPERS ON CPU AND SET ACIA CTLCMD: lda #$02 sta VBPBDD ldx #$00 stx VBPBD lda VBPAD eor #$FF sta MOACMR lda #$04 sta VBPBDD stx VBPBD lda VBPAD eor #$FF sta MOACTR stx VBPADD stx VBPBDD stx aciflg rts ; ---------------------------------------------------------------------------- ; READ PL6 AND CONFIURE VDU ACCORDINGLY (SEE ELEKTOR 11-1983 p51) getpl6: lda VBPBDD and #$1F sta VBPBDD lda VBPBD eor #$FF ldx #$05 getpla: lsr a dex bne getpla sta FORMAT rts ; ---------------------------------------------------------------------------- ; RECEIVE SERIAL CHAR ACIIN: lda #$08 and MOASR beq ACIIN lda MOADR sta AHOLD rts ; ---------------------------------------------------------------------------- ; SEND A TO SERIAL PORT ACIOUT: lda #$10 and MOASR beq ACIOUT lda AHOLD sta MOADR rts ; ---------------------------------------------------------------------------- ; VIDEO OUT FOR BASIC BASVID: jsr VIDEO ; KEY DEPRESSED DURING OUTPUT BRKOUT: lda VAIFR and #$02 bne brkchk brkret: rts ; ---------------------------------------------------------------------------- brkchk: lda VAPAD and #$7F cmp #CTRLC bne brkret sta KPDO rts ; ---------------------------------------------------------------------------- ; CENTRONICS OUT FOR BASIC BASCEN: jsr CENTRO jmp BRKOUT ; ---------------------------------------------------------------------------- ; SERIAL OUT FOR BASIC BASACI: jsr ACIOUT jmp BRKOUT ; ---------------------------------------------------------------------------- ; SEND A to CENTRONICS CENTRO: lda VBPBD and #$08 beq CTROB lda VBPBD and #$10 bne CTROB CENTRA: lda AHOLD sta VAPBD WAIT: lda VBPBD and #$08 beq CTROB lda VBPBD and #$10 bne CTROB lda VAIFR and #$10 beq WAIT lda VAIFR ora #$18 sta VAIFR CTROB: rts ; ---------------------------------------------------------------------------- ; OUTPUT CHAR TO VIDEO AND OTHER CONFIGURED CHANNELS prtchr: sta AHOLD jsr VIDEO lda cenflg beq prtcha jsr CENTRO ; CHECK FOR SERIAL OUTPUT prtcha: lda aciflg beq prtchb jsr ACIOUT ; CHECK IF KEY WAS PRESSED prtchb: lda VAIFR and #$02 bne chkbrk ; RECOVER A AND RETURN prtchx: lda AHOLD rts ; ---------------------------------------------------------------------------- ; CHECK FOR BREAK chkbrk: lda VAPAD and #$7F cmp #CTRLC bne prtchx pla pla jmp (brkvec) ; ---------------------------------------------------------------------------- ; RESET ENTRY POINT reset: cld sei lda #$04 sta savef ldx #$FF txs stx saves jsr INIKBD jsr CTLCMD jsr getpl6 jsr MOVCRT jsr RESET jsr INICEN lda #$00 sta brkpno sta aciflg sta cenflg lda #>irqhdl ldx #entry sta brkvec+1 lda #irqhdl sta nmivec+1 ; MONITOR ENTRY POINT, PRINT LOGO AND START INPUT LOOP entry: ldy #sammsg jsr prtmsg jsr prtcrlf ldx #$FF txs stx saves bne monlo2 ; NEW LINE AFTER LAST ACTION (NOT RUN AFTER RESET) monlo1: ldy #prompt jsr prtmsg ; PREPARE FOR NEW INPUT LINE monlo2: jsr zeradd jsr zerinw ; MONITOR LOOP, CHECK FOR ^, IF FOUND INCREASE ADDRESS mon_up: jsr getcme cmp #'^' bne monmin ; INCREASE MONITOR ADDRESS AND RESTART CLI LOOP addrup: jsr incadr ; PRINT NEW CLI LINE AND CONTINUE CLI LOOP monnew: jsr prtptr jmp monlo2 ; ---------------------------------------------------------------------------- ; WAS '- PRESSED? monmin: cmp #$2D bne monspc jsr decadr jmp monnew ; ---------------------------------------------------------------------------- ; WAS SPACE PRESSED? monspc: cmp #$20 bne monsla lda inword sta MONADR lda inword+1 sta MONADR+1 jmp monnew ; ---------------------------------------------------------------------------- ; WAS '/ PRESSED? monsla: cmp #$2F bne monrun lda inword ; STORE VALUE IN A INTO MONADR AND INCREASE MONADR BY 1 stobyt: ldy #$00 sta (MONADR),y beq addrup ; WAS 'G PRESSED? monrun: cmp #$47 bne mondbg ; RUN PROGRAM AT MONADR, RESTORE ALL REGISTERS AND FLAGS startp: ldx saves txs lda MONADR+1 pha lda MONADR pha lda savef pha ldx savex ldy savey lda savea rti ; ---------------------------------------------------------------------------- ; WAS 'L PRESSED? mondbg: cmp #$4C bne mon_p jsr prttra jmp monlo1 ; ---------------------------------------------------------------------------- ; PRINT LAST BRK/IRQ VALUES WITH LIST HEADER prttra: ldy #stareg jsr prtmsg ; PRINT LAST BRK/IRQ VALUES prttrb: lda savea jsr lstbyt lda savex jsr lstbyt lda savey jsr lstbyt lda #$01 jsr prtbyt lda saves jsr prtbyt ldy #msg3b jsr prtmsa ldx saves lda $0101,x jsr lstbyt lda traadr+1 jsr prtbyt lda traadr jsr lstbyt jsr prtflg jmp prtspc ; ---------------------------------------------------------------------------- ; GET CHAR, TEST FOR BREAK, ECHO IT AND RETURN IN A AS UPPERCASE getcme: jsr RECCHA cmp #$03 beq monbrk jsr prtchr cmp #$61 bmi getcmr cmp #$7B bpl getcmr sec sbc #$20 getcmr: rts ; ---------------------------------------------------------------------------- ; HANDLE BREAK AS INPUT monbrk: pla pla jmp (brkvec) ; ---------------------------------------------------------------------------- ; JUMP TO mon-t AS BRANCH TARGET jmpmont:jmp mon_t ; ---------------------------------------------------------------------------- ; WAS 'P PRESSED? mon_p: cmp #$50 bne mon_m lda traadr sta MONADR lda traadr+1 sta MONADR+1 jmp monnew ; ---------------------------------------------------------------------------- ; WAS 'M PRESSED? THEN PRINT HEXDUMP (EQUAL TO .H) mon_m: cmp #$4D bne jmpmont ; PRINT MESSAGE HEXDUMP AND WAIT FOR ADDRESS RANGE INPUT monmhd: ldy #hxdmsg jsr prtmsg jsr iprang bpl hdchkp ; IF NO PROPER ADDRESS RANGE, EXIT FUNCTION monhde: bmi hdexit ; CHECK IF PROPER ADDR WERE ENTERED AND THEN PRINT and 6 SPACES hdchkp: jsr chk2l1 bcc monhde jsr prtcrlf ldx #$06 ; PRINT SPACE LOOP AND PREP NIBBLE INDEX TITLE hdchkl: jsr prtspc dex bne hdchkl ldy #$00 lda baddr1 ; PRINT FROM START ADDRESS LAST NIBBLE 16 NEXT VALUES AS TITLE: e.g. D E F 0 1 hdtitn: tax jsr prtnib jsr prtspc jsr prtspc inx txa iny cpy #$10 bne hdtitn jsr cpybad ; START HEXDUMP LINE, PRINT ADDR AND INIT FOR 16 VALUES PRINTED hdstal: jsr prtcrlf ldx #$10 lda MONADR+1 jsr prtbyt lda MONADR jsr prtbyt ldy #prompt jsr prtmsa ; CHECK IF MONITOR ADDRESS IS LOWER THAN END ADDRESS AND THEN START PRINTING VALUES hdchka: jsr chk2lm bcs hdvalu jsr prtcrlf ; IF END ADDRESS REACHED END HEXDUMP FUNCTION hdexit: jmp monlo1 ; ---------------------------------------------------------------------------- ; PRINT ONE BYTE AND TEST IF END OF ROW hdvalu: ldy #$00 lda (MONADR),y jsr lstbyt jsr incadr dex bne hdchka sec lda MONADR sbc #$10 sta MONADR bcs hdvala dec MONADR+1 ; OVERFLOW FROM CALCULATING BACK 16 BYTES hdvala: ldx #$10 ; LOAD BYTE AND CHECK FOR PRINTABLE ASCII hdisas: lda (MONADR),y cmp #$20 bcc hdnona cmp #$80 bcs hdnona ; PRINT ASCII CHAR AND RETURN LOOP hdprta: jsr prtchr jsr incadr dex bne hdisas beq hdstal ; LOAD '.' AS CHAR TO PRINT AND JUMP TO PRINT ASCII CHAR hdnona: lda #'.' bne hdprta ; PRINT MESSAGE WITH A AS INDEX TO MESSAGE TABLE prtmsg: jsr prtcrlf prtmsa: lda imessg,y cmp #CTRLC beq prtmsx jsr prtchr iny bne prtmsa prtmsx: rts ; ---------------------------------------------------------------------------- ; PRINT CR-LF prtcrlf:lda #$0D jsr prtchr lda #$0A ; RETRUN, BELONGS TO FOLLOWING CODE AS WELL prtcrlx:jmp prtchr ; ---------------------------------------------------------------------------- ; PRINT BYTE IN A AS HEX PLUS SPACE lstbyt: jsr prtbyt ; PRINT SPACE prtspc: lda #$20 bne prtcrlx ; PRINT : xxxx yy with MONADR and value at (MONADR) prtptr: jsr prtcrlf ldy #prompt jsr prtmsa lda MONADR+1 jsr prtbyt lda MONADR jsr lstbyt ldy #$00 lda (MONADR),y jmp lstbyt ; ---------------------------------------------------------------------------- ; INCREASE MEMORY ADDRESS BY 1 incadr: inc MONADR bne incar inc MONADR+1 incar: rts ; ---------------------------------------------------------------------------- ; DECREASE MEMORY ADDRESS BY 1 decadr: sec lda MONADR sbc #$01 sta MONADR bcs decar dec MONADR+1 decar: rts ; ---------------------------------------------------------------------------- ; PRINT FLAGS STORED IN savef prtflg: lda savef sta wrkbyt ldx #$08 prtfla: asl wrkbyt bcc prtfl0 lda #$01 prtflb: jsr prtnib dex bne prtfla rts ; ---------------------------------------------------------------------------- ; PRINT A 0, BELONGS TO PREVIOUS FUNCTION prtfl0: lda #$00 beq prtflb ; ZERO BUFFER FOR INPUT ADDRESS MATRIX zeradd: ldy #$00 sty baddr1 sty baddr1+1 sty baddr2 sty baddr2+1 rts ; ---------------------------------------------------------------------------- ; ZERO BUFFER FOR INPUT VALUE zerinw: ldy #$00 sty inword sty inword+1 rts ; ---------------------------------------------------------------------------- ; MONITOR LOOP, ENTER DIGIT AND ROTATE INTO inword mon_dig:jsr ascval bmi mon_nde ldx #$04 ; LOOP TO ROTATE inword AND ENTERED VALUE AS LOW NIBBLE monrot: asl inword rol inword+1 dex bne monrot ora inword sta inword ldy #$00 rts ; ---------------------------------------------------------------------------- ; ERROR, NO COMMAND AND NO DIGIT mon_nde:ldy #errmsg jsr prtmsg jsr prtcrlf ldy #$FF rts ; ---------------------------------------------------------------------------- ; PRINT BYTE IN A AS TWO CHAR IN HEX prtbyt: pha lsr a lsr a lsr a lsr a jsr hexasc jsr prtchr pla ; PRINT LOW NIBBLE IN A AS HEX CHAR prtnib: and #$0F jsr hexasc jmp prtchr ; ---------------------------------------------------------------------------- ; CONVERT HEX NIBBLE TO ASCII VALUE hexasc: cmp #$0A clc bmi hexa adc #$07 hexa: adc #$30 rts ; ---------------------------------------------------------------------------- ; INPUT RANGE WITH xxxx,yyyy iprang: jsr getcme cmp #',' beq iprans jsr mon_dig bmi ipbx beq iprang iprans: lda inword sta baddr1 lda inword+1 sta baddr1+1 jsr zerinw ; INPUT MATRIX IPB: jsr getcme cmp #$0D beq ipba jsr mon_dig bmi ipbx beq IPB ipba: lda inword+1 sta baddr2+1 lda inword sta baddr2 ldy #$00 ipbx: rts ; ---------------------------------------------------------------------------- ; RESET HEX BUFFER AND INPUT NEW VALUES inphex: lda #$00 sta inword sta inword+1 beq IPB ; BOOT MESSAGE imessg: sammsg := * - imessg .byte $0D,$0A .byte "--SAMSON 65--" .byte $0D,$0A,CTRLC ; NEW LINE TEXT newlin := * - imessg .byte $0A,CTRLC ; STATUS REGISTER MSG ; #$14 stareg := * - imessg .byte "A X Y SP PC NV BDIZC" .byte $0D,$0A,CTRLC ; AT TEXT ; #$37 atmsg := * - imessg .byte " AT " .byte CTRLC ; This message seems to be unused ; #$3c msgef: .byte "L,P?" .byte CTRLC ; Message breakpoint list is full ;#$41 msg41 := * - imessg .byte "FULL" .byte CTRLC ; Message asking for breakpoint number ;#$46 msgno := * - imessg .byte "NR.?" .byte CTRLC ; ERROR MESSAGE ; #$4B errmsg := * - imessg .byte "WHAT" ; Question mark ; #$4f msgque := * - imessg .byte "?" .byte CTRLC ; READY MESSAGE ;#$51 rdymsg := * - imessg .byte "READY" .byte CTRLC ; HEXDUMP MENU ; the last bytes are used as prompt as well ; #$57 hxdmsg := * - imessg .byte "HEX" ; Message dump (in combination with previous is Hexdump) ;#$5A msgdmp := * - imessg .byte "DUMP" ; prompt is #$5E prompt := * - imessg .byte ": " .byte CTRLC ;#$61 msg14 := * - imessg .byte $0D,$0A,$0A .byte "ASCII " .byte CTRLC ; SPACE CHAR, seems to be unused ; #$6b spacem: .byte " " .byte CTRLC ; MENU OF CONTROL CMDS ;#$6d ctlmnu := * - imessg .byte $0D,$0A .byte "^D," ; second part of control menu, used for tracer ;#$72 ctl2mnu := * - imessg .byte "^L,^P,^S ?" .byte $0D,$0A,CTRLC ; DISASM MENU ;#$7f dismnu := * - imessg .byte "DISASM: " .byte CTRLC ; #$88 msg3b := * - imessg .byte "+1=" .byte CTRLC ; ---------------------------------------------------------------------------- ; CONVERT ASCII IN A TO HEX VALUE ascval: cmp #$30 bmi ascerr cmp #$3A bmi asca cmp #$41 bmi ascerr cmp #$47 bmi asca ; RETURN ERR $FF IF CHAR WAS NOT HEX DIGIT ascerr: ldy #$FF rts ; ---------------------------------------------------------------------------- ; IF A > 'A' ADD $09, SO THAT IT IS MASKED TO A-F LATER asca: cmp #$40 bmi ascd clc adc #$09 ; MASK LOWER NIBBLE, THAT NOW REPRESENTS HEX VALUE ascd: and #$0F rts ; ---------------------------------------------------------------------------- ; DEFAULT HANDLER FOR IRQ, SET TO irqvec BY reset irqhdl: sta savea pla sta savef pla sta traadr sta MONADR pla sta traadr+1 sta MONADR+1 sty savey stx savex tsx stx saves jsr prtptr jmp monlo2 ; ---------------------------------------------------------------------------- ; WAS 'T PRESSED? THEN START TRACER (REQUIRES EXTERNAL HW), ^S SINGLE, ^P 16 STEPS, ^L NO STOP mon_t: cmp #'T' bne mon_w ldy #ctl2mnu jsr prtmsg jsr getcme cmp #$0C beq trasta cmp #$10 beq trasta cmp #$13 beq trasta jmp monlo1 ; ---------------------------------------------------------------------------- ; SET NMI VECTOR, COUNTER TO 0 AND START TRACER AT LAST ADDRESS trasta: sta trchar lda #nmitra sta nmivec+1 lda #$00 sta scratc jmp startp ; ---------------------------------------------------------------------------- ; WAS 'W PRESSED? THEN START TRACER (REQUIRES EXTERNAL HW) AND PRINT EXEC ADDRESSES mon_w: cmp #'W' bne mon_n lda #nmitrw sta nmivec+1 lda #$00 sta scratc jmp startp ; ---------------------------------------------------------------------------- ; WAS 'N PRESSED? THEN SET NMI VECTOR IRQ HANDLER mon_n: cmp #'N' bne mon_i jsr prtcrlf lda #nminor sta nmivec+1 jmp monlo1 ; ---------------------------------------------------------------------------- ; WAS 'I PRESSED? THEN CHECK IF EMPTY BREAKPOINT (<6) AND ASK FOR NEW ONE mon_i: cmp #'I' bne mon_k lda brkpno cmp #$05 bmi newbrk ldy #msg41 jsr prtmsg jmp monlo1 ; ---------------------------------------------------------------------------- ; CREATE NEW BREAKPOINT, STORE OPCODE IN TABLE AND PUT BRK IN ORG ADDRESS newbrk: ldy #atmsg jsr prtmsa jsr inphex lda brkpno asl a adc brkpno tax inc brkpno lda inword sta brkpoi,x lda inword+1 sta brkpoi+1,x ldy #$00 lda (inword),y sta brkpoi+2,x tya sta (inword),y ldy #rdymsg jsr prtmsg jmp monlo1 ; ---------------------------------------------------------------------------- ; WAS 'K PRESSED? THEN ASK FOR BREAKPOINT TO BE KILLED mon_k: cmp #'K' bne mon_h lda brkpno bne getbri ; NO BREAKPOINT TO KILL nobrk: jmp monlo1 ; ---------------------------------------------------------------------------- ; LIST AVAILABLE BREAKPOINTS AND ASK FOR INDEX OF THE ONE TO BE DELETED getbri: jsr lstbrk ldy #msgno jsr prtmsa jsr prtspc jsr getcme cmp #$0D beq kilall jsr ascval bmi nobrk tax beq nobrk dex cpx brkpno bpl nobrk jsr delbkp ; LEAVE KILL FUNCTION kilbre: jmp monlo1 ; ---------------------------------------------------------------------------- ; ONLY WAS PRESSED, KILL ALL BREAKPOINTS kilall: ldx brkpno ; DELETE BREAKPOINT AND COUNT DOWN, THEN LOOP killop: txa jsr delbkp dex bne killop beq kilbre ; WAS 'H PRESSED? LIST ALL BREAKPOINTS mon_h: cmp #$48 bne cmddot lda brkpno beq monjmp jsr lstbrk ; JUMP TO MONITOR LOOP (AS BRANCH TARGET) monjmp: jmp monlo1 ; ---------------------------------------------------------------------------- ; CHECK IF . WAS ENTERED AND DECODE FOLLWING CHAR cmddot: cmp #'.' bne mon_hk ; CHECK IF .B WAS ENTERED AND BOOT DISK THEN cmdboo: jsr getcme cmp #'B' bne cmdasd jmp bootds ; ---------------------------------------------------------------------------- ; CHECK IF .A WAS ENTERED AND DO ASCII DUMP THEN cmdasd: cmp #'A' bne cmdhxd jmp ascdmp ; ---------------------------------------------------------------------------- ; CHECK IF .H WAS ENTERED AND DO HEXDUMP DUMP THEN, SAME AS M cmdhxd: cmp #'H' bne cmddis jmp monmhd ; ---------------------------------------------------------------------------- ; CHECK IF .D WAS ENTERED AND DO DISASM THEN cmddis: cmp #'D' bne cmdpar jmp stdisa ; ---------------------------------------------------------------------------- ; CHECK IF .P WAS ENTERED AND ENABLE PARALLEL PRINTER THEN cmdpar: cmp #'P' bne cmdser lda #$01 sta cenflg bne monjmp ; CHECK IF .S WAS ENTERED AND ENABLE SERIAL PRINTER THEN cmdser: cmp #'S' bne cmdd_r lda #$01 sta aciflg bne monjmp ; CHECK IF .R WAS ENTERED AND DECODE FOLLOWING CHAR, IF F RESET OUTPUT FLAGS cmdd_r: cmp #'R' bne cmdosd jsr getcme cmp #'F' bne regchk lda #$00 sta cenflg sta aciflg beq monjmp ; CHECK IF .O WAS ENTERED AND READ FOLLOWING CHARS cmdosd: cmp #'O' bne monjmp ldx #$00 ; CHECK INPUT CHARS WITH STRING S65D and IF MATCH, JUMP TO OS65D KERNEL cmdosx: jsr getcme cmp S65D,x bne monjmp inx cpx #$04 bcc cmdosx jmp OS65D ; ---------------------------------------------------------------------------- ; WAS KEY ' PRESSED? THEN STORE ASCII CHAR mon_hk: cmp #$27 bne mon_eq jsr getcme jmp stobyt ; ---------------------------------------------------------------------------- ; ASK FOR REGISTER AFTER .R, IF .RA ENTERED, ASSIGN VALUE TO A regchk: clv pha jsr getflg pla cmp #'A' bne regchx stx savea bvc jmpmon ; IF .RX ENTERED, ASSIGN VALUE TO X regchx: cmp #'X' bne regchy stx savex bvc jmpmon ; IF .RY ENTERED, ASSIGN VALUE TO Y regchy: cmp #'Y' bne jmpmon stx savey bvc jmpmon ; PRINT ? AND REQUEST NEW HEXVALUE, WHICH IS LOADED IN X getflg: ldy #msgque jsr prtmsa jsr inphex ldx baddr2 rts ; ---------------------------------------------------------------------------- ; WAS KEY = PRESSED? THEN COPY MEMORY BLOCK mon_eq: cmp #'=' bne mon_v lda inword sta MONADR lda inword+1 sta MONADR+1 jsr iprang bmi jmpmon lda baddr1 sta cpyadr lda baddr1+1 sta cpyadr+1 lda inword sec sbc cpyadr lda inword+1 sbc cpyadr+1 bmi jmpmon ldy #$00 ; INIT COPY LOOP mocpya: lda cpyadr cmp inword bne mocpyb lda cpyadr+1 cmp inword+1 beq jmpmon ; COPY LOOP mocpyb: lda (cpyadr),y sta (MONADR),y jsr incadr inc cpyadr bne mocpyx inc cpyadr+1 mocpyx: jmp mocpya ; ---------------------------------------------------------------------------- ; JUMP TO MONITOR LOOP jmpmon: jmp monlo1 ; ---------------------------------------------------------------------------- ; WAS 'V PRESSED? RESTORE BREAK VECTOR AND RESTART MONITOR (UNDOCUMENTED) mon_v: cmp #'V' bne mon_hsh lda #entry sta brkvec+1 jmp entry ; ---------------------------------------------------------------------------- ; WAS KEY # PRESSED? CLEAR SCREEN AND HOME CURSOR (UNDOCUMENTED) mon_hsh:cmp #$23 bne mon_at jsr HOME jsr ERTEOS jmp entry ; ---------------------------------------------------------------------------- ; WAS KEY @ PRESSED? IF SO, START QUICK INPUT MODE mon_at: cmp #'@' bne mon_inp ; PRINT START MSG FOR QUICK INPUT MODE quicki: jsr prtcrlf lda MONADR+1 jsr prtbyt lda MONADR jsr prtbyt ldy #prompt jsr prtmsa ; QUICK INPUT LOOP quickl: jsr inp_byt ldy #$00 lda inword sta (MONADR),y jsr incadr lda MONADR and #$0F beq quicki jsr prtspc jmp quickl ; ---------------------------------------------------------------------------- ; NO COMMAND, GET HEX CHAR INPUT mon_inp:jsr mon_dig bne jmpmonx jmp mon_up ; ---------------------------------------------------------------------------- ; JUMP TO MONITOR LOOP jmpmonx:jmp monlo1 ; ---------------------------------------------------------------------------- ; GET BYTE FOR QUICK INPUT, HANDLING @ AND inp_byt:lda #$00 sta scratc ; LOOP TO GET TWO NIBBLE inpnibb:jsr getcme cmp #$40 beq moninpx cmp #$08 beq inpbytd jsr mon_dig bmi inpbyti lda scratc beq inploni rts ; ---------------------------------------------------------------------------- ; RETURN LOOP FOR LOWER NIBBLE inploni:inc scratc bne inpnibb ; HANDLE DURING QUICK INPUT inpbytd:lda scratc bne inp_byt lda #$08 jsr prtchr jsr decadr ldy #$00 lda (MONADR),y lsr a lsr a lsr a lsr a sta inword inc scratc bne inpnibb ; IGNORE ILLEGAL INPUT inpbyti:pla pla jmp quicki ; ---------------------------------------------------------------------------- ; END QUICK INOUT MODE moninpx:jmp entry ; ---------------------------------------------------------------------------- ; LIST ALL BREAKPOINT ADDRESSES lstbrk: ldx #$00 ; OUTPUT STARTS WITH NO#1 IN THE FORMAT (NO): lstba: inx stx calcbp jsr prtcrlf txa jsr prtbyt lda #':' jsr prtchr jsr prtspc txa asl a adc calcbp tay lda brktbl+1,y jsr prtbyt lda brktbl,y jsr prtbyt cpx brkpno bne lstba jmp prtcrlf ; ---------------------------------------------------------------------------- ; DELETE BREAKPOINT AND RESTORE OPCODE delbkp: stx calcbp sta scratc asl a adc scratc tax lda brktbl+1,x sta inword+1 lda brktbl,x sta inword ldy #$00 lda brkpno,x sta (inword),y ; IF LAST BREAKPOINT IN LIST WAS DELETED, JUST DECREASE COUNTER delbke: lda scratc cmp brkpno bne delent ldx calcbp dec brkpno rts ; ---------------------------------------------------------------------------- ; SET COUNTER TO 3, AS TABLE HAS TO BE MOVED 3 BYTES TO PURGE DELETED ENTRY delent: txa ldy #$03 ; LOOP TO MOVE TABLE UP Y BYTES, EXKITS VIA BRANCH delena: lda brkpoi,x sta brktbl,x inx dey bne delena dex inc scratc bne delbke ; NMI ENTRY POINT FOR TRACER FUNCTION T (SET IN $FB95) nmitra: sta savea pla sta savef pla sta traadr sta MONADR sta MONVEC pla sta traadr+1 sta MONADR+1 sta MONVEC+1 sty savey stx savex tsx stx saves cld jsr prtcrlf dec scratc bpl nmitrb lda #$10 sta scratc ldy #stareg jsr prtmsg nmitrb: jsr prttrb jsr prtspc jsr prtspc jsr LF520 lda trchar cmp #$0C beq nmibrk cmp #$13 beq nmitrc lda scratc bne nmibrk ; GET NEW COMMAND AND GO TO MONITOR LOOP IF NO CONTROL COMMAND nmitrc: jsr getcme sta trchar cmp #$21 bne nmitrd jmp monlo1 ; ---------------------------------------------------------------------------- ; STORE CONTROL COMMAND AND CONTINUE WITH TRACER nmitrd: cmp #$10 beq nmibrk cmp #$13 beq nmibrk cmp #$0C bne nmitrc ; IF NEXT COMMAND IS BRK STOP TRACER AND START CLI nmibrk: ldy #$00 lda (MONADR),y beq nmitrx jmp startp ; ---------------------------------------------------------------------------- ; NO CONTROL COMMAND, GO TO MONITOR LOOP nmitrx: jmp monnew ; ---------------------------------------------------------------------------- ; NMI ENTRY POINT FOR TRACER FUNCTION W (SET IN $FBAA) nmitrw: sta savea pla sta savef pla sta MONADR pla sta MONADR+1 sty savey stx savex tsx stx saves cld dec scratc bpl nmipra lda #$09 sta scratc jsr prtcrlf ; PRINT ADDRESS OF COMMAND AND CONTINUE WITH TRACER nmipra: lda MONADR+1 jsr prtbyt lda MONADR jsr prtbyt lda #$2C jsr prtchr jsr prtspc jmp nmibrk ; ---------------------------------------------------------------------------- ; NMI ENTRY POINT FOR HANDLING LIKE IRQ nminor: cld jmp irqhdl ; ---------------------------------------------------------------------------- ; START ASCII DUMP, ASK FOR IP RANGE ascdmp: ldy #msg14 ; 61 jsr prtmsg ldy #msgdmp ; 5A jsr prtmsa jsr iprang bpl ascchk ; LEAVE FUNCTION ascdmx: jmp monlo1 ; ---------------------------------------------------------------------------- ; CHECK FOR VALID ADDRESS RANGE AND PRINT HEADER ascchk: jsr chk2l1 bcc ascdmx jsr prtcrlf ldx #$06 ; PRINT SPACES AND INIT TITLE LINE ascspc: jsr prtspc dex bne ascspc ldy #$00 lda baddr1 ; PRINT TITLE LINE AND COPY START ADDRESS asctit: tax jsr prtnib inx txa iny cpy #$10 bne asctit jsr cpybad ; START LINE AND PRINT ADDRESS asclin: jsr prtcrlf lda MONADR+1 jsr prtbyt lda MONADR jsr prtbyt ldy #prompt jsr prtmsa jsr chk2lm bcs asclia jsr prtcrlf jmp monlo1 ; ---------------------------------------------------------------------------- ; INIT FOR 16 CHARS asclia: ldx #$10 ; LOAD BYTE AND CHECK FOR PRINTABLE CHAR ascchr: ldy #$00 lda (MONADR),y cmp #$20 bcc ascnpr cmp #$80 bcs ascnpr ; PRINT CHAR AND CLOSE LOOP ascprt: jsr prtchr jsr incadr dex bne ascchr beq asclin ; REPLACE UNPRINTABLE CHAR WITH . AND GO TO PRINT ascnpr: lda #'.' bne ascprt ; CHECK IF SECOND ENTERED ADDRESS IS LARGER THAN FIRST chk2l1: sec lda baddr2 sbc baddr1 lda baddr2+1 sbc baddr1+1 rts ; ---------------------------------------------------------------------------- ; COPY FIRST INPUT ADDRESSBUFFER TO ACTUAL MONITOR ADDRESS cpybad: lda baddr1 sta MONADR lda baddr1+1 sta MONADR+1 rts ; ---------------------------------------------------------------------------- ; CHECK IF SECOND ENTERED ADDRESS IS LARGER THAN ACTUAL MONITOR ADDRESS chk2lm: sec lda baddr2 sbc MONADR lda baddr2+1 sbc MONADR+1 rts ; ---------------------------------------------------------------------------- ; START DISASM stdisa: jsr prtcrlf ldy #dismnu ; Display DISASM message jsr prtmsg jsr zerinw jsr iprang bmi stdisa jsr chk2l1 bcc stdisa lda baddr1 ldx baddr1+1 sta MONVEC stx MONVEC+1 ; PRINT CONTROL OPTIONS dishdl: ldy #ctlmnu jsr prtmsg ; GET COMMAND KEY discmd: jsr getcme cmp #$04 beq stdisa cmp #$0C bne dislo2 ; CHECK IF ADDRESS IS IN RANGE AND DISASSEMBLE ONE OPCODE dislo1: jsr chk2lv bcc dishdl jsr LF511 bvc dislo1 ; CHECK CONTROL COMMAND dislo2: cmp #$10 bne dislo4 lda #$13 sta $D8 ; DISASSEMBLE MULTIPLE LINES dislo3: jsr chk2lv bcc dishdl jsr LF511 dec $D8 bne dislo3 beq discmd ; DISASSEMBLE LAST LINE FROM MULTIPLE AND ASK FOR NEW CONTROL dislo4: cmp #$13 bne dislo5 jsr chk2lv bcc dishdl jsr LF511 bvc discmd ; CHECK FOR . COMMAND AND JUMP TO LOOP (ALLOWS . COMMANDS WITHIN DISASM) dislo5: cmp #'.' bne dislox jmp cmdboo ; ---------------------------------------------------------------------------- ; PRINT AND ASK FOR NEW DISASM CONTROL dislox: jsr prtcrlf jmp discmd ; ---------------------------------------------------------------------------- ; CHECK IF SECOND ENTERED ADDRESS IS LARGER THAN ACTUAL MONITOR VECTOR chk2lv: sec lda baddr2 sbc MONVEC lda baddr2+1 sbc MONVEC+1 rts ; ---------------------------------------------------------------------------- ; unused storage ; ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF ; .byte $FF .org $FFFA HNMIVEC:.addr nmifnc HRSTVEC:.addr reset HIRQVEC: LFFFF := * + 1 .addr irqfnc