diff --git a/src/chapter-07.md b/src/chapter-07.md index 8707015..f1a174f 100644 --- a/src/chapter-07.md +++ b/src/chapter-07.md @@ -246,21 +246,21 @@ the whole point.) .data ; Sample string to search through. SampleString label byte - db ‘This is a sample string of a long enough length ' - db ‘so that raw searching speed can outweigh any ' - db ‘extra set-up time that may be required.',0 + db 'This is a sample string of a long enough length ' + db 'so that raw searching speed can outweigh any ' + db 'extra set-up time that may be required.',0 SAMPLE_STRING_LENGTH equ $-SampleString ; User prompt. -Prompt db ‘Enter character to search for:$' +Prompt db 'Enter character to search for:$' ; Result status messages. ByteFoundMsg db 0dh,0ah - db ‘Specified byte found.',0dh,0ah,‘$' + db 'Specified byte found.',0dh,0ah,'$' ZeroByteFoundMsg db 0dh, 0ah - db ‘Zero byte encountered.',0dh,0ah,‘$' + db 'Zero byte encountered.',0dh,0ah,'$' NoByteFoundMsg db 0dh,0ah - db ‘Buffer exhausted with no match.', 0dh, 0ah, ‘$' + db 'Buffer exhausted with no match.', 0dh, 0ah, '$' .code Start proc near @@ -351,21 +351,21 @@ all the difference. .data ; Sample string to search through. SampleString label byte - db ‘This is a sample string of a long enough length ' - db ‘so that raw searching speed can outweigh any ' - db ‘extra set-up time that may be required.',0 + db 'This is a sample string of a long enough length ' + db 'so that raw searching speed can outweigh any ' + db 'extra set-up time that may be required.',0 SAMPLE_STRING_LENGTH equ $-SampleString ; User prompt. -Prompt db ‘Enter character to search for:$' +Prompt db 'Enter character to search for:$' ; Result status messages. ByteFoundMsg db 0dh,0ah - db ‘Specified byte found.',0dh,0ah,‘$' + db 'Specified byte found.',0dh,0ah,'$' ZeroByteFoundMsg db 0dh,0ah - db ‘Zero byte encountered.', 0dh, 0ah, ‘$' + db 'Zero byte encountered.', 0dh, 0ah, '$' NoByteFoundMsg db 0dh,0ah - db ‘Buffer exhausted with no match.', 0dh, 0ah, ‘$' + db 'Buffer exhausted with no match.', 0dh, 0ah, '$' ; Table of initial, possibly partial loop entry points for ; SearchMaxLength. diff --git a/src/chapter-16.md b/src/chapter-16.md index 002c87d..b327133 100644 --- a/src/chapter-16.md +++ b/src/chapter-16.md @@ -155,10 +155,10 @@ timed from a RAM disk on a 20 MHz 386. Ch = *BufferPtr++ & 0x7F; /* strip high bit, which some word processors set as an internal flag */ - CharFlag = ((Ch >= ‘a') && (Ch <= ‘z')) || - ((Ch >= ‘A') && (Ch <= ‘Z')) || - ((Ch >= ‘0') && (Ch <= ‘9')) || - (Ch == ‘\''); + CharFlag = ((Ch >= 'a') && (Ch <= 'z')) || + ((Ch >= 'A') && (Ch <= 'Z')) || + ((Ch >= '0') && (Ch <= '9')) || + (Ch == '\''); if ((!CharFlag) && PredCharFlag) { WordCo u nt++; } @@ -291,19 +291,19 @@ ScanLoop: and al,7fh ;strip high bit for word processors ; that set it as an internal flag mov bl,1 ;assume this is a char; CharFlag = 1; - cmp al,‘a' ;it is a char if between a and z + cmp al,'a' ;it is a char if between a and z jb CheckAZ - cmp al,‘z' + cmp al,'z' jna IsAChar CheckAZ: - cmp al,‘A' ;it is a char if between A and Z + cmp al,'A' ;it is a char if between A and Z jb Check09 - cmp al,‘Z' + cmp al,'Z' jna IsAChar Check09: - cmp al,‘0' ;it is a char if between 0 and 9 + cmp al,'0' ;it is a char if between 0 and 9 jb CheckApostrophe - cmp al,‘9' + cmp al,'9' jna IsAChar CheckApostrophe: cmp al,27h ;it is a char if an apostrophe @@ -745,7 +745,7 @@ jumping. mov di,[bp+CharFlag] mov bh,[di] ;bh = old CharFlag mov bl,[si] ;bl = character - add bh,‘A'-1 ;make bh into character + add bh,'A'-1 ;make bh into character add bx,bx ;prepare to index mov al,es:[bx] cbw ;get hi bit in ah (then bh) @@ -1155,7 +1155,7 @@ report a "location counter overflow" warning; ignore it.) #include #include -#define ChType( c ) (((c) & 0x7f) == ‘\'' || isalnum((c) & 0x7f)) +#define ChType( c ) (((c) & 0x7f) == '\'' || isalnum((c) & 0x7f)) int NoCarry[ 4 ] = { 0, 0x80, 1, 0x80 }; int Carry[ 4 ] = { 1, 0x81, 1, 0x80 }; diff --git a/src/chapter-17.md b/src/chapter-17.md index facb0d8..13802b6 100644 --- a/src/chapter-17.md +++ b/src/chapter-17.md @@ -176,7 +176,7 @@ void main() x = random(cellmap_width); y = random(cellmap_height); next_map.set_cell(x, y); - } while (—init_length); + } while (--init_length); current_map.copy_cells(next_map); // put init map in current_map enter_display_mode(); @@ -1207,7 +1207,7 @@ void cellmap::init() if (cell_state(x, y) == 0) { set_cell(x, y); } - } while (—init_length); + } while (--init_length); } ``` diff --git a/src/chapter-18.md b/src/chapter-18.md index 50844a8..b434fa7 100644 --- a/src/chapter-18.md +++ b/src/chapter-18.md @@ -249,7 +249,7 @@ void BuildMaps( void ) { unsigned short i, j, Size, x = 0, y, N1, N2, N3, C1, C2, C3; - printf( "_DATA segment ‘DATA'\nalign 2\n" ); + printf( "_DATA segment 'DATA'\nalign 2\n" ); printf( "public _CellMap\n" ); printf( "_CellMap label word\n" ); @@ -284,7 +284,7 @@ void BuildMaps( void ) printf( "Change1 dw offset _CHANGE:_ChangeList1\n" ); printf( "Change2 dw offset _CHANGE:_ChangeList2\n" ); printf( "ends\n\n" ); - printf( "_CHANGE segment para public ‘FAR_DATA'\n" ); + printf( "_CHANGE segment para public 'FAR_DATA'\n" ); } else { @@ -300,7 +300,7 @@ void BuildMaps( void ) printf( "dw %d dup (offset DGROUP:ChangeCell)\n", Size ); printf( "ends\n\n" ); - printf( "_LDMAP segment para public ‘FAR_DATA'\n" ); + printf( "_LDMAP segment para public 'FAR_DATA'\n" ); do { @@ -536,7 +536,7 @@ void Fix( char *Offset, char *Str, int JumpBack ) printf( "mov bh,[bx]\n" ); printf( "mov [bp+%s],bx\n", Offset ); - if( *Offset != ‘0' ) printf( "lea ax,[bp+%s]\n", Offset ); + if( *Offset != '0' ) printf( "lea ax,[bp+%s]\n", Offset ); else printf( "mov ax,bp\n" ); printf( "stosw\n" ); @@ -654,7 +654,7 @@ void main( void ) BuildMaps(); printf( "DGROUP group _DATA\n" ); - printf( "LIFE segment ‘CODE'\n" ); + printf( "LIFE segment 'CODE'\n" ); printf( "assume cs:LIFE,ds:DGROUP,ss:DGROUP,es:NOTHING\n" ); printf( ".386C\n" "public _NextGen\n\n" ); diff --git a/src/chapter-24.md b/src/chapter-24.md index 96614ed..078831c 100644 --- a/src/chapter-24.md +++ b/src/chapter-24.md @@ -126,7 +126,7 @@ only the enabled planes would be affected by each operation. ; the images with the background. ; By Michael Abrash. ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -149,23 +149,23 @@ GC_ROTATE equ 3 ;GC data rotate/logical function ; register index GC_MODE equ 5 ;GC mode register index ; -dseg segment para common ‘DATA' +dseg segment para common 'DATA' ; ; String used to label logical functions. ; LabelString label byte - db ‘UNMODIFIED AND OR XOR ' + db 'UNMODIFIED AND OR XOR ' LABEL_STRING_LENGTH equ $-LabelString ; ; Strings used to label fill patterns. ; -FillPatternFF db ‘Fill Pattern: 0FFh' +FillPatternFF db 'Fill Pattern: 0FFh' FILL_PATTERN_FF_LENGTH equ $ - FillPatternFF -FillPattern00 db ‘Fill Pattern: 000h' +FillPattern00 db 'Fill Pattern: 000h' FILL_PATTERN_00_LENGTH equ $ - FillPattern00 -FillPatternVert db ‘Fill Pattern: Vertical Bar' +FillPatternVert db 'Fill Pattern: Vertical Bar' FILL_PATTERN_VERT_LENGTH equ $ - FillPatternVert -FillPatternHorz db ‘Fill Pattern: Horizontal Bar' +FillPatternHorz db 'Fill Pattern: Horizontal Bar' FILL_PATTERN_HORZ_LENGTH equ $ - FillPatternHorz ; dseg ends @@ -192,7 +192,7 @@ TEXT_UP macro TEXT_STRING, TEXT_LENGTH, ROW, COLUMN int 10h endm ; -cseg segment para public ‘CODE' +cseg segment para public 'CODE' assume cs:cseg, ds:dseg start proc near mov ax,dseg diff --git a/src/chapter-25.md b/src/chapter-25.md index 9c16fcc..45fea60 100644 --- a/src/chapter-25.md +++ b/src/chapter-25.md @@ -112,7 +112,7 @@ BIOS, as well). ; for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h. ; By Michael Abrash. ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -127,13 +127,13 @@ GC_ROTATE equ 3 ;GC data rotate/logical function ; register index GC_BIT_MASK equ 8 ;GC bit mask register index ; -dseg segment para common ‘DATA' +dseg segment para common 'DATA' TEST_TEXT_ROW equ 69 ;row to display test text at TEST_TEXT_COL equ 17 ;column to display test text at TEST_TEXT_WIDTH equ 8 ;width of a character in pixels TestString label byte - db ‘Hello, world!',0 ;test string to print. + db 'Hello, world!',0 ;test string to print. FontPointer dd ? ;font offset dseg ends ; @@ -145,7 +145,7 @@ SETGC macro INDEX, SETTING out dx,ax endm ; -cseg segment para public ‘CODE' +cseg segment para public 'CODE' assume cs:cseg, ds:dseg start proc near mov ax,dseg @@ -452,7 +452,7 @@ set the Map Mask register to 01H and fill with blue. ; to memory that already contains data. ; By Michael Abrash. ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -475,7 +475,7 @@ SETSC macro INDEX, SETTING dec dx endm ; -cseg segment para public ‘CODE#146; +cseg segment para public 'CODE' assume cs:cseg start proc near ; @@ -575,7 +575,7 @@ off as well as 0FFH-bytes to planes that must be on. ; setting of memory that already contains data. ; By Michael Abrash. ; -stack segment para stack ‘STACK#146; +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -613,7 +613,7 @@ SETGC macro INDEX, SETTING dec dx endm ; -cseg segment para public ‘CODE#146; +cseg segment para public 'CODE' assume cs:cseg start proc near ; @@ -639,8 +639,8 @@ HorzBarLoop: dec bp jnz HorzBarLoop ; -; Fill screen with blue, using set/reset to force plane 0 to 1#146;s and all -; other plane to 0#146;s. +; Fill screen with blue, using set/reset to force plane 0 to 1's and all +; other plane to 0's. ; SETSC SC_MAP_MASK,0fh ;must set map mask to enable all ; planes, so set/reset values can @@ -707,7 +707,7 @@ be used to control individual pixels. ; with CPU data to modify setting of memory that already contains data. ; By Michael Abrash. ; -stack segment para stack ‘STACK#146; +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -745,7 +745,7 @@ SETGC macro INDEX, SETTING dec dx endm ; -cseg segment para public ‘CODE#146; +cseg segment para public 'CODE' assume cs:cseg start proc near ; diff --git a/src/chapter-26.md b/src/chapter-26.md index 3797fd1..3d45a23 100644 --- a/src/chapter-26.md +++ b/src/chapter-26.md @@ -91,7 +91,7 @@ characters can be drawn in any of the 16 available colors. ; Assembled with MASM ; By Michael Abrash ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -111,16 +111,16 @@ GC_ROTATE equ 3 ;GC data rotate/logical function GC_MODE equ 5 ;GC Mode register GC_BIT_MASK equ 8 ;GC bit mask register index ; -dseg segment para common ‘DATA' +dseg segment para common 'DATA' TEST_TEXT_ROW equ 69 ;row to display test text at TEST_TEXT_COL equ 17 ;column to display test text at TEST_TEXT_WIDTH equ 8 ;width of a character in pixels TestString label byte - db ‘Hello, world!',0 ;test string to print. + db 'Hello, world!',0 ;test string to print. FontPointer dd ? ;font offset dseg ends ; -cseg segment para public ‘CODE' +cseg segment para public 'CODE' assume cs:cseg, ds:dseg start proc near mov ax,dseg @@ -458,7 +458,7 @@ along with the tables used to alter the 8x14 and 8x16 ROM fonts into ; Assembled with MASM ; By Michael Abrash ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup(?) stack ends ; @@ -478,16 +478,16 @@ GC_ROTATE equ 3 ;GC data rotate/logical function GC_MODE equ 5 ;GC Mode register GC_BIT_MASK equ 8 ;GC bit mask register index ; -dseg segment para common ‘DATA' +dseg segment para common 'DATA' TEST_TEXT_ROW equ 69 ;row to display test text at TEST_TEXT_COL equ 17 ;column to display test text at TEST_TEXT_COLOR equ 0fh ;high intensity white TestString label byte - db ‘Hello, world!',0 ;test string to print. + db 'Hello, world!',0 ;test string to print. FontPointer dd ? ;font offset dseg ends ; -cseg segment para public ‘CODE' +cseg segment para public 'CODE' assume cs:cseg, ds:dseg start proc near mov ax,dseg diff --git a/src/chapter-27.md b/src/chapter-27.md index a93de13..c593617 100644 --- a/src/chapter-27.md +++ b/src/chapter-27.md @@ -182,7 +182,7 @@ image. ; ; By Michael Abrash ; -Stack segment para stack ‘STACK' +Stack segment para stack 'STACK' db 512 dup(0) Stack ends @@ -192,9 +192,9 @@ SC_INDEX equ 3c4h ;Sequence Controller I MAP_MASK equ 2 ;index of Map Mask register GC_INDEX equ 03ceh ;Graphics Controller Index reg GRAPHICS_MODE equ 5 ;index of Graphics Mode reg -BIT_MASKequ 8 ;index of Bit Mask reg +BIT_MASK equ 8 ;index of Bit Mask reg -Data segment para common ‘DATA' +Data segment para common 'DATA' ; ; Current location of "A" as it is animated across the screen. ; @@ -221,7 +221,7 @@ AImage label byte db 000h, 000h, 000h, 000h, 000h, 000h, 000h Data ends -Code segment para public ‘CODE' +Code segment para public 'CODE' assume cs:Code, ds:Data Start proc near mov ax,Data @@ -444,7 +444,7 @@ the CPU byte in write mode 2 to select the color in which to draw. ; ; By Michael Abrash ; -Stack segment para stack ‘STACK' +Stack segment para stack 'STACK' db 512 dup(0) Stack ends @@ -456,7 +456,7 @@ GC_INDEX equ 03ceh ;Graphics Controller Index reg GRAPHICS_MODE equ 5 ;index of Graphics Mode reg BIT_MASK equ 8 ;index of Bit Mask reg -Data segment para common ‘DATA' +Data segment para common 'DATA' Pattern0 db 16 db 0, 1, 2, 3, 4, 5, 6, 7, 8 db 9, 10, 11, 12, 13, 14, 15 @@ -468,7 +468,7 @@ Pattern3 db 9 db 1, 1, 1, 2, 2, 2, 4, 4, 4 Data ends -Code segment para public ‘CODE' +Code segment para public 'CODE' assume cs:Code, ds:Data Start proc near mov ax,Data @@ -811,8 +811,8 @@ Jolla, who wrote: "Suppose I have the EGA in mode 10H (640x350 16-color graphics). I would like to preserve some or all of the image while I temporarily switch to -text mode 3 to give my user a ‘Help' screen. Naturally memory is scarce -so I'd rather not make a copy of the video buffer at A000H to ‘remember' +text mode 3 to give my user a 'Help' screen. Naturally memory is scarce +so I'd rather not make a copy of the video buffer at A000H to 'remember' the image while I digress to the Help text. The EGA BIOS says that the screen memory will not be cleared on a mode set if bit 7 of AL is set. Yet if I try that, it is clear that writing text into the B800H buffer @@ -824,7 +824,7 @@ there a way to preserve the graphics image while I switch to text mode?'' "A corollary to this question is: Where does the 64/128/256K of EGA -memory ‘hide' when the EGA is in text mode? Some I guess is used to +memory 'hide' when the EGA is in text mode? Some I guess is used to store character sets, but what happens to the rest? Or rather, how can I protect it?" @@ -929,7 +929,7 @@ rewarding!) VGA to cover. ; ; By Michael Abrash ; -Stack segment para stack ‘STACK' +Stack segment para stack 'STACK' db 512 dup(0) Stack ends @@ -940,19 +940,19 @@ MAP_MASK equ 2 ;index of Map Mask register GC_INDEX equ 3ceh ;Graphics Controller Index register READ_MAP equ 4 ;index of Read Map register -Data segment para common ‘DATA' +Data segment para common 'DATA' GStrikeAnyKeyMsg0 label byte - db 0dh, 0ah, ‘Graphics mode', 0dh, 0ah - db ‘Strike any key to continue...', 0dh, 0ah, ‘$' + db 0dh, 0ah, 'Graphics mode', 0dh, 0ah + db 'Strike any key to continue...', 0dh, 0ah, '$' GStrikeAnyKeyMsg1 label byte - db 0dh, 0ah, ‘Graphics mode again', 0dh, 0ah - db ‘Strike any key to continue...', 0dh, 0ah, ‘$' + db 0dh, 0ah, 'Graphics mode again', 0dh, 0ah + db 'Strike any key to continue...', 0dh, 0ah, '$' TStrikeAnyKeyMsg label byte - db 0dh, 0ah, ‘Text mode', 0dh, 0ah - db ‘Strike any key to continue...', 0dh, 0ah, ‘$' + db 0dh, 0ah, 'Text mode', 0dh, 0ah + db 'Strike any key to continue...', 0dh, 0ah, '$' Plane2Save db 2000h dup (?) ;save area for plane 2 data ; where font gets loaded @@ -961,7 +961,7 @@ CharAttSave db 4000 dup (?) ;save area for memory wiped ; data in text mode Data ends -Code segment para public ‘CODE' +Code segment para public 'CODE' assume cs:Code, ds:Data Start proc near mov ax,10h @@ -1045,7 +1045,7 @@ FillBitMap: mov ax,TEXT_SEGMENT mov es,ax sub di,di - mov al,‘.' ;fill character + mov al,'.' ;fill character mov ah,7 ;fill attribute mov cx,4000/2 ;length of one text screen in words rep stosw diff --git a/src/chapter-28.md b/src/chapter-28.md index 41b178d..a8b407e 100644 --- a/src/chapter-28.md +++ b/src/chapter-28.md @@ -382,7 +382,7 @@ collisions, as illustrated by the code in Listing 28.2. ; ; By Michael Abrash ; -stack segment word stack `STACK' +stack segment word stack 'STACK' db 512 dup (?) stack ends ; @@ -395,7 +395,7 @@ COLOR_COMPARE EQU 2 ;Color Compare register index in GC GRAPHICS_MODE EQU 5 ;Graphics Mode register index in GC BIT_MASK EQU 8 ;Bit Mask register index in GC ; -code segment word `CODE' +code segment word 'CODE' assume cs:code Start proc near cld @@ -624,7 +624,7 @@ excellent pixel- and line-drawing code. ; stack segment word stack 'STACK' db 512 dup (?) -stackends +stack ends ; VGA_SEGMENT EQU 0a000h SCREEN_WIDTH EQU 80 ;in bytes diff --git a/src/chapter-29.md b/src/chapter-29.md index 7918865..574cfd8 100644 --- a/src/chapter-29.md +++ b/src/chapter-29.md @@ -81,19 +81,19 @@ READ_MAP equ 4 ;Read Map register index in G DISPLAYED_SCREEN_SIZE equ (640/8)*350 ;# of displayed bytes per plane in a ; hi-res graphics screen ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup (?) stack ends ; -Data segment word ‘DATA' -SampleText db ‘This is bit-mapped text, drawn in hi-res ' - db ‘EGA graphics mode 10h.', 0dh, 0ah, 0ah - db ‘Saving the screen (including this text)...' - db 0dh, 0ah, ‘$' -Filename db ‘SNAPSHOT.SCR',0 ;name of file we're saving to -ErrMsg1 db ‘*** Couldn't open SNAPSHOT.SCR ***',0dh,0ah,‘$' -ErrMsg2 db ‘*** Error writing to SNAPSHOT.SCR ***',0dh,0ah,‘$' -WaitKeyMsg db 0dh, 0ah, ‘Done. Press any key to end...',0dh,0ah,‘$' +Data segment word 'DATA' +SampleText db 'This is bit-mapped text, drawn in hi-res ' + db 'EGA graphics mode 10h.', 0dh, 0ah, 0ah + db 'Saving the screen (including this text)...' + db 0dh, 0ah, '$' +Filename db 'SNAPSHOT.SCR',0 ;name of file we're saving to +ErrMsg1 db '*** Couldn''t open SNAPSHOT.SCR ***',0dh,0ah,'$' +ErrMsg2 db '*** Error writing to SNAPSHOT.SCR ***',0dh,0ah,'$' +WaitKeyMsg db 0dh, 0ah, 'Done. Press any key to end...',0dh,0ah,'$' Handle dw ? ;handle of file we're saving to Plane db ? ;plane being read Data ends @@ -214,15 +214,15 @@ MAP_MASK equ 2 ;Map Mask register index in SC DISPLAYED_SCREEN_SIZE equ (640/8)*350 ;# of displayed bytes per plane in a ; hi-res graphics screen ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup (?) stack ends ; -Data segment word ‘DATA' -Filename db ‘SNAPSHOT.SCR',0 ;name of file we're restoring from -ErrMsg1 db ‘*** Couldn'‘t open SNAPSHOT.SCR ***',0dh,0ah,‘$' -ErrMsg2 db ‘*** Error reading from SNAPSHOT.SCR ***',0dh,0ah,‘$' -WaitKeyMsg db 0dh, 0ah, ‘Done. Press any key to end...',0dh,0ah,‘$' +Data segment word 'DATA' +Filename db 'SNAPSHOT.SCR',0 ;name of file we're restoring from +ErrMsg1 db '*** Couldn''t open SNAPSHOT.SCR ***',0dh,0ah,'$' +ErrMsg2 db '*** Error reading from SNAPSHOT.SCR ***',0dh,0ah,'$' +WaitKeyMsg db 0dh, 0ah, 'Done. Press any key to end...',0dh,0ah,'$' Handle dw ? ;handle of file we're restoring from Plane db ? ;plane being written Data ends @@ -529,16 +529,16 @@ BAR_HEIGHT equ 14 ;height of each bar TOP_BAR equ BAR_HEIGHT*6 ;start the bars down a bit to ; leave room for text ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup (?) stack ends ; -Data segment word ‘DATA' -KeyMsg db ‘Press any key to see the next color set. ' - db ‘There are 64 color sets in all.' +Data segment word 'DATA' +KeyMsg db 'Press any key to see the next color set. ' + db 'There are 64 color sets in all.' db 0dh, 0ah, 0ah, 0ah, 0ah - db 13 dup (‘ '), ‘Attribute' - db 38 dup (‘ '), ‘Color$' + db 13 dup (' '), 'Attribute' + db 38 dup (' '), 'Color$' ; ; Used to label the attributes of the color bars. ; @@ -546,23 +546,23 @@ AttributeNumbers label byte x= 0 rept 16 if x lt 10 - db ‘0', x+‘0', ‘h', 0ah, 8, 8, 8 + db '0', x+'0', 'h', 0ah, 8, 8, 8 else - db ‘0', x+‘A'-10, ‘h', 0ah, 8, 8, 8 + db '0', x+'A'-10, 'h', 0ah, 8, 8, 8 endif x= x+1 endm - db ‘$' + db '$' ; ; Used to label the colors of the color bars. (Color values are ; filled in on the fly.) ; ColorNumbers label byte rept 16 - db ‘000h', 0ah, 8, 8, 8, 8 + db '000h', 0ah, 8, 8, 8, 8 endm COLOR_ENTRY_LENGTH equ ($-ColorNumbers)/16 - db ‘$' + db '$' ; CurrentColor db ? ; @@ -718,10 +718,10 @@ BarUp endp BinToHexDigit proc near cmp al,9 ja IsHex - add al,‘0' + add al,'0' ret IsHex: - add al,‘A'-10 + add al,'A'-10 ret BinToHexDigit endp ; @@ -742,7 +742,7 @@ ColorNumbersUp proc near ;build color number text string on the fly mov cx,16 ;we've got 16 colors to do ColorNumberLoop: - pus hax;save the color # + push ax;save the color # and al,3fh;limit to 6-bit color values shr al,1 shr al,1 @@ -819,16 +819,16 @@ WAIT_KEY macro int 21h endm ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup (?) stack ends ; -Data segment word ‘DATA' -SampleText db ‘This is bit-mapped text, drawn in hi-res ' - db ‘EGA graphics mode 10h.', 0dh, 0ah, 0ah - db ‘Press any key to blank the screen, then ' - db ‘any key to unblank it,', 0dh, 0ah - db ‘then any key to end.$' +Data segment word 'DATA' +SampleText db 'This is bit-mapped text, drawn in hi-res ' + db 'EGA graphics mode 10h.', 0dh, 0ah, 0ah + db 'Press any key to blank the screen, then ' + db 'any key to unblank it,', 0dh, 0ah + db 'then any key to end.$' Data ends ; Code segment diff --git a/src/chapter-31.md b/src/chapter-31.md index 677289e..628a383 100644 --- a/src/chapter-31.md +++ b/src/chapter-31.md @@ -675,7 +675,7 @@ stack ends ; ; Macro to output a word value to a port. ; -OUT_WORDmacro +OUT_WORD macro if WORD_OUTS_OK out dx,ax else diff --git a/src/chapter-32.md b/src/chapter-32.md index 847b598..3dfedc0 100644 --- a/src/chapter-32.md +++ b/src/chapter-32.md @@ -148,7 +148,7 @@ WORD_OUTS_OK equ 1 ;set to 0 to assemble for ; computers that can't handle ; word outs to indexed VGA registers ; -_DATA segment public byte ‘DATA' +_DATA segment public byte 'DATA' ; ; 360x480 256-color mode CRT Controller register settings. ; (Courtesy of John Bridges.) @@ -175,7 +175,7 @@ _DATA ends ; ; Macro to output a word value to a port. ; -OUT_WORDmacro +OUT_WORD macro if WORD_OUTS_OK out dx,ax else @@ -188,8 +188,8 @@ else endif endm ; -_TEXTsegment byte public ‘CODE' - assumecs:_TEXT, ds:_DATA +_TEXT segment byte public 'CODE' + assume cs:_TEXT, ds:_DATA ; ; Sets up 360x480 256-color mode. ; (Courtesy of John Bridges.) @@ -532,10 +532,10 @@ void main() Set360x480Mode(); /* 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 * 3 / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 2); - VectorsUp(X_MAX / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 3); - VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 4); + VectorsUp(X_MAX / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4); + VectorsUp(X_MAX * 3 / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4); + VectorsUp(X_MAX / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4); + VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4); /* Wait for the enter key to be pressed */ scanf("%c", &temp); diff --git a/src/chapter-33.md b/src/chapter-33.md index 3d77be3..1ab12e4 100644 --- a/src/chapter-33.md +++ b/src/chapter-33.md @@ -463,7 +463,7 @@ Start: mov di,319 ;start at (319,0) mov bp,-1 ;draw right to left (distance from ; one column to the next) -callFillBlock;draw it + call FillBlock ;draw it ;draw diagonal lines in the lower- ; left quarter of the screen @@ -476,7 +476,7 @@ callFillBlock;draw it mov di,199*320 ;start at (0,199) mov bp,1 ;draw left to right (distance from ; one column to the next) -callFillBlock;draw it + call FillBlock ;draw it ; ;draw diagonal lines in the lower- ; right quarter of the screen @@ -489,16 +489,16 @@ callFillBlock;draw it mov di,199*320+319 ;start at (319,199) mov bp,-1 ;draw right to left (distance from ; one column to the next) -callFillBlock;draw it + callFillBlock ;draw it mov ah,1 ;wait for a key -int21h; + int 21h ; mov ax,0003h ;return to text mode -int10h; + int 10h ; mov ah,4ch ;done--return to DOS -int21h + int 21h ; Fills the specified rectangular area of the screen with diagonal lines. ; diff --git a/src/chapter-34.md b/src/chapter-34.md index 988d421..44d9e0f 100644 --- a/src/chapter-34.md +++ b/src/chapter-34.md @@ -291,7 +291,7 @@ endif ;NOT_8088 ;Storage for all 256 DAC locations, organized as one three-byte ; (actually three 6-bit values; upper two bits of each byte aren't ; significant) RGB triplet per color. -PaletteTempdb 256*3 dup(?) +PaletteTemp db 256*3 dup(?) .code start: mov ax,@data @@ -350,7 +350,7 @@ DACStoreLoop: stosb sti inc ah - loopDACStoreLoop + loop DACStoreLoop else;!GUARD_AGAINST_INTS mov dx,DAC_READ_INDEX sub al,al @@ -505,7 +505,7 @@ endif;USE_BIOS mov ah,4ch ;DOS terminate process fn int 21h - endstart + end start ``` The big question is, How does Listing 34.1 cycle colors? Via the BIOS or diff --git a/src/chapter-35.md b/src/chapter-35.md index ed3609d..db6c879 100644 --- a/src/chapter-35.md +++ b/src/chapter-35.md @@ -357,7 +357,7 @@ int XDirection; /* 1 if line is drawn left to right, /* Draw the line */ EVGADot(X0, Y0); /* draw the first pixel */ - while ( DeltaX— ) { + while ( DeltaX-- ) { /* See if it's time to advance the Y coordinate */ if ( ErrorTerm >= 0 ) { /* Advance the Y coordinate & adjust the error term @@ -392,7 +392,7 @@ int XDirection; /* 1 if line is drawn left to right, ErrorTerm = DeltaXx2 - (int) DeltaY; EVGADot(X0, Y0); /* draw the first pixel */ - while ( DeltaY— ) { + while ( DeltaY-- ) { /* See if it's time to advance the X coordinate */ if ( ErrorTerm >= 0 ) { /* Advance the X coordinate & adjust the error term @@ -517,13 +517,13 @@ int Color; /* color to draw lines in */ /* Lines from center to bottom of rectangle */ WorkingX = XCenter + XLength - 1; WorkingY = YCenter + YLength - 1; - for ( ; WorkingX >= ( XCenter - XLength ); WorkingX— ) + for ( ; WorkingX >= ( XCenter - XLength ); WorkingX-- ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color); /* Lines from center to left of rectangle */ WorkingX = XCenter - XLength; WorkingY = YCenter + YLength - 1; - for ( ; WorkingY >= ( YCenter - YLength ); WorkingY— ) + for ( ; WorkingY >= ( YCenter - YLength ); WorkingY-- ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color ); } @@ -842,7 +842,7 @@ difference is startling. ;**************************************************************** ; - model small + .model small .code ; diff --git a/src/chapter-39.md b/src/chapter-39.md index 4da6d80..3fb7ff5 100644 --- a/src/chapter-39.md +++ b/src/chapter-39.md @@ -457,7 +457,7 @@ as the C code. SCREEN_WIDTH equ 320 SCREEN_SEGMENT equ 0a000h -HLinestruc +HLine struc XStart dw ? ;X coordinate of leftmost pixel in line XEnd dw ? ;X coordinate of rightmost pixel in line HLine ends @@ -692,7 +692,7 @@ XMajorNoAdvance: align 2 ToScanEdgeExit: jmp ScanEdgeExit - align2 + align 2 IsVertical: mov ax,[bp+X1] ;starting (and only) X coordinate sub bx,[bp+SkipFirst] ;loop count = Height - SkipFirst diff --git a/src/chapter-42.md b/src/chapter-42.md index 533db48..c4144f6 100644 --- a/src/chapter-42.md +++ b/src/chapter-42.md @@ -600,6 +600,7 @@ drawn with a ruler. * Tseng Labs ET4000-based SuperVGAs. * Tested with Borland C++ in C compilation mode and the small model. */ +#include #include /* Screen dimension globals, used in main program to scale */ @@ -767,7 +768,7 @@ DoHorz: cld ;restore default direction flag jmp Done ;and we're done - align2 + align 2 NotHorz: and cx,cx ;is DeltaX 0? jnz NotVert ;no, not a vertical line @@ -780,7 +781,7 @@ VertLoop: jnz VertLoop jmp Done ;and we're done - align2 + align 2 NotVert: cmp cx,dx ;DeltaX == DeltaY? jnz NotDiag ;no, not diagonal @@ -796,11 +797,11 @@ DiagLoop: jmp Done ;and we're done ; Line is not horizontal, diagonal, or vertical. - align2 + align 2 NotDiag: ; Is this an X-major or Y-major line? cmp dx,cx - jbX Major ;it's X-major + jb XMajor ;it's X-major ; It's a Y-major line. Calculate the 16-bit fixed-point fractional part of a ; pixel that X advances each time Y advances 1 pixel, truncating the result @@ -861,7 +862,7 @@ NoXAdvance: jmp Done ;we're done with this line ; It's an X-major line. - align2 + align 2 XMajor: ; Calculate the 16-bit fixed-point fractional part of a pixel that Y advances ; each time X advances 1 pixel, truncating the result to avoid overrunning diff --git a/src/chapter-43.md b/src/chapter-43.md index 7e2289f..4f09fb1 100644 --- a/src/chapter-43.md +++ b/src/chapter-43.md @@ -263,7 +263,7 @@ WORD_OUTS_OK equ 1 ;set to 0 to assemble for ; handle word outs to ; indexed VGA regs ; -stack segment para stack ‘STACK' +stack segment para stack 'STACK' db 512 dup (?) stack ends ; @@ -297,7 +297,7 @@ PlaneSelect db ? ;mask to select plane to ; word-aligned) ObjectStructure ends ; -Data segment word ‘DATA' +Data segment word 'DATA' ; ; Palette settings to give plane 0 precedence, followed by ; planes 1, 2, and 3. Plane 3 has the lowest precedence (is @@ -423,7 +423,7 @@ Diamond label byte ; even;word-align for better 286 performance ; -ObjectListlabelObjectStructure +ObjectList label ObjectStructure ObjectStructure <1,21,Diamond,88,8,80,512,16,0,0,350,RED> ObjectStructure <1,15,Square,296,8,112,480,144,0,0,350,RED> ObjectStructure <1,23,Diamond,88,8,80,512,256,0,0,350,RED> @@ -437,9 +437,9 @@ ObjectListlabelObjectStructure ObjectStructure <1,8,Diamond,296,8,0,576,144,6,0,280,GREEN> ObjectStructure <1,8,Square,344,8,0,576,192,6,0,280,GREEN> ObjectStructure <1,8,Diamond,392,8,0,576,240,6,0,280,GREEN> -ObjectListEndlabelObjectStructure +ObjectListEnd label ObjectStructure ; -Dataends +Data ends ; ; Macro to output a word value to a port. ; diff --git a/src/chapter-44.md b/src/chapter-44.md index d8926c0..867fa26 100644 --- a/src/chapter-44.md +++ b/src/chapter-44.md @@ -93,26 +93,26 @@ Compiled with Borland C++ in C compilation mode. */ #include #include -#define SCREEN-SEG 0xA000 -#define SCREEN-PIXWIDTH 640 /* in pixels */ -#define SCREEN-WIDTH 80 /* in bytes */ -#define SPLIT-START-LINE 339 -#define SPLIT-LINES 141 -#define NONSPLIT-LINES 339 -#define SPLIT-START-OFFSET 0 -#define PAGE0-START-OFFSET (SPLIT-LINES*SCREEN-WIDTH) -#define PAGE1-START-OFFSET ((SPLIT-LINES+NONSPLIT-LINES)*SCREEN-WIDTH) -#define CRTC-INDEX 0x3D4 /* CRT Controller Index register */ -#define CRTC-DATA 0x3D5 /* CRT Controller Data register */ -#define OVERFLOW 0x07 /* index of CRTC reg holding bit 8 of the +#define SCREEN_SEG 0xA000 +#define SCREEN_PIXWIDTH 640 /* in pixels */ +#define SCREEN_WIDTH 80 /* in bytes */ +#define SPLIT_START_LINE 339 +#define SPLIT_LINES 141 +#define NONSPLIT_LINES 339 +#define SPLIT_START_OFFSET 0 +#define PAGE0_START_OFFSET (SPLIT_LINES*SCREEN_WIDTH) +#define PAGE1_START_OFFSET ((SPLIT_LINES+NONSPLIT_LINES)*SCREEN_WIDTH) +#define CRTC_INDEX 0x3D4 /* CRT Controller Index register */ +#define CRTC_DATA 0x3D5 /* CRT Controller Data register */ +#define OVERFLOW_ 0x07 /* index of CRTC reg holding bit 8 of the line the split screen starts after */ -#define MAX-SCAN 0x09 /* index of CRTC reg holding bit 9 of the +#define MAX_SCAN 0x09 /* index of CRTC reg holding bit 9 of the line the split screen starts after */ -#define LINE-COMPARE 0x18 /* index of CRTC reg holding lower 8 bits +#define LINE_COMPARE 0x18 /* index of CRTC reg holding lower 8 bits of line split screen starts after */ -#define NUM-BUMPERS (sizeof(Bumpers)/sizeof(bumper)) -#define BOUNCER-COLOR 15 -#define BACK-COLOR 1 /* playfield background color */ +#define NUM_BUMPERS (sizeof(Bumpers)/sizeof(bumper)) +#define BOUNCER_COLOR 15 +#define BACK_COLOR 1 /* playfield background color */ typedef struct { /* one solid bumper to be bounced off of */ int LeftX,TopY,RightX,BottomY; @@ -165,29 +165,29 @@ bumper Bumpers[] = { {420,160,579,163,11}, {428,210,571,213,11}, {420,260,579,263,11} }; /* Image for bouncing object when left edge is aligned with bit 7 */ -unsigned char -BouncerRotation0[] = { +unsigned char _BouncerRotation0[] = { 0xFF,0x0F,0xF0, 0xFE,0x07,0xF0, 0xFC,0x03,0xF0, 0xFC,0x03,0xF0, 0xFE,0x07,0xF0, 0xFF,0xFF,0xF0, 0xCF,0xFF,0x30, 0x87,0xFE,0x10, 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x87,0xFE,0x10, 0xCF,0xFF,0x30, 0xFF,0xFF,0xF0, 0xFE,0x07,0xF0, 0xFC,0x03,0xF0, 0xFC,0x03,0xF0, 0xFE,0x07,0xF0, 0xFF,0x0F,0xF0}; -image BouncerRotation0 = {3, 20, -BouncerRotation0}; +image BouncerRotation0 = {3, 20, _BouncerRotation0}; /* Image for bouncing object when left edge is aligned with bit 3 */ -unsigned char -BouncerRotation4[] = { +unsigned char _BouncerRotation4[] = { 0x0F,0xF0,0xFF, 0x0F,0xE0,0x7F, 0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F, 0x0F,0xE0,0x7F, 0x0F,0xFF,0xFF, 0x0C,0xFF,0xF3, 0x08,0x7F,0xE1, 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x08,0x7F,0xE1, 0x0C,0xFF,0xF3, 0x0F,0xFF,0xFF, 0x0F,0xE0,0x7F, 0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F, 0x0F,0xE0,0x7F, 0x0F,0xF0,0xFF}; -image BouncerRotation4 = {3, 20, -BouncerRotation4}; +image BouncerRotation4 = {3, 20, _BouncerRotation4}; /* Initial settings for bouncing object. Only 2 rotations are needed because the object moves 4 pixels horizontally at a time */ -bouncer Bouncer = {156,60,20,20,4,4,156,156,60,60,BOUNCER-COLOR, +bouncer Bouncer = {156,60,20,20,4,4,156,156,60,60,BOUNCER_COLOR, &BouncerRotation0,NULL,NULL,NULL,&BouncerRotation4,NULL,NULL,NULL}; unsigned int PageStartOffsets[2] = - {PAGE0-START-OFFSET,PAGE1-START-OFFSET}; + {PAGE0_START_OFFSET,PAGE1_START_OFFSET}; unsigned int BounceCount; void main() { @@ -204,9 +204,9 @@ void main() { /* Clear both pages to background and draw bumpers in each page */ for (i=0; i<2; i++) { - DrawRect(0,0,SCREEN-PIXWIDTH-1,NONSPLIT-LINES-1,BACK-COLOR, - PageStartOffsets[i],SCREEN-SEG); - DrawBumperList(Bumpers,NUM-BUMPERS,PageStartOffsets[i]); + DrawRect(0,0,SCREEN_PIXWIDTH-1,NONSPLIT_LINES-1,BACK_COLOR, + PageStartOffsets[i],SCREEN_SEG); + DrawBumperList(Bumpers,NUM_BUMPERS,PageStartOffsets[i]); } DrawSplitScreen(); /* draw the static split screen info */ @@ -215,7 +215,7 @@ void main() { /* Draw the bouncing object at its initial location */ 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 page until Esc is pressed */ @@ -227,13 +227,13 @@ void main() { Bouncer.CurrentY[NonDisplayedPage], Bouncer.CurrentX[NonDisplayedPage]+Bouncer.Width-1, Bouncer.CurrentY[NonDisplayedPage]+Bouncer.Height-1, - BACK-COLOR,PageStartOffsets[NonDisplayedPage],SCREEN-SEG); + BACK_COLOR,PageStartOffsets[NonDisplayedPage],SCREEN_SEG); /* Move the bouncer */ - MoveBouncer(&Bouncer, Bumpers, NUM-BUMPERS); + MoveBouncer(&Bouncer, Bumpers, NUM_BUMPERS); /* Draw at the new location in the nondisplayed page */ DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0, Bouncer.Color,PageStartOffsets[NonDisplayedPage], - SCREEN-SEG); + SCREEN_SEG); /* Remember where the bouncer is in the nondisplayed page */ Bouncer.CurrentX[NonDisplayedPage] = Bouncer.LeftX; Bouncer.CurrentY[NonDisplayedPage] = Bouncer.TopY; @@ -276,7 +276,7 @@ void DrawBumperList(bumper * Bumpers, int NumBumpers, for (i=0; iLeftX,Bumpers->TopY,Bumpers->RightX, Bumpers->BottomY,Bumpers->Color,PageStartOffset, - SCREEN-SEG); + SCREEN_SEG); } } @@ -285,43 +285,43 @@ void ShowBounceCount() { char CountASCII[7]; itoa(BounceCount,CountASCII,10); /* convert the count to ASCII*/ - TextUp(CountASCII,344,64,SPLIT-START-OFFSET,SCREEN-SEG); + TextUp(CountASCII,344,64,SPLIT_START_OFFSET,SCREEN_SEG); } /* Frames the split screen and fills it with various text */ void DrawSplitScreen() { - DrawRect(0,0,SCREEN-PIXWIDTH-1,SPLIT-LINES-1,0,SPLIT-START-OFFSET, - SCREEN-SEG); - DrawRect(0,1,SCREEN-PIXWIDTH-1,4,15,SPLIT-START-OFFSET, - SCREEN-SEG); - DrawRect(0,SPLIT-LINES-4,SCREEN-PIXWIDTH-1,SPLIT-LINES-1,15, - SPLIT-START-OFFSET,SCREEN-SEG); - DrawRect(0,1,3,SPLIT-LINES-1,15,SPLIT-START-OFFSET,SCREEN-SEG); - DrawRect(SCREEN-PIXWIDTH-4,1,SCREEN-PIXWIDTH-1,SPLIT-LINES-1,15, - SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("This is the split screen area...",8,8,SPLIT-START-OFFSET, - SCREEN-SEG); - TextUp("Bounces: ",272,64,SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("\033: nudge left",520,78,SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("\032: nudge right",520,90,SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("\031: nudge down",520,102,SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("\030: nudge up",520,114,SPLIT-START-OFFSET,SCREEN-SEG); - TextUp("Esc to end",520,126,SPLIT-START-OFFSET,SCREEN-SEG); + DrawRect(0,0,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,0,SPLIT_START_OFFSET, + SCREEN_SEG); + DrawRect(0,1,SCREEN_PIXWIDTH-1,4,15,SPLIT_START_OFFSET, + SCREEN_SEG); + DrawRect(0,SPLIT_LINES-4,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15, + SPLIT_START_OFFSET,SCREEN_SEG); + DrawRect(0,1,3,SPLIT_LINES-1,15,SPLIT_START_OFFSET,SCREEN_SEG); + DrawRect(SCREEN_PIXWIDTH-4,1,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15, + SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("This is the split screen area...",8,8,SPLIT_START_OFFSET, + SCREEN_SEG); + TextUp("Bounces: ",272,64,SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("\033: nudge left",520,78,SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("\032: nudge right",520,90,SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("\031: nudge down",520,102,SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("\030: nudge up",520,114,SPLIT_START_OFFSET,SCREEN_SEG); + TextUp("Esc to end",520,126,SPLIT_START_OFFSET,SCREEN_SEG); } /* Turn on the split screen at the desired line (minus 1 because the - split screen starts *after* the line specified by the LINE-COMPARE + split screen starts *after* the line specified by the LINE_COMPARE register) (bit 8 of the split screen start line is stored in the Overflow register, and bit 9 is in the Maximum Scan Line reg) */ void EnableSplitScreen() { - outp(CRTC-INDEX, LINE-COMPARE); - outp(CRTC-DATA, (SPLIT-START-LINE - 1) & 0xFF); - outp(CRTC-INDEX, OVERFLOW); - outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x100) >> 8) << 4) | - (inp(CRTC-DATA) & ~0x10))); - outp(CRTC-INDEX, MAX-SCAN); - outp(CRTC-DATA, (((((SPLIT-START-LINE - 1) & 0x200) >> 9) << 6) | - (inp(CRTC-DATA) & ~0x40))); + outp(CRTC_INDEX, LINE_COMPARE); + outp(CRTC_DATA, (SPLIT_START_LINE - 1) & 0xFF); + outp(CRTC_INDEX, OVERFLOW_); + outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x100) >> 8) << 4) | + (inp(CRTC_DATA) & ~0x10))); + outp(CRTC_INDEX, MAX_SCAN); + outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x200) >> 9) << 6) | + (inp(CRTC_DATA) & ~0x40))); } /* Moves the bouncer, bouncing if bumpers are hit */ @@ -360,7 +360,7 @@ void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) { } /* Update the bounce count display; turn over at 10000 */ if (++BounceCount >= 10000) { - TextUp("0 ",344,64,SPLIT-START-OFFSET,SCREEN-SEG); + TextUp("0 ",344,64,SPLIT_START_OFFSET,SCREEN_SEG); BounceCount = 0; } else { ShowBounceCount(); @@ -378,21 +378,21 @@ void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) { ; Low-level animation routines. ; Tested with TASM -SCREEN-WIDTH equ 80 ;screen width in bytes -INPUT-STATUS-1 equ 03dah ;Input Status 1 register -CRTC-INDEX equ 03d4h ;CRT Controller Index reg -START-ADDRESS-HIGH equ 0ch ;bitmap start address high byte -START-ADDRESS-LOW equ 0dh ;bitmap start address low byte -GC-INDEX equ 03ceh ;Graphics Controller Index reg -SET-RESET equ 0 ;GC index of Set/Reset reg -G-MODE equ 5 ;GC index of Mode register +SCREEN_WIDTH equ 80 ;screen width in bytes +INPUT_STATUS_1 equ 03dah ;Input Status 1 register +CRTC_INDEX equ 03d4h ;CRT Controller Index reg +START_ADDRESS_HIGH equ 0ch ;bitmap start address high byte +START_ADDRESS_LOW equ 0dh ;bitmap start address low byte +GC_INDEX equ 03ceh ;Graphics Controller Index reg +SET_RESET equ 0 ;GC index of Set/Reset reg +G_MODE equ 5 ;GC index of Mode register .model small .data BIOS8x8Ptr dd ? ;points to BIOS 8x8 font ; Tables used to look up left and right clip masks. -LeftMask d 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h -RightMask d 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh, 0ffh +LeftMask db 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h +RightMask db 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh, 0ffh .code ; Draws the specified filled rectangle in the specified color. @@ -415,22 +415,22 @@ ScrnOffset dw ? ;offset of base of bitmap in which to draw ScrnSegment dw ? ;segment of base of bitmap in which to draw DrawRectParms ends - public -DrawRect --DrawRect proc near + public _DrawRect +_DrawRect proc near push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame push si ;preserve caller's register variables push di cld - mov dx,GC-INDEX - mov al,SET-RESET + mov dx,GC_INDEX + mov al,SET_RESET mov ah,byte ptr Color[bp] out dx,ax ;set the color in which to draw - mov ax,G-MODE + (0300h) + mov ax,G_MODE + (0300h) out dx,ax ;set to write mode 3 les di,dword ptr ScrnOffset[bp] ;point to bitmap start - mov ax,SCREEN-WIDTH + mov ax,SCREEN_WIDTH mul TopY[bp] ;point to the start of the top scan add di,ax ; line to fill mov ax,LeftX[bp] @@ -466,13 +466,13 @@ FillLoop: js LineDone ;that's it if there's only 1 byte across jz DrawRightEdge ;no middle bytes if only 2 bytes across mov al,0ffh ;non-edge bytes are solid - rep stos ;draw the solid bytes across the middle + rep stosb ;draw the solid bytes across the middle DrawRightEdge: mov al,dh ;right-edge clip mask xchg es:[di],al ;draw the right edge LineDone: pop di ;retrieve line start offset - add di,SCREEN-WIDTH ;point to the next line + add di,SCREEN_WIDTH ;point to the next line dec bx ;count off scan lines jns FillLoop @@ -480,7 +480,7 @@ LineDone: pop si pop bp ;restore caller's stack frame ret --DrawRect endp +_DrawRect endp ; Shows the page at the specified offset in the bitmap. Page is ; displayed when this routine returns. @@ -492,37 +492,37 @@ ShowPageParms struc StartOffset dw ? ;offset in bitmap of page to display ShowPageParms ends - public -ShowPage --ShowPage proc near + public _ShowPage +_ShowPage proc near push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame ; Wait for display enable to be active (status is active low), to be ; sure both halves of the start address will take in the same frame. - mov bl,START-ADDRESS-LOW ;preload for fastest + mov bl,START_ADDRESS_LOW ;preload for fastest mov bh,byte ptr StartOffset[bp] ; flipping once display - mov cl,START-ADDRESS-HIGH ; enable is detected + mov cl,START_ADDRESS_HIGH ; enable is detected mov ch,byte ptr StartOffset+1[bp] - mov dx,INPUT-STATUS-1 + mov dx,INPUT_STATUS_1 WaitDE: in al,dx test al,01h jnz WaitDE ;display enable is active low (0 = active) ; Set the start offset in display memory of the page to display. - mov dx,CRTC-INDEX + mov dx,CRTC_INDEX mov ax,bx out dx,ax ;start address low mov ax,cx out dx,ax ;start address high ; Now wait for vertical sync, so the other page will be invisible when ; we start drawing to it. - mov dx,INPUT-STATUS-1 + mov dx,INPUT_STATUS_1 WaitVS: in al,dx test al,08h jz WaitVS ;vertical sync is active high (1 = active) pop bp ;restore caller's stack frame ret --ShowPage endp +_ShowPage endp ; Displays the specified image at the specified location in the ; specified bitmap, in the desired color. @@ -549,22 +549,22 @@ Height dw ? BitPattern dw ? image ends - public -DrawImage --DrawImage proc near + public _DrawImage +_DrawImage proc near push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame push si ;preserve caller's register variables push di cld - mov dx,GC-INDEX - mov al,SET-RESET + mov dx,GC_INDEX + mov al,SET_RESET mov ah,byte ptr DIColor[bp] out dx,ax ;set the color in which to draw - mov ax,G-MODE + (0300h) + mov ax,G_MODE + (0300h) out dx,ax ;set to write mode 3 les di,dword ptr DIScrnOffset[bp] ;point to bitmap start - mov ax,SCREEN-WIDTH + mov ax,SCREEN_WIDTH mul DITopY[bp] ;point to the start of the top scan add di,ax ; line on which to draw mov ax,DILeftX[bp] @@ -584,12 +584,12 @@ DrawImageLoop: push di ;remember line start offset mov cx,dx ;# of bytes across DrawImageLineLoop: - lods ;get the next image byte + lodsb ;get the next image byte xchg es:[di],al ;draw the next image byte inc di ;point to the following screen byte loop DrawImageLineLoop pop di ;retrieve line start offset - add di,SCREEN-WIDTH ;point to the next line + add di,SCREEN_WIDTH ;point to the next line dec bx ;count off scan lines jnz DrawImageLoop @@ -597,7 +597,7 @@ DrawImageLineLoop: pop si pop bp ;restore caller's stack frame ret --DrawImage endp +_DrawImage endp ; Draws a 0-terminated text string at the specified location in the ; specified bitmap in white, using the 8x8 BIOS font. Must be at an X @@ -616,19 +616,19 @@ TUScrnOffset dw ? ;offset of base of bitmap in which to draw TUScrnSegment dw ? ;segment of base of bitmap in which to draw TextUpParms ends - public -TextUp --TextUp proc near + public _TextUp +_TextUp proc near push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame push si ;preserve caller's register variables push di cld - mov dx,GC-INDEX - mov ax,G-MODE + (0000h) + mov dx,GC_INDEX + mov ax,G_MODE + (0000h) out dx,ax ;set to write mode 0 les di,dword ptr TUScrnOffset[bp] ;point to bitmap start - mov ax,SCREEN-WIDTH + mov ax,SCREEN_WIDTH mul TUTopY[bp] ;point to the start of the top scan add di,ax ; line the text starts on mov ax,TULeftX[bp] @@ -639,7 +639,7 @@ TextUpParms ends add di,ax ;point to the upper-left corner of first char mov si,Text[bp] ;point to text to draw TextUpLoop: - lods ;get the next character to draw + lodsb ;get the next character to draw and al,al jz TextUpDone ;done if null byte push si ;preserve text string pointer @@ -668,18 +668,18 @@ CharUp: ;draws the character in AL at ES:DI add si,bx ;point DS:Sito character data in font mov cx,8 ;characters are 8 high CharUpLoop: - movs ;copy the next character pattern byte - add di,SCREEN-WIDTH-1 ;point to the next dest byte + movsb ;copy the next character pattern byte + add di,SCREEN_WIDTH-1 ;point to the next dest byte loop CharUpLoop ret --TextUp endp +_TextUp endp ; Sets the pointer to the BIOS 8x8 font. ; ; C near-callable as: extern void SetBIOS8x8Font(void); - public -SetBIOS8x8Font --SetBIOS8x8Font proc near + public _SetBIOS8x8Font +_SetBIOS8x8Font proc near push bp ;preserve caller's stack frame push si ;preserve caller's register variables push di ; and data segment (don't assume BIOS @@ -695,7 +695,7 @@ CharUpLoop: pop si pop bp ;restore caller's stack frame ret --SetBIOS8x8Font endp +_SetBIOS8x8Font endp end ``` diff --git a/src/chapter-46.md b/src/chapter-46.md index cffd3a1..84664a7 100644 --- a/src/chapter-46.md +++ b/src/chapter-46.md @@ -105,15 +105,19 @@ to using masked images. #include #include +#ifdef __TURBOC__ #include +#else /* MSC */ +#include +#endif #include #include /* Comment out to disable overlap elimination in the dirty rectangle list. */ -#define CHECK-OVERLAP 1 -#define SCREEN-WIDTH 320 -#define SCREEN-HEIGHT 200 -#define SCREEN-SEGMENT 0xA000 +#define CHECK_OVERLAP 1 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 +#define SCREEN_SEGMENT 0xA000 /* Describes a dirty rectangle */ typedef struct { @@ -133,17 +137,17 @@ typedef struct { int InternalAnimateMax; /* maximum internal animation state */ } Entity; /* storage used for dirty rectangles */ -#define MAX-DIRTY-RECTANGLES 100 +#define MAX_DIRTY_RECTANGLES 100 int NumDirtyRectangles; -DirtyRectangle DirtyRectangles[MAX-DIRTY-RECTANGLES]; +DirtyRectangle DirtyRectangles[MAX_DIRTY_RECTANGLES]; /* head/tail of dirty rectangle list */ DirtyRectangle DirtyHead; /* If set to 1, ignore dirty rectangle list and copy the whole screen. */ int DrawWholeScreen = 0; /* pixels and masks for the two internally animated versions of the image we'll animate */ -#define IMAGE-WIDTH 13 -#define IMAGE-HEIGHT 11 +#define IMAGE_WIDTH 13 +#define IMAGE_HEIGHT 11 char ImagePixels0[] = { 0, 0, 0, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, @@ -201,8 +205,8 @@ char ImageMask1[] = { char * ImagePixelArray[] = {ImagePixels0, ImagePixels1}; char * ImageMaskArray[] = {ImageMask0, ImageMask1}; /* Animated entities */ -#define NUM-ENTITIES 15 -Entity Entities[NUM-ENTITIES]; +#define NUM_ENTITIES 15 +Entity Entities[NUM_ENTITIES]; /* pointer to system buffer into which we'll draw */ char far *SystemBufferPtr; /* pointer to screen */ @@ -211,9 +215,10 @@ void EraseEntities(void); void CopyDirtyRectanglesToScreen(void); void DrawEntities(void); void AddDirtyRect(Entity *, int, int); -void DrawMasked(char far *, char *, char *, int, int, int); -void FillRect(char far *, int, int, int, int); -void CopyRect(char far *, char far *, int, int, int, int); + +extern void DrawMasked(char far *, char *, char *, int, int, int); +extern void FillRect(char far *, int, int, int, int); +extern void CopyRect(char far *, char far *, int, int, int, int); void main() { @@ -222,26 +227,26 @@ void main() char far *TempPtr; union REGS regs; /* Allocate memory for the system buffer into which we'll draw */ - if (!(SystemBufferPtr = farmalloc((unsigned int)SCREEN-WIDTH* - SCREEN-HEIGHT))) { + if (!(SystemBufferPtr = farmalloc((unsigned int)SCREEN_WIDTH* + SCREEN_HEIGHT))) { printf("Couldn't get memory\n"); exit(1); } /* Clear the system buffer */ TempPtr = SystemBufferPtr; - for (TempCount = ((unsigned)SCREEN-WIDTH*SCREEN-HEIGHT); TempCount--; ) { + for (TempCount = ((unsigned)SCREEN_WIDTH*SCREEN_HEIGHT); TempCount--; ) { *TempPtr++ = 0; } /* Point to the screen */ - ScreenPtr = MK-FP(SCREEN-SEGMENT, 0); + ScreenPtr = MK_FP(SCREEN_SEGMENT, 0); /* Set up the entities we'll animate, at random locations */ randomize(); - for (= 0; < NUM-ENTITIES; i++) { - Entities[i].X = random(SCREEN-WIDTH - IMAGE-WIDTH); - Entities[i].Y = random(SCREEN-HEIGHT - IMAGE-HEIGHT); + for (i = 0; i < NUM_ENTITIES; i++) { + Entities[i].X = random(SCREEN_WIDTH - IMAGE_WIDTH); + Entities[i].Y = random(SCREEN_HEIGHT - IMAGE_HEIGHT); Entities[i].XDirection = 1; Entities[i].YDirection = -1; - Entities[i].InternalAnimateCount = & 1; + Entities[i].InternalAnimateCount = 0; Entities[i].InternalAnimateMax = 2; } /* Set the dirty rectangle list to empty, and set up the head/tail node @@ -270,14 +275,14 @@ void main() updating the dirty rectangle list */ EraseEntities(); /* Move the entities, bouncing off the edges of the screen */ - for (= 0; < NUM-ENTITIES; i++) { + for (i = 0; i < NUM_ENTITIES; i++) { XTemp = Entities[i].X + Entities[i].XDirection; YTemp = Entities[i].Y + Entities[i].YDirection; - if ((XTemp < 0) || ((XTemp + IMAGE-WIDTH) > SCREEN-WIDTH)) { + if ((XTemp < 0) || ((XTemp + IMAGE_WIDTH) > SCREEN_WIDTH)) { Entities[i].XDirection = -Entities[i].XDirection; XTemp = Entities[i].X + Entities[i].XDirection; } - if ((YTemp < 0) || ((YTemp + IMAGE-HEIGHT) > SCREEN-HEIGHT)) { + if ((YTemp < 0) || ((YTemp + IMAGE_HEIGHT) > SCREEN_HEIGHT)) { Entities[i].YDirection = -Entities[i].YDirection; YTemp = Entities[i].Y + Entities[i].YDirection; } @@ -300,11 +305,11 @@ void DrawEntities() char *TempPtrMask; Entity *EntityPtr; - for (= 0, EntityPtr = Entities; < NUM-ENTITIES; i++, EntityPtr++) { + for (i = 0, EntityPtr = Entities; i < NUM_ENTITIES; i++, EntityPtr++) { /* 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 */ - RowPtrBuffer = SystemBufferPtr + (EntityPtr->Y * SCREEN-WIDTH) + + RowPtrBuffer = SystemBufferPtr + (EntityPtr->Y * SCREEN_WIDTH) + EntityPtr->X; /* Advance the image animation pointer */ if (++EntityPtr->InternalAnimateCount >= @@ -314,8 +319,8 @@ void DrawEntities() /* Point to the image and mask to draw */ TempPtrImage = ImagePixelArray[EntityPtr->InternalAnimateCount]; TempPtrMask = ImageMaskArray[EntityPtr->InternalAnimateCount]; - DrawMasked(RowPtrBuffer, TempPtrImage, TempPtrMask, IMAGE-HEIGHT, - IMAGE-WIDTH, SCREEN-WIDTH); + DrawMasked(RowPtrBuffer, TempPtrImage, TempPtrMask, IMAGE_HEIGHT, + IMAGE_WIDTH, SCREEN_WIDTH); } } /* Copy the dirty rectangles, or the whole system buffer if appropriate, @@ -328,22 +333,22 @@ void CopyDirtyRectanglesToScreen() if (DrawWholeScreen) { /* Just copy the whole buffer to the screen */ DrawWholeScreen = 0; - CopyRect(ScreenPtr, SystemBufferPtr, SCREEN-HEIGHT, SCREEN-WIDTH, - SCREEN-WIDTH, SCREEN-WIDTH); + CopyRect(ScreenPtr, SystemBufferPtr, SCREEN_HEIGHT, SCREEN_WIDTH, + SCREEN_WIDTH, SCREEN_WIDTH); } else { /* Copy only the dirty rectangles, in the YX-sorted order in which they're linked */ DirtyPtr = DirtyHead.Next; - for (= 0; < NumDirtyRectangles; i++) { + for (i = 0; i < NumDirtyRectangles; i++) { /* 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; /* Dimensions of dirty rectangle */ RectWidth = DirtyPtr->Right - DirtyPtr->Left; RectHeight = DirtyPtr->Bottom - DirtyPtr->Top; /* Copy a dirty rectangle */ CopyRect(ScreenPtr + Offset, SystemBufferPtr + Offset, - RectHeight, RectWidth, SCREEN-WIDTH, SCREEN-WIDTH); + RectHeight, RectWidth, SCREEN_WIDTH, SCREEN_WIDTH); /* Point to the next dirty rectangle */ DirtyPtr = DirtyPtr->Next; } @@ -356,14 +361,14 @@ void EraseEntities() int i; char far *RowPtr; - for (= 0; < NUM-ENTITIES; i++) { + for (i = 0; i < NUM_ENTITIES; i++) { /* Remember the dirty rectangle info for this entity */ - AddDirtyRect(&Entities[i], IMAGE-HEIGHT, IMAGE-WIDTH); + AddDirtyRect(&Entities[i], IMAGE_HEIGHT, IMAGE_WIDTH); /* Point to the destination in the system buffer */ - RowPtr = SystemBufferPtr + (Entities[i].Y * SCREEN-WIDTH) + + RowPtr = SystemBufferPtr + (Entities[i].Y * SCREEN_WIDTH) + Entities[i].X; /* Clear the rectangle */ - FillRect(RowPtr, IMAGE-HEIGHT, IMAGE-WIDTH, SCREEN-WIDTH, 0); + FillRect(RowPtr, IMAGE_HEIGHT, IMAGE_WIDTH, SCREEN_WIDTH, 0); } } /* Add a dirty rectangle to the list. The list is maintained in top-to-bottom, @@ -381,7 +386,7 @@ void EraseEntities() DirtyRectangle * TempPtr; Entity TempEntity; int i; - if (NumDirtyRectangles >= MAX-DIRTY-RECTANGLES) { + if (NumDirtyRectangles >= MAX_DIRTY_RECTANGLES) { /* Too many dirty rectangles; just redraw the whole screen */ DrawWholeScreen = 1; return; @@ -389,10 +394,10 @@ void EraseEntities() /* Remember this dirty rectangle. Break up if necessary to avoid overlap with rectangles already in the list, then add whatever rectangles are left, in YX sorted order */ -#ifdef CHECK-OVERLAP +#ifdef CHECK_OVERLAP /* Check for overlap with existing rectangles */ TempPtr = DirtyHead.Next; - for (= 0; < NumDirtyRectangles; i++, TempPtr = TempPtr->Next) { + for (i = 0; i < NumDirtyRectangles; i++, TempPtr = TempPtr->Next) { if ((TempPtr->Left < (pEntity->X + ImageWidth)) && (TempPtr->Right > pEntity->X) && (TempPtr->Top < (pEntity->Y + ImageHeight)) && @@ -444,7 +449,7 @@ void EraseEntities() return; } } -#endif /* CHECK-OVERLAP */ +#endif /* CHECK_OVERLAP */ /* There's no overlap with any existing rectangle, so we can just add this rectangle as-is */ /* Find the YX-sorted insertion point. Searches will always terminate, @@ -489,8 +494,8 @@ RectWidth dw ? ;width of rectangle to fill BufferWidth dw ? ;width of buffer in which to fill Color dw ? ;color with which to fill parms ends - public -FillRect --FillRectproc near + public _FillRect +_FillRect proc near cld push bp mov bp,sp @@ -516,7 +521,7 @@ RowLoop: pop di pop bp ret --FillRect endp +_FillRect endp ; Draws a masked image (a sprite) to the specified buffer. C-callable as: ; void DrawMasked(char far * BufferPtr, char * Pixels, char * Mask, @@ -526,13 +531,13 @@ parms2 struc dw ? ;pushed return address BufferPtr2 dd ? ;far pointer to buffer in which to draw Pixels dw ? ;pointer to image pixels -Mask dw ? ;pointer to image mask +Mask_ dw ? ;pointer to image mask ImageHeight dw ? ;height of image to draw ImageWidth dw ? ;width of image to draw BufferWidth2 dw ? ;width of buffer in which to draw parms2 ends - public -DrawMasked --DrawMasked proc near + public _DrawMasked +_DrawMasked proc near cld push bp mov bp,sp @@ -540,7 +545,7 @@ parms2 ends push di les di,[bp+BufferPtr2] - mov si,[bp+Mask] + mov si,[bp+Mask_] mov bx,[bp+Pixels] mov dx,[bp+ImageHeight] mov ax,[bp+BufferWidth2] @@ -549,7 +554,7 @@ parms2 ends RowLoop2: mov cx,[bp+ImageWidth] ColumnLoop: - lods ;get the next mask byte + lodsb ;get the next mask byte and al,al ;draw this pixel? jz SkipPixel ;no mov al,[bx] ;yes, draw the pixel @@ -567,7 +572,7 @@ SkipPixel: pop si pop bp ret --DrawMasked endp +_DrawMasked endp ; Copies a rectangle from one buffer to another. C-callable as: ; void CopyRect(DestBufferPtr, SrcBufferPtr, CopyHeight, CopyWidth, @@ -583,8 +588,8 @@ CopyWidth dw ? ;width of rect to copy DestBufferWidth dw ? ;width of buffer to which to copy SrcBufferWidth dw ? ;width of buffer from which to copy parms3 ends - public -CopyRect --CopyRect proc near + public _CopyRect +_CopyRect proc near cld push bp mov bp,sp @@ -604,7 +609,7 @@ RowLoop3: shr cx,1 rep movsw ;copy as many words as possible adc cx,cx - rep movs ;copy odd byte, if any + rep movsb ;copy odd byte, if any add si,ax ;point to next source scan line add di,bx ;point to next dest scan line dec dx ;count down rows to fill @@ -615,7 +620,7 @@ RowLoop3: pop si pop bp ret --CopyRect endp +_CopyRect endp end ``` diff --git a/src/chapter-47.md b/src/chapter-47.md index 46ed167..bc397a6 100644 --- a/src/chapter-47.md +++ b/src/chapter-47.md @@ -905,8 +905,8 @@ copies, blits, and pattern fills. #include #include -void Set320x240Mode(void); -void FillRectangleX(int, int, int, int, unsigned int, int); +extern void Set320x240Mode(void); +extern void FillRectangleX(int, int, int, int, unsigned int, int); void main() { int i,j; diff --git a/src/chapter-48.md b/src/chapter-48.md index e3a6942..fc5b826 100644 --- a/src/chapter-48.md +++ b/src/chapter-48.md @@ -88,8 +88,8 @@ previous chapter's listings.) #include #include -void Set320x240Mode(void); -void FillPatternX(int, int, int, int, unsigned int, char*); +extern void Set320x240Mode(void); +extern void FillPatternX(int, int, int, int, unsigned int, char*); /* 16 4x4 patterns */ static char Patt0[]={10,0,10,0,0,10,0,10,10,0,10,0,0,10,0,10}; diff --git a/src/chapter-49.md b/src/chapter-49.md index fdfa45f..7695667 100644 --- a/src/chapter-49.md +++ b/src/chapter-49.md @@ -167,7 +167,7 @@ _CopySystemToScreenMaskedX proc near mov [bp+RectWidth],ax sub word ptr [bp+SourceBitmapWidth],ax ;distance from end of one source scan line - to start of next + ;to start of next mov ax,[bp+SourceEndY] sub ax,[bp+SourceStartY] ;height of rectangle jle CopyDone ;skip if 0 or negative height @@ -490,9 +490,11 @@ unsigned int CreateAlignedMaskedImage(MaskedImage * ImageToSet, } return DispMemOffset - DispMemStart; } +``` **LISTING 49.4 MASKIM.H** +```c /* MASKIM.H: structures used for storing and manipulating masked images */ diff --git a/src/chapter-50.md b/src/chapter-50.md index dbffbce..da9ba90 100644 --- a/src/chapter-50.md +++ b/src/chapter-50.md @@ -725,10 +725,10 @@ void main() { switch (getch()) { case 0x1B: /* Esc to exit */ Done = 1; break; - case ‘A': case ‘a': /* away (-Z) */ + case 'A': case 'a': /* away (-Z) */ PolyWorldXform[2][3] -= 3.0; break; - case ‘T': /* towards (+Z). Don't allow to get too */ - case ‘t': /* close, so Z clipping isn't needed */ + case 'T': /* towards (+Z). Don't allow to get too */ + case 't': /* close, so Z clipping isn't needed */ if (PolyWorldXform[2][3] < -40.0) PolyWorldXform[2][3] += 3.0; break; case 0: /* extended code */ diff --git a/src/chapter-51.md b/src/chapter-51.md index 6b05af4..f92af40 100644 --- a/src/chapter-51.md +++ b/src/chapter-51.md @@ -314,25 +314,25 @@ void main() { switch (getch()) { case 0x1B: /* Esc to exit */ Done = 1; break; - case ‘A': case ‘a': /* away (-Z) */ + case 'A': case 'a': /* away (-Z) */ CubeWorldXform[2][3] -= 3.0; RecalcXform = 1; break; - case ‘T': /* towards (+Z). Don't allow to get too */ - case ‘t': /* close, so Z clipping isn't needed */ + case 'T': /* towards (+Z). Don't allow to get too */ + case 't': /* close, so Z clipping isn't needed */ if (CubeWorldXform[2][3] < -40.0) { CubeWorldXform[2][3] += 3.0; RecalcXform = 1; } break; - case ‘4': /* rotate clockwise around Y */ + case '4': /* rotate clockwise around Y */ AppendRotationY(CubeWorldXform, -ROTATION); RecalcXform=1; break; - case ‘6': /* rotate counterclockwise around Y */ + case '6': /* rotate counterclockwise around Y */ AppendRotationY(CubeWorldXform, ROTATION); RecalcXform=1; break; - case ‘8': /* rotate clockwise around X */ + case '8': /* rotate clockwise around X */ AppendRotationX(CubeWorldXform, -ROTATION); RecalcXform=1; break; - case ‘2': /* rotate counterclockwise around X */ + case '2': /* rotate counterclockwise around X */ AppendRotationX(CubeWorldXform, ROTATION); RecalcXform=1; break; case 0: /* extended code */ diff --git a/src/chapter-53.md b/src/chapter-53.md index 1f5905e..976ed09 100644 --- a/src/chapter-53.md +++ b/src/chapter-53.md @@ -92,7 +92,7 @@ time to turn our optimization sights elsewhere. ```nasm ; 386-specific fixed point routines. ; Tested with TASM -ROUNDING-ON equ 1 ;1 for rounding, 0 for no rounding +ROUNDING_ON equ 1 ;1 for rounding, 0 for no rounding ;no rounding is faster, rounding is ; more accurate ALIGNMENT equ 2 @@ -110,20 +110,20 @@ M1 dd ? M2 dd ? FMparms ends align ALIGNMENT - public -FixedMul --FixedMul proc near + public _FixedMul +_FixedMul proc near push bp mov bp,sp mov eax,[bp+M1] imul dword ptr [bp+M2] ;multiply -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON shr eax,16 ;put the fractional part in AX pop bp ret --FixedMul endp +_FixedMul endp ;===================================================================== ; Divides one fixed-point value by another. ; C near-callable as: @@ -134,12 +134,12 @@ Dividend dd ? Divisor dd ? FDparms ends align ALIGNMENT -public -FixedDiv --FixedDiv proc near +public _FixedDiv +_FixedDiv proc near push bp mov bp,sp -if ROUNDING-ON +if ROUNDING_ON sub cx,cx ;assume positive result mov eax,[bp+Dividend] and eax,eax ;positive dividend? @@ -180,7 +180,7 @@ endif ;ROUNDING-ON ; fractional part is already in AX pop bp ret --FixedDiv endp +_FixedDiv endp ;===================================================================== ; Returns the sine and cosine of an angle. ; C near-callable as: @@ -198,8 +198,8 @@ Sin dw ? ;pointer to sin destination SCparms ends align ALIGNMENT - public -CosSin --CosSin proc near + public _CosSin +_CosSin proc near push bp ;preserve stack frame mov bp,sp ;set up local stack frame @@ -226,7 +226,7 @@ jg MakeInRange shl bx,2 mov eax,CosTable[bx] ;look up sine neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[bx+90*10*4] ;look up cosine + mov edx,CosTable[bx + (90*10*4)] ;look up cosine jmp short CSDone align ALIGNMENT @@ -237,7 +237,7 @@ Quadrant1: mov eax,CosTable[bx] ;look up cosine neg eax ;negative in this quadrant neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[bx+90*10*4] ;look up cosine + mov edx,CosTable[bx + (90*10*4)] ;look up cosine jmp short CSDone align ALIGNMENT @@ -250,7 +250,7 @@ BottomHalf: ;quadrant 2 or 3 shl bx, 2 mov eax,CosTable[bx] ;look up cosine neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[90*10*4+bx] ;look up sine + mov edx,CosTable[(90*10*4) + bx] ;look up sine neg edx ;negative in this quadrant jmp short CSDone @@ -262,7 +262,7 @@ Quadrant2: mov eax,CosTable[bx] ;look up cosine neg eax ;negative in this quadrant neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[90*10*4+bx] ;look up sine + mov edx,CosTable[(90*10*4) + bx] ;look up sine neg edx ;negative in this quadrant CSDone: mov bx,[bp].Cos @@ -272,7 +272,7 @@ CSDone: pop bp;restore stack frame ret --CosSin endp +_CosSin endp ;===================================================================== ; Matrix multiplies Xform by SourceVec, and stores the result in ; DestVec. Multiplies a 4x4 matrix times a 4x1 matrix; the result @@ -300,8 +300,8 @@ DestVec dw ? ;pointer to destination vector XVparms ends align ALIGNMENT - public -XformVec --XformVec proc near + public _XformVec +_XformVec proc near push bp ;preserve stack frame mov bp,sp ;set up local stack frame push si ;preserve register variables @@ -316,7 +316,7 @@ doff=0 REPT 3 ;do once each for dest X, Y, and Z mov eax,[si+soff] ;column 0 entry on this row imul dword ptr [bx] ;xform entry times source X entry -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -325,7 +325,7 @@ endif ;ROUNDING-ON mov eax,[si+soff+4] ;column 1 entry on this row imul dword ptr [bx+4] ;xform entry times source Y entry -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -334,7 +334,7 @@ endif ;ROUNDING-ON mov eax,[si+soff+8] ;column 2 entry on this row imul dword ptr [bx+8] ;xform entry times source Z entry -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -351,7 +351,7 @@ pop di;restore register variables pop si pop bp;restore stack frame ret --XformVec endp +_XformVec endp ;===================================================================== ; Matrix multiplies SourceXform1 by SourceXform2 and stores the ; result in DestXform. Multiplies a 4x4 matrix times a 4x4 matrix; @@ -386,8 +386,8 @@ DestXform dw ? ;pointer to destination xform matrix CXparms ends align ALIGNMENT - public -ConcatXforms --ConcatXforms proc near + public _ConcatXforms +_ConcatXforms proc near push bp ;preserve stack frame mov bp,sp ;set up local stack frame push si ;preserve register variables @@ -405,7 +405,7 @@ coff=0 ;column offset ; translation) mov eax,[si+roff] ;column 0 entry on this row imul dword ptr [bx+coff];times row 0 entry in column -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -414,7 +414,7 @@ endif ;ROUNDING-ON mov eax,[si+roff+4] ;column 1 entry on this row imul dword ptr [bx+coff+16];times row 1 entry in col -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -423,7 +423,7 @@ endif ;ROUNDING-ON mov eax,[si+roff+8] ;column 2 entry on this row imul dword ptr [bx+coff+32];times row 2 entry in col -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -438,7 +438,7 @@ ENDM ; translation to be performed mov eax,[si+roff] ;column 0 entry on this row imul dword ptr [bx+coff] ;times row 0 entry in column -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -447,7 +447,7 @@ endif ;ROUNDING-ON mov eax,[si+roff+4] ;column 1 entry on this row imul dword ptr [bx+coff+16];times row 1 entry in col -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON @@ -456,26 +456,26 @@ endif ;ROUNDING-ON mov eax,[si+roff+8] ;column 2 entry on this row imul dword ptr [bx+coff+32];times row 2 entry in col -if ROUNDING-ON +if ROUNDING_ON add eax,8000h ;round by adding 2^(-17) adc edx,0 ;whole part of result is in DX endif ;ROUNDING-ON shrd eax,edx,16 ;shift the result back to 16.16 form -addecx,eax;running total + add ecx,eax ;running total -addecx,[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 roff=roff+16 ;point to next col in xform2 & dest -ENDM + ENDM -pop di;restore register variables -pop si -pop bp;restore stack frame -ret --ConcatXforms endp + pop di;restore register variables + pop si + pop bp;restore stack frame + ret +_ConcatXforms endp end ``` @@ -590,7 +590,7 @@ void InitializeObjectList() { ObjectListStart.NextObject = &ObjectListEnd; ObjectListStart.PreviousObject = NULL; - ObjectListStart.CenterInView.Z = INT-TO-FIXED(-32768); + ObjectListStart.CenterInView.Z = INT_TO_FIXED(-32768); ObjectListEnd.NextObject = NULL; ObjectListEnd.PreviousObject = &ObjectListStart; ObjectListEnd.CenterInView.Z = 0x7FFFFFFFL; diff --git a/src/chapter-54.md b/src/chapter-54.md index 466388a..aaf49a6 100644 --- a/src/chapter-54.md +++ b/src/chapter-54.md @@ -83,138 +83,138 @@ and no more, as quickly as possible. ; Fixed point routines. ; Tested with TASM -USE386 equ 1 ;1 for 386-specific opcodes, 0 for +USE386 equ 1 ;1 for 386-specific opcodes, 0 for ; 8088 opcodes -MUL-ROUNDING-ON equ 1 ;1 for rounding on multiplies, +MUL_ROUNDING_ON equ 1 ;1 for rounding on multiplies, ; 0 for no rounding. Not rounding is faster, ; rounding is more accurate and generally a ; good idea -DIV-ROUNDING-ON equ 0 ;1 for rounding on divides, +DIV_ROUNDING_ON equ 0 ;1 for rounding on divides, ; 0 for no rounding. Not rounding is faster, ; rounding is more accurate, but because ; division is only performed to project to ; the screen, rounding quotients generally ; isn't necessary -ALIGNMENT equ 2 +ALIGNMENT equ 2 - .model small - .386 - .code + .model small + .386 + .code ;===================================================================== ; Multiplies two fixed-point values together. ; C near-callable as: -; Fixedpoint FixedMul(Fixedpoint M1, Fixedpoint M2); +; Fixedpoint FixedMul(Fixedpoint M1, Fixedpoint M2); FMparms struc - dw 2 dup(?) ;return address & pushed BP -M1 dd ? -M2 dd ? + dw 2 dup(?) ;return address & pushed BP +M1 dd ? +M2 dd ? FMparms ends - align ALIGNMENT - public _FixedMul -_FixedMul proc near - push bp - mov bp,sp + align ALIGNMENT + public _FixedMul +_FixedMul proc near + push bp + mov bp,sp if USE386 - mov eax,[bp+M1] - imul dword ptr [bp+M2] ;multiply -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) -adcedx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON -shreax,16 ;put the fractional part in AX - -else;!USE386 - - ;do four partial products and - ; add them together, accumulating - ; the result in CX:BX - push si ;preserve C register variables - push di - ;figure out signs, so we can use - ; unsigned multiplies - sub cx,cx ;assume both operands positive - mov ax,word ptr [bp+M1+2] - mov si,word ptr [bp+M1] - and ax,ax ;first operand negative? - jns CheckSecondOperand ;no - neg ax ;yes, so negate first operand - neg si - sbb ax,0 - inc cx ;mark that first operand is negative + mov eax,[bp+M1] + imul dword ptr [bp+M2] ;multiply +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shr eax,16 ;put the fractional part in AX + +else ;!USE386 + + ;do four partial products and + ; add them together, accumulating + ; the result in CX:BX + push si ;preserve C register variables + push di + ;figure out signs, so we can use + ; unsigned multiplies + sub cx,cx ;assume both operands positive + mov ax,word ptr [bp+M1+2] + mov si,word ptr [bp+M1] + and ax,ax ;first operand negative? + jns CheckSecondOperand ;no + neg ax ;yes, so negate first operand + neg si + sbb ax,0 + inc cx ;mark that first operand is negative CheckSecondOperand: - mov bx,word ptr [bp+M2+2] - mov di,word ptr [bp+M2] - and bx,bx ;second operand negative? - jns SaveSignStatus ;no - neg bx ;yes, so negate second operand - neg di - sbb bx,0 - xor cx,1 ;mark that second operand is negative + mov bx,word ptr [bp+M2+2] + mov di,word ptr [bp+M2] + and bx,bx ;second operand negative? + jns SaveSignStatus ;no + neg bx ;yes, so negate second operand + neg di + sbb bx,0 + xor cx,1 ;mark that second operand is negative SaveSignStatus: - push cx ;remember sign of result; 1 if result - ; negative, 0 if result nonnegative - push ax ;remember high word of M1 - mul bx ;high word M1 times high word M2 - mov cx,ax ;accumulate result in CX:BX (BX not used - ; until next operation, however) - ;assume no overflow into DX - mov ax,si ;low word M1 times high word M2 - mul bx - mov bx,ax - add cx,dx ;accumulate result in CX:BX - pop ax ;retrieve high word of M1 - mul di ;high word M1 times low word M2 - add bx,ax - adc cx,dx ;accumulate result in CX:BX - mov ax,si ;low word M1 times low word M2 -muldi -if MUL-ROUNDING-ON - add ax,8000h ;round by adding 2^(-17) -adcbx,dx -else ;!MUL-ROUNDING-ON - add bx,dx, ;don't round -endif ;MUL-ROUNDING-ON - adc cx,0 ;accumulate result in CX:BX - mov dx,cx - mov ax,bx - pop cx - and cx,cx ;is the result negative? - jz FixedMulDone ;no, we're all set - neg dx ;yes, so negate DX:AX - neg ax - sbb dx,0 + push cx ;remember sign of result; 1 if result + ; negative, 0 if result nonnegative + push ax ;remember high word of M1 + mul bx ;high word M1 times high word M2 + mov cx,ax ;accumulate result in CX:BX (BX not used + ; until next operation, however) + ;assume no overflow into DX + mov ax,si ;low word M1 times high word M2 + mul bx + mov bx,ax + add cx,dx ;accumulate result in CX:BX + pop ax ;retrieve high word of M1 + mul di ;high word M1 times low word M2 + add bx,ax + adc cx,dx ;accumulate result in CX:BX + mov ax,si ;low word M1 times low word M2 + mul di +if MUL_ROUNDING_ON + add ax,8000h ;round by adding 2^(-17) + adc bx,dx +else ;!MUL_ROUNDING_ON + add bx,dx ;don't round +endif ;MUL_ROUNDING_ON + adc cx,0 ;accumulate result in CX:BX + mov dx,cx + mov ax,bx + pop cx + and cx,cx ;is the result negative? + jz FixedMulDone ;no, we're all set + neg dx ;yes, so negate DX:AX + neg ax + sbb dx,0 FixedMulDone: - pop di ;restore C register variables - pop si + pop di ;restore C register variables + pop si -endif;USE386 +endif ;USE386 - pop bp - ret -_FixedMul endp + pop bp + ret +_FixedMul endp ;===================================================================== ; Divides one fixed-point value by another. ; C near-callable as: ; Fixedpoint FixedDiv(Fixedpoint Dividend, Fixedpoint Divisor); FDparms struc - dw 2 dup(?) ;return address & pushed BP -Dividend dd ? -Divisor dd ? + dw 2 dup(?) ;return address & pushed BP +Dividend dd ? +Divisor dd ? FDparms ends align ALIGNMENT public _FixedDiv -_FixedDivproc near +_FixedDiv proc near push bp mov bp,sp if USE386 -if DIV-ROUNDING-ON +if DIV_ROUNDING_ON sub cx,cx ;assume positive result mov eax,[bp+Dividend] and eax,eax ;positive dividend? @@ -222,7 +222,8 @@ if DIV-ROUNDING-ON inc cx ;mark it's a negative dividend neg eax ;make the dividend positive FDP1: sub edx,edx ;make it a 64-bit dividend, then shift - ; left 16 bits so that result will be in EAX + ; left 16 bits so that result will be + ; in EAX rol eax,16 ;put fractional part of dividend in ; high word of EAX mov dx,ax ;put whole part of dividend in DX @@ -243,269 +244,270 @@ FDP2: div ebx ;divide jz FDP3 ;no neg eax ;yes, negate it FDP3: -else ;!DIV-ROUNDING-ON +else ;!DIV_ROUNDING_ON mov edx,[bp+Dividend] sub eax,eax shrd eax,edx,16 ;position so that result ends up sar edx,16 ; in EAX idiv dword ptr [bp+Divisor] -endif ;DIV-ROUNDING-ON +endif ;DIV_ROUNDING_ON shld edx,eax,16 ;whole part of result in DX; ; fractional part is already in AX -else ;!USE386 - - ;NOTE!!! Non-386 division uses a 32-bit dividend but only the upper 16 bits - ; of the divisor; in other words, only the integer part of the divisor is - ; used. This is done so that the division can be accomplished with two fast - ; hardware divides instead of a slow software implementation, and is (in my - ; opinion) acceptable because division is only used to project points to the - ; screen (normally, the divisor is a Z coordinate), so there's no cumulative - ; error, although there will be some error in pixel placement (the magnitude - ; of the error is less the farther away from the Z=0 plane objects are). This - ; is *not* a general-purpose divide, though; if the divisor is less than 1, - ; for instance, a divide-by-zero error will result! For this reason, non-386 - ; projection can't be performed for points closer to the viewpoint than Z=1. - ;figure out signs, so we can use - ; unsigned divisions - sub cx,cx ;assume both operands positive - mov ax,word ptr [bp+Dividend+2] - and ax,ax;first operand negative? - jns CheckSecondOperandD ;no - neg ax ;yes, so negate first operand - neg word ptr [bp+Dividend] - sbb ax,0 - inc cx ;mark that first operand is negative - CheckSecondOperandD: - mov bx,word ptr [bp+Divisor+2] - and bx,bx ;second operand negative? -jnsSaveSignStatusD;no - neg bx ;yes, so negate second operand - neg word ptr [bp+Divisor] - sbb bx,0 - xor cx,1 ;mark that second operand is negative +else ;!USE386 + +;NOTE!!! Non-386 division uses a 32-bit dividend but only the upper 16 bits +; of the divisor; in other words, only the integer part of the divisor is +; used. This is done so that the division can be accomplished with two fast +; hardware divides instead of a slow software implementation, and is (in my +; opinion) acceptable because division is only used to project points to the +; screen (normally, the divisor is a Z coordinate), so there's no cumulative +; error, although there will be some error in pixel placement (the magnitude +; of the error is less the farther away from the Z=0 plane objects are). This +; is *not* a general-purpose divide, though; if the divisor is less than 1, +; for instance, a divide-by-zero error will result! For this reason, non-386 +; projection can't be performed for points closer to the viewpoint than Z=1. + + ;figure out signs, so we can use + ; unsigned divisions + sub cx,cx ;assume both operands positive + mov ax,word ptr [bp+Dividend+2] + and ax,ax ;first operand negative? + jns CheckSecondOperandD ;no + neg ax ;yes, so negate first operand + neg word ptr [bp+Dividend] + sbb ax,0 + inc cx ;mark that first operand is negative +CheckSecondOperandD: + mov bx,word ptr [bp+Divisor+2] + and bx,bx ;second operand negative? + jns SaveSignStatusD ;no + neg bx ;yes, so negate second operand + neg word ptr [bp+Divisor] + sbb bx,0 + xor cx,1 ;mark that second operand is negative SaveSignStatusD: - push cx ;remember sign of result; 1 if result - ; negative, 0 if result nonnegative - sub dx,dx ;put Dividend+2 (integer part) in DX:AX - div bx ;first half of 32/16 division, integer part - ; divided by integer part - mov cx,ax ;set aside integer part of result - mov ax,word ptr [bp+Dividend] ;concatenate the fractional part of - ; the dividend to the remainder (fractional - ; part) of the result from dividing the - ; integer part of the dividend - div bx ;second half of 32/16 division - -if DIV-ROUNDING-ON EQ 0 - shr bx,1 ;divisor/2, minus 1 if the divisor is - adc bx,0 ; even - dec bx - cmp bx,dx ;set Carry if the remainder is at least - adc ax,0 ; half as large as the divisor, then - adc cx,0 ; use that to round up if necessary -endif ;DIV-ROUNDING-ON - - mov dx,cx ;absolute value of result in DX:AX - pop cx - and cx,cx ;is the result negative? - jz FixedDivDone ;no, we're all set - neg dx ;yes, so negate DX:AX - neg ax - sbb dx,0 + push cx ;remember sign of result; 1 if result + ; negative, 0 if result nonnegative + sub dx,dx ;put Dividend+2 (integer part) in DX:AX + div bx ;first half of 32/16 division, integer part + ; divided by integer part + mov cx,ax ;set aside integer part of result + mov ax,word ptr [bp+Dividend] ;concatenate the fractional part of + ; the dividend to the remainder (fractional + ; part) of the result from dividing the + ; integer part of the dividend + div bx ;second half of 32/16 division + +if DIV_ROUNDING_ON EQ 0 + shr bx,1 ;divisor/2, minus 1 if the divisor is + adc bx,0 ; even + dec bx + cmp bx,dx ;set Carry if the remainder is at least + adc ax,0 ; half as large as the divisor, then + adc cx,0 ; use that to round up if necessary +endif ;DIV_ROUNDING_ON + + mov dx,cx ;absolute value of result in DX:AX + pop cx + and cx,cx ;is the result negative? + jz FixedDivDone ;no, we're all set + neg dx ;yes, so negate DX:AX + neg ax + sbb dx,0 FixedDivDone: endif ;USE386 - pop bp - ret + pop bp + ret _FixedDiv endp ;===================================================================== ; Returns the sine and cosine of an angle. ; C near-callable as: -; void CosSin(TAngle Angle, Fixedpoint *Cos, Fixedpoint *); +; void CosSin(TAngle Angle, Fixedpoint *Cos, Fixedpoint *); - alignALIGNMENT + align ALIGNMENT CosTable label dword - include costable.inc + include costable.inc SCparms struc - dw 2 dup(?) ;return address & pushed BP -Angle dw ? ;angle to calculate sine & cosine for -Cos dw ? ;pointer to cos destination -Sin dw ? ;pointer to sin destination -SCparms ends - - alignALIGNMENT - public _CosSin -_CosSin proc near - push bp ;preserve stack frame - mov bp,sp ;set up local stack frame + dw 2 dup(?) ;return address & pushed BP +Angle dw ? ;angle to calculate sine & cosine for +Cos dw ? ;pointer to cos destination +Sin dw ? ;pointer to sin destination +SCparms ends + + align ALIGNMENT + public _CosSin +_CosSin proc near + push bp ;preserve stack frame + mov bp,sp ;set up local stack frame if USE386 - mov bx,[bp].Angle - and bx,bx ;make sure angle's between 0 and 2*pi - jns CheckInRange -MakePos: ;less than 0, so make it positive - add bx,360*10 - js MakePos - jmp short CheckInRange - - align ALIGNMENT -MakeInRange: ;make sure angle is no more than 2*pi - sub bx,360*10 + mov bx,[bp].Angle + and bx,bx ;make sure angle's between 0 and 2*pi + jns CheckInRange +MakePos: ;less than 0, so make it positive + add bx,360*10 + js MakePos + jmp short CheckInRange + + align ALIGNMENT +MakeInRange: ;make sure angle is no more than 2*pi + sub bx,360*10 CheckInRange: - cmp bx,360*10 - jg MakeInRange - - cmp bx,180*10 ;figure out which quadrant - ja BottomHalf ;quadrant 2 or 3 - cmp bx,90*10 ;quadrant 0 or 1 - ja Quadrant1 -;quadrant 0 - shl bx,2 - mov eax,CosTable[bx] ;look up sine - neg bx;sin(Angle) = cos(90-Angle) - mov edx,CosTable[bx+90*10*4] ;look up cosine - jmp short CSDone - - align ALIGNMENT + cmp bx,360*10 + jg MakeInRange + + cmp bx,180*10 ;figure out which quadrant + ja BottomHalf ;quadrant 2 or 3 + cmp bx,90*10 ;quadrant 0 or 1 + ja Quadrant1 + ;quadrant 0 + shl bx,2 + mov eax,CosTable[bx] ;look up sine + neg bx ;sin(Angle) = cos(90-Angle) + mov edx,CosTable[bx + (90*10*4)] ;look up cosine + jmp short CSDone + + align ALIGNMENT Quadrant1: - neg bx - add bx,180*10 ;convert to angle between 0 and 90 - shl bx,2 - mov eax,CosTable[bx] ;look up cosine - neg eax ;negative in this quadrant - neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[bx+90*10*4] ;look up cosine - jmp short CSDone - - align ALIGNMENT -BottomHalf: ;quadrant 2 or 3 - neg bx - add bx,360*10 ;convert to angle between 0 and 180 - cmp bx,90*10 ;quadrant 2 or 3 - ja Quadrant2 - ;quadrant 3 - shl bx,2 - mov eax,CosTable[bx] ;look up cosine - neg bx;sin(Angle) = cos(90-Angle) - mov edx,CosTable[90*10*4+bx] ;look up sine - neg edx ;negative in this quadrant - jmp short CSDone - - align ALIGNMENT + neg bx + add bx,180*10 ;convert to angle between 0 and 90 + shl bx,2 + mov eax,CosTable[bx] ;look up cosine + neg eax ;negative in this quadrant + neg bx ;sin(Angle) = cos(90-Angle) + mov edx,CosTable[bx + (90*10*4)] ;look up cosine + jmp short CSDone + + align ALIGNMENT +BottomHalf: ;quadrant 2 or 3 + neg bx + add bx,360*10 ;convert to angle between 0 and 180 + cmp bx,90*10 ;quadrant 2 or 3 + ja Quadrant2 + ;quadrant 3 + shl bx,2 + mov eax,CosTable[bx] ;look up cosine + neg bx ;sin(Angle) = cos(90-Angle) + mov edx,CosTable[(90*10*4) + bx] ;look up sine + neg edx ;negative in this quadrant + jmp short CSDone + + align ALIGNMENT Quadrant2: - neg bx - add bx,180*10 ;convert to angle between 0 and 90 - shl bx,2 - mov eax,CosTable[bx] ;look up cosine - neg eax ;negative in this quadrant - neg bx ;sin(Angle) = cos(90-Angle) - mov edx,CosTable[90*10*4+bx] ;look up sine - neg edx ;negative in this quadrant + neg bx + add bx,180*10 ;convert to angle between 0 and 90 + shl bx,2 + mov eax,CosTable[bx] ;look up cosine + neg eax ;negative in this quadrant + neg bx ;sin(Angle) = cos(90-Angle) + mov edx,CosTable[(90*10*4) + bx] ;look up sine + neg edx ;negative in this quadrant CSDone: - mov bx,[bp].Cos - mov [bx],eax - mov bx,[bp].Sin - mov [bx],edx + mov bx,[bp].Cos + mov [bx],eax + mov bx,[bp].Sin + mov [bx],edx else ;!USE386 - mov bx,[bp].Angle - and bx,bx ;make sure angle's between 0 and 2*pi - jns CheckInRange -MakePos: ;less than 0, so make it positive - add bx,360*10 - js MakePos - jmp short CheckInRange - - align ALIGNMENT -MakeInRange: ; make sure angle is no more than 2*pi - sub bx,360*10 + mov bx,[bp].Angle + and bx,bx ;make sure angle's between 0 and 2*pi + jns CheckInRange +MakePos: ;less than 0, so make it positive + add bx,360*10 + js MakePos + jmp short CheckInRange + + align ALIGNMENT +MakeInRange: ;make sure angle is no more than 2*pi + sub bx,360*10 CheckInRange: - cmp bx,360*10 - jg MakeInRange - - cmp bx,180*10 ;figure out which quadrant - ja BottomHalf ;quadrant 2 or 3 - cmp bx,90*10 ;quadrant 0 or 1 -jaQuadrant1 - ;quadrant 0 - shl bx,2 - mov ax,word ptr CosTable[bx] ;look up sine - mov dx,word ptr CosTable[bx+2] - neg bx ;sin(Angle) = cos(90-Angle) - mov cx,word ptr CosTable[bx+90*10*4+2] ;look up cosine - mov bx,word ptr CosTable[bx+90*10*4] - jmp CSDone - - align ALIGNMENT + cmp bx,360*10 + jg MakeInRange + + cmp bx,180*10 ;figure out which quadrant + ja BottomHalf ;quadrant 2 or 3 + cmp bx,90*10 ;quadrant 0 or 1 + ja Quadrant1 + ;quadrant 0 + shl bx,2 + mov ax,word ptr CosTable[bx] ;look up sine + mov dx,word ptr CosTable[bx+2] + neg bx ;sin(Angle) = cos(90-Angle) + mov cx,word ptr CosTable[bx+90*10*4+2] ;look up cosine + mov bx,word ptr CosTable[bx+90*10*4] + jmp CSDone + + align ALIGNMENT Quadrant1: - neg bx - add bx,180*10 ;convert to angle between 0 and 90 - shl bx,2 - mov ax,word ptr CosTable[bx] ;look up cosine - mov dx,word ptr CosTable[bx+2] - neg dx ;negative in this quadrant - neg ax - sbb dx,0 - neg bx ;sin(Angle) = cos(90-Angle) - mov cx,word ptr CosTable[bx+90*10*4+2] ;look up cosine - mov bx,word ptr CosTable[bx+90*10*4] - jmp short CSDone - - align ALIGNMENT -BottomHalf: ;quadrant 2 or 3 - neg bx - add bx,360*10 ;convert to angle between 0 and 180 - cmp bx,90*10 ;quadrant 2 or 3 -jaQuadrant2 - ;quadrant 3 - shl bx,2 - mov ax,word ptr CosTable[bx] ;look up cosine - mov dx,word ptr CosTable[bx+2] - neg bx ;sin(Angle) = cos(90-Angle) - mov cx,word ptr CosTable[90*10*4+bx+2] ;look up sine - mov bx,word ptr CosTable[90*10*4+bx] - neg cx ;negative in this quadrant - neg bx - sbb cx,0 - jmp short CSDone - - align ALIGNMENT + neg bx + add bx,180*10 ;convert to angle between 0 and 90 + shl bx,2 + mov ax,word ptr CosTable[bx] ;look up cosine + mov dx,word ptr CosTable[bx+2] + neg dx ;negative in this quadrant + neg ax + sbb dx,0 + neg bx ;sin(Angle) = cos(90-Angle) + mov cx,word ptr CosTable[bx+90*10*4+2] ;look up cosine + mov bx,word ptr CosTable[bx+90*10*4] + jmp short CSDone + + align ALIGNMENT +BottomHalf: ;quadrant 2 or 3 + neg bx + add bx,360*10 ;convert to angle between 0 and 180 + cmp bx,90*10 ;quadrant 2 or 3 + ja Quadrant2 + ;quadrant 3 + shl bx,2 + mov ax,word ptr CosTable[bx] ;look up cosine + mov dx,word ptr CosTable[bx+2] + neg bx ;sin(Angle) = cos(90-Angle) + mov cx,word ptr CosTable[90*10*4+bx+2] ;look up sine + mov bx,word ptr CosTable[90*10*4+bx] + neg cx ;negative in this quadrant + neg bx + sbb cx,0 + jmp short CSDone + + align ALIGNMENT Quadrant2: - neg bx - add bx,180*10 ;convert to angle between 0 and 90 - shl bx,2 - mov ax,word ptr CosTable[bx] ;look up cosine - mov dx,word ptr CosTable[bx+2] - neg dx ;negative in this quadrant - neg ax - sbb dx,0 - neg bx ;sin(Angle) = cos(90-Angle) - mov cx,word ptr CosTable[90*10*4+bx+2] ;look up sine - mov bx,word ptr CosTable[90*10*4+bx] - neg cx ;negative in this quadrant - neg bx - sbb cx,0 + neg bx + add bx,180*10 ;convert to angle between 0 and 90 + shl bx,2 + mov ax,word ptr CosTable[bx] ;look up cosine + mov dx,word ptr CosTable[bx+2] + neg dx ;negative in this quadrant + neg ax + sbb dx,0 + neg bx ;sin(Angle) = cos(90-Angle) + mov cx,word ptr CosTable[90*10*4+bx+2] ;look up sine + mov bx,word ptr CosTable[90*10*4+bx] + neg cx ;negative in this quadrant + neg bx + sbb cx,0 CSDone: - push bx - mov bx,[bp].Cos - mov [bx],ax - mov [bx+2],dx - mov bx,[bp].Sin - pop ax - mov [bx],ax - mov [bx+2],cx + push bx + mov bx,[bp].Cos + mov [bx],ax + mov [bx+2],dx + mov bx,[bp].Sin + pop ax + mov [bx],ax + mov [bx+2],cx endif ;USE386 - pop bp ;restore stack frame - ret -_CosSin endp + pop bp ;restore stack frame + ret +_CosSin endp ;===================================================================== ; Matrix multiplies Xform by SourceVec, and stores the result in @@ -514,197 +516,197 @@ _CosSin endp ; bottom row of the matrix is 0 0 0 1, and doesn't bother to set ; the W coordinate of the destination. ; C near-callable as: -; void XformVec(Xform WorkingXform, Fixedpoint *SourceVec, -; Fixedpoint *DestVec); +; void XformVec(Xform WorkingXform, Fixedpoint *SourceVec, +; Fixedpoint *DestVec); ; ; This assembly code is equivalent to this C code: ; int i; ; ; for (i=0; i<3; i++) ; DestVec[i] = FixedMul(WorkingXform[i][0], SourceVec[0]) + -; FixedMul(WorkingXform[i][1], SourceVec[1]) + -; FixedMul(WorkingXform[i][2], SourceVec[2]) + -; WorkingXform[i][3]; /* no need to multiply by W = 1 */ +; FixedMul(WorkingXform[i][1], SourceVec[1]) + +; FixedMul(WorkingXform[i][2], SourceVec[2]) + +; WorkingXform[i][3]; /* no need to multiply by W = 1 */ XVparms struc - dw 2 dup(?) ;return address & pushed BP -WorkingXform dw ? ;pointer to transform matrix -SourceVec dw ? ;pointer to source vector -DestVec dw ? ;pointer to destination vector + dw 2 dup(?) ;return address & pushed BP +WorkingXform dw ? ;pointer to transform matrix +SourceVec dw ? ;pointer to source vector +DestVec dw ? ;pointer to destination vector XVparms ends ; Macro for non-386 multiply. AX, BX, CX, DX destroyed. -FIXED-MUL MACRO M1,M2 - local CheckSecondOperand,SaveSignStatus,FixedMulDone - - ;do four partial products and - ; add them together, accumulating - ; the result in CX:BX - ;figure out signs, so we can use - ; unsigned multiplies - sub cx,cx ;assume both operands positive - mov bx,word ptr [&M1&+2] - and bx,bx ;first operand negative? - jns CheckSecondOperand ;no - neg bx ;yes, so negate first operand - neg word ptr [&M1&] - sbb bx,0 - mov word ptr [&M1&+2],bx - inc cx ;mark that first operand is negative +FIXED_MUL MACRO M1,M2 + local CheckSecondOperand,SaveSignStatus,FixedMulDone + + ;do four partial products and + ; add them together, accumulating + ; the result in CX:BX + ;figure out signs, so we can use + ; unsigned multiplies + sub cx,cx ;assume both operands positive + mov bx,word ptr [&M1&+2] + and bx,bx ;first operand negative? + jns CheckSecondOperand ;no + neg bx ;yes, so negate first operand + neg word ptr [&M1&] + sbb bx,0 + mov word ptr [&M1&+2],bx + inc cx ;mark that first operand is negative CheckSecondOperand: - mov bx,word ptr [&M2&+2] - and bx,bx ;second operand negative? - jns SaveSignStatus ;no - neg bx ;yes, so negate second operand - neg word ptr [&M2&] - sbb bx,0 - mov word ptr [&M2&+2],bx - xor cx,1 ;mark that second operand is negative + mov bx,word ptr [&M2&+2] + and bx,bx ;second operand negative? + jns SaveSignStatus ;no + neg bx ;yes, so negate second operand + neg word ptr [&M2&] + sbb bx,0 + mov word ptr [&M2&+2],bx + xor cx,1 ;mark that second operand is negative SaveSignStatus: - push cx ;remember sign of result; 1 if result - ; negative, 0 if result nonnegative - mov ax,word ptr [&M1&+2] ;high word times high word - mul word ptr [&M2&+2] - mov cx,ax ; - ;assume no overflow into DX - mov ax,word ptr [&M1&+2] ;high word times low word - mul word ptr [&M2&] - mov bx,ax - add cx,dx - mov ax,word ptr [&M1&] ;low word times high word - mul word ptr [&M2&+2] - add bx,ax - adc cx,dx - mov ax,word ptr [&M1&] ;low word times low word - mul word ptr [&M2&] -if MUL-ROUNDING-ON - add ax,8000h ;round by adding 2^(-17) - adc bx,dx -else ;!MUL-ROUNDING-ON - add bx,dx ;don't round -endif ;MUL-ROUNDING-ON - adc cx,0 - mov dx,cx - mov ax,bx - pop cx - and cx,cx ;is the result negative? - jz FixedMulDone ;no, we're all set - neg dx ;yes, so negate DX:AX - neg ax - sbb dx,0 + push cx ;remember sign of result; 1 if result + ; negative, 0 if result nonnegative + mov ax,word ptr [&M1&+2] ;high word times high word + mul word ptr [&M2&+2] + mov cx,ax ; + ;assume no overflow into DX + mov ax,word ptr [&M1&+2] ;high word times low word + mul word ptr [&M2&] + mov bx,ax + add cx,dx + mov ax,word ptr [&M1&] ;low word times high word + mul word ptr [&M2&+2] + add bx,ax + adc cx,dx + mov ax,word ptr [&M1&] ;low word times low word + mul word ptr [&M2&] +if MUL_ROUNDING_ON + add ax,8000h ;round by adding 2^(-17) + adc bx,dx +else ;!MUL_ROUNDING_ON + add bx,dx ;don't round +endif ;MUL_ROUNDING_ON + adc cx,0 + mov dx,cx + mov ax,bx + pop cx + and cx,cx ;is the result negative? + jz FixedMulDone ;no, we're all set + neg dx ;yes, so negate DX:AX + neg ax + sbb dx,0 FixedMulDone: - ENDM + ENDM - align ALIGNMENT - public _XformVec -_XformVec proc near - push bp ;preserve stack frame - mov bp,sp ;set up local stack frame - push si ;preserve register variables - push di + align ALIGNMENT + public _XformVec +_XformVec proc near + push bp ;preserve stack frame + mov bp,sp ;set up local stack frame + push si ;preserve register variables + push di if USE386 - mov si,[bp].WorkingXform ;SI points to xform matrix - mov bx,[bp].SourceVec ;BX points to source vector - mov di,[bp].DestVec ;DI points to dest vector + mov si,[bp].WorkingXform ;SI points to xform matrix + mov bx,[bp].SourceVec ;BX points to source vector + mov di,[bp].DestVec ;DI points to dest vector soff=0 doff=0 - REPT 3 ;do once each for dest X, Y, and Z - mov eax,[si+soff] ;column 0 entry on this row - imul dword ptr [bx] ;xform entry times source X entry -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - mov ecx,eax ;set running total - - mov eax,[si+soff+4] ;column 1 entry on this row - imul dword ptr [bx+4] ;xform entry times source Y entry -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total for this row - - mov eax,[si+soff+8] ;column 2 entry on this row - imul dword ptr [bx+8] ;xform entry times source Z entry -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total for this row - - add ecx,[si+soff+12] ;add in translation - mov [di+doff],ecx ;save the result in the dest vector + REPT 3 ;do once each for dest X, Y, and Z + mov eax,[si+soff] ;column 0 entry on this row + imul dword ptr [bx] ;xform entry times source X entry +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + mov ecx,eax ;set running total + + mov eax,[si+soff+4] ;column 1 entry on this row + imul dword ptr [bx+4] ;xform entry times source Y entry +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total for this row + + mov eax,[si+soff+8] ;column 2 entry on this row + imul dword ptr [bx+8] ;xform entry times source Z entry +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total for this row + + add ecx,[si+soff+12] ;add in translation + mov [di+doff],ecx ;save the result in the dest vector soff=soff+16 doff=doff+4 - ENDM + ENDM else ;!USE386 - mov si,[bp].WorkingXform ;SI points to xform matrix - mov di,[bp].SourceVec ;DI points to source vector - mov bx,[bp].DestVec ;BX points to dest vector - push bp ;preserve stack frame pointer + mov si,[bp].WorkingXform ;SI points to xform matrix + mov di,[bp].SourceVec ;DI points to source vector + mov bx,[bp].DestVec ;BX points to dest vector + push bp ;preserve stack frame pointer soff=0 doff=0 - REPT 3 ;do once each for dest X, Y, and Z - push bx ;remember dest vector pointer - push word ptr [si+soff+2] - push word ptr [si+soff] - push word ptr [di+2] - push word ptr [di] - call _FixedMul ;xform entry times source X entry - add sp,8;clear parameters from stack - mov cx,ax ;set running total - mov bp,dx - - push cx ;preserve low word of running total - push word ptr [si+soff+4+2] - push word ptr [si+soff+4] - push word ptr [di+4+2] - push word ptr [di+4] - call _FixedMul ;xform entry times source Y entry - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - push cx ;preserve low word of running total - push word ptr [si+soff+8+2] - push word ptr [si+soff+8] - push word ptr [di+8+2] - push word ptr [di+8] - call _FixedMul ;xform entry times source Z entry - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - add cx,[si+soff+12] ;add in translation - adc bp,[si+soff+12+2] - pop bx ;restore dest vector pointer - mov [bx+doff],cx ;save the result in the dest vector - mov [bx+doff+2],bp + REPT 3 ;do once each for dest X, Y, and Z + push bx ;remember dest vector pointer + push word ptr [si+soff+2] + push word ptr [si+soff] + push word ptr [di+2] + push word ptr [di] + call _FixedMul ;xform entry times source X entry + add sp,8 ;clear parameters from stack + mov cx,ax ;set running total + mov bp,dx + + push cx ;preserve low word of running total + push word ptr [si+soff+4+2] + push word ptr [si+soff+4] + push word ptr [di+4+2] + push word ptr [di+4] + call _FixedMul ;xform entry times source Y entry + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + push cx ;preserve low word of running total + push word ptr [si+soff+8+2] + push word ptr [si+soff+8] + push word ptr [di+8+2] + push word ptr [di+8] + call _FixedMul ;xform entry times source Z entry + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + add cx,[si+soff+12] ;add in translation + adc bp,[si+soff+12+2] + pop bx ;restore dest vector pointer + mov [bx+doff],cx ;save the result in the dest vector + mov [bx+doff+2],bp soff=soff+16 doff=doff+4 - ENDM + ENDM - pop bp ;restore stack frame pointer + pop bp ;restore stack frame pointer endif ;USE386 - pop di ;restore register variables - pop si - pop bp ;restore stack frame -ret -_XformVec endp + pop di ;restore register variables + pop si + pop bp ;restore stack frame + ret +_XformVec endp ;===================================================================== ; Matrix multiplies SourceXform1 by SourceXform2 and stores the @@ -733,212 +735,212 @@ _XformVec endp ; } CXparms struc - dw 2 dup(?) ;return address & pushed BP -SourceXform1 dw ? ;pointer to first source xform matrix -SourceXform2 dw ? ;pointer to second source xform matrix -DestXform dw ? ;pointer to destination xform matrix + dw 2 dup(?) ;return address & pushed BP +SourceXform1 dw ? ;pointer to first source xform matrix +SourceXform2 dw ? ;pointer to second source xform matrix +DestXform dw ? ;pointer to destination xform matrix CXparms ends - align ALIGNMENT - public _ConcatXforms -_ConcatXforms proc near - push bp ;preserve stack frame - mov bp,sp ;set up local stack frame - push si ;preserve register variables - push di + align ALIGNMENT + public _ConcatXforms +_ConcatXforms proc near + push bp ;preserve stack frame + mov bp,sp ;set up local stack frame + push si ;preserve register variables + push di if USE386 - mov bx,[bp].SourceXform2 ;BX points to xform2 matrix - mov si,[bp].SourceXform1 ;SI points to xform1 matrix - mov di,[bp].DestXform ;DI points to dest xform matrix - -roff=0 ;row offset - REPT 3 ;once for each row -coff=0 ;column offset -REPT 3 ;once for each of the first 3 columns, - ; assuming 0 as the bottom entry (no - ; translation) - mov eax,[si+roff] ;column 0 entry on this row - imul dword ptr [bx+coff] ;times row 0 entry in column -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - mov ecx,eax ;set running total - - mov eax,[si+roff+4] ;column 1 entry on this row - imul dword ptr [bx+coff+16] ;times row 1 entry in col -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total - - mov eax,[si+roff+8] ;column 2 entry on this row - imul dword ptr [bx+coff+32] ;times row 2 entry in col -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total - - mov [di+coff+roff],ecx ;save the result in dest matrix -coff=coff+4 ;point to next col in xform2 & dest - ENDM -;now do the fourth column, assuming -; 1 as the bottom entry, causing -; translation to be performed - mov eax,[si+roff] ;column 0 entry on this row - imul dword ptr [bx+coff] ;times row 0 entry in column -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - mov ecx,eax ;set running total - - mov eax,[si+roff+4] ;column 1 entry on this row - imul dword ptr [bx+coff+16] ;times row 1 entry in col -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total - - mov eax,[si+roff+8] ;column 2 entry on this row - imul dword ptr [bx+coff+32] ;times row 2 entry in col -if MUL-ROUNDING-ON - add eax,8000h ;round by adding 2^(-17) - adc edx,0 ;whole part of result is in DX -endif ;MUL-ROUNDING-ON - shrd eax,edx,16 ;shift the result back to 16.16 form - add ecx,eax ;running total - - add ecx,[si+roff+12] ;add in translation - - mov [di+coff+roff],ecx ;save the result in dest matrix -coff=coff+4 ;point to next col in xform2 & dest - -roff=roff+16 ;point to next col in xform2 & dest - ENDM + mov bx,[bp].SourceXform2 ;BX points to xform2 matrix + mov si,[bp].SourceXform1 ;SI points to xform1 matrix + mov di,[bp].DestXform ;DI points to dest xform matrix + +roff=0 ;row offset + REPT 3 ;once for each row +coff=0 ;column offset + REPT 3 ;once for each of the first 3 columns, + ; assuming 0 as the bottom entry (no + ; translation) + mov eax,[si+roff] ;column 0 entry on this row + imul dword ptr [bx+coff] ;times row 0 entry in column +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + mov ecx,eax ;set running total + + mov eax,[si+roff+4] ;column 1 entry on this row + imul dword ptr [bx+coff+16] ;times row 1 entry in col +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total + + mov eax,[si+roff+8] ;column 2 entry on this row + imul dword ptr [bx+coff+32] ;times row 2 entry in col +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total + + mov [di+coff+roff],ecx ;save the result in dest matrix +coff=coff+4 ;point to next col in xform2 & dest + ENDM + ;now do the fourth column, assuming + ; 1 as the bottom entry, causing + ; translation to be performed + mov eax,[si+roff] ;column 0 entry on this row + imul dword ptr [bx+coff] ;times row 0 entry in column +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + mov ecx,eax ;set running total + + mov eax,[si+roff+4] ;column 1 entry on this row + imul dword ptr [bx+coff+16] ;times row 1 entry in col +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total + + mov eax,[si+roff+8] ;column 2 entry on this row + imul dword ptr [bx+coff+32] ;times row 2 entry in col +if MUL_ROUNDING_ON + add eax,8000h ;round by adding 2^(-17) + adc edx,0 ;whole part of result is in DX +endif ;MUL_ROUNDING_ON + shrd eax,edx,16 ;shift the result back to 16.16 form + add ecx,eax ;running total + + add ecx,[si+roff+12] ;add in translation + + mov [di+coff+roff],ecx ;save the result in dest matrix +coff=coff+4 ;point to next col in xform2 & dest + +roff=roff+16 ;point to next col in xform2 & dest + ENDM else ;!USE386 - mov di,[bp].SourceXform2 ;DI points to xform2 matrix - mov si,[bp].SourceXform1 ;SI points to xform1 matrix - mov bx,[bp].DestXform ;BX points to dest xform matrix - push bp ;preserve stack frame pointer - -roff=0 ;row offset - REPT 3 ;once for each row -coff=0 ;column offset - REPT 3 ;once for each of the first 3 columns, -; assuming 0 as the bottom entry (no -; translation) - push bx ;remember dest vector pointer - push word ptr [si+roff+2] - push word ptr [si+roff] - push word ptr [di+coff+2] - push word ptr [di+coff] - call _FixedMul ;column 0 entry on this row times row 0 -; entry in column -addsp,8;clear parameters from stack - mov cx,ax ;set running total - mov bp,dx - - push cx ;preserve low word of running total - push word ptr [si+roff+4+2] - push word ptr [si+roff+4] - push word ptr [di+coff+16+2] - push word ptr [di+coff+16] - call _FixedMul ;column 1 entry on this row times row 1 -; entry in column - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - push cx ;preserve low word of running total - push word ptr [si+roff+8+2] - push word ptr [si+roff+8] - push word ptr [di+coff+32+2] - push word ptr [di+coff+32] - call _FixedMul ;column 1 entry on this row times row 1 -; entry in column - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - pop bx ;restore DestXForm pointer - mov [bx+coff+roff],cx ;save the result in dest matrix - mov [bx+coff+roff+2],bp -coff=coff+4 ;point to next col in xform2 & dest - ENDM -;now do the fourth column, assuming -; 1 as the bottom entry, causing -; translation to be performed - push bx ;remember dest vector pointer - push word ptr [si+roff+2] - push word ptr [si+roff] - push word ptr [di+coff+2] - push word ptr [di+coff] - call _FixedMul ;column 0 entry on this row times row 0 -; entry in column - add sp,8 ;clear parameters from stack - mov cx,ax ;set running total - mov bp,dx - - push cx ;preserve low word of running total - push word ptr [si+roff+4+2] - push word ptr [si+roff+4] - push word ptr [di+coff+16+2] - push word ptr [di+coff+16] - call _FixedMul ;column 1 entry on this row times row 1 -; entry in column - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - push cx ;preserve low word of running total - push word ptr [si+roff+8+2] - push word ptr [si+roff+8] - push word ptr [di+coff+32+2] - push word ptr [di+coff+32] - call _FixedMul ;column 1 entry on this row times row 1 -; entry in column - add sp,8 ;clear parameters from stack - pop cx ;restore low word of running total - add cx,ax ;running total for this row - adc bp,dx - - add cx,[si+roff+12] ;add in translation - add bp,[si+roff+12+2] - - pop bx ;restore DestXForm pointer - mov [bx+coff+roff],cx ;save the result in dest matrix - mov [bx+coff+roff+2],bp -coff=coff+4 ;point to next col in xform2 & dest - -roff=roff+16 ;point to next col in xform2 & dest - ENDM - - pop bp ;restore stack frame pointer + mov di,[bp].SourceXform2 ;DI points to xform2 matrix + mov si,[bp].SourceXform1 ;SI points to xform1 matrix + mov bx,[bp].DestXform ;BX points to dest xform matrix + push bp ;preserve stack frame pointer + +roff=0 ;row offset + REPT 3 ;once for each row +coff=0 ;column offset + REPT 3 ;once for each of the first 3 columns, + ; assuming 0 as the bottom entry (no + ; translation) + push bx ;remember dest vector pointer + push word ptr [si+roff+2] + push word ptr [si+roff] + push word ptr [di+coff+2] + push word ptr [di+coff] + call _FixedMul ;column 0 entry on this row times row 0 + ; entry in column + add sp,8 ;clear parameters from stack + mov cx,ax ;set running total + mov bp,dx + + push cx ;preserve low word of running total + push word ptr [si+roff+4+2] + push word ptr [si+roff+4] + push word ptr [di+coff+16+2] + push word ptr [di+coff+16] + call _FixedMul ;column 1 entry on this row times row 1 + ; entry in column + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + push cx ;preserve low word of running total + push word ptr [si+roff+8+2] + push word ptr [si+roff+8] + push word ptr [di+coff+32+2] + push word ptr [di+coff+32] + call _FixedMul ;column 1 entry on this row times row 1 + ; entry in column + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + pop bx ;restore DestXForm pointer + mov [bx+coff+roff],cx ;save the result in dest matrix + mov [bx+coff+roff+2],bp +coff=coff+4 ;point to next col in xform2 & dest + ENDM + ;now do the fourth column, assuming + ; 1 as the bottom entry, causing + ; translation to be performed + push bx ;remember dest vector pointer + push word ptr [si+roff+2] + push word ptr [si+roff] + push word ptr [di+coff+2] + push word ptr [di+coff] + call _FixedMul ;column 0 entry on this row times row 0 + ; entry in column + add sp,8 ;clear parameters from stack + mov cx,ax ;set running total + mov bp,dx + + push cx ;preserve low word of running total + push word ptr [si+roff+4+2] + push word ptr [si+roff+4] + push word ptr [di+coff+16+2] + push word ptr [di+coff+16] + call _FixedMul ;column 1 entry on this row times row 1 + ; entry in column + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + push cx ;preserve low word of running total + push word ptr [si+roff+8+2] + push word ptr [si+roff+8] + push word ptr [di+coff+32+2] + push word ptr [di+coff+32] + call _FixedMul ;column 1 entry on this row times row 1 + ; entry in column + add sp,8 ;clear parameters from stack + pop cx ;restore low word of running total + add cx,ax ;running total for this row + adc bp,dx + + add cx,[si+roff+12] ;add in translation + add bp,[si+roff+12+2] + + pop bx ;restore DestXForm pointer + mov [bx+coff+roff],cx ;save the result in dest matrix + mov [bx+coff+roff+2],bp +coff=coff+4 ;point to next col in xform2 & dest + +roff=roff+16 ;point to next col in xform2 & dest + ENDM + + pop bp ;restore stack frame pointer endif ;USE386 - pop di ;restore register variables - pop si - pop bp ;restore stack frame -ret -_ConcatXforms endp -end + pop di ;restore register variables + pop si + pop bp ;restore stack frame + ret +_ConcatXforms endp + end ``` #### Shading @@ -1058,7 +1060,7 @@ void DrawPObject(PObject * ObjectToXform) ModelIntensity IntensityTemp; Point3 UnitNormal, *NormalStartpoint, *NormalEndpoint; long v1, v2, w1, w2; - Point Vertices[MAX-POLY-LENGTH]; + Point Vertices[MAX_POLY_LENGTH]; /* Draw each visible face (polygon) of the object in turn */ for (i=0; i ObjectToXform->EraseRect[NonDisplayedPage].Right) - if (Vertices[j].X < SCREEN-WIDTH) + if (Vertices[j].X < SCREEN_WIDTH) ObjectToXform->EraseRect[NonDisplayedPage].Right = Vertices[j].X; else ObjectToXform->EraseRect[NonDisplayedPage].Right = - SCREEN-WIDTH; + SCREEN_WIDTH; if (Vertices[j].Y > ObjectToXform->EraseRect[NonDisplayedPage].Bottom) - if (Vertices[j].Y < SCREEN-HEIGHT) + if (Vertices[j].Y < SCREEN_HEIGHT) ObjectToXform->EraseRect[NonDisplayedPage].Bottom = Vertices[j].Y; else ObjectToXform->EraseRect[NonDisplayedPage].Bottom= - SCREEN-HEIGHT; + SCREEN_HEIGHT; if (Vertices[j].X < ObjectToXform->EraseRect[NonDisplayedPage].Left) if (Vertices[j].X > 0) @@ -1116,18 +1118,18 @@ void DrawPObject(PObject * ObjectToXform) /* See if there's any shading */ if (FacePtr->ShadingType == 0) { /* No shading in effect, so just draw */ - DRAW-POLYGON(Vertices, NumVertices, FacePtr->ColorIndex, 0, 0); + DRAW_POLYGON(Vertices, NumVertices, FacePtr->ColorIndex, 0, 0); } else { /* Handle shading */ /* Do ambient shading, if enabled */ - if (AmbientOn && (FacePtr->ShadingType & AMBIENT-SHADING)) { + if (AmbientOn && (FacePtr->ShadingType & AMBIENT_SHADING)) { /* Use the ambient shading component */ IntensityTemp = AmbientIntensity; } else { - SET-INTENSITY(IntensityTemp, 0, 0, 0); + SET_INTENSITY(IntensityTemp, 0, 0, 0); } /* Do diffuse shading, if enabled */ - if (FacePtr->ShadingType & DIFFUSE-SHADING) { + if (FacePtr->ShadingType & DIFFUSE_SHADING) { /* Calculate the unit normal for this polygon, for use in dot products */ UnitNormal.X = NormalEndpoint->X - NormalStartpoint->X; @@ -1135,7 +1137,7 @@ void DrawPObject(PObject * ObjectToXform) UnitNormal.Z = NormalEndpoint->Z - NormalStartpoint->Z; /* Calculate the diffuse shading component for each active spotlight */ - for (Spot=0; Spot 0) { IntensityTemp.Red += FixedMul(SpotIntensity[Spot].Red, Diffusion); @@ -1161,7 +1163,7 @@ void DrawPObject(PObject * ObjectToXform) &IntensityTemp); /* Draw with the cumulative shading, converting from the general color representation to the best-match color index */ - DRAW-POLYGON(Vertices, NumVertices, + DRAW_POLYGON(Vertices, NumVertices, ModelColorToColorIndex(&ColorTemp), 0, 0); } } diff --git a/src/chapter-55.md b/src/chapter-55.md index b226edd..1780ce6 100644 --- a/src/chapter-55.md +++ b/src/chapter-55.md @@ -93,7 +93,7 @@ blue resolution, using the structure shown in Listing 55.1. **LISTING 55.1 L55-1.C** ```c -typedef struct -ModelColor { +typedef struct _ModelColor { unsigned char Red; /* 255 = max red, 0 = no red */ unsigned char Green; /* 255 = max green, 0 = no green */ unsigned char Blue; /* 255 = max blue, 0 = no blue */ @@ -451,9 +451,9 @@ but is considerably more difficult to apply. LineWidthBytes dw ? ;offset from one scan line to the next FontPtr dd ? ;pointer to font with which to draw SampleString label byte - db ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ' - db ‘abcdefghijklmnopqrstuvwxyz' - db ‘0123456789!@#$%^&*(),<.>/?;:',0 + db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + db 'abcdefghijklmnopqrstuvwxyz' + db '0123456789!@#$%^&*(),<.>/?;:',0 .code start: diff --git a/src/chapter-57.md b/src/chapter-57.md index 5e1ec87..7e61e13 100644 --- a/src/chapter-57.md +++ b/src/chapter-57.md @@ -210,7 +210,7 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge) be necessary to nudge the source start coordinates to the right by an amount corresponding to the distance from the the real (fixed-point) DestX and the first pixel (at an integer X) to be drawn). */ - DestWidth = INT-TO-FIXED(DestXMax - DestX); + DestWidth = INT_TO_FIXED(DestXMax - DestX); /* Calculate source steps that correspond to each dest X step (across the scan line) */ @@ -231,8 +231,8 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge) /* Clip left edge if necssary */ if (DestX < ClipMinX) { - SourceX += FixedMul(SourceStepX, INT-TO-FIXED(ClipMinX - DestX)); - SourceY += FixedMul(SourceStepY, INT-TO-FIXED(ClipMinX - DestX)); + SourceX += FixedMul(SourceStepX, INT_TO_FIXED(ClipMinX - DestX)); + SourceY += FixedMul(SourceStepY, INT_TO_FIXED(ClipMinX - DestX)); DestX = ClipMinX; } /* Scan across the destination scan line, updating the source image @@ -241,8 +241,8 @@ void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge) /* Get the currently mapped pixel out of the image and draw it to the screen */ WritePixelX(DestX, DestY, - GET-IMAGE-PIXEL(TexMapBits, TexMapWidth, - ROUND-FIXED-TO-INT(SourceX), ROUND-FIXED-TO-INT(SourceY)) ); + GET_IMAGE_PIXEL(TexMapBits, TexMapWidth, + ROUND_FIXED_TO_INT(SourceX), ROUND_FIXED_TO_INT(SourceY)) ); /* Point to the next source pixel */ SourceX += SourceStepX; SourceY += SourceStepY; @@ -305,17 +305,17 @@ so this is the appropriate place to optimize. ; void ScanOutLine(EdgeScan * LeftEdge, EdgeScan * RightEdge); ; Tested with TASM 3.0. -SC-INDEX equ 03c4h ;Sequence Controller Index -MAP-MASK equ 02h ;index in SC of Map Mask register -SCREEN-SEG equ 0a000h ;segment of display memory in mode X -SCREEN-WIDTH equ 80 ;width of screen in bytes from one scan line +SC_INDEX equ 03c4h ;Sequence Controller Index +MAP_MASK equ 02h ;index in SC of Map Mask register +SCREEN_SEG equ 0a000h ;segment of display memory in mode X +SCREEN_WIDTH equ 80 ;width of screen in bytes from one scan line ; to the next .model small .data - extrn -TexMapBits:word, -TexMapWidth:word, -DestY:word - extrn -CurrentPageBase:word, -ClipMinX:word - extrn -ClipMinY:word, -ClipMaxX:word, -ClipMaxY:word + extrn _TexMapBits:word, _TexMapWidth:word, _DestY:word + extrn _CurrentPageBase:word, _ClipMinX:word + extrn _ClipMinY:word, _ClipMaxX:word, _ClipMaxY:word ; Describes the current location and stepping, in both the source and ; the destination, of an edge. Mirrors structure in DRAWTEXP.C. @@ -360,28 +360,28 @@ lYAdvanceByOne equ -22 ;used to step source pointer 1 pixel ; incrementally in Y lYBaseAdvance equ -24 ;use to step source pointer minimum number of ; pixels incrementally in Y -LOCAL-SIZE equ 24 ;total size of local variables +LOCAL_SIZE equ 24 ;total size of local variables .code - extrn -FixedMul:near, -FixedDiv:near + extrn _FixedMul:near, _FixedDiv:near align 2 ToScanDone: jmp ScanDone - public -ScanOutLine + public _ScanOutLine align 2 --ScanOutLine proc near +_ScanOutLine proc near push bp ;preserve caller's stack frame mov bp,sp ;point to our stack frame - sub sp,LOCAL-SIZE ;allocate space for local variables + sub sp,LOCAL_SIZE ;allocate space for local variables push si ;preserve caller's register variables push di ; Nothing to do if destination is fully X clipped. mov di,[bp].RightEdge mov si,[di].DestX - cmp si,[-ClipMinX] + cmp si,[_ClipMinX] jle ToScanDone ;right edge is to left of clip rect, so done mov bx,[bp].LeftEdge mov dx,[bx].DestX - cmp dx,[-ClipMaxX] + cmp dx,[_ClipMaxX] jge ToScanDone ;left edge is to right of clip rect, so done sub si,dx ;destination fill width jle ToScanDone ;null or negative full width, so done @@ -406,7 +406,7 @@ ToScanDone: sbb dx,word ptr [bp].lSourceX+2 ;high word of source X width push dx ;push source X width, in fixedpoint form push ax - call -FixedDiv ;scale source X width to dest X width + call _FixedDiv ;scale source X width to dest X width add sp,8 ;clear parameters from stack mov word ptr [bp].lSourceStepX,ax ;remember source X step for mov word ptr [bp].lSourceStepX+2,dx ; 1-pixel destination X step @@ -434,11 +434,11 @@ SourceXNonNeg: sbb dx,word ptr [bp].lSourceY+2 ;high word of source Y height push dx ;push source Y height, in fixedpoint form push ax - call -FixedDiv ;scale source Y height to dest X width + call _FixedDiv ;scale source Y height to dest X width add sp,8 ;clear parameters from stack mov word ptr [bp].lSourceStepY,ax ;remember source Y step for mov word ptr [bp].lSourceStepY+2,dx ; 1-pixel destination X step - mov cx,[-TexMapWidth] ;assume source Y advances non-negative + mov cx,[_TexMapWidth] ;assume source Y advances non-negative and dx,dx ;which way does source Y advance? jns SourceYNonNeg ;non-negative neg cx ;negative @@ -450,7 +450,7 @@ SourceXNonNeg: SourceYNonNeg: mov [bp].lYAdvanceByOne,cx ;amount to add to source pointer to ; move by one in Y - mov ax,[-TexMapWidth] ;minimum distance skipped in source + mov ax,[_TexMapWidth] ;minimum distance skipped in source imul dx ; image bitmap when Y steps (ignoring mov [bp].lYBaseAdvance,ax ; carry from the fractional part) ; Advance 1/2 step in the stepping direction, to space scanned pixels evenly @@ -472,25 +472,25 @@ SourceYNonNeg: adc word ptr [bp].lSourceY+2,dx ; Clip right edge if necessary. mov si,[di].DestX - cmp si,[-ClipMaxX] + cmp si,[_ClipMaxX] jl RightEdgeClipped - mov si,[-ClipMaxX] + mov si,[_ClipMaxX] RightEdgeClipped: ; Clip left edge if necssary mov bx,[bp].LeftEdge mov di,[bx].DestX - cmp di,[-ClipMinX] + cmp di,[_ClipMinX] jge LeftEdgeClipped ; Left clipping is necessary; advance the source accordingly neg di - add di,[-ClipMinX] ;ClipMinX - DestX + add di,[_ClipMinX] ;ClipMinX - DestX ;first, advance the source in X push di ;push ClipMinX - DestX, in fixedpoint form sub ax,ax push ax ;push 0 as fractional part of ClipMinX-DestX push word ptr [bp].lSourceStepX+2 push word ptr [bp].lSourceStepX - call -FixedMul ;total source X stepping in clipped area + call _FixedMul ;total source X stepping in clipped area add sp,8 ;clear parameters from stack add word ptr [bp].lSourceX,ax;step the source X past clipping adc word ptr [bp].lSourceX+2,dx @@ -500,11 +500,11 @@ RightEdgeClipped: push ax ;push 0 as fractional part of ClipMinX-DestX push word ptr [bp].lSourceStepY+2 push word ptr [bp].lSourceStepY - call -FixedMul ;total source Y stepping in clipped area + call _FixedMul ;total source Y stepping in clipped area add sp,8 ;clear parameters from stack add word ptr [bp].lSourceY,ax;step the source Y past clipping adc word ptr [bp].lSourceY+2,dx - mov di,[-ClipMinX] ;start X coordinate in dest after clipping + mov di,[_ClipMinX] ;start X coordinate in dest after clipping LeftEdgeClipped: ; Calculate actual clipped destination drawing width. sub si,di @@ -515,26 +515,26 @@ LeftEdgeClipped: add word ptr [bp].lSourceY,8000h;add 0.5 mov ax,word ptr [bp].lSourceY+2 adc ax,0 - mul [-TexMapWidth] ;initial scan line in source image + mul [_TexMapWidth] ;initial scan line in source image add word ptr [bp].lSourceX,8000h;add 0.5 mov bx,word ptr [bp].lSourceX+2 ;offset into source scan line adc bx,ax ;initial source offset in source image - add bx,[-TexMapBits] ;DS:BX points to the initial image pixel + add bx,[_TexMapBits] ;DS:BX points to the initial image pixel ; Point to initial destination pixel. - mov ax,SCREEN-SEG + mov ax,SCREEN_SEG mov es,ax - mov ax,SCREEN-WIDTH - mul [-DestY] ;offset of initial dest scan line + mov ax,SCREEN_WIDTH + mul [_DestY] ;offset of initial dest scan line mov cx,di ;initial destination X shr di,1 shr di,1 ;X/4 = offset of pixel in scan line add di,ax ;offset of pixel in page - add di,[-CurrentPageBase] ;offset of pixel in display memory + add di,[_CurrentPageBase] ;offset of pixel in display memory ;ES:DI now points to the first destination pixel and cl,011b ;CL = pixel's plane - mov al,MAP-MASK - mov dx,SC-INDEX + mov al,MAP_MASK + mov dx,SC_INDEX out dx,al ;point the SC Index register to the Map Mask mov al,11h ;one plane bit in each nibble, so we'll get carry ; automatically when going from plane 3 to plane 0 @@ -558,7 +558,7 @@ SYStepSet: ; BX = pointer to initial image pixel ; SI = # of pixels to fill ; DI = pointer to initial destination pixel - mov dx,SC-INDEX+1 ;point to SC Data; Index points to Map Mask + mov dx,SC_INDEX+1 ;point to SC Data; Index points to Map Mask TexScanLoop: ; Set the Map Mask for this pixel's plane, then draw the pixel. out dx,al @@ -590,7 +590,7 @@ ScanDone: mov sp,bp ;deallocate local variables pop bp ;restore caller's stack frame ret --ScanOutLine endp +_ScanOutLine endp end ``` diff --git a/src/chapter-58.md b/src/chapter-58.md index 3b478f6..d38bb86 100644 --- a/src/chapter-58.md +++ b/src/chapter-58.md @@ -261,7 +261,7 @@ of *four* times faster than Listing 58.1.) ; ES:DI = pointer to initial destination pixel ; VGA set up to draw to the correct plane for this column - REPTLOOP_UNROLL + REPT LOOP_UNROLL ; Set the Map Mask for this pixel's plane, then draw the pixel. diff --git a/src/chapter-69.md b/src/chapter-69.md index d30f4b6..6dcc725 100644 --- a/src/chapter-69.md +++ b/src/chapter-69.md @@ -404,12 +404,12 @@ clear success. **LISTING 69.1 L69-1.C** ```c -// Quake's recursive subdivision triangle rasterizer; draws all -// pixels in a triangle other than the vertices by splitting an +// Quake's recursive subdivision triangle rasterizer; draws all +// pixels in a triangle other than the vertices by splitting an // edge to form a new vertex, drawing the vertex, and recursively // processing each of the two new triangles formed by using the // new vertex. Results are less accurate than from a precise -// affine or perspective texture mapper, and drawing boundaries +// affine or perspective texture mapper, and drawing boundaries // are not identical to those of a precise polygon drawer, although // they are consistent between adjacent polygons drawn with this // technique. @@ -418,103 +418,102 @@ clear success. void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3) { -int *temp; -int d; - -int new[6]; -int z; -short *zbuf; + int *temp; + int d; + int new[6]; + int z; + short *zbuf; // try to find an edge that's more than one pixel long in x or y -d = lp2[0] - lp1[0]; -if (d < -1 || d > 1) -goto split; -d = lp2[1] - lp1[1]; -if (d < -1 || d > 1) -goto split; -d = lp3[0] - lp2[0]; -if (d < -1 || d > 1) -goto split2; -d = lp3[1] - lp2[1]; -if (d < -1 || d > 1) -goto split2; -d = lp1[0] - lp3[0]; -if (d < -1 || d > 1) -goto split3; -d = lp1[1] - lp3[1]; -if (d < -1 || d > 1) -{ + d = lp2[0] - lp1[0]; + if (d < -1 || d > 1) + goto split; + d = lp2[1] - lp1[1]; + if (d < -1 || d > 1) + goto split; + d = lp3[0] - lp2[0]; + if (d < -1 || d > 1) + goto split2; + d = lp3[1] - lp2[1]; + if (d < -1 || d > 1) + goto split2; + d = lp1[0] - lp3[0]; + if (d < -1 || d > 1) + goto split3; + d = lp1[1] - lp3[1]; + if (d < -1 || d > 1) + { split3: -// shuffle points so first edge is edge to split -temp = lp1; -lp1 = lp3; -lp3 = lp2; -lp2 = temp; -goto split; -} + // shuffle points so first edge is edge to split + temp = lp1; + lp1 = lp3; + lp3 = lp2; + lp2 = temp; + goto split; + } -return; // no pixels left to fill in triangle + return; // no pixels left to fill in triangle split2: // shuffle points so first edge is edge to split -temp = lp1; -lp1 = lp2; -lp2 = lp3; -lp3 = temp; + temp = lp1; + lp1 = lp2; + lp2 = lp3; + lp3 = temp; split: // split first edge screen x, screen y, texture s, texture t, and z -// to form a new vertex. Lighting (index 4) is ignored; the -// difference between interpolating lighting and using the same -// shading for the entire triangle is unnoticeable for small -// triangles, so we just use the lighting for the first vertex of -// the original triangle (which was used during set-up to set +// to form a new vertex. Lighting (index 4) is ignored; the +// difference between interpolating lighting and using the same +// shading for the entire triangle is unnoticeable for small +// triangles, so we just use the lighting for the first vertex of +// the original triangle (which was used during set-up to set // d_colormap, used below to look up lit texels) -new[0] = (lp1[0] + lp2[0]) >> 1; // split screen x -new[1] = (lp1[1] + lp2[1]) >> 1; // split screen y -new[2] = (lp1[2] + lp2[2]) >> 1; // split texture s -new[3] = (lp1[3] + lp2[3]) >> 1; // split texture t -new[5] = (lp1[5] + lp2[5]) >> 1; // split z + new[0] = (lp1[0] + lp2[0]) >> 1; // split screen x + new[1] = (lp1[1] + lp2[1]) >> 1; // split screen y + new[2] = (lp1[2] + lp2[2]) >> 1; // split texture s + new[3] = (lp1[3] + lp2[3]) >> 1; // split texture t + new[5] = (lp1[5] + lp2[5]) >> 1; // split z // draw the point if splitting a leading edge -if (lp2[1] > lp1[1]) -goto nodraw; -if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) -goto nodraw; + if (lp2[1] > lp1[1]) + goto nodraw; + if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) + goto nodraw; -z = new[5]>>16; + z = new[5]>>16; -// point to the pixel's z-buffer entry, looking up the scanline start +// point to the pixel's z-buffer entry, looking up the scanline start // address based on screen y and adding in the screen x coordinate -zbuf = zspantable[new[1]] + new[0]; + zbuf = zspantable[new[1]] + new[0]; -// draw the split vertex if it's not obscured by something nearer, as +// draw the split vertex if it's not obscured by something nearer, as // indicated by the z-buffer -if (z >= *zbuf) -{ -int pix; - -// set the z-buffer to the new pixel's distance -*zbuf = z; - -// get the texel from the model's skin bitmap, according to -// the s and t texture coordinates, and translate it through -// the lighting look-up table set according to the first -// vertex for the original (top-level) triangle. Both s and -// t are in 16.16 format -pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; - -// draw the pixel, looking up the scanline start address -// based on screen y and adding in the screen x coordinate -d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; -} + if (z >= *zbuf) + { + int pix; + + // set the z-buffer to the new pixel's distance + *zbuf = z; + + // get the texel from the model's skin bitmap, according to + // the s and t texture coordinates, and translate it through + // the lighting look-up table set according to the first + // vertex for the original (top-level) triangle. Both s and + // t are in 16.16 format + pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; + + // draw the pixel, looking up the scanline start address + // based on screen y and adding in the screen x coordinate + d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; + } nodraw: -// recursively draw the two new triangles we created by adding the +// recursively draw the two new triangles we created by adding the // split vertex -D_PolysetRecursiveTriangle (lp3, lp1, new); -D_PolysetRecursiveTriangle (lp3, new, lp2); + D_PolysetRecursiveTriangle (lp3, lp1, new); + D_PolysetRecursiveTriangle (lp3, new, lp2); } ```