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