1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 
5 #include <fcntl.h>
6 #include <io.h>
7 #include <sys\types.h>
8 #include <sys\stat.h>
9 #include "build.h"
10 #include "pragmas.h"
11 #include "names.h"
12 #include <dos.h>
13 
14 extern char keystatus[256];
15 
16 static char tempbuf[256];
17 extern long qsetmode;
18 extern short searchsector, searchwall, searchstat;
19 extern long zmode, kensplayerheight;
20 extern short defaultspritecstat;
21 
22 extern short temppicnum, tempcstat, templotag, temphitag, tempextra;
23 extern char tempshade, temppal, tempxrepeat, tempyrepeat;
24 extern char somethingintab;
25 
26 #define NUMOPTIONS 8
27 #define NUMKEYS 19
28 static long vesares[13][2] = {320,200,360,200,320,240,360,240,320,400,
29 									360,400,640,350,640,400,640,480,800,600,
30 									1024,768,1280,1024,1600,1200};
31 static char option[NUMOPTIONS] = {0,0,0,0,0,0,1,0};
32 static char keys[NUMKEYS] =
33 {
34 	0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
35 	0x1e,0x2c,0xd1,0xc9,0x33,0x34,
36 	0x9c,0x1c,0xd,0xc,0xf,
37 };
38 
39 extern char buildkeys[NUMKEYS];
40 
41 extern long frameplace, xdimenscale, ydimen;
42 extern long posx, posy, posz, horiz;
43 extern short ang, cursectnum;
44 
45 static long hang = 0;
46 extern long stretchhline(long,long,long,long,long,long);
47 #pragma aux stretchhline parm [eax][ebx][ecx][edx][esi][edi];
48 
49 //Detecting 2D / 3D mode:
50 //   qsetmode is 200 in 3D mode
51 //   qsetmode is 350/480 in 2D mode
52 //
53 //You can read these variables when F5-F8 is pressed in 3D mode only:
54 //
55 //   If (searchstat == 0)  WALL        searchsector=sector, searchwall=wall
56 //   If (searchstat == 1)  CEILING     searchsector=sector
57 //   If (searchstat == 2)  FLOOR       searchsector=sector
58 //   If (searchstat == 3)  SPRITE      searchsector=sector, searchwall=sprite
59 //   If (searchstat == 4)  MASKED WALL searchsector=sector, searchwall=wall
60 //
61 //   searchsector is the sector of the selected item for all 5 searchstat's
62 //
63 //   searchwall is undefined if searchstat is 1 or 2
64 //   searchwall is the wall if searchstat = 0 or 4
65 //   searchwall is the sprite if searchstat = 3 (Yeah, I know - it says wall,
66 //                                      but trust me, it's the sprite number)
67 
68 long ofinetotalclock, ototalclock, averagefps;
69 #define AVERAGEFRAMES 32
70 static long frameval[AVERAGEFRAMES], framecnt = 0;
71 
72 #pragma aux inittimer42 =\
73 	"in al, 0x61",\
74 	"or al, 1",\
75 	"out 0x61, al",\
76 	"mov al, 0xb4",\
77 	"out 0x43, al",\
78 	"xor al, al",\
79 	"out 0x42, al",\
80 	"out 0x42, al",\
81 	modify exact [eax]\
82 
83 #pragma aux uninittimer42 =\
84 	"in al, 0x61",\
85 	"and al, 252",\
86 	"out 0x61, al",\
87 	modify exact [eax]\
88 
89 #pragma aux gettimer42 =\
90 	"mov al, 0x84",\
91 	"out 0x43, al",\
92 	"in al, 0x42",\
93 	"shl eax, 24",\
94 	"in al, 0x42",\
95 	"rol eax, 8",\
96 	modify [eax]\
97 
ExtInit(void)98 void ExtInit(void)
99 {
100 	long i, fil;
101 
102 	/*printf("------------------------------------------------------------------------------\n");
103 	printf("   BUILD.EXE copyright(c) 1996 by Ken Silverman.  You are granted the\n");
104 	printf("   right to use this software for your personal use only.  This is a\n");
105 	printf("   special version to be used with \"Happy Fun KenBuild\" and may not work\n");
106 	printf("   properly with other Build engine games.  Please refer to license.doc\n");
107 	printf("   for distribution rights\n");
108 	printf("------------------------------------------------------------------------------\n");
109 	getch();
110 	*/
111 
112 	initgroupfile("stuff.dat");
113 	if ((fil = open("setup.dat",O_BINARY|O_RDWR,S_IREAD)) != -1)
114 	{
115 		read(fil,&option[0],NUMOPTIONS);
116 		read(fil,&keys[0],NUMKEYS);
117 		memcpy((void *)buildkeys,(void *)keys,NUMKEYS);   //Trick to make build use setup.dat keys
118 		close(fil);
119 	}
120 	if (option[4] > 0) option[4] = 0;
121 	initmouse();
122 	initengine();
123 	vidoption = option[0]; xdim = vesares[option[6]&15][0]; ydim = vesares[option[6]&15][1];
124 
125 		//You can load your own palette lookup tables here if you just
126 		//copy the right code!
127 	for(i=0;i<256;i++)
128 		tempbuf[i] = ((i+32)&255);  //remap colors for screwy palette sectors
129 	makepalookup(16,tempbuf,0,0,0,1);
130 
131 	kensplayerheight = 32;
132 	zmode = 0;
133 	defaultspritecstat = 0;
134 	pskyoff[0] = 0; pskyoff[1] = 0; pskybits = 1;
135 }
136 
ExtUnInit(void)137 void ExtUnInit(void)
138 {
139 	uninittimer42();
140 	uninitgroupfile();
141 }
142 
143 static long daviewingrange, daaspect, horizval1, horizval2;
ExtPreCheckKeys(void)144 void ExtPreCheckKeys(void)
145 {
146 	long cosang, sinang, dx, dy, mindx, i;
147 
148 	if (keystatus[0x3e])  //F4 - screen re-size
149 	{
150 		keystatus[0x3e] = 0;
151 
152 			//cycle through all vesa modes, then screen-buffer mode
153 		getvalidvesamodes();
154 		if (vidoption == 1)
155 		{
156 			for(i=0;i<validmodecnt;i++)
157 				if ((validmodexdim[i] == xdim) && (validmodeydim[i] == ydim))
158 				{
159 					if (i == validmodecnt-1)
160 						setgamemode(2,320L,200L);
161 					else
162 						setgamemode(1,validmodexdim[i+1],validmodeydim[i+1]);
163 					break;
164 				}
165 		}
166 		else if (validmodecnt > 0)
167 			setgamemode(1,validmodexdim[0],validmodeydim[0]);
168 
169 		inittimer42();  //Must init here because VESA 0x4F02 messes timer 2
170 	}
171 
172 	if (keystatus[0x2a]|keystatus[0x36])
173 	{
174 		if (keystatus[0xcf]) hang = max(hang-1,-182);
175 		if (keystatus[0xc7]) hang = min(hang+1,182);
176 	}
177 	else
178 	{
179 		if (keystatus[0xcf]) hang = max(hang-8,-182);
180 		if (keystatus[0xc7]) hang = min(hang+8,182);
181 	}
182 	if (keystatus[0x4c]) { hang = 0; horiz = 100; }
183 	if (hang != 0)
184 	{
185 		walock[4094] = 255;
186 		if (waloff[4094] == 0) allocache(&waloff[4094],240L*384L,&walock[4094]);
187 		setviewtotile(4094,240L,384L);
188 
189 		cosang = sintable[(hang+512)&2047];
190 		sinang = sintable[hang&2047];
191 
192 		dx = dmulscale1(320,cosang,200,sinang); mindx = dx;
193 		dy = dmulscale1(-200,cosang,320,sinang);
194 		horizval1 = dy*(320>>1)/dx-1;
195 
196 		dx = dmulscale1(320,cosang,-200,sinang); mindx = min(dx,mindx);
197 		dy = dmulscale1(200,cosang,320,sinang);
198 		horizval2 = dy*(320>>1)/dx+1;
199 
200 		daviewingrange = scale(65536,16384*(xdim>>1),mindx-16);
201 		daaspect = scale(daviewingrange,scale(320,tilesizx[4094],tilesizy[4094]),horizval2+6-horizval1);
202 		setaspect(daviewingrange,scale(daaspect,ydim*320,xdim*200));
203 		horiz = 100-divscale15(horizval1+horizval2,daviewingrange);
204 	}
205 }
206 
207 #define MAXVOXMIPS 5
208 extern char *voxoff[][MAXVOXMIPS];
ExtAnalyzeSprites(void)209 void ExtAnalyzeSprites(void)
210 {
211 	long i, *longptr;
212 	spritetype *tspr;
213 
214 	for(i=0,tspr=&tsprite[0];i<spritesortcnt;i++,tspr++)
215 	{
216 		switch(tspr->picnum)
217 		{
218 			case PLAYER:
219 				if (!voxoff[0][0]) qloadkvx(0L,"voxel000.kvx");
220 				tspr->cstat |= 48;
221 				longptr = (long *)voxoff[0][0];
222 				tspr->xrepeat = scale(tspr->xrepeat,56,longptr[2]);
223 				tspr->yrepeat = scale(tspr->yrepeat,56,longptr[2]);
224 				tspr->picnum = 0;
225 				tspr->shade -= 6;
226 				break;
227 			case BROWNMONSTER:
228 				if (!voxoff[1][0]) qloadkvx(1L,"voxel001.kvx");
229 				tspr->cstat |= 48;
230 				tspr->picnum = 1;
231 				break;
232 		}
233 
234 		tspr->shade += 6;
235 		if (sector[tspr->sectnum].ceilingstat&1)
236 			tspr->shade += sector[tspr->sectnum].ceilingshade;
237 		else
238 			tspr->shade += sector[tspr->sectnum].floorshade;
239 	}
240 }
241 
242 static char timerinited = 0;
ExtCheckKeys(void)243 void ExtCheckKeys(void)
244 {
245 	long i, j, p, y, dx, dy, cosang, sinang, bufplc, tsizy, tsizyup15;
246 
247 	if (qsetmode == 200)    //In 3D mode
248 	{
249 		if (hang != 0)
250 		{
251 			bufplc = waloff[4094]+(mulscale16(horiz-100,xdimenscale)+(tilesizx[4094]>>1))*tilesizy[4094];
252 			setviewback();
253 			cosang = sintable[(hang+512)&2047];
254 			sinang = sintable[hang&2047];
255 			dx = dmulscale1(xdim,cosang,ydim,sinang);
256 			dy = dmulscale1(-ydim,cosang,xdim,sinang);
257 
258 			tsizy = tilesizy[4094];
259 			tsizyup15 = (tsizy<<15);
260 			dx = mulscale14(dx,daviewingrange);
261 			dy = mulscale14(dy,daaspect);
262 			sinang = mulscale14(sinang,daviewingrange);
263 			cosang = mulscale14(cosang,daaspect);
264 			p = ylookup[windowy1]+frameplace+windowx2+1;
265 			for(y=windowy1;y<=windowy2;y++)
266 			{
267 				i = divscale16(tsizyup15,dx);
268 				stretchhline(0,(xdim>>1)*i+tsizyup15,xdim>>2,i,mulscale32(i,dy)*tsizy+bufplc,p);
269 				dx -= sinang; dy += cosang; p += ylookup[1];
270 			}
271 			walock[4094] = 1;
272 
273 			sprintf(tempbuf,"%ld",(hang*180)>>10);
274 			printext256(0L,8L,31,-1,tempbuf,1);
275 		}
276 
277 		if (keystatus[0xa]) setaspect(viewingrange+(viewingrange>>8),yxaspect+(yxaspect>>8));
278 		if (keystatus[0xb]) setaspect(viewingrange-(viewingrange>>8),yxaspect-(yxaspect>>8));
279 		if (keystatus[0xc]) setaspect(viewingrange,yxaspect-(yxaspect>>8));
280 		if (keystatus[0xd]) setaspect(viewingrange,yxaspect+(yxaspect>>8));
281 
282 		if (!timerinited)
283 		{
284 			timerinited = 1;
285 			inittimer42();  //Must init here because VESA 0x4F02 messes timer 2
286 		}
287 		i = totalclock-ototalclock; ototalclock += i;
288 		j = ofinetotalclock-gettimer42(); ofinetotalclock -= j;
289 		i = ((i*(1193181/120)-(j&65535)+32768)&0xffff0000)+(j&65535);
290 		if (i) { frameval[framecnt&(AVERAGEFRAMES-1)] = 11931810/i; framecnt++; }
291 			//Print MAX FRAME RATE
292 		i = frameval[(framecnt-1)&(AVERAGEFRAMES-1)];
293 		for(j=AVERAGEFRAMES-1;j>0;j--) i = max(i,frameval[j]);
294 		averagefps = ((averagefps*3+i)>>2);
295 		sprintf(tempbuf,"%ld.%ld",averagefps/10,averagefps%10);
296 		printext256(0L,0L,31,-1,tempbuf,1);
297 
298 		editinput();
299 	}
300 	else
301 	{
302 		timerinited = 0;
303 	}
304 }
305 
ExtCleanUp(void)306 void ExtCleanUp(void)
307 {
308 }
309 
ExtLoadMap(const char * mapname)310 void ExtLoadMap(const char *mapname)
311 {
312 }
313 
ExtSaveMap(const char * mapname)314 void ExtSaveMap(const char *mapname)
315 {
316 }
317 
ExtGetSectorCaption(short sectnum)318 const char *ExtGetSectorCaption(short sectnum)
319 {
320 	if ((sector[sectnum].lotag|sector[sectnum].hitag) == 0)
321 	{
322 		tempbuf[0] = 0;
323 	}
324 	else
325 	{
326 		sprintf(tempbuf,"%hu,%hu",(unsigned short)sector[sectnum].hitag,
327 										  (unsigned short)sector[sectnum].lotag);
328 	}
329 	return(tempbuf);
330 }
331 
ExtGetWallCaption(short wallnum)332 const char *ExtGetWallCaption(short wallnum)
333 {
334 	if ((wall[wallnum].lotag|wall[wallnum].hitag) == 0)
335 	{
336 		tempbuf[0] = 0;
337 	}
338 	else
339 	{
340 		sprintf(tempbuf,"%hu,%hu",(unsigned short)wall[wallnum].hitag,
341 										  (unsigned short)wall[wallnum].lotag);
342 	}
343 	return(tempbuf);
344 }
345 
ExtGetSpriteCaption(short spritenum)346 const char *ExtGetSpriteCaption(short spritenum)
347 {
348 	if ((sprite[spritenum].lotag|sprite[spritenum].hitag) == 0)
349 	{
350 		tempbuf[0] = 0;
351 	}
352 	else
353 	{
354 		sprintf(tempbuf,"%hu,%hu",(unsigned short)sprite[spritenum].hitag,
355 										  (unsigned short)sprite[spritenum].lotag);
356 	}
357 	return(tempbuf);
358 }
359 
360 //printext16 parameters:
361 //printext16(long xpos, long ypos, short col, short backcol,
362 //           char name[82], char fontsize)
363 //  xpos 0-639   (top left)
364 //  ypos 0-479   (top left)
365 //  col 0-15
366 //  backcol 0-15, -1 is transparent background
367 //  name
368 //  fontsize 0=8*8, 1=3*5
369 
370 //drawline16 parameters:
371 // drawline16(long x1, long y1, long x2, long y2, char col)
372 //  x1, x2  0-639
373 //  y1, y2  0-143  (status bar is 144 high, origin is top-left of STATUS BAR)
374 //  col     0-15
375 
ExtShowSectorData(short sectnum)376 void ExtShowSectorData(short sectnum)   //F5
377 {
378 	if (qsetmode == 200)    //In 3D mode
379 	{
380 	}
381 	else
382 	{
383 		clearmidstatbar16();             //Clear middle of status bar
384 
385 		sprintf(tempbuf,"Sector %d",sectnum);
386 		printext16(8,32,11,-1,tempbuf,0);
387 
388 		printext16(8,48,11,-1,"8*8 font: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789",0);
389 		printext16(8,56,11,-1,"3*5 font: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789",1);
390 
391 		drawline16(320,68,344,80,4);       //Draw house
392 		drawline16(344,80,344,116,4);
393 		drawline16(344,116,296,116,4);
394 		drawline16(296,116,296,80,4);
395 		drawline16(296,80,320,68,4);
396 	}
397 }
398 
ExtShowWallData(short wallnum)399 void ExtShowWallData(short wallnum)       //F6
400 {
401 	if (qsetmode == 200)    //In 3D mode
402 	{
403 	}
404 	else
405 	{
406 		clearmidstatbar16();             //Clear middle of status bar
407 
408 		sprintf(tempbuf,"Wall %d",wallnum);
409 		printext16(8,32,11,-1,tempbuf,0);
410 	}
411 }
412 
ExtShowSpriteData(short spritenum)413 void ExtShowSpriteData(short spritenum)   //F6
414 {
415 	if (qsetmode == 200)    //In 3D mode
416 	{
417 	}
418 	else
419 	{
420 		clearmidstatbar16();             //Clear middle of status bar
421 
422 		sprintf(tempbuf,"Sprite %d",spritenum);
423 		printext16(8,32,11,-1,tempbuf,0);
424 	}
425 }
426 
ExtEditSectorData(short sectnum)427 void ExtEditSectorData(short sectnum)    //F7
428 {
429 	short nickdata;
430 
431 	if (qsetmode == 200)    //In 3D mode
432 	{
433 			//Ceiling
434 		if (searchstat == 1)
435 			sector[searchsector].ceilingpicnum++;   //Just a stupid example
436 
437 			//Floor
438 		if (searchstat == 2)
439 			sector[searchsector].floorshade++;      //Just a stupid example
440 	}
441 	else                    //In 2D mode
442 	{
443 		sprintf(tempbuf,"Sector (%ld) Nick's variable: ",sectnum);
444 		nickdata = 0;
445 		nickdata = getnumber16(tempbuf,nickdata,65536L);
446 
447 		printmessage16("");              //Clear message box (top right of status bar)
448 		ExtShowSectorData(sectnum);
449 	}
450 }
451 
ExtEditWallData(short wallnum)452 void ExtEditWallData(short wallnum)       //F8
453 {
454 	short nickdata;
455 
456 	if (qsetmode == 200)    //In 3D mode
457 	{
458 	}
459 	else
460 	{
461 		sprintf(tempbuf,"Wall (%ld) Nick's variable: ",wallnum);
462 		nickdata = 0;
463 		nickdata = getnumber16(tempbuf,nickdata,65536L);
464 
465 		printmessage16("");              //Clear message box (top right of status bar)
466 		ExtShowWallData(wallnum);
467 	}
468 }
469 
ExtEditSpriteData(short spritenum)470 void ExtEditSpriteData(short spritenum)   //F8
471 {
472 	short nickdata;
473 
474 	if (qsetmode == 200)    //In 3D mode
475 	{
476 	}
477 	else
478 	{
479 		sprintf(tempbuf,"Sprite (%ld) Nick's variable: ",spritenum);
480 		nickdata = 0;
481 		nickdata = getnumber16(tempbuf,nickdata,65536L);
482 		printmessage16("");
483 
484 		printmessage16("");              //Clear message box (top right of status bar)
485 		ExtShowSpriteData(spritenum);
486 	}
487 }
488 
faketimerhandler()489 faketimerhandler()
490 {
491 }
492 
493 	//Just thought you might want my getnumber16 code
494 /*
495 getnumber16(char namestart[80], short num, long maxnumber)
496 {
497 	char buffer[80];
498 	long j, k, n, danum, oldnum;
499 
500 	danum = (long)num;
501 	oldnum = danum;
502 	while ((keystatus[0x1c] != 2) && (keystatus[0x1] == 0))  //Enter, ESC
503 	{
504 		sprintf(&buffer,"%s%ld_ ",namestart,danum);
505 		printmessage16(buffer);
506 
507 		for(j=2;j<=11;j++)                //Scan numbers 0-9
508 			if (keystatus[j] > 0)
509 			{
510 				keystatus[j] = 0;
511 				k = j-1;
512 				if (k == 10) k = 0;
513 				n = (danum*10)+k;
514 				if (n < maxnumber) danum = n;
515 			}
516 		if (keystatus[0xe] > 0)    // backspace
517 		{
518 			danum /= 10;
519 			keystatus[0xe] = 0;
520 		}
521 		if (keystatus[0x1c] == 1)   //L. enter
522 		{
523 			oldnum = danum;
524 			keystatus[0x1c] = 2;
525 			asksave = 1;
526 		}
527 	}
528 	keystatus[0x1c] = 0;
529 	keystatus[0x1] = 0;
530 	return((short)oldnum);
531 }
532 */
533