C5_DRAW.C 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933
  1. /* Catacomb Armageddon 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. // C3_DRAW.C
  19. #include "DEF.H"
  20. #pragma hdrstop
  21. //#define DRAWEACH // draw walls one at a time for debugging
  22. unsigned highest;
  23. unsigned mostwalls,numwalls;
  24. /*
  25. =============================================================================
  26. LOCAL CONSTANTS
  27. =============================================================================
  28. */
  29. #define PI 3.141592657
  30. #define ANGLEQUAD (ANGLES/4)
  31. unsigned oldend;
  32. #define FINEANGLES 3600
  33. #define MINRATIO 16
  34. const unsigned MAXSCALEHEIGHT = (VIEWWIDTH/2);
  35. const unsigned MAXVISHEIGHT = (VIEWHEIGHT/2);
  36. const unsigned BASESCALE = 32;
  37. /*
  38. =============================================================================
  39. GLOBAL VARIABLES
  40. =============================================================================
  41. */
  42. //
  43. // calculate location of screens in video memory so they have the
  44. // maximum possible distance seperating them (for scaling overflow)
  45. //
  46. unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};
  47. unsigned freelatch = FREESTART;
  48. boolean fizzlein;
  49. long scaleshapecalll;
  50. long scaletablecall;
  51. /*
  52. =============================================================================
  53. LOCAL VARIABLES
  54. =============================================================================
  55. */
  56. long bytecount,endcount; // for profiling
  57. int animframe;
  58. int pixelangle[VIEWWIDTH];
  59. int far finetangent[FINEANGLES+1];
  60. int fineviewangle;
  61. unsigned viewxpix,viewypix;
  62. /*
  63. ============================================================================
  64. 3 - D DEFINITIONS
  65. ============================================================================
  66. */
  67. fixed tileglobal = TILEGLOBAL;
  68. fixed focallength = FOCALLENGTH;
  69. fixed mindist = MINDIST;
  70. int viewheight = VIEWHEIGHT;
  71. fixed scale;
  72. tilept tile,lasttile, // tile of wall being followed
  73. focal, // focal point in tiles
  74. left,mid,right; // rightmost tile in view
  75. globpt edge,view;
  76. int segstart[VIEWHEIGHT], // addline tracks line segment and draws
  77. segend[VIEWHEIGHT],
  78. segcolor[VIEWHEIGHT]; // only when the color changes
  79. walltype walls[MAXWALLS],*leftwall,*rightwall;
  80. //==========================================================================
  81. //
  82. // refresh stuff
  83. //
  84. int screenpage;
  85. long lasttimecount;
  86. //
  87. // rendering stuff
  88. //
  89. int firstangle,lastangle;
  90. fixed prestep;
  91. fixed sintable[ANGLES+ANGLES/4],*costable = sintable+(ANGLES/4);
  92. fixed viewx,viewy; // the focal point
  93. int viewangle;
  94. fixed viewsin,viewcos;
  95. int zbuffer[VIEWXH+1]; // holds the height of the wall at that point
  96. //==========================================================================
  97. void DrawLine (int xl, int xh, int y,int color);
  98. void DrawWall (walltype *wallptr);
  99. void TraceRay (unsigned angle);
  100. fixed FixedByFrac (fixed a, fixed b);
  101. fixed FixedAdd (void);
  102. fixed TransformX (fixed gx, fixed gy);
  103. int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max);
  104. int BackTrace (int finish);
  105. void ForwardTrace (void);
  106. int TurnClockwise (void);
  107. int TurnCounterClockwise (void);
  108. void FollowWall (void);
  109. void NewScene (void);
  110. void BuildTables (void);
  111. //==========================================================================
  112. #if 0
  113. /*
  114. ==================
  115. =
  116. = DrawLine
  117. =
  118. = Must be in write mode 2 with all planes enabled
  119. = The bit mask is left set to the end value, so clear it after all lines are
  120. = drawn
  121. =
  122. = draws a black dot at the left edge of the line
  123. =
  124. ==================
  125. */
  126. unsigned static char dotmask[8] = {0x80,0x40,0x20,0x10,8,4,2,1};
  127. unsigned static char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};
  128. unsigned static char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
  129. void DrawLine (int xl, int xh, int y,int color)
  130. {
  131. unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;
  132. xlb=xl/8;
  133. xhb=xh/8;
  134. if (xh<xl)
  135. Quit("DrawLine: xh<xl");
  136. if (y<VIEWY)
  137. Quit("DrawLine: y<VIEWY");
  138. if (y>VIEWYH)
  139. Quit("DrawLine: y>VIEWYH");
  140. xlp = xl&7;
  141. maskleft = leftmask[xlp];
  142. maskright = rightmask[xh&7];
  143. mid = xhb-xlb-1;
  144. dest = bufferofs+ylookup[y]+xlb;
  145. //
  146. // set the GC index register to point to the bit mask register
  147. //
  148. asm mov al,GC_BITMASK
  149. asm mov dx,GC_INDEX
  150. asm out dx,al
  151. if (xlb==xhb)
  152. {
  153. //
  154. // entire line is in one byte
  155. //
  156. maskleft&=maskright;
  157. asm mov es,[screenseg]
  158. asm mov di,[dest]
  159. asm mov dx,GC_INDEX+1
  160. asm mov al,[BYTE PTR maskleft]
  161. asm out dx,al // mask off pixels
  162. asm mov al,[BYTE PTR color]
  163. asm xchg al,[es:di] // load latches and write pixels
  164. return;
  165. }
  166. asm mov es,[screenseg]
  167. asm mov di,[dest]
  168. asm mov dx,GC_INDEX+1
  169. asm mov bh,[BYTE PTR color]
  170. //
  171. // draw left side
  172. //
  173. asm mov al,[BYTE PTR maskleft]
  174. asm out dx,al // mask off pixels
  175. asm mov al,bh
  176. asm xchg al,[es:di] // load latches and write pixels
  177. asm inc di
  178. //
  179. // draw middle
  180. //
  181. asm mov al,255
  182. asm out dx,al // no masking
  183. asm mov al,bh
  184. asm mov cx,[mid]
  185. asm rep stosb
  186. //
  187. // draw right side
  188. //
  189. asm mov al,[BYTE PTR maskright]
  190. asm out dx,al // mask off pixels
  191. asm xchg bh,[es:di] // load latches and write pixels
  192. }
  193. //==========================================================================
  194. void DrawLineDot (int xl, int xh, int y,int color)
  195. {
  196. unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;
  197. xlb=xl/8;
  198. xhb=xh/8;
  199. if (xh<xl)
  200. Quit("DrawLine: xh<xl");
  201. if (y<VIEWY)
  202. Quit("DrawLine: y<VIEWY");
  203. if (y>VIEWYH)
  204. Quit("DrawLine: y>VIEWYH");
  205. xlp = xl&7;
  206. maskdot = dotmask[xlp];
  207. maskleft = leftmask[xlp];
  208. maskright = rightmask[xh&7];
  209. mid = xhb-xlb-1;
  210. dest = bufferofs+ylookup[y]+xlb;
  211. //
  212. // set the GC index register to point to the bit mask register
  213. //
  214. asm mov al,GC_BITMASK
  215. asm mov dx,GC_INDEX
  216. asm out dx,al
  217. if (xlb==xhb)
  218. {
  219. //
  220. // entire line is in one byte
  221. //
  222. maskleft&=maskright;
  223. asm mov es,[screenseg]
  224. asm mov di,[dest]
  225. asm mov dx,GC_INDEX+1
  226. asm mov al,[BYTE PTR maskleft]
  227. asm out dx,al // mask off pixels
  228. asm mov al,[BYTE PTR color]
  229. asm xchg al,[es:di] // load latches and write pixels
  230. //
  231. // write the black dot at the start
  232. //
  233. asm mov al,[BYTE PTR maskdot]
  234. asm out dx,al // mask off pixels
  235. asm xor al,al
  236. asm xchg al,[es:di] // load latches and write pixels
  237. return;
  238. }
  239. asm mov es,[screenseg]
  240. asm mov di,[dest]
  241. asm mov dx,GC_INDEX+1
  242. asm mov bh,[BYTE PTR color]
  243. //
  244. // draw left side
  245. //
  246. asm mov al,[BYTE PTR maskleft]
  247. asm out dx,al // mask off pixels
  248. asm mov al,bh
  249. asm xchg al,[es:di] // load latches and write pixels
  250. //
  251. // write the black dot at the start
  252. //
  253. asm mov al,[BYTE PTR maskdot]
  254. asm out dx,al // mask off pixels
  255. asm xor al,al
  256. asm xchg al,[es:di] // load latches and write pixels
  257. asm inc di
  258. //
  259. // draw middle
  260. //
  261. asm mov al,255
  262. asm out dx,al // no masking
  263. asm mov al,bh
  264. asm mov cx,[mid]
  265. asm rep stosb
  266. //
  267. // draw right side
  268. //
  269. asm mov al,[BYTE PTR maskright]
  270. asm out dx,al // mask off pixels
  271. asm xchg bh,[es:di] // load latches and write pixels
  272. }
  273. #endif
  274. //==========================================================================
  275. long wallscalesource;
  276. #ifdef DRAWEACH
  277. /*
  278. ====================
  279. =
  280. = ScaleOneWall
  281. =
  282. ====================
  283. */
  284. void near ScaleOneWall (int xl, int xh)
  285. {
  286. int x,pixwidth,height;
  287. *(((unsigned *)&wallscalesource)+1) = wallseg[xl];
  288. for (x=xl;x<=xh;x+=pixwidth)
  289. {
  290. height = wallheight[x];
  291. pixwidth = wallwidth[x];
  292. (unsigned)wallscalesource = wallofs[x];
  293. *(((unsigned *)&scaletablecall)+1) = (unsigned)scaledirectory[height];
  294. (unsigned)scaletablecall = scaledirectory[height]->codeofs[0];
  295. //
  296. // scale a byte wide strip of wall
  297. //
  298. asm mov bx,[x]
  299. asm mov di,bx
  300. asm shr di,1
  301. asm shr di,1
  302. asm shr di,1 // X in bytes
  303. asm add di,[bufferofs]
  304. asm and bx,7
  305. asm shl bx,1
  306. asm shl bx,1
  307. asm shl bx,1
  308. asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1
  309. asm dec bx
  310. asm mov al,BYTE PTR [bitmasks1+bx]
  311. asm mov dx,GC_INDEX+1
  312. asm out dx,al // set bit mask register
  313. asm mov es,[screenseg]
  314. asm lds si,[wallscalesource]
  315. asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels
  316. asm mov al,BYTE PTR [ss:bitmasks2+bx]
  317. asm or al,al
  318. asm jz nosecond
  319. //
  320. // draw a second byte for vertical strips that cross two bytes
  321. //
  322. asm inc di
  323. asm out dx,al // set bit mask register
  324. asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels
  325. nosecond:
  326. asm mov ax,ss
  327. asm mov ds,ax
  328. }
  329. }
  330. #endif
  331. char wall_anim_pos[NUMFLOORS];
  332. // EAST / WEST WALLS
  333. //
  334. int far walllight1[NUMFLOORS] = {0,
  335. CRYSTAL_LIGHT_1PIC,
  336. CRYSTAL_LIGHT_2PIC,
  337. CRYSTAL_LIGHT_3PIC,
  338. CRYSTAL_LIGHT_4PIC, //4
  339. FIRE_WALL_1PIC,
  340. FIRE_WALL_2PIC,
  341. FIRE_WALL_3PIC,
  342. FIRE_WALL_4PIC, //8
  343. BRN_STONE_GATEPIC,
  344. BRN_STONE_WALL_1PIC,
  345. KUDZU_WEAK_LIGHTPIC,
  346. KUDZU_LIGHT_WALLPIC,
  347. HEDGE_WALLPIC,
  348. HEDGE_EYESPIC, //14
  349. W_GEN_DOOR1PIC, //15
  350. BRN_WINDOW_LIGHTPIC,
  351. ALTAR_LEFTPIC,
  352. ALTAR_RIGHTPIC,
  353. GRAY_LIGHT_WALLPIC,
  354. GRAY_LIGHT_SIGNPIC, //20
  355. MANICLE_LIGHT_WALLPIC,
  356. MANICLE_LIGHT_BLOODYPIC,
  357. LIGHT_CURTAIN_WINDOWPIC,
  358. LIGHT_CURTAIN_WALLPIC,
  359. BRN_LIGHT_SIGNPIC, //25
  360. LIGHT_STONE_WALLPIC,
  361. W_GEN_DOOR2PIC, //27
  362. TROLL_LIGHT_STONEPIC,
  363. BRN_FLAGSTONE_LIGHT_2PIC,
  364. W_CRYSTAL_DOORPIC,
  365. DMG_BRN_FSTN_LTPIC,
  366. RUST_METAL_LIGHTPIC,
  367. GRAY_METAL_LIGHTPIC, //33
  368. WEAK_STONE_LIGHTPIC,
  369. DMG_FIN_FSTN_LTPIC,
  370. WEAK_GRAY_RFGSTN_LIGHTPIC,
  371. 0,
  372. WEAK_CRYSTAL_LIGHTPIC,
  373. RED_MUD_LIGHTPIC,
  374. STEEL_DOOR1PIC, //40
  375. RED_MUD_WEAK_LIGHTPIC,
  376. STEEL_DOOR2PIC, //42
  377. HORN_DOORPIC,
  378. TROLL_BLOODY_LT_STONEPIC,
  379. CLOSED_DOOR_1PIC,
  380. GRY_DOOR_LTPIC, //46
  381. BRN_DOOR_LTPIC, //47
  382. GRY_FGSTN_LTPIC, //48
  383. DOOR_2PIC,
  384. WATER_LIGHT_WEAK_1PIC,
  385. WATER_LIGHT_WEAK_2PIC,
  386. WATER_LIGHT_WEAK_3PIC, //52
  387. WATER_LIGHT_1PIC,
  388. WATER_LIGHT_2PIC,
  389. WATER_LIGHT_3PIC,
  390. LIGHT_BREATH_1PIC,
  391. LIGHT_BREATH_2PIC,
  392. LIGHT_BREATH_3PIC, //58
  393. EXP_WALL_1PIC,
  394. EXP_WALL_2PIC,
  395. EXP_WALL_3PIC,
  396. WATER_EXP_WALL_1PIC,
  397. WATER_EXP_WALL_2PIC,
  398. WATER_EXP_WALL_3PIC, //64
  399. FINALWALLPIC,
  400. LT_SKEL1PIC,
  401. DK_SKEL1PIC,
  402. LT_SKEL2PIC,
  403. DK_SKEL2PIC,
  404. 0,
  405. TAP_1PIC,
  406. TAP_2PIC,
  407. TAP_3PIC,
  408. TAP_4PIC,
  409. TAP_5PIC,
  410. WATER_DOOR1_PIC,
  411. WATER_DOOR2_PIC,
  412. };
  413. // NORTH / SOUTH WALLS
  414. //
  415. int far walldark1[NUMFLOORS] = {0,
  416. CRYSTAL_DARK_1PIC,
  417. CRYSTAL_DARK_2PIC,
  418. CRYSTAL_DARK_3PIC,
  419. CRYSTAL_DARK_4PIC, //4
  420. FIRE_WALL_1PIC,
  421. FIRE_WALL_2PIC,
  422. FIRE_WALL_3PIC,
  423. FIRE_WALL_4PIC, //8
  424. BRN_STONE_GATEPIC,
  425. BRN_STONE_WALL_2PIC,
  426. KUDZU_WEAK_DARKPIC,
  427. KUDZU_DARK_WALLPIC,
  428. HEDGE_WALLPIC,
  429. HEDGE_EYESPIC, //14
  430. W_GEN_DOOR1PIC, //15
  431. BRN_WINDOW_DARKPIC,
  432. ALTAR_LEFTPIC,
  433. ALTAR_RIGHTPIC,
  434. GRAY_DARK_WALLPIC,
  435. GRAY_DARK_SIGNPIC, //20
  436. MANICLE_DARK_WALLPIC,
  437. MANICLE_DARK_BLOODYPIC,
  438. DARK_CURTAIN_WINDOWPIC,
  439. DARK_CURTAIN_WALLPIC,
  440. BRN_DARK_SIGNPIC,
  441. DARK_STONE_WALLPIC,
  442. W_GEN_DOOR2PIC, //27
  443. TROLL_DARK_STONEPIC,
  444. BRN_FLAGSTONE_DARK_2PIC,
  445. W_CRYSTAL_DOORPIC, //30
  446. DMG_BRN_FSTN_DKPIC,
  447. RUST_METAL_DARKPIC,
  448. GRAY_METAL_DARKPIC,
  449. WEAK_STONE_DARKPIC,
  450. DMG_FIN_FSTN_DKPIC, //35
  451. WEAK_GRAY_RFGSTN_DARKPIC,
  452. 0,
  453. WEAK_CRYSTAL_DARKPIC,
  454. BRN_MUD_DARKPIC,
  455. STEEL_DOOR1PIC, //40
  456. BRN_MUD_WEAK_DARKPIC,
  457. STEEL_DOOR2PIC,
  458. HORN_DOORPIC,
  459. TROLL_BLOODY_DK_STONEPIC,
  460. CLOSED_DOOR_1PIC,
  461. GRY_DOOR_DKPIC, //46
  462. BRN_DOOR_DKPIC, //47
  463. GRY_FGSTN_DKPIC, //48
  464. DOOR_2PIC,
  465. WATER_DARK_WEAK_1PIC,
  466. WATER_DARK_WEAK_2PIC,
  467. WATER_DARK_WEAK_3PIC,
  468. WATER_DARK_1PIC,
  469. WATER_DARK_2PIC,
  470. WATER_DARK_3PIC,
  471. DARK_BREATH_1PIC,
  472. DARK_BREATH_2PIC,
  473. DARK_BREATH_3PIC,
  474. EXP_WALL_1PIC,
  475. EXP_WALL_2PIC,
  476. EXP_WALL_3PIC,
  477. WATER_EXP_WALL_1PIC,
  478. WATER_EXP_WALL_2PIC,
  479. WATER_EXP_WALL_3PIC,
  480. FINALWALLPIC,
  481. LT_SKEL1PIC,
  482. DK_SKEL1PIC,
  483. LT_SKEL2PIC,
  484. DK_SKEL2PIC,
  485. 0,
  486. TAP_1PIC,
  487. TAP_2PIC,
  488. TAP_3PIC,
  489. TAP_4PIC,
  490. TAP_5PIC,
  491. WATER_DOOR1_PIC,
  492. WATER_DOOR2_PIC,
  493. };
  494. /*
  495. =====================
  496. =
  497. = DrawVWall
  498. =
  499. = Draws a wall by vertical segments, for texture mapping!
  500. =
  501. = wallptr->side is true for east/west walls (constant x)
  502. =
  503. = fracheight and fracstep are 16.16 bit fractions
  504. =
  505. =====================
  506. */
  507. void DrawVWall (walltype *wallptr)
  508. {
  509. int x,i;
  510. unsigned source;
  511. unsigned width,sourceint;
  512. unsigned wallpic,wallpicseg;
  513. unsigned skip;
  514. long fracheight,fracstep,longheightchange;
  515. unsigned height;
  516. int heightchange;
  517. unsigned slope,distance;
  518. int traceangle,angle;
  519. int mapadd;
  520. unsigned lastpix,lastsource,lastwidth;
  521. if (wallptr->rightclip < wallptr->leftclip)
  522. Quit ("DrawVWall: Right < Left");
  523. //
  524. // setup for height calculation
  525. //
  526. wallptr->height1 >>= 1;
  527. wallptr->height2 >>= 1;
  528. wallptr->planecoord>>=10; // remove non significant bits
  529. width = wallptr->x2 - wallptr->x1;
  530. if (width)
  531. {
  532. heightchange = wallptr->height2 - wallptr->height1;
  533. asm mov ax,[heightchange]
  534. asm mov WORD PTR [longheightchange+2],ax
  535. asm mov WORD PTR [longheightchange],0 // avoid long shift by 16
  536. fracstep = longheightchange/width;
  537. }
  538. fracheight = ((long)wallptr->height1<<16)+0x8000;
  539. skip = wallptr->leftclip - wallptr->x1;
  540. if (skip)
  541. fracheight += fracstep*skip;
  542. //
  543. // setup for texture mapping
  544. //
  545. // mapadd is 64*64 (to keep source positive) + the origin wall intercept
  546. // distance has 6 unit bits, and 6 frac bits
  547. // traceangle is the center view angle in FINEANGLES, moved to be in
  548. // the +-90 degree range (to thew right of origin)
  549. //
  550. traceangle = fineviewangle;
  551. //
  552. // find wall picture to map from
  553. //
  554. if (wallptr->side)
  555. { // east or west wall
  556. wallpic = walllight1[wallptr->color+wall_anim_pos[wallptr->color]];
  557. if (wallptr->planecoord < viewxpix)
  558. {
  559. distance = viewxpix-wallptr->planecoord;
  560. traceangle -= FINEANGLES/2;
  561. mapadd = (64-viewypix&63); // the pixel spot of the origin
  562. }
  563. else
  564. {
  565. distance = wallptr->planecoord-viewxpix;
  566. // traceangle is correct
  567. mapadd = viewypix&63; // the pixel spot of the origin
  568. }
  569. }
  570. else
  571. { // north or south wall
  572. wallpic = walldark1[wallptr->color+wall_anim_pos[wallptr->color]];
  573. if (wallptr->planecoord < viewypix)
  574. {
  575. distance = viewypix-wallptr->planecoord;
  576. traceangle -= FINEANGLES/4;
  577. mapadd = viewxpix&63; // the pixel spot of the origin
  578. }
  579. else
  580. {
  581. distance = wallptr->planecoord-viewypix;
  582. traceangle -= FINEANGLES*3/4;
  583. mapadd = (64-viewxpix&63); // the pixel spot of the origin
  584. }
  585. }
  586. mapadd = 64*64-mapadd; // make sure it stays positive
  587. wallpicseg = (unsigned)walldirectory[wallpic-FIRSTWALLPIC];
  588. if (traceangle > FINEANGLES/2)
  589. traceangle -= FINEANGLES;
  590. //
  591. // calculate everything
  592. //
  593. // IMPORTANT! This loop is executed around 5000 times / second!
  594. //
  595. lastpix = lastsource = (unsigned)-1;
  596. for (x = wallptr->leftclip ; x <= wallptr->rightclip ; x++)
  597. {
  598. //
  599. // height
  600. //
  601. asm mov ax,WORD PTR [fracheight]
  602. asm mov dx,WORD PTR [fracheight+2]
  603. asm mov cx,dx
  604. asm add ax,WORD PTR [fracstep]
  605. asm adc dx,WORD PTR [fracstep+2]
  606. asm mov WORD PTR [fracheight],ax
  607. asm mov WORD PTR [fracheight+2],dx
  608. asm mov bx,[x]
  609. asm shl bx,1
  610. asm cmp cx,MAXSCALEHEIGHT
  611. asm jbe storeheight
  612. asm mov cx,MAXSCALEHEIGHT
  613. storeheight:
  614. asm mov WORD PTR [wallheight+bx],cx
  615. asm mov WORD PTR [zbuffer+bx],cx
  616. // height = fracheight>>16;
  617. // fracheight += fracstep;
  618. // if (height > MAXSCALEHEIGHT)
  619. // height = MAXSCALEHEIGHT;
  620. // wallheight[x] = zbuffer[x] = height;
  621. //
  622. // texture map
  623. //
  624. angle = pixelangle[x]+traceangle;
  625. if (angle<0)
  626. angle+=FINEANGLES;
  627. slope = finetangent[angle];
  628. //
  629. // distance is an unsigned 6.6 bit number (12 pixel bits)
  630. // slope is a signed 5.10 bit number
  631. // result is a signed 11.16 bit number
  632. //
  633. #if 0
  634. source = distance*slope;
  635. source >>=20;
  636. source += mapadd;
  637. source &= 63; // mask off the unused units
  638. source = 63-source;
  639. source <<= 6; // multiply by 64 for offset into pic
  640. #endif
  641. asm mov ax,[distance]
  642. asm imul [slope] // ax is the source pixel
  643. asm mov al,ah
  644. asm shr al,1
  645. asm shr al,1 // low 6 bits is now pixel number
  646. asm add ax,[mapadd]
  647. asm and ax,63
  648. asm mov dx,63
  649. asm sub dx,ax // otherwise it is backwards
  650. asm shl dx,1
  651. asm shl dx,1
  652. asm shl dx,1
  653. asm shl dx,1
  654. asm shl dx,1
  655. asm shl dx,1 // *64 to index into shape
  656. asm mov [source],dx
  657. if (source != lastsource)
  658. {
  659. if (lastpix != (unsigned)-1)
  660. {
  661. wallofs[lastpix] = lastsource;
  662. wallseg[lastpix] = wallpicseg;
  663. wallwidth[lastpix] = lastwidth;
  664. }
  665. lastpix = x;
  666. lastsource = source;
  667. lastwidth = 1;
  668. }
  669. else
  670. lastwidth++; // optimized draw, same map as last one
  671. }
  672. wallofs[lastpix] = lastsource;
  673. wallseg[lastpix] = wallpicseg;
  674. wallwidth[lastpix] = lastwidth;
  675. }
  676. //==========================================================================
  677. /*
  678. =================
  679. =
  680. = TraceRay
  681. =
  682. = Used to find the left and rightmost tile in the view area to be traced from
  683. = Follows a ray of the given angle from viewx,viewy in the global map until
  684. = it hits a solid tile
  685. = sets:
  686. = tile.x,tile.y : tile coordinates of contacted tile
  687. = tilecolor : solid tile's color
  688. =
  689. ==================
  690. */
  691. int tilecolor;
  692. void TraceRay (unsigned angle)
  693. {
  694. long tracex,tracey,tracexstep,traceystep,searchx,searchy;
  695. fixed fixtemp;
  696. int otx,oty,searchsteps;
  697. tracexstep = costable[angle];
  698. traceystep = sintable[angle];
  699. //
  700. // advance point so it is even with the view plane before we start checking
  701. //
  702. fixtemp = FixedByFrac(prestep,tracexstep);
  703. tracex = viewx+fixtemp;
  704. fixtemp = FixedByFrac(prestep,traceystep);
  705. tracey = viewy-fixtemp;
  706. tile.x = tracex>>TILESHIFT; // starting point in tiles
  707. tile.y = tracey>>TILESHIFT;
  708. if (tracexstep<0) // use 2's complement, not signed magnitude
  709. tracexstep = -(tracexstep&0x7fffffff);
  710. if (traceystep<0) // use 2's complement, not signed magnitude
  711. traceystep = -(traceystep&0x7fffffff);
  712. //
  713. // we assume viewx,viewy is not inside a solid tile, so go ahead one step
  714. //
  715. do // until a solid tile is hit
  716. {
  717. otx = tile.x;
  718. oty = tile.y;
  719. spotvis[otx][oty] = true;
  720. tracex += tracexstep;
  721. tracey -= traceystep;
  722. tile.x = tracex>>TILESHIFT;
  723. tile.y = tracey>>TILESHIFT;
  724. if (tile.x!=otx && tile.y!=oty && (tilemap[otx][tile.y] || tilemap[tile.x][oty]) )
  725. {
  726. //
  727. // trace crossed two solid tiles, so do a binary search along the line
  728. // to find a spot where only one tile edge is crossed
  729. //
  730. searchsteps = 0;
  731. searchx = tracexstep;
  732. searchy = traceystep;
  733. do
  734. {
  735. searchx/=2;
  736. searchy/=2;
  737. if (tile.x!=otx && tile.y!=oty)
  738. {
  739. // still too far
  740. tracex -= searchx;
  741. tracey += searchy;
  742. }
  743. else
  744. {
  745. // not far enough, no tiles crossed
  746. tracex += searchx;
  747. tracey -= searchy;
  748. }
  749. //
  750. // if it is REAL close, go for the most clockwise intersection
  751. //
  752. if (++searchsteps == 16)
  753. {
  754. tracex = (long)otx<<TILESHIFT;
  755. tracey = (long)oty<<TILESHIFT;
  756. if (tracexstep>0)
  757. {
  758. if (traceystep<0)
  759. {
  760. tracex += TILEGLOBAL-1;
  761. tracey += TILEGLOBAL;
  762. }
  763. else
  764. {
  765. tracex += TILEGLOBAL;
  766. }
  767. }
  768. else
  769. {
  770. if (traceystep<0)
  771. {
  772. tracex --;
  773. tracey += TILEGLOBAL-1;
  774. }
  775. else
  776. {
  777. tracey --;
  778. }
  779. }
  780. }
  781. tile.x = tracex>>TILESHIFT;
  782. tile.y = tracey>>TILESHIFT;
  783. } while (( tile.x!=otx && tile.y!=oty) || (tile.x==otx && tile.y==oty) );
  784. }
  785. } while (!(tilecolor = tilemap[tile.x][tile.y]) );
  786. }
  787. //==========================================================================
  788. /*
  789. ========================
  790. =
  791. = FixedByFrac
  792. =
  793. = multiply a 16/16 bit, 2's complement fixed point number by a 16 bit
  794. = fraction, passed as a signed magnitude 32 bit number
  795. =
  796. ========================
  797. */
  798. #pragma warn -rvl // I stick the return value in with ASMs
  799. fixed FixedByFrac (fixed a, fixed b)
  800. {
  801. fixed value;
  802. //
  803. // setup
  804. //
  805. asm mov si,[WORD PTR b+2] // sign of result = sign of fraction
  806. asm mov ax,[WORD PTR a]
  807. asm mov cx,[WORD PTR a+2]
  808. asm or cx,cx
  809. asm jns aok: // negative?
  810. asm not ax
  811. asm not cx
  812. asm add ax,1
  813. asm adc cx,0
  814. asm xor si,0x8000 // toggle sign of result
  815. aok:
  816. //
  817. // multiply cx:ax by bx
  818. //
  819. asm mov bx,[WORD PTR b]
  820. asm mul bx // fraction*fraction
  821. asm mov di,dx // di is low word of result
  822. asm mov ax,cx //
  823. asm mul bx // units*fraction
  824. asm add ax,di
  825. asm adc dx,0
  826. //
  827. // put result dx:ax in 2's complement
  828. //
  829. asm test si,0x8000 // is the result negative?
  830. asm jz ansok:
  831. asm not ax
  832. asm not dx
  833. asm add ax,1
  834. asm adc dx,0
  835. ansok:;
  836. }
  837. #pragma warn +rvl
  838. #if 0
  839. /*
  840. =========================
  841. =
  842. = FixedAdd
  843. =
  844. = add two 16 bit fixed point numbers
  845. = to subtract, invert the sign of B before invoking
  846. =
  847. =========================
  848. */
  849. fixed FixedAdd (fixed a, fixed b)
  850. {
  851. fixed value;
  852. asm mov ax,[WORD PTR a]
  853. asm mov dx,[WORD PTR a+2]
  854. asm mov bx,[WORD PTR b]
  855. asm mov cx,[WORD PTR b+2]
  856. asm or dx,dx
  857. asm jns aok: // negative?
  858. asm and dx,0x7fff
  859. asm not ax // convert a from signed magnitude to 2's compl
  860. asm not dx
  861. asm add ax,1
  862. asm adc dx,0
  863. aok:
  864. asm or cx,cx
  865. asm jns bok: // negative?
  866. asm and cx,0x7fff
  867. asm not bx // convert b from signed magnitude to 2's compl
  868. asm not cx
  869. asm add bx,1
  870. asm adc cx,0
  871. bok:
  872. asm add ax,bx // perform the addition
  873. asm adc dx,cx
  874. asm jns done
  875. asm and dx,0x7fff // value was negative
  876. asm not ax // back to signed magnitude
  877. asm not dx
  878. asm add ax,1
  879. asm adc dx,0
  880. done:
  881. asm mov [WORD PTR value],ax
  882. asm mov [WORD PTR value+2],dx
  883. return value;
  884. }
  885. #endif
  886. //==========================================================================
  887. /*
  888. ========================
  889. =
  890. = TransformPoint
  891. =
  892. = Takes paramaters:
  893. = gx,gy : globalx/globaly of point
  894. =
  895. = globals:
  896. = viewx,viewy : point of view
  897. = viewcos,viewsin : sin/cos of viewangle
  898. =
  899. =
  900. = defines:
  901. = CENTERX : pixel location of center of view window
  902. = TILEGLOBAL : size of one
  903. = FOCALLENGTH : distance behind viewx/y for center of projection
  904. = scale : conversion from global value to screen value
  905. =
  906. = returns:
  907. = screenx,screenheight: projected edge location and size
  908. =
  909. ========================
  910. */
  911. void TransformPoint (fixed gx, fixed gy, int *screenx, unsigned *screenheight)
  912. {
  913. int ratio;
  914. fixed gxt,gyt,nx,ny;
  915. //
  916. // translate point to view centered coordinates
  917. //
  918. gx = gx-viewx;
  919. gy = gy-viewy;
  920. //
  921. // calculate newx
  922. //
  923. gxt = FixedByFrac(gx,viewcos);
  924. gyt = FixedByFrac(gy,viewsin);
  925. nx = gxt-gyt;
  926. //
  927. // calculate newy
  928. //
  929. gxt = FixedByFrac(gx,viewsin);
  930. gyt = FixedByFrac(gy,viewcos);
  931. ny = gyt+gxt;
  932. //
  933. // calculate perspective ratio
  934. //
  935. if (nx<0)
  936. nx = 0;
  937. ratio = nx*scale/FOCALLENGTH;
  938. if (ratio<=MINRATIO)
  939. ratio = MINRATIO;
  940. *screenx = CENTERX + ny/ratio;
  941. *screenheight = TILEGLOBAL/ratio;
  942. }
  943. //
  944. // transform actor
  945. //
  946. void TransformActor (objtype *ob)
  947. {
  948. int ratio;
  949. fixed gx,gy,gxt,gyt,nx,ny;
  950. //
  951. // translate point to view centered coordinates
  952. //
  953. gx = ob->x-viewx;
  954. gy = ob->y-viewy;
  955. //
  956. // calculate newx
  957. //
  958. gxt = FixedByFrac(gx,viewcos);
  959. gyt = FixedByFrac(gy,viewsin);
  960. nx = gxt-gyt-ob->size;
  961. //
  962. // calculate newy
  963. //
  964. gxt = FixedByFrac(gx,viewsin);
  965. gyt = FixedByFrac(gy,viewcos);
  966. ny = gyt+gxt;
  967. //
  968. // calculate perspective ratio
  969. //
  970. if (nx<0)
  971. nx = 0;
  972. ratio = nx*scale/FOCALLENGTH;
  973. if (ratio<=MINRATIO)
  974. ratio = MINRATIO;
  975. ob->viewx = CENTERX + ny/ratio;
  976. ob->viewheight = TILEGLOBAL/ratio;
  977. }
  978. //==========================================================================
  979. fixed TransformX (fixed gx, fixed gy)
  980. {
  981. int ratio;
  982. fixed gxt,gyt,nx,ny;
  983. //
  984. // translate point to view centered coordinates
  985. //
  986. gx = gx-viewx;
  987. gy = gy-viewy;
  988. //
  989. // calculate newx
  990. //
  991. gxt = FixedByFrac(gx,viewcos);
  992. gyt = FixedByFrac(gy,viewsin);
  993. return gxt-gyt;
  994. }
  995. //==========================================================================
  996. /*
  997. ==================
  998. =
  999. = BuildTables
  1000. =
  1001. = Calculates:
  1002. =
  1003. = scale projection constant
  1004. = sintable/costable overlapping fractional tables
  1005. = firstangle/lastangle angles from focalpoint to left/right view edges
  1006. = prestep distance from focal point before checking for tiles
  1007. =
  1008. ==================
  1009. */
  1010. void BuildTables (void)
  1011. {
  1012. int i;
  1013. long intang;
  1014. long x;
  1015. float angle,anglestep,radtoint;
  1016. double tang;
  1017. fixed value;
  1018. //
  1019. // calculate the angle offset from view angle of each pixel's ray
  1020. //
  1021. radtoint = (float)FINEANGLES/2/PI;
  1022. for (i=0;i<VIEWWIDTH/2;i++)
  1023. {
  1024. // start 1/2 pixel over, so viewangle bisects two middle pixels
  1025. x = (TILEGLOBAL*i+TILEGLOBAL/2)/VIEWWIDTH;
  1026. tang = (float)x/(FOCALLENGTH+MINDIST);
  1027. angle = atan(tang);
  1028. intang = angle*radtoint;
  1029. pixelangle[VIEWWIDTH/2-1-i] = intang;
  1030. pixelangle[VIEWWIDTH/2+i] = -intang;
  1031. }
  1032. //
  1033. // calculate fine tangents
  1034. // 1 sign bit, 5 units (clipped to), 10 fracs
  1035. //
  1036. #define MININT (-MAXINT)
  1037. for (i=0;i<FINEANGLES/4;i++)
  1038. {
  1039. intang = tan(i/radtoint)*(1l<<10);
  1040. //
  1041. // if the tangent is not reprentable in this many bits, bound the
  1042. // units part ONLY
  1043. //
  1044. if (intang>MAXINT)
  1045. intang = 0x8f00 | (intang & 0xff);
  1046. else if (intang<MININT)
  1047. intang = 0xff00 | (intang & 0xff);
  1048. finetangent[i] = intang;
  1049. // finetangent[FINEANGLES/2+i] = intang;
  1050. // finetangent[FINEANGLES/2-i-1] = -intang;
  1051. finetangent[FINEANGLES-i-1] = -intang;
  1052. }
  1053. //
  1054. // calculate scale value so one tile at mindist allmost fills the view horizontally
  1055. //
  1056. scale = GLOBAL1/VIEWWIDTH;
  1057. scale *= focallength;
  1058. scale /= (focallength+mindist);
  1059. //
  1060. // costable overlays sintable with a quarter phase shift
  1061. // ANGLES is assumed to be divisable by four
  1062. //
  1063. // The low word of the value is the fraction, the high bit is the sign bit,
  1064. // bits 16-30 should be 0
  1065. //
  1066. angle = 0;
  1067. anglestep = PI/2/ANGLEQUAD;
  1068. for (i=0;i<=ANGLEQUAD;i++)
  1069. {
  1070. value=GLOBAL1*sin(angle);
  1071. sintable[i]=
  1072. sintable[i+ANGLES]=
  1073. sintable[ANGLES/2-i] = value;
  1074. sintable[ANGLES-i]=
  1075. sintable[ANGLES/2+i] = value | 0x80000000l;
  1076. angle += anglestep;
  1077. }
  1078. //
  1079. // figure trace angles for first and last pixel on screen
  1080. //
  1081. angle = atan((float)VIEWWIDTH/2*scale/FOCALLENGTH);
  1082. angle *= ANGLES/(PI*2);
  1083. intang = (int)angle+1;
  1084. firstangle = intang;
  1085. lastangle = -intang;
  1086. prestep = GLOBAL1*((float)FOCALLENGTH/costable[firstangle]);
  1087. //
  1088. // misc stuff
  1089. //
  1090. walls[0].x2 = VIEWX-1;
  1091. walls[0].height2 = 32000;
  1092. }
  1093. //==========================================================================
  1094. /*
  1095. =====================
  1096. =
  1097. = ClearScreen
  1098. =
  1099. =====================
  1100. */
  1101. void ClearScreen (void)
  1102. {
  1103. unsigned topcolor=*skycolor, bottomcolor=*groundcolor;
  1104. unsigned topimage=topcolor&0xf0,bottomimage=bottomcolor&0xf0;
  1105. unsigned pfoffset=0;
  1106. #if USE_STRIPS
  1107. if (topimage == 0x20) // special code for lightning
  1108. topimage = topcolor = 0;
  1109. // Manually wipe screen with solid color.
  1110. // If BOTH sky and ground are 'images' don't manually clear it!
  1111. //
  1112. if ((!topimage) || (!bottomimage))
  1113. {
  1114. #endif
  1115. //
  1116. // clear the screen
  1117. //
  1118. asm mov dx,GC_INDEX
  1119. asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2
  1120. asm out dx,ax
  1121. asm mov ax,GC_BITMASK + 255*256
  1122. asm out dx,ax
  1123. //asm mov dx,40-VIEWWIDTH/8 // dx = modulo
  1124. asm mov bl,VIEWWIDTH/16
  1125. asm mov bh,CENTERY+1
  1126. asm mov ax,topcolor
  1127. asm mov es,[screenseg]
  1128. asm mov di,[bufferofs]
  1129. asm add di,((SCREENWIDTH*VIEWY)+(VIEWX/8))
  1130. toploop:
  1131. asm mov cl,bl
  1132. asm rep stosw
  1133. asm stosb
  1134. //asm add di,dx // no need to add "0" modulo
  1135. asm dec bh
  1136. asm jnz toploop
  1137. asm mov bh,CENTERY+1
  1138. asm mov ax,bottomcolor
  1139. bottomloop:
  1140. asm mov cl,bl
  1141. asm rep stosw
  1142. asm stosb
  1143. //asm add di,dx // no need to add "0" modulo
  1144. asm dec bh
  1145. asm jnz bottomloop
  1146. #if USE_STRIPS
  1147. }
  1148. //
  1149. // code to test parallax turning
  1150. //
  1151. if (topimage)
  1152. {
  1153. topimage -= 16;
  1154. pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12);
  1155. while (pfoffset >= 640)
  1156. pfoffset -= 640;
  1157. LatchDrawPicStrip(0,0,SKY1PIC+topimage,pfoffset+8);
  1158. }
  1159. if (bottomimage)
  1160. {
  1161. //// pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12)+320;
  1162. // pfoffset += 320;
  1163. // while (pfoffset >= 640)
  1164. // pfoffset -= 640;
  1165. // LatchDrawPicStrip(0,64,SKY1PIC+topimage,pfoffset+8);
  1166. bottomimage -= 16;
  1167. LatchDrawPic(0,64,GND1PIC+bottomimage);
  1168. }
  1169. #endif
  1170. asm mov dx,GC_INDEX
  1171. asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2
  1172. asm out dx,ax
  1173. asm mov al,GC_BITMASK
  1174. asm out dx,al
  1175. }
  1176. //==========================================================================
  1177. /*
  1178. =====================
  1179. =
  1180. = DrawWallList
  1181. =
  1182. = Clips and draws all the walls traced this refresh
  1183. =
  1184. =====================
  1185. */
  1186. void DrawWallList (void)
  1187. {
  1188. int i,leftx,newleft,rightclip;
  1189. walltype *wall, *check;
  1190. asm mov ax,ds
  1191. asm mov es,ax
  1192. asm mov di,OFFSET wallwidth
  1193. asm xor ax,ax
  1194. asm mov cx,VIEWWIDTH/2
  1195. asm rep stosw
  1196. ClearScreen ();
  1197. rightwall->x1 = VIEWXH+1;
  1198. rightwall->height1 = 32000;
  1199. (rightwall+1)->x1 = 32000;
  1200. leftx = -1;
  1201. for (wall=&walls[1];wall<rightwall && leftx<=VIEWXH ;wall++)
  1202. {
  1203. if (leftx >= wall->x2)
  1204. continue;
  1205. rightclip = wall->x2;
  1206. check = wall+1;
  1207. while (check->x1 <= rightclip && check->height1 >= wall->height2)
  1208. {
  1209. rightclip = check->x1-1;
  1210. check++;
  1211. }
  1212. if (rightclip>VIEWXH)
  1213. rightclip=VIEWXH;
  1214. if (leftx < wall->x1 - 1)
  1215. newleft = wall->x1-1; // there was black space between walls
  1216. else
  1217. newleft = leftx;
  1218. if (rightclip > newleft)
  1219. {
  1220. wall->leftclip = newleft+1;
  1221. wall->rightclip = rightclip;
  1222. DrawVWall (wall);
  1223. leftx = rightclip;
  1224. }
  1225. }
  1226. #ifndef DRAWEACH
  1227. ScaleWalls (); // draw all the walls
  1228. #endif
  1229. }
  1230. //==========================================================================
  1231. /*
  1232. =====================
  1233. =
  1234. = DrawScaleds
  1235. =
  1236. = Draws all objects that are visable
  1237. =
  1238. =====================
  1239. */
  1240. objtype *depthsort[MAXACTORS];
  1241. void DrawScaleds (void)
  1242. {
  1243. #if USE_INERT_LIST
  1244. extern inertobjtype inertobjlist[], *inert;
  1245. boolean inertlist=false;
  1246. #endif
  1247. int i,j,least,numvisable,height;
  1248. objtype *obj,**vislist,*farthest;
  1249. memptr shape;
  1250. byte *tilespot,*visspot;
  1251. numvisable = 0;
  1252. //
  1253. // calculate base positions of all objects
  1254. //
  1255. vislist = &depthsort[0];
  1256. obj = player->next;
  1257. while (obj)
  1258. {
  1259. tilespot = &tilemap[0][0]+(obj->tilex<<6)+obj->tiley;
  1260. visspot = &spotvis[0][0]+(obj->tilex<<6)+obj->tiley;
  1261. //
  1262. // could be in any of the nine surrounding tiles
  1263. //
  1264. if (*visspot
  1265. || ( *(visspot-1) && !*(tilespot-1) )
  1266. || ( *(visspot+1) && !*(tilespot+1) )
  1267. || ( *(visspot-65) && !*(tilespot-65) )
  1268. || ( *(visspot-64) && !*(tilespot-64) )
  1269. || ( *(visspot-63) && !*(tilespot-63) )
  1270. || ( *(visspot+65) && !*(tilespot+65) )
  1271. || ( *(visspot+64) && !*(tilespot+64) )
  1272. || ( *(visspot+63) && !*(tilespot+63) ) )
  1273. {
  1274. #if USE_INERT_LIST
  1275. if (!inertlist)
  1276. #endif
  1277. if ((obj->active == noalways) || (obj->active == always))
  1278. obj->active = always;
  1279. else
  1280. obj->active = yes;
  1281. TransformActor (obj);
  1282. if (!obj->viewheight || obj->viewheight > VIEWWIDTH)
  1283. goto cont; // too close or far away
  1284. if (!obj->state->shapenum)
  1285. goto cont;
  1286. *vislist++ = obj;
  1287. numvisable++;
  1288. }
  1289. else
  1290. #if USE_INERT_LIST
  1291. if (!inertlist)
  1292. #endif
  1293. if ((obj->active != always) && (obj->active != noalways))
  1294. obj->active = no;
  1295. cont:;
  1296. obj = obj->next;
  1297. #if USE_INERT_LIST
  1298. if ((!obj) && (!inertlist))
  1299. {
  1300. if (inert != inertobjlist)
  1301. obj = (objtype *)inertobjlist;
  1302. inertlist = true;
  1303. }
  1304. #endif
  1305. }
  1306. if (vislist == &depthsort[0])
  1307. return; // no visable objects
  1308. //
  1309. // draw from back to front
  1310. //
  1311. for (i = 0; i<numvisable; i++)
  1312. {
  1313. least = 32000;
  1314. for (j=0;j<numvisable;j++)
  1315. {
  1316. height = depthsort[j]->viewheight;
  1317. if (height < least)
  1318. {
  1319. least = height;
  1320. farthest = depthsort[j];
  1321. }
  1322. }
  1323. //
  1324. // draw farthest
  1325. //
  1326. shape = shapedirectory[farthest->state->shapenum-FIRSTSCALEPIC];
  1327. ScaleShape(farthest->viewx,shape,farthest->viewheight);
  1328. farthest->viewheight = 32000;
  1329. }
  1330. }
  1331. //==========================================================================
  1332. /*
  1333. =====================
  1334. =
  1335. = CalcTics
  1336. =
  1337. =====================
  1338. */
  1339. void CalcTics (void)
  1340. {
  1341. long newtime,oldtimecount;
  1342. #ifdef PROFILE
  1343. tics = 1;
  1344. return;
  1345. #endif
  1346. //
  1347. // calculate tics since last refresh for adaptive timing
  1348. //
  1349. if (lasttimecount > TimeCount)
  1350. TimeCount = lasttimecount; // if the game was paused a LONG time
  1351. #if 0
  1352. if (DemoMode) // demo recording and playback needs
  1353. { // to be constant
  1354. //
  1355. // take DEMOTICS or more tics, and modify Timecount to reflect time taken
  1356. //
  1357. oldtimecount = lasttimecount;
  1358. while (TimeCount<oldtimecount+DEMOTICS*2)
  1359. ;
  1360. lasttimecount = oldtimecount + DEMOTICS;
  1361. TimeCount = lasttimecount + DEMOTICS;
  1362. realtics = tics = DEMOTICS;
  1363. }
  1364. else
  1365. #endif
  1366. {
  1367. //
  1368. // non demo, so report actual time
  1369. //
  1370. newtime = TimeCount;
  1371. realtics = tics = newtime-lasttimecount;
  1372. lasttimecount = newtime;
  1373. #ifdef FILEPROFILE
  1374. strcpy (scratch,"\tTics:");
  1375. itoa (tics,str,10);
  1376. strcat (scratch,str);
  1377. strcat (scratch,"\n");
  1378. write (profilehandle,scratch,strlen(scratch));
  1379. #endif
  1380. if (tics>MAXTICS)
  1381. {
  1382. TimeCount -= (tics-MAXTICS);
  1383. tics = MAXTICS;
  1384. }
  1385. if (realtics>MAXREALTICS)
  1386. realtics = MAXREALTICS;
  1387. }
  1388. }
  1389. //==========================================================================
  1390. /*
  1391. ========================
  1392. =
  1393. = DrawHand
  1394. =
  1395. ========================
  1396. */
  1397. void DrawHand (void)
  1398. {
  1399. #define HAND_X_POS ((VIEWWIDTH/16)-(10/2)) // "10" = hand width in bytes
  1400. #define picnum HAND1PICM
  1401. memptr source;
  1402. unsigned dest,width,height;
  1403. // if (gamestate.shotpower || boltsleft)
  1404. // picnum += (((unsigned)TimeCount>>3)&1);
  1405. source = grsegs[picnum];
  1406. dest = ylookup[VIEWHEIGHT-handheight]+HAND_X_POS+bufferofs; // 12
  1407. width = picmtable[picnum-STARTPICM].width;
  1408. height = picmtable[picnum-STARTPICM].height;
  1409. VW_MaskBlock(source,0,dest,width,handheight,width*height);
  1410. EGAMAPMASK(15);
  1411. }
  1412. //==========================================================================
  1413. /*
  1414. ========================
  1415. =
  1416. = ThreeDRefresh
  1417. =
  1418. ========================
  1419. */
  1420. void ThreeDRefresh (void)
  1421. {
  1422. int tracedir;
  1423. restart:
  1424. aborttrace = false;
  1425. //
  1426. // clear out the traced array
  1427. //
  1428. asm mov ax,ds
  1429. asm mov es,ax
  1430. asm mov di,OFFSET spotvis
  1431. asm xor ax,ax
  1432. asm mov cx,[mapwidth] // mapheight*32 words
  1433. asm shl cx,1
  1434. asm shl cx,1
  1435. asm shl cx,1
  1436. asm shl cx,1
  1437. asm shl cx,1
  1438. asm rep stosw
  1439. //
  1440. // set up variables for this view
  1441. //
  1442. viewangle = player->angle;
  1443. fineviewangle = viewangle*(FINEANGLES/ANGLES);
  1444. viewsin = sintable[viewangle];
  1445. viewcos = costable[viewangle];
  1446. viewx = player->x - FixedByFrac(FOCALLENGTH,viewcos);
  1447. viewy = player->y + FixedByFrac(FOCALLENGTH,viewsin);
  1448. viewx &= 0xfffffc00; // stop on a pixel boundary
  1449. viewy &= 0xfffffc00;
  1450. viewx += 0x180;
  1451. viewy += 0x180;
  1452. viewxpix = viewx>>10;
  1453. viewypix = viewy>>10;
  1454. focal.x = viewx>>TILESHIFT;
  1455. focal.y = viewy>>TILESHIFT;
  1456. //
  1457. // find the rightmost visable tile in view
  1458. //
  1459. tracedir = viewangle + lastangle;
  1460. if (tracedir<0)
  1461. tracedir+=ANGLES;
  1462. else if (tracedir>=ANGLES)
  1463. tracedir-=ANGLES;
  1464. TraceRay( tracedir );
  1465. right.x = tile.x;
  1466. right.y = tile.y;
  1467. //
  1468. // find the leftmost visable tile in view
  1469. //
  1470. tracedir = viewangle + firstangle;
  1471. if (tracedir<0)
  1472. tracedir+=ANGLES;
  1473. else if (tracedir>=ANGLES)
  1474. tracedir-=ANGLES;
  1475. TraceRay( tracedir );
  1476. //
  1477. // follow the walls from there to the right
  1478. //
  1479. rightwall = &walls[1];
  1480. FollowWalls ();
  1481. if (aborttrace)
  1482. goto restart;
  1483. //
  1484. // actually draw stuff
  1485. //
  1486. if (++screenpage == 3)
  1487. screenpage = 0;
  1488. bufferofs = screenloc[screenpage];
  1489. EGAWRITEMODE(2);
  1490. EGAMAPMASK(15);
  1491. //
  1492. // draw the wall list saved be FollowWalls ()
  1493. //
  1494. // animframe = (TimeCount&8)>>3;
  1495. //
  1496. // draw all the scaled images
  1497. //
  1498. asm mov dx,GC_INDEX
  1499. asm mov ax,GC_COLORDONTCARE
  1500. asm out dx,ax // don't look at any of the planes
  1501. asm mov ax,GC_MODE + 256*(10) // read mode 1, write mode 2
  1502. asm out dx,ax
  1503. asm mov al,GC_BITMASK
  1504. asm out dx,al
  1505. AnimateWallList();
  1506. DrawWallList();
  1507. DrawScaleds();
  1508. EGAWRITEMODE(0);
  1509. EGABITMASK(0xff);
  1510. //
  1511. // draw hand
  1512. //
  1513. if (handheight)
  1514. DrawHand ();
  1515. //
  1516. // show screen and time last cycle
  1517. //
  1518. if (fizzlein)
  1519. {
  1520. fizzlein = false;
  1521. FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,true);
  1522. lasttimecount = TimeCount;
  1523. if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
  1524. }
  1525. asm cli
  1526. asm mov cx,[bufferofs]
  1527. asm mov dx,3d4h // CRTC address register
  1528. asm mov al,0ch // start address high register
  1529. asm out dx,al
  1530. asm inc dx
  1531. asm mov al,ch
  1532. asm out dx,al // set the high byte
  1533. asm dec dx
  1534. asm mov al,0dh // start address low register
  1535. asm out dx,al
  1536. asm inc dx
  1537. asm mov al,cl
  1538. asm out dx,al // set the low byte
  1539. asm sti
  1540. displayofs = bufferofs;
  1541. CalcTics ();
  1542. }