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