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