]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.c
wwww
[16.git] / src / lib / 16_vl.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/16_vl.h"\r
27 \r
28 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 \r
33 /////////////////////////////////////////////////////////////////////////////\r
34 //                                                                                                                                                                                                                                              //\r
35 // setvideo() - This function Manages the video modes                                                                                           //\r
36 //                                                                                                                                                                                                                                              //\r
37 /////////////////////////////////////////////////////////////////////////////\r
38 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
39 {\r
40         union REGS in, out;\r
41 \r
42         switch (vq)\r
43         {\r
44                 case 0: // deinit the video\r
45                         // change to the video mode we were in before we switched to mode 13h\r
46                         modexLeave();\r
47                         in.h.ah = 0x00;\r
48                         in.h.al = gv->video.old_mode;\r
49                         int86(0x10, &in, &out);\r
50                 break;\r
51                 default: // init the video\r
52                         // get old video mode\r
53                         //in.h.ah = 0xf;\r
54                         //int86(0x10, &in, &out);\r
55                         gv->video.old_mode = vgaGetMode();//out.h.al;\r
56                         // enter mode\r
57                         modexEnter(vq, cmem, gv);\r
58                 break;\r
59         }\r
60 }\r
61 \r
62 static void\r
63 vgaSetMode(byte mode)\r
64 {\r
65         union REGS regs;\r
66 \r
67         regs.h.ah = SET_MODE;\r
68         regs.h.al = mode;\r
69         int86(VIDEO_INT, &regs, &regs);\r
70   //int10_setmode(mode);\r
71 }\r
72 \r
73 //---------------------------------------------------\r
74 //\r
75 // Use the bios to get the current video mode\r
76 //\r
77 \r
78 byte/*FIXME: why long? "long" is 32-bit datatype, VGA modes are 8-bit numbers. */\r
79 vgaGetMode()\r
80 {\r
81         return int10_getmode();\r
82 }\r
83 \r
84 /* -========================= Entry  Points ==========================- */\r
85 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
86 {\r
87         word i;\r
88         struct vga_mode_params cm;\r
89         //int CRTParmCount;\r
90 \r
91         vgaSetMode(VGA_256_COLOR_MODE);\r
92         vga_enable_256color_modex();\r
93 \r
94         update_state_from_vga();\r
95         vga_read_crtc_mode(&cm);\r
96 \r
97         /* reprogram the CRT controller */\r
98         //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
99         //outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
100 \r
101         switch(vq)\r
102         {\r
103                 case 1:\r
104                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
105                         /*for(i=0; i<CRTParmCount; i++) {\r
106                                 outpw(CRTC_INDEX, ModeX_320x240regs[i]);\r
107                         }*/\r
108                         /* width and height */\r
109                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
110                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
111                         /* virtual width and height. match screen, at first */\r
112                         gv->video.page[0].height = gv->video.page[0].sh;\r
113                         gv->video.page[0].width = gv->video.page[0].sw;\r
114 \r
115                         // mode X BYTE mode\r
116                         cm.word_mode = 0;\r
117                         cm.dword_mode = 0;\r
118                         // 320x240 mode 60Hz\r
119                         cm.horizontal_total=0x5f + 5; /* CRTC[0]                         -5 */\r
120                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]     -1 */\r
121                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
122 //                      cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;\r
123                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
124                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
125                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
126                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
127                         cm.vertical_total = 0x20D + 2;\r
128                         cm.vertical_start_retrace = 0x1EA;\r
129                         cm.vertical_end_retrace = 0x1EC;\r
130                         cm.vertical_display_end = 480;\r
131                         cm.vertical_blank_start = 0x1E7 + 1;\r
132                         cm.vertical_blank_end = 0x206 + 1;\r
133                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
134                         cm.vsync_neg = 1;\r
135                         cm.hsync_neg = 1;\r
136                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
137                         break;\r
138                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
139                         return;\r
140                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
141                         return;\r
142                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
143                         return;\r
144                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
145                         return;\r
146                 default:\r
147                         return;\r
148         }\r
149 \r
150         vga_state.vga_stride = cm.offset * 2;\r
151         vga_write_crtc_mode(&cm,0);\r
152 \r
153         /* clear video memory */\r
154         switch (cmem)\r
155         {\r
156                 case 1: {\r
157                         /* clear video memory */\r
158                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;       /* used for faster screen clearing */\r
159                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
160                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
161                 }\r
162                 break;\r
163         }\r
164 \r
165 //      gv->video.page[0].ti.tw = gv->video.page[0].sw/TILEWH;\r
166 //      gv->video.page[0].ti.th = gv->video.page[0].sh/TILEWH;\r
167 \r
168         //TODO MAKE FLEXIBLE~\r
169 //      gv->video.page[0].ti.tilemidposscreenx = gv->video.page[0].ti.tilesw;\r
170 //      gv->video.page[0].ti.tilemidposscreeny = (gv->video.page[0].ti.tilesh/2)+1;\r
171 }\r
172 \r
173 void\r
174 modexLeave() {\r
175         /* VGAmodeX restores original mode and palette */\r
176         vgaSetMode(TEXT_MODE);\r
177 }\r
178 \r
179 page_t\r
180 modexDefaultPage(page_t *p)\r
181 {\r
182         page_t page;\r
183 \r
184         /* default page values */\r
185         //page.data = VGA;\r
186         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
187         page.data = (vga_state.vga_graphics_ram);\r
188         page.dx = 0;\r
189         page.dy = 0;\r
190         page.sw = p->sw;\r
191         page.sh = p->sh;\r
192         page.width = p->sw+TILEWHD;\r
193         page.height = p->sh+TILEWHD;\r
194         page.ti.tw = page.sw/TILEWH;\r
195         page.ti.th = page.sh/TILEWH;\r
196         page.ti.tilesw=page.width/TILEWH;\r
197         page.ti.tilesh=page.height/TILEWH;\r
198         page.ti.tilemidposscreenx = page.ti.tw/2;\r
199         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
200         page.stridew=page.width/4;\r
201         page.pagesize = (word)(page.stridew)*page.height;\r
202         page.pi=page.width*4;\r
203         page.id = 0;\r
204 \r
205         return page;\r
206 }\r
207 \r
208 /* returns the next page in contiguous memory\r
209  * the next page will be the same size as p, by default\r
210  */\r
211 page_t\r
212 modexNextPage(page_t *p) {\r
213         page_t result;\r
214 \r
215         result.data = p->data + (p->pagesize);\r
216         result.dx = p->dx;      // not used anymore we use page[0].dx\r
217         result.dy = p->dy;      // not used anymore we use page[0].dy\r
218         result.sw = p->sw;\r
219         result.sh = p->sh;\r
220         result.width = p->width;\r
221         result.height = p->height;\r
222         result.ti.tw = p->ti.tw;\r
223         result.ti.th = p->ti.th;\r
224         result.ti.tilesw = p->ti.tilesw;\r
225         result.ti.tilesh = p->ti.tilesh;\r
226         result.stridew=p->stridew;\r
227         result.pagesize = p->pagesize;\r
228         result.pi=result.width*4;\r
229         result.id = p->id+1;\r
230 \r
231         return result;\r
232 }\r
233 \r
234 //next page with defined dimentions~\r
235 page_t\r
236 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
237 {\r
238         page_t result;\r
239 \r
240         result.data = p->data + (p->pagesize);  /* compute the offset */\r
241         result.dx = 0;  // not used anymore we use page[0].dx\r
242         result.dy = 0;  // not used anymore we use page[0].dy\r
243         result.sw = x;\r
244         result.sh = y;\r
245         result.width = x;\r
246         result.height = y;\r
247         result.ti.tw = result.sw/TILEWH;\r
248         result.ti.th = result.sh/TILEWH;\r
249         result.ti.tilesw=result.width/TILEWH;\r
250         result.ti.tilesh=result.height/TILEWH;\r
251         result.id = p->id+1;\r
252         result.stridew=result.width/4;//p->sw/4;\r
253         result.pagesize = (word)(result.stridew)*result.height;\r
254 /*      switch(result.id)\r
255         {\r
256                 case 2:\r
257                         result.pi=p->width*4;\r
258                 break;\r
259                 case 3:\r
260                         result.pi=p->pi;\r
261                 break;\r
262         }*/\r
263         result.pi=result.width*4;\r
264 \r
265         return result;\r
266 }\r
267 \r
268 void modexCalcVmemRemain(video_t *video)\r
269 {\r
270         byte i;\r
271         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
272         for(i=0; i<video->num_of_pages; i++)\r
273         {\r
274                 video->vmem_remain-=video->page[i].pagesize;\r
275                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
276                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
277         }\r
278 }\r
279 \r
280 void VL_Initofs(video_t *video)\r
281 {\r
282         video->ofs.offscreen_ofs =      video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);\r
283         video->ofs.pattern_ofs =        (uint16_t)video->page[2].data;\r
284 }\r
285 \r
286 void modexHiganbanaPageSetup(video_t *video)\r
287 {\r
288         video->vmem_remain=65535U;\r
289         video->num_of_pages=0;\r
290         (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++;  //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);\r
291         (video->page[1]) = modexNextPage(&(video->page[0]));    video->num_of_pages++;\r
292 //0000  (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4);              video->num_of_pages++;\r
293 //0000  (video->page[3]) = (video->page[2]);            video->num_of_pages++;\r
294 ////    (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4);            video->num_of_pages++;\r
295 ////    (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208);        video->num_of_pages++;\r
296         (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96);      video->num_of_pages++;\r
297         (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96);      video->num_of_pages++;\r
298         modexCalcVmemRemain(video);\r
299 \r
300         video->sp=video->p=0;\r
301         video->r=1;\r
302         video->vh=video->page[0].height+video->page[1].height+video->page[3].height-8;//+video->page[2].height\r
303 \r
304         VL_Initofs(video);\r
305         //doslib origi var\r
306         video->omemptr=                 vga_state.vga_graphics_ram;\r
307         video->vga_draw_stride= vga_state.vga_draw_stride;\r
308         video->vga_draw_stride_limit=   vga_state.vga_draw_stride_limit;\r
309         //sprite render switch\r
310         video->rss=0;\r
311 \r
312         //setup the buffersize\r
313         video->page[0].dx=video->page[0].dy=\r
314                 video->page[1].dx=video->page[1].dy=TILEWH;     // 1 tile size buffer\r
315         video->page[2].dx=video->page[2].dy=\r
316                 video->page[3].dx=video->page[3].dy=0;          // cache pages are buffer wwww\r
317 }\r
318 \r
319 //\r
320 // move page to appropriate part and show it\r
321 //\r
322 void\r
323 modexShowPage(page_t *page) {\r
324         word high_address, low_address, offset;\r
325         byte crtcOffset;\r
326 \r
327         /* calculate offset */\r
328         offset = (word) page->data;\r
329         offset += page[0].dy * (page->width >> 2 );\r
330         offset += page[0].dx >> 2;\r
331 \r
332         /* calculate crtcOffset according to virtual width */\r
333         crtcOffset = page->width >> 3;\r
334 \r
335         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
336         low_address  = LOW_ADDRESS  | (offset << 8);\r
337 \r
338         /* wait for appropriate timing and then program CRTC */\r
339 //+=+=                                                                          while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
340         outpw(CRTC_INDEX, high_address);\r
341         outpw(CRTC_INDEX, low_address);\r
342         outp(CRTC_INDEX, 0x13);\r
343         outp(CRTC_DATA, crtcOffset);\r
344 \r
345         /* wait for one retrace */\r
346 //+=+=                                                                          while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
347 \r
348         /* do PEL panning here */\r
349         outp(AC_INDEX, 0x33);\r
350         outp(AC_INDEX, (page[0].dx & 0x03) << 1);\r
351 }\r
352 \r
353 //args: page, vertical sync switch, screen resolution switch, page0 switch\r
354 void\r
355 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {\r
356         word high_address, low_address, offset;\r
357         byte crtcOffset;\r
358 \r
359         // calculate offset\r
360         offset = (word) page->data;\r
361         offset += page->dy * (page->width >> 2 );\r
362         offset += page->dx >> 2;\r
363 \r
364         // calculate crtcOffset according to virtual width\r
365         switch(sr)\r
366         {\r
367                 case 1:\r
368                         crtcOffset = page->sw >> 3;\r
369                 break;\r
370                 default:\r
371                 case 0:\r
372                         crtcOffset = page->width >> 3;\r
373                 break;\r
374         }\r
375 \r
376         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
377         low_address  = LOW_ADDRESS  | (offset << 8);\r
378 \r
379         // wait for appropriate timing and then program CRTC\r
380         if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
381         outpw(CRTC_INDEX, high_address);\r
382         outpw(CRTC_INDEX, low_address);\r
383         outp(CRTC_INDEX, 0x13);\r
384         outp(CRTC_DATA, crtcOffset);\r
385 \r
386         // wait for one retrace\r
387         if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
388 \r
389         // do PEL panning here\r
390         outp(AC_INDEX, 0x33);\r
391         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
392         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;\r
393 }\r
394 \r
395 //=============================================================================\r
396 \r
397 void\r
398 modexPanPage(page_t *page, int dx, int dy) {\r
399         page[0].dx = dx;\r
400         page[0].dy = dy;\r
401 }\r
402 \r
403 void\r
404 modexSelectPlane(byte plane) {\r
405         outp(SC_INDEX, MAP_MASK);         /* select plane */\r
406         outp(SC_DATA,  plane);\r
407 }\r
408 \r
409 void\r
410 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
411         word pageOff = (word) page->data;\r
412         word xoff=x/4;     /* xoffset that begins each row */\r
413         word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
414         word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */\r
415         word nextRow = page->stridew-scanCount-1;  /* loc of next row */\r
416         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
417         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
418         byte left = lclip[x&0x03];\r
419         byte right = rclip[(x+w)&0x03];\r
420 \r
421         /* handle the case which requires an extra group */\r
422         if((x & 0x03) && !((x+w) & 0x03)) {\r
423           right=0x0f;\r
424         }\r
425 \r
426         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
427 \r
428         __asm {\r
429                 PUSHF\r
430                 PUSH ES\r
431                 PUSH AX\r
432                 PUSH BX\r
433                 PUSH CX\r
434                 PUSH DX\r
435                 PUSH SI\r
436                 PUSH DI\r
437                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
438                 MOV ES, AX\r
439                 MOV DI, poffset  ; go to the first pixel\r
440                 MOV DX, SC_INDEX        ; point to the map mask\r
441                 MOV AL, MAP_MASK\r
442                 OUT DX, AL\r
443                 INC DX\r
444                 MOV AL, color      ; get ready to write colors\r
445         SCAN_START:\r
446                 MOV CX, scanCount          ; count the line\r
447                 MOV BL, AL                ; remember color\r
448                 MOV AL, left            ; do the left clip\r
449                 OUT DX, AL                ; set the left clip\r
450                 MOV AL, BL                ; restore color\r
451                 STOSB              ; write the color\r
452                 DEC CX\r
453                 JZ SCAN_DONE            ; handle 1 group stuff\r
454 \r
455                 ;-- write the main body of the scanline\r
456                 MOV BL, AL                ; remember color\r
457                 MOV AL, 0x0f            ; write to all pixels\r
458                 OUT DX, AL\r
459                 MOV AL, BL                ; restore color\r
460                 REP STOSB                  ; write the color\r
461         SCAN_DONE:\r
462                 MOV BL, AL                ; remeber color\r
463                 MOV AL, right\r
464                 OUT DX, AL                ; do the right clip\r
465                 MOV AL, BL                ; restore color\r
466                 STOSB              ; write pixel\r
467                 ADD DI, nextRow  ; go to the next row\r
468                 DEC h\r
469                 JNZ SCAN_START\r
470                 POP DI\r
471                 POP SI\r
472                 POP DX\r
473                 POP CX\r
474                 POP BX\r
475                 POP AX\r
476                 POP ES\r
477                 POPF\r
478         }\r
479 }\r
480 \r
481 /* moved to src/lib/modex16/16render.c */\r
482 \r
483 /* copy a region of video memory from one page to another.\r
484  * It assumes that the left edge of the tile is the same on both\r
485  * regions and the memory areas do not overlap.\r
486  */\r
487 void\r
488 modexCopyPageRegion(page_t *dest, page_t *src,\r
489                         word sx, word sy,\r
490                         word dx, word dy,\r
491                         word width, word height)\r
492 {\r
493         word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;\r
494         word soffset = (word)src->data + sy*(src->stridew) + sx/4;\r
495         word scans   = vga_state.vga_stride;                            //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
496         word nextSrcRow = src->stridew - scans - 1;\r
497         word nextDestRow = dest->stridew - scans - 1;\r
498         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
499         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
500         byte left = lclip[sx&0x03];\r
501         byte right = rclip[(sx+width)&0x03];\r
502 \r
503         /* handle the case which requires an extra group */\r
504         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
505                 right=0x0f;\r
506         }\r
507 \r
508 //      printf("modexCopyPageRegion(src->stridew=%u, dest->stridew=%u, sx=%u, sy=%u, dx=%u, dy=%u, width=%u, height=%u, left=%u, right=%u)\n", src->stridew, dest->stridew, sx, sy, dx, dy, width, height, left, right);\r
509 \r
510         __asm {\r
511                 PUSHF\r
512                 PUSH ES\r
513                 PUSH AX\r
514                 PUSH BX\r
515                 PUSH CX\r
516                 PUSH DX\r
517                 PUSH SI\r
518                 PUSH DI\r
519 \r
520                 MOV AX, SCREEN_SEG        ; work in the vga space\r
521                 MOV ES, AX                ;\r
522                 MOV DI, doffset  ;\r
523                 MOV SI, soffset  ;\r
524 \r
525                 MOV DX, GC_INDEX        ; turn off cpu bits\r
526                 MOV AX, 0008h      ;\r
527                 OUT DX, AX\r
528 \r
529                 MOV AX, SC_INDEX        ; point to the mask register\r
530                 MOV DX, AX                ;\r
531                 MOV AL, MAP_MASK        ;\r
532                 OUT DX, AL                ;\r
533                 INC DX            ;\r
534 \r
535         ROW_START:\r
536                 PUSH DS\r
537                 MOV AX, ES\r
538                 MOV DS, AX\r
539                 MOV CX, scans      ; the number of latches\r
540 \r
541                 MOV AL, left            ; do the left column\r
542                 OUT DX, AL                ;\r
543                 MOVSB              ;\r
544                 DEC CX            ;\r
545 \r
546                 MOV AL, 0fh              ; do the inner columns\r
547                 OUT DX, AL\r
548                 REP MOVSB                  ; copy the pixels\r
549 \r
550                 MOV AL, right      ; do the right column\r
551                 OUT DX, AL\r
552                 MOVSB\r
553                 POP DS\r
554 \r
555                 MOV AX, SI                ; go the start of the next row\r
556                 ADD AX, nextSrcRow        ;\r
557                 MOV SI, AX                ;\r
558                 MOV AX, DI                ;\r
559                 ADD AX, nextDestRow      ;\r
560                 MOV DI, AX                ;\r
561 \r
562                 DEC height                ; do the rest of the actions\r
563                 JNZ ROW_START      ;\r
564 \r
565                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
566                 MOV AL, 0ffh            ; none from latches\r
567                 OUT DX, AL                ;\r
568 \r
569                 POP DI\r
570                 POP SI\r
571                 POP DX\r
572                 POP CX\r
573                 POP BX\r
574                 POP AX\r
575                 POP ES\r
576                 POPF\r
577         }\r
578 }\r
579 \r
580 \r
581 /* fade and flash */\r
582 void\r
583 modexFadeOn(word fade, byte *palette) {\r
584         fadePalette(-fade, 64, 64/fade+1, palette);\r
585 }\r
586 \r
587 \r
588 void\r
589 modexFadeOff(word fade, byte *palette) {\r
590         fadePalette(fade, 0, 64/fade+1, palette);\r
591 }\r
592 \r
593 \r
594 void\r
595 modexFlashOn(word fade, byte *palette) {\r
596         fadePalette(fade, -64, 64/fade+1, palette);\r
597 }\r
598 \r
599 \r
600 void\r
601 modexFlashOff(word fade, byte *palette) {\r
602         fadePalette(-fade, 0, 64/fade+1, palette);\r
603 }\r
604 \r
605 \r
606 static void\r
607 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
608         word i;\r
609         byte dim = start;\r
610 \r
611         /* handle the case where we just update */\r
612         if(iter == 0) {\r
613         modexPalUpdate1(palette);\r
614         return;\r
615         }\r
616 \r
617         while(iter > 0) {  /* FadeLoop */\r
618         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
619                 tmppal[i] = palette[i] - dim;\r
620                 if(tmppal[i] > 127) {\r
621                 tmppal[i] = 0;\r
622                 } else if(tmppal[i] > 63) {\r
623                 tmppal[i] = 63;\r
624                 }\r
625         }\r
626         modexPalUpdate1(tmppal);\r
627         iter--;\r
628         dim += fade;\r
629         }\r
630 }\r
631 \r
632 \r
633 /* save and load */\r
634 void\r
635 modexPalSave(byte *palette) {\r
636         int  i;\r
637 \r
638         outp(PAL_READ_REG, 0);    /* start at palette entry 0 */\r
639         for(i=0; i<PAL_SIZE; i++) {\r
640         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
641         }\r
642 }\r
643 \r
644 \r
645 byte *\r
646 modexNewPal() {\r
647         byte *ptr;\r
648         ptr = malloc(PAL_SIZE);\r
649 \r
650         /* handle errors */\r
651         if(!ptr) {\r
652                 printf("Could not allocate palette.\n");\r
653         }\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         }\r
677 \r
678         /* read the file */\r
679         ptr = *palette;\r
680         while(!feof(file)) {\r
681         *ptr++ = fgetc(file);\r
682         }\r
683 \r
684         fclose(file);\r
685 }\r
686 \r
687 \r
688 void VL_LoadPalFile(const char *filename, byte *palette)\r
689 {\r
690         int fd;\r
691 \r
692         fd = open(filename,O_RDONLY|O_BINARY);\r
693         if (fd >= 0) {\r
694                 word i;\r
695 \r
696                 read(fd,palette,768);\r
697                 close(fd);\r
698 \r
699                 vga_palette_lseek(0);\r
700                 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
701         }\r
702 }\r
703 \r
704 \r
705 void\r
706 modexSavePalFile(char *filename, byte *pal) {\r
707         //unsigned int i;\r
708         FILE *file;\r
709 \r
710         /* open the file for writing */\r
711         file = fopen(filename, "wb");\r
712         if(!file) {\r
713         printf("Could not open %s for writing\n", filename);\r
714         }\r
715 \r
716         /* write the data to the file */\r
717         fwrite(pal, 1, PAL_SIZE, file);\r
718         fclose(file);\r
719 }\r
720 \r
721 \r
722 /* blanking */\r
723 void\r
724 modexPalBlack() {\r
725         fadePalette(-1, 64, 1, tmppal);\r
726 }\r
727 \r
728 \r
729 void\r
730 modexPalWhite() {\r
731         fadePalette(-1, -64, 1, tmppal);\r
732 }\r
733 \r
734 \r
735 /* utility */\r
736 void\r
737 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
738 {\r
739         byte *p = bmp->palette;\r
740         word w=0;\r
741         word q=0;\r
742         word qq=0;\r
743         static word a[PAL_SIZE];        //palette array of change values!\r
744         word z=0, aq=0, aa=0, pp=0;\r
745 \r
746         //modexWaitBorder();\r
747         vga_wait_for_vsync();\r
748         if((*i)==0)\r
749         {\r
750                 memset(a, -1, sizeof(a));\r
751                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
752         }\r
753         else if(qp==0)\r
754         {\r
755                 q=(*i);\r
756         }\r
757         else\r
758         {\r
759                 q=(*i);\r
760                 qq=(*i)/3;\r
761 //                printf("q: %02d\n", (q));\r
762 //                printf("qq: %02d\n", (qq));\r
763                 //printf("        (*i)-q=%02d\n", (*i)-q);\r
764                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
765         }\r
766         if((*i)<PAL_SIZE/2 && w==0)\r
767         {\r
768                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
769                 {\r
770                         //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
771 //____            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
772                         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
773                         {\r
774                                 w++;\r
775                                 break;\r
776                         }\r
777                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
778                         {\r
779                                 //printf("qp=%d\n", qp);\r
780                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
781                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
782                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
783                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
784                         }\r
785                         else\r
786                         {\r
787                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
788                                 else\r
789                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
790                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
791                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
792                         }\r
793                 }\r
794                 //if(qp>0) printf("qp=%d\n", qp);\r
795                 //if(qp>0) printf("                                              (*i)=%d\n", (*i)/3);\r
796         }\r
797         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
798         vga_wait_for_vsync();\r
799         if((*i)>=PAL_SIZE/2 && w==0)\r
800         {\r
801                 for(; (*i)<PAL_SIZE; (*i)++)\r
802                 {\r
803 //____            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
804                         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
805                         {\r
806                                 w++;\r
807                                 break;\r
808                         }\r
809                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
810                         {\r
811                                 //printf("qp=%d\n", qp);\r
812                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
813                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
814                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
815                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
816                         }\r
817                         else\r
818                         {\r
819                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
820                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
821                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
822                         }\r
823                 }\r
824                 //printf("                                                (*i)=%d\n", (*i)/3);\r
825         }\r
826 \r
827 printf("\nqqqqqqqq\n\n");\r
828 \r
829         //palette checker~\r
830         if(q>0 && qp==0)\r
831         {\r
832                 long lq;\r
833                 long bufSize = (bmp->width * bmp->height);\r
834                 pp = q;\r
835                 //printf("1(*i)=%02d\n", (*i)/3);\r
836                 //printf("1z=%02d\n", z/3);\r
837                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
838                 //printf("2(*i)=%02d\n", (*i)/3);\r
839                 //printf("2z=%02d\n", z/3);\r
840                 aq=0;\r
841 aqpee:\r
842                 while(aq<=aa)\r
843                 {\r
844 //                        printf("a[%02d]=(%d)\n", aq, a[aq]);\r
845                         if(a[aq]==-1) aq++;\r
846                         else { aqoffset++; break; }\r
847                 }\r
848 //update the image data here!\r
849         for(lq=0; lq<bufSize; lq++)\r
850         {\r
851                                 /*\r
852                                                                         note to self\r
853                                                                         use a[qp] instead of bmp->offset for this spot!\r
854                                                                         NO! wwww\r
855                                 */\r
856 \r
857                                 /*\r
858                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
859                                 */\r
860 \r
861                 //(offset/bmp->offset)*bmp->offset\r
862 \r
863 \r
864                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
865                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
866                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
867                 /*if(bmp->data[lq]+bmp->offset==aq)\r
868                 {\r
869                         //printf("%02d", bmp->data[lq]);\r
870                         //printf("\n%02d\n", bmp->offset);\r
871                         printf("aq=%02d ", aq);\r
872                         printf("a[aq]=%02d        ", a[aq]);\r
873                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
874                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
875                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
876 //++++            bmp->data[lq]=a[aq]-aqpp;\r
877 //                        printf("_%d ", bmp->data[lq]);\r
878                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
879                 }\r
880                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
881                 {\r
882                         if(bmp->data[lq]+bmp->offset >= aq)\r
883                         {\r
884                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
885                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
886                         }\r
887                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
888                 }*/\r
889 \r
890                 //printf("%02d`", bmp->data[lq]);\r
891                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
892         }\r
893 \r
894 //printf("                aq=%02d\n", aq);\r
895 //printf("                aa=%02d\n", aa);\r
896 \r
897         //update the palette~\r
898         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
899         (*i)=pp;\r
900 \r
901         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
902         }\r
903 }\r
904 \r
905 void\r
906 modexPalUpdate1(byte *p)\r
907 {\r
908         int i;\r
909         //modexWaitBorder();\r
910         vga_wait_for_vsync();\r
911         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
912         for(i=0; i<PAL_SIZE/2; i++)\r
913         {\r
914                 outp(PAL_DATA_REG, p[i]);\r
915         }\r
916         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
917         vga_wait_for_vsync();\r
918         for(; i<PAL_SIZE; i++)\r
919         {\r
920                 outp(PAL_DATA_REG, p[(i)]);\r
921         }\r
922 }\r
923 \r
924 void\r
925 modexPalUpdate0(byte *p)\r
926 {\r
927         int i;\r
928         //modexWaitBorder();\r
929         vga_wait_for_vsync();\r
930         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
931         for(i=0; i<PAL_SIZE/2; i++)\r
932         {\r
933                 outp(PAL_DATA_REG, rand());\r
934         }\r
935         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
936         vga_wait_for_vsync();\r
937         for(; i<PAL_SIZE; i++)\r
938         {\r
939                 outp(PAL_DATA_REG, rand());\r
940         }\r
941 }\r
942 \r
943 void\r
944 modexPalOverscan(word col)\r
945 {\r
946         //modexWaitBorder();\r
947         vga_wait_for_vsync();\r
948         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
949         outp(PAL_DATA_REG, col);\r
950 }\r
951 \r
952 //color checker~\r
953 //i want to make another vesion that checks the palette when the palette is being appened~\r
954 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
955 {\r
956                 byte *pal;\r
957                 word zz=0;\r
958                 pal = modexNewPal();\r
959                 modexPalSave(pal);\r
960                 //printf("q: %02d\n", (*q));\r
961                 printf("chkcolor start~\n");\r
962                 printf("1                                  (*z): %d\n", (*z)/3);\r
963                 printf("1                                  (*i): %d\n", (*i)/3);\r
964 //                printf("1 offset of color in palette  (*q): %d\n", (*q)/3);\r
965                 printf("wwwwwwwwwwwwwwww\n");\r
966                 //check palette for dups\r
967                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
968                 {\r
969                         //printf("\n            z: %d\n", (*z));\r
970                         //printf("                q: %d\n", (*q));\r
971                         //printf("                z+q: %d\n\n", ((*z)+(*q)));\r
972                         //if((*z)%3==0)\r
973                         //{\r
974 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
975                                 if((*z)==(*i))\r
976                                 {\r
977 //                                        printf("\n%d  [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
978 //                                        printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
979 //0000                            (*z)-=3;\r
980                                         break;\r
981                                 }\r
982                                 else for(zz=0; zz<(*q); zz+=3)\r
983                                 {\r
984                                         //printf("zz: %02d\n", zz/3);\r
985                                         if(zz%3==0)\r
986                                         {\r
987                                                 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
988                                                 {\r
989 //                                                        (*z)-=3;\r
990 //                                                        (*i)-=3;\r
991 //                                                        printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
992 //                                                        printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
993                                                         break;\r
994                                                 }\r
995                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
996                                                 {\r
997 //                                                        printf("\n\nwwwwwwwwwwwwwwww\n");\r
998 //                                                        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
999 //                                                        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
1000 //                                                        //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
1001 //                                                        printf("      z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1002 //++++                                            (*i)--;\r
1003 //                                                        (*z)--;\r
1004                                                         //expand dong here\r
1005 /*\r
1006 planned features that i plan to implement~\r
1007 image that has values on the pallete list!\r
1008 wwww\r
1009 no... wait.... no wwww\r
1010 */\r
1011                                                         //for(zzii=0; zzii<3; zzii++)\r
1012                                                         //{\r
1013                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
1014                                                                 a[(((*z)+(*q)))]=zz;\r
1015                                                         //}\r
1016                                                         (*aa)=(((*z)+(*q)));\r
1017                                                         printf("!!                                        a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
1018 //                                                        printf("\n              aa: %d\n\n", (*aa));\r
1019 //                                                        printf("      a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
1020 //                                                        printf("wwwwwwwwwwwwwwww\n\n");\r
1021                                                 }\r
1022                                                 /*else\r
1023                                                 {\r
1024                                                         printf("================\n");\r
1025                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
1026                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
1027                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1028                                                         printf("================\n");\r
1029                                                 }*/\r
1030                                                 //printf("[%d]", (zz+q));\r
1031                                         }\r
1032                                 }\r
1033                 }\r
1034                 printf("wwwwwwwwwwwwwwww\n");\r
1035                 printf("2                                  (*z): %d\n", (*z)/3);\r
1036                 printf("2                                  (*i): %d\n", (*i)/3);\r
1037 //                printf("2 offset of color in palette  (*q): %d\n", (*q)/3);\r
1038                 printf("chkcolor end~\n");\r
1039                 free(pal);\r
1040 }\r
1041 \r
1042 void modexputPixel(page_t *page, int x, int y, byte color)\r
1043 {\r
1044         word pageOff = (word) page->data;\r
1045         /* Each address accesses four neighboring pixels, so set\r
1046            Write Plane Enable according to which pixel we want\r
1047            to modify.  The plane is determined by the two least\r
1048            significant bits of the x-coordinate: */\r
1049         modexSelectPlane(PLANE(x));\r
1050         //outp(SC_INDEX, 0x02);\r
1051         //outp(SC_DATA, 0x01 << (x & 3));\r
1052 \r
1053         /* The offset of the pixel into the video segment is\r
1054            offset = (width * y + x) / 4, and write the given\r
1055            color to the plane we selected above.  Heed the active\r
1056            page start selection. */\r
1057         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1058 \r
1059 }\r
1060 \r
1061 byte modexgetPixel(page_t *page, int x, int y)\r
1062 {\r
1063         word pageOff = (word) page->data;\r
1064         /* Select the plane from which we must read the pixel color: */\r
1065         outpw(GC_INDEX, 0x04);\r
1066         outpw(GC_INDEX+1, x & 3);\r
1067 \r
1068         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1069 \r
1070 }\r
1071 \r
1072 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1073 {\r
1074         /* vertical drawing routine by joncampbell123.\r
1075          *\r
1076          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1077          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1078          *\r
1079          * 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
1080         word rows = romFonts[t].charSize;\r
1081         word drawaddr;\r
1082         word colm, row;\r
1083         byte fontbyte;\r
1084         byte plane;\r
1085         byte m1,m2;\r
1086 \r
1087         plane = x & 3;\r
1088         m1 = 0x80; // left half\r
1089         m2 = 0x08; // right half\r
1090         for (colm=0;colm < 4;colm++) {\r
1091                 drawaddr = addr;\r
1092                 modexSelectPlane(PLANE(plane));\r
1093                 for (row=0;row < rows;row++) {\r
1094                         fontbyte = romFontsData.l[row];\r
1095                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1096                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1097                         drawaddr += page->width >> 2;\r
1098                 }\r
1099 \r
1100                 m1 >>= 1;\r
1101                 m2 >>= 1;\r
1102                 if ((++plane) == 4) {\r
1103                         addr++;\r
1104                         plane = 0;\r
1105                 }\r
1106         }\r
1107 }\r
1108 \r
1109 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1110 {\r
1111         word s, o, w;\r
1112         word x_draw = x;\r
1113         //word addr = (word) romFontsData.l;\r
1114         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
1115         word addrr = addrq;\r
1116         byte c;\r
1117 \r
1118         s=romFonts[t].seg;\r
1119         o=romFonts[t].off;\r
1120         w=romFonts[t].charSize;\r
1121         romFontsData.chw=0;\r
1122 \r
1123         for(; *str != '\0'; str++)\r
1124         {\r
1125         c = (*str);\r
1126         if(c=='\n')\r
1127         {\r
1128                 x = x_draw;\r
1129                 romFontsData.chw = 0;\r
1130                 addrq += (page->width / 4) * 8;\r
1131                 addrr = addrq;\r
1132                 y += 8;\r
1133                 continue;\r
1134         }\r
1135 \r
1136         // load the character into romFontsData.l\r
1137         // no need for inline assembly!\r
1138         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1139                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1140                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1141                 x_draw += 8; /* track X for edge of screen */\r
1142                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1143         }\r
1144 }\r
1145 \r
1146 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1147 {\r
1148         word i, s, o, w, j, xp;\r
1149         byte l[1024];\r
1150         word addr = (word) l;\r
1151         word chw=0;\r
1152         byte c;\r
1153 \r
1154         switch(t)\r
1155         {\r
1156                 case 0:\r
1157                         w=14;\r
1158                 break;\r
1159                 case 1:\r
1160                         w=8;\r
1161                 break;\r
1162                 case 2:\r
1163                         w=8;\r
1164                 break;\r
1165                 case 3:\r
1166                         w=16;\r
1167                 break;\r
1168                 default:\r
1169                         t=3;\r
1170                         w=16;\r
1171                 break;\r
1172         }\r
1173 \r
1174         s=romFonts[t].seg;\r
1175         o=romFonts[t].off;\r
1176 \r
1177         for(; *str != '\0'; str++)\r
1178         {\r
1179         c = (*str);\r
1180         if((c=='\n'/* || c=="\\r
1181 "*/)/* || chw>=page->width*/)\r
1182         {\r
1183                 chw=0;\r
1184                 y+=w;\r
1185                 continue;\r
1186         }\r
1187         //load the letter 'A'\r
1188         __asm {\r
1189                 PUSHF\r
1190                 PUSH ES\r
1191                 PUSH AX\r
1192                 PUSH BX\r
1193                 PUSH CX\r
1194                 PUSH DX\r
1195                 PUSH SI\r
1196                 PUSH DI\r
1197 \r
1198                 MOV DI, addr\r
1199                 MOV SI, o\r
1200                 MOV ES, s\r
1201                 SUB AH, AH\r
1202                 MOV AL, c       ; the letter\r
1203                 MOV CX, w\r
1204                 MUL CX\r
1205                 ADD SI, AX      ;the address of charcter\r
1206         L1:     MOV AX, ES:SI\r
1207                 MOV DS:DI, AX\r
1208                 INC SI\r
1209                 INC DI\r
1210                 DEC CX\r
1211                 JNZ L1\r
1212 \r
1213                 POP DI\r
1214                 POP SI\r
1215                 POP DX\r
1216                 POP CX\r
1217                 POP BX\r
1218                 POP AX\r
1219                 POP ES\r
1220                 POPF\r
1221         }\r
1222 \r
1223                 for(i=0; i<w; i++)\r
1224                 {\r
1225                         j=1<<8;\r
1226                         xp=0;\r
1227                         while(j)\r
1228                         {\r
1229                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1230                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1231                                 xp++;\r
1232                                 j>>=1;\r
1233                         }\r
1234                 }\r
1235                 chw += xp;\r
1236         }\r
1237 }\r
1238 \r
1239 /* palette dump on display! */\r
1240 void modexpdump(page_t *pee)\r
1241 {\r
1242         int mult=(QUADWH);\r
1243         int palq=(mult)*TILEWH;\r
1244         int palcol=0;\r
1245         int palx, paly;\r
1246         for(paly=0; paly<palq; paly+=mult){\r
1247                 for(palx=0; palx<palq; palx+=mult){\r
1248                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1249                         palcol++;\r
1250                 }\r
1251         }\r
1252 }\r
1253 \r
1254 /////////////////////////////////////////////////////////////////////////////\r
1255 //                                                                                                                                               //\r
1256 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1257 //               the Virtual screen.                                                                                     //\r
1258 //                                                                                                                                               //\r
1259 /////////////////////////////////////////////////////////////////////////////\r
1260 void modexcls(page_t *page, byte color, byte *Where)\r
1261 {\r
1262         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1263         /* set map mask to all 4 planes */\r
1264         outpw(SC_INDEX, 0xff02);\r
1265         //_fmemset(VGA, color, 16000);\r
1266         _fmemset(Where, color, page->stridew*page->height);\r
1267 }\r
1268 \r
1269 //\r
1270 // pattern filler from joncampbell123's code\r
1271 //\r
1272 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1273 {\r
1274         unsigned int i,j,o,     d,h,s;\r
1275         word w;\r
1276 \r
1277         switch(sw)\r
1278         {\r
1279                 case 0:\r
1280                         w=vga_state.vga_width;\r
1281                         d=0;\r
1282                         s=vga_state.vga_stride;\r
1283                         switch(allsw)\r
1284                         {\r
1285                                 case 0:\r
1286                                         h=vga_state.vga_height;\r
1287                                 break;\r
1288                                 case 1:\r
1289                                         h=video->vh;\r
1290                                 break;\r
1291                         }\r
1292                 break;\r
1293                 default:\r
1294                         w=video->page[pn].width;\r
1295                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1296                         s=video->page[pn].stridew;\r
1297                         switch(allsw)\r
1298                         {\r
1299                                 case 0:\r
1300                                         h=video->page[pn].height;\r
1301                                 break;\r
1302                                 case 1:\r
1303                                         if(!pn) h=video->vh;\r
1304                                         else h=video->page[pn].height;\r
1305                                 break;\r
1306                         }\r
1307                 break;\r
1308         }\r
1309 \r
1310         /* fill screen/pattern with a distinctive pattern */\r
1311         for (i=0;i < w;i++) {\r
1312                 o = (i >> 2) + d;\r
1313                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1314                 for (j=0;j < h;j++,o += s)\r
1315                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1316         }\r
1317 }\r
1318 \r
1319 void\r
1320 modexWaitBorder() {\r
1321         while(inp(INPUT_STATUS_1)  & 8)  {\r
1322         // spin\r
1323         }\r
1324 \r
1325         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1326         //spin\r
1327         }\r
1328 }\r
1329 \r
1330 //\r
1331 // printings of video memory information\r
1332 //\r
1333 void VL_PrintmodexmemInfo(video_t *v)\r
1334 {\r
1335         byte i;\r
1336 \r
1337 //      printf("========================================\n");\r
1338         printf("VL_PrintmodexmemInfo:\n");\r
1339 //      printf("========================================\n");\r
1340         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
1341         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
1342 \r
1343         printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1344         printf("  page");\r
1345         for(i=0; i<v->num_of_pages;i++)\r
1346         {\r
1347                 printf("        [%u]=", i);\r
1348                 printf("(%Fp)", (v->page[i].data));\r
1349                 printf(" size=%u        ", v->page[i].pagesize);\r
1350                 printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1351                 printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1352                 printf("pi=%u", v->page[i].pi);\r
1353                 printf("\n");\r
1354         }\r
1355 }\r