OSDN Git Service

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