]> 4ch.mooo.com Git - 16.git/blobdiff - 16/scrasm/SCROLL.DOC
modified: 16/DOS_GFX.EXE
[16.git] / 16 / scrasm / SCROLL.DOC
diff --git a/16/scrasm/SCROLL.DOC b/16/scrasm/SCROLL.DOC
new file mode 100644 (file)
index 0000000..0893db3
--- /dev/null
@@ -0,0 +1,297 @@
+            ________________________________________________\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