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