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