]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
cleanup and consolidate some mode-X code modesetting.
[16.git] / src / lib / modex16.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either verson 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/modex16.h"\r
27 \r
28 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 \r
33 /////////////////////////////////////////////////////////////////////////////\r
34 //                                                                                                                                                                                                                                              //\r
35 // setvideo() - This function Manages the video modes                                                                                           //\r
36 //                                                                                                                                                                                                                                              //\r
37 /////////////////////////////////////////////////////////////////////////////\r
38 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
39 {\r
40         union REGS in, out;\r
41 \r
42         switch (vq)\r
43         {\r
44                 case 0: // deinit the video\r
45                         // change to the video mode we were in before we switched to mode 13h\r
46                         modexLeave();\r
47                         in.h.ah = 0x00;\r
48                         in.h.al = gv->video.old_mode;\r
49                         int86(0x10, &in, &out);\r
50                 break;\r
51                 default: // init the video\r
52                         // get old video mode\r
53                         //in.h.ah = 0xf;\r
54                         //int86(0x10, &in, &out);\r
55                         gv->video.old_mode = vgaGetMode();//out.h.al;\r
56                         // enter mode\r
57                         modexEnter(vq, cmem, gv);\r
58                 break;\r
59         }\r
60 }\r
61 \r
62 static void\r
63 vgaSetMode(byte mode)\r
64 {\r
65   union REGS regs;\r
66 \r
67   regs.h.ah = SET_MODE;\r
68   regs.h.al = mode;\r
69   int86(VIDEO_INT, &regs, &regs);\r
70 }\r
71 \r
72 //---------------------------------------------------\r
73 //\r
74 // Use the bios to get the current video mode\r
75 //\r
76 \r
77 long\r
78 vgaGetMode()\r
79 {\r
80     union REGS rg;\r
81 \r
82     rg.h.ah = 0x0f;\r
83     int86(VIDEO_INT, &rg, &rg);\r
84 \r
85     return rg.h.al;\r
86 }\r
87 \r
88 /* -========================= Entry  Points ==========================- */\r
89 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
90 {\r
91         word i;\r
92         dword far*ptr=(dword far*)VGA;      /* used for faster screen clearing */\r
93         struct vga_mode_params cm;\r
94         int CRTParmCount;\r
95 \r
96         vgaSetMode(VGA_256_COLOR_MODE);\r
97         vga_enable_256color_modex();\r
98         update_state_from_vga();\r
99         vga_read_crtc_mode(&cm);\r
100 \r
101         switch(vq)\r
102         {\r
103                 case 1:\r
104                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
105                         /* width and height */\r
106                         gv->video.page[0].sw=vga_state.vga_width = 320; // VGA lib currently does not update this\r
107                         gv->video.page[0].sh=vga_state.vga_height = 240; // VGA lib currently does not update this\r
108 \r
109                         // 320x240 mode 60Hz\r
110                         cm.horizontal_total=0x5f + 5; /* CRTC[0]             -5 */\r
111                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]       -1 */\r
112                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
113                         cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 */\r
114                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
115                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
116                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
117                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
118                         cm.vertical_total = 0x20D + 2;\r
119                         cm.vertical_start_retrace = 0x1EA;\r
120                         cm.vertical_end_retrace = 0x1EC;\r
121                         cm.vertical_display_end = 480;\r
122                         cm.vertical_blank_start = 0x1E7 + 1;\r
123                         cm.vertical_blank_end = 0x206 + 1;\r
124                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
125                         cm.vsync_neg = 1;\r
126                         cm.hsync_neg = 1;\r
127                         break;\r
128                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
129                         return;\r
130                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
131                         return;\r
132                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
133                         return;\r
134                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
135                         return;\r
136                 default:\r
137                         return;\r
138         }\r
139 \r
140         vga_write_crtc_mode(&cm,0);\r
141 \r
142         /* clear video memory */\r
143         switch (cmem)\r
144         {\r
145                 case 1:\r
146                 /* clear video memory */\r
147                 vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
148                 for(i=0; i<0x8000; i++) ptr[i] = 0x0000;\r
149                 break;\r
150         }\r
151         gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;\r
152         gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;\r
153         //TODO MAKE FLEXIBLE~\r
154         gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;\r
155         gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;\r
156         #define PAGE_SIZE               (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)\r
157 }\r
158 \r
159 void\r
160 modexLeave() {\r
161         /* TODO restore original mode and palette */\r
162         vgaSetMode(TEXT_MODE);\r
163 }\r
164 \r
165 page_t\r
166 modexDefaultPage(page_t *p)\r
167 {\r
168     page_t page;\r
169 \r
170     /* default page values */\r
171     page.data = VGA;\r
172     page.dx = 0;\r
173     page.dy = 0;\r
174         page.sw = p->sw;\r
175         page.sh = p->sh;\r
176         page.width = p->sw;\r
177         page.height = p->sh;\r
178         page.tw = page.sw/TILEWH;\r
179         page.th = page.sh/TILEWH;\r
180         page.tilemidposscreenx = page.tw/2;\r
181         page.tilemidposscreeny = (page.th/2)+1;\r
182         page.tilesw=p->tilesw;\r
183         page.tilesh=p->tilesh;\r
184         //pageSize = p->sw*p->sh;\r
185         page.id = 0;\r
186 \r
187     return page;\r
188 }\r
189 \r
190 /* returns the next page in contiguous memory\r
191  * the next page will be the same size as p, by default\r
192  */\r
193 page_t\r
194 modexNextPage(page_t *p) {\r
195     page_t result;\r
196 \r
197     result.data = p->data + (p->width/4)*p->height;\r
198     result.dx = 0;\r
199     result.dy = 0;\r
200     result.width = p->width;\r
201     result.height = p->height;\r
202         result.tw = p->width/TILEWH;\r
203         result.th = p->height/TILEWH;\r
204         result.id = p->id+1;\r
205 \r
206         return result;\r
207 //      return modexNextPageFlexibleSize(&p, p->width, p->height);\r
208 }\r
209 \r
210 //next page with defined dimentions~\r
211 page_t\r
212 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
213 {\r
214         page_t result;\r
215 \r
216         result.data = p->data + (p->width/4)*p->height;  /* compute the offset */\r
217         result.dx = 0;\r
218         result.dy = 0;\r
219         result.width = x;\r
220         result.height = y;\r
221         result.tw = p->width/TILEWH;\r
222         result.th = p->height/TILEWH;\r
223         result.id = p->id+1;\r
224 \r
225         return result;\r
226 }\r
227 \r
228 \r
229 void\r
230 modexShowPage(page_t *page) {\r
231     word high_address;\r
232     word low_address;\r
233     word offset;\r
234     byte crtcOffset;\r
235 \r
236     /* calculate offset */\r
237     offset = (word) page->data;\r
238     offset += page->dy * (page->width >> 2 );\r
239     offset += page->dx >> 2;\r
240 \r
241     /* calculate crtcOffset according to virtual width */\r
242     crtcOffset = page->width >> 3;\r
243 \r
244     high_address = HIGH_ADDRESS | (offset & 0xff00);\r
245     low_address  = LOW_ADDRESS  | (offset << 8);\r
246 \r
247     /* wait for appropriate timing and then program CRTC */\r
248     while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
249     outpw(CRTC_INDEX, high_address);\r
250     outpw(CRTC_INDEX, low_address);\r
251     outp(CRTC_INDEX, 0x13);\r
252     outp(CRTC_DATA, crtcOffset);\r
253 \r
254     /*  wait for one retrace */\r
255     while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
256 \r
257     /* do PEL panning here */\r
258     outp(AC_INDEX, 0x33);\r
259     outp(AC_INDEX, (page->dx & 0x03) << 1);\r
260 }\r
261 \r
262 \r
263 void\r
264 modexPanPage(page_t *page, int dx, int dy) {\r
265     page->dx = dx;\r
266     page->dy = dy;\r
267 }\r
268 \r
269 \r
270 void\r
271 modexSelectPlane(byte plane) {\r
272     outp(SC_INDEX, MAP_MASK);     /* select plane */\r
273     outp(SC_DATA,  plane);\r
274 }\r
275 \r
276 \r
277 void\r
278 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
279     word pageOff = (word) page->data;\r
280     word xoff=x/4;       /* xoffset that begins each row */\r
281     word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
282     word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */\r
283     word nextRow = page->width/4-scanCount-1;  /* loc of next row */\r
284     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
285     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
286     byte left = lclip[x&0x03];\r
287     byte right = rclip[(x+w)&0x03];\r
288 \r
289     /* handle the case which requires an extra group */\r
290     if((x & 0x03) && !((x+w) & 0x03)) {\r
291       right=0x0f;\r
292     }\r
293 \r
294     __asm {\r
295                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
296                 MOV ES, AX\r
297                 MOV DI, poffset  ; go to the first pixel\r
298                 MOV DX, SC_INDEX        ; point to the map mask\r
299                 MOV AL, MAP_MASK\r
300                 OUT DX, AL\r
301                 INC DX\r
302                 MOV AL, color      ; get ready to write colors\r
303         SCAN_START:\r
304                 MOV CX, scanCount       ; count the line\r
305                 MOV BL, AL            ; remember color\r
306                 MOV AL, left        ; do the left clip\r
307                 OUT DX, AL            ; set the left clip\r
308                 MOV AL, BL            ; restore color\r
309                 STOSB              ; write the color\r
310                 DEC CX\r
311                 JZ SCAN_DONE        ; handle 1 group stuff\r
312 \r
313                 ;-- write the main body of the scanline\r
314                 MOV BL, AL            ; remember color\r
315                 MOV AL, 0x0f        ; write to all pixels\r
316                 OUT DX, AL\r
317                 MOV AL, BL            ; restore color\r
318                 REP STOSB              ; write the color\r
319         SCAN_DONE:\r
320                 MOV BL, AL            ; remeber color\r
321                 MOV AL, right\r
322                 OUT DX, AL            ; do the right clip\r
323                 MOV AL, BL            ; restore color\r
324                 STOSB              ; write pixel\r
325                 ADD DI, nextRow  ; go to the next row\r
326                 DEC h\r
327                 JNZ SCAN_START\r
328     }\r
329 }\r
330 \r
331 /* moved to src/lib/modex16/16render.c */\r
332 \r
333 /* copy a region of video memory from one page to another.\r
334  * It assumes that the left edge of the tile is the same on both\r
335  * regions and the memory areas do not overlap.\r
336  */\r
337 void\r
338 modexCopyPageRegion(page_t *dest, page_t *src,\r
339                     word sx, word sy,\r
340                     word dx, word dy,\r
341                     word width, word height)\r
342 {\r
343     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
344     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
345     word scans   = width/4;\r
346     word nextSrcRow = src->width/4 - scans - 1;\r
347     word nextDestRow = dest->width/4 - scans - 1;\r
348     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
349     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
350     byte left = lclip[sx&0x03];\r
351     byte right = rclip[(sx+width)&0x03];\r
352 \r
353     __asm {\r
354                 MOV AX, SCREEN_SEG      ; work in the vga space\r
355                 MOV ES, AX            ;\r
356                 MOV DI, doffset  ;\r
357                 MOV SI, soffset  ;\r
358 \r
359                 MOV DX, GC_INDEX        ; turn off cpu bits\r
360                 MOV AX, 0008h      ;\r
361                 OUT DX, AX\r
362 \r
363                 MOV AX, SC_INDEX        ; point to the mask register\r
364                 MOV DX, AX            ;\r
365                 MOV AL, MAP_MASK        ;\r
366                 OUT DX, AL            ;\r
367                 INC DX            ;\r
368 \r
369         ROW_START:\r
370                 PUSH DS\r
371                 MOV AX, ES\r
372                 MOV DS, AX\r
373                 MOV CX, scans      ; the number of latches\r
374 \r
375                 MOV AL, left        ; do the left column\r
376                 OUT DX, AL            ;\r
377                 MOVSB              ;\r
378                 DEC CX            ;\r
379 \r
380                 MOV AL, 0fh          ; do the inner columns\r
381                 OUT DX, AL\r
382                 REP MOVSB              ; copy the pixels\r
383 \r
384                 MOV AL, right      ; do the right column\r
385                 OUT DX, AL\r
386                 MOVSB\r
387                 POP DS\r
388 \r
389                 MOV AX, SI            ; go the start of the next row\r
390                 ADD AX, nextSrcRow      ;\r
391                 MOV SI, AX            ;\r
392                 MOV AX, DI            ;\r
393                 ADD AX, nextDestRow     ;\r
394                 MOV DI, AX            ;\r
395 \r
396                 DEC height            ; do the rest of the actions\r
397                 JNZ ROW_START      ;\r
398 \r
399                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
400                 MOV AL, 0ffh        ; none from latches\r
401                 OUT DX, AL            ;\r
402     }\r
403 }\r
404 \r
405 \r
406 /* fade and flash */\r
407 void\r
408 modexFadeOn(word fade, byte *palette) {\r
409     fadePalette(-fade, 64, 64/fade+1, palette);\r
410 }\r
411 \r
412 \r
413 void\r
414 modexFadeOff(word fade, byte *palette) {\r
415     fadePalette(fade, 0, 64/fade+1, palette);\r
416 }\r
417 \r
418 \r
419 void\r
420 modexFlashOn(word fade, byte *palette) {\r
421     fadePalette(fade, -64, 64/fade+1, palette);\r
422 }\r
423 \r
424 \r
425 void\r
426 modexFlashOff(word fade, byte *palette) {\r
427     fadePalette(-fade, 0, 64/fade+1, palette);\r
428 }\r
429 \r
430 \r
431 static void\r
432 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
433     word i;\r
434     byte dim = start;\r
435 \r
436     /* handle the case where we just update */\r
437     if(iter == 0) {\r
438         modexPalUpdate1(palette);\r
439         return;\r
440     }\r
441 \r
442     while(iter > 0) {  /* FadeLoop */\r
443         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
444             tmppal[i] = palette[i] - dim;\r
445             if(tmppal[i] > 127) {\r
446                 tmppal[i] = 0;\r
447             } else if(tmppal[i] > 63) {\r
448                 tmppal[i] = 63;\r
449             }\r
450         }\r
451         modexPalUpdate1(tmppal);\r
452         iter--;\r
453         dim += fade;\r
454     }\r
455 }\r
456 \r
457 \r
458 /* save and load */\r
459 void\r
460 modexPalSave(byte *palette) {\r
461     int  i;\r
462 \r
463     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
464     for(i=0; i<PAL_SIZE; i++) {\r
465         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
466     }\r
467 }\r
468 \r
469 \r
470 byte *\r
471 modexNewPal() {\r
472     byte *ptr;\r
473     ptr = malloc(PAL_SIZE);\r
474 \r
475     /* handle errors */\r
476     if(!ptr) {\r
477         printf("Could not allocate palette.\n");\r
478         exit(-1);\r
479     }\r
480 \r
481     return ptr;\r
482 }\r
483 \r
484 \r
485 void\r
486 modexLoadPalFile(byte *filename, byte **palette) {\r
487     FILE *file;\r
488     byte *ptr;\r
489 \r
490     /* free the palette if it exists */\r
491     if(*palette) {\r
492         free(*palette);\r
493     }\r
494 \r
495     /* allocate the new palette */\r
496     *palette = modexNewPal();\r
497 \r
498     /* open the file */\r
499     file = fopen(filename, "rb");\r
500     if(!file) {\r
501         printf("Could not open palette file: %s\n", filename);\r
502         exit(-2);\r
503     }\r
504 \r
505     /* read the file */\r
506     ptr = *palette;\r
507     while(!feof(file)) {\r
508         *ptr++ = fgetc(file);\r
509     }\r
510 \r
511     fclose(file);\r
512 }\r
513 \r
514 \r
515 void\r
516 modexSavePalFile(char *filename, byte *pal) {\r
517     unsigned int i;\r
518     FILE *file;\r
519 \r
520     /* open the file for writing */\r
521     file = fopen(filename, "wb");\r
522     if(!file) {\r
523         printf("Could not open %s for writing\n", filename);\r
524         exit(-2);\r
525     }\r
526 \r
527     /* write the data to the file */\r
528     fwrite(pal, 1, PAL_SIZE, file);\r
529     fclose(file);\r
530 }\r
531 \r
532 \r
533 /* blanking */\r
534 void\r
535 modexPalBlack() {\r
536     fadePalette(-1, 64, 1, tmppal);\r
537 }\r
538 \r
539 \r
540 void\r
541 modexPalWhite() {\r
542     fadePalette(-1, -64, 1, tmppal);\r
543 }\r
544 \r
545 \r
546 /* utility */\r
547 void\r
548 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
549 {\r
550         byte *p = bmp->palette;\r
551         word w=0;\r
552         word q=0;\r
553         word qq=0;\r
554         static word a[PAL_SIZE];        //palette array of change values!\r
555         word z=0, aq=0, aa=0, pp=0;\r
556 \r
557         modexWaitBorder();\r
558         if((*i)==0)\r
559         {\r
560                 memset(a, -1, sizeof(a));\r
561                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
562         }\r
563         else if(qp==0)\r
564         {\r
565                 q=(*i);\r
566         }\r
567         else\r
568         {\r
569                 q=(*i);\r
570                 qq=(*i)/3;\r
571 //            printf("q: %02d\n", (q));\r
572 //            printf("qq: %02d\n", (qq));\r
573                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
574                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
575         }\r
576         if((*i)<PAL_SIZE/2 && w==0)\r
577         {\r
578                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
579                 {\r
580                         //if(i%3==0 && (p[i+5]==p[i+4] && p[i+4]==p[i+3] && p[i+3]==p[i+2] && p[i+2]==p[i+1] && p[i+1]==p[i] && p[i+5]==p[i]))\r
581 //____            if((qp>0)&&((*i)-q)%3==0 && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5])) outp(PAL_DATA_REG, p[(*i)-q]); else\r
582                         if(((((*i)-q)%3==0)) && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5]))\r
583                         {\r
584                                 w++;\r
585                                 break;\r
586                         }\r
587                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
588                         {\r
589                                 //printf("qp=%d\n", qp);\r
590                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
591                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
592                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
593                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
594                         }\r
595                         else\r
596                         {\r
597                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
598                                 else\r
599                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
600                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
601                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
602                         }\r
603                 }\r
604                 //if(qp>0) printf("qp=%d\n", qp);\r
605                 //if(qp>0) printf("                                          (*i)=%d\n", (*i)/3);\r
606         }\r
607         modexWaitBorder();        /* waits one retrace -- less flicker */\r
608         if((*i)>=PAL_SIZE/2 && w==0)\r
609         {\r
610                 for(; (*i)<PAL_SIZE; (*i)++)\r
611                 {\r
612 //____            if((qp>0)&&((*i)-q)%3==0 && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5])) outp(PAL_DATA_REG, p[(*i)-q]); else\r
613                         if(((((*i)-q)%3==0)) && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5]))\r
614                         {\r
615                                 w++;\r
616                                 break;\r
617                         }\r
618                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
619                         {\r
620                                 //printf("qp=%d\n", qp);\r
621                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
622                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
623                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
624                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
625                         }\r
626                         else\r
627                         {\r
628                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
629                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
630                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
631                         }\r
632                 }\r
633                 //printf("                                            (*i)=%d\n", (*i)/3);\r
634         }\r
635 \r
636 printf("\nqqqqqqqq\n\n");\r
637 \r
638         //palette checker~\r
639         if(q>0 && qp==0)\r
640         {\r
641                 long lq;\r
642                 long bufSize = (bmp->width * bmp->height);\r
643                 pp = q;\r
644                 //printf("1(*i)=%02d\n", (*i)/3);\r
645                 //printf("1z=%02d\n", z/3);\r
646                 chkcolor(bmp, &q, &a, &aa, &z, i);\r
647                 //printf("2(*i)=%02d\n", (*i)/3);\r
648                 //printf("2z=%02d\n", z/3);\r
649                 aq=0;\r
650 aqpee:\r
651                 while(aq<=aa)\r
652                 {\r
653 //                    printf("a[%02d]=(%d)\n", aq, a[aq]);\r
654                         if(a[aq]==-1) aq++;\r
655                         else { aqoffset++; break; }\r
656                 }\r
657 //update the image data here!\r
658         for(lq=0; lq<bufSize; lq++)\r
659         {\r
660                                 /*\r
661                                                                         note to self\r
662                                                                         use a[qp] instead of bmp->offset for this spot!\r
663                                                                         NO! wwww\r
664                                 */\r
665 \r
666                                 /*\r
667                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
668                                 */\r
669 \r
670                 //(offset/bmp->offset)*bmp->offset\r
671 \r
672 \r
673                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
674                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
675                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
676                 /*if(bmp->data[lq]+bmp->offset==aq)\r
677                 {\r
678                         //printf("%02d", bmp->data[lq]);\r
679                         //printf("\n%02d\n", bmp->offset);\r
680                         printf("aq=%02d ", aq);\r
681                         printf("a[aq]=%02d      ", a[aq]);\r
682                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
683                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
684                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
685 //++++            bmp->data[lq]=a[aq]-aqpp;\r
686 //                    printf("_%d ", bmp->data[lq]);\r
687                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
688                 }\r
689                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
690                 {\r
691                         if(bmp->data[lq]+bmp->offset >= aq)\r
692                         {\r
693                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
694                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
695                         }\r
696                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
697                 }*/\r
698 \r
699                 //printf("%02d`", bmp->data[lq]);\r
700                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
701         }\r
702 \r
703 //printf("            aq=%02d\n", aq);\r
704 //printf("            aa=%02d\n", aa);\r
705 \r
706         //update the palette~\r
707         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
708         (*i)=pp;\r
709 \r
710         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
711         }\r
712 }\r
713 \r
714 void\r
715 modexPalUpdate1(byte *p)\r
716 {\r
717         int i;\r
718         modexWaitBorder();\r
719         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
720         for(i=0; i<PAL_SIZE/2; i++)\r
721         {\r
722                 outp(PAL_DATA_REG, p[i]);\r
723         }\r
724         modexWaitBorder();        /* waits one retrace -- less flicker */\r
725         for(; i<PAL_SIZE; i++)\r
726         {\r
727                 outp(PAL_DATA_REG, p[(i)]);\r
728         }\r
729 }\r
730 \r
731 void\r
732 modexPalUpdate0(byte *p)\r
733 {\r
734         int i;\r
735         modexWaitBorder();\r
736         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
737         for(i=0; i<PAL_SIZE/2; i++)\r
738         {\r
739                 outp(PAL_DATA_REG, rand());\r
740         }\r
741         modexWaitBorder();        /* waits one retrace -- less flicker */\r
742         for(; i<PAL_SIZE; i++)\r
743         {\r
744                 outp(PAL_DATA_REG, rand());\r
745         }\r
746 }\r
747 \r
748 void\r
749 modexPalOverscan(byte *p, word col)\r
750 {\r
751         modexWaitBorder();\r
752         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
753         outp(PAL_DATA_REG, col);\r
754 }\r
755 \r
756 //color checker~\r
757 //i want to make another vesion that checks the palette when the palette is being appened~\r
758 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
759 {\r
760                 byte *pal;\r
761                 word zz=0;\r
762                 pal = modexNewPal();\r
763                 modexPalSave(pal);\r
764                 //printf("q: %02d\n", (*q));\r
765                 printf("chkcolor start~\n");\r
766                 printf("1                              (*z): %d\n", (*z)/3);\r
767                 printf("1                              (*i): %d\n", (*i)/3);\r
768 //            printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
769                 printf("wwwwwwwwwwwwwwww\n");\r
770                 //check palette for dups\r
771                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
772                 {\r
773                         //printf("\n        z: %d\n", (*z));\r
774                         //printf("            q: %d\n", (*q));\r
775                         //printf("            z+q: %d\n\n", ((*z)+(*q)));\r
776                         //if((*z)%3==0)\r
777                         //{\r
778 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
779                                 if((*z)==(*i))\r
780                                 {\r
781 //                                    printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
782 //                                    printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
783 //0000                            (*z)-=3;\r
784                                         break;\r
785                                 }\r
786                                 else for(zz=0; zz<(*q); zz+=3)\r
787                                 {\r
788                                         //printf("zz: %02d\n", zz/3);\r
789                                         if(zz%3==0)\r
790                                         {\r
791                                                 if(pal[((*z)+(*q))]==pal[((*z)+(*q))+3] && pal[((*z)+(*q))+1]==pal[((*z)+(*q))+4] && pal[((*z)+(*q))+2]==pal[((*z)+(*q))+5])    //break if duplicate colors found in palette because it have reached the end of the current data of the palette\r
792                                                 {\r
793 //                                                    (*z)-=3;\r
794 //                                                    (*i)-=3;\r
795 //                                                    printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
796 //                                                    printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
797                                                         break;\r
798                                                 }\r
799                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
800                                                 {\r
801 //                                                    printf("\n\nwwwwwwwwwwwwwwww\n");\r
802 //                                                    printf("  zq: %d  [%02d][%02d][%02d] value that is needing to be changed~\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
803 //                                                    printf("  zz: %d  [%02d][%02d][%02d] value that the previous value is going to change to~\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
804 //                                                    //printf("      zv: %d  [%02d][%02d][%02d] wwww\n", (zz-z+q)/3, pal[(zz-z+q)], pal[(zz-z+q)+1], pal[(zz-z+q)+2]);\r
805 //                                                    printf("  z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
806 //++++                                            (*i)--;\r
807 //                                                    (*z)--;\r
808                                                         //expand dong here\r
809 /*\r
810 planned features that i plan to implement~\r
811 image that has values on the pallete list!\r
812 wwww\r
813 no... wait.... no wwww\r
814 */\r
815                                                         //for(zzii=0; zzii<3; zzii++)\r
816                                                         //{\r
817                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
818                                                                 a[(((*z)+(*q)))]=zz;\r
819                                                         //}\r
820                                                         (*aa)=(((*z)+(*q)));\r
821                                                         printf("!!                                    a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
822 //                                                    printf("\n              aa: %d\n\n", (*aa));\r
823 //                                                    printf("  a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
824 //                                                    printf("wwwwwwwwwwwwwwww\n\n");\r
825                                                 }\r
826                                                 /*else\r
827                                                 {\r
828                                                         printf("================\n");\r
829                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
830                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
831                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
832                                                         printf("================\n");\r
833                                                 }*/\r
834                                                 //printf("[%d]", (zz+q));\r
835                                         }\r
836                                 }\r
837                 }\r
838                 printf("wwwwwwwwwwwwwwww\n");\r
839                 printf("2                              (*z): %d\n", (*z)/3);\r
840                 printf("2                              (*i): %d\n", (*i)/3);\r
841 //            printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
842                 printf("chkcolor end~\n");\r
843                 free(pal);\r
844 }\r
845 \r
846 void modexputPixel(page_t *page, int x, int y, byte color)\r
847 {\r
848         word pageOff = (word) page->data;\r
849         /* Each address accesses four neighboring pixels, so set\r
850            Write Plane Enable according to which pixel we want\r
851            to modify.  The plane is determined by the two least\r
852            significant bits of the x-coordinate: */\r
853         modexSelectPlane(PLANE(x));\r
854         //outp(SC_INDEX, 0x02);\r
855         //outp(SC_DATA, 0x01 << (x & 3));\r
856 \r
857         /* The offset of the pixel into the video segment is\r
858            offset = (width * y + x) / 4, and write the given\r
859            color to the plane we selected above.  Heed the active\r
860            page start selection. */\r
861         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
862 \r
863 }\r
864 \r
865 byte modexgetPixel(page_t *page, int x, int y)\r
866 {\r
867         word pageOff = (word) page->data;\r
868         /* Select the plane from which we must read the pixel color: */\r
869         outpw(GC_INDEX, 0x04);\r
870         outpw(GC_INDEX+1, x & 3);\r
871 \r
872         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
873 \r
874 }\r
875 \r
876 void modexhlin(page_t *page, word xl, word xh, word y, word color)\r
877 {\r
878         word x;\r
879         word yy=0;\r
880 \r
881         for(x=0;x<xh*4;x+=4)\r
882         {\r
883                 if(x+4>=page[0].sw-1){ x=0; yy+=4; }\r
884                 modexClearRegion(page, x+xl, y+yy, 4, 4, color);\r
885         }\r
886         //modexputPixel(page, x+xl, y, color);\r
887 }\r
888 \r
889 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str, boolean q)\r
890 {\r
891         word s, o, w;\r
892         word addr = (word) romFontsData.l;\r
893         byte c;\r
894 \r
895         s=romFonts[t].seg;\r
896         o=romFonts[t].off;\r
897         w=romFonts[t].charSize;\r
898         romFontsData.chw=0;\r
899 \r
900         for(; *str != '\0'; str++)\r
901         {\r
902         c = (*str);\r
903         if((c=='\n'/* || c=="\\r
904 "*/) || romFontsData.chw\r
905 >=page->width)\r
906         {\r
907                 romFontsData.chw=0;\r
908                 y+=romFonts[t].charSize;\r
909                 continue;\r
910         }\r
911         //load the letter 'A'\r
912         __asm {\r
913                 MOV DI, addr\r
914                 MOV SI, o\r
915                 MOV ES, s\r
916                 SUB AH, AH\r
917                 MOV AL, c       ; the letter\r
918                 MOV CX, w\r
919                 MUL CX\r
920                 ADD SI, AX      ;the address of charcter\r
921         L1:     MOV AX, ES:SI\r
922                 MOV DS:DI, AX\r
923                 INC SI\r
924                 INC DI\r
925                 DEC CX\r
926                 JNZ L1\r
927         }\r
928 //TODO: OPTIMIZE THIS!!!!\r
929                 modexDrawCharPBuf(page, x, y, t, col, bgcol, q);\r
930 \r
931                 //if(!q) getch();\r
932         }\r
933 }\r
934 \r
935 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
936 {\r
937         word i, s, o, w, j, xp;\r
938         byte l[1024];\r
939         word addr = (word) l;\r
940         word chw=0;\r
941         byte c;\r
942 \r
943         switch(t)\r
944         {\r
945                 case 0:\r
946                         w=14;\r
947                 break;\r
948                 case 1:\r
949                         w=8;\r
950                 break;\r
951                 case 2:\r
952                         w=8;\r
953                 break;\r
954                 case 3:\r
955                         w=16;\r
956                 break;\r
957                 default:\r
958                         t=3;\r
959                         w=16;\r
960                 break;\r
961         }\r
962 \r
963         s=romFonts[t].seg;\r
964         o=romFonts[t].off;\r
965 \r
966         for(; *str != '\0'; str++)\r
967         {\r
968         c = (*str);\r
969         if((c=='\n'/* || c=="\\r
970 "*/)/* || chw>=page->width*/)\r
971         {\r
972                 chw=0;\r
973                 y+=w;\r
974                 continue;\r
975         }\r
976         //load the letter 'A'\r
977         __asm {\r
978                 MOV DI, addr\r
979                 MOV SI, o\r
980                 MOV ES, s\r
981                 SUB AH, AH\r
982                 MOV AL, c       ; the letter\r
983                 MOV CX, w\r
984                 MUL CX\r
985                 ADD SI, AX      ;the address of charcter\r
986         L1:     MOV AX, ES:SI\r
987                 MOV DS:DI, AX\r
988                 INC SI\r
989                 INC DI\r
990                 DEC CX\r
991                 JNZ L1\r
992         }\r
993 \r
994                 for(i=0; i<w; i++)\r
995                 {\r
996                         j=1<<8;\r
997                         xp=0;\r
998                         while(j)\r
999                         {\r
1000                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1001                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1002                                 xp++;\r
1003                                 j>>=1;\r
1004                         }\r
1005                 }\r
1006                 chw += xp;\r
1007         }\r
1008 }\r
1009 \r
1010 /* palette dump on display! */\r
1011 void pdump(page_t *pee)\r
1012 {\r
1013         int mult=(QUADWH);\r
1014         int palq=(mult)*TILEWH;\r
1015         int palcol=0;\r
1016         int palx, paly;\r
1017         for(paly=0; paly<palq; paly+=mult){\r
1018                 for(palx=0; palx<palq; palx+=mult){\r
1019                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1020                         palcol++;\r
1021                 }\r
1022         }\r
1023 }\r
1024 \r
1025 /////////////////////////////////////////////////////////////////////////////\r
1026 //                                                                                                                                               //\r
1027 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1028 //               the Virtual screen.                                                                                     //\r
1029 //                                                                                                                                               //\r
1030 /////////////////////////////////////////////////////////////////////////////\r
1031 void cls(page_t *page, byte color, byte *Where)\r
1032 {\r
1033         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1034         /* set map mask to all 4 planes */\r
1035         outpw(SC_INDEX, 0xff02);\r
1036         //_fmemset(VGA, color, 16000);\r
1037         _fmemset(Where, color, page->width*(page->height)/4);\r
1038 }\r
1039 \r
1040 void\r
1041 modexWaitBorder() {\r
1042     while(inp(INPUT_STATUS_1)  & 8)  {\r
1043         /* spin */\r
1044     }\r
1045 \r
1046     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1047         /* spin */\r
1048     }\r
1049 }\r