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