Jump to content
IGNORED

Help with video glitch


intvnut

Recommended Posts

This topic was originally posted to INTVPROG; however, Yahoo Groups has decided it doesn't like email or group postings from me. (Or maybe from anybody, I don't know.) So, I'm moving it over here. After all, this is a broad-spectrum Intellivision Programming forum, not just an IntyBASIC forum.

 

DZ-Jay posted the following:

_______________________________

 

Hi, Joe (and everyone),

I'm trying to track down a video glitch that I've noticed in my game just recently. In all my testing during the past couple of years I never noticed it until recently, when I upgraded to the latest version of jzIntv.
That is not to say that I am blaming the emulator. I seriously think it could be a timing issue on my code that is made manifest by a more accurate simulation; although I'm hard-pressed to imagine what could cause it. I haven't had a chance to test this in the hardware, but it disturbs me when it happens during emulation.
The glitch manifests as a row in the lower half of the BACKTAB being repeated, causing the screen to shift down by a row -- but only for a single frame. I managed to capture it in an AVI and then took screenshots of the frames before, during, and after the glitch (see attached).
Do you know what could cause this BACKTAB delay? I'm thinking the most likely cause is a non-interruptible sequence that runs for far too long, preventing the BUSQ fetch from happening. However, I don't think I have anything running for more than ~40 cycles at a time (outside of select critical sections).
If indeed it were a non-interruptible sequence causing the glitch, is there a more efficient and targeted way to troubleshoot it than to audit every single line of code? I tried using the "NON_INT" information from the debugger, but I don't think I understand it well. I thought it gave the number of non-interruptible cycles after a particular threshold, but looking at the program counter noted in the CPU history, it does not seem to match.
For instance, the following line from the debugger:
NON_INT = 44 at PC = RUNQ.loop ($BCF4)
Points to the following code, which is obviously interruptible:


