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