1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <SDL.h>
5 #include <math.h>
6 #include <unistd.h>
7 #include "gfx.h"
8 
9 #define REPT_DELAY 250
10 #define REPT_RATE 33
11 
12 #define MAXBACKBUFFERS 8
13 #define KEYMAX 32
14 int numdown;
15 int downcodes[KEYMAX];
16 
17 #define MAXCODES 64
18 int codelist[MAXCODES];
19 int codeput,codetake;
20 int lastcode;
21 int vxsize,vysize;
22 
23 SDL_Surface *thescreen;
24 int stride;
25 unsigned char *videomem;
26 unsigned char locked=0;
27 unsigned short *darker,*lighter;
28 int downtime;
29 unsigned char stilldown=0;
30 
31 unsigned char *backbuffers[MAXBACKBUFFERS]={0};
32 
33 unsigned char exitflag=0;
34 
35 int sdlinout[]={
36 SDLK_0,'0',')',
37 SDLK_1,'1','!',
38 SDLK_2,'2','@',
39 SDLK_3,'3','#',
40 SDLK_4,'4','$',
41 SDLK_5,'5','%',
42 SDLK_6,'6','^',
43 SDLK_7,'7','&',
44 SDLK_8,'8','*',
45 SDLK_9,'9','(',
46 SDLK_a,'a','A',
47 SDLK_b,'b','B',
48 SDLK_c,'c','C',
49 SDLK_d,'d','D',
50 SDLK_e,'e','E',
51 SDLK_f,'f','F',
52 SDLK_g,'g','G',
53 SDLK_h,'h','H',
54 SDLK_i,'i','I',
55 SDLK_j,'j','J',
56 SDLK_k,'k','K',
57 SDLK_l,'l','L',
58 SDLK_m,'m','M',
59 SDLK_n,'n','N',
60 SDLK_o,'o','O',
61 SDLK_p,'p','P',
62 SDLK_q,'q','Q',
63 SDLK_r,'r','R',
64 SDLK_s,'s','S',
65 SDLK_t,'t','T',
66 SDLK_u,'u','U',
67 SDLK_v,'v','V',
68 SDLK_w,'w','W',
69 SDLK_x,'x','X',
70 SDLK_y,'y','Y',
71 SDLK_z,'z','Z',
72 SDLK_MINUS,'-','_',
73 SDLK_EQUALS,'=','+',
74 SDLK_LEFTBRACKET,'[','{',
75 SDLK_RIGHTBRACKET,']','}',
76 SDLK_SEMICOLON,';',':',
77 SDLK_QUOTE,'\'','"',
78 SDLK_BACKSLASH,'\\','|',
79 SDLK_SLASH,'/','?',
80 SDLK_PERIOD,'.','>',
81 SDLK_COMMA,',','<',
82 SDLK_BACKQUOTE,'`','~',
83 SDLK_BACKSPACE,8,8,
84 SDLK_TAB,9,9,
85 SDLK_DELETE,MYDELETE,MYDELETE,
86 SDLK_RETURN,13,13,
87 SDLK_F1,MYF1,MYF1,
88 SDLK_F2,MYF2,MYF2,
89 SDLK_F3,MYF3,MYF3,
90 SDLK_F4,MYF4,MYF4,
91 SDLK_F5,MYF5,MYF5,
92 SDLK_F6,MYF6,MYF6,
93 SDLK_F7,MYF7,MYF7,
94 SDLK_F8,MYF8,MYF8,
95 SDLK_F9,MYF9,MYF9,
96 SDLK_F10,MYF10,MYF10,
97 SDLK_ESCAPE,0x1b,0x1b,
98 SDLK_LEFT,MYLEFT,MYLEFT,
99 SDLK_RIGHT,MYRIGHT,MYRIGHT,
100 SDLK_UP,MYUP,MYUP,
101 SDLK_DOWN,MYDOWN,MYDOWN,
102 SDLK_PAGEUP,MYPAGEUP,MYPAGEUP|MYSHIFTED,
103 SDLK_PAGEDOWN,MYPAGEDOWN,MYPAGEDOWN|MYSHIFTED,
104 SDLK_SPACE,' ',' ',
105 SDLK_HOME,MYHOME,MYHOME,
106 SDLK_END,MYEND,MYEND,
107 SDLK_LALT,MYALTL,MYALTL,
108 SDLK_RALT,MYALTR,MYALTR,
109 SDLK_LCTRL,MYCTRLL,MYCTRLL,
110 SDLK_RCTRL,MYCTRLR,MYCTRLR,
111 SDLK_LSHIFT,MYSHIFTL,MYSHIFTL,
112 SDLK_RSHIFT,MYSHIFTR,MYSHIFTR,
113 ENDMARK
114 };
115 
mapkey(int code,int qual,int * mapped)116 void mapkey(int code,int qual,int *mapped)
117 {
118 int *list;
119 	list=sdlinout;
120 	while(*list!=ENDMARK)
121 	{
122 		if(*list==code) break;
123 		list+=3;
124 	}
125 	if(*list==ENDMARK)
126 	{
127 		*mapped=mapped[1]=-1;
128 		return;
129 	}
130 	*mapped=(qual&KMOD_SHIFT) ? list[2] : list[1];
131 	if(qual & KMOD_ALT)
132 		*mapped|=MYALTED;
133 	if(qual & KMOD_CTRL)
134 		*mapped&=0x1f;
135 	mapped[1]=list[1];
136 }
nextcode(void)137 int nextcode(void)
138 {
139 int code;
140 	if(codeput==codetake) return -1;
141 	code=codelist[codetake];
142 	codetake=(codetake+1) & (MAXCODES-1);
143 	return code;
144 }
addcode(int code)145 void addcode(int code)
146 {
147 int new;
148 	new=(codeput+1) & (MAXCODES-1);
149 	if(new==codetake) return;
150 	lastcode=code;
151 	codelist[codeput]=code;
152 	codeput=new;
153 }
markkey(int code,int mod,int status)154 void markkey(int code,int mod,int status)
155 {
156 int i;
157 int *ip;
158 int mapped[2];
159 
160 	mapkey(code,mod,mapped);
161 	code=mapped[1];
162 	if(code<0) return;
163 	if(status)
164 	{
165 		addcode(*mapped);
166 		stilldown=1;
167 		downtime=SDL_GetTicks()+REPT_DELAY;
168 		ip=downcodes;
169 		i=numdown;
170 		while(i)
171 			if(*ip++==code) break;
172 			else i--;
173 		if(!i && numdown<KEYMAX)
174 			downcodes[numdown++]=code;
175 	} else
176 	{
177 		i=numdown;
178 		ip=downcodes;
179 		while(i)
180 			if(*ip++==code)
181 			{
182 				*--ip=downcodes[--numdown];
183 				break;
184 			} else i--;
185 	}
186 
187 }
188 
checkdown(int code)189 int checkdown(int code)
190 {
191 int *p,i;
192 	i=numdown;
193 	p=downcodes;
194 	while(i--)
195 		if(*p++==code) return 1;
196 	return 0;
197 }
198 
scaninput(void)199 void scaninput(void)
200 {
201 SDL_Event event;
202 int key,mod;
203 int newtime;
204 
205 //	mousedown=0;
206 	while(SDL_PollEvent(&event))
207 	{
208 		switch(event.type)
209 		{
210 		case SDL_KEYDOWN:
211 			key=event.key.keysym.sym;
212 			mod=event.key.keysym.mod;
213 			markkey(key,mod,1);
214 			break;
215 		case SDL_KEYUP:
216 			key=event.key.keysym.sym;
217 			mod=event.key.keysym.mod;
218 			markkey(key,mod,0);
219 			stilldown=0;
220 			break;
221 		case SDL_MOUSEBUTTONUP:
222 			addcode(MYMOUSE1UP);
223 			addcode(event.button.x);
224 			addcode(event.button.y);
225 /*
226 			bs&=~(1<<event.button.button-1);
227 			mousex=event.button.x;
228 			mousey=event.button.y;
229 			mouseb=bs;
230 */
231 			break;
232 		case SDL_MOUSEBUTTONDOWN:
233 			addcode(MYMOUSE1DOWN);
234 			addcode(event.button.x);
235 			addcode(event.button.y);
236 /*
237 			mousedown=1;
238 			bs|=1<<event.button.button-1;
239 			mousex=event.button.x;
240 			mousey=event.button.y;
241 			mouseb=bs;
242 */
243 			break;
244 		case SDL_MOUSEMOTION:
245 			addcode(MYMOUSEMOVE);
246 			addcode(event.motion.x);
247 			addcode(event.motion.y);
248 /*
249 			mousex=event.motion.x;
250 			mousey=event.motion.y;
251 */
252 			break;
253 		case SDL_QUIT:
254 			exitflag = 1;
255 			break;
256 		}
257 	}
258 	if(stilldown)
259 	{
260 		newtime=SDL_GetTicks();
261 		if(newtime>downtime)
262 		{
263 			downtime+=REPT_RATE;
264 			addcode(lastcode);
265 		}
266 	}
267 }
268 
opendisplay(int sx,int sy)269 void opendisplay(int sx,int sy)
270 {
271 unsigned long videoflags;
272 int i;
273 unsigned char r,g,b;
274 
275 	vxsize=sx;
276 	vysize=sy;
277 	codeput=codetake=0;
278 	darker=malloc(65536*sizeof(unsigned short));
279 	lighter=malloc(65536*sizeof(unsigned short));
280 	if(!darker || !lighter) nomem(5);
281 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
282 	{
283 		fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
284 		exit(1);
285 	}
286 	videoflags = SDL_SWSURFACE;
287 
288 	thescreen = SDL_SetVideoMode(vxsize, vysize, 16, videoflags);
289 	if ( thescreen == NULL )
290 	{
291 		fprintf(stderr, "Couldn't set display mode: %s\n",
292 							SDL_GetError());
293 		SDL_Quit();
294 		exit(5);
295 	}
296 	stride=thescreen->pitch;
297 	videomem=(void *)thescreen->pixels;
298 //	SDL_ShowCursor(0);
299 
300 	for(i=0;i<65536;++i)
301 	{
302 		SDL_GetRGB(i,thescreen->format,&r,&g,&b);
303 		darker[i]=SDL_MapRGB(thescreen->format,r*3>>2,g*3>>2,b*3>>2);
304 		if(r>128 && g>128 && b>128)
305 			lighter[i]=SDL_MapRGB(thescreen->format,(r+255)>>1,(g+255)>>1,(b+255)>>1);
306 		else
307 			lighter[i]=i;
308 	}
309 }
310 
closedisplay(void)311 void closedisplay(void)
312 {
313 	SDL_Quit();
314 }
scrlock(void)315 void scrlock(void)
316 {
317 	if(!locked && SDL_MUSTLOCK(thescreen))
318 	{
319 		if ( SDL_LockSurface(thescreen) < 0 )
320 		{
321 			fprintf(stderr, "Couldn't lock display surface: %s\n",
322 								SDL_GetError());
323 		}
324 	}
325 	locked=1;
326 }
327 
scrunlock(void)328 void scrunlock(void)
329 {
330 	if(locked && SDL_MUSTLOCK(thescreen))
331 		SDL_UnlockSurface(thescreen);
332 	locked=0;
333 }
clear(void)334 void clear(void)
335 {
336 int i;
337 unsigned char *p;
338 	scrlock();
339 	p=videomem;
340 	i=vysize;
341 	while(i--)
342 	{
343 		memset(p,0,vxsize);
344 		p+=stride;
345 	}
346 }
copyup(void)347 void copyup(void)
348 {
349 	scrunlock();
350 	SDL_UpdateRect(thescreen, 0, 0, 0, 0);
351 }
delay(int ticks)352 void delay(int ticks)
353 {
354 	SDL_Delay(ticks);
355 }
gticks(void)356 int gticks(void)
357 {
358 	return SDL_GetTicks();
359 }
360 
361 #define IBUFFLEN 1024
362 int pcxileft=0,pcxihand=0;
363 unsigned char *pcxibuff=0,*pcxitake;
364 
pcxci()365 int pcxci()
366 {
367 	if(!pcxileft)
368 	{
369 		pcxileft=read(pcxihand,pcxibuff,IBUFFLEN);
370 
371 		if(!pcxileft) return -1;
372 		pcxitake=pcxibuff;
373 	}
374 	pcxileft--;
375 	return *pcxitake++;
376 }
pcxciinit(void)377 void pcxciinit(void)
378 {
379 	if(!pcxibuff)
380 		pcxibuff=malloc(IBUFFLEN);
381 	if(!pcxibuff) nomem(1);
382 	pcxileft=0;
383 }
384 
readpcx(char * name,surface * gs)385 int readpcx(char *name,surface *gs)
386 {
387 int xs,ys;
388 int i,j,k,n,t;
389 int totalsize;
390 int width,height;
391 int y;
392 unsigned char *bm,*lp;
393 int r,g,b;
394 int numbpp;
395 unsigned char map48[48];
396 unsigned char arow[2048];
397 int perrow;
398 int pcxbyteswide;
399 	pcxciinit();
400 	memset(gs,0,sizeof(surface));
401 	gs->format=FORMAT8;
402 	pcxihand=open(name,O_RDONLY);
403 	if(pcxihand<0)
404 		return 1;
405 	if(pcxci()!=10) {close(pcxihand);return 2;} // 10=zsoft .pcx
406 	if(pcxci()!=5) {close(pcxihand);return 3;} // version 3.0
407 	if(pcxci()!=1) {close(pcxihand);return 4;} //encoding method
408 	numbpp=pcxci();
409 //	if(numbpp!=8) {close(pcxihand);return 5;} //bpp
410 	if(numbpp!=8 && numbpp!=1) {close(pcxihand);return 5;} //bpp
411 	xs=pcxci();
412 	xs|=pcxci()<<8;
413 	ys=pcxci();
414 	ys|=pcxci()<<8;
415 	width=pcxci();
416 	width|=pcxci()<<8;
417 	height=pcxci();
418 	height|=pcxci()<<8;
419 	width=width+1-xs;
420 	height=height+1-ys;
421 	for(i=0;i<4;++i) pcxci();
422 	for(i=0;i<48;++i) map48[i]=pcxci();
423 	pcxci();
424 	n=pcxci();
425 //	if(n!=1) {close(pcxihand);return 6;} // # of planes
426 	if(numbpp==8 && n!=1) {close(pcxihand);return 6;} // # of planes
427 	pcxbyteswide=pcxci();
428 	pcxbyteswide|=pcxci()<<8;
429 	perrow=pcxbyteswide*n;
430 	i=pcxci();
431 	i|=pcxci()<<8;
432 //	if(i!=1) {close(ihand);return 7;} // 1=color/bw,2=grey
433 	for(i=0;i<58;++i) pcxci();
434 	totalsize=height*width;
435 	bm=malloc(totalsize);
436 	if(!bm) {close(pcxihand);return 8;} // no memory
437 	memset(bm,0,totalsize);
438 	gs->pic=bm;
439 	gs->xsize=width;
440 	gs->ysize=height;
441 
442 	lp=bm;
443 	for(y=0;y<height;++y)
444 	{
445 		i=0;
446 		while(i<perrow)
447 		{
448 			j=pcxci();
449 			if(j<0xc0)
450 			{
451 				arow[i++]=j;
452 			} else
453 			{
454 				j&=0x3f;
455 				k=pcxci();
456 				while(j-- && i<perrow)
457 				{
458 					arow[i++]=k;
459 				}
460 			}
461 		}
462 		if(numbpp==8)
463 			memcpy(lp,arow,width);
464 		else
465 		{
466 			for(t=0;t<n;++t)
467 			{
468 				i=t*pcxbyteswide;
469 				j=0;
470 				while(j<width)
471 				{
472 					k=arow[i++] | 256;
473 					while(!(k&0x10000) && j<width)
474 					{
475 						if(k&0x80) lp[j]|=1<<t;
476 						k<<=1;
477 						++j;
478 					}
479 				}
480 			}
481 		}
482 		lp+=width;
483 	}
484 	if(numbpp==8)
485 	{
486 		lseek(pcxihand,-0x300,SEEK_END);
487 		pcxileft=0;
488 		for(i=0;i<256;++i)
489 		{
490 			r=pcxci();
491 			g=pcxci();
492 			b=pcxci();
493 			gs->rgb[i]=SDL_MapRGB(thescreen->format,r,g,b);
494 		}
495 	} else
496 	{
497 		for(i=0,j=0;i<16;++i)
498 		{
499 			r=map48[j++];
500 			g=map48[j++];
501 			b=map48[j++];
502 			gs->rgb[i]=SDL_MapRGB(thescreen->format,r,g,b);
503 		}
504 	}
505 	close(pcxihand);
506 	return 0;
507 }
gstoback(int destx,int desty,surface * gs,int sourcex,int sourcey,int sizex,int sizey)508 void gstoback(int destx,int desty,surface *gs,int sourcex,int sourcey,int sizex,int sizey)
509 {
510 unsigned short *ps;
511 unsigned char *p;
512 int i;
513 
514 	if(destx>=vxsize || desty>=vysize) return;
515 	if(destx<0)
516 	{
517 		sourcex-=destx;
518 		sizex+=destx;
519 		destx=0;
520 	}
521 	if(desty<0)
522 	{
523 		sourcey-=desty;
524 		sizey+=desty;
525 		desty=0;
526 	}
527 	if(destx+sizex>vxsize)
528 		sizex=vxsize-destx;
529 	if(desty+sizey>vysize)
530 		sizey=vysize-desty;
531 	p=gs->pic+sourcex+sourcey*gs->xsize;
532 	ps=(void *)(videomem+stride*desty+(destx<<1));
533 	while(sizey--)
534 	{
535 		i=sizex;
536 		while(i--)
537 			*ps++=gs->rgb[*p++];
538 		ps = (void *)((char *)ps + stride-sizex-sizex);
539 		p+=gs->xsize-sizex;
540 	}
541 }
rgbdot(unsigned int x,unsigned int y,unsigned char r,unsigned char g,unsigned char b)542 void rgbdot(unsigned int x,unsigned int y,unsigned char r,unsigned char g,unsigned char b)
543 {
544 	if(x<vxsize && y<vysize)
545 		*(unsigned short *)(videomem+y*stride+x+x)=
546 			SDL_MapRGB(thescreen->format,r,g,b);
547 }
eraserect(int x,int y,int sizex,int sizey)548 void eraserect(int x,int y,int sizex,int sizey)
549 {
550 unsigned char *p;
551 	if(y<0)
552 	{
553 		sizey+=y;
554 		y=0;
555 	}
556 	if(x<0)
557 	{
558 		sizex+=x;
559 		x=0;
560 	}
561 	if(x+sizex>vxsize)
562 		sizex=vxsize-x;
563 	if(y+sizey>vysize)
564 		sizey=vysize-y;
565 	p=videomem+stride*y+(x<<1);
566 	sizex<<=1;
567 	while(sizey-->0)
568 	{
569 		memset(p,0,sizex);
570 		p+=stride;
571 	}
572 
573 }
transformrect(int x,int y,int sizex,int sizey,unsigned short * trans)574 void transformrect(int x,int y,int sizex,int sizey,unsigned short *trans)
575 {
576 unsigned short *p;
577 int i;
578 	if(y<0)
579 	{
580 		sizey+=y;
581 		y=0;
582 	}
583 	if(x<0)
584 	{
585 		sizex+=x;
586 		x=0;
587 	}
588 	if(x+sizex>vxsize)
589 		sizex=vxsize-x;
590 	if(y+sizey>vysize)
591 		sizey=vysize-y;
592 	p=(void *)(videomem+stride*y+(x<<1));
593 	while(sizey-->0)
594 	{
595 		i=sizex;
596 		while(i-->0)
597 			p[i]=trans[p[i]];
598 		p = (void *)((char *)p + stride);
599 	}
600 }
darkenrect(int x,int y,int sizex,int sizey)601 void darkenrect(int x,int y,int sizex,int sizey)
602 {
603 	transformrect(x,y,sizex,sizey,darker);
604 }
lightenrect(int x,int y,int sizex,int sizey)605 void lightenrect(int x,int y,int sizex,int sizey)
606 {
607 	transformrect(x,y,sizex,sizey,lighter);
608 }
solidrect(int x,int y,int sizex,int sizey,unsigned char r,unsigned char g,unsigned char b)609 void solidrect(int x,int y,int sizex,int sizey,unsigned char r,unsigned char g,unsigned char b)
610 {
611 unsigned short *p;
612 int i;
613 int c;
614 	c=SDL_MapRGB(thescreen->format,r,g,b);
615 	if(y<0)
616 	{
617 		sizey+=y;
618 		y=0;
619 	}
620 	if(x<0)
621 	{
622 		sizex+=x;
623 		x=0;
624 	}
625 	if(x+sizex>vxsize)
626 		sizex=vxsize-x;
627 	if(y+sizey>vysize)
628 		sizey=vysize-y;
629 	p=(void *)(videomem+stride*y+(x<<1));
630 	while(sizey-->0)
631 	{
632 		i=sizex;
633 		while(i-->0)
634 			p[i]=c;
635 		p = (void *)((char *)p + stride);
636 	}
637 }
638 
applyshadowplane(unsigned char * plane)639 void applyshadowplane(unsigned char *plane)
640 {
641 unsigned short *p,*p2;
642 int i,j,k;
643 unsigned char c;
644 
645 	p=(void *)videomem;
646 	for(j=0;j<vysize;++j)
647 	{
648 		i=vxsize;
649 		p2=p;
650 		p = (void *)((char *)p + stride);
651 		while(i>0)
652 		{
653 			i-=8;
654 			c=*plane++;
655 			k=0;
656 			while(c)
657 			{
658 				if(c&1) p2[k]=darker[p2[k]];
659 				c>>=1;
660 				++k;
661 			}
662 			p2+=8;
663 		}
664 	}
665 }
copytoback(unsigned int n)666 void copytoback(unsigned int n)
667 {
668 int i;
669 unsigned char *p1,*p2;
670 
671 	if(n>=MAXBACKBUFFERS) return;
672 	if(!backbuffers[n])
673 	{
674 		backbuffers[n]=malloc(vxsize*vysize*sizeof(unsigned short));
675 		if(!backbuffers[n]) nomem(25);
676 	}
677 	p1=backbuffers[n];
678 	p2=videomem;
679 	i=vysize;
680 	while(i--)
681 	{
682 		memcpy(p1,p2,vxsize<<1);
683 		p1+=vxsize<<1;
684 		p2+=stride;
685 	}
686 }
copyfromback(unsigned int n)687 void copyfromback(unsigned int n)
688 {
689 int i;
690 unsigned char *p1,*p2;
691 	if(n>=MAXBACKBUFFERS || !backbuffers[n]) return;
692 	p1=backbuffers[n];
693 	p2=videomem;
694 	i=vysize;
695 	while(i--)
696 	{
697 		memcpy(p2,p1,vxsize<<1);
698 		p1+=vxsize<<1;
699 		p2+=stride;
700 	}
701 }
freegs(surface * gs)702 void freegs(surface *gs)
703 {
704 	if(gs->pic)
705 	{
706 		free(gs->pic);
707 		gs->pic=0;
708 	}
709 }
maprgb(int r,int g,int b)710 int maprgb(int r,int g,int b)
711 {
712 	return SDL_MapRGB(thescreen->format,r,g,b);
713 }
714