1 /*
2 XorGramana Copyright 2009 James W. Morris, james@jwm-art.net
3
4 This file is part of XorGramana.
5
6 XorGramana is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 XorGramana is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XorGramana. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "gfx.h"
20 #include "input.h"
21
22 #include <stdlib.h>
23 #include <stdarg.h>
24
25 SDL_Surface* screen=0;
26 struct gfx_mode kermode;
27 struct gfx_win* scr_win=0;
28 struct gfx_win* main_win=0;
29 struct gfx_win* cur_win=0;
30
gfx_start()31 void gfx_start()
32 {
33 int i,n;
34 int rx,by;
35 int mc=0;
36 SDL_Rect **modes;
37 if(SDL_Init(SDL_INIT_VIDEO)<0){
38 fprintf(stderr,"Couldn't initialize SDL: %s\n",SDL_GetError());
39 exit(-1);
40 }
41 SDL_WM_SetCaption("XorGramana",0);
42 kermode.def=kermode.last=kermode.mode=-1;
43 kermode.m=0;
44 kermode.modes=0;
45 modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
46 if(!modes){
47 fprintf(stderr,"No modes available!\n");
48 SDL_Quit();
49 exit(-1);
50 }
51 if(modes == (SDL_Rect **)-1){
52 fprintf(stderr,"All resolutions available.\n");
53 fprintf(stderr,"Dont't know what to do!!!!\n Probably will crash!\n");
54 /* now what? how do we know what they are? */
55 }
56 else{
57 mc=0;
58 for(i=0;modes[i];++i){
59 #ifdef GFX_DEBUG
60 printf("Checking mode: %d x %d ... ",
61 modes[i]->w,
62 modes[i]->h);
63 #endif
64 if(modes[i]->w<GFX_MIN_WIDTH
65 ||modes[i]->h<GFX_MIN_HEIGHT)
66 {
67 modes[i]=0;
68 #ifdef GFX_DEBUG
69 printf("Too small.\n");
70 #endif
71 }
72 else{
73 #ifdef GFX_DEBUG
74 printf("Ok.\n");
75 #endif
76 mc++;
77 }
78 }
79 }
80 #ifdef GFX_DEBUG
81 printf("%d gfx modes found\n",mc);
82 #endif
83 if(!(kermode.modes=malloc(sizeof(SDL_Rect*)*mc))){
84 fprintf(stderr,"Failed to allocate for gfx modes dit dit dit...");
85 SDL_Quit();
86 exit(-1);
87 }
88 if(mc==0){
89 fprintf(stderr,
90 "%d x %d video mode or larger not found.\n",
91 GFX_MIN_WIDTH,GFX_MIN_HEIGHT);
92 fprintf(stderr,"Sorry, this is a minimum requirement.\n");
93 SDL_Quit();
94 exit(-1);
95 }
96 #ifdef GFX_LARGEST_RES
97 kermode.mode=kermode.last=0;
98 #else
99 kermode.mode=kermode.last=mc-1;
100 #endif
101 mc=0;
102 n=i;
103 for(i=0;i<n;i++)
104 if(modes[i]){
105 kermode.modes[mc]=modes[i];
106 mc++;
107 }
108 kermode.m=kermode.modes[kermode.mode];
109 screen=SDL_SetVideoMode(kermode.m->w,kermode.m->h,0,
110 SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF);
111 if(!screen){
112 fprintf(stderr,
113 "Couldn't set %d x %d hardware surface video mode: %s\n",
114 kermode.m->w,kermode.m->h,SDL_GetError());
115 SDL_Quit();
116 exit(-1);
117 }
118 scr_win=gfx_new_win(GFX_CENTER_X|GFX_CENTER_Y,0,0,0,0,ICON_WIDTH,ICON_HEIGHT);
119 rx=scr_win->win_w-ICON_WIDTH;
120 by=scr_win->win_h-ICON_HEIGHT;
121 main_win=gfx_new_win(GFX_CENTER_X|GFX_CENTER_Y,0,0,rx,by,ICON_WIDTH,ICON_HEIGHT);
122 }
123
gfx_end()124 void gfx_end()
125 {
126 free(scr_win);
127 free(main_win);
128 scr_win=0;
129 SDL_Quit();
130 }
131
scr_win_border()132 void scr_win_border()
133 {
134 gfx_set_win(scr_win);
135 gfx_win_half_size();
136 gfx_box(0,0,scr_win->blk_count_x-1,scr_win->blk_count_y-1,FALSE);
137 }
138
gfx_inc_mode()139 void gfx_inc_mode()
140 {
141 }
142
gfx_dec_mode()143 void gfx_dec_mode()
144 {
145 }
146
draw_image(SDL_Surface * image,int x,int y)147 void draw_image(SDL_Surface *image, int x, int y)
148 {
149 SDL_Rect dest;
150 dest.x=x;
151 dest.y=y;
152 dest.w=image->w;
153 dest.h=image->h;
154 SDL_BlitSurface(image, NULL, screen, &dest);
155 }
156
gfx_win_draw_image(SDL_Surface * image,int blk_x,int blk_y)157 void gfx_win_draw_image(SDL_Surface *image, int blk_x, int blk_y)
158 {
159 SDL_Rect dest;
160 dest.x=cur_win->blk_tlx+blk_x*image->w;
161 dest.y=cur_win->blk_tly+blk_y*image->h;
162 dest.w=image->w;
163 dest.h=image->h;
164 SDL_BlitSurface(image, NULL, screen, &dest);
165 }
166
overlay_image(SDL_Surface * image,SDL_Surface * overlay,int x,int y)167 void overlay_image(SDL_Surface* image, SDL_Surface *overlay, int x, int y)
168 {
169 SDL_Rect dest;
170 dest.x=x;
171 dest.y=y;
172 dest.w=image->w;
173 dest.h=image->h;
174 SDL_BlitSurface(overlay, NULL, image, &dest);
175 }
176
getpixel(SDL_Surface * surface,int x,int y)177 Uint32 getpixel(SDL_Surface *surface, int x, int y)
178 {
179 int bpp=surface->format->BytesPerPixel;
180 /* Here p is the address to the pixel we want to retrieve */
181 Uint8* p=(Uint8*)surface->pixels+y*surface->pitch+x*bpp;
182 switch(bpp){
183 case 1: return *p;
184 case 2: return *(Uint16 *)p;
185 case 3:
186 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
187 return p[0] << 16 | p[1] << 8 | p[2];
188 else
189 return p[0] | p[1] << 8 | p[2] << 16;
190 case 4: return *(Uint32 *)p;
191 default:
192 return 0;
193 }
194 }
195
putpixel(SDL_Surface * surface,int x,int y,Uint32 pixel)196 void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
197 {
198 int bpp=surface->format->BytesPerPixel;
199 /* Here p is the address to the pixel we want to set */
200 Uint8* p=(Uint8*)surface->pixels+y*surface->pitch+x*bpp;
201 switch(bpp){
202 case 1: *p = pixel; break;
203 case 2: *(Uint16 *)p = pixel; break;
204 case 3:
205 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
206 p[0] = (pixel >> 16) & 0xff;
207 p[1] = (pixel >> 8) & 0xff;
208 p[2] = pixel & 0xff;
209 }
210 else{
211 p[0] = pixel & 0xff;
212 p[1] = (pixel >> 8) & 0xff;
213 p[2] = (pixel >> 16) & 0xff;
214 }
215 break;
216 case 4: *(Uint32 *)p = pixel; break;
217 }
218 }
219
220 struct gfx_win*
gfx_new_win(int flags,int tlx,int tly,int brx,int bry,int blk_width,int blk_height)221 gfx_new_win(int flags,
222 int tlx, int tly,int brx, int bry,
223 int blk_width,int blk_height)
224 {
225 struct gfx_win* win=0;
226 int tmptlx,tmptly,tmpbrx,tmpbry;
227 int offx=0;
228 int offy=0;
229 int tmp;
230 if(tlx==0&&tly==0&&brx==0&&bry==0){
231 brx=screen->w;
232 bry=screen->h;
233 }
234 if(blk_width<2||blk_height<2)
235 return 0;
236 tmptlx=((tlx>=0?tlx:0)<screen->w?tlx:screen->w);
237 tmptly=((tly>=0?tly:0)<screen->h?tly:screen->h);
238 tmpbrx=((brx>=0?brx:0)<screen->w?brx:screen->w);
239 tmpbry=((bry>=0?bry:0)<screen->h?bry:screen->h);
240 if(tmptlx>=tmpbrx||tmptly>=tmpbry)
241 return 0;
242 if(!(win=malloc(sizeof(struct gfx_win))))
243 return 0;
244 win->win_w=tmpbrx-tmptlx;
245 win->win_h=tmpbry-tmptly;
246 if(flags&GFX_CENTER_X)
247 offx=(screen->w - win->win_w)/2;
248 else if(flags&GFX_ALIGN_R)
249 offx=screen->w - win->win_w;
250 if(flags&GFX_CENTER_Y)
251 offy=(screen->h - win->win_h)/2;
252 else if(flags&GFX_ALIGN_B)
253 offy=screen->h - win->win_h;
254 win->win_tlx=offx+tmptlx;
255 win->win_tly=offy+tmptly;
256 win->win_brx=offx+tmpbrx;
257 win->win_bry=offy+tmpbry;
258 if(flags&GFX_BLK_ALIGN_X){
259 win->win_tlx=(win->win_tlx/blk_width)*blk_width;
260 win->win_brx=(win->win_brx/blk_width)*blk_width;
261 win->win_w=win->win_brx-win->win_tlx;
262 }
263 if(flags&GFX_BLK_ALIGN_Y){
264 win->win_tly=(win->win_tly/blk_height)*blk_height;
265 win->win_bry=(win->win_bry/blk_height)*blk_height;
266 win->win_h=win->win_bry-win->win_tly;
267 }
268 win->win_cx=0;
269 win->win_cy=0;
270
271 /* calc block printing area */
272 win->icon_width=blk_width;
273 win->icon_height=blk_height;
274 win->blk_count_x=win->win_w/blk_width;
275 win->blk_count_y=win->win_h/blk_height;
276 offx=0;
277 offy=0;
278
279 /* do the number of blocks fit exactly? */
280 tmp=win->blk_count_x * blk_width;
281 if(tmp<win->win_w)
282 offx=(win->win_w-tmp)/2;
283 tmp=win->blk_count_y * blk_height;
284 if(tmp<win->win_h)
285 offy=(win->win_h-tmp)/2;
286 win->blk_tlx=win->win_tlx+offx;
287 win->blk_brx=win->win_brx-offx;
288 win->blk_tly=win->win_tly+offy;
289 win->blk_bry=win->win_bry-offy;
290 win->blk_cx=0;
291 win->blk_cy=0;
292 win->icons=icons;
293 win->half_size=0;
294 return win;
295 }
296
gfx_set_win(struct gfx_win * win)297 void gfx_set_win(struct gfx_win* win)
298 {
299 cur_win=win;
300 }
301
gfx_win_half_size()302 void gfx_win_half_size()
303 {
304 if(!cur_win){
305 fprintf(stderr,"gfx_win_half_size: cur_win == NULL!\n");
306 return;
307 }
308 if(cur_win->half_size)
309 return;
310 cur_win->half_size=1;
311 cur_win->icons=hs_icons;
312 cur_win->icon_width/=2;
313 cur_win->icon_height/=2;
314 cur_win->blk_cx*=2;
315 cur_win->blk_cy*=2;
316 cur_win->blk_count_x*=2;
317 cur_win->blk_count_y*=2;
318 }
319
gfx_win_full_size()320 void gfx_win_full_size()
321 {
322 if(!cur_win){
323 fprintf(stderr,"gfx_win_full_size: cur_win == NULL!\n");
324 return;
325 }
326 if(!cur_win->half_size)
327 return;
328 cur_win->half_size=0;
329 cur_win->icons=icons;
330 cur_win->icon_width*=2;
331 cur_win->icon_height*=2;
332 cur_win->blk_cx/=2;
333 cur_win->blk_cy/=2;
334 cur_win->blk_count_x/=2;
335 cur_win->blk_count_y/=2;
336 }
337
gfx_mv_cur(su_t blk_x,su_t blk_y)338 su_t gfx_mv_cur(su_t blk_x, su_t blk_y)
339 {
340 int x,y;
341 if(!cur_win){
342 fprintf(stderr,"gfx_mv_cur: cur_win == NULL!\n");
343 return 0;
344 }
345 if(blk_x>cur_win->blk_count_x||blk_x<0
346 ||blk_y>cur_win->blk_count_y||blk_y<0)
347 {
348 fprintf(stderr,
349 "gfx_mv_cur: loc %d,%d outside range 0,0 - %d,%d\n",
350 (int)blk_x, (int)blk_y,
351 (int)cur_win->blk_count_x,(int)cur_win->blk_count_y);
352 return 0;
353 }
354 x=cur_win->blk_tlx+blk_x*cur_win->icon_width;
355 y=cur_win->blk_tly+blk_y*cur_win->icon_height;
356 cur_win->blk_cx=blk_x;
357 cur_win->blk_cy=blk_y;
358 cur_win->win_cx=x;
359 cur_win->win_cy=y;
360 return 1;
361 }
362
gfx_inc_cursor(bool line)363 void gfx_inc_cursor(bool line)
364 {
365 if(!line){
366 cur_win->blk_cx++;
367 if(cur_win->blk_cx==cur_win->blk_count_x)
368 line=TRUE;
369 }
370 if(line){
371 cur_win->blk_cx=0;
372 cur_win->blk_cy++;
373 if(cur_win->blk_cy==cur_win->blk_count_y)
374 cur_win->blk_cx=cur_win->blk_cy=0;
375 }
376 gfx_mv_cur(cur_win->blk_cx,cur_win->blk_cy);
377 }
378
gfx_printf(const char * format,...)379 int gfx_printf(const char* format, ...)
380 {
381 va_list ap;
382 int ret=0;
383 int n=0;
384 int i;
385 char buf[MAX_PRINTLEN];
386 SDL_Surface* icon;
387 if(!cur_win){
388 fprintf(stderr,"gfx_printf: cur_win == NULL!\n");
389 return 0;
390 }
391 va_start(ap, format);
392 ret=vsnprintf(buf,MAX_PRINTLEN-1,format,ap);
393 va_end(ap);
394 while(buf[n]&&n<MAX_PRINTLEN){
395 if(buf[n]=='\n'){
396 n++;
397 gfx_inc_cursor(TRUE);
398 continue;
399 }
400 i=char_to_icon(buf[n]);
401 icon=(cur_win->half_size?hs_icons[i]:icons[i]);
402 draw_image(icon,cur_win->win_cx,cur_win->win_cy);
403 gfx_inc_cursor(FALSE);
404 n++;
405 }
406 return n;
407 }
408
delay(unsigned int flimit)409 void delay(unsigned int flimit)
410 {
411 unsigned int ticks=SDL_GetTicks();
412 if (flimit<ticks)
413 return;
414 if (flimit>ticks+TICK_COUNT)
415 SDL_Delay(TICK_COUNT);
416 else
417 SDL_Delay(flimit-ticks);
418 }
419
gfx_message(const char * format,...)420 void gfx_message(const char* format, ...)
421 {
422 va_list ap;
423 int x,y;
424 int n=0;
425 bool half_size=cur_win->half_size;
426 char buf[MAX_PRINTLEN];
427 if(!cur_win){
428 fprintf(stderr,"gfx_message: cur_win == NULL!\n");
429 return;
430 }
431 va_start(ap, format);
432 n=vsnprintf(buf,MAX_PRINTLEN-1,format,ap);
433 va_end(ap);
434 if(!half_size)
435 gfx_win_half_size();
436 x=(cur_win->blk_count_x-strlen(buf))/2;
437 y=cur_win->blk_count_y/2+2;
438 gfx_box(x-1,y-1,x+n,y+1,TRUE);
439 set_space_icon(SPC_OPAQUE);
440 gfx_mv_cur(x,y);
441 gfx_printf(buf);
442 if(!half_size)
443 gfx_win_full_size();
444 SDL_Flip(screen);
445 wait_till_pressed();
446 }
447
gfx_box(int tlx,int tly,int brx,int bry,bool solid)448 void gfx_box(int tlx, int tly, int brx, int bry, bool solid)
449 {
450 int x,y;
451 for(x=tlx;x<=brx;x++){
452 gfx_win_draw_image(hs_icons[ICON_LINE_T],x, tly);
453 gfx_win_draw_image(hs_icons[ICON_LINE_B],x, bry);
454 }
455 for(y=tly;y<=bry;y++){
456 gfx_win_draw_image(hs_icons[ICON_LINE_L],tlx,y);
457 gfx_win_draw_image(hs_icons[ICON_LINE_R],brx,y);
458 }
459 gfx_win_draw_image(hs_icons[ICON_LINE_TL],tlx,tly);
460 gfx_win_draw_image(hs_icons[ICON_LINE_TR],brx,tly);
461 gfx_win_draw_image(hs_icons[ICON_LINE_BL],tlx,bry);
462 gfx_win_draw_image(hs_icons[ICON_LINE_BR],brx,bry);
463 if(solid){
464 for(y=tly+1;y<bry;y++)
465 for(x=tlx+1;x<brx;x++)
466 gfx_win_draw_image(hs_icons[ICON_SPACE_OPAQUE],x,y);
467 }
468 }
469