I_IBM.C 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205
  1. // I_IBM.C
  2. #include <dos.h>
  3. #include <conio.h>
  4. #include <stdlib.h>
  5. #include <stdarg.h>
  6. #include <graph.h>
  7. #include "DoomDef.h"
  8. #include "R_local.h"
  9. #include "sounds.h"
  10. #include "i_sound.h"
  11. #include "dmx.h"
  12. // Macros
  13. #define DPMI_INT 0x31
  14. //#define NOKBD
  15. //#define NOTIMER
  16. // Public Data
  17. int DisplayTicker = 0;
  18. // Code
  19. void main(int argc, char **argv)
  20. {
  21. myargc = argc;
  22. myargv = argv;
  23. D_DoomMain();
  24. }
  25. void I_StartupNet (void);
  26. void I_ShutdownNet (void);
  27. void I_ReadExternDriver(void);
  28. typedef struct
  29. {
  30. unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax;
  31. unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss;
  32. } dpmiregs_t;
  33. extern dpmiregs_t dpmiregs;
  34. void I_ReadMouse (void);
  35. void I_InitDiskFlash (void);
  36. extern int usemouse, usejoystick;
  37. extern void **lumpcache;
  38. /*
  39. ===============================================================================
  40. MUSIC & SFX API
  41. ===============================================================================
  42. */
  43. static channel_t channel[MAX_CHANNELS];
  44. static int rs; //the current registered song.
  45. int mus_song = -1;
  46. int mus_lumpnum;
  47. void *mus_sndptr;
  48. byte *soundCurve;
  49. extern sfxinfo_t S_sfx[];
  50. extern musicinfo_t S_music[];
  51. extern int snd_DesiredMusicDevice;
  52. extern int snd_DesiredSfxDevice;
  53. extern int snd_MaxVolume;
  54. extern int snd_MusicVolume;
  55. extern int snd_Channels;
  56. extern int startepisode;
  57. extern int startmap;
  58. int AmbChan;
  59. void S_Start(void)
  60. {
  61. int i;
  62. S_StartSong((gameepisode-1)*9 + gamemap-1, true);
  63. //stop all sounds
  64. for(i=0; i < snd_Channels; i++)
  65. {
  66. if(channel[i].handle)
  67. {
  68. S_StopSound(channel[i].mo);
  69. }
  70. }
  71. memset(channel, 0, 8*sizeof(channel_t));
  72. }
  73. void S_StartSong(int song, boolean loop)
  74. {
  75. if(song == mus_song)
  76. { // don't replay an old song
  77. return;
  78. }
  79. if(rs)
  80. {
  81. I_StopSong(rs);
  82. I_UnRegisterSong(rs);
  83. Z_ChangeTag(lumpcache[mus_lumpnum], PU_CACHE);
  84. #ifdef __WATCOMC__
  85. _dpmi_unlockregion(mus_sndptr, lumpinfo[mus_lumpnum].size);
  86. #endif
  87. }
  88. if(song < mus_e1m1 || song > NUMMUSIC)
  89. {
  90. return;
  91. }
  92. mus_lumpnum = W_GetNumForName(S_music[song].name);
  93. mus_sndptr = W_CacheLumpNum(mus_lumpnum, PU_MUSIC);
  94. #ifdef __WATCOMC__
  95. _dpmi_lockregion(mus_sndptr, lumpinfo[mus_lumpnum].size);
  96. #endif
  97. rs = I_RegisterSong(mus_sndptr);
  98. I_PlaySong(rs, loop); //'true' denotes endless looping.
  99. mus_song = song;
  100. }
  101. void S_StartSound(mobj_t *origin, int sound_id)
  102. {
  103. int dist, vol;
  104. int i;
  105. int sound;
  106. int priority;
  107. int sep;
  108. int angle;
  109. int absx;
  110. int absy;
  111. static int sndcount = 0;
  112. int chan;
  113. if(sound_id==0 || snd_MaxVolume == 0)
  114. return;
  115. if(origin == NULL)
  116. {
  117. origin = players[consoleplayer].mo;
  118. }
  119. // calculate the distance before other stuff so that we can throw out
  120. // sounds that are beyond the hearing range.
  121. absx = abs(origin->x-players[consoleplayer].mo->x);
  122. absy = abs(origin->y-players[consoleplayer].mo->y);
  123. dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
  124. dist >>= FRACBITS;
  125. // dist = P_AproxDistance(origin->x-viewx, origin->y-viewy)>>FRACBITS;
  126. if(dist >= MAX_SND_DIST)
  127. {
  128. // dist = MAX_SND_DIST - 1;
  129. return; //sound is beyond the hearing range...
  130. }
  131. if(dist < 0)
  132. {
  133. dist = 0;
  134. }
  135. priority = S_sfx[sound_id].priority;
  136. priority *= (10 - (dist/160));
  137. if(!S_StopSoundID(sound_id, priority))
  138. {
  139. return; // other sounds have greater priority
  140. }
  141. for(i=0; i<snd_Channels; i++)
  142. {
  143. if(origin->player)
  144. {
  145. i = snd_Channels;
  146. break; // let the player have more than one sound.
  147. }
  148. if(origin == channel[i].mo)
  149. { // only allow other mobjs one sound
  150. S_StopSound(channel[i].mo);
  151. break;
  152. }
  153. }
  154. if(i >= snd_Channels)
  155. {
  156. if(sound_id >= sfx_wind)
  157. {
  158. if(AmbChan != -1 && S_sfx[sound_id].priority <=
  159. S_sfx[channel[AmbChan].sound_id].priority)
  160. {
  161. return; //ambient channel already in use
  162. }
  163. else
  164. {
  165. AmbChan = -1;
  166. }
  167. }
  168. for(i=0; i<snd_Channels; i++)
  169. {
  170. if(channel[i].mo == NULL)
  171. {
  172. break;
  173. }
  174. }
  175. if(i >= snd_Channels)
  176. {
  177. //look for a lower priority sound to replace.
  178. sndcount++;
  179. if(sndcount >= snd_Channels)
  180. {
  181. sndcount = 0;
  182. }
  183. for(chan=0; chan < snd_Channels; chan++)
  184. {
  185. i = (sndcount+chan)%snd_Channels;
  186. if(priority >= channel[i].priority)
  187. {
  188. chan = -1; //denote that sound should be replaced.
  189. break;
  190. }
  191. }
  192. if(chan != -1)
  193. {
  194. return; //no free channels.
  195. }
  196. else //replace the lower priority sound.
  197. {
  198. if(channel[i].handle)
  199. {
  200. if(I_SoundIsPlaying(channel[i].handle))
  201. {
  202. I_StopSound(channel[i].handle);
  203. }
  204. if(S_sfx[channel[i].sound_id].usefulness > 0)
  205. {
  206. S_sfx[channel[i].sound_id].usefulness--;
  207. }
  208. if(AmbChan == i)
  209. {
  210. AmbChan = -1;
  211. }
  212. }
  213. }
  214. }
  215. }
  216. if(S_sfx[sound_id].lumpnum == 0)
  217. {
  218. S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]);
  219. }
  220. if(S_sfx[sound_id].snd_ptr == NULL)
  221. {
  222. S_sfx[sound_id].snd_ptr = W_CacheLumpNum(S_sfx[sound_id].lumpnum,
  223. PU_SOUND);
  224. #ifdef __WATCOMC__
  225. _dpmi_lockregion(S_sfx[sound_id].snd_ptr,
  226. lumpinfo[S_sfx[sound_id].lumpnum].size);
  227. #endif
  228. }
  229. // calculate the volume based upon the distance from the sound origin.
  230. // vol = (snd_MaxVolume*16 + dist*(-snd_MaxVolume*16)/MAX_SND_DIST)>>9;
  231. vol = soundCurve[dist];
  232. if(origin == players[consoleplayer].mo)
  233. {
  234. sep = 128;
  235. }
  236. else
  237. {
  238. angle = R_PointToAngle2(players[consoleplayer].mo->x,
  239. players[consoleplayer].mo->y, channel[i].mo->x, channel[i].mo->y);
  240. angle = (angle-viewangle)>>24;
  241. sep = angle*2-128;
  242. if(sep < 64)
  243. sep = -sep;
  244. if(sep > 192)
  245. sep = 512-sep;
  246. }
  247. channel[i].pitch = (byte)(127+(M_Random()&7)-(M_Random()&7));
  248. channel[i].handle = I_StartSound(sound_id, S_sfx[sound_id].snd_ptr, vol, sep, channel[i].pitch, 0);
  249. channel[i].mo = origin;
  250. channel[i].sound_id = sound_id;
  251. channel[i].priority = priority;
  252. if(sound_id >= sfx_wind)
  253. {
  254. AmbChan = i;
  255. }
  256. if(S_sfx[sound_id].usefulness == -1)
  257. {
  258. S_sfx[sound_id].usefulness = 1;
  259. }
  260. else
  261. {
  262. S_sfx[sound_id].usefulness++;
  263. }
  264. }
  265. void S_StartSoundAtVolume(mobj_t *origin, int sound_id, int volume)
  266. {
  267. int dist;
  268. int i;
  269. int sep;
  270. static int sndcount;
  271. int chan;
  272. if(sound_id == 0 || snd_MaxVolume == 0)
  273. return;
  274. if(origin == NULL)
  275. {
  276. origin = players[consoleplayer].mo;
  277. }
  278. if(volume == 0)
  279. {
  280. return;
  281. }
  282. volume = (volume*(snd_MaxVolume+1)*8)>>7;
  283. // no priority checking, as ambient sounds would be the LOWEST.
  284. for(i=0; i<snd_Channels; i++)
  285. {
  286. if(channel[i].mo == NULL)
  287. {
  288. break;
  289. }
  290. }
  291. if(i >= snd_Channels)
  292. {
  293. return;
  294. }
  295. if(S_sfx[sound_id].lumpnum == 0)
  296. {
  297. S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]);
  298. }
  299. if(S_sfx[sound_id].snd_ptr == NULL)
  300. {
  301. S_sfx[sound_id].snd_ptr = W_CacheLumpNum(S_sfx[sound_id].lumpnum,
  302. PU_SOUND);
  303. #ifdef __WATCOMC__
  304. _dpmi_lockregion(S_sfx[sound_id].snd_ptr,
  305. lumpinfo[S_sfx[sound_id].lumpnum].size);
  306. #endif
  307. }
  308. channel[i].pitch = (byte)(127-(M_Random()&3)+(M_Random()&3));
  309. channel[i].handle = I_StartSound(sound_id, S_sfx[sound_id].snd_ptr, volume, 128, channel[i].pitch, 0);
  310. channel[i].mo = origin;
  311. channel[i].sound_id = sound_id;
  312. channel[i].priority = 1; //super low priority.
  313. if(S_sfx[sound_id].usefulness == -1)
  314. {
  315. S_sfx[sound_id].usefulness = 1;
  316. }
  317. else
  318. {
  319. S_sfx[sound_id].usefulness++;
  320. }
  321. }
  322. boolean S_StopSoundID(int sound_id, int priority)
  323. {
  324. int i;
  325. int lp; //least priority
  326. int found;
  327. if(S_sfx[sound_id].numchannels == -1)
  328. {
  329. return(true);
  330. }
  331. lp = -1; //denote the argument sound_id
  332. found = 0;
  333. for(i=0; i<snd_Channels; i++)
  334. {
  335. if(channel[i].sound_id == sound_id && channel[i].mo)
  336. {
  337. found++; //found one. Now, should we replace it??
  338. if(priority >= channel[i].priority)
  339. { // if we're gonna kill one, then this'll be it
  340. lp = i;
  341. priority = channel[i].priority;
  342. }
  343. }
  344. }
  345. if(found < S_sfx[sound_id].numchannels)
  346. {
  347. return(true);
  348. }
  349. else if(lp == -1)
  350. {
  351. return(false); // don't replace any sounds
  352. }
  353. if(channel[lp].handle)
  354. {
  355. if(I_SoundIsPlaying(channel[lp].handle))
  356. {
  357. I_StopSound(channel[lp].handle);
  358. }
  359. if(S_sfx[channel[i].sound_id].usefulness > 0)
  360. {
  361. S_sfx[channel[i].sound_id].usefulness--;
  362. }
  363. channel[lp].mo = NULL;
  364. }
  365. return(true);
  366. }
  367. void S_StopSound(mobj_t *origin)
  368. {
  369. int i;
  370. for(i=0;i<snd_Channels;i++)
  371. {
  372. if(channel[i].mo == origin)
  373. {
  374. I_StopSound(channel[i].handle);
  375. if(S_sfx[channel[i].sound_id].usefulness > 0)
  376. {
  377. S_sfx[channel[i].sound_id].usefulness--;
  378. }
  379. channel[i].handle = 0;
  380. channel[i].mo = NULL;
  381. if(AmbChan == i)
  382. {
  383. AmbChan = -1;
  384. }
  385. }
  386. }
  387. }
  388. void S_SoundLink(mobj_t *oldactor, mobj_t *newactor)
  389. {
  390. int i;
  391. for(i=0;i<snd_Channels;i++)
  392. {
  393. if(channel[i].mo == oldactor)
  394. channel[i].mo = newactor;
  395. }
  396. }
  397. void S_PauseSound(void)
  398. {
  399. I_PauseSong(rs);
  400. }
  401. void S_ResumeSound(void)
  402. {
  403. I_ResumeSong(rs);
  404. }
  405. static int nextcleanup;
  406. void S_UpdateSounds(mobj_t *listener)
  407. {
  408. int i, dist, vol;
  409. int angle;
  410. int sep;
  411. int priority;
  412. int absx;
  413. int absy;
  414. listener = players[consoleplayer].mo;
  415. if(snd_MaxVolume == 0)
  416. {
  417. return;
  418. }
  419. if(nextcleanup < gametic)
  420. {
  421. for(i=0; i < NUMSFX; i++)
  422. {
  423. if(S_sfx[i].usefulness == 0 && S_sfx[i].snd_ptr)
  424. {
  425. if(lumpcache[S_sfx[i].lumpnum])
  426. {
  427. if(((memblock_t *)((byte *)(lumpcache[S_sfx[i].lumpnum])-
  428. sizeof(memblock_t)))->id == 0x1d4a11)
  429. { // taken directly from the Z_ChangeTag macro
  430. Z_ChangeTag2(lumpcache[S_sfx[i].lumpnum], PU_CACHE);
  431. #ifdef __WATCOMC__
  432. _dpmi_unlockregion(S_sfx[i].snd_ptr, lumpinfo[S_sfx[i].lumpnum].size);
  433. #endif
  434. }
  435. }
  436. S_sfx[i].usefulness = -1;
  437. S_sfx[i].snd_ptr = NULL;
  438. }
  439. }
  440. nextcleanup = gametic+35; //CLEANUP DEBUG cleans every second
  441. }
  442. for(i=0;i<snd_Channels;i++)
  443. {
  444. if(!channel[i].handle || S_sfx[channel[i].sound_id].usefulness == -1)
  445. {
  446. continue;
  447. }
  448. if(!I_SoundIsPlaying(channel[i].handle))
  449. {
  450. if(S_sfx[channel[i].sound_id].usefulness > 0)
  451. {
  452. S_sfx[channel[i].sound_id].usefulness--;
  453. }
  454. channel[i].handle = 0;
  455. channel[i].mo = NULL;
  456. channel[i].sound_id = 0;
  457. if(AmbChan == i)
  458. {
  459. AmbChan = -1;
  460. }
  461. }
  462. if(channel[i].mo == NULL || channel[i].sound_id == 0
  463. || channel[i].mo == players[consoleplayer].mo)
  464. {
  465. continue;
  466. }
  467. else
  468. {
  469. absx = abs(channel[i].mo->x-players[consoleplayer].mo->x);
  470. absy = abs(channel[i].mo->y-players[consoleplayer].mo->y);
  471. dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
  472. dist >>= FRACBITS;
  473. // dist = P_AproxDistance(channel[i].mo->x-listener->x, channel[i].mo->y-listener->y)>>FRACBITS;
  474. if(dist >= MAX_SND_DIST)
  475. {
  476. S_StopSound(channel[i].mo);
  477. continue;
  478. }
  479. if(dist < 0)
  480. dist = 0;
  481. // calculate the volume based upon the distance from the sound origin.
  482. // vol = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+dist)*(snd_MaxVolume*8))>>7;
  483. vol = soundCurve[dist];
  484. angle = R_PointToAngle2(players[consoleplayer].mo->x,
  485. players[consoleplayer].mo->y, channel[i].mo->x, channel[i].mo->y);
  486. angle = (angle-viewangle)>>24;
  487. sep = angle*2-128;
  488. if(sep < 64)
  489. sep = -sep;
  490. if(sep > 192)
  491. sep = 512-sep;
  492. I_UpdateSoundParams(channel[i].handle, vol, sep, channel[i].pitch);
  493. priority = S_sfx[channel[i].sound_id].priority;
  494. priority *= (10 - (dist>>8));
  495. channel[i].priority = priority;
  496. }
  497. }
  498. }
  499. void S_Init(void)
  500. {
  501. soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
  502. I_StartupSound();
  503. if(snd_Channels > 8)
  504. {
  505. snd_Channels = 8;
  506. }
  507. I_SetChannels(snd_Channels);
  508. I_SetMusicVolume(snd_MusicVolume);
  509. S_SetMaxVolume(true);
  510. }
  511. void S_GetChannelInfo(SoundInfo_t *s)
  512. {
  513. int i;
  514. ChanInfo_t *c;
  515. s->channelCount = snd_Channels;
  516. s->musicVolume = snd_MusicVolume;
  517. s->soundVolume = snd_MaxVolume;
  518. for(i = 0; i < snd_Channels; i++)
  519. {
  520. c = &s->chan[i];
  521. c->id = channel[i].sound_id;
  522. c->priority = channel[i].priority;
  523. c->name = S_sfx[c->id].name;
  524. c->mo = channel[i].mo;
  525. c->distance = P_AproxDistance(c->mo->x-viewx, c->mo->y-viewy)
  526. >>FRACBITS;
  527. }
  528. }
  529. void S_SetMaxVolume(boolean fullprocess)
  530. {
  531. int i;
  532. if(!fullprocess)
  533. {
  534. soundCurve[0] = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE))*(snd_MaxVolume*8))>>7;
  535. }
  536. else
  537. {
  538. for(i = 0; i < MAX_SND_DIST; i++)
  539. {
  540. soundCurve[i] = (*((byte *)W_CacheLumpName("SNDCURVE", PU_CACHE)+i)*(snd_MaxVolume*8))>>7;
  541. }
  542. }
  543. }
  544. static boolean musicPaused;
  545. void S_SetMusicVolume(void)
  546. {
  547. I_SetMusicVolume(snd_MusicVolume);
  548. if(snd_MusicVolume == 0)
  549. {
  550. I_PauseSong(rs);
  551. musicPaused = true;
  552. }
  553. else if(musicPaused)
  554. {
  555. musicPaused = false;
  556. I_ResumeSong(rs);
  557. }
  558. }
  559. void S_ShutDown(void)
  560. {
  561. extern int tsm_ID;
  562. if(tsm_ID != -1)
  563. {
  564. I_StopSong(rs);
  565. I_UnRegisterSong(rs);
  566. I_ShutdownSound();
  567. }
  568. }
  569. /*
  570. =============================================================================
  571. CONSTANTS
  572. =============================================================================
  573. */
  574. #define SC_INDEX 0x3C4
  575. #define SC_RESET 0
  576. #define SC_CLOCK 1
  577. #define SC_MAPMASK 2
  578. #define SC_CHARMAP 3
  579. #define SC_MEMMODE 4
  580. #define CRTC_INDEX 0x3D4
  581. #define CRTC_H_TOTAL 0
  582. #define CRTC_H_DISPEND 1
  583. #define CRTC_H_BLANK 2
  584. #define CRTC_H_ENDBLANK 3
  585. #define CRTC_H_RETRACE 4
  586. #define CRTC_H_ENDRETRACE 5
  587. #define CRTC_V_TOTAL 6
  588. #define CRTC_OVERFLOW 7
  589. #define CRTC_ROWSCAN 8
  590. #define CRTC_MAXSCANLINE 9
  591. #define CRTC_CURSORSTART 10
  592. #define CRTC_CURSOREND 11
  593. #define CRTC_STARTHIGH 12
  594. #define CRTC_STARTLOW 13
  595. #define CRTC_CURSORHIGH 14
  596. #define CRTC_CURSORLOW 15
  597. #define CRTC_V_RETRACE 16
  598. #define CRTC_V_ENDRETRACE 17
  599. #define CRTC_V_DISPEND 18
  600. #define CRTC_OFFSET 19
  601. #define CRTC_UNDERLINE 20
  602. #define CRTC_V_BLANK 21
  603. #define CRTC_V_ENDBLANK 22
  604. #define CRTC_MODE 23
  605. #define CRTC_LINECOMPARE 24
  606. #define GC_INDEX 0x3CE
  607. #define GC_SETRESET 0
  608. #define GC_ENABLESETRESET 1
  609. #define GC_COLORCOMPARE 2
  610. #define GC_DATAROTATE 3
  611. #define GC_READMAP 4
  612. #define GC_MODE 5
  613. #define GC_MISCELLANEOUS 6
  614. #define GC_COLORDONTCARE 7
  615. #define GC_BITMASK 8
  616. #define ATR_INDEX 0x3c0
  617. #define ATR_MODE 16
  618. #define ATR_OVERSCAN 17
  619. #define ATR_COLORPLANEENABLE 18
  620. #define ATR_PELPAN 19
  621. #define ATR_COLORSELECT 20
  622. #define STATUS_REGISTER_1 0x3da
  623. #define PEL_WRITE_ADR 0x3c8
  624. #define PEL_READ_ADR 0x3c7
  625. #define PEL_DATA 0x3c9
  626. #define PEL_MASK 0x3c6
  627. boolean grmode;
  628. //==================================================
  629. //
  630. // joystick vars
  631. //
  632. //==================================================
  633. boolean joystickpresent;
  634. extern unsigned joystickx, joysticky;
  635. boolean I_ReadJoystick (void); // returns false if not connected
  636. //==================================================
  637. #define VBLCOUNTER 34000 // hardware tics to a frame
  638. #define TIMERINT 8
  639. #define KEYBOARDINT 9
  640. #define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1)
  641. #define CLI _disable()
  642. #define STI _enable()
  643. #define _outbyte(x,y) (outp(x,y))
  644. #define _outhword(x,y) (outpw(x,y))
  645. #define _inbyte(x) (inp(x))
  646. #define _inhword(x) (inpw(x))
  647. #define MOUSEB1 1
  648. #define MOUSEB2 2
  649. #define MOUSEB3 4
  650. boolean mousepresent;
  651. //static int tsm_ID = -1; // tsm init flag
  652. //===============================
  653. int ticcount;
  654. // REGS stuff used for int calls
  655. union REGS regs;
  656. struct SREGS segregs;
  657. boolean novideo; // if true, stay in text mode for debugging
  658. #define KBDQUESIZE 32
  659. byte keyboardque[KBDQUESIZE];
  660. int kbdtail, kbdhead;
  661. #define KEY_LSHIFT 0xfe
  662. #define KEY_INS (0x80+0x52)
  663. #define KEY_DEL (0x80+0x53)
  664. #define KEY_PGUP (0x80+0x49)
  665. #define KEY_PGDN (0x80+0x51)
  666. #define KEY_HOME (0x80+0x47)
  667. #define KEY_END (0x80+0x4f)
  668. #define SC_RSHIFT 0x36
  669. #define SC_LSHIFT 0x2a
  670. byte scantokey[128] =
  671. {
  672. // 0 1 2 3 4 5 6 7
  673. // 8 9 A B C D E F
  674. 0 , 27, '1', '2', '3', '4', '5', '6',
  675. '7', '8', '9', '0', '-', '=', KEY_BACKSPACE, 9, // 0
  676. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  677. 'o', 'p', '[', ']', 13 , KEY_RCTRL,'a', 's', // 1
  678. 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
  679. 39 , '`', KEY_LSHIFT,92, 'z', 'x', 'c', 'v', // 2
  680. 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,'*',
  681. KEY_RALT,' ', 0 , KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3
  682. KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0 , 0 , KEY_HOME,
  683. KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4
  684. KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0, 0, KEY_F11,
  685. KEY_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5
  686. 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  687. 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
  688. 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  689. 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
  690. };
  691. //==========================================================================
  692. //--------------------------------------------------------------------------
  693. //
  694. // FUNC I_GetTime
  695. //
  696. // Returns time in 1/35th second tics.
  697. //
  698. //--------------------------------------------------------------------------
  699. int I_GetTime (void)
  700. {
  701. #ifdef NOTIMER
  702. ticcount++;
  703. #endif
  704. return(ticcount);
  705. }
  706. //--------------------------------------------------------------------------
  707. //
  708. // PROC I_ColorBorder
  709. //
  710. //--------------------------------------------------------------------------
  711. void I_ColorBorder(void)
  712. {
  713. int i;
  714. I_WaitVBL(1);
  715. _outbyte(PEL_WRITE_ADR, 0);
  716. for(i = 0; i < 3; i++)
  717. {
  718. _outbyte(PEL_DATA, 63);
  719. }
  720. }
  721. //--------------------------------------------------------------------------
  722. //
  723. // PROC I_UnColorBorder
  724. //
  725. //--------------------------------------------------------------------------
  726. void I_UnColorBorder(void)
  727. {
  728. int i;
  729. I_WaitVBL(1);
  730. _outbyte(PEL_WRITE_ADR, 0);
  731. for(i = 0; i < 3; i++)
  732. {
  733. _outbyte(PEL_DATA, 0);
  734. }
  735. }
  736. /*
  737. ============================================================================
  738. USER INPUT
  739. ============================================================================
  740. */
  741. //--------------------------------------------------------------------------
  742. //
  743. // PROC I_WaitVBL
  744. //
  745. //--------------------------------------------------------------------------
  746. void I_WaitVBL(int vbls)
  747. {
  748. int i;
  749. int old;
  750. int stat;
  751. if(novideo)
  752. {
  753. return;
  754. }
  755. while(vbls--)
  756. {
  757. do
  758. {
  759. stat = inp(STATUS_REGISTER_1);
  760. if(stat&8)
  761. {
  762. break;
  763. }
  764. } while(1);
  765. do
  766. {
  767. stat = inp(STATUS_REGISTER_1);
  768. if((stat&8) == 0)
  769. {
  770. break;
  771. }
  772. } while(1);
  773. }
  774. }
  775. //--------------------------------------------------------------------------
  776. //
  777. // PROC I_SetPalette
  778. //
  779. // Palette source must use 8 bit RGB elements.
  780. //
  781. //--------------------------------------------------------------------------
  782. void I_SetPalette(byte *palette)
  783. {
  784. int i;
  785. if(novideo)
  786. {
  787. return;
  788. }
  789. I_WaitVBL(1);
  790. _outbyte(PEL_WRITE_ADR, 0);
  791. for(i = 0; i < 768; i++)
  792. {
  793. _outbyte(PEL_DATA, (gammatable[usegamma][*palette++])>>2);
  794. }
  795. }
  796. /*
  797. ============================================================================
  798. GRAPHICS MODE
  799. ============================================================================
  800. */
  801. byte *pcscreen, *destscreen, *destview;
  802. /*
  803. ==============
  804. =
  805. = I_Update
  806. =
  807. ==============
  808. */
  809. int UpdateState;
  810. extern int screenblocks;
  811. void I_Update (void)
  812. {
  813. int i;
  814. byte *dest;
  815. int tics;
  816. static int lasttic;
  817. //
  818. // blit screen to video
  819. //
  820. if(DisplayTicker)
  821. {
  822. if(screenblocks > 9 || UpdateState&(I_FULLSCRN|I_MESSAGES))
  823. {
  824. dest = (byte *)screen;
  825. }
  826. else
  827. {
  828. dest = (byte *)pcscreen;
  829. }
  830. tics = ticcount-lasttic;
  831. lasttic = ticcount;
  832. if(tics > 20)
  833. {
  834. tics = 20;
  835. }
  836. for(i = 0; i < tics; i++)
  837. {
  838. *dest = 0xff;
  839. dest += 2;
  840. }
  841. for(i = tics; i < 20; i++)
  842. {
  843. *dest = 0x00;
  844. dest += 2;
  845. }
  846. }
  847. if(UpdateState == I_NOUPDATE)
  848. {
  849. return;
  850. }
  851. if(UpdateState&I_FULLSCRN)
  852. {
  853. memcpy(pcscreen, screen, SCREENWIDTH*SCREENHEIGHT);
  854. UpdateState = I_NOUPDATE; // clear out all draw types
  855. }
  856. if(UpdateState&I_FULLVIEW)
  857. {
  858. if(UpdateState&I_MESSAGES && screenblocks > 7)
  859. {
  860. for(i = 0; i <
  861. (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
  862. {
  863. memcpy(pcscreen+i, screen+i, SCREENWIDTH);
  864. }
  865. UpdateState &= ~(I_FULLVIEW|I_MESSAGES);
  866. }
  867. else
  868. {
  869. for(i = viewwindowy*SCREENWIDTH+viewwindowx; i <
  870. (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
  871. {
  872. memcpy(pcscreen+i, screen+i, viewwidth);
  873. }
  874. UpdateState &= ~I_FULLVIEW;
  875. }
  876. }
  877. if(UpdateState&I_STATBAR)
  878. {
  879. memcpy(pcscreen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
  880. screen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
  881. SCREENWIDTH*SBARHEIGHT);
  882. UpdateState &= ~I_STATBAR;
  883. }
  884. if(UpdateState&I_MESSAGES)
  885. {
  886. memcpy(pcscreen, screen, SCREENWIDTH*28);
  887. UpdateState &= ~I_MESSAGES;
  888. }
  889. // memcpy(pcscreen, screen, SCREENHEIGHT*SCREENWIDTH);
  890. }
  891. //--------------------------------------------------------------------------
  892. //
  893. // PROC I_InitGraphics
  894. //
  895. //--------------------------------------------------------------------------
  896. void I_InitGraphics(void)
  897. {
  898. if(novideo)
  899. {
  900. return;
  901. }
  902. grmode = true;
  903. regs.w.ax = 0x13;
  904. int386(0x10, (const union REGS *)&regs, &regs);
  905. pcscreen = destscreen = (byte *)0xa0000;
  906. I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
  907. I_InitDiskFlash();
  908. }
  909. //--------------------------------------------------------------------------
  910. //
  911. // PROC I_ShutdownGraphics
  912. //
  913. //--------------------------------------------------------------------------
  914. void I_ShutdownGraphics(void)
  915. {
  916. if(*(byte *)0x449 == 0x13) // don't reset mode if it didn't get set
  917. {
  918. regs.w.ax = 3;
  919. int386(0x10, &regs, &regs); // back to text mode
  920. }
  921. }
  922. //--------------------------------------------------------------------------
  923. //
  924. // PROC I_ReadScreen
  925. //
  926. // Reads the screen currently displayed into a linear buffer.
  927. //
  928. //--------------------------------------------------------------------------
  929. void I_ReadScreen(byte *scr)
  930. {
  931. memcpy(scr, screen, SCREENWIDTH*SCREENHEIGHT);
  932. }
  933. //===========================================================================
  934. /*
  935. ===================
  936. =
  937. = I_StartTic
  938. =
  939. // called by D_DoomLoop
  940. // called before processing each tic in a frame
  941. // can call D_PostEvent
  942. // asyncronous interrupt functions should maintain private ques that are
  943. // read by the syncronous functions to be converted into events
  944. ===================
  945. */
  946. /*
  947. OLD STARTTIC STUFF
  948. void I_StartTic (void)
  949. {
  950. int k;
  951. event_t ev;
  952. I_ReadMouse ();
  953. //
  954. // keyboard events
  955. //
  956. while (kbdtail < kbdhead)
  957. {
  958. k = keyboardque[kbdtail&(KBDQUESIZE-1)];
  959. // if (k==14)
  960. // I_Error ("exited");
  961. kbdtail++;
  962. // extended keyboard shift key bullshit
  963. if ( (k&0x7f)==KEY_RSHIFT )
  964. {
  965. if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
  966. continue;
  967. k &= 0x80;
  968. k |= KEY_RSHIFT;
  969. }
  970. if (k==0xe0)
  971. continue; // special / pause keys
  972. if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
  973. continue; // pause key bullshit
  974. if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
  975. {
  976. ev.type = ev_keydown;
  977. ev.data1 = KEY_PAUSE;
  978. D_PostEvent (&ev);
  979. continue;
  980. }
  981. if (k&0x80)
  982. ev.type = ev_keyup;
  983. else
  984. ev.type = ev_keydown;
  985. k &= 0x7f;
  986. ev.data1 = k;
  987. //ev.data1 = scantokey[k];
  988. D_PostEvent (&ev);
  989. }
  990. }
  991. */
  992. #define SC_UPARROW 0x48
  993. #define SC_DOWNARROW 0x50
  994. #define SC_LEFTARROW 0x4b
  995. #define SC_RIGHTARROW 0x4d
  996. void I_StartTic (void)
  997. {
  998. int k;
  999. event_t ev;
  1000. I_ReadMouse ();
  1001. //
  1002. // keyboard events
  1003. //
  1004. while (kbdtail < kbdhead)
  1005. {
  1006. k = keyboardque[kbdtail&(KBDQUESIZE-1)];
  1007. kbdtail++;
  1008. // extended keyboard shift key bullshit
  1009. if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
  1010. {
  1011. if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
  1012. continue;
  1013. k &= 0x80;
  1014. k |= SC_RSHIFT;
  1015. }
  1016. if (k==0xe0)
  1017. continue; // special / pause keys
  1018. if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
  1019. continue; // pause key bullshit
  1020. if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
  1021. {
  1022. ev.type = ev_keydown;
  1023. ev.data1 = KEY_PAUSE;
  1024. D_PostEvent (&ev);
  1025. continue;
  1026. }
  1027. if (k&0x80)
  1028. ev.type = ev_keyup;
  1029. else
  1030. ev.type = ev_keydown;
  1031. k &= 0x7f;
  1032. switch (k)
  1033. {
  1034. case SC_UPARROW:
  1035. ev.data1 = KEY_UPARROW;
  1036. break;
  1037. case SC_DOWNARROW:
  1038. ev.data1 = KEY_DOWNARROW;
  1039. break;
  1040. case SC_LEFTARROW:
  1041. ev.data1 = KEY_LEFTARROW;
  1042. break;
  1043. case SC_RIGHTARROW:
  1044. ev.data1 = KEY_RIGHTARROW;
  1045. break;
  1046. default:
  1047. ev.data1 = scantokey[k];
  1048. break;
  1049. }
  1050. D_PostEvent (&ev);
  1051. }
  1052. }
  1053. void I_ReadKeys (void)
  1054. {
  1055. int k;
  1056. event_t ev;
  1057. while (1)
  1058. {
  1059. while (kbdtail < kbdhead)
  1060. {
  1061. k = keyboardque[kbdtail&(KBDQUESIZE-1)];
  1062. kbdtail++;
  1063. printf ("0x%x\n",k);
  1064. if (k == 1)
  1065. I_Quit ();
  1066. }
  1067. }
  1068. }
  1069. /*
  1070. ===============
  1071. =
  1072. = I_StartFrame
  1073. =
  1074. ===============
  1075. */
  1076. void I_StartFrame (void)
  1077. {
  1078. I_JoystickEvents ();
  1079. I_ReadExternDriver();
  1080. }
  1081. /*
  1082. ============================================================================
  1083. TIMER INTERRUPT
  1084. ============================================================================
  1085. */
  1086. void I_ColorBlack (int r, int g, int b)
  1087. {
  1088. _outbyte (PEL_WRITE_ADR,0);
  1089. _outbyte(PEL_DATA,r);
  1090. _outbyte(PEL_DATA,g);
  1091. _outbyte(PEL_DATA,b);
  1092. }
  1093. /*
  1094. ================
  1095. =
  1096. = I_TimerISR
  1097. =
  1098. ================
  1099. */
  1100. int I_TimerISR (void)
  1101. {
  1102. ticcount++;
  1103. return 0;
  1104. }
  1105. /*
  1106. ============================================================================
  1107. KEYBOARD
  1108. ============================================================================
  1109. */
  1110. void (__interrupt __far *oldkeyboardisr) () = NULL;
  1111. int lastpress;
  1112. /*
  1113. ================
  1114. =
  1115. = I_KeyboardISR
  1116. =
  1117. ================
  1118. */
  1119. void __interrupt I_KeyboardISR (void)
  1120. {
  1121. // Get the scan code
  1122. keyboardque[kbdhead&(KBDQUESIZE-1)] = lastpress = _inbyte(0x60);
  1123. kbdhead++;
  1124. // acknowledge the interrupt
  1125. _outbyte(0x20,0x20);
  1126. }
  1127. /*
  1128. ===============
  1129. =
  1130. = I_StartupKeyboard
  1131. =
  1132. ===============
  1133. */
  1134. void I_StartupKeyboard (void)
  1135. {
  1136. #ifndef NOKBD
  1137. oldkeyboardisr = _dos_getvect(KEYBOARDINT);
  1138. _dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
  1139. #endif
  1140. //I_ReadKeys ();
  1141. }
  1142. void I_ShutdownKeyboard (void)
  1143. {
  1144. if (oldkeyboardisr)
  1145. _dos_setvect (KEYBOARDINT, oldkeyboardisr);
  1146. *(short *)0x41c = *(short *)0x41a; // clear bios key buffer
  1147. }
  1148. /*
  1149. ============================================================================
  1150. MOUSE
  1151. ============================================================================
  1152. */
  1153. int I_ResetMouse (void)
  1154. {
  1155. regs.w.ax = 0; // reset
  1156. int386 (0x33, &regs, &regs);
  1157. return regs.w.ax;
  1158. }
  1159. /*
  1160. ================
  1161. =
  1162. = StartupMouse
  1163. =
  1164. ================
  1165. */
  1166. void I_StartupCyberMan(void);
  1167. void I_StartupMouse (void)
  1168. {
  1169. int (far *function)();
  1170. //
  1171. // General mouse detection
  1172. //
  1173. mousepresent = 0;
  1174. if ( M_CheckParm ("-nomouse") || !usemouse )
  1175. return;
  1176. if (I_ResetMouse () != 0xffff)
  1177. {
  1178. tprintf ("Mouse: not present ",0);
  1179. return;
  1180. }
  1181. tprintf ("Mouse: detected ",0);
  1182. mousepresent = 1;
  1183. I_StartupCyberMan();
  1184. }
  1185. /*
  1186. ================
  1187. =
  1188. = ShutdownMouse
  1189. =
  1190. ================
  1191. */
  1192. void I_ShutdownMouse (void)
  1193. {
  1194. if (!mousepresent)
  1195. return;
  1196. I_ResetMouse ();
  1197. }
  1198. /*
  1199. ================
  1200. =
  1201. = I_ReadMouse
  1202. =
  1203. ================
  1204. */
  1205. void I_ReadMouse (void)
  1206. {
  1207. event_t ev;
  1208. //
  1209. // mouse events
  1210. //
  1211. if (!mousepresent)
  1212. return;
  1213. ev.type = ev_mouse;
  1214. memset (&dpmiregs,0,sizeof(dpmiregs));
  1215. dpmiregs.eax = 3; // read buttons / position
  1216. DPMIInt (0x33);
  1217. ev.data1 = dpmiregs.ebx;
  1218. dpmiregs.eax = 11; // read counters
  1219. DPMIInt (0x33);
  1220. ev.data2 = (short)dpmiregs.ecx;
  1221. ev.data3 = -(short)dpmiregs.edx;
  1222. D_PostEvent (&ev);
  1223. }
  1224. /*
  1225. ============================================================================
  1226. JOYSTICK
  1227. ============================================================================
  1228. */
  1229. int joyxl, joyxh, joyyl, joyyh;
  1230. boolean WaitJoyButton (void)
  1231. {
  1232. int oldbuttons, buttons;
  1233. oldbuttons = 0;
  1234. do
  1235. {
  1236. I_WaitVBL (1);
  1237. buttons = ((inp(0x201) >> 4)&1)^1;
  1238. if (buttons != oldbuttons)
  1239. {
  1240. oldbuttons = buttons;
  1241. continue;
  1242. }
  1243. if ( (lastpress& 0x7f) == 1 )
  1244. {
  1245. joystickpresent = false;
  1246. return false;
  1247. }
  1248. } while ( !buttons);
  1249. do
  1250. {
  1251. I_WaitVBL (1);
  1252. buttons = ((inp(0x201) >> 4)&1)^1;
  1253. if (buttons != oldbuttons)
  1254. {
  1255. oldbuttons = buttons;
  1256. continue;
  1257. }
  1258. if ( (lastpress& 0x7f) == 1 )
  1259. {
  1260. joystickpresent = false;
  1261. return false;
  1262. }
  1263. } while ( buttons);
  1264. return true;
  1265. }
  1266. /*
  1267. ===============
  1268. =
  1269. = I_StartupJoystick
  1270. =
  1271. ===============
  1272. */
  1273. int basejoyx, basejoyy;
  1274. void I_StartupJoystick (void)
  1275. {
  1276. int buttons;
  1277. int count;
  1278. int centerx, centery;
  1279. joystickpresent = 0;
  1280. if ( M_CheckParm ("-nojoy") || !usejoystick )
  1281. return;
  1282. if (!I_ReadJoystick ())
  1283. {
  1284. joystickpresent = false;
  1285. tprintf ("joystick not found ",0);
  1286. return;
  1287. }
  1288. printf("joystick found\n");
  1289. joystickpresent = true;
  1290. printf("CENTER the joystick and press button 1:");
  1291. if (!WaitJoyButton ())
  1292. return;
  1293. I_ReadJoystick ();
  1294. centerx = joystickx;
  1295. centery = joysticky;
  1296. printf("\nPush the joystick to the UPPER LEFT corner and press button 1:");
  1297. if (!WaitJoyButton ())
  1298. return;
  1299. I_ReadJoystick ();
  1300. joyxl = (centerx + joystickx)/2;
  1301. joyyl = (centerx + joysticky)/2;
  1302. printf("\nPush the joystick to the LOWER RIGHT corner and press button 1:");
  1303. if (!WaitJoyButton ())
  1304. return;
  1305. I_ReadJoystick ();
  1306. joyxh = (centerx + joystickx)/2;
  1307. joyyh = (centery + joysticky)/2;
  1308. printf("\n");
  1309. }
  1310. /*
  1311. ===============
  1312. =
  1313. = I_JoystickEvents
  1314. =
  1315. ===============
  1316. */
  1317. void I_JoystickEvents (void)
  1318. {
  1319. event_t ev;
  1320. //
  1321. // joystick events
  1322. //
  1323. if (!joystickpresent)
  1324. return;
  1325. I_ReadJoystick ();
  1326. ev.type = ev_joystick;
  1327. ev.data1 = ((inp(0x201) >> 4)&15)^15;
  1328. if (joystickx < joyxl)
  1329. ev.data2 = -1;
  1330. else if (joystickx > joyxh)
  1331. ev.data2 = 1;
  1332. else
  1333. ev.data2 = 0;
  1334. if (joysticky < joyyl)
  1335. ev.data3 = -1;
  1336. else if (joysticky > joyyh)
  1337. ev.data3 = 1;
  1338. else
  1339. ev.data3 = 0;
  1340. D_PostEvent (&ev);
  1341. }
  1342. /*
  1343. ============================================================================
  1344. DPMI STUFF
  1345. ============================================================================
  1346. */
  1347. #define REALSTACKSIZE 1024
  1348. dpmiregs_t dpmiregs;
  1349. unsigned realstackseg;
  1350. void I_DivException (void);
  1351. int I_SetDivException (void);
  1352. void DPMIFarCall (void)
  1353. {
  1354. segread (&segregs);
  1355. regs.w.ax = 0x301;
  1356. regs.w.bx = 0;
  1357. regs.w.cx = 0;
  1358. regs.x.edi = (unsigned)&dpmiregs;
  1359. segregs.es = segregs.ds;
  1360. int386x( DPMI_INT, &regs, &regs, &segregs );
  1361. }
  1362. void DPMIInt (int i)
  1363. {
  1364. dpmiregs.ss = realstackseg;
  1365. dpmiregs.sp = REALSTACKSIZE-4;
  1366. segread (&segregs);
  1367. regs.w.ax = 0x300;
  1368. regs.w.bx = i;
  1369. regs.w.cx = 0;
  1370. regs.x.edi = (unsigned)&dpmiregs;
  1371. segregs.es = segregs.ds;
  1372. int386x( DPMI_INT, &regs, &regs, &segregs );
  1373. }
  1374. /*
  1375. ==============
  1376. =
  1377. = I_StartupDPMI
  1378. =
  1379. ==============
  1380. */
  1381. void I_StartupDPMI (void)
  1382. {
  1383. extern char __begtext;
  1384. extern char ___argc;
  1385. int n,d;
  1386. //
  1387. // allocate a decent stack for real mode ISRs
  1388. //
  1389. realstackseg = (int)I_AllocLow (1024) >> 4;
  1390. //
  1391. // lock the entire program down
  1392. //
  1393. // _dpmi_lockregion (&__begtext, &___argc - &__begtext);
  1394. //
  1395. // catch divide by 0 exception
  1396. //
  1397. #if 0
  1398. segread(&segregs);
  1399. regs.w.ax = 0x0203; // DPMI set processor exception handler vector
  1400. regs.w.bx = 0; // int 0
  1401. regs.w.cx = segregs.cs;
  1402. regs.x.edx = (int)&I_DivException;
  1403. printf ("%x : %x\n",regs.w.cx, regs.x.edx);
  1404. int386( DPMI_INT, &regs, &regs);
  1405. #endif
  1406. #if 0
  1407. n = I_SetDivException ();
  1408. printf ("return: %i\n",n);
  1409. n = 100;
  1410. d = 0;
  1411. printf ("100 / 0 = %i\n",n/d);
  1412. exit (1);
  1413. #endif
  1414. }
  1415. /*
  1416. ============================================================================
  1417. TIMER INTERRUPT
  1418. ============================================================================
  1419. */
  1420. void (__interrupt __far *oldtimerisr) ();
  1421. void IO_ColorBlack (int r, int g, int b)
  1422. {
  1423. _outbyte (PEL_WRITE_ADR,0);
  1424. _outbyte(PEL_DATA,r);
  1425. _outbyte(PEL_DATA,g);
  1426. _outbyte(PEL_DATA,b);
  1427. }
  1428. /*
  1429. ================
  1430. =
  1431. = IO_TimerISR
  1432. =
  1433. ================
  1434. */
  1435. //void __interrupt IO_TimerISR (void)
  1436. void __interrupt __far IO_TimerISR (void)
  1437. {
  1438. ticcount++;
  1439. _outbyte(0x20,0x20); // Ack the interrupt
  1440. }
  1441. /*
  1442. =====================
  1443. =
  1444. = IO_SetTimer0
  1445. =
  1446. = Sets system timer 0 to the specified speed
  1447. =
  1448. =====================
  1449. */
  1450. void IO_SetTimer0(int speed)
  1451. {
  1452. if (speed > 0 && speed < 150)
  1453. I_Error ("INT_SetTimer0: %i is a bad value",speed);
  1454. _outbyte(0x43,0x36); // Change timer 0
  1455. _outbyte(0x40,speed);
  1456. _outbyte(0x40,speed >> 8);
  1457. }
  1458. /*
  1459. ===============
  1460. =
  1461. = IO_StartupTimer
  1462. =
  1463. ===============
  1464. */
  1465. void IO_StartupTimer (void)
  1466. {
  1467. oldtimerisr = _dos_getvect(TIMERINT);
  1468. _dos_setvect (0x8000 | TIMERINT, IO_TimerISR);
  1469. IO_SetTimer0 (VBLCOUNTER);
  1470. }
  1471. void IO_ShutdownTimer (void)
  1472. {
  1473. if (oldtimerisr)
  1474. {
  1475. IO_SetTimer0 (0); // back to 18.4 ips
  1476. _dos_setvect (TIMERINT, oldtimerisr);
  1477. }
  1478. }
  1479. //===========================================================================
  1480. /*
  1481. ===============
  1482. =
  1483. = I_Init
  1484. =
  1485. = hook interrupts and set graphics mode
  1486. =
  1487. ===============
  1488. */
  1489. void I_Init (void)
  1490. {
  1491. extern void I_StartupTimer(void);
  1492. novideo = M_CheckParm("novideo");
  1493. tprintf("I_StartupDPMI",1);
  1494. I_StartupDPMI();
  1495. tprintf("I_StartupMouse ",1);
  1496. I_StartupMouse();
  1497. // tprintf("I_StartupJoystick ",1);
  1498. // I_StartupJoystick();
  1499. // tprintf("I_StartupKeyboard ",1);
  1500. // I_StartupKeyboard();
  1501. tprintf("S_Init... ",1);
  1502. S_Init();
  1503. //IO_StartupTimer();
  1504. S_Start();
  1505. }
  1506. /*
  1507. ===============
  1508. =
  1509. = I_Shutdown
  1510. =
  1511. = return to default system state
  1512. =
  1513. ===============
  1514. */
  1515. void I_Shutdown (void)
  1516. {
  1517. I_ShutdownGraphics ();
  1518. IO_ShutdownTimer ();
  1519. S_ShutDown ();
  1520. I_ShutdownMouse ();
  1521. I_ShutdownKeyboard ();
  1522. IO_SetTimer0 (0);
  1523. }
  1524. /*
  1525. ================
  1526. =
  1527. = I_Error
  1528. =
  1529. ================
  1530. */
  1531. void I_Error (char *error, ...)
  1532. {
  1533. union REGS regs;
  1534. va_list argptr;
  1535. D_QuitNetGame ();
  1536. I_Shutdown ();
  1537. va_start (argptr,error);
  1538. regs.x.eax = 0x3;
  1539. int386(0x10, &regs, &regs);
  1540. vprintf (error,argptr);
  1541. va_end (argptr);
  1542. printf ("\n");
  1543. exit (1);
  1544. }
  1545. //--------------------------------------------------------------------------
  1546. //
  1547. // I_Quit
  1548. //
  1549. // Shuts down net game, saves defaults, prints the exit text message,
  1550. // goes to text mode, and exits.
  1551. //
  1552. //--------------------------------------------------------------------------
  1553. void I_Quit(void)
  1554. {
  1555. byte *scr;
  1556. char *lumpName;
  1557. int r;
  1558. D_QuitNetGame();
  1559. M_SaveDefaults();
  1560. scr = (byte *)W_CacheLumpName("ENDTEXT", PU_CACHE);
  1561. I_Shutdown();
  1562. memcpy((void *)0xb8000, scr, 80*25*2);
  1563. regs.w.ax = 0x0200;
  1564. regs.h.bh = 0;
  1565. regs.h.dl = 0;
  1566. regs.h.dh = 23;
  1567. int386(0x10, (const union REGS *)&regs, &regs); // Set text pos
  1568. _settextposition(24, 1);
  1569. exit(0);
  1570. }
  1571. /*
  1572. ===============
  1573. =
  1574. = I_ZoneBase
  1575. =
  1576. ===============
  1577. */
  1578. byte *I_ZoneBase (int *size)
  1579. {
  1580. int meminfo[32];
  1581. int heap;
  1582. int i;
  1583. int block;
  1584. byte *ptr;
  1585. memset (meminfo,0,sizeof(meminfo));
  1586. segread(&segregs);
  1587. segregs.es = segregs.ds;
  1588. regs.w.ax = 0x500; // get memory info
  1589. regs.x.edi = (int)&meminfo;
  1590. int386x( 0x31, &regs, &regs, &segregs );
  1591. heap = meminfo[0];
  1592. printf ("DPMI memory: 0x%x, ",heap);
  1593. do
  1594. {
  1595. heap -= 0x10000; // leave 64k alone
  1596. if (heap > 0x800000)
  1597. heap = 0x800000;
  1598. ptr = malloc (heap);
  1599. } while (!ptr);
  1600. printf ("0x%x allocated for zone\n", heap);
  1601. if (heap < 0x180000)
  1602. I_Error ("Insufficient DPMI memory!");
  1603. #if 0
  1604. regs.w.ax = 0x501; // allocate linear block
  1605. regs.w.bx = heap>>16;
  1606. regs.w.cx = heap&0xffff;
  1607. int386( 0x31, &regs, &regs);
  1608. if (regs.w.cflag)
  1609. I_Error ("Couldn't allocate DPMI memory!");
  1610. block = (regs.w.si << 16) + regs.w.di;
  1611. #endif
  1612. *size = heap;
  1613. return ptr;
  1614. }
  1615. /*
  1616. =============================================================================
  1617. DISK ICON FLASHING
  1618. =============================================================================
  1619. */
  1620. void I_InitDiskFlash (void)
  1621. {
  1622. #if 0
  1623. void *pic;
  1624. byte *temp;
  1625. pic = W_CacheLumpName ("STDISK",PU_CACHE);
  1626. temp = destscreen;
  1627. destscreen = (byte *)0xac000;
  1628. V_DrawPatchDirect (SCREENWIDTH-16,SCREENHEIGHT-16,0,pic);
  1629. destscreen = temp;
  1630. #endif
  1631. }
  1632. // draw disk icon
  1633. void I_BeginRead (void)
  1634. {
  1635. #if 0
  1636. byte *src,*dest;
  1637. int y;
  1638. if (!grmode)
  1639. return;
  1640. // write through all planes
  1641. outp (SC_INDEX,SC_MAPMASK);
  1642. outp (SC_INDEX+1,15);
  1643. // set write mode 1
  1644. outp (GC_INDEX,GC_MODE);
  1645. outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
  1646. // copy to backup
  1647. src = currentscreen + 184*80 + 304/4;
  1648. dest = (byte *)0xac000 + 184*80 + 288/4;
  1649. for (y=0 ; y<16 ; y++)
  1650. {
  1651. dest[0] = src[0];
  1652. dest[1] = src[1];
  1653. dest[2] = src[2];
  1654. dest[3] = src[3];
  1655. src += 80;
  1656. dest += 80;
  1657. }
  1658. // copy disk over
  1659. dest = currentscreen + 184*80 + 304/4;
  1660. src = (byte *)0xac000 + 184*80 + 304/4;
  1661. for (y=0 ; y<16 ; y++)
  1662. {
  1663. dest[0] = src[0];
  1664. dest[1] = src[1];
  1665. dest[2] = src[2];
  1666. dest[3] = src[3];
  1667. src += 80;
  1668. dest += 80;
  1669. }
  1670. // set write mode 0
  1671. outp (GC_INDEX,GC_MODE);
  1672. outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
  1673. #endif
  1674. }
  1675. // erase disk icon
  1676. void I_EndRead (void)
  1677. {
  1678. #if 0
  1679. byte *src,*dest;
  1680. int y;
  1681. if (!grmode)
  1682. return;
  1683. // write through all planes
  1684. outp (SC_INDEX,SC_MAPMASK);
  1685. outp (SC_INDEX+1,15);
  1686. // set write mode 1
  1687. outp (GC_INDEX,GC_MODE);
  1688. outp (GC_INDEX+1,inp(GC_INDEX+1)|1);
  1689. // copy disk over
  1690. dest = currentscreen + 184*80 + 304/4;
  1691. src = (byte *)0xac000 + 184*80 + 288/4;
  1692. for (y=0 ; y<16 ; y++)
  1693. {
  1694. dest[0] = src[0];
  1695. dest[1] = src[1];
  1696. dest[2] = src[2];
  1697. dest[3] = src[3];
  1698. src += 80;
  1699. dest += 80;
  1700. }
  1701. // set write mode 0
  1702. outp (GC_INDEX,GC_MODE);
  1703. outp (GC_INDEX+1,inp(GC_INDEX+1)&~1);
  1704. #endif
  1705. }
  1706. /*
  1707. =============
  1708. =
  1709. = I_AllocLow
  1710. =
  1711. =============
  1712. */
  1713. byte *I_AllocLow (int length)
  1714. {
  1715. byte *mem;
  1716. // DPMI call 100h allocates DOS memory
  1717. segread(&segregs);
  1718. regs.w.ax = 0x0100; // DPMI allocate DOS memory
  1719. regs.w.bx = (length+15) / 16;
  1720. int386( DPMI_INT, &regs, &regs);
  1721. // segment = regs.w.ax;
  1722. // selector = regs.w.dx;
  1723. if (regs.w.cflag != 0)
  1724. I_Error ("I_AllocLow: DOS alloc of %i failed, %i free",
  1725. length, regs.w.bx*16);
  1726. mem = (void *) ((regs.x.eax & 0xFFFF) << 4);
  1727. memset (mem,0,length);
  1728. return mem;
  1729. }
  1730. /*
  1731. ============================================================================
  1732. NETWORKING
  1733. ============================================================================
  1734. */
  1735. /* // FUCKED LINES
  1736. typedef struct
  1737. {
  1738. char priv[508];
  1739. } doomdata_t;
  1740. */ // FUCKED LINES
  1741. #define DOOMCOM_ID 0x12345678l
  1742. /* // FUCKED LINES
  1743. typedef struct
  1744. {
  1745. long id;
  1746. short intnum; // DOOM executes an int to execute commands
  1747. // communication between DOOM and the driver
  1748. short command; // CMD_SEND or CMD_GET
  1749. short remotenode; // dest for send, set by get (-1 = no packet)
  1750. short datalength; // bytes in doomdata to be sent
  1751. // info common to all nodes
  1752. short numnodes; // console is allways node 0
  1753. short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
  1754. short extratics; // 1 = send a backup tic in every packet
  1755. short deathmatch; // 1 = deathmatch
  1756. short savegame; // -1 = new game, 0-5 = load savegame
  1757. short episode; // 1-3
  1758. short map; // 1-9
  1759. short skill; // 1-5
  1760. // info specific to this node
  1761. short consoleplayer;
  1762. short numplayers;
  1763. short angleoffset; // 1 = left, 0 = center, -1 = right
  1764. short drone; // 1 = drone
  1765. // packet data to be sent
  1766. doomdata_t data;
  1767. } doomcom_t;
  1768. */ // FUCKED LINES
  1769. extern doomcom_t *doomcom;
  1770. /*
  1771. ====================
  1772. =
  1773. = I_InitNetwork
  1774. =
  1775. ====================
  1776. */
  1777. void I_InitNetwork (void)
  1778. {
  1779. int i;
  1780. i = M_CheckParm ("-net");
  1781. if (!i)
  1782. {
  1783. //
  1784. // single player game
  1785. //
  1786. doomcom = malloc (sizeof (*doomcom) );
  1787. memset (doomcom, 0, sizeof(*doomcom) );
  1788. netgame = false;
  1789. doomcom->id = DOOMCOM_ID;
  1790. doomcom->numplayers = doomcom->numnodes = 1;
  1791. doomcom->deathmatch = false;
  1792. doomcom->consoleplayer = 0;
  1793. doomcom->ticdup = 1;
  1794. doomcom->extratics = 0;
  1795. return;
  1796. }
  1797. netgame = true;
  1798. doomcom = (doomcom_t *)atoi(myargv[i+1]);
  1799. //DEBUG
  1800. doomcom->skill = startskill;
  1801. doomcom->episode = startepisode;
  1802. doomcom->map = startmap;
  1803. doomcom->deathmatch = deathmatch;
  1804. }
  1805. void I_NetCmd (void)
  1806. {
  1807. if (!netgame)
  1808. I_Error ("I_NetCmd when not in netgame");
  1809. DPMIInt (doomcom->intnum);
  1810. }
  1811. int i_Vector;
  1812. externdata_t *i_ExternData;
  1813. boolean useexterndriver;
  1814. //=========================================================================
  1815. //
  1816. // I_CheckExternDriver
  1817. //
  1818. // Checks to see if a vector, and an address for an external driver
  1819. // have been passed.
  1820. //=========================================================================
  1821. void I_CheckExternDriver(void)
  1822. {
  1823. int i;
  1824. if(!(i = M_CheckParm("-externdriver")))
  1825. {
  1826. return;
  1827. }
  1828. i_ExternData = (externdata_t *)atoi(myargv[i+1]);
  1829. i_Vector = i_ExternData->vector;
  1830. useexterndriver = true;
  1831. }
  1832. //=========================================================================
  1833. //
  1834. // I_ReadExternDriver
  1835. //
  1836. // calls the external interrupt, which should then update i_ExternDriver
  1837. //=========================================================================
  1838. void I_ReadExternDriver(void)
  1839. {
  1840. event_t ev;
  1841. if(useexterndriver)
  1842. {
  1843. DPMIInt(i_Vector);
  1844. }
  1845. }