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