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