Initial commit of Command & Conquer Red Alert source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:15:05 +00:00
parent b685cea758
commit 5e733d5dcc
2082 changed files with 797727 additions and 0 deletions

194
WWFLAT32/SVGAPRIM/MAKEFILE Normal file
View File

@@ -0,0 +1,194 @@
#
# 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 <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 27 , 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WWFLAT = your root WWFLAT path *
#* WWVCS = root directory for wwlib version control archive *
#* WATCOM = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WWFLAT
!error WWFLAT Environment var not configured.
!endif
!ifndef %WWVCS
!error WWVCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = svgaprim
PROJ_DIR = $(%WWFLAT)\$(PROJ_NAME)
LIB_DIR = $(%WWFLAT)\lib
!include $(%WWFLAT)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
vesa.obj &
vclear.obj &
vgetpix.obj &
vputpix.obj &
vtobuff.obj &
vtopage.obj &
vlbtove.obj &
vvetolb.obj &
vvblit.obj &
vtxtprnt.obj &
vscltove.obj &
vvetoscl.obj &
vscale.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(%WWFLAT)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WWFLAT)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WWFLAT)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WWFLAT)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WWFLAT)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $<
.asm.obj: $(%WWFLAT)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WWFLAT\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.h $(%WWFLAT)\include
copy *.inc $(%WWFLAT)\include
copy *.cpp $(%WWFLAT)\srcdebug
copy *.asm $(%WWFLAT)\srcdebug
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,77 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : SVGAPRIM.INC *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : December 8, 1994 *
;* *
;* Last Update : December 8, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
; Externs from VIDEO.CPP module of the VIDEO library
GLOBAL BankTable :DWORD
GLOBAL VesaFunc :DWORD
GLOBAL XRes :DWORD
GLOBAL YRes :DWORD
GLOBAL CurrentMode :DWORD
global cpu_video_page :dword
global cpu_page_limit :dword
; Externs from VESA.ASM module of the SVGAPRIM library
GLOBAL Vesa_Asm_Set_Win :NEAR
GLOBAL Vesa_Asm_Next_Win :NEAR
; Externs from VGETPIX.ASM module of the SVGA/MCGAPRIM library
GLOBAL Vesa_Get_Pixel :NEAR
; Externs from VPUTTPIX.ASM module of the SVGA/MCGAPRIM library
GLOBAL Vesa_Put_Pixel :NEAR
; Externs from VCLEAR.ASM module of the MCGA/SVGAPRIM library
GLOBAL Vesa_Clear :NEAR
; Externs from VBITBLIT.ASM module of the MCGA/SVGAPRIM library
GLOBAL Linear_Blit_To_Vesa :NEAR
GLOBAL Vesa_Blit_To_Linear :NEAR
GLOBAL Vesa_Blit_To_Vesa :NEAR
; Externs from VTOBUFF.ASM module of the SVGA/MCGAPRIM library
GLOBAL Vesa_To_Buffer :NEAR
; Externs from VTOPAGE.ASM module of the SVGA/MCGAPRIM library
GLOBAL Vesa_Buffer_To_Page :NEAR
; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library
GLOBAL Linear_Scale_To_Vesa :NEAR
GLOBAL Vesa_Scale_To_Linear :NEAR
GLOBAL Vesa_Scale_To_Vesa :NEAR
; Externs from VSCALE.ASM module of the SVGA/MCGAPRIM library
GLOBAL Vesa_Print :NEAR

View File

