From 9bf1cd50f58616d9384ebde9a05e22f85cb50edd Mon Sep 17 00:00:00 2001 From: Sjoerd van der Berg Date: Wed, 28 Jan 2004 14:39:05 +0000 Subject: [PATCH] Opengl output support in SDL Removed threading support in SDL Rewrite of VGA Drawing to work line for line Rewrite of VGA Text drawing using lookup tables Rewrite of render function to handle the new line for line drawing. Changed CGA/TANDY/Hercules to be more like their original hardware. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1611 --- include/render.h | 17 +- include/vga.h | 36 ++- include/video.h | 23 +- src/gui/render.cpp | 186 +++++++------ src/gui/render_normal.h | 49 ++-- src/gui/render_scale2x.h | 9 +- src/gui/sdlmain.cpp | 433 ++++++++++++++++++++---------- src/hardware/vga.cpp | 59 ++--- src/hardware/vga_crtc.cpp | 2 - src/hardware/vga_draw.cpp | 507 +++++++++++++++--------------------- src/hardware/vga_memory.cpp | 3 + 11 files changed, 714 insertions(+), 610 deletions(-) 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);