1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2017 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 //Quit ("Improper video card! If you really have a VGA card that I am not\ndetecting it!", gvar);
\r
55 =======================
\r
59 =======================
\r
62 void VL_Shutdown (global_game_variables_t *gvar)
\r
64 VGAmodeX(0, 1, gvar);
\r
68 =======================
\r
70 = VL_SetVGAPlaneMode
\r
72 =======================
\r
75 void VL_SetVGAPlaneMode (global_game_variables_t *gvar)
\r
77 VL_vgaSetMode(VGA_256_COLOR_MODE);
\r
80 VL_SetLineWidth (40, &gvar->video.ofs);
\r
84 //===========================================================================
\r
91 = Fill the entire video buffer with a given color
\r
96 void VL_ClearVideo (byte color)
\r
104 and al,0xfc // write mode 0 to store directly to video
\r
108 mov ax,SC_MAPMASK+15*256
\r
109 out dx,ax // write through all four planes
\r
115 mov cx,0x8000 // 0x8000 words, clearing 8 video bytes/word
\r
122 =============================================================================
\r
124 VGA REGISTER MANAGEMENT ROUTINES
\r
126 =============================================================================
\r
138 void VL_DePlaneVGA (void)
\r
142 // change CPU addressing to non linear mode
\r
146 // turn off chain 4 and odd/even
\r
148 outportb (SC_INDEX,SC_MEMMODE);
\r
149 outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);
\r
151 outportb (SC_INDEX,SC_MAPMASK); // leave this set throughought
\r
154 // turn off odd/even and set write mode 0
\r
156 outportb (GC_INDEX,GC_MODE);
\r
157 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);
\r
162 outportb (GC_INDEX,GC_MISCELLANEOUS);
\r
163 outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);
\r
166 // clear the entire buffer space, because int 10h only did 16 k / plane
\r
171 // change CRTC scanning from doubleword to byte mode, allowing >64k scans
\r
173 outportb (CRTC_INDEX,CRTC_UNDERLINE);
\r
174 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);
\r
176 outportb (CRTC_INDEX,CRTC_MODE);
\r
177 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);
\r
180 //===========================================================================
\r
183 ====================
\r
185 = VL_SetSplitScreen
\r
187 ====================
\r
190 void VL_SetSplitScreen (int linenum)
\r
193 linenum=linenum*2-1;
\r
194 outportb (CRTC_INDEX,CRTC_LINECOMPARE);
\r
195 outportb (CRTC_INDEX+1,linenum % 256);
\r
196 outportb (CRTC_INDEX,CRTC_OVERFLOW);
\r
197 outportb (CRTC_INDEX+1, 1+16*(linenum/256));
\r
198 outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
\r
199 outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
\r
202 /////////////////////////////////////////////////////////////////////////////
\r
204 // setvideo() - This function Manages the video modes //
\r
206 /////////////////////////////////////////////////////////////////////////////
\r
207 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)
\r
209 union REGS in, out;
\r
213 case 0: // deinit the video
\r
214 // change to the video mode we were in before we switched to mode 13h
\r
215 if(gv->video.VL_Started)
\r
219 in.h.al = gv->video.old_mode;
\r
220 int86(0x10, &in, &out);
\r
222 gv->video.VL_Started=0;
\r
224 default: // init the video
\r
225 if(gv->video.VL_Started)
\r
227 if(!gv->video.VL_Initiated)
\r
229 // get old video mode
\r
231 //int86(0x10, &in, &out);
\r
232 gv->video.old_mode = VL_vgaGetMode();//out.h.al;
\r
234 modexEnter(vq, cmem, gv);
\r
239 //---------------------------------------------------
\r
241 // Use the bios to set the current video mode
\r
245 VL_vgaSetMode(byte mode)
\r
249 regs.h.ah = SET_MODE;
\r
251 int86(VIDEO_INT, ®s, ®s);
\r
254 //---------------------------------------------------
\r
256 // Use the bios to get the current video mode
\r
260 VL_vgaGetMode(void)
\r
262 return int10_getmode();
\r
265 /* -========================= Entry Points ==========================- */
\r
266 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)
\r
269 struct vga_mode_params cm;
\r
270 //int CRTParmCount;
\r
272 VL_vgaSetMode(VGA_256_COLOR_MODE);
\r
273 vga_enable_256color_modex();
\r
275 update_state_from_vga();
\r
276 vga_read_crtc_mode(&cm);
\r
278 /* reprogram the CRT controller */
\r
279 //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
280 //outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
285 //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);
\r
286 /*for(i=0; i<CRTParmCount; i++) {
\r
287 outpw(CRTC_INDEX, ModeX_320x240regs[i]);
\r
289 /* width and height */
\r
290 gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this
\r
291 gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this
\r
292 /* virtual width and height. match screen, at first */
\r
293 gv->video.page[0].height = gv->video.page[0].sh;
\r
294 gv->video.page[0].width = gv->video.page[0].sw;
\r
296 // mode X BYTE mode
\r
299 // 320x240 mode 60Hz
\r
300 cm.horizontal_total=0x5f + 5; /* CRTC[0] -5 */
\r
301 cm.horizontal_display_end=0x4f + 1; /* CRTC[1] -1 */
\r
302 cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */
\r
303 // cm.horizontal_blank_end=0x82 + 1; /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;
\r
304 cm.horizontal_start_retrace=0x54;/* CRTC[4] */
\r
305 cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */
\r
306 //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */
\r
307 //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */
\r
308 cm.vertical_total = 0x20D + 2;
\r
309 cm.vertical_start_retrace = 0x1EA;
\r
310 cm.vertical_end_retrace = 0x1EC;
\r
311 cm.vertical_display_end = 480;
\r
312 cm.vertical_blank_start = 0x1E7 + 1;
\r
313 cm.vertical_blank_end = 0x206 + 1;
\r
314 cm.clock_select = 0; /* misc register = 0xE3 25MHz */
\r
317 cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)
\r
319 case 2: // TODO: 160x120 according to ModeX_160x120regs
\r
321 case 3: // TODO: 160x120 according to ModeX_320x200regs
\r
323 case 4: // TODO: 160x120 according to ModeX_192x144regs
\r
325 case 5: // TODO: 160x120 according to ModeX_256x192regs
\r
331 vga_state.vga_stride = cm.offset * 2;
\r
332 vga_write_crtc_mode(&cm,0);
\r
334 // clear video memory //
\r
340 dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA; // used for faster screen clearing //
\r
341 vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);
\r
342 for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB
\r
343 // fix up the palette and everything //
\r
344 modexPalBlack(); //reset the palette~//
\r
347 // clear the entire buffer space, because int 10h only did 16 k / plane
\r
353 VL_SetLineWidth (cm.offset, &gv->video.ofs);
\r
354 gv->video.VL_Started=1;
\r
357 void modexLeave(void)
\r
359 // VGAmodeX restores original mode and palette
\r
360 VL_vgaSetMode(TEXT_MODE);
\r
364 modexDefaultPage(page_t *p)
\r
368 /* default page values */
\r
370 //page.data = (byte far *)(vga_state.vga_graphics_ram);
\r
371 page.data = (vga_state.vga_graphics_ram);
\r
376 page.width = p->sw+TILEWHD;
\r
377 page.height = p->sh+TILEWHD;
\r
378 page.ti.tw = page.sw/TILEWH;
\r
379 page.ti.th = page.sh/TILEWH;
\r
380 page.ti.tilesw=page.width/TILEWH;
\r
381 page.ti.tilesh=page.height/TILEWH;
\r
382 page.ti.tilemidposscreenx = page.ti.tw/2;
\r
383 page.ti.tilemidposscreeny = (page.ti.th/2)+1;
\r
384 page.stridew=page.width/4;
\r
385 page.pagesize = (word)(page.stridew)*page.height;
\r
386 page.pi=page.width*4;
\r
392 /* returns the next page in contiguous memory
\r
393 * the next page will be the same size as p, by default
\r
396 modexNextPage(page_t *p) {
\r
399 result.data = p->data + (p->pagesize);
\r
400 result.dx = p->dx; // not used anymore we use page[0].dx
\r
401 result.dy = p->dy; // not used anymore we use page[0].dy
\r
404 result.width = p->width;
\r
405 result.height = p->height;
\r
406 result.ti.tw = p->ti.tw;
\r
407 result.ti.th = p->ti.th;
\r
408 result.ti.tilesw = p->ti.tilesw;
\r
409 result.ti.tilesh = p->ti.tilesh;
\r
410 result.stridew=p->stridew;
\r
411 result.pagesize = p->pagesize;
\r
412 result.pi=result.width*4;
\r
413 result.id = p->id+1;
\r
418 //next page with defined dimentions~
\r
420 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
424 result.data = p->data + (p->pagesize); /* compute the offset */
\r
425 result.dx = 0; // not used anymore we use page[0].dx
\r
426 result.dy = 0; // not used anymore we use page[0].dy
\r
431 result.ti.tw = result.sw/TILEWH;
\r
432 result.ti.th = result.sh/TILEWH;
\r
433 result.ti.tilesw=result.width/TILEWH;
\r
434 result.ti.tilesh=result.height/TILEWH;
\r
435 result.id = p->id+1;
\r
436 result.stridew=result.width/4;//p->sw/4;
\r
437 result.pagesize = (word)(result.stridew)*result.height;
\r
438 /* switch(result.id)
\r
441 result.pi=p->width*4;
\r
447 result.pi=result.width*4;
\r
452 void modexCalcVmemRemain(video_t *video)
\r
455 //printf("\n\n 1st vmem_remain=%u\n", video->vmem_remain);
\r
456 for(i=0; i<video->num_of_pages; i++)
\r
458 video->vmem_remain-=video->page[i].pagesize;
\r
459 //printf(" [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);
\r
460 //printf(" [%u], vmem_remain=%u\n", i, video->vmem_remain);
\r
464 void VL_Initofs(video_t *video)
\r
466 if(!video->vga_state.bgps)
\r
468 video->ofs.offscreen_ofs = video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);
\r
469 video->ofs.pattern_ofs = (uint16_t)video->page[2].data;
\r
471 video->ofs.offscreen_ofs = 0;
\r
472 video->ofs.pattern_ofs = 0;//(uint16_t)video->page[0].data;
\r
476 void modexHiganbanaPageSetup(video_t *video)
\r
478 video->vmem_remain=65535U;
\r
479 video->num_of_pages=0;
\r
480 (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++; //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);
\r
481 (video->page[1]) = modexNextPage(&(video->page[0])); video->num_of_pages++;
\r
482 //0000 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4); video->num_of_pages++;
\r
483 //0000 (video->page[3]) = (video->page[2]); video->num_of_pages++;
\r
484 //// (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4); video->num_of_pages++;
\r
485 //// (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208); video->num_of_pages++;
\r
486 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96); video->num_of_pages++;
\r
487 (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96); video->num_of_pages++;
\r
488 modexCalcVmemRemain(video);
\r
490 video->sp=video->p = 0; //showpage
\r
491 video->dorender = 1; //render
\r
492 video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;
\r
496 video->vga_state.omemptr= vga_state.vga_graphics_ram;
\r
497 video->vga_state.vga_draw_stride= vga_state.vga_draw_stride;
\r
498 video->vga_state.vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
499 //sprite render switch and bgpreservation switch
\r
500 video->vga_state.rss= 1;
\r
501 video->vga_state.bgps= 1;
\r
503 //setup the buffersize
\r
504 video->page[0].dx=video->page[0].dy=
\r
505 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
506 video->page[2].dx=video->page[2].dy=
\r
507 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
511 // move page to appropriate part and show it
\r
514 modexShowPage(page_t *page) {
\r
515 word high_address, low_address, offset;
\r
518 /* calculate offset */
\r
519 offset = (word) page->data;
\r
520 offset += page[0].dy * (page->width >> 2 );
\r
521 offset += page[0].dx >> 2;
\r
523 /* calculate crtcOffset according to virtual width */
\r
524 crtcOffset = page->width >> 3;
\r
526 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
527 low_address = LOW_ADDRESS | (offset << 8);
\r
529 /* wait for appropriate timing and then program CRTC */
\r
530 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
531 outpw(CRTC_INDEX, high_address);
\r
532 outpw(CRTC_INDEX, low_address);
\r
533 outp(CRTC_INDEX, 0x13);
\r
534 outp(CRTC_DATA, crtcOffset);
\r
536 /* wait for one retrace */
\r
537 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
539 /* do PEL panning here */
\r
540 outp(AC_INDEX, 0x33);
\r
541 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
544 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
546 VL_ShowPage(page_t *page, boolean vsync, boolean sr)
\r
548 word high_address, low_address, offset;
\r
551 // calculate offset
\r
552 offset = (word) page->data;
\r
553 offset += page->dy * (page->width >> 2 );
\r
554 offset += page->dx >> 2;
\r
556 // calculate crtcOffset according to virtual width
\r
560 crtcOffset = page->sw >> 3;
\r
564 crtcOffset = page->width >> 3;
\r
568 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
569 low_address = LOW_ADDRESS | (offset << 8);
\r
571 // wait for appropriate timing and then program CRTC
\r
572 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
573 outpw(CRTC_INDEX, high_address);
\r
574 outpw(CRTC_INDEX, low_address);
\r
575 outp(CRTC_INDEX, 0x13);
\r
576 outp(CRTC_DATA, crtcOffset);
\r
578 // wait for one retrace
\r
579 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
581 // do PEL panning here
\r
582 outp(AC_INDEX, 0x33);
\r
583 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
584 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;
\r
585 vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;
\r
588 //=============================================================================
\r
591 modexPanPage(page_t *page, int dx, int dy) {
\r
597 modexSelectPlane(byte plane) {
\r
598 outp(SC_INDEX, SC_MAPMASK); /* select plane */
\r
599 outp(SC_DATA, plane);
\r
603 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)
\r
605 word pageOff = (word) page->data;
\r
606 word xoff=(x>>2); // xoffset that begins each row
\r
607 word poffset = pageOff + y*(page->stridew) + xoff; // starting offset
\r
608 word scanCount=w>>2; // number of iterations per row (excluding right clip)
\r
609 word nextRow = page->stridew-scanCount-1; // loc of next row
\r
611 byte left = lclip[x&0x03];
\r
612 byte right = rclip[(x+w)&0x03];
\r
614 // handle the case which requires an extra group
\r
615 if((x & 0x03) && !((x+w) & 0x03)) {
\r
619 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
630 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
632 MOV DI, poffset ; go to the first pixel
\r
633 MOV DX, SC_INDEX ; point to the map mask
\r
637 MOV AL, color ; get ready to write colors
\r
639 MOV CX, scanCount ; count the line
\r
640 MOV BL, AL ; remember color
\r
641 MOV AL, left ; do the left clip
\r
642 OUT DX, AL ; set the left clip
\r
643 MOV AL, BL ; restore color
\r
644 STOSB ; write the color
\r
646 JZ SCAN_DONE ; handle 1 group stuff
\r
648 ;-- write the main body of the scanline
\r
649 MOV BL, AL ; remember color
\r
650 MOV AL, 0x0f ; write to all pixels
\r
652 MOV AL, BL ; restore color
\r
653 REP STOSB ; write the color
\r
655 MOV BL, AL ; remeber color
\r
657 OUT DX, AL ; do the right clip
\r
658 MOV AL, BL ; restore color
\r
659 STOSB ; write pixel
\r
660 ADD DI, nextRow ; go to the next row
\r
674 /* moved to src/lib/modex16/16render.c */
\r
676 /* copy a region of video memory from one page to another.
\r
677 * It assumes that the left edge of the tile is the same on both
\r
678 * regions and the memory areas do not overlap.
\r
681 modexCopyPageRegion(page_t *dest, page_t *src,
\r
684 word width, word height)
\r
686 word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);
\r
687 word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);
\r
688 word scans = vga_state.vga_stride+8; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
689 word nextSrcRow = src->stridew - scans - 1;
\r
690 word nextDestRow = dest->stridew - scans - 1;
\r
692 byte left = lclip[sx&0x03];
\r
693 byte right = rclip[(sx+width)&0x03];
\r
695 // handle the case which requires an extra group
\r
696 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
700 // 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
712 MOV AX, SCREEN_SEG ; work in the vga space
\r
717 MOV DX, GC_INDEX ; turn off cpu bits
\r
721 MOV AX, SC_INDEX ; point to the mask register
\r
723 MOV AL, SC_MAPMASK ;
\r
731 MOV CX, scans ; the number of latches
\r
733 MOV AL, left ; do the left column
\r
738 MOV AL, 0fh ; do the inner columns
\r
740 REP MOVSB ; copy the pixels
\r
742 MOV AL, right ; do the right column
\r
747 MOV AX, SI ; go the start of the next row
\r
748 ADD AX, nextSrcRow ;
\r
751 ADD AX, nextDestRow ;
\r
754 DEC height ; do the rest of the actions
\r
757 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
758 MOV AL, 0ffh ; none from latches
\r
774 /* fade and flash */
\r
776 modexFadeOn(word fade, byte *palette) {
\r
777 fadePalette(-fade, 64, 64/fade+1, palette);
\r
782 modexFadeOff(word fade, byte *palette) {
\r
783 fadePalette(fade, 0, 64/fade+1, palette);
\r
788 modexFlashOn(word fade, byte *palette) {
\r
789 fadePalette(fade, -64, 64/fade+1, palette);
\r
794 modexFlashOff(word fade, byte *palette) {
\r
795 fadePalette(-fade, 0, 64/fade+1, palette);
\r
800 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
804 /* handle the case where we just update */
\r
806 modexPalUpdate(palette);
\r
810 while(iter > 0) { /* FadeLoop */
\r
811 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
812 tmppal[i] = palette[i] - dim;
\r
813 if(tmppal[i] > 127) {
\r
815 } else if(tmppal[i] > 63) {
\r
819 modexPalUpdate(tmppal);
\r
827 void modexPalSave(byte *palette)
\r
831 outp(PAL_READ_REG, 0); // start at palette entry 0
\r
832 for(i=0; i<PAL_SIZE; i++)
\r
834 palette[i] = inp(PAL_DATA_REG); // read the palette data
\r
842 ptr = m a l l o c(PAL_SIZE);
\r
846 printf("Could not allocate palette.\n");
\r
854 modexLoadPalFile(byte *filename, byte *palette) {
\r
858 // free the palette if it exists
\r
859 //if(*palette) { free(*palette); }
\r
861 // allocate the new palette
\r
862 //*palette = modexNewPal();
\r
865 file = fopen(filename, "rb");
\r
867 printf("Could not open palette file: %s\n", filename);
\r
870 /* read the file */
\r
872 while(!feof(file)) {
\r
873 *ptr++ = fgetc(file);
\r
879 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)
\r
881 VL_LoadPalFilewithoffset(filename, palette, 8, gvar);
\r
882 // VL_LoadPalFileCore(palette);
\r
885 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)
\r
887 VL_LoadPalFilewithoffset("data/16.pal", palette, 0, gvar);
\r
890 void VL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, global_game_variables_t *gvar)
\r
894 fd = open(filename,O_RDONLY|O_BINARY);
\r
896 read(fd,palette, PAL_SIZE);
\r
899 VL_UpdatePaletteWrite(palette, o, gvar);
\r
903 void VL_UpdatePaletteWrite(byte *palette, word o, global_game_variables_t *gvar)
\r
906 vga_palette_lseek(/*1+*/o);
\r
907 //for (i=o;i < 256-o;i++)
\r
908 for (i=0;i < 256-o;i++)
\r
909 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);
\r
911 VL_PaletteSync(gvar);
\r
914 void VL_PaletteSync(global_game_variables_t *gvar)
\r
916 modexPalSave(&gvar->video.palette);
\r
920 modexSavePalFile(char *filename, byte *pal) {
\r
924 /* open the file for writing */
\r
925 file = fopen(filename, "wb");
\r
927 printf("Could not open %s for writing\n", filename);
\r
930 /* write the data to the file */
\r
931 fwrite(pal, 1, PAL_SIZE, file);
\r
939 fadePalette(-1, 64, 1, tmppal);
\r
945 fadePalette(-1, -64, 1, tmppal);
\r
950 //moved to 16_vlpal.c
\r
953 modexPalUpdate(byte *p)
\r
956 //modexWaitBorder();
\r
957 vga_wait_for_vsync();
\r
958 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
959 for(i=0; i<PAL_SIZE/2; i++)
\r
961 outp(PAL_DATA_REG, p[i]);
\r
963 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
964 vga_wait_for_vsync();
\r
965 for(; i<PAL_SIZE; i++)
\r
967 outp(PAL_DATA_REG, p[(i)]);
\r
972 //modexPalUpdate0(byte *p)
\r
973 VL_modexPalScramble(byte *p)
\r
976 //modexWaitBorder();
\r
977 vga_wait_for_vsync();
\r
978 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
979 for(i=0; i<PAL_SIZE/2; i++)
\r
981 outp(PAL_DATA_REG, rand());
\r
983 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
984 vga_wait_for_vsync();
\r
985 for(; i<PAL_SIZE; i++)
\r
987 outp(PAL_DATA_REG, rand());
\r
992 modexPalOverscan(word col)
\r
994 //modexWaitBorder();
\r
995 vga_wait_for_vsync();
\r
996 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
997 outp(PAL_DATA_REG, col);
\r
1002 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1004 word pageOff = (word) page->data;
\r
1005 /* Each address accesses four neighboring pixels, so set
\r
1006 Write Plane Enable according to which pixel we want
\r
1007 to modify. The plane is determined by the two least
\r
1008 significant bits of the x-coordinate: */
\r
1009 modexSelectPlane(PLANE(x));
\r
1010 //outp(SC_INDEX, 0x02);
\r
1011 //outp(SC_DATA, 0x01 << (x & 3));
\r
1013 /* The offset of the pixel into the video segment is
\r
1014 offset = (width * y + x) / 4, and write the given
\r
1015 color to the plane we selected above. Heed the active
\r
1016 page start selection. */
\r
1017 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1021 byte modexgetPixel(page_t *page, int x, int y)
\r
1023 word pageOff = (word) page->data;
\r
1024 /* Select the plane from which we must read the pixel color: */
\r
1025 outpw(GC_INDEX, 0x04);
\r
1026 outpw(GC_INDEX+1, x & 3);
\r
1028 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1032 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1034 /* vertical drawing routine by joncampbell123.
\r
1036 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1037 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1039 * 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
1040 word rows = romFonts[t].charSize;
\r
1048 m1 = 0x80; // left half
\r
1049 m2 = 0x08; // right half
\r
1050 for (colm=0;colm < 4;colm++) {
\r
1052 modexSelectPlane(PLANE(plane));
\r
1053 for (row=0;row < rows;row++) {
\r
1054 fontbyte = romFontsData.l[row];
\r
1055 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1056 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1057 drawaddr += page->width >> 2;
\r
1062 if ((++plane) == 4) {
\r
1069 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word col, word bgcol, boolean sw, const byte *str)
\r
1073 //word addr = (word) romFontsData.l;
\r
1081 printf("%s\n", str);
\r
1084 if(tlsw){ x-=page->tlx; y-=page->tly; }
\r
1086 addrq = (page->stridew) * y + (word)(x_draw) +
\r
1087 ((word)page->data);
\r
1089 s=romFonts[t].seg;
\r
1090 o=romFonts[t].off;
\r
1091 w=romFonts[t].charSize;
\r
1092 romFontsData.chw=0;
\r
1094 for(; *str != '\0'; str++)
\r
1100 romFontsData.chw = 0;
\r
1101 addrq += (page->stridew) * 8;
\r
1107 // load the character into romFontsData.l
\r
1108 // no need for inline assembly!
\r
1109 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1110 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1111 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1112 x_draw += 8; /* track X for edge of screen */
\r
1113 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1115 //printf("print xy:%dx%d tlxy:%dx%d\n", x, y, page->tlx, page->tly);
\r
1120 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1122 word i, s, o, w, j, xp;
\r
1124 word addr = (word) l;
\r
1148 s=romFonts[t].seg;
\r
1149 o=romFonts[t].off;
\r
1151 for(; *str != '\0'; str++)
\r
1154 if((c=='\n'/* || c=="\
\r
1155 "*/)/* || chw>=page->width*/)
\r
1161 //load the letter 'A'
\r
1176 MOV AL, c ; the letter
\r
1179 ADD SI, AX ;the address of charcter
\r
1197 for(i=0; i<w; i++)
\r
1203 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1204 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1213 /* palette dump on display! */
\r
1214 void modexpdump(page_t *pee)
\r
1216 int mult=(QUADWH);
\r
1217 int palq=(mult)*TILEWH;
\r
1220 for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){
\r
1221 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){
\r
1222 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1228 /////////////////////////////////////////////////////////////////////////////
\r
1230 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1231 // the Virtual screen. //
\r
1233 /////////////////////////////////////////////////////////////////////////////
\r
1234 void modexcls(page_t *page, byte color, byte *Where)
\r
1236 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1237 /* set map mask to all 4 planes */
\r
1238 outpw(SC_INDEX, 0xff02);
\r
1239 //_fmemset(VGA, color, 16000);
\r
1240 _fmemset(Where, color, page->stridew*page->height);
\r
1244 // pattern filler from joncampbell123's code
\r
1246 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1248 unsigned int i,j,o, d,h,s;
\r
1254 w=vga_state.vga_width;
\r
1256 s=vga_state.vga_stride;
\r
1260 h=vga_state.vga_height;
\r
1268 w=video->page[pn].width;
\r
1269 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1270 s=video->page[pn].stridew;
\r
1274 h=video->page[pn].height;
\r
1277 if(!pn) h=video->vh;
\r
1278 else h=video->page[pn].height;
\r
1284 /* fill screen/pattern with a distinctive pattern */
\r
1285 for (i=0;i < w;i++) {
\r
1287 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1288 for (j=0;j < h;j++,o += s)
\r
1289 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1294 modexWaitBorder() {
\r
1295 while(inp(INPUT_STATUS_1) & 8) {
\r
1299 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1305 modexWaitBorder_start()
\r
1307 while(inp(INPUT_STATUS_1) & 8) {
\r
1314 modexWaitBorder_end()
\r
1316 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1322 //===========================================================================
\r
1325 // printings of video memory information
\r
1327 void VL_PrintmodexmemInfo(video_t *v)
\r
1331 // printf("========================================\n");
\r
1332 printf("VL_PrintmodexmemInfo:\n");
\r
1333 // printf("========================================\n");
\r
1334 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
1335 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
1337 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1339 for(i=0; i<v->num_of_pages;i++)
\r
1341 printf(" [%u]=", i);
\r
1342 printf("(%Fp)", (v->page[i].data));
\r
1343 printf(" size=%u ", v->page[i].pagesize);
\r
1344 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1345 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1346 printf("pi=%u", v->page[i].pi);
\r