@@ -0,0 +1,171 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Clear the Full Mcga Screen *
;* *
;* File Name : CLEAR.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : August 23, 1994 [SKB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVPC::Clear -- Clears a virtual viewport instance *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
CODESEG
PROC Vesa_Clear C near
USES eax,ebx,ecx,edx,esi,edi
ARG this:DWORD ; this is a member function
ARG color:BYTE ; what color should we clear to
cld ; always go forward
mov ebx,[this] ; get a pointer to viewport
mov esi,[(GraphicViewPort ebx).GVPXAdd] ; esi = add for each line
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
push esi
mov edx,[(GraphicViewPort ebx).GVPHeight] ; ecx = height of viewport
mov esi,[(GraphicViewPort ebx).GVPWidth] ; edx = width of viewport
;*===================================================================
; Convert the color byte to a DWORD for fast storing
;*===================================================================
mov al,[color] ; get color to clear to
mov ah,al ; extend across WORD
mov ecx,eax ; extend across DWORD in
shl eax,16 ; several steps
mov ax,cx
Call Vesa_Asm_Set_Win ; set the window
;*===================================================================
; Find out if we should bother to align the row.
;*===================================================================
??row_by_row_aligned:
cmp esi , OPTIMAL_BYTE_COPY ; is it worth aligning them?
jl ??row_by_row ; if not then skip
;*===================================================================
; Now that we have the alignment offset copy each row
;*===================================================================
??aligned_loop:
lea ebx , [ edi + esi ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??in_range
xor ecx , ecx
mov ebx , esi
cmp edi , 0b0000h
jge ??no_trailing
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep stosb
??no_trailing:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
mov ecx , ebx
rep stosb
add edi , [ esp ]
dec edx ; decrement the height
jnz ??aligned_loop ; if more to do than do it
pop eax
ret
??in_range:
mov ecx , edi
mov ebx , esi
neg ecx
and ecx , 3
sub ebx , ecx
rep stosb
mov ecx , ebx
shr ecx , 2
rep stosd
mov ecx , ebx
and ecx , 3
rep stosb
add edi , [ esp ]
dec edx ; decrement the height
jnz ??aligned_loop ; if more to do than do it
pop eax
ret
;*===================================================================
; If not enough bytes to bother aligning copy each line across a byte
; at a time.
;*===================================================================
??row_by_row:
lea ebx , [ edi + esi ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , esi
jl ??in_range_bytes
xor ecx , ecx
mov ebx , esi
cmp edi , 0b0000h
jge ??no_trailing_bytes
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep stosb
??no_trailing_bytes:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
??in_range_bytes:
mov ecx , ebx
rep stosb
add edi , [ esp ]
dec edx ; decrement the height
jnz ??row_by_row ; if more to do than do it
pop eax
ret
ENDP Vesa_Clear
END

144
WWFLAT32/SVGAPRIM/VESA.ASM Normal file
View File

@@ -0,0 +1,144 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : VESA.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : December 8, 1994 *
;* *
;* Last Update : December 8, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Vesa_Asm_Set_Win -- Sets the current vesa window from Asm *
;* Vesa_Asm_Next_Window -- Sets to the next vesa window *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
GLOBAL RMVesaVector : DWORD
GLOBAL RMVesaRegs : DWORD
DPMI_INTR EQU 31h
STRUC DPMI_REGS
_edi dd ?
_esi dd ?
_ebp dd ?
dd ?
_ebx dd ?
_edx dd ?
_ecx dd ?
_eax dd ?
Flags dw ?
_es dw ?
_ds dw ?
_fs dw ?
_gs dw ?
_ip dw ?
_cs dw ?
_sp dw ?
_ss dw ?
dd ?
ENDS
DATASEG
cpu_video_page dd 0h
cpu_page_limit dd 0b0000h
CurrentBank DD 0h ; current vesa bank
RealFunc DPMI_REGS ? ; structure to call a real mode int
CODESEG
;***************************************************************************
;* VESA_ASM_SET_WIN -- Sets the current vesa window from Asm *
;* *
;* INPUT: edi - offset to set the window for *
;* *
;* OUTPUT: edi - adjusted offset for window *
;* *
;* PROTO: void Vesa_Asm_Set_Win(void); *
;* *
;* HISTORY: *
;* 12/08/1994 PWG : Created. *
;*=========================================================================*
PROC Vesa_Asm_Set_Win C near
push eax
push edi
push ecx
push ebx
mov eax , edi
and eax , 0ffff0000h
add eax , 010000h
mov [ cpu_page_limit ] , eax
lea eax , [ edi - 0a0000h ]
and eax , 0ffff0000h
mov [ cpu_video_page ] , eax
shr eax , 14
cmp eax , [ CurrentBank ]
jz ??no_change
mov [CurrentBank],eax ; it will be new current bank
mov ebx , [ BankTable + eax ] ; find gran value of new bank
mov edi , [ RMVesaRegs ] ; clean up RMRegister bank
xor eax , eax
mov ecx , 34h / 4 ; size of RMRegs Bank
rep stosd
mov edi , [ RMVesaRegs ]
mov [(type DPMI_REGS ptr edi ) . _eax ] , 04f05h
mov [(type DPMI_REGS ptr edi ) . _ebx ] , 0
mov [(type DPMI_REGS ptr edi ) . _edx ] , ebx
mov eax , 0300h
xor ecx , ecx ; set amount to copy of stack
mov ebx , [ RMVesaVector] ; set pointer to func to call
int DPMI_INTR ; make the call
??no_change:
pop ebx
pop ecx
pop edi
pop eax
and edi,0000ffffh ; adjust edi to be 64k
add edi,0a0000h
ret
ENDP Vesa_Asm_Set_Win
END

View File

@@ -0,0 +1,116 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Clear the Full Mcga Screen *
;* *
;* File Name : GETPIXEL.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 7, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GVPC::Get_Pixel -- Gets a pixel from the current graphic view port *
;* VVPC::Get_Pixel -- Gets a pixel from the current view port *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
CODESEG
;***************************************************************************
;* VVPC::GET_PIXEL -- Gets a pixel from the current view port *
;* *
;* INPUT: WORD the x pixel on the screen. *
;* WORD the y pixel on the screen. *
;* *
;* OUTPUT: UBYTE the pixel at the specified location *
;* *
;* WARNING: If pixel is to be placed outside of the viewport then *
;* this routine will abort. *
;* *
;* HISTORY: *
;* 06/07/1994 PWG : Created. *
;*=========================================================================*
PROC Vesa_Get_Pixel C near
USES ebx,ecx,edx,edi
ARG this:DWORD ; this is a member function
ARG x_pixel:DWORD ; x position of pixel to set
ARG y_pixel:DWORD ; y position of pixel to set
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[this] ; get a pointer to viewport
xor eax,eax
mov edi,[(VideoViewPort ebx).VIVPOffset] ; get the correct offset
mov ecx,[(VideoViewPort ebx).VIVPHeight] ; edx = height of viewport
mov edx,[(VideoViewPort ebx).VIVPWidth] ; ecx = width of viewport
;*===================================================================
; Verify that the X pixel offset if legal
;*===================================================================
mov eax,[x_pixel] ; find the x position
cmp eax,edx ; is it out of bounds
jae short ??exit ; if so then get out
add edi,eax ; otherwise add in offset
;*===================================================================
; Verify that the Y pixel offset if legal
;*===================================================================
mov eax,[y_pixel] ; get the y position
cmp eax,ecx ; is it out of bounds
jae ??exit ; if so then get out
add edx,[(VideoViewPort ebx).VIVPXAdd] ; otherwise find bytes per row
mul edx ; offset = bytes per row * y
add edi,eax ; add it into the offset
;*===================================================================
;* Figure out what bank we are in and set it, then adjust the
;* offset.
;*===================================================================
call Vesa_Asm_Set_Win
;*===================================================================
; Write the pixel to the screen
;*===================================================================
??in_range:
xor eax,eax ; clear the word
mov al,[edi] ; read in the pixel
??exit:
ret
ENDP Vesa_Get_Pixel
END

View File

@@ -0,0 +1,403 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : December 13, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
TRANSP equ 0
CODESEG
;***************************************************************************
;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly *
;* *
;* NOTE: All coordinate values are expressed in pixels *
;* *
;* INPUT: VideoViewPortClass *dest - Video View Port to copy to *
;* WORD src_x - Src x position to copy from *
;* WORD src_y - Src y position to copy from *
;* WORD dst_x - Dest x position to copy to *
;* WORD dst_y - Dest y position to copy to *
;* WORD w - Width of region to copy *
;* WORD h - Height of region to copy *
;* *
;* 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. *
;* *
;* HISTORY: *
;* 05/11/1994 PWG : Created. *
;* 08/05/1994 PWG : Fixed clipping problem *
;*=========================================================================*
PROC Linear_Blit_To_Vesa C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this :DWORD ; this is a member function
ARG dest :DWORD ; what are we blitting to
ARG x_pixel :DWORD ; x pixel position in source
ARG y_pixel :DWORD ; y pixel position in source
ARG dest_x0 :dword
ARG dest_y0 :dword
ARG pixel_width :DWORD ; width of rectangle to blit
ARG pixel_height:DWORD ; height of rectangle to blit
ARG trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL scr_ajust_width:DWORD
LOCAL dest_ajust_width:DWORD
LOCAL source_area : dword
LOCAL dest_area : dword
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; 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,[ ( VideoViewPort esi) . VIVPHeight ] ; 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 ??clip_against_dest
test cl , 1000b
jz ??scr_left_ok
mov [ x_pixel ] , 0
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov [ y_pixel ] , 0
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??clip_against_dest
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
; Clip Source Rectangle against destination Window boundaries.
??clip_against_dest:
mov eax , [ dest_x0 ]
mov ebx , [ dest_y0 ]
sub eax , [ x_pixel ]
sub ebx , [ y_pixel ]
add eax , [ x1_pixel ]
add ebx , [ y1_pixel ]
mov [ dest_x1 ] , eax
mov [ dest_y1 ] , ebx
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x0 ]
mov ebx , [ dest_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ dest_y0 ]
mov ebx , [ dest_y1 ]
shld ecx , eax , 1
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 , [ dest_x0 ]
mov [ dest_x0 ] , 0
sub [ x_pixel ] , eax
??dest_left_ok:
test cl , 0010b
jz ??dest_bottom_ok
mov eax , [ dest_y0 ]
mov [ dest_y0 ] , 0
sub [ y_pixel ] , eax
??dest_bottom_ok:
test dl , 0100b
jz ??dest_right_ok
mov ebx , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x1 ]
mov [ dest_x1 ] , ebx
sub eax , ebx
sub [ x1_pixel ] , eax
??dest_right_ok:
test dl , 0001b
jz ??do_blit
mov ebx , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov eax , [ dest_y1 ]
mov [ dest_y1 ] , ebx
sub eax , ebx
sub [ y1_pixel ] , eax
??do_blit:
cld
mov ebx , [ this ]
mov esi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ y_pixel ]
add esi , [ x_pixel ]
mov [ source_area ] , ecx
add esi , eax
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ scr_ajust_width ] , ecx
mov ebx , [ dest ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ dest_y0 ]
add edi , [ dest_x0 ]
mov [ dest_area ] , ecx
add edi , eax
Call Vesa_Asm_Set_Win ; set the window
mov eax , [ dest_x1 ]
sub eax , [ dest_x0 ]
jz ??real_out
sub ecx , eax
mov [ dest_ajust_width ] , ecx
mov edx , [ dest_y1 ]
sub edx , [ dest_y0 ]
jz ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
test [ trans ] , 1
jnz ??forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??in_range
xor ecx , ecx
mov ebx , eax
cmp edi , 0b0000h
jge ??no_trailing
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??no_trailing:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_dword
ret
??in_range:
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_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??in_range_bytes
xor ecx , ecx
cmp edi , 0b0000h
jge ??no_trailing_bytes
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??no_trailing_bytes:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
??in_range_bytes:
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Linear_Blit_To_Vesa
END

View File

@@ -0,0 +1,115 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Clear the Full Mcga Screen *
;* *
;* File Name : PUTPIXEL.ASM *
;* *
;* Programmer : Phil Gorrow *
;* *
;* Start Date : June 7, 1994 *
;* *
;* Last Update : June 8, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* GVPC::Put_Pixel -- Puts a pixel on a graphic viewport *
;* VIVPC::Put_Pixel -- Puts a pixel on a virtual viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
CODESEG
;***************************************************************************
;* VIVPC::PUT_PIXEL -- Puts a pixel on a video viewport *
;* *
;* INPUT: WORD the x position for the pixel relative to the upper *
;* left corner of the viewport *
;* WORD the y pos for the pixel relative to the upper left *
;* corner of the viewport *
;* UBYTE the color of the pixel to write *
;* *
;* OUTPUT: none *
;* *
;* WARNING: If pixel is to be placed outside of the viewport then *
;* this routine will abort. *
;* *
;* HISTORY: *
;* 06/08/1994 PWG : Created. *
;*=========================================================================*
PROC Vesa_Put_Pixel C near
USES eax,ebx,ecx,edx,edi,esi
ARG this:DWORD ; this is a member function
ARG x_pixel:DWORD ; x position of pixel to set
ARG y_pixel:DWORD ; y position of pixel to set
ARG color:BYTE ; what color should we clear to
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[this] ; get a pointer to viewport
mov edi,[(VideoViewPort ebx).VIVPOffset] ; get the correct offset
mov ecx,[(VideoViewPort ebx).VIVPHeight] ; edx = height of viewport
mov edx,[(VideoViewPort ebx).VIVPWidth] ; ecx = width of viewport
;*===================================================================
; Verify that the X pixel offset if legal
;*===================================================================
mov eax,[x_pixel] ; find the x position
cmp eax,edx ; is it out of bounds
jae short ??exit ; if so then get out
add edi,eax ; otherwise add in offset
;*===================================================================
; Verify that the Y pixel offset if legal
;*===================================================================
mov eax,[y_pixel] ; get the y position
cmp eax,ecx ; is it out of bounds
jae ??exit ; if so then get out
add edx,[(VideoViewPort ebx).VIVPXAdd] ; otherwise find bytes per row
mul edx ; offset = bytes per row * y
add edi,eax ; add it into the offset
;*===================================================================
;* Figure out what bank we are in and set it, then adjust the
;* offset.
;*===================================================================
call Vesa_Asm_Set_Win
;*===================================================================
; Write the pixel to the screen
;*===================================================================
mov al,[color] ; read in color value
mov [edi],al ; write it to the screen
??exit:
ret
ENDP Vesa_Put_Pixel
END

