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