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