;planes.asm  win32 masm32


.386
.387
.model flat, stdcall
option casemap :none                    ;case sensitivity is set


        include d:\masm32\include\windows.inc

        include d:\masm32\include\user32.inc
        include d:\masm32\include\kernel32.inc
        include d:\masm32\include\gdi32.inc
        include d:\masm32\include\wsock32.inc

        includelib d:\masm32\lib\user32.lib
        includelib d:\masm32\lib\kernel32.lib
        includelib d:\masm32\lib\gdi32.lib
        includelib d:\masm32\lib\wsock32.lib

;MACROS

FXIMUL  MACRO   R0
        IMUL    R0                      ;IMUL EAX,R0
        SHRD    EAX,EDX,esh             ;SHIFT WHOLE PART LEFT AND
        ENDM                            ;FRACTION INTO LOWER BITS

FXIDIV  MACRO   R0
        CDQ                             ;SIGN EXTEND INTO EDX
        SHLD    EDX,EAX,esh             ;SHIFT WHOLE PART INTO EDX AND
        SHL     EAX,esh                 ;FRACTION INTO HIGHER BITS
        IDIV    R0                      ;IDIV EDX:EAX,R0
        ENDM

limitx  macro
        cmp     eax,-40*e
        jnl     limitx1
        add     eax,xmax
        add     eax,e
limitx1:
        cmp     eax,xmax
        jng     limitx2
        sub     eax,xmax
limitx2:
        endm

limity  macro
        cmp     eax,-40*e
        jnl     limity1
        add     eax,ymax
        add     eax,e
limity1:
        cmp     eax,ymax
        jng     limity2
        sub     eax,ymax
limity2:
        endm

limitx0 macro
        cmp     eax,0
        jnl     limitx01
        add     eax,xmax
        add     eax,e
limitx01:
        cmp     eax,xmax
        jng     limitx02
        sub     eax,xmax
limitx02:
        endm

limity0  macro
        cmp     eax,0
        jnl     limity01
        add     eax,ymax
        add     eax,e
limity01:
        cmp     eax,ymax
        jng     limity02
        sub     eax,ymax
limity02:
        endm


        szText MACRO Name, Text:VARARG
          LOCAL lbl
            jmp lbl
              Name db Text,0
            lbl:
        ENDM

        m2m MACRO M1, M2
          push M2
          pop  M1
        ENDM

        return MACRO arg
          mov eax, arg
          ret
        ENDM

;Prototypes

        WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
        WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
        TopXY PROTO   :DWORD,:DWORD
        DlgProc PROTO :HWND, :DWORD, :DWORD, :DWORD

;equates

winX    EQU     640
winY    EQU     480

e       equ     256                     ;fixed.point '1'
esh     equ     8                       ;fractional bit width
WM_SOCKET equ   WM_USER+100

IDC_PORT equ 3002
IDC_EDIT  equ 3000
IDC_OK    equ 3001

.data


DlgName db "IPbox",0
hIcon1  dd      ?

sockbytes dd    ?
sockred dd      ?
sockbuf db      1024 dup (0)
readstat dd     0
wrote   dd      0
recvd   dd      0
answered dd     0

lasterror dd    0
wsadata WSADATA <>
sockError dd    ?
sock    dd      0
sock2   dd      0
connected dd    0

sin sockaddr_in <>
IPAddress db    "000.000.000.000",0,0       ;17bytes
IPPort    db    "00000",0,0                 ;7bytes
Port      dd    0
sockMode  dd    0
debugMode dd    1

draw    dd      0

xf      dd      ?       ;fixed.point xf
yf      dd      ?       ;fixed.point yf
xdiff   dd      ?       ;x difference
ydiff   dd      ?       ;y difference
radius  dd      ?       ;float
angle   dd      ?       ;int
i2      dd      2       ;int
i3      dd      3       ;int
ie      dd      e       ;int, whole fixed.point 1
i128    dd      128     ;half a circle if 256 subarcs are used
rf      dd      40      ;radius factor, limit radius
irf     dd      ?
maxr    dd      19
temp    dd      ?
i1000   dd      700

ThisTick     dd ?
LastTick     dd ?
ElapsedTicks dd ?
SecondTick   dd ?
LastSecond   dd ?
FPSprojected dd ?
FPScount     dd ?
FPScounted   dd ?
LogicTimer   dd ?
regulator    dd 20
regulator1   dd 20

;sprite var format 00  04  08   12   16   20.22 24 28.30 32  36    40    44,   48   52     56
;  name1   dd      wid,len,vidy,vidx,skip,y.y  ,sz,x.x  ,sub,yf.yf,intvl,xf.xf,type,in/out,sprbuf
;          dd      collide,frame,priority,ang,life, y1,x1,y2,x2...
;                  60      64    68       72  76    80 84 88 96


plane0  dd      020,020,000,000,0,000,000,000,0,000,000,000,020,0,0
        dd      0,08,110,0,0
        dd      1600,2000,2400,2800, 3200,3600,4000,4400
        dd      4800,5200,5600,6000, 0,400,800,1200

;               0   4   8   12 16 20  24  28 32 36  40  44  48 52 56
plane1  dd      020,020,000,000,0,000,000,000,0,000,000,000,020,0,0
        dd      0,40,100,0,0
        dd      1600,2000,2400,2800, 3200,3600,4000,4400
        dd      4800,5200,5600,6000, 0,400,800,1200

arrow0  dd      020,020,000,000,1,000,000,000,0,000,000,000,020,0,0
        dd      0,00,100,0,0
        dd      0,400,800,1200,1600, 2000,2400,2800
        dd      3200,3600,4000,4400, 4800,5200,5600,6000

bullet0 dd      020,020,000,000,1,000,000,000,0,000,000,000,020,0,0
        dd      0,00,100,0,0
        dd      0,400,800,1200,1600, 2000,2400,2800
        dd      3200,3600,4000,4400, 4800,5200,5600,6000

guy0    dd      020,020,000,000,0,000,000,000,0,000,000,000,020,0,0
        dd      0,08,090,0,0
        dd      1600,2000,2400,2800, 3200,3600,4000,4400
        dd      4800,5200,5600,6000, 0,400,800,1200

guy1    dd      020,020,000,000,0,000,000,000,0,000,000,000,020,0,0
        dd      0,08,080,0,0
        dd      1600,2000,2400,2800, 3200,3600,4000,4400
        dd      4800,5200,5600,6000, 0,400,800,1200

cur0    dd      020,020,000,000,0,000,000,000,0,000,000,000,020,0,0
        dd      0,00,100,0,0
        dd      0,400,800,1200,1600, 2000,2400,2800
        dd      3200,3600,4000,4400, 4800,5200,5600,6000


arrowtab dd     1
         dd     offset arrow0

sprtab  dd      5
        dd      offset plane0, offset plane1, offset guy0, offset guy1
        dd      offset cur0
        dd      1019 dup (0)


camtab  dd      3                           ;is table of pointers to pointers
        dd      offset play0, offset play1
        dd      offset ecur


wsprite dd      144/4 dup (0)




play0   dd      offset plane0
play1   dd      offset plane1

ecur    dd      offset cur0




r1      dd      0                       ;lower limit           random
r2      dd      99                      ;upper limit           vars
r3      dd      0                       ;seed
r4      dd      54c14f31h               ;seed2

pcxdata db      10                      ; 0 manufacturer
        db      5                       ; 1 version
        db      1                       ; 2 encoding: RLE
        db      8                       ; 3 bits per pixel
        dw      0                       ; 4 x min
        dw      0                       ; 6 y min
        dw      319                     ; 8 x max
        dw      199                     ;10 y max
        dw      320                     ;12 horiz res of creating device
        dw      200                     ;14 vert res of creating device
        db      48 dup (0)              ;16 colormap (EGA)
        db      0                       ;64 reserved
        db      1                       ;65 # planes
        dw      320                     ;66 # bytes per line
        dw      1                       ;68 palette type
        db      58 dup (0)              ;70 filler

file0   db      'ip',0
file1   db      'colors.vga',0          ;file names
file2   db      'plane.pcx',0
file3   db      'tiles.pcx',0
file4   db      'p.map',0
file5   db      'arrow.pcx',0
file6   db      'guy.pcx',0
file7   db      'guy1.pcx',0
file8   db      'bullet.pcx',0
file9   db      'cursor.pcx',0


