OSDN Git Service

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