1 line
32 KiB
C++
1 line
32 KiB
C++
#include <dos.h>
|
|
#include <conio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <graph.h>
|
|
#include "DoomDef.h"
|
|
#include "R_local.h"
|
|
|
|
#include "dmx.h"
|
|
#include "sounds.h"
|
|
#include "i_sound.h"
|
|
|
|
|
|
#define DPMI_INT 0x31
|
|
|
|
//#define NOKBD
|
|
//#define NOTIMER
|
|
|
|
void I_StartupNet (void);
|
|
void I_ShutdownNet (void);
|
|
|
|
typedef struct
|
|
{
|
|
unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax;
|
|
unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss;
|
|
} dpmiregs_t;
|
|
|
|
extern dpmiregs_t dpmiregs;
|
|
|
|
void I_ReadMouse (void);
|
|
void I_InitDiskFlash (void);
|
|
|
|
extern int usemouse, usejoystick;
|
|
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
CONSTANTS
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
|
|
//#define SC_INDEX 0x3C4
|
|
#define SC_RESET 0
|
|
#define SC_CLOCK 1
|
|
//#define SC_MAPMASK 2
|
|
#define SC_CHARMAP 3
|
|
#define SC_MEMMODE 4
|
|
|
|
#define CRTC_INDEX 0x3D4
|
|
#define CRTC_H_TOTAL 0
|
|
#define CRTC_H_DISPEND 1
|
|
#define CRTC_H_BLANK 2
|
|
#define CRTC_H_ENDBLANK 3
|
|
#define CRTC_H_RETRACE 4
|
|
#define CRTC_H_ENDRETRACE 5
|
|
#define CRTC_V_TOTAL 6
|
|
#define CRTC_OVERFLOW 7
|
|
#define CRTC_ROWSCAN 8
|
|
#define CRTC_MAXSCANLINE 9
|
|
#define CRTC_CURSORSTART 10
|
|
#define CRTC_CURSOREND 11
|
|
#define CRTC_STARTHIGH 12
|
|
#define CRTC_STARTLOW 13
|
|
#define CRTC_CURSORHIGH 14
|
|
#define CRTC_CURSORLOW 15
|
|
#define CRTC_V_RETRACE 16
|
|
#define CRTC_V_ENDRETRACE 17
|
|
#define CRTC_V_DISPEND 18
|
|
#define CRTC_OFFSET 19
|
|
#define CRTC_UNDERLINE 20
|
|
#define CRTC_V_BLANK 21
|
|
#define CRTC_V_ENDBLANK 22
|
|
#define CRTC_MODE 23
|
|
#define CRTC_LINECOMPARE 24
|
|
|
|
|
|
//#define GC_INDEX 0x3CE
|
|
#define GC_SETRESET 0
|
|
#define GC_ENABLESETRESET 1
|
|
#define GC_COLORCOMPARE 2
|
|
#define GC_DATAROTATE 3
|
|
//#define GC_READMAP 4
|
|
//#define GC_MODE 5
|
|
#define GC_MISCELLANEOUS 6
|
|
#define GC_COLORDONTCARE 7
|
|
#define GC_BITMASK 8
|
|
|
|
#define ATR_INDEX 0x3c0
|
|
#define ATR_MODE 16
|
|
#define ATR_OVERSCAN 17
|
|
#define ATR_COLORPLANEENABLE 18
|
|
#define ATR_PELPAN 19
|
|
#define ATR_COLORSELECT 20
|
|
|
|
#define STATUS_REGISTER_1 0x3da
|
|
|
|
#define PEL_WRITE_ADR 0x3c8
|
|
#define PEL_READ_ADR 0x3c7
|
|
#define PEL_DATA 0x3c9
|
|
#define PEL_MASK 0x3c6
|
|
|
|
boolean grmode;
|
|
|
|
//==================================================
|
|
//
|
|
// joystick vars
|
|
//
|
|
//==================================================
|
|
|
|
boolean joystickpresent;
|
|
extern unsigned joystickx, joysticky;
|
|
boolean I_ReadJoystick (void); // returns false if not connected
|
|
|
|
|
|
//==================================================
|
|
|
|
#define VBLCOUNTER 34000 // hardware tics to a frame
|
|
|
|
|
|
#define TIMERINT 8
|
|
#define KEYBOARDINT 9
|
|
|
|
|
|
#define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1)
|
|
#define CLI _disable()
|
|
#define STI _enable()
|
|
|
|
#define _outbyte(x,y) (outp(x,y))
|
|
#define _outhword(x,y) (outpw(x,y))
|
|
|
|
#define _inbyte(x) (inp(x))
|
|
#define _inhword(x) (inpw(x))
|
|
|
|
#define MOUSEB1 1
|
|
#define MOUSEB2 2
|
|
#define MOUSEB3 4
|
|
|
|
|
|
boolean mousepresent;
|
|
static int tsm_ID = -1; // tsm init flag
|
|
|
|
//===============================
|
|
|
|
int ticcount;
|
|
|
|
|
|
union REGS regs; // scratch for int calls
|
|
struct SREGS segregs;
|
|
|
|
boolean novideo; // if true, stay in text mode for debugging
|
|
|
|
|
|
#define KBDQUESIZE 32
|
|
byte keyboardque[KBDQUESIZE];
|
|
int kbdtail, kbdhead;
|
|
|
|
#define KEY_LSHIFT 0xfe
|
|
|
|
#define KEY_INS (0x80+0x52)
|
|
#define KEY_DEL (0x80+0x53)
|
|
#define KEY_PGUP (0x80+0x49)
|
|
#define KEY_PGDN (0x80+0x51)
|
|
#define KEY_HOME (0x80+0x47)
|
|
#define KEY_END (0x80+0x4f)
|
|
|
|
#define SC_RSHIFT 0x36
|
|
#define SC_LSHIFT 0x2a
|
|
|
|
byte scantokey[128] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7
|
|
// 8 9 A B C D E F
|
|
0 , 27, '1', '2', '3', '4', '5', '6',
|
|
'7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, // 0
|
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|
'o', 'p', '[', ']', 13 , KEY_RCTRL,'a', 's', // 1
|
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|
39 , '`', KEY_LSHIFT,92, 'z', 'x', 'c', 'v', // 2
|
|
'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,'*',
|
|
KEY_RALT,' ', 0 , KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3
|
|
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0 , 0 , KEY_HOME,
|
|
KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4
|
|
KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0, 0, KEY_F11,
|
|
KEY_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
|
|
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
|
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
|
|
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
|
|
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
|
|
};
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
// control api
|
|
//
|
|
|
|
typedef struct
|
|
{
|
|
int intnum; // doom will call this interrupt
|
|
ticcmd_t ticcmd; // then the driver will fill in this structure
|
|
} doomcontrol_t;
|
|
|
|
|
|
ticcmd_t emptycmd;
|
|
|
|
doomcontrol_t *doomcon;
|
|
|
|
|
|
ticcmd_t *I_BaseTiccmd (void)
|
|
{
|
|
if (!doomcon)
|
|
return &emptycmd;
|
|
|
|
DPMIInt (doomcon->intnum);
|
|
return &doomcon->ticcmd;
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= I_GetTime
|
|
=
|
|
= returns time in 1/35th second tics
|
|
=================
|
|
*/
|
|
|
|
int I_GetTime (void)
|
|
{
|
|
#ifdef NOTIMER
|
|
ticcount++;
|
|
#endif
|
|
|
|
return ticcount;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= I_ColorBorder
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void I_ColorBorder (void)
|
|
{
|
|
int i;
|
|
|
|
I_WaitVBL(1);
|
|
_outbyte (PEL_WRITE_ADR,0);
|
|
for (i=0 ; i<3 ; i++)
|
|
_outbyte(PEL_DATA,63 );
|
|
}
|
|
|
|
|
|
void I_UnColorBorder (void)
|
|
{
|
|
int i;
|
|
|
|
I_WaitVBL(1);
|
|
_outbyte (PEL_WRITE_ADR,0);
|
|
for (i=0 ; i<3 ; i++)
|
|
_outbyte(PEL_DATA,0);
|
|
}
|
|
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
USER INPUT
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= I_WaitVBL
|
|
=
|
|
=================
|
|
*/
|
|
|
|
void I_WaitVBL (int vbls)
|
|
{
|
|
int old;
|
|
int i,stat;
|
|
|
|
if (novideo)
|
|
return;
|
|
|
|
while (vbls--)
|
|
{
|
|
do
|
|
{
|
|
stat = inp(STATUS_REGISTER_1);
|
|
if (stat & 8)
|
|
break;
|
|
} while (1);
|
|
|
|
do
|
|
{
|
|
stat = inp(STATUS_REGISTER_1);
|
|
if ( (stat & 8) == 0 )
|
|
break;
|
|
} while ( 1 );
|
|
|
|
#if 0
|
|
// wait for display enabled, so we know it isn't just after vsync
|
|
waitdisplay:
|
|
// CLI;
|
|
while (CRTCOFF)
|
|
;
|
|
|
|
waitnodisplay:
|
|
// CLI;
|
|
while (!CRTCOFF)
|
|
;
|
|
// wait for display just turned off
|
|
waitbottom:
|
|
STI;
|
|
i--; // time for an interrupt
|
|
CLI;
|
|
|
|
for (i=0;i<10;i++)
|
|
{
|
|
stat = _inbyte(STATUS_REGISTER_1);
|
|
if (stat & 8)
|
|
goto waitdisplay; // vsync...
|
|
if (!(stat&1))
|
|
goto waitbottom;
|
|
}
|
|
STI;
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
=
|
|
= I_SetPalette
|
|
=
|
|
= takes full 8 bit values
|
|
=================
|
|
*/
|
|
|
|
void I_SetPalette (byte *palette)
|
|
{
|
|
int i;
|
|
|
|
if (novideo)
|
|
return;
|
|
I_WaitVBL (1);
|
|
_outbyte (PEL_WRITE_ADR,0);
|
|
for (i=0;i<768;i++)
|
|
_outbyte(PEL_DATA,(gammatable[usegamma][*palette++])>>2 );
|
|
}
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
GRAPHICS MODE
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
byte *screen;
|
|
byte *currentscreen, *destscreen, *destview;
|
|
|
|
#define PLANEWIDTH 80
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_UpdateBox
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_UpdateBox (int x, int y, int width, int height)
|
|
{
|
|
int ofs;
|
|
byte *source;
|
|
short *dest;
|
|
int p,x1, x2;
|
|
int srcdelta, destdelta;
|
|
int wwide;
|
|
|
|
if (x<0 || y<0 || width <= 0 || height <= 0
|
|
|| x+width > SCREENWIDTH || y+height > SCREENHEIGHT)
|
|
I_Error ("Bad I_UpdateBox (%i, %i, %i, %i)",x,y,width,height);
|
|
|
|
x1 = x>>3;
|
|
x2 = (x+width)>>3;
|
|
wwide = x2-x1+1;
|
|
|
|
ofs = y*SCREENWIDTH+(x1<<3);
|
|
srcdelta = SCREENWIDTH - (wwide<<3);
|
|
destdelta = PLANEWIDTH/2 - wwide;
|
|
outp (SC_INDEX, SC_MAPMASK);
|
|
|
|
for (p = 0 ; p < 4 ; p++)
|
|
{
|
|
outp (SC_INDEX+1, 1<<p);
|
|
source = screens[0] + ofs + p;
|
|
dest = (short *)(destscreen + (ofs>>2));
|
|
for (y=0 ; y<height ; y++)
|
|
{
|
|
for (x=wwide ; x ; x--)
|
|
{
|
|
*dest++ = *source + (source[4]<<8);
|
|
source += 8;
|
|
}
|
|
source+=srcdelta;
|
|
dest+=destdelta;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_UpdateNoBlit
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_UpdateNoBlit (void)
|
|
{
|
|
static int olddirtybox[4];
|
|
static int volddirtybox[4];
|
|
int updatebox[4];
|
|
|
|
// combine current dirtybox with olddirtyboxes
|
|
currentscreen = destscreen;
|
|
|
|
updatebox[BOXTOP] = dirtybox[BOXTOP] > volddirtybox[BOXTOP]
|
|
? dirtybox[BOXTOP] : volddirtybox[BOXTOP];
|
|
updatebox[BOXRIGHT] = dirtybox[BOXRIGHT] > volddirtybox[BOXRIGHT]
|
|
? dirtybox[BOXRIGHT] : volddirtybox[BOXRIGHT];
|
|
updatebox[BOXBOTTOM] = dirtybox[BOXBOTTOM] < volddirtybox[BOXBOTTOM]
|
|
? dirtybox[BOXBOTTOM] : volddirtybox[BOXBOTTOM];
|
|
updatebox[BOXLEFT] = dirtybox[BOXLEFT] < volddirtybox[BOXLEFT]
|
|
? dirtybox[BOXLEFT] : volddirtybox[BOXLEFT];
|
|
|
|
updatebox[BOXTOP] = updatebox[BOXTOP] > olddirtybox[BOXTOP]
|
|
? updatebox[BOXTOP] : olddirtybox[BOXTOP];
|
|
updatebox[BOXRIGHT] = updatebox[BOXRIGHT] > olddirtybox[BOXRIGHT]
|
|
? updatebox[BOXRIGHT] : olddirtybox[BOXRIGHT];
|
|
updatebox[BOXBOTTOM] = updatebox[BOXBOTTOM] < olddirtybox[BOXBOTTOM]
|
|
? updatebox[BOXBOTTOM] : olddirtybox[BOXBOTTOM];
|
|
updatebox[BOXLEFT] = updatebox[BOXLEFT] < olddirtybox[BOXLEFT]
|
|
? updatebox[BOXLEFT] : olddirtybox[BOXLEFT];
|
|
|
|
// save this drawing into olddirtybox
|
|
memcpy (volddirtybox, olddirtybox, sizeof(volddirtybox));
|
|
memcpy (olddirtybox, dirtybox, sizeof(olddirtybox));
|
|
|
|
// update other drawing
|
|
if (updatebox[BOXTOP] >= updatebox[BOXBOTTOM])
|
|
I_UpdateBox (updatebox[BOXLEFT],updatebox[BOXBOTTOM],
|
|
updatebox[BOXRIGHT] - updatebox[BOXLEFT]+1,
|
|
updatebox[BOXTOP] - updatebox[BOXBOTTOM]+1);
|
|
|
|
M_ClearBox (dirtybox);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_FinishUpdate
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_FinishUpdate (void)
|
|
{
|
|
static int lasttic;
|
|
int tics, i;
|
|
//
|
|
// draw tics
|
|
//
|
|
if (devparm)
|
|
{
|
|
tics = ticcount - lasttic;
|
|
lasttic = ticcount;
|
|
if (tics > 20)
|
|
tics = 20;
|
|
outpw (SC_INDEX, SC_MAPMASK + 256);
|
|
|
|
for (i=0 ; i<tics ; i++)
|
|
destscreen[ 199*80 + i] = 0xff;
|
|
for ( ; i<20 ; i++)
|
|
destscreen[ 199*80 + i] = 0x0;
|
|
}
|
|
|
|
// page flip
|
|
outpw(CRTC_INDEX, CRTC_STARTHIGH + ( (int)destscreen&0xff00) );
|
|
|
|
destscreen += 0x4000;
|
|
if ( (int)destscreen == 0xac000)
|
|
destscreen = (byte *)0xa0000;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_InitGraphics
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_InitGraphics (void)
|
|
{
|
|
if (novideo)
|
|
return;
|
|
|
|
//
|
|
// set 256 color mode
|
|
//
|
|
grmode = true;
|
|
|
|
regs.w.ax = 0x13;
|
|
int386 (0x10,(const union REGS *)®s,®s);
|
|
screen = currentscreen = (byte *)0xa0000;
|
|
|
|
destscreen = (byte *)0xa4000;
|
|
|
|
//
|
|
// turn off chain 4 and odd/even
|
|
//
|
|
_outbyte (SC_INDEX,SC_MEMMODE);
|
|
_outbyte (SC_INDEX+1,(_inbyte(SC_INDEX+1)&~8)|4);
|
|
|
|
//
|
|
// turn off odd/even and set write mode 0
|
|
//
|
|
_outbyte (GC_INDEX,GC_MODE);
|
|
_outbyte (GC_INDEX+1,_inbyte(GC_INDEX+1)&~0x13);
|
|
|
|
//
|
|
// turn off chain 4
|
|
//
|
|
_outbyte (GC_INDEX,GC_MISCELLANEOUS);
|
|
_outbyte (GC_INDEX+1,_inbyte(GC_INDEX+1)&~2);
|
|
|
|
//
|
|
// clear the entire buffer space, because int 10h only did 16 k / plane
|
|
//
|
|
_outhword (SC_INDEX,SC_MAPMASK+15*256);
|
|
memset (screen,0,0x10000);
|
|
|
|
//
|
|
// change CRTC scanning from doubleword to byte mode, allowing >64k scans
|
|
//
|
|
_outbyte (CRTC_INDEX,CRTC_UNDERLINE);
|
|
_outbyte (CRTC_INDEX+1,_inbyte(CRTC_INDEX+1)&~0x40);
|
|
|
|
_outbyte (CRTC_INDEX,CRTC_MODE);
|
|
_outbyte (CRTC_INDEX+1,_inbyte(CRTC_INDEX+1)|0x40);
|
|
|
|
_outbyte (GC_INDEX,GC_READMAP);
|
|
|
|
|
|
I_SetPalette (W_CacheLumpName ("PLAYPAL",PU_CACHE));
|
|
I_InitDiskFlash ();
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_ShutdownGraphics
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_ShutdownGraphics (void)
|
|
{
|
|
|
|
if ( *(byte *)0x449 == 0x13) // don't reset mode if it didn't get set
|
|
{
|
|
regs.w.ax = 3;
|
|
int386 (0x10,®s,®s); // back to text mode
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_ReadScreen
|
|
=
|
|
= Reads the screen currently displayed into a linear buffer
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_ReadScreen (byte *scr)
|
|
{
|
|
int i,p;
|
|
|
|
outp (GC_INDEX, GC_READMAP);
|
|
|
|
for (p=0 ; p<4 ; p++)
|
|
{
|
|
outp (GC_INDEX+1,p);
|
|
for (i=0 ; i<SCREENWIDTH*SCREENHEIGHT/4 ; i++)
|
|
scr[(i<<2)+p] = currentscreen[i];
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
|
|
/*
|
|
===================
|
|
=
|
|
= I_StartTic
|
|
=
|
|
// called by D_DoomLoop
|
|
// called before processing each tic in a frame
|
|
// can call D_PostEvent
|
|
// asyncronous interrupt functions should maintain private ques that are
|
|
// read by the syncronous functions to be converted into events
|
|
===================
|
|
*/
|
|
|
|
#define SC_UPARROW 0x48
|
|
#define SC_DOWNARROW 0x50
|
|
#define SC_LEFTARROW 0x4b
|
|
#define SC_RIGHTARROW 0x4d
|
|
|
|
void I_StartTic (void)
|
|
{
|
|
int k;
|
|
event_t ev;
|
|
|
|
|
|
I_ReadMouse ();
|
|
|
|
//
|
|
// keyboard events
|
|
//
|
|
while (kbdtail < kbdhead)
|
|
{
|
|
k = keyboardque[kbdtail&(KBDQUESIZE-1)];
|
|
kbdtail++;
|
|
|
|
// extended keyboard shift key bullshit
|
|
if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
|
|
{
|
|
if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
|
|
continue;
|
|
k &= 0x80;
|
|
k |= SC_RSHIFT;
|
|
}
|
|
|
|
if (k==0xe0)
|
|
continue; // special / pause keys
|
|
if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
|
|
continue; // pause key bullshit
|
|
|
|
if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
|
|
{
|
|
ev.type = ev_keydown;
|
|
ev.data1 = KEY_PAUSE;
|
|
D_PostEvent (&ev);
|
|
continue;
|
|
}
|
|
|
|
if (k&0x80)
|
|
ev.type = ev_keyup;
|
|
else
|
|
ev.type = ev_keydown;
|
|
k &= 0x7f;
|
|
switch (k)
|
|
{
|
|
case SC_UPARROW:
|
|
ev.data1 = KEY_UPARROW;
|
|
break;
|
|
case SC_DOWNARROW:
|
|
ev.data1 = KEY_DOWNARROW;
|
|
break;
|
|
case SC_LEFTARROW:
|
|
ev.data1 = KEY_LEFTARROW;
|
|
break;
|
|
case SC_RIGHTARROW:
|
|
ev.data1 = KEY_RIGHTARROW;
|
|
break;
|
|
default:
|
|
ev.data1 = scantokey[k];
|
|
break;
|
|
}
|
|
D_PostEvent (&ev);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void I_ReadKeys (void)
|
|
{
|
|
int k;
|
|
event_t ev;
|
|
|
|
|
|
while (1)
|
|
{
|
|
while (kbdtail < kbdhead)
|
|
{
|
|
k = keyboardque[kbdtail&(KBDQUESIZE-1)];
|
|
kbdtail++;
|
|
printf ("0x%x\n",k);
|
|
if (k == 1)
|
|
I_Quit ();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_StartFrame
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_StartFrame (void)
|
|
{
|
|
I_JoystickEvents ();
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
TIMER INTERRUPT
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
void I_ColorBlack (int r, int g, int b)
|
|
{
|
|
_outbyte (PEL_WRITE_ADR,0);
|
|
_outbyte(PEL_DATA,r);
|
|
_outbyte(PEL_DATA,g);
|
|
_outbyte(PEL_DATA,b);
|
|
}
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_TimerISR
|
|
=
|
|
================
|
|
*/
|
|
|
|
int I_TimerISR (void)
|
|
{
|
|
ticcount++;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
KEYBOARD
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
void (__interrupt __far *oldkeyboardisr) () = NULL;
|
|
|
|
int lastpress;
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_KeyboardISR
|
|
=
|
|
================
|
|
*/
|
|
|
|
void __interrupt I_KeyboardISR (void)
|
|
{
|
|
// Get the scan code
|
|
|
|
keyboardque[kbdhead&(KBDQUESIZE-1)] = lastpress = _inbyte(0x60);
|
|
kbdhead++;
|
|
|
|
// acknowledge the interrupt
|
|
|
|
_outbyte(0x20,0x20);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_StartupKeyboard
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_StartupKeyboard (void)
|
|
{
|
|
#ifndef NOKBD
|
|
oldkeyboardisr = _dos_getvect(KEYBOARDINT);
|
|
_dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
|
|
#endif
|
|
|
|
//I_ReadKeys ();
|
|
}
|
|
|
|
|
|
void I_ShutdownKeyboard (void)
|
|
{
|
|
if (oldkeyboardisr)
|
|
_dos_setvect (KEYBOARDINT, oldkeyboardisr);
|
|
*(short *)0x41c = *(short *)0x41a; // clear bios key buffer
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
MOUSE
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
|
|
int I_ResetMouse (void)
|
|
{
|
|
regs.w.ax = 0; // reset
|
|
int386 (0x33, ®s, ®s);
|
|
return regs.w.ax;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= StartupMouse
|
|
=
|
|
================
|
|
*/
|
|
|
|
void I_StartupCyberMan(void);
|
|
|
|
void I_StartupMouse (void)
|
|
{
|
|
int (far *function)();
|
|
|
|
//
|
|
// General mouse detection
|
|
//
|
|
mousepresent = 0;
|
|
if ( M_CheckParm ("-nomouse") || !usemouse )
|
|
return;
|
|
|
|
if (I_ResetMouse () != 0xffff)
|
|
{
|
|
printf ("Mouse: not present\n");
|
|
return;
|
|
}
|
|
printf ("Mouse: detected\n");
|
|
|
|
mousepresent = 1;
|
|
|
|
I_StartupCyberMan();
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= ShutdownMouse
|
|
=
|
|
================
|
|
*/
|
|
|
|
void I_ShutdownMouse (void)
|
|
{
|
|
if (!mousepresent)
|
|
return;
|
|
|
|
I_ResetMouse ();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_ReadMouse
|
|
=
|
|
================
|
|
*/
|
|
|
|
void I_ReadMouse (void)
|
|
{
|
|
event_t ev;
|
|
|
|
//
|
|
// mouse events
|
|
//
|
|
if (!mousepresent)
|
|
return;
|
|
|
|
ev.type = ev_mouse;
|
|
|
|
memset (&dpmiregs,0,sizeof(dpmiregs));
|
|
dpmiregs.eax = 3; // read buttons / position
|
|
DPMIInt (0x33);
|
|
ev.data1 = dpmiregs.ebx;
|
|
|
|
dpmiregs.eax = 11; // read counters
|
|
DPMIInt (0x33);
|
|
ev.data2 = (short)dpmiregs.ecx;
|
|
ev.data3 = -(short)dpmiregs.edx;
|
|
|
|
D_PostEvent (&ev);
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
JOYSTICK
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
int joyxl, joyxh, joyyl, joyyh;
|
|
|
|
boolean WaitJoyButton (void)
|
|
{
|
|
int oldbuttons, buttons;
|
|
|
|
oldbuttons = 0;
|
|
do
|
|
{
|
|
I_WaitVBL (1);
|
|
buttons = ((inp(0x201) >> 4)&1)^1;
|
|
if (buttons != oldbuttons)
|
|
{
|
|
oldbuttons = buttons;
|
|
continue;
|
|
}
|
|
|
|
if ( (lastpress& 0x7f) == 1 )
|
|
{
|
|
joystickpresent = false;
|
|
return false;
|
|
}
|
|
} while ( !buttons);
|
|
|
|
do
|
|
{
|
|
I_WaitVBL (1);
|
|
buttons = ((inp(0x201) >> 4)&1)^1;
|
|
if (buttons != oldbuttons)
|
|
{
|
|
oldbuttons = buttons;
|
|
continue;
|
|
}
|
|
|
|
if ( (lastpress& 0x7f) == 1 )
|
|
{
|
|
joystickpresent = false;
|
|
return false;
|
|
}
|
|
} while ( buttons);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_StartupJoystick
|
|
=
|
|
===============
|
|
*/
|
|
|
|
int basejoyx, basejoyy;
|
|
|
|
void I_StartupJoystick (void)
|
|
{
|
|
int buttons;
|
|
int count;
|
|
int centerx, centery;
|
|
|
|
joystickpresent = 0;
|
|
if ( M_CheckParm ("-nojoy") || !usejoystick )
|
|
return;
|
|
|
|
if (!I_ReadJoystick ())
|
|
{
|
|
joystickpresent = false;
|
|
printf ("joystick not found\n");
|
|
return;
|
|
}
|
|
printf ("joystick found\n");
|
|
joystickpresent = true;
|
|
|
|
printf ("CENTER the joystick and press button 1:");
|
|
if (!WaitJoyButton ())
|
|
return;
|
|
I_ReadJoystick ();
|
|
centerx = joystickx;
|
|
centery = joysticky;
|
|
|
|
printf ("\nPush the joystick to the UPPER LEFT corner and press button 1:");
|
|
if (!WaitJoyButton ())
|
|
return;
|
|
I_ReadJoystick ();
|
|
joyxl = (centerx + joystickx)/2;
|
|
joyyl = (centerx + joysticky)/2;
|
|
|
|
printf ("\nPush the joystick to the LOWER RIGHT corner and press button 1:");
|
|
if (!WaitJoyButton ())
|
|
return;
|
|
I_ReadJoystick ();
|
|
joyxh = (centerx + joystickx)/2;
|
|
joyyh = (centery + joysticky)/2;
|
|
printf ("\n");
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_JoystickEvents
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_JoystickEvents (void)
|
|
{
|
|
event_t ev;
|
|
|
|
//
|
|
// joystick events
|
|
//
|
|
if (!joystickpresent)
|
|
return;
|
|
|
|
I_ReadJoystick ();
|
|
ev.type = ev_joystick;
|
|
ev.data1 = ((inp(0x201) >> 4)&15)^15;
|
|
|
|
if (joystickx < joyxl)
|
|
ev.data2 = -1;
|
|
else if (joystickx > joyxh)
|
|
ev.data2 = 1;
|
|
else
|
|
ev.data2 = 0;
|
|
if (joysticky < joyyl)
|
|
ev.data3 = -1;
|
|
else if (joysticky > joyyh)
|
|
ev.data3 = 1;
|
|
else
|
|
ev.data3 = 0;
|
|
|
|
D_PostEvent (&ev);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
DPMI STUFF
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
#define REALSTACKSIZE 1024
|
|
|
|
dpmiregs_t dpmiregs;
|
|
|
|
unsigned realstackseg;
|
|
|
|
void I_DivException (void);
|
|
int I_SetDivException (void);
|
|
|
|
void DPMIFarCall (void)
|
|
{
|
|
segread (&segregs);
|
|
regs.w.ax = 0x301;
|
|
regs.w.bx = 0;
|
|
regs.w.cx = 0;
|
|
regs.x.edi = (unsigned)&dpmiregs;
|
|
segregs.es = segregs.ds;
|
|
int386x( DPMI_INT, ®s, ®s, &segregs );
|
|
}
|
|
|
|
|
|
void DPMIInt (int i)
|
|
{
|
|
dpmiregs.ss = realstackseg;
|
|
dpmiregs.sp = REALSTACKSIZE-4;
|
|
|
|
segread (&segregs);
|
|
regs.w.ax = 0x300;
|
|
regs.w.bx = i;
|
|
regs.w.cx = 0;
|
|
regs.x.edi = (unsigned)&dpmiregs;
|
|
segregs.es = segregs.ds;
|
|
int386x( DPMI_INT, ®s, ®s, &segregs );
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
=
|
|
= I_StartupDPMI
|
|
=
|
|
==============
|
|
*/
|
|
|
|
void I_StartupDPMI (void)
|
|
{
|
|
extern char __begtext;
|
|
extern char ___argc;
|
|
int n,d;
|
|
|
|
//
|
|
// allocate a decent stack for real mode ISRs
|
|
//
|
|
realstackseg = (int)I_AllocLow (1024) >> 4;
|
|
|
|
//
|
|
// lock the entire program down
|
|
//
|
|
_dpmi_lockregion (&__begtext, &___argc - &__begtext);
|
|
|
|
|
|
//
|
|
// catch divide by 0 exception
|
|
//
|
|
#if 0
|
|
segread(&segregs);
|
|
regs.w.ax = 0x0203; // DPMI set processor exception handler vector
|
|
regs.w.bx = 0; // int 0
|
|
regs.w.cx = segregs.cs;
|
|
regs.x.edx = (int)&I_DivException;
|
|
printf ("%x : %x\n",regs.w.cx, regs.x.edx);
|
|
int386( DPMI_INT, ®s, ®s);
|
|
#endif
|
|
|
|
#if 0
|
|
n = I_SetDivException ();
|
|
printf ("return: %i\n",n);
|
|
n = 100;
|
|
d = 0;
|
|
printf ("100 / 0 = %i\n",n/d);
|
|
|
|
exit (1);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
TIMER INTERRUPT
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
void (__interrupt __far *oldtimerisr) ();
|
|
|
|
|
|
void IO_ColorBlack (int r, int g, int b)
|
|
{
|
|
_outbyte (PEL_WRITE_ADR,0);
|
|
_outbyte(PEL_DATA,r);
|
|
_outbyte(PEL_DATA,g);
|
|
_outbyte(PEL_DATA,b);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= IO_TimerISR
|
|
=
|
|
================
|
|
*/
|
|
|
|
//void __interrupt IO_TimerISR (void)
|
|
|
|
void __interrupt __far IO_TimerISR (void)
|
|
{
|
|
ticcount++;
|
|
_outbyte(0x20,0x20); // Ack the interrupt
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
=
|
|
= IO_SetTimer0
|
|
=
|
|
= Sets system timer 0 to the specified speed
|
|
=
|
|
=====================
|
|
*/
|
|
|
|
void IO_SetTimer0(int speed)
|
|
{
|
|
if (speed > 0 && speed < 150)
|
|
I_Error ("INT_SetTimer0: %i is a bad value",speed);
|
|
|
|
_outbyte(0x43,0x36); // Change timer 0
|
|
_outbyte(0x40,speed);
|
|
_outbyte(0x40,speed >> 8);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= IO_StartupTimer
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void IO_StartupTimer (void)
|
|
{
|
|
oldtimerisr = _dos_getvect(TIMERINT);
|
|
|
|
_dos_setvect (0x8000 | TIMERINT, IO_TimerISR);
|
|
IO_SetTimer0 (VBLCOUNTER);
|
|
}
|
|
|
|
void IO_ShutdownTimer (void)
|
|
{
|
|
if (oldtimerisr)
|
|
{
|
|
IO_SetTimer0 (0); // back to 18.4 ips
|
|
_dos_setvect (TIMERINT, oldtimerisr);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_Init
|
|
=
|
|
= hook interrupts and set graphics mode
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_Init (void)
|
|
{
|
|
int i;
|
|
extern void I_StartupTimer(void);
|
|
|
|
novideo = M_CheckParm ("novideo");
|
|
|
|
// check for an external controler
|
|
i = M_CheckParm ("-control"); // -control <flat addres>
|
|
if (i)
|
|
{
|
|
doomcon = (doomcontrol_t *)atoi(myargv[i+1]);
|
|
printf ("Using external control API\n");
|
|
}
|
|
|
|
|
|
printf ("I_StartupDPMI\n");
|
|
I_StartupDPMI ();
|
|
printf ("I_StartupMouse\n");
|
|
I_StartupMouse ();
|
|
printf ("I_StartupJoystick\n");
|
|
I_StartupJoystick ();
|
|
printf ("I_StartupKeyboard\n");
|
|
I_StartupKeyboard ();
|
|
|
|
//printf ("I_StartupTimer\n");
|
|
// I_StartupTimer ();
|
|
//IO_StartupTimer ();
|
|
printf ("I_StartupSound\n");
|
|
I_StartupSound ();
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_Shutdown
|
|
=
|
|
= return to default system state
|
|
=
|
|
===============
|
|
*/
|
|
|
|
void I_Shutdown (void)
|
|
{
|
|
I_ShutdownGraphics ();
|
|
I_ShutdownSound ();
|
|
I_ShutdownTimer ();
|
|
//IO_ShutdownTimer ();
|
|
I_ShutdownMouse ();
|
|
I_ShutdownKeyboard ();
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_Error
|
|
=
|
|
================
|
|
*/
|
|
|
|
boolean G_CheckDemoStatus (void);
|
|
|
|
|
|
void I_Error (char *error, ...)
|
|
{
|
|
va_list argptr;
|
|
|
|
D_QuitNetGame ();
|
|
I_Shutdown ();
|
|
va_start (argptr,error);
|
|
vprintf (error,argptr);
|
|
va_end (argptr);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
=
|
|
= I_Quit
|
|
=
|
|
================
|
|
*/
|
|
|
|
void I_Quit (void)
|
|
{
|
|
byte *scr;
|
|
|
|
if (demorecording)
|
|
G_CheckDemoStatus ();
|
|
else
|
|
D_QuitNetGame ();
|
|
M_SaveDefaults ();
|
|
scr = (byte *)W_CacheLumpName ("ENDOOM", PU_CACHE);
|
|
I_Shutdown ();
|
|
#if 1
|
|
memcpy ((void *)0xb8000,scr,80*25*2);
|
|
regs.w.ax = 0x0200;
|
|
regs.h.bh = 0;
|
|
regs.h.dl = 0;
|
|
regs.h.dh = 23;
|
|
int386 (0x10,(const union REGS *)®s,®s); // set text pos
|
|
printf("\n");
|
|
#endif
|
|
exit(0);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
===============
|
|
=
|
|
= I_ZoneBase
|
|
=
|
|
===============
|
|
*/
|
|
|
|
byte *I_ZoneBase (int *size)
|
|
{
|
|
int meminfo[32];
|
|
int heap;
|
|
int i;
|
|
int block;
|
|
byte *ptr;
|
|
|
|
memset (meminfo,0,sizeof(meminfo));
|
|
segread(&segregs);
|
|
segregs.es = segregs.ds;
|
|
regs.w.ax = 0x500; // get memory info
|
|
regs.x.edi = (int)&meminfo;
|
|
int386x( 0x31, ®s, ®s, &segregs );
|
|
|
|
heap = meminfo[0];
|
|
printf ("DPMI memory: 0x%x",heap);
|
|
|
|
do
|
|
{
|
|
heap -= 0x20000; // leave 128k alone
|
|
if (heap > 0x800000)
|
|
heap = 0x800000;
|
|
ptr = malloc (heap);
|
|
} while (!ptr);
|
|
|
|
printf (", 0x%x allocated for zone\n", heap);
|
|
if (heap < 0x180000)
|
|
{
|
|
printf("\n");
|
|
printf("Insufficient memory! You need to have at least 3.7 megabytes of total\n");
|
|
printf("free memory available for DOOM to execute. Reconfigure your CONFIG.SYS\n");
|
|
printf("or AUTOEXEC.BAT to load fewer device drivers or TSR's. We recommend\n");
|
|
printf("creating a custom boot menu item in your CONFIG.SYS for optimum DOOMing.\n");
|
|
printf("Please consult your DOS manual (\"Making more memory available\") for\n");
|
|
printf("information on how to free up more memory for DOOM.\n\n");
|
|
|
|
printf("DOOM aborted.\n");
|
|
exit(1);
|
|
// I_Error ("DOOM aborted.");
|
|
}
|
|
#if 0
|
|
regs.w.ax = 0x501; // allocate linear block
|
|
regs.w.bx = heap>>16;
|
|
regs.w.cx = heap&0xffff;
|
|
int386( 0x31, ®s, ®s);
|
|
if (regs.w.cflag)
|
|
I_Error ("Couldn't allocate DPMI memory!");
|
|
|
|
block = (regs.w.si << 16) + regs.w.di;
|
|
#endif
|
|
|
|
*size = heap;
|
|
return ptr;
|
|
}
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
DISK ICON FLASHING
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
void I_InitDiskFlash (void)
|
|
{
|
|
void *pic;
|
|
byte *temp;
|
|
|
|
if (M_CheckParm("-cdrom"))
|
|
pic = W_CacheLumpName ("STCDROM",PU_CACHE);
|
|
else
|
|
pic = W_CacheLumpName ("STDISK",PU_CACHE);
|
|
temp = destscreen;
|
|
destscreen = (byte *)0xac000;
|
|
V_DrawPatchDirect (SCREENWIDTH-16,SCREENHEIGHT-16,0,pic);
|
|
destscreen = temp;
|
|
}
|
|
|
|
// draw disk icon
|
|
void I_BeginRead (void)
|
|
{
|
|
byte *src,*dest;
|
|
int y;
|
|
|
|
if (!grmode)
|
|
return;
|
|
|
|
// write through all planes
|
|
outp (SC_INDEX,SC_MAPMASK);
|
|
outp (SC_INDEX+1,15);
|
|
// set write mode 1
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
|
|
|
|
// copy to backup
|
|
src = currentscreen + 184*80 + 304/4;
|
|
dest = (byte *)0xac000 + 184*80 + 288/4;
|
|
for (y=0 ; y<16 ; y++)
|
|
{
|
|
dest[0] = src[0];
|
|
dest[1] = src[1];
|
|
dest[2] = src[2];
|
|
dest[3] = src[3];
|
|
src += 80;
|
|
dest += 80;
|
|
}
|
|
|
|
// copy disk over
|
|
dest = currentscreen + 184*80 + 304/4;
|
|
src = (byte *)0xac000 + 184*80 + 304/4;
|
|
for (y=0 ; y<16 ; y++)
|
|
{
|
|
dest[0] = src[0];
|
|
dest[1] = src[1];
|
|
dest[2] = src[2];
|
|
dest[3] = src[3];
|
|
src += 80;
|
|
dest += 80;
|
|
}
|
|
|
|
|
|
// set write mode 0
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
|
|
}
|
|
|
|
// erase disk icon
|
|
void I_EndRead (void)
|
|
{
|
|
byte *src,*dest;
|
|
int y;
|
|
|
|
if (!grmode)
|
|
return;
|
|
|
|
// write through all planes
|
|
outp (SC_INDEX,SC_MAPMASK);
|
|
outp (SC_INDEX+1,15);
|
|
// set write mode 1
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
|
|
|
|
|
|
// copy disk over
|
|
dest = currentscreen + 184*80 + 304/4;
|
|
src = (byte *)0xac000 + 184*80 + 288/4;
|
|
for (y=0 ; y<16 ; y++)
|
|
{
|
|
dest[0] = src[0];
|
|
dest[1] = src[1];
|
|
dest[2] = src[2];
|
|
dest[3] = src[3];
|
|
src += 80;
|
|
dest += 80;
|
|
}
|
|
|
|
// set write mode 0
|
|
outp (GC_INDEX,GC_MODE);
|
|
outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
=============
|
|
=
|
|
= I_AllocLow
|
|
=
|
|
=============
|
|
*/
|
|
|
|
byte *I_AllocLow (int length)
|
|
{
|
|
byte *mem;
|
|
|
|
// DPMI call 100h allocates DOS memory
|
|
segread(&segregs);
|
|
regs.w.ax = 0x0100; // DPMI allocate DOS memory
|
|
regs.w.bx = (length+15) / 16;
|
|
int386( DPMI_INT, ®s, ®s);
|
|
// segment = regs.w.ax;
|
|
// selector = regs.w.dx;
|
|
if (regs.w.cflag != 0)
|
|
I_Error ("I_AllocLow: DOS alloc of %i failed, %i free",
|
|
length, regs.w.bx*16);
|
|
|
|
|
|
mem = (void *) ((regs.x.eax & 0xFFFF) << 4);
|
|
memset (mem,0,length);
|
|
return mem;
|
|
}
|
|
|
|
/*
|
|
============================================================================
|
|
|
|
NETWORKING
|
|
|
|
============================================================================
|
|
*/
|
|
|
|
/* // FUCKED LINES
|
|
typedef struct
|
|
{
|
|
char priv[508];
|
|
} doomdata_t;
|
|
*/ // FUCKED LINES
|
|
|
|
#define DOOMCOM_ID 0x12345678l
|
|
|
|
/* // FUCKED LINES
|
|
typedef struct
|
|
{
|
|
long id;
|
|
short intnum; // DOOM executes an int to execute commands
|
|
|
|
// communication between DOOM and the driver
|
|
short command; // CMD_SEND or CMD_GET
|
|
short remotenode; // dest for send, set by get (-1 = no packet)
|
|
short datalength; // bytes in doomdata to be sent
|
|
|
|
// info common to all nodes
|
|
short numnodes; // console is allways node 0
|
|
short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
|
|
short extratics; // 1 = send a backup tic in every packet
|
|
short deathmatch; // 1 = deathmatch
|
|
short savegame; // -1 = new game, 0-5 = load savegame
|
|
short episode; // 1-3
|
|
short map; // 1-9
|
|
short skill; // 1-5
|
|
|
|
// info specific to this node
|
|
short consoleplayer;
|
|
short numplayers;
|
|
short angleoffset; // 1 = left, 0 = center, -1 = right
|
|
short drone; // 1 = drone
|
|
|
|
// packet data to be sent
|
|
doomdata_t data;
|
|
} doomcom_t;
|
|
*/ // FUCKED LINES
|
|
|
|
extern doomcom_t *doomcom;
|
|
|
|
/*
|
|
====================
|
|
=
|
|
= I_InitNetwork
|
|
=
|
|
====================
|
|
*/
|
|
|
|
void I_InitNetwork (void)
|
|
{
|
|
int i;
|
|
|
|
i = M_CheckParm ("-net");
|
|
if (!i)
|
|
{
|
|
//
|
|
// single player game
|
|
//
|
|
doomcom = malloc (sizeof (*doomcom) );
|
|
if (!doomcom) I_Error("malloc() in I_InitNetwork() failed");
|
|
memset (doomcom, 0, sizeof(*doomcom) );
|
|
netgame = false;
|
|
doomcom->id = DOOMCOM_ID;
|
|
doomcom->numplayers = doomcom->numnodes = 1;
|
|
doomcom->deathmatch = false;
|
|
doomcom->consoleplayer = 0;
|
|
doomcom->ticdup = 1;
|
|
doomcom->extratics = 0;
|
|
return;
|
|
}
|
|
|
|
netgame = true;
|
|
doomcom = (doomcom_t *)atoi(myargv[i+1]);
|
|
//DEBUG
|
|
doomcom->skill = startskill;
|
|
doomcom->episode = startepisode;
|
|
doomcom->map = startmap;
|
|
doomcom->deathmatch = deathmatch;
|
|
|
|
}
|
|
|
|
void I_NetCmd (void)
|
|
{
|
|
if (!netgame)
|
|
I_Error ("I_NetCmd when not in netgame");
|
|
DPMIInt (doomcom->intnum);
|
|
}
|