Mike Harris Posted March 4, 2019 Share Posted March 4, 2019 It has been a challenge.Ever since I tested my first game on a real ADAM it has been a discovery of blah. Maybe I thought I could do anything but I am not discouraged and want to finish the game. However, the port has to be updated to a Super type game because I just can't create a direct port so I might as well update to an improved tribute.That said...My next phase is that my character stays in the middle of the screen with the environment scrolling around you.I looked at Rally X for Coleco on Youtube and was blown away so I know it is possible. I am not asking for proprietary information but obviously there is a formula to all of this taught somewhere. I know I can pound the code and get a blah result when at the end of the day it probably is some type of SRL optimizations with a direct OUT command for speed... I don't know I just want to be professional and I can not find real info anywhere. So if someone out there willing to share some efficient Z80 8 directional scroll code I would be most appreciative.Or point me in the right direction. I am not asking anyone to write my code for me, I just need schooling and it's not like you can go to your local university and take classes on Coleco programing. Quote Link to comment Share on other sites More sharing options...
artrag Posted March 4, 2019 Share Posted March 4, 2019 Study this code for msx Same vdp, same z80, no need of ram https://github.com/artrag/scroll_8_ways A simple solution for rallyx is that all tiles are prerotated in rom and a given subset is loaded in vram when needed according to the car direction Quote Link to comment Share on other sites More sharing options...
Mike Harris Posted March 4, 2019 Author Share Posted March 4, 2019 (edited) Study this code for msx Same vdp, same z80, no need of ram https://github.com/artrag/scroll_8_ways A simple solution for rallyx is that all tiles are prerotated in rom and a given subset is loaded in vram when needed according to the car direction Can I just ask, and this is a serious question... Why could I not find this with just Google? I am seriously grateful...on all fours groveling in appreciation. My point being I hate to ask for help if I can figure it out on my own but I am learning the ins and outs of the Colecovision where the graphics are not as bad to access as the TI-994A but they are horrible compared to a lot of other machines. When I seen Rally X I was floored and I knew there was no way a thousand line hack was going to create the same result. If there is a directory somewhere with these types of routines please pass that along because if this has what I need then I will be back on track in no time. Thank you again. Edited March 4, 2019 by Mike Harris Quote Link to comment Share on other sites More sharing options...
artrag Posted March 4, 2019 Share Posted March 4, 2019 (edited) Mike, there is no magic. All tiles are precomputed, stored in rom and loaded in vram when needed If you use bluemsx, you could follow this thread from page 1 and look a the demos https://www.msx.org/forum/msx-talk/general-discussion/msx-vaporware-true-or-false?page=0 Edited March 4, 2019 by artrag Quote Link to comment Share on other sites More sharing options...
Mike Harris Posted March 6, 2019 Author Share Posted March 6, 2019 The issue that I have found is boiling down to a format that will work in a Coleco setting.TNIASM is another one. What I gather is that this is using compressed data, expanded into VRAM then page flipping... I take it that this is also the reason why Rally X is for the SGM because of the expanded memory.Being as Destructor, Zaxxon and a few others work on stock Colecovision I suspect that they used other formulas. They also are choppy in execution. If someone out there with z80 code for 8 way scrolling in Coleco format is reading could you post it please. Quote Link to comment Share on other sites More sharing options...
ChildOfCv Posted March 7, 2019 Share Posted March 7, 2019 Even without the SGM you can use page-flipping. Mode 1 only needs about 4K. Mode 2 needs 12K, and that's for full single-page usage. Either way you have a good amount of space to draw offscreen with, so that you can page-flip when done. The TMS does not seem to offer any memory block copy functionality, and the page registers are too coarse to just bump over a pattern at a time. Quote Link to comment Share on other sites More sharing options...
Mike Harris Posted March 7, 2019 Author Share Posted March 7, 2019 (edited) Even without the SGM you can use page-flipping. Mode 1 only needs about 4K. Mode 2 needs 12K, and that's for full single-page usage. Either way you have a good amount of space to draw offscreen with, so that you can page-flip when done. The TMS does not seem to offer any memory block copy functionality, and the page registers are too coarse to just bump over a pattern at a time. In my case is that I am a newbie with zero experience which makes me bug you guys on how to do it. When I was in the military it was teach you once, you do then teach others. I need source code to show me the way or I will spend the next year trying to figure it out. I get the concepts of page flipping, buffering and scrolling but at the end of the day there is a formula that is taught as gospel so you don't have to pound your way through it. Most of these guys like Pixelboy or whomever I can find articles of homebrew going back over 10 years so I know that THEY know what's what but getting info these days is pulling teeth. Example of opcode starting a course in z80 on this very website and never got past the first class that I could find. http://atariage.com/forums/topic/193683-z80-assembly-module-1-basic-z80-programming/ http://www.colecovision.dk/cv-z80-assembly.htm I am on fire to make games for the Coleco mainly for my benefit, not to take business away from anyone. Edited March 7, 2019 by Mike Harris Quote Link to comment Share on other sites More sharing options...
+nanochess Posted March 7, 2019 Share Posted March 7, 2019 A MSX game using 8-way scrolling. https://www.youtube.com/watch?v=k73p_KP0em4 A Colecovision one. (works in unexpanded Colecovision) https://www.youtube.com/watch?v=HH-OnfUuD60 The graphics that can be shown are very limited because the trick of precomputed tiles, this means you only update the pattern table (768 bytes in two frames). I'm not aware of examples of Z80 code about scrolling in 8-way. Basically it's composed of this: 1. You create your map using the most limited possible set of graphics. 2. You create a program that takes each tile and generates the intermediate versions for scrolling: tile and adjacent tiles (1 for horizontal/vertical scrolling, 3 for diagonal scrolling). One tile can expand to many tiles!!! so typically scroll is in 2-pixels step. 2.1. At same time you generate a map of tiles for each scrolling offset. (for 2 pixels scroll, it would be 4 tables, for 2 pixel diagonal scroll, it would be 16 tables) 3. If the total tiles didn't exceeded the maximum 256 tiles then you can continue. 4. Load the bitmaps into the VDP (repeat 3 times in mode 2, or only 1 in mode 1) 5. For each display frame, you extract the X,Y offset to select a table, and then take each tile from your map, translate with table, and put into VRAM screen. 2 Quote Link to comment Share on other sites More sharing options...
Pixelboy Posted March 7, 2019 Share Posted March 7, 2019 Look, artrag already answered your question: There is no magic. You really need to get this one-algorithm-fits-all idea out of your head. Each scrolling game you will ever make on the ColecoVision will have a completely different scrolling engine (unless it's a sequel that reuses the same engine, of course). This is because the CV makes it hard to do smooth scrolling to begin with, and code optimizations to get smooth scrolling will impact your game's design, and vice-versa. So there are two ways to approach a scrolling game on the ColecoVision: You first design the scrolling engine only, and once you have it working as a satisfactory demo, you build your game around it. The other method is simply to design the full game on paper, and then try to develop the scrolling engine in parallel with the entire game itself. That second option is only recommendable for expert coders who know the console inside and out. No one can really help you with this, because if someone shows you a particular smooth scrolling algorithm, this engine will probably come with technical limitations that will get in the way of your creative process for your game. To get started, you need to understand how the screen refresh interrupt works, as it's the key point of any VRAM-intensive process. Then you need to understand that you can only send a certain maximum number of bytes to VRAM during each screen refresh cycle, and this limit will strongly influence whatever scrolling engine you will ever create. Good luck, space cadet. Quote Link to comment Share on other sites More sharing options...
ChildOfCv Posted March 7, 2019 Share Posted March 7, 2019 But for the closest thing to "1 size fits all", and for mode 1, you'd note that CV BIOS sets up the following: Sprite generator table is at 3800 Pattern color table is at 2000 Sprite attribute table at 1B00 Pattern name table at 1800 Pattern generator table at 0 Mark off two buffers in VRAM. Note that the pattern generator table has 1800 bytes available. This lets you flip through 3 different full tile sets if you wanted. But maybe you're only using 2 tile types: wall or not. Well, if you want block by block scrolling, this makes it easy: Choose your second pattern name table page at, say, 1000. Now, while 1800 is being displayed, make your updates to the area at 1000. Then on vblank, set register 2 to (1000/400), or 4. Now your updates will be to the 1800 region. When finished updating and on next vblank, set register 2 to (1800/400) or 6. And so on. Note that you will likely be redrawing the entire offscreen buffer since going by what has changed would likely be slower. Now, if you want to do SMOOTH scrolling, that's where you need to start using multiple tiles with multiple permutations. You now need to have blank space with tile to right, blank space with tile above, blank space with tile upper right, blank space with tile above and upper right, blank space with tile upper right and right, blank space with walls above, right, and upper right, and inverse versions of the above. You'll need a repeat of each of these tiles with every scroll amount for right, up, and up right. You can use mirroring tricks to support the other directions and wall combinations. But now you can begin to see why this is so hard and needs to be well integrated with your game. Quote Link to comment Share on other sites More sharing options...
Kiwi Posted March 7, 2019 Share Posted March 7, 2019 I produce a source code that I used to scroll in all direction. This is the quickest way to print a ton of tiles on screen at a cost of ROM space. VDP is slow so you'll need to swap screen technique to double buffer to hide the tearing. Unfortunately it's in C, but you'll get the idea. It only takes 2 bytes to scroll the entire screen. This is the code, click spoiler to expand. #include <coleco.h> #include <getput1.h> #define chrgen 0x0000 #define coltab 0x2000 #define chrtab 0x1800 #define sprtab 0x3800 #define sprgen 0x1b00 byte a,b,c,d,e,f,x,y, game, scrolly,Wide,scrollx; const byte Leveldata[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,3,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; const byte PATTERNRLE[] = { 0x1F, 0x00, 0x20, 0x50, 0x04, 0x4A, 0xA0, 0x08, 0x14, 0x00, 0x20, 0x00, 0x04, 0x40, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0x04, 0x40, 0x00, 0x08, 0x00, 0xC3, 0x81, 0x00, 0x00, 0x81, 0xC3, 0xE7, 0xE7, 0xFE, 0x00, 0xEA, 0x00, 0x04, 0x0C, 0x18, 0x30, 0x00, 0x60, 0x82, 0x00, 0x81, 0x66, 0x85, 0x00, 0x21, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x00, 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00, 0xFF, 0x81, 0xB9, 0xA5, 0xB9, 0xA5, 0x81, 0xFF, 0x3C, 0x66, 0x3C, 0x38, 0x67, 0x66, 0x3F, 0x80, 0x00, 0x00, 0x18, 0x30, 0x85, 0x00, 0x00, 0x18, 0x82, 0x30, 0x00, 0x18, 0x82, 0x00, 0x00, 0x18, 0x82, 0x0C, 0x00, 0x18, 0x82, 0x00, 0x04, 0x5A, 0x3C, 0x7E, 0x3C, 0x5A, 0x82, 0x00, 0x81, 0x18, 0x02, 0x7E, 0x18, 0x18, 0x85, 0x00, 0x01, 0x18, 0x30, 0x84, 0x00, 0x00, 0x7E, 0x88, 0x00, 0x00, 0x18, 0x82, 0x00, 0x04, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x82, 0x00, 0x04, 0x7C, 0xCE, 0xD6, 0xE6, 0x7C, 0x82, 0x00, 0x04, 0x18, 0x38, 0x18, 0x18, 0x7E, 0x82, 0x00, 0x04, 0x7C, 0x06, 0x7E, 0x60, 0x7E, 0x82, 0x00, 0x04, 0x7C, 0x06, 0x7C, 0x06, 0x7C, 0x82, 0x00, 0x81, 0xCC, 0x02, 0xFE, 0x0C, 0x0C, 0x82, 0x00, 0x04, 0x7E, 0x60, 0x7C, 0x06, 0x7C, 0x82, 0x00, 0x04, 0x3E, 0x60, 0x7C, 0x66, 0x3C, 0x82, 0x00, 0x04, 0xFE, 0x06, 0x0C, 0x18, 0x30, 0x82, 0x00, 0x04, 0x3C, 0x66, 0x3C, 0x66, 0x3C, 0x82, 0x00, 0x04, 0x3C, 0x66, 0x3C, 0x06, 0x7C, 0x83, 0x00, 0x02, 0x18, 0x00, 0x18, 0x84, 0x00, 0x0A, 0x18, 0x00, 0x18, 0x30, 0x0E, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0E, 0x84, 0x00, 0x0A, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x70, 0x83, 0x00, 0x04, 0x38, 0x6C, 0x08, 0x00, 0x18, 0x8A, 0x00, 0x04, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x82, 0x00, 0x04, 0xFC, 0xC6, 0xFC, 0xC6, 0xFC, 0x82, 0x00, 0x04, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x82, 0x00, 0x00, 0xFC, 0x82, 0xC6, 0x00, 0xFC, 0x82, 0x00, 0x04, 0xFE, 0xC0, 0xFE, 0xC0, 0xFE, 0x82, 0x00, 0x04, 0xFE, 0xC0, 0xFE, 0xC0, 0xC0, 0x82, 0x00, 0x04, 0x7E, 0xC0, 0xDC, 0xC6, 0x7C, 0x82, 0x00, 0x81, 0xC6, 0x02, 0xFE, 0xC6, 0xC6, 0x82, 0x00, 0x00, 0xFC, 0x82, 0x30, 0x00, 0xFC, 0x82, 0x00, 0x04, 0xFE, 0x06, 0x06, 0xC6, 0x7C, 0x82, 0x00, 0x04, 0xC6, 0xCC, 0xF8, 0xCC, 0xC6, 0x82, 0x00, 0x83, 0xC0, 0x00, 0xFE, 0x82, 0x00, 0x04, 0xC6, 0xEE, 0xFE, 0xD6, 0xC6, 0x82, 0x00, 0x04, 0xC6, 0xE6, 0xFE, 0xCE, 0xC6, 0x82, 0x00, 0x00, 0x7C, 0x82, 0xC6, 0x00, 0x7C, 0x82, 0x00, 0x04, 0xFC, 0xC6, 0xFC, 0xC0, 0xC0, 0x82, 0x00, 0x04, 0x7C, 0xC6, 0xC6, 0xCC, 0x76, 0x82, 0x00, 0x04, 0xFC, 0xC6, 0xFC, 0xCC, 0xC6, 0x82, 0x00, 0x04, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x82, 0x00, 0x00, 0xFC, 0x83, 0x30, 0x82, 0x00, 0x83, 0xC6, 0x00, 0x7C, 0x82, 0x00, 0x82, 0xC6, 0x01, 0x6C, 0x38, 0x82, 0x00, 0x04, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x04, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x82, 0x00, 0x81, 0xC6, 0x02, 0x7E, 0x06, 0xFC, 0x82, 0x00, 0x04, 0xFC, 0x18, 0x30, 0x60, 0xFC, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xB2, 0x00, 0xFF}; const byte COLORRLE[] = { 0x87, 0xF4, 0x87, 0x3C, 0x87, 0xFB, 0x07, 0x12, 0x13, 0xC3, 0xC2, 0x12, 0x12, 0xC6, 0xC6, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xFE, 0xF0, 0xEE, 0xF0, 0xFF}; void Scroll(){ put_at(0,0,Leveldata+(scrolly*Wide)+scrollx,32); put_at(0,1,Leveldata+(scrolly*Wide)+scrollx+Wide*1,32); put_at(0,2,Leveldata+(scrolly*Wide)+scrollx+Wide*2,32); put_at(0,3,Leveldata+(scrolly*Wide)+scrollx+Wide*3,32); put_at(0,4,Leveldata+(scrolly*Wide)+scrollx+Wide*4,32); put_at(0,5,Leveldata+(scrolly*Wide)+scrollx+Wide*5,32); put_at(0,6,Leveldata+(scrolly*Wide)+scrollx+Wide*6,32); put_at(0,7,Leveldata+(scrolly*Wide)+scrollx+Wide*7,32); put_at(0,8,Leveldata+(scrolly*Wide)+scrollx+Wide*8,32); put_at(0,9,Leveldata+(scrolly*Wide)+scrollx+Wide*9,32); put_at(0,10,Leveldata+(scrolly*Wide)+scrollx+Wide*10,32); put_at(0,11,Leveldata+(scrolly*Wide)+scrollx+Wide*11,32); put_at(0,12,Leveldata+(scrolly*Wide)+scrollx+Wide*12,32); put_at(0,13,Leveldata+(scrolly*Wide)+scrollx+Wide*13,32); put_at(0,14,Leveldata+(scrolly*Wide)+scrollx+Wide*14,32); put_at(0,15,Leveldata+(scrolly*Wide)+scrollx+Wide*15,32); put_at(0,16,Leveldata+(scrolly*Wide)+scrollx+Wide*16,32); put_at(0,17,Leveldata+(scrolly*Wide)+scrollx+Wide*17,32); put_at(0,18,Leveldata+(scrolly*Wide)+scrollx+Wide*18,32); put_at(0,19,Leveldata+(scrolly*Wide)+scrollx+Wide*19,32); put_at(0,20,Leveldata+(scrolly*Wide)+scrollx+Wide*20,32); put_at(0,21,Leveldata+(scrolly*Wide)+scrollx+Wide*21,32); put_at(0,22,Leveldata+(scrolly*Wide)+scrollx+Wide*22,32); put_at(0,23,Leveldata+(scrolly*Wide)+scrollx+Wide*23,32); } void Scrolltest(void){ scrollx=0; scrolly=0; Wide=64; game=1; Scroll(); enable_nmi(); while(game==1){ delay(1); if((joypad_1&UP) && scrolly!=0){scrolly--;disable_nmi();Scroll();enable_nmi();} if(joypad_1&DOWN && scrolly!=24){scrolly++;disable_nmi();Scroll();;enable_nmi();} if((joypad_1&LEFT) && scrollx!=0){scrollx--;disable_nmi();Scroll();enable_nmi();} if((joypad_1&RIGHT) && scrollx!=32){scrollx++;disable_nmi();Scroll();enable_nmi();} //if(keypad_1==1){game=0;cls();} } } void main(){ disable_nmi(); screen_mode_2_text(); screen_on(); rle2vram(PATTERNRLE,0x0000); duplicate_pattern(); rle2vram(COLORRLE,0x2000); Scrolltest(); } void nmi(){ } Wide is how many tiles are in the table horizontally. The limitation is, the maximum map size is 256 by 256 due to the use of 8-bit variables. Smooth scrolling in 8 direction takes a TON of work. 1 direction smooth scrolling is difficult. I don't have the tools or skill to do it but I got the idea how it is done. I have applied smooth scrolling horizontally to A Sparrow goes Flapping. Alldirection.rom 2 Quote Link to comment Share on other sites More sharing options...
artrag Posted March 8, 2019 Share Posted March 8, 2019 (edited) http://atariage.com/forums/topic/222529-smooth-scrolling-in-c/?do=findComment&comment=2936772 This is a nice explanation of how to do smooth scrolling in screen 1 Edited March 8, 2019 by artrag Quote Link to comment Share on other sites More sharing options...
ChildOfCv Posted March 8, 2019 Share Posted March 8, 2019 (edited) To simplify the explanation (at least of the first post), note that what he does is both double-buffering and multiple pattern generation tables. The memory breakdown looks like this: +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ | 0| 300| 400| 700| 800| B00| C00| F00|1000|1300|1800|1B00|2000|2300|2800|2B00|3000|3300|3800|3B00|3C40| | PT1| |BUF1| | PT2| |BUF2| | PT3| | PT4| | PT5| | PT6| | PT7| | PT8| |CTBL| +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ PT# are the pattern tables which have the same blocks but shifted by 1 pixel each BUF# are the name tables that you swap between on different frames CTBL is the color table. I don't know why they chose to shift it over by 1 from a more rounded address. All the blank space is available for other purposes (sprites, most likely). The reason it's so fragmented is that each table type has a granularity enforced. Pattern tables are on 0x800 boundaries, pattern name tables on 0x400 boundaries, color table on 0x40 boundaries, and so on. Note that sprite generator tables must ALSO be on 0x800 boundaries, so you have two options here: Either split the pattern space between sprites and static patterns, or do 2-pixel scrolling so that you only need 4 pattern tables, and call it good enough. The sprite attribute tables are on 0x80 boundaries, so much more flexible. It's also worth noting that there is some optimization that can be done when blasting new map rows in: The VDP auto-increments its destination register so that you can keep feeding it bytes. So why send it a new address on every new line, when the new address matches where the auto-incremented address already is anyway? Also, since these strategies depend on having the decompressed map in RAM, you can skip the calculation of each new map row. If the map is 128 bytes wide, find your initial location. Then write 32 bytes and advance by (128-32) bytes, and start writing the next 32 bytes. Why go through more bit shifting and addition? Edited March 8, 2019 by ChildOfCv 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.