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