Proper Subversion configuration.
[newkind] / alg_gfx.c
CommitLineData
84bbd123 1/**
2 *
3 * Elite - The New Kind.
4 *
5 * Allegro version of Graphics routines.
6 *
7 * The code in this file has not been derived from the original Elite code.
8 * Written by C.J.Pinder 1999-2001.
9 * email: <christian@newkind.co.uk>
10 *
11 * Routines for drawing anti-aliased lines and circles by T.Harte.
12 *
13 **/
14
15#include <string.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <math.h>
19#include <ctype.h>
20
21#include "allegro.h"
22
23#include "config.h"
24#include "gfx.h"
25#include "alg_data.h"
26#include "elite.h"
27
28BITMAP *gfx_screen;
29volatile int frame_count;
30DATAFILE *datafile;
31BITMAP *scanner_image;
32
33#define MAX_POLYS 100
34
35static int start_poly;
36static int total_polys;
37
38struct poly_data
39{
40 int z;
41 int no_points;
42 int face_colour;
43 int point_list[16];
44 int next;
45};
46
47static struct poly_data poly_chain[MAX_POLYS];
48
49
50
51
52void frame_timer (void)
53{
54 frame_count++;
55}
56END_OF_FUNCTION(frame_timer);
57
58
59
60int gfx_graphics_startup (void)
61{
62 PALETTE the_palette;
63 int rv;
64
65#ifdef ALLEGRO_WINDOWS
66
67#ifdef RES_512_512
68 rv = set_gfx_mode(GFX_DIRECTX_OVL, 512, 512, 0, 0);
69
70 if (rv != 0)
71 rv = set_gfx_mode(GFX_DIRECTX_WIN, 512, 512, 0, 0);
72
73 if (rv != 0)
74 rv = set_gfx_mode(GFX_GDI, 512, 512, 0, 0);
75
76 if (rv == 0)
77 set_display_switch_mode (SWITCH_BACKGROUND);
78#else
79 rv = set_gfx_mode(GFX_DIRECTX, 800, 600, 0, 0);
80
81 if (rv != 0)
82 rv = set_gfx_mode(GFX_GDI, 800, 600, 0, 0);
83#endif
84
85#else
1a8abebd 86 rv = set_gfx_mode(prefer_window ?
87 GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT,
88 800, 600, 0, 0);
84bbd123 89#endif
90
91 if (rv != 0)
92 {
93 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
94 allegro_message("Unable to set graphics mode.");
95 return 1;
96 }
97
98 datafile = load_datafile("elite.dat");
99 if (!datafile)
100 {
101 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
102 allegro_message("Error loading %s!\n", "elite.dat");
103 return 1;
104 }
105
106 scanner_image = load_bitmap(scanner_filename, the_palette);
107 if (!scanner_image)
108 {
109 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
110 allegro_message("Error reading scanner bitmap file.\n");
111 return 1;
112 }
113
114 /* select the scanner palette */
115 set_palette(the_palette);
116
117 /* Create the screen buffer bitmap */
118 gfx_screen = create_bitmap (SCREEN_W, SCREEN_H);
119
120 clear (gfx_screen);
121
122 blit (scanner_image, gfx_screen, 0, 0, GFX_X_OFFSET, 385+GFX_Y_OFFSET, scanner_image->w, scanner_image->h);
123 gfx_draw_line (0, 0, 0, 384);
124 gfx_draw_line (0, 0, 511, 0);
125 gfx_draw_line (511, 0, 511, 384);
126
127 /* Install a timer to regulate the speed of the game... */
128
129 LOCK_VARIABLE(frame_count);
130 LOCK_FUNCTION(frame_timer);
131 frame_count = 0;
132 install_int (frame_timer, speed_cap);
133
134 return 0;
135}
136
137
138void gfx_graphics_shutdown (void)
139{
140 destroy_bitmap(scanner_image);
141 destroy_bitmap(gfx_screen);
142 unload_datafile(datafile);
143}
144
145
146/*
147 * Blit the back buffer to the screen.
148 */
149
150void gfx_update_screen (void)
151{
152 while (frame_count < 1)
153 rest (10);
154 frame_count = 0;
155
156 acquire_screen();
157 blit (gfx_screen, screen, GFX_X_OFFSET, GFX_Y_OFFSET, GFX_X_OFFSET, GFX_Y_OFFSET, 512, 512);
158 release_screen();
159}
160
161
162void gfx_acquire_screen (void)
163{
164 acquire_bitmap (gfx_screen);
165}
166
167
168void gfx_release_screen (void)
169{
170 release_bitmap(gfx_screen);
171}
172
173void gfx_fast_plot_pixel (int x, int y, int col)
174{
175// _putpixel(gfx_screen, x, y, col);
176 gfx_screen->line[y][x] = col;
177}
178
179
180void gfx_plot_pixel (int x, int y, int col)
181{
182 putpixel (gfx_screen, x + GFX_X_OFFSET, y + GFX_Y_OFFSET, col);
183}
184
185
186void gfx_draw_filled_circle (int cx, int cy, int radius, int circle_colour)
187{
188 circlefill (gfx_screen, cx + GFX_X_OFFSET, cy + GFX_Y_OFFSET, radius, circle_colour);
189}
190
191
192#define AA_BITS 3
193#define AA_AND 7
194#define AA_BASE 235
195
196#define trunc(x) ((x) & ~65535)
197#define frac(x) ((x) & 65535)
198#define invfrac(x) (65535-frac(x))
199#define plot(x,y,c) putpixel(gfx_screen, (x), (y), (c)+AA_BASE)
200
201/*
202 * Draw anti-aliased wireframe circle.
203 * By T.Harte.
204 */
205
206void gfx_draw_aa_circle(int cx, int cy, int radius)
207{
208 int x,y;
209 int s;
210 int sx, sy;
211
212 cx += GFX_X_OFFSET;
213 cy += GFX_Y_OFFSET;
214
215 radius >>= (16 - AA_BITS);
216
217 x = radius;
218 s = -radius;
219 y = 0;
220
221 while (y <= x)
222 {
223 //wide pixels
224 sx = cx + (x >> AA_BITS); sy = cy + (y >> AA_BITS);
225
226 plot(sx, sy, AA_AND - (x&AA_AND));
227 plot(sx + 1, sy, x&AA_AND);
228
229 sy = cy - (y >> AA_BITS);
230
231 plot(sx, sy, AA_AND - (x&AA_AND));
232 plot(sx + 1, sy, x&AA_AND);
233
234 sx = cx - (x >> AA_BITS);
235
236 plot(sx, sy, AA_AND - (x&AA_AND));
237 plot(sx - 1, sy, x&AA_AND);
238
239 sy = cy + (y >> AA_BITS);
240
241 plot(sx, sy, AA_AND - (x&AA_AND));
242 plot(sx - 1, sy, x&AA_AND);
243
244 //tall pixels
245 sx = cx + (y >> AA_BITS); sy = cy + (x >> AA_BITS);
246
247 plot(sx, sy, AA_AND - (x&AA_AND));
248 plot(sx, sy + 1, x&AA_AND);
249
250 sy = cy - (x >> AA_BITS);
251
252 plot(sx, sy, AA_AND - (x&AA_AND));
253 plot(sx, sy - 1, x&AA_AND);
254
255 sx = cx - (y >> AA_BITS);
256
257 plot(sx, sy, AA_AND - (x&AA_AND));
258 plot(sx, sy - 1, x&AA_AND);
259
260 sy = cy + (x >> AA_BITS);
261
262 plot(sx, sy, AA_AND - (x&AA_AND));
263 plot(sx, sy + 1, x&AA_AND);
264
265 s += AA_AND+1 + (y << (AA_BITS+1)) + ((1 << (AA_BITS+2))-2);
266 y += AA_AND+1;
267
268 while(s >= 0)
269 {
270 s -= (x << 1) + 2;
271 x --;
272 }
273 }
274}
275
276
277/*
278 * Draw anti-aliased line.
279 * By T.Harte.
280 */
281
282void gfx_draw_aa_line (int x1, int y1, int x2, int y2)
283{
284 fixed grad, xd, yd;
285 fixed xgap, ygap, xend, yend, xf, yf;
286 fixed brightness1, brightness2, swap;
287
288 int x, y, ix1, ix2, iy1, iy2;
289
290 x1 += itofix(GFX_X_OFFSET);
291 x2 += itofix(GFX_X_OFFSET);
292 y1 += itofix(GFX_Y_OFFSET);
293 y2 += itofix(GFX_Y_OFFSET);
294
295 xd = x2 - x1;
296 yd = y2 - y1;
297
298 if (abs(xd) > abs(yd))
299 {
300 if(x1 > x2)
301 {
302 swap = x1; x1 = x2; x2 = swap;
303 swap = y1; y1 = y2; y2 = swap;
304 xd = -xd;
305 yd = -yd;
306 }
307
308 grad = fdiv(yd, xd);
309
310 //end point 1
311
312 xend = trunc(x1 + 32768);
313 yend = y1 + fmul(grad, xend-x1);
314
315 xgap = invfrac(x1+32768);
316
317 ix1 = xend >> 16;
318 iy1 = yend >> 16;
319
320 brightness1 = fmul(invfrac(yend), xgap);
321 brightness2 = fmul(frac(yend), xgap);
322
323 plot(ix1, iy1, brightness1 >> (16-AA_BITS));
324 plot(ix1, iy1+1, brightness2 >> (16-AA_BITS));
325
326 yf = yend+grad;
327
328 //end point 2;
329
330 xend = trunc(x2 + 32768);
331 yend = y2 + fmul(grad, xend-x2);
332
333 xgap = invfrac(x2 - 32768);
334
335 ix2 = xend >> 16;
336 iy2 = yend >> 16;
337
338 brightness1 = fmul(invfrac(yend), xgap);
339 brightness2 = fmul(frac(yend), xgap);
340
341 plot(ix2, iy2, brightness1 >> (16-AA_BITS));
342 plot(ix2, iy2+1, brightness2 >> (16-AA_BITS));
343
344 for(x = ix1+1; x <= ix2-1; x++)
345 {
346 brightness1 = invfrac(yf);
347 brightness2 = frac(yf);
348
349 plot(x, (yf >> 16), brightness1 >> (16-AA_BITS));
350 plot(x, 1+(yf >> 16), brightness2 >> (16-AA_BITS));
351
352 yf += grad;
353 }
354 }
355 else
356 {
357 if(y1 > y2)
358 {
359 swap = x1; x1 = x2; x2 = swap;
360 swap = y1; y1 = y2; y2 = swap;
361 xd = -xd;
362 yd = -yd;
363 }
364
365 grad = fdiv(xd, yd);
366
367 //end point 1
368
369 yend = trunc(y1 + 32768);
370 xend = x1 + fmul(grad, yend-y1);
371
372 ygap = invfrac(y1+32768);
373
374 iy1 = yend >> 16;
375 ix1 = xend >> 16;
376
377 brightness1 = fmul(invfrac(xend), ygap);
378 brightness2 = fmul(frac(xend), ygap);
379
380 plot(ix1, iy1, brightness1 >> (16-AA_BITS));
381 plot(ix1+1, iy1, brightness2 >> (16-AA_BITS));
382
383 xf = xend+grad;
384
385 //end point 2;
386
387 yend = trunc(y2 + 32768);
388 xend = x2 + fmul(grad, yend-y2);
389
390 ygap = invfrac(y2 - 32768);
391
392 ix2 = xend >> 16;
393 iy2 = yend >> 16;
394
395 brightness1 = fmul(invfrac(xend), ygap);
396 brightness2 = fmul(frac(xend), ygap);
397
398 plot(ix2, iy2, brightness1 >> (16-AA_BITS));
399 plot(ix2+1, iy2, brightness2 >> (16-AA_BITS));
400
401 for(y = iy1+1; y <= iy2-1; y++)
402 {
403 brightness1 = invfrac(xf);
404 brightness2 = frac(xf);
405
406 plot((xf >> 16), y, brightness1 >> (16-AA_BITS));
407 plot(1+(xf >> 16), y, brightness2 >> (16-AA_BITS));
408
409 xf += grad;
410 }
411 }
412}
413
414#undef trunc
415#undef frac
416#undef invfrac
417#undef plot
418
419#undef AA_BITS
420#undef AA_AND
421#undef AA_BASE
422
423
424
425void gfx_draw_circle (int cx, int cy, int radius, int circle_colour)
426{
427 if (anti_alias_gfx && (circle_colour == GFX_COL_WHITE))
428 gfx_draw_aa_circle (cx, cy, itofix(radius));
429 else
430 circle (gfx_screen, cx + GFX_X_OFFSET, cy + GFX_Y_OFFSET, radius, circle_colour);
431}
432
433
434
435void gfx_draw_line (int x1, int y1, int x2, int y2)
436{
437 if (y1 == y2)
438 {
439 hline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, GFX_COL_WHITE);
440 return;
441 }
442
443 if (x1 == x2)
444 {
445 vline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, y2 + GFX_Y_OFFSET, GFX_COL_WHITE);
446 return;
447 }
448
449 if (anti_alias_gfx)
450 gfx_draw_aa_line (itofix(x1), itofix(y1), itofix(x2), itofix(y2));
451 else
452 line (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET, GFX_COL_WHITE);
453}
454
455
456
457void gfx_draw_colour_line (int x1, int y1, int x2, int y2, int line_colour)
458{
459 if (y1 == y2)
460 {
461 hline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, line_colour);
462 return;
463 }
464
465 if (x1 == x2)
466 {
467 vline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, y2 + GFX_Y_OFFSET, line_colour);
468 return;
469 }
470
471 if (anti_alias_gfx && (line_colour == GFX_COL_WHITE))
472 gfx_draw_aa_line (itofix(x1), itofix(y1), itofix(x2), itofix(y2));
473 else
474 line (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET, line_colour);
475}
476
477
478
479void gfx_draw_triangle (int x1, int y1, int x2, int y2, int x3, int y3, int col)
480{
481 triangle (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET,
482 x3 + GFX_X_OFFSET, y3 + GFX_Y_OFFSET, col);
483}
484
485
486
487void gfx_display_text (int x, int y, char *txt)
488{
489 text_mode (-1);
490 textout (gfx_screen, datafile[ELITE_1].dat, txt, (x / (2 / GFX_SCALE)) + GFX_X_OFFSET, (y / (2 / GFX_SCALE)) + GFX_Y_OFFSET, GFX_COL_WHITE);
491}
492
493
494void gfx_display_colour_text (int x, int y, char *txt, int col)
495{
496 text_mode (-1);
497 textout (gfx_screen, datafile[ELITE_1].dat, txt, (x / (2 / GFX_SCALE)) + GFX_X_OFFSET, (y / (2 / GFX_SCALE)) + GFX_Y_OFFSET, col);
498}
499
500
501
502void gfx_display_centre_text (int y, char *str, int psize, int col)
503{
504 int txt_size;
505 int txt_colour;
506
507 if (psize == 140)
508 {
509 txt_size = ELITE_2;
510 txt_colour = -1;
511 }
512 else
513 {
514 txt_size = ELITE_1;
515 txt_colour = col;
516 }
517
518 text_mode (-1);
519 textout_centre (gfx_screen, datafile[txt_size].dat, str, (128 * GFX_SCALE) + GFX_X_OFFSET, (y / (2 / GFX_SCALE)) + GFX_Y_OFFSET, txt_colour);
520}
521
522
523void gfx_clear_display (void)
524{
525 rectfill (gfx_screen, GFX_X_OFFSET + 1, GFX_Y_OFFSET + 1, 510 + GFX_X_OFFSET, 383 + GFX_Y_OFFSET, GFX_COL_BLACK);
526}
527
528void gfx_clear_text_area (void)
529{
530 rectfill (gfx_screen, GFX_X_OFFSET + 1, GFX_Y_OFFSET + 340, 510 + GFX_X_OFFSET, 383 + GFX_Y_OFFSET, GFX_COL_BLACK);
531}
532
533
534void gfx_clear_area (int tx, int ty, int bx, int by)
535{
536 rectfill (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET,
537 bx + GFX_X_OFFSET, by + GFX_Y_OFFSET, GFX_COL_BLACK);
538}
539
540void gfx_draw_rectangle (int tx, int ty, int bx, int by, int col)
541{
542 rectfill (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET,
543 bx + GFX_X_OFFSET, by + GFX_Y_OFFSET, col);
544}
545
546
547void gfx_display_pretty_text (int tx, int ty, int bx, int by, char *txt)
548{
549 char strbuf[100];
550 char *str;
551 char *bptr;
552 int len;
553 int pos;
554 int maxlen;
555
556 maxlen = (bx - tx) / 8;
557
558 str = txt;
559 len = strlen(txt);
560
561 while (len > 0)
562 {
563 pos = maxlen;
564 if (pos > len)
565 pos = len;
566
567 while ((str[pos] != ' ') && (str[pos] != ',') &&
568 (str[pos] != '.') && (str[pos] != '\0'))
569 {
570 pos--;
571 }
572
573 len = len - pos - 1;
574
575 for (bptr = strbuf; pos >= 0; pos--)
576 *bptr++ = *str++;
577
578 *bptr = '\0';
579
580 text_mode (-1);
581 textout (gfx_screen, datafile[ELITE_1].dat, strbuf, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET, GFX_COL_WHITE);
582 ty += (8 * GFX_SCALE);
583 }
584}
585
586
587void gfx_draw_scanner (void)
588{
1a8abebd 589 set_clip(gfx_screen, GFX_X_OFFSET, 385 + GFX_Y_OFFSET,
590 GFX_X_OFFSET + scanner_image->w,
591 GFX_Y_OFFSET + scanner_image->h + 385);
592 blit (scanner_image, gfx_screen, 0, 0, GFX_X_OFFSET,
593 385+GFX_Y_OFFSET, scanner_image->w, scanner_image->h);
84bbd123 594}
595
596void gfx_set_clip_region (int tx, int ty, int bx, int by)
597{
598 set_clip (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET, bx + GFX_X_OFFSET, by + GFX_Y_OFFSET);
599}
600
601
602void gfx_start_render (void)
603{
604 start_poly = 0;
605 total_polys = 0;
606}
607
608
609void gfx_render_polygon (int num_points, int *point_list, int face_colour, int zavg)
610{
611 int i;
612 int x;
613 int nx;
614
615 if (total_polys == MAX_POLYS)
616 return;
617
618 x = total_polys;
619 total_polys++;
620
621 poly_chain[x].no_points = num_points;
622 poly_chain[x].face_colour = face_colour;
623 poly_chain[x].z = zavg;
624 poly_chain[x].next = -1;
625
626 for (i = 0; i < 16; i++)
627 poly_chain[x].point_list[i] = point_list[i];
628
629 if (x == 0)
630 return;
631
632 if (zavg > poly_chain[start_poly].z)
633 {
634 poly_chain[x].next = start_poly;
635 start_poly = x;
636 return;
637 }
638
639 for (i = start_poly; poly_chain[i].next != -1; i = poly_chain[i].next)
640 {
641 nx = poly_chain[i].next;
642
643 if (zavg > poly_chain[nx].z)
644 {
645 poly_chain[i].next = x;
646 poly_chain[x].next = nx;
647 return;
648 }
649 }
650
651 poly_chain[i].next = x;
652}
653
654
655void gfx_render_line (int x1, int y1, int x2, int y2, int dist, int col)
656{
657 int point_list[4];
658
659 point_list[0] = x1;
660 point_list[1] = y1;
661 point_list[2] = x2;
662 point_list[3] = y2;
663
664 gfx_render_polygon (2, point_list, col, dist);
665}
666
667
668void gfx_finish_render (void)
669{
670 int num_points;
671 int *pl;
672 int i;
673 int col;
674
675 if (total_polys == 0)
676 return;
677
678 for (i = start_poly; i != -1; i = poly_chain[i].next)
679 {
680 num_points = poly_chain[i].no_points;
681 pl = poly_chain[i].point_list;
682 col = poly_chain[i].face_colour;
683
684 if (num_points == 2)
685 {
686 gfx_draw_colour_line (pl[0], pl[1], pl[2], pl[3], col);
687 continue;
688 }
689
690 gfx_polygon (num_points, pl, col);
691 };
692}
693
694
695void gfx_polygon (int num_points, int *poly_list, int face_colour)
696{
697 int i;
698 int x,y;
699
700 x = 0;
701 y = 1;
702 for (i = 0; i < num_points; i++)
703 {
704 poly_list[x] += GFX_X_OFFSET;
705 poly_list[y] += GFX_Y_OFFSET;
706 x += 2;
707 y += 2;
708 }
709
710 polygon (gfx_screen, num_points, poly_list, face_colour);
711}
712
713
714void gfx_draw_sprite (int sprite_no, int x, int y)
715{
716 BITMAP *sprite_bmp;
717
718 switch (sprite_no)
719 {
720 case IMG_GREEN_DOT:
721 sprite_bmp = datafile[GRNDOT].dat;
722 break;
723
724 case IMG_RED_DOT:
725 sprite_bmp = datafile[REDDOT].dat;
726 break;
727
728 case IMG_BIG_S:
729 sprite_bmp = datafile[SAFE].dat;
730 break;
731
732 case IMG_ELITE_TXT:
733 sprite_bmp = datafile[ELITETXT].dat;
734 break;
735
736 case IMG_BIG_E:
737 sprite_bmp = datafile[ECM].dat;
738 break;
739
740 case IMG_BLAKE:
741 sprite_bmp = datafile[BLAKE].dat;
742 break;
743
744 case IMG_MISSILE_GREEN:
745 sprite_bmp = datafile[MISSILE_G].dat;
746 break;
747
748 case IMG_MISSILE_YELLOW:
749 sprite_bmp = datafile[MISSILE_Y].dat;
750 break;
751
752 case IMG_MISSILE_RED:
753 sprite_bmp = datafile[MISSILE_R].dat;
754 break;
755
756 default:
757 return;
758 }
759
760 if (x == -1)
761 x = ((256 * GFX_SCALE) - sprite_bmp->w) / 2;
762
763 draw_sprite (gfx_screen, sprite_bmp, x + GFX_X_OFFSET, y + GFX_Y_OFFSET);
764}
765
766
767int gfx_request_file (char *title, char *path, char *ext)
768{
769 int okay;
770
771 show_mouse (screen);
772 okay = file_select (title, path, ext);
773 show_mouse (NULL);
774
775 return okay;
776}
777