fileHandle dd   ?                       ;file handle
br      dd      ?                       ;file bytes read
filelen dd      ?                       ;file length

szDisplayName db "Planes",0
CommandLine   dd 0
hWnd          dd 0
hInstance     dd 0


bmInfo  BITMAPINFOHEADER <SIZEOF BITMAPINFOHEADER,720,-560,1,8,BI_RGB,720*560,0,0,0,0>
colrtab dd      256 dup (?)

testnum    dd      1023


hBm     HBITMAP ?                       ;vidbuf handle

hwDC    dd      ?                       ;window DC
hDC     dd      ?                       ;client DC
hBMPDC  dd      ?                       ;vidbuf compatible DC

overrun dd      0
vidbuf  dd      0                       ;pointer to vidbuf pixels
vidbufSz dd     0

tilebuf  dd     ?                       ;pointers to allocated buffers
planebuf dd     ?
filebuf  dd     ?
mapbuf   dd     ?
guybuf   dd     ?
guy1buf  dd     ?
curbuf   dd     ?
arrowbuf dd     ?
bulletbuf dd    ?

cursorX dd      ?                       ;mouse variables
cursorY dd      ?
keyFlags dd     ?

x1      dd      ?                       ;line sub variables
y1      dd      ?
x2      dd      ?
y2      dd      ?
deldy   dd      ?
deldx   dd      ?
dels    dd      ?
delp    dd      ?
delse   dd      ?
delde   dd      ?
delsx   dd      ?
delsy   dd      ?

color   dd      ?

textx   dd      ?                       ;text out x
texty   dd      ?                       ;text out y
asciinum db 256 dup (?)                 ;text out string space
asciinumlen dd ?                        ;text out length


stats   db      '-=Planes=-',0         ; 0 = end of string
        db      13                      ;13 = cr/lf
        db      'ElapsedTicks: ',0
        db      'Regulator: ',0
        db      'CountedFPS: ',0
        db      'LastError: ',0
        db      'RF: ',0
        db      13,'X: ',0
        db      'Y: ',0
        db      'XF: ',0
        db      'YF: ',0
        db      'Radius: ',0
        db      'Angle: ',0

        db      13,'remote: X: ',0
        db      'Y: ',0
        db      'XF: ',0
        db      'YF: ',0



        db      13,'Connected: ',0
        db      'SockError: ',0
        db      'Sock ctr: ',0
        db      'Port: ',0
statse  db      13
        db      0

sm0     db      'Offline',0
sm1     db      'Winsock in limbo...',0
sm2     db      'Calling ',0
sm3     db      'Listing for call...',0
sm4     db      'Connected!',0
smodes  dd      offset sm0,offset sm1,offset sm2,offset sm3,offset sm4

se0     db      'Socket OK',0
se1     db      'Failed to start Winsock',0
se2     db      'Invalid socket',0
se4     db      'Caller socket sync failed',0
se8     db      'Connect failed',0
se16    db      'Connect did not complete',0
se32    db      'Failed to accept connect',0
se64    db      'Answering socket sync failed',0
se128   db      'Failed to close socket',0
se256   db      'Could not close Winsock',0
se512   db      'Socket bind failed',0
se1024  db      'Listen for call failed',0
se2048  db      'Write to socket failed',0
se4096  db      'Reading socket failed',0
se8192  db      'Answering socket re-sync failed',0


serrs   dd      offset se0, offset se1, offset se2, offset se4, offset se8
        dd      offset se16, offset se32, offset se64, offset se128
        dd      offset se256, offset se512, offset se1024,offset se2048
        dd      offset se4096,8192
serrmask dd     ?
serrptr dd      ?
stringbuf db    300 dup(0)
stringctr dd    ?

decobuf dd      ?                       ;pcx decode buffer pointer



palbuf  db      768 dup (?)


orgW    POINT   <>
rect    RECT    <>                  ;upperleft 0,0,width,height
rectW   RECT    <>
rectX0  dd      0                   ;left   x = 0
rectY0  dd      0                   ;top    y = 0
rectX   dd      ?                   ;right  x = client rectangle width-1
rectY   dd      ?                   ;bottom y = client rectangle height-1
rectCols dd     ?                   ;max displayable map Column
rectRows dd     ?                   ;max displayable map Row
centerX dd      ?
centerY dd      ?
LastCentX dd    ?
LastCentY dd    ?

resized dd      0
xmax    dd      ?
ymax    dd      ?
colmax  dd      ?
rowmax  dd      ?
mapsize dd      ?

camptr  dd      offset plane0       ;camera variables
camNumber dd    0
camxf   dd      ?
camyf   dd      ?

worldY  dd      ?                   ;tiler variables
worldX  dd      ?
ty      dd      ?
tx      dd      ?
row     dd      ?
col     dd      ?
wid     dd      ?



.code

start:
        invoke  GetModuleHandle,NULL    ;provides the instance handle
        mov     hInstance,eax

        invoke  GetCommandLine          ;provides the command line address
        mov     CommandLine,eax

        invoke  WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT

        invoke  ExitProcess,eax         ;cleanup & return to operating system


WinMain proc hInst     :DWORD,
             hPrevInst :DWORD,
             CmdLine   :DWORD,
             CmdShow   :DWORD





        LOCAL wc   :WNDCLASSEX          ;Put LOCALs on stack
        LOCAL msg  :MSG

        LOCAL Wwd  :DWORD
        LOCAL Wht  :DWORD
        LOCAL Wtx  :DWORD
        LOCAL Wty  :DWORD



        szText szClassName,"Generic_Class"

;==================================================
; Fill WNDCLASSEX structure with required variables
;==================================================

        mov     wc.cbSize,sizeof WNDCLASSEX
        mov     wc.style,CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
        mov     wc.lpfnWndProc,offset WndProc           ;address of WndProc
        mov     wc.cbClsExtra,NULL
        mov     wc.cbWndExtra,NULL
        m2m     wc.hInstance,hInst                      ;instance handle
        mov     wc.hbrBackground,COLOR_BTNFACE+1        ;system color
        mov     wc.lpszMenuName,NULL
        mov     wc.lpszClassName,offset szClassName     ;window class name
        invoke  LoadIcon,hInst,500                      ;icon ID resource icon
        mov     wc.hIcon,eax
        invoke  LoadCursor,NULL,IDC_ARROW               ;system cursor
        mov     wc.hCursor,eax
        mov     wc.hIconSm,0

        invoke  RegisterClassEx,ADDR wc         ;register the window class

;==============
; Center window
;==============

        mov     Wwd,winX
        mov     Wht,winY

        invoke  GetSystemMetrics,SM_CXSCREEN    ;get screen width in pixels
        invoke  TopXY,Wwd,eax
        mov     Wtx,eax

        invoke  GetSystemMetrics,SM_CYSCREEN    ;get screen height in pixels
        invoke  TopXY,Wht,eax
        mov     Wty,eax

;===================================
; Create the main application window
;===================================

        invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,
                              ADDR szClassName,
                              ADDR szDisplayName,
                              WS_OVERLAPPEDWINDOW,
                              Wtx,Wty,Wwd,Wht,
                              NULL,NULL,
                              hInst,NULL
        mov     hWnd,eax                        ;window handle

        invoke  LoadMenu,hInst,600              ;load resource menu
        invoke  SetMenu,hWnd,eax                ;set it to main window

        invoke  ShowWindow,hWnd,SW_SHOWNORMAL   ;display the window
        invoke  UpdateWindow,hWnd               ;update the display


        invoke  GetDC,hWnd                      ;get window client DC
        mov     hDC,eax                         ; store

        call    setpal                          ;set the palette

        call    getCoords                       ;get client and map Coords
        call    makeVidbuf                      ;create video buffer



        invoke  GlobalAlloc,GMEM_FIXED,256*400  ;allocate buffers
        mov     tilebuf,eax
        cmp     eax,0
        je      memError

        invoke  GlobalAlloc,GMEM_FIXED,38400
        mov     planebuf,eax
        cmp     eax,0
        je      memError

        mov     eax,planebuf
        add     eax,32000
        mov     arrowbuf,eax

        invoke  GlobalAlloc,GMEM_FIXED,19200
        mov     guybuf,eax
        cmp     eax,0
        je      memError

        invoke  GlobalAlloc,GMEM_FIXED,19200
        mov     guy1buf,eax
        cmp     eax,0
        je      memError

        invoke  GlobalAlloc,GMEM_FIXED,6400
        mov     bulletbuf,eax
        cmp     eax,0
        je      memError

        invoke  GlobalAlloc,GMEM_FIXED,6400
        mov     curbuf,eax
        cmp     eax,0
        je      memError


        invoke  GlobalAlloc,GMEM_FIXED,65536*2
        mov     filebuf,eax
        cmp     eax,0
        je      memError

        jmp     memOK