View File

@@ -0,0 +1,72 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** 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 : Testing memory. *
* *
* File Name : TEST.CPP *
* *
* Programmer : Scott K. Bowen *
* *
* Start Date : April 14, 1994 *
* *
* Last Update : January 18, 1995 [PWG] *
* *
*-------------------------------------------------------------------------*
*/
#include <mcgaprim.h>
#include <gbuffer.h>
#include <vbuffer.h>
//VideoBufferClass SeenPage(640,480);
//GraphicBufferClass HidBuff;
//GraphicBufferClass BackBuff;
int Vesa_Scale_To_Vesa ( void * scr, void * dst,
int src_x , int src_y , int dst_x , int dst_y ,
int src_wd , int src_hg , int dst_wd, int dst_hg,
BOOL trans , char * remap )
{
int area ;
int width , height ;
char * temp ;
VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;
width = src_wd - src_x ;
height = src_hg - src_y ;
area = width * height ;
temp = ( char * ) malloc ( area ) ;
if ( ! temp ) return 0 ;
scr1 -> To_Buffer ( 0, 0, width , height , temp, area );
GraphicBufferClass tempbuffer ( area , width , height , temp ) ;
tempbuffer . Scale ( * scr1 ,
0, 0, dst_x, dst_y,
width, height , dst_wd, dst_hg ,
trans , remap );
free ( temp ) ;
return 0 ;
}

View File

