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