VGA vs. NTSC timings are not giving the same desired output
Re: VGA vs. NTSC timings are not giving the same desired output
I don't have a way to test composite mode on my hardware, but I think the scanline register in the emulator is wrong when in NTSC mode, as you've discovered. There's an issue already open because someone agreed with you that it smelled fishy, and I've added some info there.
Re: VGA vs. NTSC timings are not giving the same desired output
I was thinking about what can be the problem with waiting too long on a scanline, and wonder if the acknowledgement of the IRQ LINE must happen before or after the NOPs? What if a new IRQ LINE is generated while still processing the interrupt, even if the scanline number was changed (doesn't make any sense). Then we have this annoying 9th bit of the scanline number which is different on read and write, and who knows if there is a sync issue when the hardware or emulator fetches those.
My game is much more complex compared to the test I made for this thread, with the game and interrupts not corrupting VERA state etc. But my knowledge of 6502 interrupt logic is in its infancy, with less than a year of learning a whole new CPU architecture.
My game is much more complex compared to the test I made for this thread, with the game and interrupts not corrupting VERA state etc. But my knowledge of 6502 interrupt logic is in its infancy, with less than a year of learning a whole new CPU architecture.
It's basically wrong with timings and even interlaced vs. progressive. But, the VGA is also wrongly timed when compared to the real hardware so I don't think one fix would solve all problems. The emulator will probably be fixed once people like me write games that will show up differently compared to real hardware... At least that is my hope.in the emulator is wrong when in NTSC mode
Re: VGA vs. NTSC timings are not giving the same desired output
1) Any interrupts you don't acknowledge will immediately cause another IRQ the moment you return from your ISR.
2) If another IRQ happens during your ISR, it won't trigger another IRQ as long as you didn't touch the CPU's "I" flag, but it will still set the appropriate bit in $9F27. Ideally, you'd structure your code such that you don't unexpectedly run into another line IRQ while you're already in your line ISR, but if you need to, the way you'd check for this is by acknowledging the line IRQ at the beginning, then checking $9F27 at the end to see if the bit is set again.
3) I see that your ISR always acknowledges both LINE and VBLANK IRQs regardless of which one actually hit. If your LINE ISR stretches past the time where the VBLANK IRQ happens, then your ISR will accidentally acknowledge the VBLANK IRQ and skip it entirely, so be sure not to acknowledge the VBLANK IRQ until the VBLANK path in your ISR runs.
4) If you know your line ISR will always be at risk of overlapping VBLANK IRQs, you can check for the VBLANK flag in $9F27 at the end of your line ISR and jump straight to your VBLANK ISR and save yourself the round-trip of POP/RTI/AnotherIRQ/PUSH.
2) If another IRQ happens during your ISR, it won't trigger another IRQ as long as you didn't touch the CPU's "I" flag, but it will still set the appropriate bit in $9F27. Ideally, you'd structure your code such that you don't unexpectedly run into another line IRQ while you're already in your line ISR, but if you need to, the way you'd check for this is by acknowledging the line IRQ at the beginning, then checking $9F27 at the end to see if the bit is set again.
3) I see that your ISR always acknowledges both LINE and VBLANK IRQs regardless of which one actually hit. If your LINE ISR stretches past the time where the VBLANK IRQ happens, then your ISR will accidentally acknowledge the VBLANK IRQ and skip it entirely, so be sure not to acknowledge the VBLANK IRQ until the VBLANK path in your ISR runs.
4) If you know your line ISR will always be at risk of overlapping VBLANK IRQs, you can check for the VBLANK flag in $9F27 at the end of your line ISR and jump straight to your VBLANK ISR and save yourself the round-trip of POP/RTI/AnotherIRQ/PUSH.
Re: VGA vs. NTSC timings are not giving the same desired output
I made an experimental change this weekend that moved the timing of the line interrupt to the end of active display. I ran it using the test program here. While it did move the location where the background color changes earlier, it was still in the visible area of the display. I did not expect this; it should have given roughly 12 microseconds between the end of active display of one line and the beginning of another. I'll continue digging in.
Regardless, the experimental change negatively affected some existing software. If this change were to go into VERA, it would have to be done as a special type of line interrupt to prevent breaking existing software.
Regardless, the experimental change negatively affected some existing software. If this change were to go into VERA, it would have to be done as a special type of line interrupt to prevent breaking existing software.
Re: VGA vs. NTSC timings are not giving the same desired output
It has been known for some time that there is no time to make it to our own interrupt code, but we should have had a chance by placing the interrupt at the end of the visual scanline instead of at the beginning, but we can still do something with the current setup, like waiting in the interrupt until the end of the active area (which works in VGA but not in NTSC for some odd reason)!
My first entry of this thread talks about the scroll registers before even going into the more visual backdrop color change. There is a hidden timing per scanline where the scroll registers latch (for future rendering of a scanline), and that is not fully set in stone (emulators guess this quite badly, I am afraid). With the current problems of the NTSC (that is both Composite and S-video) timings, those scroll registers are also latched at some other hidden time compared to the VGA.
The priority should be to find the NTSC problem (if there is one), and then work our way to find a safe way to set the scroll registers per scanline (only in 240p at the moment), so that current software can still work, but newer ones will benefit from adding parallax scrolling and other raster effects commonly used by other consoles and 8-bit computers.
Also thank you for testing things! I will write a new test right now that will move the sprite (mouse cursor) to whatever the scanline counter is (cache the counter, then write that to the sprite's Y coordinate), to hope find something odd. Since we can't print the value or pause the machine to read the registers, I am hoping that a visual sprite can indicate if something is bad about the counter itself. I'll post my findings later as well as respond to DragWx's post.
Re: VGA vs. NTSC timings are not giving the same desired output
Yes, but when I did just acknowledge vblank by itself, no matter if I had set the scanline to go off at 436 (before leaving vblank isr), IRQ LINE triggered directly at scanline 481 instead (in the official emulator with VGA).
As mush as I hate the round-trip, my game have quite many cycles to squeeze in between 2 scanlines (remember, 240p). Not many cycles, but enough to warrant using the raster effect in the first place.
So I did a test with the mouse cursor following the interrupted scanline, and using those 169 NOPs required by NTSC and it actually looks like it worked (at double scanline 118, do one black, then one red, and so on for 22 double scanlines; set sprite Y to scanline counter): I have no idea if there are actually cycles left inbetween those scanlines, but I really hope so.
So this test proves the (read only) scanline counter works on the real hardware.
Does NTSC work then? Possibly. I need a way to test some game logic outside of interrupt time, like another sprite moving a distance. Also I need to find when the scroll registers are latched for a particular scanline.
Attachment includes the source and program for this test, which can probably help making the emulators better (they completely fail all NTSC but also VGA timings)
Re: VGA vs. NTSC timings are not giving the same desired output
There are a few things that affect timing. One of the most significant is that each line is rendered into an 8-bit line buffer before scanout. Because of this, changes to the palette will take place immediately, but changes to line rendering (e.g. scaling) will not be visible until the line is scanned out. The change to scaling takes place close to immediately (worst case by the time the next block of data is pulled from memory) but it is not immediately visible.doslogo wrote: ↑Mon May 12, 2025 8:41 pmIt has been known for some time that there is no time to make it to our own interrupt code, but we should have had a chance by placing the interrupt at the end of the visual scanline instead of at the beginning, but we can still do something with the current setup, like waiting in the interrupt until the end of the active area (which works in VGA but not in NTSC for some odd reason)!
My first entry of this thread talks about the scroll registers before even going into the more visual backdrop color change. There is a hidden timing per scanline where the scroll registers latch (for future rendering of a scanline), and that is not fully set in stone (emulators guess this quite badly, I am afraid). With the current problems of the NTSC (that is both Composite and S-video) timings, those scroll registers are also latched at some other hidden time compared to the VGA.
The priority should be to find the NTSC problem (if there is one), and then work our way to find a safe way to set the scroll registers per scanline (only in 240p at the moment), so that current software can still work, but newer ones will benefit from adding parallax scrolling and other raster effects commonly used by other consoles and 8-bit computers.
Also thank you for testing things! I will write a new test right now that will move the sprite (mouse cursor) to whatever the scanline counter is (cache the counter, then write that to the sprite's Y coordinate), to hope find something odd. Since we can't print the value or pause the machine to read the registers, I am hoping that a visual sprite can indicate if something is bad about the counter itself. I'll post my findings later as well as respond to DragWx's post.
It should be possible to wait until the end of active display in composite mode, but one must remember that individual lines scanout at roughly half the speed in composite mode compared to VGA.
Re: VGA vs. NTSC timings are not giving the same desired output
I don't think there is any bug in NTSC on real hardware. The problem all along was that it does take a long time until the scanline has been rendered compared to VGA, but after that, there is no odd scanline but rather just the next scanline. This causes a delay to starve any remaining code outside the interrupt service routine where the VGA had at least the next scanline (the "double scanline" in the 320x240 scaled screen).
How do you get that time back and still be able to do the raster effect scanline? Well, there is only one way, and that is to set up a VIA timer. They are very unreliable between reboots so any dynamic timing is out of the question, but if you align a timer in the IRQ LINE to count down as a simulation of those NOPs that would otherwise be more reliable, you will get this result:
My new capture card and S-video helps to see that we have some kind of delay that is synchronized to scanlines, and I made the VIA timer just a little short so you can see the edge wobble. By adding a few more counts to the timer, and those will be invisible. A normal TV will hide that area anyways.
So what's the problem here? Well, first, I have no idea if the non-interrupt code is being starved since the interrupt return trip is now doubled (one for LINE and one for VIA timer1), and the other problem is the mouse cursor missing on some scanlines! <- This is a similar problem to deal with like when knowing when a scroll register "latches". Just because we can change a color doesn't mean that we can set a scroll value or a sprite offset before it is too late for that scanline. The reliable way currently is to pray.
This test project can help developing the emulators to get closer to the real hardware. Because the official emulator can't even get close to showing what you see in the animated gif above. But in its current state, it doesn't help that much:
How do you get that time back and still be able to do the raster effect scanline? Well, there is only one way, and that is to set up a VIA timer. They are very unreliable between reboots so any dynamic timing is out of the question, but if you align a timer in the IRQ LINE to count down as a simulation of those NOPs that would otherwise be more reliable, you will get this result:
My new capture card and S-video helps to see that we have some kind of delay that is synchronized to scanlines, and I made the VIA timer just a little short so you can see the edge wobble. By adding a few more counts to the timer, and those will be invisible. A normal TV will hide that area anyways.
So what's the problem here? Well, first, I have no idea if the non-interrupt code is being starved since the interrupt return trip is now doubled (one for LINE and one for VIA timer1), and the other problem is the mouse cursor missing on some scanlines! <- This is a similar problem to deal with like when knowing when a scroll register "latches". Just because we can change a color doesn't mean that we can set a scroll value or a sprite offset before it is too late for that scanline. The reliable way currently is to pray.
This test project can help developing the emulators to get closer to the real hardware. Because the official emulator can't even get close to showing what you see in the animated gif above. But in its current state, it doesn't help that much: