]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.c
Merge branch 'master' of github.com:sparky4/16
[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         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;\r
378 }\r
379 \r
380 //=============================================================================\r
381 \r
382 void\r
383 modexPanPage(page_t *page, int dx, int dy) {\r
384         page[0].dx = dx;\r
385         page[0].dy = dy;\r
386 }\r
387 \r
388 void\r
389 modexSelectPlane(byte plane) {\r
390         outp(SC_INDEX, MAP_MASK);         /* select plane */\r
391         outp(SC_DATA,  plane);\r
392 }\r
393 \r
394 void\r
395 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
396         word pageOff = (word) page->data;\r
397         word xoff=x/4;     /* xoffset that begins each row */\r
398         word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
399         word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */\r
400         word nextRow = page->stridew-scanCount-1;  /* loc of next row */\r
401         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
402         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
403         byte left = lclip[x&0x03];\r
404         byte right = rclip[(x+w)&0x03];\r
405 \r
406         /* handle the case which requires an extra group */\r
407         if((x & 0x03) && !((x+w) & 0x03)) {\r
408           right=0x0f;\r
409         }\r
410 \r
411         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
412 \r
413         __asm {\r
414                 PUSHF\r
415                 PUSH ES\r
416                 PUSH AX\r
417                 PUSH BX\r
418                 PUSH CX\r
419                 PUSH DX\r
420                 PUSH SI\r
421                 PUSH DI\r
422                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
423                 MOV ES, AX\r
424                 MOV DI, poffset  ; go to the first pixel\r
425                 MOV DX, SC_INDEX        ; point to the map mask\r
426                 MOV AL, MAP_MASK\r
427                 OUT DX, AL\r
428                 INC DX\r
429                 MOV AL, color      ; get ready to write colors\r
430         SCAN_START:\r
431                 MOV CX, scanCount          ; count the line\r
432                 MOV BL, AL                ; remember color\r
433                 MOV AL, left            ; do the left clip\r
434                 OUT DX, AL                ; set the left clip\r
435                 MOV AL, BL                ; restore color\r
436                 STOSB              ; write the color\r
437                 DEC CX\r
438                 JZ SCAN_DONE            ; handle 1 group stuff\r
439 \r
440                 ;-- write the main body of the scanline\r
441                 MOV BL, AL                ; remember color\r
442                 MOV AL, 0x0f            ; write to all pixels\r
443                 OUT DX, AL\r
444                 MOV AL, BL                ; restore color\r
445                 REP STOSB                  ; write the color\r
446         SCAN_DONE:\r
447                 MOV BL, AL                ; remeber color\r
448                 MOV AL, right\r
449                 OUT DX, AL                ; do the right clip\r
450                 MOV AL, BL                ; restore color\r
451                 STOSB              ; write pixel\r
452                 ADD DI, nextRow  ; go to the next row\r
453                 DEC h\r
454                 JNZ SCAN_START\r
455                 POP DI\r
456                 POP SI\r
457                 POP DX\r
458                 POP CX\r
459                 POP BX\r
460                 POP AX\r
461                 POP ES\r
462                 POPF\r
463         }\r
464 }\r
465 \r
466 /* moved to src/lib/modex16/16render.c */\r
467 \r
468 /* copy a region of video memory from one page to another.\r
469  * It assumes that the left edge of the tile is the same on both\r
470  * regions and the memory areas do not overlap.\r
471  */\r
472 void\r
473 modexCopyPageRegion(page_t *dest, page_t *src,\r
474                         word sx, word sy,\r
475                         word dx, word dy,\r
476                         word width, word height)\r
477 {\r
478         word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;\r
479         word soffset = (word)src->data + sy*(src->stridew) + sx/4;\r
480         word scans   = vga_state.vga_stride;                            //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
481         word nextSrcRow = src->stridew - scans - 1;\r
482         word nextDestRow = dest->stridew - scans - 1;\r
483         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
484         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
485         byte left = lclip[sx&0x03];\r
486         byte right = rclip[(sx+width)&0x03];\r
487 \r
488         /* handle the case which requires an extra group */\r
489         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
490                 right=0x0f;\r
491         }\r
492 \r
493 //      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
494 \r
495         __asm {\r
496                 PUSHF\r
497                 PUSH ES\r
498                 PUSH AX\r
499                 PUSH BX\r
500                 PUSH CX\r
501                 PUSH DX\r
502                 PUSH SI\r
503                 PUSH DI\r
504 \r
505                 MOV AX, SCREEN_SEG        ; work in the vga space\r
506                 MOV ES, AX                ;\r
507                 MOV DI, doffset  ;\r
508                 MOV SI, soffset  ;\r
509 \r
510                 MOV DX, GC_INDEX        ; turn off cpu bits\r
511                 MOV AX, 0008h      ;\r
512                 OUT DX, AX\r
513 \r
514                 MOV AX, SC_INDEX        ; point to the mask register\r
515                 MOV DX, AX                ;\r
516                 MOV AL, MAP_MASK        ;\r
517                 OUT DX, AL                ;\r
518                 INC DX            ;\r
519 \r
520         ROW_START:\r
521                 PUSH DS\r
522                 MOV AX, ES\r
523                 MOV DS, AX\r
524                 MOV CX, scans      ; the number of latches\r
525 \r
526                 MOV AL, left            ; do the left column\r
527                 OUT DX, AL                ;\r
528                 MOVSB              ;\r
529                 DEC CX            ;\r
530 \r
531                 MOV AL, 0fh              ; do the inner columns\r
532                 OUT DX, AL\r
533                 REP MOVSB                  ; copy the pixels\r
534 \r
535                 MOV AL, right      ; do the right column\r
536                 OUT DX, AL\r
537                 MOVSB\r
538                 POP DS\r
539 \r
540                 MOV AX, SI                ; go the start of the next row\r
541                 ADD AX, nextSrcRow        ;\r
542                 MOV SI, AX                ;\r
543                 MOV AX, DI                ;\r
544                 ADD AX, nextDestRow      ;\r
545                 MOV DI, AX                ;\r
546 \r
547                 DEC height                ; do the rest of the actions\r
548                 JNZ ROW_START      ;\r
549 \r
550                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
551                 MOV AL, 0ffh            ; none from latches\r
552                 OUT DX, AL                ;\r
553 \r
554                 POP DI\r
555                 POP SI\r
556                 POP DX\r
557                 POP CX\r
558                 POP BX\r
559                 POP AX\r
560                 POP ES\r
561                 POPF\r
562         }\r
563 }\r
564 \r
565 \r
566 /* fade and flash */\r
567 void\r
568 modexFadeOn(word fade, byte *palette) {\r
569         fadePalette(-fade, 64, 64/fade+1, palette);\r
570 }\r
571 \r
572 \r
573 void\r
574 modexFadeOff(word fade, byte *palette) {\r
575         fadePalette(fade, 0, 64/fade+1, palette);\r
576 }\r
577 \r
578 \r
579 void\r
580 modexFlashOn(word fade, byte *palette) {\r
581         fadePalette(fade, -64, 64/fade+1, palette);\r
582 }\r
583 \r
584 \r
585 void\r
586 modexFlashOff(word fade, byte *palette) {\r
587         fadePalette(-fade, 0, 64/fade+1, palette);\r
588 }\r
589 \r
590 \r
591 static void\r
592 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
593         word i;\r
594         byte dim = start;\r
595 \r
596         /* handle the case where we just update */\r
597         if(iter == 0) {\r
598         modexPalUpdate1(palette);\r
599         return;\r
600         }\r
601 \r
602         while(iter > 0) {  /* FadeLoop */\r
603         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
604                 tmppal[i] = palette[i] - dim;\r
605                 if(tmppal[i] > 127) {\r
606                 tmppal[i] = 0;\r
607                 } else if(tmppal[i] > 63) {\r
608                 tmppal[i] = 63;\r
609                 }\r
610         }\r
611         modexPalUpdate1(tmppal);\r
612         iter--;\r
613         dim += fade;\r
614         }\r
615 }\r
616 \r
617 \r
618 /* save and load */\r
619 void\r
620 modexPalSave(byte *palette) {\r
621         int  i;\r
622 \r
623         outp(PAL_READ_REG, 0);    /* start at palette entry 0 */\r
624         for(i=0; i<PAL_SIZE; i++) {\r
625         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
626         }\r
627 }\r
628 \r
629 \r
630 byte *\r
631 modexNewPal() {\r
632         byte *ptr;\r
633         ptr = malloc(PAL_SIZE);\r
634 \r
635         /* handle errors */\r
636         if(!ptr) {\r
637         printf("Could not allocate palette.\n");\r
638         exit(-1);\r
639         }\r
640 \r
641         return ptr;\r
642 }\r
643 \r
644 \r
645 void\r
646 modexLoadPalFile(byte *filename, byte **palette) {\r
647         FILE *file;\r
648         byte *ptr;\r
649 \r
650         /* free the palette if it exists */\r
651         if(*palette) {\r
652         free(*palette);\r
653         }\r
654 \r
655         /* allocate the new palette */\r
656         *palette = modexNewPal();\r
657 \r
658         /* open the file */\r
659         file = fopen(filename, "rb");\r
660         if(!file) {\r
661         printf("Could not open palette file: %s\n", filename);\r
662         exit(-2);\r
663         }\r
664 \r
665         /* read the file */\r
666         ptr = *palette;\r
667         while(!feof(file)) {\r
668         *ptr++ = fgetc(file);\r
669         }\r
670 \r
671         fclose(file);\r
672 }\r
673 \r
674 \r
675 void VL_LoadPalFile(const char *filename, byte *palette)\r
676 {\r
677         int fd;\r
678 \r
679         fd = open(filename,O_RDONLY|O_BINARY);\r
680         if (fd >= 0) {\r
681                 word i;\r
682 \r
683                 read(fd,palette,768);\r
684                 close(fd);\r
685 \r
686                 vga_palette_lseek(0);\r
687                 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
688         }\r
689 }\r
690 \r
691 \r
692 void\r
693 modexSavePalFile(char *filename, byte *pal) {\r
694         //unsigned int i;\r
695         FILE *file;\r
696 \r
697         /* open the file for writing */\r
698         file = fopen(filename, "wb");\r
699         if(!file) {\r
700         printf("Could not open %s for writing\n", filename);\r
701         exit(-2);\r
702         }\r
703 \r
704         /* write the data to the file */\r
705         fwrite(pal, 1, PAL_SIZE, file);\r
706         fclose(file);\r
707 }\r
708 \r
709 \r
710 /* blanking */\r
711 void\r
712 modexPalBlack() {\r
713         fadePalette(-1, 64, 1, tmppal);\r
714 }\r
715 \r
716 \r
717 void\r
718 modexPalWhite() {\r
719         fadePalette(-1, -64, 1, tmppal);\r
720 }\r
721 \r
722 \r
723 /* utility */\r
724 void\r
725 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
726 {\r
727         byte *p = bmp->palette;\r
728         word w=0;\r
729         word q=0;\r
730         word qq=0;\r
731         static word a[PAL_SIZE];        //palette array of change values!\r
732         word z=0, aq=0, aa=0, pp=0;\r
733 \r
734         //modexWaitBorder();\r
735         vga_wait_for_vsync();\r
736         if((*i)==0)\r
737         {\r
738                 memset(a, -1, sizeof(a));\r
739                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
740         }\r
741         else if(qp==0)\r
742         {\r
743                 q=(*i);\r
744         }\r
745         else\r
746         {\r
747                 q=(*i);\r
748                 qq=(*i)/3;\r
749 //                printf("q: %02d\n", (q));\r
750 //                printf("qq: %02d\n", (qq));\r
751                 //printf("        (*i)-q=%02d\n", (*i)-q);\r
752                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
753         }\r
754         if((*i)<PAL_SIZE/2 && w==0)\r
755         {\r
756                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
757                 {\r
758                         //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
759 //____            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
760                         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
761                         {\r
762                                 w++;\r
763                                 break;\r
764                         }\r
765                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
766                         {\r
767                                 //printf("qp=%d\n", qp);\r
768                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
769                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
770                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
771                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
772                         }\r
773                         else\r
774                         {\r
775                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
776                                 else\r
777                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
778                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
779                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
780                         }\r
781                 }\r
782                 //if(qp>0) printf("qp=%d\n", qp);\r
783                 //if(qp>0) printf("                                              (*i)=%d\n", (*i)/3);\r
784         }\r
785         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
786         vga_wait_for_vsync();\r
787         if((*i)>=PAL_SIZE/2 && w==0)\r
788         {\r
789                 for(; (*i)<PAL_SIZE; (*i)++)\r
790                 {\r
791 //____            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
792                         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
793                         {\r
794                                 w++;\r
795                                 break;\r
796                         }\r
797                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
798                         {\r
799                                 //printf("qp=%d\n", qp);\r
800                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
801                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
802                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
803                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
804                         }\r
805                         else\r
806                         {\r
807                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
808                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
809                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
810                         }\r
811                 }\r
812                 //printf("                                                (*i)=%d\n", (*i)/3);\r
813         }\r
814 \r
815 printf("\nqqqqqqqq\n\n");\r
816 \r
817         //palette checker~\r
818         if(q>0 && qp==0)\r
819         {\r
820                 long lq;\r
821                 long bufSize = (bmp->width * bmp->height);\r
822                 pp = q;\r
823                 //printf("1(*i)=%02d\n", (*i)/3);\r
824                 //printf("1z=%02d\n", z/3);\r
825                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
826                 //printf("2(*i)=%02d\n", (*i)/3);\r
827                 //printf("2z=%02d\n", z/3);\r
828                 aq=0;\r
829 aqpee:\r
830                 while(aq<=aa)\r
831                 {\r
832 //                        printf("a[%02d]=(%d)\n", aq, a[aq]);\r
833                         if(a[aq]==-1) aq++;\r
834                         else { aqoffset++; break; }\r
835                 }\r
836 //update the image data here!\r
837         for(lq=0; lq<bufSize; lq++)\r
838         {\r
839                                 /*\r
840                                                                         note to self\r
841                                                                         use a[qp] instead of bmp->offset for this spot!\r
842                                                                         NO! wwww\r
843                                 */\r
844 \r
845                                 /*\r
846                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
847                                 */\r
848 \r
849                 //(offset/bmp->offset)*bmp->offset\r
850 \r
851 \r
852                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
853                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
854                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
855                 /*if(bmp->data[lq]+bmp->offset==aq)\r
856                 {\r
857                         //printf("%02d", bmp->data[lq]);\r
858                         //printf("\n%02d\n", bmp->offset);\r
859                         printf("aq=%02d ", aq);\r
860                         printf("a[aq]=%02d        ", a[aq]);\r
861                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
862                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
863                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
864 //++++            bmp->data[lq]=a[aq]-aqpp;\r
865 //                        printf("_%d ", bmp->data[lq]);\r
866                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
867                 }\r
868                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
869                 {\r
870                         if(bmp->data[lq]+bmp->offset >= aq)\r
871                         {\r
872                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
873                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
874                         }\r
875                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
876                 }*/\r
877 \r
878                 //printf("%02d`", bmp->data[lq]);\r
879                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
880         }\r
881 \r
882 //printf("                aq=%02d\n", aq);\r
883 //printf("                aa=%02d\n", aa);\r
884 \r
885         //update the palette~\r
886         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
887         (*i)=pp;\r
888 \r
889         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
890         }\r
891 }\r
892 \r
893 void\r
894 modexPalUpdate1(byte *p)\r
895 {\r
896         int i;\r
897         //modexWaitBorder();\r
898         vga_wait_for_vsync();\r
899         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
900         for(i=0; i<PAL_SIZE/2; i++)\r
901         {\r
902                 outp(PAL_DATA_REG, p[i]);\r
903         }\r
904         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
905         vga_wait_for_vsync();\r
906         for(; i<PAL_SIZE; i++)\r
907         {\r
908                 outp(PAL_DATA_REG, p[(i)]);\r
909         }\r
910 }\r
911 \r
912 void\r
913 modexPalUpdate0(byte *p)\r
914 {\r
915         int i;\r
916         //modexWaitBorder();\r
917         vga_wait_for_vsync();\r
918         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
919         for(i=0; i<PAL_SIZE/2; i++)\r
920         {\r
921                 outp(PAL_DATA_REG, rand());\r
922         }\r
923         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
924         vga_wait_for_vsync();\r
925         for(; i<PAL_SIZE; i++)\r
926         {\r
927                 outp(PAL_DATA_REG, rand());\r
928         }\r
929 }\r
930 \r
931 void\r
932 modexPalOverscan(word col)\r
933 {\r
934         //modexWaitBorder();\r
935         vga_wait_for_vsync();\r
936         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
937         outp(PAL_DATA_REG, col);\r
938 }\r
939 \r
940 //color checker~\r
941 //i want to make another vesion that checks the palette when the palette is being appened~\r
942 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
943 {\r
944                 byte *pal;\r
945                 word zz=0;\r
946                 pal = modexNewPal();\r
947                 modexPalSave(pal);\r
948                 //printf("q: %02d\n", (*q));\r
949                 printf("chkcolor start~\n");\r
950                 printf("1                                  (*z): %d\n", (*z)/3);\r
951                 printf("1                                  (*i): %d\n", (*i)/3);\r
952 //                printf("1 offset of color in palette  (*q): %d\n", (*q)/3);\r
953                 printf("wwwwwwwwwwwwwwww\n");\r
954                 //check palette for dups\r
955                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
956                 {\r
957                         //printf("\n            z: %d\n", (*z));\r
958                         //printf("                q: %d\n", (*q));\r
959                         //printf("                z+q: %d\n\n", ((*z)+(*q)));\r
960                         //if((*z)%3==0)\r
961                         //{\r
962 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
963                                 if((*z)==(*i))\r
964                                 {\r
965 //                                        printf("\n%d  [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
966 //                                        printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
967 //0000                            (*z)-=3;\r
968                                         break;\r
969                                 }\r
970                                 else for(zz=0; zz<(*q); zz+=3)\r
971                                 {\r
972                                         //printf("zz: %02d\n", zz/3);\r
973                                         if(zz%3==0)\r
974                                         {\r
975                                                 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
976                                                 {\r
977 //                                                        (*z)-=3;\r
978 //                                                        (*i)-=3;\r
979 //                                                        printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
980 //                                                        printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
981                                                         break;\r
982                                                 }\r
983                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
984                                                 {\r
985 //                                                        printf("\n\nwwwwwwwwwwwwwwww\n");\r
986 //                                                        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
987 //                                                        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
988 //                                                        //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
989 //                                                        printf("      z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
990 //++++                                            (*i)--;\r
991 //                                                        (*z)--;\r
992                                                         //expand dong here\r
993 /*\r
994 planned features that i plan to implement~\r
995 image that has values on the pallete list!\r
996 wwww\r
997 no... wait.... no wwww\r
998 */\r
999                                                         //for(zzii=0; zzii<3; zzii++)\r
1000                                                         //{\r
1001                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
1002                                                                 a[(((*z)+(*q)))]=zz;\r
1003                                                         //}\r
1004                                                         (*aa)=(((*z)+(*q)));\r
1005                                                         printf("!!                                        a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
1006 //                                                        printf("\n              aa: %d\n\n", (*aa));\r
1007 //                                                        printf("      a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
1008 //                                                        printf("wwwwwwwwwwwwwwww\n\n");\r
1009                                                 }\r
1010                                                 /*else\r
1011                                                 {\r
1012                                                         printf("================\n");\r
1013                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
1014                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
1015                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1016                                                         printf("================\n");\r
1017                                                 }*/\r
1018                                                 //printf("[%d]", (zz+q));\r
1019                                         }\r
1020                                 }\r
1021                 }\r
1022                 printf("wwwwwwwwwwwwwwww\n");\r
1023                 printf("2                                  (*z): %d\n", (*z)/3);\r
1024                 printf("2                                  (*i): %d\n", (*i)/3);\r
1025 //                printf("2 offset of color in palette  (*q): %d\n", (*q)/3);\r
1026                 printf("chkcolor end~\n");\r
1027                 free(pal);\r
1028 }\r
1029 \r
1030 void modexputPixel(page_t *page, int x, int y, byte color)\r
1031 {\r
1032         word pageOff = (word) page->data;\r
1033         /* Each address accesses four neighboring pixels, so set\r
1034            Write Plane Enable according to which pixel we want\r
1035            to modify.  The plane is determined by the two least\r
1036            significant bits of the x-coordinate: */\r
1037         modexSelectPlane(PLANE(x));\r
1038         //outp(SC_INDEX, 0x02);\r
1039         //outp(SC_DATA, 0x01 << (x & 3));\r
1040 \r
1041         /* The offset of the pixel into the video segment is\r
1042            offset = (width * y + x) / 4, and write the given\r
1043            color to the plane we selected above.  Heed the active\r
1044            page start selection. */\r
1045         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1046 \r
1047 }\r
1048 \r
1049 byte modexgetPixel(page_t *page, int x, int y)\r
1050 {\r
1051         word pageOff = (word) page->data;\r
1052         /* Select the plane from which we must read the pixel color: */\r
1053         outpw(GC_INDEX, 0x04);\r
1054         outpw(GC_INDEX+1, x & 3);\r
1055 \r
1056         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1057 \r
1058 }\r
1059 \r
1060 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1061 {\r
1062         /* vertical drawing routine by joncampbell123.\r
1063          *\r
1064          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1065          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1066          *\r
1067          * 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
1068         word rows = romFonts[t].charSize;\r
1069         word drawaddr;\r
1070         word colm, row;\r
1071         byte fontbyte;\r
1072         byte plane;\r
1073         byte m1,m2;\r
1074 \r
1075         plane = x & 3;\r
1076         m1 = 0x80; // left half\r
1077         m2 = 0x08; // right half\r
1078         for (colm=0;colm < 4;colm++) {\r
1079                 drawaddr = addr;\r
1080                 modexSelectPlane(PLANE(plane));\r
1081                 for (row=0;row < rows;row++) {\r
1082                         fontbyte = romFontsData.l[row];\r
1083                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1084                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1085                         drawaddr += page->width >> 2;\r
1086                 }\r
1087 \r
1088                 m1 >>= 1;\r
1089                 m2 >>= 1;\r
1090                 if ((++plane) == 4) {\r
1091                         addr++;\r
1092                         plane = 0;\r
1093                 }\r
1094         }\r
1095 }\r
1096 \r
1097 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1098 {\r
1099         word s, o, w;\r
1100         word x_draw = x;\r
1101         //word addr = (word) romFontsData.l;\r
1102         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
1103         word addrr = addrq;\r
1104         byte c;\r
1105 \r
1106         s=romFonts[t].seg;\r
1107         o=romFonts[t].off;\r
1108         w=romFonts[t].charSize;\r
1109         romFontsData.chw=0;\r
1110 \r
1111         for(; *str != '\0'; str++)\r
1112         {\r
1113         c = (*str);\r
1114         if(c=='\n')\r
1115         {\r
1116                 x = x_draw;\r
1117                 romFontsData.chw = 0;\r
1118                 addrq += (page->width / 4) * 8;\r
1119                 addrr = addrq;\r
1120                 y += 8;\r
1121                 continue;\r
1122         }\r
1123 \r
1124         // load the character into romFontsData.l\r
1125         // no need for inline assembly!\r
1126         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1127                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1128                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1129                 x_draw += 8; /* track X for edge of screen */\r
1130                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1131         }\r
1132 }\r
1133 \r
1134 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1135 {\r
1136         word i, s, o, w, j, xp;\r
1137         byte l[1024];\r
1138         word addr = (word) l;\r
1139         word chw=0;\r
1140         byte c;\r
1141 \r
1142         switch(t)\r
1143         {\r
1144                 case 0:\r
1145                         w=14;\r
1146                 break;\r
1147                 case 1:\r
1148                         w=8;\r
1149                 break;\r
1150                 case 2:\r
1151                         w=8;\r
1152                 break;\r
1153                 case 3:\r
1154                         w=16;\r
1155                 break;\r
1156                 default:\r
1157                         t=3;\r
1158                         w=16;\r
1159                 break;\r
1160         }\r
1161 \r
1162         s=romFonts[t].seg;\r
1163         o=romFonts[t].off;\r
1164 \r
1165         for(; *str != '\0'; str++)\r
1166         {\r
1167         c = (*str);\r
1168         if((c=='\n'/* || c=="\\r
1169 "*/)/* || chw>=page->width*/)\r
1170         {\r
1171                 chw=0;\r
1172                 y+=w;\r
1173                 continue;\r
1174         }\r
1175         //load the letter 'A'\r
1176         __asm {\r
1177                 PUSHF\r
1178                 PUSH ES\r
1179                 PUSH AX\r
1180                 PUSH BX\r
1181                 PUSH CX\r
1182                 PUSH DX\r
1183                 PUSH SI\r
1184                 PUSH DI\r
1185 \r
1186                 MOV DI, addr\r
1187                 MOV SI, o\r
1188                 MOV ES, s\r
1189                 SUB AH, AH\r
1190                 MOV AL, c       ; the letter\r
1191                 MOV CX, w\r
1192                 MUL CX\r
1193                 ADD SI, AX      ;the address of charcter\r
1194         L1:     MOV AX, ES:SI\r
1195                 MOV DS:DI, AX\r
1196                 INC SI\r
1197                 INC DI\r
1198                 DEC CX\r
1199                 JNZ L1\r
1200 \r
1201                 POP DI\r
1202                 POP SI\r
1203                 POP DX\r
1204                 POP CX\r
1205                 POP BX\r
1206                 POP AX\r
1207                 POP ES\r
1208                 POPF\r
1209         }\r
1210 \r
1211                 for(i=0; i<w; i++)\r
1212                 {\r
1213                         j=1<<8;\r
1214                         xp=0;\r
1215                         while(j)\r
1216                         {\r
1217                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1218                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1219                                 xp++;\r
1220                                 j>>=1;\r
1221                         }\r
1222                 }\r
1223                 chw += xp;\r
1224         }\r
1225 }\r
1226 \r
1227 /* palette dump on display! */\r
1228 void modexpdump(page_t *pee)\r
1229 {\r
1230         int mult=(QUADWH);\r
1231         int palq=(mult)*TILEWH;\r
1232         int palcol=0;\r
1233         int palx, paly;\r
1234         for(paly=0; paly<palq; paly+=mult){\r
1235                 for(palx=0; palx<palq; palx+=mult){\r
1236                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1237                         palcol++;\r
1238                 }\r
1239         }\r
1240 }\r
1241 \r
1242 /////////////////////////////////////////////////////////////////////////////\r
1243 //                                                                                                                                               //\r
1244 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1245 //               the Virtual screen.                                                                                     //\r
1246 //                                                                                                                                               //\r
1247 /////////////////////////////////////////////////////////////////////////////\r
1248 void modexcls(page_t *page, byte color, byte *Where)\r
1249 {\r
1250         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1251         /* set map mask to all 4 planes */\r
1252         outpw(SC_INDEX, 0xff02);\r
1253         //_fmemset(VGA, color, 16000);\r
1254         _fmemset(Where, color, page->width*(page->height)/4);\r
1255 }\r
1256 \r
1257 void\r
1258 modexWaitBorder() {\r
1259         while(inp(INPUT_STATUS_1)  & 8)  {\r
1260         // spin\r
1261         }\r
1262 \r
1263         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1264         //spin\r
1265         }\r
1266 }\r
1267 \r
1268 void modexprintmeminfo(video_t *v)\r
1269 {\r
1270         byte i;\r
1271         printf("video memory remaining: %u\n", v->vmem_remain);\r
1272         printf("page ");\r
1273         for(i=0; i<v->num_of_pages;i++)\r
1274         {\r
1275                 printf("        [%u]=", i);\r
1276                 printf("(%Fp)", (v->page[i].data));\r
1277                 printf(" size=%u        ", v->page[i].pagesize);\r
1278                 printf("w=%lu  h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1279                 printf("sw=%lu  sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1280                 printf("pi=%u", v->page[i].pi);\r
1281                 printf("\n");\r
1282         }\r
1283 }\r