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/05 14:04] – [In closing] frater | back2root:archives:denthor:part-08 [2021/09/18 20:39] (Version actuelle) – [Optimisation] 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 66: | Ligne 69: | ||
</ | </ | ||
- | 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 1201: | Ligne 1208: | ||
} while (ch != 27); // if the escape code was 27 (escape key) then exit | } 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/ |