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