Change HTML4 entities to HTML5
< to < > to > & to &
This commit is contained in:
parent
56a4baa60e
commit
b8e7ce7165
105 changed files with 1117 additions and 1117 deletions
|
|
@ -120,7 +120,7 @@ IRR equ20h
|
|||
MPOPF macro
|
||||
local p1, p2
|
||||
jmp short p2
|
||||
p1: iret ; jump to pushed address & pop flags
|
||||
p1: iret ; jump to pushed address & pop flags
|
||||
p2: push cs ; construct far return address to
|
||||
call p1 ; the next instruction
|
||||
endm
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ pztime LST3-3.ASM
|
|||
<P>In order to perform any of the timing tests in this book, enter Listing 3.1 and name it PZTIMER.ASM, enter Listing 3.2 and name it PZTEST.ASM, and enter Listing 3.4 and name it PZTIME.BAT. Then simply enter the listing you wish to run into the file <I>filename</I> and enter the command:</P>
|
||||
<!-- CODE SNIP //-->
|
||||
<PRE>
|
||||
pztime <filename>
|
||||
pztime <filename>
|
||||
</PRE>
|
||||
<!-- END CODE SNIP //-->
|
||||
<P>In fact, that’s exactly how I timed each of the listings in this book. Code fragments you write yourself can be timed in just the same way. If you wish to time code directly in place in your programs, rather than in the test-bed program of Listing 3.2, simply insert calls to <B>ZTimerOn, ZTimerOff</B>, and <B>ZTimerReport</B> in the appropriate places and link PZTIMER to your program.</P>
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ TIMER_COUNT equ46ch
|
|||
MPOPF macro
|
||||
local p1, p2
|
||||
jmp short p2
|
||||
p1: iret ;jump to pushed address & pop flags
|
||||
p1: iret ;jump to pushed address & pop flags
|
||||
p2: pushcs ;construct far return address to
|
||||
call p1 ; the next instruction
|
||||
endm
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
<!-- CODE SNIP //-->
|
||||
<PRE>
|
||||
ZTimerOn():
|
||||
for (i=0, x=0; i<100; i++)
|
||||
for (i=0, x=0; i<100; i++)
|
||||
x += i;
|
||||
ZTimerOff();
|
||||
ZTimerReport();
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@
|
|||
;
|
||||
mov ax,0a000h
|
||||
mov ds,ax
|
||||
mov es,ax ;move to & from same segment
|
||||
sub si,si ;move to & from same offset
|
||||
mov es,ax ;move to & from same segment
|
||||
sub si,si ;move to & from same offset
|
||||
mov di,si
|
||||
mov cx,800h ;move 2K words
|
||||
cld
|
||||
|
|
@ -86,8 +86,8 @@
|
|||
; memory.
|
||||
;
|
||||
mov ax,ds
|
||||
mov es,ax ;move to & from same segment
|
||||
sub si,si ;move to & from same offset
|
||||
mov es,ax ;move to & from same segment
|
||||
sub si,si ;move to & from same offset
|
||||
mov di,si
|
||||
mov cx,800h ;move 2K words
|
||||
cld
|
||||
|
|
|
|||
12
05-03.html
12
05-03.html
|
|
@ -44,10 +44,10 @@
|
|||
* argument. Performs the search by reading and searching blocks
|
||||
* of size BLOCK_SIZE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <alloc.h> /* alloc.h for Borland compilers,
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <alloc.h> /* alloc.h for Borland compilers,
|
||||
malloc.h for Microsoft compilers */
|
||||
|
||||
#define BLOCK_SIZE 0x4000 /* we’ll process the file in 16K blocks */
|
||||
|
|
@ -164,7 +164,7 @@ main(int argc, char *argv[]) {
|
|||
when that block is searched)
|
||||
*/
|
||||
if ( (BlockSearchLength =
|
||||
WorkingLength - SearchStringLength + 1) <= 0 ) {
|
||||
WorkingLength - SearchStringLength + 1) <= 0 ) {
|
||||
Done = 1; /* Too few characters in this block for
|
||||
there to be any possible matches, so this
|
||||
is the final block and we’re done without
|
||||
|
|
@ -182,7 +182,7 @@ main(int argc, char *argv[]) {
|
|||
/* Copy any bytes from the end of the block that start
|
||||
potentially-matching sequences that would run off
|
||||
the end of the block over to the next block */
|
||||
if ( SearchStringLength > 1 ) {
|
||||
if ( SearchStringLength > 1 ) {
|
||||
memcpy(WorkingBlock,
|
||||
WorkingBlock+BLOCK_SIZE - SearchStringLength + 1,
|
||||
SearchStringLength - 1);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ Startendp
|
|||
; specified byte or a zero byte is encountered.
|
||||
; Input:
|
||||
; AH = character to search for
|
||||
; CX = maximum length to be searched (must be > 0)
|
||||
; CX = maximum length to be searched (must be > 0)
|
||||
; DS:SI = pointer to buffer to be searched
|
||||
; Output:
|
||||
; CX = 0 if and only if we ran out of bytes without finding
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ Startendp
|
|||
; specified byte or a zero byte is encountered.
|
||||
; Input:
|
||||
; AH = character to search for
|
||||
; CX = maximum length to be searched (must be > 0)
|
||||
; CX = maximum length to be searched (must be > 0)
|
||||
; DS:SI = pointer to buffer to be searched
|
||||
; Output:
|
||||
; CX = 0 if and only if we ran out of bytes without finding
|
||||
|
|
|
|||
38
08-03.html
38
08-03.html
|
|
@ -45,11 +45,11 @@
|
|||
the variable-sized blocks may contain any number of data entries,
|
||||
stored as an array of structures within the block. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __TURBOC__
|
||||
#include <alloc.h>
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
void main(void);
|
||||
|
|
@ -78,12 +78,12 @@ void main(void) {
|
|||
struct BlockHeader **LastBlockPointer;
|
||||
|
||||
printf(”ID # for which to find average: “);
|
||||
scanf(”%d”,&IDToFind);
|
||||
scanf(”%d”,&IDToFind);
|
||||
/* Build an array across 5 blocks, for testing */
|
||||
/* Anchor the linked list to BaseArrayBlockPointer */
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
/* Create 5 blocks of varying sizes */
|
||||
for (i = 1; i < 6; i++) {
|
||||
for (i = 1; i < 6; i++) {
|
||||
/* Try to get memory for the next block */
|
||||
if ((WorkingBlockPointer =
|
||||
(struct BlockHeader *) malloc(sizeof(struct BlockHeader) +
|
||||
|
|
@ -91,7 +91,7 @@ void main(void) {
|
|||
exit(1);
|
||||
}
|
||||
/* Set the # of data elements in this block */
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
/* Link the new block into the chain */
|
||||
*LastBlockPointer = WorkingBlockPointer;
|
||||
/* Point to the first data field */
|
||||
|
|
@ -99,16 +99,16 @@ void main(void) {
|
|||
(struct DataElement *) ((char *)WorkingBlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Fill the data fields with ID numbers and values */
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
WorkingDataPointer->ID = j;
|
||||
WorkingDataPointer->Value = i * 1000 + j;
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
WorkingDataPointer->ID = j;
|
||||
WorkingDataPointer->Value = i * 1000 + j;
|
||||
}
|
||||
/* Remember where to set link from this block to the next */
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
}
|
||||
/* Set the last block’s “next block” pointer to NULL to indicate
|
||||
that there are no more blocks */
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
printf(”Average of all elements with ID %d: %u\n”,
|
||||
IDToFind, FindIDAverage(IDToFind, BaseArrayBlockPointer));
|
||||
exit(0);
|
||||
|
|
@ -140,18 +140,18 @@ unsigned int FindIDAverage(unsigned int SearchedForID,
|
|||
/* Search all the DataElement entries within this block
|
||||
and accumulate data from all that match the desired ID */
|
||||
for (WorkingBlockCount=0;
|
||||
WorkingBlockCount<BlockPointer->BlockCount;
|
||||
WorkingBlockCount<BlockPointer->BlockCount;
|
||||
WorkingBlockCount++, DataPointer++) {
|
||||
/* If the ID matches, add in the value and increment the
|
||||
match counter */
|
||||
if (DataPointer->ID == SearchedForID) {
|
||||
if (DataPointer->ID == SearchedForID) {
|
||||
IDMatchCount++;
|
||||
IDMatchSum += DataPointer->Value;
|
||||
IDMatchSum += DataPointer->Value;
|
||||
}
|
||||
}
|
||||
/* Point to the next block, and continue as long as that pointer
|
||||
isn’t NULL */
|
||||
} while ((BlockPointer = BlockPointer->NextBlock) != NULL);
|
||||
} while ((BlockPointer = BlockPointer->NextBlock) != NULL);
|
||||
/* Calculate the average of all matches */
|
||||
if (IDMatchCount == 0)
|
||||
return(0); /* Avoid division by 0 */
|
||||
|
|
@ -170,7 +170,7 @@ unsigned int FindIDAverage(unsigned int SearchedForID,
|
|||
<PRE>
|
||||
; Code generated by Microsoft C for inner loop of FindIDAverage.
|
||||
;|*** for (WorkingBlockCount=0;
|
||||
;|*** WorkingBlockCount<BlockPointer->BlockCount;
|
||||
;|*** WorkingBlockCount<BlockPointer->BlockCount;
|
||||
;|*** WorkingBlockCount++, DataPointer++) {
|
||||
mov WORD PTR [bp-6],0 ;WorkingBlockCount
|
||||
mov bx,WORD PTR [bp+6] ;BlockPointer
|
||||
|
|
@ -181,13 +181,13 @@ unsigned int FindIDAverage(unsigned int SearchedForID,
|
|||
mov di,WORD PTR [bp-2] ;IDMatchSum
|
||||
mov dx,WORD PTR [bp-4] ;IDMatchCount
|
||||
$L20004:
|
||||
;|*** if (DataPointer->ID == SearchedForID) {
|
||||
;|*** if (DataPointer->ID == SearchedForID) {
|
||||
mov ax,WORD PTR [si]
|
||||
cmp WORD PTR [bp+4],ax ;SearchedForID
|
||||
jne $I265
|
||||
;|*** IDMatchCount++;
|
||||
inc dx
|
||||
;|*** IDMatchSum += DataPointer->Value;
|
||||
;|*** IDMatchSum += DataPointer->Value;
|
||||
add di,WORD PTR [si+2]
|
||||
;|*** }
|
||||
;|*** }
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ IntraBlockLoop:
|
|||
cmp [di+ID],ax ;Do we have an ID match?
|
||||
jnz NoMatch ;No match
|
||||
inc bx ;We have a match; IDMatchCount++;
|
||||
add dx,[di+Value] ;IDMatchSum += DataPointer->Value;
|
||||
add dx,[di+Value] ;IDMatchSum += DataPointer->Value;
|
||||
NoMatch:
|
||||
add di,DATA_ELEMENT_SIZE ;point to the next element
|
||||
loop IntraBlockLoop
|
||||
|
|
@ -205,12 +205,12 @@ LoopEntryTable label word
|
|||
dw LoopEntry4,LoopEntry5,LoopEntry6,LoopEntry7
|
||||
M_IBL macro P1
|
||||
local NoMatch
|
||||
LoopEntry&P1&:
|
||||
LoopEntry&P1&:
|
||||
scasw ;Do we have an ID match?
|
||||
jnz NoMatch ;No match
|
||||
;We have a match
|
||||
inc bx ;IDMatchCount++;
|
||||
add dx,[di] ;IDMatchSum += DataPointer->Value;
|
||||
add dx,[di] ;IDMatchSum += DataPointer->Value;
|
||||
NoMatch:
|
||||
add di,DATA_ELEMENT_SIZE-2 ;point to the next element
|
||||
; (SCASW advanced 2 bytes already)
|
||||
|
|
|
|||
22
08-05.html
22
08-05.html
|
|
@ -47,11 +47,11 @@
|
|||
stored in the form of two separate arrays, one for ID numbers and
|
||||
one for values. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __TURBOC__
|
||||
#include <alloc.h>
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
void main(void);
|
||||
|
|
@ -82,13 +82,13 @@ void main(void) {
|
|||
struct BlockHeader **LastBlockPointer;
|
||||
|
||||
printf(”ID # for which to find average: “);
|
||||
scanf(”%d”,&IDToFind);
|
||||
scanf(”%d”,&IDToFind);
|
||||
|
||||
/* Build an array across 5 blocks, for testing */
|
||||
/* Anchor the linked list to BaseArrayBlockPointer */
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
LastBlockPointer = &BaseArrayBlockPointer;
|
||||
/* Create 5 blocks of varying sizes */
|
||||
for (i = 1; i < 6; i++) {
|
||||
for (i = 1; i < 6; i++) {
|
||||
/* Try to get memory for the next block */
|
||||
if ((WorkingBlockPointer =
|
||||
(struct BlockHeader *) malloc(sizeof(struct BlockHeader) +
|
||||
|
|
@ -96,23 +96,23 @@ void main(void) {
|
|||
exit(1);
|
||||
}
|
||||
/* Set the number of data elements in this block */
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
WorkingBlockPointer->BlockCount = i * 10;
|
||||
/* Link the new block into the chain */
|
||||
*LastBlockPointer = WorkingBlockPointer;
|
||||
/* Point to the first data field */
|
||||
WorkingDataPointer = (int *) ((char *)WorkingBlockPointer +
|
||||
sizeof(struct BlockHeader));
|
||||
/* Fill the data fields with ID numbers and values */
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
for (j = 0; j < (i * 10); j++, WorkingDataPointer++) {
|
||||
*WorkingDataPointer = j;
|
||||
*(WorkingDataPointer + i * 10) = i * 1000 + j;
|
||||
}
|
||||
/* Remember where to set link from this block to the next */
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
LastBlockPointer = &WorkingBlockPointer->NextBlock;
|
||||
}
|
||||
/* Set the last block’s “next block” pointer to NULL to indicate
|
||||
that there are no more blocks */
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
WorkingBlockPointer->NextBlock = NULL;
|
||||
printf(”Average of all elements with ID %d: %u\n”,
|
||||
IDToFind, FindIDAverage2(IDToFind, BaseArrayBlockPointer));
|
||||
exit(0);
|
||||
|
|
@ -168,7 +168,7 @@ IntraBlockLoop:
|
|||
repnz scasw ;Search for the ID
|
||||
jnz DoNextBlock ;No match, the block is done
|
||||
inc bp ;We have a match; IDMatchCount++;
|
||||
add dx,[di+bx-2];IDMatchSum += DataPointer->Value;
|
||||
add dx,[di+bx-2];IDMatchSum += DataPointer->Value;
|
||||
; (SCASW has advanced DI 2 bytes)
|
||||
and cx,cx ;Is there more data to search through?
|
||||
jnz IntraBlockLoop ;yes
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ _FindStringendp
|
|||
<P><B>LISTING 9.3 L9-3.C</B></P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Program to exercise buffer-search routines in Listings 9.1 & 9.2 */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
/* Program to exercise buffer-search routines in Listings 9.1 & 9.2 */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DISPLAY_LENGTH 40
|
||||
extern unsigned char * FindString(unsigned char *, unsigned int,
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ _sort: pop dx ;get return address (entry point)
|
|||
dec cx ;decrement count
|
||||
push cx ;save count
|
||||
push dx ;restore return address
|
||||
jg top ;if cx > 0
|
||||
jg top ;if cx > 0
|
||||
|
||||
ret
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
; Tested with TASM 2.
|
||||
|
||||
parms struc
|
||||
dw 2 dup (?) ;pushed BP & return address
|
||||
dw 2 dup (?) ;pushed BP & return address
|
||||
Dividend dw ? ;pointer to value to divide, stored in Intel
|
||||
; order, with lsb at lowest address, msb at
|
||||
; highest. Must be composed of an integral
|
||||
|
|
@ -113,7 +113,7 @@ _Divendp
|
|||
/* Sample use of Div function to perform division when the result
|
||||
doesn’t fit in 16 bits */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern unsigned int Div(unsigned int * Dividend,
|
||||
int DividendLength, unsigned int Divisor,
|
||||
|
|
@ -123,7 +123,7 @@ main() {
|
|||
unsigned long m, i = 0x20000001;
|
||||
unsigned int k, j = 0x10;
|
||||
|
||||
k = Div((unsigned int *)&i, sizeof(i), j, (unsigned int *)&m);
|
||||
k = Div((unsigned int *)&i, sizeof(i), j, (unsigned int *)&m);
|
||||
printf(“%lu / %u = %lu r %u\n”, i, j, m, k);
|
||||
}
|
||||
</PRE>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
<P>The floor really did look amazing. It was actually all white; the black lines had been grooves filled with dirt. We assured her that it looked terrific, it just wasn’t that obvious until you knew to look for it; anyone would tell you that it wasn’t the kind of thing that jumped out at you, but it really was great, no kidding. We had almost smoothed things over, when a friend walked in, looked around with a start, and said, “Hey! Did you guys put in a new floor?”</P>
|
||||
<P>As I said, sometimes everything you need to know is right in front of your nose. Which brings us to Boyer-Moore string searching.</P>
|
||||
<H3><A NAME="Heading3"></A>String Searching Refresher</H3>
|
||||
<P>I’ve discussed string searching earlier in this book, in Chapters 5 and 9. You may want to refer back to these chapters for some background on string searching in general. I’m also going to use some of the code from that chapter as part of this chapter’s test suite. For further information, you may want to refer to the discussion of string searching in the excellent <I>Algorithms in C,</I> by Robert Sedgewick (Addison-Wesley), which served as the primary reference for this chapter. (If you look at Sedgewick, be aware that in the Boyer-Moore listing on page 288, there is a mistake: “j > 0” in the <B>for</B> loop should be “j >= 0,” unless I’m missing something.)</P>
|
||||
<P>I’ve discussed string searching earlier in this book, in Chapters 5 and 9. You may want to refer back to these chapters for some background on string searching in general. I’m also going to use some of the code from that chapter as part of this chapter’s test suite. For further information, you may want to refer to the discussion of string searching in the excellent <I>Algorithms in C,</I> by Robert Sedgewick (Addison-Wesley), which served as the primary reference for this chapter. (If you look at Sedgewick, be aware that in the Boyer-Moore listing on page 288, there is a mistake: “j > 0” in the <B>for</B> loop should be “j >= 0,” unless I’m missing something.)</P>
|
||||
<P>String searching is the simple matter of finding the first occurrence of a particular sequence of bytes (the pattern) within another sequence of bytes (the buffer). The obvious, brute-force approach is to try every possible match location, starting at the beginning of the buffer and advancing one position after each mismatch, until either a match is found or the buffer is exhausted. There’s even a nifty string instruction, <B>REPZ CMPS,</B> that’s perfect for comparing the pattern to the contents of the buffer at each location. What could be simpler?</P>
|
||||
<P>We have some important information that we’re not yet using, though. Typically, the buffer will contain a wide variety of bytes. Let’s assume that the buffer contains text, in which case there will be dozens of different characters; and although the distribution of characters won’t usually be even, neither will any one character constitute half the buffer, or anything close. A reasonable conclusion is that the first character of the pattern will rarely match the first character of the buffer location currently being checked. This allows us to use the speedy <B>REPNZ SCASB</B> to whiz through the buffer, eliminating most potential match locations with single repetitions of <B>SCASB.</B> Only when that first character does (infrequently) match must we drop back to the slower <B>REPZ CMPS</B> approach.</P>
|
||||
<P>It’s important to understand that we’re assuming that the buffer is typical text. That’s what I meant at the outset, when I said that the information you need may be under your nose.</P>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
<TD VALIGN="TOP" ALIGN="LEFT">(16K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(16K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(16K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(<1K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(<1K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(16K)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">(16K)
|
||||
<TR>
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
<TD VALIGN="TOP" ALIGN="LEFT">4.0
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">2.0
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><=255 pattern length + sentinelBoyer-Moore in ASM(Listing 14.4)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><=255 pattern length + sentinelBoyer-Moore in ASM(Listing 14.4)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">8.1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">5.2
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">4.6
|
||||
|
|
|
|||
20
14-04.html
20
14-04.html
|
|
@ -46,7 +46,7 @@
|
|||
no match is found.
|
||||
Tested with Borland C++ in C mode and the small model. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned char * FindString(unsigned char * BufferPtr,
|
||||
unsigned int BufferLength, unsigned char * PatternPtr,
|
||||
|
|
@ -57,7 +57,7 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
int i;
|
||||
|
||||
/* Reject if the buffer is too small */
|
||||
if (BufferLength < PatternLength) return(NULL);
|
||||
if (BufferLength < PatternLength) return(NULL);
|
||||
|
||||
/* Return an instant match if the pattern is 0-length */
|
||||
if (PatternLength == 0) return(BufferPtr);
|
||||
|
|
@ -66,7 +66,7 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
mismatches for every possible byte value */
|
||||
/* Initialize all skips to the pattern length; this is the skip
|
||||
distance for bytes that don’t appear in the pattern */
|
||||
for (i = 0; i < 256; i++) SkipTable[i] = PatternLength;
|
||||
for (i = 0; i < 256; i++) SkipTable[i] = PatternLength;
|
||||
/*Set the skip values for the bytes that do appear in the pattern
|
||||
to the distance from the byte location to the end of the
|
||||
pattern. When there are multiple instances of the same byte,
|
||||
|
|
@ -75,7 +75,7 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
if we get that value for a mismatch, we know for sure that the
|
||||
right end of the pattern has already passed the mismatch
|
||||
location, so this is not a relevant byte for skipping purposes */
|
||||
for (i = 0; i < (PatternLength - 1); i++)
|
||||
for (i = 0; i < (PatternLength - 1); i++)
|
||||
SkipTable[PatternPtr[i]] = PatternLength - i - 1;
|
||||
|
||||
/* Point to rightmost byte of the pattern */
|
||||
|
|
@ -110,7 +110,7 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
just advance by 1 to the next potential match; otherwise,
|
||||
skip ahead from the mismatch location by the skip distance
|
||||
for the mismatch character */
|
||||
if (SkipTable[*WorkingBufferPtr] <= DistanceMatched)
|
||||
if (SkipTable[*WorkingBufferPtr] <= DistanceMatched)
|
||||
Skip = 1; /* skip doesn’t do any good, advance by 1 */
|
||||
else
|
||||
/* Use skip value, accounting for distance covered by the
|
||||
|
|
@ -118,7 +118,7 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
Skip = SkipTable[*WorkingBufferPtr] - DistanceMatched;
|
||||
/* If skipping ahead would exhaust the buffer, we’re done
|
||||
without a match */
|
||||
if (Skip >= BufferLength) return(NULL);
|
||||
if (Skip >= BufferLength) return(NULL);
|
||||
/* Skip ahead and perform the next comparison */
|
||||
BufferLength -= Skip;
|
||||
BufferPtr += Skip;
|
||||
|
|
@ -129,13 +129,13 @@ unsigned char * FindString(unsigned char * BufferPtr,
|
|||
<P><B>LISTING 14.2 L14-2.C</B></P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Program to exercise buffer-search routines in Listings 14.1 & 14.3.
|
||||
/* Program to exercise buffer-search routines in Listings 14.1 & 14.3.
|
||||
(Must be modified to put copy of pattern as sentinel at end of the
|
||||
search buffer in order to be used with Listing 14.4.) */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define DISPLAY_LENGTH 40
|
||||
#define BUFFER_SIZE 0x8000
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
; unsigned int PatternLength);
|
||||
|
||||
parms struc
|
||||
dw 2 dup(?) ;pushed BP & return address
|
||||
dw 2 dup(?) ;pushed BP & return address
|
||||
BufferPtr dw ? ;pointer to buffer to be searched
|
||||
BufferLength dw ? ;# of bytes in buffer to be searched
|
||||
PatternPtr dw ? ;pointer to pattern for which to search
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@
|
|||
; unsigned int PatternLength);
|
||||
|
||||
parms struc
|
||||
dw 2 dup(?) ;pushed BP & return address
|
||||
dw 2 dup(?) ;pushed BP & return address
|
||||
BufferPtr dw ? ;pointer to buffer to be searched
|
||||
BufferLength dw ? ;# of bytes in buffer to be searched
|
||||
; (not used, actually)
|
||||
PatternPtr dw ? ;pointer to pattern for which to search
|
||||
; (pattern *MUST* exist in the buffer)
|
||||
PatternLength dw ? ;length of pattern for which to search (must
|
||||
; be <= 255)
|
||||
; be <= 255)
|
||||
parms ends
|
||||
|
||||
.model small
|
||||
|
|
|
|||
22
15-02.html
22
15-02.html
|
|
@ -48,8 +48,8 @@
|
|||
#include “llist.h”
|
||||
struct LinkNode *DeleteNodeAfter(struct LinkNode *NodeToDeleteAfter)
|
||||
{
|
||||
NodeToDeleteAfter->NextNode =
|
||||
NodeToDeleteAfter->NextNode->NextNode;
|
||||
NodeToDeleteAfter->NextNode =
|
||||
NodeToDeleteAfter->NextNode->NextNode;
|
||||
return(NodeToDeleteAfter);
|
||||
}
|
||||
</PRE>
|
||||
|
|
@ -88,10 +88,10 @@ struct LinkNode *DeleteNodeAfter(struct LinkNode **HeadOfListPtr,
|
|||
/* Handle specially if the node to delete after is actually the
|
||||
head of the list (delete the first element in the list) */
|
||||
if (NodeToDeleteAfter == (struct LinkNode *)HeadOfListPtr) {
|
||||
*HeadOfListPtr = (*HeadOfListPtr)->NextNode;
|
||||
*HeadOfListPtr = (*HeadOfListPtr)->NextNode;
|
||||
} else {
|
||||
NodeToDeleteAfter->NextNode =
|
||||
NodeToDeleteAfter->NextNode->NextNode;
|
||||
NodeToDeleteAfter->NextNode =
|
||||
NodeToDeleteAfter->NextNode->NextNode;
|
||||
}
|
||||
return(NodeToDeleteAfter);
|
||||
}
|
||||
|
|
@ -118,22 +118,22 @@ struct LinkNode *DeleteNodeAfter(struct LinkNode **HeadOfListPtr,
|
|||
preceding that node (to facilitate insertion and deletion), or a
|
||||
NULL pointer if no such value was found. Assumes the list is
|
||||
terminated with a tail node pointing to itself as the next node. */
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include “llist.h”
|
||||
struct LinkNode *FindNodeBeforeValueNotLess(
|
||||
struct LinkNode *HeadOfListNode, int SearchValue)
|
||||
{
|
||||
struct LinkNode *NodePtr = HeadOfListNode;
|
||||
|
||||
while ( (NodePtr->NextNode->NextNode != NodePtr->NextNode) &&
|
||||
(NodePtr->NextNode->Value < SearchValue) )
|
||||
NodePtr = NodePtr->NextNode;
|
||||
while ( (NodePtr->NextNode->NextNode != NodePtr->NextNode) &&
|
||||
(NodePtr->NextNode->Value < SearchValue) )
|
||||
NodePtr = NodePtr->NextNode;
|
||||
|
||||
if (NodePtr->NextNode->NextNode == NodePtr->NextNode)
|
||||
if (NodePtr->NextNode->NextNode == NodePtr->NextNode)
|
||||
return(NULL); /* we found the sentinel; failed search */
|
||||
else
|
||||
return(NodePtr); /* success; return pointer to node preceding
|
||||
node that was >= */
|
||||
node that was >= */
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
40
15-03.html
40
15-03.html
|
|
@ -47,19 +47,19 @@
|
|||
found. Assumes the list is terminated with a sentinel tail node
|
||||
containing the largest possible Value field setting and pointing
|
||||
to itself as the next node. */
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include “llist.h”
|
||||
struct LinkNode *FindNodeBeforeValueNotLess(
|
||||
struct LinkNode *HeadOfListNode, int SearchValue)
|
||||
{
|
||||
struct LinkNode *NodePtr = HeadOfListNode;
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
if (NodePtr->NextNode->NextNode == NodePtr->NextNode)
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
if (NodePtr->NextNode->NextNode == NodePtr->NextNode)
|
||||
return(NULL); /* we found the sentinel; failed search */
|
||||
else
|
||||
return(NodePtr); /* success; return pointer to node preceding
|
||||
node that was >= */
|
||||
node that was >= */
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
@ -83,9 +83,9 @@ struct LinkNode *FindNodeBeforeValueNotLess(
|
|||
is,it has a dummy node as both the head and the tail of the list.
|
||||
The dummy node is a sentinel, containing the largest possible
|
||||
Value field setting. Tested with Borland C++ in C mode. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include “llist.h”
|
||||
/* Initializes an empty linked list of LinkNode structures,
|
||||
consisting of a single head/tail/sentinel node, and returns a
|
||||
|
|
@ -96,9 +96,9 @@ struct LinkNode *InitLinkedList()
|
|||
|
||||
if ((Sentinel = malloc(sizeof(struct LinkNode))) == NULL)
|
||||
return(NULL);
|
||||
Sentinel->NextNode = Sentinel;
|
||||
Sentinel->Value = SENTINEL;
|
||||
strcpy(Sentinel->Text, “*** sentinel ***”);
|
||||
Sentinel->NextNode = Sentinel;
|
||||
Sentinel->Value = SENTINEL;
|
||||
strcpy(Sentinel->Text, “*** sentinel ***”);
|
||||
return(Sentinel);
|
||||
}
|
||||
|
||||
|
|
@ -113,12 +113,12 @@ int SearchValue)
|
|||
{
|
||||
struct LinkNode *NodePtr = HeadOfListNode;
|
||||
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
if (NodePtr->NextNode->Value == SearchValue) {
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
if (NodePtr->NextNode->Value == SearchValue) {
|
||||
/* Found the search value; success unless we found the
|
||||
sentinel (can happen only if SearchValue == SENTINEL) */
|
||||
if (NodePtr->NextNode == HeadOfListNode) {
|
||||
if (NodePtr->NextNode == HeadOfListNode) {
|
||||
return(NULL); /* failure; we found the sentinel */
|
||||
} else {
|
||||
return(NodePtr); /* success; return pointer to node
|
||||
|
|
@ -136,11 +136,11 @@ struct LinkNode *InsertNodeSorted(struct LinkNode *HeadOfListNode,
|
|||
struct LinkNode *NodeToInsert)
|
||||
{
|
||||
struct LinkNode *NodePtr = HeadOfListNode;
|
||||
int SearchValue = NodeToInsert->Value;
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
NodeToInsert->NextNode = NodePtr->NextNode;
|
||||
NodePtr->NextNode = NodeToInsert;
|
||||
int SearchValue = NodeToInsert->Value;
|
||||
while (NodePtr->NextNode->Value < SearchValue)
|
||||
NodePtr = NodePtr->NextNode;
|
||||
NodeToInsert->NextNode = NodePtr->NextNode;
|
||||
NodePtr->NextNode = NodeToInsert;
|
||||
return(NodePtr);
|
||||
}
|
||||
</PRE>
|
||||
|
|
|
|||
36
15-04.html
36
15-04.html
|
|
@ -63,7 +63,7 @@ LinkNode ends
|
|||
; struct LinkNode *InsertNodeSorted(struct LinkNode *HeadOfListNode,
|
||||
; struct LinkNode *NodeToInsert)
|
||||
parms struc
|
||||
dw 2 dup (?) ;pushed return address & BP
|
||||
dw 2 dup (?) ;pushed return address & BP
|
||||
HeadOfListNode dw ? ;pointer to head node of list
|
||||
NodeToInsert dw ? ;pointer to node to insert
|
||||
parms ends
|
||||
|
|
@ -104,11 +104,11 @@ _InsertNodeSorted endp
|
|||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Sample linked list program. Tested with Borland C++. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include “llist.h”
|
||||
|
||||
void main()
|
||||
|
|
@ -121,7 +121,7 @@ void main()
|
|||
exit(1);
|
||||
}
|
||||
while (!Done) {
|
||||
printf(“\nA=add; D=delete; F=find; L=list all; Q=quit\n>”);
|
||||
printf(“\nA=add; D=delete; F=find; L=list all; Q=quit\n>”);
|
||||
Char = toupper(getche());
|
||||
printf(“\n”);
|
||||
switch (Char) {
|
||||
|
|
@ -132,24 +132,24 @@ void main()
|
|||
exit(1);
|
||||
}
|
||||
printf(“Node value: ”);
|
||||
scanf(“%d”, &TempPtr->Value);
|
||||
if ((FindNodeBeforeValue(ListPtr,TempPtr->Value))!=NULL)
|
||||
scanf(“%d”, &TempPtr->Value);
|
||||
if ((FindNodeBeforeValue(ListPtr,TempPtr->Value))!=NULL)
|
||||
{ printf(“*** value already in list; try again ***\n”);
|
||||
free(TempPtr);
|
||||
} else {printf(“Node text: ”);
|
||||
TempBuffer[0] = MAX_TEXT_LENGTH;
|
||||
cgets(TempBuffer);
|
||||
strcpy(TempPtr->Text, &TempBuffer[2]);
|
||||
strcpy(TempPtr->Text, &TempBuffer[2]);
|
||||
InsertNodeSorted(ListPtr, TempPtr);
|
||||
printf(“\n”);
|
||||
}
|
||||
break;
|
||||
case 'D': /* delete a node */
|
||||
printf(“Value field of node to delete: ”);
|
||||
scanf(“%d”, &TempValue);
|
||||
scanf(“%d”, &TempValue);
|
||||
if ((TempPtr = FindNodeBeforeValue(ListPtr, TempValue))
|
||||
!= NULL) {
|
||||
TempPtr2 = TempPtr->NextNode; /* -> node to delete */
|
||||
TempPtr2 = TempPtr->NextNode; /* -> node to delete */
|
||||
DeleteNodeAfter(TempPtr); /* delete it */
|
||||
free(TempPtr2); /* free its memory */
|
||||
} else {
|
||||
|
|
@ -157,22 +157,22 @@ void main()
|
|||
break;
|
||||
case 'F': /* find a node */
|
||||
printf(“Value field of node to find: ”);
|
||||
scanf(“%d”, &TempValue);
|
||||
scanf(“%d”, &TempValue);
|
||||
if ((TempPtr = FindNodeBeforeValue(ListPtr, TempValue))
|
||||
!= NULL)
|
||||
printf(“Value: %d\nText: %s\n”,
|
||||
TempPtr->NextNode->Value, TempPtr->NextNode->Text);
|
||||
TempPtr->NextNode->Value, TempPtr->NextNode->Text);
|
||||
else
|
||||
printf(“*** no such value field in list ***\n”);
|
||||
break;
|
||||
case 'L': /* list all nodes */
|
||||
TempPtr = ListPtr->NextNode; /* point to first node */
|
||||
TempPtr = ListPtr->NextNode; /* point to first node */
|
||||
if (TempPtr == ListPtr) { /* empty if at sentinel */
|
||||
printf(“*** List is empty ***\n”);
|
||||
} else {
|
||||
do {printf(“Value: %d\n Text: %s\n”, TempPtr->Value,
|
||||
TempPtr->Text);
|
||||
TempPtr = TempPtr->NextNode;
|
||||
do {printf(“Value: %d\n Text: %s\n”, TempPtr->Value,
|
||||
TempPtr->Text);
|
||||
TempPtr = TempPtr->NextNode;
|
||||
} while (TempPtr != ListPtr);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
28
16-01.html
28
16-01.html
|
|
@ -67,10 +67,10 @@
|
|||
<TD ALIGN="LEFT" VALIGN="TOP">16.1 (C)
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">4.6 seconds
|
||||
<TR>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">16.2 & 16.3 (C+ASM)
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">16.2 & 16.3 (C+ASM)
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">2.4 seconds
|
||||
<TR>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">16.2 & 16.4 (C+ASM w/lookup)
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">16.2 & 16.4 (C+ASM w/lookup)
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">1.6 seconds
|
||||
<TR>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP" COLSPAN="2"><SMALL>These are the times taken to search a file containing 104,448 words, timed from a RAM disk on a 20 MHz 386.</SMALL>
|
||||
|
|
@ -85,11 +85,11 @@
|
|||
/* Word-counting program. Tested with Borland C++ in C
|
||||
compilation mode and the small model. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
|
||||
#define <I>B</I> UFFER_SIZE 0x8000 /* largest chunk of file worked
|
||||
with at any one time */
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
char *Buffer, CharFlag = 0, PredCharFlag, *BufferPtr, Ch;
|
||||
|
||||
if (argc != 2) {
|
||||
printf(“usage: wc <filename>\n”);
|
||||
printf(“usage: wc <filename>\n”);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
}
|
||||
|
||||
/* Process the file in chunks */
|
||||
while (FileSize > 0) {
|
||||
while (FileSize > 0) {
|
||||
/* Get the next chunk */
|
||||
FileSize -= (BlockSize = min(FileSize, BUFFER_SIZE));
|
||||
if (read(Handle, Buffer, BlockSize) == -1) {
|
||||
|
|
@ -134,14 +134,14 @@
|
|||
BufferPtr = Buffer;
|
||||
do {
|
||||
PredCharFlag = CharFlag;
|
||||
Ch = *BufferPtr++ & 0x7F; /* strip high bit, which some
|
||||
Ch = *BufferPtr++ & 0x7F; /* strip high bit, which some
|
||||
word processors set as an
|
||||
internal flag */
|
||||
CharFlag = ((Ch >= ‘a’) && (Ch <= ‘z’)) ||
|
||||
((Ch >= ‘A’) && (Ch <= ‘Z’)) ||
|
||||
((Ch >= ‘0’) && (Ch <= ‘9’)) ||
|
||||
CharFlag = ((Ch >= ‘a’) && (Ch <= ‘z’)) ||
|
||||
((Ch >= ‘A’) && (Ch <= ‘Z’)) ||
|
||||
((Ch >= ‘0’) && (Ch <= ‘9’)) ||
|
||||
(Ch == ‘\’’);
|
||||
if ((!CharFlag) && PredCharFlag) {
|
||||
if ((!CharFlag) && PredCharFlag) {
|
||||
WordCo <I>u</I> nt++;
|
||||
}
|
||||
} while (—BlockSize);
|
||||
|
|
|
|||
26
16-02.html
26
16-02.html
|
|
@ -42,13 +42,13 @@
|
|||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Word-counting program incorporating assembly language. Tested
|
||||
with Borland C<SMALL>++</SMALL> in C compilation mode & the small model. */
|
||||
with Borland C<SMALL>++</SMALL> in C compilation mode & the small model. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
|
||||
#define BUFFER_SIZE 0x8000 /* largest chunk of file worked
|
||||
with at any one time */
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
char *Buffer, CharFlag = 0;
|
||||
|
||||
if (argc != 2) {
|
||||
printf(“usage: wc <filename>\n”);
|
||||
printf(“usage: wc <filename>\n”);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -83,13 +83,13 @@
|
|||
}
|
||||
|
||||
CharFlag = 0;
|
||||
while (FileSize > 0) {
|
||||
while (FileSize > 0) {
|
||||
FileSize -= (BlockSize = min(FileSize, BUFFER_SIZE));
|
||||
if (read(Handle, Buffer, BlockSize) == -1) {
|
||||
printf(“Error reading file %s\n”, argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
ScanBuffer(Buffer, BlockSize, &CharFlag, &WordCount);
|
||||
ScanBuffer(Buffer, BlockSize, &CharFlag, &WordCount);
|
||||
}
|
||||
|
||||
/* Catch the last word, if any */
|
||||
|
|
@ -106,14 +106,14 @@
|
|||
<PRE>
|
||||
; Assembly subroutine for Listing 16.2. Scans through Buffer, of
|
||||
; length BufferLength, counting words and updating WordCount as
|
||||
; appropriate. BufferLength must be > 0. *CharFlag and *WordCount
|
||||
; appropriate. BufferLength must be > 0. *CharFlag and *WordCount
|
||||
; should equal 0 on the first call. Tested with TASM.
|
||||
; C near-callable as:
|
||||
; void ScanBuffer(char *Buffer, unsigned int BufferLength,
|
||||
; char *CharFlag, unsigned long *WordCount);
|
||||
|
||||
parms struc
|
||||
dw 2 dup(?) ;pushed return address & BP
|
||||
dw 2 dup(?) ;pushed return address & BP
|
||||
Buffer dw ? ;buffer to scan
|
||||
BufferLength dw ? ;length of buffer to scan
|
||||
CharFlag dw ? ;pointer to flag for state of last
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
mov di,[bp+BufferLength];get # of bytes to scan
|
||||
ScanLoop:
|
||||
mov bh,bl ;PredCharFlag = CharFlag;
|
||||
lodsb ;Ch = *BufferPtr++ & 0x7F;
|
||||
lodsb ;Ch = *BufferPtr++ & 0x7F;
|
||||
and al,7fh ;strip high bit for word processors
|
||||
; that set it as an internal flag
|
||||
mov bl,1 ;assume this is a char; CharFlag = 1;
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
jz IsAChar
|
||||
sub bl,bl ;not a char; CharFlag = 0;
|
||||
and bh,bh
|
||||
jz ScanLoopBottom ;if ((!CharFlag) && PredCharFlag) {
|
||||
jz ScanLoopBottom ;if ((!CharFlag) && PredCharFlag) {
|
||||
add cx,1 ; (WordCount)++;
|
||||
adc dx,0 ;}
|
||||
IsAChar:
|
||||
|
|
|
|||
|
|
@ -42,14 +42,14 @@
|
|||
; Assembly subroutine for Listing 16.2. Scans through Buffer, of
|
||||
; length BufferLength, counting words and updating WordCount as
|
||||
; appropriate, using a lookup table-based approach. BufferLength
|
||||
; must be > 0. *CharFlag and *WordCount should equal 0 on the
|
||||
; must be > 0. *CharFlag and *WordCount should equal 0 on the
|
||||
; first call. Tested with TASM.
|
||||
; C near-callable as:
|
||||
; void ScanBuffer(char *Buffer, unsigned int BufferLength,
|
||||
; char *CharFlag, unsigned long *WordCount);
|
||||
|
||||
parms struc
|
||||
dw 2 dup(?) ;pushed return address & BP
|
||||
dw 2 dup(?) ;pushed return address & BP
|
||||
Buffer dw ? ;buffer to scan
|
||||
BufferLength dw ? ;length of buffer to scan
|
||||
CharFlag dw ? ;pointer to flag for state of last
|
||||
|
|
|
|||
|
|
@ -139,14 +139,14 @@ jumping.
|
|||
.code
|
||||
|
||||
Test1 macro x,y ;9 or 10 bytes
|
||||
Addr&x: mov di,[bp+y] ;3 or 4 bytes
|
||||
Addr&x: mov di,[bp+y] ;3 or 4 bytes
|
||||
adc di,di
|
||||
or ax,si
|
||||
add al,[di]
|
||||
endm
|
||||
|
||||
Test2 macro x,y ;7 or 8 bytes
|
||||
Addr&x: mov di,[bp+y] ;3 or 4 bytes
|
||||
Addr&x: mov di,[bp+y] ;3 or 4 bytes
|
||||
adc di,di
|
||||
add ah,[di]
|
||||
endm
|
||||
|
|
@ -264,7 +264,7 @@ jumping.
|
|||
|
||||
.data
|
||||
Address macro X
|
||||
dw Addr&X
|
||||
dw Addr&X
|
||||
endm
|
||||
|
||||
LoopEntry label word
|
||||
|
|
|
|||
10
16-08.html
10
16-08.html
|
|
@ -67,10 +67,10 @@
|
|||
<PRE>
|
||||
// MAKETAB.C — Build QSCAN3.INC for QSCAN3.ASM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define ChType( c ) (((c) & 0x7f) == ‘\’’ || isalnum((c) & 0x7f))
|
||||
#define ChType( c ) (((c) & 0x7f) == ‘\’’ || isalnum((c) & 0x7f))
|
||||
|
||||
int NoCarry[ 4 ] = { 0, 0x80, 1, 0x80 };
|
||||
int Carry[ 4 ] = { 1, 0x81, 1, 0x80 };
|
||||
|
|
@ -82,9 +82,9 @@
|
|||
|
||||
printf( “Building table. Please wait...” );
|
||||
|
||||
for( ahChar = 0; ahChar < 128; ahChar++ )
|
||||
for( ahChar = 0; ahChar < 128; ahChar++ )
|
||||
{
|
||||
for( alChar = 0; alChar < 256; alChar++ )
|
||||
for( alChar = 0; alChar < 256; alChar++ )
|
||||
{
|
||||
i = ChType( alChar ) * 2 + ChType( ahChar );
|
||||
|
||||
|
|
|
|||
80
17-02.html
80
17-02.html
|
|
@ -42,14 +42,14 @@
|
|||
/* C++ Game of Life implementation for any mode for which mode set
|
||||
and draw pixel functions can be provided.
|
||||
Tested with Borland C++ in the small model. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <mem.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <mem.h>
|
||||
|
||||
#define ON_COLOR 15 // on-cell pixel color
|
||||
#define OFF_COLOR 0 // off-cell pixel color
|
||||
|
|
@ -68,11 +68,11 @@ private:
|
|||
public:
|
||||
cellmap(unsigned int h, unsigned int v);
|
||||
~cellmap(void);
|
||||
void copy_cells(cellmap &sourcemap);
|
||||
void copy_cells(cellmap &sourcemap);
|
||||
void set_cell(unsigned int x, unsigned int y);
|
||||
void clear_cell(unsigned int x, unsigned int y);
|
||||
int cell_state(int x, int y);
|
||||
void next_generation(cellmap& dest_map);
|
||||
void next_generation(cellmap& dest_map);
|
||||
};
|
||||
|
||||
extern void enter_display_mode(void);
|
||||
|
|
@ -86,7 +86,7 @@ extern void show_text(int x, int y, char *text);
|
|||
display at right. */
|
||||
unsigned int cellmap_width = 96;
|
||||
unsigned int cellmap_height = 96;
|
||||
/* Width & height in pixels of each cell as displayed on screen. */
|
||||
/* Width & height in pixels of each cell as displayed on screen. */
|
||||
unsigned int magnifier = 2;
|
||||
|
||||
void main()
|
||||
|
|
@ -100,12 +100,12 @@ void main()
|
|||
cellmap next_map(cellmap_height, cellmap_width);
|
||||
|
||||
// Get the seed; seed randomly if 0 entered
|
||||
cout << “Seed (0 for random seed): ”;
|
||||
cin >> seed;
|
||||
cout << “Seed (0 for random seed): ”;
|
||||
cin >> seed;
|
||||
if (seed == 0) seed = (unsigned) time(NULL);
|
||||
|
||||
// Randomly initialize the initial cell map
|
||||
cout << “Initializing...”;
|
||||
cout << “Initializing...”;
|
||||
srand(seed);
|
||||
init_length = (cellmap_height * cellmap_width) / 2;
|
||||
do {
|
||||
|
|
@ -120,7 +120,7 @@ void main()
|
|||
// Keep recalculating and redisplaying generations until a key
|
||||
// is pressed
|
||||
show_text(0, MSG_LINE, “Generation: ”);
|
||||
start_bios_time = _bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
start_bios_time = _bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
do {
|
||||
generation++;
|
||||
sprintf(gen_text, “%10lu”, generation);
|
||||
|
|
@ -132,15 +132,15 @@ void main()
|
|||
#if LIMIT_18_HZ
|
||||
// Limit to a maximum of 18.2 frames per second,for visibility
|
||||
do {
|
||||
_bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
_bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
} while (start_bios_time == bios_time);
|
||||
start_bios_time = bios_time;
|
||||
#endif
|
||||
} while (!kbhit());
|
||||
getch(); // clear keypress
|
||||
exit_display_mode();
|
||||
cout << “Total generations: ” << generation << “\nSeed: ” <<
|
||||
seed << “\n”;
|
||||
cout << “Total generations: ” << generation << “\nSeed: ” <<
|
||||
seed << “\n”;
|
||||
}
|
||||
|
||||
/* cellmap constructor. */
|
||||
|
|
@ -162,7 +162,7 @@ cellmap::~cellmap(void)
|
|||
|
||||
/* Copies one cellmap’s cells to another cellmap. Both cellmaps are
|
||||
assumed to be the same size. */
|
||||
void cellmap::copy_cells(cellmap &sourcemap)
|
||||
void cellmap::copy_cells(cellmap &sourcemap)
|
||||
{
|
||||
memcpy(cells, sourcemap.cells, length_in_bytes);
|
||||
}
|
||||
|
|
@ -173,7 +173,7 @@ void cellmap::set_cell(unsigned int x, unsigned int y)
|
|||
unsigned char *cell_ptr =
|
||||
cells + (y * width_in_bytes) + (x / 8);
|
||||
|
||||
*(cell_ptr) |= 0x80 >> (x & 0x07);
|
||||
*(cell_ptr) |= 0x80 >> (x & 0x07);
|
||||
}
|
||||
|
||||
/* Turns cell off. */
|
||||
|
|
@ -182,7 +182,7 @@ void cellmap::clear_cell(unsigned int x, unsigned int y)
|
|||
unsigned char *cell_ptr =
|
||||
cells + (y * width_in_bytes) + (x / 8);
|
||||
|
||||
*(cell_ptr) &= ~(0x80 >> (x & 0x07));
|
||||
*(cell_ptr) &= ~(0x80 >> (x & 0x07));
|
||||
}
|
||||
|
||||
/* Returns cell state (1=on or 0=off), optionally wrapping at the
|
||||
|
|
@ -192,26 +192,26 @@ int cellmap::cell_state(int x, int y)
|
|||
unsigned char *cell_ptr;
|
||||
|
||||
#if WRAP_EDGES
|
||||
while (x < 0) x += width; // wrap, if necessary
|
||||
while (x >= width) x -= width;
|
||||
while (y < 0) y += height;
|
||||
while (y >= height) y -= height;
|
||||
while (x < 0) x += width; // wrap, if necessary
|
||||
while (x >= width) x -= width;
|
||||
while (y < 0) y += height;
|
||||
while (y >= height) y -= height;
|
||||
#else
|
||||
if ((x < 0) || (x >= width) || (y < 0) || (y >= height))
|
||||
if ((x < 0) || (x >= width) || (y < 0) || (y >= height))
|
||||
return 0; // return 0 for off edges if no wrapping
|
||||
#endif
|
||||
cell_ptr = cells + (y * width_in_bytes) + (x / 8);
|
||||
return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
|
||||
return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Calculates the next generation of a cellmap and stores it in
|
||||
next_map. */
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
{
|
||||
unsigned int x, y, neighbor_count;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
// Figure out how many neighbors this cell has
|
||||
neighbor_count = cell_state(x-1, y-1) + cell_state(x, y-1) +
|
||||
cell_state(x+1, y-1) + cell_state(x-1, y) +
|
||||
|
|
@ -219,7 +219,7 @@ void cellmap::next_generation(cellmap& next_map)
|
|||
cell_state(x, y+1) + cell_state(x+1, y+1);
|
||||
if (cell_state(x, y) == 1) {
|
||||
// The cell is on; does it stay on?
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
next_map.clear_cell(x, y); // turn it off
|
||||
draw_pixel(x, y, OFF_COLOR);
|
||||
}
|
||||
|
|
@ -240,17 +240,17 @@ void cellmap::next_generation(cellmap& next_map)
|
|||
<PRE>
|
||||
/* VGA mode 13h functions for Game of Life.
|
||||
Tested with Borland C++. */
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
|
||||
#define TEXT_X_OFFSET 27
|
||||
#define SCREEN_WIDTH_IN_BYTES 320
|
||||
|
||||
/* Width & height in pixels of each cell. */
|
||||
/* Width & height in pixels of each cell. */
|
||||
extern unsigned int magnifier;
|
||||
|
||||
/* Mode 13h draw pixel function. Pixels are of width & height
|
||||
/* Mode 13h draw pixel function. Pixels are of width & height
|
||||
specified by magnifier. */
|
||||
void draw_pixel(unsigned int x, unsigned int y, unsigned int color)
|
||||
{
|
||||
|
|
@ -261,8 +261,8 @@ void draw_pixel(unsigned int x, unsigned int y, unsigned int color)
|
|||
FP_SEG(screen_ptr) = SCREEN_SEGMENT;
|
||||
FP_OFF(screen_ptr) =
|
||||
y * magnifier * SCREEN_WIDTH_IN_BYTES + x * magnifier;
|
||||
for (i=0; i<magnifier; i++) {
|
||||
for (j=0; j<magnifier; j++) {
|
||||
for (i=0; i<magnifier; i++) {
|
||||
for (j=0; j<magnifier; j++) {
|
||||
*(screen_ptr+j) = color;
|
||||
}
|
||||
screen_ptr += SCREEN_WIDTH_IN_BYTES;
|
||||
|
|
@ -275,7 +275,7 @@ void enter_display_mode()
|
|||
union REGS regset;
|
||||
|
||||
regset.x.ax = 0x0013;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
/* Text mode mode-set function. */
|
||||
|
|
@ -284,7 +284,7 @@ void exit_display_mode()
|
|||
union REGS regset;
|
||||
|
||||
regset.x.ax = 0x0003;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
/* Text display function. Offsets text to non-graphics area of
|
||||
|
|
|
|||
18
17-03.html
18
17-03.html
|
|
@ -75,19 +75,19 @@
|
|||
<TD VALIGN="TOP" ALIGN="LEFT">2
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><B>set_cell()</B>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><B>clear_cell()</B>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><B>copy_cells()</B>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TD VALIGN="TOP" ALIGN="LEFT"><1
|
||||
<TR>
|
||||
<TD COLSPAN="4"><HR>
|
||||
<TR>
|
||||
|
|
|
|||
44
17-04.html
44
17-04.html
|
|
@ -65,12 +65,12 @@ private:
|
|||
public:
|
||||
cellmap(unsigned int h, unsigned int v);
|
||||
~cellmap(void);
|
||||
void copy_cells(cellmap &sourcemap);
|
||||
void copy_cells(cellmap &sourcemap);
|
||||
void set_cell(unsigned int x, unsigned int y);
|
||||
void clear_cell(unsigned int x, unsigned int y);
|
||||
int cell_state(int x, int y);
|
||||
int count_neighbors(int x, int y);
|
||||
void next_generation(cellmap& dest_map);
|
||||
void next_generation(cellmap& dest_map);
|
||||
};
|
||||
|
||||
/* cellmap constructor. Pads around cell storage area with 1 extra
|
||||
|
|
@ -92,7 +92,7 @@ cellmap::cellmap(unsigned int h, unsigned int w)
|
|||
source first, so that the padding bytes off each edge have the
|
||||
same values as would be found by wrapping around to the opposite
|
||||
edge. Both cellmaps are assumed to be the same size. */
|
||||
void cellmap::copy_cells(cellmap &sourcemap)
|
||||
void cellmap::copy_cells(cellmap &sourcemap)
|
||||
{
|
||||
unsigned char *cell_ptr;
|
||||
int i;
|
||||
|
|
@ -100,7 +100,7 @@ void cellmap::copy_cells(cellmap &sourcemap)
|
|||
#if WRAP_EDGES
|
||||
// Copy left and right edges into padding bytes on right and left
|
||||
cell_ptr = sourcemap.cells + width_in_bytes;
|
||||
for (i=0; i<height; i++) {
|
||||
for (i=0; i<height; i++) {
|
||||
*cell_ptr = *(cell_ptr + width_in_bytes - 2);
|
||||
*(cell_ptr + width_in_bytes - 1) = *(cell_ptr + 1);
|
||||
cell_ptr += width_in_bytes;
|
||||
|
|
@ -122,7 +122,7 @@ void cellmap::set_cell(unsigned int x, unsigned int y)
|
|||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
*(cell_ptr) |= 0x80 >> (x & 0x07);
|
||||
*(cell_ptr) |= 0x80 >> (x & 0x07);
|
||||
}
|
||||
|
||||
/* Turns cell off. x and y are offset by 1 byte down and to the right,
|
||||
|
|
@ -132,7 +132,7 @@ void cellmap::clear_cell(unsigned int x, unsigned int y)
|
|||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
*(cell_ptr) &= ~(0x80 >> (x & 0x07));
|
||||
*(cell_ptr) &= ~(0x80 >> (x & 0x07));
|
||||
}
|
||||
|
||||
/* Returns cell state (1=on or 0=off). x and y are offset by 1 byte
|
||||
|
|
@ -144,7 +144,7 @@ int cellmap::cell_state(int x, int y)
|
|||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
|
||||
return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Counts the number of neighboring on-cells for specified cell. */
|
||||
|
|
@ -155,50 +155,50 @@ int cellmap::count_neighbors(int x, int y)
|
|||
|
||||
// Point to upper left neighbor
|
||||
cell_ptr = cells + ((y * width_in_bytes) + ((x + 7) / 8));
|
||||
mask = 0x80 >> ((x - 1) & 0x07);
|
||||
mask = 0x80 >> ((x - 1) & 0x07);
|
||||
// Count upper left neighbor
|
||||
neighbor_count = (*cell_ptr & mask) ? 1 : 0;
|
||||
neighbor_count = (*cell_ptr & mask) ? 1 : 0;
|
||||
// Count left neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower left neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
// Point to upper neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
}
|
||||
// Count upper neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count lower neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
// Point to upper right neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
}
|
||||
// Count upper right neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count right neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower right neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
return neighbor_count;
|
||||
}
|
||||
|
||||
/* Calculates the next generation of current_map and stores it in
|
||||
next_map. */
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
{
|
||||
unsigned int x, y, neighbor_count;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
neighbor_count = count_neighbors(x, y);
|
||||
if (cell_state(x, y) == 1) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
next_map.clear_cell(x, y); // turn it off
|
||||
draw_pixel(x, y, OFF_COLOR);
|
||||
}
|
||||
|
|
|
|||
36
17-05.html
36
17-05.html
|
|
@ -50,10 +50,10 @@
|
|||
|
||||
/* Calculates the next generation of current_map and stores it in
|
||||
next_map. */
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
void cellmap::next_generation(cellmap& next_map)
|
||||
{
|
||||
unsigned int x, y, neighbor_count;
|
||||
unsigned int width_in_bytesX2 = width_in_bytes << 1;
|
||||
unsigned int width_in_bytesX2 = width_in_bytes << 1;
|
||||
unsigned char *cell_ptr, *current_cell_ptr, mask, current_mask;
|
||||
unsigned char *base_cell_ptr, *row_cell_ptr, base_mask;
|
||||
unsigned char *dest_cell_ptr = next_map.cells;
|
||||
|
|
@ -61,24 +61,24 @@ void cellmap::next_generation(cellmap& next_map)
|
|||
// Process all cells in the current cellmap
|
||||
row_cell_ptr = cells; // point to upper left neighbor of
|
||||
// first cell in cell map
|
||||
for (y=0; y<height; y++) { // repeat for each row of cells
|
||||
for (y=0; y<height; y++) { // repeat for each row of cells
|
||||
// Cell pointer and cell bit mask for first cell in row
|
||||
base_cell_ptr = row_cell_ptr; // to access upper left neighbor
|
||||
base_mask = 0x01; // of first cell in row
|
||||
for (x=0; x<width; x++) { // repeat for each cell in row
|
||||
for (x=0; x<width; x++) { // repeat for each cell in row
|
||||
// First, count neighbors
|
||||
// Point to upper left neighbor of current cell
|
||||
cell_ptr = base_cell_ptr; // pointer and bit mask for
|
||||
mask = base_mask; // upper left neighbor
|
||||
// Count upper left neighbor
|
||||
neighbor_count = (*cell_ptr & mask) ? 1 : 0;
|
||||
neighbor_count = (*cell_ptr & mask) ? 1 : 0;
|
||||
// Count left neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower left neighbor
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
neighbor_count++;
|
||||
// Point to upper neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
}
|
||||
|
|
@ -86,25 +86,25 @@ neighbor_count++;
|
|||
current_cell_ptr = cell_ptr + width_in_bytes;
|
||||
current_mask = mask;
|
||||
// Count upper neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count lower neighbor
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
neighbor_count++;
|
||||
// Point to upper right neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
}
|
||||
// Count upper right neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count right neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower right neighbor
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
if ((*(cell_ptr + width_in_bytesX2) & mask))
|
||||
neighbor_count++;
|
||||
if (*current_cell_ptr & current_mask) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
*(dest_cell_ptr + (current_cell_ptr - cells)) &=
|
||||
if (*current_cell_ptr & current_mask) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
*(dest_cell_ptr + (current_cell_ptr - cells)) &=
|
||||
~current_mask; // turn off cell
|
||||
draw_pixel(x, y, OFF_COLOR);
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@ neighbor_count++;
|
|||
}
|
||||
}
|
||||
// Advance to the next cell on row
|
||||
if ((base_mask >>= 1) == 0) {
|
||||
if ((base_mask >>= 1) == 0) {
|
||||
base_mask = 0x80;
|
||||
base_cell_ptr++; // advance to the next cell byte
|
||||
}
|
||||
|
|
|
|||
48
17-07.html
48
17-07.html
|
|
@ -46,14 +46,14 @@
|
|||
in this implementation.
|
||||
Tested with Borland C++. To run, link with Listing 17.2
|
||||
in the large model. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <mem.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <dos.h>
|
||||
#include <bios.h>
|
||||
#include <mem.h>
|
||||
|
||||
#define ON_COLOR 15 // on-cell pixel color
|
||||
#define OFF_COLOR 0 // off-cell pixel color
|
||||
|
|
@ -91,7 +91,7 @@ extern void show_text(int x, int y, char *text);
|
|||
unsigned int cellmap_width = 96;
|
||||
unsigned int cellmap_height = 96;
|
||||
|
||||
/* Width & height in pixels of each cell. */
|
||||
/* Width & height in pixels of each cell. */
|
||||
unsigned int magnifier = 2;
|
||||
|
||||
/* Randomizing seed */
|
||||
|
|
@ -112,7 +112,7 @@ void main()
|
|||
// Keep recalculating and redisplaying generations until any key
|
||||
// is pressed
|
||||
show_text(0, MSG_LINE, “Generation: ”);
|
||||
start_bios_time = _bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
start_bios_time = _bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
do {
|
||||
generation++;
|
||||
sprintf(gen_text, “%10lu”, generation);
|
||||
|
|
@ -122,7 +122,7 @@ void main()
|
|||
#if LIMIT_18_HZ
|
||||
// Limit to a maximum of 18.2 frames per second, for visibility
|
||||
do {
|
||||
_bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
_bios_timeofday(_TIME_GETCLOCK, &bios_time);
|
||||
} while (start_bios_time == bios_time);
|
||||
start_bios_time = bios_time;
|
||||
#endif
|
||||
|
|
@ -130,8 +130,8 @@ void main()
|
|||
|
||||
getch(); // clear keypress
|
||||
exit_display_mode();
|
||||
cout << “Total generations: ” << generation << “\nSeed: ” <<
|
||||
seed << “\n”;
|
||||
cout << “Total generations: ” << generation << “\nSeed: ” <<
|
||||
seed << “\n”;
|
||||
}
|
||||
|
||||
/* cellmap constructor. */
|
||||
|
|
@ -221,7 +221,7 @@ void cellmap::clear_cell(unsigned int x, unsigned int y)
|
|||
else
|
||||
yobelow = w;
|
||||
|
||||
*(cell_ptr) &= ~0x01;
|
||||
*(cell_ptr) &= ~0x01;
|
||||
*(cell_ptr + yoabove + xoleft) -= 2;
|
||||
*(cell_ptr + yoabove ) -= 2;
|
||||
*(cell_ptr + yoabove + xoright) -= 2;
|
||||
|
|
@ -238,7 +238,7 @@ int cellmap::cell_state(int x, int y)
|
|||
unsigned char *cell_ptr;
|
||||
|
||||
cell_ptr = cells + (y * width) + x;
|
||||
return *cell_ptr & 0x01;
|
||||
return *cell_ptr & 0x01;
|
||||
}
|
||||
|
||||
/* Calculates and displays the next generation of current_map */
|
||||
|
|
@ -254,7 +254,7 @@ void cellmap::next_generation()
|
|||
|
||||
// Process all cells in the current cell map
|
||||
cell_ptr = temp_cells; // first cell in cell map
|
||||
for (y=0; y<h; y++) { // repeat for each row of cells
|
||||
for (y=0; y<h; y++) { // repeat for each row of cells
|
||||
// Process all cells in the current row of the cell map
|
||||
x = 0;
|
||||
do { // repeat for each cell in row
|
||||
|
|
@ -262,15 +262,15 @@ void cellmap::next_generation()
|
|||
// neighbors as possible
|
||||
while (*cell_ptr == 0) {
|
||||
cell_ptr++; // advance to the next cell
|
||||
if (++x >= w) goto RowDone;
|
||||
if (++x >= w) goto RowDone;
|
||||
}
|
||||
// Found a cell that’s either on or has on-neighbors,
|
||||
// so see if its state needs to be changed
|
||||
count = *cell_ptr >> 1; // # of neighboring on-cells
|
||||
if (*cell_ptr & 0x01) {
|
||||
count = *cell_ptr >> 1; // # of neighboring on-cells
|
||||
if (*cell_ptr & 0x01) {
|
||||
// Cell is on; turn it off if it doesn’t have
|
||||
// 2 or 3 neighbors
|
||||
if ((count != 2) && (count != 3)) {
|
||||
if ((count != 2) && (count != 3)) {
|
||||
clear_cell(x, y);
|
||||
draw_pixel(x, y, OFF_COLOR);
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ void cellmap::next_generation()
|
|||
}
|
||||
// Advance to the next cell
|
||||
cell_ptr++; // advance to the next cell byte
|
||||
} while (++x < w);
|
||||
} while (++x < w);
|
||||
RowDone:
|
||||
}
|
||||
}
|
||||
|
|
@ -294,14 +294,14 @@ void cellmap::init()
|
|||
unsigned int x, y, init_length;
|
||||
|
||||
// Get the seed; seed randomly if 0 entered
|
||||
cout << “Seed (0 for random seed): ”;
|
||||
cin >> seed;
|
||||
cout << “Seed (0 for random seed): ”;
|
||||
cin >> seed;
|
||||
if (seed == 0) seed = (unsigned) time(NULL);
|
||||
|
||||
// Randomly initialize the initial cell map to 50% on-pixels
|
||||
// (actually generally fewer, because some coordinates will be
|
||||
// randomly selected more than once)
|
||||
cout << “Initializing...”;
|
||||
cout << “Initializing...”;
|
||||
srand(seed);
|
||||
init_length = (height * width) / 2;
|
||||
do {
|
||||
|
|
|
|||
78
18-03.html
78
18-03.html
|
|
@ -146,43 +146,43 @@ void BuildMaps( void )
|
|||
do
|
||||
{
|
||||
// Current cell states
|
||||
C1 = (x & 0x0800) >> 11;
|
||||
C2 = (x & 0x0400) >> 10;
|
||||
C3 = (x & 0x0200) >> 9;
|
||||
C1 = (x & 0x0800) >> 11;
|
||||
C2 = (x & 0x0400) >> 10;
|
||||
C3 = (x & 0x0200) >> 9;
|
||||
|
||||
// Neighbor counts
|
||||
N1 = (x & 0x01C0) >> 6;
|
||||
N2 = (x & 0x0038) >> 3;
|
||||
N3 = (x & 0x0007);
|
||||
N1 = (x & 0x01C0) >> 6;
|
||||
N2 = (x & 0x0038) >> 3;
|
||||
N3 = (x & 0x0007);
|
||||
|
||||
y = x & 0x8FFF; // Preserve all but the next generation states
|
||||
y = x & 0x8FFF; // Preserve all but the next generation states
|
||||
|
||||
if( C1 && ((N1 + C2 == 2) || (N1 + C2 == 3)) )
|
||||
if( C1 && ((N1 + C2 == 2) || (N1 + C2 == 3)) )
|
||||
{
|
||||
y |= 0x4000;
|
||||
}
|
||||
|
||||
if( !C1 && (N1 + C2 == 3) )
|
||||
if( !C1 && (N1 + C2 == 3) )
|
||||
{
|
||||
y |= 0x4000;
|
||||
}
|
||||
|
||||
if( C2 && ((N2 + C1 + C3 == 2) || (N2 + C1 + C3 == 3)) )
|
||||
if( C2 && ((N2 + C1 + C3 == 2) || (N2 + C1 + C3 == 3)) )
|
||||
{
|
||||
y |= 0x2000;
|
||||
}
|
||||
|
||||
if( !C2 && (N2 + C1 + C3 == 3) )
|
||||
if( !C2 && (N2 + C1 + C3 == 3) )
|
||||
{
|
||||
y |= 0x2000;
|
||||
}
|
||||
|
||||
if( C3 && ((N3 + C2 == 2) || (N3 + C2 == 3)) )
|
||||
if( C3 && ((N3 + C2 == 2) || (N3 + C2 == 3)) )
|
||||
{
|
||||
y |= 0x1000;
|
||||
}
|
||||
|
||||
if( !C3 && (N3 + C2 == 3) )
|
||||
if( !C3 && (N3 + C2 == 3) )
|
||||
{
|
||||
y |= 0x1000;
|
||||
}
|
||||
|
|
@ -227,58 +227,58 @@ void FirstPass( void )
|
|||
printf( “mov bh,0\n” );
|
||||
printf( “add bx,ax\n” ); // bx = screen offset
|
||||
|
||||
if( ((New ^ Old) & 6) == 6 )
|
||||
if( ((New ^ Old) & 6) == 6 )
|
||||
{
|
||||
printf( “mov word ptr fs:[bx],0%02x%02xh\n”,
|
||||
(New & 2) ? 15 : 0,
|
||||
(New & 4) ? 15 : 0 );
|
||||
(New & 2) ? 15 : 0,
|
||||
(New & 4) ? 15 : 0 );
|
||||
|
||||
if( (New ^ Old) & 1 )
|
||||
if( (New ^ Old) & 1 )
|
||||
{
|
||||
printf( “mov byte ptr fs:[bx+2],%s\n”,
|
||||
(New & 1) ? “15” : “dl” );
|
||||
(New & 1) ? “15” : “dl” );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ((New ^ Old) & 3) == 3 )
|
||||
if( ((New ^ Old) & 3) == 3 )
|
||||
{
|
||||
printf( “mov word ptr fs:[bx+1],0%02x%02xh\n”,
|
||||
(New & 1) ? 15 : 0,
|
||||
(New & 2) ? 15 : 0 );
|
||||
(New & 1) ? 15 : 0,
|
||||
(New & 2) ? 15 : 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (New ^ Old) & 2 )
|
||||
if( (New ^ Old) & 2 )
|
||||
{
|
||||
printf( “mov byte ptr fs:[bx+1],%s\n”,
|
||||
(New & 2) ? “15” : “dl” );
|
||||
(New & 2) ? “15” : “dl” );
|
||||
}
|
||||
|
||||
if( (New ^ Old) & 1 )
|
||||
if( (New ^ Old) & 1 )
|
||||
{
|
||||
printf( “mov byte ptr fs:[bx+2],%s\n”,
|
||||
(New & 1) ? “15” : “dl” );
|
||||
(New & 1) ? “15” : “dl” );
|
||||
}
|
||||
}
|
||||
|
||||
if( (New ^ Old) & 4 )
|
||||
if( (New ^ Old) & 4 )
|
||||
{
|
||||
printf( “mov byte ptr fs:[bx],%s\n”,
|
||||
(New & 4) ? “15” : “dl” );
|
||||
(New & 4) ? “15” : “dl” );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (New ^ Old) & 4 ) UpDown += (New & 4) ? 0x48 : -0x48;
|
||||
if( (New ^ Old) & 2 ) UpDown += (New & 2) ? 0x49 : -0x49;
|
||||
if( (New ^ Old) & 1 ) UpDown += (New & 1) ? 0x09 : -0x09;
|
||||
if( (New ^ Old) & 4 ) UpDown += (New & 4) ? 0x48 : -0x48;
|
||||
if( (New ^ Old) & 2 ) UpDown += (New & 2) ? 0x49 : -0x49;
|
||||
if( (New ^ Old) & 1 ) UpDown += (New & 1) ? 0x09 : -0x09;
|
||||
|
||||
if( Edge )
|
||||
{
|
||||
GetUpAndDown(); // ah = row, al = col, cx = up, dx = down
|
||||
|
||||
if( (New ^ Old) & 4 )
|
||||
if( (New ^ Old) & 4 )
|
||||
{
|
||||
printf( “mov di,%d\n”, WRAPLEFT ); // di = left
|
||||
printf( “cmp al,0\n” );
|
||||
|
|
@ -286,7 +286,7 @@ void FirstPass( void )
|
|||
printf( “mov di,%d\n”, LEFT );
|
||||
printf( “L%d:\n”, Label );
|
||||
|
||||
if( New & 4 ) Op = “inc”;
|
||||
if( New & 4 ) Op = “inc”;
|
||||
else Op = “dec”;
|
||||
|
||||
printf( “%s word ptr [bp+di]\n”, Op );
|
||||
|
|
@ -297,7 +297,7 @@ void FirstPass( void )
|
|||
printf( “%s word ptr [bp+di]\n”, Op );
|
||||
}
|
||||
|
||||
if( (New ^ Old) & 1 )
|
||||
if( (New ^ Old) & 1 )
|
||||
{
|
||||
printf( “mov di,%d\n”, WRAPRIGHT ); // di = right
|
||||
printf( “cmp al,%d\n”, (WIDTH - 1) * 3 );
|
||||
|
|
@ -305,7 +305,7 @@ void FirstPass( void )
|
|||
printf( “mov di,%d\n”, RIGHT );
|
||||
printf( “R%d:\n”, Label );
|
||||
|
||||
if( New & 1 ) Op = “add”;
|
||||
if( New & 1 ) Op = “add”;
|
||||
else Op = “sub”;
|
||||
|
||||
printf( “%s word ptr [bp+di],40h\n”, Op );
|
||||
|
|
@ -325,9 +325,9 @@ void FirstPass( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
if( (New ^ Old) & 4 )
|
||||
if( (New ^ Old) & 4 )
|
||||
{
|
||||
if( New & 4 ) Op = “inc”;
|
||||
if( New & 4 ) Op = “inc”;
|
||||
else Op = “dec”;
|
||||
|
||||
printf( “%s byte ptr [bp+%d]\n”, Op, LEFT );
|
||||
|
|
@ -335,9 +335,9 @@ void FirstPass( void )
|
|||
printf( “%s byte ptr [bp+%d]\n”, Op, LOWERLEFT );
|
||||
}
|
||||
|
||||
if( (New ^ Old) & 1 )
|
||||
if( (New ^ Old) & 1 )
|
||||
{
|
||||
if( New & 1 ) Op = “add”;
|
||||
if( New & 1 ) Op = “add”;
|
||||
else Op = “sub”;
|
||||
|
||||
printf( “%s word ptr [bp+%d],40h\n”, Op, RIGHT );
|
||||
|
|
@ -393,7 +393,7 @@ void SecondPass( void )
|
|||
if( Edge )
|
||||
{
|
||||
// finished with second pass
|
||||
if( New == 7 && Old == 0 )
|
||||
if( New == 7 && Old == 0 )
|
||||
{
|
||||
printf( “cmp bp,offset DGROUP:ChangeCell\n” );
|
||||
printf( “jne short NotEnd\n” );
|
||||
|
|
|
|||
14
18-04.html
14
18-04.html
|
|
@ -70,9 +70,9 @@ void InitCellmap( void )
|
|||
|
||||
for( i = j = 0; i < WIDTH * HEIGHT; i++ )
|
||||
{
|
||||
if( CellMap[ i ] & 0x7000 )
|
||||
if( CellMap[ i ] & 0x7000 )
|
||||
{
|
||||
ChangeList1[ j++ ] = (short)&CellMap[ i ];
|
||||
ChangeList1[ j++ ] = (short)&CellMap[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ void main( void )
|
|||
unsigned int seed;
|
||||
|
||||
printf( “Seed (0 for random seed): ” );
|
||||
scanf( “%d”, &seed );
|
||||
scanf( “%d”, &seed );
|
||||
if( seed == 0 ) seed = (unsigned) time(NULL);
|
||||
srand( seed );
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ void main( void )
|
|||
|
||||
InitCellmap(); // randomly initialize cell map
|
||||
|
||||
_bios_timeofday( _TIME_GETCLOCK, &start_time );
|
||||
_bios_timeofday( _TIME_GETCLOCK, &start_time );
|
||||
|
||||
do
|
||||
{
|
||||
|
|
@ -116,7 +116,7 @@ void main( void )
|
|||
while( !kbhit() );
|
||||
#endif
|
||||
|
||||
_bios_timeofday( _TIME_GETCLOCK, &end_time );
|
||||
_bios_timeofday( _TIME_GETCLOCK, &end_time );
|
||||
end_time -= start_time;
|
||||
|
||||
#ifndef NODRAW
|
||||
|
|
@ -151,7 +151,7 @@ void enter_display_mode()
|
|||
union REGS regset;
|
||||
|
||||
regset.x.ax = 0x0013;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
/* Text mode mode-set function. */
|
||||
|
|
@ -160,7 +160,7 @@ void exit_display_mode()
|
|||
union REGS regset;
|
||||
|
||||
regset.x.ax = 0x0003;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
/* Text display function. Offsets text to non-graphics area of
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
; Returns checksum in AX.
|
||||
; ECX and ESI destroyed.
|
||||
; All cycle counts assume 32-bit protected mode.
|
||||
; Assumes buffer length > 0.
|
||||
; Assumes buffer length > 0.
|
||||
; Note that timing indicates that the pipe sequence and
|
||||
; cycle counts shown (based on documented execution rules)
|
||||
; differ from the actual execution sequence and cycle counts;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
; Returns checksum in AX.
|
||||
; High word of EAX, DX, ECX and ESI destroyed.
|
||||
; All cycle counts assume 32-bit protected mode.
|
||||
; Assumes buffer length > 0.
|
||||
; Assumes buffer length > 0.
|
||||
|
||||
sub eax,eax ;initialize the checksum
|
||||
mov dx,[esi] ;first word to checksum
|
||||
|
|
@ -78,7 +78,7 @@ ckloopend:
|
|||
; Returns checksum in AX.
|
||||
; High word of EAX, BX, EDX, ECX and ESI destroyed.
|
||||
; All cycle counts assume 32-bit protected mode.
|
||||
; Assumes buffer length > 0.
|
||||
; Assumes buffer length > 0.
|
||||
|
||||
sub eax,eax ;initialize the checksum
|
||||
sub edx,edx ;prepare for later ORing
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
; High word of EAX, ECX, EDX, and ESI destroyed.
|
||||
; All cycle counts assume 32-bit protected mode.
|
||||
; Assumes buffer starts on a dword boundary, is a dword multiple
|
||||
; in length, and length > 0.
|
||||
; in length, and length > 0.
|
||||
|
||||
sub eax,eax ;initialize the checksum
|
||||
shr ecx,1 ;we’ll do two words per loop
|
||||
|
|
@ -82,7 +82,7 @@ ckloopend:
|
|||
; High word of EAX, EBX, ECX, EDX, and ESI destroyed.
|
||||
; All cycle counts assume 32-bit protected mode.
|
||||
; Assumes buffer starts on a dword boundary, is a dword multiple
|
||||
; in length, and length > 0.
|
||||
; in length, and length > 0.
|
||||
|
||||
sub eax,eax ;initialize the checksum
|
||||
shr ecx,2 ;we’ll do two dwords per loop
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ PanningXInc dw 1 ;x panning factor
|
|||
PanningYInc dw 0 ;y panning factor
|
||||
HPan db 0 ;horizontal pel panning setting
|
||||
PanningStartOffset dw 0 ;start offset adjustment to produce vertical
|
||||
; panning & coarse horizontal panning
|
||||
; panning & coarse horizontal panning
|
||||
dseg ends
|
||||
;
|
||||
; Macro to set indexed register P2 of chip with index register
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ BackgroundLoop:
|
|||
TEXT_UP FillPatternVert, FILL_PATTERN_VERT_LENGTH, 15, 42
|
||||
TEXT_UP FillPatternHorz, FILL_PATTERN_HORZ_LENGTH, 21, 42
|
||||
;
|
||||
; Wait until a key’s been hit to reset screen mode & exit.
|
||||
; Wait until a key’s been hit to reset screen mode & exit.
|
||||
;
|
||||
WaitForKey:
|
||||
mov ah,1
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ Start endp
|
|||
; DS:SI = pointer to chunky image to draw, as follows:
|
||||
; word at 0: width of image, in pixels
|
||||
; word at 2: height of image, in pixels
|
||||
; byte at 4: msb/lsb = first & second chunky pixels,
|
||||
; byte at 4: msb/lsb = first & second chunky pixels,
|
||||
; repeating for the remainder of the scan line
|
||||
; of the image, then for all scan lines. Images
|
||||
; with odd widths have an unused null nibble
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ ImagePlane1 db 32*4 dup (?)
|
|||
ImagePlane2 db 32*4 dup (?)
|
||||
ImagePlane3 db 32*4 dup (?)
|
||||
;
|
||||
; Current image location & direction.
|
||||
; Current image location & direction.
|
||||
;
|
||||
ImageX dw 40 ;in bytes
|
||||
ImageY dw 100 ;in pixels
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ loopVLineLoop
|
|||
mov al,GRAPHICS_MODE
|
||||
out dx,al ;point GC Index to Graphics Mode register
|
||||
inc dx ;point to GC Data
|
||||
mov al,00001000b ;bit 3=1 is read mode 1, bits 1 & 0=00
|
||||
mov al,00001000b ;bit 3=1 is read mode 1, bits 1 & 0=00
|
||||
; is write mode 0
|
||||
out dx,al ;set Graphics Mode to read mode 1,
|
||||
; write mode 0
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ Startprocnear
|
|||
inc dx
|
||||
in al,dx ;VGA registers are readable, bless them!
|
||||
or al,00001011b ;bit 3=1 selects read mode 1, and
|
||||
; bits 1 & 0=11 selects write mode 3
|
||||
; bits 1 & 0=11 selects write mode 3
|
||||
jmp $+2 ;delay between IN and OUT to same port
|
||||
out dx,al
|
||||
dec dx
|
||||
|
|
|
|||
18
31-03.html
18
31-03.html
|
|
@ -86,15 +86,15 @@ LineControl ends
|
|||
; List of descriptors for lines to draw.
|
||||
;
|
||||
LineList label LineControl
|
||||
LineControl <130,110,1,0,60,0>
|
||||
LineControl <190,110,1,1,60,1>
|
||||
LineControl <250,170,0,1,60,2>
|
||||
LineControl <250,230,-1,1,60,3>
|
||||
LineControl <190,290,-1,0,60,4>
|
||||
LineControl <130,290,-1,-1,60,5>
|
||||
LineControl <70,230,0,-1,60,6>
|
||||
LineControl <70,170,1,-1,60,7>
|
||||
LineControl <-1,0,0,0,0,0>
|
||||
LineControl <130,110,1,0,60,0>
|
||||
LineControl <190,110,1,1,60,1>
|
||||
LineControl <250,170,0,1,60,2>
|
||||
LineControl <250,230,-1,1,60,3>
|
||||
LineControl <190,290,-1,0,60,4>
|
||||
LineControl <130,290,-1,-1,60,5>
|
||||
LineControl <70,230,0,-1,60,6>
|
||||
LineControl <70,170,1,-1,60,7>
|
||||
LineControl <-1,0,0,0,0,0>
|
||||
Data ends
|
||||
;
|
||||
; Macro to output a word value to a port.
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ int Color; /* color in which to draw line */
|
|||
while ( DeltaX-- ) {
|
||||
/* See if it’s time to advance the Y coordinate */
|
||||
if ( ErrorTerm >= 0 ) {
|
||||
/* Advance the Y coordinate & adjust the error term
|
||||
/* Advance the Y coordinate & adjust the error term
|
||||
back down */
|
||||
Y0++;
|
||||
ErrorTerm += DeltaYx2MinusDeltaXx2;
|
||||
|
|
@ -122,7 +122,7 @@ int Color; /* color in which to draw line */
|
|||
while ( DeltaY-- ) {
|
||||
/* See if it’s time to advance the X coordinate */
|
||||
if ( ErrorTerm >= 0 ) {
|
||||
/* Advance the X coordinate & adjust the error term
|
||||
/* Advance the X coordinate & adjust the error term
|
||||
back down */
|
||||
X0 += XDirection;
|
||||
ErrorTerm += DeltaXx2MinusDeltaYx2;
|
||||
|
|
@ -233,7 +233,7 @@ void main()
|
|||
VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 4);
|
||||
|
||||
/* Wait for the enter key to be pressed */
|
||||
scanf(“%c”, &temp);
|
||||
scanf(“%c”, &temp);
|
||||
|
||||
/* Back to text mode */
|
||||
_AX = TEXT_MODE;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ unsigned int Y0; /* (0,0) at the upper left of the screen */
|
|||
|
||||
/* Generate a mask with a 1 bit in the pixel’s position within the
|
||||
screen byte */
|
||||
PixelMask = 0x80 >> ( X0 & 0x07 );
|
||||
PixelMask = 0x80 >> ( X0 & 0x07 );
|
||||
|
||||
/* Set up the Graphics Controller’s Bit Mask register to allow
|
||||
only the bit corresponding to the pixel being drawn to
|
||||
|
|
@ -124,7 +124,7 @@ int XDirection; /* 1 if line is drawn left to right,
|
|||
while ( DeltaX— ) {
|
||||
/* See if it’s time to advance the Y coordinate */
|
||||
if ( ErrorTerm >= 0 ) {
|
||||
/* Advance the Y coordinate & adjust the error term
|
||||
/* Advance the Y coordinate & adjust the error term
|
||||
back down */
|
||||
Y0++;
|
||||
ErrorTerm += DeltaYx2MinusDeltaXx2;
|
||||
|
|
@ -159,7 +159,7 @@ int XDirection; /* 1 if line is drawn left to right,
|
|||
while ( DeltaY— ) {
|
||||
/* See if it’s time to advance the X coordinate */
|
||||
if ( ErrorTerm >= 0 ) {
|
||||
/* Advance the X coordinate & adjust the error term
|
||||
/* Advance the X coordinate & adjust the error term
|
||||
back down */
|
||||
X0 += XDirection;
|
||||
ErrorTerm += DeltaXx2MinusDeltaYx2;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ void main()
|
|||
Y_MAX / 4, 4);
|
||||
|
||||
/* Wait for the enter key to be pressed */
|
||||
scanf(“%c”, &temp);
|
||||
scanf(“%c”, &temp);
|
||||
|
||||
/* Return back to text mode */
|
||||
_AX = TEXT_MODE;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ endif
|
|||
; in this byte when pixel mask wraps.
|
||||
;
|
||||
MoveXCoord:
|
||||
add bp,bx ;increment error term & keep same
|
||||
add bp,bx ;increment error term & keep same
|
||||
if MOVE_LEFT
|
||||
rol ah,1 ;move pixel mask 1 pixel to the left
|
||||
else
|
||||
|
|
@ -218,7 +218,7 @@ LINE2 macro MOVE_LEFT
|
|||
sub bx,si ;DeltaX * 2 - DeltaY * 2 (used in loop)
|
||||
add si,bx ;DeltaX * 2 (used in loop)
|
||||
;
|
||||
; Set up initial bit mask & write initial pixel.
|
||||
; Set up initial bit mask & write initial pixel.
|
||||
;
|
||||
out dx,al
|
||||
xchg byte ptr [di],ah
|
||||
|
|
@ -232,7 +232,7 @@ LineLoop:
|
|||
;
|
||||
and bp,bp ;see if error term is negative
|
||||
jns ETermAction ;no, advance X coordinate
|
||||
add bp,si ;increment error term & keep same
|
||||
add bp,si ;increment error term & keep same
|
||||
jmp short MoveYCoord ; X coordinate
|
||||
ETermAction:
|
||||
;
|
||||
|
|
|
|||
10
36-01.html
10
36-01.html
|
|
@ -48,10 +48,10 @@
|
|||
<P>Second, when performance matters, never have your code perform the same calculation more than once. This sounds obvious, but it’s astonishing how often it’s ignored. For example, consider this snippet of code:</P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
for (i=0; i<RunLength; i++)
|
||||
for (i=0; i<RunLength; i++)
|
||||
{
|
||||
*WorkingScreenPtr = Color;
|
||||
if (XDelta > 0)
|
||||
if (XDelta > 0)
|
||||
{
|
||||
WorkingScreenPtr++;
|
||||
}
|
||||
|
|
@ -67,16 +67,16 @@ for (i=0; i<RunLength; i++)
|
|||
</P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
if (XDelta > 0)
|
||||
if (XDelta > 0)
|
||||
{
|
||||
for (i=0; i<RunLength; i++)
|
||||
for (i=0; i<RunLength; i++)
|
||||
{
|
||||
*WorkingScreenPtr++ = Color;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<RunLength; i++)
|
||||
for (i=0; i<RunLength; i++)
|
||||
{
|
||||
*WorkingScreenPtr-- = Color;
|
||||
}
|
||||
|
|
|
|||
46
36-03.html
46
36-03.html
|
|
@ -53,7 +53,7 @@
|
|||
320x200 256-color mode. Not optimized! Tested with Borland C++ in
|
||||
the small model. */
|
||||
|
||||
#include <dos.h>
|
||||
#include <dos.h>
|
||||
|
||||
#define SCREEN_WIDTH 320
|
||||
#define SCREEN_SEGMENT 0xA000
|
||||
|
|
@ -71,7 +71,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
|
||||
/* We’ll always draw top to bottom, to reduce the number of cases we have to
|
||||
handle, and to make lines between the same endpoints draw the same pixels */
|
||||
if (YStart > YEnd) {
|
||||
if (YStart > YEnd) {
|
||||
Temp = YStart;
|
||||
YStart = YEnd;
|
||||
YEnd = Temp;
|
||||
|
|
@ -84,7 +84,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
|
||||
/* Figure out whether we’re going left or right, and how far we’re
|
||||
going horizontally */
|
||||
if ((XDelta = XEnd - XStart) < 0)
|
||||
if ((XDelta = XEnd - XStart) < 0)
|
||||
{
|
||||
XAdvance = -1;
|
||||
XDelta = -XDelta;
|
||||
|
|
@ -101,7 +101,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
if (XDelta == 0)
|
||||
{
|
||||
/* Vertical line */
|
||||
for (i=0; i<=YDelta; i++)
|
||||
for (i=0; i<=YDelta; i++)
|
||||
{
|
||||
*ScreenPtr = Color;
|
||||
ScreenPtr += SCREEN_WIDTH;
|
||||
|
|
@ -111,7 +111,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
if (YDelta == 0)
|
||||
{
|
||||
/* Horizontal line */
|
||||
for (i=0; i<=XDelta; i++)
|
||||
for (i=0; i<=XDelta; i++)
|
||||
{
|
||||
*ScreenPtr = Color;
|
||||
ScreenPtr += XAdvance;
|
||||
|
|
@ -121,7 +121,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
if (XDelta == YDelta)
|
||||
{
|
||||
/* Diagonal line */
|
||||
for (i=0; i<=XDelta; i++)
|
||||
for (i=0; i<=XDelta; i++)
|
||||
{
|
||||
*ScreenPtr = Color;
|
||||
ScreenPtr += XAdvance + SCREEN_WIDTH;
|
||||
|
|
@ -130,7 +130,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
}
|
||||
|
||||
/* Determine whether the line is X or Y major, and handle accordingly */
|
||||
if (XDelta >= YDelta)
|
||||
if (XDelta >= YDelta)
|
||||
{
|
||||
/* X major line */
|
||||
/* Minimum # of pixels in a run in this line */
|
||||
|
|
@ -159,35 +159,35 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
advance, we have one pixel that could go to either the initial
|
||||
or last partial run, which we’ll arbitrarily allocate to the
|
||||
last run */
|
||||
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0))
|
||||
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0))
|
||||
{
|
||||
InitialPixelCount--;
|
||||
}
|
||||
/* If there’re an odd number of pixels per run, we have 1 pixel that can’t
|
||||
be allocated to either the initial or last partial run, so we’ll add 0.5
|
||||
to error term so this pixel will be handled by the normal full-run loop */
|
||||
if ((WholeStep & 0x01) != 0)
|
||||
if ((WholeStep & 0x01) != 0)
|
||||
{
|
||||
ErrorTerm += YDelta;
|
||||
}
|
||||
/* Draw the first, partial run of pixels */
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
||||
/* Draw all full runs */
|
||||
for (i=0; i<(YDelta-1); i++)
|
||||
for (i=0; i<(YDelta-1); i++)
|
||||
{
|
||||
RunLength = WholeStep; /* run is at least this long */
|
||||
/* Advance the error term and add an extra pixel if the error
|
||||
term so indicates */
|
||||
if ((ErrorTerm += AdjUp) > 0)
|
||||
if ((ErrorTerm += AdjUp) > 0)
|
||||
{
|
||||
RunLength++;
|
||||
ErrorTerm -= AdjDown; /* reset the error term */
|
||||
}
|
||||
/* Draw this scan line’s run */
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
||||
}
|
||||
/* Draw the final run of pixels */
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
||||
DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
@ -218,7 +218,7 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
/* If the basic run length is even and there’s no fractional advance, we
|
||||
have 1 pixel that could go to either the initial or last partial run,
|
||||
which we’ll arbitrarily allocate to the last run */
|
||||
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0))
|
||||
if ((AdjUp == 0) && ((WholeStep & 0x01) == 0))
|
||||
{
|
||||
InitialPixelCount--;
|
||||
}
|
||||
|
|
@ -226,29 +226,29 @@ void LineDraw(int XStart, int YStart, int XEnd, int YEnd, int Color)
|
|||
that can’t be allocated to either the initial or last partial
|
||||
run, so we’ll add 0.5 to the error term so this pixel will be
|
||||
handled by the normal full-run loop */
|
||||
if ((WholeStep & 0x01) != 0)
|
||||
if ((WholeStep & 0x01) != 0)
|
||||
{
|
||||
ErrorTerm += XDelta;
|
||||
}
|
||||
/* Draw the first, partial run of pixels */
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
|
||||
|
||||
/* Draw all full runs */
|
||||
for (i=0; i<(XDelta-1); i++)
|
||||
for (i=0; i<(XDelta-1); i++)
|
||||
{
|
||||
RunLength = WholeStep; /* run is at least this long */
|
||||
/* Advance the error term and add an extra pixel if the error
|
||||
term so indicates */
|
||||
if ((ErrorTerm += AdjUp) > 0)
|
||||
if ((ErrorTerm += AdjUp) > 0)
|
||||
{
|
||||
RunLength++;
|
||||
ErrorTerm -= AdjDown; /* reset the error term */
|
||||
}
|
||||
/* Draw this scan line’s run */
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
|
||||
}
|
||||
/* Draw the final run of pixels */
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
||||
DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -260,7 +260,7 @@ void DrawHorizontalRun(char far **ScreenPtr, int XAdvance,
|
|||
int i;
|
||||
char far *WorkingScreenPtr = *ScreenPtr;
|
||||
|
||||
for (i=0; i<RunLength; i++)
|
||||
for (i=0; i<RunLength; i++)
|
||||
{
|
||||
*WorkingScreenPtr = Color;
|
||||
WorkingScreenPtr += XAdvance;
|
||||
|
|
@ -277,7 +277,7 @@ void DrawVerticalRun(char far **ScreenPtr, int XAdvance,
|
|||
int i;
|
||||
char far *WorkingScreenPtr = *ScreenPtr;
|
||||
|
||||
for (i=0; i<RunLength; i++)
|
||||
for (i=0; i<RunLength; i++)
|
||||
{
|
||||
*WorkingScreenPtr = Color;
|
||||
WorkingScreenPtr += SCREEN_WIDTH;
|
||||
|
|
|
|||
14
36-04.html
14
36-04.html
|
|
@ -44,7 +44,7 @@
|
|||
line-drawing functions coded in LListing L36.1.C.
|
||||
Tested with Borland C++ in the small model. */
|
||||
|
||||
#include <dos.h>
|
||||
#include <dos.h>
|
||||
|
||||
#define GRAPHICS_MODE 0x13
|
||||
#define TEXT_MODE 0x03
|
||||
|
|
@ -66,28 +66,28 @@ int Color; /* color to draw lines in */
|
|||
/* lines from center to top of rectangle */
|
||||
WorkingX = XCenter - XLength;
|
||||
WorkingY = YCenter - YLength;
|
||||
for ( ; WorkingX < ( XCenter + XLength ); WorkingX++ )
|
||||
for ( ; WorkingX < ( XCenter + XLength ); WorkingX++ )
|
||||
{
|
||||
LineDraw(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||||
}
|
||||
/* lines from center to right of rectangle */
|
||||
WorkingX = XCenter + XLength - 1;
|
||||
WorkingY = YCenter - YLength;
|
||||
for ( ; WorkingY < ( YCenter + YLength ); WorkingY++ )
|
||||
for ( ; WorkingY < ( YCenter + YLength ); WorkingY++ )
|
||||
{
|
||||
LineDraw(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||||
}
|
||||
/* lines from center to bottom of rectangle */
|
||||
WorkingX = XCenter + XLength - 1;
|
||||
WorkingY = YCenter + YLength - 1;
|
||||
for ( ; WorkingX >= ( XCenter - XLength ); WorkingX-- )
|
||||
for ( ; WorkingX >= ( XCenter - XLength ); WorkingX-- )
|
||||
{
|
||||
LineDraw(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||||
}
|
||||
/* lines from center to left of rectangle */
|
||||
WorkingX = XCenter - XLength;
|
||||
WorkingY = YCenter + YLength - 1;
|
||||
for ( ; WorkingY >= ( YCenter - YLength ); WorkingY-- )
|
||||
for ( ; WorkingY >= ( YCenter - YLength ); WorkingY-- )
|
||||
{
|
||||
LineDraw(XCenter, YCenter, WorkingX, WorkingY, Color);
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ int main()
|
|||
|
||||
/* Set graphics mode */
|
||||
regs.x.ax = GRAPHICS_MODE;
|
||||
int86(BIOS_VIDEO_INT, &regs, &regs);
|
||||
int86(BIOS_VIDEO_INT, &regs, &regs);
|
||||
|
||||
/* Draw each of four rectangles full of vectors */
|
||||
VectorsUp(X_MAX / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 1);
|
||||
|
|
@ -112,7 +112,7 @@ int main()
|
|||
|
||||
/* Return back to text mode */
|
||||
regs.x.ax = TEXT_MODE;
|
||||
int86(BIOS_VIDEO_INT, &regs, &regs);
|
||||
int86(BIOS_VIDEO_INT, &regs, &regs);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
the polygon at any point would cross exactly two active edges
|
||||
(neither horizontal lines nor zero-length edges count as active
|
||||
edges; both are acceptable anywhere in the polygon), and that the
|
||||
right & left edges never cross. (It’s OK for them to touch, though,
|
||||
right & left edges never cross. (It’s OK for them to touch, though,
|
||||
so long as the right edge never crosses over to the left of the
|
||||
left edge.) Nonconvex polygons won’t be drawn properly. Returns 1
|
||||
for success, 0 if memory allocation failed. */
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
ScanEdge(VertexPtr[PreviousIndex].X + XOffset,
|
||||
VertexPtr[PreviousIndex].Y,
|
||||
VertexPtr[CurrentIndex].X + XOffset,
|
||||
VertexPtr[CurrentIndex].Y, 1, SkipFirst, &EdgePointPtr);
|
||||
VertexPtr[CurrentIndex].Y, 1, SkipFirst, &EdgePointPtr);
|
||||
PreviousIndex = CurrentIndex;
|
||||
SkipFirst = 0; /* scan convert the first point from now on */
|
||||
} while (CurrentIndex != MaxIndex);
|
||||
|
|
@ -218,13 +218,13 @@
|
|||
ScanEdge(VertexPtr[PreviousIndex].X + XOffset - 1,
|
||||
VertexPtr[PreviousIndex].Y,
|
||||
VertexPtr[CurrentIndex].X + XOffset - 1,
|
||||
VertexPtr[CurrentIndex].Y, 0, SkipFirst, &EdgePointPtr);
|
||||
VertexPtr[CurrentIndex].Y, 0, SkipFirst, &EdgePointPtr);
|
||||
PreviousIndex = CurrentIndex;
|
||||
SkipFirst = 0; /* scan convert the first point from now on */
|
||||
} while (CurrentIndex != MaxIndex);
|
||||
|
||||
/* Draw the line list representing the scan converted polygon */
|
||||
DrawHorizontalLineList(&WorkingHLineList, Color);
|
||||
DrawHorizontalLineList(&WorkingHLineList, Color);
|
||||
|
||||
/* Release the line list’s memory and we’re successfully done */
|
||||
free(WorkingHLineList.HLinePtr);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
#define DRAW_POLYGON(PointList,Color,X,Y) \
|
||||
Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
|
||||
Polygon.PointPtr = PointList; \
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
|
||||
void main(void);
|
||||
extern int FillConvexPolygon(struct PointListHeader *, int, int, int);
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
regset.x.ax = 0x0013; /* AH = 0 selects mode set function,
|
||||
AL = 0x13 selects mode 0x13
|
||||
when set as parameters for INT 0x10 */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
|
||||
/* Clear the screen to cyan */
|
||||
DRAW_POLYGON(ScreenRectangle, 3, 0, 0);
|
||||
|
|
@ -128,7 +128,7 @@
|
|||
|
||||
/* Return to text mode and exit */
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
30
39-02.html
30
39-02.html
|
|
@ -54,27 +54,27 @@
|
|||
<TD VALIGN="TOP" ALIGN="LEFT">11.69
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">5.80 seconds<BR>(50% of total)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">5.86<BR>(50%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.03<BR>(<1%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.03<BR>(<1%)
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C floating point scan/memset drawing (Listing 39.1, compact model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">6.64
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.49<BR>(7%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">6.11<BR>(92%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.04<BR>(<1%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.04<BR>(<1%)
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/memset drawing (Listing 39.1 & Listing 39.2, compact model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/memset drawing (Listing 39.1 & Listing 39.2, compact model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.60
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.49<BR>(82%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.07<BR>(12%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.04<BR>(7%)
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/ASM drawing (Listing 39.2 & Listing 39.3, small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/ASM drawing (Listing 39.2 & Listing 39.3, small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.45
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.36<BR>(80%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.06<BR>(13%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.03<BR>(7%)
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">ASM integer scan/ASM drawing (Listing 40.3 & Listing 40.4,small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">ASM integer scan/ASM drawing (Listing 40.3 & Listing 40.4,small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.42
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.36<BR>(86%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.03<BR>(7%)
|
||||
|
|
@ -82,13 +82,13 @@
|
|||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT" COLSPAN="5"><SMALL>Drawing to system memory</SMALL>
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/memset drawing (Listing 39.1 & Listing 39.2,compact model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">C integer scan/memset drawing (Listing 39.1 & Listing 39.2,compact model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.31
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.20<BR>(65%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.07<BR>(23%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.04<BR>(13%)
|
||||
<TR>
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">ASM integer scan/ASM drawing (Listing 39.3 & Listing 39.4,small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">ASM integer scan/ASM drawing (Listing 39.3 & Listing 39.4,small model)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.13
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.07<BR>(54%)
|
||||
<TD VALIGN="TOP" ALIGN="LEFT">0.03<BR>(23%)
|
||||
|
|
@ -113,8 +113,8 @@
|
|||
running in real mode or 286 protected mode.
|
||||
All C code tested with Borland C++. */
|
||||
|
||||
#include <string.h>
|
||||
#include <dos.h>
|
||||
#include <string.h>
|
||||
#include <dos.h>
|
||||
#include “polygon.h”
|
||||
|
||||
#define SCREEN_WIDTH 320
|
||||
|
|
@ -129,18 +129,18 @@ void DrawHorizontalLineList(struct HLineList * HLineListPtr,
|
|||
|
||||
/* Point to the start of the first scan line on which to draw */
|
||||
ScreenPtr = MK_FP(SCREEN_SEGMENT,
|
||||
HLineListPtr->YStart * SCREEN_WIDTH);
|
||||
HLineListPtr->YStart * SCREEN_WIDTH);
|
||||
|
||||
/* Point to the XStart/XEnd descriptor for the first (top)
|
||||
horizontal line */
|
||||
HLinePtr = HLineListPtr->HLinePtr;
|
||||
HLinePtr = HLineListPtr->HLinePtr;
|
||||
/* Draw each horizontal line in turn, starting with the top one and
|
||||
advancing one line each time */
|
||||
Length = HLineListPtr->Length;
|
||||
while (Length-- > 0) {
|
||||
Length = HLineListPtr->Length;
|
||||
while (Length-- > 0) {
|
||||
/* Draw the whole horizontal line if it has a positive width */
|
||||
if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0)
|
||||
memset(ScreenPtr + HLinePtr->XStart, Color, Width);
|
||||
if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0)
|
||||
memset(ScreenPtr + HLinePtr->XStart, Color, Width);
|
||||
HLinePtr++; /* point to next scan line X info */
|
||||
ScreenPtr += SCREEN_WIDTH; /* point to next scan line start */
|
||||
}
|
||||
|
|
|
|||
54
39-03.html
54
39-03.html
|
|
@ -49,7 +49,7 @@
|
|||
scanned edge is chosen. Uses an all-integer approach for speed and
|
||||
precision. */
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
||||
|
|
@ -60,11 +60,11 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
struct HLine *WorkingEdgePointPtr;
|
||||
|
||||
WorkingEdgePointPtr = *EdgePointPtr; /* avoid double dereference */
|
||||
AdvanceAmt = ((DeltaX = X2 - X1) > 0) ? 1 : -1;
|
||||
AdvanceAmt = ((DeltaX = X2 - X1) > 0) ? 1 : -1;
|
||||
/* direction in which X moves (Y2 is
|
||||
always > Y1, so Y always counts up) */
|
||||
always > Y1, so Y always counts up) */
|
||||
|
||||
if ((Height = Y2 - Y1) <= 0) /* Y length of the edge */
|
||||
if ((Height = Y2 - Y1) <= 0) /* Y length of the edge */
|
||||
return; /* guard against 0-length and horizontal edges */
|
||||
|
||||
/* Figure out whether the edge is vertical, diagonal, X-major
|
||||
|
|
@ -74,12 +74,12 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
/* The edge is vertical; special-case by just storing the same
|
||||
X coordinate for every scan line */
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
}
|
||||
} else if (Width == Height) {
|
||||
/* The edge is diagonal; special-case by advancing the X
|
||||
|
|
@ -87,36 +87,36 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
if (SkipFirst) /* skip the first point if so indicated */
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
}
|
||||
} else if (Height > Width) {
|
||||
} else if (Height > Width) {
|
||||
/* Edge is closer to vertical than horizontal (Y-major) */
|
||||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
else
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
if (SkipFirst) { /* skip the first point if so indicated */
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to next point */
|
||||
}
|
||||
}
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
/* Determine whether it’s time for the X coord to advance */
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
if ((ErrorTerm += Width) > 0) {
|
||||
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
|
|
@ -127,28 +127,28 @@ void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
|||
XMajorAdvanceAmt = (Width / Height) * AdvanceAmt;
|
||||
/* Error term advance for deciding when to advance X 1 extra */
|
||||
ErrorTermAdvance = Width % Height;
|
||||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
if (DeltaX >= 0)
|
||||
ErrorTerm = 0; /* initial error term going left->right */
|
||||
else
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
ErrorTerm = -Height + 1; /* going right->left */
|
||||
if (SkipFirst) { /* skip the first point if so indicated */
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
}
|
||||
/* Scan the edge for each scan line in turn */
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
|
||||
/* Store the X coordinate in the appropriate edge list */
|
||||
if (SetXStart == 1)
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
WorkingEdgePointPtr->XStart = X1;
|
||||
else
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
WorkingEdgePointPtr->XEnd = X1;
|
||||
X1 += XMajorAdvanceAmt; /* move X minimum distance */
|
||||
/* Determine whether it’s time for X to advance one extra */
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
if ((ErrorTerm += ErrorTermAdvance) > 0) {
|
||||
X1 += AdvanceAmt; /* move X one more */
|
||||
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ HLinePtr dw ? ;pointer to list of horz lines
|
|||
HLineList ends
|
||||
|
||||
Parms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
HLineListPtr dw ? ;pointer to HLineList structure
|
||||
Color dw ? ;color with which to fill
|
||||
Parms ends
|
||||
|
|
|
|||
12
39-05.html
12
39-05.html
|
|
@ -43,11 +43,11 @@
|
|||
; point at (X2,Y2). If SkipFirst == 1, the point at (X1,Y1) isn’t
|
||||
; drawn; if SkipFirst == 0, it is. For each scan line, the pixel
|
||||
; closest to the scanned edge without being to the left of the scanned
|
||||
; edge is chosen. Uses an all-integer approach for speed & precision.
|
||||
; edge is chosen. Uses an all-integer approach for speed & precision.
|
||||
; C near-callable as:
|
||||
; void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
|
||||
; int SkipFirst, struct HLine **EdgePointPtr);
|
||||
; Edges must not go bottom to top; that is, Y1 must be <= Y2.
|
||||
; Edges must not go bottom to top; that is, Y1 must be <= Y2.
|
||||
; Updates the pointer pointed to by EdgePointPtr to point to the next
|
||||
; free entry in the array of HLine structures.
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ XEnd dw ? ;X coordinate of rightmost pixel in scan line
|
|||
HLine ends
|
||||
|
||||
Parms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
X1 dw ? ;X start coord of edge
|
||||
Y1 dw ? ;Y start coord of edge
|
||||
X2 dw ? ;X end coord of edge
|
||||
|
|
@ -96,7 +96,7 @@ _ScanEdge proc
|
|||
HLinePtrSet:
|
||||
mov bx,[bp+Y2]
|
||||
sub bx,[bp+Y1] ;edge height
|
||||
jle ToScanEdgeExit ;guard against 0-length & horz edges
|
||||
jle ToScanEdgeExit ;guard against 0-length & horz edges
|
||||
mov [bp+Height],bx ;Height = Y2 - Y1
|
||||
sub cx,cx ;assume ErrorTerm starts at 0 (true if
|
||||
; we’re moving right as we draw)
|
||||
|
|
@ -104,8 +104,8 @@ HLinePtrSet:
|
|||
mov ax,[bp+X2]
|
||||
sub ax,[bp+X1] ;DeltaX = X2 - X1
|
||||
jz IsVertical ;it’s a vertical edge--special case it
|
||||
jns SetAdvanceAmt ;DeltaX >= 0
|
||||
mov cx,1 ;DeltaX < 0 (move left as we draw)
|
||||
jns SetAdvanceAmt ;DeltaX >= 0
|
||||
mov cx,1 ;DeltaX < 0 (move left as we draw)
|
||||
sub cx,bx ;ErrorTerm = -Height + 1
|
||||
neg dx ;AdvanceAmt = -1 (move left)
|
||||
neg ax ;Width = abs(DeltaX)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ void main()
|
|||
getch(); /* wait for a key press */
|
||||
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset); /* return to text mode */
|
||||
int86(0x10, &regset, &regset); /* return to text mode */
|
||||
}
|
||||
|
||||
/* Sets up the palette for antialiasing with the specified colors.
|
||||
|
|
@ -163,7 +163,7 @@ void SetPalette(struct WuColor * WColors)
|
|||
regset.x.dx = (unsigned int)PaletteBlock; /* offset of array from which
|
||||
to load RGB settings */
|
||||
sregset.es = _DS; /* segment of array from which to load settings */
|
||||
int86x(0x10, &regset, &regset, &sregset); /* load the palette block */
|
||||
int86x(0x10, &regset, &regset, &sregset); /* load the palette block */
|
||||
}
|
||||
}
|
||||
</PRE>
|
||||
|
|
@ -198,7 +198,7 @@ void SetMode()
|
|||
|
||||
/* Set to 320x200 256-color graphics mode */
|
||||
regset.x.ax = 0x0013;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
10
42-04.html
10
42-04.html
|
|
@ -79,10 +79,10 @@ void DrawLine(int X0, int Y0, int X1, int Y1, int Color)
|
|||
/* Draw all pixels between the first and last */
|
||||
do {
|
||||
ErrorAcc += ErrorAdj; /* calculate error for this pixel */
|
||||
if (ErrorAcc & ~0xFFFFL) {
|
||||
if (ErrorAcc & ~0xFFFFL) {
|
||||
/* The error accumulator turned over, so advance the X coord */
|
||||
X0 += XDir;
|
||||
ErrorAcc &= 0xFFFFL; /* clear integer part of result */
|
||||
ErrorAcc &= 0xFFFFL; /* clear integer part of result */
|
||||
}
|
||||
Y0++; /* Y-major, so always advance Y */
|
||||
DrawPixel(X0, Y0, Color);
|
||||
|
|
@ -96,10 +96,10 @@ void DrawLine(int X0, int Y0, int X1, int Y1, int Color)
|
|||
/* Draw all remaining pixels */
|
||||
do {
|
||||
ErrorAcc += ErrorAdj; /* calculate error for this pixel */
|
||||
if (ErrorAcc & ~0xFFFFL) {
|
||||
if (ErrorAcc & ~0xFFFFL) {
|
||||
/* The error accumulator turned over, so advance the Y coord */
|
||||
Y0++;
|
||||
ErrorAcc &= 0xFFFFL; /* clear integer part of result */
|
||||
ErrorAcc &= 0xFFFFL; /* clear integer part of result */
|
||||
}
|
||||
X0 += XDir; /* X-major, so always advance X */
|
||||
DrawPixel(X0, Y0, Color);
|
||||
|
|
@ -149,7 +149,7 @@ void SetMode()
|
|||
|
||||
/* Set to 640x480 256-color graphics mode */
|
||||
regset.x.ax = 0x002E;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
58
43-03.html
58
43-03.html
|
|
@ -117,19 +117,19 @@ Data segment word ‘DATA’
|
|||
Colors db 000h ;background color=black
|
||||
db 03ch ;plane 0 only=red
|
||||
db 03ah ;plane 1 only=green
|
||||
db 03ch ;planes 0&1=red (plane 0 priority)
|
||||
db 03ch ;planes 0&1=red (plane 0 priority)
|
||||
db 039h ;plane 2 only=blue
|
||||
db 03ch ;planes 0&2=red (plane 0 priority)
|
||||
db 03ah ;planes 1&2=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&2=red (plane 0 priority)
|
||||
db 03ch ;planes 0&2=red (plane 0 priority)
|
||||
db 03ah ;planes 1&2=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&2=red (plane 0 priority)
|
||||
db 03fh ;plane 3 only=white
|
||||
db 03ch ;planes 0&3=red (plane 0 priority)
|
||||
db 03ah ;planes 1&3=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&3=red (plane 0 priority)
|
||||
db 039h ;planes 2&3=blue (plane 2 priority)
|
||||
db 03ch ;planes 0&2&3=red (plane 0 priority)
|
||||
db 03ah ;planes 1&2&3=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&2&3=red (plane 0 priority)
|
||||
db 03ch ;planes 0&3=red (plane 0 priority)
|
||||
db 03ah ;planes 1&3=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&3=red (plane 0 priority)
|
||||
db 039h ;planes 2&3=blue (plane 2 priority)
|
||||
db 03ch ;planes 0&2&3=red (plane 0 priority)
|
||||
db 03ah ;planes 1&2&3=green (plane 1 priority)
|
||||
db 03ch ;planes 0&1&2&3=red (plane 0 priority)
|
||||
db 000h ;border color=black
|
||||
;
|
||||
; Image of a hollow square.
|
||||
|
|
@ -234,19 +234,19 @@ Diamond label byte
|
|||
even;word-align for better 286 performance
|
||||
;
|
||||
ObjectListlabelObjectStructure
|
||||
ObjectStructure <1,21,Diamond,88,8,80,512,16,0,0,350,RED>
|
||||
ObjectStructure <1,15,Square,296,8,112,480,144,0,0,350,RED>
|
||||
ObjectStructure <1,23,Diamond,88,8,80,512,256,0,0,350,RED>
|
||||
ObjectStructure <1,13,Square,120,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,11,Diamond,208,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,8,Square,296,0,0,640,144,4,0,288,BLUE>
|
||||
ObjectStructure <1,9,Diamond,384,0,0,640,144,4,0,288,BLUE>
|
||||
ObjectStructure <1,14,Square,472,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,8,Diamond,200,8,0,576,48,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Square,248,8,0,576,96,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Diamond,296,8,0,576,144,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Square,344,8,0,576,192,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Diamond,392,8,0,576,240,6,0,280,GREEN>
|
||||
ObjectStructure <1,21,Diamond,88,8,80,512,16,0,0,350,RED>
|
||||
ObjectStructure <1,15,Square,296,8,112,480,144,0,0,350,RED>
|
||||
ObjectStructure <1,23,Diamond,88,8,80,512,256,0,0,350,RED>
|
||||
ObjectStructure <1,13,Square,120,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,11,Diamond,208,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,8,Square,296,0,0,640,144,4,0,288,BLUE>
|
||||
ObjectStructure <1,9,Diamond,384,0,0,640,144,4,0,288,BLUE>
|
||||
ObjectStructure <1,14,Square,472,0,0,640,144,4,0,280,BLUE>
|
||||
ObjectStructure <1,8,Diamond,200,8,0,576,48,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Square,248,8,0,576,96,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Diamond,296,8,0,576,144,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Square,344,8,0,576,192,6,0,280,GREEN>
|
||||
ObjectStructure <1,8,Diamond,392,8,0,576,240,6,0,280,GREEN>
|
||||
ObjectListEndlabelObjectStructure
|
||||
;
|
||||
Dataends
|
||||
|
|
@ -290,8 +290,8 @@ Start proc near
|
|||
int 10h ;BIOS video interrupt
|
||||
;
|
||||
; Set the palette up to provide bit-plane precedence. If
|
||||
; planes 0 & 1 overlap, the plane 0 color will be shown;
|
||||
; if planes 1 & 2 overlap, the plane 1 color will be
|
||||
; planes 0 & 1 overlap, the plane 0 color will be shown;
|
||||
; if planes 1 & 2 overlap, the plane 1 color will be
|
||||
; shown; and so on.
|
||||
;
|
||||
mov ax,(10h shl 8) + 2 ;AH = 10h means
|
||||
|
|
@ -368,7 +368,7 @@ CheckXRightLimit:
|
|||
neg [bx+XInc] ;yes-reverse
|
||||
SetNewX:
|
||||
add cx,[bx+XInc] ;move the X coord
|
||||
mov [bx+XCoord],cx ; & save it
|
||||
mov [bx+XCoord],cx ; & save it
|
||||
;
|
||||
; Advance the Y coordinate, reversing direction if either
|
||||
; of the Y margins has been reached.
|
||||
|
|
@ -383,7 +383,7 @@ CheckYBottomLimit:
|
|||
neg [bx+YInc] ;yes-reverse
|
||||
SetNewY:
|
||||
add dx,[bx+YInc] ;move the Y coord
|
||||
mov [bx+YCoord],dx ; & save it
|
||||
mov [bx+YCoord],dx ; & save it
|
||||
;
|
||||
; Draw at the new location. Because of the plane select
|
||||
; above, only one plane will be affected.
|
||||
|
|
@ -417,7 +417,7 @@ CheckKey:
|
|||
int 16h ;is a key waiting?
|
||||
jz AnimationLoop ;no
|
||||
sub ah,ah
|
||||
int 16h ;yes-clear the key & done
|
||||
int 16h ;yes-clear the key & done
|
||||
;
|
||||
; Back to text mode.
|
||||
;
|
||||
|
|
|
|||
90
44-02.html
90
44-02.html
|
|
@ -44,10 +44,10 @@ top portion of the screen while displaying non-page flipped
|
|||
information in the split screen at the bottom of the screen.
|
||||
Compiled with Borland C++ in C compilation mode. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
|
||||
#define SCREEN-SEG 0xA000
|
||||
#define SCREEN-PIXWIDTH 640 /* in pixels */
|
||||
|
|
@ -141,7 +141,7 @@ image BouncerRotation4 = {3, 20, -BouncerRotation4};
|
|||
/* Initial settings for bouncing object. Only 2 rotations are needed
|
||||
because the object moves 4 pixels horizontally at a time */
|
||||
bouncer Bouncer = {156,60,20,20,4,4,156,156,60,60,BOUNCER-COLOR,
|
||||
&BouncerRotation0,NULL,NULL,NULL,&BouncerRotation4,NULL,NULL,NULL};
|
||||
&BouncerRotation0,NULL,NULL,NULL,&BouncerRotation4,NULL,NULL,NULL};
|
||||
unsigned int PageStartOffsets[2] =
|
||||
{PAGE0-START-OFFSET,PAGE1-START-OFFSET};
|
||||
unsigned int BounceCount;
|
||||
|
|
@ -151,7 +151,7 @@ void main() {
|
|||
union REGS regset;
|
||||
|
||||
regset.x.ax = 0x0012; /* set display to 640x480 16-color mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
SetBIOS8x8Font(); /* set the pointer to the BIOS 8x8 font */
|
||||
EnableSplitScreen(); /* turn on the split screen */
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ void main() {
|
|||
ShowPage(PageStartOffsets[DisplayedPage = 0]);
|
||||
|
||||
/* Clear both pages to background and draw bumpers in each page */
|
||||
for (i=0; i<2; i++) {
|
||||
for (i=0; i<2; i++) {
|
||||
DrawRect(0,0,SCREEN-PIXWIDTH-1,NONSPLIT-LINES-1,BACK-COLOR,
|
||||
PageStartOffsets[i],SCREEN-SEG);
|
||||
DrawBumperList(Bumpers,NUM-BUMPERS,PageStartOffsets[i]);
|
||||
|
|
@ -170,7 +170,7 @@ void main() {
|
|||
ShowBounceCount(); /* put up the initial zero count */
|
||||
|
||||
/* Draw the bouncing object at its initial location */
|
||||
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
|
||||
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
|
||||
Bouncer.Color,PageStartOffsets[DisplayedPage],SCREEN-SEG);
|
||||
|
||||
/* Move the object, draw it in the nondisplayed page, and flip the
|
||||
|
|
@ -185,9 +185,9 @@ void main() {
|
|||
Bouncer.CurrentY[NonDisplayedPage]+Bouncer.Height-1,
|
||||
BACK-COLOR,PageStartOffsets[NonDisplayedPage],SCREEN-SEG);
|
||||
/* Move the bouncer */
|
||||
MoveBouncer(&Bouncer, Bumpers, NUM-BUMPERS);
|
||||
MoveBouncer(&Bouncer, Bumpers, NUM-BUMPERS);
|
||||
/* Draw at the new location in the nondisplayed page */
|
||||
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
|
||||
DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
|
||||
Bouncer.Color,PageStartOffsets[NonDisplayedPage],
|
||||
SCREEN-SEG);
|
||||
/* Remember where the bouncer is in the nondisplayed page */
|
||||
|
|
@ -220,7 +220,7 @@ void main() {
|
|||
|
||||
/* Restore text mode and done */
|
||||
regset.x.ax = 0x0003;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
/* Draws the specified list of bumpers into the specified page */
|
||||
|
|
@ -229,9 +229,9 @@ void DrawBumperList(bumper * Bumpers, int NumBumpers,
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NumBumpers; i++,Bumpers++) {
|
||||
DrawRect(Bumpers->LeftX,Bumpers->TopY,Bumpers->RightX,
|
||||
Bumpers->BottomY,Bumpers->Color,PageStartOffset,
|
||||
for (i=0; i<NumBumpers; i++,Bumpers++) {
|
||||
DrawRect(Bumpers->LeftX,Bumpers->TopY,Bumpers->RightX,
|
||||
Bumpers->BottomY,Bumpers->Color,PageStartOffset,
|
||||
SCREEN-SEG);
|
||||
}
|
||||
}
|
||||
|
|
@ -271,13 +271,13 @@ void DrawSplitScreen() {
|
|||
Overflow register, and bit 9 is in the Maximum Scan Line reg) */
|
||||
void EnableSplitScreen() {
|
||||
outp(CRTC-INDEX, LINE-COMPARE);
|
||||
outp(CRTC-DATA, (SPLIT-START-LINE - 1) & 0xFF);
|
||||
outp(CRTC-DATA, (SPLIT-START-LINE - 1) & 0xFF);
|
||||
outp(CRTC-INDEX, OVERFLOW);
|
||||
outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x100) >> 8) << 4) |
|
||||
(inp(CRTC-DATA) & ~0x10)));
|
||||
outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x100) >> 8) << 4) |
|
||||
(inp(CRTC-DATA) & ~0x10)));
|
||||
outp(CRTC-INDEX, MAX-SCAN);
|
||||
outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x200) >> 9) << 6) |
|
||||
(inp(CRTC-DATA) & ~0x40)));
|
||||
outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x200) >> 9) << 6) |
|
||||
(inp(CRTC-DATA) & ~0x40)));
|
||||
}
|
||||
|
||||
/* Moves the bouncer, bouncing if bumpers are hit */
|
||||
|
|
@ -285,37 +285,37 @@ void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) {
|
|||
int NewLeftX, NewTopY, NewRightX, NewBottomY, i;
|
||||
|
||||
/* Move to new location, bouncing if necessary */
|
||||
NewLeftX = Bouncer->LeftX + Bouncer->DirX; /* new coords */
|
||||
NewTopY = Bouncer->TopY + Bouncer->DirY;
|
||||
NewRightX = NewLeftX + Bouncer->Width - 1;
|
||||
NewBottomY = NewTopY + Bouncer->Height - 1;
|
||||
NewLeftX = Bouncer->LeftX + Bouncer->DirX; /* new coords */
|
||||
NewTopY = Bouncer->TopY + Bouncer->DirY;
|
||||
NewRightX = NewLeftX + Bouncer->Width - 1;
|
||||
NewBottomY = NewTopY + Bouncer->Height - 1;
|
||||
/* Compare the new location to all bumpers, checking for bounce */
|
||||
for (i=0; i<NumBumpers; i++,BumperPtr++) {
|
||||
for (i=0; i<NumBumpers; i++,BumperPtr++) {
|
||||
/* If moving puts the bouncer inside this bumper, bounce */
|
||||
if ( (NewLeftX <= BumperPtr->RightX) &&
|
||||
(NewRightX >= BumperPtr->LeftX) &&
|
||||
(NewTopY <= BumperPtr->BottomY) &&
|
||||
(NewBottomY >= BumperPtr->TopY) ) {
|
||||
if ( (NewLeftX <= BumperPtr->RightX) &&
|
||||
(NewRightX >= BumperPtr->LeftX) &&
|
||||
(NewTopY <= BumperPtr->BottomY) &&
|
||||
(NewBottomY >= BumperPtr->TopY) ) {
|
||||
/* The bouncer has tried to move into this bumper; figure
|
||||
out which edge(s) it crossed, and bounce accordingly */
|
||||
if (((Bouncer->LeftX > BumperPtr->RightX) &&
|
||||
(NewLeftX <= BumperPtr->RightX)) ||
|
||||
(((Bouncer->LeftX + Bouncer->Width - 1) <
|
||||
BumperPtr->LeftX) &&
|
||||
(NewRightX >= BumperPtr->LeftX))) {
|
||||
Bouncer->DirX = -Bouncer->DirX; /* bounce horizontally */
|
||||
NewLeftX = Bouncer->LeftX + Bouncer->DirX;
|
||||
if (((Bouncer->LeftX > BumperPtr->RightX) &&
|
||||
(NewLeftX <= BumperPtr->RightX)) ||
|
||||
(((Bouncer->LeftX + Bouncer->Width - 1) <
|
||||
BumperPtr->LeftX) &&
|
||||
(NewRightX >= BumperPtr->LeftX))) {
|
||||
Bouncer->DirX = -Bouncer->DirX; /* bounce horizontally */
|
||||
NewLeftX = Bouncer->LeftX + Bouncer->DirX;
|
||||
}
|
||||
if (((Bouncer->TopY > BumperPtr->BottomY) &&
|
||||
(NewTopY <= BumperPtr->BottomY)) ||
|
||||
(((Bouncer->TopY + Bouncer->Height - 1) <
|
||||
BumperPtr->TopY) &&
|
||||
(NewBottomY >= BumperPtr->TopY))) {
|
||||
Bouncer->DirY = -Bouncer->DirY; /* bounce vertically */
|
||||
NewTopY = Bouncer->TopY + Bouncer->DirY;
|
||||
if (((Bouncer->TopY > BumperPtr->BottomY) &&
|
||||
(NewTopY <= BumperPtr->BottomY)) ||
|
||||
(((Bouncer->TopY + Bouncer->Height - 1) <
|
||||
BumperPtr->TopY) &&
|
||||
(NewBottomY >= BumperPtr->TopY))) {
|
||||
Bouncer->DirY = -Bouncer->DirY; /* bounce vertically */
|
||||
NewTopY = Bouncer->TopY + Bouncer->DirY;
|
||||
}
|
||||
/* Update the bounce count display; turn over at 10000 */
|
||||
if (++BounceCount >= 10000) {
|
||||
if (++BounceCount >= 10000) {
|
||||
TextUp(“0 ”,344,64,SPLIT-START-OFFSET,SCREEN-SEG);
|
||||
BounceCount = 0;
|
||||
} else {
|
||||
|
|
@ -323,8 +323,8 @@ void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) {
|
|||
}
|
||||
}
|
||||
}
|
||||
Bouncer->LeftX = NewLeftX; /* set the final new coordinates */
|
||||
Bouncer->TopY = NewTopY;
|
||||
Bouncer->LeftX = NewLeftX; /* set the final new coordinates */
|
||||
Bouncer->TopY = NewTopY;
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ void main()
|
|||
}
|
||||
/* Set 320x200 256-color graphics mode */
|
||||
regs.x.ax = 0x0013;
|
||||
int86(0x10, &regs, &regs);
|
||||
int86(0x10, &regs, &regs);
|
||||
|
||||
/* Loop and draw until a key is pressed */
|
||||
do {
|
||||
|
|
@ -181,7 +181,7 @@ void main()
|
|||
getch(); /* clear the keypress */
|
||||
/* Back to text mode */
|
||||
regs.x.ax = 0x0003;
|
||||
int86(0x10, &regs, &regs);
|
||||
int86(0x10, &regs, &regs);
|
||||
}
|
||||
/* Draw entities at current locations, updating dirty rectangle list. */
|
||||
void DrawEntities()
|
||||
|
|
|
|||
|
|
@ -62,12 +62,12 @@ void Set640x400()
|
|||
|
||||
/* First, set to standard 640x350 mode (mode 10h) */
|
||||
regset.x.ax = 0x0010;
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
|
||||
/* Modify the sync polarity bits (bits 7 & 6) of the
|
||||
/* Modify the sync polarity bits (bits 7 & 6) of the
|
||||
Miscellaneous Output register (readable at 0x3CC, writable at
|
||||
0x3C2) to select the 400-scan-line vertical scanning rate */
|
||||
outp(0x3C2, ((inp(0x3CC) & 0x3F) | 0x40));
|
||||
outp(0x3C2, ((inp(0x3CC) & 0x3F) | 0x40));
|
||||
|
||||
/* Now, tweak the registers needed to convert the vertical
|
||||
timings from 350 to 400 scan lines */
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void main()
|
|||
|
||||
/* Return to text mode and exit */
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
|
||||
void Wait30Frames()
|
||||
|
|
@ -107,9 +107,9 @@ void Wait30Frames()
|
|||
|
||||
for (i=0; i<30; i++) {
|
||||
/* Wait until we’re not in vertical sync, so we can catch leading edge */
|
||||
while ((inp(INPUT_STATUS_1) & 0x08) != 0) ;
|
||||
while ((inp(INPUT_STATUS_1) & 0x08) != 0) ;
|
||||
/* Wait until we are in vertical sync */
|
||||
while ((inp(INPUT_STATUS_1) & 0x08) == 0) ;
|
||||
while ((inp(INPUT_STATUS_1) & 0x08) == 0) ;
|
||||
}
|
||||
}
|
||||
</PRE>
|
||||
|
|
@ -132,7 +132,7 @@ void Set640x400()
|
|||
regs.h.ah = 0x11; /* character generator function */
|
||||
regs.h.al = 0x24; /* use ROM 8x6 character set for graphics */
|
||||
regs.h.bl = 2; /* 25 rows */
|
||||
int86(0x10, &regs, &regs); /* invoke the BIOS video interrupt
|
||||
int86(0x10, &regs, &regs); /* invoke the BIOS video interrupt
|
||||
to set up the text */
|
||||
}
|
||||
</PRE>
|
||||
|
|
|
|||
140
46-02.html
140
46-02.html
|
|
@ -43,11 +43,11 @@
|
|||
featuring internal animation, masked images (sprites), and nonoverlapping dirty
|
||||
rectangle copying. Tested with Borland C++ in the small model. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
#include <alloc.h>
|
||||
#include <memory.h>
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
#include <alloc.h>
|
||||
#include <memory.h>
|
||||
#include <dos.h>
|
||||
|
||||
/* Comment out to disable overlap elimination in the dirty rectangle list. */
|
||||
#define CHECK-OVERLAP 1
|
||||
|
|
@ -176,25 +176,25 @@ void main()
|
|||
ScreenPtr = MK-FP(SCREEN-SEGMENT, 0);
|
||||
/* Set up the entities we’ll animate, at random locations */
|
||||
randomize();
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
Entities[i].X = random(SCREEN-WIDTH - IMAGE-WIDTH);
|
||||
Entities[i].Y = random(SCREEN-HEIGHT - IMAGE-HEIGHT);
|
||||
Entities[i].XDirection = 1;
|
||||
Entities[i].YDirection = -1;
|
||||
Entities[i].InternalAnimateCount = & 1;
|
||||
Entities[i].InternalAnimateCount = & 1;
|
||||
Entities[i].InternalAnimateMax = 2;
|
||||
}
|
||||
/* Set the dirty rectangle list to empty, and set up the head/tail node
|
||||
as a sentinel */
|
||||
NumDirtyRectangles = 0;
|
||||
DirtyHead.Next = &DirtyHead;
|
||||
DirtyHead.Next = &DirtyHead;
|
||||
DirtyHead.Top = 0x7FFF;
|
||||
DirtyHead.Left= 0x7FFF;
|
||||
DirtyHead.Bottom = 0x7FFF;
|
||||
DirtyHead.Right = 0x7FFF;
|
||||
/* Set 320x200 256-color graphics mode */
|
||||
regs.x.ax = 0x0013;
|
||||
int86(0x10, &regs, &regs);
|
||||
int86(0x10, &regs, &regs);
|
||||
/* Loop and draw until a key is pressed */
|
||||
do {
|
||||
/* Draw the entities to the system buffer at their current locations,
|
||||
|
|
@ -205,19 +205,19 @@ void main()
|
|||
CopyDirtyRectanglesToScreen();
|
||||
/* Reset the dirty rectangle list to empty */
|
||||
NumDirtyRectangles = 0;
|
||||
DirtyHead.Next = &DirtyHead;
|
||||
DirtyHead.Next = &DirtyHead;
|
||||
/* Erase the entities in the system buffer at their old locations,
|
||||
updating the dirty rectangle list */
|
||||
EraseEntities();
|
||||
/* Move the entities, bouncing off the edges of the screen */
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
XTemp = Entities[i].X + Entities[i].XDirection;
|
||||
YTemp = Entities[i].Y + Entities[i].YDirection;
|
||||
if ((XTemp < 0) || ((XTemp + IMAGE-WIDTH) > SCREEN-WIDTH)) {
|
||||
if ((XTemp < 0) || ((XTemp + IMAGE-WIDTH) > SCREEN-WIDTH)) {
|
||||
Entities[i].XDirection = -Entities[i].XDirection;
|
||||
XTemp = Entities[i].X + Entities[i].XDirection;
|
||||
}
|
||||
if ((YTemp < 0) || ((YTemp + IMAGE-HEIGHT) > SCREEN-HEIGHT)) {
|
||||
if ((YTemp < 0) || ((YTemp + IMAGE-HEIGHT) > SCREEN-HEIGHT)) {
|
||||
Entities[i].YDirection = -Entities[i].YDirection;
|
||||
YTemp = Entities[i].Y + Entities[i].YDirection;
|
||||
}
|
||||
|
|
@ -229,7 +229,7 @@ void main()
|
|||
|
||||
/* Return back to text mode */
|
||||
regs.x.ax = 0x0003;
|
||||
int86(0x10, &regs, &regs);
|
||||
int86(0x10, &regs, &regs);
|
||||
}
|
||||
/* Draw entities at their current locations, updating dirty rectangle list. */
|
||||
void DrawEntities()
|
||||
|
|
@ -240,20 +240,20 @@ void DrawEntities()
|
|||
char *TempPtrMask;
|
||||
Entity *EntityPtr;
|
||||
|
||||
for (= 0, EntityPtr = Entities; < NUM-ENTITIES; i++, EntityPtr++) {
|
||||
for (= 0, EntityPtr = Entities; < NUM-ENTITIES; i++, EntityPtr++) {
|
||||
/* Remember the dirty rectangle info for this entity */
|
||||
AddDirtyRect(EntityPtr, IMAGE-HEIGHT, IMAGE-WIDTH);
|
||||
/* Point to the destination in the system buffer */
|
||||
RowPtrBuffer = SystemBufferPtr + (EntityPtr->Y * SCREEN-WIDTH) +
|
||||
EntityPtr->X;
|
||||
RowPtrBuffer = SystemBufferPtr + (EntityPtr->Y * SCREEN-WIDTH) +
|
||||
EntityPtr->X;
|
||||
/* Advance the image animation pointer */
|
||||
if (++EntityPtr->InternalAnimateCount >=
|
||||
EntityPtr->InternalAnimateMax) {
|
||||
EntityPtr->InternalAnimateCount = 0;
|
||||
if (++EntityPtr->InternalAnimateCount >=
|
||||
EntityPtr->InternalAnimateMax) {
|
||||
EntityPtr->InternalAnimateCount = 0;
|
||||
}
|
||||
/* Point to the image and mask to draw */
|
||||
TempPtrImage = ImagePixelArray[EntityPtr->InternalAnimateCount];
|
||||
TempPtrMask = ImageMaskArray[EntityPtr->InternalAnimateCount];
|
||||
TempPtrImage = ImagePixelArray[EntityPtr->InternalAnimateCount];
|
||||
TempPtrMask = ImageMaskArray[EntityPtr->InternalAnimateCount];
|
||||
DrawMasked(RowPtrBuffer, TempPtrImage, TempPtrMask, IMAGE-HEIGHT,
|
||||
IMAGE-WIDTH, SCREEN-WIDTH);
|
||||
}
|
||||
|
|
@ -274,18 +274,18 @@ void CopyDirtyRectanglesToScreen()
|
|||
/* Copy only the dirty rectangles, in the YX-sorted order in which
|
||||
they’re linked */
|
||||
DirtyPtr = DirtyHead.Next;
|
||||
for (= 0; < NumDirtyRectangles; i++) {
|
||||
for (= 0; < NumDirtyRectangles; i++) {
|
||||
/* Offset in both system buffer and screen of image */
|
||||
Offset = (unsigned int) (DirtyPtr->Top * SCREEN-WIDTH) +
|
||||
DirtyPtr->Left;
|
||||
Offset = (unsigned int) (DirtyPtr->Top * SCREEN-WIDTH) +
|
||||
DirtyPtr->Left;
|
||||
/* Dimensions of dirty rectangle */
|
||||
RectWidth = DirtyPtr->Right - DirtyPtr->Left;
|
||||
RectHeight = DirtyPtr->Bottom - DirtyPtr->Top;
|
||||
RectWidth = DirtyPtr->Right - DirtyPtr->Left;
|
||||
RectHeight = DirtyPtr->Bottom - DirtyPtr->Top;
|
||||
/* Copy a dirty rectangle */
|
||||
CopyRect(ScreenPtr + Offset, SystemBufferPtr + Offset,
|
||||
RectHeight, RectWidth, SCREEN-WIDTH, SCREEN-WIDTH);
|
||||
/* Point to the next dirty rectangle */
|
||||
DirtyPtr = DirtyPtr->Next;
|
||||
DirtyPtr = DirtyPtr->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -296,9 +296,9 @@ void EraseEntities()
|
|||
int i;
|
||||
char far *RowPtr;
|
||||
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
for (= 0; < NUM-ENTITIES; i++) {
|
||||
/* Remember the dirty rectangle info for this entity */
|
||||
AddDirtyRect(&Entities[i], IMAGE-HEIGHT, IMAGE-WIDTH);
|
||||
AddDirtyRect(&Entities[i], IMAGE-HEIGHT, IMAGE-WIDTH);
|
||||
/* Point to the destination in the system buffer */
|
||||
RowPtr = SystemBufferPtr + (Entities[i].Y * SCREEN-WIDTH) +
|
||||
Entities[i].X;
|
||||
|
|
@ -321,7 +321,7 @@ void EraseEntities()
|
|||
DirtyRectangle * TempPtr;
|
||||
Entity TempEntity;
|
||||
int i;
|
||||
if (NumDirtyRectangles >= MAX-DIRTY-RECTANGLES) {
|
||||
if (NumDirtyRectangles >= MAX-DIRTY-RECTANGLES) {
|
||||
/* Too many dirty rectangles; just redraw the whole screen */
|
||||
DrawWholeScreen = 1;
|
||||
return;
|
||||
|
|
@ -332,53 +332,53 @@ void EraseEntities()
|
|||
#ifdef CHECK-OVERLAP
|
||||
/* Check for overlap with existing rectangles */
|
||||
TempPtr = DirtyHead.Next;
|
||||
for (= 0; < NumDirtyRectangles; i++, TempPtr = TempPtr->Next) {
|
||||
if ((TempPtr->Left < (pEntity->X + ImageWidth)) &&
|
||||
(TempPtr->Right > pEntity->X) &&
|
||||
(TempPtr->Top < (pEntity->Y + ImageHeight)) &&
|
||||
(TempPtr->Bottom > pEntity->Y)) {
|
||||
for (= 0; < NumDirtyRectangles; i++, TempPtr = TempPtr->Next) {
|
||||
if ((TempPtr->Left < (pEntity->X + ImageWidth)) &&
|
||||
(TempPtr->Right > pEntity->X) &&
|
||||
(TempPtr->Top < (pEntity->Y + ImageHeight)) &&
|
||||
(TempPtr->Bottom > pEntity->Y)) {
|
||||
|
||||
/* We’ve found an overlapping rectangle. Calculate the
|
||||
rectangles, if any, remaining after subtracting out the
|
||||
overlapped areas, and add them to the dirty list */
|
||||
/* Check for a nonoverlapped left portion */
|
||||
if (TempPtr->Left > pEntity->X) {
|
||||
if (TempPtr->Left > pEntity->X) {
|
||||
/* There’s definitely a nonoverlapped portion at the left; add
|
||||
it, but only to at most the top and bottom of the overlapping
|
||||
rect; top and bottom strips are taken care of below */
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = max(pEntity->Y, TempPtr->Top);
|
||||
AddDirtyRect(&TempEntity,
|
||||
min(pEntity->Y + ImageHeight, TempPtr->Bottom) -
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = max(pEntity->Y, TempPtr->Top);
|
||||
AddDirtyRect(&TempEntity,
|
||||
min(pEntity->Y + ImageHeight, TempPtr->Bottom) -
|
||||
TempEntity.Y,
|
||||
TempPtr->Left - pEntity->X);
|
||||
TempPtr->Left - pEntity->X);
|
||||
}
|
||||
/* Check for a nonoverlapped right portion */
|
||||
if (TempPtr->Right < (pEntity->X + ImageWidth)) {
|
||||
if (TempPtr->Right < (pEntity->X + ImageWidth)) {
|
||||
/* There’s definitely a nonoverlapped portion at the right; add
|
||||
it, but only to at most the top and bottom of the overlapping
|
||||
rect; top and bottom strips are taken care of below */
|
||||
TempEntity.X = TempPtr->Right;
|
||||
TempEntity.Y = max(pEntity->Y, TempPtr->Top);
|
||||
AddDirtyRect(&TempEntity,
|
||||
min(pEntity->Y + ImageHeight, TempPtr->Bottom) -
|
||||
TempEntity.X = TempPtr->Right;
|
||||
TempEntity.Y = max(pEntity->Y, TempPtr->Top);
|
||||
AddDirtyRect(&TempEntity,
|
||||
min(pEntity->Y + ImageHeight, TempPtr->Bottom) -
|
||||
TempEntity.Y,
|
||||
(pEntity->X + ImageWidth) - TempPtr->Right);
|
||||
(pEntity->X + ImageWidth) - TempPtr->Right);
|
||||
}
|
||||
/* Check for a nonoverlapped top portion */
|
||||
if (TempPtr->Top > pEntity->Y) {
|
||||
if (TempPtr->Top > pEntity->Y) {
|
||||
/* There’s a top portion that’s not overlapped */
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = pEntity->Y;
|
||||
AddDirtyRect(&TempEntity, TempPtr->Top - pEntity->Y, ImageWidth);
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = pEntity->Y;
|
||||
AddDirtyRect(&TempEntity, TempPtr->Top - pEntity->Y, ImageWidth);
|
||||
}
|
||||
/* Check for a nonoverlapped bottom portion */
|
||||
if (TempPtr->Bottom < (pEntity->Y + ImageHeight)) {
|
||||
if (TempPtr->Bottom < (pEntity->Y + ImageHeight)) {
|
||||
/* There’s a bottom portion that’s not overlapped */
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = TempPtr->Bottom;
|
||||
AddDirtyRect(&TempEntity,
|
||||
(pEntity->Y + ImageHeight) - TempPtr->Bottom, ImageWidth);
|
||||
TempEntity.X = pEntity->X;
|
||||
TempEntity.Y = TempPtr->Bottom;
|
||||
AddDirtyRect(&TempEntity,
|
||||
(pEntity->Y + ImageHeight) - TempPtr->Bottom, ImageWidth);
|
||||
}
|
||||
/* We’ve added all non-overlapped portions to the dirty list */
|
||||
return;
|
||||
|
|
@ -389,22 +389,22 @@ void EraseEntities()
|
|||
add this rectangle as-is */
|
||||
/* Find the YX-sorted insertion point. Searches will always terminate,
|
||||
because the head/tail rectangle is set to the maximum values */
|
||||
TempPtr = &DirtyHead;
|
||||
while (((DirtyRectangle *)TempPtr->Next)->Top < pEntity->Y) {
|
||||
TempPtr = TempPtr->Next;
|
||||
TempPtr = &DirtyHead;
|
||||
while (((DirtyRectangle *)TempPtr->Next)->Top < pEntity->Y) {
|
||||
TempPtr = TempPtr->Next;
|
||||
}
|
||||
while ((((DirtyRectangle *)TempPtr->Next)->Top == pEntity->Y) &&
|
||||
(((DirtyRectangle *)TempPtr->Next)->Left < pEntity->X)) {
|
||||
TempPtr = TempPtr->Next;
|
||||
while ((((DirtyRectangle *)TempPtr->Next)->Top == pEntity->Y) &&
|
||||
(((DirtyRectangle *)TempPtr->Next)->Left < pEntity->X)) {
|
||||
TempPtr = TempPtr->Next;
|
||||
}
|
||||
/* Set the rectangle and actually add it to the dirty list */
|
||||
DirtyPtr = &DirtyRectangles[NumDirtyRectangles++];
|
||||
DirtyPtr->Left = pEntity->X;
|
||||
DirtyPtr->Top = pEntity->Y;
|
||||
DirtyPtr->Right = pEntity->X + ImageWidth;
|
||||
DirtyPtr->Bottom = pEntity->Y + ImageHeight;
|
||||
DirtyPtr->Next = TempPtr->Next;
|
||||
TempPtr->Next = DirtyPtr;
|
||||
DirtyPtr = &DirtyRectangles[NumDirtyRectangles++];
|
||||
DirtyPtr->Left = pEntity->X;
|
||||
DirtyPtr->Top = pEntity->Y;
|
||||
DirtyPtr->Right = pEntity->X + ImageWidth;
|
||||
DirtyPtr->Bottom = pEntity->Y + ImageHeight;
|
||||
DirtyPtr->Next = TempPtr->Next;
|
||||
TempPtr->Next = DirtyPtr;
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ void main() {
|
|||
}
|
||||
getch();
|
||||
regset.x.ax = 0x0003; /* switch back to text mode and done */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
10
48-01.html
10
48-01.html
|
|
@ -58,8 +58,8 @@
|
|||
rectangle fills by filling the screen with adjacent 80x60
|
||||
rectangles in a variety of patterns. Tested with Borland C++
|
||||
in C compilation mode and the small model */
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
|
||||
void Set320x240Mode(void);
|
||||
void FillPatternX(int, int, int, int, unsigned int, char*);
|
||||
|
|
@ -89,14 +89,14 @@ void main() {
|
|||
union REGS regset;
|
||||
|
||||
Set320x240Mode();
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
FillPatternX(i*80,j*60,i*80+80,j*60+60,0,PattTable[j*4+i]);
|
||||
}
|
||||
}
|
||||
getch();
|
||||
regset.x.ax = 0x0003; /* switch back to text mode and done */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ DoRightEdge:
|
|||
; latches)
|
||||
CopyLoopBottom:
|
||||
add si,[bp+SourceNextScanOffset] ;point to the start of
|
||||
add di,[bp+DestNextScanOffset] ; next source & dest lines
|
||||
add di,[bp+DestNextScanOffset] ; next source & dest lines
|
||||
dec word ptr [bp+Height] ;count down scan lines
|
||||
jnz CopyRowsLoop
|
||||
CopyDone:
|
||||
|
|
|
|||
48
49-04.html
48
49-04.html
|
|
@ -134,26 +134,26 @@ typedef struct {
|
|||
MaskedImage *Image;
|
||||
} AnimatedObject;
|
||||
AnimatedObject AnimatedObjects[] = {
|
||||
{ 0, 0,KITE_WIDTH,KITE_HEIGHT, 1, 1, 0, 0,&KiteImage},
|
||||
{ 10, 10,KITE_WIDTH,KITE_HEIGHT, 0, 1, 10, 10,&KiteImage},
|
||||
{ 20, 20,KITE_WIDTH,KITE_HEIGHT,-1, 1, 20, 20,&KiteImage},
|
||||
{ 30, 30,KITE_WIDTH,KITE_HEIGHT,-1,-1, 30, 30,&KiteImage},
|
||||
{ 40, 40,KITE_WIDTH,KITE_HEIGHT, 1,-1, 40, 40,&KiteImage},
|
||||
{ 50, 50,KITE_WIDTH,KITE_HEIGHT, 0,-1, 50, 50,&KiteImage},
|
||||
{ 60, 60,KITE_WIDTH,KITE_HEIGHT, 1, 0, 60, 60,&KiteImage},
|
||||
{ 70, 70,KITE_WIDTH,KITE_HEIGHT,-1, 0, 70, 70,&KiteImage},
|
||||
{ 80, 80,KITE_WIDTH,KITE_HEIGHT, 1, 2, 80, 80,&KiteImage},
|
||||
{ 90, 90,KITE_WIDTH,KITE_HEIGHT, 0, 2, 90, 90,&KiteImage},
|
||||
{100,100,KITE_WIDTH,KITE_HEIGHT,-1, 2,100,100,&KiteImage},
|
||||
{110,110,KITE_WIDTH,KITE_HEIGHT,-1,-2,110,110,&KiteImage},
|
||||
{120,120,KITE_WIDTH,KITE_HEIGHT, 1,-2,120,120,&KiteImage},
|
||||
{130,130,KITE_WIDTH,KITE_HEIGHT, 0,-2,130,130,&KiteImage},
|
||||
{140,140,KITE_WIDTH,KITE_HEIGHT, 2, 0,140,140,&KiteImage},
|
||||
{150,150,KITE_WIDTH,KITE_HEIGHT,-2, 0,150,150,&KiteImage},
|
||||
{160,160,KITE_WIDTH,KITE_HEIGHT, 2, 2,160,160,&KiteImage},
|
||||
{170,170,KITE_WIDTH,KITE_HEIGHT,-2, 2,170,170,&KiteImage},
|
||||
{180,180,KITE_WIDTH,KITE_HEIGHT,-2,-2,180,180,&KiteImage},
|
||||
{190,190,KITE_WIDTH,KITE_HEIGHT, 2,-2,190,190,&KiteImage},
|
||||
{ 0, 0,KITE_WIDTH,KITE_HEIGHT, 1, 1, 0, 0,&KiteImage},
|
||||
{ 10, 10,KITE_WIDTH,KITE_HEIGHT, 0, 1, 10, 10,&KiteImage},
|
||||
{ 20, 20,KITE_WIDTH,KITE_HEIGHT,-1, 1, 20, 20,&KiteImage},
|
||||
{ 30, 30,KITE_WIDTH,KITE_HEIGHT,-1,-1, 30, 30,&KiteImage},
|
||||
{ 40, 40,KITE_WIDTH,KITE_HEIGHT, 1,-1, 40, 40,&KiteImage},
|
||||
{ 50, 50,KITE_WIDTH,KITE_HEIGHT, 0,-1, 50, 50,&KiteImage},
|
||||
{ 60, 60,KITE_WIDTH,KITE_HEIGHT, 1, 0, 60, 60,&KiteImage},
|
||||
{ 70, 70,KITE_WIDTH,KITE_HEIGHT,-1, 0, 70, 70,&KiteImage},
|
||||
{ 80, 80,KITE_WIDTH,KITE_HEIGHT, 1, 2, 80, 80,&KiteImage},
|
||||
{ 90, 90,KITE_WIDTH,KITE_HEIGHT, 0, 2, 90, 90,&KiteImage},
|
||||
{100,100,KITE_WIDTH,KITE_HEIGHT,-1, 2,100,100,&KiteImage},
|
||||
{110,110,KITE_WIDTH,KITE_HEIGHT,-1,-2,110,110,&KiteImage},
|
||||
{120,120,KITE_WIDTH,KITE_HEIGHT, 1,-2,120,120,&KiteImage},
|
||||
{130,130,KITE_WIDTH,KITE_HEIGHT, 0,-2,130,130,&KiteImage},
|
||||
{140,140,KITE_WIDTH,KITE_HEIGHT, 2, 0,140,140,&KiteImage},
|
||||
{150,150,KITE_WIDTH,KITE_HEIGHT,-2, 0,150,150,&KiteImage},
|
||||
{160,160,KITE_WIDTH,KITE_HEIGHT, 2, 2,160,160,&KiteImage},
|
||||
{170,170,KITE_WIDTH,KITE_HEIGHT,-2, 2,170,170,&KiteImage},
|
||||
{180,180,KITE_WIDTH,KITE_HEIGHT,-2,-2,180,180,&KiteImage},
|
||||
{190,190,KITE_WIDTH,KITE_HEIGHT, 2,-2,190,190,&KiteImage},
|
||||
};
|
||||
void main(void);
|
||||
void DrawBackground(unsigned int);
|
||||
|
|
@ -177,9 +177,9 @@ void main()
|
|||
union REGS regset;
|
||||
Set320x240Mode();
|
||||
/* Download the kite image for fast copying later. */
|
||||
if (CreateAlignedMaskedImage(&KiteImage, DOWNLOAD_START_OFFSET,
|
||||
if (CreateAlignedMaskedImage(&KiteImage, DOWNLOAD_START_OFFSET,
|
||||
KitePixels, KITE_WIDTH, KITE_HEIGHT, KiteMask) == 0) {
|
||||
regset.x.ax = 0x0003; int86(0x10, &regset, &regset);
|
||||
regset.x.ax = 0x0003; int86(0x10, &regset, &regset);
|
||||
printf(“Couldn’t get memory\n”); exit();
|
||||
}
|
||||
/* Draw the background to the background page. */
|
||||
|
|
@ -209,7 +209,7 @@ void main()
|
|||
}
|
||||
/* Move and draw each object in the nondisplayed page. */
|
||||
for (i=0; i<NUM_OBJECTS; i++) {
|
||||
MoveObject(&AnimatedObjects[i]);
|
||||
MoveObject(&AnimatedObjects[i]);
|
||||
/* Draw object into nondisplayed page at new location */
|
||||
CopyScreenToScreenMaskedX(0, 0, AnimatedObjects[i].Width,
|
||||
AnimatedObjects[i].Height, AnimatedObjects[i].X,
|
||||
|
|
@ -224,7 +224,7 @@ void main()
|
|||
}
|
||||
} while (!Done);
|
||||
/* Restore text mode and done. */
|
||||
regset.x.ax = 0x0003; int86(0x10, &regset, &regset);
|
||||
regset.x.ax = 0x0003; int86(0x10, &regset, &regset);
|
||||
}
|
||||
void DrawBackground(unsigned int PageStart)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ HLinePtr dw ? ;pointer to list of horz lines
|
|||
HLineList ends
|
||||
|
||||
Parms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
HLineListPtr dw ? ;pointer to HLineList structure
|
||||
Color dw ? ;color with which to fill
|
||||
Parms ends
|
||||
|
|
@ -149,10 +149,10 @@ MaxXNotClipped:
|
|||
add di,dx ;offset of first rect pixel in display mem
|
||||
mov dx,si ;XStart
|
||||
and si,0003h ;look up left-edge plane mask
|
||||
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
|
||||
mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
|
||||
mov si,cx
|
||||
and si,0003h ;look up right-edge plane
|
||||
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
|
||||
mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
|
||||
and dx,not 011b ;calculate # of addresses across rect
|
||||
sub cx,dx
|
||||
shr cx,1
|
||||
|
|
|
|||
32
50-04.html
32
50-04.html
|
|
@ -59,9 +59,9 @@ void XformVec(double Xform[4][4], double * SourceVec,
|
|||
{
|
||||
int i,j;
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
for (i=0; i<4; i++) {
|
||||
DestVec[i] = 0;
|
||||
for (j=0; j<4; j++)
|
||||
for (j=0; j<4; j++)
|
||||
DestVec[i] += Xform[i][j] * SourceVec[j];
|
||||
}
|
||||
}
|
||||
|
|
@ -79,10 +79,10 @@ void ConcatXforms(double SourceXform1[4][4], double SourceXform2[4][4],
|
|||
{
|
||||
int i,j,k;
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
for (i=0; i<4; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
DestXform[i][j] = 0;
|
||||
for (k=0; k<4; k++)
|
||||
for (k=0; k<4; k++)
|
||||
DestXform[i][j] += SourceXform1[i][k] * SourceXform2[k][j];
|
||||
}
|
||||
}
|
||||
|
|
@ -110,10 +110,10 @@ void XformAndProjectPoly(double Xform[4][4], struct Point3 * Poly,
|
|||
struct PointListHeader Polygon;
|
||||
|
||||
/* Transform to view space, then project to the screen */
|
||||
for (i=0; i<PolyLength; i++) {
|
||||
for (i=0; i<PolyLength; i++) {
|
||||
/* Transform to view space */
|
||||
XformVec(Xform, (double *)&Poly[i], (double *)&XformedPoly[i]);
|
||||
/* Project the X & Y coordinates to the screen, rounding to the
|
||||
XformVec(Xform, (double *)&Poly[i], (double *)&XformedPoly[i]);
|
||||
/* Project the X & Y coordinates to the screen, rounding to the
|
||||
nearest integral coordinates. The Y coordinate is negated to
|
||||
flip from view space, where increasing Y is up, to screen
|
||||
space, where increasing Y is down. Add in half the screen
|
||||
|
|
@ -125,20 +125,20 @@ void XformAndProjectPoly(double Xform[4][4], struct Point3 * Poly,
|
|||
SCREEN_HEIGHT/2;
|
||||
/* Appropriately adjust the extent of the rectangle used to
|
||||
erase this page later */
|
||||
if (ProjectedPoly[i].X > EraseRect[NonDisplayedPage].Right)
|
||||
if (ProjectedPoly[i].X < SCREEN_WIDTH)
|
||||
if (ProjectedPoly[i].X > EraseRect[NonDisplayedPage].Right)
|
||||
if (ProjectedPoly[i].X < SCREEN_WIDTH)
|
||||
EraseRect[NonDisplayedPage].Right = ProjectedPoly[i].X;
|
||||
else EraseRect[NonDisplayedPage].Right = SCREEN_WIDTH;
|
||||
if (ProjectedPoly[i].Y > EraseRect[NonDisplayedPage].Bottom)
|
||||
if (ProjectedPoly[i].Y < SCREEN_HEIGHT)
|
||||
if (ProjectedPoly[i].Y > EraseRect[NonDisplayedPage].Bottom)
|
||||
if (ProjectedPoly[i].Y < SCREEN_HEIGHT)
|
||||
EraseRect[NonDisplayedPage].Bottom = ProjectedPoly[i].Y;
|
||||
else EraseRect[NonDisplayedPage].Bottom = SCREEN_HEIGHT;
|
||||
if (ProjectedPoly[i].X < EraseRect[NonDisplayedPage].Left)
|
||||
if (ProjectedPoly[i].X > 0)
|
||||
if (ProjectedPoly[i].X < EraseRect[NonDisplayedPage].Left)
|
||||
if (ProjectedPoly[i].X > 0)
|
||||
EraseRect[NonDisplayedPage].Left = ProjectedPoly[i].X;
|
||||
else EraseRect[NonDisplayedPage].Left = 0;
|
||||
if (ProjectedPoly[i].Y < EraseRect[NonDisplayedPage].Top)
|
||||
if (ProjectedPoly[i].Y > 0)
|
||||
if (ProjectedPoly[i].Y < EraseRect[NonDisplayedPage].Top)
|
||||
if (ProjectedPoly[i].Y > 0)
|
||||
EraseRect[NonDisplayedPage].Top = ProjectedPoly[i].Y;
|
||||
else EraseRect[NonDisplayedPage].Top = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
#define DRAW_POLYGON(PointList,NumPoints,Color,X,Y) \
|
||||
Polygon.Length = NumPoints; \
|
||||
Polygon.PointPtr = PointList; \
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
|
||||
/* Describes a single 2-D point */
|
||||
struct Point {
|
||||
|
|
|
|||
14
50-06.html
14
50-06.html
|
|
@ -45,10 +45,10 @@
|
|||
the direction of increasingly negative Z. A right-handed
|
||||
coordinate system is used throughout.
|
||||
Tested with Borland C++ in the small model. */
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
void main(void);
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ void main() {
|
|||
/* Flip to display the page into which we just drew */
|
||||
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
|
||||
/* Rotate 6 degrees farther around the Y axis */
|
||||
if ((Rotation += (M_PI/30.0)) >= (M_PI*2)) Rotation -= M_PI*2;
|
||||
if ((Rotation += (M_PI/30.0)) >= (M_PI*2)) Rotation -= M_PI*2;
|
||||
if (kbhit()) {
|
||||
switch (getch()) {
|
||||
case 0x1B: /* Esc to exit */
|
||||
|
|
@ -134,7 +134,7 @@ void main() {
|
|||
PolyWorldXform[2][3] -= 3.0; break;
|
||||
case ‘T’: /* towards (+Z). Don’t allow to get too */
|
||||
case ‘t’: /* close, so Z clipping isn’t needed */
|
||||
if (PolyWorldXform[2][3] < -40.0)
|
||||
if (PolyWorldXform[2][3] < -40.0)
|
||||
PolyWorldXform[2][3] += 3.0; break;
|
||||
case 0: /* extended code */
|
||||
switch (getch()) {
|
||||
|
|
@ -157,7 +157,7 @@ void main() {
|
|||
} while (!Done);
|
||||
/* Return to text mode and exit */
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
16
51-03.html
16
51-03.html
|
|
@ -43,9 +43,9 @@
|
|||
is fixed at the origin (0,0,0) of world space, looking in the direction of
|
||||
increasingly negative Z. A right-handed coordinate system is used throughout.
|
||||
All C code tested with Borland C++ in C compilation mode. */
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
#define ROTATION (M_PI / 30.0) /* rotate by 6 degrees at a time */
|
||||
|
|
@ -121,12 +121,12 @@ void main() {
|
|||
/* Keep transforming the cube, drawing it to the undisplayed page,
|
||||
and flipping the page to show it */
|
||||
do {
|
||||
/* Regenerate the object->view transformation and
|
||||
/* Regenerate the object->view transformation and
|
||||
retransform/project if necessary */
|
||||
if (RecalcXform) {
|
||||
ConcatXforms(WorldViewXform, CubeWorldXform, WorkingXform);
|
||||
/* Transform and project all the vertices in the cube */
|
||||
XformAndProjectPoints(WorkingXform, &Cube);
|
||||
XformAndProjectPoints(WorkingXform, &Cube);
|
||||
RecalcXform = 0;
|
||||
}
|
||||
CurrentPageBase = /* select other page for drawing to */
|
||||
|
|
@ -142,7 +142,7 @@ void main() {
|
|||
EraseRect[NonDisplayedPage].Right =
|
||||
EraseRect[NonDisplayedPage].Bottom = 0;
|
||||
/* Draw all visible faces of the cube */
|
||||
DrawVisibleFaces(&Cube);
|
||||
DrawVisibleFaces(&Cube);
|
||||
/* Flip to display the page into which we just drew */
|
||||
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
|
||||
while (kbhit()) {
|
||||
|
|
@ -153,7 +153,7 @@ void main() {
|
|||
CubeWorldXform[2][3] -= 3.0; RecalcXform = 1; break;
|
||||
case ‘T’: /* towards (+Z). Don’t allow to get too */
|
||||
case ‘t’: /* close, so Z clipping isn’t needed */
|
||||
if (CubeWorldXform[2][3] < -40.0) {
|
||||
if (CubeWorldXform[2][3] < -40.0) {
|
||||
CubeWorldXform[2][3] += 3.0;
|
||||
RecalcXform = 1;
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ void main() {
|
|||
} while (!Done);
|
||||
/* Return to text mode and exit */
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
58
51-04.html
58
51-04.html
|
|
@ -42,34 +42,34 @@
|
|||
/* Transforms all vertices in the specified object into view spa ce, then
|
||||
perspective projects them to screen space and maps them to screen coordinates,
|
||||
storing the results in the object. */
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”/
|
||||
|
||||
void XformAndProjectPoints(double Xform[4][4],
|
||||
struct Object * ObjectToXform)
|
||||
{
|
||||
int i, NumPoints = ObjectToXform->NumVerts;
|
||||
struct Point3 * Points = ObjectToXform->VertexList;
|
||||
struct Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
||||
struct Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
int i, NumPoints = ObjectToXform->NumVerts;
|
||||
struct Point3 * Points = ObjectToXform->VertexList;
|
||||
struct Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
||||
struct Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
|
||||
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
||||
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
||||
ProjectedPoints++, ScreenPoints++) {
|
||||
/* Transform to view space */
|
||||
XformVec(Xform, (double *)Points, (double *)XformedPoints);
|
||||
/* Perspective-project to screen space */
|
||||
ProjectedPoints->X = XformedPoints->X / XformedPoints->Z *
|
||||
ProjectedPoints->X = XformedPoints->X / XformedPoints->Z *
|
||||
PROJECTION_RATIO * (SCREEN_WIDTH / 2.0);
|
||||
ProjectedPoints->Y = XformedPoints->Y / XformedPoints->Z *
|
||||
ProjectedPoints->Y = XformedPoints->Y / XformedPoints->Z *
|
||||
PROJECTION_RATIO * (SCREEN_WIDTH / 2.0);
|
||||
ProjectedPoints->Z = XformedPoints->Z;
|
||||
ProjectedPoints->Z = XformedPoints->Z;
|
||||
/* Convert to screen coordinates. The Y coord is negated to
|
||||
flip from increasing Y being up to increasing Y being down,
|
||||
as expected by the polygon filler. Add in half the screen
|
||||
width and height to center on the screen. */
|
||||
ScreenPoints->X = ((int) floor(ProjectedPoints->X + 0.5)) + SCREEN_WIDTH/2;
|
||||
ScreenPoints->Y = (-((int) floor(ProjectedPoints->Y + 0.5))) +
|
||||
ScreenPoints->X = ((int) floor(ProjectedPoints->X + 0.5)) + SCREEN_WIDTH/2;
|
||||
ScreenPoints->Y = (-((int) floor(ProjectedPoints->Y + 0.5))) +
|
||||
SCREEN_HEIGHT/2;
|
||||
}
|
||||
}
|
||||
|
|
@ -85,19 +85,19 @@ void XformAndProjectPoints(double Xform[4][4],
|
|||
|
||||
void DrawVisibleFaces(struct Object * ObjectToXform)
|
||||
{
|
||||
int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
|
||||
int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
|
||||
int * VertNumsPtr;
|
||||
struct Face * FacePtr = ObjectToXform->FaceList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
struct Face * FacePtr = ObjectToXform->FaceList;
|
||||
struct Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
long v1,v2,w1,w2;
|
||||
struct Point Vertices[MAX_POLY_LENGTH];
|
||||
struct PointListHeader Polygon;
|
||||
|
||||
/* Draw each visible face (polygon) of the object in turn */
|
||||
for (i=0; i<NumFaces; i++, FacePtr++) {
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
for (i=0; i<NumFaces; i++, FacePtr++) {
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
/* Copy over the face’s vertices from the vertex list */
|
||||
for (j=0, VertNumsPtr=FacePtr->VertNums; j<NumVertices; j++)
|
||||
for (j=0, VertNumsPtr=FacePtr->VertNums; j<NumVertices; j++)
|
||||
Vertices[j] = ScreenPoints[*VertNumsPtr++];
|
||||
/* Draw only if outside face showing (if the normal to the
|
||||
polygon points toward the viewer; that is, has a positive
|
||||
|
|
@ -106,30 +106,30 @@ void DrawVisibleFaces(struct Object * ObjectToXform)
|
|||
w1 = Vertices[NumVertices-1].X - Vertices[0].X;
|
||||
v2 = Vertices[1].Y - Vertices[0].Y;
|
||||
w2 = Vertices[NumVertices-1].Y - Vertices[0].Y;
|
||||
if ((v1*w2 - v2*w1) > 0) {
|
||||
if ((v1*w2 - v2*w1) > 0) {
|
||||
/* It is facing the screen, so draw */
|
||||
/* Appropriately adjust the extent of the rectangle used to
|
||||
erase this page later */
|
||||
for (j=0; j<NumVertices; j++) {
|
||||
if (Vertices[j].X > EraseRect[NonDisplayedPage].Right)
|
||||
if (Vertices[j].X < SCREEN_WIDTH)
|
||||
for (j=0; j<NumVertices; j++) {
|
||||
if (Vertices[j].X > EraseRect[NonDisplayedPage].Right)
|
||||
if (Vertices[j].X < SCREEN_WIDTH)
|
||||
EraseRect[NonDisplayedPage].Right = Vertices[j].X;
|
||||
else EraseRect[NonDisplayedPage].Right = SCREEN_WIDTH;
|
||||
if (Vertices[j].Y > EraseRect[NonDisplayedPage].Bottom)
|
||||
if (Vertices[j].Y < SCREEN_HEIGHT)
|
||||
if (Vertices[j].Y > EraseRect[NonDisplayedPage].Bottom)
|
||||
if (Vertices[j].Y < SCREEN_HEIGHT)
|
||||
EraseRect[NonDisplayedPage].Bottom = Vertices[j].Y;
|
||||
else EraseRect[NonDisplayedPage].Bottom=SCREEN_HEIGHT;
|
||||
if (Vertices[j].X < EraseRect[NonDisplayedPage].Left)
|
||||
if (Vertices[j].X > 0)
|
||||
if (Vertices[j].X < EraseRect[NonDisplayedPage].Left)
|
||||
if (Vertices[j].X > 0)
|
||||
EraseRect[NonDisplayedPage].Left = Vertices[j].X;
|
||||
else EraseRect[NonDisplayedPage].Left = 0;
|
||||
if (Vertices[j].Y < EraseRect[NonDisplayedPage].Top)
|
||||
if (Vertices[j].Y > 0)
|
||||
if (Vertices[j].Y < EraseRect[NonDisplayedPage].Top)
|
||||
if (Vertices[j].Y > 0)
|
||||
EraseRect[NonDisplayedPage].Top = Vertices[j].Y;
|
||||
else EraseRect[NonDisplayedPage].Top = 0;
|
||||
}
|
||||
/* Draw the polygon */
|
||||
DRAW_POLYGON(Vertices, NumVertices, FacePtr->Color, 0, 0);
|
||||
DRAW_POLYGON(Vertices, NumVertices, FacePtr->Color, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* Routines to perform incremental rotations around the three axes */
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
/* Concatenate a rotation by Angle around the X axis to the transformation in
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
all vertices offset by (X,Y) */
|
||||
#define DRAW_POLYGON(PointList,NumPoints,Color,X,Y) \
|
||||
Polygon.Length = NumPoints; Polygon.PointPtr = PointList; \
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
/* Describes a single 2D point */
|
||||
struct Point {
|
||||
int X; /* X coordinate */
|
||||
|
|
|
|||
82
52-02.html
82
52-02.html
|
|
@ -42,8 +42,8 @@
|
|||
/* 3-D animation program to rotate 12 cubes. Uses fixed point. All C code
|
||||
tested with Borland C++ in C compilation mode and the small model. */
|
||||
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include <conio.h>
|
||||
#include <dos.h>
|
||||
#include “polygon.h”
|
||||
|
||||
/* base offset of page to which to draw */
|
||||
|
|
@ -73,11 +73,11 @@ void main() {
|
|||
and flipping the page to show it */
|
||||
do {
|
||||
/* For each object, regenerate viewing info, if necessary */
|
||||
for (i=0; i<NumObjects; i++) {
|
||||
if ((ObjectPtr = ObjectList[i])->RecalcXform ||
|
||||
for (i=0; i<NumObjects; i++) {
|
||||
if ((ObjectPtr = ObjectList[i])->RecalcXform ||
|
||||
RecalcAllXforms) {
|
||||
ObjectPtr->RecalcFunc(ObjectPtr);
|
||||
ObjectPtr->RecalcXform = 0;
|
||||
ObjectPtr->RecalcFunc(ObjectPtr);
|
||||
ObjectPtr->RecalcXform = 0;
|
||||
}
|
||||
}
|
||||
RecalcAllXforms = 0;
|
||||
|
|
@ -85,32 +85,32 @@ void main() {
|
|||
PageStartOffsets[NonDisplayedPage = DisplayedPage ^ 1];
|
||||
/* For each object, clear the portion of the non-displayed page
|
||||
that was drawn to last time, then reset the erase extent */
|
||||
for (i=0; i<NumObjects; i++) {
|
||||
for (i=0; i<NumObjects; i++) {
|
||||
ObjectPtr = ObjectList[i];
|
||||
FillRectangleX(ObjectPtr->EraseRect[NonDisplayedPage].Left,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Top,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Right,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Bottom,
|
||||
FillRectangleX(ObjectPtr->EraseRect[NonDisplayedPage].Left,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Top,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Right,
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Bottom,
|
||||
CurrentPageBase, 0);
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Left =
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Top = 0x7FFF;
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Right =
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Bottom = 0;
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Left =
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Top = 0x7FFF;
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Right =
|
||||
ObjectPtr->EraseRect[NonDisplayedPage].Bottom = 0;
|
||||
}
|
||||
/* Draw all objects */
|
||||
for (i=0; i<NumObjects; i++)
|
||||
ObjectList[i]->DrawFunc(ObjectList[i]);
|
||||
for (i=0; i<NumObjects; i++)
|
||||
ObjectList[i]->DrawFunc(ObjectList[i]);
|
||||
/* Flip to display the page into which we just drew */
|
||||
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
|
||||
/* Move and reorient each object */
|
||||
for (i=0; i<NumObjects; i++)
|
||||
ObjectList[i]->MoveFunc(ObjectList[i]);
|
||||
for (i=0; i<NumObjects; i++)
|
||||
ObjectList[i]->MoveFunc(ObjectList[i]);
|
||||
if (kbhit())
|
||||
if (getch() == 0x1B) Done = 1; /* Esc to exit */
|
||||
} while (!Done);
|
||||
/* Return to text mode and exit */
|
||||
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
||||
int86(0x10, &regset, &regset);
|
||||
int86(0x10, &regset, &regset);
|
||||
exit(1);
|
||||
}
|
||||
</PRE>
|
||||
|
|
@ -120,45 +120,45 @@ void main() {
|
|||
<PRE>
|
||||
/* Transforms all vertices in the specified polygon-based object into view
|
||||
space, then perspective projects them to screen space and maps them to screen
|
||||
coordinates, storing results in the object. Recalculates object->view
|
||||
coordinates, storing results in the object. Recalculates object->view
|
||||
transformation because only if transform changes would we bother
|
||||
to retransform the vertices. */
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
void XformAndProjectPObject(PObject * ObjectToXform)
|
||||
{
|
||||
int i, NumPoints = ObjectToXform->NumVerts;
|
||||
Point3 * Points = ObjectToXform->VertexList;
|
||||
Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
||||
Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
||||
Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
int i, NumPoints = ObjectToXform->NumVerts;
|
||||
Point3 * Points = ObjectToXform->VertexList;
|
||||
Point3 * XformedPoints = ObjectToXform->XformedVertexList;
|
||||
Point3 * ProjectedPoints = ObjectToXform->ProjectedVertexList;
|
||||
Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
|
||||
/* Recalculate the object->view transform */
|
||||
ConcatXforms(WorldViewXform, ObjectToXform->XformToWorld,
|
||||
ObjectToXform->XformToView);
|
||||
/* Recalculate the object->view transform */
|
||||
ConcatXforms(WorldViewXform, ObjectToXform->XformToWorld,
|
||||
ObjectToXform->XformToView);
|
||||
/* Apply that new transformation and project the points */
|
||||
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
||||
for (i=0; i<NumPoints; i++, Points++, XformedPoints++,
|
||||
ProjectedPoints++, ScreenPoints++) {
|
||||
/* Transform to view space */
|
||||
XformVec(ObjectToXform->XformToView, (Fixedpoint *) Points,
|
||||
XformVec(ObjectToXform->XformToView, (Fixedpoint *) Points,
|
||||
(Fixedpoint *) XformedPoints);
|
||||
/* Perspective-project to screen space */
|
||||
ProjectedPoints->X =
|
||||
FixedMul(FixedDiv(XformedPoints->X, XformedPoints->Z),
|
||||
ProjectedPoints->X =
|
||||
FixedMul(FixedDiv(XformedPoints->X, XformedPoints->Z),
|
||||
DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2)));
|
||||
ProjectedPoints->Y =
|
||||
FixedMul(FixedDiv(XformedPoints->Y, XformedPoints->Z),
|
||||
ProjectedPoints->Y =
|
||||
FixedMul(FixedDiv(XformedPoints->Y, XformedPoints->Z),
|
||||
DOUBLE_TO_FIXED(PROJECTION_RATIO * (SCREEN_WIDTH/2)));
|
||||
ProjectedPoints->Z = XformedPoints->Z;
|
||||
ProjectedPoints->Z = XformedPoints->Z;
|
||||
/* Convert to screen coordinates. The Y coord is negated to flip from
|
||||
increasing Y being up to increasing Y being down, as expected by polygon
|
||||
filler. Add in half the screen width and height to center on screen. */
|
||||
ScreenPoints->X = ((int) ((ProjectedPoints->X +
|
||||
DOUBLE_TO_FIXED(0.5)) >> 16)) + SCREEN_WIDTH/2;
|
||||
ScreenPoints->Y = (-((int) ((ProjectedPoints->Y +
|
||||
DOUBLE_TO_FIXED(0.5)) >> 16))) + SCREEN_HEIGHT/2;
|
||||
ScreenPoints->X = ((int) ((ProjectedPoints->X +
|
||||
DOUBLE_TO_FIXED(0.5)) >> 16)) + SCREEN_WIDTH/2;
|
||||
ScreenPoints->Y = (-((int) ((ProjectedPoints->Y +
|
||||
DOUBLE_TO_FIXED(0.5)) >> 16))) + SCREEN_HEIGHT/2;
|
||||
}
|
||||
}<B></B>
|
||||
</PRE>
|
||||
|
|
|
|||
14
52-03.html
14
52-03.html
|
|
@ -41,7 +41,7 @@
|
|||
<PRE>
|
||||
/* Routines to perform incremental rotations around the three axes. */
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
/* Concatenate a rotation by Angle around the X axis to transformation in
|
||||
|
|
@ -141,7 +141,7 @@ void XformVec(Xform WorkingXform, Fixedpoint *SourceVec,
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
for (i=0; i<3; i++)
|
||||
DestVec[i] = FixedMul(WorkingXform[i][0], SourceVec[0]) +
|
||||
FixedMul(WorkingXform[i][1], SourceVec[1]) +
|
||||
FixedMul(WorkingXform[i][2], SourceVec[2]) +
|
||||
|
|
@ -157,8 +157,8 @@ void ConcatXforms(Xform SourceXform1, Xform SourceXform2,
|
|||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
for (j=0; j<4; j++)
|
||||
for (i=0; i<3; i++) {
|
||||
for (j=0; j<4; j++)
|
||||
DestXform[i][j] =
|
||||
FixedMul(SourceXform1[i][0], SourceXform2[0][j]) +
|
||||
FixedMul(SourceXform1[i][1], SourceXform2[1][j]) +
|
||||
|
|
@ -189,10 +189,10 @@ void InitializeFixedPoint()
|
|||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<3; i++)
|
||||
for (j=0; j<4; j++)
|
||||
for (i=0; i<3; i++)
|
||||
for (j=0; j<4; j++)
|
||||
WorldViewXform[i][j] = INT_TO_FIXED(IntWorldViewXform[i][j]);
|
||||
for (i=0; i<NUM_CUBE_VERTS; i++) {
|
||||
for (i=0; i<NUM_CUBE_VERTS; i++) {
|
||||
CubeVerts[i].X = INT_TO_FIXED(IntCubeVerts[i].X);
|
||||
CubeVerts[i].Y = INT_TO_FIXED(IntCubeVerts[i].Y);
|
||||
CubeVerts[i].Z = INT_TO_FIXED(IntCubeVerts[i].Z);
|
||||
|
|
|
|||
94
52-04.html
94
52-04.html
|
|
@ -46,26 +46,26 @@
|
|||
|
||||
void RotateAndMovePObject(PObject * ObjectToMove)
|
||||
{
|
||||
if (--ObjectToMove->RDelayCount == 0) { /* rotate */
|
||||
ObjectToMove->RDelayCount = ObjectToMove->RDelayCountBase;
|
||||
if (ObjectToMove->Rotate.RotateX != 0.0)
|
||||
AppendRotationX(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateX);
|
||||
if (ObjectToMove->Rotate.RotateY != 0.0)
|
||||
AppendRotationY(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateY);
|
||||
if (ObjectToMove->Rotate.RotateZ != 0.0)
|
||||
AppendRotationZ(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateZ);
|
||||
ObjectToMove->RecalcXform = 1;
|
||||
if (--ObjectToMove->RDelayCount == 0) { /* rotate */
|
||||
ObjectToMove->RDelayCount = ObjectToMove->RDelayCountBase;
|
||||
if (ObjectToMove->Rotate.RotateX != 0.0)
|
||||
AppendRotationX(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateX);
|
||||
if (ObjectToMove->Rotate.RotateY != 0.0)
|
||||
AppendRotationY(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateY);
|
||||
if (ObjectToMove->Rotate.RotateZ != 0.0)
|
||||
AppendRotationZ(ObjectToMove->XformToWorld,
|
||||
ObjectToMove->Rotate.RotateZ);
|
||||
ObjectToMove->RecalcXform = 1;
|
||||
}
|
||||
/* Move in Z, checking for bouncing and stopping */
|
||||
if (--ObjectToMove->MDelayCount == 0) {
|
||||
ObjectToMove->MDelayCount = ObjectToMove->MDelayCountBase;
|
||||
ObjectToMove->XformToWorld[2][3] += ObjectToMove->Move.MoveZ;
|
||||
if (ObjectToMove->XformToWorld[2][3]>ObjectToMove->Move.MaxZ)
|
||||
ObjectToMove->Move.MoveZ = 0; /* stop if close enough */
|
||||
ObjectToMove->RecalcXform = 1;
|
||||
if (--ObjectToMove->MDelayCount == 0) {
|
||||
ObjectToMove->MDelayCount = ObjectToMove->MDelayCountBase;
|
||||
ObjectToMove->XformToWorld[2][3] += ObjectToMove->Move.MoveZ;
|
||||
if (ObjectToMove->XformToWorld[2][3]>ObjectToMove->Move.MaxZ)
|
||||
ObjectToMove->Move.MoveZ = 0; /* stop if close enough */
|
||||
ObjectToMove->RecalcXform = 1;
|
||||
}
|
||||
}
|
||||
</PRE>
|
||||
|
|
@ -81,19 +81,19 @@ void RotateAndMovePObject(PObject * ObjectToMove)
|
|||
|
||||
void DrawPObject(PObject * ObjectToXform)
|
||||
{
|
||||
int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
|
||||
int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
|
||||
int * VertNumsPtr;
|
||||
Face * FacePtr = ObjectToXform->FaceList;
|
||||
Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
Face * FacePtr = ObjectToXform->FaceList;
|
||||
Point * ScreenPoints = ObjectToXform->ScreenVertexList;
|
||||
long v1, v2, w1, w2;
|
||||
Point Vertices[MAX_POLY_LENGTH];
|
||||
PointListHeader Polygon;
|
||||
|
||||
/* Draw each visible face (polygon) of the object in turn */
|
||||
for (i=0; i<NumFaces; i++, FacePtr++) {
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
for (i=0; i<NumFaces; i++, FacePtr++) {
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
/* Copy over the face's vertices from the vertex list */
|
||||
for (j=0, VertNumsPtr=FacePtr->VertNums; j<NumVertices; j++)
|
||||
for (j=0, VertNumsPtr=FacePtr->VertNums; j<NumVertices; j++)
|
||||
Vertices[j] = ScreenPoints[*VertNumsPtr++];
|
||||
/* Draw only if outside face showing (if the normal to the
|
||||
polygon points toward viewer; that is, has a positive Z component) */
|
||||
|
|
@ -101,40 +101,40 @@ void DrawPObject(PObject * ObjectToXform)
|
|||
w1 = Vertices[NumVertices-1].X - Vertices[0].X;
|
||||
v2 = Vertices[1].Y - Vertices[0].Y;
|
||||
w2 = Vertices[NumVertices-1].Y - Vertices[0].Y;
|
||||
if ((v1*w2 - v2*w1) > 0) {
|
||||
if ((v1*w2 - v2*w1) > 0) {
|
||||
/* It is facing the screen, so draw */
|
||||
/* Appropriately adjust the extent of the rectangle used to
|
||||
erase this object later */
|
||||
for (j=0; j<NumVertices; j++) {
|
||||
if (Vertices[j].X >
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Right)
|
||||
if (Vertices[j].X < SCREEN_WIDTH)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Right =
|
||||
for (j=0; j<NumVertices; j++) {
|
||||
if (Vertices[j].X >
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Right)
|
||||
if (Vertices[j].X < SCREEN_WIDTH)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Right =
|
||||
Vertices[j].X;
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Right =
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Right =
|
||||
SCREEN_WIDTH;
|
||||
if (Vertices[j].Y >
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Bottom)
|
||||
if (Vertices[j].Y < SCREEN_HEIGHT)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Bottom =
|
||||
if (Vertices[j].Y >
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Bottom)
|
||||
if (Vertices[j].Y < SCREEN_HEIGHT)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Bottom =
|
||||
Vertices[j].Y;
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Bottom=
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Bottom=
|
||||
SCREEN_HEIGHT;
|
||||
if (Vertices[j].X <
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Left)
|
||||
if (Vertices[j].X > 0)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Left =
|
||||
if (Vertices[j].X <
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Left)
|
||||
if (Vertices[j].X > 0)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Left =
|
||||
Vertices[j].X;
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Left=0;
|
||||
if (Vertices[j].Y <
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Top)
|
||||
if (Vertices[j].Y > 0)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Top =
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Left=0;
|
||||
if (Vertices[j].Y <
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Top)
|
||||
if (Vertices[j].Y > 0)
|
||||
ObjectToXform->EraseRect[NonDisplayedPage].Top =
|
||||
Vertices[j].Y;
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Top=0;
|
||||
else ObjectToXform->EraseRect[NonDisplayedPage].Top=0;
|
||||
}
|
||||
/* Draw the polygon */
|
||||
DRAW_POLYGON(Vertices, NumVertices, FacePtr->Color, 0, 0);
|
||||
DRAW_POLYGON(Vertices, NumVertices, FacePtr->Color, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
92
52-05.html
92
52-05.html
|
|
@ -41,8 +41,8 @@
|
|||
<PRE>
|
||||
/* Initializes the cubes and adds them to the object list. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
|
||||
#define ROT_6 (M_PI / 30.0) /* rotate 6 degrees at a time */
|
||||
|
|
@ -99,64 +99,64 @@ void InitializeCubes()
|
|||
int i, j, k;
|
||||
PObject *WorkingCube;
|
||||
|
||||
for (i=0; i<NUM_CUBES; i++) {
|
||||
for (i=0; i<NUM_CUBES; i++) {
|
||||
if ((WorkingCube = malloc(sizeof(PObject))) == NULL) {
|
||||
printf(“Couldn't get memory\n”); exit(1); }
|
||||
WorkingCube->DrawFunc = DrawPObject;
|
||||
WorkingCube->RecalcFunc = XformAndProjectPObject;
|
||||
WorkingCube->MoveFunc = RotateAndMovePObject;
|
||||
WorkingCube->RecalcXform = 1;
|
||||
for (k=0; k<2; k++) {
|
||||
WorkingCube->EraseRect[k].Left =
|
||||
WorkingCube->EraseRect[k].Top = 0x7FFF;
|
||||
WorkingCube->EraseRect[k].Right = 0;
|
||||
WorkingCube->EraseRect[k].Bottom = 0;
|
||||
WorkingCube->DrawFunc = DrawPObject;
|
||||
WorkingCube->RecalcFunc = XformAndProjectPObject;
|
||||
WorkingCube->MoveFunc = RotateAndMovePObject;
|
||||
WorkingCube->RecalcXform = 1;
|
||||
for (k=0; k<2; k++) {
|
||||
WorkingCube->EraseRect[k].Left =
|
||||
WorkingCube->EraseRect[k].Top = 0x7FFF;
|
||||
WorkingCube->EraseRect[k].Right = 0;
|
||||
WorkingCube->EraseRect[k].Bottom = 0;
|
||||
}
|
||||
WorkingCube->RDelayCount = InitRDelayCounts[i];
|
||||
WorkingCube->RDelayCountBase = BaseRDelayCounts[i];
|
||||
WorkingCube->MDelayCount = InitMDelayCounts[i];
|
||||
WorkingCube->MDelayCountBase = BaseMDelayCounts[i];
|
||||
/* Set the object->world xform to none */
|
||||
for (j=0; j<3; j++)
|
||||
for (k=0; k<4; k++)
|
||||
WorkingCube->XformToWorld[j][k] = INT_TO_FIXED(0);
|
||||
WorkingCube->XformToWorld[0][0] =
|
||||
WorkingCube->XformToWorld[1][1] =
|
||||
WorkingCube->XformToWorld[2][2] =
|
||||
WorkingCube->XformToWorld[3][3] = INT_TO_FIXED(1);
|
||||
WorkingCube->RDelayCount = InitRDelayCounts[i];
|
||||
WorkingCube->RDelayCountBase = BaseRDelayCounts[i];
|
||||
WorkingCube->MDelayCount = InitMDelayCounts[i];
|
||||
WorkingCube->MDelayCountBase = BaseMDelayCounts[i];
|
||||
/* Set the object->world xform to none */
|
||||
for (j=0; j<3; j++)
|
||||
for (k=0; k<4; k++)
|
||||
WorkingCube->XformToWorld[j][k] = INT_TO_FIXED(0);
|
||||
WorkingCube->XformToWorld[0][0] =
|
||||
WorkingCube->XformToWorld[1][1] =
|
||||
WorkingCube->XformToWorld[2][2] =
|
||||
WorkingCube->XformToWorld[3][3] = INT_TO_FIXED(1);
|
||||
/* Set the initial location */
|
||||
for (j=0; j<3; j++) WorkingCube->XformToWorld[j][3] =
|
||||
for (j=0; j<3; j++) WorkingCube->XformToWorld[j][3] =
|
||||
INT_TO_FIXED(CubeStartCoords[i][j]);
|
||||
WorkingCube->NumVerts = NUM_CUBE_VERTS;
|
||||
WorkingCube->VertexList = CubeVerts;
|
||||
WorkingCube->NumFaces = NUM_CUBE_FACES;
|
||||
WorkingCube->Rotate = InitialRotate[i];
|
||||
WorkingCube->Move.MoveX = INT_TO_FIXED(InitialMove[i].MoveX);
|
||||
WorkingCube->Move.MoveY = INT_TO_FIXED(InitialMove[i].MoveY);
|
||||
WorkingCube->Move.MoveZ = INT_TO_FIXED(InitialMove[i].MoveZ);
|
||||
WorkingCube->Move.MinX = INT_TO_FIXED(InitialMove[i].MinX);
|
||||
WorkingCube->Move.MinY = INT_TO_FIXED(InitialMove[i].MinY);
|
||||
WorkingCube->Move.MinZ = INT_TO_FIXED(InitialMove[i].MinZ);
|
||||
WorkingCube->Move.MaxX = INT_TO_FIXED(InitialMove[i].MaxX);
|
||||
WorkingCube->Move.MaxY = INT_TO_FIXED(InitialMove[i].MaxY);
|
||||
WorkingCube->Move.MaxZ = INT_TO_FIXED(InitialMove[i].MaxZ);
|
||||
if ((WorkingCube->XformedVertexList =
|
||||
WorkingCube->NumVerts = NUM_CUBE_VERTS;
|
||||
WorkingCube->VertexList = CubeVerts;
|
||||
WorkingCube->NumFaces = NUM_CUBE_FACES;
|
||||
WorkingCube->Rotate = InitialRotate[i];
|
||||
WorkingCube->Move.MoveX = INT_TO_FIXED(InitialMove[i].MoveX);
|
||||
WorkingCube->Move.MoveY = INT_TO_FIXED(InitialMove[i].MoveY);
|
||||
WorkingCube->Move.MoveZ = INT_TO_FIXED(InitialMove[i].MoveZ);
|
||||
WorkingCube->Move.MinX = INT_TO_FIXED(InitialMove[i].MinX);
|
||||
WorkingCube->Move.MinY = INT_TO_FIXED(InitialMove[i].MinY);
|
||||
WorkingCube->Move.MinZ = INT_TO_FIXED(InitialMove[i].MinZ);
|
||||
WorkingCube->Move.MaxX = INT_TO_FIXED(InitialMove[i].MaxX);
|
||||
WorkingCube->Move.MaxY = INT_TO_FIXED(InitialMove[i].MaxY);
|
||||
WorkingCube->Move.MaxZ = INT_TO_FIXED(InitialMove[i].MaxZ);
|
||||
if ((WorkingCube->XformedVertexList =
|
||||
malloc(NUM_CUBE_VERTS*sizeof(Point3))) == NULL) {
|
||||
printf(“Couldn't get memory\n”); exit(1); }
|
||||
if ((WorkingCube->ProjectedVertexList =
|
||||
if ((WorkingCube->ProjectedVertexList =
|
||||
malloc(NUM_CUBE_VERTS*sizeof(Point3))) == NULL) {
|
||||
printf(“Couldn't get memory\n”); exit(1); }
|
||||
if ((WorkingCube->ScreenVertexList =
|
||||
if ((WorkingCube->ScreenVertexList =
|
||||
malloc(NUM_CUBE_VERTS*sizeof(Point))) == NULL) {
|
||||
printf(“Couldn't get memory\n”); exit(1); }
|
||||
if ((WorkingCube->FaceList =
|
||||
if ((WorkingCube->FaceList =
|
||||
malloc(NUM_CUBE_FACES*sizeof(Face))) == NULL) {
|
||||
printf(“Couldn't get memory\n”); exit(1); }
|
||||
/* Initialize the faces */
|
||||
for (j=0; j<NUM_CUBE_FACES; j++) {
|
||||
WorkingCube->FaceList[j].VertNums = VertNumList[j];
|
||||
WorkingCube->FaceList[j].NumVerts = VertsInFace[j];
|
||||
WorkingCube->FaceList[j].Color = Colors[i][j];
|
||||
for (j=0; j<NUM_CUBE_FACES; j++) {
|
||||
WorkingCube->FaceList[j].VertNums = VertNumList[j];
|
||||
WorkingCube->FaceList[j].NumVerts = VertsInFace[j];
|
||||
WorkingCube->FaceList[j].Color = Colors[i][j];
|
||||
}
|
||||
ObjectList[NumObjects++] = (Object *)WorkingCube;
|
||||
}
|
||||
|
|
|
|||
12
52-06.html
12
52-06.html
|
|
@ -52,7 +52,7 @@
|
|||
public _FixedMul,_FixedDiv
|
||||
; Multiplies two fixed-point values together.
|
||||
FMparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
M1 dd ?
|
||||
M2 dd ?
|
||||
FMparms ends
|
||||
|
|
@ -70,7 +70,7 @@ _FixedMul proc near
|
|||
_FixedMul endp
|
||||
; Divides one fixed-point value by another.
|
||||
FDparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Dividend dd ?
|
||||
Divisor dd ?
|
||||
FDparms ends
|
||||
|
|
@ -137,8 +137,8 @@ _FixedDiv endp
|
|||
Color with all vertices offset by (X,Y) */
|
||||
#define DRAW_POLYGON(PointList,NumPoints,Color,X,Y) \
|
||||
Polygon.Length = NumPoints; Polygon.PointPtr = PointList; \
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
#define INT_TO_FIXED(x) (((long)(int)x) << 16)
|
||||
FillConvexPolygon(&Polygon, Color, X, Y);
|
||||
#define INT_TO_FIXED(x) (((long)(int)x) << 16)
|
||||
#define DOUBLE_TO_FIXED(x) ((long) (x * 65536.0 + 0.5))
|
||||
|
||||
typedef long Fixedpoint;
|
||||
|
|
@ -181,8 +181,8 @@ typedef struct {
|
|||
BASE_OBJECT
|
||||
int RDelayCount, RDelayCountBase; /* controls rotation speed */
|
||||
int MDelayCount, MDelayCountBase; /* controls movement speed */
|
||||
Xform XformToWorld; /* transform from object->world space */
|
||||
Xform XformToView; /* transform from object->view space */
|
||||
Xform XformToWorld; /* transform from object->world space */
|
||||
Xform XformToView; /* transform from object->view space */
|
||||
RotateControl Rotate; /* controls rotation change over time */
|
||||
MoveControl Move; /* controls object movement over time */
|
||||
int NumVerts; /* # vertices in VertexList */
|
||||
|
|
|
|||
18
53-02.html
18
53-02.html
|
|
@ -54,7 +54,7 @@ ALIGNMENT equ 2
|
|||
; Fixedpoint FixedMul(Fixedpoint M1, Fixedpoint M2);
|
||||
; Fixedpoint FixedDiv(Fixedpoint Dividend, Fixedpoint Divisor);
|
||||
FMparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
M1 dd ?
|
||||
M2 dd ?
|
||||
FMparms ends
|
||||
|
|
@ -78,7 +78,7 @@ endif ;ROUNDING-ON
|
|||
; C near-callable as:
|
||||
; Fixedpoint FixedDiv(Fixedpoint Dividend, Fixedpoint Divisor);
|
||||
FDparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Dividend dd ?
|
||||
Divisor dd ?
|
||||
FDparms ends
|
||||
|
|
@ -140,8 +140,8 @@ CosTable label dword
|
|||
include costable.inc
|
||||
|
||||
SCparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Angle dw ? ;angle to calculate sine & cosine for
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Angle dw ? ;angle to calculate sine & cosine for
|
||||
Cos dw ? ;pointer to cos destination
|
||||
Sin dw ? ;pointer to sin destination
|
||||
SCparms ends
|
||||
|
|
@ -242,7 +242,7 @@ ret
|
|||
; WorkingXform[i][3]; /* no need to multiply by W = 1 */
|
||||
|
||||
XVparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
WorkingXform dw ? ;pointer to transform matrix
|
||||
SourceVec dw ? ;pointer to source vector
|
||||
DestVec dw ? ;pointer to destination vector
|
||||
|
|
@ -328,7 +328,7 @@ ret
|
|||
; }
|
||||
|
||||
CXparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
SourceXform1 dw ? ;pointer to first source xform matrix
|
||||
SourceXform2 dw ? ;pointer to second source xform matrix
|
||||
DestXform dw ? ;pointer to destination xform matrix
|
||||
|
|
@ -380,7 +380,7 @@ endif ;ROUNDING-ON
|
|||
add ecx,eax ;running total
|
||||
|
||||
mov[di+coff+roff],ecx ;save the result in dest matrix
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
;now do the fourth column, assuming
|
||||
; 1 as the bottom entry, causing
|
||||
|
|
@ -415,9 +415,9 @@ addecx,eax;running total
|
|||
addecx,[si+roff+12];add in translation
|
||||
|
||||
mov[di+coff+roff],ecx;save the result in dest matrix
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
|
||||
popdi;restore register variables
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
terminate searches */
|
||||
void InitializeObjectList()
|
||||
{
|
||||
ObjectListStart.NextObject = &ObjectListEnd;
|
||||
ObjectListStart.NextObject = &ObjectListEnd;
|
||||
ObjectListStart.PreviousObject = NULL;
|
||||
ObjectListStart.CenterInView.Z = INT-TO-FIXED(-32768);
|
||||
ObjectListEnd.NextObject = NULL;
|
||||
ObjectListEnd.PreviousObject = &ObjectListStart;
|
||||
ObjectListEnd.PreviousObject = &ObjectListStart;
|
||||
ObjectListEnd.CenterInView.Z = 0x7FFFFFFFL;
|
||||
NumObjects = 0;
|
||||
}
|
||||
|
|
|
|||
52
54-02.html
52
54-02.html
|
|
@ -65,7 +65,7 @@ ALIGNMENT equ 2
|
|||
; C near-callable as:
|
||||
; Fixedpoint FixedMul(Fixedpoint M1, Fixedpoint M2);
|
||||
FMparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
M1 dd ?
|
||||
M2 dd ?
|
||||
FMparms ends
|
||||
|
|
@ -161,7 +161,7 @@ _FixedMul endp
|
|||
; C near-callable as:
|
||||
; Fixedpoint FixedDiv(Fixedpoint Dividend, Fixedpoint Divisor);
|
||||
FDparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Dividend dd?
|
||||
Divisor dd?
|
||||
FDparms ends
|
||||
|
|
@ -290,8 +290,8 @@ CosTable label dword
|
|||
include costable.inc
|
||||
|
||||
SCparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Angle dw ? ;angle to calculate sine & cosine for
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
Angle dw ? ;angle to calculate sine & cosine for
|
||||
Cos dw ? ;pointer to cos destination
|
||||
Sin dw ? ;pointer to sin destination
|
||||
SCparms ends
|
||||
|
|
@ -486,7 +486,7 @@ _CosSin endp
|
|||
; WorkingXform[i][3]; /* no need to multiply by W = 1 */
|
||||
|
||||
XVparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
WorkingXform dw ? ;pointer to transform matrix
|
||||
SourceVec dw ? ;pointer to source vector
|
||||
DestVec dw ? ;pointer to destination vector
|
||||
|
|
@ -502,40 +502,40 @@ FIXED-MUL MACRO M1,M2
|
|||
;figure out signs, so we can use
|
||||
; unsigned multiplies
|
||||
sub cx,cx ;assume both operands positive
|
||||
mov bx,word ptr [&M1&+2]
|
||||
mov bx,word ptr [&M1&+2]
|
||||
and bx,bx ;first operand negative?
|
||||
jns CheckSecondOperand ;no
|
||||
neg bx ;yes, so negate first operand
|
||||
neg word ptr [&M1&]
|
||||
neg word ptr [&M1&]
|
||||
sbb bx,0
|
||||
mov word ptr [&M1&+2],bx
|
||||
mov word ptr [&M1&+2],bx
|
||||
inc cx ;mark that first operand is negative
|
||||
CheckSecondOperand:
|
||||
mov bx,word ptr [&M2&+2]
|
||||
mov bx,word ptr [&M2&+2]
|
||||
and bx,bx ;second operand negative?
|
||||
jns SaveSignStatus ;no
|
||||
neg bx ;yes, so negate second operand
|
||||
neg word ptr [&M2&]
|
||||
neg word ptr [&M2&]
|
||||
sbb bx,0
|
||||
mov word ptr [&M2&+2],bx
|
||||
mov word ptr [&M2&+2],bx
|
||||
xor cx,1 ;mark that second operand is negative
|
||||
SaveSignStatus:
|
||||
push cx ;remember sign of result; 1 if result
|
||||
; negative, 0 if result nonnegative
|
||||
mov ax,word ptr [&M1&+2] ;high word times high word
|
||||
mul word ptr [&M2&+2]
|
||||
mov ax,word ptr [&M1&+2] ;high word times high word
|
||||
mul word ptr [&M2&+2]
|
||||
mov cx,ax ;
|
||||
;assume no overflow into DX
|
||||
mov ax,word ptr [&M1&+2] ;high word times low word
|
||||
mul word ptr [&M2&]
|
||||
mov ax,word ptr [&M1&+2] ;high word times low word
|
||||
mul word ptr [&M2&]
|
||||
mov bx,ax
|
||||
add cx,dx
|
||||
mov ax,word ptr [&M1&] ;low word times high word
|
||||
mul word ptr [&M2&+2]
|
||||
mov ax,word ptr [&M1&] ;low word times high word
|
||||
mul word ptr [&M2&+2]
|
||||
add bx,ax
|
||||
adc cx,dx
|
||||
mov ax,word ptr [&M1&] ;low word times low word
|
||||
mul word ptr [&M2&]
|
||||
mov ax,word ptr [&M1&] ;low word times low word
|
||||
mul word ptr [&M2&]
|
||||
if MUL-ROUNDING-ON
|
||||
add ax,8000h ;round by adding 2^(-17)
|
||||
adc bx,dx
|
||||
|
|
@ -692,7 +692,7 @@ _XformVecendp
|
|||
; }
|
||||
|
||||
CXparms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
SourceXform1 dw ? ;pointer to first source xform matrix
|
||||
SourceXform2 dw ? ;pointer to second source xform matrix
|
||||
DestXform dw ? ;pointer to destination xform matrix
|
||||
|
|
@ -746,7 +746,7 @@ endif ;MUL-ROUNDING-ON
|
|||
add ecx,eax ;running total
|
||||
|
||||
mov [di+coff+roff],ecx ;save the result in dest matrix
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
;now do the fourth column, assuming
|
||||
; 1 as the bottom entry, causing
|
||||
|
|
@ -781,9 +781,9 @@ endif ;MUL-ROUNDING-ON
|
|||
add ecx,[si+roff+12] ;add in translation
|
||||
|
||||
mov [di+coff+roff],ecx ;save the result in dest matrix
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
|
||||
else ;!USE386
|
||||
|
|
@ -837,7 +837,7 @@ addsp,8;clear parameters from stack
|
|||
pop bx ;restore DestXForm pointer
|
||||
mov [bx+coff+roff],cx ;save the result in dest matrix
|
||||
mov [bx+coff+roff+2],bp
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
;now do the fourth column, assuming
|
||||
; 1 as the bottom entry, causing
|
||||
|
|
@ -883,9 +883,9 @@ coff=coff+4 ;point to next col in xform2 & dest
|
|||
pop bx ;restore DestXForm pointer
|
||||
mov [bx+coff+roff],cx ;save the result in dest matrix
|
||||
mov [bx+coff+roff+2],bp
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
coff=coff+4 ;point to next col in xform2 & dest
|
||||
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
roff=roff+16 ;point to next col in xform2 & dest
|
||||
ENDM
|
||||
|
||||
pop bp ;restore stack frame pointer
|
||||
|
|
|
|||
14
54-04.html
14
54-04.html
|
|
@ -66,8 +66,8 @@ void DrawPObject(PObject * ObjectToXform)
|
|||
must be the first and second entries in the polgyon's vertex list.
|
||||
Note that the second point is also an active polygon vertex */
|
||||
VertNumsPtr = FacePtr->VertNums;
|
||||
NormalEndpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr++];
|
||||
NormalStartpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr];
|
||||
NormalEndpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr++];
|
||||
NormalStartpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr];
|
||||
/* Copy over the face's vertices from the vertex list */
|
||||
NumVertices = FacePtr->NumVerts;
|
||||
for (j=0; j<NumVertices; j++)
|
||||
|
|
@ -118,14 +118,14 @@ void DrawPObject(PObject * ObjectToXform)
|
|||
} else {
|
||||
/* Handle shading */
|
||||
/* Do ambient shading, if enabled */
|
||||
if (AmbientOn && (FacePtr->ShadingType & AMBIENT-SHADING)) {
|
||||
if (AmbientOn && (FacePtr->ShadingType & AMBIENT-SHADING)) {
|
||||
/* Use the ambient shading component */
|
||||
IntensityTemp = AmbientIntensity;
|
||||
} else {
|
||||
SET-INTENSITY(IntensityTemp, 0, 0, 0);
|
||||
}
|
||||
/* Do diffuse shading, if enabled */
|
||||
if (FacePtr->ShadingType & DIFFUSE-SHADING) {
|
||||
if (FacePtr->ShadingType & DIFFUSE-SHADING) {
|
||||
/* Calculate the unit normal for this polygon, for use in dot
|
||||
products */
|
||||
UnitNormal.X = NormalEndpoint->X - NormalStartpoint->X;
|
||||
|
|
@ -155,12 +155,12 @@ void DrawPObject(PObject * ObjectToXform)
|
|||
}
|
||||
/* Convert the drawing color to the desired fraction of the
|
||||
brightest possible color */
|
||||
IntensityAdjustColor(&ColorTemp, &FacePtr->FullColor,
|
||||
&IntensityTemp);
|
||||
IntensityAdjustColor(&ColorTemp, &FacePtr->FullColor,
|
||||
&IntensityTemp);
|
||||
/* Draw with the cumulative shading, converting from the general
|
||||
color representation to the best-match color index */
|
||||
DRAW-POLYGON(Vertices, NumVertices,
|
||||
ModelColorToColorIndex(&ColorTemp), 0, 0);
|
||||
ModelColorToColorIndex(&ColorTemp), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
55-02.html
18
55-02.html
|
|
@ -70,7 +70,7 @@
|
|||
even intensity steps on the screen.
|
||||
*/
|
||||
|
||||
#include <dos.h>
|
||||
#include <dos.h>
|
||||
#include "polygon.h"
|
||||
|
||||
static unsigned char Gamma4Levels[] = { 0, 39, 53, 63 };
|
||||
|
|
@ -89,10 +89,10 @@
|
|||
union REGS regset;
|
||||
struct SREGS sregset;
|
||||
|
||||
for (Red=0; Red<4; Red++) {
|
||||
for (Green=0; Green<4; Green++) {
|
||||
for (Blue=0; Blue<4; Blue++) {
|
||||
Index = (Red<<4)+(Green<<2)+Blue;
|
||||
for (Red=0; Red<4; Red++) {
|
||||
for (Green=0; Green<4; Green++) {
|
||||
for (Blue=0; Blue<4; Blue++) {
|
||||
Index = (Red<<4)+(Green<<2)+Blue;
|
||||
PaletteBlock[Index][0] = Gamma4Levels[Red];
|
||||
PaletteBlock[Index][1] = Gamma4Levels[Green];
|
||||
PaletteBlock[Index][2] = Gamma4Levels[Blue];
|
||||
|
|
@ -100,19 +100,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
for (Red=0; Red<64; Red++) {
|
||||
for (Red=0; Red<64; Red++) {
|
||||
PaletteBlock[64+Red][0] = Gamma64Levels[Red];
|
||||
PaletteBlock[64+Red][1] = 0;
|
||||
PaletteBlock[64+Red][2] = 0;
|
||||
}
|
||||
|
||||
for (Green=0; Green<64; Green++) {
|
||||
for (Green=0; Green<64; Green++) {
|
||||
PaletteBlock[128+Green][0] = 0;
|
||||
PaletteBlock[128+Green][1] = Gamma64Levels[Green];
|
||||
PaletteBlock[128+Green][2] = 0;
|
||||
}
|
||||
|
||||
for (Blue=0; Blue<64; Blue++) {
|
||||
for (Blue=0; Blue<64; Blue++) {
|
||||
PaletteBlock[192+Blue][0] = 0;
|
||||
PaletteBlock[192+Blue][1] = 0;
|
||||
PaletteBlock[192+Blue][2] = Gamma64Levels[Blue];
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
regset.x.dx = (unsigned int)PaletteBlock; /* offset of array from which
|
||||
to load RGB settings */
|
||||
sregset.es = DS; /* segment of array from which to load settings */
|
||||
int86x(0x10, &regset, &regset, &sregset); /* load the palette block */
|
||||
int86x(0x10, &regset, &regset, &sregset); /* load the palette block */
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
|
|
|
|||
18
55-03.html
18
55-03.html
|
|
@ -44,22 +44,22 @@
|
|||
special-cased, and everything else is handled by a 2-2-2 model. */
|
||||
int ModelColorToColorIndex(ModelColor * Color)
|
||||
{
|
||||
if (Color->Red == 0) {
|
||||
if (Color->Green == 0) {
|
||||
if (Color->Red == 0) {
|
||||
if (Color->Green == 0) {
|
||||
/* Pure blue */
|
||||
return(192+(Color->Blue >> 2));
|
||||
} else if (Color->Blue == 0) {
|
||||
return(192+(Color->Blue >> 2));
|
||||
} else if (Color->Blue == 0) {
|
||||
/* Pure green */
|
||||
return(128+(Color->Green >> 2));
|
||||
return(128+(Color->Green >> 2));
|
||||
}
|
||||
} else if ((Color->Green == 0) && (Color->Blue == 0)) {
|
||||
} else if ((Color->Green == 0) && (Color->Blue == 0)) {
|
||||
/* Pure red */
|
||||
return(64+(Color->Red >> 2));
|
||||
return(64+(Color->Red >> 2));
|
||||
}
|
||||
/* Multi-color mix; look up the index with the two most significant bits
|
||||
of each color component */
|
||||
return(((Color->Red & 0xC0) >> 2) | ((Color->Green & 0xC0) >> 4) |
|
||||
((Color->Blue & 0xC0) >> 6));
|
||||
return(((Color->Red & 0xC0) >> 2) | ((Color->Green & 0xC0) >> 4) |
|
||||
((Color->Blue & 0xC0) >> 6));
|
||||
}
|
||||
|
||||
</PRE>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
; Demonstrates drawing solid text on the VGA, using the BitMan’s write mode
|
||||
; 3-based, one-pass technique.
|
||||
|
||||
CHAR_HEIGHT equ 8 ;# of scan lines per character (must be <256)
|
||||
CHAR_HEIGHT equ 8 ;# of scan lines per character (must be <256)
|
||||
SCREEN_HEIGHT equ 480 ;# of scan lines per screen
|
||||
SCREEN_SEGMENT equ 0a000h ;where screen memory is
|
||||
FG_COLOR equ 14 ;text color
|
||||
|
|
@ -64,14 +64,14 @@
|
|||
.stack 200h
|
||||
.data
|
||||
Line dw ? ;current line #
|
||||
CharHeight dw ? ;# of scan lines in each character (must be <256)
|
||||
CharHeight dw ? ;# of scan lines in each character (must be <256)
|
||||
MaxLines dw ? ;max # of scan lines of text that will fit on screen
|
||||
LineWidthBytes dw ? ;offset from one scan line to the next
|
||||
FontPtr dd ? ;pointer to font with which to draw
|
||||
SampleString label byte
|
||||
db ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
|
||||
db ‘abcdefghijklmnopqrstuvwxyz’
|
||||
db ‘0123456789!@#$%^&*(),<.>/?;:’,0
|
||||
db ‘0123456789!@#$%^&*(),<.>/?;:’,0
|
||||
|
||||
.code
|
||||
start:
|
||||
|
|
|
|||
128
56-03.html
128
56-03.html
|
|
@ -50,10 +50,10 @@
|
|||
texture mapped onto it */
|
||||
#define DRAW_TEXTURED_POLYGON(PointList,NumPoints,TexVerts,TexMap) \
|
||||
Polygon.Length = NumPoints; Polygon.PointPtr = PointList; \
|
||||
DrawTexturedPolygon(&Polygon, TexVerts, TexMap);
|
||||
#define FIXED_TO_INT(FixedVal) ((int) (FixedVal >> 16))
|
||||
DrawTexturedPolygon(&Polygon, TexVerts, TexMap);
|
||||
#define FIXED_TO_INT(FixedVal) ((int) (FixedVal >> 16))
|
||||
#define ROUND_FIXED_TO_INT(FixedVal) \
|
||||
((int) ((FixedVal + DOUBLE_TO_FIXED(0.5)) >> 16))
|
||||
((int) ((FixedVal + DOUBLE_TO_FIXED(0.5)) >> 16))
|
||||
/* Retrieves specified pixel from specified image bitmap of specified width. */
|
||||
#define GET_IMAGE_PIXEL(TexMapBits, TexMapWidth, X, Y) \
|
||||
TexMapBits[(Y * TexMapWidth) + X]
|
||||
|
|
@ -97,10 +97,10 @@ extern void DrawTexturedPolygon(PointListHeader *, Point *, TextureMap *);
|
|||
“Convex” means that every horizontal line drawn through the polygon at any
|
||||
point would cross exactly two active edges (neither horizontal lines nor
|
||||
zero-length edges count as active edges; both are acceptable anywhere in
|
||||
the polygon), and that the right & left edges never cross. Nonconvex
|
||||
the polygon), and that the right & left edges never cross. Nonconvex
|
||||
polygons won’t be drawn properly. Can’t fail. */
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include “polygon.h”
|
||||
/* Describes the current location and stepping, in both the source and
|
||||
the destination, of an edge */
|
||||
|
|
@ -143,13 +143,13 @@ void DrawTexturedPolygon(PointListHeader * Polygon, Point * TexVerts,
|
|||
{
|
||||
int MinY, MaxY, MinVert, i;
|
||||
EdgeScan LeftEdge, RightEdge;
|
||||
NumVerts = Polygon->Length;
|
||||
VertexPtr = Polygon->PointPtr;
|
||||
NumVerts = Polygon->Length;
|
||||
VertexPtr = Polygon->PointPtr;
|
||||
TexVertsPtr = TexVerts;
|
||||
TexMapBits = TexMap->TexMapBits;
|
||||
TexMapWidth = TexMap->TexMapWidth;
|
||||
TexMapBits = TexMap->TexMapBits;
|
||||
TexMapWidth = TexMap->TexMapWidth;
|
||||
/* Nothing to draw if less than 3 vertices */
|
||||
if (NumVerts < 3) {
|
||||
if (NumVerts < 3) {
|
||||
return;
|
||||
}
|
||||
/* Scan through the destination polygon vertices and find the top of the
|
||||
|
|
@ -158,18 +158,18 @@ void DrawTexturedPolygon(PointListHeader * Polygon, Point * TexVerts,
|
|||
backface removal) */
|
||||
MinY = 32767;
|
||||
MaxY = -32768;
|
||||
for (i=0; i<NumVerts; i++) {
|
||||
if (VertexPtr[i].Y < MinY) {
|
||||
for (i=0; i<NumVerts; i++) {
|
||||
if (VertexPtr[i].Y < MinY) {
|
||||
MinY = VertexPtr[i].Y;
|
||||
MinVert = i;
|
||||
}
|
||||
if (VertexPtr[i].Y > MaxY) {
|
||||
if (VertexPtr[i].Y > MaxY) {
|
||||
MaxY = VertexPtr[i].Y;
|
||||
MaxVert = i;
|
||||
}
|
||||
}
|
||||
/* Reject flat (0-pixel-high) polygons */
|
||||
if (MinY >= MaxY) {
|
||||
if (MinY >= MaxY) {
|
||||
return;
|
||||
}
|
||||
/* The destination Y coordinate is not edge specific; it applies to
|
||||
|
|
@ -180,9 +180,9 @@ void DrawTexturedPolygon(PointListHeader * Polygon, Point * TexVerts,
|
|||
by one in Y, so calculate the corresponding destination X step for
|
||||
each edge, and then the corresponding source image X and Y steps */
|
||||
LeftEdge.Direction = -1; /* set up left edge first */
|
||||
SetUpEdge(&LeftEdge, MinVert);
|
||||
SetUpEdge(&LeftEdge, MinVert);
|
||||
RightEdge.Direction = 1; /* set up right edge */
|
||||
SetUpEdge(&RightEdge, MinVert);
|
||||
SetUpEdge(&RightEdge, MinVert);
|
||||
/* Step down destination edges one scan line at a time. At each scan
|
||||
line, find the corresponding edge points in the source image. Scan
|
||||
between the edge points in the source, drawing the corresponding
|
||||
|
|
@ -192,20 +192,20 @@ void DrawTexturedPolygon(PointListHeader * Polygon, Point * TexVerts,
|
|||
in clockwise order as seen from the viewpoint) */
|
||||
for (;;) {
|
||||
/* Done if off bottom of clip rectangle */
|
||||
if (DestY >= ClipMaxY) {
|
||||
if (DestY >= ClipMaxY) {
|
||||
return;
|
||||
}
|
||||
/* Draw only if inside Y bounds of clip rectangle */
|
||||
if (DestY >= ClipMinY) {
|
||||
if (DestY >= ClipMinY) {
|
||||
/* Draw the scan line between the two current edges */
|
||||
ScanOutLine(&LeftEdge, &RightEdge);
|
||||
ScanOutLine(&LeftEdge, &RightEdge);
|
||||
}
|
||||
/* Advance the source and destination polygon edges, ending if we’ve
|
||||
scanned all the way to the bottom of the polygon */
|
||||
if (!StepEdge(&LeftEdge)) {
|
||||
if (!StepEdge(&LeftEdge)) {
|
||||
break;
|
||||
}
|
||||
if (!StepEdge(&RightEdge)) {
|
||||
if (!StepEdge(&RightEdge)) {
|
||||
break;
|
||||
}
|
||||
DestY++;
|
||||
|
|
@ -218,28 +218,28 @@ int StepEdge(EdgeScan * Edge)
|
|||
{
|
||||
/* Count off the scan line we stepped last time; if this edge is
|
||||
finished, try to start another one */
|
||||
if (--Edge->RemainingScans == 0) {
|
||||
if (--Edge->RemainingScans == 0) {
|
||||
/* Set up the next edge; done if there is no next edge */
|
||||
if (SetUpEdge(Edge, Edge->CurrentEnd) == 0) {
|
||||
if (SetUpEdge(Edge, Edge->CurrentEnd) == 0) {
|
||||
return(0); /* no more edges; done drawing polygon */
|
||||
}
|
||||
return(1); /* all set to draw the new edge */
|
||||
}
|
||||
/* Step the current source edge */
|
||||
Edge->SourceX += Edge->SourceStepX;
|
||||
Edge->SourceY += Edge->SourceStepY;
|
||||
Edge->SourceX += Edge->SourceStepX;
|
||||
Edge->SourceY += Edge->SourceStepY;
|
||||
/* Step dest X with Bresenham-style variables, to get precise dest pixel
|
||||
placement and avoid gaps */
|
||||
Edge->DestX += Edge->DestXIntStep; /* whole pixel step */
|
||||
Edge->DestX += Edge->DestXIntStep; /* whole pixel step */
|
||||
/* Do error term stuff for fractional pixel X step handling */
|
||||
if ((Edge->DestXErrTerm += Edge->DestXAdjUp) > 0) {
|
||||
Edge->DestX += Edge->DestXDirection;
|
||||
Edge->DestXErrTerm -= Edge->DestXAdjDown;
|
||||
if ((Edge->DestXErrTerm += Edge->DestXAdjUp) > 0) {
|
||||
Edge->DestX += Edge->DestXDirection;
|
||||
Edge->DestXErrTerm -= Edge->DestXAdjDown;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
/* Sets up an edge to be scanned; the edge starts at StartVert and proceeds
|
||||
in direction Edge->Direction through the vertex list. Edge->Direction must
|
||||
in direction Edge->Direction through the vertex list. Edge->Direction must
|
||||
be set prior to call; -1 to scan a left edge (backward through the vertex
|
||||
list), 1 to scan a right edge (forward through the vertex list).
|
||||
Automatically skips over 0-height edges. Returns 1 for success, or 0 if
|
||||
|
|
@ -255,41 +255,41 @@ int SetUpEdge(EdgeScan * Edge, int StartVert)
|
|||
}
|
||||
/* Advance to the next vertex, wrapping if we run off the start or end
|
||||
of the vertex list */
|
||||
NextVert = StartVert + Edge->Direction;
|
||||
if (NextVert >= NumVerts) {
|
||||
NextVert = StartVert + Edge->Direction;
|
||||
if (NextVert >= NumVerts) {
|
||||
NextVert = 0;
|
||||
} else if (NextVert < 0) {
|
||||
} else if (NextVert < 0) {
|
||||
NextVert = NumVerts - 1;
|
||||
}
|
||||
/* Calculate the variables for this edge and done if this is not a
|
||||
zero-height edge */
|
||||
if ((Edge->RemainingScans =
|
||||
if ((Edge->RemainingScans =
|
||||
VertexPtr[NextVert].Y - VertexPtr[StartVert].Y) != 0) {
|
||||
DestYHeight = INT_TO_FIXED(Edge->RemainingScans);
|
||||
Edge->CurrentEnd = NextVert;
|
||||
Edge->SourceX = INT_TO_FIXED(TexVertsPtr[StartVert].X);
|
||||
Edge->SourceY = INT_TO_FIXED(TexVertsPtr[StartVert].Y);
|
||||
Edge->SourceStepX = FixedDiv(INT_TO_FIXED(TexVertsPtr[NextVert].X) -
|
||||
Edge->SourceX, DestYHeight);
|
||||
Edge->SourceStepY = FixedDiv(INT_TO_FIXED(TexVertsPtr[NextVert].Y) -
|
||||
Edge->SourceY, DestYHeight);
|
||||
DestYHeight = INT_TO_FIXED(Edge->RemainingScans);
|
||||
Edge->CurrentEnd = NextVert;
|
||||
Edge->SourceX = INT_TO_FIXED(TexVertsPtr[StartVert].X);
|
||||
Edge->SourceY = INT_TO_FIXED(TexVertsPtr[StartVert].Y);
|
||||
Edge->SourceStepX = FixedDiv(INT_TO_FIXED(TexVertsPtr[NextVert].X) -
|
||||
Edge->SourceX, DestYHeight);
|
||||
Edge->SourceStepY = FixedDiv(INT_TO_FIXED(TexVertsPtr[NextVert].Y) -
|
||||
Edge->SourceY, DestYHeight);
|
||||
/* Set up Bresenham-style variables for dest X stepping */
|
||||
Edge->DestX = VertexPtr[StartVert].X;
|
||||
Edge->DestX = VertexPtr[StartVert].X;
|
||||
if ((DestXWidth =
|
||||
(VertexPtr[NextVert].X - VertexPtr[StartVert].X)) < 0) {
|
||||
(VertexPtr[NextVert].X - VertexPtr[StartVert].X)) < 0) {
|
||||
/* Set up for drawing right to left */
|
||||
Edge->DestXDirection = -1;
|
||||
Edge->DestXDirection = -1;
|
||||
DestXWidth = -DestXWidth;
|
||||
Edge->DestXErrTerm = 1 - Edge->RemainingScans;
|
||||
Edge->DestXIntStep = -(DestXWidth / Edge->RemainingScans);
|
||||
Edge->DestXErrTerm = 1 - Edge->RemainingScans;
|
||||
Edge->DestXIntStep = -(DestXWidth / Edge->RemainingScans);
|
||||
} else {
|
||||
/* Set up for drawing left to right */
|
||||
Edge->DestXDirection = 1;
|
||||
Edge->DestXErrTerm = 0;
|
||||
Edge->DestXIntStep = DestXWidth / Edge->RemainingScans;
|
||||
Edge->DestXDirection = 1;
|
||||
Edge->DestXErrTerm = 0;
|
||||
Edge->DestXIntStep = DestXWidth / Edge->RemainingScans;
|
||||
}
|
||||
Edge->DestXAdjUp = DestXWidth % Edge->RemainingScans;
|
||||
Edge->DestXAdjDown = Edge->RemainingScans;
|
||||
Edge->DestXAdjUp = DestXWidth % Edge->RemainingScans;
|
||||
Edge->DestXAdjDown = Edge->RemainingScans;
|
||||
return(1); /* success */
|
||||
}
|
||||
StartVert = NextVert; /* keep looking for a non-0-height edge */
|
||||
|
|
@ -298,17 +298,17 @@ int SetUpEdge(EdgeScan * Edge, int StartVert)
|
|||
/* Texture-map-draw the scan line between two edges. */
|
||||
void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge)
|
||||
{
|
||||
Fixedpoint SourceX = LeftEdge->SourceX;
|
||||
Fixedpoint SourceY = LeftEdge->SourceY;
|
||||
int DestX = LeftEdge->DestX;
|
||||
int DestXMax = RightEdge->DestX;
|
||||
Fixedpoint SourceX = LeftEdge->SourceX;
|
||||
Fixedpoint SourceY = LeftEdge->SourceY;
|
||||
int DestX = LeftEdge->DestX;
|
||||
int DestXMax = RightEdge->DestX;
|
||||
Fixedpoint DestWidth;
|
||||
Fixedpoint SourceXStep, SourceYStep;
|
||||
/* Nothing to do if fully X clipped */
|
||||
if ((DestXMax <= ClipMinX) || (DestX >= ClipMaxX)) {
|
||||
if ((DestXMax <= ClipMinX) || (DestX >= ClipMaxX)) {
|
||||
return;
|
||||
}
|
||||
if ((DestXMax - DestX) <= 0) {
|
||||
if ((DestXMax - DestX) <= 0) {
|
||||
return; /* nothing to draw */
|
||||
}
|
||||
/* Width of destination scan line, for scaling. Note: because this is an
|
||||
|
|
@ -321,21 +321,21 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge)
|
|||
DestWidth = INT_TO_FIXED(DestXMax - DestX);
|
||||
/* Calculate source steps that correspond to each dest X step (across
|
||||
the scan line) */
|
||||
SourceXStep = FixedDiv(RightEdge->SourceX - SourceX, DestWidth);
|
||||
SourceYStep = FixedDiv(RightEdge->SourceY - SourceY, DestWidth);
|
||||
SourceXStep = FixedDiv(RightEdge->SourceX - SourceX, DestWidth);
|
||||
SourceYStep = FixedDiv(RightEdge->SourceY - SourceY, DestWidth);
|
||||
/* Clip right edge if necessary */
|
||||
if (DestXMax > ClipMaxX) {
|
||||
if (DestXMax > ClipMaxX) {
|
||||
DestXMax = ClipMaxX;
|
||||
}
|
||||
/* Clip left edge if necssary */
|
||||
if (DestX < ClipMinX) {
|
||||
if (DestX < ClipMinX) {
|
||||
SourceX += SourceXStep * (ClipMinX - DestX);
|
||||
SourceY += SourceYStep * (ClipMinX - DestX);
|
||||
DestX = ClipMinX;
|
||||
}
|
||||
/* Scan across the destination scan line, updating the source image
|
||||
position accordingly */
|
||||
for (; DestX<DestXMax; DestX++) {
|
||||
for (; DestX<DestXMax; DestX++) {
|
||||
/* Get currently mapped pixel out of image and draw it to screen */
|
||||
WritePixelX(DestX, DestY,
|
||||
GET_IMAGE_PIXEL(TexMapBits, TexMapWidth,
|
||||
|
|
|
|||
26
57-02.html
26
57-02.html
|
|
@ -57,21 +57,21 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge)
|
|||
{
|
||||
Fixedpoint SourceX;
|
||||
Fixedpoint SourceY;
|
||||
int DestX = LeftEdge->DestX;
|
||||
int DestXMax = RightEdge->DestX;
|
||||
int DestX = LeftEdge->DestX;
|
||||
int DestXMax = RightEdge->DestX;
|
||||
Fixedpoint DestWidth;
|
||||
Fixedpoint SourceStepX, SourceStepY;
|
||||
|
||||
/* Nothing to do if fully X clipped */
|
||||
if ((DestXMax <= ClipMinX) || (DestX >= ClipMaxX)) {
|
||||
if ((DestXMax <= ClipMinX) || (DestX >= ClipMaxX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((DestXMax - DestX) <= 0) {
|
||||
if ((DestXMax - DestX) <= 0) {
|
||||
return; /* nothing to draw */
|
||||
}
|
||||
SourceX = LeftEdge->SourceX;
|
||||
SourceY = LeftEdge->SourceY;
|
||||
SourceX = LeftEdge->SourceX;
|
||||
SourceY = LeftEdge->SourceY;
|
||||
|
||||
/* Width of destination scan line, for scaling. Note: because this is an
|
||||
integer-based scaling, it can have a total error of as much as nearly
|
||||
|
|
@ -84,30 +84,30 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge)
|
|||
|
||||
/* Calculate source steps that correspond to each dest X step (across
|
||||
the scan line) */
|
||||
SourceStepX = FixedDiv(RightEdge->SourceX - SourceX, DestWidth);
|
||||
SourceStepY = FixedDiv(RightEdge->SourceY - SourceY, DestWidth);
|
||||
SourceStepX = FixedDiv(RightEdge->SourceX - SourceX, DestWidth);
|
||||
SourceStepY = FixedDiv(RightEdge->SourceY - SourceY, DestWidth);
|
||||
|
||||
/* Advance 1/2 step in the stepping direction, to space scanned pixels
|
||||
evenly between the left and right edges. (There’s a slight inaccuracy
|
||||
in dividing negative numbers by 2 by shifting rather than dividing,
|
||||
but the inaccuracy is in the least significant bit, and we’ll just
|
||||
live with it.) */
|
||||
SourceX += SourceStepX >> 1;
|
||||
SourceY += SourceStepY >> 1;
|
||||
SourceX += SourceStepX >> 1;
|
||||
SourceY += SourceStepY >> 1;
|
||||
|
||||
/* Clip right edge if necssary */
|
||||
if (DestXMax > ClipMaxX)
|
||||
if (DestXMax > ClipMaxX)
|
||||
DestXMax = ClipMaxX;
|
||||
|
||||
/* Clip left edge if necssary */
|
||||
if (DestX < ClipMinX) {
|
||||
if (DestX < ClipMinX) {
|
||||
SourceX += FixedMul(SourceStepX, INT-TO-FIXED(ClipMinX - DestX));
|
||||
SourceY += FixedMul(SourceStepY, INT-TO-FIXED(ClipMinX - DestX));
|
||||
DestX = ClipMinX;
|
||||
}
|
||||
/* Scan across the destination scan line, updating the source image
|
||||
position accordingly */
|
||||
for (; DestX<DestXMax; DestX++) {
|
||||
for (; DestX<DestXMax; DestX++) {
|
||||
/* Get the currently mapped pixel out of the image and draw it to
|
||||
the screen */
|
||||
WritePixelX(DestX, DestY,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ DestXAdjDown dw ? ;amount to subtract from error term when the
|
|||
EdgeScan ends
|
||||
|
||||
Parms struc
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
dw 2 dup(?) ;return address & pushed BP
|
||||
LeftEdge dw ? ;pointer to EdgeScan structure for left edge
|
||||
RightEdge dw ? ;pointer to EdgeScan structure for right edge
|
||||
Parms ends
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
; EDX = fractional source texture Y coordinate in lower
|
||||
; 15 bits of CX, fractional source texture X coord
|
||||
; in high word of ECX, bit 15 set to 0
|
||||
; SI = sum of integral X & Y source pointer advances
|
||||
; SI = sum of integral X & Y source pointer advances
|
||||
; DS:DI = initial destination pointer
|
||||
; SS:BP = initial source texture pointer
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ SCANOFFSET=0
|
|||
add edx,ecx ;advance frac Y in DX,
|
||||
; frac X in high word of EDX
|
||||
adc bp,si ;advance source pointer by integral
|
||||
; X & Y amount, also accounting for
|
||||
; X & Y amount, also accounting for
|
||||
; carry from X fractional addition
|
||||
test dh,80h ;carry from Y fractional addition?
|
||||
jz @F ;no
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
; rather than a horizontal scanline. Maxed-out 32-bit version.
|
||||
;
|
||||
; At this point:
|
||||
; EAX = sum of integral X & Y source pointer advances
|
||||
; EAX = sum of integral X & Y source pointer advances
|
||||
; ECX = source pointer increment to advance one in Y
|
||||
; EDX = fractional source texture Y coordinate in lower
|
||||
; 15 bits of DX, fractional source texture X coord
|
||||
|
|
@ -62,7 +62,7 @@ SCANOFFSET=0
|
|||
add edx,ebp ;advance frac Y in DX,
|
||||
; frac X in high word of EDX
|
||||
adc esi,eax ;advance source pointer by integral
|
||||
; X & Y amount, also accounting for
|
||||
; X & Y amount, also accounting for
|
||||
; carry from X fractional addition
|
||||
mov [edi+SCANOFFSET],bl ;set screen pixel
|
||||
; (located here to avoid 486
|
||||
|
|
|
|||
16
59-03.html
16
59-03.html
|
|
@ -76,20 +76,20 @@
|
|||
void WalkBSPTree(NODE *pNode)
|
||||
{
|
||||
if (WallFacingForward(pNode) {
|
||||
if (pNode->BackChild) {
|
||||
WalkBSPTree(pNode->BackChild);
|
||||
if (pNode->BackChild) {
|
||||
WalkBSPTree(pNode->BackChild);
|
||||
}
|
||||
Draw(pNode);
|
||||
if (pNode->FrontChild) {
|
||||
WalkBSPTree(pNode->FrontChild);
|
||||
if (pNode->FrontChild) {
|
||||
WalkBSPTree(pNode->FrontChild);
|
||||
}
|
||||
} else {
|
||||
if (pNode->FrontChild) {
|
||||
WalkBSPTree(pNode->FrontChild);
|
||||
if (pNode->FrontChild) {
|
||||
WalkBSPTree(pNode->FrontChild);
|
||||
}
|
||||
Draw(pNode);
|
||||
if (pNode->BackChild) {
|
||||
WalkBSPTree(pNode->BackChild);
|
||||
if (pNode->BackChild) {
|
||||
WalkBSPTree(pNode->BackChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
59-04.html
20
59-04.html
|
|
@ -49,7 +49,7 @@
|
|||
<PRE>
|
||||
// Function to inorder walk a tree, using code recursion.
|
||||
// Tested with 32-bit Visual C++ 1.10.
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include “tree.h”
|
||||
extern void Visit(NODE *pNode);
|
||||
void WalkTree(NODE *pNode)
|
||||
|
|
@ -58,16 +58,16 @@ void WalkTree(NODE *pNode)
|
|||
if (pNode != NULL)
|
||||
{
|
||||
// Traverse the left subtree, if there is one
|
||||
if (pNode->pLeftChild != NULL)
|
||||
if (pNode->pLeftChild != NULL)
|
||||
{
|
||||
WalkTree(pNode->pLeftChild);
|
||||
WalkTree(pNode->pLeftChild);
|
||||
}
|
||||
// Visit this node
|
||||
Visit(pNode);
|
||||
// Traverse the right subtree, if there is one
|
||||
if (pNode->pRightChild != NULL)
|
||||
if (pNode->pRightChild != NULL)
|
||||
{
|
||||
WalkTree(pNode->pRightChild);
|
||||
WalkTree(pNode->pRightChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ struct _NODE *pRightChild;
|
|||
// Function to inorder walk a tree, using data recursion.
|
||||
// No stack overflow testing is performed.
|
||||
// Tested with 32-bit Visual C++ 1.10.
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include “tree.h”
|
||||
#define MAX_PUSHED_NODES 100
|
||||
extern void Visit(NODE *pNode);
|
||||
|
|
@ -118,10 +118,10 @@ void WalkTree(NODE *pNode)
|
|||
// Keep doing this until we come to a node
|
||||
// with no left child; that’s the next node to
|
||||
// visit in inorder sequence
|
||||
while (pNode->pLeftChild != NULL)
|
||||
while (pNode->pLeftChild != NULL)
|
||||
{
|
||||
*pNodeStack++ = pNode;
|
||||
pNode = pNode->pLeftChild;
|
||||
pNode = pNode->pLeftChild;
|
||||
}
|
||||
// We’re at a node that has no left child, so
|
||||
// visit the node, then visit the right
|
||||
|
|
@ -143,11 +143,11 @@ void WalkTree(NODE *pNode)
|
|||
// passed on the way down, until we find a
|
||||
// node with a right subtree to traverse
|
||||
// or run out of pushed nodes and are done
|
||||
if (pNode->pRightChild != NULL)
|
||||
if (pNode->pRightChild != NULL)
|
||||
{
|
||||
// Current node has a right child;
|
||||
// traverse the right subtree
|
||||
pNode = pNode->pRightChild;
|
||||
pNode = pNode->pRightChild;
|
||||
break;
|
||||
}
|
||||
// Pop the next node from the stack so
|
||||
|
|
|
|||
30
59-05.html
30
59-05.html
|
|
@ -53,10 +53,10 @@
|
|||
// Sample program to exercise and time the performance of
|
||||
// implementations of WalkTree().
|
||||
// Tested with 32-bit Visual C++ 1.10 under Windows NT.
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include “tree.h”
|
||||
long VisitCount = 0;
|
||||
void main(void);
|
||||
|
|
@ -68,12 +68,12 @@ void main()
|
|||
int i;
|
||||
long StartTime;
|
||||
// Build a sample tree
|
||||
BuildTree(&RootNode, 14);
|
||||
BuildTree(&RootNode, 14);
|
||||
// Walk the tree 1000 times and see how long it takes
|
||||
StartTime = time(NULL);
|
||||
for (i=0; i<1000; i++)
|
||||
for (i=0; i<1000; i++)
|
||||
{
|
||||
WalkTree(&RootNode);
|
||||
WalkTree(&RootNode);
|
||||
}
|
||||
printf(“Seconds elapsed: %ld\n”,
|
||||
time(NULL) - StartTime);
|
||||
|
|
@ -87,25 +87,25 @@ void BuildTree(NODE *pNode, int RemainingDepth)
|
|||
{
|
||||
if (RemainingDepth == 0)
|
||||
{
|
||||
pNode->pLeftChild = NULL;
|
||||
pNode->pRightChild = NULL;
|
||||
pNode->pLeftChild = NULL;
|
||||
pNode->pRightChild = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pNode->pLeftChild = malloc(sizeof(NODE));
|
||||
if (pNode->pLeftChild == NULL)
|
||||
pNode->pLeftChild = malloc(sizeof(NODE));
|
||||
if (pNode->pLeftChild == NULL)
|
||||
{
|
||||
printf(“Out of memory\n”);
|
||||
exit(1);
|
||||
}
|
||||
pNode->pRightChild = malloc(sizeof(NODE));
|
||||
if (pNode->pRightChild == NULL)
|
||||
pNode->pRightChild = malloc(sizeof(NODE));
|
||||
if (pNode->pRightChild == NULL)
|
||||
{
|
||||
printf(“Out of memory\n”);
|
||||
exit(1);
|
||||
}
|
||||
BuildTree(pNode->pLeftChild, RemainingDepth - 1);
|
||||
BuildTree(pNode->pRightChild, RemainingDepth - 1);
|
||||
BuildTree(pNode->pLeftChild, RemainingDepth - 1);
|
||||
BuildTree(pNode->pRightChild, RemainingDepth - 1);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
</P>
|
||||
<P>For our purposes, <I>projection</I> is the process of mapping coordinates onto a line or surface. <I>Perspective projection</I> projects 3-D coordinates onto a viewplane, scaling coordinates according to their z distance from the viewpoint in order to provide proper perspective. <I>Objectspace</I> is the coordinate space in which an object is defined, independent of other objects and the world itself. <I>Worldspace</I> is the absolute frame of reference for a 3-D world; all objects’ locations and orientations are with respect to worldspace, and this is the frame of reference around which the viewpoint and view direction move. <I>Viewspace</I> is worldspace as seen from the viewpoint, looking in the view direction. <I>Screenspace</I> is viewspace after perspective projection and scaling to the screen.</P>
|
||||
<P>Finally, <I>transformation</I> is the process of converting points from one coordinate space into another; in our case, that’ll mean rotating and translating (moving) points from objectspace or worldspace to viewspace.</P>
|
||||
<P>For additional information, you might want to check out Foley & van Dam’s <I>Computer Graphics</I> (ISBN 0-201-12110-7), or the chapters in this book dealing with my X-Sharp 3-D graphics library.</P>
|
||||
<P>For additional information, you might want to check out Foley & van Dam’s <I>Computer Graphics</I> (ISBN 0-201-12110-7), or the chapters in this book dealing with my X-Sharp 3-D graphics library.</P>
|
||||
<H3><A NAME="Heading5"></A>The Dot Product</H3>
|
||||
<P>Now we’re ready to move on to the dot product. Given two vectors <B>U</B> = [u<SUB>1</SUB> u<SUB>2</SUB> u<SUB>3</SUB>] and <B>V</B> = [v<SUB>1</SUB> v<SUB>2</SUB> v<SUB>3</SUB>], their dot product, denoted by the symbol •, is calculated as:</P>
|
||||
<P ALIGN="LEFT"><P ALIGN="CENTER"><IMG SRC="images/61-02d.jpg"></P>
|
||||
|
|
|
|||
10
62-02.html
10
62-02.html
|
|
@ -262,8 +262,8 @@ void ClipWalls()
|
|||
// perform a quick test for trivial rejection by seeing if
|
||||
// the end point is outside the view triangle on the same
|
||||
// side as the start point
|
||||
if (((tempstartx>tempstartz) && (tempendx>tempendz)) ||
|
||||
((tempstartx<-tempstartz) && (tempendx<-tempendz)))
|
||||
if (((tempstartx>tempstartz) && (tempendx>tempendz)) ||
|
||||
((tempstartx<-tempstartz) && (tempendx<-tempendz)))
|
||||
// Fully clipped—trivially reject
|
||||
goto NextWall;
|
||||
// Clip the start point
|
||||
|
|
@ -327,9 +327,9 @@ void ClipWalls()
|
|||
(tempendwalltop > tempendz) ||
|
||||
(tempendwallbottom < -tempendz)) {
|
||||
// Not trivially unclipped; check for fully clipped
|
||||
if ((tempstartwallbottom > tempstartz) &&
|
||||
(tempstartwalltop < -tempstartz) &&
|
||||
(tempendwallbottom > tempendz) &&
|
||||
if ((tempstartwallbottom > tempstartz) &&
|
||||
(tempstartwalltop < -tempstartz) &&
|
||||
(tempendwallbottom > tempendz) &&
|
||||
(tempendwalltop < -tempendz)) {
|
||||
// Outside view triangle, trivially clipped
|
||||
goto NextWall;
|
||||
|
|
|
|||
|
|
@ -108,11 +108,11 @@ FSUB ST(0),ST(1)
|
|||
<!-- CODE //-->
|
||||
<PRE>
|
||||
; use of fxch to allow addition of first two; products to start while third : multiplication finishes
|
||||
fld [vec0+0] ;starts & ends on cycle 0
|
||||
fld [vec0+0] ;starts & ends on cycle 0
|
||||
fmul [vec1+0] ;starts on cycle 1
|
||||
fld [vec0+4] ;starts & ends on cycle 2
|
||||
fld [vec0+4] ;starts & ends on cycle 2
|
||||
fmul [vec1+4] ;starts on cycle 3
|
||||
fld [vec0+8] ;starts & ends on cycle 4
|
||||
fld [vec0+8] ;starts & ends on cycle 4
|
||||
fmul [vec1+8] ;starts on cycle 5
|
||||
fxch st(1) ;no cost
|
||||
faddp st(2),st(0) ;starts on cycle 6
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue