OSDN Git Service

no idea how to get joy buttons 2 and 3 to function.
[proj16/16.git] / 16 / scrasm / SCROLL.DOC
1             ________________________________________________\r
2            |+----------------------------------------------+|\r
3            ||          I N T R O D U C I N G :             ||\r
4            |+----------------------------------------------+|\r
5            ||               Steve's 4-Way                  ||\r
6            ||    ___    ___   ____     ___    _      _     ||\r
7            ||   / __|  / __| |  _ \   / _ \  | |    | |    ||\r
8            ||  | <_   | |    | |_> | | | | | | |    | |    ||\r
9            ||   \_ \  | |    |    /  | | | | | |    | |    ||\r
10            ||   __> | | |__  | |\ \  | |_| | | |__  | |__  ||\r
11            ||  |___/   \___| |_| \_|  \___/  |____| |____| ||\r
12            |+______________________________________________+|\r
13            +------------------------------------------------+\r
14 \r
15   There, now that I have the hype outta the way, let me explain what\r
16 this program is.  I'm releasing the source code to my 4-way scrolling\r
17 code so that others can learn from it.  There aren't enough really\r
18 good resources out there for someone learning to program games, so I'm\r
19 trying to do my part to help.\r
20 \r
21 WHAT IT IS:\r
22 \r
23   The code is 100% assembly, for which I use MASM 6.0, so there may\r
24 be a few problems converting to Turbo Assembler.  I also use the ".386"\r
25 directive, meaning that you can't run this code with a 286 or earlier.\r
26 But most of the code should be easily convertible.  I haven't been\r
27 programming for 386's much so I really don't make the use of the 386\r
28 registers like I could have.  Mostly I just did it for some extra 386\r
29 instructions.\r
30 \r
31   You'll need a VGA which can support mode 13h, the MCGA mode.  This\r
32 code runs in "tweaked" MCGA mode, or what is called "Mode X".  For more\r
33 information on Mode X, check out the 1991 - 1992 issues of Doctor Dobbs\r
34 Journal, wherein you will find Michael Abrash's excellent Graphics\r
35 Programming column.  This is where I (and many others) found out about\r
36 Mode X, which is an excellent graphics mode for fast 256-color graphics.\r
37 Also, you can take a look at XLIB, YakIcons, FastGraph, etc which are all\r
38 graphics libraries (public domain or otherwise) which support Mode X\r
39 graphics and probably have some good documentation on programming the mode.\r
40 Additionally, check out _The Programmer's Guide to the EGA and VGA Cards_,\r
41 by Richard Ferraro, and _Power Graphics Programming_ (out of print, but\r
42 available directly from Que Books) by Michael Abrash.  Finally, you can\r
43 ask about graphics programming on many newsgroups such as\r
44 "rec.games.programmer"...\r
45 \r
46 WHAT IT DOES:\r
47 \r
48   The code will allow you to create "tiled" background patterns and then\r
49 to omnidirectionally scroll over them.  You could implement sprite routines\r
50 and then animate them over the background, but I haven't gotten this far\r
51 yet.  The scrolling is always relational -- ie no "jump-to"'s, just "scroll\r
52 left", "scroll up", etc.  Jump to would be very easy to implement, I just\r
53 haven't done it yet.\r
54 \r
55   It runs at about 60-70 fps on a 386/20, which means that it is operating\r
56 in under the time of one vertical refresh (_just_ under, according to some\r
57 timing I've done).  This could probably be reduced, but the best way to\r
58 reduce it is to limit the speed at which it scrolls -- if you stick to\r
59 scrolling at most 8 pixels at a time in two axes or 16 pixels at a time\r
60 in one axis, it is very fast.  More than that, and it occasionally takes\r
61 more than one refresh period even on my 486.  Still, that should be\r
62 fast enough for just about any game.\r
63 \r
64   I also included some routines to generate maps, tiles, and palettes\r
65 so you can see the file formats.  These are in C, and the executables\r
66 are around in case you don't care to recompile.  None of the utilities\r
67 are exactly production quality.  You'll have to look at the code to\r
68 figure out the arguments!  Luckily you can just run them with no args\r
69 and they perform default behavior.\r
70 \r
71   Lastly, the program SCROLL.EXE is a demo of what it can do.  In this\r
72 demo you can use one of two sets of keyboard controls to scroll around.\r
73 One, the default set of commands, lets you press up/down/left/right and\r
74 scroll in that direction.  The other has "intertia" -- pressing up/down\r
75 left/right will accelerate you in that direction.  You'll see what I\r
76 mean, just experiment.  You can switch keyhandlers by pressing K.\r
77 You can also switch between the diagonal pattern map and a logo map\r
78 by pressing M.  (By the way, it will eventually run out of memory loading\r
79 the maps and the diagonal map will screw up... don't worry about it,\r
80 it'd be fixed if I had more time).  Try it out.\r
81 \r
82 CREDIT WHERE CREDIT IS DUE:\r
83 \r
84   People who (unknowingly) helped me out:\r
85 \r
86         Keyboard by Steven Dollins, Brown Computer Group.  From his\r
87                 KEYINT routines, which is an INT 9 handler to let you\r
88                 keep track of many keys being pressed at the same time.\r
89         Graphics, basically, by Michael Abrash, whose Mode X columns\r
90                 influenced me greatly.\r
91         Palette fades and file I/O by the Future Crew.  Thanks for\r
92                 letting out the Mental Surgery code!\r
93         CPU detection by Ray Duncan, taken from one of his books.\r
94 \r
95   Obviously I haven't just pirated the code, it's all from publicly\r
96 released source code and I modified it a bit.  But I wouldn't have come\r
97 up with this whole thing without those helping hands.  Thanks.\r
98 \r
99 HOW IT WORKS:\r
100 \r
101   Here's how the scrolling works.  I'll explain it from a single-page\r
102 point of view, although it actually uses several pages of video memory.\r
103 The video memory is laid out like this:\r
104 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ\r
105 º                                ³ /  /  /  / º  ³\r
106 º                                ³/  /  /  /  º  ³\r
107 º                                ³  /  /  /  /º  ³\r
108 º           Visible page         ³ / Not /  / º  ³\r
109 º                                ³/ visible/  º  ³\r
110 º                                ³  /  /  /  /º 64K\r
111 º                                ³ /  /  /  / º  ³\r
112 ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ/  /  /  /  º  ³\r
113 º  /  /  /  /  /  /  /  /  /  /  /  /  /  /  /º  ³\r
114 º /  /  /  /  /  /  /  /  /  /  /  /  /  /  / º  ³\r
115 º/  /  /  /  /  /  /  /  /  /  /  /  /  /  /  º  ³\r
116 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
117 In other words, it has a virtual width greater than the actual screen\r
118 width, and a virtual height higher than the actual screen height.  The\r
119 VGA hardware allows hardware panning around within the virtual area, so\r
120 that makes panning much easier:  you only have to draw the information\r
121 that is coming on to the screen with each pan.\r
122 \r
123 What is Happening:      What the user sees:\r
124 ÉÍÍÍÍÍÍÍÍÑÍÍÍÍ»          ÚÄÄÄÄÄÄÄÄ¿\r
125 º     hel³////º          ³     hel³           The picture that is\r
126 ÇÄÄÄÄÄÄÄÄÙ////º          ÀÄÄÄÄÄÄÄÄÙ           coming on to the screen\r
127 º/////////////º                               ("hello") appears to\r
128 ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ                               the user to be scrolling\r
129 ÉÍÑÍÍÍÍÍÍÍÑÍÍÍ»          ÚÄÄÄÄÄÄÄÄ¿           left, although it is\r
130 º/³   hell³///º          ³    hell³           actually at a stationary\r
131 º/ÀÄÄÄÄÄÄÄÙ///º          ÀÄÄÄÄÄÄÄÄÙ           location in memory...\r
132 º/////////////º                               Each time the frame moves,\r
133 ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ                               it is not necessary to\r
134 ÉÍÍÑÍÍÍÍÍÍÍÑÍÍ»          ÚÄÄÄÄÄÄÄÄ¿           redraw the parts that stay\r
135 º//³  hello³//º          ³   hello³           on the screen, just the\r
136 º//ÀÄÄÄÄÄÄÄÙ//º          ÀÄÄÄÄÄÄÄÄÙ           parts that become visible.\r
137 º/////////////º\r
138 ÈÍÍÍÍÍÍÍÍÍÍÍÍͼ\r
139 \r
140   The same works up&down too, or even left/right and up/down at the same\r
141 time.  The problem occurs when you scroll enough to hit the edge of the\r
142 virtual space.  Luckily, video memory increases and wraps at the right\r
143 edge to one line down on the left edge.  So you end up with a situation\r
144 like this after scrolling too far right:\r
145 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍ» ÄÄÄ\r
146 ÇÄÄÄÄÄÄÄ¿//////³    º  ³        User sees:\r
147 º       ³//////³  Thº  ³       ÚÄÄÄÄÄÄÄÄÄÄÄ¿\r
148 ºe quick³//////³    º 64K      ³           ³\r
149 º       ³//////ÀÄÄÄĶ  ³       ³  The quick³\r
150 ÇÄÄÄÄÄÄÄÙ///////////º  ³       ³           ³\r
151 º///////////////////º  ³       ÀÄÄÄÄÄÄÄÄÄÄÄÙ\r
152 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
153 The wrapping is transparent to the user.  So, it appears that you can\r
154 scroll left & right infinitely, by simply always updating the amount of\r
155 memory that has scrolled into view.\r
156 \r
157   But what happens when you scroll too far down?  Now Intel segments come\r
158 to the rescue!  Because the video memory is 64K, and that is also the\r
159 largest amount of memory you can access in a segment, the segment arithmetic\r
160 performs the top-to-bottom wrapping for me.  It results in a similar\r
161 situation as is pictured above, but with the screen split horizontally\r
162 instead of vertically.  Again, it's completely transparent to the user.\r
163 \r
164   One performance optimization that I've done is to organize the background\r
165 picture that is being scrolled into quantitized "tiles" -- 16x16 pixels in\r
166 area.  This means that you can store a large amount of picture data if that\r
167 data is repetitive -- as the backgrounds of many video games are.  This also\r
168 helps when figuring out how much new stuff to draw on the screen.  I can wait\r
169 until the panning crosses a 16-pixel border, then draw another 16-pixel\r
170 strip, and then wait for another tile crossing, etc.  You can see this in\r
171 the MAP.INC and SCROLL.INC code.  16x16 pixels also leads to 256-pixel-square\r
172 tiles, which is always a convenient number in assembly... it helps out in\r
173 several places in the code.\r
174 \r
175   So, the display page is "wandering" around the video memory, only drawing\r
176 what is necessary at any time.  Meanwhile you can animate sprites over the\r
177 background, etc.  The only problem is that with one page, information is\r
178 constantly being drawn to that page and you can never guarantee that it is in\r
179 a correct state at the time of a vertical refresh period.  Instead, I actually\r
180 use several pages, so that one can be shown while the other is worked on.\r
181 This guarantees a perfect picture at any time.  So for now, let's ignore the\r
182 scrolling for a second, and talk about the paging, because it's easier to\r
183 understand the paging if scrolling isn't happening.\r
184 \r
185   Here's a basic explanation of how the paging works.  I use three separate\r
186 pages, a Draw page, a Show page, and a Blank page.  The Show page refers to\r
187 the page that is currently showing, the Draw page to the page that is\r
188 under construction (to be shown next frame), and the Blank page should always\r
189 be maintained as an up-to-date blank background page.  (The Blank page is\r
190 useful for sprite programming which I am going to be doing next.)  Each\r
191 of the pages is 352x240, although the screen resolution is only 320x200.\r
192 \r
193   Each frame, the pages rotate DrawPage->ShowPage->BlankPage->DrawPage.\r
194 This means that at the beginning of the frame, the Draw Page is already\r
195 blank, so all that is necessary is to draw on a bunch of sprites.  The\r
196 BlankPage, though, is no longer blank (it's still got stuff from what\r
197 was the ShowPage) so we have to erase it, by blanking out the sprites\r
198 (luckily the new DrawPage _is_ empty, so we can use a Mode X 32-bit video-\r
199 to-video copy to blank it).  Hope you're still with me.\r
200 \r
201   So, this loop continues with each frame, and the loop invariants are\r
202 maintained:  Show Page is always a "good" frame -- don't touch it.  Blank\r
203 Page is always blank.  Draw Page can look like anything.  Now to include\r
204 the scrolling again:\r
205 \r
206   The way I do scrolling with several pages is that the pages ALL wander\r
207 around video memory, only they're smaller (1/3 of the size that they could\r
208 have been, to be exact!).  Here's a picture of the situation at its worst:\r
209 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ÄÄÄ\r
210 º  ³//ÀÄÄÄÄÄÄÄĺ  ³\r
211 ºÄÄÙ///////////º  ³\r
212 º/////ÚÄÄÄÄÄÄÄĺ  ³\r
213 ºÄÄ¿//³PAGE 0  º  ³\r
214 º  ³//³ (Draw) º  ³\r
215 º  ³//ÀÄÄÄÄÄÄÄĺ  ³\r
216 ºÄÄÙ///////////º 64K\r
217 º/////ÚÄÄÄÄÄÄÄĺ (21K each page)\r
218 ºÄÄ¿//³PAGE 1  º  ³\r
219 º  ³//³ (Show) º  ³\r
220 º  ³//ÀÄÄÄÄÄÄÄĺ  ³\r
221 ºÄÄÙ///////////º  ³\r
222 º/////ÚÄÄÄÄÄÄÄĺ  ³\r
223 ºÄÄ¿//³PAGE 2  º  ³\r
224 º  ³//³ (Blank)º  ³\r
225 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÄÄÄ\r
226 The pages always maintain an equal distance apart as they wander.  Since\r
227 all pages move in parallel, the way it used to work is that as soon as the\r
228 pages scrolled, I would draw the newly-visible picture information on\r
229 all three of the pages.  This worked great, except that it resulted in\r
230 a slight pause every time the screen scrolled because it was doing hardware\r
231 pan most of the time (which is very fast) and the drawing routines were\r
232 slow.  Now, I've spread the copying over successive frames to allow a\r
233 smoother scrolling rate.  This is possible because it's not really necessary\r
234 to draw the new information to a page before that page becomes the show\r
235 page...\r
236 \r
237   I hope that this has made some sense.  It's pretty complicated stuff.\r
238 Take a look at the code and maybe that will help.  Or, write me mail\r
239 (my email address is below).  Or, design your own way and ignore this\r
240 whole thing.\r
241 \r
242 COMING SOON:\r
243 \r
244   Next up are Sprite routines.  I threw in what I started as SPRITE.INC,\r
245 although it's not included in the project right now.\r
246   Sound support\r
247 \r
248   Who knows what else?  Depends on what people send me!\r
249 \r
250 -------------------------------------------------------------------------\r
251                            R E A D   T H I S\r
252 -------------------------------------------------------------------------\r
253                            R E A D   T H I S\r
254 -------------------------------------------------------------------------\r
255 \r
256   This code is being released as "SwapWare".  That means that if you wanted\r
257 to go ahead and use my code directly, I really wouldn't care.  But I ask\r
258 that you send me some of your code that you think is neat.  Especially if\r
259 it's modifications that you make to this code, such as quick sprite drawing\r
260 or optimizations.\r
261 \r
262   I'm not going to brag and say that I "threw this together in a few hours".\r
263 I didn't, it took me many days of work to get it working properly.  But\r
264 I'm also not looking for money as recompensation for my labor.  I make\r
265 great money at my real day job and you probably have a better use for your\r
266 donations, such as legitimizing your unregistered shareware and pirated\r
267 games.  I'm in this for the knowledge ... so my best payback would be to\r
268 get lots of code from people out there, stuff to really help make a great\r
269 game.  In particular, these would be great:\r
270         * 32-bit code\r
271         * Tricky optimizations\r
272         * Fast BitBlt/masked BitBlt code\r
273         * Useful File I/O functions\r
274         * 3D polygon and texture mapping code\r
275         * Maintenance routines -- like numeric conversions, etc.\r
276         * Hardware access code like timing routines and interrupt\r
277           handlers\r
278 Any of those would be very helpful when writing a fast scrolling game.\r
279 \r
280 You can contact me (for the rest of this term only) at\r
281         seisner@athena.mit.edu\r
282 Feel free to ask any questions you want!  I check my mail about once or\r
283 twice a week so don't expect instant turnaround...  If you're desperate\r
284 to talk to me, say if you work at Origin and want to give me the source\r
285 code to Strike Commander or whatnot, you can also reach me at:\r
286         Steve Eisner\r
287         (617) 247-8691\r
288 and leave a message.  But I'd rather you wrote e-mail.\r
289 \r
290                                         Thanks,\r
291                                            Steve Eisner\r
292 \r
293 *  Read rec.games.programmer!   And for those who already do:\r
294    I dream of a world where no one argues over why Wolfenstein\r
295    3-D sucks or why it doesn't.  Would people just give it a\r
296    break?\r
297 \1a