23 int DisplayTicker = 0;
27 void main(int argc, char **argv)
34 void I_StartupNet (void);
35 void I_ShutdownNet (void);
36 void I_ReadExternDriver(void);
40 unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax;
41 unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss;
44 extern dpmiregs_t dpmiregs;
46 void I_ReadMouse (void);
47 void I_InitDiskFlash (void);
49 extern int usemouse, usejoystick;
51 extern void **lumpcache;
54 ===============================================================================
58 ===============================================================================
61 static channel_t channel[MAX_CHANNELS];
63 static int rs; //the current registered song.
69 extern sfxinfo_t S_sfx[];
70 extern musicinfo_t S_music[];
72 extern int snd_DesiredMusicDevice;
73 extern int snd_DesiredSfxDevice;
74 extern int snd_MaxVolume;
75 extern int snd_MusicVolume;
76 extern int snd_Channels;
78 extern int startepisode;
87 S_StartSong((gameepisode-1)*9 + gamemap-1, true);
90 for(i=0; i < snd_Channels; i++)
94 S_StopSound(channel[i].mo);
97 memset(channel, 0, 8*sizeof(channel_t));
100 void S_StartSong(int song, boolean loop)
103 { // don't replay an old song
109 I_UnRegisterSong(rs);
110 Z_ChangeTag(lumpcache[mus_lumpnum], PU_CACHE);
112 _dpmi_unlockregion(mus_sndptr, lumpinfo[mus_lumpnum].size);
115 if(song < mus_e1m1 || song > NUMMUSIC)
119 mus_lumpnum = W_GetNumForName(S_music[song].name);
120 mus_sndptr = W_CacheLumpNum(mus_lumpnum, PU_MUSIC);
122 _dpmi_lockregion(mus_sndptr, lumpinfo[mus_lumpnum].size);
124 rs = I_RegisterSong(mus_sndptr);
125 I_PlaySong(rs, loop); //'true' denotes endless looping.
129 void S_StartSound(mobj_t *origin, int sound_id)
140 static int sndcount = 0;
143 if(sound_id==0 || snd_MaxVolume == 0)
147 origin = players[consoleplayer].mo;
150 // calculate the distance before other stuff so that we can throw out
151 // sounds that are beyond the hearing range.
152 absx = abs(origin->x-players[consoleplayer].mo->x);
153 absy = abs(origin->y-players[consoleplayer].mo->y);
154 dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
156 // dist = P_AproxDistance(origin->x-viewx, origin->y-viewy)>>FRACBITS;
158 if(dist >= MAX_SND_DIST)
160 // dist = MAX_SND_DIST - 1;
161 return; //sound is beyond the hearing range...
167 priority = S_sfx[sound_id].priority;
168 priority *= (10 - (dist/160));
169 if(!S_StopSoundID(sound_id, priority))
171 return; // other sounds have greater priority
173 for(i=0; i<snd_Channels; i++)
178 break; // let the player have more than one sound.
180 if(origin == channel[i].mo)
181 { // only allow other mobjs one sound
182 S_StopSound(channel[i].mo);
186 if(i >= snd_Channels)
188 if(sound_id >= sfx_wind)
190 if(AmbChan != -1 && S_sfx[sound_id].priority <=
191 S_sfx[channel[AmbChan].sound_id].priority)
193 return; //ambient channel already in use
200 for(i=0; i<snd_Channels; i++)
202 if(channel[i].mo == NULL)
207 if(i >= snd_Channels)
209 //look for a lower priority sound to replace.
211 if(sndcount >= snd_Channels)
215 for(chan=0; chan < snd_Channels; chan++)
217 i = (sndcount+chan)%snd_Channels;
218 if(priority >= channel[i].priority)
220 chan = -1; //denote that sound should be replaced.
226 return; //no free channels.
228 else //replace the lower priority sound.
230 if(channel[i].handle)
232 if(I_SoundIsPlaying(channel[i].handle))
234 I_StopSound(channel[i].handle);
236 if(S_sfx[channel[i].sound_id].usefulness > 0)
238 S_sfx[channel[i].sound_id].usefulness--;
249 if(S_sfx[sound_id].lumpnum == 0)
251 S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]);
253 if(S_sfx[sound_id].snd_ptr == NULL)
255 S_sfx[sound_id].snd_ptr = W_CacheLumpNum(S_sfx[sound_id].lumpnum,
258 _dpmi_lockregion(S_sfx[sound_id].snd_ptr,
259 lumpinfo[S_sfx[sound_id].lumpnum].size);
263 // calculate the volume based upon the distance from the sound origin.
264 // vol = (snd_MaxVolume*16 + dist*(-snd_MaxVolume*16)/MAX_SND_DIST)>>9;
265 vol = soundCurve[dist];
267 if(origin == players[consoleplayer].mo)
273 angle = R_PointToAngle2(players[consoleplayer].mo->x,
274 players[consoleplayer].mo->y, channel[i].mo->x, channel[i].mo->y);
275 angle = (angle-viewangle)>>24;
283 channel[i].pitch = (byte)(127+(M_Random()&7)-(M_Random()&7));
284 channel[i].handle = I_StartSound(sound_id, S_sfx[sound_id].snd_ptr, vol, sep, channel[i].pitch, 0);
285 channel[i].mo = origin;
286 channel[i].sound_id = sound_id;
287 channel[i].priority = priority;
288 if(sound_id >= sfx_wind)
292 if(S_sfx[sound_id].usefulness == -1)
294 S_sfx[sound_id].usefulness = 1;
298 S_sfx[sound_id].usefulness++;
302 void S_StartSoundAtVolume(mobj_t *origin, int sound_id, int volume)
311 if(sound_id == 0 || snd_MaxVolume == 0)
315 origin = players[consoleplayer].mo;
322 volume = (volume*(snd_MaxVolume+1)*8)>>7;
324 // no priority checking, as ambient sounds would be the LOWEST.
325 for(i=0; i<snd_Channels; i++)
327 if(channel[i].mo == NULL)
332 if(i >= snd_Channels)
336 if(S_sfx[sound_id].lumpnum == 0)
338 S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]);
340 if(S_sfx[sound_id].snd_ptr == NULL)
342 S_sfx[sound_id].snd_ptr = W_CacheLumpNum(S_sfx[sound_id].lumpnum,
345 _dpmi_lockregion(S_sfx[sound_id].snd_ptr,
346 lumpinfo[S_sfx[sound_id].lumpnum].size);
349 channel[i].pitch = (byte)(127-(M_Random()&3)+(M_Random()&3));
350 channel[i].handle = I_StartSound(sound_id, S_sfx[sound_id].snd_ptr, volume, 128, channel[i].pitch, 0);
351 channel[i].mo = origin;
352 channel[i].sound_id = sound_id;
353 channel[i].priority = 1; //super low priority.
354 if(S_sfx[sound_id].usefulness == -1)
356 S_sfx[sound_id].usefulness = 1;
360 S_sfx[sound_id].usefulness++;
364 boolean S_StopSoundID(int sound_id, int priority)
367 int lp; //least priority
370 if(S_sfx[sound_id].numchannels == -1)
374 lp = -1; //denote the argument sound_id
376 for(i=0; i<snd_Channels; i++)
378 if(channel[i].sound_id == sound_id && channel[i].mo)
380 found++; //found one. Now, should we replace it??
381 if(priority >= channel[i].priority)
382 { // if we're gonna kill one, then this'll be it
384 priority = channel[i].priority;
388 if(found < S_sfx[sound_id].numchannels)
394 return(false); // don't replace any sounds
396 if(channel[lp].handle)
398 if(I_SoundIsPlaying(channel[lp].handle))
400 I_StopSound(channel[lp].handle);
402 if(S_sfx[channel[i].sound_id].usefulness > 0)
404 S_sfx[channel[i].sound_id].usefulness--;
406 channel[lp].mo = NULL;
411 void S_StopSound(mobj_t *origin)
415 for(i=0;i<snd_Channels;i++)
417 if(channel[i].mo == origin)
419 I_StopSound(channel[i].handle);
420 if(S_sfx[channel[i].sound_id].usefulness > 0)
422 S_sfx[channel[i].sound_id].usefulness--;
424 channel[i].handle = 0;
425 channel[i].mo = NULL;
434 void S_SoundLink(mobj_t *oldactor, mobj_t *newactor)
438 for(i=0;i<snd_Channels;i++)
440 if(channel[i].mo == oldactor)
441 channel[i].mo = newactor;
445 void S_PauseSound(void)
450 void S_ResumeSound(void)
455 static int nextcleanup;
457 void S_UpdateSounds(mobj_t *listener)
466 listener = players[consoleplayer].mo;
467 if(snd_MaxVolume == 0)
471 if(nextcleanup < gametic)
473 for(i=0; i < NUMSFX; i++)
475 if(S_sfx[i].usefulness == 0 && S_sfx[i].snd_ptr)
477 if(lumpcache[S_sfx[i].lumpnum])
479 if(((memblock_t *)((byte *)(lumpcache[S_sfx[i].lumpnum])-
480 sizeof(memblock_t)))->id == 0x1d4a11)
481 { // taken directly from the Z_ChangeTag macro
482 Z_ChangeTag2(lumpcache[S_sfx[i].lumpnum], PU_CACHE);
484 _dpmi_unlockregion(S_sfx[i].snd_ptr, lumpinfo[S_sfx[i].lumpnum].size);
488 S_sfx[i].usefulness = -1;
489 S_sfx[i].snd_ptr = NULL;
492 nextcleanup = gametic+35; //CLEANUP DEBUG cleans every second
494 for(i=0;i<snd_Channels;i++)
496 if(!channel[i].handle || S_sfx[channel[i].sound_id].usefulness == -1)
500 if(!I_SoundIsPlaying(channel[i].handle))
502 if(S_sfx[channel[i].sound_id].usefulness > 0)
504 S_sfx[channel[i].sound_id].usefulness--;
506 channel[i].handle = 0;
507 channel[i].mo = NULL;
508 channel[i].sound_id = 0;
514 if(channel[i].mo == NULL || channel[i].sound_id == 0
515 || channel[i].mo == players[consoleplayer].mo)
521 absx = abs(channel[i].mo->x-players[consoleplayer].mo->x);
522 absy = abs(channel[i].mo->y-players[consoleplayer].mo->y);
523 dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
525 // dist = P_AproxDistance(channel[i].mo->x-listener->x, channel[i].mo->y-listener->y)>>FRACBITS;
527 if(dist >= MAX_SND_DIST)
529 S_StopSound(channel[i].mo);
535 // calculate the volume based upon the distance from the sound origin.
536 // vol = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+dist)*(snd_MaxVolume*8))>>7;
537 vol = soundCurve[dist];
539 angle = R_PointToAngle2(players[consoleplayer].mo->x,
540 players[consoleplayer].mo->y, channel[i].mo->x, channel[i].mo->y);
541 angle = (angle-viewangle)>>24;
547 I_UpdateSoundParams(channel[i].handle, vol, sep, channel[i].pitch);
548 priority = S_sfx[channel[i].sound_id].priority;
549 priority *= (10 - (dist>>8));
550 channel[i].priority = priority;
557 soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
563 I_SetChannels(snd_Channels);
564 I_SetMusicVolume(snd_MusicVolume);
565 S_SetMaxVolume(true);
568 void S_GetChannelInfo(SoundInfo_t *s)
573 s->channelCount = snd_Channels;
574 s->musicVolume = snd_MusicVolume;
575 s->soundVolume = snd_MaxVolume;
576 for(i = 0; i < snd_Channels; i++)
579 c->id = channel[i].sound_id;
580 c->priority = channel[i].priority;
581 c->name = S_sfx[c->id].name;
582 c->mo = channel[i].mo;
583 c->distance = P_AproxDistance(c->mo->x-viewx, c->mo->y-viewy)
588 void S_SetMaxVolume(boolean fullprocess)
594 soundCurve[0] = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE))*(snd_MaxVolume*8))>>7;
598 for(i = 0; i < MAX_SND_DIST; i++)
600 soundCurve[i] = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+i)*(snd_MaxVolume*8))>>7;
605 static boolean musicPaused;
606 void S_SetMusicVolume(void)
608 I_SetMusicVolume(snd_MusicVolume);
609 if(snd_MusicVolume == 0)
621 void S_ShutDown(void)
627 I_UnRegisterSong(rs);
633 =============================================================================
637 =============================================================================
640 #define SC_INDEX 0x3C4
647 #define CRTC_INDEX 0x3D4
648 #define CRTC_H_TOTAL 0
649 #define CRTC_H_DISPEND 1
650 #define CRTC_H_BLANK 2
651 #define CRTC_H_ENDBLANK 3
652 #define CRTC_H_RETRACE 4
653 #define CRTC_H_ENDRETRACE 5
654 #define CRTC_V_TOTAL 6
655 #define CRTC_OVERFLOW 7
656 #define CRTC_ROWSCAN 8
657 #define CRTC_MAXSCANLINE 9
658 #define CRTC_CURSORSTART 10
659 #define CRTC_CURSOREND 11
660 #define CRTC_STARTHIGH 12
661 #define CRTC_STARTLOW 13
662 #define CRTC_CURSORHIGH 14
663 #define CRTC_CURSORLOW 15
664 #define CRTC_V_RETRACE 16
665 #define CRTC_V_ENDRETRACE 17
666 #define CRTC_V_DISPEND 18
667 #define CRTC_OFFSET 19
668 #define CRTC_UNDERLINE 20
669 #define CRTC_V_BLANK 21
670 #define CRTC_V_ENDBLANK 22
672 #define CRTC_LINECOMPARE 24
675 #define GC_INDEX 0x3CE
676 #define GC_SETRESET 0
677 #define GC_ENABLESETRESET 1
678 #define GC_COLORCOMPARE 2
679 #define GC_DATAROTATE 3
682 #define GC_MISCELLANEOUS 6
683 #define GC_COLORDONTCARE 7
686 #define ATR_INDEX 0x3c0
688 #define ATR_OVERSCAN 17
689 #define ATR_COLORPLANEENABLE 18
690 #define ATR_PELPAN 19
691 #define ATR_COLORSELECT 20
693 #define STATUS_REGISTER_1 0x3da
695 #define PEL_WRITE_ADR 0x3c8
696 #define PEL_READ_ADR 0x3c7
697 #define PEL_DATA 0x3c9
698 #define PEL_MASK 0x3c6
702 //==================================================
706 //==================================================
708 boolean joystickpresent;
709 extern unsigned joystickx, joysticky;
710 boolean I_ReadJoystick (void); // returns false if not connected
713 //==================================================
715 #define VBLCOUNTER 34000 // hardware tics to a frame
719 #define KEYBOARDINT 9
721 #define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1)
722 #define CLI _disable()
723 #define STI _enable()
725 #define _outbyte(x,y) (outp(x,y))
726 #define _outhword(x,y) (outpw(x,y))
728 #define _inbyte(x) (inp(x))
729 #define _inhword(x) (inpw(x))
735 boolean mousepresent;
736 //static int tsm_ID = -1; // tsm init flag
738 //===============================
742 // REGS stuff used for int calls
744 struct SREGS segregs;
746 boolean novideo; // if true, stay in text mode for debugging
748 #define KBDQUESIZE 32
749 byte keyboardque[KBDQUESIZE];
750 int kbdtail, kbdhead;
752 #define KEY_LSHIFT 0xfe
754 #define KEY_INS (0x80+0x52)
755 #define KEY_DEL (0x80+0x53)
756 #define KEY_PGUP (0x80+0x49)
757 #define KEY_PGDN (0x80+0x51)
758 #define KEY_HOME (0x80+0x47)
759 #define KEY_END (0x80+0x4f)
761 #define SC_RSHIFT 0x36
762 #define SC_LSHIFT 0x2a
764 byte scantokey[128] =
768 0 , 27, '1', '2', '3', '4', '5', '6',
769 '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, // 0
770 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
771 'o', 'p', '[', ']', 13 , KEY_RCTRL,'a', 's', // 1
772 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
773 39 , '`', KEY_LSHIFT,92, 'z', 'x', 'c', 'v', // 2
774 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,'*',
775 KEY_RALT,' ', 0 , KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3
776 KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0 , 0 , KEY_HOME,
777 KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4
778 KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0, 0, KEY_F11,
779 KEY_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
780 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
781 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
782 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
783 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
786 //==========================================================================
788 //--------------------------------------------------------------------------
792 // Returns time in 1/35th second tics.
794 //--------------------------------------------------------------------------
804 //--------------------------------------------------------------------------
806 // PROC I_ColorBorder
808 //--------------------------------------------------------------------------
810 void I_ColorBorder(void)
815 _outbyte(PEL_WRITE_ADR, 0);
816 for(i = 0; i < 3; i++)
818 _outbyte(PEL_DATA, 63);
822 //--------------------------------------------------------------------------
824 // PROC I_UnColorBorder
826 //--------------------------------------------------------------------------
828 void I_UnColorBorder(void)
833 _outbyte(PEL_WRITE_ADR, 0);
834 for(i = 0; i < 3; i++)
836 _outbyte(PEL_DATA, 0);
841 ============================================================================
845 ============================================================================
848 //--------------------------------------------------------------------------
852 //--------------------------------------------------------------------------
854 void I_WaitVBL(int vbls)
868 stat = inp(STATUS_REGISTER_1);
876 stat = inp(STATUS_REGISTER_1);
885 //--------------------------------------------------------------------------
889 // Palette source must use 8 bit RGB elements.
891 //--------------------------------------------------------------------------
893 void I_SetPalette(byte *palette)
902 _outbyte(PEL_WRITE_ADR, 0);
903 for(i = 0; i < 768; i++)
905 _outbyte(PEL_DATA, (gammatable[usegamma][*palette++])>>2);
910 ============================================================================
914 ============================================================================
917 byte *pcscreen, *destscreen, *destview;
929 extern int screenblocks;
939 // blit screen to video
943 if(screenblocks > 9 || UpdateState&(I_FULLSCRN|I_MESSAGES))
945 dest = (byte *)screen;
949 dest = (byte *)pcscreen;
951 tics = ticcount-lasttic;
957 for(i = 0; i < tics; i++)
962 for(i = tics; i < 20; i++)
968 if(UpdateState == I_NOUPDATE)
972 if(UpdateState&I_FULLSCRN)
974 memcpy(pcscreen, screen, SCREENWIDTH*SCREENHEIGHT);
975 UpdateState = I_NOUPDATE; // clear out all draw types
977 if(UpdateState&I_FULLVIEW)
979 if(UpdateState&I_MESSAGES && screenblocks > 7)
982 (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
984 memcpy(pcscreen+i, screen+i, SCREENWIDTH);
986 UpdateState &= ~(I_FULLVIEW|I_MESSAGES);
990 for(i = viewwindowy*SCREENWIDTH+viewwindowx; i <
991 (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
993 memcpy(pcscreen+i, screen+i, viewwidth);
995 UpdateState &= ~I_FULLVIEW;
998 if(UpdateState&I_STATBAR)
1000 memcpy(pcscreen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
1001 screen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
1002 SCREENWIDTH*SBARHEIGHT);
1003 UpdateState &= ~I_STATBAR;
1005 if(UpdateState&I_MESSAGES)
1007 memcpy(pcscreen, screen, SCREENWIDTH*28);
1008 UpdateState &= ~I_MESSAGES;
1011 // memcpy(pcscreen, screen, SCREENHEIGHT*SCREENWIDTH);
1014 //--------------------------------------------------------------------------
1016 // PROC I_InitGraphics
1018 //--------------------------------------------------------------------------
1020 void I_InitGraphics(void)
1028 int386(0x10, (const union REGS *)®s, ®s);
1029 pcscreen = destscreen = (byte *)0xa0000;
1030 I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
1034 //--------------------------------------------------------------------------
1036 // PROC I_ShutdownGraphics
1038 //--------------------------------------------------------------------------
1040 void I_ShutdownGraphics(void)
1043 if(*(byte *)0x449 == 0x13) // don't reset mode if it didn't get set
1046 int386(0x10, ®s, ®s); // back to text mode
1050 //--------------------------------------------------------------------------
1052 // PROC I_ReadScreen
1054 // Reads the screen currently displayed into a linear buffer.
1056 //--------------------------------------------------------------------------
1058 void I_ReadScreen(byte *scr)
1060 memcpy(scr, screen, SCREENWIDTH*SCREENHEIGHT);
1064 //===========================================================================
1071 // called by D_DoomLoop
1072 // called before processing each tic in a frame
1073 // can call D_PostEvent
1074 // asyncronous interrupt functions should maintain private ques that are
1075 // read by the syncronous functions to be converted into events
1082 void I_StartTic (void)
1093 while (kbdtail < kbdhead)
1095 k = keyboardque[kbdtail&(KBDQUESIZE-1)];
1098 // I_Error ("exited");
1102 // extended keyboard shift key bullshit
1103 if ( (k&0x7f)==KEY_RSHIFT )
1105 if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
1112 continue; // special / pause keys
1113 if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
1114 continue; // pause key bullshit
1116 if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
1118 ev.type = ev_keydown;
1119 ev.data1 = KEY_PAUSE;
1127 ev.type = ev_keydown;
1131 //ev.data1 = scantokey[k];
1138 #define SC_UPARROW 0x48
1139 #define SC_DOWNARROW 0x50
1140 #define SC_LEFTARROW 0x4b
1141 #define SC_RIGHTARROW 0x4d
1143 void I_StartTic (void)
1154 while (kbdtail < kbdhead)
1156 k = keyboardque[kbdtail&(KBDQUESIZE-1)];
1159 // extended keyboard shift key bullshit
1160 if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
1162 if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
1169 continue; // special / pause keys
1170 if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
1171 continue; // pause key bullshit
1173 if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
1175 ev.type = ev_keydown;
1176 ev.data1 = KEY_PAUSE;
1184 ev.type = ev_keydown;
1189 ev.data1 = KEY_UPARROW;
1192 ev.data1 = KEY_DOWNARROW;
1195 ev.data1 = KEY_LEFTARROW;
1198 ev.data1 = KEY_RIGHTARROW;
1201 ev.data1 = scantokey[k];
1210 void I_ReadKeys (void)
1218 while (kbdtail < kbdhead)
1220 k = keyboardque[kbdtail&(KBDQUESIZE-1)];
1222 printf ("0x%x\n",k);
1237 void I_StartFrame (void)
1239 I_JoystickEvents ();
1240 I_ReadExternDriver();
1244 ============================================================================
1248 ============================================================================
1251 void I_ColorBlack (int r, int g, int b)
1253 _outbyte (PEL_WRITE_ADR,0);
1254 _outbyte(PEL_DATA,r);
1255 _outbyte(PEL_DATA,g);
1256 _outbyte(PEL_DATA,b);
1268 int I_TimerISR (void)
1275 ============================================================================
1279 ============================================================================
1282 void (__interrupt __far *oldkeyboardisr) () = NULL;
1294 void __interrupt I_KeyboardISR (void)
1296 // Get the scan code
1298 keyboardque[kbdhead&(KBDQUESIZE-1)] = lastpress = _inbyte(0x60);
1301 // acknowledge the interrupt
1303 _outbyte(0x20,0x20);
1316 void I_StartupKeyboard (void)
1319 oldkeyboardisr = _dos_getvect(KEYBOARDINT);
1320 _dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
1327 void I_ShutdownKeyboard (void)
1330 _dos_setvect (KEYBOARDINT, oldkeyboardisr);
1331 *(short *)0x41c = *(short *)0x41a; // clear bios key buffer
1337 ============================================================================
1341 ============================================================================
1345 int I_ResetMouse (void)
1347 regs.w.ax = 0; // reset
1348 int386 (0x33, ®s, ®s);
1362 void I_StartupCyberMan(void);
1364 void I_StartupMouse (void)
1366 int (far *function)();
1369 // General mouse detection
1372 if ( M_CheckParm ("-nomouse") || !usemouse )
1375 if (I_ResetMouse () != 0xffff)
1377 tprintf ("Mouse: not present ",0);
1380 tprintf ("Mouse: detected ",0);
1384 I_StartupCyberMan();
1396 void I_ShutdownMouse (void)
1413 void I_ReadMouse (void)
1425 memset (&dpmiregs,0,sizeof(dpmiregs));
1426 dpmiregs.eax = 3; // read buttons / position
1428 ev.data1 = dpmiregs.ebx;
1430 dpmiregs.eax = 11; // read counters
1432 ev.data2 = (short)dpmiregs.ecx;
1433 ev.data3 = -(short)dpmiregs.edx;
1439 ============================================================================
1443 ============================================================================
1446 int joyxl, joyxh, joyyl, joyyh;
1448 boolean WaitJoyButton (void)
1450 int oldbuttons, buttons;
1456 buttons = ((inp(0x201) >> 4)&1)^1;
1457 if (buttons != oldbuttons)
1459 oldbuttons = buttons;
1463 if ( (lastpress& 0x7f) == 1 )
1465 joystickpresent = false;
1468 } while ( !buttons);
1473 buttons = ((inp(0x201) >> 4)&1)^1;
1474 if (buttons != oldbuttons)
1476 oldbuttons = buttons;
1480 if ( (lastpress& 0x7f) == 1 )
1482 joystickpresent = false;
1500 int basejoyx, basejoyy;
1502 void I_StartupJoystick (void)
1506 int centerx, centery;
1508 joystickpresent = 0;
1509 if ( M_CheckParm ("-nojoy") || !usejoystick )
1512 if (!I_ReadJoystick ())
1514 joystickpresent = false;
1515 tprintf ("joystick not found ",0);
1518 printf("joystick found\n");
1519 joystickpresent = true;
1521 printf("CENTER the joystick and press button 1:");
1522 if (!WaitJoyButton ())
1525 centerx = joystickx;
1526 centery = joysticky;
1528 printf("\nPush the joystick to the UPPER LEFT corner and press button 1:");
1529 if (!WaitJoyButton ())
1532 joyxl = (centerx + joystickx)/2;
1533 joyyl = (centerx + joysticky)/2;
1535 printf("\nPush the joystick to the LOWER RIGHT corner and press button 1:");
1536 if (!WaitJoyButton ())
1539 joyxh = (centerx + joystickx)/2;
1540 joyyh = (centery + joysticky)/2;
1552 void I_JoystickEvents (void)
1559 if (!joystickpresent)
1563 ev.type = ev_joystick;
1564 ev.data1 = ((inp(0x201) >> 4)&15)^15;
1566 if (joystickx < joyxl)
1568 else if (joystickx > joyxh)
1572 if (joysticky < joyyl)
1574 else if (joysticky > joyyh)
1585 ============================================================================
1589 ============================================================================
1592 #define REALSTACKSIZE 1024
1594 dpmiregs_t dpmiregs;
1596 unsigned realstackseg;
1598 void I_DivException (void);
1599 int I_SetDivException (void);
1601 void DPMIFarCall (void)
1607 regs.x.edi = (unsigned)&dpmiregs;
1608 segregs.es = segregs.ds;
1609 int386x( DPMI_INT, ®s, ®s, &segregs );
1613 void DPMIInt (int i)
1615 dpmiregs.ss = realstackseg;
1616 dpmiregs.sp = REALSTACKSIZE-4;
1622 regs.x.edi = (unsigned)&dpmiregs;
1623 segregs.es = segregs.ds;
1624 int386x( DPMI_INT, ®s, ®s, &segregs );
1636 void I_StartupDPMI (void)
1638 extern char __begtext;
1639 extern char ___argc;
1643 // allocate a decent stack for real mode ISRs
1645 realstackseg = (int)I_AllocLow (1024) >> 4;
1648 // lock the entire program down
1651 // _dpmi_lockregion (&__begtext, &___argc - &__begtext);
1655 // catch divide by 0 exception
1659 regs.w.ax = 0x0203; // DPMI set processor exception handler vector
1660 regs.w.bx = 0; // int 0
1661 regs.w.cx = segregs.cs;
1662 regs.x.edx = (int)&I_DivException;
1663 printf ("%x : %x\n",regs.w.cx, regs.x.edx);
1664 int386( DPMI_INT, ®s, ®s);
1668 n = I_SetDivException ();
1669 printf ("return: %i\n",n);
1672 printf ("100 / 0 = %i\n",n/d);
1681 ============================================================================
1685 ============================================================================
1688 void (__interrupt __far *oldtimerisr) ();
1691 void IO_ColorBlack (int r, int g, int b)
1693 _outbyte (PEL_WRITE_ADR,0);
1694 _outbyte(PEL_DATA,r);
1695 _outbyte(PEL_DATA,g);
1696 _outbyte(PEL_DATA,b);
1708 //void __interrupt IO_TimerISR (void)
1710 void __interrupt __far IO_TimerISR (void)
1713 _outbyte(0x20,0x20); // Ack the interrupt
1717 =====================
1721 = Sets system timer 0 to the specified speed
1723 =====================
1726 void IO_SetTimer0(int speed)
1728 if (speed > 0 && speed < 150)
1729 I_Error ("INT_SetTimer0: %i is a bad value",speed);
1731 _outbyte(0x43,0x36); // Change timer 0
1732 _outbyte(0x40,speed);
1733 _outbyte(0x40,speed >> 8);
1746 void IO_StartupTimer (void)
1748 oldtimerisr = _dos_getvect(TIMERINT);
1750 _dos_setvect (0x8000 | TIMERINT, IO_TimerISR);
1751 IO_SetTimer0 (VBLCOUNTER);
1754 void IO_ShutdownTimer (void)
1758 IO_SetTimer0 (0); // back to 18.4 ips
1759 _dos_setvect (TIMERINT, oldtimerisr);
1763 //===========================================================================
1771 = hook interrupts and set graphics mode
1778 extern void I_StartupTimer(void);
1780 novideo = M_CheckParm("novideo");
1781 tprintf("I_StartupDPMI",1);
1783 tprintf("I_StartupMouse ",1);
1785 // tprintf("I_StartupJoystick ",1);
1786 // I_StartupJoystick();
1787 // tprintf("I_StartupKeyboard ",1);
1788 // I_StartupKeyboard();
1789 tprintf("S_Init... ",1);
1791 //IO_StartupTimer();
1801 = return to default system state
1806 void I_Shutdown (void)
1808 I_ShutdownGraphics ();
1809 IO_ShutdownTimer ();
1812 I_ShutdownKeyboard ();
1826 void I_Error (char *error, ...)
1834 va_start (argptr,error);
1836 int386(0x10, ®s, ®s);
1837 vprintf (error,argptr);
1843 //--------------------------------------------------------------------------
1847 // Shuts down net game, saves defaults, prints the exit text message,
1848 // goes to text mode, and exits.
1850 //--------------------------------------------------------------------------
1860 scr = (byte *)W_CacheLumpName("ENDTEXT", PU_CACHE);
1862 memcpy((void *)0xb8000, scr, 80*25*2);
1867 int386(0x10, (const union REGS *)®s, ®s); // Set text pos
1868 _settextposition(24, 1);
1880 byte *I_ZoneBase (int *size)
1888 memset (meminfo,0,sizeof(meminfo));
1890 segregs.es = segregs.ds;
1891 regs.w.ax = 0x500; // get memory info
1892 regs.x.edi = (int)&meminfo;
1893 int386x( 0x31, ®s, ®s, &segregs );
1896 printf ("DPMI memory: 0x%x, ",heap);
1900 heap -= 0x10000; // leave 64k alone
1901 if (heap > 0x800000)
1903 ptr = malloc (heap);
1906 printf ("0x%x allocated for zone\n", heap);
1907 if (heap < 0x180000)
1908 I_Error ("Insufficient DPMI memory!");
1910 regs.w.ax = 0x501; // allocate linear block
1911 regs.w.bx = heap>>16;
1912 regs.w.cx = heap&0xffff;
1913 int386( 0x31, ®s, ®s);
1915 I_Error ("Couldn't allocate DPMI memory!");
1917 block = (regs.w.si << 16) + regs.w.di;
1925 =============================================================================
1929 =============================================================================
1932 void I_InitDiskFlash (void)
1938 pic = W_CacheLumpName ("STDISK",PU_CACHE);
1940 destscreen = (byte *)0xac000;
1941 V_DrawPatchDirect (SCREENWIDTH-16,SCREENHEIGHT-16,0,pic);
1947 void I_BeginRead (void)
1956 // write through all planes
1957 outp (SC_INDEX,SC_MAPMASK);
1958 outp (SC_INDEX+1,15);
1960 outp (GC_INDEX,GC_MODE);
1961 outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
1964 src = currentscreen + 184*80 + 304/4;
1965 dest = (byte *)0xac000 + 184*80 + 288/4;
1966 for (y=0 ; y<16 ; y++)
1977 dest = currentscreen + 184*80 + 304/4;
1978 src = (byte *)0xac000 + 184*80 + 304/4;
1979 for (y=0 ; y<16 ; y++)
1991 outp (GC_INDEX,GC_MODE);
1992 outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
1997 void I_EndRead (void)
2006 // write through all planes
2007 outp (SC_INDEX,SC_MAPMASK);
2008 outp (SC_INDEX+1,15);
2010 outp (GC_INDEX,GC_MODE);
2011 outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
2015 dest = currentscreen + 184*80 + 304/4;
2016 src = (byte *)0xac000 + 184*80 + 288/4;
2017 for (y=0 ; y<16 ; y++)
2028 outp (GC_INDEX,GC_MODE);
2029 outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
2043 byte *I_AllocLow (int length)
2047 // DPMI call 100h allocates DOS memory
2049 regs.w.ax = 0x0100; // DPMI allocate DOS memory
2050 regs.w.bx = (length+15) / 16;
2051 int386( DPMI_INT, ®s, ®s);
2052 // segment = regs.w.ax;
2053 // selector = regs.w.dx;
2054 if (regs.w.cflag != 0)
2055 I_Error ("I_AllocLow: DOS alloc of %i failed, %i free",
2056 length, regs.w.bx*16);
2059 mem = (void *) ((regs.x.eax & 0xFFFF) << 4);
2061 memset (mem,0,length);
2066 ============================================================================
2070 ============================================================================
2080 #define DOOMCOM_ID 0x12345678l
2086 short intnum; // DOOM executes an int to execute commands
2088 // communication between DOOM and the driver
2089 short command; // CMD_SEND or CMD_GET
2090 short remotenode; // dest for send, set by get (-1 = no packet)
2091 short datalength; // bytes in doomdata to be sent
2093 // info common to all nodes
2094 short numnodes; // console is allways node 0
2095 short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
2096 short extratics; // 1 = send a backup tic in every packet
2097 short deathmatch; // 1 = deathmatch
2098 short savegame; // -1 = new game, 0-5 = load savegame
2099 short episode; // 1-3
2103 // info specific to this node
2104 short consoleplayer;
2106 short angleoffset; // 1 = left, 0 = center, -1 = right
2107 short drone; // 1 = drone
2109 // packet data to be sent
2114 extern doomcom_t *doomcom;
2117 ====================
2121 ====================
2124 void I_InitNetwork (void)
2128 i = M_CheckParm ("-net");
2132 // single player game
2134 doomcom = malloc (sizeof (*doomcom) );
2135 memset (doomcom, 0, sizeof(*doomcom) );
2137 doomcom->id = DOOMCOM_ID;
2138 doomcom->numplayers = doomcom->numnodes = 1;
2139 doomcom->deathmatch = false;
2140 doomcom->consoleplayer = 0;
2141 doomcom->ticdup = 1;
2142 doomcom->extratics = 0;
2147 doomcom = (doomcom_t *)atoi(myargv[i+1]);
2149 doomcom->skill = startskill;
2150 doomcom->episode = startepisode;
2151 doomcom->map = startmap;
2152 doomcom->deathmatch = deathmatch;
2156 void I_NetCmd (void)
2159 I_Error ("I_NetCmd when not in netgame");
2160 DPMIInt (doomcom->intnum);
2164 externdata_t *i_ExternData;
2165 boolean useexterndriver;
2167 //=========================================================================
2169 // I_CheckExternDriver
2171 // Checks to see if a vector, and an address for an external driver
2172 // have been passed.
2173 //=========================================================================
2175 void I_CheckExternDriver(void)
2179 if(!(i = M_CheckParm("-externdriver")))
2183 i_ExternData = (externdata_t *)atoi(myargv[i+1]);
2184 i_Vector = i_ExternData->vector;
2186 useexterndriver = true;
2189 //=========================================================================
2191 // I_ReadExternDriver
2193 // calls the external interrupt, which should then update i_ExternDriver
2194 //=========================================================================
2196 void I_ReadExternDriver(void)