]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
remove wraparound check in modex print, add addr adjust for newline.
[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 x_draw = x;\r
884         word addr = (word) romFontsData.l;\r
885         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
886         word addrr = addrq;\r
887         byte c;\r
888 \r
889         s=romFonts[t].seg;\r
890         o=romFonts[t].off;\r
891         w=romFonts[t].charSize;\r
892         romFontsData.chw=0;\r
893 \r
894         for(; *str != '\0'; str++)\r
895         {\r
896         c = (*str);\r
897         if(c=='\n')\r
898         {\r
899                 x = x_draw;\r
900                 romFontsData.chw = 0;\r
901                 addrq += (page->width / 4) * 8;\r
902                 addrr = addrq;\r
903                 y += 8;\r
904                 continue;\r
905         }\r
906         //load the letter 'A'\r
907         __asm {\r
908                 MOV DI, addr\r
909                 MOV SI, o\r
910                 MOV ES, s\r
911                 SUB AH, AH\r
912                 MOV AL, c       ; the letter\r
913                 MOV CX, w\r
914                 MUL CX\r
915                 ADD SI, AX      ;the address of charcter\r
916         L1:     MOV AX, ES:SI\r
917                 MOV DS:DI, AX\r
918                 INC SI\r
919                 INC DI\r
920                 DEC CX\r
921                 JNZ L1\r
922         }\r
923 //TODO: OPTIMIZE THIS!!!!\r
924                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
925                 x_draw += 8; /* track X for edge of screen */\r
926                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
927         }\r
928 }\r
929 \r
930 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
931 {\r
932         word i, s, o, w, j, xp;\r
933         byte l[1024];\r
934         word addr = (word) l;\r
935         word chw=0;\r
936         byte c;\r
937 \r
938         switch(t)\r
939         {\r
940                 case 0:\r
941                         w=14;\r
942                 break;\r
943                 case 1:\r
944                         w=8;\r
945                 break;\r
946                 case 2:\r
947                         w=8;\r
948                 break;\r
949                 case 3:\r
950                         w=16;\r
951                 break;\r
952                 default:\r
953                         t=3;\r
954                         w=16;\r
955                 break;\r
956         }\r
957 \r
958         s=romFonts[t].seg;\r
959         o=romFonts[t].off;\r
960 \r
961         for(; *str != '\0'; str++)\r
962         {\r
963         c = (*str);\r
964         if((c=='\n'/* || c=="\\r
965 "*/)/* || chw>=page->width*/)\r
966         {\r
967                 chw=0;\r
968                 y+=w;\r
969                 continue;\r
970         }\r
971         //load the letter 'A'\r
972         __asm {\r
973                 MOV DI, addr\r
974                 MOV SI, o\r
975                 MOV ES, s\r
976                 SUB AH, AH\r
977                 MOV AL, c       ; the letter\r
978                 MOV CX, w\r
979                 MUL CX\r
980                 ADD SI, AX      ;the address of charcter\r
981         L1:     MOV AX, ES:SI\r
982                 MOV DS:DI, AX\r
983                 INC SI\r
984                 INC DI\r
985                 DEC CX\r
986                 JNZ L1\r
987         }\r
988 \r
989                 for(i=0; i<w; i++)\r
990                 {\r
991                         j=1<<8;\r
992                         xp=0;\r
993                         while(j)\r
994                         {\r
995                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
996                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
997                                 xp++;\r
998                                 j>>=1;\r
999                         }\r
1000                 }\r
1001                 chw += xp;\r
1002         }\r
1003 }\r
1004 \r
1005 /* palette dump on display! */\r
1006 void modexpdump(page_t *pee)\r
1007 {\r
1008         int mult=(QUADWH);\r
1009         int palq=(mult)*TILEWH;\r
1010         int palcol=0;\r
1011         int palx, paly;\r
1012         for(paly=0; paly<palq; paly+=mult){\r
1013                 for(palx=0; palx<palq; palx+=mult){\r
1014                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1015                         palcol++;\r
1016                 }\r
1017         }\r
1018 }\r
1019 \r
1020 /////////////////////////////////////////////////////////////////////////////\r
1021 //                                                                                                                                               //\r
1022 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1023 //               the Virtual screen.                                                                                     //\r
1024 //                                                                                                                                               //\r
1025 /////////////////////////////////////////////////////////////////////////////\r
1026 void modexcls(page_t *page, byte color, byte *Where)\r
1027 {\r
1028         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1029         /* set map mask to all 4 planes */\r
1030         outpw(SC_INDEX, 0xff02);\r
1031         //_fmemset(VGA, color, 16000);\r
1032         _fmemset(Where, color, page->width*(page->height)/4);\r
1033 }\r
1034 \r
1035 /*void\r
1036 modexWaitBorder() {\r
1037     while(inp(INPUT_STATUS_1)  & 8)  {\r
1038         // spin\r
1039     }\r
1040 \r
1041     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1042         // spin\r
1043     }\r
1044 }*/\r
1045 \r
1046 void bios_cls() {\r
1047         VGA_ALPHA_PTR ap;\r
1048         VGA_RAM_PTR rp;\r
1049         unsigned char m;\r
1050 \r
1051         m = int10_getmode();\r
1052         if ((rp=vga_state.vga_graphics_ram) != NULL && !(m <= 3 || m == 7)) {\r
1053                 unsigned int i,im;\r
1054 \r
1055                 im = (FP_SEG(vga_state.vga_graphics_ram_fence) - FP_SEG(vga_state.vga_graphics_ram));\r
1056                 if (im > 0xFFE) im = 0xFFE;\r
1057                 im <<= 4;\r
1058                 for (i=0;i < im;i++) vga_state.vga_graphics_ram[i] = 0;\r
1059         }\r
1060         else if ((ap=vga_state.vga_alpha_ram) != NULL) {\r
1061                 unsigned int i,im;\r
1062 \r
1063                 im = (FP_SEG(vga_state.vga_alpha_ram_fence) - FP_SEG(vga_state.vga_alpha_ram));\r
1064                 if (im > 0x7FE) im = 0x7FE;\r
1065                 im <<= 4 - 1; /* because ptr is type uint16_t */\r
1066                 for (i=0;i < im;i++) vga_state.vga_alpha_ram[i] = 0x0720;\r
1067         }\r
1068         else {\r
1069                 printf("WARNING: bios cls no ptr\n");\r
1070         }\r
1071 }\r