Page 1 of 1

Senior Moment With SCNKEY

Posted: Sat Nov 30, 2013 7:26 am
by FD22
As per the title, I'm convinced I'm having a senior moment with SCNKEY at $EB1E; I've obviously just forgotten something elementary here and can't see the wood for the trees. Running this is VICE is doing something odd:

Code: Select all

; wait for selection
.waitkey	jsr _SCNKEY					; [6]	scan keyboard
			  lda _KEYPRESS				 ; [3]	ZP get key scan code
			  cmp #$3B					   ; [2]	keycode for '8'
			  beq .relblk5				  ; [2/3] relocate to 8K block 5
			  cmp #$01					   ; [2]	keycode for '3'
			  beq .relblk0				  ; [2/3] relocate to 3K block 0
			  cmp #$3C					   ; [2]	keycode for '0'
			  bne .waitkey				  ; [3/2] keep scanning if not a valid key
Dead simple, right? Call SCNKEY at $EB1E, get the scancode from $C5, test to see if it was '8', '3' or '0' (fall out of the loop if '0') and keep iterating until one comes up. So why are some other keys sometimes registering as one of the three I'm looking for (e.g. pressing 'H', sometimes once, sometimes a few times) drops #$3B into $C5 and registers as '8'? If I do a PEEK(197) loop in BASIC this never happens.

I'm at the point where I'm studying the SCNKEY code to see if I can find a subtle speed-related bug relating to the code-table lookup; maybe the VIA strobe logic and/or the scancode lookup fails intermittently if the routine is called in a tight loop instead of just on the IRQ...? I've got interrupts disabled at this point, by the way.

This can't be right. I must be missing something obvious. Maybe it's the VICE keyboard table not playing-nice with this laptop...

Re: Senior Moment With SCNKEY

Posted: Sat Nov 30, 2013 10:25 am
by buzbard
Why not skip the SCNKEY and just read the current key being pressed at $CB?

Re: Senior Moment With SCNKEY

Posted: Sat Nov 30, 2013 12:58 pm
by FD22
Because it's SCNKEY that updates $CB and $C5. The keycode for the current keypress is read from the keycode table based on the VIA port-scan result and dropped into $CB - this is then checked against $C5 which holds the keycode from the previous SCNKEY pass, to see if auto-repeat is needed. The last thing SCNKEY does is drop the value it has stashed in $CB into $C5 as well, ready for the next pass.

Normally this happens as part of the regular IRQ processing - SCNKEY is called from the ISR at $EABF; but if you have interrupts disabled, there's no ISR running and therefore SCNKEY isn't updating $CB/$C5. Thus, to read the keyboard, I call SCNKEY and read $C5 (although that's just an arbitrary choice - I could just as easily read $CB instead, since they're essentially the same thing).

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 3:12 am
by tlr
FD22 wrote:Normally this happens as part of the regular IRQ processing - SCNKEY is called from the ISR at $EABF; but if you have interrupts disabled, there's no ISR running and therefore SCNKEY isn't updating $CB/$C5. Thus, to read the keyboard, I call SCNKEY and read $C5 (although that's just an arbitrary choice - I could just as easily read $CB instead, since they're essentially the same thing).
So you do have IRQs disabled at all times, right? Otherwise you've got a problem. SCNKEY isn't thread safe.

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 4:04 am
by FD22
Oh yes, quite definitely; this is the initialisation phase of something that runs in the IRQ, so my very first instruction is SEI because I'm twiddling the IRQ vector. In any case, the entire ROM is pretty-much thread-unsafe, so it's not an assumption I would ever make. ;)

In fact, the keypress check is for a small selection menu giving the choice of where to relocate my IRQ routine (and its associated data structures) to, so interrupts have to be disabled here because the final values for the IRQ vector adjustment are decided and set just after this.

I'm wondering if this is a VICE peculiarity. It looks suspiciously like a keyscan column misfire, because for example I'm looking for '8', but 'U', 'H' and 'B' can also return the same scancode if I hit them two or three times in quick succession.

Anyone else seen this? Or am I doing something daft here?

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 4:45 am
by tlr
I'm using scnkey directly in fcbpaint and that doesn't have any problems.

Your code looks ok. It's hard to tell what the problems are without seeing more of the environment it lives in.

Are you perhaps running this from cartridge code and in that case are the VIA DDR regs correctly set up?

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 5:39 am
by FD22
Alright, here you go - the code from the beginning to the point where I'd do some relocation of the IRQ routine based on the selection. This is running on a standard 8K-expanded VIC, with a BASIC line stub just before this with a SYS pointing at 'begin'. The program is loaded as a normal .PRG at $1200 and works as far as it goes; the only problem is that keys other than '0', '3' or '8' are returning scancodes which match (i.e. 'U', 'H' and 'B' can be hit in quick succession and produce $3B).

Code: Select all

Removed - completely re-organised following _STROUT interrupt revelation below

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 5:55 am
by tlr
FD22 wrote:

Code: Select all

			lda #<_LISTMSG				; [2]	title message start lo-byte
			ldy #>_LISTMSG				; [2]	title message start hi-byte
			jsr _STROUT					; [6]	display string
I'm guessing that _STROUT = $cb1e, right? In any case something that calls CHROUT ($ffd2) will enable interrupts...

Disabling it again before the call to SCNKEY will probably do the trick.

Re: Senior Moment With SCNKEY

Posted: Sun Dec 01, 2013 11:29 am
by FD22
Yep, _STROUT = $CB1E.

Oh holy blap, you're right - interrupts ARE being enabled by _STROUT, as it falls through _SETSPRNT at $E6C5. Why the hell does it do that?? That has got to be a typo in the original ROM source, since it follows a CLC; there's just no reason to do a CLI there.

:shock:

Re: Senior Moment With SCNKEY

Posted: Tue Dec 03, 2013 6:58 am
by wimoos
This may very well have to do with the function of the CTRL-key during PRINT.

Regards,

Wim.

Re: Senior Moment With SCNKEY

Posted: Tue Dec 03, 2013 1:09 pm
by groepaz
This may very well have to do with the function of the CTRL-key during PRINT.
... and the function of run/stop during disk operations, yes.

Re: Senior Moment With SCNKEY

Posted: Tue Dec 03, 2013 3:02 pm
by FD22
Agreed - but those conditions should either be checked-for in STROUT, or better yet handled outside it. To just arbitrarily enable interrupts in a character-output routine is irresponsible, and is bound to trip people up. Me, for example. ;)

Re: Senior Moment With SCNKEY

Posted: Wed Dec 04, 2013 9:36 am
by groepaz
hehe, it probably saved a byte or two somewhere.... the irq is disabled during some IEC operations, i guess this cli makes sure they are enabled afterwards :)

Re: Senior Moment With SCNKEY

Posted: Wed Dec 04, 2013 1:36 pm
by FD22
Oh, doubtless it's probably saving a few bytes somewhere. Now, let's just count the NOPs in the ROM, shall we...? ;)

Anyway, problem solved. The screen I/O code is now outside the interrupt-disabled area, so it's all good.

EDIT: I did. 113.