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