]> 4ch.mooo.com Git - 16.git/blob - 16/modex16/modex16.c
I fixed the keyboard bug~ ^^
[16.git] / 16 / modex16 / modex16.c
1 #include <dos.h>\r
2 #include <string.h>\r
3 #include <mem.h>\r
4 #include <conio.h>\r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 #include "modex16.h"\r
8 \r
9 \r
10 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
11 \r
12 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
13 static byte tmppal[PAL_SIZE];\r
14 static struct pcxHeader {\r
15     byte id;\r
16     byte version;\r
17     byte encoding;\r
18     byte bpp;\r
19     word xmin;\r
20     word ymin;\r
21     word xmax;\r
22     word ymax;\r
23     word hres;\r
24     word vres;\r
25     byte pal16[48];\r
26     byte res1;\r
27     word bpplane;\r
28     word palType;\r
29     word hScreenSize;\r
30     word vScreenSize;\r
31     byte padding[54];\r
32 };\r
33 \r
34 \r
35 static void\r
36 vgaSetMode(byte mode)\r
37 {\r
38   union REGS regs;\r
39 \r
40   regs.h.ah = SET_MODE;\r
41   regs.h.al = mode;\r
42   int86(VIDEO_INT, &regs, &regs);\r
43 }\r
44 \r
45 \r
46 /* -========================= Entry  Points ==========================- */\r
47 void\r
48 modexEnter() {\r
49     word i;\r
50     dword far*ptr=(dword far*)VGA;      /* used for faster screen clearing */\r
51     word CRTParms[] = {\r
52         0x0d06,         /* vertical total */\r
53         0x3e07,         /* overflow (bit 8 of vertical counts) */\r
54         0x4109,         /* cell height (2 to double-scan */\r
55         0xea10,         /* v sync start */\r
56         0xac11,         /* v sync end and protect cr0-cr7 */\r
57         0xdf12,         /* vertical displayed */\r
58         0x0014,         /* turn off dword mode */\r
59         0xe715,         /* v blank start */\r
60         0x0616,         /* v blank end */\r
61         0xe317          /* turn on byte mode */\r
62     };\r
63     int CRTParmCount = sizeof(CRTParms) / sizeof(CRTParms[0]);\r
64 \r
65     /* TODO save current video mode and palette */\r
66     vgaSetMode(VGA_256_COLOR_MODE);\r
67 \r
68     /* disable chain4 mode */\r
69     outpw(SC_INDEX, 0x0604);\r
70 \r
71     /* synchronous reset while setting Misc Output */\r
72     outpw(SC_INDEX, 0x0100);\r
73 \r
74     /* select 25 MHz dot clock & 60 Hz scanning rate */\r
75     outp(MISC_OUTPUT, 0xe3);\r
76 \r
77     /* undo reset (restart sequencer) */\r
78     outpw(SC_INDEX, 0x0300);\r
79 \r
80     /* reprogram the CRT controller */\r
81     outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
82     outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
83 \r
84     /* send the CRTParms */\r
85     for(i=0; i<CRTParmCount; i++) {\r
86         outpw(CRTC_INDEX, CRTParms[i]);\r
87     }\r
88 \r
89     /* clear video memory */\r
90     outpw(SC_INDEX, 0x0f02);\r
91     for(i=0; i<0x8000; i++) {\r
92         ptr[i] = 0x0000;\r
93     }\r
94 }\r
95 \r
96 \r
97 void\r
98 modexLeave() {\r
99     /* TODO restore original mode and palette */\r
100     vgaSetMode(TEXT_MODE);\r
101 }\r
102 \r
103 \r
104 page_t\r
105 modexDefaultPage() {\r
106     page_t page;\r
107 \r
108     /* default page values */\r
109     page.data = VGA;\r
110     page.dx = 0;\r
111     page.dy = 0;\r
112     page.width = SCREEN_WIDTH;\r
113     page.height = SCREEN_HEIGHT;\r
114 \r
115     return page;\r
116 }\r
117 \r
118 /* returns the next page in contiguous memory\r
119  * the next page will be the same size as p, by default\r
120  */\r
121 page_t\r
122 modexNextPage(page_t *p) {\r
123     page_t result;\r
124 \r
125     result.data = p->data + (p->width/4)*p->height;  /* compute the offset */\r
126     result.dx = 0;\r
127     result.dy = 0;\r
128     result.width = p->width;\r
129     result.height = p->height;\r
130 \r
131     return result;\r
132 }\r
133 \r
134 \r
135 void\r
136 modexShowPage(page_t *page) {\r
137     word high_address;\r
138     word low_address;\r
139     word offset;\r
140     byte crtcOffset;\r
141 \r
142     /* calculate offset */\r
143     offset = (word) page->data;\r
144     offset += page->dy * (page->width >> 2 );\r
145     offset += page->dx >> 2;\r
146 \r
147     /* calculate crtcOffset according to virtual width */\r
148     crtcOffset = page->width >> 3;\r
149 \r
150     high_address = HIGH_ADDRESS | (offset & 0xff00);\r
151     low_address  = LOW_ADDRESS  | (offset << 8);\r
152 \r
153     /* wait for appropriate timing and then program CRTC */\r
154     while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
155     outpw(CRTC_INDEX, high_address);\r
156     outpw(CRTC_INDEX, low_address);\r
157     outp(CRTC_INDEX, 0x13);\r
158     outp(CRTC_DATA, crtcOffset);\r
159 \r
160     /*  wait for one retrace */\r
161     while (!(inp(INPUT_STATUS_1) & VRETRACE)); \r
162 \r
163     /* do PEL panning here */\r
164     outp(AC_INDEX, 0x33);\r
165     outp(AC_INDEX, (page->dx & 0x03) << 1);\r
166 }\r
167 \r
168 \r
169 void\r
170 modexPanPage(page_t *page, int dx, int dy) {\r
171     page->dx = dx;\r
172     page->dy = dy;\r
173 }\r
174 \r
175 \r
176 void\r
177 modexSelectPlane(byte plane) {\r
178     outp(SC_INDEX, MAP_MASK);          /* select plane */\r
179     outp(SC_DATA,  plane);\r
180 }\r
181 \r
182 \r
183 void\r
184 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
185     word pageOff = (word) page->data;\r
186     word xoff=x/4;       /* xoffset that begins each row */\r
187     word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
188     word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */\r
189     word nextRow = page->width/4-scanCount-1;  /* loc of next row */\r
190     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
191     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
192     byte left = lclip[x&0x03];\r
193     byte right = rclip[(x+w)&0x03];\r
194 \r
195     /* handle the case which requires an extra group */\r
196     if((x & 0x03) && !((x+w) & 0x03)) {\r
197       right=0x0f;\r
198     }\r
199 \r
200     __asm {\r
201                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
202                 MOV ES, AX\r
203                 MOV DI, poffset         ; go to the first pixel\r
204                 MOV DX, SC_INDEX        ; point to the map mask\r
205                 MOV AL, MAP_MASK\r
206                 OUT DX, AL\r
207                 INC DX\r
208                 MOV AL, color           ; get ready to write colors\r
209         SCAN_START:\r
210                 MOV CX, scanCount       ; count the line\r
211                 MOV BL, AL              ; remember color\r
212                 MOV AL, left            ; do the left clip\r
213                 OUT DX, AL              ; set the left clip\r
214                 MOV AL, BL              ; restore color\r
215                 STOSB                   ; write the color\r
216                 DEC CX\r
217                 JZ SCAN_DONE            ; handle 1 group stuff\r
218 \r
219                 ;-- write the main body of the scanline\r
220                 MOV BL, AL              ; remember color\r
221                 MOV AL, 0x0f            ; write to all pixels\r
222                 OUT DX, AL\r
223                 MOV AL, BL              ; restore color\r
224                 REP STOSB               ; write the color\r
225         SCAN_DONE:\r
226                 MOV BL, AL              ; remeber color\r
227                 MOV AL, right\r
228                 OUT DX, AL              ; do the right clip\r
229                 MOV AL, BL              ; restore color\r
230                 STOSB                   ; write pixel\r
231                 ADD DI, nextRow         ; go to the next row\r
232                 DEC h\r
233                 JNZ SCAN_START\r
234     }\r
235 }\r
236 \r
237 \r
238 void\r
239 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {\r
240     /* draw the region (the entire freakin bitmap) */\r
241     modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
242 }\r
243 \r
244 \r
245 void\r
246 modexDrawBmpRegion(page_t *page, int x, int y,\r
247                    int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
248     word poffset = (word) page->data  + y*(page->width/4) + x/4;\r
249     byte *data = bmp->data;\r
250     word bmpOffset = (word) data + ry * bmp->width + rx;\r
251     word width = rw;\r
252     word height = rh;\r
253     byte plane = 1 << ((byte) x & 0x03);\r
254     word scanCount = width/4 + (width%4 ? 1 :0);\r
255     word nextPageRow = page->width/4 - scanCount;\r
256     word nextBmpRow = (word) bmp->width - width;\r
257     word rowCounter;\r
258     byte planeCounter = 4;\r
259 \r
260     __asm {\r
261                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
262                 MOV ES, AX\r
263 \r
264                 MOV DX, SC_INDEX        ; point at the map mask register\r
265                 MOV AL, MAP_MASK        ;\r
266                 OUT DX, AL              ;\r
267 \r
268         PLANE_LOOP:\r
269                 MOV DX, SC_DATA         ; select the current plane\r
270                 MOV AL, plane           ;\r
271                 OUT DX, AL              ;\r
272 \r
273                 ;-- begin plane painting\r
274                 MOV AX, height          ; start the row counter\r
275                 MOV rowCounter, AX      ; \r
276                 MOV DI, poffset         ; go to the first pixel\r
277                 MOV SI, bmpOffset       ; go to the bmp pixel\r
278         ROW_LOOP:\r
279                 MOV CX, width           ; count the columns\r
280         SCAN_LOOP:\r
281                 MOVSB                   ; copy the pixel\r
282                 SUB CX, 3               ; we skip the next 3\r
283                 ADD SI, 3               ; skip the bmp pixels\r
284                 LOOP SCAN_LOOP          ; finish the scan\r
285 \r
286                 MOV AX, nextPageRow\r
287                 ADD DI, AX              ; go to the next row on screen\r
288                 MOV AX, nextBmpRow\r
289                 ADD SI, AX              ; go to the next row on bmp\r
290 \r
291                 DEC rowCounter\r
292                 JNZ ROW_LOOP            ; do all the rows\r
293                 ;-- end plane painting\r
294 \r
295                 MOV AL, plane           ; advance to the next plane\r
296                 SHL AL, 1               ;\r
297                 AND AL, 0x0f            ; mask the plane properly\r
298                 MOV plane, AL           ; store the plane\r
299 \r
300                 INC bmpOffset           ; start bmp at the right spot\r
301 \r
302                 DEC planeCounter\r
303                 JNZ PLANE_LOOP          ; do all 4 planes\r
304     }\r
305 }\r
306 \r
307 \r
308 void\r
309 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
310     /* draw the whole sprite */\r
311     modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
312 }\r
313 \r
314 void\r
315 modexDrawSpriteRegion(page_t *page, int x, int y,\r
316                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
317     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
318     byte *data = bmp->data;\r
319     word bmpOffset = (word) data + ry * bmp->width + rx;\r
320     word width = rw;\r
321     word height = rh;\r
322     byte plane = 1 << ((byte) x & 0x03);\r
323     word scanCount = width/4 + (width%4 ? 1 :0);\r
324     word nextPageRow = page->width/4 - scanCount;\r
325     word nextBmpRow = (word) bmp->width - width;\r
326     word rowCounter;\r
327     byte planeCounter = 4;\r
328 \r
329     __asm {\r
330                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
331                 MOV ES, AX\r
332 \r
333                 MOV DX, SC_INDEX        ; point at the map mask register\r
334                 MOV AL, MAP_MASK        ;\r
335                 OUT DX, AL              ;\r
336 \r
337         PLANE_LOOP:\r
338                 MOV DX, SC_DATA         ; select the current plane\r
339                 MOV AL, plane           ;\r
340                 OUT DX, AL              ;\r
341 \r
342                 ;-- begin plane painting\r
343                 MOV AX, height          ; start the row counter\r
344                 MOV rowCounter, AX      ; \r
345                 MOV DI, poffset         ; go to the first pixel\r
346                 MOV SI, bmpOffset       ; go to the bmp pixel\r
347         ROW_LOOP:\r
348                 MOV CX, width           ; count the columns\r
349         SCAN_LOOP:\r
350                 LODSB\r
351                 DEC SI\r
352                 CMP AL, 0\r
353                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
354 \r
355                 INC DI                  ; skip the transparent pixel\r
356                 ADD SI, 1\r
357                 JMP NEXT_PIXEL\r
358         DRAW_PIXEL:\r
359                 MOVSB                   ; copy the pixel\r
360         NEXT_PIXEL:\r
361                 SUB CX, 3               ; we skip the next 3\r
362                 ADD SI, 3               ; skip the bmp pixels\r
363                 LOOP SCAN_LOOP          ; finish the scan\r
364 \r
365                 MOV AX, nextPageRow\r
366                 ADD DI, AX              ; go to the next row on screen\r
367                 MOV AX, nextBmpRow\r
368                 ADD SI, AX              ; go to the next row on bmp\r
369 \r
370                 DEC rowCounter\r
371                 JNZ ROW_LOOP            ; do all the rows\r
372                 ;-- end plane painting\r
373 \r
374                 MOV AL, plane           ; advance to the next plane\r
375                 SHL AL, 1               ;\r
376                 AND AL, 0x0f            ; mask the plane properly\r
377                 MOV plane, AL           ; store the plane\r
378 \r
379                 INC bmpOffset           ; start bmp at the right spot\r
380 \r
381                 DEC planeCounter\r
382                 JNZ PLANE_LOOP          ; do all 4 planes\r
383     }\r
384 }\r
385 \r
386 \r
387 /* copy a region of video memory from one page to another.\r
388  * It assumes that the left edge of the tile is the same on both\r
389  * regions and the memory areas do not overlap.\r
390  */\r
391 void\r
392 modexCopyPageRegion(page_t *dest, page_t *src,\r
393                     word sx, word sy,\r
394                     word dx, word dy,\r
395                     word width, word height)\r
396 {\r
397     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
398     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
399     word scans   = width/4;\r
400     word nextSrcRow = src->width/4 - scans - 1;\r
401     word nextDestRow = dest->width/4 - scans - 1;\r
402     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
403     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
404     byte left = lclip[sx&0x03];\r
405     byte right = rclip[(sx+width)&0x03];\r
406 \r
407     __asm {\r
408                 MOV AX, SCREEN_SEG      ; work in the vga space\r
409                 MOV ES, AX              ;\r
410                 MOV DI, doffset         ;\r
411                 MOV SI, soffset         ;\r
412 \r
413                 MOV DX, GC_INDEX        ; turn off cpu bits\r
414                 MOV AX, 0008h           ;\r
415                 OUT DX, AX\r
416 \r
417                 MOV AX, SC_INDEX        ; point to the mask register\r
418                 MOV DX, AX              ;\r
419                 MOV AL, MAP_MASK        ;\r
420                 OUT DX, AL              ;\r
421                 INC DX                  ;\r
422 \r
423         ROW_START:\r
424                 PUSH DS\r
425                 MOV AX, ES\r
426                 MOV DS, AX\r
427                 MOV CX, scans           ; the number of latches\r
428 \r
429                 MOV AL, left            ; do the left column\r
430                 OUT DX, AL              ;\r
431                 MOVSB                   ;\r
432                 DEC CX                  ;\r
433 \r
434                 MOV AL, 0fh             ; do the inner columns\r
435                 OUT DX, AL\r
436                 REP MOVSB               ; copy the pixels\r
437 \r
438                 MOV AL, right           ; do the right column\r
439                 OUT DX, AL\r
440                 MOVSB\r
441                 POP DS\r
442 \r
443                 MOV AX, SI              ; go the start of the next row\r
444                 ADD AX, nextSrcRow      ;\r
445                 MOV SI, AX              ;\r
446                 MOV AX, DI              ;\r
447                 ADD AX, nextDestRow     ;\r
448                 MOV DI, AX              ;\r
449 \r
450                 DEC height              ; do the rest of the actions\r
451                 JNZ ROW_START           ;\r
452 \r
453                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
454                 MOV AL, 0ffh            ; none from latches\r
455                 OUT DX, AL              ;\r
456     }\r
457 }\r
458 \r
459 \r
460 /* fade and flash */\r
461 void\r
462 modexFadeOn(word fade, byte *palette) {\r
463     fadePalette(-fade, 64, 64/fade+1, palette);\r
464 }\r
465 \r
466 \r
467 void\r
468 modexFadeOff(word fade, byte *palette) {\r
469     fadePalette(fade, 0, 64/fade+1, palette);\r
470 }\r
471 \r
472 \r
473 void\r
474 modexFlashOn(word fade, byte *palette) {\r
475     fadePalette(fade, -64, 64/fade+1, palette);\r
476 }\r
477 \r
478 \r
479 void\r
480 modexFlashOff(word fade, byte *palette) {\r
481     fadePalette(-fade, 0, 64/fade+1, palette);\r
482 }\r
483 \r
484 \r
485 static void\r
486 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
487     word i;\r
488     byte dim = start;\r
489 \r
490     /* handle the case where we just update */\r
491     if(iter == 0) {\r
492         modexPalUpdate(palette);\r
493         return;\r
494     }\r
495 \r
496     while(iter > 0) {  /* FadeLoop */\r
497         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
498             tmppal[i] = palette[i] - dim;\r
499             if(tmppal[i] > 127) {\r
500                 tmppal[i] = 0;\r
501             } else if(tmppal[i] > 63) {\r
502                 tmppal[i] = 63;\r
503             }\r
504         }\r
505         modexPalUpdate(tmppal);\r
506         iter--;\r
507         dim += fade;\r
508     }\r
509 }\r
510 \r
511 \r
512 /* save and load */\r
513 void\r
514 modexPalSave(byte *palette) {\r
515     int  i;\r
516 \r
517     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
518     for(i=0; i<PAL_SIZE; i++) {\r
519         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
520     }\r
521 }\r
522 \r
523 \r
524 byte *\r
525 modexNewPal() {\r
526     byte *ptr;\r
527     ptr = malloc(PAL_SIZE);\r
528 \r
529     /* handle errors */\r
530     if(!ptr) {\r
531         printf("Could not allocate palette.\n");\r
532         exit(-1);\r
533     }\r
534 \r
535     return ptr;\r
536 }\r
537 \r
538 \r
539 void\r
540 modexLoadPalFile(byte *filename, byte **palette) {\r
541     FILE *file;\r
542     byte *ptr;\r
543 \r
544     /* free the palette if it exists */\r
545     if(*palette) {\r
546         free(*palette);\r
547     }\r
548 \r
549     /* allocate the new palette */\r
550     *palette = modexNewPal();\r
551 \r
552     /* open the file */\r
553     file = fopen(filename, "rb");\r
554     if(!file) {\r
555         printf("Could not open palette file: %s\n", filename);\r
556         exit(-2);\r
557     }\r
558 \r
559     /* read the file */\r
560     ptr = *palette;\r
561     while(!feof(file)) {\r
562         *ptr++ = fgetc(file);\r
563     }\r
564 \r
565     fclose(file);\r
566 }\r
567 \r
568 \r
569 void\r
570 modexSavePalFile(char *filename, byte *pal) {\r
571     unsigned int i;\r
572     FILE *file;\r
573 \r
574     /* open the file for writing */\r
575     file = fopen(filename, "wb");\r
576     if(!file) {\r
577         printf("Could not open %s for writing\n", filename);\r
578         exit(-2);\r
579     }\r
580 \r
581     /* write the data to the file */\r
582     fwrite(pal, 1, PAL_SIZE, file);\r
583     fclose(file);\r
584 }\r
585 \r
586 \r
587 /* blanking */\r
588 void\r
589 modexPalBlack() {\r
590     fadePalette(-1, 64, 1, tmppal);\r
591 }\r
592 \r
593 \r
594 void\r
595 modexPalWhite() {\r
596     fadePalette(-1, -64, 1, tmppal);\r
597 }\r
598 \r
599 \r
600 /* utility */\r
601 void\r
602 modexPalUpdate(byte *p) {\r
603     int i;\r
604     modexWaitBorder();\r
605     outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
606     for(i=0; i<PAL_SIZE/2; i++) {\r
607         outp(PAL_DATA_REG, p[i]);\r
608     }\r
609     modexWaitBorder();      /* waits one retrace -- less flicker */\r
610     for(i=PAL_SIZE/2; i<PAL_SIZE; i++) {\r
611         outp(PAL_DATA_REG, p[i]);\r
612     }\r
613 }\r
614 \r
615 \r
616 void\r
617 modexWaitBorder() {\r
618     while(inp(INPUT_STATUS_1)  & 8)  {\r
619         /* spin */\r
620     }\r
621 \r
622     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
623         /* spin */\r
624     }\r
625 }\r
626 \r
627 \r
628 bitmap_t\r
629 modexLoadPcx(char *filename) {\r
630     FILE *file;\r
631     bitmap_t result;\r
632     struct pcxHeader head;\r
633     long bufSize;\r
634     int index;\r
635     byte count, val;\r
636 \r
637     /* open the PCX file for reading */\r
638     file = fopen(filename, "rb");\r
639     if(!file) {\r
640         printf("Could not open %s for reading.\n", filename);\r
641         exit(-2);\r
642     }\r
643 \r
644     /* read the header */\r
645     fread(&head, sizeof(char), sizeof(struct pcxHeader), file);\r
646 \r
647     /* make sure this  is 8bpp */\r
648     if(head.bpp != 8) {\r
649         printf("I only know how to handle 8bpp pcx files!\n");\r
650         fclose(file);\r
651         exit(-2);\r
652     }\r
653 \r
654     /* allocate the buffer */\r
655     result.width = head.xmax - head.xmin + 1;\r
656     result.height = head.ymax - head.ymin + 1;\r
657     bufSize = result.width * result.height;\r
658     result.data = malloc(bufSize);\r
659     if(!result.data) {\r
660         printf("Could not allocate memory for bitmap data.");\r
661         fclose(file);\r
662         exit(-1);\r
663     }\r
664 \r
665     /*  read the buffer in */\r
666     index = 0;\r
667     do {\r
668         /* get the run length and the value */\r
669         count = fgetc(file);\r
670         if(0xC0 ==  (count & 0xC0)) { /* this is the run count */\r
671             count &= 0x3f;\r
672             val = fgetc(file);\r
673         } else {\r
674             val = count;\r
675             count = 1;\r
676         }\r
677 \r
678         /* write the pixel the specified number of times */\r
679         for(; count && index < bufSize; count--,index++)  {\r
680             result.data[index] = val;\r
681         }\r
682     } while(index < bufSize);\r
683 \r
684     /* handle the palette */\r
685     fseek(file, -769, SEEK_END);\r
686     val = fgetc(file);\r
687     result.palette = modexNewPal();\r
688     if(head.version == 5 && val == 12) {\r
689         /* use the vga palette */\r
690         for(index=0; !feof(file) && index < PAL_SIZE; index++) {\r
691             val = fgetc(file);\r
692             result.palette[index] = val >> 2;\r
693         }\r
694     } else {\r
695         /* use the 16 color palette */\r
696         for(index=0; index<48; index++) {\r
697             result.palette[index]  = head.pal16[index];\r
698         }\r
699     }\r
700 \r
701     fclose(file);\r
702 \r
703     return result;\r
704 }\r