OSDN Git Service

==YAY! I GOT IT WORKING THE PLANAR BUFFER RENDERING==
[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 void\r
398 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, byte sprite)\r
399 {\r
400         int plane;\r
401         int px, py, i;\r
402 //      byte near *buff;\r
403 \r
404         px=x;\r
405         py=y;\r
406 //      buff = _nmalloc(p->pwidth+1);\r
407         // TODO Make this fast.  It's SLOOOOOOW\r
408 //      for(plane=0; plane < 4; plane++) {\r
409 //              i=0;\r
410 //              modexSelectPlane(PLANE(plane+x));\r
411 //              for(px = plane; px < p->width; px+=4) {\r
412 //                      offset=px;\r
413 //                      for(py=0; py<p->height/2; py++) {\r
414 //                              //SELECT_ALL_PLANES();\r
415 //                              if(!sprite || p->plane[offset])\r
416 //                                      page->data = &(p->plane[offset][i++]);\r
417 //                              offset+=p->width;\r
418 //                              offset++;\r
419 //                      }\r
420 //              }\r
421 //      }\r
422         for(plane=0; plane < 4; plane++) {\r
423                 i=0;\r
424                 modexSelectPlane(PLANE(plane+x));\r
425                 for(; y < p->height-1; y++) {\r
426                         //for(px=0; px < p->width; px++) {\r
427                                 //printf("%02X ", (int) p->plane[plane][i++]);\r
428 //                              _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);\r
429 //                              printf("buff %u==%s\n", y, *buff);\r
430 //                              _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);\r
431                                 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);\r
432                         //}\r
433                 }\r
434                 //getch();\r
435                 x=px;\r
436                 y=py;\r
437         }\r
438 //      _nfree(buff);\r
439 }\r
440 \r
441 void\r
442 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)\r
443 {\r
444         byte plane;\r
445         word px, py;\r
446         word offset;\r
447 \r
448         /* TODO Make this fast.  It's SLOOOOOOW */\r
449         for(plane=0; plane < 4; plane++) {\r
450                 modexSelectPlane(PLANE(plane+x));\r
451                 for(px = plane; px < bmp->width; px+=4) {\r
452                         offset=px;\r
453                         for(py=0; py<bmp->height; py++) {\r
454                         if(!sprite || bmp->data[offset])\r
455                                 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
456                         offset+=bmp->width;\r
457                         }\r
458                 }\r
459         }\r
460 }\r
461 \r
462 void\r
463 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)\r
464 {\r
465         byte plane;\r
466         word px, py;\r
467         word offset=0;\r
468 \r
469 \r
470         /* TODO Make this fast.  It's SLOOOOOOW */\r
471         for(plane=0; plane < 4; plane++) {\r
472                 modexSelectPlane(PLANE(plane+x));\r
473                 for(px = plane; px < bmp->width; px+=4) {\r
474                         offset=px;\r
475                         for(py=0; py<bmp->height; py++) {\r
476                         if(!sprite || bmp->data[offset])\r
477                                 //modexputPixel(page, x+px, y+py, bmp->data[offset]);\r
478                                 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
479                         offset+=bmp->width;\r
480                         }\r
481                 }\r
482         }\r
483 }\r
484 \r
485 void\r
486 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {\r
487     /* draw the region (the entire freakin bitmap) */\r
488     modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
489 }\r
490 \r
491 void\r
492 modexDrawBmpRegion(page_t *page, int x, int y,\r
493                    int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
494     word poffset = (word) page->data  + y*(page->width/4) + x/4;\r
495     byte far *data = bmp->data;//+bmp->offset;\r
496     word bmpOffset = (word) data + ry * bmp->width + rx;\r
497     word width = rw;\r
498     word height = rh;\r
499     byte plane = 1 << ((byte) x & 0x03);\r
500     word scanCount = width/4 + (width%4 ? 1 :0);\r
501     word nextPageRow = page->width/4 - scanCount;\r
502     word nextBmpRow = (word) bmp->width - width;\r
503     word rowCounter;\r
504     byte planeCounter = 4;\r
505 \r
506 /*      printf("bmp->data=%Fp\n",bmp->data);\r
507         printf("*bmp->data=%Fp\n",*(bmp->data));\r
508         printf("&bmp->data=%Fp\n",&(bmp->data));*/\r
509 \r
510         //code is a bit slow here\r
511     __asm {\r
512                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
513                 MOV ES, AX\r
514 \r
515                 MOV DX, SC_INDEX        ; point at the map mask register\r
516                 MOV AL, MAP_MASK        ;\r
517                 OUT DX, AL              ;\r
518 \r
519         PLANE_LOOP:\r
520                 MOV DX, SC_DATA         ; select the current plane\r
521                 MOV AL, plane           ;\r
522                 OUT DX, AL              ;\r
523 \r
524                 ;-- begin plane painting\r
525                 MOV AX, height          ; start the row counter\r
526                 MOV rowCounter, AX      ;\r
527                 MOV DI, poffset         ; go to the first pixel\r
528                 MOV SI, bmpOffset       ; go to the bmp pixel\r
529         ROW_LOOP:\r
530                 MOV CX, width           ; count the columns\r
531         SCAN_LOOP:\r
532                 MOVSB                   ; copy the pixel\r
533                 SUB CX, 3               ; we skip the next 3\r
534                 ADD SI, 3               ; skip the bmp pixels\r
535                 LOOP SCAN_LOOP          ; finish the scan\r
536 \r
537                 MOV AX, nextPageRow\r
538                 ADD DI, AX              ; go to the next row on screen\r
539                 MOV AX, nextBmpRow\r
540                 ADD SI, AX              ; go to the next row on bmp\r
541 \r
542                 DEC rowCounter\r
543                 JNZ ROW_LOOP            ; do all the rows\r
544                 ;-- end plane painting\r
545 \r
546                 MOV AL, plane           ; advance to the next plane\r
547                 SHL AL, 1               ;\r
548                 AND AL, 0x0f            ; mask the plane properly\r
549                 MOV plane, AL           ; store the plane\r
550 \r
551                 INC bmpOffset           ; start bmp at the right spot\r
552 \r
553                 DEC planeCounter\r
554                 JNZ PLANE_LOOP          ; do all 4 planes\r
555     }\r
556 }\r
557 \r
558 void\r
559 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
560     /* TODO - adapt from test code */\r
561         int plane;\r
562         for(plane=0; plane < 4; plane++)\r
563         {\r
564                 //fack\r
565         }\r
566 }\r
567 \r
568 \r
569 void\r
570 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
571     /* draw the whole sprite */\r
572     modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
573 }\r
574 \r
575 /*void\r
576 modexDrawSpriteRegion(page_t *page, int x, int y,\r
577                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
578     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
579     byte *data = bmp->data;//+bmp->offset;\r
580     word bmpOffset = (word) data + ry * bmp->width + rx;\r
581     word width = rw;\r
582     word height = rh;\r
583     byte plane = 1 << ((byte) x & 0x03);\r
584     word scanCount = width/4 + (width%4 ? 1 :0);\r
585     word nextPageRow = page->width/4 - scanCount;\r
586     word nextBmpRow = (word) bmp->width - width;\r
587     word rowCounter;\r
588     byte planeCounter = 4;\r
589 \r
590     __asm {\r
591                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
592                 MOV ES, AX\r
593 \r
594                 MOV DX, SC_INDEX        ; point at the map mask register\r
595                 MOV AL, MAP_MASK        ;\r
596                 OUT DX, AL              ;\r
597 \r
598         PLANE_LOOP:\r
599                 MOV DX, SC_DATA         ; select the current plane\r
600                 MOV AL, plane           ;\r
601                 OUT DX, AL              ;\r
602 \r
603                 ;-- begin plane painting\r
604                 MOV AX, height          ; start the row counter\r
605                 MOV rowCounter, AX      ;\r
606                 MOV DI, poffset         ; go to the first pixel\r
607                 MOV SI, bmpOffset       ; go to the bmp pixel\r
608         ROW_LOOP:\r
609                 MOV CX, width           ; count the columns\r
610         SCAN_LOOP:\r
611                 LODSB\r
612                 DEC SI\r
613                 CMP AL, 0\r
614                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
615 \r
616                 INC DI                  ; skip the transparent pixel\r
617                 ADD SI, 1\r
618                 JMP NEXT_PIXEL\r
619         DRAW_PIXEL:\r
620                 MOVSB                   ; copy the pixel\r
621         NEXT_PIXEL:\r
622                 SUB CX, 3               ; we skip the next 3\r
623                 ADD SI, 3               ; skip the bmp pixels\r
624                 LOOP SCAN_LOOP          ; finish the scan\r
625 \r
626                 MOV AX, nextPageRow\r
627                 ADD DI, AX              ; go to the next row on screen\r
628                 MOV AX, nextBmpRow\r
629                 ADD SI, AX              ; go to the next row on bmp\r
630 \r
631                 DEC rowCounter\r
632                 JNZ ROW_LOOP            ; do all the rows\r
633                 ;-- end plane painting\r
634 \r
635                 MOV AL, plane           ; advance to the next plane\r
636                 SHL AL, 1               ;\r
637                 AND AL, 0x0f            ; mask the plane properly\r
638                 MOV plane, AL           ; store the plane\r
639 \r
640                 INC bmpOffset           ; start bmp at the right spot\r
641 \r
642                 DEC planeCounter\r
643                 JNZ PLANE_LOOP          ; do all 4 planes\r
644     }\r
645 }//backup!*/\r
646 \r
647 void\r
648 modexDrawSpriteRegion(page_t *page, int x, int y,\r
649                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
650     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
651     byte huge *data = bmp->data;//+bmp->offset;\r
652     word bmpOffset = (word) data + ry * bmp->width + rx;\r
653     word width = rw;\r
654     word height = rh;\r
655     byte plane = 1 << ((byte) x & 0x03);\r
656     word scanCount = width/4 + (width%4 ? 1 :0);\r
657     word nextPageRow = page->width/4 - scanCount;\r
658     word nextBmpRow = (word) bmp->width - width;\r
659     word rowCounter;\r
660     byte planeCounter = 4;\r
661 \r
662     __asm {\r
663                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
664                 MOV ES, AX\r
665 \r
666                 MOV DX, SC_INDEX        ; point at the map mask register\r
667                 MOV AL, MAP_MASK        ;\r
668                 OUT DX, AL              ;\r
669 \r
670         PLANE_LOOP:\r
671                 MOV DX, SC_DATA         ; select the current plane\r
672                 MOV AL, plane           ;\r
673                 OUT DX, AL              ;\r
674 \r
675                 ;-- begin plane painting\r
676                 MOV AX, height          ; start the row counter\r
677                 MOV rowCounter, AX      ;\r
678                 MOV DI, poffset         ; go to the first pixel\r
679                 MOV SI, bmpOffset       ; go to the bmp pixel\r
680         ROW_LOOP:\r
681                 MOV CX, width           ; count the columns\r
682         SCAN_LOOP:\r
683                 LODSB\r
684                 DEC SI\r
685                 CMP AL, 0\r
686                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
687 \r
688                 INC DI                  ; skip the transparent pixel\r
689                 ADD SI, 1\r
690                 JMP NEXT_PIXEL\r
691         DRAW_PIXEL:\r
692                 MOVSB                   ; copy the pixel\r
693         NEXT_PIXEL:\r
694                 SUB CX, 3               ; we skip the next 3\r
695                 ADD SI, 3               ; skip the bmp pixels\r
696                 LOOP SCAN_LOOP          ; finish the scan\r
697 \r
698                 MOV AX, nextPageRow\r
699                 ADD DI, AX              ; go to the next row on screen\r
700                 MOV AX, nextBmpRow\r
701                 ADD SI, AX              ; go to the next row on bmp\r
702 \r
703                 DEC rowCounter\r
704                 JNZ ROW_LOOP            ; do all the rows\r
705                 ;-- end plane painting\r
706 \r
707                 MOV AL, plane           ; advance to the next plane\r
708                 SHL AL, 1               ;\r
709                 AND AL, 0x0f            ; mask the plane properly\r
710                 MOV plane, AL           ; store the plane\r
711 \r
712                 INC bmpOffset           ; start bmp at the right spot\r
713 \r
714                 DEC planeCounter\r
715                 JNZ PLANE_LOOP          ; do all 4 planes\r
716     }\r
717 }\r
718 \r
719 /* copy a region of video memory from one page to another.\r
720  * It assumes that the left edge of the tile is the same on both\r
721  * regions and the memory areas do not overlap.\r
722  */\r
723 void\r
724 modexCopyPageRegion(page_t *dest, page_t *src,\r
725                     word sx, word sy,\r
726                     word dx, word dy,\r
727                     word width, word height)\r
728 {\r
729     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
730     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
731     word scans   = width/4;\r
732     word nextSrcRow = src->width/4 - scans - 1;\r
733     word nextDestRow = dest->width/4 - scans - 1;\r
734     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
735     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
736     byte left = lclip[sx&0x03];\r
737     byte right = rclip[(sx+width)&0x03];\r
738 \r
739     __asm {\r
740                 MOV AX, SCREEN_SEG      ; work in the vga space\r
741                 MOV ES, AX              ;\r
742                 MOV DI, doffset         ;\r
743                 MOV SI, soffset         ;\r
744 \r
745                 MOV DX, GC_INDEX        ; turn off cpu bits\r
746                 MOV AX, 0008h           ;\r
747                 OUT DX, AX\r
748 \r
749                 MOV AX, SC_INDEX        ; point to the mask register\r
750                 MOV DX, AX              ;\r
751                 MOV AL, MAP_MASK        ;\r
752                 OUT DX, AL              ;\r
753                 INC DX                  ;\r
754 \r
755         ROW_START:\r
756                 PUSH DS\r
757                 MOV AX, ES\r
758                 MOV DS, AX\r
759                 MOV CX, scans           ; the number of latches\r
760 \r
761                 MOV AL, left            ; do the left column\r
762                 OUT DX, AL              ;\r
763                 MOVSB                   ;\r
764                 DEC CX                  ;\r
765 \r
766                 MOV AL, 0fh             ; do the inner columns\r
767                 OUT DX, AL\r
768                 REP MOVSB               ; copy the pixels\r
769 \r
770                 MOV AL, right           ; do the right column\r
771                 OUT DX, AL\r
772                 MOVSB\r
773                 POP DS\r
774 \r
775                 MOV AX, SI              ; go the start of the next row\r
776                 ADD AX, nextSrcRow      ;\r
777                 MOV SI, AX              ;\r
778                 MOV AX, DI              ;\r
779                 ADD AX, nextDestRow     ;\r
780                 MOV DI, AX              ;\r
781 \r
782                 DEC height              ; do the rest of the actions\r
783                 JNZ ROW_START           ;\r
784 \r
785                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
786                 MOV AL, 0ffh            ; none from latches\r
787                 OUT DX, AL              ;\r
788     }\r
789 }\r
790 \r
791 \r
792 /* fade and flash */\r
793 void\r
794 modexFadeOn(word fade, byte *palette) {\r
795     fadePalette(-fade, 64, 64/fade+1, palette);\r
796 }\r
797 \r
798 \r
799 void\r
800 modexFadeOff(word fade, byte *palette) {\r
801     fadePalette(fade, 0, 64/fade+1, palette);\r
802 }\r
803 \r
804 \r
805 void\r
806 modexFlashOn(word fade, byte *palette) {\r
807     fadePalette(fade, -64, 64/fade+1, palette);\r
808 }\r
809 \r
810 \r
811 void\r
812 modexFlashOff(word fade, byte *palette) {\r
813     fadePalette(-fade, 0, 64/fade+1, palette);\r
814 }\r
815 \r
816 \r
817 static void\r
818 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
819     word i;\r
820     byte dim = start;\r
821 \r
822     /* handle the case where we just update */\r
823     if(iter == 0) {\r
824         modexPalUpdate1(palette);\r
825         return;\r
826     }\r
827 \r
828     while(iter > 0) {  /* FadeLoop */\r
829         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
830             tmppal[i] = palette[i] - dim;\r
831             if(tmppal[i] > 127) {\r
832                 tmppal[i] = 0;\r
833             } else if(tmppal[i] > 63) {\r
834                 tmppal[i] = 63;\r
835             }\r
836         }\r
837         modexPalUpdate1(tmppal);\r
838         iter--;\r
839         dim += fade;\r
840     }\r
841 }\r
842 \r
843 \r
844 /* save and load */\r
845 void\r
846 modexPalSave(byte *palette) {\r
847     int  i;\r
848 \r
849     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
850     for(i=0; i<PAL_SIZE; i++) {\r
851         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
852     }\r
853 }\r
854 \r
855 \r
856 byte *\r
857 modexNewPal() {\r
858     byte *ptr;\r
859     ptr = malloc(PAL_SIZE);\r
860 \r
861     /* handle errors */\r
862     if(!ptr) {\r
863         printf("Could not allocate palette.\n");\r
864         exit(-1);\r
865     }\r
866 \r
867     return ptr;\r
868 }\r
869 \r
870 \r
871 void\r
872 modexLoadPalFile(byte *filename, byte **palette) {\r
873     FILE *file;\r
874     byte *ptr;\r
875 \r
876     /* free the palette if it exists */\r
877     if(*palette) {\r
878         free(*palette);\r
879     }\r
880 \r
881     /* allocate the new palette */\r
882     *palette = modexNewPal();\r
883 \r
884     /* open the file */\r
885     file = fopen(filename, "rb");\r
886     if(!file) {\r
887         printf("Could not open palette file: %s\n", filename);\r
888         exit(-2);\r
889     }\r
890 \r
891     /* read the file */\r
892     ptr = *palette;\r
893     while(!feof(file)) {\r
894         *ptr++ = fgetc(file);\r
895     }\r
896 \r
897     fclose(file);\r
898 }\r
899 \r
900 \r
901 void\r
902 modexSavePalFile(char *filename, byte *pal) {\r
903     unsigned int i;\r
904     FILE *file;\r
905 \r
906     /* open the file for writing */\r
907     file = fopen(filename, "wb");\r
908     if(!file) {\r
909         printf("Could not open %s for writing\n", filename);\r
910         exit(-2);\r
911     }\r
912 \r
913     /* write the data to the file */\r
914     fwrite(pal, 1, PAL_SIZE, file);\r
915     fclose(file);\r
916 }\r
917 \r
918 \r
919 /* blanking */\r
920 void\r
921 modexPalBlack() {\r
922     fadePalette(-1, 64, 1, tmppal);\r
923 }\r
924 \r
925 \r
926 void\r
927 modexPalWhite() {\r
928     fadePalette(-1, -64, 1, tmppal);\r
929 }\r
930 \r
931 \r
932 /* utility */\r
933 void\r
934 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
935 {\r
936         byte *p = bmp->palette;\r
937         word w=0;\r
938         word q=0;\r
939         word qq=0;\r
940         static word a[PAL_SIZE];        //palette array of change values!\r
941         word z=0, aq=0, aa=0, pp=0;\r
942 \r
943         modexWaitBorder();\r
944         if((*i)==0)\r
945         {\r
946                 memset(a, -1, sizeof(a));\r
947                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
948         }\r
949         else if(qp==0)\r
950         {\r
951                 q=(*i);\r
952         }\r
953         else\r
954         {\r
955                 q=(*i);\r
956                 qq=(*i)/3;\r
957 //              printf("q: %02d\n", (q));\r
958 //              printf("qq: %02d\n", (qq));\r
959                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
960                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
961         }\r
962         if((*i)<PAL_SIZE/2 && w==0)\r
963         {\r
964                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
965                 {\r
966                         //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
967 //____                  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
968                         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
969                         {\r
970                                 w++;\r
971                                 break;\r
972                         }\r
973                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
974                         {\r
975                                 //printf("qp=%d\n", qp);\r
976                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
977                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
978                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
979                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
980                         }\r
981                         else\r
982                         {\r
983                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
984                                 else\r
985                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
986                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
987                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
988                         }\r
989                 }\r
990                 //if(qp>0) printf("qp=%d\n", qp);\r
991                 //if(qp>0) printf("                                             (*i)=%d\n", (*i)/3);\r
992         }\r
993         modexWaitBorder();          /* waits one retrace -- less flicker */\r
994         if((*i)>=PAL_SIZE/2 && w==0)\r
995         {\r
996                 for(; (*i)<PAL_SIZE; (*i)++)\r
997                 {\r
998 //____                  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
999                         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
1000                         {\r
1001                                 w++;\r
1002                                 break;\r
1003                         }\r
1004                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
1005                         {\r
1006                                 //printf("qp=%d\n", qp);\r
1007                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
1008                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
1009                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
1010                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
1011                         }\r
1012                         else\r
1013                         {\r
1014                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
1015                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
1016                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
1017                         }\r
1018                 }\r
1019                 //printf("                                              (*i)=%d\n", (*i)/3);\r
1020         }\r
1021 \r
1022 printf("\nqqqqqqqq\n\n");\r
1023 \r
1024         //palette checker~\r
1025         if(q>0 && qp==0)\r
1026         {\r
1027                 long lq;\r
1028                 long bufSize = (bmp->width * bmp->height);\r
1029                 pp = q;\r
1030                 //printf("1(*i)=%02d\n", (*i)/3);\r
1031                 //printf("1z=%02d\n", z/3);\r
1032                 chkcolor(bmp, &q, &a, &aa, &z, i);\r
1033                 //printf("2(*i)=%02d\n", (*i)/3);\r
1034                 //printf("2z=%02d\n", z/3);\r
1035                 aq=0;\r
1036 aqpee:\r
1037                 while(aq<=aa)\r
1038                 {\r
1039 //                      printf("a[%02d]=(%d)\n", aq, a[aq]);\r
1040                         if(a[aq]==-1) aq++;\r
1041                         else { aqoffset++; break; }\r
1042                 }\r
1043 //update the image data here!\r
1044         for(lq=0; lq<bufSize; lq++)\r
1045         {\r
1046                                 /*\r
1047                                                                         note to self\r
1048                                                                         use a[qp] instead of bmp->offset for this spot!\r
1049                                                                         NO! wwww\r
1050                                 */\r
1051 \r
1052                                 /*\r
1053                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
1054                                 */\r
1055 \r
1056                 //(offset/bmp->offset)*bmp->offset\r
1057 \r
1058 \r
1059                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
1060                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1061                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
1062                 /*if(bmp->data[lq]+bmp->offset==aq)\r
1063                 {\r
1064                         //printf("%02d", bmp->data[lq]);\r
1065                         //printf("\n%02d\n", bmp->offset);\r
1066                         printf("aq=%02d ", aq);\r
1067                         printf("a[aq]=%02d      ", a[aq]);\r
1068                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
1069                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
1070                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
1071 //++++                  bmp->data[lq]=a[aq]-aqpp;\r
1072 //                      printf("_%d ", bmp->data[lq]);\r
1073                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1074                 }\r
1075                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
1076                 {\r
1077                         if(bmp->data[lq]+bmp->offset >= aq)\r
1078                         {\r
1079                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
1080                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
1081                         }\r
1082                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
1083                 }*/\r
1084 \r
1085                 //printf("%02d`", bmp->data[lq]);\r
1086                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1087         }\r
1088 \r
1089 //printf("              aq=%02d\n", aq);\r
1090 //printf("              aa=%02d\n", aa);\r
1091 \r
1092         //update the palette~\r
1093         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
1094         (*i)=pp;\r
1095 \r
1096         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
1097         }\r
1098 }\r
1099 \r
1100 void\r
1101 modexPalUpdate1(byte *p)\r
1102 {\r
1103         int i;\r
1104         modexWaitBorder();\r
1105         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1106         for(i=0; i<PAL_SIZE/2; i++)\r
1107         {\r
1108                 outp(PAL_DATA_REG, p[i]);\r
1109         }\r
1110         modexWaitBorder();          /* waits one retrace -- less flicker */\r
1111         for(; i<PAL_SIZE; i++)\r
1112         {\r
1113                 outp(PAL_DATA_REG, p[(i)]);\r
1114         }\r
1115 }\r
1116 \r
1117 void\r
1118 modexPalUpdate0(byte *p)\r
1119 {\r
1120         int i;\r
1121         modexWaitBorder();\r
1122         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1123         for(i=0; i<PAL_SIZE/2; i++)\r
1124         {\r
1125                 outp(PAL_DATA_REG, rand());\r
1126         }\r
1127         modexWaitBorder();          /* waits one retrace -- less flicker */\r
1128         for(; i<PAL_SIZE; i++)\r
1129         {\r
1130                 outp(PAL_DATA_REG, rand());\r
1131         }\r
1132 }\r
1133 \r
1134 void\r
1135 modexPalOverscan(byte *p, word col)\r
1136 {\r
1137         modexWaitBorder();\r
1138         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1139         outp(PAL_DATA_REG, col);\r
1140 }\r
1141 \r
1142 //color checker~\r
1143 //i want to make another vesion that checks the palette when the palette is being appened~\r
1144 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
1145 {\r
1146                 byte *pal;\r
1147                 word zz=0;\r
1148                 pal = modexNewPal();\r
1149                 modexPalSave(pal);\r
1150                 //printf("q: %02d\n", (*q));\r
1151                 printf("chkcolor start~\n");\r
1152                 printf("1                               (*z): %d\n", (*z)/3);\r
1153                 printf("1                               (*i): %d\n", (*i)/3);\r
1154 //              printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
1155                 printf("wwwwwwwwwwwwwwww\n");\r
1156                 //check palette for dups\r
1157                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
1158                 {\r
1159                         //printf("\n            z: %d\n", (*z));\r
1160                         //printf("              q: %d\n", (*q));\r
1161                         //printf("              z+q: %d\n\n", ((*z)+(*q)));\r
1162                         //if((*z)%3==0)\r
1163                         //{\r
1164 //----                          if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
1165                                 if((*z)==(*i))\r
1166                                 {\r
1167 //                                      printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1168 //                                      printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
1169 //0000                                  (*z)-=3;\r
1170                                         break;\r
1171                                 }\r
1172                                 else for(zz=0; zz<(*q); zz+=3)\r
1173                                 {\r
1174                                         //printf("zz: %02d\n", zz/3);\r
1175                                         if(zz%3==0)\r
1176                                         {\r
1177                                                 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
1178                                                 {\r
1179 //                                                      (*z)-=3;\r
1180 //                                                      (*i)-=3;\r
1181 //                                                      printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
1182 //                                                      printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
1183                                                         break;\r
1184                                                 }\r
1185                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
1186                                                 {\r
1187 //                                                      printf("\n\nwwwwwwwwwwwwwwww\n");\r
1188 //                                                      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
1189 //                                                      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
1190 //                                                      //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
1191 //                                                      printf("        z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1192 //++++                                                  (*i)--;\r
1193 //                                                      (*z)--;\r
1194                                                         //expand dong here\r
1195 /*\r
1196 planned features that i plan to implement~\r
1197 image that has values on the pallete list!\r
1198 wwww\r
1199 no... wait.... no wwww\r
1200 */\r
1201                                                         //for(zzii=0; zzii<3; zzii++)\r
1202                                                         //{\r
1203                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
1204                                                                 a[(((*z)+(*q)))]=zz;\r
1205                                                         //}\r
1206                                                         (*aa)=(((*z)+(*q)));\r
1207                                                         printf("!!                                      a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
1208 //                                                      printf("\n              aa: %d\n\n", (*aa));\r
1209 //                                                      printf("        a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
1210 //                                                      printf("wwwwwwwwwwwwwwww\n\n");\r
1211                                                 }\r
1212                                                 /*else\r
1213                                                 {\r
1214                                                         printf("================\n");\r
1215                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
1216                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
1217                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1218                                                         printf("================\n");\r
1219                                                 }*/\r
1220                                                 //printf("[%d]", (zz+q));\r
1221                                         }\r
1222                                 }\r
1223                 }\r
1224                 printf("wwwwwwwwwwwwwwww\n");\r
1225                 printf("2                               (*z): %d\n", (*z)/3);\r
1226                 printf("2                               (*i): %d\n", (*i)/3);\r
1227 //              printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
1228                 printf("chkcolor end~\n");\r
1229                 free(pal);\r
1230 }\r
1231 \r
1232 void modexputPixel(page_t *page, int x, int y, byte color)\r
1233 {\r
1234         word pageOff = (word) page->data;\r
1235         /* Each address accesses four neighboring pixels, so set\r
1236            Write Plane Enable according to which pixel we want\r
1237            to modify.  The plane is determined by the two least\r
1238            significant bits of the x-coordinate: */\r
1239         modexSelectPlane(PLANE(x));\r
1240         //outp(SC_INDEX, 0x02);\r
1241         //outp(SC_DATA, 0x01 << (x & 3));\r
1242 \r
1243         /* The offset of the pixel into the video segment is\r
1244            offset = (width * y + x) / 4, and write the given\r
1245            color to the plane we selected above.  Heed the active\r
1246            page start selection. */\r
1247         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1248 \r
1249 }\r
1250 \r
1251 byte modexgetPixel(page_t *page, int x, int y)\r
1252 {\r
1253         word pageOff = (word) page->data;\r
1254         /* Select the plane from which we must read the pixel color: */\r
1255         outpw(GC_INDEX, 0x04);\r
1256         outpw(GC_INDEX+1, x & 3);\r
1257 \r
1258         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1259 \r
1260 }\r
1261 \r
1262 void modexhlin(page_t *page, word xl, word xh, word y, word color)\r
1263 {\r
1264         word x;\r
1265         word yy=0;\r
1266 \r
1267         for(x=0;x<xh*4;x+=4)\r
1268         {\r
1269                 if(x+4>=page[0].sw-1){ x=0; yy+=4; }\r
1270                 modexClearRegion(page, x+xl, y+yy, 4, 4, color);\r
1271         }\r
1272         //modexputPixel(page, x+xl, y, color);\r
1273 }\r
1274 \r
1275 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1276 {\r
1277         word i, s, o, w, j, xp;\r
1278         byte l[1024];\r
1279         word addr = (word) l;\r
1280         word chw=0;\r
1281         byte c;\r
1282 \r
1283         switch(t)\r
1284         {\r
1285                 case 0:\r
1286                         w=14;\r
1287                 break;\r
1288                 case 1:\r
1289                         w=8;\r
1290                 break;\r
1291                 case 2:\r
1292                         w=8;\r
1293                 break;\r
1294                 case 3:\r
1295                         w=16;\r
1296                 break;\r
1297                 default:\r
1298                         t=3;\r
1299                         w=16;\r
1300                 break;\r
1301         }\r
1302 \r
1303         s=romFonts[t].seg;\r
1304         o=romFonts[t].off;\r
1305 \r
1306         for(; *str != '\0'; str++)\r
1307         {\r
1308         c = (*str);\r
1309         if((c=='\n'/* || c=="\\r
1310 "*/) || chw\r
1311 >=page->width)\r
1312         {\r
1313                 chw=0;\r
1314                 y+=w;\r
1315                 continue;\r
1316         }\r
1317         //load the letter 'A'\r
1318         __asm {\r
1319                 MOV DI, addr\r
1320                 MOV SI, o\r
1321                 MOV ES, s\r
1322                 SUB AH, AH\r
1323                 MOV AL, c       ; the letter\r
1324                 MOV CX, w\r
1325                 MUL CX\r
1326                 ADD SI, AX      ;the address of charcter\r
1327         L1:     MOV AX, ES:SI\r
1328                 MOV DS:DI, AX\r
1329                 INC SI\r
1330                 INC DI\r
1331                 DEC CX\r
1332                 JNZ L1\r
1333         }\r
1334 \r
1335                 for(i=0; i<w; i++)\r
1336                 {\r
1337                         j=1<<8;\r
1338                         xp=0;\r
1339                         while(j)\r
1340                         {\r
1341                                 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1342                                 xp++;\r
1343                                 j>>=1;\r
1344                         }\r
1345                 }\r
1346                 chw += xp;\r
1347         }\r
1348 }\r
1349 \r
1350 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1351 {\r
1352         word i, s, o, w, j, xp;\r
1353         byte l[1024];\r
1354         word addr = (word) l;\r
1355         word chw=0;\r
1356         byte c;\r
1357 \r
1358         switch(t)\r
1359         {\r
1360                 case 0:\r
1361                         w=14;\r
1362                 break;\r
1363                 case 1:\r
1364                         w=8;\r
1365                 break;\r
1366                 case 2:\r
1367                         w=8;\r
1368                 break;\r
1369                 case 3:\r
1370                         w=16;\r
1371                 break;\r
1372                 default:\r
1373                         t=3;\r
1374                         w=16;\r
1375                 break;\r
1376         }\r
1377 \r
1378         s=romFonts[t].seg;\r
1379         o=romFonts[t].off;\r
1380 \r
1381         for(; *str != '\0'; str++)\r
1382         {\r
1383         c = (*str);\r
1384         if((c=='\n'/* || c=="\\r
1385 "*/)/* || chw>=page->width*/)\r
1386         {\r
1387                 chw=0;\r
1388                 y+=w;\r
1389                 continue;\r
1390         }\r
1391         //load the letter 'A'\r
1392         __asm {\r
1393                 MOV DI, addr\r
1394                 MOV SI, o\r
1395                 MOV ES, s\r
1396                 SUB AH, AH\r
1397                 MOV AL, c       ; the letter\r
1398                 MOV CX, w\r
1399                 MUL CX\r
1400                 ADD SI, AX      ;the address of charcter\r
1401         L1:     MOV AX, ES:SI\r
1402                 MOV DS:DI, AX\r
1403                 INC SI\r
1404                 INC DI\r
1405                 DEC CX\r
1406                 JNZ L1\r
1407         }\r
1408 \r
1409                 for(i=0; i<w; i++)\r
1410                 {\r
1411                         j=1<<8;\r
1412                         xp=0;\r
1413                         while(j)\r
1414                         {\r
1415                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1416                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1417                                 xp++;\r
1418                                 j>>=1;\r
1419                         }\r
1420                 }\r
1421                 chw += xp;\r
1422         }\r
1423 }\r
1424 \r
1425 /* palette dump on display! */\r
1426 void pdump(page_t *pee)\r
1427 {\r
1428         int mult=(QUADWH);\r
1429         int palq=(mult)*TILEWH;\r
1430         int palcol=0;\r
1431         int palx, paly;\r
1432         for(paly=0; paly<palq; paly+=mult){\r
1433                 for(palx=0; palx<palq; palx+=mult){\r
1434                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1435                         palcol++;\r
1436                 }\r
1437         }\r
1438 }\r
1439 \r
1440 /////////////////////////////////////////////////////////////////////////////\r
1441 //                                                                                                                                               //\r
1442 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1443 //               the Virtual screen.                                                                                     //\r
1444 //                                                                                                                                               //\r
1445 /////////////////////////////////////////////////////////////////////////////\r
1446 void cls(page_t *page, byte color, byte *Where)\r
1447 {\r
1448         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1449         /* set map mask to all 4 planes */\r
1450         outpw(SC_INDEX, 0xff02);\r
1451         //_fmemset(VGA, color, 16000);\r
1452         _fmemset(Where, color, page->width*(page->height));\r
1453 }\r
1454 \r
1455 void\r
1456 modexWaitBorder() {\r
1457     while(inp(INPUT_STATUS_1)  & 8)  {\r
1458         /* spin */\r
1459     }\r
1460 \r
1461     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1462         /* spin */\r
1463     }\r
1464 }\r