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