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