OSDN Git Service

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