@@ -0,0 +1,730 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : VSCALE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : January 16, 1995 *
;* *
;* Last Update : January 16, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Linear_Scale_To_Vesa -- Scales a graphic viewport to a vesa viewport *
;* Vesa_Scale_To_Linear -- Scales a Vesa viewport to a graphic viewport *
;* Vesa_Scale_To_Vesa -- Scales a vesa viewport to a vesa viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE "mcgaprim.inc"
INCLUDE "gbuffer.inc"
GLOBAL Vesa_Asm_Set_Win : near
GLOBAL cpu_video_page : dword
GLOBAL cpu_page_limit : dword
CODESEG
;***************************************************************************
;* LINEAR_SCALE_TO_VESA -- Scales a graphic viewport to a vesa viewport *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* PROTO: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 01/16/1995 PWG : Created. *
;*=========================================================================*
PROC Linear_Scale_To_Vesa C near
;*===================================================================
;* Define the arguements that our function takes.
;*===================================================================
ARG this:DWORD ; pointer to source view port
ARG dest:DWORD ; pointer to destination view port
ARG src_x:DWORD ; source x offset into view port
ARG src_y:DWORD ; source y offset into view port
ARG dst_x:DWORD ; dest x offset into view port
ARG dst_y:DWORD ; dest y offset into view port
ARG src_width:DWORD ; width of source rectangle
ARG src_height:DWORD ; height of source rectangle
ARG dst_width:DWORD ; width of dest rectangle
ARG dst_height:DWORD ; width of dest height
ARG trans:DWORD ; is this transparent?
ARG remap:DWORD ; pointer to table to remap source
;*===================================================================
;* Define local variables to hold the viewport characteristics
;*===================================================================
local src_x0 : dword
local src_y0 : dword
local src_x1 : dword
local src_y1 : dword
local dst_x0 : dword
local dst_y0 : dword
local dst_x1 : dword
local dst_y1 : dword
local src_win_width : dword
local dst_win_width : dword
local dy_intr : dword
local dy_frac : dword
local dy_acc : dword
local dx_frac : dword
local dx_intr : dword
local scan_line : dword
local counter_x : dword
local counter_y : dword
local remap_counter :dword
local entry : dword
;*===================================================================
;* Check for scale error when to or from size 0,0
;*===================================================================
cmp [dst_width],0
je ??all_done
cmp [dst_height],0
je ??all_done
cmp [src_width],0
je ??all_done
cmp [src_height],0
je ??all_done
mov eax , [ src_x ]
mov ebx , [ src_y ]
mov [ src_x0 ] , eax
mov [ src_y0 ] , ebx
add eax , [ src_width ]
add ebx , [ src_height ]
mov [ src_x1 ] , eax
mov [ src_y1 ] , ebx
mov eax , [ dst_x ]
mov ebx , [ dst_y ]
mov [ dst_x0 ] , eax
mov [ dst_y0 ] , ebx
add eax , [ dst_width ]
add ebx , [ dst_height ]
mov [ dst_x1 ] , eax
mov [ dst_y1 ] , ebx
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ src_x0 ]
mov ebx , [ src_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ src_y0 ]
mov ebx , [ src_y1 ]
shld ecx , eax , 1
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 ??all_done
or al , dl
jz ??clip_against_dest
mov bl , dl
test cl , 1000b
jz ??src_left_ok
xor eax , eax
mov [ src_x0 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x0 ] , eax
??src_left_ok:
test cl , 0010b
jz ??src_bottom_ok
xor eax , eax
mov [ src_y0 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y0 ] , eax
??src_bottom_ok:
test bl , 0100b
jz ??src_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ src_x1 ] , eax
sub eax , [ src_x ]
imul [ dst_width ]
idiv [ src_width ]
add eax , [ dst_x ]
mov [ dst_x1 ] , eax
??src_right_ok:
test bl , 0001b
jz ??clip_against_dest
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ src_y1 ] , eax
sub eax , [ src_y ]
imul [ dst_height ]
idiv [ src_height ]
add eax , [ dst_y ]
mov [ dst_y1 ] , eax
; Clip destination Rectangle against source Window boundaries.
??clip_against_dest:
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dst_x0 ]
mov ebx , [ dst_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ dst_y0 ]
mov ebx , [ dst_y1 ]
shld ecx , eax , 1
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 ??all_done
or al , dl
jz ??do_scaling
mov bl , dl
test cl , 1000b
jz ??dst_left_ok
xor eax , eax
mov [ dst_x0 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x0 ] , eax
??dst_left_ok:
test cl , 0010b
jz ??dst_bottom_ok
xor eax , eax
mov [ dst_y0 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y0 ] , eax
??dst_bottom_ok:
test bl , 0100b
jz ??dst_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ dst_x1 ] , eax
sub eax , [ dst_x ]
imul [ src_width ]
idiv [ dst_width ]
add eax , [ src_x ]
mov [ src_x1 ] , eax
??dst_right_ok:
test bl , 0001b
jz ??do_scaling
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ dst_y1 ] , eax
sub eax , [ dst_y ]
imul [ src_height ]
idiv [ dst_height ]
add eax , [ src_y ]
mov [ src_y1 ] , eax
??do_scaling:
cld
mov ebx , [ this ]
mov esi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov [ src_win_width ] , eax
mul [ src_y0 ]
add esi , [ src_x0 ]
add esi , eax
mov ebx , [ dest ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov [ dst_win_width ] , eax
mul [ dst_y0 ]
add edi , [ dst_x0 ]
add edi , eax
call Vesa_Asm_Set_Win ; set the window
mov eax , [ src_height ]
xor edx , edx
mov ebx , [ dst_height ]
idiv [ dst_height ]
imul eax , [ src_win_width ]
neg ebx
mov [ dy_intr ] , eax
mov [ dy_frac ] , edx
mov [ dy_acc ] , ebx
mov eax , [ src_width ]
xor edx , edx
shl eax , 16
idiv [ dst_width ]
xor edx , edx
shld edx , eax , 16
shl eax , 16
mov ecx , [ dst_y1 ]
mov ebx , [ dst_x1 ]
sub ecx , [ dst_y0 ]
jz ??all_done
sub ebx , [ dst_x0 ]
jz ??all_done
mov [ counter_y ] , ecx
mov [ scan_line ] , ebx
cmp [ trans ] , 0
jnz ??transparency
cmp [ remap ] , 0
jnz ??normal_remap
; *************************************************************************
; normal scale
mov ecx , ebx
and ecx , 01fh
lea ecx , [ ecx + ecx * 2 ]
shr ebx , 5
neg ecx
mov [ counter_x ] , ebx
lea ecx , [ ??ref_point + ecx + ecx * 2 ]
mov [ entry ] , ecx
??outter_loop:
mov ebx , [ scan_line ]
push esi
add ebx , edi
xor ecx , ecx
add ebx , [ cpu_video_page ]
push edi
cmp ebx , [ cpu_page_limit ]
jl ??in_range
mov ebx , [ scan_line ]
jmp ??trailing_entry
??trailing_bytes:
mov cl , [ esi ]
add ecx , eax
adc esi , edx
mov [ edi ] , cl
inc edi
dec ebx
??trailing_entry:
cmp edi , 0b0000h
jl ??trailing_bytes
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; set the window
??end_of_scanline:
mov cl , [ esi ]
add ecx , eax
adc esi , edx
mov [ edi ] , cl
inc edi
dec ebx
jg ??end_of_scanline
sub [ dword ptr esp ] , 010000h
jmp ??next_line
??in_range:
mov ebx , [ counter_x ]
jmp [ entry ]
??inner_loop:
REPT 32
mov cl , [ esi ]
add ecx , eax
adc esi , edx
mov [ edi ] , cl
inc edi
ENDM
??ref_point:
dec ebx
jge ??inner_loop
??next_line:
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??outter_loop
ret
; *************************************************************************
; normal scale with remap
??normal_remap:
mov ecx , ebx
mov [ dx_frac ] , eax
mov [ dx_intr ] , edx
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 13
mov [ counter_x ] , ebx
lea ecx , [ ??remapref_point + ecx ]
mov [ entry ] , ecx
??remapoutter_loop:
mov ebx , [ scan_line ]
push esi
add ebx , edi
xor ecx , ecx
add ebx , [ cpu_video_page ]
push edi
cmp ebx , [ cpu_page_limit ]
jl ??remap_in_range
mov edx , [ scan_line ]
xor ebx , ebx
jmp ??remap_trailing_entry
??remap_trailing_bytes:
mov bl , [ esi ]
add ecx , [ dx_frac ]
adc esi , [ dx_intr ]
mov cl , [ eax + ebx ]
mov [ edi ] , cl
inc edi
dec edx
??remap_trailing_entry:
cmp edi , 0b0000h
jl ??remap_trailing_bytes
??remap_no_trailing:
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; set the window
??remap_end_of_scanline:
mov bl , [ esi ]
add ecx , [ dx_frac ]
adc esi , [ dx_intr ]
mov cl , [ eax + ebx ]
mov [ edi ] , cl
inc edi
dec edx
jg ??remap_end_of_scanline
sub [ dword ptr esp ] , 010000h
jmp ??remap_next_line
??remap_in_range:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
mov edx , [ dx_intr ]
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??remapinner_loop:
REPT 32
mov bl , [ esi ]
add ecx , [ dx_frac ]
adc esi , edx
mov cl , [ eax + ebx ]
mov [ edi ] , cl
inc edi
ENDM
??remapref_point:
dec [ remap_counter ]
jge ??remapinner_loop
??remap_next_line:
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??remapoutter_loop
ret
;****************************************************************************
; scale with transparency
??transparency:
cmp [ remap ] , 0
jnz ??trans_remap
; *************************************************************************
; normal scale with transparency
mov ecx , ebx
and ecx , 01fh
imul ecx , -13
shr ebx , 5
mov [ counter_x ] , ebx
lea ecx , [ ??tr_ref_point + ecx ]
mov [ entry ] , ecx
??tr_outter_loop:
mov ebx , [ scan_line ]
push esi
add ebx , edi
xor ecx , ecx
add ebx , [ cpu_video_page ]
push edi
cmp ebx , [ cpu_page_limit ]
jl ??tr_in_range
mov ebx , [ scan_line ]
jmp ??tr_trailing_entry
??tr_trailing_bytes:
mov cl , [ esi ]
test cl , cl
jz ??tr_skip
mov [ edi ] , cl
??tr_skip:
add ecx , eax
adc esi , edx
inc edi
dec ebx
??tr_trailing_entry:
cmp edi , 0b0000h
jl ??tr_trailing_bytes
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; set the window
??tr_end_of_scanline:
mov cl , [ esi ]
test cl , cl
jz ??tr_skip1
mov [ edi ] , cl
??tr_skip1:
add ecx , eax
adc esi , edx
inc edi
dec ebx
jg ??tr_end_of_scanline
sub [ dword ptr esp ] , 010000h
jmp ??tr_next_line
??tr_in_range:
mov ebx , [ counter_x ]
jmp [ entry ]
??tr_inner_loop:
REPT 32
local skip
mov cl , [ esi ]
test cl , cl
jz skip
mov [ edi ] , cl
skip:
add ecx , eax
adc esi , edx
inc edi
ENDM
??tr_ref_point:
dec ebx
jge ??tr_inner_loop
??tr_next_line:
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??tr_skip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??tr_skip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??tr_outter_loop
ret
; *************************************************************************
; normal scale with remap and transparency
??trans_remap:
mov ecx , ebx
mov [ dx_frac ], eax
mov [ dx_intr ] , edx
and ecx , 01fh
mov eax , [ remap ]
shr ebx , 5
imul ecx , - 17
mov [ counter_x ] , ebx
lea ecx , [ ??trans_remapref_point + ecx ]
mov [ entry ] , ecx
??trans_remapoutter_loop:
mov ebx , [ scan_line ]
push esi
add ebx , edi
xor ecx , ecx
add ebx , [ cpu_video_page ]
push edi
cmp ebx , [ cpu_page_limit ]
jl ??trans_remap_in_range
mov edx , [ scan_line ]
xor ebx , ebx
jmp ??trans_remap_trailing_bytes1
??trans_remap_trailing_bytes:
mov bl , [ esi ]
test bl , bl
jz ??trans_remp
mov cl , [ eax + ebx ]
mov [ edi ] , cl
??trans_remp:
add ecx , [ dx_frac ]
adc esi , [ dx_intr ]
inc edi
dec edx
??trans_remap_trailing_bytes1:
cmp edi , 0b0000h
jl ??trans_remap_trailing_bytes
??trans_remap_no_trailing:
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; set the window
??trans_remap_end_of_scanline:
mov bl , [ esi ]
test bl , bl
jz ??trans_remp1
mov cl , [ eax + ebx ]
mov [ edi ] , cl
??trans_remp1:
add ecx , [ dx_frac ]
adc esi , [ dx_intr ]
inc edi
dec edx
jg ??trans_remap_end_of_scanline
sub [ dword ptr esp ] , 010000h
jmp ??trans_remap_next_line
??trans_remap_in_range:
mov ebx , [ counter_x ]
push esi
mov [ remap_counter ] , ebx
push edi
mov edx , [ dx_intr ]
xor ecx , ecx
xor ebx , ebx
jmp [ entry ]
??trans_remapinner_loop:
REPT 32
local skip
mov bl , [ esi ]
test bl , bl
jz skip
mov cl , [ eax + ebx ]
mov [ edi ] , cl
skip:
add ecx , [ dx_frac ]
adc esi , edx
inc edi
ENDM
??trans_remapref_point:
dec [ remap_counter ]
jge ??trans_remapinner_loop
??trans_remap_next_line:
pop edi
pop esi
add edi , [ dst_win_width ]
add esi , [ dy_intr ]
mov ebx , [ dy_acc ]
add ebx , [ dy_frac ]
jle ??trans_remapskip_line
add esi , [ src_win_width ]
sub ebx , [ dst_height ]
??trans_remapskip_line:
dec [ counter_y ]
mov [ dy_acc ] , ebx
jnz ??trans_remapoutter_loop
ret
??all_done:
ret
ENDP Linear_Scale_To_Vesa
END

View File

@@ -0,0 +1,344 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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 32 bit Library *
;* *
;* File Name : TOBUFFER.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : June 15, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VVC::TOBUFFER -- Copies a virtual viewport to a linear buffer *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
TRANSP equ 0
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
CODESEG
;***************************************************************************
;* VIVC::TOBUFFER -- Copies a virtual viewport to a linear buffer *
;* *
;* INPUT: BYTE * dest - buffer to copy to *
;* size - size of the buffer to copy to *
;* x_pixel - x pixel on viewport to copy from *
;* y_pixel - y pixel on viewport to copy from *
;* pixel_width - the width of copy region *
;* pixel_height - the height of copy region *
;* *
;* 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. *
;*=========================================================================*
PROC Vesa_To_Buffer C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this:DWORD ; this is a class member function
ARG x_pixel:DWORD ; Page X pixel coordinate.
ARG y_pixel:DWORD ; Page Y pixel coordinate.
ARG pixel_width:DWORD ; Width of region in pixels.
ARG pixel_height:DWORD ; Height of region in pixels.
ARG dest:DWORD ; the buffer to copy to
ARG size:DWORD ; the size of the buffer
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL dest_ajust_width:DWORD
LOCAL scr_ajust_width:DWORD
LOCAL dest_area : dword
; Clip dest Rectangle against source Window boundaries.
mov [ dest_x1 ] , 0
mov [ dest_y1 ] , 0
mov esi , [ this ] ; get ptr to dest
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; 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,[ ( VideoViewPort esi) . VIVPHeight ] ; 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 ??scr_left_ok
mov eax , [ x_pixel ]
neg eax
mov [ x_pixel ] , 0
mov [ dest_x1 ] , eax
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov eax , [ y_pixel ]
neg eax
mov [ y_pixel ] , 0
mov [ dest_y1 ] , eax
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??do_blit
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
??do_blit:
cld
mov eax , [ (VideoViewPort esi) . VIVPXAdd ]
add eax , [ (VideoViewPort esi) . VIVPWidth ]
mov edi , [ (VideoViewPort esi) . VIVPOffset ]
mov ecx , eax
mul [ y_pixel ]
add edi , [ x_pixel ]
add edi , eax
Call Vesa_Asm_Set_Win ; set the window
mov esi , edi
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ scr_ajust_width ] , ecx
mov edi , [ dest ]
mov eax , [ pixel_width ]
sub eax , [ x1_pixel ]
add eax , [ x_pixel ]
mov [ dest_ajust_width ] , eax
mov eax , [ dest_y1 ]
mul [ pixel_width ]
add eax , [ dest_x1 ]
add edi , eax
mov edx , [ y1_pixel ]
sub edx , [ y_pixel ]
jz ??real_out
mov eax , [ x1_pixel ]
sub eax , [ x_pixel ]
jz ??real_out
mov ebx , [ pixel_width ]
imul ebx , edx
cmp ebx , [ size ]
jg ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
test [ trans ] , 1
jnz ??forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??in_range
xor ecx , ecx
cmp esi , 0b0000h
mov ebx , eax
jge ??no_trailing
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??no_trailing:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_dword
ret
??in_range:
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_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??in_range_bytes
xor ecx , ecx
cmp esi , 0b0000h
jge ??no_trailing_bytes
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??no_trailing_bytes:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
??in_range_bytes:
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Vesa_To_Buffer
END

