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