; ; Command & Conquer Red Alert(tm) ; Copyright 2025 Electronic Arts Inc. ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ; ;*************************************************************************** ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** ;*************************************************************************** ;* * ;* Project Name : Command & Conquer * ;* * ;* File Name : KEYFBUFF.ASM * ;* * ;* Programmer : David R. Dettmer * ;* * ;* Start Date : March 3, 1995 * ;* * ;* Last Update : * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* Buffer_Frame_To_Page -- Copies a linear buffer to a virtual viewport * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ;********************** Model & Processor Directives *********************** IDEAL P386 MODEL USE32 FLAT ;******************************** Includes ********************************* INCLUDE "gbuffer.inc" ;******************************** Equates ********************************** TRUE equ 1 ; Boolean 'true' value FALSE equ 0 ; Boolean 'false' value ;*=========================================================================*/ ;* The following are defines used to control what functions are linked * ;* in for Buffer_Frame_To_Page. * ;*=========================================================================*/ ;USE_NORMAL EQU TRUE ;USE_HORZ_REV EQU TRUE ;USE_VERT_REV EQU TRUE ;USE_SCALING EQU TRUE FLAG_NORMAL EQU 0 FLAG_TRANS EQU 1 FLAG_GHOST EQU 2 FLAG_FADING EQU 4 FLAG_PREDATOR EQU 8 FLAG_MASK EQU 0Fh SHAPE_NORMAL EQU 0000h ; Standard shape ;SHAPE_HORZ_REV EQU 0001h ; Flipped horizontally ;SHAPE_VERT_REV EQU 0002h ; Flipped vertically ;SHAPE_SCALING EQU 0004h ; Scaled (WORD scale_x, WORD scale_y) ;SHAPE_VIEWPORT_REL EQU 0010h ; Coords are window-relative ;SHAPE_WIN_REL EQU 0010h ; Coordinates are window relative instead of absolute. SHAPE_CENTER EQU 0020h ; Coords are based on shape's center pt SHAPE_TRANS EQU 0040h ; has transparency SHAPE_FADING EQU 0100h ; Fading effect (VOID * fading_table, ; WORD fading_num) SHAPE_PREDATOR EQU 0200h ; Transparent warping effect ;SHAPE_COMPACT EQU 0400h ; Never use this bit ;SHAPE_PRIORITY EQU 0800h ; Use priority system when drawing SHAPE_GHOST EQU 1000h ; Shape is drawn ghosted ;SHAPE_SHADOW EQU 2000h SHAPE_PARTIAL EQU 4000h ;SHAPE_COLOR EQU 8000h ; Remap the shape's colors ; (VOID * color_table) ; ;.......................... Shadow Effect .................................. ; SHADOW_COL EQU 00FFh ; magic number for shadows ;......................... Priority System ................................. ; CLEAR_UNUSED_BITS EQU 0007h ; and with 0000-0111 to clear ; non-walkable high bit and ; scaling id bits NON_WALKABLE_BIT EQU 0080h ; and with 1000-0000 to clear all ; but non-walkable bit ; ;......................... Predator Effect ................................. ; ;PRED_MASK EQU 0007h ; mask used for predator pixel puts PRED_MASK EQU 000Eh ; mask used for predator pixel puts ;--------------------------------------------------------------------------- ; ; Use a macro to make code a little cleaner. ; The parameter varname is optional. ; Syntax to use macro is : ; WANT equ expression ; USE func [,varname] ; If the 'varname' is defined, a table declaration is created like: ; GLOBAL TableName:DWORD ; Then, the table entry is created: ; If WANT is true, the table entry is created for the given function: ; varname DD func ; If WANT is not TRUE, a Not_Supported entry is put in the table: ; varname DD Not_Supported ; The resulting tables look like: ; ; GLOBAL ExampTable:DWORD ; ExampTable DD routine1 ; DD routine2 ; DD routine3 ; ... ; Thus, each table is an array of function pointers. ; ;--------------------------------------------------------------------------- MACRO USE func, varname IF WANT varname DD func ELSE varname DD Not_Supported ENDIF ENDM ; IFNB ; GLOBAL varname:DWORD ; ENDIF ;--------------------------------------------------------------------------- DATASEG ;--------------------------------------------------------------------------- ; Predator effect variables ;--------------------------------------------------------------------------- ; make table for negative offset and use the used space for other variables BFPredNegTable DW -1, -3, -2, -5, -2, -4, -3, -1 ; 8 words below calculated DW 0, 0, 0, 0, 0, 0, 0, 0 ; index ffffff00 DD 0, 0, 0, 0 ; index ffffff10 BFPredOffset DD 0, 0, 0, 0 ; index ffffff20 DD 0, 0, 0, 0 ; index ffffff30 ; partially faded predator effect value BFPartialPred DD 0, 0, 0, 0 ; index ffffff40 BFPartialCount DD 0, 0, 0, 0 ; index ffffff50 DD 0, 0, 0, 0 ; index ffffff60 DD 0, 0, 0, 0 ; index ffffff70 DD 0, 0, 0, 0 ; index ffffff80 DD 0, 0, 0, 0 ; index ffffff90 DD 0, 0, 0, 0 ; index ffffffa0 DD 0, 0, 0, 0 ; index ffffffb0 DD 0, 0, 0, 0 ; index ffffffc0 DD 0, 0, 0, 0 ; index ffffffd0 DD 0, 0, 0, 0 ; index ffffffe0 DD 0, 0, 0, 0 ; index fffffff0 BFPredTable DW 1, 3, 2, 5, 2, 3, 4, 1 ;BFPredTable DB 1, 3, 2, 5, 4, 3, 2, 1 CODESEG ;--------------------------------------------------------------------------- ; Code Segment Tables: ; This code uses the USE macro to set up tables of function addresses. ; The tables have the following format: ; Tables defined are: ; BufferFrameTable ;--------------------------------------------------------------------------- WANT equ USE BF_Copy, BufferFrameTable WANT equ USE BF_Trans WANT equ USE BF_Ghost WANT equ USE BF_Ghost_Trans WANT equ USE BF_Fading WANT equ USE BF_Fading_Trans WANT equ USE BF_Ghost_Fading WANT equ USE BF_Ghost_Fading_Trans WANT equ USE BF_Predator WANT equ USE BF_Predator_Trans WANT equ USE BF_Predator_Ghost WANT equ USE BF_Predator_Ghost_Trans WANT equ USE BF_Predator_Fading WANT equ USE BF_Predator_Fading_Trans WANT equ USE BF_Predator_Ghost_Fading WANT equ USE BF_Predator_Ghost_Fading_Trans ;--------------------------------------------------------------------------- global _Int3:near proc _Int3 near int 3 ret endp ;*************************************************************************** ;* VVC::TOPAGE -- Copies a linear buffer to a virtual viewport * ;* * ;* INPUT: WORD x_pixel - x pixel on viewport to copy from * ;* WORD y_pixel - y pixel on viewport to copy from * ;* WORD pixel_width - the width of copy region * ;* WORD pixel_height - the height of copy region * ;* BYTE * src - buffer to copy from * ;* VVPC * dest - virtual viewport to copy to * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: Coordinates and dimensions will be adjusted if they exceed * ;* the boundaries. In the event that no adjustment is * ;* possible this routine will abort. If the size of the * ;* region to copy exceeds the size passed in for the buffer * ;* the routine will automatically abort. * ;* * ;* HISTORY: * ;* 06/15/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Buffer_Frame_To_Page:NEAR PROC Buffer_Frame_To_Page C near USES eax,ebx,ecx,edx,esi,edi ;*=================================================================== ;* define the arguements that our function takes. ;*=================================================================== ARG x_pixel :DWORD ; x pixel position in source ARG y_pixel :DWORD ; y pixel position in source ARG pixel_width :DWORD ; width of rectangle to blit ARG pixel_height:DWORD ; height of rectangle to blit ARG src :DWORD ; this is a member function ARG dest :DWORD ; what are we blitting to ARG flags :DWORD ; flags passed ;*=================================================================== ; Define some locals so that we can handle things quickly ;*=================================================================== LOCAL IsTranslucent :DWORD ; ptr to the is_translucent table LOCAL Translucent :DWORD ; ptr to the actual translucent table LOCAL FadingTable :DWORD ; extracted fading table pointer LOCAL FadingNum :DWORD ; get the number of times to fade LOCAL StashECX :DWORD ; temp variable for ECX register LOCAL jflags :DWORD ; flags used to goto correct buff frame routine LOCAL BufferFrameRout :DWORD ; ptr to the buffer frame routine LOCAL jmp_loc :DWORD ; calculated jump location LOCAL loop_cnt :DWORD LOCAL x1_pixel :DWORD LOCAL y1_pixel :DWORD LOCAL scr_x :DWORD LOCAL scr_y :DWORD LOCAL dest_adjust_width :DWORD LOCAL scr_adjust_width :DWORD cmp [ src ] , 0 jz ??real_out ;==================================================================== ; Pull off optional arguments: ; EDI is used as an offset from the 'flags' parameter, to point ; to the optional argument currently being processed. ;==================================================================== ??do_args: mov edi , 4 ; optional params start past flags mov [ jflags ] , 0 ; clear jump flags ??check_centering: ;------------------------------------------------------------------- ; See if we need to center the frame ;------------------------------------------------------------------- test [ flags ] , SHAPE_CENTER ; does this need to be centered? je ??check_trans ; if not the skip over this stuff mov eax , [ pixel_width ] mov ebx , [ pixel_height ] sar eax , 1 sar ebx , 1 sub [ x_pixel ] , eax sub [ y_pixel ] , ebx ??check_trans: test [ flags ] , SHAPE_TRANS jz ??check_ghost or [ jflags ] , FLAG_TRANS ;-------------------------------------------------------------------- ; SHAPE_GHOST: DWORD is_translucent tbl ;-------------------------------------------------------------------- ??check_ghost: test [ flags ] , SHAPE_GHOST ; are we ghosting this shape jz ??check_fading mov eax , [ flags + edi ] or [ jflags ] , FLAG_GHOST mov [ IsTranslucent ] , eax ; save ptr to is_trans. tbl add eax , 0100h ; add 256 for first table add edi , 4 ; next argument mov [ Translucent ] , eax ; save ptr to translucent tbl ;-------------------------------------------------------------------- ; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count ;-------------------------------------------------------------------- ??check_fading: test [ flags ] , SHAPE_FADING ; are we fading this shape jz ??check_predator mov eax , [ flags + edi ] mov [ FadingTable ] , eax ; save address of fading tbl mov eax , [ flags + edi + 4 ] ; get fade num or [ jflags ] , FLAG_FADING and eax , 03fh ; no need for more than 63 add edi , 8 ; next argument cmp eax , 0 ; check if it's 0 jnz ??set_fading ; if not, store fade num and [ flags ] , NOT SHAPE_FADING ; otherwise, don't fade ??set_fading: mov [ FadingNum ] , eax ;-------------------------------------------------------------------- ; SHAPE_PREDATOR: DWORD init_pred_lookup_offset (0-7) ;-------------------------------------------------------------------- ??check_predator: test [ flags ] , SHAPE_PREDATOR ; is predator effect on jz ??check_partial mov eax , [ flags + edi ] ; pull the partial value or [ jflags ] , FLAG_PREDATOR shl eax , 1 cmp eax , 0 jge ??check_range neg eax mov ebx , -1 and eax , PRED_MASK ; keep entries within bounds mov bl , al mov eax , ebx ; will be ffffff00-ffffff07 jmp ??pred_cont ??check_range: and eax , PRED_MASK ; keep entries within bounds ??pred_cont: add edi , 4 ; next argument mov [ BFPredOffset ] , eax mov [ BFPartialCount ] , 0 ; clear the partial count mov [ BFPartialPred ] , 100h ; init partial to off ??pred_neg_init: mov esi , [ dest ] ; get ptr to dest mov ebx, 7 * 2 ??pred_loop: movzx eax , [ WORD PTR BFPredNegTable + ebx ] add eax , [ (GraphicViewPort esi) . GVPWidth ] ; add width add eax , [ (GraphicViewPort esi) . GVPXAdd ] ; add x add mov [ WORD PTR BFPredNegTable + 16 + ebx ] , ax dec ebx dec ebx jge ??pred_loop ;-------------------------------------------------------------------- ; SHAPE_PARTIAL: DWORD partial_pred_value (0-255) ;-------------------------------------------------------------------- ??check_partial: test [ flags ] , SHAPE_PARTIAL ; is this a partial pred? jz ??setupfunc mov eax , [ flags + edi ] ; pull the partial value add edi , 4 ; next argument and eax , 0ffh ; make sure 0-255 mov [ BFPartialPred ] , eax ; store it off ??setupfunc: mov ebx , [ jflags ] ; load flags value and ebx , FLAG_MASK ; clip high bits add ebx , ebx ; mult by 4 to get DWORD offset add ebx , ebx mov ebx , [ BufferFrameTable + ebx ] ; get table value mov [ BufferFrameRout ] , ebx ; store it in the function pointer ; Clip dest Rectangle against source Window boundaries. mov [ scr_x ] , 0 mov [ scr_y ] , 0 mov esi , [ dest ] ; get ptr to dest xor ecx , ecx xor edx , edx mov edi , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register mov ebx , [ x_pixel ] mov eax , [ x_pixel ] add ebx , [ pixel_width ] shld ecx , eax , 1 mov [ x1_pixel ] , ebx inc edi shld edx , ebx , 1 sub eax , edi sub ebx , edi shld ecx , eax , 1 shld edx , ebx , 1 mov edi,[ ( GraphicViewPort esi) . GVPHeight ] ; get height into register mov ebx , [ y_pixel ] mov eax , [ y_pixel ] add ebx , [ pixel_height ] shld ecx , eax , 1 mov [ y1_pixel ] , ebx inc edi shld edx , ebx , 1 sub eax , edi sub ebx , edi shld ecx , eax , 1 shld edx , ebx , 1 xor cl , 5 xor dl , 5 mov al , cl test dl , cl jnz ??real_out or al , dl jz ??do_blit test cl , 1000b jz ??dest_left_ok mov eax , [ x_pixel ] neg eax mov [ x_pixel ] , 0 mov [ scr_x ] , eax ??dest_left_ok: test cl , 0010b jz ??dest_bottom_ok mov eax , [ y_pixel ] neg eax mov [ y_pixel ] , 0 mov [ scr_y ] , eax ??dest_bottom_ok: test dl , 0100b jz ??dest_right_ok mov eax , [ (GraphicViewPort esi) . GVPWidth ] ; get width into register mov [ x1_pixel ] , eax ??dest_right_ok: test dl , 0001b jz ??do_blit mov eax , [ (GraphicViewPort esi) . GVPHeight ] ; get width into register mov [ y1_pixel ] , eax ??do_blit: cld mov eax , [ (GraphicViewPort esi) . GVPXAdd ] add eax , [ (GraphicViewPort esi) . GVPWidth ] mov edi , [ (GraphicViewPort esi) . GVPOffset ] mov ecx , eax mul [ y_pixel ] add edi , [ x_pixel ] add edi , eax add ecx , [ x_pixel ] sub ecx , [ x1_pixel ] mov [ dest_adjust_width ] , ecx mov esi , [ src ] mov eax , [ pixel_width ] sub eax , [ x1_pixel ] add eax , [ x_pixel ] mov [ scr_adjust_width ] , eax mov eax , [ scr_y ] mul [ pixel_width ] add eax , [ scr_x ] add esi , eax mov edx , [ y1_pixel ] mov eax , [ x1_pixel ] sub edx , [ y_pixel ] jle ??real_out sub eax , [ x_pixel ] jle ??real_out jmp [ BufferFrameRout ] ; buffer frame to viewport routine ??real_out: ret ; ******************************************************************** ; Forward bitblit only ; the inner loop is so efficient that ; the optimal consept no longer apply because ; the optimal byte have to by a number greather than 9 bytes ; ******************************************************************** BF_Copy: cmp eax , 10 jl ??forward_loop_bytes ??forward_loop_dword: mov ecx , edi mov ebx , eax neg ecx and ecx , 3 sub ebx , ecx rep movsb mov ecx , ebx shr ecx , 2 rep movsd mov ecx , ebx and ecx , 3 rep movsb add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??forward_loop_dword ret ??forward_loop_bytes: mov ecx , eax rep movsb add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx ; decrement the height jnz ??forward_loop_bytes ret ;******************************************************************** ;******************************************************************** BF_Trans: ; calc the code location to skip to 10 bytes per REPT below!!!! mov ecx , eax and ecx , 01fh lea ecx , [ ecx + ecx * 4 ] ; quick multiply by 5 neg ecx shr eax , 5 lea ecx , [ ??trans_reference + ecx * 2 ] ; next multiply by 2 mov [ loop_cnt ] , eax mov [ jmp_loc ] , ecx ??trans_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ; the following code should NOT be changed without changing the calculation ; above!!!!!! ??trans_line: REPT 32 local trans_pixel mov bl , [ esi ] inc esi test bl , bl jz trans_pixel mov [ edi ] , bl trans_pixel: inc edi ENDM ??trans_reference: dec ecx jge ??trans_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??trans_loop ret ;******************************************************************** ;******************************************************************** BF_Ghost: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??ghost_reference - ??ghost_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??ghost_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??ghost_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??ghost_line: REPT 32 local store_pixel mov al , [ esi ] inc esi mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je store_pixel and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al store_pixel: mov [ edi ] , al inc edi ENDM ??ghost_reference: dec ecx jge ??ghost_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??ghost_loop ret ;******************************************************************** ;******************************************************************** BF_Ghost_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??ghost_t_reference - ??ghost_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??ghost_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??ghost_t_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??ghost_t_line: REPT 32 local transp_pixel local store_pixel mov al , [ esi ] inc esi test al , al jz transp_pixel mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je store_pixel and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al store_pixel: mov [ edi ] , al transp_pixel: inc edi ENDM ??ghost_t_reference: dec ecx jge ??ghost_t_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??ghost_t_loop ret ;******************************************************************** ;******************************************************************** BF_Fading: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??fading_reference - ??fading_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??fading_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??fading_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later mov ebx , [ FadingTable ] ; run color through fading table jmp [ jmp_loc ] ??fading_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??fading_line: REPT 32 local fade_loop mov al , [ esi ] inc esi mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop mov [ edi ] , al inc edi ENDM ??fading_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??fading_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??fading_loop ret ;******************************************************************** ;******************************************************************** BF_Fading_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??fading_t_reference - ??fading_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??fading_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??fading_t_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later mov ebx , [ FadingTable ] ; run color through fading table jmp [ jmp_loc ] ??fading_t_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??fading_t_line: REPT 32 local transp_pixel local fade_loop mov al , [ esi ] inc esi test al , al jz transp_pixel mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop mov [ edi ] , al transp_pixel: inc edi ENDM ??fading_t_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??fading_t_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??fading_t_loop ret ;******************************************************************** ;******************************************************************** BF_Ghost_Fading: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??ghost_f_reference - ??ghost_f_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??ghost_f_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??ghost_f_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??ghost_f_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??ghost_f_line: REPT 32 local store_pixel local do_fading local fade_loop mov al , [ esi ] inc esi mov ebx , [ IsTranslucent ] ; is it a lucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je do_fading and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the lation table ; ((_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (_color * 256) of the lation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al ; DRD jmp store_pixel do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop store_pixel: mov [ edi ] , al inc edi ENDM ??ghost_f_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??ghost_f_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??ghost_f_loop ret ;******************************************************************** ;******************************************************************** BF_Ghost_Fading_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??ghost_f_t_reference - ??ghost_f_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??ghost_f_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??ghost_f_t_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??ghost_f_t_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??ghost_f_t_line: REPT 32 local transp_pixel local store_pixel local do_fading local fade_loop mov al , [ esi ] inc esi test al , al jz transp_pixel mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je do_fading and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al ; DRD jmp store_pixel do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop store_pixel: mov [ edi ] , al transp_pixel: inc edi ENDM ??ghost_f_t_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??ghost_f_t_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??ghost_f_t_loop ret ;******************************************************************** ;******************************************************************** BF_Predator: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_reference - ??predator_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??predator_line: REPT 32 local get_pred local skip_pixel mov al , [ esi ] inc esi mov ebx , [ BFPartialCount ] add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp skip_pixel get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address ; xor bh , bh ; mov eax , [ BFPredValue ] ; pick up a color offset a pseudo- ; ; random amount from the current ; mov [ BFPartialCount ] , ebx ; mov al , [ edi + eax ] ; viewport address mov [ edi ] , al skip_pixel: inc edi ENDM ??predator_reference: dec ecx jge ??predator_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_t_reference - ??predator_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_t_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??predator_t_line: REPT 32 local trans_pixel local get_pred local store_pixel mov al , [ esi ] inc esi test al , al jz trans_pixel mov ebx , [ BFPartialCount ] add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp store_pixel get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address store_pixel: mov [ edi ] , al trans_pixel: inc edi ENDM ??predator_t_reference: dec ecx jge ??predator_t_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_t_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Ghost: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_g_reference - ??predator_g_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_g_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_g_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??predator_g_line: REPT 32 local get_pred local check_ghost local store_pixel mov al , [ esi ] mov ebx , [ BFPartialCount ] inc esi add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp check_ghost get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address check_ghost: mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je store_pixel and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al store_pixel: mov [ edi ] , al inc edi ENDM ??predator_g_reference: dec ecx jge ??predator_g_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_g_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Ghost_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_g_t_reference - ??predator_g_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_g_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_g_t_loop: mov ecx , [ loop_cnt ] jmp [ jmp_loc ] ??predator_g_t_line: REPT 32 local trans_pixel local get_pred local check_ghost local store_pixel mov al , [ esi ] inc esi test al , al jz trans_pixel mov ebx , [ BFPartialCount ] add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp check_ghost get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address check_ghost: mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je store_pixel and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al store_pixel: mov [ edi ] , al trans_pixel: inc edi ENDM ??predator_g_t_reference: dec ecx jge ??predator_g_t_line add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_g_t_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Fading: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_f_reference - ??predator_f_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_f_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_f_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??predator_f_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??predator_f_line: REPT 32 local get_pred local do_fading local fade_loop mov al , [ esi ] mov ebx , [ BFPartialCount ] inc esi add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp do_fading get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop mov [ edi ] , al inc edi ENDM ??predator_f_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??predator_f_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_f_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Fading_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_f_t_reference - ??predator_f_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_f_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_f_t_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??predator_f_t_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??predator_f_t_line: REPT 32 local trans_pixel local get_pred local do_fading local fade_loop mov al , [ esi ] inc esi test al , al jz trans_pixel mov ebx , [ BFPartialCount ] add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp do_fading get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop mov [ edi ] , al trans_pixel: inc edi ENDM ??predator_f_t_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??predator_f_t_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_f_t_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Ghost_Fading: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_g_f_reference - ??predator_g_f_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_g_f_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_g_f_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??predator_g_f_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??predator_g_f_line: REPT 32 local get_pred local check_ghost local store_pixel local do_fading local fade_loop mov al , [ esi ] mov ebx , [ BFPartialCount ] inc esi add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp check_ghost get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address check_ghost: mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je do_fading and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al ; DRD jmp store_pixel do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop store_pixel: mov [ edi ] , al inc edi ENDM ??predator_g_f_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??predator_g_f_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_g_f_loop ret ;******************************************************************** ;******************************************************************** BF_Predator_Ghost_Fading_Trans: mov ebx , eax ; width ; NOTE: the below calculation assumes a group of instructions is ; less than 256 bytes ; get length of the 32 groups of instructions lea ecx , [ ??predator_g_f_t_reference - ??predator_g_f_t_line ] shr ebx , 5 ; width / 32 shr ecx , 5 ; length of instructions / 32 and eax , 01fh ; mod of width / 32 mul cl ; calc offset to start of group neg eax ; inverse of width mov [ loop_cnt ] , ebx ; save width / 32 lea ecx , [ ??predator_g_f_t_reference + eax ] mov eax , 0 mov [ jmp_loc ] , ecx ??predator_g_f_t_loop: mov ecx , [ loop_cnt ] mov [ StashECX ] , ecx ; preserve ecx for later jmp [ jmp_loc ] ??predator_g_f_t_line_begin: mov [ StashECX ] , ecx ; preserve ecx for later ??predator_g_f_t_line: REPT 32 local trans_pixel local get_pred local check_ghost local store_pixel local do_fading local fade_loop mov al , [ esi ] inc esi test al , al jz trans_pixel mov ebx , [ BFPartialCount ] add ebx , [ BFPartialPred ] or bh , bh jnz get_pred ; is this a predator pixel? mov [ BFPartialCount ] , ebx jmp check_ghost get_pred: xor bh , bh mov eax, [ BFPredOffset ] mov [ BFPartialCount ] , ebx add [ BYTE PTR BFPredOffset ] , 2 movzx eax , [ WORD PTR BFPredTable + eax ] and [ BYTE PTR BFPredOffset ] , PRED_MASK ; pick up a color offset a pseudo- ; random amount from the current movzx eax , [ BYTE PTR edi + eax ] ; viewport address check_ghost: mov ebx , [ IsTranslucent ] ; is it a translucent color? mov bh , [ BYTE PTR ebx + eax ] cmp bh , 0ffh je do_fading and ebx , 0FF00h ; clear all of ebx except bh ; we have the index to the translation table ; ((trans_colour * 256) + dest colour) mov al , [ edi ] ; mov pixel at destination to al add ebx , [ Translucent ] ; get the ptr to it! ; Add the (trans_color * 256) of the translation equ. mov al , [ BYTE PTR ebx + eax ] ; get new pixel in al ; DRD jmp store_pixel do_fading: mov ebx , [ FadingTable ] ; run color through fading table mov ecx , [ FadingNum ] fade_loop: mov al, [BYTE PTR ebx + eax] dec ecx jnz fade_loop store_pixel: mov [ edi ] , al trans_pixel: inc edi ENDM ??predator_g_f_t_reference: mov ecx , [ StashECX ] ; restore ecx for main draw loop dec ecx jge ??predator_g_f_t_line_begin add esi , [ scr_adjust_width ] add edi , [ dest_adjust_width ] dec edx jnz ??predator_g_f_t_loop ret ;******************************************************************** ;******************************************************************** Not_Supported: ret ENDP Buffer_Frame_To_Page END ;*************************************************************************** ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** ;*************************************************************************** ;* * ;* Project Name : Westwood Library * ;* * ;* File Name : KEYFBUFF.ASM * ;* * ;* Programmer : Phil W. Gorrow * ;* * ;* Start Date : July 16, 1992 * ;* * ;* Last Update : October 2, 1994 [JLB] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* BUFFER_FRAME_TO_LOGICPAGE -- * ;* Normal_Draw -- Function that writes a normal pixel line * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * IDEAL P386 IDEAL_MODE EQU 1 INCLUDE "wwlib.i" ;------------------------------------------------------------------- ; Extern all the library variables that this module requires ;------------------------------------------------------------------- EXTRN C MaskPage:WORD EXTRN C BackGroundPage:WORD ;------------------------------------------------------------------- ; Define all the equates that this module requires ;------------------------------------------------------------------- WIN_X EQU 0 ; offset for the x coordinate WIN_Y EQU 2 ; offset for the y coordinate WIN_WIDTH EQU 4 ; offset for the window width WIN_HEIGHT EQU 6 ; offset for the window height BYTESPERROW EQU 320 ; number of bytes per row FLAG_NORMAL EQU 0 ; flag for normal draw FLAG_GHOST EQU 1 ; This flag enables the ghost FLAG_PRIORITY_TRANS EQU 2 ; flag for priority and transparent FLAG_TRANS EQU 4 ; flag for transparent draw FLAG_PRIORITY EQU 8 ; flag for priority draw ; fx on the above flags FLAG_MASK EQU 15 ; used to and of uneeded bits SHAPE_NORMAL EQU 0000h ; Standard shape. ;SHAPE_HORZ_REV EQU 0001h ; Flipped horizontally. ;SHAPE_VERT_REV EQU 0002h ; Flipped vertically. ;SHAPE_SCALING EQU 0004h ; Scaled (WORD scale_x, WORD scale_y) SHAPE_WIN_REL EQU 0010h ; Coordinates are window relative instead of absolute. SHAPE_CENTER EQU 0020h ; Coordinates are based on shape's center point. SHAPE_TRANS EQU 0040h ; has transparency ;SHAPE_FADING EQU 0100h ; Fading effect active (VOID * fading_table, WORD fading_num). ;SHAPE_PREDATOR EQU 0200h ; Transparent warping effect. ;SHAPE_COMPACT EQU 0400h ; Never use this bit. SHAPE_PRIORITY EQU 0800h ; Use priority system when drawing. SHAPE_GHOST EQU 1000h ; Transluscent table process. ;SHAPE_SHADOW EQU 2000h ; ???? ;SHAPE_PARTIAL EQU 4000h ; ???? ;SHAPE_COLOR EQU 8000h ; Remap the shape's colors (VOID * color_table). ; MBL MOD 12.1.92 CLEAR_NON_WALK_BIT_AND_SCALE_BITS EQU 7 ; Makes it one AND per pixel in Priority_Trans display CLEAR_NON_WALK_BIT EQU 7fh ; and with 0111-1111 to clear non-walkable high bit CLEAR_SCALE_BITS EQU 87h ; and with 1000-0111 to clear scaling id bits NON_WALKABLE_BIT EQU 80h ; and with 1000-0000 to clear all but non-walkable bit ; END MBL MOD CODESEG ; 1 = GHOST (all odd entrys are prefixed with Ghost_) ; 2 = BLAAAH ; 4 = Trans (prfx) ; 8 = Prior (prfx) ;--------------------------------------------------------------------------- ; Define the table of different line draw types ;--------------------------------------------------------------------------- LineTable DW WSA_Normal_Draw ;0 DW Ghost_Normal_Draw ;1 DW 0 ;2 DW 0 ;3 DW Transparent_Draw ;4 DW Ghost_Transparent_Draw ;5 DW 0 ;6 DW 0 ;7 DW Priority_Draw ;8 DW Ghost_Priority_Draw ;9 DW 0 ;10 DW 0 ;11 DW Priority_Transparent_Draw ;12 DW Ghost_Priority_Transparent_Draw ;13 DW 0 ;14 DW 0 ;15 ;*************************************************************************** ;* BUFFER_FRAME_TO_LOGICPAGE -- * ;* * ;* * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 07/16/1992 PWG : Created. * ;*=========================================================================* PUBLIC C Buffer_Frame_To_LogicPage PROC C Buffer_Frame_To_LogicPage FAR USES ax bx ecx dx ds esi es edi ;------------------------------------------------------------------- ; Define the arguements that our program takes. ;------------------------------------------------------------------- ARG x_pixel:WORD ; x pixel position to draw at ARG y_pixel:WORD ; y pixel position to draw at ARG pixel_w:WORD ; pixel width of draw region ARG pixel_h:WORD ; pixel height of draw region ARG win:WORD ; window to clip around ARG flags:WORD ; flags that this routine will take ARG buffer:DWORD ; pointer to the buffer with data ARG args:WORD ;------------------------------------------------------------------- ; Define the local variables that our program uses ;------------------------------------------------------------------- LOCAL IsTranslucent:DWORD ; ptr to the is_translucent table LOCAL Translucent:DWORD ; ptr to the actual translucent table LOCAL win_x1:WORD ; clip window left x pixel position LOCAL win_x2:WORD ; clip window right x pixel position LOCAL win_y1:WORD ; clip window top y pixel position LOCAL win_y2:WORD ; clip window bottom y pixel position LOCAL clipleft:WORD ; number of pixels to clip on left LOCAL clipright:WORD ; number of pixels to clip on right LOCAL nextline:WORD ; offset to the next line LOCAL putmiddle:WORD ; routine to call to put the middle LOCAL maskpage:WORD ; location of the depth masks LOCAL background:WORD ; location of the background data LOCAL jflags:WORD ; location of the background data LOCAL priority:BYTE ; the priority level of the back push fs xor ecx,ecx ;-------------------------------------------------------------------- ; Check to see if we have supplied any GHOST tables. ;-------------------------------------------------------------------- push di mov di,6 mov [jflags],0 ??ghost: test [flags],SHAPE_GHOST ; are we ghosting this shape jz short ??no_ghost ; if not then skip and do more or [jflags],FLAG_GHOST les ax,[DWORD PTR buffer + di] ; get the "are we really translucent?" table mov [WORD PTR IsTranslucent],ax mov [WORD PTR IsTranslucent + 2],es add ax,0100h ; add to offset for tables ; get the "ok we are translucent!!" table mov [WORD PTR Translucent],ax mov [WORD PTR Translucent + 2],es add di,4 ??no_ghost: pop di ;------------------------------------------------------------------- ; See if we need to center the frame ;------------------------------------------------------------------- test [flags],SHAPE_CENTER ; does this need to be centered? je short ??no_centering ; if not the skip over this stuff mov ax,[pixel_w] mov bx,[pixel_h] sar ax,1 sar bx,1 sub [x_pixel],ax sub [y_pixel],bx ??no_centering: mov ax,[flags] and ax,SHAPE_PRIORITY+SHAPE_TRANS cmp ax,SHAPE_PRIORITY+SHAPE_TRANS jne short ??test_trans or [jflags],FLAG_PRIORITY_TRANS jmp short ??priority ;------------------------------------------------------------------- ; Get the trans information if we need to get it ;------------------------------------------------------------------- ??test_trans: test [flags],SHAPE_TRANS ; does this draw use transparencies? je short ??test_priority ; if not the skip over this junk or [jflags],FLAG_TRANS ??test_priority: ;------------------------------------------------------------------- ; Get the priority information if we need to get it ;------------------------------------------------------------------- test [flags],SHAPE_PRIORITY ; does this draw use priorities? je short ??no_priority ; if not the skip over this junk or [jflags],FLAG_PRIORITY ??priority: mov ax,[BackGroundPage] ; get the background page from ds mov [background],ax ; and store it on the stack mov ax,[MaskPage] ; get the mask page from ds mov [maskpage],ax ; and store it on the stack mov ax,[WORD PTR buffer + 4]; get the priority level from args mov [priority],al ; and store it in a local ;------------------------------------------------------------------- ; Get the draw routine that we are going to draw with ;------------------------------------------------------------------- ??no_priority: ; mov bx,[flags] ; load in the current flags byte ; and bx,FLAG_MASK ; prevent lockup on bad value mov bx,[jflags] ; load in the jump table flags shl bx,1 mov ax,[WORD PTR LineTable + bx] ; get the offset of the skip table mov [putmiddle],ax ; store off the new offset ;------------------------------------------------------------------- ; Get a pointer to the logic page to where we will draw our buffer ;------------------------------------------------------------------- push [LogicPage] ; push the current logic page call FAR PTR Get_Page ; get the physical page address add sp,2 ; pull the parameter from the stack mov es,dx ; store the address in the dest ;-------------------------------------------------------------------- ; Point DI to the beginning of the window that we need to look at. ; that way we can access all of the info through di. ;-------------------------------------------------------------------- mov si,OFFSET WindowList ; get the offset of the window list mov cl,4 ; shift 3 times = multiply by 16 mov ax,[win] ; get the window number we are using shl ax,cl ; each window is 8 words long add si,ax ; add that into the offset of window ;-------------------------------------------------------------------- ; Place all the clipping values on the stack so our function will ; be truly re-entrant and will not need to shadow these values. ;-------------------------------------------------------------------- mov cl,3 ; to convert x to pixel mult by 8 mov ax,[si + WIN_X] ; get the left clip position shl ax,cl ; convert to a pixel x position mov [win_x1],ax ; store the left edge of window mov [win_x2],ax mov ax,[si + WIN_WIDTH] ; get the width of the window shl ax,cl ; convert to a pixel width add [win_x2],ax ; add to get the right window edge mov ax,[si + WIN_Y] ; get the win y coordinate to clip mov [win_y1],ax ; and save it onto the stack add ax,[si + WIN_HEIGHT] ; calculate the bottom win y coord mov [win_y2],ax ; and save it onto the stack test [flags],SHAPE_WIN_REL ; is this window relative? je short ??get_buffer ; if not the skip over mov ax,[win_x1] ; get left edge of window add [x_pixel],ax ; add to x pixel position mov ax,[win_y1] ; get top edge of window add [y_pixel],ax ; add to y pixel position ;-------------------------------------------------------------------- ; Get a pointer to the source buffer so we can handle the clipping ;-------------------------------------------------------------------- ??get_buffer: lds si,[buffer] ; get a pointer to the buffer ;-------------------------------------------------------------------- ; Check the top of our shape and clip any lines that are necessary ;-------------------------------------------------------------------- mov ax,[y_pixel] ; get the y_pixel draw position sub ax,[win_y1] ; subtract out the window y top jns short ??check_bottom ; skip if y below window top add ax,[pixel_h] ; add in the height of the region jg short ??clip_top ; if positive then clip top lines ??jump_exit: jmp ??exit ; otherwise completely clipped ??clip_top: xchg [pixel_h],ax sub ax,[pixel_h] add [y_pixel],ax mul [pixel_w] ; convert to number of bytes to skip add si,ax ; skip past the necessary bytes ;-------------------------------------------------------------------- ; Check the bottom of our shape and clip it if necessary ;-------------------------------------------------------------------- ??check_bottom: mov ax,[win_y2] ; get the bottom y of the window sub ax,[y_pixel] ; subtract of the y to draw at js ??jump_exit ; if its signed then nothing to draw jz ??jump_exit ; if its zero then nothing to draw cmp ax,[pixel_h] ; if more room to draw then height jae short ??clip_x_left ; then go check the left clip mov [pixel_h],ax ; clip all but amount that will fit ??clip_x_left: mov [clipleft],0 ; clear clip on left of region mov ax,[x_pixel] ; get the pixel x of draw region sub ax,[win_x1] ; pull out the window coordinate jns short ??clip_x_right neg ax ; negate to get amnt to skip in buf mov [clipleft],ax ; store it in the left clip info add [x_pixel],ax ; move to the edge of the window sub [pixel_w],ax ; pull it out of the pixel width ??clip_x_right: mov [clipright],0 ; clear clip on right of region mov ax,[win_x2] ; get the window x of clip region sub ax,[x_pixel] ; subtract the draw edge of region js ??jump_exit ; if its negative then get out jz ??jump_exit ; if its zero then get out cmp ax,[pixel_w] ; is space available larger than w jae short ??draw_prep ; if so then go get drawing xchg [pixel_w],ax ; amt to draw in pixel_w (wid in ax) sub ax,[pixel_w] ; pull out the amount to draw mov [clipright],ax ; this is the amount to clip on right ??draw_prep: push si ; save off source pos in buffer push ds ; both offset and segment mov ax,@data mov ds,ax mov bx,[y_pixel] shl bx,1 ; shift left by 1 for word table look lds si,[YTable] ; get the address of the ytable mov di,[ds:si+bx] ; look up the multiplied value pop ds ; restore source pos in buffer pop si ; both offset and segment add di,[x_pixel] ; add in the x pixel position mov [nextline],di ; save it off in the next line ;-------------------------------------------------------------------- ; Now determine the type of the shape and process it in the proper ; way. ;-------------------------------------------------------------------- mov dx,[pixel_h] ; Check to see if the WSA is the screen width and there is no ; clipping. In this case, then a special single call to the ; line processing routine is possible. mov ax,[clipleft] add ax,[clipright] jne short ??top_of_loop cmp [pixel_w],BYTESPERROW jne short ??top_of_loop ;------------------------------------ ; The width of the WSA is the screen width, so just process as ; one large WSA line. mov ax,BYTESPERROW imul dx mov cx,ax call [putmiddle] jmp short ??exit ;------------------------------------ ; Process line by line. ??top_of_loop: add si,[clipleft] ; skip whats necessary on left edge mov cx,[pixel_w] ; get the width we need to draw ; Copy the source to the destination as appropriate. This routine can ; trash AX, BX, CX, and DI. It must properly modify SI to point one byte past ; the end of the data. call [putmiddle] add si,[clipright] ; skip past the left clip add [nextline],BYTESPERROW mov di,[nextline] dec dx jnz ??top_of_loop ??exit: pop fs ret ENDP ;*************************************************************************** ;* NORMAL_DRAW -- Function that writes a normal pixel line * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;*=========================================================================* PROC NOLANGUAGE WSA_Normal_Draw NEAR IF 1 ; This version is marginally faster than the later version. mov ax,cx shr cx,2 rep movsd and ax,011b mov cx,ax shr cx,1 rep movsw adc cx,cx rep movsb ret ELSE shr cx,1 ; convert to words (odd pix in carry) rep movsw ; write out the needed words adc cx,0 ; add the carry into cx rep movsb ; write out the odd byte if any ret ENDIF ENDP ;*************************************************************************** ;* TRANSPARENT_DRAW -- Function that writes a transparent pixel line * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;* 10/02/1994 JLB : Optimized for 250% speed improvement. * ;*=========================================================================* PROC NOLANGUAGE Transparent_Draw NEAR IF 1 ; Preserve DX since it is used as a scratch register. push dx ??loop: ; Swap DS:SI and ES:DI back in preparation for the REP SCASB ; instruction. xchg di,si mov dx,es mov ax,ds mov ds,dx mov es,ax ; Remember the bytes remaining in order to calculate the position ; of the scan when it stops. mov bx,cx ; Scan looking for a non-zero value in the source buffer. xor al,al repe scasb ; When the loop ends, if the EQ flag is set then the scanning is ; complete. Jump to the end of the routine in order to fixup the ; pointers. je short ??fini ; Advance the destination pointer by the amount necessary to match ; the source movement. DS:SI points to where data should be written. add si,bx inc cx ; SCASB leaves CX one too low, fix it. dec di ; SCASB leaves DI one byte too far, fix it. sub si,cx ; Scan for the duration of non-zero pixels. This yields a count which ; is used to copy the source data to the destination. Preserve DI. mov dx,di mov bx,cx repne scasb mov di,dx ; Set BX to equal the number of bytes to copy from source to dest. inc cx ; SCASB leaves CX one too low, fix it. sub bx,cx ; Move the data from ES:DI to DS:SI for BX bytes. xchg cx,bx ; Make CX=bytes to move, BX=bytes remaining. ; Swap DS:SI and ES:DI in preparation for the REP MOV instruction. xchg di,si mov dx,es mov ax,ds mov ds,dx mov es,ax ; Move the data from source to dest. First try to move double ; words. Then copy the remainder bytes (if any). Putting jumps in ; this section doesn't result in any savings -- oh well. mov ax,cx shr cx,2 rep movsd and ax,0011b mov cx,ax shr cx,1 rep movsw adc cx,cx rep movsb ; Restore CX with the remaining bytes to process. mov cx,bx ; If there are more bytes to process, then loop back. or cx,cx jne short ??loop ??fini: ; Swap ES:DI and DS:SI back to original orientation. mov ax,ds mov bx,es mov es,ax mov ds,bx xchg di,si ; Restore DX and return. pop dx ret ELSE ??loop_top: lodsb or al,al jz short ??skip mov [es:di],al ; store the pixel to the screen ??skip: inc di loop ??loop_top ret ENDIF ENDP ;*************************************************************************** ;* PRIORITY_DRAW -- Function that writes a pixels if they are in front of * ;* the given plate. * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;* 12/01/1992 MBL : Updated to work with latest mask data encoding. * ;* 17/01/1993 MCC : Updated for 386, and optimized * ;*=========================================================================* PROC NOLANGUAGE Priority_Draw NEAR mov fs,[background] ; get the SEG of the background page mov gs,[maskpage] ; get the SEG of the mask info mov ah,[priority] ; keep a copy of priority varible for faster cmp ??loop_top: lodsb ; get the pixel to draw on the screen ; get the mask byte for our pixel mov bl,[ds:di] ; get rid of non-walkable bit and ; get rid of scaling id bits and bl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS cmp ah,bl ; are we more toward the front? jge short ??out_pixel ; if so then write the pixel mov al,[fs:di] ; get the pixel to write ??out_pixel: stosb ; write the pixel and inc the DI loop ??loop_top ret ENDP ;*************************************************************************** ;* PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they are * ;* in front of the given plate. It also deals with * ;* transparent pixels. * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;* 12/01/1992 MBL : Updated to work with latest mask data encoding. * ;* 17/01/1993 MCC : Updated for 386, and optimized * ;*=========================================================================* PROC NOLANGUAGE Priority_Transparent_Draw NEAR mov fs,[background] ; get the SEG of the background page mov gs,[maskpage] ; get the SEG of the mask info mov ah,[priority] ; keep a copy of priority varible for faster cmp ??loop_top: lodsb ; get the pixel on the screen or al,al ; check to see if al is transparent je short ??write_back ; if it is go write background mov bl,[gs:di] ; get the mask byte for our pixel ; get rid of non-walkable bit and ; get rid of scaling id bits and bl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS cmp ah,bl ; are we more toward the front? jge short ??out_pixel ; if so then write the pixel ??write_back: mov al,[fs:di] ; get the pixel to write ??out_pixel: stosb ; write the pixel loop ??loop_top ret ENDP ;*************************************************************************** ;* GHOST_NORMAL_DRAW -- Function that writes a normal pixel line * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 05/27/1993 MCC : Created. * ;*=========================================================================* PROC NOLANGUAGE Ghost_Normal_Draw NEAR ??loop_top: lodsb ;--- ; Ok, find out if the colour is a Translucent colour push ax push ds lds bx,[IsTranslucent] mov ah,al ; preserve real pixel xlat ; get new al (transluecent pixel xchg ah,al ; get real pixel back into AL just in case cmp ah,255 je short ??normal_pixel ; is it a translucent ? ; if we get passed here value in ; AH should be 0-15 ; yes, it is a translucent colour so goto our translucent translation ; table and set up a ptr to the correct table mov al,[es:di] ; mov pixel at destination to al and we have ; the index to the translation table ; ((trans_colour * 256) + dest colour) lds bx,[Translucent] ; get the ptr to it! add bh,ah ; Add the (trans_color * 256) of the translation equ. ; XLAT only uses AL so no need to clear AH xlat ; get new pixel in AL ??normal_pixel: pop ds pop bx mov ah,bh ;--- mov [es:di],al ; store the pixel to the screen ??skip: inc di loop ??loop_top ret ENDP ;*************************************************************************** ;* GHOST_TRANSPARENT_DRAW -- Function that writes a transparent pixel line * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 05/27/1993 MCC : Created. * ;*=========================================================================* PROC NOLANGUAGE Ghost_Transparent_Draw NEAR ??loop_top: lodsb or al,al jz short ??skip ;--- ; Ok, find out if the colour is a Translucent colour push ax push ds lds bx,[IsTranslucent] mov ah,al ; preserve real pixel xlat ; get new al (transluecent pixel xchg ah,al ; get real pixel back into AL just in case cmp ah,255 je short ??normal_pixel ; is it a translucent ? ; if we get passed here value in ; AH should be 0-15 ; yes, it is a translucent colour so goto our translucent translation ; table and set up a ptr to the correct table mov al,[es:di] ; mov pixel at destination to al and we have ; the index to the translation table ; ((trans_colour * 256) + dest colour) lds bx,[Translucent] ; get the ptr to it! add bh,ah ; Add the (trans_color * 256) of the translation equ. ; XLAT only uses AL so no need to clear AH xlat ; get new pixel in AL ??normal_pixel: pop ds pop bx mov ah,bh ;--- mov [es:di],al ; store the pixel to the screen ??skip: inc di loop ??loop_top ret ENDP ;*************************************************************************** ;* GHOST_PRIORITY_DRAW -- Function that writes a pixels if they are in fron* ;* the given plate. * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;* 12/01/1992 MBL : Updated to work with latest mask data encoding. * ;* 05/27/1993 MCC : Updated to use the new Ghosting fx * ;* 17/01/1993 MCC : Updated for 386, and optimized * ;*=========================================================================* PROC NOLANGUAGE Ghost_Priority_Draw NEAR mov fs,[background] ; get the SEG of the background page mov gs,[maskpage] ; get the SEG of the mask info mov ah,[priority] ; keep a copy of priority varible for faster cmp ??loop_top: lodsb ; get the pixel to draw on the screen ; get the mask byte for our pixel mov bl,[ds:di] ; get rid of non-walkable bit and ; get rid of scaling id bits and bl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS cmp ah,bl ; are we more toward the front? jge short ??out_pixel ; if so then write the pixel mov al,[fs:di] ; get the pixel to write ??out_pixel: stosb ; write the pixel and inc the DI loop ??loop_top ret ENDP ;*************************************************************************** ;* GHOST_PRIORITY_TRANSPARENT_DRAW -- Function that writes a pixels if they* ;* in front of the given plate. It also deals with * ;* transparent pixels. * ;* * ;* INPUT: cx - number of pixels to write * ;* ds:si - buffer which holds the pixels to write * ;* es:di - place to put the pixels we are writing * ;* * ;* OUTPUT: ds:si - points to next pixel past last pixel read * ;* es:di - points to next pixel past last pixel written * ;* * ;* WARNINGS: none * ;* * ;* HISTORY: * ;* 07/17/1992 PWG : Created. * ;* 12/01/1992 MBL : Updated to work with latest mask data encoding. * ;* 05/27/1993 MCC : Updated to use the new Ghosting fx * ;* 17/01/1993 MCC : Updated for 386, and optimized * ;*=========================================================================* PROC NOLANGUAGE Ghost_Priority_Transparent_Draw NEAR mov fs,[background] ; get the SEG of the background page mov gs,[maskpage] ; get the SEG of the mask info mov ah,[priority] ; keep a copy of priority varible for faster cmp ??loop_top: lodsb ; get the pixel on the screen or al,al ; check to see if al is transparent je short ??write_back ; if it is go write background mov bl,[gs:di] ; get the mask byte for our pixel ; get rid of non-walkable bit and ; get rid of scaling id bits and bl,CLEAR_NON_WALK_BIT_AND_SCALE_BITS cmp ah,bl ; are we more toward the front? jge short ??out_pixel ; if so then write the pixel ??write_back: mov al,[fs:di] ; get the pixel to write ??out_pixel: stosb ; write the pixel loop ??loop_top ret ENDP END