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