3 ms·
> colour changes only every few rows near the top of the screen. E.g. let those buildings (or whatever) extend to the top, but require the top floors to stick t
by jimsmart 4y ago
> colour changes only every few rows near the top of the screen. E.g. let those buildings (or whatever) extend to the top, but require the top floors to stick to the same colour. Now you can reduce e.g LDA/STA/LDA/STA/LDA/STA to LDA/STA/STA/STA and similarly reduce your inlined scroll code.
Here's the thing: I've just looked at video of Cobra. It's 100% plain to my eye (having worked on a multitude of published C64 games, over a number of years, and played a hundreds of C64 games, and taken their code apart to see how they tick) that this game is using full colour scrolling — albeit in only one direction. It might look like it's not, particularly on the first level, because you think the graphics look too simple. But sadly that's just how it looks.
You can plainly see this when various accent colours for e.g. windows and such like scroll into view. Don't be fooled by the fact it's tile based and the first level has poor graphics. And the fact it's full colour scrolling is even more obvious on later maps, e.g. see 5mins into this video:
https://www.youtube.com/watch?v=eog6-zvts6g https://www.youtube.com/watch?v=eog6-zvts6g
— That's full colour scrolling. In one direction. With tiles of 2x2 chars, with each char in the tile being able to have its own colour. 100%. There's no tricks there. Your theoretical/toy code example simply won't do what is seen on at the 5min mark there (level 2 or whatever).
- vidarh 4y ago> It might look like it's not, particularly on the first level, because you think the graphics look too simple. But sadly that's just how it looks. I specificaly did not say that Cobra isn't using full colour scrolling. You're probably right that it is. But what you've described does not require it. I am saying that Cobra is an example of the style of level design that could easily get savings without sacrificing the graphics - including the accent colours. Cobra is otherwise simple enough that it probably wouldn't be worth it, but that is entirely besides the point I was making. I did note the windows etc., yes. But the point is that there is no place in the whole game where there's a lot of big or different transitions going on at once, and the number of transitions is very small, and notably a lot of the transitions only occur at specific rows. The graphics as is is very constrained. The 5m mark is a perfect example of exactly what I'm saying - only about ~11 rows changes colour, and from what I saw that's one of the most extreme transitions in the game. But while it affects many rows, it also uses few colours and so you can offset even some of that cost. The way it's structured in faux 3D "layers" seems ripe to "decompress" the levels into a set of transition functions inspired by painters algorithm to "paint" bottom up, front to back, and then JSR at an offset into the transition function for the object "behind" if it extends past. You'd want to flatten some of the "layers" (at the cost of increasing the number of transition functions). Here's what I'd try: Since the transition functions can hardcode LDA immediate's, and STA absolute gets X indexing for one extra cycle, you can have the transition functions X index and used that to reuse the transition functions for every column. So e.g. instead of this: scroll_splat_colour: LDA #$00 # colour data for char STA $D800 # colour ram LDA #$00 STA $D801 You'd get this for each transition sequence (could be a slice of an object, but in practice you'd probably want to flatten it somewhat, at the cost of more transition functions but reducing the cycle cost because of fewer JSR/RTS pairs): some_transition: LDA #$col1 STA $D800+offset_of_last_row_start, X STA $D800+offset_of_second_to_last_row_start,X ... and so on until colour change LDA #$col2 .... sta to next row. RTS You then decompress the level into a series of JSR calls per column, right to left + DEX, and a set of offsets. Every time you scroll, you then overwrite the DEX after the last (leftmost) transition with an RTS (and fix up the previous one), and JSR to the first (rightmost) list of bottom-up JSRs. [Beware the likely errors in counting; long time since I've looked at cycle counts..] You need to save 12 cycles per transition function for the JSR/RTS plus 2 for the DEX per column plus a handful of cycles to do the setup per frame to break even, plus 1 cycle per STA. An LDA immediate/STA absolute pair is 6 cycles, so moving, say a 39x20 field adds up to 4680 cycles that way. If "everything" fails and you have one JSR + one DEX for 39 columns + STA absolute X-indexed for all 780 characters, you pay a cost of an extra 1287 cycles plus setup. Let's call it 1320. But this is before taking into account that you now don't need to do this: LDA scroll_splat_colour+6 STA scroll_splat_colour+1 LDA scroll_splat_colour+11 STA scroll_splat_colour+6 Assuming you split that in 7 segments of 111 (for 780/7) updates of 4+4 cycles each, for 888 cycles, we're 432 short in the pathological case where every colour is different to the one below it and different to the one to its right. But each STA absolute X-indexed we save, because colours do not change right to left, saves us 5 cycles. Each LDA we save because colours often repeat bottom to top saves us 2 cycles. If we assume these are evenly spread, we need 62 of each every frame to break even. In other words only 8% need to repeat. Of course if it just breaks even it's pointless. The only constraint on the artist to do this would be to set a "budget" for transitions to make sure there's always enough repetition to make it worthwhile, but it's certainly doable.
- jimsmart 4y agoThe main issue here is that this doesn't really work for anything but horizontal scrolling. The code I explained works for all directions. One of the games I coded was an 8-way scroller. Another had horizontal sections seamlessly connected to diagonal sections. Granted I didn't show different version of moving the data through the splat code, for different directions, I only showed a single direction. And I now realise that multi-direction was not mentioned in my OP. Which is most likely why we seem to be talking at odds with one another somewhat here. The code I showed works for all of these cases (8-way, horizontal-diagonal transitions, pure horizontal or vertical) — sure, one needs extra variations on the actual scroll code, but not the splat code — plus it is easier to reason about, quicker to develop, and doesn't impose artificial constraints on the graphics/map/tile-usage — which means the graphics won't take as many iterations to get right (you can bet the artist will make mistakes in the map, 100% guaranteed — cos without also modifying the tooling to account for all of this, that's what artists always do. Speaking from experience!). > The only constraint on the artist to do this would be to set a "budget" for transitions to make sure there's always enough repetition to make it worthwhile, but it's certainly doable. Even for a single-way scroller, it's quite hard to tell if the benefits you claim here really outweigh all of the costs involved (not just CPU costs - but dev time, map design time, adjustments to tooling, etc). IDK if it'd get the go ahead in any of the places I've worked, without a fully working demo. But yes, sure, your idea may well be more optimal at runtime, for single direction scrollers. But I don't see how it would / could work for all scroll directions. And the additional constraints would likely give the artists nightmares! ;) And, as you say, worst case is still gonna be ~25% slower. The biggest problem that one is trying to overcome here is the additional hit to CPU budget every n-frames (usually 8), when the color RAM update is needed. Having something that might, under certain conditions, be slower, could be problematic. Whereas having something that is constant time is, perhaps arguably, always going to be easier to deal with. But thanks for taking the time to explain. I kinda thought that that's what you were implying. Apologies I hadn't been clear that the code I showed (immediate load-stores) was a colour RAM splat technique that was applicable to scrolling in any direction. It's kind of a key point really, and I see I completely omitted it :/ I thought it was mentioned, but I now see that the 8-way scrolling conversation was a slightly different thread.