]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
wwww
[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                         // 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_state.vga_graphics_ram;//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         vga_wait_for_vsync();\r
550         if((*i)==0)\r
551         {\r
552                 memset(a, -1, sizeof(a));\r
553                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
554         }\r
555         else if(qp==0)\r
556         {\r
557                 q=(*i);\r
558         }\r
559         else\r
560         {\r
561                 q=(*i);\r
562                 qq=(*i)/3;\r
563 //            printf("q: %02d\n", (q));\r
564 //            printf("qq: %02d\n", (qq));\r
565                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
566                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
567         }\r
568         if((*i)<PAL_SIZE/2 && w==0)\r
569         {\r
570                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
571                 {\r
572                         //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
573 //____            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
574                         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
575                         {\r
576                                 w++;\r
577                                 break;\r
578                         }\r
579                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
580                         {\r
581                                 //printf("qp=%d\n", qp);\r
582                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
583                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
584                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
585                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
586                         }\r
587                         else\r
588                         {\r
589                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
590                                 else\r
591                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
592                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
593                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
594                         }\r
595                 }\r
596                 //if(qp>0) printf("qp=%d\n", qp);\r
597                 //if(qp>0) printf("                                          (*i)=%d\n", (*i)/3);\r
598         }\r
599         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
600         vga_wait_for_vsync();\r
601         if((*i)>=PAL_SIZE/2 && w==0)\r
602         {\r
603                 for(; (*i)<PAL_SIZE; (*i)++)\r
604                 {\r
605 //____            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
606                         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
607                         {\r
608                                 w++;\r
609                                 break;\r
610                         }\r
611                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
612                         {\r
613                                 //printf("qp=%d\n", qp);\r
614                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
615                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
616                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
617                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
618                         }\r
619                         else\r
620                         {\r
621                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
622                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
623                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
624                         }\r
625                 }\r
626                 //printf("                                            (*i)=%d\n", (*i)/3);\r
627         }\r
628 \r
629 printf("\nqqqqqqqq\n\n");\r
630 \r
631         //palette checker~\r
632         if(q>0 && qp==0)\r
633         {\r
634                 long lq;\r
635                 long bufSize = (bmp->width * bmp->height);\r
636                 pp = q;\r
637                 //printf("1(*i)=%02d\n", (*i)/3);\r
638                 //printf("1z=%02d\n", z/3);\r
639                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
640                 //printf("2(*i)=%02d\n", (*i)/3);\r
641                 //printf("2z=%02d\n", z/3);\r
642                 aq=0;\r
643 aqpee:\r
644                 while(aq<=aa)\r
645                 {\r
646 //                    printf("a[%02d]=(%d)\n", aq, a[aq]);\r
647                         if(a[aq]==-1) aq++;\r
648                         else { aqoffset++; break; }\r
649                 }\r
650 //update the image data here!\r
651         for(lq=0; lq<bufSize; lq++)\r
652         {\r
653                                 /*\r
654                                                                         note to self\r
655                                                                         use a[qp] instead of bmp->offset for this spot!\r
656                                                                         NO! wwww\r
657                                 */\r
658 \r
659                                 /*\r
660                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
661                                 */\r
662 \r
663                 //(offset/bmp->offset)*bmp->offset\r
664 \r
665 \r
666                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
667                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
668                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
669                 /*if(bmp->data[lq]+bmp->offset==aq)\r
670                 {\r
671                         //printf("%02d", bmp->data[lq]);\r
672                         //printf("\n%02d\n", bmp->offset);\r
673                         printf("aq=%02d ", aq);\r
674                         printf("a[aq]=%02d      ", a[aq]);\r
675                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
676                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
677                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
678 //++++            bmp->data[lq]=a[aq]-aqpp;\r
679 //                    printf("_%d ", bmp->data[lq]);\r
680                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
681                 }\r
682                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
683                 {\r
684                         if(bmp->data[lq]+bmp->offset >= aq)\r
685                         {\r
686                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
687                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
688                         }\r
689                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
690                 }*/\r
691 \r
692                 //printf("%02d`", bmp->data[lq]);\r
693                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
694         }\r
695 \r
696 //printf("            aq=%02d\n", aq);\r
697 //printf("            aa=%02d\n", aa);\r
698 \r
699         //update the palette~\r
700         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
701         (*i)=pp;\r
702 \r
703         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
704         }\r
705 }\r
706 \r
707 void\r
708 modexPalUpdate1(byte *p)\r
709 {\r
710         int i;\r
711         //modexWaitBorder();\r
712         vga_wait_for_vsync();\r
713         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
714         for(i=0; i<PAL_SIZE/2; i++)\r
715         {\r
716                 outp(PAL_DATA_REG, p[i]);\r
717         }\r
718         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
719         vga_wait_for_vsync();\r
720         for(; i<PAL_SIZE; i++)\r
721         {\r
722                 outp(PAL_DATA_REG, p[(i)]);\r
723         }\r
724 }\r
725 \r
726 void\r
727 modexPalUpdate0(byte *p)\r
728 {\r
729         int i;\r
730         //modexWaitBorder();\r
731         vga_wait_for_vsync();\r
732         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
733         for(i=0; i<PAL_SIZE/2; i++)\r
734         {\r
735                 outp(PAL_DATA_REG, rand());\r
736         }\r
737         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
738         vga_wait_for_vsync();\r
739         for(; i<PAL_SIZE; i++)\r
740         {\r
741                 outp(PAL_DATA_REG, rand());\r
742         }\r
743 }\r
744 \r
745 void\r
746 modexPalOverscan(byte *p, word col)\r
747 {\r
748         //modexWaitBorder();\r
749         vga_wait_for_vsync();\r
750         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
751         outp(PAL_DATA_REG, col);\r
752 }\r
753 \r
754 //color checker~\r
755 //i want to make another vesion that checks the palette when the palette is being appened~\r
756 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
757 {\r
758                 byte *pal;\r
759                 word zz=0;\r
760                 pal = modexNewPal();\r
761                 modexPalSave(pal);\r
762                 //printf("q: %02d\n", (*q));\r
763                 printf("chkcolor start~\n");\r
764                 printf("1                              (*z): %d\n", (*z)/3);\r
765                 printf("1                              (*i): %d\n", (*i)/3);\r
766 //            printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
767                 printf("wwwwwwwwwwwwwwww\n");\r
768                 //check palette for dups\r
769                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
770                 {\r
771                         //printf("\n        z: %d\n", (*z));\r
772                         //printf("            q: %d\n", (*q));\r
773                         //printf("            z+q: %d\n\n", ((*z)+(*q)));\r
774                         //if((*z)%3==0)\r
775                         //{\r
776 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
777                                 if((*z)==(*i))\r
778                                 {\r
779 //                                    printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
780 //                                    printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
781 //0000                            (*z)-=3;\r
782                                         break;\r
783                                 }\r
784                                 else for(zz=0; zz<(*q); zz+=3)\r
785                                 {\r
786                                         //printf("zz: %02d\n", zz/3);\r
787                                         if(zz%3==0)\r
788                                         {\r
789                                                 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
790                                                 {\r
791 //                                                    (*z)-=3;\r
792 //                                                    (*i)-=3;\r
793 //                                                    printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
794 //                                                    printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
795                                                         break;\r
796                                                 }\r
797                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
798                                                 {\r
799 //                                                    printf("\n\nwwwwwwwwwwwwwwww\n");\r
800 //                                                    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
801 //                                                    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
802 //                                                    //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
803 //                                                    printf("  z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
804 //++++                                            (*i)--;\r
805 //                                                    (*z)--;\r
806                                                         //expand dong here\r
807 /*\r
808 planned features that i plan to implement~\r
809 image that has values on the pallete list!\r
810 wwww\r
811 no... wait.... no wwww\r
812 */\r
813                                                         //for(zzii=0; zzii<3; zzii++)\r
814                                                         //{\r
815                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
816                                                                 a[(((*z)+(*q)))]=zz;\r
817                                                         //}\r
818                                                         (*aa)=(((*z)+(*q)));\r
819                                                         printf("!!                                    a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
820 //                                                    printf("\n              aa: %d\n\n", (*aa));\r
821 //                                                    printf("  a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
822 //                                                    printf("wwwwwwwwwwwwwwww\n\n");\r
823                                                 }\r
824                                                 /*else\r
825                                                 {\r
826                                                         printf("================\n");\r
827                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
828                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
829                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
830                                                         printf("================\n");\r
831                                                 }*/\r
832                                                 //printf("[%d]", (zz+q));\r
833                                         }\r
834                                 }\r
835                 }\r
836                 printf("wwwwwwwwwwwwwwww\n");\r
837                 printf("2                              (*z): %d\n", (*z)/3);\r
838                 printf("2                              (*i): %d\n", (*i)/3);\r
839 //            printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
840                 printf("chkcolor end~\n");\r
841                 free(pal);\r
842 }\r
843 \r
844 void modexputPixel(page_t *page, int x, int y, byte color)\r
845 {\r
846         word pageOff = (word) page->data;\r
847         /* Each address accesses four neighboring pixels, so set\r
848            Write Plane Enable according to which pixel we want\r
849            to modify.  The plane is determined by the two least\r
850            significant bits of the x-coordinate: */\r
851         modexSelectPlane(PLANE(x));\r
852         //outp(SC_INDEX, 0x02);\r
853         //outp(SC_DATA, 0x01 << (x & 3));\r
854 \r
855         /* The offset of the pixel into the video segment is\r
856            offset = (width * y + x) / 4, and write the given\r
857            color to the plane we selected above.  Heed the active\r
858            page start selection. */\r
859         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
860 \r
861 }\r
862 \r
863 byte modexgetPixel(page_t *page, int x, int y)\r
864 {\r
865         word pageOff = (word) page->data;\r
866         /* Select the plane from which we must read the pixel color: */\r
867         outpw(GC_INDEX, 0x04);\r
868         outpw(GC_INDEX+1, x & 3);\r
869 \r
870         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
871 \r
872 }\r
873 \r
874 void modexhlin(page_t *page, word xl, word xh, word y, word color)\r
875 {\r
876         word x;\r
877         word yy=0;\r
878 \r
879         for(x=0;x<xh*4;x+=4)\r
880         {\r
881                 if(x+4>=page[0].sw-1){ x=0; yy+=4; }\r
882                 modexClearRegion(page, x+xl, y+yy, 4, 4, color);\r
883         }\r
884         //modexputPixel(page, x+xl, y, color);\r
885 }\r
886 \r
887 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str, boolean q)\r
888 {\r
889         word s, o, w;\r
890         word addr = (word) romFontsData.l;\r
891         byte c;\r
892 \r
893         s=romFonts[t].seg;\r
894         o=romFonts[t].off;\r
895         w=romFonts[t].charSize;\r
896         romFontsData.chw=0;\r
897 \r
898         for(; *str != '\0'; str++)\r
899         {\r
900         c = (*str);\r
901         if((c=='\n'/* || c=="\\r
902 "*/) || romFontsData.chw\r
903 >=page->width)\r
904         {\r
905                 romFontsData.chw=0;\r
906                 y+=romFonts[t].charSize;\r
907                 continue;\r
908         }\r
909         //load the letter 'A'\r
910         __asm {\r
911                 MOV DI, addr\r
912                 MOV SI, o\r
913                 MOV ES, s\r
914                 SUB AH, AH\r
915                 MOV AL, c       ; the letter\r
916                 MOV CX, w\r
917                 MUL CX\r
918                 ADD SI, AX      ;the address of charcter\r
919         L1:     MOV AX, ES:SI\r
920                 MOV DS:DI, AX\r
921                 INC SI\r
922                 INC DI\r
923                 DEC CX\r
924                 JNZ L1\r
925         }\r
926 //TODO: OPTIMIZE THIS!!!!\r
927                 modexDrawCharPBuf(page, x, y, t, col, bgcol, q);\r
928 \r
929                 //if(!q) getch();\r
930         }\r
931 }\r
932 \r
933 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
934 {\r
935         word i, s, o, w, j, xp;\r
936         byte l[1024];\r
937         word addr = (word) l;\r
938         word chw=0;\r
939         byte c;\r
940 \r
941         switch(t)\r
942         {\r
943                 case 0:\r
944                         w=14;\r
945                 break;\r
946                 case 1:\r
947                         w=8;\r
948                 break;\r
949                 case 2:\r
950                         w=8;\r
951                 break;\r
952                 case 3:\r
953                         w=16;\r
954                 break;\r
955                 default:\r
956                         t=3;\r
957                         w=16;\r
958                 break;\r
959         }\r
960 \r
961         s=romFonts[t].seg;\r
962         o=romFonts[t].off;\r
963 \r
964         for(; *str != '\0'; str++)\r
965         {\r
966         c = (*str);\r
967         if((c=='\n'/* || c=="\\r
968 "*/)/* || chw>=page->width*/)\r
969         {\r
970                 chw=0;\r
971                 y+=w;\r
972                 continue;\r
973         }\r
974         //load the letter 'A'\r
975         __asm {\r
976                 MOV DI, addr\r
977                 MOV SI, o\r
978                 MOV ES, s\r
979                 SUB AH, AH\r
980                 MOV AL, c       ; the letter\r
981                 MOV CX, w\r
982                 MUL CX\r
983                 ADD SI, AX      ;the address of charcter\r
984         L1:     MOV AX, ES:SI\r
985                 MOV DS:DI, AX\r
986                 INC SI\r
987                 INC DI\r
988                 DEC CX\r
989                 JNZ L1\r
990         }\r
991 \r
992                 for(i=0; i<w; i++)\r
993                 {\r
994                         j=1<<8;\r
995                         xp=0;\r
996                         while(j)\r
997                         {\r
998                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
999                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1000                                 xp++;\r
1001                                 j>>=1;\r
1002                         }\r
1003                 }\r
1004                 chw += xp;\r
1005         }\r
1006 }\r
1007 \r
1008 /* palette dump on display! */\r
1009 void modexpdump(page_t *pee)\r
1010 {\r
1011         int mult=(QUADWH);\r
1012         int palq=(mult)*TILEWH;\r
1013         int palcol=0;\r
1014         int palx, paly;\r
1015         for(paly=0; paly<palq; paly+=mult){\r
1016                 for(palx=0; palx<palq; palx+=mult){\r
1017                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1018                         palcol++;\r
1019                 }\r
1020         }\r
1021 }\r
1022 \r
1023 /////////////////////////////////////////////////////////////////////////////\r
1024 //                                                                                                                                               //\r
1025 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1026 //               the Virtual screen.                                                                                     //\r
1027 //                                                                                                                                               //\r
1028 /////////////////////////////////////////////////////////////////////////////\r
1029 void modexcls(page_t *page, byte color, byte *Where)\r
1030 {\r
1031         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1032         /* set map mask to all 4 planes */\r
1033         outpw(SC_INDEX, 0xff02);\r
1034         //_fmemset(VGA, color, 16000);\r
1035         _fmemset(Where, color, page->width*(page->height)/4);\r
1036 }\r
1037 \r
1038 /*void\r
1039 modexWaitBorder() {\r
1040     while(inp(INPUT_STATUS_1)  & 8)  {\r
1041         // spin\r
1042     }\r
1043 \r
1044     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1045         // spin\r
1046     }\r
1047 }*/\r