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