PCRLIB_C.C 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626
  1. /* The Catacomb Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #define CATALOG
  19. #include "pcrlib.h"
  20. #include <conio.h>
  21. char ch,str[80]; // scratch space
  22. /*========================================================================*/
  23. inputtype playermode[3] = {0,keyboard,joystick1};
  24. boolean keydown[128];
  25. int JoyXlow [3], JoyXhigh [3], JoyYlow [3], JoyYhigh [3];
  26. int MouseSensitivity;
  27. char key[8],keyB1,keyB2;
  28. void interrupt (*oldint9) ()=NULL;
  29. char demobuffer[5000];
  30. char *demoptr;
  31. int democount;
  32. int lastdemoval; // so demo can be RLE compressed
  33. enum demoenum indemo;
  34. /*=======================================================================*/
  35. /*
  36. =======================
  37. =
  38. = SetupKBD
  39. = Clears the keydown array and installs the INT 9 ISR if it isn't allready
  40. = hooked up.
  41. =
  42. =======================
  43. */
  44. void SetupKBD ()
  45. {
  46. void far *vect = getvect (9);
  47. int i;
  48. for (i=0;i<128;i++) /* clear our key down table */
  49. keydown[i]= false;
  50. poke (0x40,0x1c,peek(0x40,0x1a)); /* clear the bios key buffer */
  51. if ( &Int9ISR != vect ) /* is our handler allready set up? */
  52. {
  53. oldint9 = vect;
  54. setvect (9,Int9ISR);
  55. }
  56. }
  57. /*
  58. =========================
  59. =
  60. = Int9ISR
  61. = Called for every keypress. Keeps track of which keys are down, and passes
  62. = the key on to DOS after clearing the dos buffer (max 1 char in buffer).
  63. =
  64. =========================
  65. */
  66. void interrupt Int9ISR ()
  67. {
  68. int key = inportb (0x60); /* get the key pressed */
  69. if (key>127)
  70. keydown [key-128] = false; /* break scan code */
  71. else
  72. {
  73. keydown [key] = true; /* make scan code */
  74. poke (0x40,0x1c,peek(0x40,0x1a)); /* clear the bios key buffer */
  75. }
  76. asm {
  77. push ax
  78. push bx
  79. push cx
  80. push dx
  81. push si
  82. push di
  83. push bp
  84. }
  85. oldint9 (); /* give it to DOS */
  86. asm {
  87. pop bp
  88. pop di
  89. pop si
  90. pop dx
  91. pop cx
  92. pop bx
  93. pop ax
  94. }
  95. outport (0x20,0x20); /* tell the int manager we got it */
  96. }
  97. /*
  98. ===========================
  99. =
  100. = ShutdownKBD
  101. = Sets the int 9 vector back to oldint 9
  102. =
  103. ===========================
  104. */
  105. void ShutdownKBD ()
  106. {
  107. if (oldint9 != NULL)
  108. setvect (9,oldint9);
  109. }
  110. /*
  111. ===========================
  112. =
  113. = ControlKBD
  114. =
  115. ===========================
  116. */
  117. ControlStruct ControlKBD ()
  118. {
  119. int xmove=0,
  120. ymove=0;
  121. ControlStruct action;
  122. if (keydown [key[north]])
  123. ymove=-1;
  124. if (keydown [key[east]])
  125. xmove=1;
  126. if (keydown [key[south]])
  127. ymove=1;
  128. if (keydown [key[west]])
  129. xmove=-1;
  130. if (keydown [key[northeast]])
  131. {
  132. ymove=-1;
  133. xmove=1;
  134. }
  135. if (keydown [key[northwest]])
  136. {
  137. ymove=-1;
  138. xmove=-1;
  139. }
  140. if (keydown [key[southeast]])
  141. {
  142. ymove=1;
  143. xmove=1;
  144. }
  145. if (keydown [key[southwest]])
  146. {
  147. ymove=1;
  148. xmove=-1;
  149. }
  150. switch (ymove*3+xmove)
  151. {
  152. case -4: action.dir = northwest; break;
  153. case -3: action.dir = north; break;
  154. case -2: action.dir = northeast; break;
  155. case -1: action.dir = west; break;
  156. case 0: action.dir = nodir; break;
  157. case 1: action.dir = east; break;
  158. case 2: action.dir = southwest; break;
  159. case 3: action.dir = south; break;
  160. case 4: action.dir = southeast; break;
  161. }
  162. action.button1 = keydown [keyB1];
  163. action.button2 = keydown [keyB2];
  164. return (action);
  165. }
  166. /*
  167. ============================
  168. =
  169. = ControlMouse
  170. =
  171. ============================
  172. */
  173. ControlStruct ControlMouse ()
  174. {
  175. int newx,newy, /* mickeys the mouse has moved */
  176. xmove = 0,
  177. ymove = 0;
  178. ControlStruct action;
  179. _AX = 3;
  180. geninterrupt (0x33); /* mouse status */
  181. newx = _CX;
  182. newy = _DX;
  183. action.button1 = _BX & 1;
  184. action.button2 = (_BX & 2) >> 1;
  185. if ((newx-320)/2>MouseSensitivity)
  186. {
  187. xmove = 1;
  188. newx = newx - MouseSensitivity*2;
  189. }
  190. else if ((newx-320)/2<-MouseSensitivity)
  191. {
  192. xmove = -1;
  193. newx = newx + MouseSensitivity*2;
  194. }
  195. if ((newy-100)>MouseSensitivity)
  196. {
  197. ymove = 1;
  198. newy = newy - MouseSensitivity;
  199. }
  200. else if ((newy-100)<-MouseSensitivity)
  201. {
  202. ymove = -1;
  203. newy = newy + MouseSensitivity;
  204. }
  205. _AX = 4;
  206. _CX=newx;
  207. _DX=newy;
  208. geninterrupt (0x33); /* set mouse status */
  209. switch (ymove*3+xmove)
  210. {
  211. case -4: action.dir = northwest; break;
  212. case -3: action.dir = north; break;
  213. case -2: action.dir = northeast; break;
  214. case -1: action.dir = west; break;
  215. case 0: action.dir = nodir; break;
  216. case 1: action.dir = east; break;
  217. case 2: action.dir = southwest; break;
  218. case 3: action.dir = south; break;
  219. case 4: action.dir = southeast; break;
  220. }
  221. return (action);
  222. }
  223. /*
  224. ===============================
  225. =
  226. = ReadJoystick
  227. = Just return the resistance count of the joystick
  228. =
  229. ===============================
  230. */
  231. void ReadJoystick (int joynum,int *xcount,int *ycount)
  232. {
  233. int portval,a1,a2,xbit,ybit;
  234. if (joynum==1)
  235. {
  236. xbit=1;
  237. ybit=2;
  238. }
  239. else
  240. {
  241. xbit=4;
  242. ybit=8;
  243. }
  244. *xcount = 0;
  245. *ycount = 0;
  246. outportb (0x201,inportb (0x201)); /* start the signal pulse */
  247. asm cli;
  248. do
  249. {
  250. portval = inportb (0x201);
  251. a1 = (portval & xbit) != 0;
  252. a2 = (portval & ybit) != 0;
  253. *xcount+=a1;
  254. *ycount+=a2;
  255. } while ((a1+a2!=0) && (*xcount<500) && (*ycount<500));
  256. asm sti;
  257. }
  258. /*
  259. =============================
  260. =
  261. = ControlJoystick (joy# = 1 / 2)
  262. =
  263. =============================
  264. */
  265. ControlStruct ControlJoystick (int joynum)
  266. {
  267. int joyx = 0,joyy = 0, /* resistance in joystick */
  268. xmove = 0,
  269. ymove = 0,
  270. buttons;
  271. ControlStruct action;
  272. ReadJoystick (joynum,&joyx,&joyy);
  273. if ( (joyx>500) | (joyy>500) )
  274. {
  275. joyx=JoyXlow [joynum] + 1; /* no joystick connected, do nothing */
  276. joyy=JoyYlow [joynum] + 1;
  277. }
  278. if (joyx > JoyXhigh [joynum])
  279. xmove = 1;
  280. else if (joyx < JoyXlow [joynum])
  281. xmove = -1;
  282. if (joyy > JoyYhigh [joynum])
  283. ymove = 1;
  284. else if (joyy < JoyYlow [joynum])
  285. ymove = -1;
  286. switch (ymove*3+xmove)
  287. {
  288. case -4: action.dir = northwest; break;
  289. case -3: action.dir = north; break;
  290. case -2: action.dir = northeast; break;
  291. case -1: action.dir = west; break;
  292. case 0: action.dir = nodir; break;
  293. case 1: action.dir = east; break;
  294. case 2: action.dir = southwest; break;
  295. case 3: action.dir = south; break;
  296. case 4: action.dir = southeast; break;
  297. }
  298. buttons = inportb (0x201); /* get all four button status */
  299. if (joynum == 1)
  300. {
  301. action.button1 = ((buttons & 0x10) == 0);
  302. action.button2 = ((buttons & 0x20) == 0);
  303. }
  304. else
  305. {
  306. action.button1 = ((buttons & 0x40) == 0);
  307. action.button2 = ((buttons & 0x80) == 0);
  308. }
  309. return (action);
  310. }
  311. /*
  312. =============================
  313. =
  314. = ControlPlayer
  315. =
  316. = Expects a 1 or a 2
  317. =
  318. =============================
  319. */
  320. ControlStruct ControlPlayer (int player)
  321. {
  322. ControlStruct ret;
  323. int val;
  324. if (indemo == notdemo || indemo == recording)
  325. {
  326. switch (playermode[player])
  327. {
  328. case keyboard : ret = ControlKBD (); break;
  329. case mouse : ret = ControlMouse (); break;
  330. case joystick1: ret = ControlJoystick(1); break;
  331. case joystick2: ret = ControlJoystick(2); break;
  332. }
  333. //
  334. // recording a demo?
  335. //
  336. if (indemo == recording)
  337. {
  338. val = (ret.dir << 2) | (ret.button2 << 1) | ret.button1;
  339. *demoptr++=val;
  340. }
  341. }
  342. else
  343. //
  344. // get the command from the demo buffer
  345. //
  346. {
  347. val = *demoptr++;
  348. ret.button1 = val & 1;
  349. ret.button2 = (val & 2) >> 1;
  350. ret.dir = (dirtype) ( (val & (4+8+16+32) ) >> 2);
  351. }
  352. return (ret);
  353. }
  354. ////////////////////////
  355. //
  356. // RecordDemo
  357. // Clears the demo buffer and starts capturing events
  358. //
  359. ////////////////////////
  360. void RecordDemo (void)
  361. {
  362. demobuffer[0]=level;
  363. demoptr = &demobuffer[1];
  364. indemo = recording;
  365. }
  366. ////////////////////////
  367. //
  368. // LoadDemo / SaveDemo
  369. // Loads a demo from disk or
  370. // saves the accumulated demo command string to disk
  371. //
  372. ////////////////////////
  373. void LoadDemo (int demonum)
  374. {
  375. char st2[5];
  376. strcpy (str,"DEMO");
  377. itoa (demonum,st2,10);
  378. strcat (str,st2);
  379. strcat (str,".");
  380. strcat (str,_extension);
  381. LoadFile (str,MK_FP(_DS,&demobuffer));
  382. level=demobuffer[0];
  383. demoptr = &demobuffer[1];
  384. indemo = demoplay;
  385. }
  386. void SaveDemo (int demonum)
  387. {
  388. char st2[5];
  389. strcpy (str,"DEMO");
  390. itoa (demonum,st2,10);
  391. strcat (str,st2);
  392. strcat (str,".");
  393. strcat (str,_extension);
  394. SaveFile (str,MK_FP(_DS,&demobuffer),(demoptr-&demobuffer[0]));
  395. indemo = notdemo;
  396. }
  397. ////////////////////////
  398. //
  399. // StartDemo
  400. //
  401. ////////////////////////
  402. /*=========================================================================*/
  403. /*
  404. ** Miscellanious library routines
  405. */
  406. ///////////////////////////////
  407. //
  408. // clearkeys
  409. // Clears out the bios buffer and zeros out the keydown array
  410. //
  411. ///////////////////////////////
  412. void clearkeys (void)
  413. {
  414. int i;
  415. while (bioskey (1))
  416. bioskey(0);
  417. for (i=0;i<128;i++)
  418. keydown [i]=0;
  419. }
  420. /*
  421. ===========================================
  422. =
  423. = Allocate a block aligned on a paragraph
  424. =
  425. ===========================================
  426. */
  427. void far *lastparalloc; // global variable of the EXACT (not paralign)
  428. // last block, so it can be freed right
  429. void huge *paralloc (long size)
  430. {
  431. void huge *temp;
  432. word seg,ofs;
  433. /* allocate a block with extra space */
  434. lastparalloc = (void far*)temp = farmalloc (size+15);
  435. if (temp == NULL)
  436. //
  437. // not enough memory!
  438. //
  439. {
  440. setscreenmode (text);
  441. _quit ("Out of memory!");
  442. }
  443. ofs=FP_OFF(temp);
  444. if (ofs!=0) /* set offset to 0 and bump segment */
  445. {
  446. seg=FP_SEG(temp);
  447. seg++;
  448. ofs=0;
  449. temp=MK_FP (seg,ofs);
  450. }
  451. return (void huge *) temp;
  452. }
  453. //==========================================================================
  454. /*
  455. ==============================================
  456. =
  457. = Load a *LARGE* file into a FAR buffer!
  458. = by John Romero (C) 1990 PCRcade
  459. =
  460. ==============================================
  461. */
  462. unsigned long LoadFile(char *filename,char huge *buffer)
  463. {
  464. unsigned int handle,flength1=0,flength2=0,buf1,buf2,foff1,foff2;
  465. buf1=FP_OFF(buffer);
  466. buf2=FP_SEG(buffer);
  467. asm mov WORD PTR foff1,0 // file offset = 0 (start)
  468. asm mov WORD PTR foff2,0
  469. asm mov dx,filename
  470. asm mov ax,3d00h // OPEN w/handle (read only)
  471. asm int 21h
  472. asm jc out
  473. asm mov handle,ax
  474. asm mov bx,ax
  475. asm xor cx,cx
  476. asm xor dx,dx
  477. asm mov ax,4202h
  478. asm int 21h // SEEK (find file length)
  479. asm jc out
  480. asm mov flength1,ax
  481. asm mov flength2,dx
  482. asm mov cx,flength2
  483. asm inc cx // <- at least once!
  484. L_1:
  485. asm push cx
  486. asm mov cx,foff2
  487. asm mov dx,foff1
  488. asm mov ax,4200h
  489. asm int 21h // SEEK from start
  490. asm push ds
  491. asm mov bx,handle
  492. asm mov cx,-1
  493. asm mov dx,buf1
  494. asm mov ax,buf2
  495. asm mov ds,ax
  496. asm mov ah,3fh // READ w/handle
  497. asm int 21h
  498. asm pop ds
  499. asm pop cx
  500. asm jc out
  501. asm cmp ax,-1
  502. asm jne out
  503. asm push cx // need to read the last byte
  504. asm push ds // into the segment! IMPORTANT!
  505. asm mov bx,handle
  506. asm mov cx,1
  507. asm mov dx,buf1
  508. asm add dx,-1
  509. asm mov ax,buf2
  510. asm mov ds,ax
  511. asm mov ah,3fh
  512. asm int 21h
  513. asm pop ds
  514. asm pop cx
  515. asm add buf2,1000h
  516. asm inc WORD PTR foff2
  517. asm loop L_1
  518. out:
  519. asm mov bx,handle // CLOSE w/handle
  520. asm mov ah,3eh
  521. asm int 21h
  522. return (flength2*0x10000+flength1);
  523. }
  524. //===========================================================================
  525. /*
  526. ==============================================
  527. =
  528. = Save a *LARGE* file far a FAR buffer!
  529. = by John Romero (C) 1990 PCRcade
  530. =
  531. ==============================================
  532. */
  533. void SaveFile(char *filename,char huge *buffer, long size)
  534. {
  535. unsigned int handle,buf1,buf2,foff1,foff2;
  536. buf1=FP_OFF(buffer);
  537. buf2=FP_SEG(buffer);
  538. asm mov WORD PTR foff1,0 // file offset = 0 (start)
  539. asm mov WORD PTR foff2,0
  540. asm mov dx,filename
  541. asm mov ax,3c00h // CREATE w/handle (read only)
  542. asm xor cx,cx
  543. asm int 21h
  544. asm jc out
  545. asm mov handle,ax
  546. asm cmp word ptr size+2,0 // larger than 1 segment?
  547. asm je L2
  548. L1:
  549. asm push ds
  550. asm mov bx,handle
  551. asm mov cx,8000h
  552. asm mov dx,buf1
  553. asm mov ax,buf2
  554. asm mov ds,ax
  555. asm mov ah,40h // WRITE w/handle
  556. asm int 21h
  557. asm pop ds
  558. asm add buf2,800h // bump ptr up 1/2 segment
  559. asm sub WORD PTR size,8000h // done yet?
  560. asm sbb WORD PTR size+2,0
  561. asm cmp WORD PTR size+2,0
  562. asm ja L1
  563. asm cmp WORD PTR size,8000h
  564. asm jae L1
  565. L2:
  566. asm push ds
  567. asm mov bx,handle
  568. asm mov cx,WORD PTR size
  569. asm mov dx,buf1
  570. asm mov ax,buf2
  571. asm mov ds,ax
  572. asm mov ah,40h // WRITE w/handle
  573. asm int 21h
  574. asm pop ds
  575. asm jmp out
  576. out:
  577. asm mov bx,handle // CLOSE w/handle
  578. asm mov ah,3eh
  579. asm int 21h
  580. }
  581. //==========================================================================
  582. /*
  583. ====================================
  584. =
  585. = bloadin
  586. = Paraligns just enough space and bloads in the
  587. = specified file, returning a pointer to the start
  588. =
  589. ====================================
  590. */
  591. void huge *bloadin (char *filename)
  592. {
  593. int handle;
  594. long length;
  595. char huge *location;
  596. if ( (handle = open (filename,O_BINARY)) != -1 )
  597. {
  598. length = filelength (handle);
  599. location = paralloc (length);
  600. close (handle);
  601. LoadFile (filename,location);
  602. return location;
  603. }
  604. else
  605. return NULL;
  606. }
  607. /*==================================================================================*/
  608. /*
  609. ** Graphic routines
  610. */
  611. grtype grmode;
  612. cardtype _videocard;
  613. void huge *charptr; // 8*8 tileset
  614. void huge *tileptr; // 16*16 tileset
  615. void huge *picptr; // any size picture set
  616. void huge *spriteptr; // any size masked and hit rect sprites
  617. void huge *egaspriteptr[4]; // spriteptr for each ega plane's data
  618. unsigned crtcaddr;
  619. int sx,sy,leftedge;
  620. /*
  621. ========================
  622. =
  623. = setscreenmode
  624. = Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr
  625. =
  626. ========================
  627. */
  628. void setscreenmode (grtype mode)
  629. {
  630. char extern VGAPAL; // deluxepaint vga pallet .OBJ file
  631. void far *vgapal = &VGAPAL;
  632. switch (mode)
  633. {
  634. case text: _AX = 3;
  635. geninterrupt (0x10);
  636. screenseg=0xb800;
  637. break;
  638. case CGAgr: _AX = 4;
  639. geninterrupt (0x10);
  640. screenseg=0xb800;
  641. break;
  642. case EGAgr: _AX = 0xd;
  643. geninterrupt (0x10);
  644. screenseg=0xa000;
  645. EGAmove ();
  646. moveega ();
  647. break;
  648. case VGAgr: _AX = 0x13;
  649. geninterrupt (0x10);
  650. screenseg=0xa000;
  651. _ES = FP_SEG(vgapal);
  652. _DX = FP_OFF(vgapal);
  653. _BX = 0;
  654. _CX = 0x100;
  655. _AX = 0x1012;
  656. geninterrupt(0x10); // set the deluxepaint pallet
  657. break;
  658. }
  659. crtcaddr = 0x3d4; //peek (0x40,0x63) if not for two monitors...
  660. }
  661. /*
  662. ========================
  663. =
  664. = egasplitscreen
  665. =
  666. ========================
  667. */
  668. void egasplitscreen (int linenum)
  669. {
  670. WaitVBL ();
  671. if (_videocard==VGAcard)
  672. linenum*=2;
  673. outportb (crtcaddr,CRTCLINECOMPARE);
  674. outportb (crtcaddr+1,linenum % 256);
  675. outportb (crtcaddr,CRTCOVERFLOW);
  676. outportb (crtcaddr+1, 1+16*(linenum/256));
  677. if (_videocard==VGAcard)
  678. {
  679. outportb (crtcaddr,CRTCMAXSCANLINE);
  680. outportb (crtcaddr+1,inportb(crtcaddr+1) & (255-64));
  681. }
  682. }
  683. /*
  684. ========================
  685. =
  686. = crtcstart
  687. =
  688. ========================
  689. */
  690. void crtcstart (unsigned start)
  691. {
  692. WaitVBL ();
  693. outportb (crtcaddr,CRTCSTARTL);
  694. outportb (crtcaddr+1,start % 256);
  695. outportb (crtcaddr,CRTCSTARTH);
  696. outportb (crtcaddr+1,start / 256);
  697. }
  698. int win_xl,win_yl,win_xh,win_yh;
  699. int screencenterx = 19,screencentery = 11;
  700. //////////////////////////
  701. //
  702. // drawwindow
  703. // draws a bordered window and homes the cursor
  704. //
  705. //////////////////////////
  706. void drawwindow (int xl, int yl, int xh, int yh)
  707. {
  708. int x,y;
  709. win_xl=xl;
  710. win_yl=yl;
  711. win_xh=xh;
  712. win_yh=yh; // so the window can be erased
  713. drawchar (xl,yl,1);
  714. for (x=xl+1;x<xh;x++)
  715. drawchar (x,yl,2);
  716. drawchar (xh,yl,3);
  717. for (y=yl+1;y<yh;y++)
  718. {
  719. drawchar (xl,y,4);
  720. for (x=xl+1;x<xh;x++)
  721. drawchar (x,y,' ');
  722. drawchar (xh,y,5);
  723. }
  724. drawchar (xl,yh,6);
  725. for (x=xl+1;x<xh;x++)
  726. drawchar (x,yh,7);
  727. drawchar (xh,yh,8);
  728. sx = leftedge = xl+1;
  729. sy = yl+1;
  730. }
  731. ////////////////////////////
  732. //
  733. // erasewindow
  734. // clears out the last window and it's border to spaces
  735. //
  736. ///////////////////////////
  737. void bar (int xl, int yl, int xh, int yh, int ch)
  738. {
  739. int x,y;
  740. for (y=yl;y<=yh;y++)
  741. for (x=xl;x<=xh;x++)
  742. drawchar (x,y,ch);
  743. }
  744. void erasewindow (void)
  745. {
  746. bar (win_xl,win_yl,win_xh,win_yh,' ');
  747. }
  748. /////////////////////////////
  749. //
  750. // centerwindow
  751. // Centers a drawwindow of the given size
  752. //
  753. /////////////////////////////
  754. void centerwindow (int width, int height)
  755. {
  756. int xl = screencenterx-width/2;
  757. int yl = screencentery-height/2;
  758. drawwindow (xl,yl,xl+width+1,yl+height+1);
  759. }
  760. ///////////////////////////////
  761. //
  762. // expwin {h / v}
  763. // Grows the window outward
  764. //
  765. ///////////////////////////////
  766. void expwin (int width, int height)
  767. {
  768. if (width > 2)
  769. {
  770. if (height >2)
  771. expwin (width-2,height-2);
  772. else
  773. expwinh (width-2,height);
  774. }
  775. else
  776. if (height >2)
  777. expwinv (width,height-2);
  778. WaitVBL ();
  779. centerwindow (width,height);
  780. }
  781. void expwinh (int width, int height)
  782. {
  783. if (width > 2)
  784. expwinh (width-2,height);
  785. WaitVBL ();
  786. centerwindow (width,height);
  787. }
  788. void expwinv (int width, int height)
  789. {
  790. if (height >2)
  791. expwinv (width,height-2);
  792. WaitVBL ();
  793. centerwindow (width,height);
  794. }
  795. /////////////////////////
  796. //
  797. // get
  798. // Flash a cursor at sx,sy and waits for a user bioskey
  799. //
  800. /////////////////////////
  801. int get (void)
  802. {
  803. int cycle,key;
  804. do
  805. {
  806. cycle = 9;
  807. while (!(key = bioskey(1)) && cycle<13)
  808. {
  809. drawchar (sx,sy,cycle++);
  810. WaitVBL ();
  811. WaitVBL ();
  812. WaitVBL ();
  813. WaitVBL ();
  814. WaitVBL ();
  815. }
  816. } while (key == 0);
  817. drawchar (sx,sy,' ');
  818. return bioskey(0); // take it out of the buffer
  819. }
  820. /////////////////////////
  821. //
  822. // print
  823. // Prints a string at sx,sy. No clipping!!!
  824. //
  825. /////////////////////////
  826. void print (const char *str)
  827. {
  828. char ch;
  829. while ((ch=*str++) != 0)
  830. if (ch == '\n')
  831. {
  832. sy++;
  833. sx=leftedge;
  834. }
  835. else if (ch == '\r')
  836. sx=leftedge;
  837. else
  838. drawchar (sx++,sy,ch);
  839. }
  840. ///////////////////////////
  841. //
  842. // printint / printlong
  843. // Converts the value to a string and prints it
  844. //
  845. ///////////////////////////
  846. void printint (int val)
  847. {
  848. itoa(val,str,10);
  849. print (str);
  850. }
  851. void printlong (long val)
  852. {
  853. ltoa(val,str,10);
  854. print (str);
  855. }
  856. /*========================================================================*/
  857. int _MouseStatus;
  858. ////////////////////////////////////////////////////////////////////
  859. //
  860. // Mouse Routines
  861. //
  862. ////////////////////////////////////////////////////////////////////
  863. int _MouseInit(void)
  864. {
  865. union REGS regs;
  866. unsigned char far *vector;
  867. if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL) return 0;
  868. if (*vector == 207)
  869. return _MouseStatus = 0;
  870. _AX=0;
  871. geninterrupt(0x33);
  872. return _MouseStatus = 1;
  873. }
  874. void _MouseHide(void)
  875. {
  876. if (!_MouseStatus) return;
  877. _AX=2;
  878. geninterrupt(0x33);
  879. }
  880. void _MouseShow(void)
  881. {
  882. if (!_MouseStatus) return;
  883. _AX=1;
  884. geninterrupt(0x33);
  885. }
  886. int _MouseButton(void)
  887. {
  888. union REGS regs;
  889. if (!_MouseStatus) return 0;
  890. regs.x.ax=3;
  891. int86(0x33,&regs,&regs);
  892. return(regs.x.bx);
  893. }
  894. void _MouseCoords(int *x,int *y)
  895. {
  896. union REGS regs;
  897. if (!_MouseStatus) return;
  898. regs.x.ax=3;
  899. int86(0x33,&regs,&regs);
  900. *x=regs.x.cx;
  901. *y=regs.x.dx;
  902. *x/=2;
  903. }
  904. ////////////////////////////////////////////////////////////////////
  905. //
  906. // Verify a file's existence
  907. //
  908. ////////////////////////////////////////////////////////////////////
  909. long _Verify(char *filename)
  910. {
  911. int handle;
  912. long size;
  913. if ((handle=open(filename,O_BINARY))==-1) return 0;
  914. size=filelength(handle);
  915. close(handle);
  916. return size;
  917. }
  918. ////////////////////////////////////////////////////////////////////
  919. //
  920. // print hex byte
  921. //
  922. ////////////////////////////////////////////////////////////////////
  923. void _printhexb(unsigned char value)
  924. {
  925. int loop;
  926. char hexstr[16]="0123456789ABCDEF",str[2]="";
  927. for (loop=0;loop<2;loop++)
  928. {
  929. str[0]=hexstr[(value>>(1-loop)*4)&15];
  930. print(str);
  931. }
  932. }
  933. ////////////////////////////////////////////////////////////////////
  934. //
  935. // print hex
  936. //
  937. ////////////////////////////////////////////////////////////////////
  938. void _printhex(unsigned value)
  939. {
  940. print("$");
  941. _printhexb(value>>8);
  942. _printhexb(value&0xff);
  943. }
  944. ////////////////////////////////////////////////////////////////////
  945. //
  946. // print bin
  947. //
  948. ////////////////////////////////////////////////////////////////////
  949. void _printbin(unsigned value)
  950. {
  951. int loop;
  952. print("%");
  953. for (loop=0;loop<16;loop++)
  954. if ((value>>15-loop)&1) print("1"); else print("0");
  955. }
  956. ////////////////////////////////////////////////////////////////////
  957. //
  958. // center print
  959. //
  960. ////////////////////////////////////////////////////////////////////
  961. void _printc(char *string)
  962. {
  963. sx=1+screencenterx-(strlen(string)/2);
  964. print(string);
  965. }
  966. ////////////////////////////////////////////////////////////////////
  967. //
  968. // input unsigned
  969. //
  970. ////////////////////////////////////////////////////////////////////
  971. unsigned _inputint(void)
  972. {
  973. char string[18]="",digit,hexstr[16]="0123456789ABCDEF";
  974. unsigned value,loop,loop1;
  975. _input(string,17);
  976. if (string[0]=='$')
  977. {
  978. int digits;
  979. digits=strlen(string)-2;
  980. if (digits<0) return 0;
  981. for (value=0,loop1=0;loop1<=digits;loop1++)
  982. {
  983. digit=toupper(string[loop1+1]);
  984. for (loop=0;loop<16;loop++)
  985. if (digit==hexstr[loop])
  986. {
  987. value|=(loop<<(digits-loop1)*4);
  988. break;
  989. }
  990. }
  991. }
  992. else if (string[0]=='%')
  993. {
  994. int digits;
  995. digits=strlen(string)-2;
  996. if (digits<0) return 0;
  997. for (value=0,loop1=0;loop1<=digits;loop1++)
  998. {
  999. if (string[loop1+1]<'0' || string[loop1+1]>'1') return 0;
  1000. value|=(string[loop1+1]-'0')<<(digits-loop1);
  1001. }
  1002. }
  1003. else value=atoi(string);
  1004. return value;
  1005. }
  1006. ////////////////////////////////////////////////////////////////////
  1007. //
  1008. // line input routine
  1009. //
  1010. ////////////////////////////////////////////////////////////////////
  1011. int _input(char *string,int max)
  1012. {
  1013. char key;
  1014. int count=0,loop;
  1015. do {
  1016. key=toupper(get()&0xff);
  1017. if ((key==127 || key==8)&&count>0)
  1018. {
  1019. count--;
  1020. drawchar(sx,sy,' ');
  1021. sx--;
  1022. }
  1023. if (key>=' ' && key<='z' && count<max)
  1024. {
  1025. *(string+count++)=key;
  1026. drawchar(sx++,sy,key);
  1027. }
  1028. } while (key!=27 && key!=13);
  1029. for (loop=count;loop<max;loop++) *(string+loop)=0;
  1030. if (key==13) return 1;
  1031. return 0;
  1032. }
  1033. /*========================================================================*/
  1034. /*
  1035. ** Game routines
  1036. */
  1037. struct scores scoreswap, highscores[5];
  1038. long score;
  1039. int level;
  1040. int _numlevels, _maxplayers;
  1041. char *_extension = "PCR";
  1042. boolean _cgaok, _egaok, _vgaok;
  1043. ////////////////////////
  1044. //
  1045. // _loadctrls
  1046. // Tries to load the control panel settings
  1047. // creates a default if not present
  1048. //
  1049. ////////////////////////
  1050. void _loadctrls (void)
  1051. {
  1052. int handle;
  1053. strcpy (str,"CTLPANEL.");
  1054. strcat (str,_extension);
  1055. if ((handle = open(str, O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
  1056. //
  1057. // set up default control panel settings
  1058. //
  1059. {
  1060. grmode=VGAgr;
  1061. soundmode=spkr;
  1062. playermode[1] = keyboard;
  1063. playermode[2] = joystick1;
  1064. JoyXlow [1] = JoyXlow [2] = 20;
  1065. JoyXhigh[1] = JoyXhigh[2] = 60;
  1066. JoyYlow [1] = JoyYlow [2] = 20;
  1067. JoyYhigh[1] = JoyYhigh[2] = 60;
  1068. MouseSensitivity = 5;
  1069. key[north] = 0x48;
  1070. key[northeast] = 0x49;
  1071. key[east] = 0x4d;
  1072. key[southeast] = 0x51;
  1073. key[south] = 0x50;
  1074. key[southwest] = 0x4f;
  1075. key[west] = 0x4b;
  1076. key[northwest] = 0x47;
  1077. keyB1 = 0x1d;
  1078. keyB2 = 0x38;
  1079. }
  1080. else
  1081. {
  1082. read(handle, &grmode, sizeof(grmode));
  1083. read(handle, &soundmode, sizeof(soundmode));
  1084. read(handle, &playermode, sizeof(playermode));
  1085. read(handle, &JoyXlow, sizeof(JoyXlow));
  1086. read(handle, &JoyYlow, sizeof(JoyYlow));
  1087. read(handle, &JoyXhigh, sizeof(JoyXhigh));
  1088. read(handle, &JoyYhigh, sizeof(JoyYhigh));
  1089. read(handle, &MouseSensitivity, sizeof(MouseSensitivity));
  1090. read(handle, &key, sizeof(key));
  1091. read(handle, &keyB1, sizeof(keyB1));
  1092. read(handle, &keyB2, sizeof(keyB2));
  1093. close(handle);
  1094. }
  1095. }
  1096. void _savectrls (void)
  1097. {
  1098. int handle;
  1099. strcpy (str,"CTLPANEL.");
  1100. strcat (str,_extension);
  1101. if ((handle = open(str, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE)) == -1)
  1102. return;
  1103. write(handle, &grmode, sizeof(grmode));
  1104. write(handle, &soundmode, sizeof(soundmode));
  1105. write(handle, &playermode, sizeof(playermode));
  1106. write(handle, &JoyXlow, sizeof(JoyXlow));
  1107. write(handle, &JoyYlow, sizeof(JoyYlow));
  1108. write(handle, &JoyXhigh, sizeof(JoyXhigh));
  1109. write(handle, &JoyYhigh, sizeof(JoyYhigh));
  1110. write(handle, &MouseSensitivity, sizeof(MouseSensitivity));
  1111. write(handle, &key, sizeof(key));
  1112. write(handle, &keyB1, sizeof(keyB1));
  1113. write(handle, &keyB2, sizeof(keyB2));
  1114. close(handle);
  1115. }
  1116. ////////////////////////
  1117. //
  1118. // loadhighscores
  1119. // Tries to load the score file
  1120. // creates a default if not present
  1121. //
  1122. ////////////////////////
  1123. void _loadhighscores (void)
  1124. {
  1125. int i;
  1126. strcpy (str,"SCORES.");
  1127. strcat (str,_extension);
  1128. if (LoadFile(str,(char huge *)highscores) == 0 )
  1129. for (i=0;i<5;i++)
  1130. {
  1131. highscores[i].score = 100;
  1132. highscores[i].level = 1;
  1133. strcpy(highscores[i].initials,"PCR");
  1134. }
  1135. }
  1136. void _savehighscores (void)
  1137. {
  1138. strcpy (str,"SCORES.");
  1139. strcat (str,_extension);
  1140. SaveFile(str,(char huge *)highscores,sizeof (highscores));
  1141. }
  1142. ////////////////////////
  1143. //
  1144. // _showhighscores
  1145. // Brings up a dialog box with the high score lists and returns immediately
  1146. //
  1147. ////////////////////////
  1148. void _showhighscores (void)
  1149. {
  1150. int i;
  1151. long h;
  1152. char st2[10];
  1153. centerwindow (17,17);
  1154. print ("\n HIGH SCORES\n\n");
  1155. print (" # SCORE LV BY\n");
  1156. print (" - ------ -- ---\n");
  1157. for (i=0;i<5;i++)
  1158. {
  1159. sx++;
  1160. drawchar (sx,sy,'1'+i);
  1161. sx+=2;
  1162. h=highscores[i].score;
  1163. if (h<100000l)
  1164. sx++;
  1165. if (h<10000l)
  1166. sx++;
  1167. if (h<1000l)
  1168. sx++;
  1169. if (h<100l)
  1170. sx++;
  1171. if (h<10l)
  1172. sx++;
  1173. ltoa(h,str,10);
  1174. print (str);
  1175. sx++;
  1176. if (highscores[i].level<10)
  1177. sx++;
  1178. itoa(highscores[i].level,str,10);
  1179. print (str);
  1180. sx++;
  1181. print (highscores[i].initials);
  1182. print ("\n\n");
  1183. }
  1184. strcpy (str,"SCORE:");
  1185. ltoa (score,st2,10);
  1186. strcat (str,st2);
  1187. _printc (str);
  1188. }
  1189. //////////////////////////
  1190. //
  1191. // _checkhighscore
  1192. // Compares score to highscores, and inserts place if needed.
  1193. // calls showhighscores in any case
  1194. //
  1195. //////////////////////////
  1196. void _checkhighscore (void)
  1197. {
  1198. int i,j,k;
  1199. for (i=0;i<5;i++)
  1200. if (score>highscores[i].score)
  1201. {
  1202. for (j=4;i<j;j--)
  1203. {
  1204. k=j-1;
  1205. highscores[j] = highscores[k];
  1206. }
  1207. highscores[i].score = score;
  1208. highscores[i].level = level;
  1209. strcpy(highscores[i].initials," ");
  1210. break;
  1211. }
  1212. _showhighscores ();
  1213. //
  1214. // did get a high score
  1215. //
  1216. if (i<5)
  1217. {
  1218. PlaySound (16);
  1219. clearkeys ();
  1220. sx = screencenterx-17/2+14;
  1221. sy = screencentery-17/2+6+i*2;
  1222. j=0;
  1223. do
  1224. {
  1225. ch = k = get();
  1226. if (ch>=' ' && j<3)
  1227. {
  1228. drawchar (sx,sy,ch);
  1229. sx++;
  1230. highscores[i].initials[j]=ch;
  1231. j++;
  1232. }
  1233. if (ch==8 || k==19200)
  1234. if (j>0)
  1235. {
  1236. sx--;
  1237. j--;
  1238. }
  1239. } while (ch != 13);
  1240. }
  1241. }
  1242. ////////////////////
  1243. //
  1244. // _setupgame
  1245. //
  1246. ////////////////////
  1247. void _setupgame (void)
  1248. {
  1249. //
  1250. // set up game's library routines
  1251. //
  1252. _videocard = VideoID ();
  1253. grmode = text;
  1254. if (!(_videocard == VGAcard || _videocard == MCGAcard))
  1255. _vgaok = false;
  1256. if (!(_videocard == EGAcard || _videocard == VGAcard))
  1257. _egaok = false;
  1258. // allways assume CGA compatability for simCGA garbage
  1259. _loadctrls ();
  1260. if (grmode==VGAgr && _vgaok)
  1261. grmode=VGAgr;
  1262. else if (grmode>=EGAgr && _egaok)
  1263. grmode=EGAgr;
  1264. else
  1265. grmode=CGAgr;
  1266. strcpy (str,"SOUNDS.");
  1267. strcat (str,_extension);
  1268. SoundData = (char huge *) bloadin (str);
  1269. StartupSound ();
  1270. SetupKBD ();
  1271. initrndt (1); // setup random routines
  1272. // initrnd (1);
  1273. _loadhighscores ();
  1274. loadgrfiles (); // load the graphic files
  1275. }
  1276. ////////////////////
  1277. //
  1278. // _quit
  1279. //
  1280. ////////////////////
  1281. char extern far PIRACY;
  1282. void _quit (char *error)
  1283. {
  1284. setscreenmode (text);
  1285. if (!(*error))
  1286. {
  1287. _savehighscores ();
  1288. _savectrls ();
  1289. }
  1290. else
  1291. {
  1292. puts (error);
  1293. puts("\n");
  1294. puts("\n");
  1295. puts("For techinical assistance with running this software\n");
  1296. puts(" call Softdisk Publishing at 1-318-221-8311\n");
  1297. puts("\n");
  1298. exit(1);
  1299. }
  1300. ShutdownKBD (); // shut down the interrupt driven stuff if needed
  1301. ShutdownSound ();
  1302. #ifndef CATALOG
  1303. _argc = 2;
  1304. _argv[1] = "LAST.SHL";
  1305. _argv[2] = "ENDSCN.SCN";
  1306. _argv[3] = NULL;
  1307. if (execv("LOADSCN.EXE", _argv) == -1)
  1308. _quit("Couldn't find executable LOADSCN.EXE.\n");
  1309. #endif
  1310. // movedata (FP_SEG(&PIRACY),FP_OFF(&PIRACY),0xb800,0,4000);
  1311. // clearkeys ();
  1312. // bioskey (0);
  1313. clrscr ();
  1314. exit (0); // quit to DOS
  1315. }