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