intvnut Posted January 31, 2018 Share Posted January 31, 2018 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. Quote Link to comment Share on other sites More sharing options...
intvnut Posted January 31, 2018 Author Share Posted January 31, 2018 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. Quote Link to comment Share on other sites More sharing options...
intvnut Posted January 31, 2018 Author Share Posted January 31, 2018 (edited) 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 January 31, 2018 by intvnut Quote Link to comment Share on other sites More sharing options...
intvnut Posted January 31, 2018 Author Share Posted January 31, 2018 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. 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 31, 2018 Share Posted January 31, 2018 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... Quote Link to comment Share on other sites More sharing options...
intvnut Posted January 31, 2018 Author Share Posted January 31, 2018 I didn't think it'd be an issue cross-posting that here, since INTVPROG archives are public, IIRC. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted January 31, 2018 Share Posted January 31, 2018 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. Quote Link to comment Share on other sites More sharing options...
intvnut Posted February 1, 2018 Author Share Posted February 1, 2018 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. Quote Link to comment Share on other sites More sharing options...
Kiwi Posted February 1, 2018 Share Posted February 1, 2018 I'm not afraid to post assembly language over here. :-) After all, before IntyBASIC, we did that all the time. Always good to see assembly code to look at and study. I learned how to program the Atari 2600 using assembly. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted February 1, 2018 Share Posted February 1, 2018 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. Quote Link to comment Share on other sites More sharing options...
+nanochess Posted February 1, 2018 Share Posted February 1, 2018 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.