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