--- /dev/null
+ ________________________________________________\r
+ |+----------------------------------------------+|\r
+ || I N T R O D U C I N G : ||\r
+ |+----------------------------------------------+|\r
+ || Steve's 4-Way ||\r
+ || ___ ___ ____ ___ _ _ ||\r
+ || / __| / __| | _ \ / _ \ | | | | ||\r
+ || | <_ | | | |_> | | | | | | | | | ||\r
+ || \_ \ | | | / | | | | | | | | ||\r
+ || __> | | |__ | |\ \ | |_| | | |__ | |__ ||\r
+ || |___/ \___| |_| \_| \___/ |____| |____| ||\r
+ |+______________________________________________+|\r
+ +------------------------------------------------+\r
+\r
+ There, now that I have the hype outta the way, let me explain what\r
+this program is. I'm releasing the source code to my 4-way scrolling\r
+code so that others can learn from it. There aren't enough really\r
+good resources out there for someone learning to program games, so I'm\r
+trying to do my part to help.\r
+\r
+WHAT IT IS:\r
+\r
+ The code is 100% assembly, for which I use MASM 6.0, so there may\r
+be a few problems converting to Turbo Assembler. I also use the ".386"\r
+directive, meaning that you can't run this code with a 286 or earlier.\r
+But most of the code should be easily convertible. I haven't been\r
+programming for 386's much so I really don't make the use of the 386\r
+registers like I could have. Mostly I just did it for some extra 386\r
+instructions.\r
+\r
+ You'll need a VGA which can support mode 13h, the MCGA mode. This\r
+code runs in "tweaked" MCGA mode, or what is called "Mode X". For more\r
+information on Mode X, check out the 1991 - 1992 issues of Doctor Dobbs\r
+Journal, wherein you will find Michael Abrash's excellent Graphics\r
+Programming column. This is where I (and many others) found out about\r
+Mode X, which is an excellent graphics mode for fast 256-color graphics.\r
+Also, you can take a look at XLIB, YakIcons, FastGraph, etc which are all\r
+graphics libraries (public domain or otherwise) which support Mode X\r
+graphics and probably have some good documentation on programming the mode.\r
+Additionally, check out _The Programmer's Guide to the EGA and VGA Cards_,\r
+by Richard Ferraro, and _Power Graphics Programming_ (out of print, but\r
+available directly from Que Books) by Michael Abrash. Finally, you can\r
+ask about graphics programming on many newsgroups such as\r
+"rec.games.programmer"...\r
+\r
+WHAT IT DOES:\r
+\r
+ The code will allow you to create "tiled" background patterns and then\r
+to omnidirectionally scroll over them. You could implement sprite routines\r
+and then animate them over the background, but I haven't gotten this far\r
+yet. The scrolling is always relational -- ie no "jump-to"'s, just "scroll\r
+left", "scroll up", etc. Jump to would be very easy to implement, I just\r
+haven't done it yet.\r
+\r
+ It runs at about 60-70 fps on a 386/20, which means that it is operating\r
+in under the time of one vertical refresh (_just_ under, according to some\r
+timing I've done). This could probably be reduced, but the best way to\r
+reduce it is to limit the speed at which it scrolls -- if you stick to\r
+scrolling at most 8 pixels at a time in two axes or 16 pixels at a time\r
+in one axis, it is very fast. More than that, and it occasionally takes\r
+more than one refresh period even on my 486. Still, that should be\r
+fast enough for just about any game.\r
+\r
+ I also included some routines to generate maps, tiles, and palettes\r
+so you can see the file formats. These are in C, and the executables\r
+are around in case you don't care to recompile. None of the utilities\r
+are exactly production quality. You'll have to look at the code to\r
+figure out the arguments! Luckily you can just run them with no args\r
+and they perform default behavior.\r
+\r
+ Lastly, the program SCROLL.EXE is a demo of what it can do. In this\r
+demo you can use one of two sets of keyboard controls to scroll around.\r
+One, the default set of commands, lets you press up/down/left/right and\r
+scroll in that direction. The other has "intertia" -- pressing up/down\r
+left/right will accelerate you in that direction. You'll see what I\r
+mean, just experiment. You can switch keyhandlers by pressing K.\r
+You can also switch between the diagonal pattern map and a logo map\r
+by pressing M. (By the way, it will eventually run out of memory loading\r
+the maps and the diagonal map will screw up... don't worry about it,\r
+it'd be fixed if I had more time). Try it out.\r
+\r
+CREDIT WHERE CREDIT IS DUE:\r
+\r
+ People who (unknowingly) helped me out:\r
+\r
+ Keyboard by Steven Dollins, Brown Computer Group. From his\r
+ KEYINT routines, which is an INT 9 handler to let you\r
+ keep track of many keys being pressed at the same time.\r
+ Graphics, basically, by Michael Abrash, whose Mode X columns\r
+ influenced me greatly.\r
+ Palette fades and file I/O by the Future Crew. Thanks for\r
+ letting out the Mental Surgery code!\r
+ CPU detection by Ray Duncan, taken from one of his books.\r
+\r
+ Obviously I haven't just pirated the code, it's all from publicly\r
+released source code and I modified it a bit. But I wouldn't have come\r
+up with this whole thing without those helping hands. Thanks.\r
+\r
+HOW IT WORKS:\r
+\r
+ Here's how the scrolling works. I'll explain it from a single-page\r
+point of view, although it actually uses several pages of video memory.\r
+The video memory is laid out like this:\r
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ\r
+º ³ / / / / º ³\r
+º ³/ / / / º ³\r
+º ³ / / / /º ³\r
+º Visible page ³ / Not / / º ³\r
+º ³/ visible/ º ³\r
+º ³ / / / /º 64K\r
+º ³ / / / / º ³\r
+ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ/ / / / º ³\r
+º / / / / / / / / / / / / / / /º ³\r
+º / / / / / / / / / / / / / / / º ³\r
+º/ / / / / / / / / / / / / / / º ³\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
+In other words, it has a virtual width greater than the actual screen\r
+width, and a virtual height higher than the actual screen height. The\r
+VGA hardware allows hardware panning around within the virtual area, so\r
+that makes panning much easier: you only have to draw the information\r
+that is coming on to the screen with each pan.\r
+\r
+What is Happening: What the user sees:\r
+ÉÍÍÍÍÍÍÍÍÑÍÍÍÍ» ÚÄÄÄÄÄÄÄÄ¿\r
+º hel³////º ³ hel³ The picture that is\r
+ÇÄÄÄÄÄÄÄÄÙ////º ÀÄÄÄÄÄÄÄÄÙ coming on to the screen\r
+º/////////////º ("hello") appears to\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ the user to be scrolling\r
+ÉÍÑÍÍÍÍÍÍÍÑÍÍÍ» ÚÄÄÄÄÄÄÄÄ¿ left, although it is\r
+º/³ hell³///º ³ hell³ actually at a stationary\r
+º/ÀÄÄÄÄÄÄÄÙ///º ÀÄÄÄÄÄÄÄÄÙ location in memory...\r
+º/////////////º Each time the frame moves,\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ it is not necessary to\r
+ÉÍÍÑÍÍÍÍÍÍÍÑÍÍ» ÚÄÄÄÄÄÄÄÄ¿ redraw the parts that stay\r
+º//³ hello³//º ³ hello³ on the screen, just the\r
+º//ÀÄÄÄÄÄÄÄÙ//º ÀÄÄÄÄÄÄÄÄÙ parts that become visible.\r
+º/////////////º\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ\r
+\r
+ The same works up&down too, or even left/right and up/down at the same\r
+time. The problem occurs when you scroll enough to hit the edge of the\r
+virtual space. Luckily, video memory increases and wraps at the right\r
+edge to one line down on the left edge. So you end up with a situation\r
+like this after scrolling too far right:\r
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍ» ÄÄÄ\r
+ÇÄÄÄÄÄÄÄ¿//////³ º ³ User sees:\r
+º ³//////³ Thº ³ ÚÄÄÄÄÄÄÄÄÄÄÄ¿\r
+ºe quick³//////³ º 64K ³ ³\r
+º ³//////ÀÄÄÄĶ ³ ³ The quick³\r
+ÇÄÄÄÄÄÄÄÙ///////////º ³ ³ ³\r
+º///////////////////º ³ ÀÄÄÄÄÄÄÄÄÄÄÄÙ\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
+The wrapping is transparent to the user. So, it appears that you can\r
+scroll left & right infinitely, by simply always updating the amount of\r
+memory that has scrolled into view.\r
+\r
+ But what happens when you scroll too far down? Now Intel segments come\r
+to the rescue! Because the video memory is 64K, and that is also the\r
+largest amount of memory you can access in a segment, the segment arithmetic\r
+performs the top-to-bottom wrapping for me. It results in a similar\r
+situation as is pictured above, but with the screen split horizontally\r
+instead of vertically. Again, it's completely transparent to the user.\r
+\r
+ One performance optimization that I've done is to organize the background\r
+picture that is being scrolled into quantitized "tiles" -- 16x16 pixels in\r
+area. This means that you can store a large amount of picture data if that\r
+data is repetitive -- as the backgrounds of many video games are. This also\r
+helps when figuring out how much new stuff to draw on the screen. I can wait\r
+until the panning crosses a 16-pixel border, then draw another 16-pixel\r
+strip, and then wait for another tile crossing, etc. You can see this in\r
+the MAP.INC and SCROLL.INC code. 16x16 pixels also leads to 256-pixel-square\r
+tiles, which is always a convenient number in assembly... it helps out in\r
+several places in the code.\r
+\r
+ So, the display page is "wandering" around the video memory, only drawing\r
+what is necessary at any time. Meanwhile you can animate sprites over the\r
+background, etc. The only problem is that with one page, information is\r
+constantly being drawn to that page and you can never guarantee that it is in\r
+a correct state at the time of a vertical refresh period. Instead, I actually\r
+use several pages, so that one can be shown while the other is worked on.\r
+This guarantees a perfect picture at any time. So for now, let's ignore the\r
+scrolling for a second, and talk about the paging, because it's easier to\r
+understand the paging if scrolling isn't happening.\r
+\r
+ Here's a basic explanation of how the paging works. I use three separate\r
+pages, a Draw page, a Show page, and a Blank page. The Show page refers to\r
+the page that is currently showing, the Draw page to the page that is\r
+under construction (to be shown next frame), and the Blank page should always\r
+be maintained as an up-to-date blank background page. (The Blank page is\r
+useful for sprite programming which I am going to be doing next.) Each\r
+of the pages is 352x240, although the screen resolution is only 320x200.\r
+\r
+ Each frame, the pages rotate DrawPage->ShowPage->BlankPage->DrawPage.\r
+This means that at the beginning of the frame, the Draw Page is already\r
+blank, so all that is necessary is to draw on a bunch of sprites. The\r
+BlankPage, though, is no longer blank (it's still got stuff from what\r
+was the ShowPage) so we have to erase it, by blanking out the sprites\r
+(luckily the new DrawPage _is_ empty, so we can use a Mode X 32-bit video-\r
+to-video copy to blank it). Hope you're still with me.\r
+\r
+ So, this loop continues with each frame, and the loop invariants are\r
+maintained: Show Page is always a "good" frame -- don't touch it. Blank\r
+Page is always blank. Draw Page can look like anything. Now to include\r
+the scrolling again:\r
+\r
+ The way I do scrolling with several pages is that the pages ALL wander\r
+around video memory, only they're smaller (1/3 of the size that they could\r
+have been, to be exact!). Here's a picture of the situation at its worst:\r
+ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ\r
+º ³//ÀÄÄÄÄÄÄÄĺ ³\r
+ºÄÄÙ///////////º ³\r
+º/////ÚÄÄÄÄÄÄÄĺ ³\r
+ºÄÄ¿//³PAGE 0 º ³\r
+º ³//³ (Draw) º ³\r
+º ³//ÀÄÄÄÄÄÄÄĺ ³\r
+ºÄÄÙ///////////º 64K\r
+º/////ÚÄÄÄÄÄÄÄĺ (21K each page)\r
+ºÄÄ¿//³PAGE 1 º ³\r
+º ³//³ (Show) º ³\r
+º ³//ÀÄÄÄÄÄÄÄĺ ³\r
+ºÄÄÙ///////////º ³\r
+º/////ÚÄÄÄÄÄÄÄĺ ³\r
+ºÄÄ¿//³PAGE 2 º ³\r
+º ³//³ (Blank)º ³\r
+ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
+The pages always maintain an equal distance apart as they wander. Since\r
+all pages move in parallel, the way it used to work is that as soon as the\r
+pages scrolled, I would draw the newly-visible picture information on\r
+all three of the pages. This worked great, except that it resulted in\r
+a slight pause every time the screen scrolled because it was doing hardware\r
+pan most of the time (which is very fast) and the drawing routines were\r
+slow. Now, I've spread the copying over successive frames to allow a\r
+smoother scrolling rate. This is possible because it's not really necessary\r
+to draw the new information to a page before that page becomes the show\r
+page...\r
+\r
+ I hope that this has made some sense. It's pretty complicated stuff.\r
+Take a look at the code and maybe that will help. Or, write me mail\r
+(my email address is below). Or, design your own way and ignore this\r
+whole thing.\r
+\r
+COMING SOON:\r
+\r
+ Next up are Sprite routines. I threw in what I started as SPRITE.INC,\r
+although it's not included in the project right now.\r
+ Sound support\r
+\r
+ Who knows what else? Depends on what people send me!\r
+\r
+-------------------------------------------------------------------------\r
+ R E A D T H I S\r
+-------------------------------------------------------------------------\r
+ R E A D T H I S\r
+-------------------------------------------------------------------------\r
+\r
+ This code is being released as "SwapWare". That means that if you wanted\r
+to go ahead and use my code directly, I really wouldn't care. But I ask\r
+that you send me some of your code that you think is neat. Especially if\r
+it's modifications that you make to this code, such as quick sprite drawing\r
+or optimizations.\r
+\r
+ I'm not going to brag and say that I "threw this together in a few hours".\r
+I didn't, it took me many days of work to get it working properly. But\r
+I'm also not looking for money as recompensation for my labor. I make\r
+great money at my real day job and you probably have a better use for your\r
+donations, such as legitimizing your unregistered shareware and pirated\r
+games. I'm in this for the knowledge ... so my best payback would be to\r
+get lots of code from people out there, stuff to really help make a great\r
+game. In particular, these would be great:\r
+ * 32-bit code\r
+ * Tricky optimizations\r
+ * Fast BitBlt/masked BitBlt code\r
+ * Useful File I/O functions\r
+ * 3D polygon and texture mapping code\r
+ * Maintenance routines -- like numeric conversions, etc.\r
+ * Hardware access code like timing routines and interrupt\r
+ handlers\r
+Any of those would be very helpful when writing a fast scrolling game.\r
+\r
+You can contact me (for the rest of this term only) at\r
+ seisner@athena.mit.edu\r
+Feel free to ask any questions you want! I check my mail about once or\r
+twice a week so don't expect instant turnaround... If you're desperate\r
+to talk to me, say if you work at Origin and want to give me the source\r
+code to Strike Commander or whatnot, you can also reach me at:\r
+ Steve Eisner\r
+ (617) 247-8691\r
+and leave a message. But I'd rather you wrote e-mail.\r
+\r
+ Thanks,\r
+ Steve Eisner\r
+\r
+* Read rec.games.programmer! And for those who already do:\r
+ I dream of a world where no one argues over why Wolfenstein\r
+ 3-D sucks or why it doesn't. Would people just give it a\r
+ break?\r
+\1a
\ No newline at end of file