Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
back2root:archives:denthor:part-08 [2021/09/02 11:34] – frater | back2root:archives:denthor:part-08 [2024/08/27 09:04] (Version actuelle) – [Drawing a 3D point to screen] frater | ||
---|---|---|---|
Ligne 24: | Ligne 24: | ||
==== Optimisation ==== | ==== Optimisation ==== | ||
- | Before I begin with the note on 3-D, I would like to stress that many of these routines, and probably most of your own, could be sped up quite a bit with a little optimisation. One must realise, however, that you must | + | Before I begin with the note on 3-D, I would like to stress that many of these routines, and probably most of your own, could be sped up quite a bit with a little optimisation. |
- | take a look at WHAT to optimise ... converting a routine that is only called once at startup into a tightly coded assembler routine may show off your merits as a coder, but does absolutely nothing to speed up your program. Something that is called often per frame is something that needs to be as fast as possible. For some, a much used procedure is the PutPixel procedure. Here is the putpixel procedure I gave you last week: | + | |
+ | One must realise, however, that you must take a look at WHAT to optimise ... converting a routine that is only called once at startup into a tightly coded assembler routine may show off your merits as a coder, but does absolutely nothing to speed up your program. | ||
+ | |||
+ | Something that is called often per frame is something that needs to be as fast as possible. For some, a much used procedure is the PutPixel procedure. Here is the putpixel procedure I gave you last week: | ||
<code pascal> | <code pascal> | ||
Ligne 62: | Ligne 65: | ||
Total = 153 clock ticks | Total = 153 clock ticks | ||
| | ||
- | <WRAP center round important | + | <WRAP center round important> |
Don't take my clock ticks as gospel, I probably got one or two wrong. | Don't take my clock ticks as gospel, I probably got one or two wrong. | ||
</ | </ | ||
- | Right, now for some optimising. Firstly, if you have 286 instructions turned on, you may replace the 6 shl,1 with shl,6. Secondly, the Pascal compiler automatically pushes and pops ES, so those two lines may be removed. DS:[SI] is not altered in this procedure, so we may remove those too. Also, instead of moving COL into ah, we move it into AL and call stosb (es: | + | Right, now for some optimising. Firstly, if you have 286 instructions turned on, you may replace the 6 shl,1 with shl, |
+ | |||
+ | Secondly, the Pascal compiler automatically pushes and pops ES, so those two lines may be removed. DS:[SI] is not altered in this procedure, so we may remove those too. Also, instead of moving COL into ah, we move it into AL and call stosb (es: | ||
<code pascal> | <code pascal> | ||
Ligne 92: | Ligne 97: | ||
Total = 95 clock ticks | Total = 95 clock ticks | ||
- | Now, let us move the value of BX directly into DI, thereby removing a costly push and pop. The MOV and the XOR of DX can be replaced by it's equivalent, SHL DX,8 | + | Now, let us move the value of BX directly into DI, thereby removing a costly push and pop. The MOV and the XOR of DX can be replaced by it's equivalent, |
<code pascal> | <code pascal> | ||
Ligne 113: | Ligne 118: | ||
Total = 71 clock ticks | Total = 71 clock ticks | ||
- | As you can see, we have brought the clock ticks down from 153 ticks to 71 ticks ... quite an improvement. (The current ASPHYXIA putpixel takes 48 clock ticks) . As you can see, by going through your routines a few times, you can spot and remove unnecessary instructions, | + | As you can see, we have brought the clock ticks down from 153 ticks to 71 ticks ... quite an improvement. (The current ASPHYXIA putpixel takes 48 clock ticks). |
+ | |||
+ | As you can see, by going through your routines a few times, you can spot and remove unnecessary instructions, | ||
==== Defining a 3-D object ==== | ==== Defining a 3-D object ==== | ||
Ligne 139: | Ligne 146: | ||
==== Rotating a point with matrixes ==== | ==== Rotating a point with matrixes ==== | ||
- | <WRAP center round tip 60%> | + | <WRAP center round tip> |
I thought that more then one matix are matrisese (sp), but my spellchecker insists it is matrixes, so I let it have it's way ;-) | I thought that more then one matix are matrisese (sp), but my spellchecker insists it is matrixes, so I let it have it's way ;-) | ||
</ | </ | ||
Ligne 220: | Ligne 227: | ||
</ | </ | ||
- | <WRAP center round info 60%> | + | <WRAP center round info> |
Zoff is how far away the entire object is, Xoff is the objects X value, and Yoff is the objects Y value. In the sample program, Xoff start off at 160 and Yoff starts off at 100, so that the object is in the middle of the screen. | Zoff is how far away the entire object is, Xoff is the objects X value, and Yoff is the objects Y value. In the sample program, Xoff start off at 160 and Yoff starts off at 100, so that the object is in the middle of the screen. | ||
</ | </ | ||
Ligne 267: | Ligne 274: | ||
File = Available in file base | File = Available in file base | ||
Past = Previous Parts available | Past = Previous Parts available | ||
+ | |||
+ | ==== Code Source ==== | ||
+ | |||
+ | === PASCAL === | ||
+ | |||
+ | <code pascal> | ||
+ | (*****************************************************************************) | ||
+ | (* *) | ||
+ | (* TUT8.PAS - VGA Trainer Program 8 (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 the basis of 3D. *) | ||
+ | (* *) | ||
+ | (* Author | ||
+ | (* *) | ||
+ | (*****************************************************************************) | ||
+ | |||
+ | {$X+} | ||
+ | USES Crt; | ||
+ | |||
+ | CONST VGA = $A000; | ||
+ | MaxLines = 12; | ||
+ | Obj : Array [1..MaxLines, | ||
+ | ( | ||
+ | ((-10, | ||
+ | ((-10, | ||
+ | ((-10, | ||
+ | ((-10, | ||
+ | ((-10, | ||
+ | ((10, | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the two ends of a line } | ||
+ | |||
+ | |||
+ | Type Point = Record | ||
+ | | ||
+ | END; | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | VAR Lines : Array [1..MaxLines, | ||
+ | Translated : Array [1..MaxLines, | ||
+ | Xoff, | ||
+ | lookup : Array [0..360, | ||
+ | Virscr : VirtPtr; | ||
+ | Vaddr : word; { The segment of our virtual screen} | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetMCGA; | ||
+ | BEGIN | ||
+ | asm | ||
+ | | ||
+ | | ||
+ | end; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetText; | ||
+ | BEGIN | ||
+ | asm | ||
+ | | ||
+ | | ||
+ | end; | ||
+ | END; | ||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Cls (Where: | ||
+ | { This clears the screen to the specified color } | ||
+ | BEGIN | ||
+ | asm | ||
+ | push es | ||
+ | mov cx, 32000; | ||
+ | mov | ||
+ | xor di,di | ||
+ | mov | ||
+ | mov ah,al | ||
+ | rep stosw | ||
+ | pop es | ||
+ | End; | ||
+ | END; | ||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetUpVirtual; | ||
+ | { This sets up the memory needed for the virtual screen } | ||
+ | BEGIN | ||
+ | GetMem (VirScr, | ||
+ | vaddr := seg (virscr^); | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure ShutDown; | ||
+ | { This frees the memory used by the virtual screen } | ||
+ | BEGIN | ||
+ | FreeMem (VirScr, | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | procedure flip(source, | ||
+ | { This copies the entire screen at " | ||
+ | begin | ||
+ | asm | ||
+ | push ds | ||
+ | mov ax, [Dest] | ||
+ | mov es, ax | ||
+ | mov ax, [Source] | ||
+ | mov ds, ax | ||
+ | xor si, si | ||
+ | xor di, di | ||
+ | mov cx, 32000 | ||
+ | rep movsw | ||
+ | pop ds | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Pal(Col, | ||
+ | { This sets the Red, Green and Blue values of a certain color } | ||
+ | Begin | ||
+ | asm | ||
+ | mov dx,3c8h | ||
+ | mov al,[col] | ||
+ | out dx,al | ||
+ | inc dx | ||
+ | mov al,[r] | ||
+ | out dx,al | ||
+ | mov al,[g] | ||
+ | out dx,al | ||
+ | mov al,[b] | ||
+ | out dx,al | ||
+ | end; | ||
+ | End; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Function rad (theta : real) : real; | ||
+ | { This calculates the degrees of an angle } | ||
+ | BEGIN | ||
+ | rad := theta * pi / 180 | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetUpPoints; | ||
+ | { This sets the basic offsets of the object, creates the lookup table and | ||
+ | moves the object from a constant to a variable } | ||
+ | VAR loop1: | ||
+ | BEGIN | ||
+ | Xoff:=160; | ||
+ | Yoff:=100; | ||
+ | Zoff:=-256; | ||
+ | For loop1:=0 to 360 do BEGIN | ||
+ | lookup [loop1, | ||
+ | lookup [loop1, | ||
+ | END; | ||
+ | For loop1:=1 to MaxLines do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Putpixel (X,Y : Integer; Col : Byte; where: | ||
+ | { This puts a pixel on the screen by writing directly to memory. } | ||
+ | BEGIN | ||
+ | Asm | ||
+ | mov | ||
+ | mov es,ax | ||
+ | mov | ||
+ | mov | ||
+ | mov di,bx | ||
+ | mov bx, dx {; bx = dx} | ||
+ | shl dx, 8 | ||
+ | shl bx, 6 | ||
+ | add dx, bx {; dx = dx + bx (ie y*320)} | ||
+ | add di, dx {; finalise location} | ||
+ | mov al, [Col] | ||
+ | stosb | ||
+ | End; | ||
+ | END; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Line(a, | ||
+ | { This draws a solid line from a,b to c,d in colour col } | ||
+ | function sgn(a: | ||
+ | begin | ||
+ | if a>0 then sgn:=+1; | ||
+ | if a<0 then sgn:=-1; | ||
+ | if a=0 then sgn:=0; | ||
+ | end; | ||
+ | var i, | ||
+ | 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 := m shr 1; | ||
+ | FOR i := 0 TO m DO | ||
+ | BEGIN | ||
+ | putpixel(a, | ||
+ | s := s + n; | ||
+ | IF not (s<m) THEN | ||
+ | BEGIN | ||
+ | s := s - m; | ||
+ | a:= a + d1x; | ||
+ | b := b + d1y; | ||
+ | END | ||
+ | ELSE | ||
+ | BEGIN | ||
+ | a := a + d2x; | ||
+ | b := b + d2y; | ||
+ | END; | ||
+ | end; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure DrawLogo; | ||
+ | { This draws ' | ||
+ | CONST ball : Array [1..5,1..5] of byte = | ||
+ | | ||
+ | (1, | ||
+ | (1, | ||
+ | (1, | ||
+ | (0, | ||
+ | |||
+ | VAR Logo : Array [1..5] of String; | ||
+ | loop1, | ||
+ | BEGIN | ||
+ | pal (13, | ||
+ | pal (1,0,0,40); | ||
+ | pal (2,0,0,45); | ||
+ | pal (3,0,0,50); | ||
+ | pal (4,0,0,60); | ||
+ | Logo[1]: | ||
+ | Logo[2]: | ||
+ | Logo[3]: | ||
+ | Logo[4]: | ||
+ | Logo[5]: | ||
+ | For loop1:=1 to 5 do | ||
+ | For loop2:=1 to 31 do | ||
+ | if logo[loop1][loop2]=' | ||
+ | For loop3:=1 to 5 do | ||
+ | For loop4:=1 to 5 do | ||
+ | putpixel (loop2*10+loop3, | ||
+ | END; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure RotatePoints (X, | ||
+ | { This rotates object lines by X,Y and Z; then places the result in | ||
+ | TRANSLATED } | ||
+ | VAR loop1: | ||
+ | temp:point; | ||
+ | BEGIN | ||
+ | For loop1:=1 to maxlines do BEGIN | ||
+ | temp.x: | ||
+ | temp.y: | ||
+ | temp.z: | ||
+ | |||
+ | translated[loop1, | ||
+ | |||
+ | If y>0 then BEGIN | ||
+ | temp.x: | ||
+ | temp.y: | ||
+ | temp.z: | ||
+ | translated[loop1, | ||
+ | END; | ||
+ | |||
+ | If z>0 then BEGIN | ||
+ | temp.x: | ||
+ | temp.y: | ||
+ | temp.z: | ||
+ | translated[loop1, | ||
+ | END; | ||
+ | |||
+ | temp.x: | ||
+ | temp.y:=cos (rad(X))*lines[loop1, | ||
+ | temp.z:=sin (rad(X))*lines[loop1, | ||
+ | |||
+ | translated[loop1, | ||
+ | |||
+ | If y>0 then BEGIN | ||
+ | temp.x:=cos (rad(Y))*translated[loop1, | ||
+ | temp.y:=sin (rad(Y))*translated[loop1, | ||
+ | temp.z: | ||
+ | translated[loop1, | ||
+ | END; | ||
+ | |||
+ | If z>0 then BEGIN | ||
+ | temp.x:=cos (rad(Z))*translated[loop1, | ||
+ | temp.y: | ||
+ | temp.z: | ||
+ | translated[loop1, | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure DrawPoints; | ||
+ | { This draws the translated object to the virtual screen } | ||
+ | VAR loop1: | ||
+ | nx, | ||
+ | temp: | ||
+ | BEGIN | ||
+ | For loop1:=1 to MaxLines do BEGIN | ||
+ | If (translated[loop1, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx :=round (256*translated[loop1, | ||
+ | ny :=round (256*translated[loop1, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx2:=round (256*translated[loop1, | ||
+ | ny2:=round (256*translated[loop1, | ||
+ | If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and | ||
+ | | ||
+ | line (nx, | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure ClearPoints; | ||
+ | { This clears the translated object from the virtual screen ... believe it | ||
+ | or not, this is faster then a straight "cls (vaddr, | ||
+ | VAR loop1: | ||
+ | nx, | ||
+ | temp: | ||
+ | BEGIN | ||
+ | For loop1:=1 to MaxLines do BEGIN | ||
+ | If (translated[loop1, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx :=round (256*translated[loop1, | ||
+ | ny :=round (256*translated[loop1, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx2:=round (256*translated[loop1, | ||
+ | ny2:=round (256*translated[loop1, | ||
+ | If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and | ||
+ | | ||
+ | line (nx, | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure MoveAround; | ||
+ | { This is the main display procedure. Firstly it brings the object towards | ||
+ | the viewer by increasing the Zoff, then passes control to the user } | ||
+ | VAR deg, | ||
+ | ch:char; | ||
+ | BEGIN | ||
+ | deg:=0; | ||
+ | ch:=#0; | ||
+ | Cls (vaddr,0); | ||
+ | DrawLogo; | ||
+ | For loop1:=-256 to -40 do BEGIN | ||
+ | zoff: | ||
+ | RotatePoints (deg, | ||
+ | DrawPoints; | ||
+ | flip (vaddr, | ||
+ | ClearPoints; | ||
+ | deg: | ||
+ | END; | ||
+ | |||
+ | Repeat | ||
+ | if keypressed then BEGIN | ||
+ | ch:=upcase (Readkey); | ||
+ | Case ch of ' | ||
+ | ' | ||
+ | ',' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | END; | ||
+ | END; | ||
+ | DrawPoints; | ||
+ | flip (vaddr, | ||
+ | ClearPoints; | ||
+ | RotatePoints (deg, | ||
+ | deg: | ||
+ | Until ch=#27; | ||
+ | END; | ||
+ | |||
+ | |||
+ | BEGIN | ||
+ | SetUpVirtual; | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('When it gets close, you get control. " | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('it should be easy enough to put in yourself ... if you have any'); | ||
+ | Writeln (' | ||
+ | Writeln; | ||
+ | Writeln ('Read the main text file for ideas on improving this code ... and'); | ||
+ | Writeln (' | ||
+ | writeln; | ||
+ | writeln; | ||
+ | Write (' | ||
+ | Readkey; | ||
+ | SetMCGA; | ||
+ | SetUpPoints; | ||
+ | MoveAround; | ||
+ | SetText; | ||
+ | ShutDown; | ||
+ | Writeln ('All done. This concludes the eigth sample program in the ASPHYXIA' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('For discussion purposes, I am also the moderator of the Programming' | ||
+ | Writeln (' | ||
+ | Writeln ('The numbers are available in the main text. You may also write to me at:'); | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('I hope to hear from you soon!' | ||
+ | Writeln; Writeln; | ||
+ | Write | ||
+ | Readkey; | ||
+ | END. | ||
+ | </ | ||
+ | |||
+ | === C === | ||
+ | |||
+ | <code c file: | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // TUTPROG8.CPP - VGA Trainer Program 8 (in Turbo C++ 3.0) // | ||
+ | // // | ||
+ | // "The VGA Trainer Program" | ||
+ | // was limited to only Pascal 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 the basics of 3D. Please note // | ||
+ | // that the compiled C++ version of this program runs // | ||
+ | // much faster than the Pascal version. | ||
+ | // a 486DX/33 or higher, you may wish to turn turbo off. // | ||
+ | // // | ||
+ | // If you are compiling this program from within the // | ||
+ | // Turbo C++ environment, | ||
+ | // | ||
+ | // 80 or greater. | ||
+ | // with the code a bit, I suggest raising this to about // | ||
+ | // 100 just to be on the safe side. You don't have to // | ||
+ | // worry about this if you are compiling command line. // | ||
+ | // // | ||
+ | // Just for reference, this is what I use: // | ||
+ | // // | ||
+ | // tcc -mc -a -G -2 -O tut8.cpp | ||
+ | // // | ||
+ | // The way things are set up, there is no need to compile | ||
+ | // or link tut8.cpp and gfx1.cpp seperately. | ||
+ | // // | ||
+ | // The Compact memory model (-mc) seems to provide the // | ||
+ | // best results for this tutorial. | ||
+ | // | ||
+ | // and lots of data. // | ||
+ | // // | ||
+ | // Author | ||
+ | // Translator | ||
+ | // // | ||
+ | // Last Modified : January 14, 1995 // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // // | ||
+ | // INCLUDE FILES // | ||
+ | // // | ||
+ | |||
+ | #include < | ||
+ | // farcalloc() | ||
+ | #include < | ||
+ | // clrscr(), getch(), kbhit() | ||
+ | #include < | ||
+ | // FP_SEG, geninterrupt() | ||
+ | #include < | ||
+ | // cout | ||
+ | #include < | ||
+ | // sin(), cos() | ||
+ | #include < | ||
+ | // exit() | ||
+ | #include " | ||
+ | |||
+ | // // | ||
+ | // TYPEDEFS // | ||
+ | // // | ||
+ | |||
+ | typedef unsigned char byte; | ||
+ | typedef unsigned int word; | ||
+ | |||
+ | // // | ||
+ | // CONSTANTS // | ||
+ | // // | ||
+ | |||
+ | const MAXLINES = 12; // the number of lines in our cube | ||
+ | |||
+ | // The 3-D coordinates of our object ... stored as {X1,Y1,Z1}, | ||
+ | // {X2,Y2,Z2} ... for the two ends of a line | ||
+ | const int Obj[MAXLINES][2][3] = | ||
+ | { {{-10, | ||
+ | {{-10, | ||
+ | {{-10, 10,-10}, { 10, 10,-10}}, // 2 9 | A | | ||
+ | {{ 10, | ||
+ | {{-10,-10, 10}, { 10,-10, 10}}, // 4 .------6---. | ||
+ | {{-10,-10, 10}, {-10, 10, 10}}, // 5 | | ||
+ | {{-10, 10, 10}, { 10, 10, 10}}, // 6 | | ||
+ | {{ 10,-10, 10}, { 10, 10, 10}}, // 7 | | ||
+ | {{-10,-10, 10}, {-10, | ||
+ | {{-10, 10, 10}, {-10, 10,-10}}, // 9 | / | ||
+ | {{ 10, 10, 10}, { 10, 10,-10}}, // A | 8 | B | ||
+ | {{ 10,-10, 10}, { 10, | ||
+ | }; // | ||
+ | |||
+ | // // | ||
+ | // FUNCTION PROTOTYPES // | ||
+ | // // | ||
+ | |||
+ | // MEMORY ALLOCATION FUNCTIONS | ||
+ | void SetUpVirtual (); | ||
+ | void ShutDown | ||
+ | |||
+ | // LOGO-FUNCTION | ||
+ | void DrawLogo | ||
+ | |||
+ | // 3D POINTS FUNCTIONS | ||
+ | void SetUpPoints | ||
+ | void RotatePoints (int X, int Y, int Z); | ||
+ | void DrawPoints | ||
+ | void ClearPoints | ||
+ | |||
+ | // MID-LEVEL FUNCTION | ||
+ | void MoveAround | ||
+ | |||
+ | // // | ||
+ | // STRUCTURES // | ||
+ | // // | ||
+ | |||
+ | // The data on every point we rotate | ||
+ | struct Point { | ||
+ | float x; | ||
+ | float y; | ||
+ | float z; | ||
+ | }; | ||
+ | |||
+ | // // | ||
+ | // GLOBAL VARIABLE DECLARATIONS // | ||
+ | // // | ||
+ | |||
+ | byte far *Virscr=NULL; | ||
+ | word Vaddr; | ||
+ | float Lookup[360][2]; | ||
+ | int Xoff, Yoff, Zoff; // Used for movement of the objects | ||
+ | Point Lines[MAXLINES][2]; | ||
+ | Point Translated[MAXLINES][2]; | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // MAIN FUNCTION | ||
+ | // // | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void main() { | ||
+ | |||
+ | SetUpVirtual(); | ||
+ | clrscr(); | ||
+ | cout | ||
+ | << " | ||
+ | << "year! ;-) ... Anyway, this tutorial is on 3-D, so this is what is\n" | ||
+ | << "going to happen ... a wireframe square will come towards you.\n" | ||
+ | << "When it gets close, you get control. "" | ||
+ | << " | ||
+ | << " | ||
+ | << "it should be easy enough to put in yourself ... if you have any\n" | ||
+ | << " | ||
+ | cout | ||
+ | << "Read the main text file for ideas on improving this code ... and\n" | ||
+ | << " | ||
+ | cout << "Hit any key to contine ...\n"; | ||
+ | getch(); | ||
+ | |||
+ | SetMCGA(); | ||
+ | |||
+ | SetUpPoints(); | ||
+ | MoveAround(); | ||
+ | |||
+ | ShutDown(); | ||
+ | SetText(); | ||
+ | |||
+ | cout | ||
+ | << "All done. This concludes the eigth sample program in the ASPHYXIA\n" | ||
+ | << " | ||
+ | << " | ||
+ | << " | ||
+ | << "For discussion purposes, I am also the moderator of the Programming\n" | ||
+ | << " | ||
+ | << "The numbers are available in the main text. You may also write to me at:\n" | ||
+ | << " | ||
+ | << " | ||
+ | << " | ||
+ | << " | ||
+ | << "I hope to hear from you soon!\n\n\n"; | ||
+ | cout << "Hit any key to exit ...\n"; | ||
+ | getch(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetUpVirtual() - This sets up the memory needed for the virtual screen. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetUpVirtual() { | ||
+ | |||
+ | Virscr = (byte far *) farcalloc(64000, | ||
+ | |||
+ | // always check to see if enough memory was allocated | ||
+ | if (Virscr == NULL) { | ||
+ | SetText(); | ||
+ | cout << " | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | Vaddr = FP_SEG(Virscr); | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // ShutDown() - This frees the memory used by the virtual screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void ShutDown() { | ||
+ | free(Virscr); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // DrawLogo() - This draws ' | ||
+ | // balls. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void DrawLogo() { | ||
+ | |||
+ | const byte ball[5][5] = { 0,1,1,1,0, | ||
+ | 1,4,3,2,1, | ||
+ | 1,3,3,2,1, | ||
+ | 1,2,2,2,1, | ||
+ | 0,1,1,1,0 | ||
+ | }; | ||
+ | |||
+ | const char *Logo[5] = { {"OOO OOO OOO O O O O O OOO OOO"}, | ||
+ | {" | ||
+ | {"OOO O O O O O O O O O O OOO O O"}, | ||
+ | {" | ||
+ | {"OOO O O OOO O O O O O O O O O"} | ||
+ | }; | ||
+ | |||
+ | int loop1, loop2, loop3, loop4; | ||
+ | |||
+ | Pal(13, 0,63, 0); // set the color for the cube lines | ||
+ | Pal( 1, 0, 0,40); // set the colors for the dots | ||
+ | Pal( 2, 0, 0,45); | ||
+ | Pal( 3, 0, 0,50); | ||
+ | Pal( 4, 0, 0,60); | ||
+ | |||
+ | for (loop1=0; loop1<5; loop1++) | ||
+ | for (loop2=0; loop2< | ||
+ | if (Logo[loop1][loop2] == ' | ||
+ | for (loop3=0; loop3<5; loop3++) | ||
+ | for (loop4=0; loop4<5; loop4++) | ||
+ | Putpixel ((loop2+1)*10+loop3, | ||
+ | ball[loop3][loop4], | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetUpPoints() - This sets the basic offsets of the object, creates the // | ||
+ | // | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetUpPoints() { | ||
+ | |||
+ | int loop1; | ||
+ | |||
+ | // set the starting offsets of the cube | ||
+ | Xoff = 160; | ||
+ | Yoff = 100; | ||
+ | Zoff = -256; | ||
+ | |||
+ | // generate the sin() and cos() tables | ||
+ | for (loop1=0; loop1< | ||
+ | Lookup [loop1][0] = sin(rad(loop1)); | ||
+ | Lookup [loop1][1] = cos(rad(loop1)); | ||
+ | } | ||
+ | |||
+ | // move the Obj constant array into the Lines array | ||
+ | for (loop1=0; loop1< | ||
+ | Lines[loop1][0].x = Obj[loop1][0][0]; | ||
+ | Lines[loop1][0].y = Obj[loop1][0][1]; | ||
+ | Lines[loop1][0].z = Obj[loop1][0][2]; | ||
+ | Lines[loop1][1].x = Obj[loop1][1][0]; | ||
+ | Lines[loop1][1].y = Obj[loop1][1][1]; | ||
+ | Lines[loop1][1].z = Obj[loop1][1][2]; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // RotatePoints() - This rotates object lines by X, Y, and Z. Then it // | ||
+ | // places the result in Translated. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void RotatePoints (int X,int Y,int Z) { | ||
+ | |||
+ | int loop1; | ||
+ | Point temp; | ||
+ | |||
+ | // for each line... | ||
+ | for (loop1=0; loop1< | ||
+ | |||
+ | // start point of line | ||
+ | |||
+ | temp.x = Lines[loop1][0].x; | ||
+ | temp.y = Lookup[X][1]*Lines[loop1][0].y - Lookup[X][0]*Lines[loop1][0].z; | ||
+ | temp.z = Lookup[X][0]*Lines[loop1][0].y + Lookup[X][1]*Lines[loop1][0].z; | ||
+ | Translated[loop1][0] = temp; | ||
+ | |||
+ | if (Y > 0) { | ||
+ | temp.x = Lookup[Y][1]*Translated[loop1][0].x - Lookup[Y][0]*Translated[loop1][0].y; | ||
+ | temp.y = Lookup[Y][0]*Translated[loop1][0].x + Lookup[Y][1]*Translated[loop1][0].y; | ||
+ | temp.z = Translated[loop1][0].z; | ||
+ | Translated[loop1][0] =temp; | ||
+ | } | ||
+ | |||
+ | if (Z > 0) { | ||
+ | temp.x = Lookup[Z][1]*Translated[loop1][0].x + Lookup[Z][0]*Translated[loop1][0].z; | ||
+ | temp.y = Translated[loop1][0].y; | ||
+ | temp.z = (-Lookup[Z][0])*Translated[loop1][0].x + Lookup[Z][1]*Translated[loop1][0].z; | ||
+ | Translated[loop1][0] = temp; | ||
+ | } | ||
+ | |||
+ | // end point of line | ||
+ | |||
+ | temp.x = Lines[loop1][1].x; | ||
+ | temp.y = cos(rad(X))*Lines[loop1][1].y - sin(rad(X))*Lines[loop1][1].z; | ||
+ | temp.z = sin(rad(X))*Lines[loop1][1].y + cos(rad(X))*Lines[loop1][1].z; | ||
+ | Translated[loop1][1] = temp; | ||
+ | |||
+ | if (Y > 0) { | ||
+ | temp.x = cos(rad(X))*Translated[loop1][1].x - sin(rad(Y))*Translated[loop1][1].y; | ||
+ | temp.y = sin(rad(Y))*Translated[loop1][1].x + cos(rad(Y))*Translated[loop1][1].y; | ||
+ | temp.z = Translated[loop1][1].z; | ||
+ | Translated[loop1][1] = temp; | ||
+ | } | ||
+ | |||
+ | if (Z > 0) { | ||
+ | temp.x = cos(rad(Z))*Translated[loop1][1].x + sin(rad(Z))*Translated[loop1][1].z; | ||
+ | temp.y = Translated[loop1][1].y; | ||
+ | temp.z = (-sin(rad(Z)))*Translated[loop1][1].x + cos(rad(Z))*Translated[loop1][1].z; | ||
+ | Translated[loop1][1] = temp; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // DrawPoints() - This draws the translated object to the virtual screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void DrawPoints() { | ||
+ | |||
+ | int loop1, nx, ny, nx2, ny2, temp; | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | if ((Translated[loop1][0].z+Zoff< | ||
+ | |||
+ | // start point of line | ||
+ | temp = Translated[loop1][0].z + Zoff; | ||
+ | nx = ((256*Translated[loop1][0].x) / temp) + Xoff; | ||
+ | ny = ((256*Translated[loop1][0].y) / temp) + Yoff; | ||
+ | |||
+ | // end point of line | ||
+ | temp = Translated[loop1][1].z + Zoff; | ||
+ | nx2 = ((256*Translated[loop1][1].x) / temp) + Xoff; | ||
+ | ny2 = ((256*Translated[loop1][1].y) / temp) + Yoff; | ||
+ | |||
+ | // check to make sure the line is within bounds | ||
+ | if ((nx >-1) && (nx <320) && (ny >25) && (ny <200) && | ||
+ | (nx2>-1) && (nx2< | ||
+ | Line(nx, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // ClearPoints() - This clears the translated object from the virtual | ||
+ | // | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void ClearPoints() { | ||
+ | |||
+ | int loop1, nx, ny, nx2, ny2, temp; | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | if ((Translated[loop1][0].z+Zoff< | ||
+ | |||
+ | // start point of line | ||
+ | temp = Translated[loop1][0].z + Zoff; | ||
+ | nx = ((256*Translated[loop1][0].x) / temp) + Xoff; | ||
+ | ny = ((256*Translated[loop1][0].y) / temp) + Yoff; | ||
+ | |||
+ | // end point of line | ||
+ | temp = Translated[loop1][1].z + Zoff; | ||
+ | nx2 = ((256*Translated[loop1][1].x) / temp) + Xoff; | ||
+ | ny2 = ((256*Translated[loop1][1].y) / temp) + Yoff; | ||
+ | |||
+ | // check to make sure the line is within bounds | ||
+ | if ((nx >-1) && (nx <320) && (ny >25) && (ny <200) && | ||
+ | (nx2>-1) && (nx2< | ||
+ | Line(nx, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // MoveAround() - This is the main display function. | ||
+ | // object towards the viewer by increasing the Zoff, then // | ||
+ | // it passes control to the user. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void MoveAround() { | ||
+ | |||
+ | // For some reason, the values we defined Xoff, Yoff, and Zoff to be in | ||
+ | // the function SetUpPoints() won't hold until this point. | ||
+ | // the reason, please send it to r3cgm@dax.cc.uakron.edu | ||
+ | Xoff = 160; // redefined | ||
+ | Yoff = 100; // redefined | ||
+ | Zoff = -256; // redefined | ||
+ | |||
+ | int deg=0, loop1; | ||
+ | byte ch=1; // assign a dummy value to ch | ||
+ | |||
+ | Cls(0, | ||
+ | |||
+ | DrawLogo(); | ||
+ | |||
+ | for (loop1=(-256); | ||
+ | Zoff = loop1 * 2; | ||
+ | RotatePoints(deg, | ||
+ | DrawPoints(); | ||
+ | Flip(Vaddr, | ||
+ | ClearPoints(); | ||
+ | deg = (deg + 5) % 360; | ||
+ | } | ||
+ | |||
+ | do { | ||
+ | |||
+ | if (kbhit()) { | ||
+ | ch = getch(); | ||
+ | switch (ch) { | ||
+ | // We are not going to use toupper() because if we did, we'd have | ||
+ | // to include the whole ctype.h file. This might take a little more | ||
+ | // time, but the program will be smaller. | ||
+ | // files, and its getting a bit rediculous. | ||
+ | case ' | ||
+ | case ' | ||
+ | case ',': | ||
+ | case ' | ||
+ | case ' | ||
+ | case ' | ||
+ | } | ||
+ | } | ||
+ | DrawPoints(); | ||
+ | Flip(Vaddr, | ||
+ | ClearPoints(); | ||
+ | RotatePoints(deg, | ||
+ | deg = (deg + 5) % 360; | ||
+ | |||
+ | // if the key pressed above was 0 (i.e. a control character) then | ||
+ | // read the character code | ||
+ | if (ch == 0) ch = getch(); | ||
+ | |||
+ | } while (ch != 27); // if the escape code was 27 (escape key) then exit | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code c file: | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // GFX1.CPP - VGA Trainer Program secondary module containing graphics | ||
+ | // functions. | ||
+ | // programming practices. | ||
+ | // VGA tutorial series. | ||
+ | // module with a different source file, some modifications may // | ||
+ | // be necessary. | ||
+ | // // | ||
+ | // Author | ||
+ | // Translator | ||
+ | // // | ||
+ | // Last Modified : January 13, 1995 // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // // | ||
+ | // INCLUDE FILES // | ||
+ | // // | ||
+ | |||
+ | #include < | ||
+ | // geninterrupt() | ||
+ | #include < | ||
+ | // abs() | ||
+ | |||
+ | // // | ||
+ | // DEFINES // | ||
+ | // // | ||
+ | |||
+ | #if !defined(PI) | ||
+ | #define PI 3.1415927 | ||
+ | #endif | ||
+ | |||
+ | #if !defined(VGA) | ||
+ | #define VGA 0xA000 | ||
+ | #endif | ||
+ | |||
+ | // // | ||
+ | // TYPEDEFS // | ||
+ | // // | ||
+ | |||
+ | typedef unsigned char byte; | ||
+ | typedef unsigned int word; | ||
+ | |||
+ | // // | ||
+ | // FUNCTION PROTOTYPES // | ||
+ | // // | ||
+ | |||
+ | // MODE SETTING FUNCTIONS | ||
+ | void SetMCGA | ||
+ | void SetText | ||
+ | |||
+ | // PALLETTE FUNCTIONS | ||
+ | void Pal (byte Col, byte R, byte G, byte B); | ||
+ | void GetPal | ||
+ | |||
+ | // MATH-LIKE FUNCTIONS | ||
+ | float rad | ||
+ | int | ||
+ | |||
+ | // DRAWING FUNCTIONS | ||
+ | void Putpixel | ||
+ | void Line (int a, int b, int c, int d, int col, word Where); | ||
+ | |||
+ | // VIDEO MEMORY FUNCTIONS | ||
+ | void Cls (byte Col, word Where); | ||
+ | void Flip (word source, word dest); | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // 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); | ||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Pal() - This sets the Red, Green, and Blue values of a certain color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal (byte Col, byte R, byte G, byte B) { | ||
+ | asm { | ||
+ | mov dx, 0x3C8 // load DX with 3C8 (write pallette function) | ||
+ | mov al, [Col] // move color to AL | ||
+ | out dx, al // write DX to the VGA (tell VGA that we want to | ||
+ | // | ||
+ | inc | ||
+ | mov al, [R] // move Red to AL | ||
+ | out dx, al // write DX to VGA (tell VGA that we want to use | ||
+ | // | ||
+ | mov al, [G] // move Green to AL | ||
+ | out dx, al // write DX to VGA | ||
+ | mov al, [B] // move Blue to AL | ||
+ | out dx, al // write DX to VGA | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // GetPal() - This reads the values of the Red, Green, and Blue values of // | ||
+ | // a certain color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void GetPal (byte Col, byte &R, byte &G, byte &B) { | ||
+ | |||
+ | byte rr,gg,bb; | ||
+ | |||
+ | asm { | ||
+ | mov dx, 0x03C7 | ||
+ | mov al, [Col] // move color to AL | ||
+ | out dx, al // write DX to the VGA (tell VGA that we want to | ||
+ | // | ||
+ | add dx, 2 // load DX with 3C9 (read RGB colors) | ||
+ | in al, dx // read Red to AL | ||
+ | mov | ||
+ | in al, dx // read Green to AL | ||
+ | mov | ||
+ | in al, dx // read Blue to AL | ||
+ | mov | ||
+ | } | ||
+ | |||
+ | R = rr; | ||
+ | G = gg; | ||
+ | B = bb; | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // rad() - This calculates the degrees of an angle. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | float rad(float theta) { | ||
+ | return ((theta * PI)/180); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // sgn() - This checks the sign of an integer and returns a 1, -1, or 0. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | int sgn (int a) { | ||
+ | |||
+ | if (a > 0) return +1; | ||
+ | if (a < 0) return -1; | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Putpixel() - This puts a pixel on the screen by writing directly to // | ||
+ | // memory. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Putpixel (word X, word Y, byte Col, word Where) { | ||
+ | asm { | ||
+ | push ds // save DS | ||
+ | push es // save ES | ||
+ | mov ax, [Where] | ||
+ | mov es, ax // set ES to segment of Where | ||
+ | mov bx, [X] // set BX to X | ||
+ | mov dx, [Y] // set DX to Y | ||
+ | push bx // save BX (our X value) | ||
+ | mov bx, dx // now BX and DX are equal to Y | ||
+ | mov dh, dl // copy DL to DH (multiply Y by 256) | ||
+ | xor dl, dl // zero out DL | ||
+ | shl bx, 6 // shift BX left 6 places (multiply Y by 64). | ||
+ | add dx, bx // add BX to DX (Y*64 + Y*256 = Y*320) | ||
+ | pop | ||
+ | add bx, dx // add BX to DX (Y*320 + X). this gives you | ||
+ | // | ||
+ | mov di, bx // move the offset to DI | ||
+ | xor al, al // zero out AL | ||
+ | mov ah, [Col] // move value of Col into AH | ||
+ | mov | ||
+ | pop | ||
+ | pop | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Line() - This draws a line from a,b to c,d of color col on screne Where // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Line(int a, int b, int c, int d, int col, word Where) { | ||
+ | |||
+ | 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 = 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; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Cls() - This clears the screen at location Where to color Col // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Cls(byte Col, word Where) { | ||
+ | asm { | ||
+ | push es // save ES | ||
+ | mov cx, 32000 // this is our loop counter. | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | mov es, [Where] | ||
+ | xor di, di // zero out DI | ||
+ | mov al, [Col] // move color to AL | ||
+ | mov ah, al // move color to AH (Remember, will be moving | ||
+ | // | ||
+ | rep | ||
+ | // | ||
+ | pop | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Flip() - This copies the entire screen at " | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Flip(word source, word dest) { | ||
+ | asm { | ||
+ | push ds // save DS | ||
+ | mov ax, [dest] | ||
+ | mov es, ax // set ES to point to destination | ||
+ | mov ax, [source] // copy segment of source to AX | ||
+ | mov ds, ax // set DS to point to source | ||
+ | xor si, si // zero out SI | ||
+ | xor di, di // zero out DI | ||
+ | mov cx, 32000 // set our counter to 32000 | ||
+ | rep | ||
+ | // | ||
+ | pop | ||
+ | } | ||
+ | } | ||
+ | </ | ||
<nspages back2root/ | <nspages back2root/ |