From 0dba278956bba7ad53d8b1b14565901d82b09cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Mon, 10 Dec 2007 22:11:13 +0000 Subject: [PATCH] fix some bugs+enhance the s3/xga emulation (hal) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3059 --- include/paging.h | 4 +- include/vga.h | 7 +- src/hardware/memory.cpp | 9 +- src/hardware/vga.cpp | 42 ++- src/hardware/vga_draw.cpp | 111 +++--- src/hardware/vga_memory.cpp | 75 +--- src/hardware/vga_misc.cpp | 4 +- src/hardware/vga_s3.cpp | 74 ++-- src/hardware/vga_xga.cpp | 687 ++++++++++++++++++++++-------------- src/ints/int10_modes.cpp | 130 +++++-- src/ints/int10_vesa.cpp | 69 ++-- 11 files changed, 728 insertions(+), 484 deletions(-) diff --git a/include/paging.h b/include/paging.h index b80a2571..f35c3fcc 100644 --- a/include/paging.h +++ b/include/paging.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: paging.h,v 1.29 2007-11-24 17:26:48 c2woody Exp $ */ +/* $Id: paging.h,v 1.30 2007-12-10 22:11:13 c2woody Exp $ */ #ifndef DOSBOX_PAGING_H #define DOSBOX_PAGING_H @@ -94,7 +94,7 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages); void PAGING_MapPage(Bitu lin_page,Bitu phys_page); bool PAGING_MakePhysPage(Bitu & page); -void MEM_SetLFB( Bitu page, Bitu pages, PageHandler *handler); +void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler); void MEM_SetPageHandler(Bitu phys_page, Bitu pages, PageHandler * handler); void MEM_ResetPageHandler(Bitu phys_page, Bitu pages); diff --git a/include/vga.h b/include/vga.h index 582f9b7b..1d8faf84 100644 --- a/include/vga.h +++ b/include/vga.h @@ -178,12 +178,17 @@ typedef struct { Bit8u reg_lock2; Bit8u reg_31; Bit8u reg_35; + Bit8u reg_3a; // 4/8/doublepixel bit in there Bit8u reg_40; // 8415/A functionality register + Bit8u reg_41; // BIOS flags Bit8u reg_43; Bit8u reg_45; // Hardware graphics cursor - Bit8u reg_58; + Bit8u reg_50; Bit8u reg_51; + Bit8u reg_52; Bit8u reg_55; + Bit8u reg_58; + Bit8u reg_6b; // LFB BIOS scratchpad Bit8u ex_hor_overflow; Bit8u ex_ver_overflow; Bit16u la_window; diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index 99eb482e..afe051d2 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: memory.cpp,v 1.52 2007-09-29 13:23:59 c2woody Exp $ */ +/* $Id: memory.cpp,v 1.53 2007-12-10 22:11:13 c2woody Exp $ */ #include "dosbox.h" #include "mem.h" @@ -48,6 +48,7 @@ static struct MemoryBlock { Bitu end_page; Bitu pages; PageHandler *handler; + PageHandler *mmiohandler; } lfb; struct { bool enabled; @@ -122,8 +123,9 @@ static IllegalPageHandler illegal_page_handler; static RAMPageHandler ram_page_handler; static ROMPageHandler rom_page_handler; -void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler) { +void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler) { memory.lfb.handler=handler; + memory.lfb.mmiohandler=mmiohandler; memory.lfb.start_page=page; memory.lfb.end_page=page+pages; memory.lfb.pages=pages; @@ -135,6 +137,9 @@ PageHandler * MEM_GetPageHandler(Bitu phys_page) { return memory.phandlers[phys_page]; } else if ((phys_page>=memory.lfb.start_page) && (phys_page=memory.lfb.start_page+0x01000000/4096) && + (phys_page> 4) { - case 1:VGA_SetMode(M_LIN8);break; - case 3:VGA_SetMode(M_LIN15);break; - case 5:VGA_SetMode(M_LIN16);break; - case 13:VGA_SetMode(M_LIN32);break; + switch (vga.s3.misc_control_2 >> 4) { + case 0: + if (vga.attr.mode_control & 1) { // graphics mode + if (IS_VGA_ARCH && (vga.gfx.mode & 0x40)) { + // access above 256k? + if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN8); + else VGA_SetMode(M_VGA); + } + else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); + else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); + else { + // access above 256k? + if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN4); + else VGA_SetMode(M_EGA); + } + } else { + VGA_SetMode(M_TEXT); } - /* Test for graphics or alphanumeric mode */ - } else if (vga.attr.mode_control & 1) { - if (IS_VGA_ARCH && (vga.gfx.mode & 0x40)) VGA_SetMode(M_VGA); - else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); - else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); - else { - if (vga.s3.reg_31 & 0x8) - VGA_SetMode(M_LIN4); - else - VGA_SetMode(M_EGA); - } - } else { - VGA_SetMode(M_TEXT); + break; + case 1:VGA_SetMode(M_LIN8);break; + case 3:VGA_SetMode(M_LIN15);break; + case 5:VGA_SetMode(M_LIN16);break; + case 13:VGA_SetMode(M_LIN32);break; } } diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 251cedfb..c78c0625 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_draw.cpp,v 1.88 2007-12-09 17:02:55 c2woody Exp $ */ +/* $Id: vga_draw.cpp,v 1.89 2007-12-10 22:11:13 c2woody Exp $ */ #include #include @@ -207,7 +207,7 @@ static Bit8u * VGA_Draw_Chain_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = vidstart / vga.draw.width; + Bitu lineat = (vidstart-(vga.config.real_start<<2)) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; } else { @@ -267,7 +267,7 @@ static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = (vidstart >> 1) / vga.draw.width; + Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 1) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; } else { @@ -330,7 +330,7 @@ static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = (vidstart >> 2) / vga.draw.width; + Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 2) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { return &vga.mem.linear[ vidstart ]; } else { @@ -379,7 +379,7 @@ static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu line) { TempLine[xat] = ~TempLine[xat]; TempLine[xat+1] = ~TempLine[xat+1]; TempLine[xat+2] = ~TempLine[xat+2]; - TempLine[xat+2] = ~TempLine[xat+3]; + TempLine[xat+3] = ~TempLine[xat+3]; break; } xat+=4; @@ -586,7 +586,7 @@ skip_cursor: static void VGA_VerticalDisplayEnd(Bitu val) { // vga.config.retrace=true; - vga.config.real_start=vga.config.display_start & ((2*1024*1024)-1); + vga.config.real_start=vga.config.display_start & ((VGA_MEMORY)-1); } static void VGA_HorizontalTimer(void) { @@ -909,53 +909,60 @@ void VGA_SetupDrawing(Bitu val) { Bitu htotal, hdend, hbstart, hbend, hrstart, hrend; Bitu vtotal, vdend, vbstart, vbend, vrstart, vrend; if (IS_EGAVGA_ARCH) { - htotal = 2 + vga.crtc.horizontal_total; - if (IS_VGA_ARCH) htotal += 3; - hdend = 1 + vga.crtc.horizontal_display_end; - hbstart = vga.crtc.start_horizontal_blanking; + htotal = vga.crtc.horizontal_total; + hdend = vga.crtc.horizontal_display_end; hbend = vga.crtc.end_horizontal_blanking&0x1F; - if (IS_VGA_ARCH) hbend |= (vga.crtc.end_horizontal_retrace&0x80)>>2; - hbend = hbstart + ((hbend - hbstart) & 0x3F); + hbstart = vga.crtc.start_horizontal_blanking; hrstart = vga.crtc.start_horizontal_retrace; - hrend = vga.crtc.end_horizontal_retrace & 0x1f; - hrend = (hrend - hrstart) & 0x1f; - if ( !hrend ) - hrend = hrstart + 0x1f + 1; - else - hrend = hrstart + hrend; - vtotal= 2 + vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8); - vdend = 1 + vga.crtc.vertical_display_end | ((vga.crtc.overflow & 2)<<7); + vtotal= vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8); + vdend = vga.crtc.vertical_display_end | ((vga.crtc.overflow & 2)<<7); + vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5); vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6); + if (IS_VGA_ARCH) { // additional bits only present on vga cards + htotal |= (vga.s3.ex_hor_overflow & 0x1) << 8; + htotal += 3; + hdend |= (vga.s3.ex_hor_overflow & 0x2) << 7; + hbend |= (vga.crtc.end_horizontal_retrace&0x80) >> 2; + hbstart |= (vga.s3.ex_hor_overflow & 0x4) << 6; + hrstart |= (vga.s3.ex_hor_overflow & 0x10) << 4; + vtotal |= (vga.crtc.overflow & 0x20) << 4; - vdend |= ((vga.crtc.overflow & 0x40) << 3) | - ((vga.s3.ex_ver_overflow & 0x2) << 9); + vtotal |= (vga.s3.ex_ver_overflow & 0x1) << 10; + vdend |= (vga.crtc.overflow & 0x40) << 3; + vdend |= (vga.s3.ex_ver_overflow & 0x2) << 9; + vbstart |= (vga.crtc.maximum_scan_line & 0x20) << 4; + vbstart |= (vga.s3.ex_ver_overflow & 0x4) << 8; vrstart |= ((vga.crtc.overflow & 0x80) << 2); - } - - vrend = vga.crtc.vertical_retrace_end & 0xF; - vrend = ( vrend - vrstart)&0xF; - if ( !vrend) - vrend = vrstart + 0xf + 1; - else - vrend = vrstart + vrend; - - vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5); - if (IS_VGA_ARCH) { - vbstart |= ((vga.crtc.maximum_scan_line & 0x20) << 4); + vrstart |= (vga.s3.ex_ver_overflow & 0x10) << 6; vbend = vga.crtc.end_vertical_blanking & 0x3f; } else { vbend = vga.crtc.end_vertical_blanking & 0xf; } - vbend = (vbend - vbstart) & 0x3f; - if ( !vbend) - vbend = vbstart + 0x3f + 1; - else - vbend = vbstart + vbend; - + htotal += 2; + vtotal += 2; + hdend += 1; + vdend += 1; + hbend = hbstart + ((hbend - hbstart) & 0x3F); + hrend = vga.crtc.end_horizontal_retrace & 0x1f; + hrend = (hrend - hrstart) & 0x1f; + + if ( !hrend ) hrend = hrstart + 0x1f + 1; + else hrend = hrstart + hrend; + + vrend = vga.crtc.vertical_retrace_end & 0xF; + vrend = ( vrend - vrstart)&0xF; + + if ( !vrend) vrend = vrstart + 0xf + 1; + else vrend = vrstart + vrend; + + vbend = (vbend - vbstart) & 0x3f; + if ( !vbend) vbend = vbstart + 0x3f + 1; + else vbend = vbstart + vbend; + switch (svgaCard) { case SVGA_S3Trio: clock = SVGA_S3_GetClock(); @@ -1141,14 +1148,22 @@ void VGA_SetupDrawing(Bitu val) { } else VGA_DrawLine = VGA_Draw_Linear_Line; break; case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - width<<=3; - if (vga.crtc.mode_control & 0x8) { - doublewidth = true; - width >>= 1; + if (vga.crtc.mode_control & 0x8) + width >>=1; + else if(!(vga.s3.reg_3a&0x10)) { + doublewidth=true; + width >>=1; } + // fall-through + case M_LIN32: + width<<=1; + // fall-through + case M_LIN15: + case M_LIN16: + // 15/16 bpp modes double the horizontal values + width<<=2; + if (vga.crtc.mode_control & 0x8) + doublewidth = true; /* Use HW mouse cursor drawer if enabled */ VGA_ActivateHardwareCursor(); break; @@ -1194,7 +1209,7 @@ void VGA_SetupDrawing(Bitu val) { aspect_ratio=1.0; vga.draw.blocks=width; doublewidth=(vga.seq.clocking_mode & 0x8) > 0; - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None) && (vga.seq.clocking_mode&0x01)) { + if ((IS_VGA_ARCH) && (svgaCard==SVGA_None) && !(vga.seq.clocking_mode&0x01)) { width*=9; /* 9 bit wide text font */ VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line_9; bpp=16; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 71905f75..00f9fe98 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_memory.cpp,v 1.44 2007-10-20 16:01:40 c2woody Exp $ */ +/* $Id: vga_memory.cpp,v 1.45 2007-12-10 22:11:13 c2woody Exp $ */ #include #include @@ -574,81 +574,39 @@ public: } }; +extern void XGA_Write(Bitu port, Bitu val, Bitu len); +extern Bitu XGA_Read(Bitu port, Bitu len); + class VGA_MMIO_Handler : public PageHandler { public: - Bit16u regmem[16384]; VGA_MMIO_Handler() { flags=PFLAG_NOCODE; - //memset(®mem[0], 0, sizeof(regmem)); } void writeb(PhysPt addr,Bitu val) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) IO_WriteB(port, val); - if(port <= 0x4000) { - if(port == 0x0000) { - IO_WriteB(0xe2e0, val); - } else { - IO_WriteB(0xe2e8, val); - } - } - //LOG_MSG("MMIO: Write byte to %x with %x", addr, val); + XGA_Write(port, val, 1); } void writew(PhysPt addr,Bitu val) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) IO_WriteW(port, val); - if(port == 0x8118) IO_WriteW(0x9ae8, val); - if(port <= 0x4000) { - if(port == 0x0000) { - IO_WriteW(0xe2e0, val); - } else { - IO_WriteW(0xe2e8, val); - } - } - //LOG_MSG("MMIO: Write word to %x with %x", addr, val); + XGA_Write(port, val, 2); } void writed(PhysPt addr,Bitu val) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) IO_WriteD(port, val); - if(port == 0x8100) { - IO_WriteW(0x86e8, (val >> 16)); - IO_WriteW(0x82e8, (val & 0xffff)); - } - if(port == 0x8148) { - IO_WriteW(0x96e8, (val >> 16)); - IO_WriteW(0xbee8, (val & 0xffff)); - } - if(port <= 0x4000) { - if(port == 0x0000) { - IO_WriteW(0xe2e0, (val & 0xffff)); - IO_WriteW(0xe2e8, (val >> 16)); - } else { - IO_WriteW(0xe2e8, (val & 0xffff)); - IO_WriteW(0xe2e8, (val >> 16)); - } - } - - //LOG_MSG("MMIO: Write dword to %x with %x", addr, val); + XGA_Write(port, val, 4); } Bitu readb(PhysPt addr) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) return IO_ReadB(port); - //LOG_MSG("MMIO: Read byte from %x", addr); - return 0x00; + return XGA_Read(port, 1); } Bitu readw(PhysPt addr) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) return IO_ReadW(port); - //LOG_MSG("MMIO: Read word from %x", addr); - return 0x00; + return XGA_Read(port, 2); } Bitu readd(PhysPt addr) { Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - if(port >= 0x82E8) return IO_ReadD(port); - //LOG_MSG("MMIO: Read dword from %x", addr); - return 0x00; + return XGA_Read(port, 4); } - }; class VGA_TANDY_PageHandler : public PageHandler { @@ -845,7 +803,7 @@ void VGA_SetupHandlers(void) { MEM_ResetPageHandler( VGA_PAGE_B0, 8 ); break; } - if(((vga.s3.ext_mem_ctrl & 0x10) != 0x00) /*&& (vga.mode == M_LIN8)*/) + if(vga.s3.ext_mem_ctrl & 0x10) MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); range_done: PAGING_ClearTLB(); @@ -859,18 +817,9 @@ void VGA_StartUpdateLFB(void) { #else vga.lfb.handler = &vgaph.lfbchanges; #endif - MEM_SetLFB(vga.s3.la_window << 4 ,VGA_MEMORY/4096, vga.lfb.handler ); + MEM_SetLFB(vga.s3.la_window << 4 ,VGA_MEMORY/4096, vga.lfb.handler, &vgaph.mmio); } -void VGA_MapMMIO(void) { - MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); -} - -void VGA_UnmapMMIO(void) { - //MEM_SetPageHandler(VGA_PAGE_A0, &ram_page_handler); -} - - void VGA_SetupMemory() { // allocate 16byte-aligned memory vga.mem.linear = new Bit8u[VGA_MEMORY+16]; diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index d3638c37..f20bbdcb 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_misc.cpp,v 1.35 2007-10-13 16:34:06 c2woody Exp $ */ +/* $Id: vga_misc.cpp,v 1.36 2007-12-10 22:11:13 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -30,7 +30,7 @@ Bitu vga_read_p3d4(Bitu port,Bitu iolen); void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen); Bitu vga_read_p3d5(Bitu port,Bitu iolen); -static Bitu vga_read_p3da(Bitu port,Bitu iolen) { +Bitu vga_read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; vga.tandy.pcjr_flipflop=false; Bit8u retval=0; diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp index a48ab1c4..5c718456 100644 --- a/src/hardware/vga_s3.cpp +++ b/src/hardware/vga_s3.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_s3.cpp,v 1.8 2007-06-28 16:02:27 c2woody Exp $ */ +/* $Id: vga_s3.cpp,v 1.9 2007-12-10 22:11:13 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -70,9 +70,15 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { case 0x39: /* CR39 Register Lock 2 */ vga.s3.reg_lock2=val; break; + case 0x3a: + vga.s3.reg_3a = val; + break; case 0x40: /* CR40 System Config */ vga.s3.reg_40 = val; break; + case 0x41: /* CR41 BIOS flags */ + vga.s3.reg_41 = val; + break; case 0x43: /* CR43 Extended Mode */ vga.s3.reg_43=val & ~0x4; if (((val & 0x4) ^ (vga.config.scan_len >> 6)) & 0x4) { @@ -114,17 +120,22 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { vga.s3.hgc.bstackpos++; break; case 0x4c: /* HGC start address high byte*/ - vga.s3.hgc.startaddr = vga.s3.hgc.startaddr | ((val & 0xff) << 8); + vga.s3.hgc.startaddr &=0xff; + vga.s3.hgc.startaddr |= ((val & 0xf) << 8); break; case 0x4d: /* HGC start address low byte*/ - vga.s3.hgc.startaddr = vga.s3.hgc.startaddr | (val & 0xff); + vga.s3.hgc.startaddr &=0xff00; + vga.s3.hgc.startaddr |= (val & 0xff); break; case 0x4e: /* HGC pattern start X */ vga.s3.hgc.posx = val; break; - case 0x4f: /* HGC pattern start X */ + case 0x4f: /* HGC pattern start Y */ vga.s3.hgc.posy = val; break; + case 0x50: // Extended System Control 1 + vga.s3.reg_50 = val; + break; case 0x51: /* Extended System Control 2 */ vga.s3.reg_51=val & 0xc0; //Only store bits 6,7 //TODO Display start @@ -161,17 +172,17 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { 7 (not 864/964) Enable EPROM Write. If set enables flash memory write control to the BIOS ROM address */ + case 0x52: // Extended System Control 1 + vga.s3.reg_52 = val; + break; case 0x53: - if((val & 0x10) != (vga.s3.ext_mem_ctrl & 0x10)) { - /* Map or unmap MMIO */ - if ((val & 0x10) != 0) { - //LOG_MSG("VGA: Mapping Memory Mapped I/O to 0xA0000"); -// VGA_MapMMIO(); - } else { -// VGA_UnmapMMIO(); - } + // Map or unmap MMIO + // bit 4 = MMIO at A0000 + // bit 3 = MMIO at LFB + 16M (should be fine if its always enabled for now) + if(vga.s3.ext_mem_ctrl!=val) { + vga.s3.ext_mem_ctrl = val; + VGA_SetupHandlers(); } - vga.s3.ext_mem_ctrl = val; break; case 0x55: /* Extended Video DAC Control */ vga.s3.reg_55=val; @@ -302,6 +313,9 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { vga.s3.svga_bank.b.bank=val & 0x3f; VGA_SetupHandlers(); break; + case 0x6b: // BIOS scratchpad: LFB adress + vga.s3.reg_6b=(Bit8u)val; + break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC:Write to illegal index %2X", reg ); break; @@ -317,38 +331,56 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { return 0x11; //Trio 64 id case 0x2f: /* Revision */ - return 0x00; + return 0x44; case 0x30: /* CR30 Chip ID/REV register */ - return 0xe0; //Trio+ dual byte - // Trio32/64 has 0xe0. extended + return 0xe1; //Trio+ dual byte + //return 0xc0; // 864 + case 0x31: /* CR31 Memory Configuration */ //TODO mix in bits from baseaddress; return vga.s3.reg_31; case 0x35: /* CR35 CRT Register Lock */ return vga.s3.reg_35|(vga.s3.svga_bank.b.bank & 0xf); case 0x36: /* CR36 Reset State Read 1 */ - //return 0x8f; - return 0x8e; /* PCI version */ + return 0x92; /* PCI version */ //2 Mb PCI and some bios settings case 0x37: /* Reset state read 2 */ return 0x2b; case 0x38: /* CR38 Register Lock 1 */ return vga.s3.reg_lock1; case 0x39: /* CR39 Register Lock 2 */ - return vga.s3.reg_lock2; + return vga.s3.reg_lock2; + case 0x3a: + return vga.s3.reg_3a; case 0x40: /* CR40 system config */ return vga.s3.reg_40; + case 0x41: /* CR40 system config */ + return vga.s3.reg_41; + case 0x42: // not interlaced + return 0x0d; case 0x43: /* CR43 Extended Mode */ return vga.s3.reg_43|((vga.config.scan_len>>6)&0x4); case 0x45: /* Hardware cursor mode */ vga.s3.hgc.bstackpos = 0; vga.s3.hgc.fstackpos = 0; - return vga.s3.hgc.curmode; + return vga.s3.hgc.curmode|0xa0; + case 0x46: + return vga.s3.hgc.originx>>8; + case 0x47: /* HGC orgX */ + return vga.s3.hgc.originx&0xff; + case 0x48: + return vga.s3.hgc.originy>>8; + case 0x49: /* HGC orgY */ + return vga.s3.hgc.originy&0xff; + case 0x50: // CR50 Extended System Control 1 + return vga.s3.reg_50; case 0x51: /* Extended System Control 2 */ return ((vga.config.display_start >> 16) & 3 ) | ((vga.s3.svga_bank.b.bank & 0x30) >> 2) | ((vga.config.scan_len & 0x300) >> 4) | vga.s3.reg_51; + case 0x52: // CR52 Extended BIOS flags 1 + return vga.s3.reg_52; case 0x53: return vga.s3.ext_mem_ctrl; case 0x55: /* Extended Video DAC Control */ @@ -369,6 +401,8 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { return (Bit8u)((vga.config.display_start & 0x1f0000)>>16); case 0x6a: /* Extended System Control 4 */ return (Bit8u)(vga.s3.svga_bank.b.bank & 0x3f); + case 0x6b: // BIOS scatchpad: LFB address + return vga.s3.reg_6b; default: return 0x00; } diff --git a/src/hardware/vga_xga.cpp b/src/hardware/vga_xga.cpp index e8557970..4054be5f 100644 --- a/src/hardware/vga_xga.cpp +++ b/src/hardware/vga_xga.cpp @@ -16,12 +16,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: vga_xga.cpp,v 1.10 2007-12-10 22:11:13 c2woody Exp $ */ + #include #include "dosbox.h" #include "inout.h" #include "vga.h" #include #include +#include "callback.h" +#include "cpu.h" // for 0x3da delay #define XGA_SCREEN_WIDTH vga.draw.width @@ -63,6 +67,7 @@ struct XGAStatus { Bit16u x1, y1, x2, y2, sizex, sizey; Bit32u data; /* transient data passed by multiple calls */ Bitu datasize; + Bitu buswidth; } waitcmd; } xga; @@ -71,25 +76,25 @@ void XGA_Write_Multifunc(Bitu val, Bitu len) { Bitu regselect = val >> 12; Bitu dataval = val & 0xfff; switch(regselect) { - case 0: + case 0: // minor axis pixel count xga.MIPcount = dataval; break; - case 1: + case 1: // top scissors xga.scissors.y1 = dataval; break; - case 2: + case 2: // left xga.scissors.x1 = dataval; break; - case 3: + case 3: // bottom xga.scissors.y2 = dataval; break; - case 4: + case 4: // right xga.scissors.x2 = dataval; break; - case 0xa: + case 0xa: // data manip control xga.pix_cntl = dataval; break; - case 0xd: + case 0xd: // misc 2 xga.control2 = dataval; break; case 0xe: @@ -104,8 +109,7 @@ void XGA_Write_Multifunc(Bitu val, Bitu len) { } } -Bitu XGA_Read_Multifunc() -{ +Bitu XGA_Read_Multifunc() { switch(xga.read_sel++) { case 0: return xga.MIPcount; case 1: return xga.scissors.y1; @@ -124,7 +128,6 @@ Bitu XGA_Read_Multifunc() void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) { - if(!(xga.curcommand & 0x1)) return; if(!(xga.curcommand & 0x10)) return; @@ -139,18 +142,24 @@ void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) { during windows dragging. */ switch(vga.mode) { case M_LIN8: vga.mem.linear[memaddr] = c; break; - case M_LIN15: ((Bit16u*)(vga.mem.linear))[memaddr] = c&0x7fff; break; - case M_LIN16: ((Bit16u*)(vga.mem.linear))[memaddr] = c; break; - case M_LIN32: ((Bit32u*)(vga.mem.linear))[memaddr] = c&0x00ffffff; break; + case M_LIN15: ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0x7fff); break; + case M_LIN16: ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0xffff); break; + case M_LIN32: ((Bit32u*)(vga.mem.linear))[memaddr] = c; } } Bitu XGA_GetPoint(Bitu x, Bitu y) { Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x; + + if(VGA_MEMORY < memaddr) { + //LOG_MSG("getpoint mem over: x%d y%d",x,y); + return 0; + } switch(vga.mode) { case M_LIN8: return vga.mem.linear[memaddr]; - case M_LIN15: case M_LIN16: return ((Bit16u*)(vga.mem.linear))[memaddr]; + case M_LIN15: + case M_LIN16: return ((Bit16u*)(vga.mem.linear))[memaddr]; case M_LIN32: return ((Bit32u*)(vga.mem.linear))[memaddr]; } return 0; @@ -213,7 +222,6 @@ Bitu XGA_GetMixResult(Bitu mixmode, Bitu srcval, Bitu dstdata) { break; } return destval; - } void XGA_DrawLineVector(Bitu val) { @@ -268,8 +276,6 @@ void XGA_DrawLineVector(Bitu val) { break; } - //for(yat=y1;yat<=y2;yat++) { - // for(xat=x1;xat<=x2;xat++) { for (i=0;i<=dx;i++) { Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; switch (mixmode) { @@ -284,7 +290,7 @@ void XGA_DrawLineVector(Bitu val) { break; case 0x02: /* Src is pixel data from PIX_TRANS register */ //srcval = tmpval; - LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register"); + //LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register"); break; case 0x03: /* Src is bitmap data */ LOG_MSG("XGA: DrawRect: Wants data from srcdata"); @@ -310,9 +316,6 @@ void XGA_DrawLineVector(Bitu val) { xga.curx = xat-1; xga.cury = yat; - // } - //} - } void XGA_DrawLineBresenham(Bitu val) { @@ -326,12 +329,19 @@ void XGA_DrawLineBresenham(Bitu val) { #define SWAP(a,b) tmpswap = a; a = b; b = tmpswap; - Bits dx, sx, dy, sy, e, dmajor, dminor; + Bits dx, sx, dy, sy, e, dmajor, dminor,destxtmp; // Probably a lot easier way to do this, but this works. - dminor = (Bits)((Bit16s)xga.desty) >> 1; - dmajor = -((Bits)((Bit16s)xga.destx) - (dminor << 1)) >> 1; + dminor = (Bits)((Bit16s)xga.desty); + if(xga.desty&0x2000) dminor |= 0xffffe000; + dminor >>= 1; + + destxtmp=(Bits)((Bit16s)xga.destx); + if(xga.destx&0x2000) destxtmp |= 0xffffe000; + + + dmajor = -(destxtmp - (dminor << 1)) >> 1; dx = dmajor; if((val >> 5) & 0x1) { @@ -346,6 +356,7 @@ void XGA_DrawLineBresenham(Bitu val) { sy = -1; } e = (Bits)((Bit16s)xga.ErrTerm); + if(xga.ErrTerm&0x2000) e |= 0xffffe000; xat = xga.curx; yat = xga.cury; @@ -357,10 +368,8 @@ void XGA_DrawLineBresenham(Bitu val) { steep = true; } - //LOG_MSG("XGA: Bresenham: ASC %d, LPDSC %d, sx %d, sy %d, err %d, steep %d, length %d, dmajor %d, dminor %d", dx, dy, sx, sy, e, steep, xga.MAPcount, dmajor, dminor); + //LOG_MSG("XGA: Bresenham: ASC %d, LPDSC %d, sx %d, sy %d, err %d, steep %d, length %d, dmajor %d, dminor %d, xstart %d, ystart %d", dx, dy, sx, sy, e, steep, xga.MAPcount, dmajor, dminor,xat,yat); - //for(yat=y1;yat<=y2;yat++) { - // for(xat=x1;xat<=x2;xat++) { for (i=0;i<=xga.MAPcount;i++) { Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; switch (mixmode) { @@ -405,7 +414,7 @@ void XGA_DrawLineBresenham(Bitu val) { LOG_MSG("XGA: DrawLine: Needs mixmode %x", mixmode); break; } - while (e >= 0) { + while (e > 0) { yat += sy; e -= (dx << 1); } @@ -476,7 +485,7 @@ void XGA_DrawRectangle(Bitu val) { default: LOG_MSG("XGA: DrawRect: Needs mixmode %x", mixmode); break; - } + } srcx += dx; } srcy += dy; @@ -490,192 +499,206 @@ void XGA_DrawRectangle(Bitu val) { bool XGA_CheckX(void) { bool newline = false; if(!xga.waitcmd.newline) { - if(xga.waitcmd.curx > xga.waitcmd.x2) { + + if((xga.waitcmd.curx<2048) && xga.waitcmd.curx > (xga.waitcmd.x2)) { xga.waitcmd.curx = xga.waitcmd.x1; xga.waitcmd.cury++; + xga.waitcmd.cury&=0x0fff; newline = true; xga.waitcmd.newline = true; - if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false; - } + if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) + xga.waitcmd.wait = false; + } else if(xga.waitcmd.curx>=2048) { + Bit16u realx = 4096-xga.waitcmd.curx; + if(xga.waitcmd.x2>2047) { // x end is negative too + Bit16u realxend=4096-xga.waitcmd.x2; + if(realx==realxend) { + xga.waitcmd.curx = xga.waitcmd.x1; + xga.waitcmd.cury++; + xga.waitcmd.cury&=0x0fff; + newline = true; + xga.waitcmd.newline = true; + if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) + xga.waitcmd.wait = false; + } + } else { // else overlapping + if(realx==xga.waitcmd.x2) { + xga.waitcmd.curx = xga.waitcmd.x1; + xga.waitcmd.cury++; + xga.waitcmd.cury&=0x0fff; + newline = true; + xga.waitcmd.newline = true; + if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) + xga.waitcmd.wait = false; + } + } + } } else { xga.waitcmd.newline = false; } return newline; } +void XGA_DrawWaitSub(Bitu mixmode, Bitu srcval) { + Bitu destval; + Bitu dstdata; + dstdata = XGA_GetPoint(xga.waitcmd.curx, xga.waitcmd.cury); + destval = XGA_GetMixResult(mixmode, srcval, dstdata); + //LOG_MSG("XGA: DrawPattern: Mixmode: %x srcval: %x", mixmode, srcval); + + XGA_DrawPoint(xga.waitcmd.curx, xga.waitcmd.cury, destval); + xga.waitcmd.curx++; + xga.waitcmd.curx&=0x0fff; + XGA_CheckX(); +} void XGA_DrawWait(Bitu val, Bitu len) { if(!xga.waitcmd.wait) return; - - //if(!(xga.curcommand & 0x2)) return; - Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; Bitu srcval; - Bitu destval; - Bitu dstdata; - //Bitu tmpval; - Bits bitneed; - switch(xga.waitcmd.cmd) { case 2: /* Rectangle */ switch(mixmode) { case 0x00: /* FOREMIX always used */ mixmode = xga.foremix; - Bitu t; - for(t=0;t> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - /* This register is 16 bit. In theory, it is possible to access it as 8-bit - or 32-bit but all calls from Win3 drivers are 16-bit. 8-bit color modes - would work regardless of the access size (although something else in this - function may break), other color modes may require more complex code to - collect transient data or break incoming data in chunks. */ - if(vga.mode == M_LIN8) - srcval = (val >> (8 * t)) & 0xff; - else if(vga.mode == M_LIN32) { /* May need transient data */ - if(xga.waitcmd.datasize == 0) { - xga.waitcmd.data = val; - xga.waitcmd.datasize = 2; - return; - } else { - srcval = (val<<16)|xga.waitcmd.data; - xga.waitcmd.data = 0; - xga.waitcmd.datasize = 0; - t = len; /* All data used */ - } + +/* switch((mixmode >> 5) & 0x03) { + case 0x00: // Src is background color + srcval = xga.backcolor; + break; + case 0x01: // Src is foreground color + srcval = xga.forecolor; + break; + case 0x02: // Src is pixel data from PIX_TRANS register +*/ + if(((mixmode >> 5) & 0x03) != 0x2) { + // those cases don't seem to occur + LOG_MSG("XGA: unsupported drawwait operation"); + break; + } + switch(xga.waitcmd.buswidth) { + case M_LIN8: // 8 bit + XGA_DrawWaitSub(mixmode, val); + break; + case 0x20 | M_LIN8: // 16 bit + XGA_DrawWaitSub(mixmode, val); + if(!xga.waitcmd.newline) + XGA_DrawWaitSub(mixmode, val>>8); + break; + case 0x40 | M_LIN8: // 32 bit + for(int i = 0; i < 4; i++) + XGA_DrawWaitSub(mixmode, (val>>(8*i))&0xff); + break; + case (0x20 | M_LIN32): + if(len!=4) { // Win 3.11 864 'hack?' + if(xga.waitcmd.datasize == 0) { + // set it up to wait for the next word + xga.waitcmd.data = val; + xga.waitcmd.datasize = 2; + return; + } else { + srcval = (val<<16)|xga.waitcmd.data; + xga.waitcmd.data = 0; + xga.waitcmd.datasize = 0; + XGA_DrawWaitSub(mixmode, srcval); } - else { - srcval = val; - t = len; /* All data used */ - } - //LOG_MSG("XGA: DrawBlitWait: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - LOG_MSG("XGA: DrawBlitWait: Wants data from srcdata"); - //srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawBlitWait: Shouldn't be able to get here!"); - break; - } - - - - dstdata = XGA_GetPoint(xga.waitcmd.curx, xga.waitcmd.cury); - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - //LOG_MSG("XGA: DrawPattern: Mixmode: %x srcval: %x", mixmode, srcval); - - XGA_DrawPoint(xga.waitcmd.curx++, xga.waitcmd.cury, destval); - - XGA_CheckX(); - if(xga.waitcmd.newline) break; - } + break; + } // fall-through + case 0x40 | M_LIN32: // 32 bit + XGA_DrawWaitSub(mixmode, val); + break; + case 0x20 | M_LIN15: // 16 bit + case 0x20 | M_LIN16: // 16 bit + XGA_DrawWaitSub(mixmode, val); + break; + case 0x40 | M_LIN15: // 32 bit + case 0x40 | M_LIN16: // 32 bit + XGA_DrawWaitSub(mixmode, val&0xffff); + if(!xga.waitcmd.newline) + XGA_DrawWaitSub(mixmode, val>>16); + break; + default: + // Let's hope they never show up ;) + LOG_MSG("XGA: unsupported bpp / datawidth combination %x", + xga.waitcmd.buswidth); + break; + }; break; - case 0x02: /* Data from PIX_TRANS selects the mix */ - Bitu bitcount; - int i; - switch(len) { - case 1: - bitcount = 8; - break; - case 2: - bitcount = 16; - val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); - break; - case 4: - bitcount = 32; - break; - } - - - bitneed = ((Bits)xga.waitcmd.x2 - (Bits)xga.waitcmd.curx) ; - //xga.waitcmd.curx = xga.waitcmd.x1; - xga.waitcmd.newline = false; - - - i = bitcount -1 ; - //bitneed = i; - - for(;bitneed>=0;--bitneed) { - //for(;i>=0;--i) { - Bitu bitval = (val >> i) & 0x1; - //Bitu bitval = (val >> bitneed) & 0x1; - - //XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, i); - Bitu mixmode = 0x67; - - if(bitval) { - mixmode = xga.foremix; - } else { - mixmode = xga.backmix; - } - - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - LOG_MSG("XGA: DrawBlitWait: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - LOG_MSG("XGA: DrawBlitWait: Wants data from srcdata"); - //srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawBlitWait: Shouldn't be able to get here!"); - break; - } - - Bitu dstdata = XGA_GetPoint(xga.waitcmd.curx, xga.waitcmd.cury); - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - XGA_DrawPoint(xga.waitcmd.curx, xga.waitcmd.cury, destval); - - --i; - if(i < 0) break; - //--bitneed; - //if(bitneed < 0) break; - - xga.waitcmd.curx++; - XGA_CheckX(); - if(xga.waitcmd.newline) break; - } - //xga.waitcmd.cury++; - - if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false; + case 0x02: // Data from PIX_TRANS selects the mix + Bitu chunksize; + Bitu chunks; + switch(xga.waitcmd.buswidth&0x60) { + case 0x0: + chunksize=8; + chunks=1; + break; + case 0x20: // 16 bit + chunksize=16; + if(len==4) chunks=2; + else chunks = 1; + break; + case 0x40: // 32 bit + chunksize=16; + if(len==4) chunks=2; + else chunks = 1; + break; + case 0x60: // undocumented guess (but works) + chunksize=8; + chunks=4; + break; + } + + for(Bitu k = 0; k < chunks; k++) { // chunks counter + xga.waitcmd.newline = false; + for(Bitu n = 0; n < chunksize; n++) { // pixels + Bitu mixmode; + + // This formula can rule the world ;) + Bitu mask = 1 << ((((n&0xF8)+(8-(n&0x7)))-1)+chunksize*k); + if(val&mask) mixmode = xga.foremix; + else mixmode = xga.backmix; + + switch((mixmode >> 5) & 0x03) { + case 0x00: // Src is background color + srcval = xga.backcolor; + break; + case 0x01: // Src is foreground color + srcval = xga.forecolor; + break; + default: + LOG_MSG("XGA: DrawBlitWait: Unsupported src %x", + (mixmode >> 5) & 0x03); + srcval=0; + break; + } + XGA_DrawWaitSub(mixmode, srcval); + + if((xga.waitcmd.cury<2048) && + (xga.waitcmd.cury >= xga.waitcmd.y2)) { + xga.waitcmd.wait = false; + k=1000; // no more chunks + break; + } + // next chunk goes to next line + if(xga.waitcmd.newline) break; + } // pixels loop + } // chunks loop break; + default: LOG_MSG("XGA: DrawBlitWait: Unhandled mixmode: %d", mixmode); break; - } + } // switch mixmode break; default: LOG_MSG("XGA: Unhandled draw command %x", xga.waitcmd.cmd); break; } - } void XGA_BlitRect(Bitu val) { Bit32u xat, yat; -// Bit32u xmass, xmod, xdist, memrec; - //Bit8u *srcptr; - //Bit8u *destptr; - //Bit8u *destline; - //Bit8u *srcline; Bitu srcdata; Bitu dstdata; @@ -683,28 +706,18 @@ void XGA_BlitRect(Bitu val) { Bitu destval; Bits srcx, srcy, tarx, tary, dx, dy; - //bool incx = false; - //bool incy = false; dx = -1; dy = -1; - //if(((val >> 5) & 0x01) != 0) incx = true; - //if(((val >> 7) & 0x01) != 0) incy = true; - if(((val >> 5) & 0x01) != 0) dx = 1; if(((val >> 7) & 0x01) != 0) dy = 1; - //Bit32u srcaddr = (xga.cury * (Bit32u)XGA_SCREEN_WIDTH) + xga.curx; - //Bit32u destaddr = (xga.desty * (Bit32u)XGA_SCREEN_WIDTH) + xga.destx; srcx = xga.curx; srcy = xga.cury; tarx = xga.destx; tary = xga.desty; - //srcptr = &vga.mem.linear[srcaddr]; - //destptr = &vga.mem.linear[destaddr]; - Bitu mixselect = (xga.pix_cntl >> 6) & 0x3; Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */ switch(mixselect) { @@ -718,7 +731,7 @@ void XGA_BlitRect(Bitu val) { //LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix); break; default: - LOG_MSG("XGA: DrawPattern: Unknown mix select register"); + LOG_MSG("XGA: BlitRect: Unknown mix select register"); break; } @@ -733,17 +746,17 @@ void XGA_BlitRect(Bitu val) { dstdata = XGA_GetPoint(tarx, tary); if(mixselect == 0x3) { - if(srcdata == xga.forecolor) { - mixmode = xga.foremix; + if(srcdata == xga.forecolor) { + mixmode = xga.foremix; + } else { + if(srcdata == xga.backcolor) { + mixmode = xga.backmix; } else { - if(srcdata == xga.backcolor) { - mixmode = xga.backmix; - } else { - /* Best guess otherwise */ - mixmode = 0x67; /* Source is bitmap data, mix mode is src */ + /* Best guess otherwise */ + mixmode = 0x67; /* Source is bitmap data, mix mode is src */ + } + } } - } - } switch((mixmode >> 5) & 0x03) { case 0x00: /* Src is background color */ @@ -761,13 +774,11 @@ void XGA_BlitRect(Bitu val) { default: LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!"); break; - } + } destval = XGA_GetMixResult(mixmode, srcval, dstdata); - //LOG_MSG("XGA: DrawPattern: Mixmode: %x Mixselect: %x", mixmode, mixselect); - //*smallptr++ = destval; XGA_DrawPoint(tarx, tary, destval); srcx += dx; @@ -776,7 +787,6 @@ void XGA_BlitRect(Bitu val) { srcy += dy; tary += dy; } - } void XGA_DrawPattern(Bitu val) { @@ -799,17 +809,17 @@ void XGA_DrawPattern(Bitu val) { tary = xga.desty; - Bitu mixselect = (xga.pix_cntl >> 6) & 0x3; - Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */ - switch(mixselect) { - case 0x00: /* Foreground mix is always used */ - mixmode = xga.foremix; - break; - case 0x02: /* CPU Data determines mix used */ - LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register"); - break; - case 0x03: /* Video memory determines mix */ - //LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix); + Bitu mixselect = (xga.pix_cntl >> 6) & 0x3; + Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */ + switch(mixselect) { + case 0x00: /* Foreground mix is always used */ + mixmode = xga.foremix; + break; + case 0x02: /* CPU Data determines mix used */ + LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register"); + break; + case 0x03: /* Video memory determines mix */ + //LOG_MSG("XGA: Pixctl: %x, Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x",xga.pix_cntl, srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix); break; default: LOG_MSG("XGA: DrawPattern: Unknown mix select register"); @@ -821,20 +831,16 @@ void XGA_DrawPattern(Bitu val) { for(xat=0;xat<=xga.MAPcount;xat++) { srcdata = XGA_GetPoint(srcx + (tarx & 0x7), srcy + (tary & 0x7)); + //LOG_MSG("patternpoint (%3d/%3d)v%x",srcx + (tarx & 0x7), srcy + (tary & 0x7),srcdata); dstdata = XGA_GetPoint(tarx, tary); if(mixselect == 0x3) { - if(srcdata == xga.forecolor) { - mixmode = xga.foremix; - } else { - if(srcdata == xga.backcolor) { - mixmode = xga.backmix; - } else { - /* Best guess otherwise */ - mixmode = 0x67; /* Source is bitmap data, mix mode is src */ - } - } + // TODO lots of guessing here but best results this way + /*if(srcdata == xga.forecolor)*/ mixmode = xga.foremix; + // else + if(srcdata == xga.backcolor || srcdata == 0) + mixmode = xga.backmix; } switch((mixmode >> 5) & 0x03) { @@ -862,16 +868,14 @@ void XGA_DrawPattern(Bitu val) { tarx += dx; } tary += dy; - } - } void XGA_DrawCmd(Bitu val, Bitu len) { Bit16u cmd; cmd = val >> 13; #if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Draw command %x", cmd); + //LOG_MSG("XGA: Draw command %x", cmd); #endif xga.curcommand = val; switch(cmd) { @@ -895,10 +899,12 @@ void XGA_DrawCmd(Bitu val, Bitu len) { case 2: /* Rectangle fill */ if((val & 0x100) == 0) { xga.waitcmd.wait = false; - XGA_DrawRectangle(val); #if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Draw immediate rect"); + LOG_MSG("XGA: Draw immediate rect: xy(%3d/%3d), len(%3d/%3d)", + xga.curx,xga.cury,xga.MAPcount,xga.MIPcount); #endif + XGA_DrawRectangle(val); + } else { xga.waitcmd.newline = true; @@ -907,44 +913,50 @@ void XGA_DrawCmd(Bitu val, Bitu len) { xga.waitcmd.cury = xga.cury; xga.waitcmd.x1 = xga.curx; xga.waitcmd.y1 = xga.cury; - xga.waitcmd.x2 = xga.curx + xga.MAPcount; - xga.waitcmd.y2 = xga.cury + xga.MIPcount + 1; + xga.waitcmd.x2 = (Bit16u)((xga.curx + xga.MAPcount)&0x0fff); + xga.waitcmd.y2 = (Bit16u)((xga.cury + xga.MIPcount + 1)&0x0fff); xga.waitcmd.sizex = xga.MAPcount; xga.waitcmd.sizey = xga.MIPcount + 1; xga.waitcmd.cmd = 2; - + xga.waitcmd.buswidth = vga.mode | ((val&0x600) >> 4); xga.waitcmd.data = 0; xga.waitcmd.datasize = 0; #if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Draw wait rect, width %d, heigth %d", xga.MAPcount, xga.MIPcount+1); + LOG_MSG("XGA: Draw wait rect, w/h(%3d/%3d), x/y1(%3d/%3d), x/y2(%3d/%3d), %4x", + xga.MAPcount+1, xga.MIPcount+1,xga.curx,xga.cury, + (xga.curx + xga.MAPcount)&0x0fff, + (xga.cury + xga.MIPcount + 1)&0x0fff,val&0xffff); #endif + } break; case 6: /* BitBLT */ - XGA_BlitRect(val); #if XGA_SHOW_COMMAND_TRACE == 1 LOG_MSG("XGA: Blit Rect"); #endif + XGA_BlitRect(val); break; case 7: /* Pattern fill */ - XGA_DrawPattern(val); #if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Pattern fill"); + LOG_MSG("XGA: Pattern fill: src(%3d/%3d), dest(%3d/%3d), fill(%3d/%3d)", + xga.curx,xga.cury,xga.destx,xga.desty,xga.MAPcount,xga.MIPcount); #endif + XGA_DrawPattern(val); break; default: LOG_MSG("XGA: Unhandled draw command %x", cmd); break; - } } -void XGA_SetDualReg(Bit32u& reg, Bitu val) -{ +void XGA_SetDualReg(Bit32u& reg, Bitu val) { switch(vga.mode) { - case M_LIN8: reg = val&0x000000ff; break; - case M_LIN15: case M_LIN16: reg = val&0x0000ffff; break; + case M_LIN8: + reg = (Bit8u)(val&0xff); break; + case M_LIN15: + case M_LIN16: + reg = (Bit16u)(val&0xffff); break; case M_LIN32: { if(xga.control1 & 0x200) reg = val; @@ -958,11 +970,12 @@ void XGA_SetDualReg(Bit32u& reg, Bitu val) } } -Bitu XGA_GetDualReg(Bit32u reg) -{ +Bitu XGA_GetDualReg(Bit32u reg) { switch(vga.mode) { - case M_LIN8: return reg&0x000000ff; - case M_LIN15: case M_LIN16: return reg&0x0000ffff; + case M_LIN8: + return (Bit8u)(reg&0xff); + case M_LIN15: case M_LIN16: + return (Bit16u)(reg&0xffff); case M_LIN32: { if(xga.control1 & 0x200) return reg; @@ -976,15 +989,111 @@ Bitu XGA_GetDualReg(Bit32u reg) return 0; } +extern Bitu vga_read_p3da(Bitu port,Bitu iolen); + +extern void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen); +extern Bitu vga_read_p3d4(Bitu port,Bitu iolen); + +extern void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen); +extern Bitu vga_read_p3d5(Bitu port,Bitu iolen); + void XGA_Write(Bitu port, Bitu val, Bitu len) { + //LOG_MSG("XGA: Write to port %x, val %8x, len %x", port,val, len); + switch(port) { + case 0x8100:// drawing control: row (low word), column (high word) + // "CUR_X" and "CUR_Y" (see PORT 82E8h,PORT 86E8h) + xga.cury = val & 0x0fff; + if(len==4) xga.curx = (val>>16)&0x0fff; + break; + case 0x8102: + xga.curx = val& 0x0fff; + break; + + case 0x8108:// DWORD drawing control: destination Y and axial step + // constant (low word), destination X and axial step + // constant (high word) (see PORT 8AE8h,PORT 8EE8h) + xga.desty = val&0x3FFF; + if(len==4) xga.destx = (val>>16)&0x3fff; + break; + case 0x810a: + xga.destx = val&0x3fff; + break; + case 0x8110: // WORD error term (see PORT 92E8h) + xga.ErrTerm = val&0x3FFF; + break; + + case 0x8120: // packed MMIO: DWORD background color (see PORT A2E8h) + //if(len==4) xga.backcolor = val; + //else + XGA_SetDualReg(xga.backcolor, val); + break; + case 0x8124: // packed MMIO: DWORD foreground color (see PORT A6E8h) + //if(len==4) xga.forecolor = val; // TODO + //else + XGA_SetDualReg(xga.forecolor, val); + break; + case 0x8128: // DWORD write mask (see PORT AAE8h) + //if(len==4) xga.writemask = val; + //else + XGA_SetDualReg(xga.writemask, val); + break; + case 0x812C: // DWORD read mask (see PORT AEE8h) + //if(len==4) xga.readmask = val; + //else + XGA_SetDualReg(xga.readmask, val); + break; + case 0x8134: // packed MMIO: DWORD background mix (low word) and + // foreground mix (high word) (see PORT B6E8h,PORT BAE8h) + xga.backmix = val&0xFFFF; + if(len==4) xga.foremix = (val>>16); + break; + case 0x8136: + xga.foremix = val; + break; + case 0x8138:// DWORD top scissors (low word) and left scissors (high + // word) (see PORT BEE8h,#P1047) + xga.scissors.y1=val&0x0fff; + if(len==4) xga.scissors.x1 = (val>>16)&0x0fff; + break; + case 0x813a: + xga.scissors.x1 = val&0x0fff; + break; + case 0x813C:// DWORD bottom scissors (low word) and right scissors + // (high word) (see PORT BEE8h,#P1047) + xga.scissors.y2=val&0x0fff; + if(len==4) xga.scissors.x2 = (val>>16)&0x0fff; + break; + case 0x813e: + xga.scissors.x2 = val&0x0fff; + break; + + case 0x8140:// DWORD data manipulation control (low word) and + // miscellaneous 2 (high word) (see PORT BEE8h,#P1047) + xga.pix_cntl=val&0xFFFF; + if(len==4) xga.control2=(val>>16)&0x0fff; + break; + case 0x8144:// DWORD miscellaneous (low word) and read register select + // (high word)(see PORT BEE8h,#P1047) + xga.control1=val&0xffff; + if(len==4)xga.read_sel=(val>>16)&0x7; + break; + case 0x8148:// DWORD minor axis pixel count (low word) and major axis + // pixel count (high word) (see PORT BEE8h,#P1047,PORT 96E8h) + xga.MIPcount = val&0x0fff; + if(len==4) xga.MAPcount = (val>>16)&0x0fff; + break; + case 0x814a: + xga.MAPcount = val&0x0fff; + break; case 0x92e8: - xga.ErrTerm = val; + xga.ErrTerm = val&0x3FFF; break; case 0x96e8: - xga.MAPcount = val; + xga.MAPcount = val&0x0fff; break; case 0x9ae8: + case 0x8118: // Trio64V+ packed MMIO XGA_DrawCmd(val, len); break; case 0xa2e8: @@ -1000,16 +1109,19 @@ void XGA_Write(Bitu port, Bitu val, Bitu len) { XGA_SetDualReg(xga.readmask, val); break; case 0x82e8: - xga.cury = val; + xga.cury = val&0x0fff; break; case 0x86e8: - xga.curx = val; + xga.curx = val&0x0fff; break; case 0x8ae8: - xga.desty = val; + xga.desty = val&0x3fff; break; case 0x8ee8: - xga.destx = val; + xga.destx = val&0x3fff; + break; + case 0xb2e8: + LOG_MSG("COLOR_CMP not implemented"); break; case 0xb6e8: xga.backmix = val; @@ -1020,38 +1132,63 @@ void XGA_Write(Bitu port, Bitu val, Bitu len) { case 0xbee8: XGA_Write_Multifunc(val, len); break; - case 0x0e2e0: - if(!xga.waitcmd.newline) { - xga.waitcmd.curx = xga.waitcmd.x1; - xga.waitcmd.cury++; - xga.waitcmd.newline = true; - } - - XGA_DrawWait(val, len); - if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false; - break; case 0xe2e8: xga.waitcmd.newline = false; XGA_DrawWait(val, len); break; + case 0x83d4: + if(len==1) vga_write_p3d4(0,val,1); + else if(len==2) { + vga_write_p3d4(0,val&0xff,1); + vga_write_p3d5(0,val>>8,1); + } + else E_Exit("unimplemented XGA MMIO"); + break; + case 0x83d5: + if(len==1) vga_write_p3d5(0,val,1); + else E_Exit("unimplemented XGA MMIO"); + break; default: - LOG_MSG("XGA: Wrote to port %x with %x, len %x", port, val, len); + if(port <= 0x4000) { + //LOG_MSG("XGA: Wrote to port %4x with %08x, len %x", port, val, len); + xga.waitcmd.newline = false; + XGA_DrawWait(val, len); + + } + else LOG_MSG("XGA: Wrote to port %x with %x, len %x", port, val, len); break; } - } Bitu XGA_Read(Bitu port, Bitu len) { - //LOG_MSG("XGA: Read from port %x, len %x", port, len); switch(port) { + case 0x8118: case 0x9ae8: - return 0x0; - case 0x9ae9: - if(xga.waitcmd.wait) { - return 0x4; - } else { - return 0x0; + return 0x400; // nothing busy + break; + case 0x81ec: // S3 video data processor + return 0x00007000; + break; + case 0x83da: + { + Bits delaycyc = CPU_CycleMax/5000; + if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; + CPU_Cycles -= delaycyc; + CPU_IODelayRemoved += delaycyc; + return vga_read_p3da(0,0); + break; } + case 0x83d4: + if(len==1) return vga_read_p3d4(0,0); + else E_Exit("unimplemented XGA MMIO"); + break; + case 0x83d5: + if(len==1) return vga_read_p3d5(0,0); + else E_Exit("unimplemented XGA MMIO"); + break; + case 0x9ae9: + if(xga.waitcmd.wait) return 0x4; + else return 0x0; case 0xbee8: return XGA_Read_Multifunc(); case 0xa2e8: @@ -1067,9 +1204,10 @@ Bitu XGA_Read(Bitu port, Bitu len) { return XGA_GetDualReg(xga.readmask); break; default: - LOG_MSG("XGA: Read from port %x, len %x", port, len); - return 0x0; + //LOG_MSG("XGA: Read from port %x, len %x", port, len); + break; } + return 0xffffffff; } void VGA_SetupXGA(void) { @@ -1077,6 +1215,11 @@ void VGA_SetupXGA(void) { memset(&xga, 0, sizeof(XGAStatus)); + xga.scissors.y1 = 0; + xga.scissors.x1 = 0; + xga.scissors.y2 = 0xFFF; + xga.scissors.x2 = 0xFFF; + IO_RegisterWriteHandler(0x42e8,&XGA_Write,IO_MB | IO_MW | IO_MD); IO_RegisterReadHandler(0x42e8,&XGA_Read,IO_MB | IO_MW | IO_MD); diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index da24595a..f008954b 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_modes.cpp,v 1.70 2007-11-05 18:42:56 qbix79 Exp $ */ +/* $Id: int10_modes.cpp,v 1.71 2007-12-10 22:11:13 c2woody Exp $ */ #include @@ -57,51 +57,69 @@ VideoModeBlock ModeList_VGA[]={ { 0x054 ,M_TEXT ,1056,688, 132,43, 8, 16, 1 ,0xB8000 ,0x4000, 192, 800, 132,688, 0 }, { 0x055 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 192, 449, 132,400, 0 }, +/* Alias of mode 102 */ { 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, /* Follow vesa 1.2 for first 0x20 */ { 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, { 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, -{ 0x102 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, -{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, -{ 0x104 ,M_LIN4 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,150 ,800 ,128,768 ,0 }, -{ 0x105 ,M_LIN8 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,150 ,800 ,128,768 ,0 }, +{ 0x102 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, +{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, +{ 0x104 ,M_LIN4 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, +{ 0x105 ,M_LIN8 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, +{ 0x106 ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, +{ 0x107 ,M_LIN8 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, { 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, { 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x110 ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, -{ 0x111 ,M_LIN16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, +{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, +{ 0x110 ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 }, +{ 0x111 ,M_LIN16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 }, { 0x112 ,M_LIN32 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, -{ 0x113 ,M_LIN15 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, -{ 0x114 ,M_LIN16 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, -{ 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, - -{ 0x116 ,M_LIN15 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,150 ,800 ,128,768 ,0 }, -{ 0x117 ,M_LIN16 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,150 ,800 ,128,768 ,0 }, -{ 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,150 ,800 ,128,768 ,0 }, +{ 0x113 ,M_LIN15 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 }, +{ 0x114 ,M_LIN16 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 }, +{ 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, +{ 0x116 ,M_LIN15 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 }, +{ 0x117 ,M_LIN16 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 }, +{ 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, +/* those should be interlaced but ok */ +//{ 0x119 ,M_LIN15 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 }, +//{ 0x11A ,M_LIN16 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 }, { 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, { 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, { 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE }, { 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, +{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, +{ 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE }, +{ 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE }, +{ 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 }, -{ 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x171 ,M_LIN16 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x172 ,M_LIN16 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x175 ,M_LIN16 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, +{ 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, +{ 0x171 ,M_LIN16 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE }, +{ 0x172 ,M_LIN16 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE }, +{ 0x175 ,M_LIN16 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 }, -{ 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x191 ,M_LIN32 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x192 ,M_LIN32 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x195 ,M_LIN32 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, +{ 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, +{ 0x191 ,M_LIN32 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE }, +{ 0x192 ,M_LIN32 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE }, +/* S3 specific modes */ +{ 0x207 ,M_LIN8 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 }, +{ 0x209 ,M_LIN15 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 }, +{ 0x20A ,M_LIN16 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 }, +//{ 0x20B ,M_LIN32 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 }, +{ 0x213 ,M_LIN32 ,640 ,400,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, + +/* Some custom modes */ +//{ 0x220 ,M_LIN32 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, +// A nice 16:9 mode +{ 0x222 ,M_LIN8 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 }, +{ 0x223 ,M_LIN15 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 }, +{ 0x224 ,M_LIN16 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 }, +{ 0x225 ,M_LIN32 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 }, {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, }; @@ -515,6 +533,9 @@ bool INT10_SetVideoMode(Bitu mode) { if (mono_mode) crtc_base=0x3b4; else crtc_base=0x3d4; + // Disable MMIO here so we can read / write memory + if (IS_VGA_ARCH) IO_Write(crtc_base,0x53);IO_Write(crtc_base+1,0x0); + /* Setup MISC Output Register */ Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); @@ -804,9 +825,7 @@ bool INT10_SetVideoMode(Bitu mode) { /* Setup Pixel format */ switch (CurMode->type) { case M_LIN8: - /* This should be 0x0 according to the specs but makes it easier to detect - compared to normal vga modes now */ - misc_control_2=0x10; + misc_control_2=0x00; break; case M_LIN15: misc_control_2=0x30; @@ -939,7 +958,9 @@ att_text16: break; case M_VGA: case M_LIN8: + case M_LIN15: case M_LIN16: + case M_LIN32: for (i=0;i<16;i++) att_data[i]=i; att_data[0x10]=0x41; //Color Graphics 8-bit break; @@ -993,7 +1014,9 @@ dac_text16: break; case M_VGA: case M_LIN8: + case M_LIN15: case M_LIN16: + case M_LIN32: for (i=0;i<256;i++) { IO_Write(0x3c9,vga_palette[i][0]); IO_Write(0x3c9,vga_palette[i][1]); @@ -1056,10 +1079,51 @@ dac_text16: IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); IO_Write(crtc_base,0x5a); IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16)); + IO_Write(crtc_base,0x6b); // BIOS scratchpad + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); + /* Setup some remaining S3 registers */ - Bitu reg_31; + IO_Write(crtc_base,0x41); // BIOS scratchpad + IO_Write(crtc_base+1,0x88); + IO_Write(crtc_base,0x52); // extended BIOS scratchpad + IO_Write(crtc_base+1,0x80); + + // Accellerator setup + Bitu reg_50=0; switch (CurMode->type) { - case M_LIN4: + case M_LIN15: + case M_LIN16: reg_50|=0x10; break; + case M_LIN32: reg_50|=0x30; break; + } + switch(CurMode->swidth) + { + case 640: reg_50|=0x40; break; + case 800: reg_50|=0x80; break; + case 1024: break; + case 1152: reg_50|=0x01; break; + case 1280: reg_50|=0xc1; break; + } + IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1,reg_50); + + Bitu reg_31, reg_3a; + switch (CurMode->type) { + case M_LIN15: + case M_LIN16: + case M_LIN32: + reg_3a=0x15; + break; + case M_LIN8: + // S3VBE20 does it this way. The other double pixel bit does not + // seem to have an effect on the Trio64. + if(CurMode->special&_VGA_PIXEL_DOUBLE) reg_3a=0x5; + else reg_3a=0x15; + break; + default: + reg_3a=5; + }; + + switch (CurMode->type) { + case M_LIN4: // <- Theres a discrepance with real hardware on this case M_LIN8: case M_LIN15: case M_LIN16: @@ -1070,9 +1134,9 @@ dac_text16: reg_31 = 0; break; } + IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1,reg_3a); IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing - IO_Write(crtc_base,0x53);IO_Write(crtc_base+1,0x0); //Disable MMIO IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp index b66a0d2b..0aaf6c06 100644 --- a/src/ints/int10_vesa.cpp +++ b/src/ints/int10_vesa.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_vesa.cpp,v 1.29 2007-09-24 20:50:40 c2woody Exp $ */ +/* $Id: int10_vesa.cpp,v 1.30 2007-12-10 22:11:13 c2woody Exp $ */ #include #include @@ -115,7 +115,7 @@ Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) { } mem_writed(buffer+0x0a,0x0); //Capabilities and flags mem_writed(buffer+0x0e,int10.rom.vesa_modes); //VESA Mode list - mem_writew(buffer+0x12,32); //32 64kb blocks for 2 mb memory + mem_writew(buffer+0x12,Bit16u(VGA_MEMORY/(64*1024))); // memory size in 64kb blocks return 0x00; } @@ -124,6 +124,7 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) { memset(&minfo,0,sizeof(minfo)); PhysPt buf=PhysMake(seg,off); Bitu pageSize; + Bit8u modeAttributes; Bitu i=0; mode&=0x3fff; // vbe2 compatible, ignore lfb and keep screen content bits @@ -138,27 +139,33 @@ foundit: case M_LIN4: pageSize = mblock->sheight * mblock->swidth/2; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(512*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth/8); var_write(&minfo.NumberOfPlanes,0x4); var_write(&minfo.BitsPerPixel,4); var_write(&minfo.MemoryModel,3); //ega planar mode - var_write(&minfo.ModeAttributes,0x1b); //Color, graphics, no linear buffer + modeAttributes = 0x1b; // Color, graphics, no linear buffer + + if(pageSize > 512*1024) { // this limitation is not on the real card + var_write(&minfo.ModeAttributes, modeAttributes & ~0x1); + var_write(&minfo.NumberOfImagePages,0); + } else { + var_write(&minfo.ModeAttributes, modeAttributes); + Bitu pages = (512*1024 / pageSize)-1; + var_write(&minfo.NumberOfImagePages,pages); + } break; case M_LIN8: pageSize = mblock->sheight * mblock->swidth; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(2*1024*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth); var_write(&minfo.NumberOfPlanes,0x1); var_write(&minfo.BitsPerPixel,8); var_write(&minfo.MemoryModel,4); //packed pixel - var_write(&minfo.ModeAttributes,0x9b); //Color, graphics, linear buffer + modeAttributes = 0x9b; // Color, graphics, linear buffer break; case M_LIN15: pageSize = mblock->sheight * mblock->swidth*2; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(2*1024*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth*2); var_write(&minfo.NumberOfPlanes,0x1); var_write(&minfo.BitsPerPixel,15); @@ -171,12 +178,11 @@ foundit: var_write(&minfo.BlueMaskPos,0); var_write(&minfo.ReservedMaskSize,0x01); var_write(&minfo.ReservedMaskPos,0x0f); - var_write(&minfo.ModeAttributes,0x9b); //Color, graphics, linear buffer + modeAttributes = 0x9b; // Color, graphics, linear buffer break; case M_LIN16: pageSize = mblock->sheight * mblock->swidth*2; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(2*1024*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth*2); var_write(&minfo.NumberOfPlanes,0x1); var_write(&minfo.BitsPerPixel,16); @@ -187,12 +193,11 @@ foundit: var_write(&minfo.GreenMaskPos,5); var_write(&minfo.BlueMaskSize,5); var_write(&minfo.BlueMaskPos,0); - var_write(&minfo.ModeAttributes,0x9b); //Color, graphics, linear buffer + modeAttributes = 0x9b; // Color, graphics, linear buffer break; case M_LIN32: pageSize = mblock->sheight * mblock->swidth*4; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(2*1024*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth*4); var_write(&minfo.NumberOfPlanes,0x1); var_write(&minfo.BitsPerPixel,32); @@ -205,22 +210,33 @@ foundit: var_write(&minfo.BlueMaskPos,0x0); var_write(&minfo.ReservedMaskSize,0x8); var_write(&minfo.ReservedMaskPos,0x18); - var_write(&minfo.ModeAttributes,0x9b); //Color, graphics, linear buffer + modeAttributes = 0x9b; // Color, graphics, linear buffer break; /* case M_TEXT: pageSize = mblock->sheight/8 * mblock->swidth*2/8; pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.NumberOfImagePages,(2*1024*1024 / pageSize)-1); var_write(&minfo.BytesPerScanLine,mblock->swidth*2/8); var_write(&minfo.NumberOfPlanes,0x4); var_write(&minfo.BitsPerPixel,4); var_write(&minfo.MemoryModel,0); //Text - var_write(&minfo.ModeAttributes,0x0f); //Color, text, bios output + modeAttributes = 0x0f; //Color, text, bios output break; */ default: return 0x1; } - var_write(&minfo.WinAAttributes,0x7); //Exists/readable/writable + var_write(&minfo.WinAAttributes,0x7); // Exists/readable/writable + + if(mblock->type != M_LIN4) + if(pageSize > VGA_MEMORY) { + // Mode not supported by current hardware configuration + var_write(&minfo.ModeAttributes, modeAttributes & ~0x1); + var_write(&minfo.NumberOfImagePages,0); + } else { + var_write(&minfo.ModeAttributes, modeAttributes); + Bitu pages = (VGA_MEMORY / pageSize)-1; + var_write(&minfo.NumberOfImagePages,pages); + } + if (mblock->type==M_TEXT) { var_write(&minfo.WinGranularity,32); var_write(&minfo.WinSize,32); @@ -333,15 +349,17 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixe } switch (subcall) { case 0x00: /* Set in pixels */ - vga.config.scan_len = (val * bpp); + if(CurMode->type==M_LIN4) vga.config.scan_len=val/2; + else vga.config.scan_len = (val * bpp); break; case 0x02: /* Set in bytes */ - vga.config.scan_len = val; + if(CurMode->type==M_LIN4) vga.config.scan_len = val*4; + else vga.config.scan_len = val; break; case 0x03: /* Get maximum */ bytes=0x400*4; pixels=bytes/bpp; - lines = 2*1024*1024 / bytes; + lines = VGA_MEMORY / bytes; return 0x00; case 0x01: /* Get lengths */ break; @@ -354,9 +372,16 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixe vga.config.scan_len += 8; vga.config.scan_len /= 8; } - pixels=(vga.config.scan_len*8)/bpp; - bytes=vga.config.scan_len*8; - lines = 2*1024*1024 / bytes; + if(CurMode->type==M_LIN4) { + pixels=(vga.config.scan_len*16)/bpp; + bytes=vga.config.scan_len*2; + lines = Bit16u(VGA_MEMORY /( bytes*4)); + } + else { + pixels=(vga.config.scan_len*8)/bpp; + bytes=vga.config.scan_len*8; + lines = Bit16u(VGA_MEMORY / bytes); + } VGA_StartResize(); return 0x0; } @@ -366,7 +391,7 @@ Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) { Bitu start; switch (CurMode->type) { case M_LIN4: - start=vga.config.scan_len*8*y+x; + start=vga.config.scan_len*16*y+x; vga.config.display_start=start/8; IO_Read(0x3da); IO_Write(0x3c0,0x13+32);