CnC_Remastered_Collection/TIBERIANDAWN/WINASM.ASM
PG-SteveT 03416d24e1 Initial Source Code commit
Initial commit of original Tiberian Dawn and Red Alert source code converted to build as DLLs, and compatible with the release version of Command & Conquer Remastered.
2020-05-27 12:16:20 -07:00

888 lines
16 KiB
NASM

;
; Copyright 2020 Electronic Arts Inc.
;
; TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
; in the hope that it will be useful, but with permitted additional restrictions
; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
; distributed with this program. You should have received a copy of the
; GNU General Public License along with permitted additional restrictions
; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
;***************************************************************************
;** 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 I N C **
;***************************************************************************
;* *
;* Project Name : Command & Conquer *
;* *
;* File Name : WINSAM.ASM *
;* *
;* Programmer : Steve Tall *
;* *
;* Start Date : October 26th, 1995 *
;* *
;* Last Update : October 26th, 1995 [ST] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
global C _AbortModemFunctionPtr:dword
global C Memory_Error_Exit :dword
global C MouseQX :dword
global C MouseQY :dword
global FastGetPortHardware_ :near
global FastSetPortHardware_ :near
global PortOpenGreenleafFast_ :near
global HMWaitForOK_ :near
global HMSetDialingMethod_ :near
global HMDial_ :near
global HMInputLine_ :near
global HMAnswer_ :near
global PortKillTime_ :near
global HMSendStringNoWait_ :near
global HMSetUpEchoRoutine_ :near
global HMSetUpAbortKey_ :near
global SetAbortModemFunctionPtr_:near
global Change8259Priority_ :near
global HMSendString_ :near
global C Stop_Execution :near
global _IPX_Initialise:near
global _ASM_IPX_Initialise:near
codeseg
proc _ASM_IPX_Initialise near
int 3
jmp _IPX_Initialise
endp
global _Int3:near
proc _Int3 near
;int 3
ret
endp
proc Stop_Execution C near
nop
ret
endp
;
; Stuff needed from the shape library
;
;
;
INCLUDE "shape.inc"
;***************************************************************************
;* ModeX_Blit -- Copy a 320x200 graphic view port to a modex screen *
;* *
;* *
;* INPUT: eax - graphic view port *
;* *
;* OUTPUT: none *
;* *
;* PROTO: extern "C" void ModeX_Blit (GraphicBufferClass *source); *
;* *
;* HISTORY: *
;* 10/26/1994 PWG : Created. *
;*=========================================================================*
SEQUENCER =3c4h ; sequencer port
MAP_MASK =2 ; map mask register
INCLUDE "gbuffer.inc"
global ModeX_Blit_:near
proc ModeX_Blit_ NEAR
pushad
mov ebx,eax
mov esi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov edi,0a0000h
mov ebx,eax
mov al,MAP_MASK
mov ebp,200
??each_line_lp: mov ah,1 ;1st plane
push ebx
push esi
??each_plane_lp:mov edx,SEQUENCER
out dx,ax
push esi
push edi
push eax
rept 10
mov al,[esi]
mov bl,[esi+8]
mov cl,[esi+16]
mov dl,[esi+24]
mov ah,[esi+4]
mov bh,[esi+12]
mov ch,[esi+20]
mov dh,[esi+28]
shl ebx,16
shl edx,16
or ebx,eax
or edx,ecx
mov [edi],ebx
mov [edi+4],edx
add esi,32
add edi,8
endm
pop eax
pop edi
pop esi
inc esi
shl ah,1
cmp ah,16
jl ??each_plane_lp
pop esi
pop ebx
lea esi,[esi+ebx+320]
add edi,80
dec ebp
jnz ??each_line_lp
popad
ret
endp ModeX_Blit_
ifdef cuts
pushad
mov ebx,eax
mov esi,[(GraphicViewPort ebx).GVPOffset]
mov eax,[(GraphicViewPort ebx).GVPXAdd]
add eax,[(GraphicViewPort ebx).GVPPitch]
mov edi,0a0000h
mov ebx,eax
mov al,MAP_MASK
mov ah,1 ;1st plane
??each_plane_lp:mov edx,SEQUENCER
out dx,ax
mov ebp,200 ;do 200 lines
push esi
push edi
??each_line_lp: mov ecx,320/4
??each_pixel_lp:mov dl,[esi]
mov [edi],dl
add esi,4
inc edi
dec ecx
jnz ??each_pixel_lp
add esi,ebx
dec ebp
jnz ??each_line_lp
pop edi
pop esi
inc esi
shl ah,1
cmp ah,16
jl ??each_plane_lp
endif
proc FastGetPortHardware_ NEAR
endp
proc FastSetPortHardware_ NEAR
endp
proc PortOpenGreenleafFast_ NEAR
endp
proc HMWaitForOK_ NEAR
endp
proc HMSetDialingMethod_ NEAR
endp
proc HMDial_ NEAR
endp
proc HMInputLine_ NEAR
endp
proc HMAnswer_ NEAR
endp
proc PortKillTime_ NEAR
endp
proc HMSendStringNoWait_ NEAR
endp
proc HMSetUpEchoRoutine_ NEAR
endp
proc HMSetUpAbortKey_ NEAR
endp
proc SetAbortModemFunctionPtr_ NEAR
endp
proc Change8259Priority_ NEAR
endp
proc HMSendString_ NEAR
endp
ret
masm
;
; Change a DAC colour register directly
;
; register number in al
;
; bh=red bl=green cl=blue
;
set_dac_col proc near
pushad
cli
push eax
mov dx,03dah
in al,dx
jmp @@1
@@1: mov dx,03c8h
pop eax
out dx,al
jmp @@2
@@2: inc dl
mov al,bh
out dx,al
jmp @@3
@@3: mov al,bl
out dx,al
jmp @@4
@@4: mov al,cl
out dx,al
jmp @@5
@@5: sti
popad
ret
set_dac_col endp
ideal
global Set_Palette_Register_:near
proc Set_Palette_Register_ near
pushad
and cl,63
mov bh,dl
and bh,63
and bl,63
call set_dac_col
popad
ret
endp Set_Palette_Register_
locals ??
ends
dataseg
LineBuffer dd 640 dup (?)
ends
segment mycode page public use32 'code' ; Need stricter segment alignment
global C Asm_Interpolate:near
global C Asm_Interpolate_Line_Double:near
global C Asm_Interpolate_Line_Interpolate:near
global C PaletteInterpolationTable:byte
;*********************************************************************************************
;* Asm_Interpolate -- interpolate a 320x200 buffer to a 640x400 screen *
;* *
;* INPUT: ptr to source buffer (320x200 image) *
;* ptr to dest buffer (640x400) *
;* height of source buffer *
;* width of source buffer *
;* width of dest buffer *
;* *
;* *
;* OUTPUT: none *
;* *
;* Warnings: *
;* *
;* HISTORY: *
;* 12/15/95 ST : Created. *
;*===========================================================================================*
PROC Asm_Interpolate C near
ARG src_ptr:dword
ARG dest_ptr:dword
ARG source_height:dword
ARG source_width:dword
ARG dest_width:dword
LOCAL old_dest:dword
pushad
mov eax,[dest_ptr]
mov [old_dest],eax
mov esi,[src_ptr]
??each_line_loop:
mov ecx,[source_width]
sub ecx,2
shr ecx,1
mov edi,[old_dest]
jmp ??interpolate_loop
align 32
;
; convert 2 pixels of source into 4 pixels of destination
; so we can write to video memory with dwords
;
??interpolate_loop:
mov eax,[esi]
lea esi,[esi+2]
mov edx,eax
mov ebx,eax
and edx,65535
ror ebx,8
mov bl,[edx+PaletteInterpolationTable]
mov bh,ah
and eax,000ffff00h
ror ebx,8
;1st 3 pixels now in ebx
shr eax,8
mov bh,[eax+PaletteInterpolationTable]
ror ebx,16
mov [edi],ebx
add edi,4
dec ecx
jnz ??interpolate_loop
; do the last three pixels and a blank on the end of a row
xor eax,eax
mov ax,[esi]
mov [edi],al
inc edi
lea esi,[esi+2]
mov al,[eax+PaletteInterpolationTable]
mov [edi],al
inc edi
mov [edi],ah
inc edi
mov [byte edi],0
mov edi,[dest_width]
add [old_dest],edi
dec [source_height]
jnz ??each_line_loop
popad
ret
endp Asm_Interpolate
PROC Asm_Interpolate_Line_Double C near
ARG src_ptr:dword
ARG dest_ptr:dword
ARG source_height:dword
ARG source_width:dword
ARG dest_width:dword
LOCAL old_dest:dword
LOCAL width_counter:dword
LOCAL pixel_count:dword
pushad
mov eax,[dest_ptr]
mov [old_dest],eax
mov esi,[src_ptr]
mov edi,[dest_ptr]
??each_line_loop:
mov [width_counter],0
mov ecx,[source_width]
sub ecx,2
shr ecx,1
mov [pixel_count],ecx
mov ecx,offset LineBuffer
mov edi,[old_dest]
jmp ??interpolate_loop
align 16
; convert 2 pixels of source into 4 pixels of destination
??interpolate_loop:
mov eax,[esi]
lea esi,[esi+2]
mov edx,eax
mov ebx,eax
and edx,65535
ror ebx,8
mov bl,[edx+PaletteInterpolationTable]
mov bh,ah
and eax,000ffff00h
ror ebx,8
;1st 3 pixels now in ebx
shr eax,8
mov bh,[eax+PaletteInterpolationTable]
ror ebx,16
mov [edi],ebx
mov [ecx],ebx
add edi,4
add ecx,4
dec [pixel_count]
jnz ??interpolate_loop
; do the last three pixels and a blank
xor eax,eax
mov ax,[esi]
mov [edi],al
mov [ecx],al
inc edi
inc ecx
lea esi,[esi+2]
mov al,[eax+PaletteInterpolationTable]
mov [edi],al
mov [ecx],al
inc edi
inc ecx
mov [edi],ah
mov [ecx],ah
inc edi
inc ecx
mov [byte edi],0
mov [byte ecx],0
mov edi,[dest_width]
shr edi,1
add [old_dest],edi
push esi
push edi
mov esi,offset LineBuffer
mov edi,[old_dest]
mov ecx,[source_width]
shr ecx,1
rep movsd
pop edi
pop esi
add [old_dest],edi
mov edi,[old_dest]
dec [source_height]
jnz ??each_line_loop
popad
ret
endp Asm_Interpolate_Line_Double
ends
dataseg
TopLine dd 640 dup (?)
BottomLine dd 640 dup (?)
segment mycode page public use32 'code' ; Need stricter segment alignment
proc Interpolate_Single_Line C near
ARG source_ptr:dword
ARG dest_ptr:dword
ARG source_width:dword
pushad
mov ecx,[source_width]
sub ecx,2
shr ecx,1
mov esi,[source_ptr]
mov edi,[dest_ptr]
??interpolate_loop:
mov eax,[esi]
lea esi,[esi+2]
mov edx,eax
mov ebx,eax
and edx,65535
ror ebx,8
mov bl,[edx+PaletteInterpolationTable]
mov bh,ah
and eax,000ffff00h
ror ebx,8
;1st 3 pixels now in ebx
shr eax,8
mov bh,[eax+PaletteInterpolationTable]
ror ebx,16
mov [edi],ebx
add edi,4
dec ecx
jnz ??interpolate_loop
; do the last three pixels and a blank
xor eax,eax
mov ax,[esi]
mov [edi],al
inc edi
mov al,[eax+PaletteInterpolationTable]
mov [edi],al
inc edi
mov [edi],ah
inc edi
mov [byte edi],0
popad
ret
endp Interpolate_Single_Line
proc Interpolate_Between_Lines C near
ARG source1:dword
ARG source2:dword
ARG destination:dword
ARG source_width:dword
pushad
mov esi,[source1]
mov edi,[destination]
mov ebx,[source2]
xor eax,eax
mov ecx,[source_width]
add ecx,ecx
??interpolate_each_pixel_loop:
mov al,[esi]
mov ah,[ebx]
inc esi
inc ebx
mov dl,[eax+PaletteInterpolationTable]
mov [edi],dl
inc edi
dec ecx
jnz ??interpolate_each_pixel_loop
popad
ret
endp Interpolate_Between_Lines
macro Lineswp
push [next_line]
push [last_line]
pop [next_line]
pop [last_line]
endm
PROC Asm_Interpolate_Line_Interpolate C near
ARG src_ptr:dword
ARG dest_ptr:dword
ARG source_lines:dword
ARG source_width:dword
ARG dest_width:dword
LOCAL old_dest:dword
LOCAL pixel_count:dword
LOCAL next_line:dword
LOCAL last_line:dword
pushad
mov eax,[dest_ptr]
mov [old_dest],eax
mov [next_line],offset TopLine
mov [last_line],offset BottomLine
mov ecx,[source_width]
shr ecx,1
mov [pixel_count],ecx
shr [dest_width],1
call Interpolate_Single_Line C,[src_ptr],[next_line],[source_width]
mov esi,[source_width]
Lineswp
add [src_ptr],esi
dec [source_lines]
??each_line_pair_loop:
call Interpolate_Single_Line C,[src_ptr],[next_line],[source_width]
call Interpolate_Between_Lines C,[last_line],[next_line],offset LineBuffer,[source_width]
mov esi,[last_line]
mov edi,[old_dest]
mov ecx,[pixel_count]
rep movsd
mov edi,[old_dest]
mov esi,offset LineBuffer
add edi,[dest_width]
mov ecx,[pixel_count]
mov [old_dest],edi
rep movsd
mov edi,[old_dest]
mov esi,[source_width]
add edi,[dest_width]
add [src_ptr],esi
mov [old_dest],edi
Lineswp
dec [source_lines]
jnz ??each_line_pair_loop
call Interpolate_Single_Line C,[src_ptr],[next_line],[source_width]
mov esi,[next_line]
mov edi,[old_dest]
mov ecx,[pixel_count]
rep movsd
popad
ret
endp Asm_Interpolate_Line_Interpolate
ends mycode
global C Asm_Create_Palette_Interpolation_Table:near
global C InterpolationPalette:dword
codeseg
proc Asm_Create_Palette_Interpolation_Table C near
LOCAL palette_counter:dword
LOCAL first_palette:dword
LOCAL second_palette:dword
LOCAL dest_ptr:dword
LOCAL count:dword
LOCAL closest_colour:dword
LOCAL distance_of_closest:dword
pushad
mov [dest_ptr],0
mov [palette_counter],256
mov esi,[InterpolationPalette]
??palette_outer_loop:
mov edi,[InterpolationPalette]
mov ecx,256
??palette_inner_loop:
mov bl,[esi]
add bl,[edi]
shr bl,1
mov bh,[esi+1]
add bh,[edi+1]
shr bh,1
mov dl,[esi+2]
add dl,[edi+2]
shr dl,1
mov [closest_colour],0
mov [distance_of_closest],-1
push edi
push ecx
mov edi,[InterpolationPalette]
mov [count],0
??cmp_pal_lp: xor eax,eax
xor ecx,ecx
mov al,[edi]
sub al,bl
imul al
mov ecx,eax
mov al,[edi+1]
sub al,bh
imul al
add ecx,eax
mov al,[edi+2]
sub al,dl
imul al
add ecx,eax
cmp ecx,[distance_of_closest]
ja ??end_cmp_lp
mov [distance_of_closest],ecx
mov eax,[count]
mov [closest_colour],eax
test ecx,ecx
jz ??got_perfect
??end_cmp_lp: lea edi,[edi+3]
inc [count]
cmp [count],256
jb ??cmp_pal_lp
??got_perfect: mov edi,[dest_ptr]
mov eax,[closest_colour]
mov [edi+PaletteInterpolationTable],al
inc [dest_ptr]
pop ecx
pop edi
lea edi,[edi+3]
dec ecx
jnz ??palette_inner_loop
lea esi,[esi+3]
dec [palette_counter]
jnz ??palette_outer_loop
popad
ret
endp Asm_Create_Palette_Interpolation_Table
DATASEG
_AbortModemFunctionPtr dd 0
Memory_Error_Exit dd 0
MouseQX dd 0
MouseQY dd 0
end