Tursi Posted April 4, 2010 Share Posted April 4, 2010 I wonder what could be done by just storing 8 versions of the background so you can scroll smooth? I think you would need a background with a repetitive nature too. I've been messing around with this concept. I did the math out of curiousity to see what it would take to do a fast smooth scroll. There's enough VRAM in Graphics0 for 4 copies of the full character set. If you wanted, then, you could have 4 different shift positions for 128 characters (since a single character needs two slots when it's shifted). Then you can "scroll" the screen by 2 pixels at a time just by changing the base address of the pattern table. I'm successfully using this technique in my Coleco Super Space Acer game right now to move the bosses smoothly horizontally (next release will show that). If you wanted single pixel accuracy, you could divide the character set in half, and have each table define "two" sets of 128 characters (in theory only, not in hardware). Scrolling would then entail changing the pattern table base and redrawing the screen (768 bytes). A little more expensive, but still feasible in vblank. However, with the pre-shifting, you'll only have 64 characters to work with. There are a couple of limitations with this. The first is that if you have two characters touching each other, you always need them touching each other through the scroll, so each combination would need to be accounted for. The second is that you're somewhat out of luck when it comes to color sets - first because they'll be artificially smaller due to the character overlap, second because you can't put two different colors side-by-side (you'll need at least one character of background color between them), otherwise colors will distort as they "scroll". Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 4, 2010 Share Posted April 4, 2010 To put a little more detail... in SSA, the bosses get characters 121-255. Because they are a block of graphics in a fixed layout, I only actually need one extra character per horizontal row to do the smooth scrolling - the largest boss is 12 rows by 10 columns, which is 120 characters. Since there are 12 rows, I need 12 extra characters for it to shift into, so it uses a total of 132 characters. My game defines pattern tables at >1000, >1800, >2000, and >2800. The offset of >0800 is chosen because this is the minimum step in the VDP. When the boss needs to come in, I load the default patterns into the first table. I then have a small piece of code that preshifts by 2 pixels into each of the other character sets. (The patterns from 0-120 are static in all four tables, so they don't appear to change). It causes a noticable hiccup in the game, but I will smooth this out by doing it over a number of frames. Ultimately, when moving the boss across the screen, I track it's column by pixel value divided by 2 (so, from 0-127). We need to get two values from that: the pattern table to select, and the horizontal column to draw at. The pattern table is easy, we just take the two lower bits with an AND. The value to write to the VDP register is the base value (>1000 = >0800*2, so '2' is the base) + that, so : (0x02 + (bc&0x03)). That gives the correct sub-character offset. The actual character is easy, too... it's the column divided by 4, which is just a shift operation (bc>>2). Draw the boss normally at that column, and it's done. With the calculations done that way at draw time, I never need to consider the scroll mechanism when moving the boss, I just update the 'bc' (boss column) as I choose. The other nice thing... even with all that, there's still plenty of room for a full sprite pattern table in VRAM, too. So this doesn't limit anything, really, it just uses a little more of the often-unused VRAM space. My VRAM map looks like this: // VRAM map: // >0000 Screen Image Table // >0300 Sprite Descriptor Table // >0380 Color Table // >03A0 (Unused) // >0800 Sprite Pattern Table // >1000 Pattern table (scroll 0) // >1800 Pattern table (scroll 2) // >2000 Pattern table (scroll 4) // >2800 Pattern table (scroll 6) // >3000 (Unused) There's still a bit over 5k left there. Unfortunately each pattern table takes 2k, so you can't do 8 full tables, it would use all 16k of VRAM (unless you were willing to sacrifice some characters for the other tables, of course! Might not be a bad alternative to my half-table suggestion above.) Scrolling by 2 pixels only needs 4 tables, which is just 8k. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted April 5, 2010 Share Posted April 5, 2010 2 pixel scrolling sounds great to me!!! NES side scrollers, many times, used 2 pixel scrolling... TI engineers never got as far as we have lately. Even TI's best scrollers weren't as tight as 2 pixels from what I understand. Great stuff man. Quote Link to comment Share on other sites More sharing options...
in8regs Posted April 5, 2010 Share Posted April 5, 2010 (edited) To put a little more detail... in SSA, the bosses get characters 121-255. Because they are a block of graphics in a fixed layout, I only actually need one extra character per horizontal row to do the smooth scrolling - the largest boss is 12 rows by 10 columns, which is 120 characters. Since there are 12 rows, I need 12 extra characters for it to shift into, so it uses a total of 132 characters. My game defines pattern tables at >1000, >1800, >2000, and >2800. The offset of >0800 is chosen because this is the minimum step in the VDP. When the boss needs to come in, I load the default patterns into the first table. I then have a small piece of code that preshifts by 2 pixels into each of the other character sets. (The patterns from 0-120 are static in all four tables, so they don't appear to change). It causes a noticable hiccup in the game, but I will smooth this out by doing it over a number of frames. Ultimately, when moving the boss across the screen, I track it's column by pixel value divided by 2 (so, from 0-127). We need to get two values from that: the pattern table to select, and the horizontal column to draw at. The pattern table is easy, we just take the two lower bits with an AND. The value to write to the VDP register is the base value (>1000 = >0800*2, so '2' is the base) + that, so : (0x02 + (bc&0x03)). That gives the correct sub-character offset. The actual character is easy, too... it's the column divided by 4, which is just a shift operation (bc>>2). Draw the boss normally at that column, and it's done. With the calculations done that way at draw time, I never need to consider the scroll mechanism when moving the boss, I just update the 'bc' (boss column) as I choose. The other nice thing... even with all that, there's still plenty of room for a full sprite pattern table in VRAM, too. So this doesn't limit anything, really, it just uses a little more of the often-unused VRAM space. My VRAM map looks like this: // VRAM map: // >0000 Screen Image Table // >0300 Sprite Descriptor Table // >0380 Color Table // >03A0 (Unused) // >0800 Sprite Pattern Table // >1000 Pattern table (scroll 0) // >1800 Pattern table (scroll 2) // >2000 Pattern table (scroll 4) // >2800 Pattern table (scroll 6) // >3000 (Unused) There's still a bit over 5k left there. Unfortunately each pattern table takes 2k, so you can't do 8 full tables, it would use all 16k of VRAM (unless you were willing to sacrifice some characters for the other tables, of course! Might not be a bad alternative to my half-table suggestion above.) Scrolling by 2 pixels only needs 4 tables, which is just 8k. K, short on space, what's the cycles situation? With TI graphics being highly compressible, even simple compression like RLE would make a lot of room. If cycles are tight, since you're just short of fitting, compress/process just enough, x line/characters needed to fit everything without sacrificing characters. Edited April 5, 2010 by in8regs Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted April 5, 2010 Share Posted April 5, 2010 TI engineers never got as far as we have lately. Even TI's best scrollers weren't as tight as 2 pixels from what I understand. Great stuff man. Parsec is still somewhat technically unsurpassed. Scroll, speech, scratchpad, pixel perfect terrain collision detection while trying to maintain gameplay, that’s something ! The prototype Vanguard had very nice full screen scrolling using some of the VDP “tricks”. http://www.youtube.com/watch?v=XHOnuOh4ahk Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 5, 2010 Share Posted April 5, 2010 K, short on space, what's the cycles situation? With TI graphics being highly compressible, even simple compression like RLE would make a lot of room. If cycles are tight, since you're just short of fitting, compress/process just enough, x line/characters needed to fit everything without sacrificing characters. You're sort of crossing ideas here, though. For the scroll trick I am describing to work, you have to have everything predefined. Each table /must/ take 2k because that is the granularity of the VDP. Pre-defining it allows a very fast scroll - just a couple of cycles until you cross a character boundary and have to redraw it. You could try compression, but even full uncompressed writes to VDP would be tough to redescribe the entire character set in a single frame, unfortunately. (2k of data won't fit in vblank, making the scroll visible). You could do it if you restricted the number of characters - but then you are in the same situation as I described above. Restricting the number of characters is not necessarily a killer, it just depends on your background detail. Also, you can do a combination of the two - you have enough characters to define one screen, and dynamically update the character set as you move through the world. You just have to leave space in your character sets for the other VDP tables.. the SIT is the largest at 768 bytes, so that's 96 characters, leaving 160 characters available for the pre-defined scroll. You'd likely want sprites... you could use those 96 characters from one of the other tables for a fully distinct sprite table. That's enough characters for 24 of the 32 sprites, if you don't mind dynamically loading the patterns (which can be more easily staged in vblank). You could likewise double-buffer the sprite patterns, or even more than that, since you'd probably have 6 of the tables with unused space. Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 5, 2010 Share Posted April 5, 2010 Parsec is still somewhat technically unsurpassed. Scroll, speech, scratchpad, pixel perfect terrain collision detection while trying to maintain gameplay, that’s something ! The prototype Vanguard had very nice full screen scrolling using some of the VDP “tricks”. Moon Patrol offers similar smooth scrolling of its mountains with parallax to boot, but it doesn't get much attention. Of course, it doesn't offer the rest of that, which was indeed well done. I never saw Vanguard, I wouldn't mind seeing what tricks it used. We (well, I) took Parsec's scroll routine apart on the Yahoo list and I think it could have been optimized some. It hasn't been beaten, I feel, more because nobody's done it than because it's the best that can be done. Parsec achieved some kind of legendary status for that little piece of smooth scroll code. I take apart the Parsec code here: http://tech.groups.yahoo.com/group/ti99-4a/message/62752 Since that's the point of interest, I'll copy and paste that one. The point was that someone mentioned that Parsec copied the scroll routine to scratchpad RAM every single frame. Parsec does indeed write and execute a small piece of scratchpad RAMevery frame, from 0x83E0. However, there's a lot of code executing in the scratchpad, which does not get written repeatedly. Here's a function at >8354: 65D0 bl @>8354 8354 movb @>8800,@>833c(R3) 835A inct R3 835C jlt >8354 835E b *R11 8360 mov @>833c(R4),R1 8364 src R1,0 8366 movb R1,@>8c00 836A inct R4 836C jlt >8360 836E b *R11 >8360 contains another subroutine: 6714 bl @>8360 8360 mov @>833c(R4),R1 8364 src R1,0 8366 movb R1,@>8c00 836A inct R4 836C jlt >8360 836E b *R11 Parsec does not appear to write the scroll routine to scratchpad every frame. I tested this by adding code that would flag all executed bytes in the scratchpad RAM, then emit debug if they were written to. After the game was up and scrolling, I breakpointed the emulator and cleared those flags, then resumed. There was no debug emitted. When I started the game, that's when I saw the messages about data at >83Ex being executed and written. The code that ends up there, and thus gets rewritten, looks like this at game start: 7F34 bl @>83e0 83E0 movb @>9000,R10 83E4 jmp >83e6 83E6 jmp >83e8 83E8 jmp >83ea 83EA b *R11 Note those three JMPs are NOPs, so all this does is a delay. Since it's reading from >9000, this is probably just a little routine to safely get the speech status without touching the 8-bit bus. This is the only code that is written to scratchpad every frame, the rest lives there permanently. It's only updated when it thinks it might be speaking. By breakpointing on that code, it looks like Parsec has a 5-frame scroll sequence, and it writes and calls this function for every frame. The five frames seem to be: -Scroll first quarter of scenery -Scroll second quarter of scenery -Scroll third quarter of scenery -Scroll fourth quarter of scenery -Scroll stars and animate ship flame Quote Link to comment Share on other sites More sharing options...
Kurt_Woloch Posted April 6, 2010 Share Posted April 6, 2010 While we are at scrolling examples on the TI-99, I still think that one very impressive example of smooth scrolling on the TI is Parker Brothers' Frogger. Here three quarters of the whole screen are scrolling in 2-pixel steps, and each row of cars, logs or turtles scrolls in a different speed. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted April 6, 2010 Share Posted April 6, 2010 (edited) Moon Patrol offers similar smooth scrolling of its mountains with parallax to boot, but it doesn't get much attention. Of course, it doesn't offer the rest of that, which was indeed well done. I never saw Vanguard, I wouldn't mind seeing what tricks it used. Yeah, I had just posted and walked away, when I also thought of Moon Patrol. Unzip the attached file to your DSK1 directory of Classic99. EA3, File name: DSK1.MAIN3O, Program name: TEST Start by watching the VDP registers in Debugger ... Edited February 5, 2014 by sometimes99er Quote Link to comment Share on other sites More sharing options...
Tursi Posted April 7, 2010 Share Posted April 7, 2010 Not bad... it's just double-buffering, though (both the screen and the character set). Gives a nice smooth result, though 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.