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