Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
back2root:archives:denthor:part-02 [2021/08/26 21:53] – créée frater | back2root:archives:denthor:part-02 [2023/05/20 23:28] (Version actuelle) – [How do I stop the "fuzz" that appears on my screen when I change the pallette?] frater | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ===== PART 2 : Colors palette ===== | + | ===== PART 02 : Colors palette ===== |
- | Hi there again! This is Grant Smith, AKA Denthor of ASPHYXIA. This is the second part of my Training Program for new programmers. I have only had a lukewarm response to my first part of the trainer series ... remember, if | + | Hi there again! This is Grant Smith, AKA Denthor of ASPHYXIA. This is the second part of my Training Program for new programmers. I have only had a lukewarm response to my first part of the trainer series ... |
- | I don't hear from you, I will assume that you are all dead and will stop writing the series ;-). Also, if you do get in contact with me I will give you some of our fast assembly routines which will speed up your demos no | + | |
- | end. So go on, leave mail to GRANT SMITH in the main section of the MailBox BBS, start up a discussion or ask a few questions in this Conference, leave mail to ASPHYXIA on the ASPHYXIA BBS, leave mail to Denthor on | + | remember, if I don't hear from you, I will assume that you are all dead and will stop writing the series ;-). |
- | Connectix, or write to | + | |
+ | Also, if you do get in contact with me I will give you some of our fast assembly routines which will speed up your demos no end. So go on, leave mail to GRANT SMITH in the main section of the MailBox BBS, start up a discussion or ask a few questions in this Conference, leave mail to ASPHYXIA on the ASPHYXIA BBS, leave mail to Denthor on Connectix, or write to | ||
< | < | ||
Grant Smith, | Grant Smith, | ||
Ligne 18: | Ligne 19: | ||
Most of these quesions will be answered in this, the second part of my Trainer Series for Pascal. | Most of these quesions will be answered in this, the second part of my Trainer Series for Pascal. | ||
- | ==== What is the Pallette? ==== | + | ==== What is the Palette? ==== |
A few weeks ago a friend of mine was playing a computer game. In the game there was a machine with stripes of blue running across it. When the machine was activated, while half of the the blue stripes stayed the same, the other half started to change color and glow. He asked me how two stripes of the same color suddenly become different like that. The answer is simple: | A few weeks ago a friend of mine was playing a computer game. In the game there was a machine with stripes of blue running across it. When the machine was activated, while half of the the blue stripes stayed the same, the other half started to change color and glow. He asked me how two stripes of the same color suddenly become different like that. The answer is simple: | ||
- | the program was changing the pallette. As you know from Part 1, there are 256 colors in MCGA mode, numbered 0 to 255. What you don't know is that each if those colors is made up of different intensities of Red, Green and Blue, the primary colors (you should have learned about the primary colors at school). These intensities are numbers between 0 and 63. The color of bright red would for example be obtained by setting red intensity to 63, | + | the program was changing the palette. As you know from Part 1, there are 256 colors in MCGA mode, numbered 0 to 255. |
- | green intensity to 0, and blue intensity to 0. This means that two colors can look exactly the same, eg you can set color 10 to bright red and color 78 to color bright red. If you draw a picture using both of those colors, | + | |
- | no-one will be able to tell the difference between the two.. It is only when you again change the pallette | + | What you don't know is that each if those colors is made up of different intensities of Red, Green and Blue, the primary colors (you should have learned about the primary colors at school). |
- | the "Fade in" and "Fade out" effects found in many demos and games. | + | |
+ | These intensities are numbers between 0 and 63. The color of bright red would for example be obtained by setting red intensity to 63, green intensity to 0, and blue intensity to 0. | ||
+ | |||
+ | This means that two colors can look exactly the same, eg you can set color 10 to bright red and color 78 to color bright red. | ||
+ | |||
+ | If you draw a picture using both of those colors, no-one will be able to tell the difference between the two.. | ||
+ | |||
+ | It is only when you again change the palette | ||
+ | |||
+ | Also, by changing the whole palette, you can obtain the "Fade in" and "Fade out" effects found in many demos and games. | ||
- | Pallette | + | Palette |
==== How do I read in the pallette value of a color? ==== | ==== How do I read in the pallette value of a color? ==== | ||
Ligne 69: | Ligne 79: | ||
The way we counter this is as follows : There is an elctron beam on your monitor that is constantly updating your screen from top to bottom. As it gets to the bottom of the screen, it takes a while for it to get back up to the top of the screen to start updating the screen again. The period where it moves from the bottom to the top is called the Verticle Retrace. During the verticle retrace you may change the pallette without affecting what is on the screen. What we do is that we wait until a verticle retrace has started by calling a certain procedure; this means that everything we do now will only be shown after the verticle retrace, so we can do all sorts of strange and unusual things to the screen during this retrace and only the results will be shown when the retrace is finished. This is way cool, as it means that when we change the pallette, the fuzz doesn' | The way we counter this is as follows : There is an elctron beam on your monitor that is constantly updating your screen from top to bottom. As it gets to the bottom of the screen, it takes a while for it to get back up to the top of the screen to start updating the screen again. The period where it moves from the bottom to the top is called the Verticle Retrace. During the verticle retrace you may change the pallette without affecting what is on the screen. What we do is that we wait until a verticle retrace has started by calling a certain procedure; this means that everything we do now will only be shown after the verticle retrace, so we can do all sorts of strange and unusual things to the screen during this retrace and only the results will be shown when the retrace is finished. This is way cool, as it means that when we change the pallette, the fuzz doesn' | ||
- | < | + | <WRAP round info> |
- | WaitRetrace can be a great help to your coding ... code that fits into one retrace will mean that the demo will run at the same speed no matter what your computer speed (unless you are doing a lot during the WaitRetrace and the computer is slooooow). Note that in the following sample program and in our SilkyDemo, the thing will run at the same speed whether turbo is on or off. | + | WaitRetrace can be a great help to your coding ... |
+ | |||
+ | code that fits into one retrace will mean that the demo will run at the same speed no matter what your computer speed (unless you are doing a lot during the WaitRetrace and the computer is slooooow). | ||
+ | |||
+ | Note that in the following sample program and in our SilkyDemo, the thing will run at the same speed whether turbo is on or off. | ||
</ | </ | ||
Ligne 205: | Ligne 219: | ||
See you next week! | See you next week! | ||
Denthor | Denthor | ||
+ | |||
+ | ==== Code Source ==== | ||
+ | |||
+ | === PASCAL === | ||
+ | |||
+ | <code pascal> | ||
+ | (*****************************************************************************) | ||
+ | (* *) | ||
+ | (* TUTPROG2.PAS - VGA Trainer Program 2 (in Pascal) | ||
+ | (* *) | ||
+ | (* "The VGA Trainer Program" | ||
+ | (* was limited to Pascal only in its first run. All I have done is taken *) | ||
+ | (* his original release, translated it to C++, and touched up a few things. | ||
+ | (* I take absolutely no credit for the concepts presented in this code, and *) | ||
+ | (* am NOT the person to ask for help if you are having trouble. | ||
+ | (* *) | ||
+ | (* Program Notes : This program presents many new concepts, including: | ||
+ | (* line drawing, pallette manipulation, | ||
+ | (* the computer into graphics mode, testing out two differ- | ||
+ | (* ent methods of putting pixels to the screen, and finally | ||
+ | (* | ||
+ | (* *) | ||
+ | (* Author | ||
+ | (* *) | ||
+ | (*****************************************************************************) | ||
+ | |||
+ | {$X+} | ||
+ | |||
+ | Uses Crt; | ||
+ | |||
+ | CONST VGA=$a000; | ||
+ | |||
+ | Var Pall,Pall2 : Array[0..255, | ||
+ | { This declares the PALL variable. 0 to 255 signify the colors of the | ||
+ | | ||
+ | going to use this as a sort of " | ||
+ | as much as I want, then suddenly bang it to screen. Pall2 is used | ||
+ | to " | ||
+ | the end of the program. } | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetMCGA; | ||
+ | BEGIN | ||
+ | asm | ||
+ | | ||
+ | | ||
+ | end; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetText; | ||
+ | BEGIN | ||
+ | asm | ||
+ | | ||
+ | | ||
+ | end; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | procedure WaitRetrace; | ||
+ | { This waits until you are in a Verticle Retrace ... this means that all | ||
+ | screen manipulation you do only appears on screen in the next verticle | ||
+ | retrace ... this removes most of the " | ||
+ | when changing the pallette. It unfortunately slows down your program | ||
+ | by " | ||
+ | that the program will run at almost the same speed on different | ||
+ | speeds of computers which have similar monitors. In our SilkyDemo, | ||
+ | we used a WaitRetrace, | ||
+ | fast) speed when Turbo is on or off. } | ||
+ | |||
+ | label | ||
+ | l1, l2; | ||
+ | asm | ||
+ | mov dx,3DAh | ||
+ | l1: | ||
+ | in al,dx | ||
+ | and al,08h | ||
+ | jnz l1 | ||
+ | l2: | ||
+ | in al,dx | ||
+ | and al,08h | ||
+ | jz l2 | ||
+ | end; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure GetPal(ColorNo : Byte; Var R,G,B : Byte); | ||
+ | { This reads the values of the Red, Green and Blue values of a certain | ||
+ | color and returns them to you. } | ||
+ | Begin | ||
+ | | ||
+ | R := Port[$3c9]; | ||
+ | G := Port[$3c9]; | ||
+ | B := Port[$3c9]; | ||
+ | End; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Pal(ColorNo : Byte; R,G,B : Byte); | ||
+ | { This sets the Red, Green and Blue values of a certain color } | ||
+ | Begin | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | End; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Putpixel (X,Y : Integer; Col : Byte); | ||
+ | { This puts a pixel on the screen by writing directly to memory. } | ||
+ | BEGIN | ||
+ | Mem [VGA: | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure line(a, | ||
+ | { This draws a line from a,b to c,d of color col. } | ||
+ | | ||
+ | BEGIN | ||
+ | if a>0 then sgn:=+1; | ||
+ | if a<0 then sgn:=-1; | ||
+ | if a=0 then sgn:=0; | ||
+ | END; | ||
+ | var u, | ||
+ | i:integer; | ||
+ | BEGIN | ||
+ | u:= c - a; | ||
+ | v:= d - b; | ||
+ | d1x:= SGN(u); | ||
+ | d1y:= SGN(v); | ||
+ | d2x:= SGN(u); | ||
+ | d2y:= 0; | ||
+ | m:= ABS(u); | ||
+ | n := ABS(v); | ||
+ | IF NOT (M>N) then | ||
+ | BEGIN | ||
+ | d2x := 0 ; | ||
+ | d2y := SGN(v); | ||
+ | m := ABS(v); | ||
+ | n := ABS(u); | ||
+ | END; | ||
+ | s := INT(m / 2); | ||
+ | FOR i := 0 TO round(m) DO | ||
+ | BEGIN | ||
+ | putpixel(a, | ||
+ | s := s + n; | ||
+ | IF not (s<m) THEN | ||
+ | BEGIN | ||
+ | s := s - m; | ||
+ | a:= a +round(d1x); | ||
+ | b := b + round(d1y); | ||
+ | END | ||
+ | ELSE | ||
+ | BEGIN | ||
+ | a := a + round(d2x); | ||
+ | b := b + round(d2y); | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure PalPlay; | ||
+ | { This procedure mucks about with our " | ||
+ | to screen. } | ||
+ | Var Tmp : Array[1..3] of Byte; | ||
+ | { This is used as a " | ||
+ | loop1 : Integer; | ||
+ | BEGIN | ||
+ | | ||
+ | { This copies color 200 from our virtual pallette to the Tmp variable } | ||
+ | | ||
+ | { This moves the entire virtual pallette up one color } | ||
+ | | ||
+ | { This copies the Tmp variable to the bottom of the virtual pallette } | ||
+ | | ||
+ | For loop1:=1 to 255 do | ||
+ | pal (loop1, | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetUpScreen; | ||
+ | { This gets our screen ready but setting up the pallette and drawing | ||
+ | the lines. } | ||
+ | Var j,Loop : Integer; | ||
+ | BEGIN | ||
+ | | ||
+ | { Clear the entire PALL variable to zero. } | ||
+ | For Loop := 0 to 31 do BEGIN | ||
+ | Pall[Loop, | ||
+ | j := 63; | ||
+ | For Loop := 32 to 63 do BEGIN | ||
+ | Pall[Loop, | ||
+ | For Loop := 64 to 127 do BEGIN | ||
+ | Pall[Loop, | ||
+ | For Loop := 128 to 196 do BEGIN | ||
+ | Pall[Loop, | ||
+ | |||
+ | END; | ||
+ | { This sets colors 0 to 200 in the PALL variable to values between | ||
+ | 0 to 63. the MOD function gives you the remainder of a division, | ||
+ | ie. 105 mod 10 = 5 } | ||
+ | |||
+ | For Loop := 1 to 320 do BEGIN | ||
+ | Line(320-Loop, | ||
+ | { These two lines start drawing lines from the left and the right | ||
+ | hand sides of the screen, using colors 1 to 199. Look at these | ||
+ | two lines and understand them. } | ||
+ | PalPlay; | ||
+ | { This calls the PalPlay procedure } | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure GrabPallette; | ||
+ | VAR loop1: | ||
+ | BEGIN | ||
+ | For loop1:=0 to 255 do | ||
+ | Getpal (loop1, | ||
+ | END; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Blackout; | ||
+ | { This procedure blackens the screen by setting the pallette values of | ||
+ | all the colors to zero. } | ||
+ | VAR loop1: | ||
+ | BEGIN | ||
+ | WaitRetrace; | ||
+ | For loop1:=0 to 255 do | ||
+ | Pal (loop1, | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure HiddenScreenSetup; | ||
+ | { This procedure sets up the screen while it is blacked out, so that the | ||
+ | user can't see what is happening. } | ||
+ | VAR loop1, | ||
+ | BEGIN | ||
+ | For loop1:=0 to 319 do | ||
+ | For loop2:=0 to 199 do | ||
+ | PutPixel (loop1, | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Fadeup; | ||
+ | { This procedure slowly fades up the new screen } | ||
+ | VAR loop1, | ||
+ | Tmp : Array [1..3] of byte; | ||
+ | { This is temporary storage for the values of a color } | ||
+ | BEGIN | ||
+ | For loop1:=1 to 64 do BEGIN | ||
+ | { A color value for Red, green or blue is 0 to 63, so this loop only | ||
+ | need be executed a maximum of 64 times } | ||
+ | WaitRetrace; | ||
+ | For loop2:=0 to 255 do BEGIN | ||
+ | Getpal (loop2, | ||
+ | If Tmp[1]< | ||
+ | If Tmp[2]< | ||
+ | If Tmp[3]< | ||
+ | { If the Red, Green or Blue values of color loop2 are less then they | ||
+ | should be, increase them by one. } | ||
+ | Pal (loop2, | ||
+ | { Set the new, altered pallette color. } | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure FadeDown; | ||
+ | { This procedure fades the screen out to black. } | ||
+ | VAR loop1, | ||
+ | Tmp : Array [1..3] of byte; | ||
+ | { This is temporary storage for the values of a color } | ||
+ | BEGIN | ||
+ | For loop1:=1 to 64 do BEGIN | ||
+ | WaitRetrace; | ||
+ | For loop2:=0 to 255 do BEGIN | ||
+ | Getpal (loop2, | ||
+ | If Tmp[1]>0 then dec (Tmp[1]); | ||
+ | If Tmp[2]>0 then dec (Tmp[2]); | ||
+ | If Tmp[3]>0 then dec (Tmp[3]); | ||
+ | { If the Red, Green or Blue values of color loop2 are not yet zero, | ||
+ | then, decrease them by one. } | ||
+ | Pal (loop2, | ||
+ | { Set the new, altered pallette color. } | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure RestorePallette; | ||
+ | { This procedure restores the origional pallette } | ||
+ | VAR loop1: | ||
+ | BEGIN | ||
+ | WaitRetrace; | ||
+ | For loop1:=0 to 255 do | ||
+ | pal (loop1, | ||
+ | END; | ||
+ | |||
+ | |||
+ | BEGIN | ||
+ | ClrScr; | ||
+ | Writeln ('This program will draw lines of different colors across the'); | ||
+ | Writeln (' | ||
+ | Writeln ('The nice thing about using the pallette is that one pallette' | ||
+ | Writeln (' | ||
+ | Writeln ('you having to redraw it. Because I am using a WaitRetrace' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln; | ||
+ | Writeln ('The second part of the demo blacks out the screen using the'); | ||
+ | Writeln (' | ||
+ | Writeln ('it out again. I haven'' | ||
+ | Writeln ('so you will have to put '' | ||
+ | Writeln (' | ||
+ | Writeln; Writeln; | ||
+ | Writeln ('Hit any key to continue ...'); | ||
+ | Readkey; | ||
+ | SetMCGA; | ||
+ | GrabPallette; | ||
+ | SetUpScreen; | ||
+ | repeat | ||
+ | | ||
+ | { Call the PalPlay procedure repeatedly until a key is pressed. } | ||
+ | Until Keypressed; | ||
+ | Readkey; | ||
+ | { Read in the key pressed otherwise it is left in the keyboard buffer } | ||
+ | Blackout; | ||
+ | HiddenScreenSetup; | ||
+ | { FadeUp; | ||
+ | Readkey; | ||
+ | FadeDown; | ||
+ | Readkey;} | ||
+ | RestorePallette; | ||
+ | SetText; | ||
+ | Writeln ('All done. This concludes the second sample program in the ASPHYXIA' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('I hope to hear from you soon!' | ||
+ | Writeln; Writeln; | ||
+ | Write | ||
+ | Readkey; | ||
+ | END. | ||
+ | </ | ||
+ | |||
+ | === C === | ||
+ | |||
+ | <code c> | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // TUTPROG2.CPP - VGA Trainer Program 2 (in Turbo C++ 3.0) // | ||
+ | // // | ||
+ | // "The VGA Trainer Program" | ||
+ | // was limited to Pascal only in its first run. All I have done is taken // | ||
+ | // his original release, translated it to C++ and touched up a few things. // | ||
+ | // I take absolutely no credit for the concepts presented in this code and // | ||
+ | // am NOT the person to ask for help if you are having trouble. | ||
+ | // // | ||
+ | // Program Notes : This program presents many new concepts, including: | ||
+ | // line drawing, pallette manipulation, | ||
+ | // // | ||
+ | // If you are compiling this code command line, be sure to // | ||
+ | // use the " | ||
+ | // | ||
+ | // lock up your system. | ||
+ | // // | ||
+ | // Author | ||
+ | // Translator | ||
+ | // // | ||
+ | // Last Modified : November 29, 1994 // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | |||
+ | // // | ||
+ | // INCLUDE FILES // | ||
+ | // // | ||
+ | |||
+ | #include < | ||
+ | // getch(), clrscr() | ||
+ | #include < | ||
+ | // MK_FP, Geninterrupt() | ||
+ | #include < | ||
+ | // floor(), ceil() | ||
+ | #include < | ||
+ | // memset(), movmem() | ||
+ | #include < | ||
+ | // cout | ||
+ | #include < | ||
+ | // abs(), rand() | ||
+ | |||
+ | |||
+ | // // | ||
+ | // FUNCTION PROTOTYPES // | ||
+ | // // | ||
+ | |||
+ | // MODE SETTING FUNCTIONS | ||
+ | void SetMCGA(); | ||
+ | void SetText(); | ||
+ | |||
+ | // PALLETTE FUNCTIONS | ||
+ | void GrabPallette(); | ||
+ | void GetPal (unsigned char ColorNo, | ||
+ | | ||
+ | void Pal (unsigned char ColorNo, | ||
+ | | ||
+ | void PalPlay | ||
+ | void Fadeup | ||
+ | void FadeDown (); | ||
+ | void Blackout (); | ||
+ | void RestorePallette(); | ||
+ | |||
+ | // SMALL UTILITY FUNCTIONS | ||
+ | int sgn (long a); | ||
+ | int round(long a); | ||
+ | |||
+ | // DRAWING FUNCTIONS | ||
+ | void Putpixel (int x, int y, unsigned char Col); | ||
+ | void Line(int a, int b, int c, int d, int col); | ||
+ | void WaitRetrace(); | ||
+ | |||
+ | // MID-LEVEL (COMBINATION) FUNCTIONS | ||
+ | void SetUpScreen(); | ||
+ | void HiddenScreenSetup(); | ||
+ | |||
+ | |||
+ | // // | ||
+ | // GLOBAL VARIABLE DECLARATIONS // | ||
+ | // // | ||
+ | |||
+ | // declare a pointer to the offset of VGA memory | ||
+ | unsigned char *vga = (unsigned char *) MK_FP(0xA000, | ||
+ | |||
+ | // This declares the PALL variable. 0 to 255 signifies the colors of the | ||
+ | // pallette, 1 to 3 signifies the Red, Green and Blue values. I am | ||
+ | // going to use this as a sort of " | ||
+ | // as much as I want, then suddenly bang it to screen. Pall2 is used | ||
+ | // to " | ||
+ | // the end of the program. */ | ||
+ | unsigned char Pall[256][3], | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // MAIN FUNCTION | ||
+ | // // | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void main() { | ||
+ | |||
+ | clrscr(); | ||
+ | cout << "This program will draw lines of different colors across the\n" | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | |||
+ | cout << "The second part of the demo blacks out the screen using the\n" | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | cout << "Hit any key to continue ..."; | ||
+ | getch(); | ||
+ | |||
+ | SetMCGA(); | ||
+ | GrabPallette(); | ||
+ | SetUpScreen(); | ||
+ | |||
+ | while (!kbhit()) PalPlay(); | ||
+ | getch(); | ||
+ | |||
+ | Blackout(); | ||
+ | HiddenScreenSetup(); | ||
+ | Fadeup(); | ||
+ | getch(); | ||
+ | FadeDown(); | ||
+ | getch(); | ||
+ | |||
+ | RestorePallette(); | ||
+ | SetText(); | ||
+ | cout << "All done. This concludes the second sample program in the ASPHYXIA\n" | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | << | ||
+ | |||
+ | cout << "Hit any key to exit ..."; | ||
+ | getch(); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetMCGA() - This function gets you into 320x200x256 mode. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetMCGA() { | ||
+ | _AX = 0x0013; | ||
+ | geninterrupt (0x10); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetText() - This function gets you into text mode. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetText() { | ||
+ | _AX = 0x0003; | ||
+ | geninterrupt (0x10); | ||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // GrabPallette() - This function retrieves the current pallette. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void GrabPallette() { | ||
+ | |||
+ | for(int loop1=0; | ||
+ | GetPal(loop1, | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // GetPal() - This reads the values of the Red, Green, and Blue values of // | ||
+ | // a certain color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void GetPal(unsigned char ColorNo, unsigned char &R, | ||
+ | unsigned char & | ||
+ | |||
+ | outp (0x03C7, | ||
+ | R = inp (0x03C9); | ||
+ | G = inp (0x03C9); | ||
+ | B = inp (0x03C9); | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Pal() - This sets the Red, Green, and Blue values of a certain color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal(unsigned char ColorNo, unsigned char R, | ||
+ | unsigned char G, | ||
+ | |||
+ | outp (0x03C8, | ||
+ | outp (0x03C9,R); | ||
+ | outp (0x03C9,G); | ||
+ | outp (0x03C9,B); | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalPlay() - This function mucks about with our " | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void PalPlay() { | ||
+ | |||
+ | unsigned char Tmp[3]; | ||
+ | |||
+ | // This copies color 200 from our virtual pallette to the Tmp variable. | ||
+ | _fmemmove(Tmp, | ||
+ | |||
+ | // This moves the entire virtual pallette up one color. | ||
+ | _fmemmove(Pall[2], | ||
+ | |||
+ | // This copies the Tmp variable to the bottom of the virtual pallette. | ||
+ | // Don't change 0: leave this always black to not change overscan color. | ||
+ | _fmemmove(Pall[1], | ||
+ | |||
+ | WaitRetrace(); | ||
+ | for (int loop1=0; | ||
+ | | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Fadeup() - This function slowly fades up the new screen | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Fadeup() { | ||
+ | |||
+ | //This is temporary storage for the values of a color | ||
+ | unsigned char Tmp[3]; | ||
+ | |||
+ | // A color value for Red, green or blue is 0 to 63, so this loop only | ||
+ | // need be executed a maximum of 64 times. | ||
+ | for(int loop1=0; | ||
+ | |||
+ | WaitRetrace(); | ||
+ | |||
+ | for(int loop2=0; loop2< | ||
+ | GetPal(loop2, | ||
+ | |||
+ | // If the Red, Green or Blue values of color loop2 are less then they | ||
+ | // should be, increase them by one. | ||
+ | if ((Tmp[0] < Pall2[loop2][0]) && (Tmp[0] < 63)) Tmp[0]++; | ||
+ | if ((Tmp[1] < Pall2[loop2][1]) && (Tmp[1] < 63)) Tmp[1]++; | ||
+ | if ((Tmp[2] < Pall2[loop2][2]) && (Tmp[2] < 63)) Tmp[2]++; | ||
+ | |||
+ | // Set the new, altered pallette color. | ||
+ | Pal (loop2, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // FadeDown() - This function fades the screen out to black. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void FadeDown() { | ||
+ | |||
+ | // This is temporary storage for the values of a color | ||
+ | unsigned char Tmp[3]; | ||
+ | |||
+ | for(int loop1=0; loop1< | ||
+ | |||
+ | WaitRetrace(); | ||
+ | |||
+ | for(int loop2=0; loop2< | ||
+ | GetPal(loop2, | ||
+ | |||
+ | // If the Red, Green or Blue values of color loop2 are not yet zero, | ||
+ | // then, decrease them by one. | ||
+ | if (Tmp[0] > 0) Tmp[0]--; | ||
+ | if (Tmp[1] > 0) Tmp[1]--; | ||
+ | if (Tmp[2] > 0) Tmp[2]--; | ||
+ | |||
+ | // Set the new, altered pallette color. | ||
+ | Pal(loop2, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Blackout() - This function just clears the screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Blackout() { | ||
+ | |||
+ | WaitRetrace(); | ||
+ | for (int loop1=0; | ||
+ | Pal (loop1, | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // RestorePallette() - This function restores the origional pallette. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void RestorePallette() { | ||
+ | |||
+ | WaitRetrace(); | ||
+ | for(int loop1=0; loop1< | ||
+ | Pal(loop1, | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // sgn() - This function is used by Line() to determine the sign of a long // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | int sgn (long a) { | ||
+ | |||
+ | if (a > 0) return +1; | ||
+ | else if (a < 0) return -1; | ||
+ | else return 0; | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // round() - This function is used by Line() to round a long to the // | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | int round (long a) { | ||
+ | if ( (a - (int)a) < 0.5) return floor(a); | ||
+ | else return ceil(a); | ||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Putpixel() - This puts a pixel on the screen by writing directly to // | ||
+ | // memory. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Putpixel (int x, int y, unsigned char Col) { | ||
+ | |||
+ | memset(vga+(x+(y*320)), | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Line() - This draws a line from a,b to c,d of color col. // | ||
+ | // This function will be explained in more detail in tut3new.zip | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Line(int a, int b, int c, int d, int col) { | ||
+ | |||
+ | long u, | ||
+ | int i; | ||
+ | |||
+ | u = c-a; // x2-x1 | ||
+ | v = d-b; // y2-y1 | ||
+ | d1x = sgn(u); | ||
+ | d1y = sgn(v); | ||
+ | d2x = sgn(u); | ||
+ | d2y = 0; | ||
+ | m = abs(u); | ||
+ | n = abs(v); | ||
+ | |||
+ | if (m<=n) { // if the x distance is greater than the y distance | ||
+ | d2x = 0; | ||
+ | d2y = sgn(v); // d2y is the sign of v (x2-x1) (VALUE -1,0,1) | ||
+ | m = abs(v); // m is the distance between y1 and y2 | ||
+ | n = abs(u); // n is the distance between x1 and x2 | ||
+ | } | ||
+ | |||
+ | s = (int)(m / 2); // s is the m distance (either x or y) divided by 2 | ||
+ | |||
+ | for (i=0; | ||
+ | // is = to m (y or x distance) | ||
+ | Putpixel(a, | ||
+ | s += n; // add n (dis of x or y) to s (dis of x of y) | ||
+ | if (s >= m) { // if s is >= m (distance between y1 and y2) | ||
+ | s -= m; | ||
+ | a += d1x; | ||
+ | b += d1y; | ||
+ | } | ||
+ | else { | ||
+ | a += d2x; | ||
+ | b += d2y; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // WaitRetrace() - This waits until you are in a Verticle Retrace ... // | ||
+ | // this means that all screen manipulation you do only // | ||
+ | // | ||
+ | // | ||
+ | // when changing the pallette. It unfortunately slows down // | ||
+ | // your program by " | ||
+ | // | ||
+ | // at almost the same speed on different speeds of // | ||
+ | // | ||
+ | // | ||
+ | // runs at the same (fairly fast) speed when Turbo is on // | ||
+ | // or off. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void WaitRetrace() { | ||
+ | |||
+ | _DX = 0x03DA; | ||
+ | |||
+ | l1: asm { | ||
+ | in al,dx; | ||
+ | and al,0x08; | ||
+ | jnz l1; | ||
+ | } | ||
+ | |||
+ | l2: asm { | ||
+ | in al,dx; | ||
+ | and al,0x08; | ||
+ | jz l2; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetUpScreen() - This gets our screen ready by setting up the pallette | ||
+ | // and drawing the lines. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetUpScreen() { | ||
+ | |||
+ | // Clear the entire PALL variable to zero. | ||
+ | _fmemset(Pall, | ||
+ | |||
+ | // This sets colors 0 to 200 in the PALL variable to values between | ||
+ | // 0 to 63. the modulus function gives you the remainder of a division, | ||
+ | // ie. 105 % 10 = 5. | ||
+ | for (int loop = 0; loop < 201;loop++) | ||
+ | Pall[loop][0] = loop % 64; | ||
+ | |||
+ | for (loop = 0; loop < 321; loop++) { | ||
+ | |||
+ | // These two lines start drawing lines from the left and the right | ||
+ | // hand sides of the screen, using colors 1 to 199. Look at these | ||
+ | // two lines and understand them. | ||
+ | Line(319, | ||
+ | Line(0, | ||
+ | |||
+ | // This calls the PalPlay function. | ||
+ | PalPlay(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // HiddenScreenSetup() - This function sets up the screen while it is // | ||
+ | // | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void HiddenScreenSetup() { | ||
+ | |||
+ | for (int loop1=0; loop1< | ||
+ | for (int loop2=0; loop2< | ||
+ | Putpixel (loop1, | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <nspages back2root/ |