3 * Elite - The New Kind.
5 * Allegro version of Graphics routines.
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>
11 * Routines for drawing anti-aliased lines and circles by T.Harte.
29 volatile int frame_count
;
31 BITMAP
*scanner_image
;
35 static int start_poly
;
36 static int total_polys
;
47 static struct poly_data poly_chain
[MAX_POLYS
];
52 void frame_timer (void)
56 END_OF_FUNCTION(frame_timer
);
60 int gfx_graphics_startup (void)
65 #ifdef ALLEGRO_WINDOWS
68 rv
= set_gfx_mode(GFX_DIRECTX_OVL
, 512, 512, 0, 0);
71 rv
= set_gfx_mode(GFX_DIRECTX_WIN
, 512, 512, 0, 0);
74 rv
= set_gfx_mode(GFX_GDI
, 512, 512, 0, 0);
77 set_display_switch_mode (SWITCH_BACKGROUND
);
79 rv
= set_gfx_mode(GFX_DIRECTX
, 800, 600, 0, 0);
82 rv
= set_gfx_mode(GFX_GDI
, 800, 600, 0, 0);
86 rv
= set_gfx_mode(prefer_window ?
87 GFX_AUTODETECT_WINDOWED
: GFX_AUTODETECT
,
93 set_gfx_mode(GFX_TEXT
, 0, 0, 0, 0);
94 allegro_message("Unable to set graphics mode.");
98 datafile
= load_datafile("elite.dat");
101 set_gfx_mode(GFX_TEXT
, 0, 0, 0, 0);
102 allegro_message("Error loading %s!\n", "elite.dat");
106 scanner_image
= load_bitmap(scanner_filename
, the_palette
);
109 set_gfx_mode(GFX_TEXT
, 0, 0, 0, 0);
110 allegro_message("Error reading scanner bitmap file.\n");
114 /* select the scanner palette */
115 set_palette(the_palette
);
117 /* Create the screen buffer bitmap */
118 gfx_screen
= create_bitmap (SCREEN_W
, SCREEN_H
);
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);
127 /* Install a timer to regulate the speed of the game... */
129 LOCK_VARIABLE(frame_count
);
130 LOCK_FUNCTION(frame_timer
);
132 install_int (frame_timer
, speed_cap
);
138 void gfx_graphics_shutdown (void)
140 destroy_bitmap(scanner_image
);
141 destroy_bitmap(gfx_screen
);
142 unload_datafile(datafile
);
147 * Blit the back buffer to the screen.
150 void gfx_update_screen (void)
152 while (frame_count
< 1)
157 blit (gfx_screen
, screen
, GFX_X_OFFSET
, GFX_Y_OFFSET
, GFX_X_OFFSET
, GFX_Y_OFFSET
, 512, 512);
162 void gfx_acquire_screen (void)
164 acquire_bitmap (gfx_screen
);
168 void gfx_release_screen (void)
170 release_bitmap(gfx_screen
);
173 void gfx_fast_plot_pixel (int x
, int y
, int col
)
175 // _putpixel(gfx_screen, x, y, col);
176 gfx_screen
->line
[y
][x
] = col
;
180 void gfx_plot_pixel (int x
, int y
, int col
)
182 putpixel (gfx_screen
, x
+ GFX_X_OFFSET
, y
+ GFX_Y_OFFSET
, col
);
186 void gfx_draw_filled_circle (int cx
, int cy
, int radius
, int circle_colour
)
188 circlefill (gfx_screen
, cx
+ GFX_X_OFFSET
, cy
+ GFX_Y_OFFSET
, radius
, circle_colour
);
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)
202 * Draw anti-aliased wireframe circle.
206 void gfx_draw_aa_circle(int cx
, int cy
, int radius
)
215 radius
>>= (16 - AA_BITS
);
224 sx
= cx
+ (x
>> AA_BITS
); sy
= cy
+ (y
>> AA_BITS
);
226 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
227 plot(sx
+ 1, sy
, x
&AA_AND
);
229 sy
= cy
- (y
>> AA_BITS
);
231 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
232 plot(sx
+ 1, sy
, x
&AA_AND
);
234 sx
= cx
- (x
>> AA_BITS
);
236 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
237 plot(sx
- 1, sy
, x
&AA_AND
);
239 sy
= cy
+ (y
>> AA_BITS
);
241 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
242 plot(sx
- 1, sy
, x
&AA_AND
);
245 sx
= cx
+ (y
>> AA_BITS
); sy
= cy
+ (x
>> AA_BITS
);
247 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
248 plot(sx
, sy
+ 1, x
&AA_AND
);
250 sy
= cy
- (x
>> AA_BITS
);
252 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
253 plot(sx
, sy
- 1, x
&AA_AND
);
255 sx
= cx
- (y
>> AA_BITS
);
257 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
258 plot(sx
, sy
- 1, x
&AA_AND
);
260 sy
= cy
+ (x
>> AA_BITS
);
262 plot(sx
, sy
, AA_AND
- (x
&AA_AND
));
263 plot(sx
, sy
+ 1, x
&AA_AND
);
265 s
+= AA_AND
+1 + (y
<< (AA_BITS
+1)) + ((1 << (AA_BITS
+2))-2);
278 * Draw anti-aliased line.
282 void gfx_draw_aa_line (int x1
, int y1
, int x2
, int y2
)
285 fixed xgap
, ygap
, xend
, yend
, xf
, yf
;
286 fixed brightness1
, brightness2
, swap
;
288 int x
, y
, ix1
, ix2
, iy1
, iy2
;
290 x1
+= itofix(GFX_X_OFFSET
);
291 x2
+= itofix(GFX_X_OFFSET
);
292 y1
+= itofix(GFX_Y_OFFSET
);
293 y2
+= itofix(GFX_Y_OFFSET
);
298 if (abs(xd
) > abs(yd
))
302 swap
= x1
; x1
= x2
; x2
= swap
;
303 swap
= y1
; y1
= y2
; y2
= swap
;
312 xend
= trunc(x1
+ 32768);
313 yend
= y1
+ fmul(grad
, xend
-x1
);
315 xgap
= invfrac(x1
+32768);
320 brightness1
= fmul(invfrac(yend
), xgap
);
321 brightness2
= fmul(frac(yend
), xgap
);
323 plot(ix1
, iy1
, brightness1
>> (16-AA_BITS
));
324 plot(ix1
, iy1
+1, brightness2
>> (16-AA_BITS
));
330 xend
= trunc(x2
+ 32768);
331 yend
= y2
+ fmul(grad
, xend
-x2
);
333 xgap
= invfrac(x2
- 32768);
338 brightness1
= fmul(invfrac(yend
), xgap
);
339 brightness2
= fmul(frac(yend
), xgap
);
341 plot(ix2
, iy2
, brightness1
>> (16-AA_BITS
));
342 plot(ix2
, iy2
+1, brightness2
>> (16-AA_BITS
));
344 for(x
= ix1
+1; x
<= ix2
-1; x
++)
346 brightness1
= invfrac(yf
);
347 brightness2
= frac(yf
);
349 plot(x
, (yf
>> 16), brightness1
>> (16-AA_BITS
));
350 plot(x
, 1+(yf
>> 16), brightness2
>> (16-AA_BITS
));
359 swap
= x1
; x1
= x2
; x2
= swap
;
360 swap
= y1
; y1
= y2
; y2
= swap
;
369 yend
= trunc(y1
+ 32768);
370 xend
= x1
+ fmul(grad
, yend
-y1
);
372 ygap
= invfrac(y1
+32768);
377 brightness1
= fmul(invfrac(xend
), ygap
);
378 brightness2
= fmul(frac(xend
), ygap
);
380 plot(ix1
, iy1
, brightness1
>> (16-AA_BITS
));
381 plot(ix1
+1, iy1
, brightness2
>> (16-AA_BITS
));
387 yend
= trunc(y2
+ 32768);
388 xend
= x2
+ fmul(grad
, yend
-y2
);
390 ygap
= invfrac(y2
- 32768);
395 brightness1
= fmul(invfrac(xend
), ygap
);
396 brightness2
= fmul(frac(xend
), ygap
);
398 plot(ix2
, iy2
, brightness1
>> (16-AA_BITS
));
399 plot(ix2
+1, iy2
, brightness2
>> (16-AA_BITS
));
401 for(y
= iy1
+1; y
<= iy2
-1; y
++)
403 brightness1
= invfrac(xf
);
404 brightness2
= frac(xf
);
406 plot((xf
>> 16), y
, brightness1
>> (16-AA_BITS
));
407 plot(1+(xf
>> 16), y
, brightness2
>> (16-AA_BITS
));
425 void gfx_draw_circle (int cx
, int cy
, int radius
, int circle_colour
)
427 if (anti_alias_gfx
&& (circle_colour
== GFX_COL_WHITE
))
428 gfx_draw_aa_circle (cx
, cy
, itofix(radius
));
430 circle (gfx_screen
, cx
+ GFX_X_OFFSET
, cy
+ GFX_Y_OFFSET
, radius
, circle_colour
);
435 void gfx_draw_line (int x1
, int y1
, int x2
, int y2
)
439 hline (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, x2
+ GFX_X_OFFSET
, GFX_COL_WHITE
);
445 vline (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, y2
+ GFX_Y_OFFSET
, GFX_COL_WHITE
);
450 gfx_draw_aa_line (itofix(x1
), itofix(y1
), itofix(x2
), itofix(y2
));
452 line (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, x2
+ GFX_X_OFFSET
, y2
+ GFX_Y_OFFSET
, GFX_COL_WHITE
);
457 void gfx_draw_colour_line (int x1
, int y1
, int x2
, int y2
, int line_colour
)
461 hline (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, x2
+ GFX_X_OFFSET
, line_colour
);
467 vline (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, y2
+ GFX_Y_OFFSET
, line_colour
);
471 if (anti_alias_gfx
&& (line_colour
== GFX_COL_WHITE
))
472 gfx_draw_aa_line (itofix(x1
), itofix(y1
), itofix(x2
), itofix(y2
));
474 line (gfx_screen
, x1
+ GFX_X_OFFSET
, y1
+ GFX_Y_OFFSET
, x2
+ GFX_X_OFFSET
, y2
+ GFX_Y_OFFSET
, line_colour
);
479 void gfx_draw_triangle (int x1
, int y1
, int x2
, int y2
, int x3
, int y3
, int col
)
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
);
487 void gfx_display_text (int x
, int y
, char *txt
)
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
);
494 void gfx_display_colour_text (int x
, int y
, char *txt
, int col
)
497 textout (gfx_screen
, datafile
[ELITE_1
].dat
, txt
, (x
/ (2 / GFX_SCALE
)) + GFX_X_OFFSET
, (y
/ (2 / GFX_SCALE
)) + GFX_Y_OFFSET
, col
);
502 void gfx_display_centre_text (int y
, char *str
, int psize
, int col
)
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
);
523 void gfx_clear_display (void)
525 rectfill (gfx_screen
, GFX_X_OFFSET
+ 1, GFX_Y_OFFSET
+ 1, 510 + GFX_X_OFFSET
, 383 + GFX_Y_OFFSET
, GFX_COL_BLACK
);
528 void gfx_clear_text_area (void)
530 rectfill (gfx_screen
, GFX_X_OFFSET
+ 1, GFX_Y_OFFSET
+ 340, 510 + GFX_X_OFFSET
, 383 + GFX_Y_OFFSET
, GFX_COL_BLACK
);
534 void gfx_clear_area (int tx
, int ty
, int bx
, int by
)
536 rectfill (gfx_screen
, tx
+ GFX_X_OFFSET
, ty
+ GFX_Y_OFFSET
,
537 bx
+ GFX_X_OFFSET
, by
+ GFX_Y_OFFSET
, GFX_COL_BLACK
);
540 void gfx_draw_rectangle (int tx
, int ty
, int bx
, int by
, int col
)
542 rectfill (gfx_screen
, tx
+ GFX_X_OFFSET
, ty
+ GFX_Y_OFFSET
,
543 bx
+ GFX_X_OFFSET
, by
+ GFX_Y_OFFSET
, col
);
547 void gfx_display_pretty_text (int tx
, int ty
, int bx
, int by
, char *txt
)
556 maxlen
= (bx
- tx
) / 8;
567 while ((str
[pos
] != ' ') && (str
[pos
] != ',') &&
568 (str
[pos
] != '.') && (str
[pos
] != '\0'))
575 for (bptr
= strbuf
; pos
>= 0; pos
--)
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
);
587 void gfx_draw_scanner (void)
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
);
596 void gfx_set_clip_region (int tx
, int ty
, int bx
, int by
)
598 set_clip (gfx_screen
, tx
+ GFX_X_OFFSET
, ty
+ GFX_Y_OFFSET
, bx
+ GFX_X_OFFSET
, by
+ GFX_Y_OFFSET
);
602 void gfx_start_render (void)
609 void gfx_render_polygon (int num_points
, int *point_list
, int face_colour
, int zavg
)
615 if (total_polys
== MAX_POLYS
)
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;
626 for (i
= 0; i
< 16; i
++)
627 poly_chain
[x
].point_list
[i
] = point_list
[i
];
632 if (zavg
> poly_chain
[start_poly
].z
)
634 poly_chain
[x
].next
= start_poly
;
639 for (i
= start_poly
; poly_chain
[i
].next
!= -1; i
= poly_chain
[i
].next
)
641 nx
= poly_chain
[i
].next
;
643 if (zavg
> poly_chain
[nx
].z
)
645 poly_chain
[i
].next
= x
;
646 poly_chain
[x
].next
= nx
;
651 poly_chain
[i
].next
= x
;
655 void gfx_render_line (int x1
, int y1
, int x2
, int y2
, int dist
, int col
)
664 gfx_render_polygon (2, point_list
, col
, dist
);
668 void gfx_finish_render (void)
675 if (total_polys
== 0)
678 for (i
= start_poly
; i
!= -1; i
= poly_chain
[i
].next
)
680 num_points
= poly_chain
[i
].no_points
;
681 pl
= poly_chain
[i
].point_list
;
682 col
= poly_chain
[i
].face_colour
;
686 gfx_draw_colour_line (pl
[0], pl
[1], pl
[2], pl
[3], col
);
690 gfx_polygon (num_points
, pl
, col
);
695 void gfx_polygon (int num_points
, int *poly_list
, int face_colour
)
702 for (i
= 0; i
< num_points
; i
++)
704 poly_list
[x
] += GFX_X_OFFSET
;
705 poly_list
[y
] += GFX_Y_OFFSET
;
710 polygon (gfx_screen
, num_points
, poly_list
, face_colour
);
714 void gfx_draw_sprite (int sprite_no
, int x
, int y
)
721 sprite_bmp
= datafile
[GRNDOT
].dat
;
725 sprite_bmp
= datafile
[REDDOT
].dat
;
729 sprite_bmp
= datafile
[SAFE
].dat
;
733 sprite_bmp
= datafile
[ELITETXT
].dat
;
737 sprite_bmp
= datafile
[ECM
].dat
;
741 sprite_bmp
= datafile
[BLAKE
].dat
;
744 case IMG_MISSILE_GREEN
:
745 sprite_bmp
= datafile
[MISSILE_G
].dat
;
748 case IMG_MISSILE_YELLOW
:
749 sprite_bmp
= datafile
[MISSILE_Y
].dat
;
752 case IMG_MISSILE_RED
:
753 sprite_bmp
= datafile
[MISSILE_R
].dat
;
761 x
= ((256 * GFX_SCALE
) - sprite_bmp
->w
) / 2;
763 draw_sprite (gfx_screen
, sprite_bmp
, x
+ GFX_X_OFFSET
, y
+ GFX_Y_OFFSET
);
767 int gfx_request_file (char *title
, char *path
, char *ext
)
772 okay
= file_select (title
, path
, ext
);