Upon start the disk boot code initializes the PIA, drive 1 is selected, the code checks for track 0 and keeps stepping down until the signal is active. Then it checks the index signal, looping until it is active and then looping until it is inactive. Then it resets the disk ACIA and starts reading data.
One tool you could use to identify where the code is stuck is the 6502 Non-maskable interrupt.
I wrote an NMI handler that sits between the OSI NMI vector (0130) and the IRQ vector (01C0) using all available space which will print out the instruction address, processor status, registers and stack pointer to the serial port.
To trigger it, you need to pull pin 6 of the 6502 low. Although there is some protection against nested interrupts, it's best if it is a single debounced pulse. (To be honest, I just ground the pin through a 470ohm resistor when I want to trigger it.)
When triggered it will print a line like:
"NI=FD=09 P=A4 A=80 X=00 Y=FF K=24"
Where FD09 is the address of the current instruction being processed
P is the processor status register corresponding to the processor flags NV-BDIZC
A,X,Y are the register values
K is the value of the stack pointer (before interrupt)
Attached is the source and object files for 65A and 65V monitors. After loading the machine should end up back at the reset prompt. The NMI handler should survive RESETs fine.
One caveat is that the interrupt handler is swapped out when disk BASIC is loaded, and would have to be reinstalled when BASIC is running, but that shouldn't be an issue for this problem. (The ACIA address needs to be changed for C1P users).
Good Luck!
Code: Select all
;
;Simple NMI handler for OSI C2/C3/C4/C8
;Will print NMI address and registers to serial port upon interrupt
;Will need to be reinstalled if BASIC is loaded from disk as BASIC swaps stack & zero page out
;code lives in stack between $0130 and $01BF, just below IRQ handler
;To load, start monitor and load code.
;To generate NMI, pull pin 6 of 6502 low temporarily, perhaps with a 470ohm resistor to ground.
;Although multiple interrupts may be generated, they should mostly be ignored when one is being processed
ACIA=$FC00 ;change to $F000 for C1P
*=$0130-7
;0129 Set C3/65A Go address (reset vector) Y=6C, X=FC, A=FF, P=4, k=FD PCh PCl
.BYTE $6C,$FC,$FF,$04,$FD,$01,$29
*=$0130 ;NMI entry point
;CLD
PHA ;we push A
INIRQ=*+1
LDA #$00
BNE NOIRQ ;avoid recursive interrupts
INC INIRQ
TXA
PHA ;we push X
TYA
PHA ;we push Y
LOOP
JSR PRNMSG
OFFSET=*+1
LDA $0108,X ;since X is set in subroutine (TSX), need to add 2 to get real values
JSR PHEXA
DEC OFFSET
CPY #$00
BNE LOOP
JSR PRNMSG
TXA
ADC #$07 ;carry is set from prnmsg
JSR PHEXA ;print stack pointer before interrupt
LDX #$06 ;restore modified values
STX PRNIDX
LDX #$08
STX OFFSET
IRQEXIT ;prepare to return to regularly scheduled pgm
PLA
TYA
PLA
TAX
DEC INIRQ ;2 instruction window of nested interrupts
NOIRQ
PLA
RTI
PRNMSG
LDX #$00
PRNIDX=*+1
LDY #$06 ;start with last msg 1st
MLOOP
LDA MSG,X
BEQ CHKY
CPY #$00
BNE NXTONE ;not interested in this msg, don't print
JSR OUTPUT
NXTONE
INX
BNE MLOOP
CHKY
LDA #$3D
INX
DEY
BPL MLOOP
DEC PRNIDX
LDY PRNIDX
TSX
BNE OUTPUT ;assume K is never 0
; PRINT HEX BYTE (A)
PHEXA
PHA
LSR A
LSR A
LSR A
LSR A
JSR PHEXA1
PLA
PHEXA1
AND #$F
ORA #'0'
CMP #'9'+1
BMI PHEXA2
CLC
ADC #7
PHEXA2
OUTPUT
PHA
OUTPUT1
LDA ACIA ;wait for TxEmpty
LSR A
LSR A
BCC OUTPUT1
PLA
STA ACIA+1
RTS
MSG
.BYTE " K",0
.BYTE " Y",0
.BYTE " X",0
.BYTE " A",0
.BYTE " P",0
.BYTE 0
.BYTE $0D,$0A,"NI",0