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.
This commit is contained in:
parent
ea8ecc76fa
commit
03416d24e1
1038 changed files with 629779 additions and 0 deletions
316
REDALERT/IPXREAL.ASM
Normal file
316
REDALERT/IPXREAL.ASM
Normal file
|
@ -0,0 +1,316 @@
|
|||
;
|
||||
; 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 **
|
||||
;***************************************************************************
|
||||
;* *
|
||||
;* Project Name : VQLIB *
|
||||
;* *
|
||||
;* File Name : HANDLER.ASM *
|
||||
;* *
|
||||
;* Programmer : Bill Randolph *
|
||||
;* *
|
||||
;* Start Date : April 7, 1995 *
|
||||
;* *
|
||||
;* Last Update : April 7, 1995 [BRR] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* IPXHandler -- callback routine for IPX *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
;********************* Model & Processor Directives ************************
|
||||
IDEAL
|
||||
MODEL LARGE
|
||||
P386N
|
||||
LOCALS ??
|
||||
|
||||
|
||||
;******************************** Includes *********************************
|
||||
|
||||
|
||||
;******************************** Defines ***********************************
|
||||
|
||||
|
||||
;****************************** Declarations ********************************
|
||||
GLOBAL IPXHandler:FAR
|
||||
|
||||
|
||||
;********************************* Code ************************************
|
||||
CODESEG
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; The markers let the application verify that it's mapping this memory
|
||||
; correctly.
|
||||
;---------------------------------------------------------------------------
|
||||
Marker1 DW 1111h ; placeholder to find data start
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; This is the IPX Event Control Block:
|
||||
;---------------------------------------------------------------------------
|
||||
ECB_LinkAddress DD ?
|
||||
ECB_EventServiceRoutine DD ? ; Event Handler ptr
|
||||
ECB_InUse DB ? ; 0 = event is complete
|
||||
ECB_CompletionCode DB ? ; 0 = OK, IPX error otherwise
|
||||
ECB_SocketNumber DW ? ; socket to listen/send on
|
||||
ECB_ConnectionID DW ?
|
||||
ECB_RestOfWorkspace DW ?
|
||||
ECB_DriverWorkSpace DB 12 DUP (?)
|
||||
ECB_ImmediateAddress DB 6 DUP (?) ; bridge address
|
||||
ECB_PacketCount DW ? ; # data areas (2)
|
||||
ECB_HeaderAddress DD ? ; ptr to IPX header buffer
|
||||
ECB_HeaderLength DW ? ; length of IPX header buffer
|
||||
ECB_PacketAddress DD ? ; ptr to packet buffer
|
||||
ECB_PacketLength DW ? ; length of packet buffer
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; The rest of the variables are for telling IPX which buffer to store the
|
||||
; next incoming packet in. They must be initialized by the application.
|
||||
;---------------------------------------------------------------------------
|
||||
NumBufs DW 0 ; # buffers provided by app
|
||||
BufferFlags DD 0 ; array of in-use flags (1 = in use)
|
||||
PacketSize DW 0 ; total size of 1 buf (incl IPX hdr)
|
||||
FirstPacketBuf DD 0 ; ptr to 1st packet buffer
|
||||
CurIndex DW 0 ; current packet/flag index
|
||||
CurPacketBuf DD 0 ; ptr to current packet buf
|
||||
FuncOffset DW StartLabel ; offset of our routine
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; These values are for preventing re-entrancy; they're currently not used.
|
||||
;---------------------------------------------------------------------------
|
||||
Semaphore DB 0 ; prevents re-entrancy
|
||||
ReEntrantCount DW 0 ; times we've been called re-entrantly
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Local stack space
|
||||
;---------------------------------------------------------------------------
|
||||
StackPtr DW 0 ; saved copy of stack ptr
|
||||
StackSeg DW 0 ; saved copy of stack seg
|
||||
StackPtr_int DW 0 ; our internal stack ptr
|
||||
StackSeg_int DW 0 ; our internal stack seg
|
||||
StackCheck DW 1234h ; check for stack overflow
|
||||
DW 256 DUP (0) ; stack storage space
|
||||
StackSpace DW 0 ; label for our stack space
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; These bytes mark the end of the real-mode data area
|
||||
;---------------------------------------------------------------------------
|
||||
Marker2 DW 2222h ; placeholder to find data end
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* IPXHandler -- IPX callback routine *
|
||||
;* *
|
||||
;* This routine is assembled as a stand-alone executable, then loaded *
|
||||
;* into low DOS memory by a protected-mode application. *
|
||||
;* *
|
||||
;* INPUT: *
|
||||
;* none. *
|
||||
;* *
|
||||
;* OUTPUT: *
|
||||
;* none. *
|
||||
;* *
|
||||
;* WARNINGS: *
|
||||
;* none. *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 04/07/1995 BRR : Created. *
|
||||
;*=========================================================================*
|
||||
label StartLabel
|
||||
PROC IPXHandler C FAR USES
|
||||
|
||||
;...................................................................
|
||||
; Turn off interrupts; make sure memory copies go forward
|
||||
;...................................................................
|
||||
pushf
|
||||
cli
|
||||
cld
|
||||
|
||||
;...................................................................
|
||||
; Set up segment registers to point DS to CS
|
||||
;...................................................................
|
||||
push ds
|
||||
push ax
|
||||
mov ax,cs
|
||||
mov ds,ax
|
||||
|
||||
;...................................................................
|
||||
; Set up our local stack; save SS & SP first.
|
||||
;...................................................................
|
||||
mov [StackSeg],ss
|
||||
mov [StackPtr],sp
|
||||
mov [StackPtr_int], OFFSET StackSpace
|
||||
mov [StackSeg_int], SEG StackSpace
|
||||
lss sp, [DWORD PTR StackPtr_int]
|
||||
|
||||
|
||||
;...................................................................
|
||||
; Save all registers
|
||||
;...................................................................
|
||||
pushad
|
||||
push es
|
||||
|
||||
;...................................................................
|
||||
; If we've been called re-entrantly, just exit
|
||||
;...................................................................
|
||||
cmp [Semaphore],0
|
||||
jz ??Start_Handler
|
||||
add [ReEntrantCount],1
|
||||
jmp ??Exit_Handler
|
||||
|
||||
??Start_Handler:
|
||||
;...................................................................
|
||||
; Set our semaphore
|
||||
;...................................................................
|
||||
mov [Semaphore],1
|
||||
|
||||
;-------------------------------------------------------------------
|
||||
; Set 'CurIndex' to the index of the next-available receive buffer,
|
||||
; and 'CurPacketBuf to the next-available packet buffer
|
||||
;-------------------------------------------------------------------
|
||||
;...................................................................
|
||||
; Get 'CurIndex' & increment it. Wrap to 0 if we reach 'NumBufs'
|
||||
; Since I'm treating 'CurPacketBuf' as a long integer (and not as
|
||||
; a segment:offset), the entire data area can't be larger than 64K.
|
||||
;...................................................................
|
||||
mov dx,[CurIndex] ; DX = CurIndex
|
||||
mov eax,[CurPacketBuf] ; EAX = current packet buffer addr
|
||||
inc dx ; DX = next index
|
||||
add ax,[PacketSize] ; EAX = next buffer ptr
|
||||
cmp dx,[NumBufs] ; see if DX is past # buffers
|
||||
jb ??Get_Flag
|
||||
mov dx,0 ; wrap to 1st index
|
||||
mov eax,[FirstPacketBuf] ; wrap to 1st packet buffer
|
||||
|
||||
??Get_Flag:
|
||||
;...................................................................
|
||||
; Get the next buffer-in-use flag; if it's 0, load [CurIndex] with
|
||||
; the value of SI (the next index). If it's 1, skip the updating of
|
||||
; the index, flag & buffer ptr.
|
||||
; DX = new CurIndex
|
||||
; EAX = new CurPacketBuf
|
||||
;...................................................................
|
||||
les di,[BufferFlags] ; ES:DI = BufferFlags address
|
||||
mov bx,di ; BX = DI + new CurIndex
|
||||
add bx,dx
|
||||
|
||||
cmp [BYTE PTR es:bx],0 ; compare next flag to 0 (avail)
|
||||
jne ??Set_ECB ; if not avail, skip setting new values
|
||||
|
||||
;...................................................................
|
||||
; The next buffer is available; so, set this buffer's In-Use flag
|
||||
; to 1, and move on to the next buffer. Do not set this buffer's
|
||||
; flag to 1 until we move on to the next buffer, to prevent the
|
||||
; application from reading the currently-in-use packet buffer.
|
||||
; DX = new CurIndex
|
||||
; EAX = new CurPacketBuf
|
||||
; ES:DI = BufferFlags address
|
||||
;...................................................................
|
||||
mov bx,di ; BX = DI + old CurIndex
|
||||
add bx,[CurIndex]
|
||||
mov [BYTE PTR es:bx],1 ; set old BufferFlags value to in-use
|
||||
|
||||
mov [CurIndex],dx ; save new index
|
||||
mov [CurPacketBuf],eax ; save new packet address
|
||||
|
||||
;-------------------------------------------------------------------
|
||||
; Set up the Event Control Block to tell IPX to start listening.
|
||||
; The following entries are filled in by the app, and should be left
|
||||
; alone:
|
||||
; - EventServiceRoutine
|
||||
; - SocketNumber
|
||||
; The rest should be re-initialized. Note that EBX is now pointing
|
||||
; to an unavailable buffer if the next buffer was already in use;
|
||||
; so it must be reloaded with the correct buffer address from
|
||||
; [CurPacketBuf].
|
||||
;-------------------------------------------------------------------
|
||||
??Set_ECB:
|
||||
mov [ECB_LinkAddress],0 ; default
|
||||
mov [ECB_InUse],0 ; default
|
||||
mov [ECB_CompletionCode],0 ; default
|
||||
mov [ECB_ConnectionID],0 ; default
|
||||
mov [ECB_RestOfWorkspace],0 ; default
|
||||
mov [ECB_DriverWorkSpace],0 ; default
|
||||
mov [ECB_ImmediateAddress],0 ; default
|
||||
mov [ECB_PacketCount],2 ; use 2 data areas
|
||||
mov ebx,[CurPacketBuf] ; get current buffer address
|
||||
mov [ECB_HeaderAddress],ebx ; set header address
|
||||
mov [ECB_HeaderLength],30 ; size of IPX header
|
||||
add ebx,30 ; point to past the header
|
||||
mov [ECB_PacketAddress],ebx ; set packet data address
|
||||
mov ax,[PacketSize] ; get size of one buffer
|
||||
sub ax,30 ; remove size of IPX header
|
||||
mov [ECB_PacketLength],ax ; set size of packet data
|
||||
|
||||
;-------------------------------------------------------------------
|
||||
; Clear the IPX header for this packet
|
||||
;-------------------------------------------------------------------
|
||||
les di,[ECB_HeaderAddress] ; ES:DI = IPX Listen Header
|
||||
mov cx,30 ; (30 bytes = size of header)
|
||||
mov al,0
|
||||
rep stosb ; clear to 0's
|
||||
|
||||
;-------------------------------------------------------------------
|
||||
; Command IPX to start listening again.
|
||||
;-------------------------------------------------------------------
|
||||
mov bx,4 ; IPX code for Listen
|
||||
mov ax,ds ; ES = segment of ListenECB
|
||||
mov es,ax
|
||||
mov ax,OFFSET ECB_LinkAddress
|
||||
mov si,ax ; ES:SI = address of ECB
|
||||
int 07ah ; call IPX interrupt
|
||||
|
||||
;...................................................................
|
||||
; Clear our semaphore
|
||||
;...................................................................
|
||||
mov [Semaphore],0
|
||||
|
||||
??Exit_Handler:
|
||||
;...................................................................
|
||||
; Pop values from our local stack
|
||||
;...................................................................
|
||||
pop es
|
||||
popad
|
||||
|
||||
;...................................................................
|
||||
; Check our stack-check value; if the stack has overflowed, generate
|
||||
; a debugger break.
|
||||
;...................................................................
|
||||
cmp [StackCheck],1234h
|
||||
je ??Restore_Stack
|
||||
int 3
|
||||
|
||||
;...................................................................
|
||||
; Restore the stack to its previous value
|
||||
;...................................................................
|
||||
??Restore_Stack:
|
||||
lss sp, [DWORD PTR StackPtr]
|
||||
|
||||
;...................................................................
|
||||
; Pop the rest of the registers
|
||||
;...................................................................
|
||||
pop ax
|
||||
pop ds
|
||||
|
||||
popf
|
||||
|
||||
ret
|
||||
|
||||
ENDP IPXHandler
|
||||
|
||||
END
|
||||
|
||||
;************************** End of handler.asm *****************************
|
Reference in a new issue