memError:
        szText  TheMsg1,"Memory Allocation Error"
        invoke  MessageBox,hWnd,ADDR TheMsg1,ADDR szDisplayName,MB_OK
        invoke  PostQuitMessage,NULL
        return  0

fileError:
        szText  TheMsg3,"A file specified in Index could not be loaded"
        invoke  MessageBox,hWnd,ADDR TheMsg3,ADDR szDisplayName,MB_OK
        invoke  PostQuitMessage,NULL
        return 0


memOK:

        mov     eax,planebuf            ;load planes
        mov     edx,offset file2
        call    lpcx

        mov     eax,arrowbuf            ;load arrow
        mov     edx,offset file5
        call    lpcx

        mov     eax,tilebuf             ;load tiles
        mov     edx,offset file3
        call    lpcx

        mov     eax,guybuf              ;load guy
        mov     edx,offset file6
        call    lpcx

        mov     eax,guy1buf             ;load guy1
        mov     edx,offset file7
        call    lpcx

        mov     eax,bulletbuf           ;load bullets
        mov     edx,offset file8
        call    lpcx


        mov     eax,curbuf              ;load tile edit cursors
        mov     edx,offset file9
        call    lpcx




        call    isprite                 ;init all sprites


        call    loadip                  ;get ip and port from file

        call    loadmap
        cmp     eax,0
        je      memError

        finit


        mov     LogicTimer,0

;===================================
; Loop until PostQuitMessage is sent
;===================================

.while 1


    invoke PeekMessage, ADDR msg, NULL, 0, 0, PM_REMOVE
    ;invoke  GetMessage, ADDR msg,0,0,0
    .if eax!=0

        .if msg.message == WM_QUIT



            call    stopSock

            invoke  DeleteDC,hBMPDC
            invoke  ReleaseDC,hWnd,hDC



            invoke  PostQuitMessage, msg.wParam  ;quit

            .break
        .else
            invoke TranslateMessage, ADDR msg
            invoke DispatchMessage, ADDR msg
        .endif

    .endif

        cmp     resized,1
        jne     sizeOK
        mov     resized,0
        call    getCoords
        call    makeVidbuf


    sizeOK:


        mov     eax,ThisTick
        mov     LastTick,eax
        invoke  GetTickCount
        mov     ThisTick,eax
        sub     eax,LastTick
        mov     ElapsedTicks,eax




        mov     eax,ElapsedTicks
        add     LogicTimer,eax
        mov     eax,regulator
        cmp     LogicTimer,eax
        jl      skipLogic

        mov     LogicTimer,0





        call    player
        call    player1
        call    guya
        call    guyb
        call    cur

        call    camera
        call    world



    skipLogic:

        cmp     ElapsedTicks,20
        jg      skipVideo

        call    tiler

        mov     ebx,offset sprtab
        call    sprite

        call    doStats

        call    arrow

        invoke  SelectObject,hBMPDC,hBm
        invoke  BitBlt,hDC,0,0,rectX,rectY,hBMPDC,40,40,SRCCOPY


        mov     eax,SecondTick
        mov     LastSecond,eax
        mov     eax,ThisTick
        xor     edx,edx
        mov     ebx,1000
        div     ebx
        mov     SecondTick,eax
        cmp     eax,LastSecond
        je      SameSecond
        mov     eax,FPScount
        mov     FPScounted,eax
        mov     FPScount,0
      SameSecond:
        inc     FPScount

    skipVideo:





.endw

return msg.wParam

WinMain endp


WndProc proc hWin   :DWORD,
             uMsg   :DWORD,
             wParam :DWORD,
             lParam :DWORD

    .if uMsg == WM_COMMAND              ;menu commands

        .if wParam == 1090
            invoke SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL

        .elseif wParam == 1900
            szText TheMsg,"Lame win32 by mcarp"
            invoke MessageBox,hWin,ADDR TheMsg,ADDR szDisplayName,MB_OK

        .elseif wParam == 1000
            call    isprite

        .elseif wParam == 1200
            cmp     sockMode,0
            jne     dontConnect

            mov     eax,offset plane1
            mov     play0,eax
            mov     eax,offset plane0
            mov     play1,eax
            call    isprite

            call    startSock                       ;connect to remote
            mov     sin.sin_family, AF_INET
            mov     sin.sin_addr.S_un.S_addr,INADDR_ANY   ;
            invoke  htons,Port
            mov     sin.sin_port,ax

            INVOKE  bind,sock,addr sin,sizeof sin
            cmp     eax,SOCKET_ERROR
            jne     bindOK1
            or      sockError,512
          bindOK1:

            invoke  inet_addr, addr IPAddress
            mov     sin.sin_addr,eax
            invoke  connect,sock,addr sin,sizeof sin
            cmp     eax,SOCKET_ERROR
            jne     sockOK3
            invoke  WSAGetLastError
            cmp     eax,WSAEWOULDBLOCK
            je      sockOK3
            or      sockError,8
          sockOK3:
            mov     sockMode,2
          dontConnect:

        .elseif wParam == 1210

            cmp     sockMode,0
            jne     dontListen

            mov     eax,offset plane0
            mov     play0,eax
            mov     eax,offset plane1
            mov     play1,eax
            call    isprite

                                                    ;start listening
            call    startSock
            mov     sin.sin_family,AF_INET
            mov     sin.sin_addr.S_un.S_addr,INADDR_ANY
            INVOKE  htons,Port
            mov     sin.sin_port,ax
            INVOKE  WSAAsyncSelect,sock,hWin,WM_SOCKET,FD_ACCEPT
            cmp     eax,SOCKET_ERROR
            jne     lsinkOK
            or      sockError,64
          lsinkOK:
            INVOKE  bind,sock,addr sin,sizeof sin
            cmp     eax,SOCKET_ERROR
            jne     bindOK
            or      sockError,512
          bindOK:
            INVOKE  listen,sock,5      ;Listen for connections
            cmp     eax,SOCKET_ERROR
            jne     listenOK
            or      sockError,1024
          listenOK:
            mov     sockMode,3
          dontListen:

        .elseif wParam == 1220
            call    stopSock            ;stop winsock

        .elseif wParam == 1230
                                        ;start enter IP dialog

            invoke DialogBoxParam,hInstance, addr DlgName,hWin,OFFSET DlgProc,NULL


        .elseif wParam == 1240          ;toggle debug stats
            xor     debugMode,1

        .endif



    .elseif uMsg == WM_CREATE           ;start controls, child windows


    .elseif uMsg == WM_CLOSE            ;exit conditions, file saves, etc


    .elseif uMsg == WM_DESTROY          ;exit process

        invoke  DeleteDC,hBMPDC
        invoke  ReleaseDC,hWnd,hDC

        invoke  PostQuitMessage,NULL
        return  0



    .elseif uMsg == WM_MOUSEMOVE        ;mouse events

        push    eax
        mov     eax,wParam
        mov     keyFlags,eax            ;key flags
        mov     eax,lParam
        and     eax,0FFFFh
        mov     cursorX,eax             ;cursorX
        mov     eax,lParam
        shr     eax,16
        mov     cursorY,eax             ;cursorY
        pop     eax


    .elseif uMsg == WM_SIZE

        mov     resized,1       ;makes WinMain recreate vidbuf at new size



    .elseif uMsg == WM_CHAR
        mov     eax,wParam
        cmp     al,9
        jne     k1

        call    camNext
        jmp     keyx

      k1:

      keyx:

    .elseif uMsg==WM_SOCKET     ; a socket message
            inc readstat

        mov     eax,lParam
        .if ax==FD_CONNECT  ;the low word of lParam contains the event code.
            shr eax,16      ;the error code (if any) is in the high word of lParam
            .if ax==NULL


                invoke  WSAGetLastError
                mov     lasterror,eax

                mov     connected,1
                mov     sockMode,4
                ;<no error occurs so proceed>
             .else
                or   sockError,16

            .endif

        .elseif ax==FD_ACCEPT
            INVOKE  accept,sock,0,0
            cmp     eax,INVALID_SOCKET
            jne     acceptOK
            or      sockError,32
          acceptOK:
            push    sock
            mov     sock,eax
            pop     sock2

            push    eax
            invoke  WSAGetLastError
            mov     lasterror,eax
            pop     eax


            INVOKE  WSAAsyncSelect,eax,hWin,WM_SOCKET,FD_READ or FD_CLOSE
            cmp     eax,SOCKET_ERROR
            jne     syncOK
            or      sockError,8192
          syncOK:
            mov     connected,1
            mov     answered,1
            mov     sockMode,4

        .elseif ax==FD_READ

            call    fdread
            mov     draw,1

        .elseif ax==FD_CLOSE
            call    stopSock

        .endif

    .endif


    invoke DefWindowProc,hWin,uMsg,wParam,lParam  ;default message processing


    ret