RUNQ.loop:
0000 0000 0000 FF5A 01E0 BCF4 02F0 BCF4 S---I-i-  MOVR R7,R5         23192833
0000 0000 0000 FF5A 01E0 BCF5 02F0 BCF5 S---I-i-  DECR R5            23192839
There is indeed a critical section wrapped in DIS/EIS following the loop,
RUNQ.loop:
0000 0000 0000 FF5A 01E0 BCF4 02F0 BCF4 S---I-i-  MOVR R7,R5         23192833
0000 0000 0000 FF5A 01E0 BCF5 02F0 BCF5 S---I-i-  DECR R5            23192839
0000 0000 0000 FF5A 01E0 BCF4 02F0 BCF6 S---I-i-  DIS                23192845
0000 0000 0000 FF5A 01E0 BCF4 02F0 BCF7 S-------  MVII #$0103,R4     23192849
0000 0000 0000 FF5A 0103 BCF4 02F0 BCF9 S-----i-  MVI@ R4,R1         23192857
0000 0004 0000 FF5A 0104 BCF4 02F0 BCFA S-----i-  CMP@ R4,R1         23192865
0000 0004 0000 FF5A 0105 BCF4 02F0 BCFB S-----i-  BEQ  RUNQ.bktsk ($ 23192873
0000 0004 0000 FF5A 0105 BCF4 02F0 BCFD S-----i-  INCR R1            23192880
0000 0005 0000 FF5A 0105 BCF4 02F0 BCFE ------i-  ANDI #$0007,R1     23192886
0000 0005 0000 FF5A 0105 BCF4 02F0 BD00 ------i-  MVO  R1,TSKQTL ($0 23192894
0000 0005 0000 FF5A 0105 BCF4 02F0 BD02 --------  ADDR R1,R4         23192905
0000 0005 0000 FF5A 010A BCF4 02F0 BD03 ------i-  ADDR R1,R4         23192911
0000 0005 0000 FF5A 010F BCF4 02F0 BD04 ------i-  SDBD               23192917
0000 0005 0000 FF5A 010F BCF4 02F0 BD05 -----D--  MVI@ R4,R2         23192921
0000 0005 017E FF5A 0111 BCF4 02F0 BD06 ------i-  ADDI #$0300,R1     23192931
0000 0305 017E FF5A 0111 BCF4 02F0 BD08 ------i-  EIS                23192939
0000 0305 017E FF5A 0111 BCF4 02F0 BD09 ----I---  MVI@ R1,R7         23192943
But it is 94 cycles, not 44, so I'm confused on how to use this particular bit of information effectively.
Any help will be appreciated!
Regards,
- j.

 

post-14113-0-02538700-1517380346.png post-14113-0-36837400-1517380359.png post-14113-0-77865000-1517380372.png

Link to comment
Share on other sites

DZ-Jay provided a follow-on post:

____________________________

 

By the way, the preceding code in the history up to the point of reference by the "NON_INT" report also does not seem to be non-interruptible. For example:

CTRL_CHECKKEY:
BE3E FF43 0000 BCF4 0144 BCF4 02F0 5131 S---I-i- MOVR R5,R3 4459120
BE3E FF43 0000 BCF4 0144 BCF4 02F0 5132 S---I-i- JSR R5,.GET_KEY ( 4459126
..GET_KEY:
BE3E FF43 0000 BCF4 0144 5135 02F0 51AC S---I-i- CLRR R2 4459139
BE3E FF43 0000 BCF4 0144 5135 02F0 51AD ---ZI-i- MVII #$01E9,R1 4459145
BE3E 01E9 0000 BCF4 0144 5135 02F0 51AF ---ZI-i- MVII #$01FE,R4 4459153
BE3E 01E9 0000 BCF4 01FE 5135 02F0 51B1 ---ZI-i- MVI@ R4,R0 4459161
00FF 01E9 0000 BCF4 01FF 5135 02F0 51B2 ---ZI-i- AND@ R4,R0 4459169
00FF 01E9 0000 BCF4 0200 5135 02F0 51B3 ----I-i- XORI #$00FF,R0 4459177
0000 01E9 0000 BCF4 0200 5135 02F0 51B5 ---ZI-i- CMP@ R1,R0 4459185
0000 01E9 0000 BCF4 0200 5135 02F0 51B6 -C-ZI-i- BEQ .GET_KEY.__sa 4459193
..GET_KEY.__same:
0000 01E9 0000 BCF4 0200 5135 02F0 51BE -C-ZI-i- INCR R1 4459202
0000 01EA 0000 BCF4 0200 5135 02F0 51BF -C--I-i- MVI@ R1,R4 4459208
0000 01EA 0000 BCF4 0000 5135 02F0 51C0 -C--I-i- DECR R4 4459216
0000 01EA 0000 BCF4 FFFF 5135 02F0 51C1 SC--I-i- BMI .GET_KEY.__ig 4459222
..GET_KEY.__ignore:
0000 01EA 0000 BCF4 FFFF 5135 02F0 51D3 SC--I-i- MOVR R5,R7 4459231
0000 01EA 0000 BCF4 FFFF 5135 02F0 5135 -C--I-i- TSTR R2 4459238
0000 01EA 0000 BCF4 FFFF 5135 02F0 5136 -C-ZI-i- BEQ CTRL_CHECKKEY 4459244
CTRL_CHECKKEY.__no_key:
0000 01EA 0000 BCF4 FFFF 5135 02F0 515D -C-ZI-i- MOVR R3,R7 4459253
RUNQ.loop:
0000 01EA 0000 BCF4 FFFF 5135 02F0 BCF4 SC--I-i- MOVR R7,R5 4459260
0000 01EA 0000 BCF4 FFFF BCF5 02F0 BCF5 SC--I-i- DECR R5 4459266


I obviously am reading the "NON_INT" report wrong.

-dZ.

Link to comment
Share on other sites

I replied yesterday:

 

NON_INT is reporting a string of instructions that are classified as non-interruptible (MVO, shifts, SDBD, EIS, DIS, TCI, SIN), as opposed to periods with interrupts disabled.

The BACKTAB-row-jumping glitch is associated with non-interruptible instructions, and is not influenced by whether interrupts are disabled. Non-interruptible instructions also block bus DMA requests (BUSRQ*/BUSAK), and that's what causes the STIC glitch. Interrupt disable, OTOH, only masks maskable interrupts (INTRM*), and so does not cause BACKTAB to jump.
You can spot non-interruptible sequences in the register history. The small 'i' in the flags indicates whether the previous instruction is considered "interruptible." A pending BUSRQ will show up as a 'b' in the flags. The instruction that does get preempted by a BUSRQ will be flagged with >> followed by a cycle with a B in place of the b:

.

0000 0000 F760 0100 0200 5E84 034A 581A ---ZI-i-  MVO  R0,$0156      15149636
0000 0000 F760 0100 0200 5E84 034A 581C ---ZI---  CLRR R0            15149647

0000 0000 F760 0100 0200 5E84 034A 581D ---ZI-i-  MVO  R0,$0172      15149653
0000 0000 F760 0100 0200 5E84 034A 581F ---ZI---  MVO  R0,$0343      15149664
0000 0000 F760 0100 0200 5E84 034A 5821 ---ZI--b  B    $5829         15149675
0000 0000 F760 0100 0200 5E84 034A 5829 ---ZI-ib>>  MVI  $0170,R1    15149684  <= preempted by BUSRQ
0000 0000 F760 0100 0200 5E84 034A 5829 ---ZI-iB  MVI  $0170,R1      15149711  <= just finished BUSRQ (note time gap)
0000 00FF F760 0100 0200 5E84 034A 582B ---ZI-i-  SAR  R1,2          15149721

.

The reason the 'i' shows up on the next instruction is that it controls whether that instruction can get pre-empted by a bus request or an interrupt. The "non-interruptibility" behavior is something that happens after the instruction that causes it. The flags always show the state of the machine before the instruction starts, as opposed to what the state of the machine will be after it executes. It shows machine state, not instruction attributes.
jzIntv checks the non-interruptible sequence threshold after executing the first interruptible instruction after a string of non-interruptible instructions. That's because a non-interruptible string of instructions includes the final instruction in the string, and that instruction is always an interruptible instruction. For example, this non-interruptible sequence is 17 cycles—9 cycles for MVO@, and 8 cycles for MVI@—because the CPU won't yield for a BUSRQ until the entire 17 cycles completes:

.

    MVO@ R0, R1   ; 9 cycles
    MVI@ R2, R0   ; 8 cycles

.

Now here's a slightly annoying thing: I'm pretty sure jzIntv will report the above as 9, not 17. This was due to a misunderstanding on my part on how the accounting should work. That's why I dialed the error reporting threshold down so low. It really should be higher, but the reported count should also include the cost of the non-interruptible instruction in the sequence. Here's a slightly longer example:

.

            ORG $7000
            NOP                     ;    $7000
            DIS                     ; 4  $7001
            MVO@    R0,     R1      ; 9  $7002
            MVO@    R0,     R1      ; 9  $7003
            MVO@    R0,     R1      ; 9  $7004
            MVO@    R0,     R1      ; 9  $7005
            MVO@    R0,     R1      ; 9  $7006
            MVO@    R0,     R1      ; 9  $7007
            MVI@    R1,     R0      ; 8  $7008
            NOP                     ;    $7009
            DECR    R7              ;    $700A

.

When you run this in the current jzIntv release, you'll see:

.

> f7000
Starting jzIntv...
Fast forwarded to $7000
 0000 7000 0000 0000 01FE 103D 02F1 7000 ------i-  NOP                     654
> s10
 0000 7000 0000 0000 01FE 103D 02F1 7001 ------i-  DIS                     660
 0000 7000 0000 0000 01FE 103D 02F1 7002 --------  MVO@ R0,R1              664
 0000 7000 0000 0000 01FE 103D 02F1 7003 --------  MVO@ R0,R1              673
 0000 7000 0000 0000 01FE 103D 02F1 7004 --------  MVO@ R0,R1              682
 0000 7000 0000 0000 01FE 103D 02F1 7005 --------  MVO@ R0,R1              691
 0000 7000 0000 0000 01FE 103D 02F1 7006 --------  MVO@ R0,R1              700
 0000 7000 0000 0000 01FE 103D 02F1 7007 --------  MVO@ R0,R1              709
 0000 7000 0000 0000 01FE 103D 02F1 7008 --------  MVI@ R1,R0              718
NON_INT = 58 at PC = $7009
 0034 7000 0000 0000 01FE 103D 02F1 7009 ------i-  NOP                     726
 0034 7000 0000 0000 01FE 103D 02F1 700A ------i-  DECR R7                 732

.


Notice PC shown is for the NOP. The last non-interruptible instruction is the MVI@ before it. The total length of the non-interruptible sequence is 4 + 6*9 + 8 = 4 + 54 + 8 = 66 cycles. However, I report the total as 58. That defect aside...
The address you give appears to be the top of RUNQ's main queue dispatch loop, so whatever task returned to RUNQ had a lengthy non-interruptible sequence, and the return statement was the first interruptible instruction. The NON_INT gets reported after that instruction completes, and by then PC = the top of RUNQ's main loop.
The top of RUNQ's loop will literally have every possible dispatched-to task as its predecessor, so you'll need to catch it on the exact instance NON_INT makes a complaint. I suspect the traces you showed above did not trigger the NON_INT warning.
Clearly this is a PITA. I should try to remember the PC of the last actual instruction in the sequence, and I should include the cost of the last instruction in the non-interruptible sequence. Also, I should consider adding a "halt on STIC BACKTAB glitch" debug flag.
Edited by intvnut
Link to comment
Share on other sites

And later last night:

 

OK, first patch to jzIntv: It will now report the actual range of non-interruptible instructions, and it includes the cost of the terminating instruction:

.

> f 7000
Starting jzIntv...
Fast forwarded to $7000
 0000 7000 0000 0000 01FE 103D 02F1 7000 ------i-  NOP                     654
> s10
 0000 7000 0000 0000 01FE 103D 02F1 7001 ------i-  DIS                     660
 0000 7000 0000 0000 01FE 103D 02F1 7002 --------  MVO@ R0,R1              664
 0000 7000 0000 0000 01FE 103D 02F1 7003 --------  MVO@ R0,R1              673
 0000 7000 0000 0000 01FE 103D 02F1 7004 --------  MVO@ R0,R1              682
 0000 7000 0000 0000 01FE 103D 02F1 7005 --------  MVO@ R0,R1              691
 0000 7000 0000 0000 01FE 103D 02F1 7006 --------  MVO@ R0,R1              700
 0000 7000 0000 0000 01FE 103D 02F1 7007 --------  MVO@ R0,R1              709
 0000 7000 0000 0000 01FE 103D 02F1 7008 --------  MVI@ R1,R0              718
NON_INT = 66 at PC = $7001 .. $7008
 0034 7000 0000 0000 01FE 103D 02F1 7009 ------i-  NOP                     726
 0034 7000 0000 0000 01FE 103D 02F1 700A ------i-  DECR R7                 732
> 

.

(Also notice how it nicely aligns with the 'i' designations in the flags?)
I've also made the default non-interrupt threshold higher (54), and made it programmable with the command 'ni':

.


 0000 0000 0000 0000 0000 1003 0000 1026 --------  MVII #$02F1,R6           13
> h
Register History is On
> ni 20
Setting NON_INT threshold to 20
 0000 0000 0000 0000 0000 1003 02F1 1028 ------i-  JSR  R5,$1A83            22
> f7000
NON_INT = 35 at PC = $1A83 .. $1A86
NON_INT = 24 at PC = $173A .. $173C
NON_INT = 23 at PC = $1A8F .. $1A91
NON_INT = 25 at PC = $1031 .. $1034
NON_INT = 24 at PC = $1037 .. $1039
Fast forwarded to $7000
 0000 7000 0000 0000 01FE 103D 02F1 7000 ------i-  NOP                     654

.

You can see how that low threshold snares some pretty innocuous sequences:

.

 $1031:    0240 0101              MVO  R0,$0101                              
 $1033:    0001                   SDBD                                       
 $1034:    02B8 0014 0050         MVII #$5014,R0

.

...and...

.


 $1037:    0240 02F0              MVO  R0,$02F0                              
 $1039:    0004 0110 001D         JSR  R5,$101D     

.

Second patch to jzIntv: Add 'bb' and 'bi' commands to the debugger. These will halt asynchronously near a dropped BUSRQ or a dropped INTRM, respectively. I've tested this on INTRM at least.

Both of these changes will be in the next jzIntv release.

  • Like 1
Link to comment
Share on other sites

Thanks for that, Joe! I figured out the problem before you posted. One other change I would recommend, which would have gone a long way in helping me troubleshoot this issue, is for the NON_INT message to include the CPU cycle counter. That way, it could be traced in the CPU history and point precisely to the execution path that caused it.

 

By the way, to everyone here: ignore those screenshots... :ponder:

Link to comment
Share on other sites

I didn't think it'd be an issue cross-posting that here, since INTVPROG archives are public, IIRC.

No, no, no issue at all. It's all good. I was being coy as to what the screenshots represent. :)

 

I don't post these questions in AtariAge because most people here just use IntyBASIC, so to me it still feels like the INTV-Prog mailing list is the forum for assembly programming, hardware issues, and other low-level topics.

 

dZ.

Link to comment
Share on other sites

One other change I would recommend, which would have gone a long way in helping me troubleshoot this issue, is for the NON_INT message to include the CPU cycle counter. That way, it could be traced in the CPU history and point precisely to the execution path that caused it.

 

Good idea. I think it should be easy to add.

 

 

No, no, no issue at all. It's all good. I was being coy as to what the screenshots represent. :)

 

Cool.

 

 

I don't post these questions in AtariAge because most people here just use IntyBASIC, so to me it still feels like the INTV-Prog mailing list is the forum for assembly programming, hardware issues, and other low-level topics.

 

I'm not afraid to post assembly language over here. :-) After all, before IntyBASIC, we did that all the time. ;-)

Link to comment
Share on other sites

 

I'm not afraid to post assembly language over here. :-) After all, before IntyBASIC, we did that all the time. ;-)

 

I'm not afraid to post assembly language here. It's just that the INTV-Prog list feels more like the assembly language/SDK-1600 community, to whatever extent it is still a community (it seems you and I are the only ones who post there). Besides, I do not have to log in nor mess with browser idiosyncrasies to post a response or a question. Old school habits, I guess.

 

Anyway, unless you feel the need to close down the mailing list, I will probably continue posting there.

 

-dZ.

Link to comment
Share on other sites

I read with great interest anything about assembler, so I welcome Joe decision to trans-post this.

 

In fact I should put up two or three commented assembler routines I've developed along these years.

 

Also I need to post a small guide to the parts where IntyBASIC isn't so good generating assembler.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...