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