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