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