diff --git a/f256/jr.asm b/f256/jr.asm index 29112ba..25cd646 100755 --- a/f256/jr.asm +++ b/f256/jr.asm @@ -88,6 +88,7 @@ nmi_saved_mmu .byte ? ; victim mmu_ctrl (active LUT) at NMI nmi_saved_io .byte ? ; victim io_ctrl at NMI nmi_saved_slot5 .byte ? ; (unused since Task1) legacy LUT0 slot-5 save nmi_in_progress .byte ? ; non-zero while a handler is active (nested guard) +nmi_entry_src .byte ? ; 0 = Foenix-key break, 1 = BRK (breakpoint/step) nmi_ptr .word ? ; (unused since Task1) legacy header entry pointer nmi_orig_slot4 .byte ? ; victim LUT slot-4 bank displaced by the handler nmi_orig_slot5 .byte ? ; victim LUT slot-5 bank displaced by the handler @@ -95,7 +96,6 @@ nmi_save2 .byte ? ; LUT0 slot-2 saved during the flash->RAM copy nmi_save4 .byte ? ; LUT0 slot-4 saved during the flash->RAM copy nmi_src .word ? ; flash->RAM copy source pointer nmi_dst .word ? ; flash->RAM copy dest pointer -nmi_fillb .byte ? ; fill byte for screen clear .send .section startup ; The following is ALWAYS at $E000 @@ -288,11 +288,9 @@ VIA_IER = $DC0E ; 65C22 VIA Interrupt Enable Register NMI_MON_BANK = $4a ; monitor flash block 0 ($40 + CSV 0a); block 1 = $4b NMI_RAM_LO = $3e ; reserved RAM bank -> victim slot 4 ($8000): image block 0 NMI_RAM_HI = $3f ; reserved RAM bank -> victim slot 5 ($A000): image block 1 -NMI_TEXT_BANK = $3c ; reserved RAM bank: saved victim text page -NMI_COLR_BANK = $3d ; reserved RAM bank: saved victim color page -NMI_SCR_CLEAR = $10 ; cleared color attribute (FG=white, BG=black) +NMI_MEMTEXT_LO = $3b ; reserved RAM banks $3b-$3d: monitor MemText/state MACHINE_ID_REG = $d6a7 -JR2_MID = $18 +JR2_MID = $22 ; $A2 on current JR2 cores, ignoring clock bits [7:6] JR2_SYSRQ_CTRL = $d6b6 ; bit 7: sticky SysRq NMI cause, W1C hw_nmi: @@ -317,7 +315,7 @@ hw_nmi: ; SysRq NMI cause in $D6B6 bit 7. Accept and acknowledge only that cause; ; an IEC NMI must not enter the monitor accidentally. lda MACHINE_ID_REG - and #$1f + and #$3f cmp #JR2_MID bne _nmi_gate_k2 lda JR2_SYSRQ_CTRL @@ -333,10 +331,13 @@ _nmi_gate_k2 beq _nmi_ours jmp nmi_not_ours ; Foenix not held -> ignore _nmi_ours + stz nmi_entry_src ; 0 = entered via Foenix key ; Decline a break INTO the monitor itself: it runs from reserved bank ; NMI_RAM_HI ($3f) in slot 5, so freezing it would clobber its own RAM ; during the flash->RAM copy and could not be resumed. If the victim's ; slot 5 is that bank, ignore the NMI and resume it untouched. + ; (The BRK path in hw_irq joins here, having set nmi_entry_src = 1.) +nmi_selfguard: jsr nmi_edit_vlut lda mmu+5 stz mmu_ctrl ; active LUT0, edit off @@ -349,9 +350,6 @@ _nmi_notmon lda io_ctrl sta nmi_saved_io - ; c2: save the victim's text+color screen and clear it for the monitor - jsr nmi_save_screen - ; --- save the victim's original slot-4 and slot-5 banks --- jsr nmi_edit_vlut ; edit-enable the victim's LUT lda mmu+4 @@ -380,7 +378,16 @@ _nmi_notmon jsr nmi_copy8k ; poke the victim's slot-4 bank into the RAM image's reserved header byte ; (offset 9); RAM_LO is mapped at LUT0 slot4 ($8000), so that is $8009. + ; Bank numbers are <= $3f, so bit 7 is free: set it when the entry was a + ; BRK (breakpoint/step) so the monitor can tell BRK from a Foenix break. + lda nmi_entry_src + beq _poke_key + lda nmi_orig_slot4 + ora #$80 + bra _poke_do +_poke_key lda nmi_orig_slot4 +_poke_do sta $8009 ; block 1: flash NMI_MON_BANK+1 -> RAM_HI lda #$80 @@ -424,9 +431,6 @@ _nmi_notmon sta mmu+5 stz mmu_ctrl - ; c2: restore the victim's text+color screen - jsr nmi_restore_screen - ; --- inject a Foenix-key RELEASE for the resumed program --- ; The victim cached the Foenix PRESS before the break but never saw the ; release (the monitor consumed it), so it still thinks Foenix is held. @@ -512,142 +516,6 @@ _nc1 lda (nmi_src),y bne _nc rts - ; ---- Screen save / restore (c2) --------------------------------------- - ; Runs under LUT0. Saves the victim's text + color pages into reserved - ; RAM banks and clears the screen for the monitor; restores on exit. - ; The 80x60 text/color screens are 4800 bytes each at $C000 (io page 2 - ; = text, io page 3 = color); a reserved bank is mapped into LUT0 slot 4 - ; ($8000) as the copy buffer. - - ; nmi_cp4800: copy 4800 bytes (nmi_src)->(nmi_dst). -nmi_cp4800 - ldx #18 ; 18 full pages -_cp0 ldy #0 -_cp1 lda (nmi_src),y - sta (nmi_dst),y - iny - bne _cp1 - inc nmi_src+1 - inc nmi_dst+1 - dex - bne _cp0 - ldy #0 ; + 192 bytes = 4800 -_cp2 lda (nmi_src),y - sta (nmi_dst),y - iny - cpy #192 - bne _cp2 - rts - - ; nmi_fill4800: fill 4800 bytes at $C000 with nmi_fillb (current io page). -nmi_fill4800 - stz nmi_dst - lda #$c0 - sta nmi_dst+1 - ldx #18 -_fl0 ldy #0 -_fl1 lda nmi_fillb - sta (nmi_dst),y - iny - bne _fl1 - inc nmi_dst+1 - dex - bne _fl0 - ldy #0 -_fl2 lda nmi_fillb - sta (nmi_dst),y - iny - cpy #192 - bne _fl2 - rts - - ; map bank A into LUT0 slot 4 ($8000), saving the displaced bank -nmi_map4 - pha - lda #$80 - sta mmu_ctrl ; edit LUT0 - lda mmu+4 - sta nmi_save4 - pla - sta mmu+4 - stz mmu_ctrl - rts -nmi_unmap4 - lda #$80 - sta mmu_ctrl - lda nmi_save4 - sta mmu+4 - stz mmu_ctrl - rts - - ; nmi_save_screen: save text->$3d, color->$3e, clear screen + home cursor -nmi_save_screen - lda #NMI_TEXT_BANK - jsr nmi_map4 ; $3d -> slot 4 ($8000) - lda #2 - sta io_ctrl ; text page at $C000 - stz nmi_src - lda #$c0 - sta nmi_src+1 ; src = $C000 - stz nmi_dst - lda #$80 - sta nmi_dst+1 ; dst = $8000 - jsr nmi_cp4800 - lda #NMI_COLR_BANK - jsr nmi_map4 ; $3e -> slot 4 (nmi_save4 reused; ok, sequential) - lda #3 - sta io_ctrl ; color page at $C000 - stz nmi_src - lda #$c0 - sta nmi_src+1 - stz nmi_dst - lda #$80 - sta nmi_dst+1 - jsr nmi_cp4800 - jsr nmi_unmap4 - ; clear text (spaces) + color (attr), home the hardware cursor - lda #2 - sta io_ctrl - lda #$20 - sta nmi_fillb - jsr nmi_fill4800 - lda #3 - sta io_ctrl - lda #NMI_SCR_CLEAR - sta nmi_fillb - jsr nmi_fill4800 - lda #2 - sta io_ctrl ; leave text page selected - rts ; cursor is homed by the monitor (after it saves - ; the victim's cursor regs in its c1 block) - - ; nmi_restore_screen: restore text from $3d, color from $3e -nmi_restore_screen - lda #NMI_TEXT_BANK - jsr nmi_map4 - lda #2 - sta io_ctrl - stz nmi_src - lda #$80 - sta nmi_src+1 ; src = $8000 ($3d) - stz nmi_dst - lda #$c0 - sta nmi_dst+1 ; dst = $C000 (text) - jsr nmi_cp4800 - lda #NMI_COLR_BANK - jsr nmi_map4 - lda #3 - sta io_ctrl - stz nmi_src - lda #$80 - sta nmi_src+1 - stz nmi_dst - lda #$c0 - sta nmi_dst+1 - jsr nmi_cp4800 - jsr nmi_unmap4 - rts - ; Not our modifier combo: save area is valid (we are the outer handler); ; restore victim LUT/SP/regs without any slot changes. nmi_not_ours @@ -668,7 +536,7 @@ nmi_reenter ; mistaken for that old key press. Preserve A, which holds the victim LUT. pha lda MACHINE_ID_REG - and #$1f + and #$3f cmp #JR2_MID bne _nmi_reenter_restore lda JR2_SYSRQ_CTRL @@ -697,6 +565,27 @@ hw_irq: phx phy + ; Distinguish a BRK ($00) from a hardware IRQ: in emulation mode the CPU + ; pushes the status with bit 4 (B) = 1 for BRK, 0 for IRQ. A,X,Y were just + ; pushed above the interrupt frame, so pushed-P is at SP+4. + tsx + lda $0104,x + and #$10 + beq _hw_irq_norm + ; --- BRK: dispatch into the break monitor (mirror the hw_nmi prologue, + ; but skip the Foenix gate; X = victim SP from the tsx above). --- + lda mmu_ctrl ; A = victim active LUT + stz mmu_ctrl ; -> kernel LUT (LUT0) + ldy nmi_in_progress + beq + + jmp nmi_reenter ++ sta nmi_saved_mmu + stx nmi_saved_sp + lda #1 + sta nmi_entry_src ; 1 = entered via BRK + jmp nmi_selfguard + +_hw_irq_norm ; Save MMU state and switch to the kernel's MMU table. lda mmu_ctrl ; Get the current mmu state. stz mmu_ctrl ; Switch to the kernel's mmu table. @@ -800,4 +689,3 @@ k2_feature_detect .send .endn -