WndProc endp




fdread  proc
         cmp    recvd,1
         je     fdreadOK
        invoke ioctlsocket, sock, FIONREAD, addr sockbytes
        .if eax==NULL
            invoke recv, sock, offset sockbuf, sockbytes, 0
            cmp     eax,SOCKET_ERROR
            jne     readOK

            mov     sockred,0
            or      sockError,4096
            mov     ebx,play1
            mov     dword ptr [ebx+16],1
            jmp     readBAD

          readOK:
            mov     sockred,eax
            inc     readstat
          readBAD:
        .endif
            mov     wrote,0
            mov     recvd,1

          fdreadOK:
            invoke  WSAGetLastError
            mov     lasterror,eax

            ret
fdread  endp

getCoords proc
        invoke  GetClientRect,hWnd,offset rect  ;get client area size


        mov     eax,rect.right                  ;check for width/4=int
        and     eax,11b
        cmp     eax,0
        je      getco1

                                                ;do annoying work to force
        invoke  GetWindowRect,hWnd,offset rectW ;client area to rect/4=int

        mov     edx,rectW.right
        sub     edx,rectW.left
        sub     edx,rect.right

        mov     eax,rect.right                  ;client width
        and     eax,0FFFFFFFCh                  ;force to width/4=int
        add     eax,edx                         ; + border width takeup

        mov     edx,rectW.bottom                ;same window height
        sub     edx,rectW.top



        invoke  MoveWindow,hWnd,rectW.left,rectW.top,eax,edx,TRUE

        invoke  GetClientRect,hWnd,offset rect  ;redo get client area size

getco1:
        mov     eax,rect.right                  ; and set max coords
        dec     eax
        mov     rectX,eax
        mov     eax,rect.bottom
        dec     eax
        mov     rectY,eax

        xor     edx,edx
        mov     eax,rect.right
        mov     ebx,20
        div     ebx
        add     eax,2
        mov     rectCols,eax                     ;max map Column

        xor     edx,edx
        mov     eax,rect.bottom
        mov     ebx,20
        div     ebx
        add     eax,2
        mov     rectRows,eax                     ;max map Row

        mov     eax,centerX
        mov     LastCentX,eax
        mov     eax,centerY
        mov     LastCentY,eax


        mov     eax,rect.right
        shr     eax,1
        mov     centerX,eax                     ;client X center

        mov     eax,rect.bottom
        shr     eax,1
        mov     centerY,eax                     ;client Y center



        ret
getCoords endp

makeVidbuf proc
        cmp     vidbuf,0                ;cant kill DC if first time
        je      mv1                     ;   vidbuf=0 if first time

        invoke  DeleteDC,hBMPDC

mv1:
        call    setpal

        mov     eax,rect.right
        add     eax,80
        mov     bmInfo.biWidth,eax
        mov     edx,rect.bottom
        add     edx,80
        neg     edx
        mov     bmInfo.biHeight,edx
        neg     edx
        mul     edx
        mov     bmInfo.biSizeImage,eax
        mov     vidbufSz,eax

        INVOKE  CreateDIBSection,hDC,ADDR bmInfo,DIB_RGB_COLORS,ADDR overrun,NULL,0
        mov     hBm,eax


        INVOKE  CreateCompatibleDC,hDC          ;DC for vidbuf object
        mov     hBMPDC,eax

        invoke  SetBkMode,hBMPDC,TRANSPARENT
        invoke  SetTextColor,hBMPDC,0FFFFFFh


        mov     eax,rect.right                  ;bytes per line
        add     eax,80
        mov     edx,40                          ;40 lines of top overrun
        mul     edx
        add     eax,40                          ;40 pixels overrun at left
        add     eax,overrun                     ; + overrun pointer
        mov     vidbuf,eax                      ;new vidbuf address

        ret
makeVidbuf endp


DlgProc PROC hwnd:HWND,iMsg:DWORD,wParam:WPARAM, lParam:LPARAM
        .if iMsg==WM_INITDIALOG
                invoke GetDlgItem,hwnd,IDC_EDIT
                invoke SetFocus,eax
                invoke SetDlgItemText,hwnd,IDC_EDIT,ADDR IPAddress
                invoke SetDlgItemText,hwnd,IDC_PORT,ADDR IPPort

                invoke LoadIcon,hInstance,500
                mov hIcon1, eax
                invoke SendMessage,hwnd,WM_SETICON,1,hIcon1


        .elseif iMsg==WM_CLOSE
                invoke EndDialog,hwnd,NULL
        .elseif iMsg==WM_COMMAND
                mov eax,wParam
                mov edx,eax
                shr edx,16

                cmp eax,IDC_OK
                jne continueDialog
                    invoke GetDlgItemText,hwnd,IDC_EDIT,ADDR IPAddress,16
                    invoke GetDlgItemText,hwnd,IDC_PORT,ADDR IPPort,7
                    invoke SendMessage,hwnd,WM_CLOSE,NULL,NULL
                    call saveip
              continueDialog:

        .else
                mov eax,FALSE
                ret
        .endif
        mov  eax,TRUE
        ret
DlgProc endp

loadmap proc
        invoke  CreateFile,offset file4,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
        mov     fileHandle,eax
        invoke  ReadFile,fileHandle,offset colmax,8,offset br,0

        mov     eax,colmax
        inc     eax
        mov     ebx,rowmax
        inc     ebx
        mul     ebx
        mov     ecx,eax                 ;rows * cols = map size
        shl     ecx,1                   ; * words
        mov     mapsize,ecx

        invoke  GlobalAlloc,GMEM_FIXED,mapsize
        mov     mapbuf,eax
        cmp     eax,0
        je      loadmapx

        invoke  ReadFile,fileHandle,mapbuf,mapsize,offset br,0

        invoke  CloseHandle,fileHandle

loadmapx:
        mov     eax,colmax
        inc     eax
        mov     ebx,20
        mul     ebx
        dec     eax
        shl     eax,esh
        mov     xmax,eax

        mov     eax,rowmax
        inc     eax
        mov     ebx,20
        mul     ebx
        dec     eax
        shl     eax,esh
        mov     ymax,eax


        ret

loadmap endp

asc2num proc    ;call with esi = offset to string eax returns value
        push    ebx
        push    ecx
        push    edx

        xor     ebx,ebx
        mov     ecx,10
asc2num1:
        mov     bl,[esi]                ;get a digit
        inc     esi                     ;ptr to next char
        cmp     bl,0                    ;end string?
        je      asc2numx                ;yeah, number convered
        sub     bl,48                   ;make digit binary

        mul     ecx                     ;total * 10
        add     eax,ebx                 ;+ digit
        jmp     asc2num1                ;next digit

asc2numx:
        pop     edx
        pop     ecx
        pop     ebx
        ret
asc2num endp

loadip  proc
        invoke  CreateFile,offset file0,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
        mov     fileHandle,eax
        invoke  ReadFile,fileHandle,filebuf,24,offset br,0
        invoke  CloseHandle,fileHandle
        cmp     br,12
        jl      ldipx

        mov     esi,filebuf             ;point to filebuffer
        mov     edi,offset IPAddress    ;fix IPAddress string up to 16 bytes
        mov     ecx,16
ldip1:
        lodsb
        cmp     al,13
        je      ldip2
        cmp     al,10
        je      ldip2
        stosb
        loop    ldip1
ldip2:
        mov     al,0
        stosb
        lodsb   ;skip lf or cr

        mov     edi,offset IPPort       ;fix IPPort string up to 6 bytes
        mov     ecx,6
