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