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