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);