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