OSDN Git Service

wwww
[proj16/16.git] / doc / scroll.txt
1
2
3
4       SSSSS   CCCCC  RRRRR    OOOOO  LL    LL    IIIIII NN    NN  GGGGG
5      SS   SS CC   CC RR  RR  OO   OO LL    LL      II   NNN   NN GG   GG
6      SS      CC      RR   RR OO   OO LL    LL      II   NNNN  NN GG
7       SSSSS  CC      RR  RR  OO   OO LL    LL      II   NN NN NN GG
8           SS CC      RRRRR   OO   OO LL    LL      II   NN  NNNN GG  GGG
9      SS   SS CC   CC RR  RR  OO   OO LL    LL      II   NN   NNN GG   GG
10       SSSSS   CCCCC  RR   RR  OOOOO  LLLLL LLLLL IIIIII NN    NN  GGGGG
11
12                     by Alec Thomas (Kestrel) of FORGE Software Australia
13                                           (c9223826@cs.newcastle.edu.au)
14
15
16 ------------
17 INTRODUCTION
18 ------------
19 Okay, here it is fans (and air conditioners, open windows...geez I hate that
20 joke!), how to do scrolling using either X-mode (and associated variants) and
21 standard mode 13h (not hard but I thought I'd put it in anyway :) as well as
22 the basics of parallax scrolling...
23
24 First things first - X-mode. Throughout this little dissertation, I'm going
25 to assume that you know the basics of X-mode (or mode-X or mode-Y or
26 whatever you want to call it) such as how to get into it, how to set the
27 offset register, etc. and just get on with the scrolling :) I'm not trying
28 to teach you X-mode, but SCROLLING!!
29
30 One further thing. I'm not saying that the methods I'll explain below are
31 the best method of scrolling, I'm just showing how I got it to work myself
32 in the hope that someone out there can use it. Anyway, enough of this crap,
33 on with the STUFF!!!
34
35 (just a little note, when I'm talking about rows, they number from 0-199 and
36 the same with columns (except 0-319), etc. unless otherwise stated)
37
38 ********************************************************************************
39 *                              X-MODE SCROLLING                        *
40 ********************************************************************************
41 ------------------
42 VERTICAL SCROLLING
43 ------------------
44 Ok, this is the easiest form of scrolling using the VGA hardware...fast and
45 clean. The following example assumes you are using 320x200 X-mode with the
46 visible page starting at the top of the first page (offset 0).
47
48 To scroll what is on the screen up off the top, you simply add 80 (decimal)
49 to the screen offset register. This causes the screen to jump up by one
50 row. However, it also causes whatever is off the bottom of the screen
51 (the next page!) to become visible...not a desireable effect.
52
53 Easily fixed however. Draw the image you want to scroll, on the row that
54 will scroll on. So, when the screen offset is changed to scroll the screen
55 up, the new data is already there for all to see. Beautiful!!!
56
57 ----------- Scrolling A (up) --------------
58 OFFSET = 0
59 WHILE NOT FINISHED DO
60   OFFSET = OFFSET + 80
61   DRAW TO ROW 200
62   SET VGA OFFSET = OFFSET
63 END WHILE
64 -------------------------------------------
65
66 Bzzzzz! Wrong! This works fine, until you have scrolled down to the
67 bottom of page 4. Because you're effectively off the bottom of the VGA
68 window (starting at segment A000h), you can't write to the rest of the
69 VGA memory (if there is any - only SVGA's have more than 256K on board
70 memory) and so, you'll be viewing garbage.
71
72 No problem. The way around it is to only use two pages!!! "What?" I hear
73 you say. In fact, by using only two pages for scrolling, you gain two
74 major advantages: page flipping (because you're only using two pages for
75 the actual scrolling, you can use the spare two to perform page flipping)
76 and infinite scroll regions.
77
78 You perform the infinite scrolling in exactly the same way as before, with
79 two minor additions: after changing the offset register, you copy the row
80 just scrolled on to the row just scrolled off. Also, after you have scrolled
81 a full page, you reset the offset to the top of the original page.
82
83 ----------- Scrolling B (up) --------------
84 OFFSET = 0
85 WHILE NOT FINISHED DO
86   OFFSET = OFFSET + 80
87   IF OFFSET >= (200 * 80) THEN OFFSET = 0
88   DRAW TO ROW 200
89   SET VGA OFFSET = OFFSET
90   DRAW TO ROW -1 (was row 0 before scroll)
91 END WHILE
92 -------------------------------------------
93
94 Ok, so that's how to do vertical scrolling, now on with horizontal scrolling.
95
96
97
98 --------------------
99 HORIZONTAL SCROLLING
100 --------------------
101 Horizontal scrolling is essentially the same as vertical scrolling, all
102 you do is increment or decrement the VGA offset register by 1 instead of
103 80 as with vertical scrolling.
104
105 However, horizontal scrolling is complicated by two things
106
107   1. Incrementing the offset register by one actually scrolls by FOUR
108      pixels (and there are FOUR planes on the VGA, what a coincidence)
109
110   2. You can't draw the image off the screen and then scroll it on
111      because of the way the VGA wraps to the next row every 80 bytes
112      (80 bytes * 4 planes = 320 pixels), if you tried it, you would
113      actually be drawing to the other side of the screen (which is
114      entirely visible)
115
116 I'll solve these problems one at a time.
117
118 Firstly, to get the VGA to scroll by only one pixel you use the horizontal
119 pixel panning (HPP) register. This register resides at
120
121   PORT:     3C0H
122   INDEX:    13h
123
124 and in real life, you use it like this
125
126 ----------------- Pixel Panning ---------------
127 IN PORT 3DAH (this clears an internal
128   flip-flop of the VGA)
129 OUT 13H TO PORT 3C0H
130 OUT value TO PORT 3C0H (where "value" is the
131   number of pixels to offset)
132 -----------------------------------------------
133
134 To implement smooth horizontal scrolling, you would do the following:
135
136 -------------- Horizontal Scrolling ------------
137 FOR X = 0 TO 319 DO
138   SET HPP TO ( X MOD 4 )
139   SET VGA OFFSET TO ( X/4 )
140 END FOR
141 ------------------------------------------------
142
143 Okay, no problem at all (although I think you might have to fiddle
144 around with the HPP a bit to get it right...try different values and
145 see what works :).
146
147 So, the next problem is with drawing the images off the screen where
148 they aren't visible and then scrolling them on!!! As it turns out,
149 there's yet ANOTHER register to accomplish this. This one's called the
150 offset register (no, not the one I was talking about before, that one
151 was actually the "start address" register) and it's at
152
153   PORT:     3D4H/3D5H
154   OFFSET:   13H
155
156 and here's how to use it
157
158 -------------- Offset Register ---------------
159 OUT 13H TO PORT 3D4H
160 OUT value TO PORT 3D5H
161 ----------------------------------------------
162
163 Now, what my VGA reference says is that this register holds the number
164 of bytes (not pixels) difference between the start address of each row.
165 So, in X-mode it normally contains the value 80 (as we remember,
166 80 bytes * 4 planes = 320 pixels). This register does not affect the
167 VISIBLE width of the display, only the difference between addresses on
168 each row.
169
170 When we scroll horizontally, we need a little bit of extra working space
171 so we can draw off the edge of the screen.
172
173 Perhaps a little diagram will clarify it. The following picture is of a
174 standard X-mode addressing scheme with the OFFSET register set to 80.
175
176       ROW    OFFSET
177       0  0 ========================
178       1 80 [                  ]
179       2       160 [                   ]
180       ..       .. [       VISIBLE       ]
181                   [     SCREEN  ]
182                   [                   ]
183                   [                   ]
184       ..       .. [                   ]
185       199   15920 ========================
186
187 and the next diagram is of a modified addressing scheme with the OFFSET
188 register set to 82 (to give us 4 extra pixels on each side of the screen)
189
190 ROW    OFFSET
191 0        0 ------========================------
192 1       82 |   V [                    ]   V |
193 2       164 |   I [                   ]   I |
194 ..       .. | N S [      VISIBLE         ] N S |
195             | O I [       SCREEN         ] O I |
196             | T B [                   ] T B |
197             |   L [                   ]   L |
198 ..       .. |   E [                   ]   E |
199 199   16318 ------========================------
200
201 Beautiful!!!
202
203 As with vertical scrolling, however, you still have the problem of when
204 you reach the bottom of page 4...and it's fixed in the same manner.
205
206 I haven't actually managed to get infinite horizontal scrolling working,
207 but the method I have just stated will give you a horizontal scrolling
208 range of over 200 screens!!!! So if you need more (which is extremely
209 unlikely), figure it out yourself.
210
211
212 ------------------
213 COMBINED SCROLLING
214 ------------------
215 To do both horizontal and vertical scrolling, all you have to do is combine
216 the two methods with a few little extras (it's always the way isn't it).
217
218 You have to start off with the original screen on the current page and the
219 next page as well. When you scroll horizontally, you have to draw the edge
220 that's coming in to the screen to BOTH pages (that means you'll be drawing
221 the incoming edge twice, once for each page). You do this so that when you
222 have scrolled vertically down through a complete page, you can jump back
223 to the first page and it will (hopefully) have an identical copy, and you
224 can then continue scrolling again.
225
226 I'm sorry about this being so confusing but it's a bit difficult to explain.
227
228
229
230
231
232 ********************************************************************************
233 *                           STANDARD VGA SCROLLING                          *
234 ********************************************************************************
235 Without X-mode, there is no easy way to do scrolling using the VGA hardware.
236 So basically, you have to resort to redrawing the entire screen for every
237 frame. Several popular games (Raptor and Mortal Kombat spring to mind)
238 utilise this method with excellent effect, so it is quite effective.
239
240 Basically all you do to implement this is redraw the screen every frame
241 with a slightly different offset into the "map".
242
243 The following bit of pseudo-code will scroll down and to the right
244 through the map.
245
246 ------------- Standard Scrolling ---------------
247 X = 0
248 Y = 0
249 WHILE NOT FINISHED DO
250   DRAW TO SCREEN( 0, 0 ) FROM MAP( X, Y )
251   X = X + 1
252   Y = Y + 1
253 END WHILE
254 ------------------------------------------------
255
256
257
258
259
260 ********************************************************************************
261 *                             PARALLAX SCROLLING                              *
262 ********************************************************************************
263 Parallax scrolling is when the "world" appears to have different levels
264 of perspective. That is, images further away from the viewer move
265 proportionately slower than images closer to the screen.
266
267 To implement parallax scrolling, you need two or more "maps". You start
268 from the most distant map and end with the closest map. When you scroll,
269 you offset the map furthest away by the smallest value and the map
270 closest to you by the largest value.
271
272 The following pseudo-code implements a 3 level parallax scrolling world,
273 scrolling (as above) down to the right.
274
275 --------------- Parallax Scrolling ------------------
276 X = 0
277 Y = 0
278 WHILE NOT FINISHED DO
279   DRAW TO SCREEN( 0, 0 ) USING MAP_FAR AT ( X/4, Y/4 )
280   DRAW TO SCREEN( 0, 0 ) USING MAP_MEDIUM AT ( X/2, Y/2 )
281   DRAW TO SCREEN( 0, 0 ) USING MAP_NEAR AT ( X, Y )
282   X = X + 4
283   Y = Y + 4
284 END WHILE
285 -----------------------------------------------------
286
287 Obviously, with parallax scrolling, each successive map shouldn't delete
288 the previous map entirely. So you'll have to draw the maps using some
289 sort of masking (masking being where you can see through the background
290 colour to what was there previously).
291
292
293 ********************************************************************************
294 *                                 DISCLAIMER                              *
295 ********************************************************************************
296 I'm sorry if any of this is confusing, but hey that's half the fun of it -
297 figuring out what the hell I'm raving on about :)
298
299 So, if you can figure it out, have fun and make games (preferably good ones!)
300
301 Later,
302       Kestrel => FORGE Software Australia