RevEng Posted May 2, 2020 Share Posted May 2, 2020 Like with many other systems, a vertical scroll routine on the 7800 is a combination of fine-scrolling and coarse scrolling. The coarse scroll is just a straightforward change of data being displayed in each zone, so I won't talk about that. The fine scroll is where the interesting stuff happens. The usual approach to fine-scroll upwards on the 7800 is to to decrease the height of a zone at the top of your scroll area, and correspondingly increase the height of a zone at the bottom of your scroll area. (swap "increase" and "decrease" in the previous sentence to fine-scroll downwards) The other thing you need to do on the 7800 is you need to set an interrupt that runs prior to the bottom zone, and adjust the CHARBASE character register; if you don't do this, when you shorten the height of the bottom zone, it causes the graphics in the last zone to incorrectly align with the graphics in the zone directly above it. The problem with this technique, is that when the screen gets really DMA heavy (lots of objects) around your last zone, Maria will starve the 6502 of execution time, and your interrupt code will take several scanlines to complete, leaving some or all of the last zone without the CHARBASE fix. So I came up with an alternative technique, which I'll dub "DMA Masking". Instead of modifying the height of the last zone, which is ultimately what messes up the alignment, you leave it the same height, but creatively use Maria's DMA-limits to mask-off the bottom lines of the zone as desired. i.e. you create 4x 32-byte wide sprite objects at the front of that last DL. Then you adjust all 4x sprite object HI pointers so they point partway into a DMA hole, deep enough that Maria will skip these objects for N scanlines (allowing other objects to be drawn) and then after N scanlines your objects are rendered, causing Maria to run out of DMA time for any other objects in the zone. There are a few disadvantages to using DMA Masking: 1. 4 extra objects are now in that last zone, which means this zone has some extra DMA penalty, even when Maria is skipping your 4 sprites. (i.e. tere are 44 fewer Maria cycles to spare) So if your last zone is heavily loaded with objects, a few of them may not be displayed in the unmasked area of the last zone. 2. To make the DMA masking sprites invisible, you'll either need to dedicate some ROM to empty graphics, or waste a palette index using it to draw your 4x sprites with the background color. The advantages of DMA Masking: 1. Since the timing of adjusting your bottom zone masking isn't super critical, it doesn't need to happen in an interrupt. This means simplified interrupts. 2. It results in minimal glitching for that final zone, even when your DMA penalties are through the roof. I think the trade-offs are worth it for many game designs. I've been playing around with it, and it works great in emulation (for emulators that implement DMA limits) and real hardware. 6 Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted May 2, 2020 Share Posted May 2, 2020 (edited) This sounds great, is this something that will find its way into 7800 in the future in terms of a feature or commands to manipulate it? I was thinking about scrolling the other day and was going to ask. I figured for a coarse scroll I could "cheat" and use tiles and pokechar them in. Fine scrolling would be very neat indeed! Edited May 2, 2020 by Muddyfunster 4 Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 2, 2020 Author Share Posted May 2, 2020 Yeah, scrolling is definitely on the "to do" list for 7800basic. Part of the challenge is doing scrolling in a generic way, is that different game designs have different needs from the scroll interaction, and that changes what needs to happen on the back end. e.g. Games that do infinite scroll and/or algorithmic terrain differ substantially from ones that just need to scroll over some ROM. I'm trying to work it out - that's part of the reason I came up with DMA Masking - but as there's also a bunch of other things I need to take on first. 8 Quote Link to comment Share on other sites More sharing options...
fultonbot Posted May 3, 2020 Share Posted May 3, 2020 This is wonderful! Thanks! 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 3, 2020 Author Share Posted May 3, 2020 Glad you enjoyed it. 2 Quote Link to comment Share on other sites More sharing options...
PacManPlus Posted May 3, 2020 Share Posted May 3, 2020 (edited) hmm.... Trying to figure out a way to leverage this for PMC_XM... I might be able to... Thank you for this! Edited May 3, 2020 by PacManPlus 3 Quote Link to comment Share on other sites More sharing options...
TailChao Posted May 3, 2020 Share Posted May 3, 2020 There's even bigger gains for this approach if you're not using character mode and want to keep your background drawing generic. Another method which favors low color modes (320A / 320B) is the following... Don't modify the height of the last visible DLL region in your playfield - as with the DMA Masking technique. Trigger a DLI on the entry before this, then WSYNC into your fine scroll offset. Zero all the palette registers. You'll lose cycles in the opposite direction here, and there is some risk of jitter since Sally is responsible for making the change. But since there's only a few registers to change the noise isn't much worse than the status bar divide in Super Mario Bros 3 or Kirby's Adventure. This is one of the reasons I dropped a raster comparator into a mapper, which drops the requirement for the WSYNC step. 6 Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 3, 2020 Author Share Posted May 3, 2020 4 hours ago, TailChao said: There's even bigger gains for this approach if you're not using character mode and want to keep your background drawing generic. Ah, I hadn't even considered that, which is funny, because I've been moving toward sprites-as-tiles designs in the last year or so. Excellent observation, and great suggestion for an interrupt-based alternative to CHARBASE tweaking too. ? 2 Quote Link to comment Share on other sites More sharing options...
SlidellMan Posted May 3, 2020 Share Posted May 3, 2020 Rev Eng, just what can one do with DMA Masking? Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 3, 2020 Author Share Posted May 3, 2020 DMA Masking is useful as an alternative to the usual vertical scrolling approach. It allows the developer to max out the number moving objects on the screen, without fear of glitching out the bottom row. With the older method you'd need to either be more conservative with the number of moving objects, or risk corruption at the bottom. As TailChao pointed out, DMA Masking also allows for scrolling with game designs that use sprites as tiles, which in turn allows the game to draw different tiles with different palettes, resulting in a more colorful game. 1 Quote Link to comment Share on other sites More sharing options...
+mksmith Posted May 4, 2020 Share Posted May 4, 2020 This all sounds great Mike ?? 1 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 13, 2020 Author Share Posted May 13, 2020 On 5/3/2020 at 9:03 AM, TailChao said: Another method which favors low color modes (320A / 320B) is the following... Don't modify the height of the last visible DLL region in your playfield - as with the DMA Masking technique. Trigger a DLI on the entry before this, then WSYNC into your fine scroll offset. Zero all the palette registers. A variation on your interrupt method, that occurred to me today... instead of hitting the palette registers when you're at the desired scanline, you could write a zero-terminator over the first object in that bottom zone DL. (and then restore it later) That would work better with higher color modes. Untested (I'm sticking with dma masking) but I don't see why it wouldn't work. 2 Quote Link to comment Share on other sites More sharing options...
TailChao Posted May 13, 2020 Share Posted May 13, 2020 10 hours ago, RevEng said: A variation on your interrupt method, that occurred to me today... instead of hitting a the palette registers when you're at the desired scanline, you could write a zero-terminator over the first object in that bottom zone DL. (and then restore it later) That would work better with higher color modes. Untested (I'm sticking with dma masking) but I don't see why it wouldn't work. It should be fine - as long as the write makes it in. Maria walks the Display List each active line. Three options, now 2 Quote Link to comment Share on other sites More sharing options...
+bsteux Posted August 18 Share Posted August 18 Hi, "DMA masking" is I think the idea I was looking wrt vertical scrolling. At the moment, in cc7800, I'm using a black object to overlay the bottom of the screen, which is a similar idea but is not as effective as yours. I've got 2 questions to you Atari 7800 expert (I'm just starting on my side) : 1 - you're stating that on the upper part of the bottom DLL the DMA cost is 44 cycles. Why not 10 * 4 = 40 ? Is there something I misunderstand ? The idea is to overuse DMA on the bottom lines with 4 x 32 bytes. With 4 5-bytes DLs, the actual cost DMA cost would be (10 + 3 * 32) * 4 = 424 cycles, which together with the DMA startup and shutdown times + 7 CPU delay cycles should cover the 454 DMA cycles available. On the Holey DMA covered part, this should consume 40 cycles no ? 2 - What if we draw these 32 bytes outside the screen, at position 160 ? Do you know if Maria eats up DMA cycles in that case or if Maria is clever enough to disengage offscreen writing and spare DMA cycles ? (which would be nice in the general case, but not convenient in our case, since otherwise we would have to really draw something either transparent or background color ON screen). Best regards ! Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 18 Author Share Posted August 18 8 hours ago, bsteux said: Hi, "DMA masking" is I think the idea I was looking wrt vertical scrolling. At the moment, in cc7800, I'm using a black object to overlay the bottom of the screen, which is a similar idea but is not as effective as yours. I've got 2 questions to you Atari 7800 expert (I'm just starting on my side) : 1 - you're stating that on the upper part of the bottom DLL the DMA cost is 44 cycles. Why not 10 * 4 = 40 ? Is there something I misunderstand ? The idea is to overuse DMA on the bottom lines with 4 x 32 bytes. With 4 5-bytes DLs, the actual cost DMA cost would be (10 + 3 * 32) * 4 = 424 cycles, which together with the DMA startup and shutdown times + 7 CPU delay cycles should cover the 454 DMA cycles available. On the Holey DMA covered part, this should consume 40 cycles no ? 2 - What if we draw these 32 bytes outside the screen, at position 160 ? Do you know if Maria eats up DMA cycles in that case or if Maria is clever enough to disengage offscreen writing and spare DMA cycles ? (which would be nice in the general case, but not convenient in our case, since otherwise we would have to really draw something either transparent or background color ON screen). Best regards ! 1. It's been suggested in the past that an object's holey dma takes up 1 maria cycle, rather than none, for the calculation/abort. It's one of those things I should have verified a while back, but haven't done yet. I used the +1 cycle per holey graphic in my calculation, to err on the side of caution. 2. That should work - nice variation! Maria still "renders" objects that are outside the 0-159 range, with all the regular dma costs. It just doesn't actually update the scanline buffer with any out-of range pixels. 1 Quote Link to comment Share on other sites More sharing options...
+bsteux Posted August 19 Share Posted August 19 Thanks for your answer. This is what I thought about Maria - straightforward design: out of screen uses the same logic as in screen, but the line RAM is just not on chip for positions 160 to 255. This gives a good solution for vertical scrolling, since we can eat up DMA cycles for the last lines with any sprite data. No need for using precious holey DMA ROM for transparent or full data, and no need also to eat up a precious palette entry. I will implement this in my multisprites.h header in cc7800 and go back with the results. Wrt 1 cycle DMA penalty existence, that would be surprising (but not excluded, a look at schematics would be required or an experimental check): in Maria, the high address on which the logic to continue the state machine for DMA access is based on (test on A11 or A12 bit) is not the last byte of each DL, so there is plenty of time to add the OFFSET and implement the logic to decide to jump to the next DL or continue with DMA access... The logic is a simple adder, followed by simple combinatorial logic, which certainly runs in a single cycle. I don't see why there would be a need for an additional cycle, and it's also not mentioned in GCC documentation. Anyway, thank you for your answer and your expertise. We'll have a better vertical scrolling available soon... Regards. 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted August 19 Author Share Posted August 19 6 hours ago, bsteux said: Wrt 1 cycle DMA penalty existence, that would be surprising (but not excluded, a look at schematics would be required or an experimental check): in Maria, the high address on which the logic to continue the state machine for DMA access is based on (test on A11 or A12 bit) is not the last byte of each DL, so there is plenty of time to add the OFFSET and implement the logic to decide to jump to the next DL or continue with DMA access.. I ran the test, and it's actually worse - you lose 3 cycles of DMA for sprites with graaphics that are in the hole. (in addition to the header dma, of course) Additional info is over in the 7800 Hardware Facts thread. 2 Quote Link to comment Share on other sites More sharing options...
+bsteux Posted August 19 Share Posted August 19 16 minutes ago, RevEng said: I ran the test, and it's actually worse - you lose 3 cycles of DMA for sprites with graaphics that are in the hole. (in addition to the header dma, of course) Additional info is over in the 7800 Hardware Facts thread. So sad... Unexpected but interesting... I'll have a look at the other thread. Let's keep this one for vertical scrolling innovations 🙂 2 Quote Link to comment Share on other sites More sharing options...
+playsoft Posted September 15 Share Posted September 15 I have been helping with a 7800basic project that requires vertical scrolling and the idea of adding extra objects to the bottom row to use up all the Maria cycles seems to work very well. In case it is of any use, attached is the source for a demo program making use of the technique. scroll.zip 5 2 Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted September 15 Share Posted September 15 31 minutes ago, playsoft said: I have been helping with a 7800basic project that requires vertical scrolling and the idea of adding extra objects to the bottom row to use up all the Maria cycles seems to work very well. In case it is of any use, attached is the source for a demo program making use of the technique. scroll.zip 14.62 kB · 0 downloads Thanks for sharing this Paul, really interesting! 3 Quote Link to comment Share on other sites More sharing options...
+Trebor Posted September 15 Share Posted September 15 Thinking this demo definitely should not have been exposed to water or fed after midnight. 2 Quote Link to comment Share on other sites More sharing options...
+playsoft Posted September 17 Share Posted September 17 On 9/15/2023 at 1:24 PM, Muddyfunster said: Thanks for sharing this Paul, really interesting! Yes, it was a great idea and works really well in 7800basic. For the vertical scrolling project we have allowed for a variable number of palettes per row, but here it's just a single palette per row. If you used a single palette for the whole playfield then you could use plotmap and wouldn't need much in the way of assembly code at all. 5 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.