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(GFX_AUTODETECT, 800, 600, 0, 0);
91 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
92 allegro_message("Unable to set graphics mode.");
96 datafile = load_datafile("elite.dat");
99 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
100 allegro_message("Error loading %s!\n", "elite.dat");
104 scanner_image = load_bitmap(scanner_filename, the_palette);
107 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
108 allegro_message("Error reading scanner bitmap file.\n");
112 /* select the scanner palette */
113 set_palette(the_palette);
115 /* Create the screen buffer bitmap */
116 gfx_screen = create_bitmap (SCREEN_W, SCREEN_H);
120 blit (scanner_image, gfx_screen, 0, 0, GFX_X_OFFSET, 385+GFX_Y_OFFSET, scanner_image->w, scanner_image->h);
121 gfx_draw_line (0, 0, 0, 384);
122 gfx_draw_line (0, 0, 511, 0);
123 gfx_draw_line (511, 0, 511, 384);
125 /* Install a timer to regulate the speed of the game... */
127 LOCK_VARIABLE(frame_count);
128 LOCK_FUNCTION(frame_timer);
130 install_int (frame_timer, speed_cap);
136 void gfx_graphics_shutdown (void)
138 destroy_bitmap(scanner_image);
139 destroy_bitmap(gfx_screen);
140 unload_datafile(datafile);
145 * Blit the back buffer to the screen.
148 void gfx_update_screen (void)
150 while (frame_count < 1)
155 blit (gfx_screen, screen, GFX_X_OFFSET, GFX_Y_OFFSET, GFX_X_OFFSET, GFX_Y_OFFSET, 512, 512);
160 void gfx_acquire_screen (void)
162 acquire_bitmap (gfx_screen);
166 void gfx_release_screen (void)
168 release_bitmap(gfx_screen);
171 void gfx_fast_plot_pixel (int x, int y, int col)
173 // _putpixel(gfx_screen, x, y, col);
174 gfx_screen->line[y][x] = col;
178 void gfx_plot_pixel (int x, int y, int col)
180 putpixel (gfx_screen, x + GFX_X_OFFSET, y + GFX_Y_OFFSET, col);
184 void gfx_draw_filled_circle (int cx, int cy, int radius, int circle_colour)
186 circlefill (gfx_screen, cx + GFX_X_OFFSET, cy + GFX_Y_OFFSET, radius, circle_colour);
194 #define trunc(x) ((x) & ~65535)
195 #define frac(x) ((x) & 65535)
196 #define invfrac(x) (65535-frac(x))
197 #define plot(x,y,c) putpixel(gfx_screen, (x), (y), (c)+AA_BASE)
200 * Draw anti-aliased wireframe circle.
204 void gfx_draw_aa_circle(int cx, int cy, int radius)
213 radius >>= (16 - AA_BITS);
222 sx = cx + (x >> AA_BITS); sy = cy + (y >> AA_BITS);
224 plot(sx, sy, AA_AND - (x&AA_AND));
225 plot(sx + 1, sy, x&AA_AND);
227 sy = cy - (y >> AA_BITS);
229 plot(sx, sy, AA_AND - (x&AA_AND));
230 plot(sx + 1, sy, x&AA_AND);
232 sx = cx - (x >> AA_BITS);
234 plot(sx, sy, AA_AND - (x&AA_AND));
235 plot(sx - 1, sy, x&AA_AND);
237 sy = cy + (y >> AA_BITS);
239 plot(sx, sy, AA_AND - (x&AA_AND));
240 plot(sx - 1, sy, x&AA_AND);
243 sx = cx + (y >> AA_BITS); sy = cy + (x >> AA_BITS);
245 plot(sx, sy, AA_AND - (x&AA_AND));
246 plot(sx, sy + 1, x&AA_AND);
248 sy = cy - (x >> AA_BITS);
250 plot(sx, sy, AA_AND - (x&AA_AND));
251 plot(sx, sy - 1, x&AA_AND);
253 sx = cx - (y >> AA_BITS);
255 plot(sx, sy, AA_AND - (x&AA_AND));
256 plot(sx, sy - 1, x&AA_AND);
258 sy = cy + (x >> AA_BITS);
260 plot(sx, sy, AA_AND - (x&AA_AND));
261 plot(sx, sy + 1, x&AA_AND);
263 s += AA_AND+1 + (y << (AA_BITS+1)) + ((1 << (AA_BITS+2))-2);
276 * Draw anti-aliased line.
280 void gfx_draw_aa_line (int x1, int y1, int x2, int y2)
283 fixed xgap, ygap, xend, yend, xf, yf;
284 fixed brightness1, brightness2, swap;
286 int x, y, ix1, ix2, iy1, iy2;
288 x1 += itofix(GFX_X_OFFSET);
289 x2 += itofix(GFX_X_OFFSET);
290 y1 += itofix(GFX_Y_OFFSET);
291 y2 += itofix(GFX_Y_OFFSET);
296 if (abs(xd) > abs(yd))
300 swap = x1; x1 = x2; x2 = swap;
301 swap = y1; y1 = y2; y2 = swap;
310 xend = trunc(x1 + 32768);
311 yend = y1 + fmul(grad, xend-x1);
313 xgap = invfrac(x1+32768);
318 brightness1 = fmul(invfrac(yend), xgap);
319 brightness2 = fmul(frac(yend), xgap);
321 plot(ix1, iy1, brightness1 >> (16-AA_BITS));
322 plot(ix1, iy1+1, brightness2 >> (16-AA_BITS));
328 xend = trunc(x2 + 32768);
329 yend = y2 + fmul(grad, xend-x2);
331 xgap = invfrac(x2 - 32768);
336 brightness1 = fmul(invfrac(yend), xgap);
337 brightness2 = fmul(frac(yend), xgap);
339 plot(ix2, iy2, brightness1 >> (16-AA_BITS));
340 plot(ix2, iy2+1, brightness2 >> (16-AA_BITS));
342 for(x = ix1+1; x <= ix2-1; x++)
344 brightness1 = invfrac(yf);
345 brightness2 = frac(yf);
347 plot(x, (yf >> 16), brightness1 >> (16-AA_BITS));
348 plot(x, 1+(yf >> 16), brightness2 >> (16-AA_BITS));
357 swap = x1; x1 = x2; x2 = swap;
358 swap = y1; y1 = y2; y2 = swap;
367 yend = trunc(y1 + 32768);
368 xend = x1 + fmul(grad, yend-y1);
370 ygap = invfrac(y1+32768);
375 brightness1 = fmul(invfrac(xend), ygap);
376 brightness2 = fmul(frac(xend), ygap);
378 plot(ix1, iy1, brightness1 >> (16-AA_BITS));
379 plot(ix1+1, iy1, brightness2 >> (16-AA_BITS));
385 yend = trunc(y2 + 32768);
386 xend = x2 + fmul(grad, yend-y2);
388 ygap = invfrac(y2 - 32768);
393 brightness1 = fmul(invfrac(xend), ygap);
394 brightness2 = fmul(frac(xend), ygap);
396 plot(ix2, iy2, brightness1 >> (16-AA_BITS));
397 plot(ix2+1, iy2, brightness2 >> (16-AA_BITS));
399 for(y = iy1+1; y <= iy2-1; y++)
401 brightness1 = invfrac(xf);
402 brightness2 = frac(xf);
404 plot((xf >> 16), y, brightness1 >> (16-AA_BITS));
405 plot(1+(xf >> 16), y, brightness2 >> (16-AA_BITS));
423 void gfx_draw_circle (int cx, int cy, int radius, int circle_colour)
425 if (anti_alias_gfx && (circle_colour == GFX_COL_WHITE))
426 gfx_draw_aa_circle (cx, cy, itofix(radius));
428 circle (gfx_screen, cx + GFX_X_OFFSET, cy + GFX_Y_OFFSET, radius, circle_colour);
433 void gfx_draw_line (int x1, int y1, int x2, int y2)
437 hline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, GFX_COL_WHITE);
443 vline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, y2 + GFX_Y_OFFSET, GFX_COL_WHITE);
448 gfx_draw_aa_line (itofix(x1), itofix(y1), itofix(x2), itofix(y2));
450 line (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET, GFX_COL_WHITE);
455 void gfx_draw_colour_line (int x1, int y1, int x2, int y2, int line_colour)
459 hline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, line_colour);
465 vline (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, y2 + GFX_Y_OFFSET, line_colour);
469 if (anti_alias_gfx && (line_colour == GFX_COL_WHITE))
470 gfx_draw_aa_line (itofix(x1), itofix(y1), itofix(x2), itofix(y2));
472 line (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET, line_colour);
477 void gfx_draw_triangle (int x1, int y1, int x2, int y2, int x3, int y3, int col)
479 triangle (gfx_screen, x1 + GFX_X_OFFSET, y1 + GFX_Y_OFFSET, x2 + GFX_X_OFFSET, y2 + GFX_Y_OFFSET,
480 x3 + GFX_X_OFFSET, y3 + GFX_Y_OFFSET, col);
485 void gfx_display_text (int x, int y, char *txt)
488 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);
492 void gfx_display_colour_text (int x, int y, char *txt, int col)
495 textout (gfx_screen, datafile[ELITE_1].dat, txt, (x / (2 / GFX_SCALE)) + GFX_X_OFFSET, (y / (2 / GFX_SCALE)) + GFX_Y_OFFSET, col);
500 void gfx_display_centre_text (int y, char *str, int psize, int col)
517 textout_centre (gfx_screen, datafile[txt_size].dat, str, (128 * GFX_SCALE) + GFX_X_OFFSET, (y / (2 / GFX_SCALE)) + GFX_Y_OFFSET, txt_colour);
521 void gfx_clear_display (void)
523 rectfill (gfx_screen, GFX_X_OFFSET + 1, GFX_Y_OFFSET + 1, 510 + GFX_X_OFFSET, 383 + GFX_Y_OFFSET, GFX_COL_BLACK);
526 void gfx_clear_text_area (void)
528 rectfill (gfx_screen, GFX_X_OFFSET + 1, GFX_Y_OFFSET + 340, 510 + GFX_X_OFFSET, 383 + GFX_Y_OFFSET, GFX_COL_BLACK);
532 void gfx_clear_area (int tx, int ty, int bx, int by)
534 rectfill (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET,
535 bx + GFX_X_OFFSET, by + GFX_Y_OFFSET, GFX_COL_BLACK);
538 void gfx_draw_rectangle (int tx, int ty, int bx, int by, int col)
540 rectfill (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET,
541 bx + GFX_X_OFFSET, by + GFX_Y_OFFSET, col);
545 void gfx_display_pretty_text (int tx, int ty, int bx, int by, char *txt)
554 maxlen = (bx - tx) / 8;
565 while ((str[pos] != ' ') && (str[pos] != ',') &&
566 (str[pos] != '.') && (str[pos] != '\0'))
573 for (bptr = strbuf; pos >= 0; pos--)
579 textout (gfx_screen, datafile[ELITE_1].dat, strbuf, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET, GFX_COL_WHITE);
580 ty += (8 * GFX_SCALE);
585 void gfx_draw_scanner (void)
587 blit (scanner_image, gfx_screen, 0, 0, GFX_X_OFFSET, 385+GFX_Y_OFFSET, scanner_image->w, scanner_image->h);
590 void gfx_set_clip_region (int tx, int ty, int bx, int by)
592 set_clip (gfx_screen, tx + GFX_X_OFFSET, ty + GFX_Y_OFFSET, bx + GFX_X_OFFSET, by + GFX_Y_OFFSET);
596 void gfx_start_render (void)
603 void gfx_render_polygon (int num_points, int *point_list, int face_colour, int zavg)
609 if (total_polys == MAX_POLYS)
615 poly_chain[x].no_points = num_points;
616 poly_chain[x].face_colour = face_colour;
617 poly_chain[x].z = zavg;
618 poly_chain[x].next = -1;
620 for (i = 0; i < 16; i++)
621 poly_chain[x].point_list[i] = point_list[i];
626 if (zavg > poly_chain[start_poly].z)
628 poly_chain[x].next = start_poly;
633 for (i = start_poly; poly_chain[i].next != -1; i = poly_chain[i].next)
635 nx = poly_chain[i].next;
637 if (zavg > poly_chain[nx].z)
639 poly_chain[i].next = x;
640 poly_chain[x].next = nx;
645 poly_chain[i].next = x;
649 void gfx_render_line (int x1, int y1, int x2, int y2, int dist, int col)
658 gfx_render_polygon (2, point_list, col, dist);
662 void gfx_finish_render (void)
669 if (total_polys == 0)
672 for (i = start_poly; i != -1; i = poly_chain[i].next)
674 num_points = poly_chain[i].no_points;
675 pl = poly_chain[i].point_list;
676 col = poly_chain[i].face_colour;
680 gfx_draw_colour_line (pl[0], pl[1], pl[2], pl[3], col);
684 gfx_polygon (num_points, pl, col);
689 void gfx_polygon (int num_points, int *poly_list, int face_colour)
696 for (i = 0; i < num_points; i++)
698 poly_list[x] += GFX_X_OFFSET;
699 poly_list[y] += GFX_Y_OFFSET;
704 polygon (gfx_screen, num_points, poly_list, face_colour);
708 void gfx_draw_sprite (int sprite_no, int x, int y)
715 sprite_bmp = datafile[GRNDOT].dat;
719 sprite_bmp = datafile[REDDOT].dat;
723 sprite_bmp = datafile[SAFE].dat;
727 sprite_bmp = datafile[ELITETXT].dat;
731 sprite_bmp = datafile[ECM].dat;
735 sprite_bmp = datafile[BLAKE].dat;
738 case IMG_MISSILE_GREEN:
739 sprite_bmp = datafile[MISSILE_G].dat;
742 case IMG_MISSILE_YELLOW:
743 sprite_bmp = datafile[MISSILE_Y].dat;
746 case IMG_MISSILE_RED:
747 sprite_bmp = datafile[MISSILE_R].dat;
755 x = ((256 * GFX_SCALE) - sprite_bmp->w) / 2;
757 draw_sprite (gfx_screen, sprite_bmp, x + GFX_X_OFFSET, y + GFX_Y_OFFSET);
761 int gfx_request_file (char *title, char *path, char *ext)
766 okay = file_select (title, path, ext);