OSDN Git Service

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