safer NMI handling
This commit is contained in:
1 parent
1c118d9bc9
commit
f8e57f1cf2
10 files changed
+114
-19
No files matched your search
@@ -56,7 +56,10 @@ wedge_arrow_L:
|
||||
wedge_arrow_H:
|
||||
|
||||
jsr tape_head_align
|
||||
jmp basic_main_loop
|
||||
|
||||
jsr print_return
|
||||
ldx #B_ERR_BREAK
|
||||
jmp do_basic_error
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,4 +20,8 @@ return_from_interrupt:
|
||||
plx_trash_a
|
||||
pla
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
return_from_interrupt_rti:
|
||||
|
||||
rti
|
||||
@@ -5,17 +5,16 @@
|
||||
|
||||
hw_entry_nmi:
|
||||
|
||||
sei // do not allow IRQ to interfere, see https://www.c64-wiki.com/wiki/Interrupt
|
||||
sei // do not allow IRQ to interfere, see https://www.c64-wiki.com/wiki/Interrupt
|
||||
|
||||
#if CONFIG_CPU_MOS_6502 && CONFIG_BCD_SAFE_INTERRUPTS
|
||||
cld // clear decimal flag to allow using it without disabling interrupts
|
||||
cld // clear decimal flag to allow using it without disabling interrupts
|
||||
#endif
|
||||
|
||||
// Call interrupt routine (only if initialised)
|
||||
pha
|
||||
lda NMINV
|
||||
ora NMINV+1
|
||||
beq !+
|
||||
lda NMINV+1 // consider zeropage NMI address as uninitialized vector
|
||||
beq !+ // this allows safer interrupt vector modifications
|
||||
pla
|
||||
jmp (NMINV)
|
||||
!:
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# * KERNAL_0 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Routine to lock NMI interrupts, using a trick described here:
|
||||
// - https://codebase64.org/doku.php?id=base:nmi_lock
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
// XXX consider broader usage of this method to make IO safer
|
||||
|
||||
|
||||
nmi_lock:
|
||||
|
||||
// We will have to change NMI vector to point empty routine,
|
||||
// which will not acknowledge the interrupt - thus preventing
|
||||
// the NMI to be triggered again
|
||||
|
||||
// Our code considers zeropage address invalid, so put
|
||||
// it there as a preparation
|
||||
|
||||
ldx #$00
|
||||
stx NMINV+1
|
||||
|
||||
// We can now safelly replace the vector
|
||||
|
||||
lda #<return_from_interrupt_rti
|
||||
sta NMINV+0
|
||||
lda #>return_from_interrupt_rti
|
||||
sta NMINV+1
|
||||
|
||||
// Stop timer A
|
||||
|
||||
stx CIA2_CRA // $DD0E
|
||||
|
||||
// Set timer A to 0, after starting NMI will occur immediately
|
||||
|
||||
stx CIA2_TIMALO // $DD04
|
||||
stx CIA2_TIMAHI // $DD05
|
||||
|
||||
// Set timer A as source for NMI
|
||||
|
||||
lda #$81
|
||||
sta CIA2_ICR // $DD0D
|
||||
|
||||
// Start timer A to trigger the NMI
|
||||
|
||||
lda #$01
|
||||
sta CIA2_CRA // $DD0E
|
||||
|
||||
// All done. Unmaskable interrupts are now masked.
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,9 @@ vector_real:
|
||||
sty MEMUSS + 1
|
||||
stx MEMUSS + 0
|
||||
|
||||
lda #$00
|
||||
sta NMINV + 1 // our routine considers this a disabled interrupt
|
||||
|
||||
// Select routine variant - store or restore vectors
|
||||
ldy #$1F
|
||||
bcc vector_restore
|
||||
@@ -30,7 +33,7 @@ vector_real:
|
||||
lda CINV, y
|
||||
sta (MEMUSS), y
|
||||
|
||||
bcs vector_end_loop // branch always
|
||||
bcs vector_end_loop // branch always
|
||||
|
||||
vector_restore:
|
||||
lda (MEMUSS), y
|
||||
|
||||
+10
-3
@@ -22,11 +22,18 @@ panic:
|
||||
jsr setup_vicii
|
||||
jsr clear_screen
|
||||
|
||||
// Disable NMIs - our routine checks for NULL vector
|
||||
// Disable NMIs
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
jsr nmi_lock
|
||||
|
||||
#else
|
||||
|
||||
lda #$00
|
||||
sta NMINV+0
|
||||
sta NMINV+1
|
||||
sta NMINV + 1 // our routine does not allow zeropage vectors
|
||||
|
||||
#endif
|
||||
|
||||
// Display KERNAL PANIC message
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ load_tape_normal:
|
||||
// Start playing
|
||||
jsr tape_common_prepare_cia
|
||||
jsr tape_ask_play
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
jsr tape_prepare_reading
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ load_tape_auto:
|
||||
// Start playing
|
||||
jsr tape_common_prepare_cia
|
||||
jsr tape_ask_play
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
jsr tape_prepare_reading
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
|
||||
@@ -104,6 +104,17 @@ tape_wait_first_pulse:
|
||||
|
||||
tape_wait_play_done:
|
||||
|
||||
lda #$01
|
||||
sta CAS1 // set the interlock
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
rts
|
||||
|
||||
tape_prepare_reading:
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
#if CONFIG_MB_MEGA_65
|
||||
|
||||
// Display confirmation
|
||||
@@ -115,9 +126,6 @@ tape_wait_play_done:
|
||||
|
||||
// Prepare for reading
|
||||
|
||||
lda #$01
|
||||
sta CAS1 // set the interlock
|
||||
|
||||
jsr print_return
|
||||
jmp tape_screen_off_motor_on
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
|
||||
// XXX for Mega65 it can be done more easily, by just disabling the badlines
|
||||
|
||||
// XXX consider "PRESS PLAY ON TAPE" before start, with option to stop
|
||||
// XXX document CONFIG_TAPE_HEAD_ALIGN option
|
||||
// XXX block NMIs
|
||||
// XXX fix Mega65 build compilation issues
|
||||
|
||||
|
||||
@@ -50,12 +48,22 @@ tape_head_align:
|
||||
|
||||
#else
|
||||
|
||||
// Make sure user really wants to launch the tool
|
||||
|
||||
jsr tape_ask_play
|
||||
|
||||
// Disable interrupts, set proper I/O values
|
||||
|
||||
jsr CLALL
|
||||
|
||||
sei
|
||||
|
||||
jsr IOINIT
|
||||
jsr cint_legacy
|
||||
jsr CINT
|
||||
|
||||
jsr nmi_lock
|
||||
|
||||
// Prepare CIA timers
|
||||
|
||||
ldx #$02 // set timer A to 3 ticks
|
||||
jsr tape_common_prepare_cia_by_x
|
||||
@@ -111,8 +119,6 @@ tape_head_align:
|
||||
dey
|
||||
bne !-
|
||||
|
||||
|
||||
|
||||
// Set graphics mode
|
||||
|
||||
lda #$28 // graphics start at $2000, color at $0800
|
||||
@@ -252,7 +258,6 @@ tape_head_align_drawn:
|
||||
beq tape_head_align_loop_1
|
||||
|
||||
|
||||
|
||||
tape_head_align_quit:
|
||||
|
||||
// It makes no sense to return to system, as we already destroyed
|
||||
|
||||
Reference in new issue
Block a user