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