ldip3:
        lodsb
        cmp     al,13
        je      ldip4
        cmp     al,10
        je      ldip4
        stosb
        loop    ldip3
ldip4:
        mov     al,0
        stosb

        mov     esi,offset IPPort       ;convert port string to binary
        call    asc2num
        mov     Port,eax

ldipx:
        ret
loadip  endp

saveip  proc

        mov     edi,filebuf             ;point to filebuffer
        mov     esi,offset IPAddress    ;fix IPAddress string up to 16 bytes
        mov     ecx,16
        mov     br,0
svip1:
        lodsb
        cmp     al,0
        je      svip2
        stosb
        inc     br
        loop    svip1
svip2:
        mov     al,13
        stosb
        inc     br
        mov     al,10
        stosb
        inc     br

        mov     esi,offset IPPort       ;fix IPPort string up to 6 bytes
        mov     ecx,6
svip3:
        lodsb
        cmp     al,0
        je      svip4
        stosb
        inc     br
        loop    svip3
svip4:
        mov     al,13
        stosb
        inc     br
        mov     al,10
        stosb
        inc     br


        invoke  CreateFile,offset file0,GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
        mov     fileHandle,eax
        invoke  WriteFile,fileHandle,filebuf,br,offset br,0
        invoke  CloseHandle,fileHandle



svipx:
        call    loadip
        ret
saveip  endp



stopSock proc
        cmp     sockMode,0
        je      nostop

        cmp     sock2,0
        je      notsock2
        invoke  closesocket,sock2
notsock2:
        invoke  closesocket,sock                ;stop winsock
        cmp     eax,SOCKET_ERROR
        jne     closeOK
        or      sockError,128
closeOK:
        invoke  WSACleanup
        cmp     eax,SOCKET_ERROR
        jne     cleanupOK
        or      sockError,256
        jmp     cleanupFailed
cleanupOK:
        ;mov     sockError,0
cleanupFailed:
        mov     sockMode,0
        mov     connected,0
        mov     regulator1,20
nostop:
        ret
stopSock endp


startSock proc
        mov     sockError,0
        mov     recvd,0
        mov     wrote,0
        mov     answered,0

        invoke  WSAStartup, 0101h,addr wsadata   ;start winsock
        ;invoke  WSAStartup, 0002h,addr wsadata   ;start winsock
        or      sockError,eax

        ;invoke  socket,AF_INET,SOCK_DGRAM,0    ;Create a DATA GRAM socket for
        invoke  socket,AF_INET,SOCK_STREAM,0  ;Create a stream socket for
        cmp     eax,INVALID_SOCKET             ; internet use
        jne     sockOK
        or      sockError,2
sockOK:
        mov     sock,eax
                                                ;set to asnyc socket

        ;invoke  WSAAsyncSelect,sock,hWnd,WM_SOCKET,FD_READ
        invoke  WSAAsyncSelect,sock,hWnd,WM_SOCKET,FD_CONNECT or FD_READ or FD_CLOSE
        cmp     eax,SOCKET_ERROR
        jne     sockOK1
        or      sockError,4
        ret
sockOK1:
        mov     sockMode,1
        ret
startSock endp



TopXY proc wDim:DWORD, sDim:DWORD

        shr     sDim,1      ; divide screen dimension by 2
        shr     wDim,1      ; divide window dimension by 2
        mov     eax,wDim    ; copy window dimension into eax
        sub     sDim,eax    ; sub half win dimension from half screen dimension

        return  sDim

TopXY endp


setpal  proc
        invoke  CreateFile,offset file1,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
        cmp     eax,INVALID_HANDLE_VALUE
        je      setpalerr
        mov     fileHandle,eax
        invoke  ReadFile,fileHandle,offset palbuf,768,offset br,0
        cmp     eax,0
        je      setpalerr

        invoke  CloseHandle,fileHandle

        mov     ecx,256
        mov     esi,offset palbuf  ;filebuf
        mov     edi,offset colrtab
setpal0:
        xor     eax,eax
        lodsb
        shl     eax,8
        lodsb
        shl     eax,8
        lodsb
        shl     eax,2
        stosd
        loop    setpal0
setpalerr:
        ret

setpal  endp

cls     proc
        mov     edi,overrun
        mov     ecx,vidbufSz
        shr     ecx,2
        mov     eax,0
        rep     stosd

        ret
cls     endp


tiler   proc

        xor     edx,edx                 ;get world Y and limit
        mov     eax,worldY
        cmp     eax,0
        jnl     tiler0
        add     eax,ymax
        add     eax,e
tiler0:
        sar     eax,esh
        mov     ebx,20
        div     ebx
        mov     row,eax                 ;starting row
        mov     ty,edx                  ;tile Y scroll offset

        xor     edx,edx                 ;get world X
        mov     eax,worldX
        cmp     eax,0
        jnl     tiler0a
        add     eax,xmax
        add     eax,e
tiler0a:
        sar     eax,esh
        mov     ebx,20
        div     ebx
        mov     col,eax                 ;starting column
        mov     tx,edx                  ;tile X scroll offset


        mov     eax,ty
        mov     edx,rect.right
        add     edx,80
        mul     edx
        add     eax,tx

        mov     edi,vidbuf              ;scrolled tiling start address
        sub     edi,eax


        mov     ecx,rectRows            ;# tile rows to fill client rect
tiler1:
        push    ecx
        push    edi

        mov     ecx,rectCols            ;# tile columns to file client rect
tiler2:
        push    ecx
        call    tbounds

        mov     eax,row                 ;get tile #
        mov     ebx,colmax
        inc     ebx
        mul     ebx
        add     eax,col                 ;= map index
        mov     ebx,eax
        shl     ebx,1                   ;make word index
        add     ebx,mapbuf              ;+ mapbuf = total map index
        xor     eax,eax
        mov     ax,[ebx]                ;ax = tile #

        mov     edx,400                 ;*400 bytes per tile
        mul     edx
        mov     esi,eax
        add     esi,tilebuf             ;+ tilebuf = tile address

        push    edi

        mov     ecx,20                  ;20 lines per tile
tiler3:
        movsd                           ;tile line
        movsd
        movsd
        movsd
        movsd
        add     edi,rect.right          ;goto the next line address
        add     edi,80
        sub     edi,20                  ; - tile width
        loop    tiler3                  ;next tile line

        pop     edi                     ;next tile address
        add     edi,20


        pop     ecx
        inc     col                     ;next column
        loop    tiler2                  ;next tile


        pop     edi

        mov     eax,rect.right          ;client width * 20 lines
        add     eax,80
        mov     edx,20
        mul     edx

        add     edi,eax                 ;goto the next row address

        pop     ecx
        mov     eax,rectCols
        sub     col,eax                 ;back to first column
        inc     row
        loop    tiler1_long             ;next row

        ret

tiler1_long:
        jmp     tiler1
tiler   endp


tbounds proc
        mov     eax,rowmax

        cmp     row,0                  ;bounds check
        jnl     tbounds1                ; and wrap
        add     row,eax
        inc     row
        jmp     tbounds2
tbounds1:
        cmp     row,eax
        jng     tbounds2
        sub     row,eax
        dec     row
tbounds2:
        mov     eax,colmax

        cmp     col,0
        jnl     tbounds3
        add     col,eax
        inc     col
        jmp     tbounds4

tbounds3:
        cmp     col,eax
        jng     tbounds4
        sub     col,eax
        dec     col
tbounds4:
        ret
tbounds endp


rnd     proc                    ;call w/ r1 = lower limit  r2 = upper limit
        push    eax             ;        r3 = dword seed
        push    edx

        mov     ecx,r3          ;seed
        add     ecx,12345678h   ;
        ror     ecx,11          ;
        mov     r3,ecx          ;new seed

        ;add     ecx,249D62E4h   ;
        ;ror     ecx,3
        ;mov     r3,eax          ;new seed2


        mov     eax,r2          ;upper
        sub     eax,r1          ; - lower
        mul     ecx             ; * seed
        mov     ecx,edx         ;whole part
        add     ecx,r1          ; + lower

        pop     edx
        pop     eax
        ret                     ;return w/ cx = rnd number r1 - r2
rnd     endp


line    proc
        push    ebx
        push    ecx
        push    edx
        push    esi
        push    edi
        push    eax

        mov     esi,1
        mov     edi,1
        mov     edx,y2
        sub     edx,y1
        jge     storey
        neg     edi
        neg     edx