View File

@@ -0,0 +1,343 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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 32 bit Library *
;* *
;* File Name : TOPAGE.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : December 9, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* Buffer_To_Page(GVC) -- Copies a linear buffer to a graphic viewport *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
TRANSP equ 0
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
CODESEG
;***************************************************************************
;* 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. *
;* 12/09/1994 PWG : Made SVGA Modifications *
;*=========================================================================*
PROC Vesa_Buffer_To_Page C near
USES 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 trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL scr_x1 : dword
LOCAL scr_y1 : dword
LOCAL dest_ajust_width:DWORD
LOCAL scr_ajust_width:DWORD
LOCAL dest_area : dword
cmp [ src ] , 0
jz ??real_out
; Clip dest Rectangle against source Window boundaries.
mov [ scr_x1 ] , 0
mov [ scr_y1 ] , 0
mov esi , [ dest ] ; get ptr to dest
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; 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,[ ( VideoViewPort esi) . VIVPHeight ] ; 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_x1 ] , eax
??dest_left_ok:
test cl , 0010b
jz ??dest_bottom_ok
mov eax , [ y_pixel ]
neg eax
mov [ y_pixel ] , 0
mov [ scr_y1 ] , eax
??dest_bottom_ok:
test dl , 0100b
jz ??dest_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??dest_right_ok:
test dl , 0001b
jz ??do_blit
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
??do_blit:
cld
mov eax , [ (VideoViewPort esi) . VIVPXAdd ]
add eax , [ (VideoViewPort esi) . VIVPWidth ]
mov edi , [ (VideoViewPort esi) . VIVPOffset ]
mov ecx , eax
mul [ y_pixel ]
add edi , [ x_pixel ]
add edi , eax
call Vesa_Asm_Set_Win ; set the window
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ dest_ajust_width ] , ecx
mov esi , [ src ]
mov eax , [ pixel_width ]
sub eax , [ x1_pixel ]
add eax , [ x_pixel ]
mov [ scr_ajust_width ] , eax
mov eax , [ scr_y1 ]
mul [ pixel_width ]
add eax , [ scr_x1 ]
add esi , eax
mov edx , [ y1_pixel ]
sub edx , [ y_pixel ]
jz ??real_out
mov eax , [ x1_pixel ]
sub eax , [ x_pixel ]
jz ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
test [ trans ] , 1
jnz ??forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??in_range
xor ecx , ecx
mov ebx , eax
cmp edi , 0b0000h
jge ??no_trailing
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??no_trailing:
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; set the window
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_dword
ret
??in_range:
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_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??in_range_bytes
xor ecx , ecx
cmp edi , 0b0000h
jge ??no_trailing_bytes
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??no_trailing_bytes:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
??in_range_bytes:
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Vesa_Buffer_To_Page
END

View File

