diff --git a/include/render.h b/include/render.h index bfb45ba9..49369c22 100644 --- a/include/render.h +++ b/include/render.h @@ -16,7 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#ifndef __RENDER_H +#define __RENDER_H enum RENDER_Operation { OP_None, @@ -25,11 +26,13 @@ enum RENDER_Operation { OP_AdvMame2x, }; -typedef void (* RENDER_Part_Handler)(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); -typedef void (* RENDER_Draw_Handler)(RENDER_Part_Handler part_handler); - -void RENDER_DoUpdate(void); - -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh,RENDER_Draw_Handler draw_handler); +typedef void (* RENDER_Line_Handler)(Bit8u * src); +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh); +bool RENDER_StartUpdate(void); +void RENDER_EndUpdate(void); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); +extern RENDER_Line_Handler RENDER_DrawLine; + +#endif + diff --git a/include/vga.h b/include/vga.h index 3999bfad..c320ac44 100644 --- a/include/vga.h +++ b/include/vga.h @@ -64,9 +64,6 @@ typedef struct { bool chained; /* Enable or Disabled Chain 4 Mode */ bool blinking; /* Attribute bit 7 is blinking */ - bool vline_double; - Bit8u vline_height; - /* Pixel Scrolling */ Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ Bit8u hlines_skip; @@ -94,19 +91,39 @@ typedef struct { typedef struct { bool resizing; + bool drawing; Bitu width; Bitu height; Bitu pitch; - Bitu blank; + Bitu blocks; + Bitu panning; + Bitu address; + Bitu address_add; + Bitu address_line_total; + Bitu address_line; + Bitu lines_total; + Bitu lines_left; + Bitu lines_scaled; + Bitu split_line; + Bitu parts_total; + Bitu parts_lines; + Bitu parts_left; + struct { + Bitu vtotal; + Bitu vstart; + Bitu vend; + Bitu htotal; + Bitu hstart; + Bitu hend; + Bitu parts; + } micro; Bitu scaleh; - bool double_width; - bool double_height; - Bitu lines; + bool double_scan; + bool double_scan_active; Bit8u font_height; Bit8u font[64*1024]; Bitu font1_start; Bitu font2_start; - Bitu rows,cols; struct { Bit8u sline,eline; Bit8u count,delay; @@ -302,6 +319,9 @@ extern Bit32u FillTable[16]; extern Bit32u CGA_2_Table[16]; extern Bit32u CGA_4_Table[256]; extern Bit32u CGA_16_Table[256]; +extern Bit32u TXT_Font_Table[16]; +extern Bit32u TXT_FG_Table[16]; +extern Bit32u TXT_BG_Table[16]; extern Bit32u Expand16Table[4][16]; extern Bit32u Expand16BigTable[0x10000]; diff --git a/include/video.h b/include/video.h index 72151dcc..ced09ad6 100644 --- a/include/video.h +++ b/include/video.h @@ -19,21 +19,8 @@ #ifndef __VIDEO_H #define __VIDEO_H - -enum GFX_MODES { - GFX_8BPP=0, - GFX_15BPP=1, - GFX_16BPP=2, - GFX_24BPP=3, - GFX_32BPP=4, - GFX_YUV=5, - GFX_MODE_SIZE=6 -}; - typedef void (* GFX_ResetCallBack)(void); -typedef void (* GFX_RenderCallBack)(Bit8u * data,Bitu pitch); - struct GFX_PalEntry { Bit8u r; Bit8u g; @@ -46,18 +33,16 @@ struct GFX_PalEntry { void GFX_Events(void); void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); -GFX_MODES GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags); +Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags); Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue); -void GFX_SetSize(Bitu width,Bitu height,GFX_MODES gfx_mode,double scalex,double scaley,GFX_ResetCallBack cb_reset, GFX_RenderCallBack cb_render); +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset); void GFX_Start(void); void GFX_Stop(void); void GFX_SwitchFullScreen(void); - -void GFX_Render_Blit(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); - -void GFX_DoUpdate(void); +bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch); +void GFX_EndUpdate(void); #endif diff --git a/src/gui/render.cpp b/src/gui/render.cpp index b435ddde..2bbfb4b0 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: render.cpp,v 1.22 2004-01-10 14:03:35 qbix79 Exp $ */ +/* $Id: render.cpp,v 1.23 2004-01-28 14:39:05 harekiet Exp $ */ #include #include @@ -60,17 +60,17 @@ static struct { Bitu scalew; Bitu scaleh; double ratio; - RENDER_Draw_Handler draw_handler; } src; struct { Bitu width; Bitu height; Bitu pitch; - GFX_MODES gfx_mode; + Bitu line; + Bitu bpp; RENDER_Operation type; RENDER_Operation want_type; - RENDER_Part_Handler part_handler; - Bit8u * dest; + RENDER_Line_Handler line_handler; + Bit8u * draw; Bit8u * buffer; Bit8u * pixels; } op; @@ -90,16 +90,19 @@ static struct { #if (C_SSHOT) struct { RENDER_Operation type; - Bitu pitch; + Bitu bpp,width,height,line; const char * dir; - Bit8u * buffer; + Bit8u * buffer,* draw; + bool usesrc; } shot; #endif - bool screenshot; bool active; bool aspect; + bool updating; } render; +RENDER_Line_Handler RENDER_DrawLine; + /* Forward declerations */ static void RENDER_ResetPal(void); @@ -112,13 +115,11 @@ static void RENDER_ResetPal(void); #if (C_SSHOT) #include -static void RENDER_ShotDraw(Bit8u * src,Bitu x,Bitu y,Bitu _dx,Bitu _dy) { - Bit8u * dst=render.shot.buffer+render.src.width*y; - for (;_dy>0;_dy--) { - memcpy(dst,src,_dx); - dst+=render.src.width; - src+=render.src.pitch; - } +static void RENDER_ShotDraw(Bit8u * src) { + if (render.shot.usesrc) { + memcpy(render.shot.draw,src,render.shot.line); + render.shot.draw+=render.shot.line; + } else render.op.line_handler(src); } /* Take a screenshot of the data that should be rendered */ @@ -177,8 +178,8 @@ static void TakeScreenShot(Bit8u * bitmap) { png_set_compression_method(png_ptr, 8); png_set_compression_buffer_size(png_ptr, 8192); - if (render.src.bpp==8) { - png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height, + if (render.shot.bpp==8) { + png_set_IHDR(png_ptr, info_ptr, render.shot.width, render.shot.height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i=0;i<256;i++) { @@ -188,14 +189,14 @@ static void TakeScreenShot(Bit8u * bitmap) { } png_set_PLTE(png_ptr, info_ptr, palette,256); } else { - png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + png_set_IHDR(png_ptr, info_ptr, render.shot.width, render.shot.height, + render.shot.bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } /*Allocate an array of scanline pointers*/ - row_pointers=(png_bytep*)malloc(render.src.height*sizeof(png_bytep)); - for (i=0;irender.pal.last) return; Bitu i; - switch (render.op.gfx_mode) { - case GFX_8BPP: + switch (render.op.bpp) { + case 8: GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); break; - case GFX_15BPP: - case GFX_16BPP: + case 16: for (i=render.pal.first;i<=render.pal.last;i++) { Bit8u r=render.pal.rgb[i].red; Bit8u g=render.pal.rgb[i].green; @@ -239,8 +238,8 @@ static void Check_Palette(void) { render.pal.lookup.bpp16[i]=GFX_GetRGB(r,g,b); } break; - case GFX_24BPP: - case GFX_32BPP: + case 24: + case 32: for (i=render.pal.first;i<=render.pal.last;i++) { Bit8u r=render.pal.rgb[i].red; Bit8u g=render.pal.rgb[i].green; @@ -248,17 +247,6 @@ static void Check_Palette(void) { render.pal.lookup.bpp32[i]=GFX_GetRGB(r,g,b); } break; - case GFX_YUV: - for (i=render.pal.first;i<=render.pal.last;i++) { - Bit8u r=render.pal.rgb[i].red; - Bit8u g=render.pal.rgb[i].green; - Bit8u b=render.pal.rgb[i].blue; - Bit8u y = ( 9797*(r) + 19237*(g) + 3734*(b) ) >> 15; - Bit8u u = (18492*((b)-(y)) >> 15) + 128; - Bit8u v = (23372*((r)-(y)) >> 15) + 128; - render.pal.lookup.yuv[i]=(u << 0) | (y << 8) | (v << 16) | (y << 24); - } - break; } /* Setup pal index to startup values */ render.pal.first=256; @@ -278,38 +266,74 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { if (render.pal.last1.0) gfx_scaleh*=render.src.ratio; else gfx_scalew*=(1/render.src.ratio); - GFX_MODES gfx_mode;Bitu gfx_flags; - gfx_mode=GFX_GetBestMode(render.src.bpp,gfx_flags); + Bitu gfx_flags; + Bitu bpp=GFX_GetBestMode(render.src.bpp,gfx_flags); Bitu index; - switch (gfx_mode) { - case GFX_8BPP: index=0;break; - case GFX_15BPP: index=1;break; - case GFX_16BPP: index=1;break; - case GFX_24BPP: index=2;break; - case GFX_32BPP: index=3;break; - case GFX_YUV: index=3;break; + switch (bpp) { + case 8: index=0;break; + case 16:index=1;break; + case 24:index=2;break; + case 32:index=3;break; } /* Initial scaler testing */ switch (render.op.want_type) { @@ -358,7 +378,7 @@ normalop: if (gfx_flags & GFX_HASSCALING) { gfx_scalew*=scalew; gfx_scaleh*=scaleh; - render.op.part_handler=Normal_SINGLE_8[index]; + render.op.line_handler=Normal_8[index]; for (Bitu i=0;i1 && (render.op.type==OP_None)) { - render.op.part_handler=Normal_SINGLE_8[index]; + render.op.line_handler=Normal_8[index]; scalew>>=1;gfx_scaleh/=2; } else { - render.op.part_handler=Normal_DOUBLE_8[index]; + render.op.line_handler=Normal_2x_8[index]; } - } else render.op.part_handler=Normal_SINGLE_8[index]; + } else render.op.line_handler=Normal_8[index]; width*=scalew; double lines=0.0; gfx_scaleh=(gfx_scaleh*render.src.height-(double)render.src.height)/(double)render.src.height; @@ -426,24 +446,24 @@ normalop: break; } } - render.op.part_handler=AdvMame2x_8_Table[index]; + render.op.line_handler=AdvMame2x_8_Table[index]; } break; } - render.op.gfx_mode=gfx_mode; + render.op.bpp=bpp; render.op.width=width; render.op.height=height; - GFX_SetSize(width,height,gfx_mode,gfx_scalew,gfx_scaleh,&RENDER_ReInit,RENDER_DrawScreen); + GFX_SetSize(width,height,bpp,gfx_scalew,gfx_scaleh,&RENDER_ReInit); RENDER_ResetPal(); - GFX_Start(); + render.active=true; } -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh,RENDER_Draw_Handler draw_handler) { +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh) { if ((!width) || (!height) || (!pitch)) { - render.active=false;return; + render.active=false; + return; } - GFX_Stop(); render.src.width=width; render.src.height=height; render.src.bpp=bpp; @@ -451,9 +471,7 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu render.src.ratio=render.aspect ? ratio : 1.0; render.src.scalew=scalew; render.src.scaleh=scaleh; - render.src.draw_handler=draw_handler; RENDER_ReInit(); - } extern void GFX_SetTitle(Bits cycles, Bits frameskip); @@ -477,8 +495,10 @@ void RENDER_Init(Section * sec) { render.aspect=section->Get_bool("aspect"); render.frameskip.max=section->Get_int("frameskip"); render.frameskip.count=0; + render.updating=true; #if (C_SSHOT) render.shot.dir=section->Get_string("snapdir"); + render.shot.usesrc=true; KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot); #endif const char * scaler;std::string cline; diff --git a/src/gui/render_normal.h b/src/gui/render_normal.h index 20aded8d..95ae4ea9 100644 --- a/src/gui/render_normal.h +++ b/src/gui/render_normal.h @@ -19,46 +19,41 @@ static Bit8u normal_cache[RENDER_MAXWIDTH*2*4]; template -static void Normal(Bit8u * src,Bitu x,Bitu y,Bitu _dx,Bitu _dy) { - Bit8u * dst=render.op.pixels+(render.normal.hindex[y]*render.op.pitch); - Bitu line_size=LineSize(_dx) * (xdouble ? 2 : 1); - src+=x; +static void Normal(Bit8u * src) { + Bitu line_size=LineSize(render.src.width) * (xdouble ? 2 : 1); Bit8u * line; - for (;_dy;_dy--) { - if (sbpp == dbpp && !xdouble) { - line=src; - BituMove(dst,line,line_size); - } else { - Bit8u * line_dst=&normal_cache[0]; - Bit8u * real_dst=dst; - line=line_dst; - Bit8u * temp_src=src; - for (Bitu tempx=_dx;tempx;tempx--) { - Bitu val=ConvBPP(LoadSrc(temp_src)); + if (sbpp == dbpp && !xdouble) { + line=src; + BituMove(render.op.pixels,line,line_size); + } else { + Bit8u * line_dst=&normal_cache[0]; + Bit8u * real_dst=render.op.pixels; + line=line_dst; + Bit8u * temp_src=src; + for (Bitu tempx=render.src.width;tempx;tempx--) { + Bitu val=ConvBPP(LoadSrc(temp_src)); + AddDst(line_dst,val); + AddDst(real_dst,val); + if (xdouble) { AddDst(line_dst,val); AddDst(real_dst,val); - if (xdouble) { - AddDst(line_dst,val); - AddDst(real_dst,val); - } } } - dst+=render.op.pitch; - for (Bitu lines=render.normal.hlines[y++];lines;lines--) { - BituMove(dst,line,line_size); - dst+=render.op.pitch; - } - src+=render.src.pitch; + } + render.op.pixels+=render.op.pitch; + for (Bitu lines=render.normal.hlines[render.op.line++];lines;lines--) { + BituMove(render.op.pixels,line,line_size); + render.op.pixels+=render.op.pitch; } } -static RENDER_Part_Handler Normal_SINGLE_8[4]={ +static RENDER_Line_Handler Normal_8[4]={ Normal<8,8 ,false>,Normal<8,16,false>, Normal<8,24,false>,Normal<8,32,false>, }; -static RENDER_Part_Handler Normal_DOUBLE_8[4]={ +static RENDER_Line_Handler Normal_2x_8[4]={ Normal<8,8 ,true>,Normal<8,16,true>, Normal<8,24,true>,Normal<8,32,true>, }; diff --git a/src/gui/render_scale2x.h b/src/gui/render_scale2x.h index fcbc16f7..fc92a0ae 100644 --- a/src/gui/render_scale2x.h +++ b/src/gui/render_scale2x.h @@ -53,23 +53,24 @@ static void AdvMame2x_line(Bit8u * dst, const Bit8u * src0, const Bit8u * src1, } template -static void AdvMame2x(Bit8u * src,Bitu x,Bitu y,Bitu _dx,Bitu _dy) { +static void AdvMame2x(Bit8u * src) { +#if 0 _dy=render.advmame2x.hindex[y+_dy]; y=render.advmame2x.hindex[y]; Bit8u * dest=render.op.pixels+render.op.pitch*y; src-=render.advmame2x.line_starts[y][0]; - src+=x; for (;y<_dy;y++) { Bit8u * src0=src+render.advmame2x.line_starts[y][0]; Bit8u * src1=src+render.advmame2x.line_starts[y][1]; Bit8u * src2=src+render.advmame2x.line_starts[y][2]; - AdvMame2x_line(dest,src0,src1,src2,_dx); + AdvMame2x_line(dest,src0,src1,src2,render.src.width); dest+=render.op.pitch; } +#endif } -static RENDER_Part_Handler AdvMame2x_8_Table[4]={ +static RENDER_Line_Handler AdvMame2x_8_Table[4]={ AdvMame2x<8,8>,AdvMame2x<8,16>,AdvMame2x<8,24>,AdvMame2x<8,32> }; diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 7fc8ecb0..52336849 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdlmain.cpp,v 1.55 2004-01-08 11:47:26 qbix79 Exp $ */ +/* $Id: sdlmain.cpp,v 1.56 2004-01-28 14:39:05 harekiet Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -28,9 +28,7 @@ #include #include - #include "SDL.h" -#include "SDL_thread.h" #include "dosbox.h" #include "video.h" @@ -40,10 +38,43 @@ #include "pic.h" #include "timer.h" #include "setup.h" +#include "support.h" #include "debug.h" +#if C_OPENGL +#include "SDL_opengl.h" + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifdef __WIN32__ +#ifndef WGL_NV_allocate_memory +#define WGL_NV_allocate_memory 1 +typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); +typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); +PFNWGLALLOCATEMEMORYNVPROC db_glAllocateMemoryNV = NULL; +PFNWGLFREEMEMORYNVPROC db_glFreeMemoryNV = NULL; +#endif +#else + + +#endif + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL; +#endif + +#endif //C_OPENGL + //#define DISABLE_JOYSTICK -#define C_GFXTHREADED 1 //Enabled by default #if !(ENVIRON_INCLUDED) extern char** environ; @@ -72,17 +103,14 @@ enum SCREEN_TYPES { struct SDL_Block { - volatile bool active; //If this isn't set don't draw - volatile bool drawing; + bool active; //If this isn't set don't draw + bool updating; struct { Bit32u width; Bit32u height; - GFX_MODES gfx_mode; + Bitu bpp; double scalex,scaley; - struct { - GFX_ResetCallBack reset; - GFX_RenderCallBack render; - } cb; + GFX_ResetCallBack reset; } draw; bool wait_on_error; struct { @@ -91,19 +119,28 @@ struct SDL_Block { bool fullscreen; bool doublebuf; SCREEN_TYPES type; + SCREEN_TYPES want_type; + double hwscale; } desktop; +#if C_OPENGL + struct { + Bitu pitch; + void * framebuf; + GLuint texture; + GLuint displaylist; + GLint max_texsize; + bool packed_pixel; + bool paletted_texture; +#ifdef GL_NV_pixel_data_range + bool pixel_data_range; +#endif + } opengl; +#endif SDL_Rect clip; SDL_Surface * surface; SDL_Overlay * overlay; SDL_Joystick * joy; SDL_cond *cond; -#if C_GFXTHREADED - SDL_mutex *mutex; - SDL_Thread *thread; - SDL_sem *sem; - volatile bool kill_thread; -#endif - struct { bool autolock; bool autoenable; @@ -127,62 +164,59 @@ void GFX_SetTitle(Bits cycles,Bits frameskip){ } /* Reset the screen with current values in the sdl structure */ -GFX_MODES GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags) { - GFX_MODES gfx_mode;gfx_flags=0; - switch (sdl.desktop.type) { +Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags) { + gfx_flags=0; + switch (sdl.desktop.want_type) { case SCREEN_SURFACE: - Bitu what_bpp; if (sdl.desktop.fullscreen) { - what_bpp=SDL_VideoModeOK(640,480,bpp,SDL_FULLSCREEN|SDL_HWSURFACE | + bpp=SDL_VideoModeOK(640,480,bpp,SDL_FULLSCREEN|SDL_HWSURFACE | (sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0) | ((bpp==8) ? SDL_HWPALETTE : 0) ); } else { - what_bpp=sdl.desktop.bpp; + bpp=sdl.desktop.bpp; } gfx_flags|=GFX_HASCONVERT; - switch (what_bpp) { - case 8: gfx_mode=GFX_8BPP;break; - case 15: gfx_mode=GFX_15BPP;break; - case 16: gfx_mode=GFX_16BPP;break; - case 24: gfx_mode=GFX_24BPP;break; - case 32: gfx_mode=GFX_32BPP;break; - } break; case SCREEN_OVERLAY: - gfx_mode=GFX_YUV; + bpp=32; gfx_flags|=GFX_HASSCALING; + break; +#if C_OPENGL + case SCREEN_OPENGL: + bpp=32; + gfx_flags|=GFX_HASSCALING; + break; +#endif } - return gfx_mode; + return bpp; } static void ResetScreen(void) { GFX_Stop(); - if (sdl.draw.cb.reset) (sdl.draw.cb.reset)(); + if (sdl.draw.reset) (sdl.draw.reset)(); GFX_Start(); } -void GFX_SetSize(Bitu width,Bitu height,GFX_MODES gfx_mode,double scalex,double scaley,GFX_ResetCallBack cb_reset, GFX_RenderCallBack cb_render) { - GFX_Stop(); +static int int_log2 (int val) { + int log = 0; + while ((val >>= 1) != 0) + log++; + return log; +} + +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack reset) { + if (sdl.updating) GFX_EndUpdate(); sdl.draw.width=width; sdl.draw.height=height; - sdl.draw.gfx_mode=gfx_mode; - sdl.draw.cb.render=cb_render; - sdl.draw.cb.reset=cb_reset; + sdl.draw.bpp=bpp; + sdl.draw.reset=reset; sdl.draw.scalex=scalex; sdl.draw.scaley=scaley; - Bitu bpp; - switch (gfx_mode) { - case GFX_8BPP:bpp=8;break; - case GFX_15BPP:bpp=15;break; - case GFX_16BPP:bpp=16;break; - case GFX_24BPP:bpp=24;break; - case GFX_32BPP:bpp=32;break; - case GFX_YUV:bpp=0;break; - } - switch (sdl.desktop.type) { + switch (sdl.desktop.want_type) { case SCREEN_SURFACE: dosurface: + sdl.desktop.type=SCREEN_SURFACE; sdl.clip.w=width; sdl.clip.h=height; if (sdl.desktop.fullscreen) { @@ -204,7 +238,7 @@ dosurface: case SCREEN_OVERLAY: if (sdl.overlay) SDL_FreeYUVOverlay(sdl.overlay); sdl.overlay=0; - if (gfx_mode!=GFX_YUV) goto dosurface; + if (bpp!=32) goto dosurface; if (sdl.desktop.fullscreen) { if (sdl.desktop.fixed) { double ratio_w=(double)sdl.desktop.width/(width*scalex); @@ -218,22 +252,132 @@ dosurface: } sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp,SDL_FULLSCREEN|SDL_HWSURFACE); + sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, + SDL_FULLSCREEN|SDL_HWSURFACE); } else { sdl.clip.x=0;sdl.clip.y=0; sdl.clip.w=(Bit16u)(width*scalex); sdl.clip.h=(Bit16u)(height*scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,SDL_FULLSCREEN|SDL_HWSURFACE); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_FULLSCREEN|SDL_HWSURFACE); } } else { sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(width*scalex); - sdl.clip.h=(Bit16u)(height*scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,SDL_HWSURFACE); + sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); + sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0,SDL_HWSURFACE); } sdl.overlay=SDL_CreateYUVOverlay(width*2,height,SDL_UYVY_OVERLAY,sdl.surface); + if (!sdl.overlay) { + LOG_MSG("SDL:Failed to create overlay, switching back to surface"); + goto dosurface; + } + sdl.desktop.type=SCREEN_OVERLAY; break; - } +#if C_OPENGL + case SCREEN_OPENGL: + { + if (sdl.opengl.framebuf) db_glFreeMemoryNV(sdl.opengl.framebuf); + sdl.opengl.framebuf=0; + if (bpp!=32) goto dosurface; + int texsize=2 << int_log2(width > height ? width : height); + if (texsize>sdl.opengl.max_texsize) { + LOG_MSG("SDL:OPENGL:No support for texturesize of %d, falling back to surface",texsize); + goto dosurface; + } + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + if (sdl.desktop.fullscreen) { + if (sdl.desktop.fixed) { + double ratio_w=(double)sdl.desktop.width/(width*scalex); + double ratio_h=(double)sdl.desktop.height/(height*scaley); + if ( ratio_w < ratio_h) { + sdl.clip.w=(Bit16u)sdl.desktop.width; + sdl.clip.h=(Bit16u)(height*scaley*ratio_w); + } else { + sdl.clip.w=(Bit16u)(width*scalex*ratio_h); + sdl.clip.h=(Bit16u)sdl.desktop.height; + } + sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); + sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); + sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, + SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex); + sdl.clip.h=(Bit16u)(height*scaley); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); + } + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); + sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_OPENGL|SDL_HWSURFACE); + } + if (!sdl.surface || sdl.surface->format->BitsPerPixel<15) { + LOG_MSG("SDL:OPENGL:Can't open drawing surface, are you running in 16bpp(or higher) mode?"); + goto dosurface; + } + /* Create the texture and display list */ +#ifdef GL_NV_pixel_data_range + if (sdl.opengl.pixel_data_range) { + sdl.opengl.framebuf=db_glAllocateMemoryNV(width*height*4,0.0,1.0,1.0); + glPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV,width*height*4,sdl.opengl.framebuf); + glEnableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV); + } else { +#else + { +#endif + sdl.opengl.framebuf=malloc(width*height*4); //32 bit color + } + sdl.opengl.pitch=width*4; + glMatrixMode (GL_PROJECTION); + glDeleteTextures(1,&sdl.opengl.texture); + glGenTextures(1,&sdl.opengl.texture); + glBindTexture(GL_TEXTURE_2D,sdl.opengl.texture); + // No borders + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + // Bilinear filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texsize, texsize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); + + glClearColor (1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glShadeModel (GL_FLAT); + glDisable (GL_DEPTH_TEST); + glDisable (GL_LIGHTING); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + GLfloat tex_width=((GLfloat)(width)/(GLfloat)texsize); + GLfloat tex_height=((GLfloat)(height)/(GLfloat)texsize); + + if (glIsList(sdl.opengl.displaylist)) glDeleteLists(sdl.opengl.displaylist, 1); + sdl.opengl.displaylist = glGenLists(1); + glNewList(sdl.opengl.displaylist, GL_COMPILE); + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + glBegin(GL_QUADS); + // lower left + glTexCoord2f(0,tex_height); glVertex2f(-1.0f,-1.0f); + // lower right + glTexCoord2f(tex_width,tex_height); glVertex2f(1.0f, -1.0f); + // upper right + glTexCoord2f(tex_width,0); glVertex2f(1.0f, 1.0f); + // upper left + glTexCoord2f(0,0); glVertex2f(-1.0f, 1.0f); + glEnd(); + glEndList(); + sdl.desktop.type=SCREEN_OPENGL; + break; + }//OPENGL +#endif //C_OPENGL + }//CASE GFX_Start(); } @@ -252,7 +396,6 @@ static void CaptureMouse(void) { static void SwitchFullScreen(void) { sdl.desktop.fullscreen=!sdl.desktop.fullscreen; if (sdl.desktop.fullscreen) { -//TODO Give an resize event if (!sdl.mouse.locked) CaptureMouse(); } else { if (sdl.mouse.locked) CaptureMouse(); @@ -264,73 +407,68 @@ void GFX_SwitchFullScreen(void) { SwitchFullScreen(); } - -static void SDL_DrawScreen(void) { - Bit8u * pixels;Bitu pitch; - sdl.drawing=true; +bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { + if (!sdl.active || sdl.updating) return false; + sdl.updating=true; switch (sdl.desktop.type) { case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { if (SDL_LockSurface(sdl.surface)) { LOG_MSG("SDL Lock failed"); - sdl.drawing=false; - return; + sdl.updating=false; + return false; } } pixels=(Bit8u *)sdl.surface->pixels; pixels+=sdl.clip.y*sdl.surface->pitch; pixels+=sdl.clip.x*sdl.surface->format->BytesPerPixel; - sdl.draw.cb.render(pixels,sdl.surface->pitch); + pitch=sdl.surface->pitch; + return true; + case SCREEN_OVERLAY: + SDL_LockYUVOverlay(sdl.overlay); + pixels=(Bit8u *)*(sdl.overlay->pixels); + pitch=*(sdl.overlay->pitches); + return true; +#if C_OPENGL + case SCREEN_OPENGL: + pixels=(Bit8u *)sdl.opengl.framebuf; + pitch=sdl.opengl.pitch; + return true; +#endif + } + return false; +} + +void GFX_EndUpdate(void) { + if (!sdl.updating) return; + sdl.updating=false; + switch (sdl.desktop.type) { + case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { SDL_UnlockSurface(sdl.surface); } SDL_Flip(sdl.surface); break; case SCREEN_OVERLAY: - SDL_LockYUVOverlay(sdl.overlay); - pixels=(Bit8u *)*(sdl.overlay->pixels); - pitch=*(sdl.overlay->pitches); - sdl.draw.cb.render(pixels,pitch); SDL_UnlockYUVOverlay(sdl.overlay); SDL_DisplayYUVOverlay(sdl.overlay,&sdl.clip); - - } - sdl.drawing=false; -} - -#if C_GFXTHREADED -int SDL_DisplayThread(void * data) { - while (!SDL_SemWait(sdl.sem)) { - if (sdl.kill_thread) return 0; - if (!sdl.active) continue; - if (sdl.drawing) continue; - SDL_mutexP(sdl.mutex); - SDL_DrawScreen(); - SDL_mutexV(sdl.mutex); - } - return 0; -} -#endif - -void GFX_DoUpdate(void) { - if (!sdl.active) - return; - if (sdl.drawing)return; -#if C_GFXTHREADED - SDL_SemPost(sdl.sem); -#else - SDL_DrawScreen(); + break; +#if C_OPENGL + case SCREEN_OPENGL: + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + sdl.draw.width, sdl.draw.height, GL_BGRA_EXT, + GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf); + glCallList(sdl.opengl.displaylist); + SDL_GL_SwapBuffers(); + break; #endif + } } void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { -#if C_GFXTHREADED - if (SDL_mutexP(sdl.mutex)) { - E_Exit("SDL:Can't lock Mutex"); - }; -#endif /* I should probably not change the GFX_PalEntry :) */ if (sdl.surface->flags & SDL_HWPALETTE) { if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) { @@ -341,26 +479,29 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { E_Exit("SDL:Can't set palette"); } } -#if C_GFXTHREADED - if (SDL_mutexV(sdl.mutex)) { - E_Exit("SDL:Can't release Mutex"); - }; -#endif } Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { - return SDL_MapRGB(sdl.surface->format,red,green,blue); + switch (sdl.desktop.type) { + case SCREEN_SURFACE: + return SDL_MapRGB(sdl.surface->format,red,green,blue); + case SCREEN_OVERLAY: + { + Bit8u y = ( 9797*(red) + 19237*(green) + 3734*(blue) ) >> 15; + Bit8u u = (18492*((blue)-(y)) >> 15) + 128; + Bit8u v = (23372*((red)-(y)) >> 15) + 128; + return (u << 0) | (y << 8) | (v << 16) | (y << 24); + } + case SCREEN_OPENGL: +// return ((red << 0) | (green << 8) | (blue << 16)) | (255 << 24); + //USE BGRA + return ((blue << 0) | (green << 8) | (red << 16)) | (255 << 24); + } + return 0; } void GFX_Stop() { -#if C_GFXTHREADED - SDL_mutexP(sdl.mutex); -#endif sdl.active=false; -#if C_GFXTHREADED - SDL_mutexV(sdl.mutex); -#endif - } void GFX_Start() { @@ -371,14 +512,6 @@ static void GUI_ShutDown(Section * sec) { GFX_Stop(); if (sdl.mouse.locked) CaptureMouse(); if (sdl.desktop.fullscreen) SwitchFullScreen(); -#if C_GFXTHREADED - sdl.kill_thread=true; - SDL_SemPost(sdl.sem); - SDL_WaitThread(sdl.thread,0); - SDL_DestroyMutex(sdl.mutex); - SDL_DestroySemaphore(sdl.sem); -#endif - } static void KillSwitch(void){ @@ -389,6 +522,7 @@ static void GUI_StartUp(Section * sec) { sec->AddDestroyFunction(&GUI_ShutDown); Section_prop * section=static_cast(sec); sdl.active=false; + sdl.updating=false; sdl.desktop.fullscreen=section->Get_bool("fullscreen"); sdl.wait_on_error=section->Get_bool("waitonerror"); sdl.mouse.locked=false; @@ -397,6 +531,7 @@ static void GUI_StartUp(Section * sec) { sdl.desktop.width=section->Get_int("fullwidth"); sdl.desktop.height=section->Get_int("fullheight"); sdl.desktop.doublebuf=section->Get_bool("fulldouble"); + sdl.desktop.hwscale=1.2; if (!sdl.desktop.width) { #ifdef WIN32 sdl.desktop.width=GetSystemMetrics(SM_CXSCREEN); @@ -414,17 +549,39 @@ static void GUI_StartUp(Section * sec) { sdl.mouse.autoenable=section->Get_bool("autolock"); sdl.mouse.autolock=false; sdl.mouse.sensitivity=section->Get_int("sensitivity"); - if (section->Get_bool("overlay")) { - sdl.desktop.type=SCREEN_OVERLAY; + const char * output=section->Get_string("output"); + if (!strcasecmp(output,"surface")) { + sdl.desktop.want_type=SCREEN_SURFACE; + } else if (!strcasecmp(output,"overlay")) { + sdl.desktop.want_type=SCREEN_OVERLAY; +#if C_OPENGL + } else if (!strcasecmp(output,"opengl")) { + sdl.desktop.want_type=SCREEN_OPENGL; +#endif } else { - sdl.desktop.type=SCREEN_SURFACE; + LOG_MSG("SDL:Unsupported output device %s, switching back to surface",output); + sdl.desktop.want_type=SCREEN_SURFACE; } + sdl.overlay=0; -#if C_GFXTHREADED - sdl.kill_thread=false; - sdl.mutex=SDL_CreateMutex(); - sdl.sem=SDL_CreateSemaphore(0); - sdl.thread=SDL_CreateThread(&SDL_DisplayThread,0); +#if C_OPENGL + sdl.surface=SDL_SetVideoMode(640,400,0,SDL_OPENGL); + sdl.opengl.framebuf=0; + sdl.opengl.texture=0; + sdl.opengl.displaylist=0; + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &sdl.opengl.max_texsize); +#if defined(__WIN32__) + glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC) wglGetProcAddress("glPixelDataRangeNV"); + db_glAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC) wglGetProcAddress("wglAllocateMemoryNV"); + db_glFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) wglGetProcAddress("wglFreeMemoryNV"); +#endif + const char * gl_ext = (const char *)glGetString (GL_EXTENSIONS); + sdl.opengl.packed_pixel=strstr(gl_ext,"EXT_packed_pixels") > 0; + sdl.opengl.paletted_texture=strstr(gl_ext,"EXT_paletted_texture") > 0; +#ifdef GL_NV_pixel_data_range + sdl.opengl.pixel_data_range=strstr(gl_ext,"GL_NV_pixel_data_range") >0 && + glPixelDataRangeNV; +#endif #endif /* Initialize screen for first time */ sdl.surface=SDL_SetVideoMode(640,400,0,0); @@ -432,7 +589,7 @@ static void GUI_StartUp(Section * sec) { if (sdl.desktop.bpp==24) { LOG_MSG("SDL:You are running in 24 bpp mode, this will slow down things!"); } - GFX_SetSize(640,400,GFX_8BPP,1.0,1.0,0,0); + GFX_SetSize(640,400,8,1.0,1.0,0); SDL_EnableKeyRepeat(250,30); SDL_EnableUNICODE(1); /* Get some Keybinds */ @@ -744,20 +901,28 @@ int main(int argc, char* argv[]) { sdl_sec->Add_bool("fullfixed",false); sdl_sec->Add_int("fullwidth",0); sdl_sec->Add_int("fullheight",0); - sdl_sec->Add_bool("overlay",false); + sdl_sec->Add_string("output","surface"); + sdl_sec->Add_string("hwscale","1.0"); sdl_sec->Add_bool("autolock",true); sdl_sec->Add_int("sensitivity",100); sdl_sec->Add_bool("waitonerror",true); - /* Init all the dosbox subsystems */ MSG_Add("SDL_CONFIGFILE_HELP", "fullscreen -- Start dosbox directly in fullscreen.\n" + "fulldouble -- Use double buffering in fullscreen.\n" + "fullfixed -- Don't resize the screen when in fullscreen.\n" + "fullwidth/height -- What resolution to use for fullscreen, use together with fullfixed.\n" + "output -- What to use for output: surface,overlay" +#if C_OPENGL + ",opengl" +#endif + ".\n" + "hwscale -- Extra scaling of window if the output devive supports hardware scaling.\n" "autolock -- Mouse will automatically lock, if you click on the screen.\n" "sensitiviy -- Mouse sensitivity.\n" "waitonerror -- Wait before closing the console if dosbox has an error.\n" ); - - + /* Init all the dosbox subsystems */ DOSBOX_Init(); std::string config_file; if (control->cmdline->FindString("-conf",config_file,true)) { diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 78631c6a..3b9c3255 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -31,10 +31,14 @@ VGA_Type vga; Bit32u CGA_2_Table[16]; Bit32u CGA_4_Table[256]; Bit32u CGA_16_Table[256]; +Bit32u TXT_Font_Table[16]; +Bit32u TXT_FG_Table[16]; +Bit32u TXT_BG_Table[16]; Bit32u ExpandTable[256]; Bit32u Expand16Table[4][16]; -Bit32u Expand16BigTable[0x10000]; Bit32u FillTable[16]; +Bit32u ColorTable[16]; + void VGA_SetMode(VGAModes mode) { @@ -107,18 +111,34 @@ void VGA_Init(Section* sec) { #endif } for (i=0;i<16;i++) { + TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); + TXT_BG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); + #ifdef WORDS_BIGENDIAN CGA_2_Table[i]=((i>>0)&1) | (((i>>1)&1) << 8)| (((i>>1)&1) <<16) | (((i>>3)&1) << 24); - FillTable[i]= ((i & 1) ? 0xff000000 : 0) | + FillTable[i]= + ((i & 1) ? 0xff000000 : 0) | ((i & 2) ? 0x00ff0000 : 0) | - ((i & 4) ? 0x0000ff00 : 0) | - ((i & 8) ? 0x000000ff : 0) ; + ((i & 4) ? 0x0000ff00 : 0) | + ((i & 8) ? 0x000000ff : 0) ; + TXT_Font_Table[i]= + ((i & 1) ? 0x000000ff : 0) | + ((i & 2) ? 0x0000ff00 : 0) | + ((i & 4) ? 0x00ff0000 : 0) | + ((i & 8) ? 0xff000000 : 0) ; #else CGA_2_Table[i]=((i>>3)&1) | (((i>>2)&1) << 8)| (((i>>1)&1) <<16) | (((i>>0)&1) << 24); - FillTable[i]= ((i & 1) ? 0x000000ff : 0) | - ((i & 2) ? 0x0000ff00 : 0) | - ((i & 4) ? 0x00ff0000 : 0) | - ((i & 8) ? 0xff000000 : 0) ; + FillTable[i]= + ((i & 1) ? 0x000000ff : 0) | + ((i & 2) ? 0x0000ff00 : 0) | + ((i & 4) ? 0x00ff0000 : 0) | + ((i & 8) ? 0xff000000 : 0) ; + TXT_Font_Table[i]= + ((i & 1) ? 0xff000000 : 0) | + ((i & 2) ? 0x00ff0000 : 0) | + ((i & 4) ? 0x0000ff00 : 0) | + ((i & 8) ? 0x000000ff : 0) ; + #endif } for (j=0;j<4;j++) { @@ -138,28 +158,5 @@ void VGA_Init(Section* sec) { #endif } } - for (i=0;i<0x10000;i++) { - Bit32u val=0; - if (i & 0x1) val|=0x1 << 24; - if (i & 0x2) val|=0x1 << 16; - if (i & 0x4) val|=0x1 << 8; - if (i & 0x8) val|=0x1 << 0; - - if (i & 0x10) val|=0x4 << 24; - if (i & 0x20) val|=0x4 << 16; - if (i & 0x40) val|=0x4 << 8; - if (i & 0x80) val|=0x4 << 0; - - if (i & 0x100) val|=0x2 << 24; - if (i & 0x200) val|=0x2 << 16; - if (i & 0x400) val|=0x2 << 8; - if (i & 0x800) val|=0x2 << 0; - - if (i & 0x1000) val|=0x8 << 24; - if (i & 0x2000) val|=0x8 << 16; - if (i & 0x4000) val|=0x8 << 8; - if (i & 0x8000) val|=0x8 << 0; - Expand16BigTable[i]=val; - } } diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index 8152fe31..e957f8ec 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -127,8 +127,6 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x09: /* Maximum Scan Line Register */ - vga.config.vline_double=(val & 128)>1; - vga.config.vline_height=(val & 0xf); vga.config.line_compare=(vga.config.line_compare & 0x5ff)|(val&0x40)<<3; if ((vga.crtc.maximum_scan_line ^ val) & 0xbf) { crtc(maximum_scan_line)=val; diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 0843f384..75731ad2 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -17,73 +17,50 @@ */ #include +#include #include "dosbox.h" #include "video.h" #include "render.h" #include "vga.h" #include "pic.h" -//TODO Make the full draw like the vga really does from video memory. +#define VGA_PARTS 4 -#define FIXED_CGA_SIZED 1 +static Bit8u VGA_DrawBuffer[2048]; -static void VGA_HERC_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[0]; - for (Bitu y=0;y>3;x>0;x--) { - Bit8u val=*(tempread++); - *(Bit32u *)(draw+0)=CGA_2_Table[val >> 4]; - *(Bit32u *)(draw+4)=CGA_2_Table[val & 0xf]; - draw+=8; - } - if ((y & 3)==3) reader+=90; - bitdata+=pitch; +typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart,Bitu panning,Bitu line); + +static VGA_Line_Handler VGA_DrawLine; + +static Bit8u * VGA_HERC_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)&VGA_DrawBuffer[0]; + for (Bitu x=vga.draw.blocks;x>0;x--) { + Bitu val=*reader++; + *draw++=CGA_2_Table[val >> 4]; + *draw++=CGA_2_Table[val & 0xf]; } + return VGA_DrawBuffer; } -static void VGA_CGA2_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[0]; - Bit8u * flip=&vga.mem.linear[8*1024]; - Bit8u * draw; - for (Bitu y=0;y>3;x>0;x--) { - Bit8u val=*(tempread++); - *(Bit32u *)(draw+0)=CGA_2_Table[val >> 4]; - *(Bit32u *)(draw+4)=CGA_2_Table[val & 0xf]; - draw+=8; - } - bitdata+=pitch; +static Bit8u * VGA_CGA2_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)&VGA_DrawBuffer[0]; + for (Bitu x=vga.draw.blocks;x>0;x--) { + Bitu val=*reader++; + *draw++=CGA_2_Table[val >> 4]; + *draw++=CGA_2_Table[val & 0xf]; } + return VGA_DrawBuffer; } -static void VGA_CGA4_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[0]; - Bit8u * flip=&vga.mem.linear[8*1024]; - Bit8u * draw; - for (Bitu y=0;y=flip) reader-=8*1024; - } - draw=bitdata; - for (Bitu x=0;x>2;x++) { - Bit8u val=*(tempread++); - *(Bit32u *)draw=CGA_4_Table[val]; - draw+=4; - } - bitdata+=pitch; +static Bit8u * VGA_CGA4_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)&VGA_DrawBuffer[0]; + for (Bitu x=0;x=flip) reader-=8*1024; - } - draw=bitdata; - for (Bitu x=0;x<80;x++) { - Bit8u val=*(tempread++); - - Bit32u full=convert16[(val & 0xf0) >> 4] | convert16[val & 0xf] << 16; - full|=full<<8; - *(Bit32u *)draw=full; - draw+=4; - } - bitdata+=pitch; +static Bit8u * VGA_CGA16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)&VGA_DrawBuffer[0]; + for (Bitu x=0;x> 4] | convert16[val & 0xf] << 16; + *draw++=full|=full<<8; } + return VGA_DrawBuffer; } -static void VGA_TANDY16_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vga.config.display_start*2]; - - for (Bitu y=0;y>2;x++) { - Bit8u val1=*(tempread++); - Bit8u val2=*(tempread++); - Bit32u full=(val1 & 0x0f) << 8 | - (val1 & 0xf0) >> 4 | - (val2 & 0x0f) << 24 | - (val2 & 0xf0) << 12; - *(Bit32u *)draw=full; - draw+=4; - } - bitdata+=pitch; - if ((y & 3)==3)reader+=160; +static Bit8u * VGA_TANDY16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vidstart + (line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)&VGA_DrawBuffer[0]; + for (Bitu x=0;x> 4 | + (val2 & 0x0f) << 24 | + (val2 & 0xf0) << 12; } + return VGA_DrawBuffer; } +static Bit8u * VGA_EGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + return &vga.mem.linear[512*1024+vidstart*8+panning]; +} +static Bit8u * VGA_VGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + return &vga.mem.linear[vidstart*4+panning/2]; +} -void VGA_TEXT_Draw(Bit8u * bitdata,Bitu start,Bitu panning,Bitu rows) { - Bit8u * reader=&vga.mem.linear[start*2]; - Bit8u * draw_start=bitdata; -/* Todo Blinking and high intensity colors */ - Bitu next_charline=vga.draw.font_height*vga.draw.width; - Bitu next_line=vga.draw.width; - Bitu next_start=(vga.config.scan_len*2)-vga.draw.cols; +static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * draw=VGA_DrawBuffer; + Bit8u * vidmem=&vga.mem.linear[vidstart]; + for (Bitu cx=0;cx>4]; + Bit32u mask2=TXT_Font_Table[font&0xf]; + Bitu col=vidmem[cx*2+1]; + Bit32u fg=TXT_FG_Table[col&0xf]; + Bit32u bg=TXT_BG_Table[col>>4]; + *(Bit32u*)draw=fg&mask1 | bg&~mask1; + draw+=4; + *(Bit32u*)draw=fg&mask2 | bg&~mask2; + draw+=4; + } + return VGA_DrawBuffer; +} + +void VGA_TEXT_Draw(Bit8u * bitdata,Bitu start,Bitu panning,Bitu lines) { +#if 0 + Bit8u * reader=&vga.mem.linear[start*2];Bitu rows=lines/vga.draw.font_height; for (Bitu cy=rows;cy>0;cy--) { - Bit8u * draw_char=draw_start; - /* Do first character keeping track of panning */ - { - Bit8u c=*(reader++); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader++); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw_line=draw_char; - Bit8u bit_index=1 << (7-panning); - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u * draw=draw_line; - draw_line+=next_line; - Bit8u bit=bit_index; - Bit8u bit_mask=*findex++; - while (bit) { - if (bit_mask & bit) *draw=fg; - else *draw=bg; - draw++;bit>>=1; - } - } - draw_char+=8-panning; - } - for (Bitu cx=vga.draw.cols-1;cx>0;cx--) { - Bit8u c=*(reader++); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader++); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw=draw_char; - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u bit_mask=*findex++; - #include "font-switch.h" - draw+=next_line; - } - draw_char+=8; - } - /* Do last character if needed */ - if (panning) { - Bit8u c=*(reader); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader+1); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw_line=draw_char; - Bit8u bit_index=1 << panning; - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u * draw=draw_line; - draw_line+=next_line; - Bit8u bit=bit_index; - Bit8u bit_mask=*findex++; - while (bit) { - if (bit_mask & bit) *draw=fg; - else *draw=bg; - draw++;bit>>=1; - } + for (Bitu y=0;y>4]; + Bit32u mask2=TXT_Font_Table[font&0xf]; + Bit8u col=reader[cx*2+1]; + Bit32u fg=TXT_FG_Table[col&0xf]; + Bit32u bg=TXT_BG_Table[col>>4]; + *(Bit32u*)draw=fg&mask1 | bg&~mask1; + draw+=4; + *(Bit32u*)draw=fg&mask2 | bg&~mask2; + draw+=4; } } - draw_start+=next_charline; - reader+=next_start; + reader+=(vga.config.scan_len*4); } /* Cursor handling */ - vga.draw.cursor.count++; - if (vga.draw.cursor.count>16) vga.draw.cursor.count=0; - if(vga.draw.cursor.enabled && (vga.draw.cursor.count>8)) { /* Draw a cursor if enabled */ Bits cur_start=vga.config.cursor_start-start; if (cur_start<0) return; @@ -219,8 +150,7 @@ void VGA_TEXT_Draw(Bit8u * bitdata,Bitu start,Bitu panning,Bitu rows) { Bitu row=cur_start / (vga.config.scan_len*2); Bitu col=cur_start % (vga.config.scan_len*2); Bit32u att=vga.mem.linear[vga.config.cursor_start*2+1]&0xf; - att=(att << 8) | att; - att=(att << 16) | att; + att=TXT_BG_Table[att]; if ((col*8)>=vga.draw.width) return; if ((row*vga.draw.font_height)>=vga.draw.height) return; @@ -234,118 +164,60 @@ void VGA_TEXT_Draw(Bit8u * bitdata,Bitu start,Bitu panning,Bitu rows) { cursor_draw+=vga.draw.width; } } +#endif } -static void EndRetrace(void) { - /* start the actual display update now */ - RENDER_DoUpdate(); - vga.config.retrace=false; -} - -static void VGA_BlankTimer() { - PIC_AddEvent(VGA_BlankTimer,vga.draw.blank); - PIC_AddEvent(EndRetrace,667); - /* Setup a timer to destroy the vertical retrace bit in a few microseconds */ - vga.config.real_start=vga.config.display_start; +static void VGA_VerticalDisplayEnd(void) { vga.config.retrace=true; + vga.config.real_start=vga.config.display_start; } -void VGA_DrawHandler(RENDER_Part_Handler part_handler) { - Bit8u * buf,* bufsplit; - /* Draw the current frame */ - if (!vga.draw.resizing) { - if (vga.config.line_compare=vga.draw.height){ - LOG(LOG_VGAGFX,LOG_NORMAL)("Split at %d",stop); - goto drawnormal; - } - switch (vga.mode) { - case M_EGA16: - buf=&vga.mem.linear[512*1024+vga.config.real_start*8+vga.config.pel_panning]; - bufsplit=&vga.mem.linear[512*1024]; - break; - case M_VGA: - case M_LIN8: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning]; - bufsplit=vga.mem.linear; - break; - case M_TEXT2: - case M_TEXT16: - { - Bitu first_rows=stop/vga.draw.font_height; - if (vga.config.hlines_skip) first_rows++; - if (stop%vga.draw.font_height) first_rows++; - Bitu next_rows=(vga.draw.height-stop)/vga.draw.font_height; - if ((vga.draw.height-stop)%vga.draw.font_height) next_rows++; - VGA_TEXT_Draw(&vga.mem.linear[512*1024],vga.config.real_start,vga.config.pel_panning,first_rows); - VGA_TEXT_Draw(&vga.mem.linear[1024*1024],0,0,next_rows); - buf=&vga.mem.linear[512*1024+vga.config.hlines_skip*vga.draw.width]; - bufsplit=&vga.mem.linear[1024*1024]; - } - break; - default: - LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:Unhandled split screen mode %d",vga.mode); - goto norender; - } - if (stop) part_handler(buf,0,0,vga.draw.width,stop); - if (vga.draw.height-stop) part_handler(bufsplit,0,stop,vga.draw.width,vga.draw.height-stop); - } else { -drawnormal: - switch (vga.mode) { - case M_HERC: - VGA_HERC_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_CGA2: - VGA_CGA2_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_CGA4: - VGA_CGA4_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_CGA16: - VGA_CGA16_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_TANDY16: - VGA_TANDY16_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_EGA16: - buf=&vga.mem.linear[512*1024+vga.config.real_start*8+vga.config.pel_panning]; - break; - case M_VGA: - case M_LIN8: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning]; - break; - case M_TEXT2: - case M_TEXT16: - { - Bitu rows=vga.draw.rows; - if (vga.config.hlines_skip) rows++; - VGA_TEXT_Draw(&vga.mem.linear[512*1024],vga.config.real_start,vga.config.pel_panning,rows); - buf=&vga.mem.linear[512*1024+vga.config.hlines_skip*vga.draw.width]; - } - break; - default: - return; - } - part_handler(buf,0,0,vga.draw.width,vga.draw.height); +static void VGA_HorizontalTimer(void) { + +} + +static void VGA_DrawPart(void) { + Bitu subline=0;Bitu vidofs=vga.config.real_start; + Bit8u * draw=0; + while (vga.draw.lines_left) { + vga.draw.lines_left--; + Bit8u * data=VGA_DrawLine(vga.draw.address,vga.draw.panning,vga.draw.address_line); + RENDER_DrawLine(data); + vga.draw.address_line++; + if (vga.draw.address_line>=vga.draw.address_line_total) { + vga.draw.address_line=0; + vga.draw.address+=vga.draw.address_add; + } + if (vga.draw.split_line==vga.draw.lines_left) { + vga.draw.address=0;vga.draw.panning=0; } -norender:; } - + RENDER_EndUpdate(); +// vga.draw.parts_left--; +// if (vga.draw.parts_left) PIC_AddEvent(VGA_DrawPart,vga.draw.micro.parts); } +static void VGA_VerticalTimer(void) { + vga.config.retrace=false; + vga.draw.cursor.count++;vga.draw.cursor.count&=0xf; + PIC_AddEvent(VGA_VerticalTimer,vga.draw.micro.vtotal); + PIC_AddEvent(VGA_VerticalDisplayEnd,vga.draw.micro.vend); + vga.draw.parts_left=4; + vga.draw.lines_left=vga.draw.lines_total; + vga.draw.address=vga.config.real_start; + vga.draw.address_line=vga.config.hlines_skip; + vga.draw.split_line=vga.draw.lines_total-(vga.config.line_compare/vga.draw.lines_scaled); + vga.draw.panning=vga.config.pel_panning; + if (RENDER_StartUpdate()) { + VGA_DrawPart(); + } +} void VGA_SetupDrawing(void) { /* Calculate the FPS for this screen */ double fps; Bitu vtotal=2 + vga.crtc.vertical_total | - ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4) - ; + ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4); Bitu htotal=5 + vga.crtc.horizontal_total; Bitu vdispend = 1 + (vga.crtc.vertical_display_end | ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) | @@ -353,12 +225,16 @@ void VGA_SetupDrawing(void) { Bitu hdispend = 1 + (vga.crtc.horizontal_display_end); Bitu hbstart = vga.crtc.start_horizontal_blanking; - Bitu vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) | ((vga.crtc.maximum_scan_line & 0x20) << 4) ; - - if (hbstart> 2) & 3; clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); /* Check for 8 for 9 character clock mode */ @@ -369,11 +245,20 @@ void VGA_SetupDrawing(void) { } /* Check for dual transfer whatever thing,master clock/2 */ if (vga.s3.pll.cmd & 0x10) clock/=2; - LOG(LOG_VGA,LOG_NORMAL)("H total %d, V Total %d",htotal,vtotal); LOG(LOG_VGA,LOG_NORMAL)("H D End %d, V D End %d",hdispend,vdispend); fps=clock/(vtotal*htotal); + double linemicro=(1000000/fps); + vga.draw.parts_total=VGA_PARTS; + vga.draw.micro.vtotal=(Bitu)(linemicro); + linemicro/=vtotal; //Really make it the line_micro + vga.draw.micro.vend=(Bitu)(linemicro*vrstart); + vga.draw.micro.parts=(Bitu)((linemicro*vdispend)/vga.draw.parts_total); + vga.draw.micro.htotal=(Bitu)(linemicro); + vga.draw.micro.hend=(Bitu)((linemicro/htotal)*hrstart); + + double correct_ratio=(100.0/525.0); double aspect_ratio=((double)htotal/((double)vtotal)/correct_ratio); @@ -382,80 +267,113 @@ void VGA_SetupDrawing(void) { Bitu scalew=1; Bitu scaleh=1; - vga.draw.lines=height=vdispend; width=hdispend; - vga.draw.double_height=vga.config.vline_double; - vga.draw.double_width=(vga.seq.clocking_mode & 0x8)>0; - vga.draw.font_height=vga.config.vline_height+1; + height=vdispend; + vga.draw.double_scan=false; + vga.draw.font_height=(vga.crtc.maximum_scan_line&0xf)+1; switch (vga.mode) { case M_VGA: - vga.draw.double_width=true; //Hack since 256 color modes use 2 clocks for a pixel - /* Don't know might do this different sometime, will have to do for now */ + scalew=2; scaleh*=vga.draw.font_height; + if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; + vga.draw.lines_scaled=scaleh; + height/=scaleh; width<<=2; pitch=vga.config.scan_len*8; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_VGA_Draw_Line; break; case M_LIN8: width<<=3; scaleh*=vga.draw.font_height; - pitch=vga.config.scan_len*8; + pitch=vga.config.scan_len*4; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.lines_scaled=scaleh; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_VGA_Draw_Line; break; case M_EGA16: width<<=3; pitch=vga.config.scan_len*16; scaleh*=vga.draw.font_height; + if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; + vga.draw.lines_scaled=scaleh; + height/=scaleh; + if (vga.seq.clocking_mode & 0x8) scalew*=2; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_EGA_Draw_Line; break; case M_CGA4: case M_CGA16: //Let is use 320x200 res and double pixels myself - vga.draw.double_width=true; //Hack if there's a runtime switch - vga.draw.double_height=true; //Hack if there's a runtime switch + scaleh=2;scalew=2; + vga.draw.blocks=width; width<<=2; pitch=width; + vga.draw.lines_scaled=1; + vga.draw.address_line_total=2; + vga.draw.address_add=80; //CGA doesn't have an offset reg + VGA_DrawLine=(vga.mode == M_CGA4) ? VGA_CGA4_Draw_Line : VGA_CGA16_Draw_Line; break; case M_CGA2: - vga.draw.double_width=false; //Hack if there's a runtime switch + scaleh=2; + vga.draw.address_line_total=2; + vga.draw.blocks=width; width<<=3; pitch=width; + vga.draw.address_line_total=2; + vga.draw.address_add=80; //CGA doesn't have an offset reg + vga.draw.lines_scaled=1; + VGA_DrawLine=VGA_CGA2_Draw_Line; break; case M_HERC: - vga.draw.double_height=false; //Hack if there's a runtime switch + vga.draw.address_line_total=4; width*=9; + vga.draw.blocks=width/8; + vga.draw.address_add=width/8; + vga.draw.lines_scaled=1; height=348; pitch=width; aspect_ratio=1.5; + VGA_DrawLine=VGA_HERC_Draw_Line; break; case M_TANDY16: - width<<=3; + scaleh=2;scalew=2; + vga.draw.blocks=width*2; + vga.draw.address_add=160; + vga.draw.address_line_total=4; + vga.draw.lines_scaled=1; + width<<=2; pitch=width; + VGA_DrawLine=VGA_TANDY16_Draw_Line; break; case M_TEXT2: case M_TEXT16: aspect_ratio=1.0; - vga.draw.font_height=vga.config.vline_height+1; + vga.draw.address_line_total=vga.draw.font_height; if (vga.draw.font_height<4 && (machine640) width=640; if (height>480) height=480; pitch=width; + VGA_DrawLine=VGA_TEXT_Draw_Line; break; default: LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA type %d while checking for resolution"); }; - if (vga.draw.double_height) { - scaleh*=2; - } - height/=scaleh; - if (vga.draw.double_width) { - /* Double width is dividing main clock, the width should be correct already for this */ - scalew*=2; - } + vga.draw.lines_total=height; if (( width != vga.draw.width) || (height != vga.draw.height) || (pitch != vga.draw.pitch)) { - PIC_RemoveEvents(VGA_BlankTimer); + PIC_RemoveEvents(VGA_VerticalTimer); + PIC_RemoveEvents(VGA_VerticalDisplayEnd); vga.draw.width=width; vga.draw.height=height; vga.draw.pitch=pitch; @@ -463,8 +381,7 @@ void VGA_SetupDrawing(void) { LOG(LOG_VGA,LOG_NORMAL)("Width %d, Height %d, fps %f",width,height,fps); LOG(LOG_VGA,LOG_NORMAL)("Scalew %d, Scaleh %d aspect %f",scalew,scaleh,aspect_ratio); - RENDER_SetSize(width,height,8,pitch,aspect_ratio,scalew,scaleh,&VGA_DrawHandler); - vga.draw.blank=(Bitu)(1000000/fps); - PIC_AddEvent(VGA_BlankTimer,vga.draw.blank); + RENDER_SetSize(width,height,8,pitch,aspect_ratio,scalew,scaleh); + PIC_AddEvent(VGA_VerticalTimer,vga.draw.micro.vtotal); } }; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 45d720f2..0842dd15 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -308,6 +308,9 @@ void VGA_SetupHandlers(void) { } switch ((vga.gfx.miscellaneous >> 2) & 3) { case 0: + vgapages.map_base=VGA_PAGE_A0; + MEM_SetPageHandler(VGA_PAGE_A0,32,range_handler); + break; case 1: vgapages.map_base=VGA_PAGE_A0; MEM_SetPageHandler(VGA_PAGE_A0,16,range_handler);