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