OSDN Git Service

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