CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

IPXREAL.ASM (13381B)


      1 ;
      2 ; Copyright 2020 Electronic Arts Inc.
      3 ;
      4 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 ; software: you can redistribute it and/or modify it under the terms of 
      6 ; the GNU General Public License as published by the Free Software Foundation, 
      7 ; either version 3 of the License, or (at your option) any later version.
      8 
      9 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 ; in the hope that it will be useful, but with permitted additional restrictions 
     11 ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 ; distributed with this program. You should have received a copy of the 
     13 ; GNU General Public License along with permitted additional restrictions 
     14 ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
     15 
     16 ;***************************************************************************
     17 ;**   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        **
     18 ;***************************************************************************
     19 ;*                                                                         *
     20 ;*                 Project Name : VQLIB                                    *
     21 ;*                                                                         *
     22 ;*                    File Name : HANDLER.ASM                              *
     23 ;*                                                                         *
     24 ;*                   Programmer : Bill Randolph                            *
     25 ;*                                                                         *
     26 ;*                   Start Date : April 7, 1995                            *
     27 ;*                                                                         *
     28 ;*                  Last Update : April 7, 1995   [BRR]                    *
     29 ;*                                                                         *
     30 ;*-------------------------------------------------------------------------*
     31 ;* Functions:                                                              *
     32 ;*   IPXHandler -- callback routine for IPX                                *
     33 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
     34 ;********************* Model & Processor Directives ************************
     35 IDEAL
     36 MODEL LARGE
     37 P386N
     38 LOCALS ??
     39 
     40 
     41 ;******************************** Includes *********************************
     42 
     43 
     44 ;******************************** Defines ***********************************
     45 
     46 
     47 ;****************************** Declarations ********************************
     48 global C	IPXHandler:FAR
     49 
     50 
     51 ;********************************* Code ************************************
     52 	CODESEG
     53 
     54 
     55 ;---------------------------------------------------------------------------
     56 ; The markers let the application verify that it's mapping this memory
     57 ; correctly.
     58 ;---------------------------------------------------------------------------
     59 Marker1			DW 1111h	; placeholder to find data start
     60 
     61 ;---------------------------------------------------------------------------
     62 ; This is the IPX Event Control Block:
     63 ;---------------------------------------------------------------------------
     64 ECB_LinkAddress		DD ?
     65 ECB_EventServiceRoutine	DD ?		; Event Handler ptr
     66 ECB_InUse		DB ?		; 0 = event is complete
     67 ECB_CompletionCode	DB ?		; 0 = OK, IPX error otherwise
     68 ECB_SocketNumber	DW ?		; socket to listen/send on
     69 ECB_ConnectionID	DW ?
     70 ECB_RestOfWorkspace	DW ?
     71 ECB_DriverWorkSpace	DB 12 DUP (?)
     72 ECB_ImmediateAddress	DB 6 DUP (?)	; bridge address
     73 ECB_PacketCount		DW ?		; # data areas (2)
     74 ECB_HeaderAddress	DD ?		; ptr to IPX header buffer
     75 ECB_HeaderLength	DW ?		; length of IPX header buffer
     76 ECB_PacketAddress	DD ? 		; ptr to packet buffer
     77 ECB_PacketLength	DW ?		; length of packet buffer
     78 
     79 ;---------------------------------------------------------------------------
     80 ; The rest of the variables are for telling IPX which buffer to store the
     81 ; next incoming packet in.  They must be initialized by the application.
     82 ;---------------------------------------------------------------------------
     83 NumBufs		DW 0			; # buffers provided by app
     84 BufferFlags	DD 0			; array of in-use flags (1 = in use)
     85 PacketSize	DW 0			; total size of 1 buf (incl IPX hdr)
     86 FirstPacketBuf	DD 0			; ptr to 1st packet buffer
     87 CurIndex	DW 0			; current packet/flag index
     88 CurPacketBuf	DD 0			; ptr to current packet buf
     89 FuncOffset	DW StartLabel		; offset of our routine
     90 
     91 ;---------------------------------------------------------------------------
     92 ; These values are for preventing re-entrancy; they're currently not used.
     93 ;---------------------------------------------------------------------------
     94 Semaphore	DB 0			; prevents re-entrancy
     95 ReEntrantCount	DW 0			; times we've been called re-entrantly
     96 
     97 ;---------------------------------------------------------------------------
     98 ; Local stack space
     99 ;---------------------------------------------------------------------------
    100 StackPtr	DW 0			; saved copy of stack ptr
    101 StackSeg	DW 0			; saved copy of stack seg
    102 StackPtr_int	DW 0			; our internal stack ptr
    103 StackSeg_int	DW 0			; our internal stack seg
    104 StackCheck	DW 1234h		; check for stack overflow
    105 		DW 256 DUP (0)		; stack storage space
    106 StackSpace	DW 0			; label for our stack space
    107 
    108 ;---------------------------------------------------------------------------
    109 ; These bytes mark the end of the real-mode data area
    110 ;---------------------------------------------------------------------------
    111 Marker2		DW 2222h		; placeholder to find data end
    112 
    113 
    114 ;***************************************************************************
    115 ;* IPXHandler -- IPX callback routine					   *
    116 ;*                                                                         *
    117 ;* This routine is assembled as a stand-alone executable, then loaded      *
    118 ;* into low DOS memory by a protected-mode application.                    *
    119 ;*                                                                         *
    120 ;* INPUT:                                                                  *
    121 ;*	none.								   *
    122 ;*									   *
    123 ;* OUTPUT: 			                                           *
    124 ;*	none.								   *
    125 ;*                                                                         *
    126 ;* WARNINGS:                                                               *
    127 ;*	none.								   *
    128 ;* 									   *
    129 ;* HISTORY:                                                                *
    130 ;*   04/07/1995 BRR : Created.                                             *
    131 ;*=========================================================================*
    132 	label StartLabel
    133 	PROC	IPXHandler C FAR USES
    134 
    135 	;...................................................................
    136 	; Turn off interrupts; make sure memory copies go forward
    137 	;...................................................................
    138 	pushf
    139 	cli
    140 	cld
    141 
    142 	;...................................................................
    143 	; Set up segment registers to point DS to CS
    144 	;...................................................................
    145 	push	ds
    146 	push	ax
    147 	mov	ax,cs
    148 	mov	ds,ax
    149 
    150 	;...................................................................
    151 	; Set up our local stack; save SS & SP first.
    152 	;...................................................................
    153 	mov	[StackSeg],ss
    154 	mov	[StackPtr],sp
    155 	mov	[StackPtr_int], OFFSET StackSpace
    156 	mov	[StackSeg_int], SEG StackSpace
    157 	lss	sp, [DWORD PTR StackPtr_int]
    158 
    159 
    160 	;...................................................................
    161 	; Save all registers
    162 	;...................................................................
    163 	pushad
    164 	push	es
    165 
    166 	;...................................................................
    167 	; If we've been called re-entrantly, just exit
    168 	;...................................................................
    169 	cmp	[Semaphore],0
    170 	jz	??Start_Handler
    171 	add	[ReEntrantCount],1
    172 	jmp	??Exit_Handler
    173 
    174 ??Start_Handler:
    175 	;...................................................................
    176 	; Set our semaphore
    177 	;...................................................................
    178 	mov	[Semaphore],1
    179 
    180 	;-------------------------------------------------------------------
    181 	; Set 'CurIndex' to the index of the next-available receive buffer,
    182 	; and 'CurPacketBuf to the next-available packet buffer
    183 	;-------------------------------------------------------------------
    184 	;...................................................................
    185 	; Get 'CurIndex' & increment it.  Wrap to 0 if we reach 'NumBufs'
    186 	; Since I'm treating 'CurPacketBuf' as a long integer (and not as
    187 	; a segment:offset), the entire data area can't be larger than 64K.
    188 	;...................................................................
    189 	mov	dx,[CurIndex]		; DX = CurIndex
    190 	mov	eax,[CurPacketBuf]	; EAX = current packet buffer addr
    191 	inc	dx			; DX = next index
    192 	add	ax,[PacketSize]		; EAX = next buffer ptr
    193 	cmp	dx,[NumBufs]		; see if DX is past # buffers
    194 	jb	??Get_Flag
    195 	mov	dx,0			; wrap to 1st index
    196 	mov	eax,[FirstPacketBuf]	; wrap to 1st packet buffer
    197 
    198 ??Get_Flag:
    199 	;...................................................................
    200 	; Get the next buffer-in-use flag; if it's 0, load [CurIndex] with
    201 	; the value of SI (the next index).  If it's 1, skip the updating of
    202 	; the index, flag & buffer ptr.
    203 	; DX = new CurIndex
    204 	; EAX = new CurPacketBuf
    205 	;...................................................................
    206 	les	di,[BufferFlags]	; ES:DI = BufferFlags address
    207 	mov	bx,di			; BX = DI + new CurIndex
    208 	add	bx,dx
    209 
    210 	cmp	[BYTE PTR es:bx],0	; compare next flag to 0 (avail)
    211 	jne	??Set_ECB		; if not avail, skip setting new values
    212 
    213 	;...................................................................
    214 	; The next buffer is available; so, set this buffer's In-Use flag
    215 	; to 1, and move on to the next buffer.  Do not set this buffer's
    216 	; flag to 1 until we move on to the next buffer, to prevent the
    217 	; application from reading the currently-in-use packet buffer.
    218 	; DX = new CurIndex
    219 	; EAX = new CurPacketBuf
    220 	; ES:DI = BufferFlags address
    221 	;...................................................................
    222 	mov	bx,di			; BX = DI + old CurIndex
    223 	add	bx,[CurIndex]
    224 	mov	[BYTE PTR es:bx],1	; set old BufferFlags value to in-use
    225 
    226 	mov	[CurIndex],dx		; save new index
    227 	mov	[CurPacketBuf],eax	; save new packet address
    228 
    229 	;-------------------------------------------------------------------
    230 	; Set up the Event Control Block to tell IPX to start listening.
    231 	; The following entries are filled in by the app, and should be left
    232 	; alone:
    233 	; - EventServiceRoutine
    234 	; - SocketNumber
    235 	; The rest should be re-initialized.  Note that EBX is now pointing
    236 	; to an unavailable buffer if the next buffer was already in use;
    237 	; so it must be reloaded with the correct buffer address from
    238 	; [CurPacketBuf].
    239 	;-------------------------------------------------------------------
    240 ??Set_ECB:
    241 	mov	[ECB_LinkAddress],0		; default
    242 	mov	[ECB_InUse],0			; default
    243 	mov	[ECB_CompletionCode],0		; default
    244 	mov	[ECB_ConnectionID],0		; default
    245 	mov	[ECB_RestOfWorkspace],0		; default
    246 	mov	[ECB_DriverWorkSpace],0		; default
    247 	mov	[ECB_ImmediateAddress],0	; default
    248 	mov	[ECB_PacketCount],2		; use 2 data areas
    249 	mov	ebx,[CurPacketBuf]		; get current buffer address
    250 	mov	[ECB_HeaderAddress],ebx		; set header address
    251 	mov	[ECB_HeaderLength],30		; size of IPX header
    252 	add	ebx,30				; point to past the header
    253 	mov	[ECB_PacketAddress],ebx		; set packet data address
    254 	mov	ax,[PacketSize]			; get size of one buffer
    255 	sub	ax,30				; remove size of IPX header
    256 	mov	[ECB_PacketLength],ax		; set size of packet data
    257 
    258 	;-------------------------------------------------------------------
    259 	; Clear the IPX header for this packet
    260 	;-------------------------------------------------------------------
    261 	les	di,[ECB_HeaderAddress]		; ES:DI = IPX Listen Header
    262 	mov	cx,30				; (30 bytes = size of header)
    263 	mov	al,0
    264 	rep	stosb				; clear to 0's
    265 
    266 	;-------------------------------------------------------------------
    267 	; Command IPX to start listening again.
    268 	;-------------------------------------------------------------------
    269 	mov	bx,4				; IPX code for Listen
    270 	mov	ax,ds				; ES = segment of ListenECB
    271 	mov	es,ax
    272 	mov	ax,OFFSET ECB_LinkAddress
    273 	mov	si,ax				; ES:SI = address of ECB
    274 	int	07ah				; call IPX interrupt
    275 
    276 	;...................................................................
    277 	; Clear our semaphore
    278 	;...................................................................
    279 	mov	[Semaphore],0
    280 
    281 ??Exit_Handler:
    282 	;...................................................................
    283 	; Pop values from our local stack
    284 	;...................................................................
    285 	pop	es
    286 	popad
    287 
    288 	;...................................................................
    289 	; Check our stack-check value; if the stack has overflowed, generate
    290 	; a debugger break.
    291 	;...................................................................
    292 	cmp	[StackCheck],1234h
    293 	je	??Restore_Stack
    294 	int	3
    295 
    296 	;...................................................................
    297 	; Restore the stack to its previous value
    298 	;...................................................................
    299 ??Restore_Stack:
    300 	lss	sp, [DWORD PTR StackPtr]
    301 
    302 	;...................................................................
    303 	; Pop the rest of the registers
    304 	;...................................................................
    305 	pop	ax
    306 	pop	ds
    307 
    308 	popf
    309 
    310 	ret
    311 
    312 ENDP		IPXHandler
    313 
    314 END
    315 
    316 ;************************** End of handler.asm *****************************