Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 38 additions & 150 deletions f256/jr.asm
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ 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
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
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -800,4 +689,3 @@ k2_feature_detect

.send
.endn