1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2022 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
\r
4 * This file is part of Project 16.
\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
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
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
26 #include "src/lib/16_vl.h"
\r
28 byte far* VGA=(byte far*) 0xA0000000; /* this points to video memory. */
\r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);
\r
31 /*static */byte tmppal[PAL_SIZE];
\r
33 //===========================================================================
\r
36 =======================
\r
40 =======================
\r
43 void VL_Startup (global_game_variables_t *gvar)
\r
47 VGAmodeX(1/*TODO other modes*/, 1, gvar);
\r
48 //-- VL_LoadPalFileCore(gvar->video.palette, gvar);
\r
49 VL_SetCorePal(gvar);
\r
50 //Quit ("Improper video card! If you really have a VGA card that I am not\ndetecting it!", gvar);
\r
56 =======================
\r
60 =======================
\r
63 void VL_Shutdown (global_game_variables_t *gvar)
\r
65 VGAmodeX(0, 1, gvar);
\r
69 =======================
\r
71 = VL_SetVGAPlaneMode
\r
73 =======================
\r
76 void VL_SetVGAPlaneMode (global_game_variables_t *gvar)
\r
78 VL_vgaSetMode(VGA_256_COLOR_MODE);
\r
81 VL_SetLineWidth (40, &gvar->video.ofs);
\r
85 //===========================================================================
\r
92 = Fill the entire video buffer with a given color
\r
97 void VL_ClearVideo (byte color)
\r
105 and al,0xfc // write mode 0 to store directly to video
\r
109 mov ax,SC_MAPMASK+15*256
\r
110 out dx,ax // write through all four planes
\r
116 mov cx,0x8000 // 0x8000 words, clearing 8 video bytes/word
\r
123 =============================================================================
\r
125 VGA REGISTER MANAGEMENT ROUTINES
\r
127 =============================================================================
\r
139 void VL_DePlaneVGA (void)
\r
143 // change CPU addressing to non linear mode
\r
147 // turn off chain 4 and odd/even
\r
149 outportb (SC_INDEX,SC_MEMMODE);
\r
150 outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);
\r
152 outportb (SC_INDEX,SC_MAPMASK); // leave this set throughought
\r
155 // turn off odd/even and set write mode 0
\r
157 outportb (GC_INDEX,GC_MODE);
\r
158 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);
\r
163 outportb (GC_INDEX,GC_MISCELLANEOUS);
\r
164 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);
\r
167 // clear the entire buffer space, because int 10h only did 16 k / plane
\r
172 // change CRTC scanning from doubleword to byte mode, allowing >64k scans
\r
174 outportb (CRTC_INDEX,CRTC_UNDERLINE);
\r
175 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);
\r
177 outportb (CRTC_INDEX,CRTC_MODE);
\r
178 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);
\r
181 //===========================================================================
\r
184 ====================
\r
186 = VL_SetSplitScreen
\r
188 ====================
\r
191 void VL_SetSplitScreen (int linenum)
\r
194 linenum=linenum*2-1;
\r
195 outportb (CRTC_INDEX,CRTC_LINECOMPARE);
\r
196 outportb (CRTC_INDEX+1,linenum % 256);
\r
197 outportb (CRTC_INDEX,CRTC_OVERFLOW);
\r
198 outportb (CRTC_INDEX+1, 1+16*(linenum/256));
\r
199 outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
\r
200 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
\r
203 /////////////////////////////////////////////////////////////////////////////
\r
205 // setvideo() - This function Manages the video modes //
\r
207 /////////////////////////////////////////////////////////////////////////////
\r
208 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)
\r
210 union REGS in, out;
\r
214 case 0: // deinit the video
\r
215 // change to the video mode we were in before we switched to mode 13h
\r
216 if(gv->video.VL_Started)
\r
220 in.h.al = gv->video.old_mode;
\r
221 int86(0x10, &in, &out);
\r
223 gv->video.VL_Started=0;
\r
225 default: // init the video
\r
226 if(gv->video.VL_Started)
\r
228 if(!gv->video.VL_Initiated)
\r
230 // get old video mode
\r
232 //int86(0x10, &in, &out);
\r
233 gv->video.old_mode = VL_vgaGetMode();//out.h.al;
\r
235 modexEnter(vq, cmem, gv);
\r
240 //---------------------------------------------------
\r
242 // Use the bios to set the current video mode
\r
246 VL_vgaSetMode(byte mode)
\r
250 regs.h.ah = SET_MODE;
\r
252 int86(VIDEO_INT, ®s, ®s);
\r
255 //---------------------------------------------------
\r
257 // Use the bios to get the current video mode
\r
261 VL_vgaGetMode(void)
\r
263 return int10_getmode();
\r
266 /* -========================= Entry Points ==========================- */
\r
267 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)
\r
270 struct vga_mode_params cm;
\r
271 //int CRTParmCount;
\r
273 VL_vgaSetMode(VGA_256_COLOR_MODE);
\r
274 vga_enable_256color_modex();
\r
276 update_state_from_vga();
\r
277 vga_read_crtc_mode(&cm);
\r
279 /* reprogram the CRT controller */
\r
280 //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
281 //outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
286 case 8: //320x240 no buffer
\r
287 //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);
\r
288 /*for(i=0; i<CRTParmCount; i++) {
\r
289 outpw(CRTC_INDEX, ModeX_320x240regs[i]);
\r
291 // width and height //
\r
292 gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this
\r
293 gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this
\r
294 // virtual width and height. match screen, at first //
\r
295 gv->video.page[0].height = gv->video.page[0].sh;
\r
296 gv->video.page[0].width = gv->video.page[0].sw;
\r
298 // mode X BYTE mode
\r
301 // 320x240 mode 60Hz
\r
302 cm.horizontal_total=0x5f + 5; /* CRTC[0] -5 */
\r
303 cm.horizontal_display_end=0x4f + 1; /* CRTC[1] -1 */
\r
304 cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */
\r
305 // cm.horizontal_blank_end=0x82 + 1; /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;
\r
306 cm.horizontal_start_retrace=0x54;/* CRTC[4] */
\r
307 cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */
\r
308 //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */
\r
309 //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */
\r
310 cm.vertical_total = 0x20D + 2;
\r
311 cm.vertical_start_retrace = 0x1EA;
\r
312 cm.vertical_end_retrace = 0x1EC;
\r
313 cm.vertical_display_end = 480;
\r
314 cm.vertical_blank_start = 0x1E7 + 1;
\r
315 cm.vertical_blank_end = 0x206 + 1;
\r
316 cm.clock_select = 0; /* misc register = 0xE3 25MHz */
\r
319 cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)
\r
321 case 2: // TODO: 160x120 according to ModeX_160x120regs
\r
323 case 3: // TODO: 160x120 according to ModeX_320x200regs
\r
325 case 4: // TODO: 160x120 according to ModeX_192x144regs
\r
327 case 5: // TODO: 160x120 according to ModeX_256x192regs
\r
333 vga_state.vga_stride = cm.offset * 2;
\r
334 vga_write_crtc_mode(&cm,0);
\r
336 // clear video memory //
\r
342 dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA; // used for faster screen clearing //
\r
343 vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);
\r
344 for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB
\r
345 // fix up the palette and everything //
\r
346 modexPalBlack(); //reset the palette~//
\r
349 // clear the entire buffer space, because int 10h only did 16 k / plane
\r
355 //-- VL_SetLineWidth (cm.offset, gv);
\r
356 //gv->video.ofs.displayofs = 0;
\r
357 //gv->video.ofs.bufferofs = gv->video.page[0].width*gv->video.page[0].height;//gvar->video.page[0].pagesize;
\r
358 gv->video.curr_mode=vq;
\r
359 gv->video.VL_Started=1;
\r
362 void modexLeave(void)
\r
364 // VGAmodeX restores original mode and palette
\r
365 VL_vgaSetMode(TEXT_MODE);
\r
370 modexDefaultPage(page_t *p)
\r
373 /* default page values */
\r
375 //page.data = (byte far *)(vga_state.vga_graphics_ram);
\r
376 page.data = (vga_state.vga_graphics_ram);
\r
381 page.width = p->sw;
\r
382 page.height = p->sh;
\r
383 page.ti.tw = page.sw/TILEWH;
\r
384 page.ti.th = page.sh/TILEWH;
\r
385 page.ti.tilesw=page.width/TILEWH;
\r
386 page.ti.tilesh=page.height/TILEWH;
\r
387 page.ti.tilemidposscreenx = page.ti.tw/2;
\r
388 page.ti.tilemidposscreeny = (page.ti.th/2)+1;
\r
389 page.stridew=page.width/4;
\r
390 page.pagesize = (word)(page.stridew)*page.height;
\r
391 page.pi=page.width*4;
\r
393 if(ggvv->video.curr_mode = 1)
\r
395 page.width += TILEWHD;
\r
396 page.height += TILEWHD;
\r
402 modexDefaultPage(page_t *p, global_game_variables_t *gvar)
\r
406 /* default page values */
\r
408 //page.data = (byte far *)(vga_state.vga_graphics_ram);
\r
409 page.data = (vga_state.vga_graphics_ram);
\r
414 page.width = p->sw;
\r
415 page.height = p->sh;
\r
416 if(gvar->video.curr_mode == 1)
\r
417 { page.width += TILEWHD;
\r
418 page.height += TILEWHD; }
\r
419 page.ti.tw = page.sw/TILEWH;
\r
420 page.ti.th = page.sh/TILEWH;
\r
421 page.ti.tilesw=page.width/TILEWH;
\r
422 page.ti.tilesh=page.height/TILEWH;
\r
423 page.ti.tilemidposscreenx = page.ti.tw/2;
\r
424 page.ti.tilemidposscreeny = (page.ti.th/2)+1;
\r
425 page.stridew=page.width/4;
\r
426 page.pagesize = (word)(page.stridew)*page.height;
\r
427 page.pi=page.width*4;
\r
433 /* returns the next page in contiguous memory
\r
434 * the next page will be the same size as p, by default
\r
437 modexNextPage(page_t *p) {
\r
440 result.data = p->data + (p->pagesize);
\r
441 result.dx = p->dx; // not used anymore we use page[0].dx
\r
442 result.dy = p->dy; // not used anymore we use page[0].dy
\r
445 result.width = p->width;
\r
446 result.height = p->height;
\r
447 result.ti.tw = p->ti.tw;
\r
448 result.ti.th = p->ti.th;
\r
449 result.ti.tilesw = p->ti.tilesw;
\r
450 result.ti.tilesh = p->ti.tilesh;
\r
451 result.stridew=p->stridew;
\r
452 result.pagesize = p->pagesize;
\r
453 result.pi=result.width*4;
\r
454 result.id = p->id+1;
\r
459 //next page with defined dimentions~
\r
461 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
465 result.data = p->data + (p->pagesize); /* compute the offset */
\r
466 result.dx = 0; // not used anymore we use page[0].dx
\r
467 result.dy = 0; // not used anymore we use page[0].dy
\r
472 result.ti.tw = result.sw/TILEWH;
\r
473 result.ti.th = result.sh/TILEWH;
\r
474 result.ti.tilesw=result.width/TILEWH;
\r
475 result.ti.tilesh=result.height/TILEWH;
\r
476 result.id = p->id+1;
\r
477 result.stridew=result.width/4;//p->sw/4;
\r
478 result.pagesize = (word)(result.stridew)*result.height;
\r
479 /* switch(result.id)
\r
482 result.pi=p->width*4;
\r
488 result.pi=result.width*4;
\r
493 void modexCalcVmemRemain(video_t *video)
\r
496 //printf("\n\n 1st vmem_remain=%u\n", video->vmem_remain);
\r
497 for(i=0; i<video->num_of_pages; i++)
\r
499 video->vmem_remain-=video->page[i].pagesize;
\r
500 //printf(" [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);
\r
501 //printf(" [%u], vmem_remain=%u\n", i, video->vmem_remain);
\r
505 void VL_Initofs(video_t *video)
\r
507 if(!video->vga_state.bgps)
\r
509 video->ofs.offscreen_ofs = video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);
\r
510 video->ofs.pattern_ofs = (uint16_t)video->page[2].data;
\r
512 video->ofs.offscreen_ofs = 0;
\r
513 video->ofs.pattern_ofs = 0;//(uint16_t)video->page[0].data;
\r
517 void modexHiganbanaPageSetup(global_game_variables_t *gvar)
\r
519 gvar->video.vmem_remain=65535U;
\r
520 gvar->video.num_of_pages=0;
\r
521 (gvar->video.page[0]) = modexDefaultPage(&(gvar->video.page[0]), gvar); gvar->video.num_of_pages++; //gvar->video.page[0].width += (TILEWHD); gvar->video.page[0].height += (TILEWHD);
\r
522 (gvar->video.page[1]) = modexNextPage(&(gvar->video.page[0])); gvar->video.num_of_pages++;
\r
523 //0000 (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), (gvar->video.page[0]).width, TILEWH*4); gvar->video.num_of_pages++;
\r
524 //0000 (gvar->video.page[3]) = (gvar->video.page[2]); gvar->video.num_of_pages++;
\r
525 //// (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), TILEWH*4, TILEWH*4); gvar->video.num_of_pages++;
\r
526 //// (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].sw, 208); gvar->video.num_of_pages++;
\r
527 (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), gvar->video.page[0].width, 96); gvar->video.num_of_pages++;
\r
528 (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].width, 96); gvar->video.num_of_pages++;
\r
529 modexCalcVmemRemain(&gvar->video);
\r
531 gvar->video.sp=gvar->video.p = 0; //showpage
\r
532 gvar->video.dorender = 1; //render
\r
533 gvar->video.vh=gvar->video.page[0].height+gvar->video.page[1].height+gvar->video.page[2].height+gvar->video.page[3].height;
\r
535 VL_Initofs(&gvar->video);
\r
537 gvar->video.vga_state.omemptr= vga_state.vga_graphics_ram;
\r
538 gvar->video.vga_state.vga_draw_stride= vga_state.vga_draw_stride;
\r
539 gvar->video.vga_state.vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
540 //sprite render switch and bgpreservation switch
\r
541 gvar->video.vga_state.rss= 1;
\r
542 gvar->video.vga_state.bgps= 1;
\r
544 //setup the buffersize
\r
545 gvar->video.page[0].dx=gvar->video.page[0].dy=
\r
546 gvar->video.page[1].dx=gvar->video.page[1].dy=TILEWH; // 1 tile size buffer
\r
547 gvar->video.page[2].dx=gvar->video.page[2].dy=
\r
548 gvar->video.page[3].dx=gvar->video.page[3].dy=0; // cache pages are buffer wwww
\r
550 gvar->video.page[0].tlx=gvar->mv[0].tx*TILEWH;
\r
551 gvar->video.page[0].tly=gvar->mv[0].ty*TILEWH;
\r
555 // move page to appropriate part and show it
\r
558 modexShowPage(page_t *page) {
\r
559 word high_address, low_address, offset;
\r
562 /* calculate offset */
\r
563 offset = (word) page->data;
\r
564 offset += page[0].dy * (page->width >> 2 );
\r
565 offset += page[0].dx >> 2;
\r
567 /* calculate crtcOffset according to virtual width */
\r
568 crtcOffset = page->width >> 3;
\r
570 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
571 low_address = LOW_ADDRESS | (offset << 8);
\r
573 /* wait for appropriate timing and then program CRTC */
\r
574 //+=+= while ((inp(STATUS_REGISTER_1) & DISPLAY_ENABLE));
\r
575 outpw(CRTC_INDEX, high_address);
\r
576 outpw(CRTC_INDEX, low_address);
\r
577 outp(CRTC_INDEX, 0x13);
\r
578 outp(CRTC_DATA, crtcOffset);
\r
580 /* wait for one retrace */
\r
581 //+=+= while (!(inp(STATUS_REGISTER_1) & VRETRACE));
\r
583 /* do PEL panning here */
\r
584 outp(AC_INDEX, 0x33);
\r
585 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
588 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
590 VL_ShowPage(page_t *page, boolean vsync, boolean sr)
\r
592 word high_address, low_address, offset;
\r
595 // calculate offset
\r
596 offset = (word) page->data;
\r
597 offset += page->dy * (page->width >> 2 );
\r
598 offset += page->dx >> 2;
\r
600 // calculate crtcOffset according to virtual width
\r
604 crtcOffset = page->sw >> 3;
\r
608 crtcOffset = page->width >> 3;
\r
612 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
613 low_address = LOW_ADDRESS | (offset << 8);
\r
615 // wait for appropriate timing and then program CRTC
\r
616 if(vsync) while ((inp(STATUS_REGISTER_1) & DISPLAY_ENABLE));
\r
617 outpw(CRTC_INDEX, high_address);
\r
618 outpw(CRTC_INDEX, low_address);
\r
619 outp(CRTC_INDEX, 0x13);
\r
620 outp(CRTC_DATA, crtcOffset);
\r
622 // wait for one retrace
\r
623 if(vsync) while (!(inp(STATUS_REGISTER_1) & VRETRACE));
\r
625 // do PEL panning here
\r
626 outp(AC_INDEX, 0x33);
\r
627 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
628 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;
\r
629 vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;
\r
632 //=============================================================================
\r
635 modexPanPage(page_t *page, int dx, int dy) {
\r
641 modexSelectPlane(byte plane) {
\r
642 outp(SC_INDEX, SC_MAPMASK); /* select plane */
\r
643 outp(SC_DATA, plane);
\r
647 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)
\r
649 word pageOff = (word) page->data;
\r
650 word xoff=(x>>2); // xoffset that begins each row
\r
651 word poffset = pageOff + y*(page->stridew) + xoff; // starting offset
\r
652 word scanCount=w>>2; // number of iterations per row (excluding right clip)
\r
653 word nextRow = page->stridew-scanCount-1; // loc of next row
\r
655 byte left = lclip[x&0x03];
\r
656 byte right = rclip[(x+w)&0x03];
\r
658 // handle the case which requires an extra group
\r
659 if((x & 0x03) && !((x+w) & 0x03)) {
\r
663 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
674 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
676 MOV DI, poffset ; go to the first pixel
\r
677 MOV DX, SC_INDEX ; point to the map mask
\r
681 MOV AL, color ; get ready to write colors
\r
683 MOV CX, scanCount ; count the line
\r
684 MOV BL, AL ; remember color
\r
685 MOV AL, left ; do the left clip
\r
686 OUT DX, AL ; set the left clip
\r
687 MOV AL, BL ; restore color
\r
688 STOSB ; write the color
\r
690 JZ SCAN_DONE ; handle 1 group stuff
\r
692 ;-- write the main body of the scanline
\r
693 MOV BL, AL ; remember color
\r
694 MOV AL, 0x0f ; write to all pixels
\r
696 MOV AL, BL ; restore color
\r
697 REP STOSB ; write the color
\r
699 MOV BL, AL ; remeber color
\r
701 OUT DX, AL ; do the right clip
\r
702 MOV AL, BL ; restore color
\r
703 STOSB ; write pixel
\r
704 ADD DI, nextRow ; go to the next row
\r
718 /* moved to src/lib/modex16/16render.c */
\r
720 /* copy a region of video memory from one page to another.
\r
721 * It assumes that the left edge of the tile is the same on both
\r
722 * regions and the memory areas do not overlap.
\r
725 modexCopyPageRegion(page_t *dest, page_t *src,
\r
728 word width, word height)
\r
730 word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);
\r
731 word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);
\r
732 word scans = vga_state.vga_stride+8; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
733 word nextSrcRow = src->stridew - scans - 1;
\r
734 word nextDestRow = dest->stridew - scans - 1;
\r
736 byte left = lclip[sx&0x03];
\r
737 byte right = rclip[(sx+width)&0x03];
\r
739 // handle the case which requires an extra group
\r
740 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
744 // 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
756 MOV AX, SCREEN_SEG ; work in the vga space
\r
761 MOV DX, GC_INDEX ; turn off cpu bits
\r
765 MOV AX, SC_INDEX ; point to the mask register
\r
767 MOV AL, SC_MAPMASK ;
\r
775 MOV CX, scans ; the number of latches
\r
777 MOV AL, left ; do the left column
\r
782 MOV AL, 0fh ; do the inner columns
\r
784 REP MOVSB ; copy the pixels
\r
786 MOV AL, right ; do the right column
\r
791 MOV AX, SI ; go the start of the next row
\r
792 ADD AX, nextSrcRow ;
\r
795 ADD AX, nextDestRow ;
\r
798 DEC height ; do the rest of the actions
\r
801 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
802 MOV AL, 0ffh ; none from latches
\r
818 /* fade and flash */
\r
820 modexFadeOn(word fade, byte *palette) {
\r
821 fadePalette(-fade, 64, 64/fade+1, palette);
\r
826 modexFadeOff(word fade, byte *palette) {
\r
827 fadePalette(fade, 0, 64/fade+1, palette);
\r
832 modexFlashOn(word fade, byte *palette) {
\r
833 fadePalette(fade, -64, 64/fade+1, palette);
\r
838 modexFlashOff(word fade, byte *palette) {
\r
839 fadePalette(-fade, 0, 64/fade+1, palette);
\r
844 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
848 /* handle the case where we just update */
\r
850 modexPalUpdate(palette);
\r
854 while(iter > 0) { /* FadeLoop */
\r
855 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
856 tmppal[i] = palette[i] - dim;
\r
857 if(tmppal[i] > 127) {
\r
859 } else if(tmppal[i] > 63) {
\r
863 modexPalUpdate(tmppal);
\r
871 void modexPalSave(byte *palette)
\r
875 outp(PAL_READ_REG, 0); // start at palette entry 0
\r
876 for(i=0; i<PAL_SIZE; i++)
\r
878 palette[i] = inp(PAL_DATA_REG); // read the palette data
\r
886 ptr = malloc(PAL_SIZE);
\r
890 printf("Could not Allocate palette.\n");
\r
896 static struct pcxHeader {
\r
917 static void loadPcxStage1(FILE *file, bitmap_t *result) {
\r
923 /* read the header */
\r
924 fread(&head, sizeof(char), sizeof(struct pcxHeader), file);
\r
926 /* get the width and height */
\r
927 result->width = head.xmax - head.xmin + 1;
\r
928 result->height = head.ymax - head.ymin + 1;
\r
930 /* make sure this is 8bpp */
\r
931 if(head.bpp != 8) {
\r
932 printf("I only know how to handle 8bpp pcx files!\n");
\r
938 void loadPcxPalette(FILE *file, bitmap_t *result) {
\r
942 /* handle the palette */
\r
943 fseek(file, -769, SEEK_END);
\r
945 result->palette = modexNewPal();
\r
946 if(head.version == 5 && val == 12) {
\r
947 /* use the vga palette */
\r
948 for(index=0; !feof(file) && index < PAL_SIZE; index++) {
\r
950 result->palette[index] = val >> 2;
\r
953 /* use the 16 color palette */
\r
954 for(index=0; index<48; index++) {
\r
955 result->palette[index] = head.pal16[index];
\r
962 modexLoadPalFile(byte *filename, byte *palette) {
\r
966 // free the palette if it exists
\r
967 //if(*palette) { free(*palette); }
\r
969 // allocate the new palette
\r
970 //*palette = modexNewPal();
\r
973 file = fopen(filename, "rb");
\r
975 printf("Could not open palette file: %s\n", filename);
\r
978 /* read the file */
\r
980 while(!feof(file)) {
\r
981 *ptr++ = fgetc(file);
\r
988 bitmapLoadPcx(char *filename) {
\r
995 /* open the PCX file for reading */
\r
996 file = fopen(filename, "rb");
\r
998 printf("Could not open %s for reading.\n", filename);
\r
1002 /* load the first part of the pcx file */
\r
1003 loadPcxStage1(file, &result);
\r
1005 /* allocate the buffer */
\r
1006 bufSize = result.width * result.height;
\r
1007 result.data = malloc(bufSize);
\r
1008 if(!result.data) {
\r
1009 printf("Could not allocate memory for bitmap data.");
\r
1014 /* read the buffer in */
\r
1017 /* get the run length and the value */
\r
1018 count = fgetc(file);
\r
1019 if(0xC0 == (count & 0xC0)) { /* this is the run count */
\r
1021 val = fgetc(file);
\r
1027 /* write the pixel the specified number of times */
\r
1028 for(; count && index < bufSize; count--,index++) {
\r
1029 result.data[index] = val;
\r
1031 } while(index < bufSize);
\r
1033 loadPcxPalette(file, &result);
\r
1042 bitmapLoadPcxTiles(char *filename, word twidth, word theight) {
\r
1048 /* open the PCX file for reading */
\r
1049 file = fopen(filename, "rb");
\r
1051 printf("Could not open %s for reading.\n", filename);
\r
1055 /* load the first part of the pcx file */
\r
1056 loadPcxStage1(file, &result);
\r
1058 /* get the number of tiles and set up the result structure */
\r
1059 ts.twidth = twidth;
\r
1060 ts.theight = theight;
\r
1061 ts.ntiles = (result.width/twidth) * (result.height/theight);
\r
1062 ts.palette = result.palette;
\r
1064 /* allocate the pixel storage for the tiles */
\r
1065 ts.data = malloc(sizeof(byte*) * ts.ntiles);
\r
1066 ts.data[0] = malloc(sizeof(byte) * ts.ntiles * twidth * theight);
\r
1067 for(i=1; i < ts.ntiles; i++) {
\r
1068 ts.data[i] = ts.data[i-1] + twidth * theight;
\r
1071 /* finish off the file */
\r
1072 loadPcxPalette(file, &result);
\r
1080 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
1086 /* TODO Make this fast. It's SLOOOOOOW */
\r
1087 for(plane=0; plane < 4; plane++) {
\r
1088 modexSelectPlane(PLANE(plane+x));
\r
1089 for(px = plane; px < bmp->width; px+=4) {
\r
1091 for(py=0; py<bmp->height; py++) {
\r
1092 if(!sprite || bmp->data[offset])
\r
1093 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
1094 offset+=bmp->width;
\r
1100 //* normal versions *//
\r
1102 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
1103 /* draw the region (the entire freakin bitmap) */
\r
1104 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
1108 modexDrawBmpRegion(page_t *page, int x, int y,
\r
1109 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
1110 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
1111 byte *data = bmp->data;//+bmp->offset;
\r
1112 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
1115 byte plane = 1 << ((byte) x & 0x03);
\r
1116 word scanCount = width/4 + (width%4 ? 1 :0);
\r
1117 word nextPageRow = page->width/4 - scanCount;
\r
1118 word nextBmpRow = (word) bmp->width - width;
\r
1119 word rowCounter=0;
\r
1120 byte planeCounter = 4;
\r
1123 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
1126 MOV DX, SC_INDEX ; point at the map mask register
\r
1127 MOV AL, SC_MAPMASK ;
\r
1131 MOV DX, SC_DATA ; select the current plane
\r
1135 ;-- begin plane painting
\r
1136 MOV AX, height ; start the row counter
\r
1137 MOV rowCounter, AX ;
\r
1138 MOV DI, poffset ; go to the first pixel
\r
1139 MOV SI, bmpOffset ; go to the bmp pixel
\r
1141 MOV CX, width ; count the columns
\r
1143 MOVSB ; copy the pixel
\r
1144 SUB CX, 3 ; we skip the next 3
\r
1145 ADD SI, 3 ; skip the bmp pixels
\r
1146 LOOP SCAN_LOOP ; finish the scan
\r
1148 MOV AX, nextPageRow
\r
1149 ADD DI, AX ; go to the next row on screen
\r
1150 MOV AX, nextBmpRow
\r
1151 ADD SI, AX ; go to the next row on bmp
\r
1154 JNZ ROW_LOOP ; do all the rows
\r
1155 ;-- end plane painting
\r
1156 MOV AL, plane ; advance to the next plane
\r
1158 AND AL, 0x0f ; mask the plane properly
\r
1159 MOV plane, AL ; store the plane
\r
1161 INC bmpOffset ; start bmp at the right spot
\r
1164 JNZ PLANE_LOOP ; do all 4 planes
\r
1169 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
1170 /* draw the whole sprite */
\r
1171 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
1175 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
1176 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
1177 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
1178 byte *data = bmp->data;//+bmp->offset;
\r
1179 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
1182 byte plane = 1 << ((byte) x & 0x03);
\r
1183 word scanCount = width/4 + (width%4 ? 1 :0);
\r
1184 word nextPageRow = page->width/4 - scanCount;
\r
1185 word nextBmpRow = (word) bmp->width - width;
\r
1186 word rowCounter=0;
\r
1187 byte planeCounter = 4;
\r
1190 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
1193 MOV DX, SC_INDEX ; point at the map mask register
\r
1194 MOV AL, SC_MAPMASK ;
\r
1198 MOV DX, SC_DATA ; select the current plane
\r
1202 ;-- begin plane painting
\r
1203 MOV AX, height ; start the row counter
\r
1204 MOV rowCounter, AX ;
\r
1205 MOV DI, poffset ; go to the first pixel
\r
1206 MOV SI, bmpOffset ; go to the bmp pixel
\r
1208 MOV CX, width ; count the columns
\r
1213 JNE DRAW_PIXEL ; draw non-zero pixels
\r
1215 INC DI ; skip the transparent pixel
\r
1219 MOVSB ; copy the pixel
\r
1221 SUB CX, 3 ; we skip the next 3
\r
1222 ADD SI, 3 ; skip the bmp pixels
\r
1223 LOOP SCAN_LOOP ; finish the scan
\r
1225 MOV AX, nextPageRow
\r
1226 ADD DI, AX ; go to the next row on screen
\r
1227 MOV AX, nextBmpRow
\r
1228 ADD SI, AX ; go to the next row on bmp
\r
1231 JNZ ROW_LOOP ; do all the rows
\r
1232 ;-- end plane painting
\r
1234 MOV AL, plane ; advance to the next plane
\r
1236 AND AL, 0x0f ; mask the plane properly
\r
1237 MOV plane, AL ; store the plane
\r
1239 INC bmpOffset ; start bmp at the right spot
\r
1242 JNZ PLANE_LOOP ; do all 4 planes
\r
1246 //* planar buffer versions *//
\r
1248 modexDrawBmpPBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
1249 /* draw the region (the entire freakin bitmap) */
\r
1250 modexDrawBmpPBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
1254 modexDrawBmpPBufRegion(page_t *page, int x, int y,
\r
1255 int rx, int ry, int rw, int rh, planar_buf_t *bmp) {
\r
1256 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
1257 byte *data = (byte *)bmp->plane[0];
\r
1258 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
1261 byte plane = 1 << ((byte) x & 0x03);
\r
1262 word scanCount = width/4 + (width%4 ? 1 :0);
\r
1263 word nextPageRow = page->width/4 - scanCount;
\r
1264 word nextBmpRow = (word) bmp->width - width;
\r
1265 word rowCounter=0;
\r
1266 byte planeCounter = 4;
\r
1269 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
1272 MOV DX, SC_INDEX ; point at the map mask register
\r
1273 MOV AL, SC_MAPMASK ;
\r
1277 MOV DX, SC_DATA ; select the current plane
\r
1281 ;-- begin plane painting
\r
1282 MOV AX, height ; start the row counter
\r
1283 MOV rowCounter, AX ;
\r
1284 MOV DI, poffset ; go to the first pixel
\r
1285 MOV SI, bmpOffset ; go to the bmp pixel
\r
1287 MOV CX, width ; count the columns
\r
1298 MOVSB ; copy the pixel
\r
1300 SUB CX, 3 ; we skip the next 3
\r
1301 ADD SI, 3 ; skip the bmp pixels
\r
1302 LOOP SCAN_LOOP ; finish the scan
\r
1304 MOV AX, nextPageRow
\r
1305 ADD DI, AX ; go to the next row on screen
\r
1306 MOV AX, nextBmpRow
\r
1307 ADD SI, AX ; go to the next row on bmp
\r
1310 JNZ ROW_LOOP ; do all the rows
\r
1311 ;-- end plane painting
\r
1313 MOV AL, plane ; advance to the next plane
\r
1315 AND AL, 0x0f ; mask the plane properly
\r
1316 MOV plane, AL ; store the plane
\r
1318 INC bmpOffset ; start bmp at the right spot
\r
1321 JNZ PLANE_LOOP ; do all 4 planes
\r
1326 modexDrawSpritePBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
1327 /* draw the whole sprite */
\r
1328 modexDrawSpritePBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
1332 modexDrawSpritePBufRegion(page_t *page, int x, int y,
\r
1333 int rx, int ry, int rw, int rh, planar_buf_t *bmp) {
\r
1334 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
1335 byte *data = (byte *)bmp->plane[0];
\r
1336 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
1339 byte plane = 1 << ((byte) x & 0x03);
\r
1340 word scanCount = width/4 + (width%4 ? 1 :0);
\r
1341 word nextPageRow = page->width/4 - scanCount;
\r
1342 word nextBmpRow = (word) bmp->width - width;
\r
1343 word rowCounter=0;
\r
1344 byte planeCounter = 4;
\r
1347 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
1350 MOV DX, SC_INDEX ; point at the map mask register
\r
1351 MOV AL, SC_MAPMASK ;
\r
1355 MOV DX, SC_DATA ; select the current plane
\r
1359 ;-- begin plane painting
\r
1360 MOV AX, height ; start the row counter
\r
1361 MOV rowCounter, AX ;
\r
1362 MOV DI, poffset ; go to the first pixel
\r
1363 MOV SI, bmpOffset ; go to the bmp pixel
\r
1365 MOV CX, width ; count the columns
\r
1370 JNE DRAW_PIXEL ; draw non-zero pixels
\r
1372 INC DI ; skip the transparent pixel
\r
1376 MOVSB ; copy the pixel
\r
1378 SUB CX, 3 ; we skip the next 3
\r
1379 ADD SI, 3 ; skip the bmp pixels
\r
1380 LOOP SCAN_LOOP ; finish the scan
\r
1382 MOV AX, nextPageRow
\r
1383 ADD DI, AX ; go to the next row on screen
\r
1384 MOV AX, nextBmpRow
\r
1385 ADD SI, AX ; go to the next row on bmp
\r
1388 JNZ ROW_LOOP ; do all the rows
\r
1389 ;-- end plane painting
\r
1391 MOV AL, plane ; advance to the next plane
\r
1393 AND AL, 0x0f ; mask the plane properly
\r
1394 MOV plane, AL ; store the plane
\r
1396 INC bmpOffset ; start bmp at the right spot
\r
1399 JNZ PLANE_LOOP ; do all 4 planes
\r
1402 // end of old library
\r
1404 #define COREPALSIZE 9//27 //3*9
\r
1406 void VLL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, word palsize, global_game_variables_t *gvar)
\r
1411 fd = open(filename,O_RDONLY|O_BINARY);
\r
1413 read(fd,palette, palsize*3);
\r
1416 if(palsize==COREPALSIZE) newpalette = palette; else{ //if core then load it
\r
1417 newpalette = &palette[3]; //skip overscan color
\r
1420 VL_UpdatePaletteWrite(newpalette, o, palsize, gvar);
\r
1425 void VL_SetCorePal(global_game_variables_t *gvar)
\r
1427 byte *palette = &corepal;
\r
1430 vga_palette_lseek(0);
\r
1431 for (i=0;i < COREPALSIZE;i++)
\r
1432 vga_palette_write(palette[(i*3)+0]>>2,
\r
1433 palette[(i*3)+1]>>2,
\r
1434 palette[(i*3)+2]>>2);
\r
1436 VL_PaletteSync(gvar);
\r
1439 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)
\r
1441 VLL_LoadPalFilewithoffset(filename, palette,
\r
1442 0, //overwrite core/system palette
\r
1443 // COREPALSIZE, //preserved core/system palette
\r
1444 PAL_SIZE/3, gvar);
\r
1447 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)
\r
1449 VLL_LoadPalFilewithoffset("data/16.pal", palette, 0, COREPALSIZE, gvar);
\r
1452 void VL_UpdatePaletteWrite(byte *palette, word o, word p, global_game_variables_t *gvar)
\r
1456 vga_palette_lseek(o);
\r
1457 for (i=0;i < p-o;i++)
\r
1458 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);
\r
1460 VL_PaletteSync(gvar);
\r
1463 void VL_PaletteSync(global_game_variables_t *gvar)
\r
1465 modexPalSave(&gvar->video.palette);
\r
1469 modexSavePalFile(char *filename, byte *pal) {
\r
1473 /* open the file for writing */
\r
1474 file = fopen(filename, "wb");
\r
1476 printf("Could not open %s for writing\n", filename);
\r
1479 /* write the data to the file */
\r
1480 fwrite(pal, 1, PAL_SIZE, file);
\r
1488 fadePalette(-1, 64, 1, tmppal);
\r
1494 fadePalette(-1, -64, 1, tmppal);
\r
1499 //moved to 16_vlpal.c
\r
1502 modexPalUpdate(byte *p)
\r
1505 //modexWaitBorder();
\r
1506 vga_wait_for_vsync();
\r
1507 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1508 for(i=0; i<PAL_SIZE/2; i++)
\r
1510 outp(PAL_DATA_REG, p[i]);
\r
1512 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1513 vga_wait_for_vsync();
\r
1514 for(; i<PAL_SIZE; i++)
\r
1516 outp(PAL_DATA_REG, p[(i)]);
\r
1521 //modexPalUpdate0(byte *p)
\r
1522 VL_modexPalScramble(byte *p)
\r
1525 //modexWaitBorder();
\r
1526 vga_wait_for_vsync();
\r
1527 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1528 for(i=0; i<PAL_SIZE/2; i++)
\r
1530 outp(PAL_DATA_REG, rand());
\r
1532 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1533 vga_wait_for_vsync();
\r
1534 for(; i<PAL_SIZE; i++)
\r
1536 outp(PAL_DATA_REG, rand());
\r
1541 VL_modexPalOverscan(byte *p, word col)
\r
1544 //modexWaitBorder();
\r
1545 vga_wait_for_vsync();
\r
1546 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1547 for(i=col; i<(3+col); i++)
\r
1549 outp(PAL_DATA_REG, p[i]);
\r
1551 // modexPalSave(p);
\r
1557 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1559 word pageOff = (word) page->data;
\r
1560 /* Each address accesses four neighboring pixels, so set
\r
1561 Write Plane Enable according to which pixel we want
\r
1562 to modify. The plane is determined by the two least
\r
1563 significant bits of the x-coordinate: */
\r
1564 modexSelectPlane(PLANE(x));
\r
1565 //outp(SC_INDEX, 0x02);
\r
1566 //outp(SC_DATA, 0x01 << (x & 3));
\r
1568 /* The offset of the pixel into the video segment is
\r
1569 offset = (width * y + x) / 4, and write the given
\r
1570 color to the plane we selected above. Heed the active
\r
1571 page start selection. */
\r
1572 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1576 byte modexgetPixel(page_t *page, int x, int y)
\r
1578 word pageOff = (word) page->data;
\r
1579 /* Select the plane from which we must read the pixel color: */
\r
1580 outpw(GC_INDEX, 0x04);
\r
1581 outpw(GC_INDEX+1, x & 3);
\r
1583 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1587 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1589 /* vertical drawing routine by joncampbell123.
\r
1591 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1592 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1594 * 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
1595 word rows = romFonts[t].charSize;
\r
1603 m1 = 0x80; // left half
\r
1604 m2 = 0x08; // right half
\r
1605 for (colm=0;colm < 4;colm++) {
\r
1607 modexSelectPlane(PLANE(plane));
\r
1608 for (row=0;row < rows;row++) {
\r
1609 fontbyte = romFontsData.l[row];
\r
1610 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1611 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1612 drawaddr += page->width >> 2;
\r
1617 if ((++plane) == 4) {
\r
1624 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word color, word bgcolor, boolean vidsw, const byte *str)
\r
1628 //word addr = (word) romFontsData.l;
\r
1636 printf("%s\n", str);
\r
1639 if(tlsw){ x-=page->tlx; y-=page->tly; }
\r
1641 addrq = (page->stridew) * y + (word)(x_draw) +
\r
1642 ((word)page->data);
\r
1644 s=romFonts[t].seg;
\r
1645 o=romFonts[t].off;
\r
1646 w=romFonts[t].charSize;
\r
1647 romFontsData.chw=0;
\r
1649 for(; *str != '\0'; str++)
\r
1655 romFontsData.chw = 0;
\r
1656 addrq += (page->stridew) * 8;
\r
1662 // load the character into romFontsData.l
\r
1663 // no need for inline assembly!
\r
1664 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1665 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1666 modexDrawChar(page, x_draw/*for mode X planar use*/, t, color, bgcolor, addrr);
\r
1667 x_draw += 8; /* track X for edge of screen */
\r
1668 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1670 //printf("print xy:%dx%d tlxy:%dx%d\n", x, y, page->tlx, page->tly);
\r
1675 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1677 word i, s, o, w, j, xp;
\r
1679 word addr = (word) l;
\r
1703 s=romFonts[t].seg;
\r
1704 o=romFonts[t].off;
\r
1706 for(; *str != '\0'; str++)
\r
1709 if((c=='\n'/* || c=="\
\r
1710 "*/)/* || chw>=page->width*/)
\r
1716 //load the letter 'A'
\r
1731 MOV AL, c ; the letter
\r
1734 ADD SI, AX ;the address of charcter
\r
1752 for(i=0; i<w; i++)
\r
1758 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1759 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1768 // short hand of modexprint
\r
1769 void VL_print(const byte *str, nibble pagenum, global_game_variables_t *gvar)
\r
1771 modexprint(&(gvar->video.page[pagenum]), gvar->video.print.x, gvar->video.print.y, gvar->video.print.t, gvar->video.print.tlsw, gvar->video.print.color, gvar->video.print.bgcolor, gvar->video.VL_Started, str);
\r
1774 /* palette dump on display! */
\r
1775 void modexpdump(nibble pagenum, global_game_variables_t *gvar)
\r
1777 int mult=(QUADWH);
\r
1778 int palq=(mult)*TILEWH;
\r
1781 for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){
\r
1782 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){
\r
1783 modexClearRegion(&gvar->video.page[pagenum], palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1787 modexPalSave(gvar->video.palette);
\r
1790 /////////////////////////////////////////////////////////////////////////////
\r
1792 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1793 // the Virtual screen. //
\r
1795 /////////////////////////////////////////////////////////////////////////////
\r
1796 void modexcls(page_t *page, byte color, byte *Where)
\r
1798 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1799 /* set map mask to all 4 planes */
\r
1800 outpw(SC_INDEX, 0xff02);
\r
1801 //_fmemset(VGA, color, 16000);
\r
1802 _fmemset(Where, color, page->stridew*page->height);
\r
1806 // pattern filler from joncampbell123's code
\r
1808 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1810 unsigned int i,j,o, d,h,s;
\r
1816 w=vga_state.vga_width;
\r
1818 s=vga_state.vga_stride;
\r
1822 h=vga_state.vga_height;
\r
1830 w=video->page[pn].width;
\r
1831 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1832 s=video->page[pn].stridew;
\r
1836 h=video->page[pn].height;
\r
1839 if(!pn) h=video->vh;
\r
1840 else h=video->page[pn].height;
\r
1846 /* fill screen/pattern with a distinctive pattern */
\r
1847 for (i=0;i < w;i++) {
\r
1849 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1850 for (j=0;j < h;j++,o += s)
\r
1851 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1856 modexWaitBorder() {
\r
1857 while(inp(STATUS_REGISTER_1) & 8) {
\r
1861 while(!(inp(STATUS_REGISTER_1) & 8)) {
\r
1867 modexWaitBorder_start()
\r
1869 while(inp(STATUS_REGISTER_1) & 8) {
\r
1876 modexWaitBorder_end()
\r
1878 while(!(inp(STATUS_REGISTER_1) & 8)) {
\r
1884 //===========================================================================
\r
1887 // printings of video memory information
\r
1889 void VL_PrintmodexmemInfo(video_t *v)
\r
1893 // printf("========================================\n");
\r
1894 printf("VL_PrintmodexmemInfo:\n");
\r
1895 // printf("========================================\n");
\r
1896 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
1897 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
1898 printf(" vga_stride: %u ", vga_state.vga_stride);
\r
1899 printf("pagestride: %u ", v->page[0].stridew);
\r
1900 printf("draw_stride: %u ", vga_state.vga_draw_stride);
\r
1901 printf("draw_stride_limit: %u\n", vga_state.vga_draw_stride_limit);
\r
1903 if(v->vmem_remain)
\r
1904 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1905 if(v->num_of_pages)
\r
1908 for(i=0; i<v->num_of_pages;i++)
\r
1910 printf(" [%u]=", i);
\r
1911 printf("(%Fp)", (v->page[i].data));
\r
1912 printf(" size=%u ", v->page[i].pagesize);
\r
1913 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1914 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1915 printf("pi=%u", v->page[i].pi);
\r