1 /*
2  *  Cursor motion stuff to simulate a "no refresh" version of curses
3  */
4 #include	"rogue.h"
5 #include	"curses.h"
6 
7 char *sbrk();
8 /*
9  *  Globals for curses
10  */
11 int LINES=25, COLS=80;
12 int is_saved = FALSE;
13 int iscuron = TRUE;
14 int ch_attr = 0x7;
15 int old_page_no;
16 int no_check = FALSE;
17 
18 int scr_ds=0xB800;
19 int svwin_ds;
20 
21 char *savewin;
22 int scr_type = -1;
23 int tab_size = 8;
24 int page_no = 0;
25 
26 #define MAXATTR 17
27 byte color_attr[] = {
28     7,  /*  0 normal         */
29     2,  /*  1 green          */
30     3,  /*  2 cyan           */
31     4,  /*  3 red            */
32     5,  /*  4 magenta        */
33     6,  /*  5 brown          */
34     8,  /*  6 dark grey      */
35     9,  /*  7 light blue     */
36     10, /*  8 light green    */
37     12, /*  9 light red      */
38     13, /* 10 light magenta  */
39     14, /* 11 yellow         */
40     15, /* 12 uline          */
41     1,  /* 13 blue           */
42     112,/* 14 reverse        */
43     15, /* 15 high intensity */
44    112, /* bold				 */
45     0   /* no more           */
46 } ;
47 
48 byte monoc_attr[] = {
49       7,  /*  0 normal         */
50      7,  /*  1 green          */
51      7,  /*  2 cyan           */
52      7,  /*  3 red            */
53      7,  /*  4 magenta        */
54      7,  /*  5 brown          */
55      7,  /*  6 dark grey      */
56      7,  /*  7 light blue     */
57      7,  /*  8 light green    */
58      7,  /*  9 light red      */
59      7,  /* 10 light magenta  */
60      7,  /* 11 yellow         */
61      17,  /* 12 uline          */
62      7,  /* 13 blue           */
63     120,  /* 14 reverse        */
64      7,  /* 15 white/hight    */
65     120,  /* 16 bold		   */
66     0     /* no more           */
67 } ;
68 
69 byte *at_table;
70 
71 int c_row, c_col;   /*  Save cursor positions so we don't ask dos */
72 int scr_row[25];
73 
74 byte dbl_box[BX_SIZE] = {
75 	0xc9, 0xbb, 0xc8, 0xbc, 0xba, 0xcd, 0xcd
76 };
77 
78 byte sng_box[BX_SIZE] = {
79 	0xda, 0xbf, 0xc0, 0xd9, 0xb3, 0xc4, 0xc4
80 };
81 
82 byte fat_box[BX_SIZE] = {
83 	0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdf, 0xdc
84 };
85 
86 byte spc_box[BX_SIZE] = {
87 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
88 };
89 
90 /*
91  * clear screen
92  */
93 clear()
94 {
95 	if (scr_ds == svwin_ds)
96 		wsetmem(savewin, LINES*COLS, 0x0720);
97 	else
98 		blot_out(0,0,LINES-1,COLS-1);
99 }	
100 
101 
102 /*
103  *  Turn cursor on and off
104  */
105 cursor(ison)
106 	bool ison;
107 {
108 	register int oldstate;
109 	register int w_state;
110 
111 
112 	if (iscuron == ison)
113 		return ison;
114 	oldstate = iscuron;
115 	iscuron = ison;
116 	
117 	regs->ax = 0x100;
118 	if (ison)
119 	{
120 		regs->cx = (is_color ? 0x607 : 0xb0c);
121 		swint(SW_SCR, regs);
122 		move(c_row, c_col);
123 	}
124 	else
125 	{
126 		regs->cx = 0xf00;
127 		swint(SW_SCR, regs);
128 	}
129 	return(oldstate);
130 }
131 
132 
133 /*
134  * get curent cursor position
135  */
136 getrc(rp,cp)
137 	int *rp, *cp;
138 {
139 	*rp = c_row;
140 	*cp = c_col;
141 }
142 
143 real_rc(pn, rp,cp)
144 	int *rp, *cp;
145 {
146 	/*
147 	 * pc bios: read current cursor position
148 	 */
149 	regs->ax = 0x300;
150 	regs->bx = pn << 8;
151 
152 	swint(SW_SCR, regs);
153 
154 	*rp = regs->dx >> 8;
155 	*cp = regs->dx & 0xff;
156 }
157 
158 /*
159  *	clrtoeol
160  */
161 clrtoeol()
162 {
163 	int r,c;
164 
165 	if (scr_ds == svwin_ds)
166 		return;
167 	getrc(&r,&c);
168 	blot_out(r,c,r,COLS-1);
169 }
170 
171 mvaddstr(r,c,s)
172 	int r,c;
173 	char *s;
174 {
175 	move(r, c);
176 	addstr(s);
177 }
178 
179 mvaddch(r,c,chr)
180 	int r, c;
181 	char chr;
182 {
183 	move(r, c);
184 	addch(chr);
185 }
186 
187 mvinch(r, c)
188 	int r, c;
189 {	
190 	move(r, c);
191 	return(curch()&0xff);
192 }
193 
194 /*
195  * put the character on the screen and update the
196  * character position
197  */
198 
199 addch(chr)
200 	byte chr;
201 {
202 	int r, c;
203     register int newc, newr;
204 	byte old_attr;
205 
206 	old_attr = ch_attr;
207 
208 	if (at_table == color_attr)
209 	{
210 	    /* if it is inside a room */
211 	    if (ch_attr == 7)
212 		switch(chr)
213 		{
214 		    case DOOR:
215 		    case VWALL:
216 		    case HWALL:
217 		    case ULWALL:
218 		    case URWALL:
219 		    case LLWALL:
220 		    case LRWALL:
221 		        ch_attr = 6;  /* brown */
222 		        break;
223 		    case FLOOR:
224 		    	ch_attr = 10;  /* light green */
225 		    	break;
226 		    case STAIRS:
227 		        ch_attr = 160; /* black on green*/
228 		        break;
229 		    case TRAP:
230 		        ch_attr = 5;  /* magenta */
231 		    	break;
232 		    case GOLD:
233 		    case PLAYER:
234 		        ch_attr = 14;  /* yellow */
235 		        break;
236 		    case POTION:
237 		    case SCROLL:
238 		    case STICK:
239 		    case ARMOR:
240 		    case AMULET:
241 		    case RING:
242 		    case WEAPON:
243 		    	ch_attr = 9;
244 		    	break;
245 		    case FOOD:
246 		        ch_attr = 4;
247 		        break;
248 		}
249 		/* if inside a passage or a maze */
250 	    else if (ch_attr == 112)
251 		switch(chr)
252 		{
253 		    case FOOD:
254 		        ch_attr = 116;   /* red */
255 		        break;
256 		    case GOLD:
257 		    case PLAYER:
258 		        ch_attr = 126;  /* yellow on white */
259 		        break;
260 		    case POTION:
261 		    case SCROLL:
262 		    case STICK:
263 		    case ARMOR:
264 		    case AMULET:
265 		    case RING:
266 		    case WEAPON:
267 		    	ch_attr = 113;    /* blue on white */
268 		    	break;
269 		}
270 	    else if (ch_attr == 15 && chr == STAIRS)
271 	        ch_attr = 160;
272 	}
273 	
274 	getrc(&r,&c);
275 	if (chr == '\n') {
276 		if (r == LINES-1) {
277 			scroll_up(0, LINES-1, 1);
278 			move(LINES-1, 0);
279 		} else
280 			move(r+1, 0);
281 			ch_attr = old_attr;
282 		return c_row;
283 	}
284 	putchr(chr);
285 	move(r,c+1);
286 	ch_attr = old_attr;
287 	/*
288 	 * if you have gone of the screen scroll the whole window
289 	 */
290     return(c_row);
291 }
292 
293 addstr(s)
294 	char *s;
295 {
296 	while(*s)
297 		addch(*s++);
298 }	
299 
300 set_attr(bute)
301 	int bute;
302 {
303 	if (bute < MAXATTR)
304 		ch_attr = at_table[bute];
305 	else
306 		ch_attr = bute;
307 }	
308 
309 error(mline,msg,a1,a2,a3,a4,a5)
310 	int mline;
311 	char *msg;
312 	int a1,a2,a3,a4,a5;
313 {
314 	int row, col;
315 
316 	getrc(&row,&col);
317 	move(mline,0);
318 	clrtoeol();
319 	printw(msg,a1,a2,a3,a4,a5);
320 	move(row,col);
321 }
322 
323 /*
324  * Called when rogue runs to move our cursor to be where DOS thinks
325  * the cursor is
326  */
327 
328 set_cursor()
329 {
330 /*
331 	regs->ax = 15 << 8;
332 	swint(SW_SCR, regs);
333 	real_rc(regs->bx >> 8, &c_row, &c_col);
334 */
335 }
336 
337 /*
338  *  winit(win_name):
339  *		initialize window -- open disk window
340  *						  -- determine type of moniter
341  *						  -- determine screen memory location for dma
342  */
343 winit(drive)
344 	char drive;	
345 {
346 	register int i, cnt;
347 	extern int _dsval;
348 
349 	/*
350 	 * Get monitor type
351 	 */
352 	regs->ax = 15 << 8;
353 	swint(SW_SCR, regs);
354 	old_page_no = regs->bx >> 8;
355 	scr_type = regs->ax = 0xff & regs->ax;
356 	/*
357 	 * initialization is any good because restarting game
358 	 * has old values!!!
359 	 * So reassign defaults
360 	 */
361 	LINES   =  25;
362 	COLS    =  80;
363 	scr_ds  =  0xB800;
364 	at_table = monoc_attr;
365 
366 	switch (scr_type) {
367 		/*
368 		 *  It is a TV
369 		 */
370 		case 1:
371 			at_table = color_attr;
372 		case 0:
373 			COLS = 40;
374 			break;
375 
376 		/*
377 		 * Its a high resolution monitor
378 		 */
379 		case 3:
380 			at_table = color_attr;
381 		case 2:
382 			break;
383 		case 7:
384 			scr_ds = 0xB000;
385 			no_check = TRUE;
386 			break;
387 		/*
388 		 * Just to save text space lets eliminate these
389 		 *
390 		case 4:
391 		case 5:
392 		case 6:
393 		    move(24,0);
394 		    fatal("Program can't be run in graphics mode");
395 	     */
396 		default:
397 			move(24,0);
398 			fatal("Unknown screen type (%d)",regs->ax);
399 	}
400 	/*
401 	 * Read current cursor position
402 	 */
403 	real_rc(old_page_no, &c_row, &c_col);
404 	if ((savewin = sbrk(4096)) == -1) {
405 		svwin_ds = -1;
406 		savewin = (char *) _flags;
407 		if (scr_type == 7)
408 			fatal(no_mem);
409 	} else {
410 		savewin = (char *) (((int) savewin + 0xf) & 0xfff0);
411 		svwin_ds = (((int) savewin >> 4) & 0xfff) + _dsval;
412 	}
413 	for (i = 0, cnt = 0; i < 25; cnt += 2*COLS, i++)
414 		scr_row[i] = cnt;
415 	newmem(2);
416 	switch_page(3);
417 	if (old_page_no != page_no)
418 		clear();
419 	move(c_row, c_col);
420 	if (isjr())
421 		no_check = TRUE;
422 }
423 
424 forcebw()
425 {
426 	at_table = monoc_attr;
427 }
428 
429 /*
430  *  wdump(windex)
431  *		dump the screen off to disk, the window is save so that
432  *		it can be retieved using windex
433  */
434 wdump()
435 {
436 	sav_win();
437     dmain(savewin,LINES*COLS,scr_ds,0);
438     is_saved = TRUE;
439 }
440 
441 sav_win()
442 {
443 	if (savewin == _flags)
444 		dmaout(savewin,LINES*COLS,0xb800,8192);
445 	return(savewin);
446 }
447 
448 res_win()
449 {
450 	if (savewin == _flags)
451 		dmain(savewin,LINES*COLS,0xb800,8192);
452 }
453 
454 /*
455  *	wrestor(windex):
456  *		restor the window saved on disk
457  */
458 wrestor()
459 {
460 	dmaout(savewin,LINES*COLS,scr_ds,0);
461 	res_win();
462 	is_saved = FALSE;
463 }	
464 
465 /*
466  * wclose()
467  *   close the window file
468  */
469 wclose()
470 {
471 
472 	/*
473 	 * Restor cursor (really you want to restor video state, but be carefull)
474  	 */
475  	if (scr_type >= 0)
476 		cursor(TRUE);
477 	if (page_no != old_page_no)
478 		switch_page(old_page_no);
479 }
480 
481 /*
482  *  Some general drawing routines
483  */
484 
485 box(ul_r, ul_c, lr_r, lr_c)
486 {
487 	vbox(dbl_box, ul_r, ul_c, lr_r, lr_c);
488 }
489 
490 /*
491  *  box:  draw a box using given the
492  *        upper left coordinate and the lower right
493  */
494 
495 vbox(box, ul_r,ul_c,lr_r,lr_c)
496 	byte box[BX_SIZE];
497 	int ul_r,ul_c,lr_r,lr_c;
498 {
499 	register int i, wason;
500 	int r,c;
501 
502 	wason = cursor(FALSE);
503 	getrc(&r,&c);
504 
505 	/*
506 	 * draw horizontal boundry
507 	 */
508 	move(ul_r, ul_c+1);
509 	repchr(box[BX_HT], i = (lr_c - ul_c - 1));
510 	move(lr_r, ul_c+1);
511 	repchr(box[BX_HB], i);
512 	/*
513 	 * draw vertical boundry
514 	 */
515 	for (i=ul_r+1;i<lr_r;i++) {
516 		mvaddch(i,ul_c,box[BX_VW]);
517 		mvaddch(i,lr_c,box[BX_VW]);
518 	}
519 	/*
520 	 * draw corners
521 	 */
522 	mvaddch(ul_r,ul_c,box[BX_UL]);
523 	mvaddch(ul_r,lr_c,box[BX_UR]);
524 	mvaddch(lr_r,ul_c,box[BX_LL]);
525 	mvaddch(lr_r,lr_c,box[BX_LR]);
526 
527 	move(r,c);
528 	cursor(wason);
529 }	
530 
531 /*
532  * center a string according to how many columns there really are
533  */
534 center(row,string)
535 	int row;
536 	char *string;
537 {
538 	mvaddstr(row,(COLS-strlen(string))/2,string);
539 }
540 	
541 
542 /*
543  * printw(Ieeeee)
544  */
545 printw(msg,a1,a2,a3,a4,a5,a6,a7,a8)
546 	char *msg;
547 	int a1, a2, a3, a4, a5, a6, a7, a8;
548 {
549 	char pwbuf[132];
550 	sprintf(pwbuf,msg,a1,a2,a3,a4,a5,a6,a7,a8);
551 	addstr(pwbuf);
552 }
553 
554 scroll_up(start_row,end_row,nlines)
555 	int start_row,end_row,nlines;
556 {
557 	regs->ax = 0x600 + nlines;
558 	regs->bx = 0x700;
559 	regs->cx = start_row << 8;
560 	regs->dx = (end_row << 8) + COLS - 1;
561 	swint(SW_SCR,regs);
562 	move(end_row,c_col);
563 }
564 scroll_dn(start_row,end_row,nlines)
565 	int start_row,end_row,nlines;
566 {
567 	regs->ax = 0x700 + nlines;
568 	regs->bx = 0x700;
569 	regs->cx = start_row << 8;
570 	regs->dx = (end_row << 8) + COLS - 1;
571 	swint(SW_SCR,regs);
572 	move(start_row,c_col);
573 }
574 
575 scroll()
576 {
577 	scroll_up(0,24,1);
578 }
579 
580 
581 
582 /*
583  * blot_out region
584  *    (upper left row, upper left column)
585  *	  (lower right row, lower right column)
586  */
587 blot_out(ul_row,ul_col,lr_row,lr_col)
588 {
589 	regs->ax = 0x600;
590 	regs->bx = 0x700;
591 	regs->cx = (ul_row<<8) + ul_col;
592 	regs->dx = (lr_row<<8) + lr_col;
593 	swint(SW_SCR,regs);
594 	move(ul_row,ul_col);
595 }
596 
597 repchr(chr,cnt)
598 	int chr, cnt;
599 {
600 	while(cnt-- > 0) {
601 		putchr(chr);
602 		c_col++;
603 	}
604 }
605 
606 /*
607  * try to fixup screen after we get a control break
608  */
609 fixup()
610 {
611     blot_out(c_row,c_col,c_row,c_col+1);
612 }
613 
614 /*
615  * Clear the screen in an interesting fashion
616  */
617 
618 implode()
619 {
620 	int j, delay, r, c, cinc = COLS/10/2, er, ec;
621 
622 	er = (COLS == 80 ? LINES-3 : LINES-4);
623 	/*
624 	 * If the curtain is down, just clear the memory
625 	 */
626 	if (scr_ds == svwin_ds) {
627 		wsetmem(savewin, (er + 1) * COLS, 0x0720);
628 		return;
629 	}
630 	delay = scr_type == 7 ? 500 : 10;
631 	for (r = 0,c = 0,ec = COLS-1; r < 10; r++,c += cinc,er--,ec -= cinc) {
632 		vbox(sng_box, r, c, er, ec);
633 		for (j = delay; j--; )
634 			;
635 		for (j = r+1; j <= er-1; j++) {
636 			move(j, c+1); repchr(' ', cinc-1);
637 			move(j, ec-cinc+1); repchr(' ', cinc-1);
638 		}
639 		vbox(spc_box, r, c, er, ec);
640 	}
641 }
642 
643 /*
644  * drop_curtain:
645  *	Close a door on the screen and redirect output to the temporary buffer
646  */
647 static int old_ds;
648 drop_curtain()
649 {
650 	register int r, c, j, delay;
651 
652 	if (svwin_ds == -1)
653 		return;
654 	old_ds = scr_ds;
655 	dmain(savewin, LINES * COLS, scr_ds, 0);
656 	cursor(FALSE);
657 	delay = (scr_type == 7 ? 3000 : 2000);
658 	green();
659 	vbox(sng_box, 0, 0, LINES-1, COLS-1);
660 	yellow();
661 	for (r = 1; r < LINES-1; r++) {
662 		move(r, 1);
663 		repchr(0xb1, COLS-2);
664 		for (j = delay; j--; )
665 			;
666 	}
667 	scr_ds = svwin_ds;
668 	move(0,0);
669 	standend();
670 }
671 
672 raise_curtain()
673 {
674 	register int i, j, o, delay;
675 
676 	if (svwin_ds == -1)
677 		return;
678 	scr_ds = old_ds;
679 	delay = (scr_type == 7 ? 3000 : 2000);
680 	for (i = 0, o = (LINES-1)*COLS*2; i < LINES; i++, o -= COLS*2) {
681 		dmaout(savewin + o, COLS, scr_ds, o);
682 		for (j = delay; j--; )
683 			;
684 	}
685 }
686 
687 switch_page(pn)
688 {
689 	register int pgsize;
690 
691 	if (scr_type == 7) {
692 		page_no = 0;
693 		return;
694 	}
695 	if (COLS == 40)
696 		pgsize = 2048;
697 	else
698 		pgsize = 4096;
699 	regs->ax = 0x0500 | pn;
700 	swint(SW_SCR, regs);
701 	scr_ds = 0xb800 + ((pgsize * pn) >> 4);
702 	page_no = pn;
703 }
704 
705 get_mode(type)
706 {
707 	struct sw_regs regs;
708 
709 	regs.ax = 0xF00;
710 	swint(SW_SCR,&regs);
711 	return 0xff & regs.ax;
712 }
713 
714 video_mode(type)
715 {
716 	struct sw_regs regs;
717 
718 	regs.ax = type;
719 	swint(SW_SCR,&regs);
720 	return regs.ax;
721 }
722 