storey:
        mov     deldy,edi
        mov     ecx,x2
        sub     ecx,x1
        jge     storex
        neg     esi
        neg     ecx
storex: mov     deldx,esi
        cmp     ecx,edx
        jge     setdiag
        mov     esi,0
        xchg    ecx,edx
        jmp     storedelsxy
setdiag:
        mov     edi,0
storedelsxy:
        mov     dels,ecx
        mov     delp,edx
        mov     delsx,esi
        mov     delsy,edi
        mov     esi,x1
        mov     edi,y1
        mov     eax,delp
        sal     eax,1
        mov     delse,eax
        sub     eax,ecx
        mov     ebx,eax
        sub     eax,ecx
        mov     delde,eax
        inc     ecx                      ;cx is count


lineloop:
        call    pset

        cmp     ebx,0
        jge     diagonal
straight:
        add     esi,delsx
        add     edi,delsy
        add     ebx,delse
        loop    lineloop
        jmp     lineexit
diagonal:
        add     esi,deldx
        add     edi,deldy
        add     ebx,delde
        loop    lineloop
lineexit:
        pop     eax
        pop     edi
        pop     esi
        pop     edx
        pop     ecx
        pop     ebx
        ret
line    endp


pset    proc
        push    eax                     ;call with  esi = x     edi = y
        push    ebx                     ;           color = 8 color
        push    ecx
        push    edx


        mov     eax,edi                 ;y
        mov     ecx,rect.right          ;* client width
        add     ecx,80
        mul     ecx
        mov     ebx,eax
        add     ebx,esi                 ;+x
        add     ebx,vidbuf              ;+vidbuf

        mov     eax,color
        mov     byte ptr [ebx],al

        pop     edx
        pop     ecx
        pop     ebx
        pop     eax
        ret
pset    endp






lpcx    proc
        mov     decobuf,eax             ;call w/ eax = decode buffer offset
                                        ;        edx = offset to filename

        invoke  CreateFile,edx,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
        mov     fileHandle,eax
        invoke  GetFileSize,fileHandle,0
        mov     filelen,eax
        invoke  ReadFile,fileHandle,filebuf,filelen,offset br,0
        invoke  CloseHandle,fileHandle


        mov     esi,filebuf             ;copy pcxdata
        mov     edi,offset pcxdata
        mov     ecx,128
        rep     movsb

        mov     esi,filebuf             ;copy palette
        add     esi,filelen
        sub     esi,768
        mov     edi,offset colrtab
        mov     ecx,768
lpcxp:
        lodsb
        shr     al,2
        stosb
        loop    lpcxp


        mov     ebx,filebuf
        mov     esi,ebx
        add     esi,128                 ;skip header
        mov     edi,decobuf
        cld

        xor     ecx,ecx

        mov     cx,[ebx+10]             ;y res
        sub     cx,[ebx+6]
        inc     cx
        ;cmp     cx,480
        ;jng     lpcx0
        ;mov     ecx,480

lpcx0:
        push    ecx
        ;push    edi

        xor     ecx,ecx

        mov     cx,[ebx+08]             ;x res
        sub     cx,[ebx+4]
        inc     cx
        cmp     cx,640
        jng     lpcx1
        mov     ecx,640

lpcx1:
        push    ecx
        mov     edx,0

        lodsb                           ;get rle code
        cmp     al,11000000b            ;if top 2 bits, al is run len
        jnb     lpcx2
        stosb                           ;not top 2 bits, runlen = 1, al=data

        jmp     lpcx3
lpcx2:
        and     eax,00111111b
        mov     edx,eax
        dec     edx
        mov     ecx,eax
        lodsb
        rep     stosb
lpcx3:
        pop     ecx
        sub     ecx,edx
        loop    lpcx1


        pop     ecx
        loop    lpcx0

lpcx4:

        ret
lpcx    endp

sbounds proc
        mov     edx,[ebx+12]            ;check x bounds
        cmp     edx,rectX
        jg      sbOUT
        cmp     edx,-40
        jl      sbOUT

        mov     edx,[ebx+8]             ;check y bounds
        cmp     edx,rectY
        jg      sbOUT
        cmp     edx,-40
        jl      sbOUT

        mov     eax,0                  ;is in
        ret

sbOUT:
        mov     eax,1                   ;is out
        ret
sbounds endp


sprite  proc

        ;mov     ebx,offset sprtab  ;ebx now provided on entry, pointer to
        mov     ecx,[ebx]           ; a table of sprites
        add     ebx,4

sprite1:
        push    ecx
        push    ebx

        mov     ebx,[ebx]               ;sprite's variables


        call    toWorld

        cmp     dword ptr [ebx+16],1    ;is dead?
        jne     sprite1b
        jmp     sprite5
sprite1b:

        call    sbounds                 ;is out of bounds?
        cmp     eax,1
        je      sprite5

        mov     esi,[ebx+64]            ;frame ptr #
        add     esi,80                  ;+ start of frame ptr's
        add     esi,ebx                 ;+ sprite's vars
        mov     esi,[esi]               ;= frame offset
        add     esi,[ebx+56]            ;+ image buffer


        mov     eax,rect.right          ;maxX
        add     eax,80
        mov     edi,[ebx+8]             ;vidy
        mul     edi                     ;maxX * vidy
        mov     edi,eax                 ;= line
        add     edi,[ebx+12]            ;+ vidx
        add     edi,vidbuf              ;+ vidbuf = total dest addr


        mov     ecx,[ebx+4]             ;height # of lines
sprite2:
        push    ecx

        mov     ecx,[ebx]               ;width
sprite3:
        lodsb
        cmp     al,0
        jne     stoit
        inc     edi
        loop    sprite3
        jmp     sprite4
stoit:
        stosb
        loop    sprite3

sprite4:
        sub     edi,[ebx]               ;-width
        add     edi,rect.right          ;+line width
        add     edi,80
        pop     ecx
        loop    sprite2                 ;next sprite line
sprite5:

        pop     ebx
        add     ebx,4                   ;next sprite var index

        pop     ecx
        loop    sprite1                 ;next sprite


        ret
sprite  endp



isprite proc
        mov     readstat,0

        mov     camxf,0
        mov     camyf,0
        mov     worldX,0
        mov     worldY,0

        mov     eax,planebuf            ;plane images
        add     eax,400*16*3            ;blue
        mov     ebx,offset plane0       ;set image buffer for player0
        mov     [ebx+56],eax

        mov     eax,centerY
        mov     dword ptr[ebx+08],eax   ;vidy
        mov     eax,centerX
        mov     dword ptr[ebx+12],eax   ;vidx
        mov     dword ptr[ebx+16],0     ;unskip
        mov     eax,centerY
        shl     eax,esh
        mov     dword ptr[ebx+20],eax   ;y
        mov     eax,centerX
        shl     eax,esh
        mov     dword ptr[ebx+28],eax   ;x
        mov     dword ptr[ebx+36],0     ;yf
        mov     dword ptr[ebx+44],0     ;xf
        mov     dword ptr[ebx+64],8     ;frame

        mov     eax,planebuf            ;red
        mov     ebx,offset plane1       ;set image buffer for player1
        mov     [ebx+56],eax
        mov     dword ptr[ebx+16],0     ;unskip
        mov     dword ptr[ebx+20],0     ;y
        mov     dword ptr[ebx+28],0     ;x
        mov     dword ptr[ebx+36],0     ;yf
        mov     dword ptr[ebx+44],0     ;xf
        mov     dword ptr[ebx+64],40    ;frame


        mov     eax,guybuf              ;guy images
        mov     ebx,offset guy0
        mov     [ebx+56],eax

        mov     dword ptr[ebx+08],400   ;vidy
        mov     dword ptr[ebx+12],500   ;vidx
        mov     dword ptr[ebx+16],0     ;unskip
        mov     dword ptr[ebx+20],400*e ;y
        mov     dword ptr[ebx+28],500*e ;x
        mov     dword ptr[ebx+36],0     ;yf
        mov     dword ptr[ebx+44],0     ;xf
        mov     dword ptr[ebx+64],8     ;frame

        mov     eax,guy1buf             ;guy1 images
        mov     ebx,offset guy1
        mov     [ebx+56],eax

        mov     dword ptr[ebx+08],440   ;vidy
        mov     dword ptr[ebx+12],540   ;vidx
        mov     dword ptr[ebx+16],0     ;unskip
        mov     dword ptr[ebx+20],440*e ;y
        mov     dword ptr[ebx+28],540*e ;x
        mov     dword ptr[ebx+36],0     ;yf
        mov     dword ptr[ebx+44],0     ;xf
        mov     dword ptr[ebx+64],0     ;frame


        mov     eax,curbuf              ;edit cursor images
        mov     ebx,offset cur0
        mov     [ebx+56],eax

        mov     dword ptr[ebx+08],20    ;vidy
        mov     dword ptr[ebx+12],20    ;vidx
        mov     dword ptr[ebx+16],0     ;unskip
        mov     dword ptr[ebx+20],20*e  ;y
        mov     dword ptr[ebx+28],20*e  ;x
        mov     dword ptr[ebx+36],0     ;yf
        mov     dword ptr[ebx+44],0     ;xf
        mov     dword ptr[ebx+64],0     ;frame




        mov     ebx,offset arrow0
        mov     eax,arrowbuf
        mov     [ebx+56],eax


        mov     camNumber,2
        call    camNext


        ret
