Page 1 of 1

NMI Restart

Posted: Mon Sep 05, 2022 7:33 am
by chysn
All right, I need what my former co-worker called a "stupid check." Every one of my games restarts when the user presses RESTORE. And I've always done something along the lines of the following. But in this case, it only works once. On first run, the screen color changes. Press RESTORE, the screen color changes again. But that's it. I've been pouring over the ROM disassembly and trying things for an hour.

Code: Select all

* = $1200

; Initialize 
Init:       lda #<Target        ; Install the custom NMI (restart)
            sta $0318           ; ,, 
            lda #>Target        ; ,,
            sta $0319           ; ,, 
            ; Fall through to Target

; Do something
Target:     ldx #$fb            ; Reset stack for NMI restart
            txs                 ; ,,
            cli                 ; Clear SEI from $FEA9 in ROM
            inc $900f           ; Do some visible thing, it doesn't matter what
forever:    jmp forever         ; And then do nothing
VICE says the NMI vector is the same after RESTORE. $FEA9 is the hardware vector, and that just does this:

Code: Select all

LAB_FEA9
	SEI				; disable interrupts
	JMP	(LAB_0318)		; do NMI vector
I'm sure this is something simple, but what the heck? I'd hate to think that my games have worked correctly for two years by some accident.

Re: NMI Restart

Posted: Mon Sep 05, 2022 7:59 am
by srowe
Are you reading the VIA to clear the interrupt? NMI is edge triggered if you don't clear the source it won't fire again.

Edit: the KERNAL uses a BIT to do this

https://eden.mose.org.uk/gitweb/?p=rom- ... EAD#l15468

Re: NMI Restart

Posted: Mon Sep 05, 2022 8:18 am
by chysn
Oh, jeez, thank you so much! :D Works like a charm. For anyone reading this in the future, it's

Code: Select all

bit $9111

Re: NMI Restart

Posted: Mon Sep 05, 2022 12:22 pm
by groepaz
I fell into the same trap on vic20 :) (on c64 the NMI line goes directly to the CPU, so no ACKing is required)

Re: NMI Restart

Posted: Mon Sep 05, 2022 1:24 pm
by rhurst
OK, a "custom" restart is wanted here. FWIIW, since the VIC did not come standard with a hardware reset, I was never a fan of games not allowing for a soft reset that would return the machine back to normal control. And the built-in Run/Stop RESTORE was no guarantee after the better games "took over" the machine. I've always felt RESTORE alone should do that for me in the "VIC friendly" way:

Code: Select all

; enable RESTORE key as RESET
LDX $FFFC
LDY $FFFD
STX $0318
STY $0319

Re: NMI Restart

Posted: Mon Sep 05, 2022 5:56 pm
by chysn
rhurst wrote: Mon Sep 05, 2022 1:24 pm I was never a fan of games not allowing for a soft reset that would return the machine back to normal control. And the built-in Run/Stop RESTORE was no guarantee after the better games "took over" the machine.
In this case, I'm differentiating between RESTORE and STOP/RESTORE. RESTORE will restart the game, and STOP/RESTORE behaves as usual.

Re: NMI Restart

Posted: Thu Sep 08, 2022 1:53 am
by tlr
rhurst wrote: Mon Sep 05, 2022 1:24 pm OK, a "custom" restart is wanted here. FWIIW, since the VIC did not come standard with a hardware reset, I was never a fan of games not allowing for a soft reset that would return the machine back to normal control. And the built-in Run/Stop RESTORE was no guarantee after the better games "took over" the machine. I've always felt RESTORE alone should do that for me in the "VIC friendly" way:

Code: Select all

; enable RESTORE key as RESET
LDX $FFFC
LDY $FFFD
STX $0318
STY $0319
My take is:

Code: Select all

nmi_entry:
	ldx	#$7f
	stx	$911e	; disable VIA NMI interrupts
	inx
	stx	$9002	; screen width = 0
	stx	$900e	; vol = 0, (aux = orange)
	stx	$900f	; border = black, (background = orange)
	jmp	($fffc)
If you are running periodic NMI's in your code I find that the KERNAL reset code sometimes locks up, hence the added disabling of VIA interrupts.

Re: NMI Restart

Posted: Thu Sep 08, 2022 2:07 am
by srowe
tlr wrote: Thu Sep 08, 2022 1:53 am If you are running periodic NMI's in your code I find that the KERNAL reset code sometimes locks up, hence the added disabling of VIA interrupts.
Because the primary vector in the KERNAL is just set to jump to a vector in page 3 if an NMI goes off before (or while) the vector is written by the cold start routine the CPU is going to go off to a random address. Disabling the IER will stop this from happening for any interrupts coming from the VIA but there's nothing you can do about NMIs triggered from the expansion port.

Re: NMI Restart

Posted: Thu Sep 08, 2022 2:47 am
by tlr
srowe wrote: Thu Sep 08, 2022 2:07 am
tlr wrote: Thu Sep 08, 2022 1:53 am If you are running periodic NMI's in your code I find that the KERNAL reset code sometimes locks up, hence the added disabling of VIA interrupts.
Because the primary vector in the KERNAL is just set to jump to a vector in page 3 if an NMI goes off before (or while) the vector is written by the cold start routine the CPU is going to go off to a random address. Disabling the IER will stop this from happening for any interrupts coming from the VIA but there's nothing you can do about NMIs triggered from the expansion port.
Probably, yes. It would have been better if the KERNAL initialized the VIA's before wiping the vectors. In the C64 KERNAL this order has been corrected and the CIA's are initialized first.

Re: NMI Restart

Posted: Thu Sep 08, 2022 3:54 am
by Mike
tlr wrote:Probably, yes. It would have been better if the KERNAL initialized the VIA's before wiping the vectors. In the C64 KERNAL this order has been corrected and the CIA's are initialized first.
One should add, that the VIAs are connected to the /RESET line and have both their IERs/IFRs cleared and ports set to input upon reset, so this oversight in the VIC-20 KERNAL does not matter in case of a hard reset (with power on, push button or more intricate logic).

If the "full" reset sequence is performed by KERNAL, even if the NMI vector survived, there still might be the A0CBM signature of the cartridge present, so the more intricate logic I mentioned above optionally opens and pulls high the /BLK5 signal to the cartridge for a split second, together with /RESET. The KERNAL then does not find the signature and you end up in the normal startup screen.