@@ -0,0 +1,444 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : TXTPRNT.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : January 17, 1995 *
;* *
;* Last Update : January 17, 1995 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* VESA_Print -- Assembly VESA text print routine *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE "svgaprim.inc"
INCLUDE ".\gbuffer.inc"
;*=========================================================================*
;* Extern the font pointer which is defined by the font class *
;*=========================================================================*
GLOBAL FontPtr:DWORD
GLOBAL ColorXlat:BYTE
;*=========================================================================*
;* Define the necessary equates for structures and bounds checking *
;*=========================================================================*
; The header of the font file looks like this:
; UWORD FontLength; 0
; BYTE FontCompress; 2
; BYTE FontDataBlocks; 3
; UWORD InfoBlockOffset; 4
; UWORD OffsetBlockOffset; 6
; UWORD WidthBlockOffset; 8
; UWORD DataBlockOffset; 10
; UWORD HeightOffset; 12
; For this reason the following equates have these values:
FONTINFOBLOCK EQU 4
FONTOFFSETBLOCK EQU 6
FONTWIDTHBLOCK EQU 8
FONTDATABLOCK EQU 10
FONTHEIGHTBLOCK EQU 12
FONTINFOMAXHEIGHT EQU 4
FONTINFOMAXWIDTH EQU 5
LOCALS ??
;*=========================================================================*
;* Define the color xlate table in the data segment *
;*=========================================================================*
CODESEG
;***************************************************************************
;* VESA_PRINT -- Assembly VESA text print routine *
;* *
;* *
;* *
;* INPUT: *
;* *
;* OUTPUT: *
;* *
;* PROTO: *
;* *
;* WARNINGS: *
;* *
;* HISTORY: *
;* 01/17/1995 PWG : Created. *
;*=========================================================================*
PROC Vesa_Print C near
USES ebx,ecx,edx,esi,edi
ARG this:DWORD
ARG string:DWORD
ARG x_pixel:DWORD
ARG y_pixel:DWORD
ARG fcolor:DWORD
ARG bcolor:DWORD
LOCAL infoblock:DWORD ; pointer to info block
LOCAL offsetblock:DWORD ; pointer to offset block (UWORD *)
LOCAL widthblock:DWORD ; pointer to width block (BYTE *)
LOCAL heightblock:DWORD ; pointer to height block (UWORD *)
LOCAL curline:DWORD ; pointer to first column of current row.
local ptr_string:dword ; pointer to string
LOCAL bufferwidth:DWORD ; width of buffer (vpwidth + Xadd)
LOCAL nextdraw:DWORD ; bufferwidth - width of cur character.
LOCAL startdraw:DWORD ; where next character will start being drawn.
LOCAL char:DWORD ; current character value.
LOCAL maxheight:BYTE ; max height of characters in font.
LOCAL bottomblank:BYTE ; amount of empty space below current character.
LOCAL charheight:BYTE ; true height of current character.
LOCAL vpwidth:DWORD
LOCAL vpheight:DWORD
LOCAL remainder:DWORD
LOCAL fullwidth:DWORD
LOCAL currwidth:DWORD
;-------------------------------- Where to draw -----------------------------------------------
; Set up memory location to start drawing.
mov ebx,[this] ; get a pointer to dest
mov eax,[(GraphicViewPort ebx).GVPHeight] ; get height of viewport
mov [vpheight],eax ; save off height of viewport
mov eax,[(GraphicViewPort ebx).GVPWidth] ; get width of viewport
mov [vpwidth],eax ; save it off for later
add eax,[(GraphicViewPort ebx).GVPXAdd] ; add in xadd for bytes_per_line
mov [bufferwidth],eax ; save it off for later use.
mul [y_pixel] ; multiply rowsize * y_pixel start.
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get start of the viewport
add edi,eax ; add y position to start of vp
mov [curline],edi ; save 0,y address for line feed stuff.
add edi,[x_pixel] ; add to get starting column in starting row.
mov [startdraw],edi ; save it off.
;-------------------------------- Create block pointers ----------------------------------------
; Get the pointer to the font.
; We could check for NULL but why waste the time.
; It is up to programmer to make sure it is set.
mov esi,[FontPtr] ; Get the font pointer
or esi,esi
jz ??done
; Set up some pointers to the different memory blocks.
; esi (FontPtr) is added to each to get the true address of each block.
; Many registers are used for P5 optimizations.
; ebx is used for InfoBlock which is then used in the next section.
movzx eax,[WORD PTR esi+FONTOFFSETBLOCK] ; get offset to offset block
movzx ebx,[WORD PTR esi+FONTINFOBLOCK] ; get offset to info block (must be ebx for height test)
movzx ecx,[WORD PTR esi+FONTWIDTHBLOCK] ; get offset to width block
movzx edx,[WORD PTR esi+FONTHEIGHTBLOCK] ; get offset to height block
add eax,esi ; add offset of FontPtr to offset block
add ebx,esi ; add offset of FontPtr to info block
add ecx,esi ; add offset of FontPtr to width block
add edx,esi ; add offset of FontPtr to height block
mov [offsetblock],eax ; save offset to offset block
mov [infoblock],ebx ; save offset to info block
mov [widthblock],ecx ; save offset to width block
mov [heightblock],edx ; save offset to height block
;------------------------------------------ Test for fit ----------------------------------------------
; Test to make sure the height of the max character will fit on this line
; and and not fall out of the viewport.
; remember we set ebx to FONTINFOBLOCK above.
movzx eax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.
mov [maxheight],al ; save it for later use.
add eax,[y_pixel] ; add current y_value.
cmp eax,[vpheight] ; are we over the edge?
jg ??done ; if so, we're outa here.
mov [y_pixel],eax ; save for next line feed. y value for next line.
cld ; Make sure we are always forward copying.
;------------------------ Set palette foreground and background ----------------------------------
mov eax,[fcolor] ; foreground color
mov [ColorXlat+1],al
mov [ColorXlat+16],al
mov eax,[bcolor] ; background color
mov [ColorXlat],al
;-------------------------------------------------------------------------------------------------
;----------------------------------------- Main loop ----------------------------------------------
; Now we go into the main loop of reading each character in the string and doing
; something with it.
??next_char:
; while (*string++)
xor eax,eax ; zero out since we will just load al.
mov esi,[string] ; get address on next character.
lodsb ; load the character into al.
test eax,0FFH ; test to see if character is a NULL
jz ??done ; character is NULL, get outa here.
mov edi,[startdraw] ; Load the starting address.
mov [string],esi ; save index into string. (incremented by lodsb)
cmp eax,10 ; is the character a line feed?
je ??line_feed ; if so, go to special case.
cmp eax,13 ; is the character a line feed?
je ??line_feed ; if so, go to special case.
mov [char],eax ; save the character off for later reference.
mov ebx,eax ; save it in ebx for later use also.
add eax,[widthblock] ; figure address of width of character.
mov ecx,[x_pixel] ; get current x_pixel.
movzx edx,[BYTE PTR eax] ; get the width of the character in dl.
add ecx,edx ; add width of char to current x_pixel.
add [startdraw],edx ; save start draw for next character.
cmp ecx,[vpwidth] ; is the pixel greater then the vp width?
jg ??force_line_feed ; if so, force a line feed.
mov [x_pixel],ecx ; save value of start of next character.
mov ecx,[bufferwidth] ; get amount to next y same x (one row down)
sub ecx,edx ; take the current width off.
mov [nextdraw],ecx ; save it to add to edi when done with a row.
; At this point we got the character. It is now time to find out specifics
; about drawing the darn thing.
; ebx = char so they can be used as an indexes.
; edx = width of character for loop later.
; get offset of data for character into esi.
shl ebx,1 ; mult by 2 to later use as a WORD index.
mov esi,[offsetblock] ; get pointer to begining of offset block.
add esi,ebx ; index into offset block.
movzx esi,[WORD PTR esi] ; get true offset into data block from FontPtr.
add esi,[FontPtr] ; Now add FontPtr address to get true address.
; Get top and bottom blank sizes and the true height of the character.
add ebx,[heightblock] ; point ebx to element in height array.
mov al,[ebx+1] ; load the data height into dl.
mov cl,[ebx] ; load the first data row into cl.
mov bl,[maxheight] ; get the max height of characters.
mov [charheight],al ; get number of rows with data.
add al,cl ; add the two heights.
sub bl,al ; subract topblank + char height from maxheight.
mov [bottomblank],bl ; save off the number of blank rows on the bottom.
; leaving this section:
; dl is still the width of the character.
; cl is the height of the top blank area.
mov ebx,OFFSET ColorXlat ; setup ebx for xlat commands.
mov dh,dl ; save the width of the character to restore each loop.
call Vesa_Asm_Set_Win ; adjust edi & vesa page
cmp cl,0 ; is there any blank rows on top?
jz ??draw_char ; if not go and draw the real character.
xor eax,eax ; get color 0 for background.
xlat [ebx] ; get translated color into al
test al,al ; is it transparent black
jnz ??loop_top ; if not go and write the color
;----------------------------------------- skip Top blank area ----------------------------------------
; this case, the top is transparrent, but we need to increase our dest pointer to correct row.
movzx eax,cl ; get number of rows into eax;
mov ecx,edx ; save width since edx will be destroyed by mul.
mul [bufferwidth] ; multiply that by the width of the buffer.
mov edx,ecx ; restore the width
add edi,eax ; update the pointer.
cmp edi,0b0000h ; have we gone over win edge
jl ??draw_char ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
jmp short ??draw_char ; now go draw the character.
;----------------------------------------- fill Top blank area ----------------------------------------
??loop_top:
stosb ; store the value
cmp edi,0b0000h ; have we gone over win edge
jl ??top_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??top_no_window_change:
dec dh ; decrement our width.
jnz ??loop_top ; if more width, continue on.
add edi,[nextdraw] ; add amount for entire row.
cmp edi,0b0000h ; have we gone over win edge
jl ??top2_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??top2_no_window_change:
dec cl ; decrement or row count
mov dh,dl ; restore width in dh for loop.
jz ??draw_char ; we are done here, go draw the character.
jmp short ??loop_top ; go back to top of loop.
;----------------------------------------- Draw character ----------------------------------------------
??draw_char:
movzx ecx,[charheight] ; get the height of character to count down rows.
test ecx,ecx ; is there any data? (blank would not have any)
jz ??next_char ; if no data, go on to next character.
??while_data:
lodsb ; get byte value from font data
mov ah,al ; save hinibble
and eax,0F00FH ; mask of low nibble in al hi nibble in ah.
xlat [ebx] ; get new color
test al,al ; is it a transparent?
jz short ??skiplo ; skip over write
mov [es:edi],al ; write it out
??skiplo:
inc edi
cmp edi,0b0000h ; have we gone over win edge
jl ??lo_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??lo_no_window_change:
dec dh ; decrement our width.
jz short ??nextrow ; check if done with width of char
mov al,ah ; restore to get
; test the time difference between looking up in a large table when shr al,4 is not done as
; compared to using only a 16 byte table when using the shr al,4
;shr al,4 ; shift the hi nibble down to low nibble
xlat [ebx] ; get new color
test al,al ; is it a transparent?
jz short ??skiphi ; skip over write
mov [edi],al ; write it out
??skiphi:
inc edi
cmp edi,0b0000h ; have we gone over win edge
jl ??hi_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??hi_no_window_change:
dec dh ; decrement our width.
jnz short ??while_data ; check if done with width of char
??nextrow:
add edi,[nextdraw] ; go to next line.
cmp edi,0b0000h ; have we gone over win edge
jl ??next_row_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??next_row_no_window_change:
dec ecx ; decrement the number of rows to go
mov dh,dl ; restore our column count for row.
jnz ??while_data ; more data for character.
; Now it is time to setup for clearing out the bottom of the character.
movzx ecx,[bottomblank] ; get amount on bottom that is blank
cmp ecx,0 ; if there is no blank bottom...
jz ??next_char ; then skip to go to next character
xor eax,eax ; get color 0 for background.
xlat [ebx] ; get translated color into al
test al,al ; is it transparent black
jz ??next_char ; skip the top black section to let the background through
mov dh,dl ; restore width in dh for loop.
;----------------------------------------- Blank below character -----------------------------------
??loop_bottom:
stosb ; store the value
cmp edi,0b0000h ; have we gone over win edge
jl ??bottom_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??bottom_no_window_change:
dec dh ; decrement our width.
jnz ??loop_bottom ; if more width, continue on.
add edi,[nextdraw] ; add amount for entire row.
cmp edi,0b0000h ; have we gone over win edge
jl ??bottom2_no_window_change ; if not keep writing to window
add edi , [ cpu_video_page ]
call Vesa_Asm_Set_Win ; instead switch to next window
??bottom2_no_window_change:
mov dh,dl ; restore width in dh for loop.
dec cl ; decrement or row count
jz ??next_char ; we are done here, go to the next character.
jmp short ??loop_bottom ; go back to top of loop.
;----------------------------------- end of next_char (main) loop ------------------------------------
;-------------------------------------------------------------------------------------------------
;----------------------------------- special case line feeds ----------------------------------------
; JRJ 05/01/95 This is the problem However made this change introduced
; a error in the code, this function is not supposed to handle
; Text wrapping
??force_line_feed:
; decrement pointer *string so that it will be back at same character
; when it goes through the loop.
dec [dword ptr string] ; overflow by one charater
jmp ??done
??line_feed:
mov edx,[y_pixel] ; get the current y pixel value.
movzx ecx,[maxheight] ; get max height for later use.
add edx,ecx ; add max height to y_pixel
cmp edx,[vpheight] ; are we over the edge?
jg ??done ; if so, we are outa here.
mov eax,[bufferwidth] ; get bytes to next line.
mov edi,[curline] ; get start of current line.
mul ecx ; mult max height * next line.
add edi,eax ; add adjustment to current line.
add [y_pixel],ecx ; increment to our next y position.
mov [curline],edi ; save it off for next line_feed.
mov [startdraw],edi ; save it off so we know where to draw next char.w
mov [x_pixel],0 ; zero out x_pixel
jmp ??next_char
??done:
mov eax,[string] ; return the number of charaters
sub eax,[ptr_string] ; printed
ret
ENDP Vesa_Print
END

