Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédente | |||
back2root:archives:denthor:part-09 [2021/09/02 11:49] – frater | back2root:archives:denthor:part-09 [2021/09/05 14:09] (Version actuelle) – [In closing] frater | ||
---|---|---|---|
Ligne 206: | Ligne 206: | ||
Does no other BBS's ANYWHERE carry the trainer? Am I writing this for three people who get it from one of these BBS's each week? Should I go on? (Hehehehe ... I was pleased to note that Tut 8 was THE most downloaded file from ASPHYXIA BBS last month ... ) | Does no other BBS's ANYWHERE carry the trainer? Am I writing this for three people who get it from one of these BBS's each week? Should I go on? (Hehehehe ... I was pleased to note that Tut 8 was THE most downloaded file from ASPHYXIA BBS last month ... ) | ||
+ | |||
+ | ==== Code Source ==== | ||
+ | |||
+ | === PaSCAL === | ||
+ | |||
+ | <code pascal> | ||
+ | (*****************************************************************************) | ||
+ | (* *) | ||
+ | (* TUT9.PAS - VGA Trainer Program 9 (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. *) | ||
+ | (* -Christopher G. Mann (Snowman) | ||
+ | (* *) | ||
+ | (* Program Notes : This program presents polygons. | ||
+ | (* *) | ||
+ | (* Author | ||
+ | (* *) | ||
+ | (*****************************************************************************) | ||
+ | |||
+ | {$X+} | ||
+ | USES Crt; | ||
+ | |||
+ | CONST VGA = $A000; | ||
+ | maxpolys = 5; | ||
+ | A : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | S : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | P : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | H : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | Y : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | X : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | I : Array [1..maxpolys, | ||
+ | ( | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), } | ||
+ | { (X2,Y2,Z2) ... for the 4 points of a poly } | ||
+ | |||
+ | |||
+ | Type Point = Record | ||
+ | | ||
+ | END; | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | VAR Lines : Array [1..maxpolys, | ||
+ | Translated : Array [1..maxpolys, | ||
+ | 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; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure Hline (x1, | ||
+ | { This draws a horizontal line from x1 to x2 on line y in color col } | ||
+ | asm | ||
+ | mov | ||
+ | mov es,ax | ||
+ | mov ax,y | ||
+ | mov di,ax | ||
+ | shl ax,8 | ||
+ | shl di,6 | ||
+ | add di,ax | ||
+ | add di,x1 | ||
+ | |||
+ | mov | ||
+ | mov ah,al | ||
+ | mov cx,x2 | ||
+ | sub cx,x1 | ||
+ | shr cx,1 | ||
+ | jnc | ||
+ | stosb | ||
+ | @Start : | ||
+ | rep stosw | ||
+ | end; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure DrawPoly(x1, | ||
+ | { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4 | ||
+ | in color col } | ||
+ | var | ||
+ | x:integer; | ||
+ | mny, | ||
+ | mnx, | ||
+ | mul1,div1, | ||
+ | mul2,div2, | ||
+ | mul3,div3, | ||
+ | mul4, | ||
+ | |||
+ | begin | ||
+ | mny:=y1; mxy:=y1; | ||
+ | if y2<mny then mny:=y2; | ||
+ | if y2>mxy then mxy:=y2; | ||
+ | if y3<mny then mny:=y3; | ||
+ | if y3>mxy then mxy: | ||
+ | if y4<mny then mny:=y4; | ||
+ | if y4>mxy then mxy:=y4; | ||
+ | |||
+ | if mny<0 then mny:=0; | ||
+ | if mxy>199 then mxy:=199; | ||
+ | if mny>199 then exit; | ||
+ | if mxy<0 then exit; { Verticle range checking } | ||
+ | |||
+ | mul1: | ||
+ | mul2: | ||
+ | mul3: | ||
+ | mul4: | ||
+ | |||
+ | for yc:=mny to mxy do | ||
+ | begin | ||
+ | mnx:=320; | ||
+ | mxx:=-1; | ||
+ | if (y4>=yc) or (y1>=yc) then | ||
+ | if (y4<=yc) or (y1<=yc) then { Check that yc is between y1 and y4 } | ||
+ | if not(y4=y1) then | ||
+ | begin | ||
+ | x: | ||
+ | if x<mnx then | ||
+ | mnx:=x; | ||
+ | if x>mxx then | ||
+ | mxx: | ||
+ | end; | ||
+ | if (y1>=yc) or (y2>=yc) then | ||
+ | if (y1<=yc) or (y2<=yc) then { Check that yc is between y1 and y2 } | ||
+ | if not(y1=y2) then | ||
+ | begin | ||
+ | x: | ||
+ | if x<mnx then | ||
+ | mnx:=x; | ||
+ | if x>mxx then | ||
+ | mxx: | ||
+ | end; | ||
+ | if (y2>=yc) or (y3>=yc) then | ||
+ | if (y2<=yc) or (y3<=yc) then { Check that yc is between y2 and y3 } | ||
+ | if not(y2=y3) then | ||
+ | begin | ||
+ | x: | ||
+ | if x<mnx then | ||
+ | mnx:=x; | ||
+ | if x>mxx then | ||
+ | mxx: | ||
+ | end; | ||
+ | if (y3>=yc) or (y4>=yc) then | ||
+ | if (y3<=yc) or (y4<=yc) then { Check that yc is between y3 and y4 } | ||
+ | if not(y3=y4) then | ||
+ | begin | ||
+ | x: | ||
+ | if x<mnx then | ||
+ | mnx:=x; | ||
+ | if x>mxx then | ||
+ | mxx: | ||
+ | end; | ||
+ | if mnx<0 then | ||
+ | mnx:=0; | ||
+ | if mxx>319 then | ||
+ | mxx: | ||
+ | if mnx<=mxx then | ||
+ | hline (mnx, | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Function rad (theta : real) : real; | ||
+ | { This calculates the degrees of an angle } | ||
+ | BEGIN | ||
+ | rad := theta * pi / 180 | ||
+ | END; | ||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure SetUpPoints; | ||
+ | { This creates the lookup table } | ||
+ | VAR loop1, | ||
+ | BEGIN | ||
+ | For loop1:=0 to 360 do BEGIN | ||
+ | lookup [loop1, | ||
+ | lookup [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 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 maxpolys do BEGIN | ||
+ | For loop2:=1 to 4 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; | ||
+ | END; | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | |||
+ | |||
+ | {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ} | ||
+ | Procedure DrawPoints; | ||
+ | { This draws the translated object to the virtual screen } | ||
+ | VAR loop1: | ||
+ | nx, | ||
+ | temp: | ||
+ | BEGIN | ||
+ | For loop1:=1 to maxpolys 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, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx3:=round (256*translated[loop1, | ||
+ | ny3:=round (256*translated[loop1, | ||
+ | temp:=round (translated[loop1, | ||
+ | nx4:=round (256*translated[loop1, | ||
+ | ny4:=round (256*translated[loop1, | ||
+ | drawpoly (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; | ||
+ | |||
+ | Procedure Whizz (sub: | ||
+ | VAR loop1: | ||
+ | BEGIN | ||
+ | For loop1:=-64 to -5 do BEGIN | ||
+ | zoff: | ||
+ | if sub then xoff: | ||
+ | RotatePoints (deg, | ||
+ | DrawPoints; | ||
+ | flip (vaddr, | ||
+ | Cls (vaddr,0); | ||
+ | deg: | ||
+ | END; | ||
+ | END; | ||
+ | |||
+ | BEGIN | ||
+ | deg:=0; | ||
+ | ch:=#0; | ||
+ | Yoff:=100; | ||
+ | Xoff:=350; | ||
+ | Cls (vaddr,0); | ||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (TRUE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (FALSE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (TRUE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (FALSE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (TRUE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (FALSE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (TRUE); | ||
+ | |||
+ | For loop1:=1 to maxpolys do | ||
+ | For loop2:=1 to 4 do BEGIN | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | Lines [loop1, | ||
+ | END; | ||
+ | Whizz (FALSE); | ||
+ | |||
+ | cls (vaddr,0); | ||
+ | cls (vga,0); | ||
+ | Xoff := 160; | ||
+ | |||
+ | Repeat | ||
+ | if keypressed then BEGIN | ||
+ | ch:=upcase (Readkey); | ||
+ | Case ch of ' | ||
+ | ' | ||
+ | ',' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | END; | ||
+ | END; | ||
+ | DrawPoints; | ||
+ | flip (vaddr, | ||
+ | cls (vaddr,0); | ||
+ | RotatePoints (deg, | ||
+ | deg: | ||
+ | Until ch=#27; | ||
+ | END; | ||
+ | |||
+ | |||
+ | BEGIN | ||
+ | SetUpVirtual; | ||
+ | clrscr; | ||
+ | Writeln (' | ||
+ | Writeln ('back to the grindstone ;-) ... anyway, this tutorial is, by'); | ||
+ | Writeln (' | ||
+ | Writeln; | ||
+ | Writeln ('In this program, the letters of ASPHYXIA will fly past you. As you'); | ||
+ | Writeln ('will see, they are solid, not wireframe. After the last letter has'); | ||
+ | Writeln (' | ||
+ | Writeln; | ||
+ | Writeln ('You will be able to move it around the screen, and you will notice' | ||
+ | Writeln ('that it may have bits only half on the screen, i.e. clipping is'); | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | Writeln ('it should be easy enough to put in yourself ... if you have any'); | ||
+ | Writeln (' | ||
+ | Writeln; | ||
+ | Writeln ('I hope this is what you wanted...leave me mail for new ideas.' | ||
+ | writeln; | ||
+ | writeln; | ||
+ | Write (' | ||
+ | Readkey; | ||
+ | SetMCGA; | ||
+ | SetUpPoints; | ||
+ | MoveAround; | ||
+ | SetText; | ||
+ | ShutDown; | ||
+ | Writeln ('All done. This concludes the ninth sample program in the ASPHYXIA' | ||
+ | Writeln (' | ||
+ | Writeln (' | ||
+ | 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: | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // TUTPROG9.CPP - VGA Trainer Program 9 (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. // | ||
+ | // // | ||
+ | // Program Notes : This program demonstrates polygon moving and rotation. | ||
+ | // // | ||
+ | // 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 tut9.cpp | ||
+ | // // | ||
+ | // The way things are set up, there is no need to compile | ||
+ | // or link tut9.cpp and gfx2.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 21, 1995 // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // // | ||
+ | // INCLUDE FILES // | ||
+ | // // | ||
+ | |||
+ | #include < | ||
+ | // clrscr(), getch(), kbhit() | ||
+ | #include < | ||
+ | // cout() | ||
+ | #include < | ||
+ | // sin(), cos() | ||
+ | #include < | ||
+ | // exit() | ||
+ | #include " | ||
+ | // our graphics library tools | ||
+ | |||
+ | // // | ||
+ | // TYPEDEFS // | ||
+ | // // | ||
+ | |||
+ | typedef unsigned char byte; | ||
+ | typedef unsigned int word; | ||
+ | |||
+ | // // | ||
+ | // CONSTANTS // | ||
+ | // // | ||
+ | |||
+ | const MAXPOLYS | ||
+ | const POLYPOINTS = 4; | ||
+ | const POLYCORDS | ||
+ | |||
+ | // // | ||
+ | // LETTER DATA // | ||
+ | // // | ||
+ | |||
+ | // The 3-D coordinates of our object ... stored as {X1,Y1,Z1}, | ||
+ | // {X2,Y2,Z2} ... for the 4 points of a poly. | ||
+ | const int A[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-10, 10, 0},{ -2,-10, 0},{ 0,-10, 0},{ -5,10, 0}}, // 1 | ||
+ | {{ 10, 10, 0},{ 2,-10, 0},{ 0,-10, 0},{ 5,10, 0}}, // 2 | ||
+ | {{ -2,-10, 0},{ 2,-10, 0},{ 2, -5, 0},{ -2,-5, 0}}, // 3 | ||
+ | {{ -6, 0, 0},{ 6, 0, 0},{ 7, 5, 0},{ -7, 5, 0}}, // 4 | ||
+ | {{ 0, 0, 0},{ 0, 0, 0},{ 0, 0, 0},{ 0, 0, 0}} }; // 5 | ||
+ | |||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // |....| | ||
+ | // `.4------+------4.' | ||
+ | // | ||
+ | // | ||
+ | // ||.....|.....|| | ||
+ | // ||.....|.....|| | ||
+ | // -------+---4+----+----+4---+------- | ||
+ | // |...| | |...| | ||
+ | // `...` | ' | ||
+ | // |...|||...| | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // ||.|.|| | ||
+ | // ||.|.|| | ||
+ | // `|.|.|' | ||
+ | // 3-2-3 | ||
+ | |||
+ | const int S[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-10,-10, 0},{ 10,-10, 0},{10, -7, 0},{-10, -7, 0}}, | ||
+ | {{-10, 10, 0},{ 10, 10, 0}, | ||
+ | {{-10, | ||
+ | {{-10, -8, 0},{ -7, -8, 0}, | ||
+ | {{ 10, 8, 0},{ 7, 8, 0},{ 7, 0, 0},{ 10, 0, 0}} }; | ||
+ | |||
+ | const int P[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-10, | ||
+ | {{10, | ||
+ | {{-9, | ||
+ | {{-9, | ||
+ | {{0, | ||
+ | |||
+ | const int H[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-10, | ||
+ | {{10, | ||
+ | {{-9, | ||
+ | {{0, | ||
+ | {{0, | ||
+ | |||
+ | const int Y[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-7, | ||
+ | {{7, | ||
+ | {{-2, | ||
+ | {{0, | ||
+ | {{0, | ||
+ | |||
+ | const int X[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-7, | ||
+ | {{7, | ||
+ | {{0, | ||
+ | {{0, | ||
+ | {{0, | ||
+ | |||
+ | const int I[MAXPOLYS][POLYPOINTS][POLYCORDS] = | ||
+ | { {{-10, | ||
+ | {{-10, | ||
+ | {{-2, | ||
+ | {{0, | ||
+ | {{0, | ||
+ | |||
+ | // // | ||
+ | // FUNCTION PROTOTYPES // | ||
+ | // // | ||
+ | |||
+ | void DrawPoly | ||
+ | int x3, int y3, int x4, int y4, | ||
+ | byte Col, word Where); | ||
+ | void SetUpPoints | ||
+ | void RotatePoints (int X, int Y, int Z); | ||
+ | void DrawPoints | ||
+ | void Whizz (int sub, int °); | ||
+ | void MoveAround | ||
+ | |||
+ | // // | ||
+ | // STRUCTURES // | ||
+ | // // | ||
+ | |||
+ | // The data for 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 object | ||
+ | Point Lines[MAXPOLYS][4]; | ||
+ | Point Translated[MAXPOLYS][4]; | ||
+ | |||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // MAIN FUNCTION | ||
+ | // // | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void main() { | ||
+ | |||
+ | SetUpVirtual(Virscr, | ||
+ | // always check to see if enough memory was allocated | ||
+ | if (Virscr == NULL) { | ||
+ | SetText(); | ||
+ | cout << " | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | clrscr(); | ||
+ | cout | ||
+ | << "Hello there! Varsity has begun once again, so it is once again\n" | ||
+ | << "back to the grindstone ;-) ... anyway, this tutorial is, by\n" | ||
+ | << " | ||
+ | << "In this program, the letters of ASPHYXIA will fly past you. As you\n" | ||
+ | << "will see, they are solid, not wireframe. After the last letter has\n" | ||
+ | << "flown by, a large A will be left in the middle of the screen.\n\n" | ||
+ | << "You will be able to move it around the screen, and you will notice\n" | ||
+ | << "that it may have bits only half on the screen, i.e. clipping is\n" | ||
+ | << " | ||
+ | << " | ||
+ | << " | ||
+ | << "it should be easy enough to put in yourself ... if you have any\n" | ||
+ | << " | ||
+ | cout << "Hit any key to continue ...\n"; | ||
+ | getch(); | ||
+ | SetMCGA(); | ||
+ | |||
+ | SetUpPoints(); | ||
+ | |||
+ | MoveAround(); | ||
+ | SetText(); | ||
+ | |||
+ | ShutDown(Virscr); | ||
+ | |||
+ | cout | ||
+ | << "All done. This concludes the ninth sample program in the ASPHYXIA\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"; | ||
+ | cout << "Hit any key to exit ...\n"; | ||
+ | getch(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // DrawPoly() - This draws a polygon with 4 points at x1,y1, x2,y2, x3,y3, // | ||
+ | // x4,y4 in color Col at location Where // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void DrawPoly(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, | ||
+ | byte Col, word Where) { | ||
+ | |||
+ | int x, mny, mxy, mnx, mxx, yc; | ||
+ | int mul1, div1, mul2, div2, mul3, div3, mul4, div4; | ||
+ | |||
+ | // find the maximum y (mny) and minimum y (mny) | ||
+ | mny = y1; | ||
+ | mxy = y1; | ||
+ | if (y2<mny) mny = y2; | ||
+ | if (y2>mxy) mxy = y2; | ||
+ | if (y3<mny) mny = y3; | ||
+ | if (y3>mxy) mxy = y3; | ||
+ | if (y4<mny) mny = y4; | ||
+ | if (y4>mxy) mxy = y4; | ||
+ | |||
+ | // if the mimimum or maximum is out of bounds, bring it back in | ||
+ | if (mny< | ||
+ | if (mxy> | ||
+ | |||
+ | // verticle range checking | ||
+ | if (mny> | ||
+ | if (mxy< | ||
+ | |||
+ | // constants needed for intersection calculations | ||
+ | mul1 = x1-x4; | ||
+ | mul2 = x2-x1; | ||
+ | mul3 = x3-x2; | ||
+ | mul4 = x4-x3; | ||
+ | |||
+ | for (yc=mny; yc<mxy; yc++) { | ||
+ | mnx = 320; | ||
+ | mxx = -1; | ||
+ | |||
+ | if ((y4 >= yc) || (y1 >= yc)) | ||
+ | if ((y4 <= yc) || (y1 <= yc)) | ||
+ | if (y4 != y1) { | ||
+ | x = ((yc-y4) * mul1 / div1) + x4; | ||
+ | if (x<mnx) mnx = x; | ||
+ | if (x>mxx) mxx = x; | ||
+ | } | ||
+ | |||
+ | if ((y1 >= yc) || (y2 >= yc)) | ||
+ | if ((y1 <= yc) || (y2 <= yc)) | ||
+ | if (y1 != y2) { | ||
+ | x = ((yc-y1) * mul2 / div2) + x1; | ||
+ | if (x<mnx) mnx = x; | ||
+ | if (x>mxx) mxx = x; | ||
+ | } | ||
+ | |||
+ | if ((y2 >= yc) || (y3 >= yc)) | ||
+ | if ((y2 <= yc) || (y3 <= yc)) | ||
+ | if (y2 != y3) { | ||
+ | x = ((yc-y2) * mul3 / div3) + x2; | ||
+ | if (x<mnx) mnx = x; | ||
+ | if (x>mxx) mxx = x; | ||
+ | } | ||
+ | |||
+ | if ((y3 >= yc) || (y4 >= yc)) | ||
+ | if ((y3 <= yc) || (y4 <= yc)) | ||
+ | if (y3 != y4) { | ||
+ | x = ((yc-y3) * mul4 / div4) + x3; | ||
+ | if (x<mnx) mnx = x; | ||
+ | if (x>mxx) mxx = x; | ||
+ | } | ||
+ | |||
+ | // horizontal range checking | ||
+ | if (mnx< | ||
+ | if (mxx> | ||
+ | |||
+ | if (mnx< | ||
+ | // draw the horizontal line | ||
+ | Hline(mnx, | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetUpPoints() - This creates the lookup table. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetUpPoints() { | ||
+ | |||
+ | int loop1; | ||
+ | |||
+ | // generate the sin() and cos() tables | ||
+ | for (loop1=0; loop1< | ||
+ | Lookup [loop1][0] = sin(rad(loop1)); | ||
+ | Lookup [loop1][1] = cos(rad(loop1)); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // RotatePoints() - This rotates object lines by X,Y and Z, then places | ||
+ | // the result in Translated[] | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void RotatePoints(int X, int Y, int Z) { | ||
+ | |||
+ | int loop1, loop2; | ||
+ | Point temp; | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2<4; loop2++) { | ||
+ | temp.x = Lines[loop1][loop2].x; | ||
+ | temp.y = Lookup[X][1] * Lines[loop1][loop2].y - Lookup[X][0] * Lines[loop1][loop2].z; | ||
+ | temp.z = Lookup[X][0] * Lines[loop1][loop2].y + Lookup[X][1] * Lines[loop1][loop2].z; | ||
+ | Translated[loop1][loop2] = temp; | ||
+ | |||
+ | if (Y>0) { | ||
+ | temp.x = Lookup[Y][1] * Translated[loop1][loop2].x - Lookup[Y][0] * Translated[loop1][loop2].y; | ||
+ | temp.y = Lookup[Y][0] * Translated[loop1][loop2].x + Lookup[Y][1] * Translated[loop1][loop2].y; | ||
+ | temp.z = Translated[loop1][loop2].z; | ||
+ | Translated[loop1][loop2] = temp; | ||
+ | } | ||
+ | |||
+ | if (Z>0) { | ||
+ | temp.x = Lookup[Z][1] * Translated[loop1][loop2].x + Lookup[Z][0] * Translated[loop1][loop2].z; | ||
+ | temp.y = Translated[loop1][loop2].y; | ||
+ | temp.z = Lookup[Z][0] * Translated[loop1][loop2].x + Lookup[Z][1] * Translated[loop1][loop2].z; | ||
+ | Translated[loop1][loop2] = temp; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // DrawPoints() - This draws the translated object to the virtual screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void DrawPoints() { | ||
+ | |||
+ | int nx, ny, nx2, ny2, nx3, ny3, nx4, ny4, temp, loop1; | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | if ((Translated[loop1][0].z+Zoff< | ||
+ | (Translated[loop1][2].z+Zoff< | ||
+ | |||
+ | temp = Translated[loop1][0].z + Zoff; | ||
+ | nx = ((256*Translated[loop1][0].x) / temp) + Xoff; | ||
+ | ny = ((256*Translated[loop1][0].y) / temp) + Yoff; | ||
+ | |||
+ | temp = Translated[loop1][1].z + Zoff; | ||
+ | nx2 = ((256*Translated[loop1][1].x) / temp) + Xoff; | ||
+ | ny2 = ((256*Translated[loop1][1].y) / temp) + Yoff; | ||
+ | |||
+ | temp = Translated[loop1][2].z + Zoff; | ||
+ | nx3 = ((256*Translated[loop1][2].x) / temp) + Xoff; | ||
+ | ny3 = ((256*Translated[loop1][2].y) / temp) + Yoff; | ||
+ | |||
+ | temp = Translated[loop1][3].z + Zoff; | ||
+ | nx4 = ((256*Translated[loop1][3].x) / temp) + Xoff; | ||
+ | ny4 = ((256*Translated[loop1][3].y) / temp) + Yoff; | ||
+ | |||
+ | DrawPoly(nx, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Whizz() - This function moves the letters from one side of the screen | ||
+ | // to the other and also zooms them closer as they move. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Whizz(int sub, int °) { | ||
+ | |||
+ | int loop1; | ||
+ | |||
+ | for (loop1=(-64); | ||
+ | |||
+ | Zoff = (loop1 * 8) - 15; | ||
+ | if (sub == 1) Xoff -= 7; else Xoff += 7; | ||
+ | RotatePoints(deg, | ||
+ | DrawPoints(); | ||
+ | Flip(Vaddr, | ||
+ | Cls(0, | ||
+ | deg = (deg + 5) % 360; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // MoveAround() - This is the main display function. | ||
+ | // object towards the viewer by increasing the Zoff, then // | ||
+ | // it passes control to the user. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void MoveAround() { | ||
+ | |||
+ | int deg=0, loop1, loop2; | ||
+ | byte ch=1; // assign a dummy value to ch | ||
+ | |||
+ | Yoff = 100; | ||
+ | Xoff = 350; | ||
+ | Cls(0, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = A[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = A[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = A[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(1, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = S[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = S[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = S[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(0, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = P[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = P[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = P[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(1, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = H[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = H[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = H[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(0, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = Y[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = Y[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = Y[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(1, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = X[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = X[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = X[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(0, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = I[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = I[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = I[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(1, | ||
+ | |||
+ | for (loop1=0; loop1< | ||
+ | for (loop2=0; loop2< | ||
+ | Lines[loop1][loop2].x = A[loop1][loop2][0]; | ||
+ | Lines[loop1][loop2].y = A[loop1][loop2][1]; | ||
+ | Lines[loop1][loop2].z = A[loop1][loop2][2]; | ||
+ | } | ||
+ | Whizz(0, | ||
+ | |||
+ | Cls(0, | ||
+ | Cls(0,VGA); | ||
+ | |||
+ | Xoff = 160; | ||
+ | |||
+ | do { | ||
+ | if (kbhit()) { | ||
+ | ch = getch(); | ||
+ | switch (ch) { | ||
+ | case ' | ||
+ | case ' | ||
+ | case ',': | ||
+ | case ' | ||
+ | case ' | ||
+ | case ' | ||
+ | } | ||
+ | } | ||
+ | DrawPoints(); | ||
+ | Flip(Vaddr, | ||
+ | Cls(0, | ||
+ | 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: | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // GFX2.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 21, 1995 // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | // // | ||
+ | // INCLUDE FILES // | ||
+ | // // | ||
+ | |||
+ | #include < | ||
+ | // farcalloc(), | ||
+ | #include < | ||
+ | // geninterrupt(), | ||
+ | |||
+ | // // | ||
+ | // 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 // | ||
+ | // // | ||
+ | |||
+ | // VIRTUAL SCREEN FUNCTIONS | ||
+ | void SetUpVirtual(byte far *& | ||
+ | void ShutDown | ||
+ | void Cls (byte Col, word Where); | ||
+ | void Flip (word source, word dest); | ||
+ | |||
+ | // MODE SETTING FUNCTIONS | ||
+ | void SetMCGA | ||
+ | void SetText | ||
+ | |||
+ | // PALLETTE CLASS (DATA OBJECT AND RELATED FUNCTIONS) | ||
+ | class Pal { | ||
+ | public: | ||
+ | Pal(); | ||
+ | void PalSet | ||
+ | void PalGet | ||
+ | void PalPut | ||
+ | void PalInc | ||
+ | void PalDec | ||
+ | private: | ||
+ | byte R; // 0-63 | ||
+ | byte G; // 0-63 | ||
+ | byte B; // 0-63 | ||
+ | }; | ||
+ | |||
+ | // MATH-LIKE FUNCTIONS | ||
+ | float rad | ||
+ | int | ||
+ | |||
+ | template< | ||
+ | T abso(T value) { if (value >= 0) return value; | ||
+ | |||
+ | // DRAWING FUNCTIONS | ||
+ | void Putpixel | ||
+ | void PutpixelVGA (word X, word Y, byte Col); | ||
+ | void Line (int a, int b, int c, int d, int col, word Where); | ||
+ | void Hline (word X1, word X2, word Y, byte Col, word Where); | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // SetUpVirtual() - This sets up the memory needed for a virtual screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void SetUpVirtual(byte far *& | ||
+ | Virscr = (byte far *) farcalloc(64000, | ||
+ | Vaddr = FP_SEG(Virscr); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // ShutDown() - This frees the memory used by a virtual screen. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void ShutDown(byte far *& | ||
+ | farfree(Virscr); | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Cls() - This clears the screen at 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 64000 bytes from " | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | 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 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // 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 constructor initializes all Pal variables (R, G, and B) to // | ||
+ | // | ||
+ | // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | Pal::Pal() { R = B = G = 0; } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalSet() - This sets the Red, Green, and Blue values of a given color. | ||
+ | // Set invalid colors ( >63 ) equal to 0. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal:: | ||
+ | |||
+ | R = (Rset < 64) ? Rset : 0; | ||
+ | G = (Gset < 64) ? Gset : 0; | ||
+ | B = (Bset < 64) ? Bset : 0; | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalGet() - This reads the values of the Red, Green, and Blue values of // | ||
+ | // a certain color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal:: | ||
+ | |||
+ | byte Rtemp, Gtemp, Btemp; | ||
+ | |||
+ | 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 = Rtemp; | ||
+ | G = Gtemp; | ||
+ | B = Btemp; | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalPut() - This sets the Red, Green, and Blue values of a color. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal::PalPut (byte Col) { | ||
+ | |||
+ | byte Rtemp = R, Gtemp = G, Btemp = 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, [Rtemp] | ||
+ | out dx, al // write DX to VGA (tell VGA that we want to use | ||
+ | // | ||
+ | mov al, [Gtemp] | ||
+ | out dx, al // write DX to VGA | ||
+ | mov al, [Btemp] | ||
+ | out dx, al // write DX to VGA | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalInc() - This increments the R, G, and B values of a given Pal // | ||
+ | // variable, keeping all values less than 64. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal:: | ||
+ | |||
+ | // if (R < 63) R = R + 1; else R = 63; | ||
+ | R = (R < 63) ? (R + 1) : 63; | ||
+ | G = (G < 63) ? (G + 1) : 63; | ||
+ | B = (B < 63) ? (B + 1) : 63; | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PalDec() - This decrements the R, G, and B values of a given Pal // | ||
+ | // variable, keeping all values greater than or equal to zero. // | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Pal:: | ||
+ | |||
+ | // if (R > 0) R = R - 1; else R = 0; | ||
+ | R = (R > 0) ? (R - 1) : 0; | ||
+ | G = (G > 0) ? (G - 1) : 0; | ||
+ | B = (B > 0) ? (B - 1) : 0; | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // 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 { | ||
+ | mov ax, [Where] | ||
+ | mov es, ax // ES = VGA | ||
+ | mov bx, [X] // BX = X | ||
+ | mov dx, [Y] // DX = Y | ||
+ | mov ah, dl // AH = Y*256 | ||
+ | xor al, al // AX = Y*256 | ||
+ | shl dx, 6 // DX = Y*64 | ||
+ | add dx, ax // DX = Y*320 | ||
+ | add bx, dx // BX = Y*320 + X | ||
+ | mov ah, [Col] // move value of Col into AH | ||
+ | mov byte ptr es:[bx], ah // move Col to the offset in memory (DI) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // PutpixelVGA() - This puts a pixel on the screen by writing directly to // | ||
+ | // VGA memory. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void PutpixelVGA (word X, word Y, byte Col) { | ||
+ | asm { | ||
+ | mov ax, 0xA000 | ||
+ | mov es, ax // ES = VGA Segment | ||
+ | mov bx, [X] // BX = X | ||
+ | mov dx, [Y] // DX = Y | ||
+ | mov ah, dl // AX = Y*256 (AL is already 0 from A000 address) | ||
+ | shl dx, 6 // DX = Y*64 | ||
+ | add dx, ax // DX = Y*320 | ||
+ | add bx, dx // BX = Y*320 + X | ||
+ | mov ah, [Col] // move value of Col into AH | ||
+ | mov byte ptr es:[bx], ah // move Col to the offset in memory (DI) | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // 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 = abso(u); | ||
+ | n = abso(v); | ||
+ | |||
+ | if (m<=n) { // if the x distance is greater than the y distance | ||
+ | d2x = 0; | ||
+ | d2y = sgn(v); | ||
+ | m = abso(v); // m is the distance between y1 and y2 | ||
+ | n = abso(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; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | // // | ||
+ | // Hline() - This draws a horizontal line from X1 to X2 on line Y in color // | ||
+ | // Col at memory location Where. | ||
+ | // // | ||
+ | ///////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void Hline (word X1, word X2, word Y, byte Col, word Where) { | ||
+ | asm { | ||
+ | mov ax, [Where] | ||
+ | mov es, ax // set ES to segment of Where | ||
+ | mov ax, [Y] // set AX to Y | ||
+ | mov di, ax // set DI to Y | ||
+ | shl ax, 8 // shift AX left 8 places (multiply Y by 256) | ||
+ | shl di, 6 // shift DI left 6 places (multiply Y by 64) | ||
+ | add di, ax // add AX to DI (Y*64 + Y*256 = Y*320) | ||
+ | add di, [X1] // add the X1 offset to DI | ||
+ | mov al, [Col] // move Col to AL | ||
+ | mov ah, al // move Col to AH (we want 2 copies for word moving) | ||
+ | mov cx, [X2] // move X2 to CX | ||
+ | sub cx, [X1] // move the change in X to CX | ||
+ | shr cx, 1 // divide change in X by 2 (for word moving) | ||
+ | jnc | ||
+ | stosb // otherwise, move one byte more | ||
+ | } | ||
+ | Start: asm { | ||
+ | rep | ||
+ | } | ||
+ | } | ||
+ | </ | ||
<nspages back2root/ | <nspages back2root/ | ||