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