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