chiark / gitweb /
Proper Subversion configuration.
[newkind] / alg_gfx.c
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
28 BITMAP *gfx_screen;
29 volatile int frame_count;
30 DATAFILE *datafile;
31 BITMAP *scanner_image;
32
33 #define MAX_POLYS       100
34
35 static int start_poly;
36 static int total_polys;
37
38 struct poly_data
39 {
40         int z;
41         int no_points;
42         int face_colour;
43         int point_list[16];
44         int next;
45 };
46
47 static struct poly_data poly_chain[MAX_POLYS];
48
49
50
51
52 void frame_timer (void)
53 {
54         frame_count++;
55 }
56 END_OF_FUNCTION(frame_timer);
57
58
59
60 int 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
86         rv = set_gfx_mode(prefer_window ?
87                             GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT,
88                           800, 600, 0, 0);
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
138 void 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
150 void 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
162 void gfx_acquire_screen (void)
163 {
164         acquire_bitmap (gfx_screen);
165 }
166
167
168 void gfx_release_screen (void)
169 {
170         release_bitmap(gfx_screen);
171 }
172
173 void 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
180 void 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
186 void 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
206 void 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  
282 void 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
425 void 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
435 void 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
457 void 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
479 void 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
487 void 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
494 void 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
502 void 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
523 void 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
528 void 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
534 void 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
540 void 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
547 void 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
587 void gfx_draw_scanner (void)
588 {
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);
594 }
595
596 void 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
602 void gfx_start_render (void)
603 {
604         start_poly = 0;
605         total_polys = 0;
606 }
607
608
609 void 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
655 void 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
668 void 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
695 void 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
714 void 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
767 int 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