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