isprite endp

num2asca proc
        push    eax
        push    ebx
        push    ecx
        push    edx

        cmp     eax,0
        jnl     num2asc0
        neg     eax
        inc     stringctr
        mov     cl,'-'
        mov     [edi],cl
        inc     edi

num2asc0:

        mov     ecx,0
num2asc1:
        mov     edx,0
        mov     ebx,10
        div     ebx

        inc     ecx

        add     dl,48
        push    edx

        cmp     eax,0
        je      num2asc2

        jmp     num2asc1

num2asc2:
        cmp     ecx,2
        jnl     num2asc2a
        inc     ecx
        mov     edx,'0'
        push    edx

num2asc2a:
        cmp     ecx,0
        je      num2asc3

        pop     eax
        stosb
        inc     stringctr
        dec     ecx
        jmp     num2asc2a

num2asc3:
        mov     al,32
        stosb
        inc     stringctr
        mov     al,32
        stosb
        inc     stringctr

        pop     edx
        pop     ecx
        pop     ebx
        pop     eax
        ret
num2asca endp

num2asc proc
        push    eax
        push    ebx
        push    ecx
        push    edx

        cmp     eax,0
        jnl     num2asc0
        neg     eax
        inc     stringctr
        mov     cl,'-'
        mov     [edi],cl
        inc     edi

num2asc0:

        mov     ecx,0
num2asc1:
        mov     edx,0
        mov     ebx,10
        div     ebx

        inc     ecx

        add     dl,48
        push    edx

        cmp     eax,0
        je      num2asc2

        jmp     num2asc1

num2asc2:
        cmp     ecx,0
        je      num2asc3

        pop     eax
        stosb
        inc     stringctr
        dec     ecx
        jmp     num2asc2

num2asc3:
        mov     al,32
        stosb
        inc     stringctr
        mov     al,32
        stosb
        inc     stringctr

        pop     edx
        pop     ecx
        pop     ebx
        pop     eax
        ret
num2asc endp

stringer proc
        push    ebx
        push    ecx
str1:
        lodsb
        cmp     al,13
        jne     str2

        invoke  SelectObject,hBMPDC,hBm
        invoke  TextOut,hBMPDC,textx,texty,offset stringbuf ,stringctr


        add     texty,16
        mov     textx,40
        mov     stringctr,0
        mov     edi,offset stringbuf
        jmp     str1
str2:
        cmp     al,0
        je      str4
str3:
        stosb
        inc     stringctr
        jmp     str1
str4:
        pop     ecx
        pop     ebx
        ret
stringer endp

doStats proc
        cmp     debugMode,1
        je      dostat1
        ret
dostat1:
        mov     esi,offset stats
        mov     edi,offset stringbuf
        mov     stringctr,0
        mov     textx,40
        mov     texty,40

        call    stringer

        call    stringer
        mov     eax,ElapsedTicks
        call    num2asca


        call    stringer
        mov     eax,regulator
        call    num2asc


        call    stringer
        mov     eax,FPScounted
        call    num2asc

        call    stringer
        mov     eax,lasterror
        call    num2asc

        call    stringer
        mov     eax,irf
        call    num2asc

        call    stringer
        mov     eax,play0
        mov     eax,[eax+28]
        sar     eax,esh
        call    num2asc


        call    stringer
        mov     eax,play0
        mov     eax,[eax+20]
        sar     eax,esh
        call    num2asc



        call    stringer
        mov     eax,xf
        sar     eax,esh
        call    num2asc

        call    stringer
        mov     eax,yf
        sar     eax,esh
        call    num2asc

        call    stringer
        mov     eax,radius
        call    num2asc

        call    stringer
        mov     eax,angle
        call    num2asc






        call    stringer            ;remote player stats
        mov     ebx,play1
        mov     eax,[ebx+28]
        sar     eax,esh
        call    num2asc

        call    stringer
        mov     eax,[ebx+20]
        sar     eax,esh
        call    num2asc

        call    stringer
        mov     eax,[ebx+44]
        sar     eax,esh
        call    num2asc

        call    stringer
        mov     eax,[ebx+36]
        sar     eax,esh
        call    num2asc






        call    stringer
        mov     eax,connected
        call    num2asc

        call    stringer
        mov     eax,sockError
        call    num2asc

        call    stringer
        mov     eax,readstat
        call    num2asc

        call    stringer
        mov     eax,Port
        call    num2asc

        call    stringer

        mov     esi,offset IPAddress
        call    stringer

        mov     esi,offset statse
        call    stringer


        call    doSockErr

        call    smode




        ret
doStats endp

smode   proc
        mov     esi,sockMode
        shl     esi,2
        add     esi,offset smodes
        mov     esi,[esi]
        mov     edi,offset stringbuf
        mov     stringctr,0
        call    stringer

        mov     esi,offset statse
        call    stringer


        ret
smode   endp

doSockErr proc
        mov     esi,offset serrs
        mov     serrmask,1
        mov     serrptr,0
        mov     ecx,14
        cmp     sockError,0
        jne     dse1

        mov     esi,[esi]
        mov     edi,offset stringbuf
        mov     stringctr,0
        call    stringer
        mov     esi,offset statse
        call    stringer
        jmp     dseX
dse1:
        push    ecx
        mov     eax,sockError
        and     eax,serrmask
        shl     serrmask,1
        add     serrptr,4
        cmp     eax,0
        je      dse2

        mov     esi,offset serrs
        add     esi,serrptr
        mov     esi,[esi]
        mov     edi,offset stringbuf
        mov     stringctr,0

        call    stringer
        mov     esi,offset statse
        call    stringer
dse2:
        pop     ecx
        loop    dse1

dseX:
        ret
doSockErr endp

arrow   proc
        mov     ebx,offset arrow0

        mov     eax,cursorX
        shl     eax,esh
        mov     [ebx+28],eax
        add     eax,worldX
        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax

        mov     eax,cursorY
        shl     eax,esh
        add     eax,[ebx+36]
        add     eax,worldY
        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        mov     eax,angle               ;frame
        add     eax,8
        and     eax,0FFh
        shr     eax,4
        shl     eax,2
        mov     [ebx+64],eax




        cmp     cursorX,10              ;cursor boundries
        jl      arrow10
        cmp     cursorY,10
        jl      arrow10
        mov     eax,rectX
        sub     eax,10
        cmp     cursorX,eax
        jg      arrow10
        mov     eax,rectY
        sub     eax,10
        cmp     cursorY,eax
        jg      arrow10
                                        ;cursor is in bounds

        cmp     dword ptr [ebx+16],0    ;arrow skipped?
        je      arrow20                 ;no, exit
        mov     dword ptr [ebx+16],0    ;yes, turn it on
        invoke  ShowCursor,FALSE        ;kill system cursor
        jmp     arrow20                 ;done.

arrow10:                                ;cursor out of bounds
        cmp     dword ptr [ebx+16],1
        je      arrow20

        mov     dword ptr [ebx+16],1    ;kill arrow
        invoke  ShowCursor,TRUE         ;show system cursor

arrow20:

        mov     ebx,offset arrowtab
        call    sprite

        ret
arrow   endp

