| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- ;
- ; Command & Conquer(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 : 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 C 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 *****************************
|