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