player  proc
        mov     ebx,play0


        mov     eax,cursorY             ;cursor y
        mov     edx,centerY             ;screen center y

        ;add     edx,10
        sub     eax,edx
        mov     ydiff,eax               ;cursor y - player y

        mov     eax,cursorX             ;cursor x
        mov     edx,centerX             ;screen center x

        ;add     edx,10
        sub     eax,edx
        mov     xdiff,eax               ;cursor x - player x

        fild    i1000
        fild    regulator  ;ElapsedTicks            ;compute rf
        fdiv
        fst     rf
        fistp   irf


        fild    ydiff                   ;ydiff
        fmul    st,st                   ;^2
        fild    xdiff                   ;xdiff
        fmul    st,st                   ;^2
        fadd                            ;ydiff^2+xdiff^2
        fsqrt                           ;sqrt(ydiff^2+xdiff^2)

        fist    radius                  ;radius = sqr(xdiff^2 + ydiff^2)/rf

                                        ;radius on fpu stack!
player5:
        fild    ydiff
        fild    xdiff
        fpatan                          ; a = atan(y/x)

        cmp     ydiff,0
        jnl     player7

        fldpi
        fadd
        fldpi
        fadd


player7:
        fild    i128
        fld     st(1)
        fmul
        fldpi
        fdiv
        fistp   angle                   ;store angle for frame lookup


        fld     st                      ;a
        fcos                            ;cos(a)
        fld     st(2)                   ;r
        fmul                            ;r*cos(a)
        fld     rf
        fdiv
        fild    ie                      ;e
        fmul                            ;make fixed
        fistp   xf                      ;fixed.point xf = e*r*cos(a)


        fsin                            ;sin(a)
        fmul                            ;r*sin(a)
        fld     rf
        fdiv
        fild    ie                      ;e
        fmul                            ;make fixed
        fistp   yf                      ;fixed.point yf = e*r*sin(a)



player8:

        mov     eax,rectY
        cmp     cursorY,eax
        jg      player9
        mov     eax,rectX
        cmp     cursorX,eax
        jg      player9

        cmp     keyFlags,MK_LBUTTON
        jne     player9


        mov     eax,yf                  ;store in plane0 var's
        mov     [ebx+36],eax
        mov     eax,xf
        mov     [ebx+44],eax
        mov     eax,angle
        mov     [ebx+72],eax




player9:



player10:
        mov     eax,[ebx+28]            ;x
        add     eax,[ebx+44]            ;xf

        limitx
        mov     [ebx+28],eax            ;store new x
        sar     eax,esh

        mov     [ebx+12],eax            ;vidx


        mov     eax,[ebx+20]            ;y
        add     eax,[ebx+36]            ;yf

        limity
        mov     [ebx+20],eax            ;store new  y
        sar     eax,esh

        mov     [ebx+8],eax             ;vidy





player50:
        mov     eax,[ebx+72]            ;angle 2 frame
        add     eax,8
        and     eax,0FFh
        shr     eax,4
        shl     eax,2
        mov     [ebx+64],eax





        cmp     answered,1              ;cant write if answerer hasnt started
        jne     notAnswerer
        mov     answered,0              ;answerer must clear
        mov     recvd,1
        jmp     startsending

notAnswerer:

        cmp     recvd,1                 ;any remote player data?
        jne     remoteOK                ;no, skip


        cmp     sockred,40              ;was it 40 bytes?
        jne     remoteOK                ;no, skip

        mov     esi,offset sockbuf      ;got data from remote
        mov     ebx,play1               ; update remote player pos

        lodsd
        cmp     eax,1
        jne     notPos

        lodsd
        mov     [ebx+8],eax             ;vidy
        lodsd
        mov     [ebx+12],eax            ;vidx
        lodsd
        mov     [ebx+20],eax            ;y
        lodsd
        mov     [ebx+28],eax            ;x
        lodsd
        mov     [ebx+36],eax            ;yf
        lodsd
        mov     [ebx+44],eax            ;xf
        lodsd
        mov     [ebx+60],eax            ;collide
        lodsd
        mov     [ebx+64],eax            ;frame
        lodsd
        mov     [ebx+72],eax            ;angle

notPos:


startsending:


        call    fdwrite                 ;send local player pos to remote

remoteOK:


        ret
player  endp

fdwrite proc
        cmp     wrote,1                 ;cant write if already wrote
        je      sendOK

        mov     recvd,0
        mov     wrote,1

        mov     esi,play0
        mov     edi,offset sockbuf

        mov     eax,1                   ;command 1 = remote position data
        stosd
        mov     eax,[esi+8]             ;vidy
        stosd
        mov     eax,[esi+12]            ;vidx
        stosd
        mov     eax,[esi+20]            ;y
        stosd
        mov     eax,[esi+28]            ;x
        stosd
        mov     eax,[esi+36]            ;yf
        stosd
        mov     eax,[esi+44]            ;xf
        stosd
        mov     eax,[esi+60]            ;collide
        stosd
        mov     eax,[esi+64]            ;frame
        stosd
        mov     eax,[esi+72]            ;angle
        stosd


        invoke  send,sock,offset sockbuf,40,0    ;send pos to remote
        cmp     eax,SOCKET_ERROR
        jne     sendOK
        invoke  WSAGetLastError
        mov     lasterror,eax


        or      sockError,2048
        mov     ebx,play1
        mov     dword ptr[ebx+16],1
sendOK:
        ret
fdwrite endp





player1 proc
        cmp     sockMode,0
        jne     player1a
        ret

player1a:
        mov     ebx,play1
        mov     eax,[ebx+28]            ;x
        add     eax,[ebx+44]            ;+xf

        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax


        mov     eax,[ebx+20]            ;y
        add     eax,[ebx+36]            ;+xf

        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        ret
player1 endp


guya    proc

        mov     ebx,offset guy0
        mov     eax,[ebx+28]            ;x
        add     eax,[ebx+44]            ;+xf

        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax


        mov     eax,[ebx+20]            ;y
        add     eax,[ebx+36]            ;+xf

        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        ret
guya    endp

guyb    proc

        mov     ebx,offset guy1
        mov     eax,[ebx+28]            ;x
        add     eax,[ebx+44]            ;+xf

        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax


        mov     eax,[ebx+20]            ;y
        add     eax,[ebx+36]            ;+xf

        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        ret
guyb    endp

cur     proc


        cmp     camNumber,2
        jne     cur10


        ;invoke  GetCursorPos,orgW




        ;invoke  SetCursorPos,eax,edx

cur10:
        mov     ebx,offset cur0
        mov     eax,[ebx+28]            ;x
        add     eax,[ebx+44]            ;+xf

        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax


        mov     eax,[ebx+20]            ;y
        add     eax,[ebx+36]            ;+xf

        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        ret
cur     endp




world   proc
        mov     eax,worldX
        add     eax,camxf
        limitx
        mov     worldX,eax


        mov     eax,worldY
        add     eax,camyf
        limity
        mov     worldY,eax



        ret

world   endp

camNext proc
        inc     camNumber
        mov     eax,camtab
        cmp     camNumber,eax
        jne     camNext1
        mov     camNumber,0
camNext1:
        mov     ebx,offset camtab+4
        mov     eax,camNumber
        shl     eax,2
        add     ebx,eax
        mov     eax,[ebx]
        mov     eax,[eax]
        mov     camptr,eax

        ret
camNext endp

camera  proc
        mov     ebx,camptr


        mov     eax,[ebx+44]            ;xf
        mov     camxf,eax


        mov     eax,[ebx+28]            ;x
        mov     edx,centerX
        shl     edx,esh
        sub     eax,edx
        limitx0
        mov     worldX,eax

        mov     eax,[ebx+36]            ;yf
        mov     camyf,eax

        mov     eax,[ebx+20]            ;y
        mov     edx,centerY
        shl     edx,esh
        sub     eax,edx
        limity0
        mov     worldY,eax

        ret
camera  endp

toWorld proc
        mov     esi,ebx                 ;copy to world sprite
        mov     edi,offset wsprite
        mov     ecx,144/4
        rep     movsd

        mov     ebx,offset wsprite

        mov     eax,[ebx+20]            ;y
        sub     eax,worldY
        limity
        mov     [ebx+20],eax
        sar     eax,esh
        mov     [ebx+8],eax

        mov     eax,[ebx+28]            ;x
        sub     eax,worldX
        limitx
        mov     [ebx+28],eax
        sar     eax,esh
        mov     [ebx+12],eax

        ret
toWorld endp




        end     start