View File

@@ -0,0 +1,597 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : December 13, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
TRANSP equ 0
POOLSIZE equ 8000
CODESEG
PROC Vesa_Blit_To_Vesa C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this :DWORD ; this is a member function
ARG dest :DWORD ; what are we blitting to
ARG x_pixel :DWORD ; x pixel position in source
ARG y_pixel :DWORD ; y pixel position in source
ARG dest_x0 :dword
ARG dest_y0 :dword
ARG pixel_width :DWORD ; width of rectangle to blit
ARG pixel_height:DWORD ; height of rectangle to blit
ARG trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL scr_ajust_width:DWORD
LOCAL dest_ajust_width:DWORD
LOCAL source_area : dword
LOCAL dest_area : dword
local total_lines : dword
local count_dy : dword
local mem_page : dword
local vesa_page : dword
local mem_pool : byte : POOLSIZE
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; 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,[ ( VideoViewPort esi) . VIVPHeight ] ; 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 ??clip_against_dest
test cl , 1000b
jz ??scr_left_ok
mov [ x_pixel ] , 0
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov [ y_pixel ] , 0
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??clip_against_dest
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
; Clip Source Rectangle against destination Window boundaries.
??clip_against_dest:
mov eax , [ dest_x0 ]
mov ebx , [ dest_y0 ]
sub eax , [ x_pixel ]
sub ebx , [ y_pixel ]
add eax , [ x1_pixel ]
add ebx , [ y1_pixel ]
mov [ dest_x1 ] , eax
mov [ dest_y1 ] , ebx
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x0 ]
mov ebx , [ dest_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ dest_y0 ]
mov ebx , [ dest_y1 ]
shld ecx , eax , 1
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 , [ dest_x0 ]
mov [ dest_x0 ] , 0
sub [ x_pixel ] , eax
??dest_left_ok:
test cl , 0010b
jz ??dest_bottom_ok
mov eax , [ dest_y0 ]
mov [ dest_y0 ] , 0
sub [ y_pixel ] , eax
??dest_bottom_ok:
test dl , 0100b
jz ??dest_right_ok
mov ebx , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x1 ]
mov [ dest_x1 ] , ebx
sub eax , ebx
sub [ x1_pixel ] , eax
??dest_right_ok:
test dl , 0001b
jz ??do_blit
mov ebx , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov eax , [ dest_y1 ]
mov [ dest_y1 ] , ebx
sub eax , ebx
sub [ y1_pixel ] , eax
??do_blit:
cld
mov ebx , [ this ]
mov esi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ y_pixel ]
add esi , [ x_pixel ]
mov [ source_area ] , ecx
add esi , eax
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ scr_ajust_width ] , ecx
mov ebx , [ dest ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ dest_y0 ]
add edi , [ dest_x0 ]
mov [ dest_area ] , ecx
add edi , eax
mov eax , [ dest_x1 ]
sub eax , [ dest_x0 ]
jz ??real_out
sub ecx , eax
mov [ dest_ajust_width ] , ecx
mov edx , [ dest_y1 ]
sub edx , [ dest_y0 ]
jz ??real_out
push eax
mov [ mem_page ] , 0
mov [ vesa_page ] , 0
mov [ total_lines ] , edx
mov eax , POOLSIZE
xor edx , edx
idiv [ dword ptr esp ]
mov [ count_dy ] , eax
pop eax
; **************************************************************************
; check direction of motions
cmp esi , edi
jl ??backupward_blit
ret
;***********************************************************************
; Backupward blit
??back_mem_loop:
push edi
lea edi , [ mem_pool ]
mov edx , [ count_dy ]
call ??vesa_to_memory
pop edi
push esi
lea esi , [ mem_pool ]
mov edx , [ count_dy ]
call ??memory_to_vesa
pop esi
??backupward_blit:
mov edx , [ total_lines ]
sub edx , [ count_dy ]
mov [ total_lines ] , edx
jg ??back_mem_loop
add edx , [ count_dy ]
push edi
push edx
lea edi , [ mem_pool ]
call ??vesa_to_memory
pop edx
pop edi
push esi
lea esi , [ mem_pool ]
call ??memory_to_vesa
pop esi
ret
??real_out:
ret
; ********************************************************************
; Move Vesa video page to memory buffer
??vesa_to_memory:
xchg edi , esi
add edi , [ mem_page ]
call Vesa_Asm_Set_Win
xchg edi , esi
IF TRANSP
test [ trans ] , 1
jnz ??tomem_forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??tomem_forward_loop_bytes
??tomem_forward_loop_dword:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??tomem_in_range
xor ecx , ecx
mov ebx , eax
cmp esi , 0b0000h
jge ??tomem_no_trailing
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??tomem_no_trailing:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
dec edx ; decrement the height
jnz ??tomem_forward_loop_dword
mov edx , [ cpu_video_page ]
mov [ mem_page ] , edx
retn
??tomem_in_range:
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_ajust_width ]
dec edx
jnz ??tomem_forward_loop_dword
mov edx , [ cpu_video_page ]
mov [ mem_page ] , edx
retn
??tomem_forward_loop_bytes:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??tomem_in_range_bytes
xor ecx , ecx
cmp esi , 0b0000h
jge ??tomem_no_trailing_bytes
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??tomem_no_trailing_bytes:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
??tomem_in_range_bytes:
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
dec edx ; decrement the height
jnz ??tomem_forward_loop_bytes
mov edx , [ cpu_video_page ]
mov [ mem_page ] , edx
retn
IF TRANSP
??tomem_forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??tomem_transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??tomem_forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??tomem_forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
inc esi
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc edi
ENDM
??tomem_transp_reference:
dec ecx
jge ??tomem_forward_trans_line
add esi , [ scr_ajust_width ]
dec edx
jnz ??tomem_forward_loop_trans
mov edx , [ cpu_video_page ]
mov [ mem_page ] , edx
retn
ENDIF
;*************************************************************************
; copy from memory to vesa page
??memory_to_vesa:
add edi , [ vesa_page ]
Call Vesa_Asm_Set_Win
IF TRANSP
test [ trans ] , 1
jnz ??tovesa_forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??tovesa_forward_loop_bytes
??tovesa_forward_loop_dword:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??tovesa_in_range
xor ecx , ecx
cmp edi , 0b0000h
mov ebx , eax
jge ??tovesa_no_trailing
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??tovesa_no_trailing:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
mov ecx , ebx
rep movsb
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??tovesa_forward_loop_dword
mov edx , [ cpu_video_page ]
mov [ vesa_page ] , edx
retn
??tovesa_in_range:
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 edi , [ dest_ajust_width ]
dec edx
jnz ??tovesa_forward_loop_dword
mov edx , [ cpu_video_page ]
mov [ vesa_page ] , edx
retn
??tovesa_forward_loop_bytes:
lea ebx , [ edi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??tovesa_in_range_bytes
xor ecx , ecx
cmp edi , 0b0000h
jge ??tovesa_no_trailing_bytes
mov ecx , 0b0000h
sub ecx , edi
sub ebx , ecx
rep movsb
??tovesa_no_trailing_bytes:
add edi , [ cpu_video_page ]
Call Vesa_Asm_Set_Win ; set the window
??tovesa_in_range_bytes:
mov ecx , ebx
rep movsb
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??tovesa_forward_loop_bytes
mov edx , [ cpu_video_page ]
mov [ vesa_page ] , edx
retn
IF TRANSP
??tovesa_forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??tovesa_transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??tovesa_forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??tovesa_forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??tovesa_transp_reference:
dec ecx
jge ??tovesa_forward_trans_line
add edi , [ dest_ajust_width ]
dec edx
jnz ??tovesa_forward_loop_trans
mov edx , [ cpu_video_page ]
mov [ vesa_page ] , edx
retn
ENDIF
ENDP Vesa_Blit_To_Vesa
END

View File

@@ -0,0 +1,409 @@
;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : June 8, 1994 *
;* *
;* Last Update : December 13, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "svgaprim.inc"
INCLUDE "gbuffer.inc"
TRANSP equ 0
CODESEG
;***************************************************************************
;* GVC::BLIT -- Copies a buffer to a graphic page non-linearly *
;* *
;* NOTE: All coordinate values are expressed in pixels *
;* *
;* INPUT: VirtualViewPortClass *dest - Virtual View Port to copy to *
;* WORD src_x - Src x position to copy from *
;* WORD src_y - Src y position to copy from *
;* WORD dst_x - Dest x position to copy to *
;* WORD dst_y - Dest y position to copy to *
;* WORD w - Width of region to copy *
;* WORD h - Height of region to copy *
;* *
;* 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. *
;* *
;* HISTORY: *
;* 05/11/1994 PWG : Created. *
;* 08/05/1994 PWG : Fixed clipping problem *
;*=========================================================================*
PROC Vesa_Blit_To_Linear C near
USES ebx,ecx,edx,esi,edi
;*===================================================================
;* define the arguements that our function takes.
;*===================================================================
ARG this :DWORD ; this is a member function
ARG dest :DWORD ; what are we blitting to
ARG x_pixel :DWORD ; x pixel position in source
ARG y_pixel :DWORD ; y pixel position in source
ARG dest_x0 :dword
ARG dest_y0 :dword
ARG pixel_width :DWORD ; width of rectangle to blit
ARG pixel_height:DWORD ; height of rectangle to blit
ARG trans :DWORD ; do we deal with transparents?
;*===================================================================
; Define some locals so that we can handle things quickly
;*===================================================================
LOCAL x1_pixel :dword
LOCAL y1_pixel :dword
LOCAL dest_x1 : dword
LOCAL dest_y1 : dword
LOCAL scr_ajust_width:DWORD
LOCAL dest_ajust_width:DWORD
LOCAL source_area : dword
LOCAL dest_area : dword
; Clip Source Rectangle against source Window boundaries.
mov esi , [ this ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; 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,[ ( VideoViewPort esi) . VIVPHeight ] ; 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 ??clip_against_dest
test cl , 1000b
jz ??scr_left_ok
mov [ x_pixel ] , 0
??scr_left_ok:
test cl , 0010b
jz ??scr_bottom_ok
mov [ y_pixel ] , 0
??scr_bottom_ok:
test dl , 0100b
jz ??scr_right_ok
mov eax , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov [ x1_pixel ] , eax
??scr_right_ok:
test dl , 0001b
jz ??clip_against_dest
mov eax , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov [ y1_pixel ] , eax
; Clip Source Rectangle against destination Window boundaries.
??clip_against_dest:
mov eax , [ dest_x0 ]
mov ebx , [ dest_y0 ]
sub eax , [ x_pixel ]
sub ebx , [ y_pixel ]
add eax , [ x1_pixel ]
add ebx , [ y1_pixel ]
mov [ dest_x1 ] , eax
mov [ dest_y1 ] , ebx
mov esi , [ dest ] ; get ptr to src
xor ecx , ecx
xor edx , edx
mov edi , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x0 ]
mov ebx , [ dest_x1 ]
shld ecx , eax , 1
inc edi
shld edx , ebx , 1
sub eax , edi
sub ebx , edi
shld ecx , eax , 1
shld edx , ebx , 1
mov edi,[ ( VideoViewPort esi) . VIVPHeight ] ; get height into register
mov eax , [ dest_y0 ]
mov ebx , [ dest_y1 ]
shld ecx , eax , 1
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 , [ dest_x0 ]
mov [ dest_x0 ] , 0
sub [ x_pixel ] , eax
??dest_left_ok:
test cl , 0010b
jz ??dest_bottom_ok
mov eax , [ dest_y0 ]
mov [ dest_y0 ] , 0
sub [ y_pixel ] , eax
??dest_bottom_ok:
test dl , 0100b
jz ??dest_right_ok
mov ebx , [ (VideoViewPort esi) . VIVPWidth ] ; get width into register
mov eax , [ dest_x1 ]
mov [ dest_x1 ] , ebx
sub eax , ebx
sub [ x1_pixel ] , eax
??dest_right_ok:
test dl , 0001b
jz ??do_blit
mov ebx , [ (VideoViewPort esi) . VIVPHeight ] ; get width into register
mov eax , [ dest_y1 ]
mov [ dest_y1 ] , ebx
sub eax , ebx
sub [ y1_pixel ] , eax
??do_blit:
cld
mov ebx , [ this ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ y_pixel ]
add edi , [ x_pixel ]
mov [ source_area ] , ecx
add edi , eax
call Vesa_Asm_Set_Win ; set the window
mov esi , edi
add ecx , [ x_pixel ]
sub ecx , [ x1_pixel ]
mov [ scr_ajust_width ] , ecx
mov ebx , [ dest ]
mov edi , [ (VideoViewPort ebx) . VIVPOffset ]
mov eax , [ (VideoViewPort ebx) . VIVPXAdd ]
add eax , [ (VideoViewPort ebx) . VIVPWidth ]
mov ecx , eax
mul [ dest_y0 ]
add edi , [ dest_x0 ]
mov [ dest_area ] , ecx
add edi , eax
mov eax , [ dest_x1 ]
sub eax , [ dest_x0 ]
jz ??real_out
sub ecx , eax
mov [ dest_ajust_width ] , ecx
mov edx , [ dest_y1 ]
sub edx , [ dest_y0 ]
jz ??real_out
; ********************************************************************
; Forward bitblit only
IF TRANSP
test [ trans ] , 1
jnz ??forward_Blit_trans
ENDIF
; 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
cmp eax , 10
jl ??forward_loop_bytes
??forward_loop_dword:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
jl ??in_range
xor ecx , ecx
mov ebx , eax
cmp esi , 0b0000h
jge ??no_trailing
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??no_trailing:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_dword
ret
??in_range:
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_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_dword
ret
??forward_loop_bytes:
lea ebx , [ esi + eax ]
add ebx , [ cpu_video_page ]
cmp ebx , [ cpu_page_limit ]
mov ebx , eax
jl ??in_range_bytes
xor ecx , ecx
cmp esi , 0b0000h
jge ??no_trailing_bytes
mov ecx , 0b0000h
sub ecx , esi
sub ebx , ecx
rep movsb
??no_trailing_bytes:
add esi , [ cpu_video_page ]
xchg edi , esi
Call Vesa_Asm_Set_Win ; set the window
xchg edi , esi
??in_range_bytes:
mov ecx , ebx
rep movsb
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx ; decrement the height
jnz ??forward_loop_bytes
ret
IF TRANSP
??forward_Blit_trans:
mov ecx , eax
and ecx , 01fh
lea ecx , [ ecx + ecx * 4 ]
neg ecx
shr eax , 5
lea ecx , [ ??transp_reference + ecx * 2 ]
mov [ y1_pixel ] , ecx
??forward_loop_trans:
mov ecx , eax
jmp [ y1_pixel ]
??forward_trans_line:
REPT 32
local transp_pixel
mov bl , [ esi ]
test bl , bl
jz transp_pixel
mov [ edi ] , bl
transp_pixel:
inc esi
inc edi
ENDM
??transp_reference:
dec ecx
jge ??forward_trans_line
add esi , [ scr_ajust_width ]
add edi , [ dest_ajust_width ]
dec edx
jnz ??forward_loop_trans
ret
ENDIF
??real_out:
ret
ENDP Vesa_Blit_To_Linear
END

View File

@@ -0,0 +1,65 @@
/*
** 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 <http://www.gnu.org/licenses/>.
*/
/***************************************************************************
** 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 : Testing memory. *
* *
* File Name : TEST.CPP *
* *
* Programmer : Julio Jerez *
* *
* Start Date : Feb 13, 1995 *
* *
* *
*-------------------------------------------------------------------------*
*/
#include <mcgaprim.h>
#include <gbuffer.h>
#include <vbuffer.h>
int Vesa_Scale_To_Linear ( void * scr, void * dst,
int src_x , int src_y , int dst_x , int dst_y ,
int src_wd , int src_hg , int dst_wd, int dst_hg,
BOOL trans , char * remap )
{
int area ;
int width , height ;
char * temp ;
VideoViewPortClass * scr1 = ( VideoViewPortClass * ) scr ;
width = src_wd - src_x ;
height = src_hg - src_y ;
area = width * height ;
temp = ( char * ) malloc ( area ) ;
if ( ! temp ) return 0 ;
scr1 -> To_Buffer ( 0, 0, width , height , temp, area );
GraphicBufferClass tempbuffer ( area , width , height , temp ) ;
Linear_Scale_To_Linear ( & tempbuffer , dst ,
0 , 0 , dst_x , dst_y ,
width , height , dst_wd , dst_hg ,
trans , remap ) ;
free ( temp ) ;
return 0 ;
}