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