From 50917251f442780277105699e298e3247fa87a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Strohh=C3=A4cker?= Date: Sat, 12 Jan 2008 17:37:48 +0000 Subject: [PATCH] add variable-size graphics memory, enable some more vga memory wrapping (vasyl) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3077 --- include/vga.h | 18 +++-- src/hardware/vga.cpp | 7 +- src/hardware/vga_draw.cpp | 30 +++++--- src/hardware/vga_memory.cpp | 124 +++++++++++++++++++++++++++------- src/hardware/vga_paradise.cpp | 31 +++++++-- src/hardware/vga_s3.cpp | 38 +++++++++-- src/hardware/vga_tseng.cpp | 25 +++++-- src/hardware/vga_xga.cpp | 4 +- src/ints/int10_modes.cpp | 52 +++++++++++++- src/ints/int10_vesa.cpp | 32 +++++---- 10 files changed, 285 insertions(+), 76 deletions(-) diff --git a/include/vga.h b/include/vga.h index a497b33a..9cf7d2df 100644 --- a/include/vga.h +++ b/include/vga.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga.h,v 1.37 2008-01-09 20:34:21 c2woody Exp $ */ +/* $Id: vga.h,v 1.38 2008-01-12 17:36:48 c2woody Exp $ */ #ifndef DOSBOX_VGA_H #define DOSBOX_VGA_H @@ -31,9 +31,6 @@ #define VGA_MEMORY (2*1024*1024) #define VGA_CHANGE_SHIFT 9 -//Offset inside VGA_MEMORY that will be used for certain types of caching -#define VGA_CACHE_OFFSET (512*1024) - class PageHandler; @@ -164,6 +161,7 @@ typedef struct { Bit8u reg_lock2; Bit8u reg_31; Bit8u reg_35; + Bit8u reg_36; // RAM size Bit8u reg_3a; // 4/8/doublepixel bit in there Bit8u reg_40; // 8415/A functionality register Bit8u reg_41; // BIOS flags @@ -330,11 +328,12 @@ typedef union { typedef struct { Bit8u* linear; + Bit8u* linear_orgptr; } VGA_Memory; typedef struct { //Add a few more just to be safe - Bit8u map[(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32]; + Bit8u* map; /* allocated dynamically: [(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32] */ Bit8u checkMask, frame, writeMask; bool active; Bit32u clearMask; @@ -370,6 +369,10 @@ typedef struct { VGA_TANDY tandy; VGA_OTHER other; VGA_Memory mem; + Bit32u vmemwrap; /* this is assumed to be power of 2 */ + Bit8u* fastmem; /* memory for fast (usually 16-color) rendering, always twice as big as vmemsize */ + Bit8u* fastmem_orgptr; + Bit32u vmemsize; #ifdef VGA_KEEP_CHANGES VGA_Changes changes; #endif @@ -394,7 +397,7 @@ void VGA_ATTR_SetPalette(Bit8u index,Bit8u val); /* The VGA Subfunction startups */ void VGA_SetupAttr(void); -void VGA_SetupMemory(void); +void VGA_SetupMemory(Section* sec); void VGA_SetupDAC(void); void VGA_SetupCRTC(void); void VGA_SetupMisc(void); @@ -472,6 +475,9 @@ void SVGA_Setup_TsengET3K(void); void SVGA_Setup_ParadisePVGA1A(void); void SVGA_Setup_Driver(void); +// Amount of video memory required for a mode, implemented in int10_modes.cpp +Bitu VideoModeMemSize(Bitu mode); + extern Bit32u ExpandTable[256]; extern Bit32u FillTable[16]; extern Bit32u CGA_2_Table[16]; diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 5a52b026..060ab750 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga.cpp,v 1.32 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga.cpp,v 1.33 2008-01-12 17:37:48 c2woody Exp $ */ #include "dosbox.h" //#include "setup.h" @@ -170,7 +170,7 @@ void VGA_Init(Section* sec) { vga.draw.resizing=false; vga.mode=M_ERROR; //For first init SVGA_Setup_Driver(); - VGA_SetupMemory(); + VGA_SetupMemory(sec); VGA_SetupMisc(); VGA_SetupDAC(); VGA_SetupGFX(); @@ -249,5 +249,8 @@ void SVGA_Setup_Driver(void) { case SVGA_ParadisePVGA1A: SVGA_Setup_ParadisePVGA1A(); break; + default: + vga.vmemsize = vga.vmemwrap = 256*1024; + break; } } diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index ed9b5de1..28640222 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.91 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga_draw.cpp,v 1.92 2008-01-12 17:37:48 c2woody Exp $ */ #include #include @@ -150,7 +150,10 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) { Bitu end = ((vidstart + vga.draw.line_length ) >> VGA_CHANGE_SHIFT); for (; start <= end;start++) { if ( map[start] & checkMask ) { - Bit8u *ret = &vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]; + Bitu offset = vidstart & vga.draw.linear_mask; + if(vga.draw.linear_mask-offset < vga.draw.line_length) + memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length); + Bit8u *ret = &vga.draw.linear_base[ offset ]; #if !defined(C_UNALIGNED_MEMORY) if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { memcpy( TempLine, ret, vga.draw.line_length ); @@ -168,7 +171,12 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) { #endif static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu line) { - Bit8u *ret = &vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]; +// There is guaranteed extra memory past the wrap boundary. So, instead of using temporary +// storage just copy appropriate chunk from the beginning to the wrap boundary when needed. + Bitu offset = vidstart & vga.draw.linear_mask; + if (vga.draw.linear_mask-offset < vga.draw.line_length) + memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length); + Bit8u *ret = &vga.draw.linear_base[ offset ]; #if !defined(C_UNALIGNED_MEMORY) if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { memcpy( TempLine, ret, vga.draw.line_length ); @@ -598,7 +606,7 @@ skip_cursor: static void VGA_VerticalDisplayEnd(Bitu val) { // vga.config.retrace=true; - vga.config.real_start=vga.config.display_start & ((VGA_MEMORY)-1); + vga.config.real_start=vga.config.display_start & (vga.vmemwrap-1); } static void VGA_HorizontalTimer(void) { @@ -800,11 +808,11 @@ static void VGA_VerticalTimer(Bitu val) { break; case M_VGA: if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) { - vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; + vga.draw.linear_base = vga.fastmem; vga.draw.linear_mask = 0xffff; } else { vga.draw.linear_base = vga.mem.linear; - vga.draw.linear_mask = VGA_MEMORY - 1; + vga.draw.linear_mask = vga.vmemwrap - 1; } case M_LIN8: case M_LIN15: @@ -1148,7 +1156,7 @@ void VGA_SetupDrawing(Bitu val) { break; } vga.draw.linear_base = vga.mem.linear; - vga.draw.linear_mask = VGA_MEMORY - 1; + vga.draw.linear_mask = vga.vmemwrap - 1; switch (vga.mode) { case M_VGA: doublewidth=true; @@ -1187,8 +1195,8 @@ void VGA_SetupDrawing(Bitu val) { vga.draw.blocks = width; width<<=3; VGA_DrawLine=VGA_Draw_Linear_Line; - vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; - vga.draw.linear_mask = 1024 * 1024 - 1; + vga.draw.linear_base = vga.fastmem; + vga.draw.linear_mask = (vga.vmemwrap<<1) - 1; break; case M_EGA: doublewidth=(vga.seq.clocking_mode & 0x8) > 0; @@ -1199,8 +1207,8 @@ void VGA_SetupDrawing(Bitu val) { VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line; } else VGA_DrawLine=VGA_Draw_Linear_Line; - vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; - vga.draw.linear_mask = 512 * 1024 - 1; + vga.draw.linear_base = vga.fastmem; + vga.draw.linear_mask = (vga.vmemwrap<<1) - 1; break; case M_CGA16: doubleheight=true; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index fd9ab374..9193fd7d 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.46 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga_memory.cpp,v 1.47 2008-01-12 17:37:48 c2woody Exp $ */ #include #include @@ -26,6 +26,27 @@ #include "paging.h" #include "pic.h" #include "inout.h" +#include "setup.h" + + +/* #ifndef C_VGARAM_CHECKED +#define C_VGARAM_CHECKED 1 +#endif */ + +#if C_VGARAM_CHECKED +// Checked linear offset +#define CHECKED(v) ((v)&(vga.vmemwrap-1)) +// Checked planar offset (latched access) +#define CHECKED2(v) ((v)&((vga.vmemwrap>>2)-1)) +// Checked planar offset (latched access) +#else +#define CHECKED(v) (v) +#define CHECKED2(v) (v) +#endif + +#define CHECKED3(v) ((v)&(vga.vmemwrap-1)) +#define CHECKED4(v) ((v)&((vga.vmemwrap>>2)-1)) + #ifdef VGA_KEEP_CHANGES #define MEM_CHANGED( _MEM ) vga.changes.map[ (_MEM) >> VGA_CHANGE_SHIFT ] |= vga.changes.writeMask; @@ -133,11 +154,13 @@ public: Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED2(addr); return readHandler(addr); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED2(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); @@ -145,6 +168,7 @@ public: Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED2(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -166,7 +190,7 @@ public: start >>= 2; pixels.d=((Bit32u*)vga.mem.linear)[start]; - Bit8u * write_pixels=&vga.mem.linear[VGA_CACHE_OFFSET+(start<<3)]; + Bit8u * write_pixels=&vga.fastmem[start<<3]; Bit32u colors0_3, colors4_7; VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; @@ -191,12 +215,14 @@ public: void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -204,6 +230,7 @@ public: void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -213,11 +240,13 @@ public: Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return readHandler(addr); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); @@ -225,6 +254,7 @@ public: Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -244,7 +274,7 @@ public: pixels.d&=vga.config.full_not_map_mask; pixels.d|=(data & vga.config.full_map_mask); ((Bit32u*)vga.mem.linear)[start]=pixels.d; - Bit8u * write_pixels=&vga.mem.linear[VGA_CACHE_OFFSET+(start<<3)]; + Bit8u * write_pixels=&vga.fastmem[start<<3]; Bit32u colors0_3, colors4_7; VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; @@ -261,10 +291,6 @@ public: Expand16Table[2][temp.b[2]] | Expand16Table[3][temp.b[3]]; *(Bit32u *)(write_pixels+4)=colors4_7; - if (wrapping && GCC_UNLIKELY( start < 512)) { - *(Bit32u *)(write_pixels+512*1024)=colors0_3; - *(Bit32u *)(write_pixels+512*1024+4)=colors4_7; - } } public: VGA_UnchainedEGA_Handler() { @@ -273,12 +299,14 @@ public: void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -286,6 +314,7 @@ public: void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -306,10 +335,10 @@ public: } template static INLINE void writeCache(PhysPt addr, Bitu val) { - hostWrite( &vga.mem.linear[VGA_CACHE_OFFSET+addr], val ); + hostWrite( &vga.fastmem[addr], val ); if (GCC_UNLIKELY(addr < 320)) { // And replicate the first line - hostWrite( &vga.mem.linear[VGA_CACHE_OFFSET+addr+64*1024], val ); + hostWrite( &vga.fastmem[addr+64*1024], val ); } } template @@ -320,11 +349,13 @@ public: Bitu readb(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return readHandler( addr ); } Bitu readw(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); if (GCC_UNLIKELY(addr & 1)) return (readHandler( addr+0 ) << 0 ) | @@ -335,6 +366,7 @@ public: Bitu readd(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); if (GCC_UNLIKELY(addr & 3)) return (readHandler( addr+0 ) << 0 ) | @@ -347,6 +379,7 @@ public: void writeb(PhysPt addr, Bitu val ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); writeHandler( addr, val ); writeCache( addr, val ); @@ -354,6 +387,7 @@ public: void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); // MEM_CHANGED( addr + 1); if (GCC_UNLIKELY(addr & 1)) { @@ -367,6 +401,7 @@ public: void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); // MEM_CHANGED( addr + 3); if (GCC_UNLIKELY(addr & 3)) { @@ -391,7 +426,7 @@ public: pixels.d|=(data & vga.config.full_map_mask); ((Bit32u*)vga.mem.linear)[addr]=pixels.d; if(vga.config.compatible_chain4) - ((Bit32u*)vga.mem.linear)[addr+64*1024]=pixels.d; + ((Bit32u*)vga.mem.linear)[CHECKED2(addr+64*1024)]=pixels.d; } public: VGA_UnchainedVGA_Handler() { @@ -400,12 +435,14 @@ public: void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 2 ); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -413,6 +450,7 @@ public: void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED2(addr); MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -445,11 +483,11 @@ public: } HostPt GetHostReadPt(Bitu phys_page) { phys_page-=vgapages.base; - return &vga.mem.linear[vga.svga.bank_read_full+phys_page*4096]; + return &vga.mem.linear[CHECKED3(vga.svga.bank_read_full+phys_page*4096)]; } HostPt GetHostWritePt(Bitu phys_page) { phys_page-=vgapages.base; - return &vga.mem.linear[vga.svga.bank_write_full+phys_page*4096]; + return &vga.mem.linear[CHECKED3(vga.svga.bank_write_full+phys_page*4096)]; } }; @@ -461,33 +499,39 @@ public: Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_read_full; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; addr += vga.svga.bank_write_full; + addr = CHECKED(addr); MEM_CHANGED( addr ); hostWrite( &vga.mem.linear[addr], val ); } @@ -500,20 +544,20 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); MEM_CHANGED( addr << 3 ); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); @@ -522,19 +566,19 @@ public: } Bitu readb(PhysPt addr) { addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); return readHandler(addr); } Bitu readw(PhysPt addr) { addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); } Bitu readd(PhysPt addr) { addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (128*1024-1); + addr = CHECKED4(addr); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -551,28 +595,34 @@ public: } Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); return hostRead( &vga.mem.linear[addr] ); } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); hostWrite( &vga.mem.linear[addr], val ); MEM_CHANGED( addr ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); hostWrite( &vga.mem.linear[addr], val ); MEM_CHANGED( addr ); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + addr = CHECKED(addr); hostWrite( &vga.mem.linear[addr], val ); MEM_CHANGED( addr ); } @@ -585,7 +635,7 @@ public: } HostPt GetHostReadPt( Bitu phys_page ) { phys_page -= vga.lfb.page; - return &vga.mem.linear[phys_page * 4096]; + return &vga.mem.linear[CHECKED3(phys_page * 4096)]; } HostPt GetHostWritePt( Bitu phys_page ) { return GetHostReadPt( phys_page ); @@ -838,21 +888,45 @@ void VGA_StartUpdateLFB(void) { #else vga.lfb.handler = &vgaph.lfbchanges; #endif - MEM_SetLFB(vga.s3.la_window << 4 ,VGA_MEMORY/4096, vga.lfb.handler, &vgaph.mmio); + MEM_SetLFB(vga.s3.la_window << 4 ,vga.vmemsize/4096, vga.lfb.handler, &vgaph.mmio); } -void VGA_SetupMemory() { - // allocate 16byte-aligned memory - vga.mem.linear = new Bit8u[VGA_MEMORY+16]; - vga.mem.linear=(Bit8u*)(((Bitu)vga.mem.linear + 16-1) & ~(16-1)); - memset( vga.mem.linear, 0, VGA_MEMORY ); +static void VGA_Memory_ShutDown(Section * sec) { + delete[] vga.mem.linear_orgptr; + delete[] vga.fastmem_orgptr; +#ifdef VGA_KEEP_CHANGES + delete[] vga.changes.map; +#endif +} + +void VGA_SetupMemory(Section* sec) { + vga.svga.bank_read = vga.svga.bank_write = 0; + vga.svga.bank_read_full = vga.svga.bank_write_full = 0; + + // We reserve extra 2K for one scan line + vga.mem.linear_orgptr = new Bit8u[vga.vmemsize+2048+16]; + vga.mem.linear=(Bit8u*)(((Bitu)vga.mem.linear_orgptr + 16-1) & ~(16-1)); + memset(vga.mem.linear,0,vga.vmemsize); + + vga.fastmem_orgptr = new Bit8u[(vga.vmemsize<<1)+4096+16]; + vga.fastmem=(Bit8u*)(((Bitu)vga.fastmem_orgptr + 16-1) & ~(16-1)); + + // In most cases these values stay the same. Assumptions: vmemwrap is power of 2, + // vmemwrap <= vmemsize, fastmem implicitly has mem wrap twice as big + vga.vmemwrap = vga.vmemsize; + #ifdef VGA_KEEP_CHANGES memset( &vga.changes, 0, sizeof( vga.changes )); + int changesMapSize = (vga.vmemsize >> VGA_CHANGE_SHIFT) + 32; + vga.changes.map = new Bit8u[changesMapSize]; + memset(vga.changes.map, 0, changesMapSize); #endif vga.svga.bank_read = vga.svga.bank_write = 0; vga.svga.bank_read_full = vga.svga.bank_write_full = 0; vga.svga.bank_size = 0x10000; /* most common bank size is 64K */ + sec->AddDestroyFunction(&VGA_Memory_ShutDown); + if (machine==MCH_PCJR) { /* PCJr does not have dedicated graphics memory but uses conventional memory below 128k */ diff --git a/src/hardware/vga_paradise.cpp b/src/hardware/vga_paradise.cpp index 8a10c76e..6ce124f3 100644 --- a/src/hardware/vga_paradise.cpp +++ b/src/hardware/vga_paradise.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_paradise.cpp,v 1.1 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga_paradise.cpp,v 1.2 2008-01-12 17:37:48 c2woody Exp $ */ #include "dosbox.h" #include "setup.h" @@ -162,10 +162,13 @@ void FinishSetMode_PVGA1A(Bitu /*crtc_base*/, VGA_ModeExtraData* modeData) { if (svga.determine_mode) svga.determine_mode(); - if (vga.mode != M_VGA) - vga.config.compatible_chain4 = false; // in process of verification - else + if(vga.mode != M_VGA) { + vga.config.compatible_chain4 = false; + vga.vmemwrap = vga.vmemsize; + } else { vga.config.compatible_chain4 = true; + vga.vmemwrap = 256*1024; + } VGA_SetupHandlers(); } @@ -195,6 +198,10 @@ Bitu GetClock_PVGA1A() { return pvga1a.clockFreq[(vga.misc_output >> 2) & 3]; } +bool AcceptsMode_PVGA1A(Bitu mode) { + return VideoModeMemSize(mode) < vga.vmemsize; +} + void SVGA_Setup_ParadisePVGA1A(void) { svga.write_p3cf = &write_p3cf_pvga1a; svga.read_p3cf = &read_p3cf_pvga1a; @@ -203,14 +210,26 @@ void SVGA_Setup_ParadisePVGA1A(void) { svga.determine_mode = &DetermineMode_PVGA1A; svga.set_clock = &SetClock_PVGA1A; svga.get_clock = &GetClock_PVGA1A; + svga.accepts_mode = &AcceptsMode_PVGA1A; VGA_SetClock(0,CLK_25); VGA_SetClock(1,CLK_28); VGA_SetClock(2,32400); // could not find documentation VGA_SetClock(3,35900); - // Set memory size at 512K (standard for PVGA1A) - pvga1a.PR1 = 2<<6; + // Adjust memory, default to 512K + if (vga.vmemsize == 0) + vga.vmemsize = 512*1024; + + if (vga.vmemsize < 512*1024) { + vga.vmemsize = 256*1024; + pvga1a.PR1 = 1<<6; + } else if (vga.vmemsize > 512*1024) { + vga.vmemsize = 1024*1024; + pvga1a.PR1 = 3<<6; + } else { + pvga1a.PR1 = 2<<6; + } // Paradise ROM signature PhysPt rom_base=PhysMake(0xc000,0); diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp index 2f5484e6..a927ced5 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.11 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga_s3.cpp,v 1.12 2008-01-12 17:37:48 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -28,6 +28,8 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { //TODO Base address vga.s3.reg_31 = val; vga.config.compatible_chain4 = !(val&0x08); + if (vga.config.compatible_chain4) vga.vmemwrap = 256*1024; + else vga.vmemwrap = vga.vmemsize; vga.config.display_start = (vga.config.display_start&~0x30000)|((val&0x30)<<12); VGA_DetermineMode(); VGA_SetupHandlers(); @@ -312,7 +314,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { } break; case 0x6a: /* Extended System Control 4 */ - vga.svga.bank_read=val & 0x3f; + vga.svga.bank_read=val & 0x7f; vga.svga.bank_write = vga.svga.bank_read; VGA_SetupHandlers(); break; @@ -345,8 +347,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { case 0x35: /* CR35 CRT Register Lock */ return vga.s3.reg_35|(vga.svga.bank_read & 0xf); case 0x36: /* CR36 Reset State Read 1 */ - return 0x92; /* PCI version */ - //2 Mb PCI and some bios settings + return vga.s3.reg_36; case 0x37: /* Reset state read 2 */ return 0x2b; case 0x38: /* CR38 Register Lock 1 */ @@ -403,7 +404,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { case 0x69: /* Extended System Control 3 */ return (Bit8u)((vga.config.display_start & 0x1f0000)>>16); case 0x6a: /* Extended System Control 4 */ - return (Bit8u)(vga.svga.bank_read & 0x3f); + return (Bit8u)(vga.svga.bank_read & 0x7f); case 0x6b: // BIOS scatchpad: LFB address return vga.s3.reg_6b; default: @@ -483,6 +484,10 @@ bool SVGA_S3_HWCursorActive(void) { return (vga.s3.hgc.curmode & 0x1) != 0; } +bool SVGA_S3_AcceptsMode(Bitu mode) { + return VideoModeMemSize(mode) < vga.vmemsize; +} + void SVGA_Setup_S3Trio(void) { svga.write_p3d5 = &SVGA_S3_WriteCRTC; svga.read_p3d5 = &SVGA_S3_ReadCRTC; @@ -496,5 +501,26 @@ void SVGA_Setup_S3Trio(void) { svga.set_clock = 0; /* implemented in core */ svga.get_clock = &SVGA_S3_GetClock; svga.hardware_cursor_active = &SVGA_S3_HWCursorActive; - svga.accepts_mode = 0; /* don't filter modes */ + svga.accepts_mode = &SVGA_S3_AcceptsMode; + + if (vga.vmemsize == 0) + vga.vmemsize = VGA_MEMORY; // the most common S3 configuration + + // Set CRTC 36 to specify amount of VRAM and PCI + if (vga.vmemsize < 1024*1024) { + vga.vmemsize = 512*1024; + vga.s3.reg_36 = 0xf2; + } else if (vga.vmemsize < 2048*1024) { + vga.vmemsize = 1024*1024; + vga.s3.reg_36 = 0xd2; + } else if (vga.vmemsize < 3072*1024) { + vga.vmemsize = 2048*1024; + vga.s3.reg_36 = 0x92; + } else if (vga.vmemsize < 4096*1024) { + vga.vmemsize = 3072*1024; + vga.s3.reg_36 = 0x52; + } else { // Trio64 supported only up to 4M + vga.vmemsize = 4096*1024; + vga.s3.reg_36 = 0x12; + } } diff --git a/src/hardware/vga_tseng.cpp b/src/hardware/vga_tseng.cpp index 3dadc70f..3e86ee51 100644 --- a/src/hardware/vga_tseng.cpp +++ b/src/hardware/vga_tseng.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_tseng.cpp,v 1.1 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: vga_tseng.cpp,v 1.2 2008-01-12 17:37:48 c2woody Exp $ */ #include "dosbox.h" #include "setup.h" @@ -147,6 +147,7 @@ void write_p3d5_et4k(Bitu reg,Bitu val,Bitu iolen) { case 0x37: if (val != et4k.store_3d4_37) { et4k.store_3d4_37 = val; + vga.vmemwrap = ((64*1024)<<((val&8)>>2))<<((val&3)-1); VGA_SetupHandlers(); } break; @@ -340,7 +341,7 @@ void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) { IO_Write(crtc_base,0x33);IO_Write(crtc_base+1,0); IO_Write(crtc_base,0x34);IO_Write(crtc_base+1,0); IO_Write(crtc_base,0x36);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0f); // 1M video ram (0x0e for 512K, 0x0d for 256K) + IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0c|(vga.vmemsize==1024*1024?3:vga.vmemsize==512*1024?2:1)); // Clear ext SEQ IO_Write(0x3c4,0x06);IO_Write(0x3c5,0); IO_Write(0x3c4,0x07);IO_Write(0x3c5,0); @@ -368,6 +369,7 @@ void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) { // Verified (on real hardware and in a few games): Tseng ET4000 used chain4 implementation // different from standard VGA. It was also not limited to 64K in regular mode 13h. vga.config.compatible_chain4 = false; + vga.vmemwrap = vga.vmemsize; VGA_SetupHandlers(); } @@ -396,7 +398,8 @@ Bitu GetClock_ET4K() { } bool AcceptsMode_ET4K(Bitu mode) { - return mode != 0x3d; + return VideoModeMemSize(mode) < vga.vmemsize; +// return mode != 0x3d; } void SVGA_Setup_TsengET4K(void) { @@ -434,6 +437,17 @@ void SVGA_Setup_TsengET4K(void) { IO_RegisterReadHandler(0x3cd,read_p3cd_et4k,IO_MB); IO_RegisterWriteHandler(0x3cd,write_p3cd_et4k,IO_MB); + // Default to 1M of VRAM + if (vga.vmemsize == 0) + vga.vmemsize = 1024*1024; + + if (vga.vmemsize < 512*1024) + vga.vmemsize = 256*1024; + else if (vga.vmemsize < 1024*1024) + vga.vmemsize = 512*1024; + else + vga.vmemsize = 1024*1024; + // Tseng ROM signature PhysPt rom_base=PhysMake(0xc000,0); phys_writeb(rom_base+0x0075,' '); @@ -716,6 +730,7 @@ void FinishSetMode_ET3K(Bitu crtc_base, VGA_ModeExtraData* modeData) { // Verified on functioning (at last!) hardware: Tseng ET3000 is the same as ET4000 when // it comes to chain4 architecture vga.config.compatible_chain4 = false; + vga.vmemwrap = vga.vmemsize; VGA_SetupHandlers(); } @@ -744,7 +759,7 @@ Bitu GetClock_ET3K() { } bool AcceptsMode_ET3K(Bitu mode) { - return mode <= 0x37 && mode != 0x2f; + return mode <= 0x37 && mode != 0x2f && VideoModeMemSize(mode) < vga.vmemsize; } void SVGA_Setup_TsengET3K(void) { @@ -773,6 +788,8 @@ void SVGA_Setup_TsengET3K(void) { IO_RegisterReadHandler(0x3cd,read_p3cd_et3k,IO_MB); IO_RegisterWriteHandler(0x3cd,write_p3cd_et3k,IO_MB); + vga.vmemsize = 512*1024; // Cannot figure how this was supposed to work on the real card + // Tseng ROM signature PhysPt rom_base=PhysMake(0xc000,0); phys_writeb(rom_base+0x0075,' '); diff --git a/src/hardware/vga_xga.cpp b/src/hardware/vga_xga.cpp index d92d6413..1b11b7e0 100644 --- a/src/hardware/vga_xga.cpp +++ b/src/hardware/vga_xga.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_xga.cpp,v 1.11 2008-01-10 20:36:03 c2woody Exp $ */ +/* $Id: vga_xga.cpp,v 1.12 2008-01-12 17:37:48 c2woody Exp $ */ #include #include "dosbox.h" @@ -152,7 +152,7 @@ void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) { Bitu XGA_GetPoint(Bitu x, Bitu y) { Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x; - if(VGA_MEMORY < memaddr) { + if(vga.vmemsize < memaddr) { //LOG_MSG("getpoint mem over: x%d y%d",x,y); return 0; } diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index a3b3cb92..41210be8 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.74 2008-01-09 20:34:51 c2woody Exp $ */ +/* $Id: int10_modes.cpp,v 1.75 2008-01-12 17:37:48 c2woody Exp $ */ #include @@ -368,7 +368,8 @@ static void FinishSetMode(bool clearmem) { case M_LIN16: case M_LIN32: /* Hack we just acess the memory directly */ - memset(vga.mem.linear,0,VGA_MEMORY); + memset(vga.mem.linear,0,vga.vmemsize); + memset(vga.fastmem, 0, vga.vmemsize<<1); } } /* Setup the BIOS */ @@ -1270,3 +1271,50 @@ dac_text16: } return true; } + +Bitu VideoModeMemSize(Bitu mode) { + if (!IS_VGA_ARCH) + return 0; + + VideoModeBlock* modelist = NULL; + + switch (svgaCard) { + case SVGA_TsengET4K: + case SVGA_TsengET3K: + modelist = ModeList_VGA_Tseng; + break; + case SVGA_ParadisePVGA1A: + modelist = ModeList_VGA_Paradise; + break; + default: + modelist = ModeList_VGA; + break; + } + + VideoModeBlock* vmodeBlock = NULL; + Bitu i=0; + while (modelist[i].mode!=0xffff) { + if (modelist[i].mode==mode) { + vmodeBlock = &modelist[i]; + break; + } + i++; + } + if (!vmodeBlock) + return 0; + + switch(vmodeBlock->type) { + case M_LIN4: + return vmodeBlock->swidth*vmodeBlock->sheight/2; + case M_LIN8: + return vmodeBlock->swidth*vmodeBlock->sheight; + case M_LIN15: case M_LIN16: + return vmodeBlock->swidth*vmodeBlock->sheight*2; + case M_LIN32: + return vmodeBlock->swidth*vmodeBlock->sheight*4; + case M_TEXT: + return vmodeBlock->twidth*vmodeBlock->theight*2; + } + // Return 0 for all other types, those always fit in memory + return 0; +} diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp index 0aaf6c06..08d035ce 100644 --- a/src/ints/int10_vesa.cpp +++ b/src/ints/int10_vesa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 The DOSBox Team + * Copyright (C) 2002-2008 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_vesa.cpp,v 1.30 2007-12-10 22:11:13 c2woody Exp $ */ +/* $Id: int10_vesa.cpp,v 1.31 2008-01-12 17:37:48 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,Bit16u(VGA_MEMORY/(64*1024))); // memory size in 64kb blocks + mem_writew(buffer+0x12,(Bit16u)(vga.vmemsize/(64*1024))); // memory size in 64kb blocks return 0x00; } @@ -129,6 +129,9 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) { mode&=0x3fff; // vbe2 compatible, ignore lfb and keep screen content bits if (mode<0x100) return 0x01; + if (svga.accepts_mode) { + if (!svga.accepts_mode(mode)) return 0x01; + } while (ModeList_VGA[i].mode!=0xffff) { if (mode==ModeList_VGA[i].mode) goto foundit; else i++; } @@ -145,12 +148,12 @@ foundit: var_write(&minfo.MemoryModel,3); //ega planar mode modeAttributes = 0x1b; // Color, graphics, no linear buffer - if(pageSize > 512*1024) { // this limitation is not on the real card + if(pageSize > vga.vmemsize/4) { // 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; + Bitu pages = ((vga.vmemsize/4) / pageSize)-1; var_write(&minfo.NumberOfImagePages,pages); } break; @@ -227,13 +230,13 @@ foundit: var_write(&minfo.WinAAttributes,0x7); // Exists/readable/writable if(mblock->type != M_LIN4) - if(pageSize > VGA_MEMORY) { + if(pageSize > vga.vmemsize) { // 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; + Bitu pages = (vga.vmemsize / pageSize)-1; var_write(&minfo.NumberOfImagePages,pages); } @@ -274,7 +277,7 @@ Bit8u VESA_GetSVGAMode(Bit16u & mode) { Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address) { if (window) return 0x1; - if ((address<32)) { + if (((Bit32u)(address)*64*1024type==M_LIN4) { pixels=(vga.config.scan_len*16)/bpp; bytes=vga.config.scan_len*2; - lines = Bit16u(VGA_MEMORY /( bytes*4)); + lines = (Bit16u)(vga.vmemsize /( bytes*4)); } else { pixels=(vga.config.scan_len*8)/bpp; bytes=vga.config.scan_len*8; - lines = Bit16u(VGA_MEMORY / bytes); + lines = (Bit16u)(vga.vmemsize / bytes); } VGA_StartResize(); return 0x0; @@ -465,7 +468,12 @@ void INT10_SetupVESA(void) { int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used); //TODO Maybe add normal vga modes too, but only seems to complicate things while (ModeList_VGA[i].mode!=0xffff) { - if (ModeList_VGA[i].mode>=0x100){ + bool canuse_mode=false; + if (!svga.accepts_mode) canuse_mode=true; + else { + if (svga.accepts_mode(ModeList_VGA[i].mode)) canuse_mode=true; + } + if (ModeList_VGA[i].mode>=0x100 && canuse_mode) { phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode); int10.rom.used+=2; }