Thomas Jentzsch Posted March 8, 2020 Share Posted March 8, 2020 The attached ROM (a dead simple variation of How to Draw a Playfield) behaves perfectly in Stella, but it mysteriously rolls like mad on my CRT (how about your's?). ? And if I add one simple NOP (set STOP_ROLL to 1 in the source code), the rolling stops. The code has no branches, only loops which are executed exactly the same each frame. Therefore the timing seems 100% constant. There are also no WSYNCs which are on the edge. So there must be some difference between Stella and real hardware which is new to (at least) me. Or a stupid mistake. Can you help me here and find the reason? Test_Roll_01.bin Test_Roll_01.asm Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted March 8, 2020 Share Posted March 8, 2020 I just tried the test program out on my NTSC standard CRT TV (circa 1997) and it doesn't roll there. But of course that doesn't mean much as TVs are generally designed to be as tolerant as possible. The only thing I can think of is the Overscan timer is expiring too close to the end of a line. Sometimes it hits before and sometimes it hits after causing an occasional extra scanline. So you may have found an edge case in which Stella (maybe the RIOT emulation) might be slightly off from real hardware. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 8, 2020 Share Posted March 8, 2020 Has a stable display on my C= 1084S. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 8, 2020 Author Share Posted March 8, 2020 The timers are not the problem, at least debugging doesn't show any problem. But since it so far only rolls on my TV, I start to wonder if that's the problem. Quote Link to comment Share on other sites More sharing options...
high voltage Posted March 8, 2020 Share Posted March 8, 2020 Quote Link to comment Share on other sites More sharing options...
DEBRO Posted March 10, 2020 Share Posted March 10, 2020 Hi Thomas, On 3/8/2020 at 11:55 AM, Thomas Jentzsch said: But since it so far only rolls on my TV, I start to wonder if that's the problem. This is strange. BTW, is this the same VCS and TV you used to test SWOOPS!? I remember you reporting a similar issue on [stella] that I believe we never diagnosed completely. (Without looking it up) I believe we thought it had to do with activity during VSYNC or not disabling the TIA. I see you are disabling the TIA in this code though. This is very strange. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 10, 2020 Author Share Posted March 10, 2020 SWOOPS! did not enable VBlank. This worked as long as the background was black, but when it was flickering the screen started rolling on some TVs. I double checked this for the test ROM and VBlank is definitely enabled. BTW: Does it roll for you? Quote Link to comment Share on other sites More sharing options...
DEBRO Posted March 10, 2020 Share Posted March 10, 2020 Hi Thomas, 3 hours ago, Thomas Jentzsch said: BTW: Does it roll for you? Sorry, my hardware isn't setup at the moment for me to try. Quote Link to comment Share on other sites More sharing options...
DEBRO Posted March 12, 2020 Share Posted March 12, 2020 Hi Thomas, I noticed a similar coding in Astroblast. In the TimerWait routine there is a NOP instruction after the read to T1024T expires. This is located as locations $F453 - $F460. Since your display rolls in your example without your NOP; try modifying the Astroblast code by removing the NOP at $F458 and see if the screen rolls for you. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 12, 2020 Author Share Posted March 12, 2020 The test ROM rolls on @DirtyHairy's TV too. So it is not my CRT and there must be a problem in the code (and Stella emulation). Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 12, 2020 Author Share Posted March 12, 2020 6 hours ago, DEBRO said: try modifying the Astroblast code by removing the NOP at $F458 and see if the screen rolls for you. I tried, it makes no difference. Quote Link to comment Share on other sites More sharing options...
Dionoid Posted March 12, 2020 Share Posted March 12, 2020 It rolls for me too. Has it something to do with PAL TV's? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 12, 2020 Author Share Posted March 12, 2020 That was my vague idea too. Thanks for confirming. But it could as well be the PAL console instead. Anyway, I would like to understand what exactly triggers the problem. The code is dead simple, so there must be something quite fundamental wrong. Either in my code (likely) or in our understanding of the 2600. Quote Link to comment Share on other sites More sharing options...
DirtyHairy Posted March 12, 2020 Share Posted March 12, 2020 38 minutes ago, Dionoid said: It rolls for me too. Has it something to do with PAL TV's? Yeah, PAL TVs seem to be the common denominator. Unfortunately, I have zero ideas beyond that. Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted March 13, 2020 Share Posted March 13, 2020 Just to be clear, are you guys using the PAL version or the or the PAL60 version? There are a whole pile of systematic tests we could do to box the problem into a smaller area. Honestly, it really seems like the timer is not behaving as expected but we should rule out things that should have no effect first. This is easier done by someone who could build the problem source and test on a TV that is known to be rolling. Using the version of the rom that rolls, consider these initial tests: Note each item is to be tested is independent of each other, with no cascading changes: - Put some some NOP's at the beginning of the rom before START, to effective shift all of the addresses. - Change the RORG addresses. - Use alternative addresses for TIM64T and INTIM. There is actually a lot of different registers that could be tested like the edge detection, but ideally do one at a time. That thread overall is very informative as well as this document for the timer. - Start replacing sections of the code with WSYNC's instead of using the timer, to isolate VBLANK and OVERSCAN reading of INTIM. - Build a new test rom that is stable (with the fix, or a bunch of WSYNC's). Make a new timer routine in the middle of the kernel that changes the background color, and when it is done reset the background color. Use some PF blocks to see if where the timer runs out is the same on your TV as Stella. It would be nice to push this into a smaller place so that we can figure it out. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 13, 2020 Author Share Posted March 13, 2020 (edited) I am only using and providing the 60Hz version. I already tested many of these, plus many more like changing the initial timer values. Currently it seems that a large T1024T might be part of the problem. But that might be completely wrong. Over the weekend I will do more testing. Edited March 13, 2020 by Thomas Jentzsch Quote Link to comment Share on other sites More sharing options...
+stephena Posted March 13, 2020 Share Posted March 13, 2020 42 minutes ago, Thomas Jentzsch said: Currently it seems that a large T1024T might be part of the problem. There's another test ROM floating around (in one of the Stella issues) that displays incorrect values for T1024T too. We never did figure out why. Perhaps this is related?? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 14, 2020 Author Share Posted March 14, 2020 I suppose you are referring to this issue: https://github.com/stella-emu/stella/issues/108 Quote Link to comment Share on other sites More sharing options...
alex_79 Posted April 1, 2020 Share Posted April 1, 2020 (edited) I confirm that it rolls on my PAL CRT too. I hooked up a cheap logic analizer to my vader console to see what's happening. I slightly modified the test rom: I set COLUBK to $02 for the entire display, and used the playfield for the white bar at the top. In this way I can see when the video is blanked (during HBLANK and VBLANK periods) by monitoring the "LUM0" pin of the TIA. (PAL TIA lacks the "BLANK" pin that you can find on the NTSC version). So it turns out that the "ROLL" rom (without the extra "nop") outputs 238 scanlines instead of 262. In particular, the VBLANK area after the three VSYNC lines is only 6 scanlines instead of 30. All the other values are the same: no roll: vsync 3 vblank 30 display 205 overscan 24 -------------------- total 262 roll: vsync 3 vblank 6 <========= display 205 overscan 24 --------------------- total 238 Here are a couple of pitures showing the signals: the large area where LUM0 pin is low is when VBLANK is set in the TIA (that corresponds to the Overscan + Vertical Sync + Vertical Blank) In the corresponding area of the CSYNC pin you can clearly see the three scanlines where VSYNC is set. Note how the Vertical blank area between the end of VSYNC and the start of the display (LUM0) is much shorter in the "ROLL" rom. "NO ROLL": "ROLL" Test_Roll_02.zip Edited April 1, 2020 by alex_79 5 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 1, 2020 Author Share Posted April 1, 2020 Many thanks for the analysis. ? So it is the VBlank overscan timer loop (and not the T1024T timer) which is not working correctly. Which still leaves the question what is happening here. Ideas welcome! Quote Link to comment Share on other sites More sharing options...
RevEng Posted April 1, 2020 Share Posted April 1, 2020 Some other things to try... Is there any change if you use bpl for the INTIM test, rather than bne? test hypothesis: INTIM is briefly returning zero incorrectly. Is there any change If you write the overscan value to TIM64T twice? test hypothesis: TIM64T is failing to be correctly updated. On that second test, some elaboration is probably needed; in my own experiments, double-writes seem to resolve RIOT timer update issues on the 7800 when it's running at 7800 mode speed. (RIOT timers are known to be unreliable in this mode.) Since this fix may be specific to 7800 mode, continued bad timing with double-writes doesn't disprove this hypothesis, but if the bad timing goes away, it would strengthen the hypothesis. If bad timing does go away, I think you'd want to retest with either write replaced to another destination, to confirm it didn't go away due to simple timing change. 1 Quote Link to comment Share on other sites More sharing options...
alex_79 Posted April 1, 2020 Share Posted April 1, 2020 5 hours ago, RevEng said: Is there any change if you use bpl for the INTIM test, rather than bne? test hypothesis: INTIM is briefly returning zero incorrectly. No change, it still rolls 5 hours ago, RevEng said: Is there any change If you write the overscan value to TIM64T twice? test hypothesis: TIM64T is failing to be correctly updated. Tried with double writes and then replacing one of the two with a write to SWCHA: TIM64T twice: stable TIM64T SWCHA: rolls SWCHA TIM64T: stable Test_Roll_write_TIM64T_twice.binTest_Roll_write_TIM64T_SWCHA.binTest_Roll_write_SWCHA_TIM64T.binTest_Roll_bpl.bin So it seems that the fail to update TIM64T depends on the specific timing of the write. I also tried again the previous rom (bne for INTIM test, single write to TIM64T), by using the "enable interrupt" addresses for writes to TIM64T ($029e) e read from INTIM ($028c) and connected the logic analyzer also to the RIOT IRQ pin (which isn't connected to anything in the VCS) and to the RDY pin of the TIA (which help identifying when WSYNC is strobed). I tested both the "ROLL" and "NO ROLL" (with extra "nop") versions: In both roms, the interrupt is set slightly before the start of VSYNC (which indicates that the Timer wraps around from 0 to $FF and starts counting down at 1 clock decrement). In the pictures below, I circled in yellow the write access to TIM64T. Note that while in the "NO ROLL" rom, the interrupt is immediately reset after that write, it stays set in the "ROLL" one. Test_Roll_Timer_int_ROLL.binTest_Roll_Timer_int_NO_ROLL.binTest_Roll_Timer_int.asm NO ROLL: detail: ROLL: detail: I attach here the samples from the logic analyzer. They can be opened with the "Pulseview" software, and exported in various formats. Test_Timer_int_roll.srTest_Timer_int_noroll.sr The signals I used are the following (TIA is the PAL version) TIA pin 11 TIA CLK TIA pin 4 CPU CLK TIA pin 2 CSYNC TIA pin 7 LUM0 TIA pin 5 LUM1 RIOT pin 25 RIOT IRQ RIOT pin 35 R/W TIA pin 3 RDY 3 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 1, 2020 Author Share Posted April 1, 2020 42 minutes ago, alex_79 said: Note that while in the "NO ROLL" rom, the interrupt is immediately reset after that write, it stays set in the "ROLL" one. So what does that mean? In the "ROLL" case the write to TIM64T is ignored? Quote Link to comment Share on other sites More sharing options...
alex_79 Posted April 1, 2020 Share Posted April 1, 2020 According to the Stella debugger, right before the write to TIM64T at $f02e, the INTIM value is "03", and the interrupt flag in TIMINT is set, so it's counting at 1 clock increment. The write takes 4 cycles. I think that this write that happens while the timer wraps around with the interrupt set is the cause of the strange behaviour. What happens normally when the interrupt is set, and the timer counts down at a 1 clock increment if there are no read or writes to the timer and it wraps around again to $FF? Is the interrupt cleared and the timer resumes counting at the divider that was set before, or it stays set and the timer keeps counting at 1 clock rate? 2 Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted April 1, 2020 Author Share Posted April 1, 2020 42 minutes ago, alex_79 said: I think that this write that happens while the timer wraps around with the interrupt set is the cause of the strange behaviour. Hm, that seems to make sense. But then, why did this not happen more frequently before? The pattern (wait for timer, vertical sync, start new timer) is pretty common. 42 minutes ago, alex_79 said: What happens normally when the interrupt is set, and the timer counts down at a 1 clock increment if there are no read or writes to the timer and it wraps around again to $FF? Is the interrupt cleared and the timer resumes counting at the divider that was set before, or it stays set and the timer keeps counting at 1 clock rate? No clue. I could only lookup what Stella is doing. And that might be wrong. 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.