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