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