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