1 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
\r
3 ³ To the VGA Trainer Program ³ ³
\r
5 ³ DENTHOR of ASPHYXIA ³ ³ ³
\r
6 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
\r
7 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
\r
8 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
14 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
17 Hello! By popular request, this part is all about animation. I will be
\r
18 going over three methods of doing animation on a PC, and will
\r
19 concerntrate specifically on one, which will be demonstrated in the
\r
20 attached sample code.
\r
22 Although not often used in demo coding, animation is usually used in
\r
23 games coding, which can be almost as rewarding ;-)
\r
25 In this part I will also be a lot less stingy with assembler code :)
\r
26 Included will be a fairly fast pure assembler putpixel, an asm screen
\r
27 flip command, an asm icon placer, an asm partial-flip and one or two
\r
28 others. I will be explaining how these work in detail, so this may also
\r
29 be used as a bit of an asm-trainer too.
\r
31 By the way, I apologise for this part taking so long to be released, but
\r
32 I only finished my exams a few days ago, and they of course took
\r
33 preference ;-). I have also noticed that the MailBox BBS is no longer
\r
34 operational, so the trainer will be uploaded regularly to the BBS lists
\r
35 shown at the end of this tutorial.
\r
37 If you would like to contact me, or the team, there are many ways you
\r
38 can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
\r
39 on the ASPHYXIA BBS.
\r
40 2) Write a message in the Programming conference on the
\r
41 For Your Eyes Only BBS (of which I am the Moderator )
\r
42 This is preferred if you have a general programming query
\r
43 or problem others would benefit from.
\r
44 4) Write to Denthor, Eze or Livewire on Connectix.
\r
45 5) Write to : Grant Smith
\r
49 6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
\r
50 call during varsity)
\r
51 7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
\r
52 mention the word Denthor near the top of the letter.
\r
54 NB : If you are a representative of a company or BBS, and want ASPHYXIA
\r
55 to do you a demo, leave mail to me; we can discuss it.
\r
56 NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
\r
57 quite lonely and want to meet/help out/exchange code with other demo
\r
58 groups. What do you have to lose? Leave a message here and we can work
\r
59 out how to transfer it. We really want to hear from you!
\r
63 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
64 þ The Principals of Animation
\r
66 I am sure all of you have seen a computer game with animation at one or
\r
67 other time. There are a few things that an animation sequence must do in
\r
68 order to give an impression of realism. Firstly, it must move,
\r
69 preferably using different frames to add to the realism (for example,
\r
70 with a man walking you should have different frames with the arms an
\r
71 legs in different positions). Secondly, it must not destroy the
\r
72 background, but restore it after it has passed over it.
\r
74 This sounds obvious enough, but can be very difficult to code when you
\r
75 have no idea of how to go about achieving that.
\r
77 In this trainer I will discuss various methods of meeting these two
\r
82 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
83 þ Frames and Object Control
\r
85 It is quite obvious that for most animation to succeed, you must have
\r
86 numerous frames of the object in various poses (such as a man with
\r
87 several frames of him walking). When shown one after the other, these
\r
88 give the impression of natural movement.
\r
90 So, how do we store these frames? I hear you cry. Well, the obvious
\r
91 method is to store them in arrays. After drawing a frame in Autodesk
\r
92 Animator and saving it as a .CEL, we usually use the following code to
\r
95 TYPE icon = Array [1..50,1..50] of byte;
\r
99 Procedure LoadCEL (FileName : string; ScrPtr : pointer);
\r
102 Buf : array [1..1024] of byte;
\r
103 BlocksRead, Count : word;
\r
105 assign (Fil, FileName);
\r
107 BlockRead (Fil, Buf, 800); { Read and ignore the 800 byte header }
\r
108 Count := 0; BlocksRead := $FFFF;
\r
109 while (not eof (Fil)) and (BlocksRead <> 0) do begin
\r
110 BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
\r
111 Count := Count + 1024;
\r
117 Loadcel ('Tree.CEL',addr (tree));
\r
120 We now have the 50x50 picture of TREE.CEL in our array tree. We may access
\r
121 this array in the usual manner (eg. col:=tree [25,30]). If the frame is
\r
122 large, or if you have many frames, try using pointers (see previous
\r
125 Now that we have the picture, how do we control the object? What if we
\r
126 want multiple trees wandering around doing their own thing? The solution
\r
127 is to have a record of information for each tree. A typical data
\r
128 structure may look like the following :
\r
130 TYPE Treeinfo = Record
\r
131 x,y:word; { Where the tree is }
\r
132 speed:byte; { How fast the tree is moving }
\r
133 Direction:byte; { Where the tree is facing }
\r
134 frame:byte { Which animation frame the tree is
\r
135 currently involved in }
\r
136 active:boolean; { Is the tree actually supposed to be
\r
140 VAR Forest : Array [1..20] of Treeinfo;
\r
142 You now have 20 trees, each with their own information, location etc.
\r
143 These are accessed using the following means :
\r
144 Forest [15].x:=100;
\r
145 This would set the 15th tree's x coordinate to 100.
\r
149 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
150 þ Restoring the Overwritten Background
\r
152 I will discuss three methods of doing this. These are NOT NECESSARILY
\r
153 THE ONLY OR BEST WAYS TO DO THIS! You must experiment and decide which
\r
154 is the best for your particular type of program.
\r
158 Step 1 : Create two virtual pages, Vaddr and Vaddr2.
\r
159 Step 2 : Draw the background to Vaddr2.
\r
160 Step 3 : Flip Vaddr2 to Vaddr.
\r
161 Step 4 : Draw all the foreground objects onto Vaddr.
\r
162 Step 5 : Flip Vaddr to VGA.
\r
163 Step 6 : Repeat from 3 continuously.
\r
165 In ascii, it looks like follows ...
\r
167 +---------+ +---------+ +---------+
\r
169 | VGA | <======= | VADDR | <====== | VADDR2 |
\r
170 | | | (bckgnd)| | (bckgnd)|
\r
171 | | |+(icons) | | |
\r
172 +---------+ +---------+ +---------+
\r
174 The advantages of this approach is that it is straightforward, continual
\r
175 reading of the background is not needed, there is no flicker and it is
\r
176 simple to implement. The disadvantages are that two 64000 byte virtual
\r
177 screens are needed, and the procedure is not very fast because of the
\r
178 slow speed of flipping.
\r
183 Step 1 : Draw background to VGA.
\r
184 Step 2 : Grab portion of background that icon will be placed on.
\r
185 Step 3 : Place icon.
\r
186 Step 4 : Replace portion of background from Step 2 over icon.
\r
187 Step 5 : Repeat from step 2 continuously.
\r
189 In terms of ascii ...
\r
192 | +--|------- + Background restored (3)
\r
193 | * -|------> * Background saved to memory (1)
\r
195 | +--|------- # Icon placed (2)
\r
198 The advantages of this method is that very little extra memory is
\r
199 needed. The disadvantages are that writing to VGA is slower then writing
\r
200 to memory, and there may be large amounts of flicker.
\r
205 Step 1 : Set up one virtual screen, VADDR.
\r
206 Step 2 : Draw background to VADDR.
\r
207 Step 3 : Flip VADDR to VGA.
\r
208 Step 4 : Draw icon to VGA.
\r
209 Step 5 : Transfer background portion from VADDR to VGA.
\r
210 Step 6 : Repeat from step 4 continuously.
\r
214 +---------+ +---------+
\r
218 | Icon>* <|-----------|--+ |
\r
219 +---------+ +---------+
\r
221 The advantages are that writing from the virtual screen is quicker then
\r
222 from VGA, and there is less flicker then in Method 2. Disadvantages are
\r
223 that you are using a 64000 byte virtual screen, and flickering occurs
\r
224 with large numbers of objects.
\r
226 In the attached sample program, a mixture of Method 3 and Method 1 is
\r
227 used. It is faster then Method 1, and has no flicker, unlike Method 3.
\r
228 What I do is I use VADDR2 for background, but only restore the
\r
229 background that has been changed to VADDR, before flipping to VGA.
\r
231 In the sample program, you will see that I restore the entire background
\r
232 of each of the icons, and then place all the icons. This is because if I
\r
233 replace the background then place the icon on each object individually,
\r
234 if two objects are overlapping, one is partially overwritten.
\r
236 The following sections are explanations of how the various assembler
\r
237 routines work. This will probably be fairly boring for you if you
\r
238 already know assembler, but should help beginners and dabblers alike.
\r
241 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
244 To begin with, I will explain a few of the ASM variables and functions :
\r
246 <NOTE THAT THIS IS AN EXTREMELY SIMPLISTIC VIEW OF ASSEMBLY LANGUAGE!
\r
247 There are numerous books to advance your knowledge, and the Norton
\r
248 Guides assembler guide may be invaluable for people beginning to code
\r
249 in assembler. I haven't given you the pretty pictures you are supposed
\r
250 to have to help you understand it easier, I have merely laid it out like
\r
251 a programming language with it's own special procedures. >
\r
253 There are 4 register variables : AX,BX,CX,DX. These are words (double
\r
254 bytes) with a range from 0 to 65535. You may access the high and low
\r
255 bytes of these by replacing the X with a "H" for high or "L" for low.
\r
256 For example, AL has a range from 0-255.
\r
258 You also have two pointers : ES:DI and DS:SI. The part on the left is
\r
259 the segment to which you are pointing (eg $a000), and the right hand
\r
260 part is the offset, which is how far into the segment you are pointing.
\r
261 Turbo Pascal places a variable over 16k into the base of a segment, ie.
\r
262 DI or SI will be zero at the start of the variable.
\r
264 If you wish to be pointing to pixel number 3000 on the VGA screen (see
\r
265 previous parts for the layout of the VGA screen), ES would be equal to
\r
266 $a000 and DI would be equal to 3000. You can quite as easily make ES or
\r
267 DS be equal to the offset of a virtual screen.
\r
269 Here are a few functions that you will need to know :
\r
271 mov destination,source This moves the value in source to
\r
272 destination. eg mov ax,50
\r
273 add destination,source This adds source to destination,
\r
274 the result being stored in destination
\r
275 mul source This multiplies AX by source. If
\r
276 source is a byte, the source is
\r
277 multiplied by AL, the result being
\r
278 stored in AX. If source is a word,
\r
279 the source is multiplied by AX, the
\r
280 result being stored in DX:AX
\r
281 movsb This moves the byte that DS:SI is
\r
282 pointing to into ES:DI, and
\r
283 increments SI and DI.
\r
284 movsw Same as movsb except it moves a
\r
285 word instead of a byte.
\r
286 stosw This moves AX into ES:DI. stosb
\r
287 moves AL into ES:DI. DI is then
\r
289 push register This saves the value of register by
\r
290 pushing it onto the stack. The
\r
291 register may then be altered, but
\r
292 will be restored to it's original
\r
294 pop register This restores the value of a pushed
\r
295 register. NOTE : Pushed values must
\r
296 be popped in the SAME ORDER but
\r
298 rep command This repeats Command by as many
\r
299 times as the value in CX
\r
302 SHL Destination,count ;
\r
303 and SHR Destination,count ;
\r
304 need a bit more explaining. As you know, computers think in ones and
\r
305 zeroes. Each number may be represented in this base 2 operation. A byte
\r
306 consists of 8 ones and zeroes (bits), and have a range from 0 to 255. A
\r
307 word consists of 16 ones and zeroes (bits), and has a range from 0 to
\r
308 65535. A double word consists of 32 bits.
\r
310 The number 53 may be represented as follows : 00110101. Ask someone who
\r
311 looks clever to explain to you how to convert from binary to decimal and
\r
314 What happens if you shift everything to the left? Drop the leftmost
\r
315 number and add a zero to the right? This is what happens :
\r
321 As you can see, the value has doubled! In the same way, by shifting one
\r
322 to the right, you halve the value! This is a VERY quick way of
\r
323 multiplying or dividing by 2. (note that for dividing by shifting, we
\r
324 get the trunc of the result ... ie. 15 shr 1 = 7)
\r
326 In assembler the format is SHL destination,count This shifts
\r
327 destination by as many bits in count (1=*2, 2=*4, 3=*8, 4=*16 etc)
\r
328 Note that a shift takes only 2 clock cycles, while a mul can take up to 133
\r
329 clock cycles. Quite a difference, no? Only 286es or above may have count
\r
330 being greater then one.
\r
332 This is why to do the following to calculate the screen coordinates for
\r
333 a putpixel is very slow :
\r
341 But alas! I hear you cry. 320 is not a value you may shift by, as you
\r
342 may only shift by 2,4,8,16,32,64,128,256,512 etc.etc. The solution is
\r
343 very cunning. Watch.
\r
348 mov bx, dx {; bx = dx = Y}
\r
349 mov dh, dl {; dh = dl = Y}
\r
350 xor dl, dl {; These 2 lines equal dx*256 }
\r
356 shl bx, 1 {; bx = bx * 64}
\r
357 add dx, bx {; dx = dx + bx (ie y*320)}
\r
358 pop bx {; get back our x}
\r
359 add bx, dx {; finalise location}
\r
362 Let us have a look at this a bit closer shall we?
\r
363 bx=dx=y dx=dx*256 ; bx=bx*64 ( Note, 256+64 = 320 )
\r
365 dx+bx=Correct y value, just add X!
\r
367 As you can see, in assembler, the shortest code is often not the
\r
370 The complete putpixel procedure is as follows :
\r
372 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
\r
373 { This puts a pixel on the screen by writing directly to memory. }
\r
376 push ds {; Make sure these two go out the }
\r
377 push es {; same they went in }
\r
379 mov es,ax {; Point to segment of screen }
\r
382 push bx {; and this again for later}
\r
383 mov bx, dx {; bx = dx}
\r
384 mov dh, dl {; dx = dx * 256}
\r
391 shl bx, 1 {; bx = bx * 64}
\r
392 add dx, bx {; dx = dx + bx (ie y*320)}
\r
393 pop bx {; get back our x}
\r
394 add bx, dx {; finalise location}
\r
395 mov di, bx {; di = offset }
\r
396 {; es:di = where to go}
\r
399 mov es:[di],ah {; move the value in ah to screen
\r
406 Note that with DI and SI, when you use them :
\r
407 mov di,50 Moves di to position 50
\r
408 mov [di],50 Moves 50 into the place di is pointing to
\r
411 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
412 þ The Flip Procedure
\r
414 This is fairly straightforward. We get ES:DI to point to the start of
\r
415 the destination screen, and DS:SI to point to the start of the source
\r
416 screen, then do 32000 movsw (64000 bytes).
\r
418 procedure flip(source,dest:Word);
\r
419 { This copies the entire screen at "source" to destination }
\r
424 mov es, ax { ES = Segment of source }
\r
426 mov ds, ax { DS = Segment of source }
\r
427 xor si, si { SI = 0 Faster then mov si,0 }
\r
428 xor di, di { DI = 0 }
\r
430 rep movsw { Repeat movsw 32000 times }
\r
435 The cls procedure works in much the same way, only it moves the color
\r
436 into AX then uses a rep stosw (see program for details)
\r
438 The PAL command is almost exactly the same as it's Pascal equivalent
\r
439 (see previous tutorials). Look in the sample code to see how it uses the
\r
440 out and in commands.
\r
443 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
446 The assembler procedures presented to you in here are not at their best.
\r
447 Most of these are procedures ASPHYXIA abandoned for better ones after
\r
448 months of use. But, as you will soon see, they are all MUCH faster then
\r
449 the original Pascal equivalents I originally gave you. In future, I
\r
450 hope to give you more and more assembler procedures for your ever
\r
451 growing collections. But, as you know, I am not always very prompt with
\r
452 this series (I don't know if even one has been released within one week
\r
453 of the previous one), so if you want to get any stuff done, try do it
\r
454 yourself. What do you have to lose, aside from your temper and a few
\r
455 rather inventive reboots ;-)
\r
457 What should I do for the next trainer? A simple 3-d tutorial? You may
\r
458 not like it, because I would go into minute detail of how it works :)
\r
459 Leave me suggestions for future trainers by any of the means discussed
\r
460 at the top of this trainer.
\r
462 After the customary quote, I will place a listing of the BBSes I
\r
463 currently know that regularly carry this Trainer Series. If your BBS
\r
464 receives it regularly, no matter where in the country you are, get a
\r
465 message to me and I'll add it to the list. Let's make it more convenient
\r
466 for locals to grab a copy without calling long distance ;-)
\r
468 [ There they sit, the preschooler class encircling their
\r
469 mentor, the substitute teacher.
\r
470 "Now class, today we will talk about what you want to be
\r
471 when you grow up. Isn't that fun?" The teacher looks
\r
472 around and spots the child, silent, apart from the others
\r
473 and deep in thought. "Jonny, why don't you start?" she
\r
475 Jonny looks around, confused, his train of thought
\r
476 disrupted. He collects himself, and stares at the teacher
\r
477 with a steady eye. "I want to code demos," he says,
\r
478 his words becoming stronger and more confidant as he
\r
479 speaks. "I want to write something that will change
\r
480 peoples perception of reality. I want them to walk
\r
481 away from the computer dazed, unsure of their footing
\r
482 and eyesight. I want to write something that will
\r
483 reach out of the screen and grab them, making
\r
484 heartbeats and breathing slow to almost a halt. I want
\r
485 to write something that, when it is finished, they
\r
486 are reluctant to leave, knowing that nothing they
\r
487 experience that day will be quite as real, as
\r
488 insightful, as good. I want to write demos."
\r
489 Silence. The class and the teacher stare at Jonny, stunned. It
\r
490 is the teachers turn to be confused. Jonny blushes,
\r
491 feeling that something more is required. "Either that
\r
492 or I want to be a fireman."
\r
501 These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
\r
503 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
\r
504 ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
\r
505 ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
\r
506 ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
\r
507 ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
\r
508 ºConnectix BBS º(031) 266-9992 ºALL º * º * º * º
\r
509 ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º
\r
510 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
\r
512 Open = Open at all times or only A/H
\r
513 Msg = Available in message base
\r
514 File = Available in file base
\r
515 Past = Previous Parts available
\r
518 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
527 Type Toastinfo = Record { This is format of of each of our }
\r
528 x,y:integer; { records for the flying toasters }
\r
529 speed,frame:integer;
\r
533 icon = Array [1..30*48] of byte; { This is the size of our pictures }
\r
535 Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
\r
536 VirtPtr = ^Virtual; { Pointer to the virtual screen }
\r
538 CONST frame1 : icon = (
\r
539 0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,
\r
540 7,7,7,7,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,
\r
541 5,7,7,7,7,7,7,7,8,8,7,7,7,7,7,7,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
\r
542 0,0,0,0,0,5,5,7,7,7,7,7,8,8,7,8,8,7,8,7,8,7,7,7,5,8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,
\r
543 5,0,0,0,0,0,0,0,0,0,0,0,5,7,7,7,7,7,7,8,7,7,7,8,7,7,7,7,7,7,0,0,0,0,0,0,8,5,5,5,
\r
544 5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,7,7,8,8,7,7,8,7,7,8,7,7,7,7,7,0,0,0,0,0,
\r
545 0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,5,7,8,8,8,7,7,8,7,7,8,7,7,7,
\r
546 7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,5,7,8,8,8,7,7,
\r
547 8,8,8,8,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
548 9,5,7,8,8,8,8,8,7,7,8,8,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
\r
549 1,1,1,1,9,9,9,9,5,7,7,8,8,8,8,7,7,8,8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
\r
550 1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,5,7,8,8,7,7,8,8,7,8,8,8,7,0,0,0,0,0,0,0,0,0,0,0,0,
\r
551 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,5,7,8,8,7,7,7,7,8,8,7,7,7,0,0,0,0,
\r
552 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,8,8,8,8,8,8,8,7,
\r
553 7,7,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,7,
\r
554 7,7,7,7,7,7,7,7,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
\r
555 1,1,1,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,1,1,
\r
556 1,1,0,0,0,1,1,1,1,1,1,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,
\r
557 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,
\r
558 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
\r
559 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
\r
560 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,1,1,1,1,0,0,0,1,1,1,
\r
561 1,1,1,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,1,4,
\r
562 4,6,6,6,6,6,6,1,1,1,1,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,
\r
563 0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
\r
564 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
\r
565 9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
566 9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
\r
567 1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
568 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
569 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
570 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
571 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
572 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
573 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
574 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
\r
577 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
578 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
579 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
580 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
581 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
582 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
583 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
584 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
585 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
586 9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
\r
587 1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,
\r
588 1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,
\r
589 0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
\r
590 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
\r
591 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,5,
\r
592 5,5,5,5,5,5,5,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,
\r
593 1,1,1,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
\r
594 1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
595 0,0,0,0,0,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,
\r
596 0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,5,5,5,5,
\r
597 5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
\r
598 2,2,2,2,2,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,0,0,0,1,1,1,
\r
599 1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,7,1,4,
\r
600 4,6,6,6,6,6,6,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,
\r
601 0,0,0,5,5,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,0,0,
\r
602 0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,
\r
603 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
604 9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
\r
605 1,1,1,1,9,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,
\r
606 1,7,7,1,7,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,
\r
607 0,0,0,0,0,0,0,5,5,1,7,7,7,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,0,
\r
608 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,1,1,5,5,5,5,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,
\r
609 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,
\r
610 0,0,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
611 0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
612 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
\r
615 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
616 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
617 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
618 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
619 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
620 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
621 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
622 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
623 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
624 9,9,9,9,9,9,9,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,1,1,1,1,1,1,1,1,1,1,1,
\r
625 1,1,1,1,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,7,1,1,1,1,1,
\r
626 1,1,0,0,0,1,1,1,1,1,1,1,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,
\r
627 0,7,1,1,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,7,7,7,7,5,5,5,5,5,5,
\r
628 5,0,0,0,0,0,0,0,7,1,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,5,5,1,1,1,7,7,
\r
629 1,1,7,5,5,5,5,5,5,5,0,0,0,0,0,0,1,1,7,1,1,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
\r
630 2,1,7,7,7,1,7,7,7,7,7,5,5,5,5,5,5,5,5,0,0,0,0,0,1,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,
\r
631 1,1,1,2,2,2,2,2,2,1,7,7,7,7,7,7,7,1,1,5,5,5,5,5,5,5,5,5,0,0,0,0,7,7,1,7,1,7,1,1,
\r
632 1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,2,2,5,5,5,5,5,5,5,5,5,5,5,0,0,0,
\r
633 7,7,7,7,7,1,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,
\r
634 5,5,5,5,5,0,0,0,7,7,0,0,7,7,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,
\r
635 2,2,5,5,0,0,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,2,2,2,2,2,
\r
636 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,1,1,1,1,0,0,0,1,1,1,
\r
637 1,1,1,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,1,4,
\r
638 4,6,6,6,6,6,6,1,1,1,1,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,
\r
639 0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
\r
640 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,3,3,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,
\r
641 9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,
\r
642 9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
\r
643 1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
644 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
645 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
646 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
647 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
648 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
649 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
650 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
\r
654 VAR Virscr : VirtPtr; { Our first Virtual screen }
\r
655 VirScr2 : VirtPtr; { Our second Virtual screen }
\r
656 Vaddr : word; { The segment of our virtual screen}
\r
657 Vaddr2 : Word; { The segment of our 2nd virt. screen}
\r
658 ourpal : Array [0..255,1..3] of byte; { A virtual pallette }
\r
659 toaster : Array [1..10] of toastinfo; { The toaster info }
\r
661 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
662 Procedure SetMCGA; { This procedure gets you into 320x200x256 mode. }
\r
671 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
672 Procedure SetText; { This procedure returns you to text mode. }
\r
680 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
681 Procedure Cls (Col : Byte; Where:word);
\r
682 { This clears the screen to the specified color }
\r
697 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
698 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
\r
699 { This puts a pixel on the screen by writing directly to memory. }
\r
708 push bx {; and this again for later}
\r
709 mov bx, dx {; bx = dx}
\r
710 mov dh, dl {; dx = dx * 256}
\r
717 shl bx, 1 {; bx = bx * 64}
\r
718 add dx, bx {; dx = dx + bx (ie y*320)}
\r
719 pop bx {; get back our x}
\r
720 add bx, dx {; finalise location}
\r
722 {; es:di = where to go}
\r
732 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
733 procedure WaitRetrace; assembler;
\r
734 { This waits for a vertical retrace to reduce snow on the screen }
\r
750 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
751 Procedure Pal(Col,R,G,B : Byte);
\r
752 { This sets the Red, Green and Blue values of a certain color }
\r
768 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
769 Procedure GetPal(Col : Byte; Var R,G,B : Byte);
\r
770 { This gets the Red, Green and Blue values of a certain color }
\r
793 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
794 Procedure SetUpVirtual;
\r
795 { This sets up the memory needed for the virtual screen }
\r
797 GetMem (VirScr,64000);
\r
798 vaddr := seg (virscr^);
\r
799 GetMem (VirScr2,64000);
\r
800 vaddr2 := seg (virscr2^);
\r
804 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
805 Procedure ShutDown;
\r
806 { This frees the memory used by the virtual screen }
\r
808 FreeMem (VirScr,64000);
\r
809 FreeMem (VirScr2,64000);
\r
813 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
814 procedure flip(source,dest:Word);
\r
815 { This copies the entire screen at "source" to destination }
\r
832 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
833 Procedure putico(X,Y:Word;VAR sprt : icon;Where:Word); ASSEMBLER;
\r
834 { This puts an icon, EXCEPT it's color 0 (black) pixels, onto the screen
\r
835 "where", at position X,Y }
\r
837 _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
\r
843 mov ax,X { ax = x }
\r
844 mov bx,Y { bx = y }
\r
850 mov ax, bx {; ax = bx x = y}
\r
851 mov bh, bl {; y = y * 256 bx = bx * 256}
\r
858 shl ax, 1 {; y = y * 64 ax = ax * 64}
\r
859 add bx, ax {; y = (y*256) + (Y*64) bx = bx + ax (ie y*320)}
\r
861 pop ax {; get back our x}
\r
864 add ax, bx {; finalise location}
\r
867 mov dl,30 { dl = height of sprite }
\r
869 mov cl,48 { cx = width of sprite }
\r
874 push di { store y adr. for later }
\r
875 mov cx,ax { store width }
\r
877 mov bl,byte ptr [si]
\r
892 add di,320 { di = next line of sprite }
\r
904 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
905 Procedure Funny_line(a,b,c,d:integer;where:word);
\r
906 { This procedure draws a line from a,b to c,d on screen "where". After
\r
907 each pixel it plots, it increments a color counter for the next pixel.
\r
908 you may easily alter this to be a normal line procedure, and it will
\r
909 be quite a bit faster than the origional one I gave you. This is
\r
910 because I replaced all the reals with integers. }
\r
912 function sgn(a:real):integer;
\r
914 if a>0 then sgn:=+1;
\r
915 if a<0 then sgn:=-1;
\r
916 if a=0 then sgn:=0;
\r
918 var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
\r
940 putpixel(a,b,count,where);
\r
942 if count=101 then count:=50;
\r
960 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
961 Procedure SetUpScreen;
\r
962 { This procedure sets up the static background to be used in the program }
\r
964 CONST circ : Array [1..5,1..5] of byte =
\r
972 loop1,loop2,loop3:integer;
\r
989 For loop1:=50 to 100 do
\r
990 pal (loop1,0,0,loop1-36);
\r
992 For loop1:=0 to 255 do
\r
993 getpal (loop1,OurPal[loop1,1],OurPal[loop1,2],OurPal[loop1,3]);
\r
995 For loop1:=0 to 319 do
\r
996 Funny_line (0,199,loop1,0,vaddr);
\r
997 For loop1:=0 to 199 do
\r
998 Funny_line (0,199,319,loop1,vaddr);
\r
1000 For loop1:=1 to 200 do BEGIN
\r
1003 For loop2:=1 to 5 do
\r
1004 For loop3:=1 to 5 do
\r
1005 if circ [loop2,loop3]<>0 then
\r
1006 putpixel (x+loop2,y+loop3,circ [loop2,loop3],vaddr);
\r
1008 flip (vaddr,vga); { Copy the entire screen at vaddr, our virtual screen }
\r
1009 { on which we have done all our graphics, onto the }
\r
1010 { screen you see, VGA }
\r
1011 flip (vaddr,vaddr2);
\r
1015 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
1016 Procedure rotatepal;
\r
1017 { This procedure rotates the colors between 50 and 100 }
\r
1018 VAR temp : Array [1..3] of byte;
\r
1021 Move(OurPal[100],Temp,3);
\r
1022 Move(OurPal[50],OurPal[51],50*3);
\r
1023 Move(Temp,OurPal[50],3);
\r
1024 For loop1:=50 to 100 do
\r
1025 pal (loop1,OurPal[loop1,1],OurPal[loop1,2],OurPal[loop1,3]);
\r
1029 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
1030 Procedure ScreenTrans (x,y:word);
\r
1031 { This is a small procedure to copy a 30x30 pixel block from coordinates
\r
1032 x,y on the virtual screen to coordinates x,y on the true vga screen }
\r
1043 push bx {; and this again for later}
\r
1044 mov bx, dx {; bx = dx}
\r
1045 mov dh, dl {; dx = dx * 256}
\r
1052 shl bx, 1 {; bx = bx * 64}
\r
1053 add dx, bx {; dx = dx + bx (ie y*320)}
\r
1054 pop bx {; get back our x}
\r
1055 add bx, dx {; finalise location}
\r
1056 mov di, bx {; es:di = where to go}
\r
1059 mov bx, 30 { Hight of block to copy }
\r
1061 mov cx, 24 { Width of block to copy divided by 2 }
\r
1063 add di,110h { 320 - 48 = 272 .. or 110 in hex }
\r
1071 { I wrote this procedure late last night, so it may not be in it's
\r
1072 most optimised state. Sorry :-)}
\r
1076 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
1077 Procedure NewToaster;
\r
1078 { This adds a new toaster to the screen }
\r
1079 VAR loop1:integer;
\r
1084 if not (toaster[loop1].active) then BEGIN
\r
1085 toaster[loop1].x:=random (200)+70;
\r
1086 toaster[loop1].y:=0;
\r
1087 toaster[loop1].active:=true;
\r
1088 toaster[loop1].frame:=1;
\r
1089 toaster[loop1].speed:=Random (3)+1;
\r
1096 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
1098 { This is the procedure where we move and put the toasters }
\r
1099 VAR loop1,loop2:integer;
\r
1102 For loop1:=1 to 10 do
\r
1103 toaster[loop1].active:=FALSE;
\r
1107 if keypressed then BEGIN
\r
1109 if ch='+' then NewToaster; { If '+' is pressed, add a toaster }
\r
1110 if ch='-' then BEGIN { if '-' is pressed, remove a toaster }
\r
1114 if toaster[loop1].active then BEGIN
\r
1115 screentrans (toaster[loop1].x,toaster[loop1].y);
\r
1116 toaster [loop1].active:=FALSE;
\r
1122 for loop1:=1 to 10 do
\r
1123 if toaster[loop1].active then BEGIN
\r
1124 screentrans (toaster[loop1].x,toaster[loop1].y);
\r
1125 { Restore the backgrond the toaster was over }
\r
1126 dec (toaster[loop1].x,toaster[loop1].speed);
\r
1127 inc (toaster[loop1].y,toaster[loop1].speed);
\r
1128 { Move the toaster }
\r
1129 if (toaster[loop1].x<1) or (toaster[loop1].y>170) then BEGIN
\r
1130 toaster[loop1].active:=FALSE;
\r
1133 { When toaster reaches the edge of the screen, render it inactive
\r
1134 and bring a new one into existance. }
\r
1136 for loop1:=1 to 10 do
\r
1137 if toaster[loop1].active then BEGIN
\r
1138 CASE toaster [loop1].frame of
\r
1139 1 : putico (toaster[loop1].x,toaster[loop1].y,frame1,vaddr);
\r
1140 3 : putico (toaster[loop1].x,toaster[loop1].y,frame2,vaddr);
\r
1141 2,4 : putico (toaster[loop1].x,toaster[loop1].y,frame3,vaddr);
\r
1143 toaster[loop1].frame:=toaster[loop1].frame+1;
\r
1144 if toaster [loop1].frame=5 then toaster[loop1].frame:=1;
\r
1145 { Draw all the toasters on the VGA screen }
\r
1155 Randomize; { Make sure that the RANDOM funcion really is random }
\r
1156 SetupVirtual; { Set up virtual page, VADDR }
\r
1158 writeln ('Hello! This program will demonstrate the principals of animation.');
\r
1159 writeln ('The program will firstly generate an arb background screen to a');
\r
1160 writeln ('virtual page, then flip it to the VGA. A toaster will then start');
\r
1161 writeln ('to move across the screen. Note that the background will be restored');
\r
1162 writeln ('after the toaster has passed over it. You may add or remove toasters');
\r
1163 writeln ('by hitting "+" or "-" respectively. Note that the more frames you');
\r
1164 writeln ('use, usually the better the routine looks. Because of space');
\r
1165 writeln ('restrictions, we only had room for three frames.');
\r
1167 writeln ('The toasters were drawn by Fubar (Pieter Buys) in Autodesk Animator.');
\r
1168 writeln ('I wrote a small little program to convert them into CONSTANTS. See');
\r
1169 writeln ('the main text to find out how to load up AA CEL files directly.');
\r
1172 Write (' Hit any key to contine ...');
\r
1175 SetupScreen; { Draw the background screen to VADDR, then flip it to
\r
1177 Fly; { Make the toasters fly around the screen }
\r
1179 ShutDown; { Free the memory taken up by virtual page }
\r
1180 Writeln ('All done. This concludes the seventh sample program in the ASPHYXIA');
\r
1181 Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
\r
1182 Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
\r
1183 Writeln ('Connectix BBS user, which is unfortunatly offline for the moment.');
\r
1184 Writeln ('For discussion purposes, I am also the moderator of the Programming');
\r
1185 Writeln ('newsgroup on the For Your Eyes Only BBS.');
\r
1186 Writeln ('The numbers are available in the main text. You may also write to me at:');
\r
1187 Writeln (' Grant Smith');
\r
1188 Writeln (' P.O. Box 270');
\r
1189 Writeln (' Kloof');
\r
1190 Writeln (' 3640');
\r
1191 Writeln ('I hope to hear from you soon!');
\r
1193 Write ('Hit any key to exit ...');
\r