+++ /dev/null
-; Reconstructed Commander Keen 4-6 Source Code\r
-; Copyright (C) 2021 K1n9_Duk3\r
-;\r
-; This file is primarily based on:\r
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; EGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All EGA drawing routines that write out words need to have alternate forms\r
-; for starting on even and odd addresses, because writing a word at segment\r
-; offset 0xffff causes an exception! To work around this, write a single\r
-; byte out to make the address even, so it wraps cleanly at the end.\r
-;\r
-; All of these routines assume read/write mode 0, and will allways return\r
-; in that state.\r
-; The direction flag should be clear\r
-; readmap/writemask is left in an undefined state\r
-;\r
-;============================================================================\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 128,64,32,16,8,4,2,1\r
-\r
-CODESEG\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov bl,[BYTE color]\r
- xchg bl,[es:di] ; load latches and write pixel\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov bh,[BYTE color]\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov bl,bh\r
- xchg bl,[es:di] ; load latches and write pixel\r
- add di,dx\r
-\r
- loop @@plot\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov [ss:screendest],di ;screen destination\r
-\r
- mov bx,[linewidth]\r
- dec bx\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
- mov cx,4 ;planes to draw\r
- mov ah,0001b ;map mask\r
-\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-@@planeloop:\r
- WORDOUT\r
- shl ah,1 ;shift plane mask over for next plane\r
-\r
- mov di,[ss:screendest] ;start at same place in all planes\r
-\r
-REPT 7\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
-\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 10\r
-\r
-\r
-maskroutines dw mask0,mask0,mask1E,mask1E,mask2E,mask2O,mask3E,mask3O\r
- dw mask4E,mask4O,mask5E,mask5O,mask6E,mask6O\r
- dw mask7E,mask7O,mask8E,mask8O,mask9E,mask9O\r
- dw mask10E,mask10O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,[wide]\r
- mov [linedelta],dx ;amount to add after drawing each line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
- mov [routinetouse],OFFSET generalmask\r
- jmp NEAR @@startloop\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,[maskroutines+di] ;call the right routine\r
- mov [routinetouse],ax\r
-\r
-@@startloop:\r
- mov ds,[segm]\r
-\r
-@@drawplane:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- mov si,[ofs] ;start back at the top of the mask\r
- mov di,[dest] ;start at same place in all planes\r
- mov cx,[height] ;scan lines to draw\r
- mov dx,[ss:linedelta]\r
-\r
- jmp [ss:routinetouse] ;draw one plane\r
-planereturn: ;routine jmps back here\r
-\r
- add bx,[ss:planesize] ;start of mask = start of next plane\r
-\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- jne @@drawplane\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
-generalmask:\r
- mov dx,cx\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
- jmp planereturn\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- lodsb\r
- and al,[es:di]\r
- or al,[bx+si-1]\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- lodsw\r
- and ax,[es:di]\r
- or ax,[bx+si-2]\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- jmp planereturn\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask1E:\r
- MASKBYTE\r
- SPRITELOOP mask1E\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask3E:\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask3E\r
-\r
-EVEN\r
-mask3O:\r
- MASKBYTE\r
- MASKWORD\r
- SPRITELOOP mask3O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask5E:\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask5E\r
-\r
-EVEN\r
-mask5O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask5O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask7E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask7E\r
-\r
-EVEN\r
-mask7O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask7O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask9E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask9E\r
-\r
-EVEN\r
-mask9O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask9O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_InverseMask\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_InverseMask segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_InverseMask\r
-USES SI,DI\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+16*256 ;set function = OR\r
- WORDOUT\r
-\r
- mov es, [screenseg]\r
- mov ax, [wide]\r
- mov dx, [linewidth]\r
- sub dx, ax;\r
- mov ds, [segm]\r
- mov si, [ofs]\r
- mov di, [dest]\r
- mov bx, [height]\r
-@@yloop:\r
- mov cx, [wide]\r
-@@xloop:\r
- lodsb\r
- not al\r
- xchg al, [es:di]\r
- inc di\r
- loop @@xloop\r
- add di, dx\r
- dec bx\r
- jnz @@yloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+0*256 ;set function = no change\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; using write mode 1 (sets it and returns with write mode 0). bufferofs is\r
-; NOT accounted for.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- pushf\r
- cli\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- popf\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-\r
-@@lineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; with four planes of width by height data, and draws it to dest in the\r
-; virtual screen, based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even video address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEE:\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne eventoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOE:\r
- mov cx,[wide]\r
- rep movsw\r
- movsb ;copy the last byte\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- dec [wide] ;one word has to be handled seperately\r
-EOplaneloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
- movsb\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne EOplaneloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoodd\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- mov ax,GC_READMAP ;read map for plane 0\r
-\r
- xor di,di\r
-\r
-@@planeloop:\r
- mov dx,GC_INDEX\r
- WORDOUT\r
-\r
- mov si,[source] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- inc ah\r
- cmp ah,4 ;done all four planes?\r
- jne @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VWL_UpdateScreenBlocks\r
-;\r
-; Scans through the update matrix and copies any areas that have changed\r
-; to the visable screen, then zeros the update array\r
-;\r
-;============================================================================\r
-\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to end of bufferblocks\r
-\r
-PROC VWL_UpdateScreenBlocks\r
-PUBLIC VWL_UpdateScreenBlocks\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- mov dx,GC_INDEX ; restore write mode 0\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- xor ax,ax ; clear out the update matrix\r
- mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
- mov di,[updateptr]\r
- rep stosw\r
-\r
- ret\r
-\r
-@@realstart:\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- mov di,[updateptr] ; start of floating update screen\r
- mov bp,di\r
- add bp,UPDATEWIDE*UPDATEHIGH+1 ; when di = bp, all tiles have been scanned\r
-\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- jae @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,2\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,bx ; offset to next line on screen\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
- rep movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
- rep movsb\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC EGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;=================\r
-;\r
-; VWL_WaitRetrace\r
-;\r
-;=================\r
-\r
-DATASEG\r
-\r
-EXTRN TimeCount :DWORD\r
-EXTRN jerk :WORD\r
-EXTRN nopan :WORD\r
-\r
-CODESEG\r
-\r
-PROC VWL_WaitRetrace NEAR\r
- mov dx,STATUS_REGISTER_1\r
- mov bx,[WORD TimeCount]\r
-@@waitloop:\r
- sti\r
- jmp $+2\r
- cli\r
-\r
- in al,dx\r
- test al,8\r
- jnz @@done\r
- mov ax,[WORD TimeCount]\r
- sub ax,bx\r
- cmp ax,1\r
- jbe @@waitloop\r
-\r
-@@done:\r
- ret\r
-ENDP\r
-\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD, pel:WORD\r
-PUBLIC VW_SetScreen\r
-\r
-if waitforvbl\r
-\r
- mov dx,STATUS_REGISTER_1\r
-\r
-;\r
-; wait util the CRTC just starts scaning a diplayed line to set the CRTC start\r
-;\r
- cli\r
-\r
-@@waitnodisplay:\r
- in al,dx\r
- test al,01b\r
- jz @@waitnodisplay\r
-\r
-@@waitdisplay:\r
- in al,dx\r
- test al,01b\r
- jnz @@waitdisplay\r
-\r
-endif\r
-\r
-;\r
-; set CRTC start\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
- test [jerk],1\r
- jz @@l3\r
- call VWL_WaitRetrace\r
-\r
-@@l3:\r
- test [nopan],1\r
- jnz @@l4\r
-;\r
-; set horizontal panning\r
-;\r
-\r
- mov dx,ATR_INDEX\r
- mov al,ATR_PELPAN or 20h\r
- out dx,al\r
- jmp $+2\r
- mov al,[BYTE pel] ;pel pan value\r
- out dx,al\r
-\r
-@@l4:\r
- test [jerk],1\r
- jnz @@done\r
- call VWL_WaitRetrace\r
-\r
-@@done:\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-\r
-BUFFWIDTH = 50\r
-BUFFHEIGHT = 32 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-PUBLIC bufferwidth,bufferheight,screenspot\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; BufferToScreen\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the EGA screen in the current write mode\r
-;\r
-;========================\r
-\r
-PROC BufferToScreen NEAR\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
-@@lineloop:\r
- mov cx,[bufferwidth] ;bytes to copy\r
-@@byteloop:\r
- lodsb ;get a byte from the buffer\r
- xchg [es:di],al ;load latches and store back to screen\r
- inc di\r
-\r
- loop @@byteloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
- ret\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop4\r
- ret\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop5\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
-\r
-; set xor/or mode\r
- mov dx,GC_INDEX\r
- mov al,GC_DATAROTATE\r
- mov ah,[pdrawmode]\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
-; set AND mode to punch out the mask\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 8*256\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set OR mode to fill in the color\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 16*256\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r