diff --git a/include/render.h b/include/render.h index c3dc8603..93d20f29 100644 --- a/include/render.h +++ b/include/render.h @@ -21,6 +21,10 @@ #include "../src/gui/render_scalers.h" +#define RENDER_SKIP_CACHE 16 +//Enable this for scalers to support 0 input for empty lines +//#define RENDER_NULL_INPUT + typedef struct { struct { Bit8u red; @@ -40,7 +44,7 @@ typedef struct { typedef struct { struct { - Bitu width; + Bitu width, start; Bitu height; Bitu bpp; bool dblw,dblh; @@ -50,6 +54,8 @@ typedef struct { struct { Bitu count; Bitu max; + Bitu index; + Bit8u hadSkip[RENDER_SKIP_CACHE]; } frameskip; struct { Bitu size; @@ -71,13 +77,14 @@ typedef struct { bool updating; bool active; bool aspect; + bool fullFrame; } Render_t; extern Render_t render; extern ScalerLineHandler_t RENDER_DrawLine; void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh); bool RENDER_StartUpdate(void); -void RENDER_EndUpdate( bool fullUpdate ); +void RENDER_EndUpdate( ); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); diff --git a/include/vga.h b/include/vga.h index 6f60c63b..0c6fb456 100644 --- a/include/vga.h +++ b/include/vga.h @@ -23,8 +23,18 @@ #include "dosbox.h" #endif +//Don't enable keeping changes and mapping lfb probably... +#define VGA_LFB_MAPPED +//#define VGA_KEEP_CHANGES +#define VGA_MEMORY (2*1024*1024) +#define VGA_CHANGE_SHIFT 9 + +//Offset inside VGA_MEMORY that will be used for certain types of caching +#define VGA_CACHE_OFFSET (512*1024) + class PageHandler; + enum VGAModes { M_CGA2, M_CGA4, M_EGA, M_VGA, @@ -70,6 +80,7 @@ typedef struct { Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ Bit8u hlines_skip; Bit8u bytes_skip; + Bit8u addr_shift; /* Specific stuff memory write/read handling */ @@ -97,6 +108,10 @@ typedef struct { Bitu blocks; Bitu panning; Bitu address; + Bit8u *linear_base; + Bitu linear_mask; + Bitu address_mask; + Bitu address_last; Bitu address_add; Bitu address_line_total; Bitu address_line; @@ -108,13 +123,14 @@ typedef struct { Bitu parts_lines; Bitu parts_left; struct { - float vtotal; - float vstart; - float vend; - float htotal; - float hstart; - float hend; - float parts; + double framestart; + double vrstart, vrend; // V-retrace + double hrstart, hrend; // H-retrace + double hblkstart, hblkend; // H-blanking + double vblkstart, vblkend; // V-Blanking + double vdend, vtotal; + double hdend, htotal; + double parts; } delay; bool double_scan; bool doublewidth,doubleheight; @@ -194,31 +210,36 @@ typedef struct { Bit8u htotal; Bit8u hdend; Bit8u hsyncp; - Bit8u hsyncw; + Bit8u syncw; Bit8u vtotal; Bit8u vdend; Bit8u vadjust; Bit8u vsyncp; Bit8u vsyncw; Bit8u max_scanline; + Bit8u lpen_low, lpen_high; + Bit8u cursor_start; + Bit8u cursor_end; } VGA_OTHER; typedef struct { + Bit8u pcjr_flipflop; Bit8u mode_control; Bit8u color_select; - Bit8u mem_bank; Bit8u disp_bank; Bit8u reg_index; Bit8u gfx_control; Bit8u palette_mask; + Bit8u extended_ram; Bit8u border_color; - bool is_32k_mode; - bool pcjr_flipflop; + Bit8u line_mask, line_shift; + Bit8u draw_bank, mem_bank; + Bit8u *draw_base, *mem_base; + Bitu addr_mask; } VGA_TANDY; typedef struct { Bit8u index; - Bit8u reset; Bit8u clocking_mode; Bit8u map_mask; @@ -281,11 +302,11 @@ typedef struct { Bit8u bit_mask; } VGA_Gfx; -struct RGBEntry { +typedef struct { Bit8u red; Bit8u green; Bit8u blue; -}; +} RGBEntry; typedef struct { Bit8u bits; /* DAC bits, usually 6 or 8 */ @@ -298,16 +319,30 @@ typedef struct { RGBEntry rgb[0x100]; } VGA_Dac; -union VGA_Latch { +typedef struct { + Bitu readStart, writeStart; + Bitu bankMask; +} VGA_SVGA; + +typedef union { Bit32u d; Bit8u b[4]; -}; +} VGA_Latch; -union VGA_Memory { - Bit8u linear[512*1024*4]; - Bit8u paged[512*1024][4]; - VGA_Latch latched[512*1024]; -}; +typedef struct { + Bit8u linear[VGA_MEMORY]; +} VGA_Memory; + +typedef struct { + //Add a few more just to be safe + Bit8u map[(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32]; + Bit8u checkMask, frame, writeMask; + bool active; + Bit32u lineWidth; + Bit32u clearMask; + Bit32u start, last; + Bit32u lastAddress; +} VGA_Changes; typedef struct { Bit32u page; @@ -316,8 +351,6 @@ typedef struct { PageHandler *handler; } VGA_LFB; -#define VGA_CHANGE_SHIFT 9 -typedef Bit8u VGA_Changed[(2*1024*1024) >> VGA_CHANGE_SHIFT]; typedef struct { VGAModes mode; /* The mode the vga system is in */ VGAModes lastmode; @@ -333,13 +366,15 @@ typedef struct { VGA_Dac dac; VGA_Latch latch; VGA_S3 s3; + VGA_SVGA svga; VGA_HERC herc; VGA_TANDY tandy; VGA_OTHER other; VGA_Memory mem; +#ifdef VGA_KEEP_CHANGES + VGA_Changes changes; +#endif VGA_LFB lfb; - VGA_Changed changed; - Bit8u * gfxmem_start; } VGA_Type; @@ -351,6 +386,7 @@ void VGA_SetupHandlers(void); void VGA_StartResize(void); void VGA_SetupDrawing(Bitu val); void VGA_CheckScanLength(void); +void VGA_ChangedBank(void); /* Some DAC/Attribute functions */ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal); diff --git a/src/gui/render.cpp b/src/gui/render.cpp index e25c9087..37316ea7 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.49 2007-01-08 19:45:39 qbix79 Exp $ */ +/* $Id: render.cpp,v 1.50 2007-01-24 16:29:09 harekiet Exp $ */ #include #include @@ -37,6 +37,8 @@ Render_t render; ScalerLineHandler_t RENDER_DrawLine; +static void RENDER_CallBack( GFX_CallBackFunctions_t function ); + static void Check_Palette(void) { /* Clean up any previous changed palette data */ if (render.pal.changed) { @@ -95,6 +97,30 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { static void RENDER_EmptyLineHandler(const void * src) { } +static void RENDER_StartLineHandler(const void * s) { + if (s) { + const Bitu *src = (Bitu*)s; + Bitu *cache = (Bitu*)(render.scale.cacheRead); + for (Bits x=render.src.start;x>0;) { + if (GCC_UNLIKELY(src[0] != cache[0])) { + if (!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )) { + RENDER_DrawLine = RENDER_EmptyLineHandler; + return; + } + render.scale.outWrite += render.scale.outPitch * Scaler_ChangedLines[0]; + RENDER_DrawLine = render.scale.lineHandler; + RENDER_DrawLine( s ); + return; + } + x--; src++; cache++; + } + } + render.scale.cacheRead += render.scale.cachePitch; + Scaler_ChangedLines[0] += Scaler_Aspect[ render.scale.inLine ]; + render.scale.inLine++; + render.scale.outLine++; +} + static void RENDER_ClearCacheHandler(const void * src) { Bitu x, width; Bit32u *srcLine, *cacheLine; @@ -119,33 +145,54 @@ bool RENDER_StartUpdate(void) { if (render.scale.inMode == scalerMode8) { Check_Palette(); } - if (GCC_UNLIKELY(!GFX_StartUpdate(render.scale.outWrite,render.scale.outPitch))) - return false; render.scale.inLine = 0; render.scale.outLine = 0; render.scale.cacheRead = (Bit8u*)&scalerSourceCache; + render.scale.outWrite = 0; + render.scale.outPitch = 0; Scaler_ChangedLines[0] = 0; Scaler_ChangedLineIndex = 0; /* Clearing the cache will first process the line to make sure it's never the same */ if (GCC_UNLIKELY( render.scale.clearCache) ) { // LOG_MSG("Clearing cache"); + //Will always have to update the screen with this one anyway, so let's update already + if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch ))) + return false; + render.fullFrame = true; render.scale.clearCache = false; RENDER_DrawLine = RENDER_ClearCacheHandler; } else { - if (render.pal.changed) + if (render.pal.changed) { + /* Assume pal changes always do a full screen update anyway */ + if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch ))) + return false; RENDER_DrawLine = render.scale.linePalHandler; - else - RENDER_DrawLine = render.scale.lineHandler; + render.fullFrame = true; + } else { + RENDER_DrawLine = RENDER_StartLineHandler; + if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) + render.fullFrame = true; + else + render.fullFrame = false; + } } - render.updating=true; + render.updating = true; return true; } -void RENDER_EndUpdate( bool fullUpdate ) { - if (!render.updating) +static void RENDER_Halt( void ) { + RENDER_DrawLine = RENDER_EmptyLineHandler; + GFX_EndUpdate( 0 ); + render.updating=false; + render.active=false; +} + +extern Bitu PIC_Ticks; +void RENDER_EndUpdate( void ) { + if (GCC_UNLIKELY(!render.updating)) return; RENDER_DrawLine = RENDER_EmptyLineHandler; - if (CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO)) { + if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) { Bitu pitch, flags; flags = 0; if (render.src.dblw != render.src.dblh) { @@ -159,40 +206,46 @@ void RENDER_EndUpdate( bool fullUpdate ) { CAPTURE_AddImage( render.src.width, render.src.height, render.src.bpp, pitch, flags, fps, (Bit8u *)&scalerSourceCache, (Bit8u*)&render.pal.rgb ); } - GFX_EndUpdate( fullUpdate ? Scaler_ChangedLines : 0); + if ( render.scale.outWrite ) { + GFX_EndUpdate( Scaler_ChangedLines ); + render.frameskip.hadSkip[render.frameskip.index] = 0; + } else { +#if 0 + Bitu total = 0, i; + render.frameskip.hadSkip[render.frameskip.index] = 1; + for (i = 0;i=miny) { - Bitu templines=(Bitu)lines; - lines-=templines; - linesadded+=templines; - Scaler_Aspect[1+i]=templines-miny; - } else Scaler_Aspect[1+i]=0; + for (i=0;i= miny) { + Bitu templines = (Bitu)lines; + lines -= templines; + linesadded += templines; + Scaler_Aspect[i] = templines; + } else { + Scaler_Aspect[i] = 0; + } } return linesadded; } -void RENDER_CallBack( GFX_CallBackFunctions_t function ) { - if (render.updating) { - /* Still updating the current screen, shut it down correctly */ - RENDER_EndUpdate( false ); - } - - if (function == GFX_CallBackStop) - return; - - if (function == GFX_CallBackRedraw) { - //LOG_MSG("redraw"); - render.scale.clearCache = true; - return; - } +static void RENDER_Reset( void ) { Bitu width=render.src.width; Bitu height=render.src.height; bool dblw=render.src.dblw; @@ -301,20 +354,24 @@ forcenormal: } switch (render.src.bpp) { case 8: + render.src.start = ( render.src.width * 1) / sizeof(Bitu); if (gfx_flags & GFX_CAN_8) gfx_flags |= GFX_LOVE_8; else gfx_flags |= GFX_LOVE_32; break; case 15: + render.src.start = ( render.src.width * 2) / sizeof(Bitu); gfx_flags |= GFX_LOVE_15; gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; break; case 16: + render.src.start = ( render.src.width * 2) / sizeof(Bitu); gfx_flags |= GFX_LOVE_16; gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; break; case 32: + render.src.start = ( render.src.width * 4) / sizeof(Bitu); gfx_flags |= GFX_LOVE_32; gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; break; @@ -327,15 +384,16 @@ forcenormal: goto forcenormal; } width *= xscale; + Bitu skip = complexBlock ? 1 : 0; if (gfx_flags & GFX_SCALING) { - height = MakeAspectTable(render.src.height, yscale, yscale ); + height = MakeAspectTable(skip, render.src.height, yscale, yscale ); } else { if ((gfx_flags & GFX_CAN_RANDOM) && gfx_scaleh > 1) { gfx_scaleh *= yscale; - height = MakeAspectTable(render.src.height, gfx_scaleh, yscale ); + height = MakeAspectTable( skip, render.src.height, gfx_scaleh, yscale ); } else { gfx_flags &= ~GFX_CAN_RANDOM; //Hardware surface when possible - height = MakeAspectTable(render.src.height, yscale, yscale); + height = MakeAspectTable( skip, render.src.height, yscale, yscale); } } /* Setup the scaler variables */ @@ -409,12 +467,26 @@ forcenormal: render.active=true; } +static void RENDER_CallBack( GFX_CallBackFunctions_t function ) { + if (function == GFX_CallBackStop) { + RENDER_Halt( ); + return; + } else if (function == GFX_CallBackRedraw) { + render.scale.clearCache = true; + return; + } else if ( function == GFX_CallBackReset) { + GFX_EndUpdate( 0 ); + RENDER_Reset(); + } else { + E_Exit("Unhandled GFX_CallBackReset %d", function ); + } +} + void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh) { + RENDER_Halt( ); if (!width || !height || width > SCALER_MAXWIDTH || height > SCALER_MAXHEIGHT) { - render.active=false; return; } - RENDER_EndUpdate( false ); render.src.width=width; render.src.height=height; render.src.bpp=bpp; @@ -422,7 +494,7 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool render.src.dblh=dblh; render.src.fps=fps; render.src.ratio=ratio; - RENDER_CallBack( GFX_CallBackReset ); + RENDER_Reset( ); } extern void GFX_SetTitle(Bit32s cycles, Bits frameskip,bool paused); @@ -499,6 +571,7 @@ void RENDER_Init(Section * sec) { //If something changed that needs a ReInit if(running && (render.aspect != aspect || render.scale.op != scaleOp)) RENDER_CallBack( GFX_CallBackReset ); + if(!running) render.updating=true; running = true; diff --git a/src/gui/render_loops.h b/src/gui/render_loops.h index bc6799cc..a87c7fb8 100644 --- a/src/gui/render_loops.h +++ b/src/gui/render_loops.h @@ -21,6 +21,7 @@ static void conc3d(SCALERNAME,SBPP,L)(void) { #else static void conc3d(SCALERNAME,SBPP,R)(void) { #endif +//Skip the first one for multiline input scalers if (!render.scale.outLine) { render.scale.outLine++; return; @@ -30,14 +31,9 @@ lastagain: #if defined(SCALERLINEAR) Bitu scaleLines = SCALERHEIGHT; #else - Bitu scaleLines = SCALERHEIGHT + Scaler_Aspect[ render.scale.outLine ]; + Bitu scaleLines = Scaler_Aspect[ render.scale.outLine ]; #endif - render.scale.outWrite += render.scale.outPitch * scaleLines; - if (!(Scaler_ChangedLineIndex & 1)) { - Scaler_ChangedLines[Scaler_ChangedLineIndex] += scaleLines; - } else { - Scaler_ChangedLines[++Scaler_ChangedLineIndex] = scaleLines; - } + ScalerAddLines( 0, scaleLines ); if (++render.scale.outLine == render.scale.inHeight) goto lastagain; return; @@ -141,25 +137,15 @@ lastagain: } #if defined(SCALERLINEAR) Bitu scaleLines = SCALERHEIGHT; - render.scale.outWrite += render.scale.outPitch * scaleLines; #else - Bitu scaleLines = SCALERHEIGHT; - if ( Scaler_Aspect[ render.scale.outLine ] ) { - scaleLines++; + Bitu scaleLines = Scaler_Aspect[ render.scale.outLine ]; + if ( ((Bits)(scaleLines - SCALERHEIGHT)) > 0 ) { BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, render.scale.outWrite + render.scale.outPitch * (SCALERHEIGHT-1), render.src.width * SCALERWIDTH * PSIZE); - render.scale.outWrite += render.scale.outPitch * (SCALERHEIGHT + 1); - } else { - render.scale.outWrite += render.scale.outPitch * SCALERHEIGHT; } #endif - /* Keep track of changed lines */ - if (Scaler_ChangedLineIndex & 1) { - Scaler_ChangedLines[Scaler_ChangedLineIndex] += scaleLines; - } else { - Scaler_ChangedLines[++Scaler_ChangedLineIndex] = scaleLines; - } + ScalerAddLines( 1, scaleLines ); if (++render.scale.outLine == render.scale.inHeight) goto lastagain; } diff --git a/src/gui/render_scalers.cpp b/src/gui/render_scalers.cpp index baeb3d59..ad6ae67d 100644 --- a/src/gui/render_scalers.cpp +++ b/src/gui/render_scalers.cpp @@ -59,6 +59,16 @@ static INLINE void BituMove( void *_dst, const void * _src, Bitu size) { dst[x] = src[x]; } +static INLINE void ScalerAddLines( Bitu changed, Bitu count ) { + if ((Scaler_ChangedLineIndex & 1) == changed ) { + Scaler_ChangedLines[Scaler_ChangedLineIndex] += count; + } else { + Scaler_ChangedLines[++Scaler_ChangedLineIndex] = count; + } + render.scale.outWrite += render.scale.outPitch * count; +} + + #define BituMove2(_DST,_SRC,_SIZE) \ { \ Bitu bsize=(_SIZE)/sizeof(Bitu); \ diff --git a/src/gui/render_simple.h b/src/gui/render_simple.h index c1c9cfb4..4581a5e2 100644 --- a/src/gui/render_simple.h +++ b/src/gui/render_simple.h @@ -20,13 +20,25 @@ static void conc4d(SCALERNAME,SBPP,DBPP,L)(const void *s) { #else static void conc4d(SCALERNAME,SBPP,DBPP,R)(const void *s) { +#endif +#ifdef RENDER_NULL_INPUT + if (!s) { + render.scale.cacheRead += render.scale.cachePitch; +#if defined(SCALERLINEAR) + Bitu skipLines = SCALERHEIGHT; +#else + Bitu skipLines = Scaler_Aspect[ render.scale.outLine++ ]; +#endif + ScalerAddLines( 0, skipLines ); + return; + } #endif /* Clear the complete line marker */ + Bitu hadChange; const SRCTYPE *src = (SRCTYPE*)s; SRCTYPE *cache = (SRCTYPE*)(render.scale.cacheRead); render.scale.cacheRead += render.scale.cachePitch; PTYPE * line0=(PTYPE *)(render.scale.outWrite); - Bitu hadChange = 0; #if (SBPP == 9) for (Bits x=render.src.width;x>0;) { if (*(Bit32u const*)src == *(Bit32u*)cache && !( @@ -90,26 +102,15 @@ static void conc4d(SCALERNAME,SBPP,DBPP,R)(const void *s) { } #if defined(SCALERLINEAR) Bitu scaleLines = SCALERHEIGHT; - render.scale.outWrite += render.scale.outPitch * scaleLines; #else - Bitu scaleLines = SCALERHEIGHT; - if ( Scaler_Aspect[ render.scale.outLine++ ] ) { - scaleLines++; - if (hadChange) - BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, + Bitu scaleLines = Scaler_Aspect[ render.scale.outLine++ ]; + if ( scaleLines - SCALERHEIGHT && hadChange ) { + BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, render.scale.outWrite + render.scale.outPitch * (SCALERHEIGHT-1), render.src.width * SCALERWIDTH * PSIZE); - render.scale.outWrite += render.scale.outPitch * (SCALERHEIGHT + 1); - } else { - render.scale.outWrite += render.scale.outPitch * SCALERHEIGHT; - } - /* Keep track of changed lines */ - if ((Scaler_ChangedLineIndex & 1) == hadChange) { - Scaler_ChangedLines[Scaler_ChangedLineIndex] += scaleLines; - } else { - Scaler_ChangedLines[++Scaler_ChangedLineIndex] = scaleLines; } #endif + ScalerAddLines( hadChange, scaleLines ); } #if !defined(SCALERLINEAR) diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h index f697ef77..a3ce579b 100644 --- a/src/gui/render_templates.h +++ b/src/gui/render_templates.h @@ -153,6 +153,14 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) { +#ifdef RENDER_NULL_INPUT + if (!s) { + render.scale.cacheRead += render.scale.cachePitch; + render.scale.inLine++; + render.scale.complexHandler(); + return; + } +#endif const SRCTYPE * src = (SRCTYPE*)s; PTYPE *fc= &FC[render.scale.inLine+1][1]; SRCTYPE *sc = (SRCTYPE*)(render.scale.cacheRead); diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index d8097360..7f885a10 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.126 2007-01-10 15:01:15 c2woody Exp $ */ +/* $Id: sdlmain.cpp,v 1.127 2007-01-24 16:29:09 harekiet Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -328,7 +328,8 @@ check_gotbpp: void GFX_ResetScreen(void) { GFX_Stop(); - if (sdl.draw.callback) (sdl.draw.callback)( GFX_CallBackReset ); + if (sdl.draw.callback) + (sdl.draw.callback)( GFX_CallBackReset ); GFX_Start(); } @@ -661,7 +662,8 @@ static void SwitchFullScreen(bool pressed) { bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { - if (!sdl.active || sdl.updating) return false; + if (!sdl.active || sdl.updating) + return false; switch (sdl.desktop.type) { case SCREEN_SURFACE: if (sdl.blit.surface) { @@ -710,7 +712,8 @@ bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { void GFX_EndUpdate( const Bit16u *changedLines ) { int ret; - if (!sdl.updating) return; + if (!sdl.updating) + return; sdl.updating=false; switch (sdl.desktop.type) { case SCREEN_SURFACE: @@ -745,15 +748,11 @@ void GFX_EndUpdate( const Bit16u *changedLines ) { } if (rectCount) SDL_UpdateRects( sdl.surface, rectCount, sdl.updateRects ); - } else { - SDL_Flip(sdl.surface); } break; #if (HAVE_DDRAW_H) && defined(WIN32) case SCREEN_SURFACE_DDRAW: - if (SDL_MUSTLOCK(sdl.blit.surface)) { - SDL_UnlockSurface(sdl.blit.surface); - } + SDL_UnlockSurface(sdl.blit.surface); ret=IDirectDrawSurface3_Blt( sdl.surface->hwdata->dd_writebuf,&sdl.blit.rect, sdl.blit.surface->hwdata->dd_surface,0, diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index ec47222d..b6d0f661 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -64,7 +64,6 @@ void VGA_DetermineMode(void) { VGA_SetMode(M_LIN4); else VGA_SetMode(M_EGA); - } } else { VGA_SetMode(M_TEXT); diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index efbc61d6..0f8fcf52 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -242,6 +242,13 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) { break; case 0x14: /* Underline Location Register */ crtc(underline_location)=val; + //Byte,word,dword mode + if ( crtc(underline_location) & 0x20 ) + vga.config.addr_shift = 2; + else if ( crtc( mode_control) & 0x40 ) + vga.config.addr_shift = 0; + else + vga.config.addr_shift = 1; /* 0-4 Position of underline within Character cell. 5 If set memory address is only changed every fourth character clock. @@ -268,7 +275,24 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) { break; case 0x17: /* Mode Control Register */ crtc(mode_control)=val; + vga.tandy.line_mask = (~val) & 3; + //Byte,word,dword mode + if ( crtc(underline_location) & 0x20 ) + vga.config.addr_shift = 2; + else if ( crtc( mode_control) & 0x40 ) + vga.config.addr_shift = 0; + else + vga.config.addr_shift = 1; + + if ( vga.tandy.line_mask ) { + vga.tandy.line_shift = 13; + vga.tandy.addr_mask = (1 << 13) - 1; + } else { + vga.tandy.addr_mask = ~0; + vga.tandy.line_shift = 0; + } VGA_DetermineMode(); + //Should we really need to do a determinemode here? /* 0 If clear use CGA compatible memory addressing system by substituting character row scan counter bit 0 for address bit 13, diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index a67432f1..1de5a1b3 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -27,46 +27,41 @@ #define VGA_PARTS 4 -typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart,Bitu panning,Bitu line); -typedef void (* VGA_FrameStart_Handler)(); +typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart, Bitu line); static VGA_Line_Handler VGA_DrawLine; -static VGA_FrameStart_Handler VGA_FrameStart; static Bit8u TempLine[SCALER_MAXWIDTH * 4]; -static Bit8u * VGA_Draw_1BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; - for (Bitu x=vga.draw.blocks;x>0;x--) { - Bitu val=vga.gfxmem_start[vidstart+line]; - vidstart++; - if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing - vidstart &= 0x1dfff; +static Bit8u * VGA_Draw_1BPP_Line(Bitu vidstart, Bitu line) { + const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); + Bit32u *draw = (Bit32u *)TempLine; + for (Bitu x=vga.draw.blocks;x>0;x--, vidstart++) { + Bitu val = base[(vidstart & (8 * 1024 -1))]; *draw++=CGA_2_Table[val >> 4]; *draw++=CGA_2_Table[val & 0xf]; } return TempLine; } -static Bit8u * VGA_Draw_2BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; +static Bit8u * VGA_Draw_2BPP_Line(Bitu vidstart, Bitu line) { + const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); + Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=0;x>4)|(val2&0xf0)]; *draw++=CGA_4_HiRes_Table[(val1&0x0f)|((val2&0x0f)<<4)]; } @@ -75,8 +70,9 @@ static Bit8u * VGA_Draw_2BPPHiRes_Line(Bitu vidstart,Bitu panning,Bitu line) { static Bitu temp[643]={0}; -static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart,Bitu panning,Bitu line) { - const Bit8u * reader=&vga.mem.linear[vidstart + (line * 8 * 1024)]; +static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) { + const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); + const Bit8u *reader = base + vidstart; Bit32u * draw=(Bit32u *)TempLine; //Generate a temporary bitline to calculate the avarage //over bit-2 bit-1 bit bit+1. @@ -114,17 +110,14 @@ static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart,Bitu panning,Bitu line) { return TempLine; } -static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; +static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) { + const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); + Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=0;x> 4 | (val2 & 0x0f) << 24 | @@ -133,13 +126,12 @@ static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { return TempLine; } -static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; +static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart, Bitu line) { + const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); + Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=0;x> 4 | (val & 0xf0) << 4 | (val & 0x0f) << 16 | @@ -148,43 +140,48 @@ static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart,Bitu panning,Bitu line) { return TempLine; } -static Bit8u * VGA_Draw_LIN4_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[512*1024+vidstart*8+panning]; -} -static Bit8u * VGA_Draw_EGA_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[512*1024+vidstart*8+panning]; -} -static Bit8u * VGA_Draw_VGA_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[vidstart*4+panning]; -} -static Bit8u * VGA_Draw_LIN16_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[vidstart*4+panning]; -} -static Bit8u * VGA_Draw_LIN32_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[vidstart*4+panning]; +#ifdef VGA_KEEP_CHANGES +static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) { + Bitu checkMask = vga.changes.checkMask; + Bit8u *map = vga.changes.map; + Bitu start = (vidstart >> VGA_CHANGE_SHIFT); + Bitu end = ((vidstart + vga.changes.lineWidth ) >> VGA_CHANGE_SHIFT); + for (; start <= end;start++) { + if ( map[start] & checkMask ) { + return &vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]; + } + } +// memset( TempLine, 0x30, vga.changes.lineWidth ); +// return TempLine; + return 0; } -static Bit8u * VGA_Draw_VGAChained_Line(Bitu vidstart,Bitu panning,Bitu line) { - return &vga.mem.linear[512*1024+((vidstart*4+panning)&0xffff)]; +#endif + +static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu line) { + return &vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]; } -static void VGA_StartFrame_VGA() { - if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) - VGA_DrawLine=VGA_Draw_VGAChained_Line; - else - VGA_DrawLine = VGA_Draw_VGA_Line; +static Bit8u * VGA_Draw_Chain_Line(Bitu vidstart, Bitu line) { + Bitu i = 0; + for ( i = 0; i < vga.draw.width;i++ ) { + Bitu addr = vidstart + i; + TempLine[i] = vga.mem.linear[((addr&~3)<<2)+(addr&3)]; + } + return TempLine; } -static Bit8u * VGA_Draw_VGA_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) { + +static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = 4 * vidstart / vga.draw.width; + Bitu lineat = vidstart / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { - return VGA_Draw_VGA_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } else { - memcpy(TempLine, VGA_Draw_VGA_Line(vidstart, panning, line), vga.draw.width); + memcpy(TempLine, &vga.mem.linear[ vidstart ], vga.draw.width); /* Draw mouse cursor */ Bits moff = ((Bits)lineat - (Bits)vga.s3.hgc.originy) + (Bits)vga.s3.hgc.posy; - if(moff>63) return VGA_Draw_VGA_Line(vidstart, panning, line); + if(moff>63) return &vga.mem.linear[ vidstart ]; if(moff<0) moff+=64; Bitu xat = vga.s3.hgc.originx; Bitu m, mapat; @@ -231,20 +228,20 @@ static Bit8u * VGA_Draw_VGA_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) } } else { /* HW Mouse not enabled, use the tried and true call */ - return VGA_Draw_VGA_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } } -static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) { +static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = 2 * vidstart / vga.draw.width; + Bitu lineat = (vidstart >> 1) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { - return VGA_Draw_LIN16_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } else { - memcpy(TempLine, VGA_Draw_LIN16_Line(vidstart, panning, line), 2*vga.draw.width); + memcpy(TempLine, &vga.mem.linear[ vidstart ], 2*vga.draw.width); /* Draw mouse cursor */ Bits moff = ((Bits)lineat - (Bits)vga.s3.hgc.originy) + (Bits)vga.s3.hgc.posy; - if(moff>63) return VGA_Draw_LIN16_Line(vidstart, panning, line); + if(moff>63) return &vga.mem.linear[ vidstart ]; if(moff<0) moff+=64; Bitu xat = 2*vga.s3.hgc.originx; Bitu m, mapat; @@ -294,20 +291,20 @@ static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu lin } } else { /* HW Mouse not enabled, use the tried and true call */ - return VGA_Draw_LIN16_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } } -static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) { +static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu line) { if(vga.s3.hgc.curmode & 0x1) { - Bitu lineat = vidstart / vga.draw.width; + Bitu lineat = (vidstart >> 2) / vga.draw.width; if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63U))) { - return VGA_Draw_LIN32_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } else { - memcpy(TempLine, VGA_Draw_LIN32_Line(vidstart, panning, line), 4*vga.draw.width); + memcpy(TempLine, &vga.mem.linear[ vidstart ], 4*vga.draw.width); /* Draw mouse cursor */ Bits moff = ((Bits)lineat - (Bits)vga.s3.hgc.originy) + (Bits)vga.s3.hgc.posy; - if(moff>63) return VGA_Draw_LIN32_Line(vidstart, panning, line); + if(moff>63) return &vga.mem.linear[ vidstart ]; if(moff<0) moff+=64; Bitu xat = 4*vga.s3.hgc.originx; Bitu m, mapat; @@ -363,15 +360,15 @@ static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu lin } } else { /* HW Mouse not enabled, use the tried and true call */ - return VGA_Draw_LIN32_Line(vidstart, panning, line); + return &vga.mem.linear[ vidstart ]; } } static Bit32u FontMask[2]={0xffffffff,0x0}; -static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { +static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) { Bitu font_addr; Bit32u * draw=(Bit32u *)TempLine; - Bit8u * vidmem=&vga.gfxmem_start[vidstart]; + const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; for (Bitu cx=0;cxvga.draw.cursor.eline) goto skip_cursor; draw=(Bit32u *)&TempLine[font_addr*8]; - Bit32u att=TXT_FG_Table[vga.gfxmem_start[vga.draw.cursor.address+1]&0xf]; + Bit32u att=TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]; *draw++=att;*draw++=att; } skip_cursor: @@ -397,7 +394,7 @@ skip_cursor: } static void VGA_VerticalDisplayEnd(Bitu val) { - vga.config.retrace=true; +// vga.config.retrace=true; vga.config.real_start=vga.config.display_start & ((2*1024*1024)-1); } @@ -405,28 +402,55 @@ static void VGA_HorizontalTimer(void) { } +#ifdef VGA_KEEP_CHANGES +static INLINE void VGA_ChangesEnd(void ) { + if ( vga.changes.active ) { +// vga.changes.active = false; + Bitu end = vga.draw.address >> VGA_CHANGE_SHIFT; + Bitu total = 4 + end - vga.changes.start; + Bit32u clearMask = vga.changes.clearMask; + total >>= 2; + Bit32u *clear = (Bit32u *)&vga.changes.map[ vga.changes.start & ~3 ]; + while ( total-- ) { + clear[0] &= clearMask; + clear++; + } + } +} +#endif + + static void VGA_DrawPart(Bitu lines) { while (lines--) { - vga.draw.lines_done++; - Bit8u * data=VGA_DrawLine(vga.draw.address,vga.draw.panning,vga.draw.address_line); + Bit8u * data=VGA_DrawLine( vga.draw.address, 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; } + vga.draw.lines_done++; if (vga.draw.split_line==vga.draw.lines_done) { +#ifdef VGA_KEEP_CHANGES + VGA_ChangesEnd( ); +#endif vga.draw.address=0; - if(vga.attr.mode_control&0x20) - vga.draw.panning=0; + if(!(vga.attr.mode_control&0x20)) + vga.draw.address += vga.draw.panning; vga.draw.address_line=0; +#ifdef VGA_KEEP_CHANGES + vga.changes.start = vga.draw.address >> VGA_CHANGE_SHIFT; +#endif } } if (--vga.draw.parts_left) { - PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts, + PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts, (vga.draw.parts_left!=1) ? vga.draw.parts_lines : (vga.draw.lines_total - vga.draw.lines_done)); } else { - RENDER_EndUpdate( true ); +#ifdef VGA_KEEP_CHANGES + VGA_ChangesEnd(); +#endif + RENDER_EndUpdate(); } } @@ -445,26 +469,81 @@ void VGA_SetBlinking(Bitu enabled) { for (Bitu i=0;i<8;i++) TXT_BG_Table[i+8]=(b+i) | ((b+i) << 8)| ((b+i) <<16) | ((b+i) << 24); } -static void VGA_VerticalTimer(Bitu val) { - if (VGA_FrameStart) - VGA_FrameStart(); - vga.config.retrace=false; - PIC_AddEvent(VGA_VerticalTimer,vga.draw.delay.vtotal); - PIC_AddEvent(VGA_VerticalDisplayEnd,vga.draw.delay.vend); - bool bDoDraw = RENDER_StartUpdate(); - if (bDoDraw) { -// if (RENDER_StartUpdate()) { - vga.draw.parts_left=vga.draw.parts_total; - vga.draw.lines_done=0; - vga.draw.address=vga.config.real_start; - vga.draw.address_line=vga.config.hlines_skip; - vga.draw.split_line=(vga.config.line_compare/vga.draw.lines_scaled); - vga.draw.panning=vga.config.pel_panning; -// PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts,vga.draw.parts_lines); +#ifdef VGA_KEEP_CHANGES +static void INLINE VGA_ChangesStart( void ) { + vga.changes.start = vga.draw.address >> VGA_CHANGE_SHIFT; + vga.changes.last = vga.changes.start; + if ( vga.changes.lastAddress != vga.draw.address ) { +// LOG_MSG("Address"); + VGA_DrawLine = VGA_Draw_Linear_Line; + vga.changes.lastAddress = vga.draw.address; + } else if ( render.fullFrame ) { +// LOG_MSG("Full Frame"); + VGA_DrawLine = VGA_Draw_Linear_Line; + } else { +// LOG_MSG("Changes"); + VGA_DrawLine = VGA_Draw_Changes_Line; } + vga.changes.active = true; + vga.changes.checkMask = vga.changes.writeMask; + vga.changes.clearMask = ~( 0x01010101 << (vga.changes.frame & 7)); + vga.changes.frame++; + vga.changes.writeMask = 1 << (vga.changes.frame & 7); +} +#endif + + +static void VGA_VerticalTimer(Bitu val) { + double error = vga.draw.delay.framestart; + vga.draw.delay.framestart = PIC_FullIndex(); + error = vga.draw.delay.framestart - error - vga.draw.delay.vtotal; +// if (abs(error) > 0.001 ) +// LOG_MSG("vgaerror: %f",error); + PIC_AddEvent(VGA_VerticalTimer, (float)vga.draw.delay.vtotal ); + if ( GCC_UNLIKELY( vga.draw.parts_left )) { + LOG_MSG( "parts left: %d", vga.draw.parts_left ); + PIC_RemoveEvents( &VGA_DrawPart ); + } + //Check if we can actually render, else skip the rest + if (!RENDER_StartUpdate()) + return; + //TODO Maybe check for an active frame on parts_left and clear that first? + vga.draw.parts_left=vga.draw.parts_total; + vga.draw.lines_done=0; + vga.draw.address=vga.config.display_start; + vga.draw.address_line=vga.config.hlines_skip; + vga.draw.split_line=(vga.config.line_compare/vga.draw.lines_scaled); switch (vga.mode) { + case M_EGA: + vga.draw.address *= 8; + vga.draw.address += vga.config.pel_panning; +#ifdef VGA_KEEP_CHANGES + VGA_ChangesStart(); +#endif + break; + case M_VGA: + if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) { + vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; + vga.draw.linear_mask = 0xffff; + VGA_DrawLine = VGA_Draw_Chain_Line; + } else { + vga.draw.linear_base = vga.mem.linear; + vga.draw.linear_mask = VGA_MEMORY - 1; + VGA_DrawLine = VGA_Draw_Linear_Line; + } + case M_LIN8: + case M_LIN15: + case M_LIN16: + case M_LIN32: + vga.draw.address *= 4; + vga.draw.address += vga.config.pel_panning; +#ifdef VGA_KEEP_CHANGES + VGA_ChangesStart(); +#endif + break; case M_TEXT: - vga.draw.address=(vga.draw.address*2); + vga.draw.address *= 2; + vga.draw.panning = vga.config.pel_panning; case M_TANDY_TEXT: case M_HERC_TEXT: vga.draw.cursor.address=vga.config.cursor_start*2; @@ -473,30 +552,32 @@ static void VGA_VerticalTimer(Bitu val) { FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ? 0 : 0xffffffff; break; - case M_CGA4:case M_CGA2:case M_CGA16: - case M_TANDY2:case M_TANDY4:case M_TANDY16: + case M_HERC_GFX: + break; + case M_CGA4:case M_CGA2: vga.draw.address=(vga.draw.address*2)&0x1fff; break; + case M_CGA16: + case M_TANDY2:case M_TANDY4:case M_TANDY16: + vga.draw.address *= 2; + break; } - if (IS_TANDY_ARCH) { - vga.draw.address+=vga.tandy.disp_bank << 14; - vga.draw.cursor.address+=vga.tandy.disp_bank << 14; - } - if (bDoDraw) -// VGA_DrawPart(vga.draw.parts_lines); - PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts/2,vga.draw.parts_lines); //Else tearline in Tyrian and second reality + VGA_DrawPart( vga.draw.parts_lines ); +// PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts/2,vga.draw.parts_lines); //Else tearline in Tyrian and second reality } void VGA_CheckScanLength(void) { switch (vga.mode) { case M_EGA: - case M_VGA: case M_LIN4: + vga.draw.address_add=vga.config.scan_len*16; + break; + case M_VGA: case M_LIN8: case M_LIN15: case M_LIN16: case M_LIN32: - vga.draw.address_add=vga.config.scan_len*2; + vga.draw.address_add=vga.config.scan_len*8; break; case M_TEXT: vga.draw.address_add=vga.config.scan_len*4; @@ -541,17 +622,7 @@ void VGA_ActivateHardwareCursor(void) { VGA_DrawLine=VGA_Draw_VGA_Line_HWMouse; } } else { - switch(vga.mode) { - case M_LIN32: - VGA_DrawLine=VGA_Draw_LIN32_Line; - break; - case M_LIN15: - case M_LIN16: - VGA_DrawLine=VGA_Draw_LIN16_Line; - break; - default: - VGA_DrawLine=VGA_Draw_VGA_Line; - } + VGA_DrawLine=VGA_Draw_Linear_Line; } } @@ -563,24 +634,49 @@ void VGA_SetupDrawing(Bitu val) { } /* Calculate the FPS for this screen */ float fps;Bitu clock; - Bitu htotal,hdispend,hbstart,hrstart; - Bitu vtotal,vdispend,vbstart,vrstart; + Bitu htotal, hdend, hbstart, hbend, hrstart, hrend; + Bitu vtotal, vdend, vbstart, vbend, vrstart, vrend; if (machine==MCH_VGA) { + htotal = 5 + vga.crtc.horizontal_total; + hdend = 1 + vga.crtc.horizontal_display_end; + hbstart = vga.crtc.start_horizontal_blanking; + hbend = vga.crtc.end_horizontal_blanking&0x1F | + ((vga.crtc.end_horizontal_retrace&0x80)>>2); + hbend = hbstart + ((hbend - hbstart) & 0x3F); + hrstart = vga.crtc.start_horizontal_retrace; + hrend = vga.crtc.end_horizontal_retrace & 0x1f; + hrend = (hrend - hrstart) & 0x1f; + if ( !hrend ) + hrend = hrstart + 0x1f + 1; + else + hrend = hrstart + hrend; + vtotal=2 + vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4); - htotal=5 + vga.crtc.horizontal_total; - vdispend = 1 + (vga.crtc.vertical_display_end | - ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) | + vdend = 1 + (vga.crtc.vertical_display_end | + ((vga.crtc.overflow & 2)<<7) | + ((vga.crtc.overflow & 0x40) << 3) | ((vga.s3.ex_ver_overflow & 0x2) << 9)); - hdispend = 1 + (vga.crtc.horizontal_display_end); - hbstart = vga.crtc.start_horizontal_blanking; - vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) | - ((vga.crtc.maximum_scan_line & 0x20) << 4) ; - hrstart = vga.crtc.start_horizontal_retrace; - vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6) | + vrstart = vga.crtc.vertical_retrace_start + + ((vga.crtc.overflow & 0x04) << 6) | ((vga.crtc.overflow & 0x80) << 2); - if (hbstart0; } else { - vga.draw.address_line_total=vga.other.max_scanline+1; - htotal=vga.other.htotal+1; - hdispend=vga.other.hdend; - hrstart=vga.other.hsyncp; - vtotal=vga.draw.address_line_total*(vga.other.vtotal+1)+vga.other.vadjust; - vdispend=vga.draw.address_line_total*vga.other.vdend; - vrstart=vga.draw.address_line_total*vga.other.vsyncp; + htotal = vga.other.htotal + 1; + hdend = vga.other.hdend; + hbstart = hdend; + hbend = htotal; + hrstart = vga.other.hsyncp; + hrend = hrstart + (vga.other.syncw & 0xf) ; + + vga.draw.address_line_total = vga.other.max_scanline + 1; + vtotal = vga.draw.address_line_total * (vga.other.vtotal+1)+vga.other.vadjust; + vdend = vga.draw.address_line_total * vga.other.vdend; + vrstart = vga.draw.address_line_total * vga.other.vsyncp; + vrend = (vga.other.syncw >> 4); + if (!vrend) + vrend = vrstart + 0xf + 1; + else + vrend = vrstart + vrend; + vbstart = vdend; + vbend = vtotal; vga.draw.double_scan=false; switch (machine) { case MCH_CGA: @@ -627,69 +734,92 @@ void VGA_SetupDrawing(Bitu val) { break; } } - 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); + LOG(LOG_VGA,LOG_NORMAL)("h total %d end %d blank (%d/%d) retrace (%d/%d)", + htotal, hdend, hbstart, hbend, hrstart, hrend ); + LOG(LOG_VGA,LOG_NORMAL)("v total %d end %d blank (%d/%d) retrace (%d/%d)", + vtotal, vdend, vbstart, vbend, vrstart, vrend ); + if (!htotal) return; if (!vtotal) return; + fps=(float)clock/(vtotal*htotal); - float linetime=1000.0f/fps; - vga.draw.parts_total=VGA_PARTS; - vga.draw.delay.vtotal=linetime; - linetime/=vtotal; //Really make it the line_delay - vga.draw.delay.vend=linetime*vrstart; - vga.draw.delay.parts=(linetime*vdispend)/vga.draw.parts_total; - vga.draw.delay.htotal=linetime; - vga.draw.delay.hend=(linetime/htotal)*hrstart; + // The time a complete video frame takes + vga.draw.delay.vtotal = (1000.0 * (double)(vtotal*htotal)) / (double)clock; + // Horizontal total (that's how long a line takes with whistles and bells) + vga.draw.delay.htotal = htotal*1000.0/clock; //in milliseconds + // Start and End of horizontal blanking + vga.draw.delay.hblkstart = hbstart*1000.0/clock; //in milliseconds + vga.draw.delay.hblkend = hbend*1000.0/clock; + vga.draw.delay.hrstart = 0; + + // Start and End of vertical blanking + vga.draw.delay.vblkstart = vbstart * vga.draw.delay.htotal; + vga.draw.delay.vblkend = vbend * vga.draw.delay.htotal; + // Start and End of vertical retrace pulse + vga.draw.delay.vrstart = vrstart * vga.draw.delay.htotal; + vga.draw.delay.vrend = vrend * vga.draw.delay.htotal; + // Display end + vga.draw.delay.vdend = vdend * vga.draw.delay.htotal; + /* + // just curious + LOG_MSG("H total %d, V Total %d",htotal,vtotal); + LOG_MSG("H D End %d, V D End %d",hdispend,vdispend); + LOG_MSG("vrstart: %d, vrend: %d\n",vrstart,vrend); + LOG_MSG("htotal: %2.6f, vtotal: %2.6f,\n"\ + "hblkstart: %2.6f, hblkend: %2.6f,\n"\ + "vblkstart: %2.6f, vblkend: %2.6f,\n"\ + "vrstart: %2.6f, vrend: %2.6f,\n"\ + "vdispend: %2.6f", + vga.draw.delay.htotal, vga.draw.delay.vtotal, + vga.draw.delay.hblkstart, vga.draw.delay.hblkend, + vga.draw.delay.vblkstart, vga.draw.delay.vblkend, + vga.draw.delay.vrstart, vga.draw.delay.vrend, + vga.draw.delay.vend); + */ + vga.draw.parts_total=VGA_PARTS; double correct_ratio=(100.0/525.0); double aspect_ratio=((double)htotal/((double)vtotal)/correct_ratio); vga.draw.resizing=false; - Bitu width=hdispend; - Bitu height=vdispend; - Bitu bpp=8; + + //Check to prevent useless black areas + if (hbstart>= 1; - } - /* Use HW mouse cursor drawer if enabled */ - VGA_ActivateHardwareCursor(); - break; case M_LIN15: - bpp = 15; - width<<=3; - if (vga.crtc.mode_control & 0x8) { - doublewidth = true; - width >>= 1; - } - /* Use HW mouse cursor drawer if enabled */ - VGA_ActivateHardwareCursor(); - break; case M_LIN16: - bpp = 16; - width<<=3; - if (vga.crtc.mode_control & 0x8) { - doublewidth = true; - width >>= 1; - } - /* Use HW mouse cursor drawer if enabled */ - VGA_ActivateHardwareCursor(); - break; case M_LIN32: - bpp = 32; width<<=3; if (vga.crtc.mode_control & 0x8) { doublewidth = true; @@ -702,13 +832,17 @@ void VGA_SetupDrawing(Bitu val) { doublewidth=(vga.seq.clocking_mode & 0x8) > 0; vga.draw.blocks = width; width<<=3; - VGA_DrawLine=VGA_Draw_LIN4_Line; + VGA_DrawLine=VGA_Draw_Linear_Line; + vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; + vga.draw.linear_mask = 1024 * 1024 - 1; break; case M_EGA: doublewidth=(vga.seq.clocking_mode & 0x8) > 0; vga.draw.blocks = width; width<<=3; - VGA_DrawLine=VGA_Draw_EGA_Line; + VGA_DrawLine=VGA_Draw_Linear_Line; + vga.draw.linear_base = vga.mem.linear + VGA_CACHE_OFFSET; + vga.draw.linear_mask = 512 * 1024 - 1; break; case M_CGA16: doubleheight=true; @@ -758,18 +892,26 @@ void VGA_SetupDrawing(Bitu val) { vga.draw.blocks=width * 2; width=vga.draw.blocks*4; if ((machine==MCH_TANDY && (vga.tandy.gfx_control & 0x8)) || - (machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) VGA_DrawLine=VGA_Draw_2BPPHiRes_Line; + (machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) + VGA_DrawLine=VGA_Draw_2BPPHiRes_Line; else VGA_DrawLine=VGA_Draw_2BPP_Line; break; case M_TANDY16: aspect_ratio=1.2; doubleheight=true; - doublewidth=true; vga.draw.blocks=width*2; if (vga.tandy.mode_control & 0x1) { - width=vga.draw.blocks*2; + if ( vga.tandy.mode_control & 0x10 ) { + doublewidth = false; + vga.draw.blocks*=2; + width=vga.draw.blocks*2; + } else { + doublewidth = true; + width=vga.draw.blocks*2; + } VGA_DrawLine=VGA_Draw_4BPP_Line; } else { + doublewidth=true; width=vga.draw.blocks*4; VGA_DrawLine=VGA_Draw_4BPP_Line_Double; } @@ -799,6 +941,13 @@ void VGA_SetupDrawing(Bitu val) { } vga.draw.lines_total=height; vga.draw.parts_lines=vga.draw.lines_total/vga.draw.parts_total; + +#ifdef VGA_KEEP_CHANGES + vga.changes.active = false; + vga.changes.lineWidth = width * ((bpp + 1) / 8); + vga.changes.frame = 0; + vga.changes.writeMask = 1; +#endif if (( width != vga.draw.width) || (height != vga.draw.height) || (vga.mode != vga.lastmode)) { vga.lastmode = vga.mode; PIC_RemoveEvents(VGA_VerticalTimer); @@ -816,7 +965,8 @@ void VGA_SetupDrawing(Bitu val) { doublewidth ? "double":"normal",doubleheight ? "double":"normal",aspect_ratio); #endif RENDER_SetSize(width,height,bpp,fps,aspect_ratio,doublewidth,doubleheight); - PIC_AddEvent(VGA_VerticalTimer,vga.draw.delay.vtotal); + vga.draw.delay.framestart = PIC_FullIndex(); + PIC_AddEvent( VGA_VerticalTimer , vga.draw.delay.vtotal ); } }; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index fc078f70..2588264e 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -25,6 +25,37 @@ #include "pic.h" #include "inout.h" +#ifdef VGA_KEEP_CHANGES +#define MEM_CHANGED( _MEM ) vga.changes.map[ (_MEM) >> VGA_CHANGE_SHIFT ] |= vga.changes.writeMask; +//#define MEM_CHANGED( _MEM ) vga.changes.map[ (_MEM) >> VGA_CHANGE_SHIFT ] = 1; +#else +#define MEM_CHANGED( _MEM ) +#endif + +#define TANDY_VIDBASE(_X_) &MemBase[ 0x80000 + (_X_)] + +template +static INLINE void hostWrite(HostPt off, Bitu val) { + if ( sizeof( Size ) == 1) + host_writeb( off, (Bit8u)val ); + else if ( sizeof( Size ) == 2) + host_writew( off, (Bit16u)val ); + else if ( sizeof( Size ) == 4) + host_writed( off, (Bit32u)val ); +} + +template +static INLINE Bitu hostRead(HostPt off ) { + if ( sizeof( Size ) == 1) + return host_readb( off ); + else if ( sizeof( Size ) == 2) + return host_readw( off ); + else if ( sizeof( Size ) == 4) + return host_readd( off ); + return 0; +} + + void VGA_MapMMIO(void); //Nice one from DosEmu INLINE static Bit32u RasterOp(Bit32u input,Bit32u mask) { @@ -83,8 +114,7 @@ static struct { class VGA_UnchainedRead_Handler : public PageHandler { public: Bitu readHandler(PhysPt start) { - start += vga.s3.svga_bank.fullbank; - vga.latch.d=vga.mem.latched[start].d; + vga.latch.d=((Bit32u*)vga.mem.linear)[start]; switch (vga.config.read_mode) { case 0: return (vga.latch.b[vga.config.read_map_select]); @@ -116,45 +146,20 @@ public: } }; -class VGA_Chained_ReadHandler : public PageHandler { +class VGA_ChainedEGA_Handler : public PageHandler { public: Bitu readHandler(PhysPt addr) { - if(vga.mode == M_VGA) - return vga.mem.linear[((addr&~3)<<2)|(addr&3)]; return vga.mem.linear[addr]; } -public: - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - return readHandler(addr); - } - Bitu readw(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8); - } - Bitu readd(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8) | - (readHandler(addr+2) << 16) | - (readHandler(addr+3) << 24); - } -}; - -class VGA_ChainedEGA_Handler : public VGA_Chained_ReadHandler { -public: void writeHandler(PhysPt start, Bit8u val) { Bit32u data=ModeOperation(val); /* Update video memory and the pixel buffer */ VGA_Latch pixels; vga.mem.linear[start] = val; start >>= 2; - pixels.d=vga.mem.latched[start].d; + pixels.d=((Bit32u*)vga.mem.linear)[start]; - Bit8u * write_pixels=&vga.mem.linear[512*1024+(start<<3)]; + Bit8u * write_pixels=&vga.mem.linear[VGA_CACHE_OFFSET+(start<<3)]; Bit32u colors0_3, colors4_7; VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; @@ -178,33 +183,55 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + MEM_CHANGED( addr << 3); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); writeHandler(addr+2,(Bit8u)(val >> 16)); writeHandler(addr+3,(Bit8u)(val >> 24)); } + Bitu readb(PhysPt addr) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + return readHandler(addr); + } + Bitu readw(PhysPt addr) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + return + (readHandler(addr+0) << 0) | + (readHandler(addr+1) << 8); + } + Bitu readd(PhysPt addr) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + return + (readHandler(addr+0) << 0) | + (readHandler(addr+1) << 8) | + (readHandler(addr+2) << 16) | + (readHandler(addr+3) << 24); + } }; class VGA_UnchainedEGA_Handler : public VGA_UnchainedRead_Handler { public: + template< bool wrapping> void writeHandler(PhysPt start, Bit8u val) { Bit32u data=ModeOperation(val); /* Update video memory and the pixel buffer */ VGA_Latch pixels; - pixels.d=vga.mem.latched[start].d; + pixels.d=((Bit32u*)vga.mem.linear)[start]; pixels.d&=vga.config.full_not_map_mask; pixels.d|=(data & vga.config.full_map_mask); - vga.mem.latched[start].d=pixels.d; - Bit8u * write_pixels=&vga.mem.linear[512*1024+(start<<3)]; + ((Bit32u*)vga.mem.linear)[start]=pixels.d; + Bit8u * write_pixels=&vga.mem.linear[VGA_CACHE_OFFSET+(start<<3)]; Bit32u colors0_3, colors4_7; VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; @@ -214,7 +241,6 @@ public: Expand16Table[2][temp.b[2]] | Expand16Table[3][temp.b[3]]; *(Bit32u *)write_pixels=colors0_3; - *(Bit32u *)(write_pixels+512*1024)=colors0_3; temp.d=pixels.d & 0x0f0f0f0f; colors4_7 = Expand16Table[0][temp.b[0]] | @@ -222,7 +248,10 @@ public: Expand16Table[2][temp.b[2]] | Expand16Table[3][temp.b[3]]; *(Bit32u *)(write_pixels+4)=colors4_7; - *(Bit32u *)(write_pixels+512*1024+4)=colors4_7; + if (wrapping && GCC_UNLIKELY( start < 512)) { + *(Bit32u *)(write_pixels+512*1024)=colors0_3; + *(Bit32u *)(write_pixels+512*1024+4)=colors4_7; + } } public: VGA_UnchainedEGA_Handler() { @@ -230,68 +259,147 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); + MEM_CHANGED( addr << 3); + writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); + MEM_CHANGED( addr << 3); + writeHandler(addr+0,(Bit8u)(val >> 0)); + writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); + MEM_CHANGED( addr << 3); + writeHandler(addr+0,(Bit8u)(val >> 0)); + writeHandler(addr+1,(Bit8u)(val >> 8)); + writeHandler(addr+2,(Bit8u)(val >> 16)); + writeHandler(addr+3,(Bit8u)(val >> 24)); } }; - -class VGA_ChainedVGA_Handler : public VGA_Chained_ReadHandler { +//Slighly unusual version, will directly write 8,16,32 bits values +class VGA_ChainedVGA_Handler : public PageHandler { public: - void writeHandler(PhysPt addr, Bitu val) { - // No need to check for compatible chains here, this one is only enabled if that bit is set - vga.mem.linear[((addr&~3)<<2)|(addr&3)] = val; - // Linearized version for faster rendering - vga.mem.linear[512*1024+addr] = val; - if (addr >= 320) return; - // And replicate the first line - vga.mem.linear[512*1024+addr+64*1024] = val; - } -public: VGA_ChainedVGA_Handler() { flags=PFLAG_NOCODE; } - void writeb(PhysPt addr,Bitu val) { + template + static INLINE Bitu readHandler(PhysPt addr ) { + return hostRead( &vga.mem.linear[((addr&~3)<<2)+(addr&3)] ); + } + template + static INLINE void writeCache(PhysPt addr, Bitu val) { + hostWrite( &vga.mem.linear[VGA_CACHE_OFFSET+addr], val ); + if (GCC_UNLIKELY(addr < 320)) { + // And replicate the first line + hostWrite( &vga.mem.linear[VGA_CACHE_OFFSET+addr+64*1024], val ); + } + } + template + static INLINE void writeHandler(PhysPt addr, Bitu val) { + // No need to check for compatible chains here, this one is only enabled if that bit is set + hostWrite( &vga.mem.linear[((addr&~3)<<2)+(addr&3)], val ); + } + Bitu readb(PhysPt addr ) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); + return readHandler( addr ); + } + Bitu readw(PhysPt addr ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + return readHandler( addr ); + } + Bitu readd(PhysPt addr ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + return readHandler( addr ); + } + bool readw_checked( PhysPt addr,Bitu *val ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + if ( addr & 1) { + *val = + (readHandler( addr+0 ) << 0 ) | + (readHandler( addr+1 ) << 8 ); + } else { + *val = readHandler( addr ); + } + return false; + } + bool readd_checked( PhysPt addr,Bitu *val ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + if ( addr & 3) { + *val = + (readHandler( addr+0 ) << 0 ) | + (readHandler( addr+1 ) << 8 ) | + (readHandler( addr+2 ) << 16 ) | + (readHandler( addr+3 ) << 24 ); + } else { + *val = readHandler( addr ); + } + return false; + } + void writeb(PhysPt addr, Bitu val ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + MEM_CHANGED( addr ); + writeHandler( addr, val ); + writeCache( addr, val ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); + MEM_CHANGED( addr ); + writeHandler( addr, val ); + writeCache( addr, val ); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); + MEM_CHANGED( addr ); + writeHandler( addr, val ); + writeCache( addr, val ); + } + bool writew_checked( PhysPt addr,Bitu val ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + if ( addr & 1 ) { + MEM_CHANGED( addr ); + MEM_CHANGED( addr + 1); + writeHandler( addr+0, val >> 0 ); + writeHandler( addr+1, val >> 8 ); + writeCache( addr, val ); + } else { + MEM_CHANGED( addr ); + writeHandler( addr, val ); + writeCache( addr, val ); + } + return false; + } + bool writed_checked( PhysPt addr,Bitu val ) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + if ( addr & 3) { + MEM_CHANGED( addr ); + MEM_CHANGED( addr + 3); + writeHandler( addr+0, val >> 0 ); + writeHandler( addr+1, val >> 8 ); + writeHandler( addr+2, val >> 16 ); + writeHandler( addr+3, val >> 24 ); + writeCache( addr, val ); + } else { + MEM_CHANGED( addr ); + writeHandler( addr, val ); + writeCache( addr, val ); + } + return false; } }; class VGA_UnchainedVGA_Handler : public VGA_UnchainedRead_Handler { public: void writeHandler( PhysPt addr, Bit8u val ) { - addr += vga.s3.svga_bank.fullbank; Bit32u data=ModeOperation(val); VGA_Latch pixels; - pixels.d=vga.mem.latched[addr].d; + pixels.d=((Bit32u*)vga.mem.linear)[addr]; pixels.d&=vga.config.full_not_map_mask; pixels.d|=(data & vga.config.full_map_mask); - vga.mem.latched[addr].d=pixels.d; + ((Bit32u*)vga.mem.linear)[addr]=pixels.d; if(vga.config.compatible_chain4) - vga.mem.latched[addr+64*1024].d=pixels.d; + ((Bit32u*)vga.mem.linear)[addr+64*1024]=pixels.d; } public: VGA_UnchainedVGA_Handler() { @@ -299,15 +407,21 @@ public: } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr << 2 ); writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr << 2); writeHandler(addr+0,(Bit8u)(val >> 0)); writeHandler(addr+1,(Bit8u)(val >> 8)); writeHandler(addr+2,(Bit8u)(val >> 16)); @@ -332,9 +446,9 @@ public: } }; -class VGA_MAP_PageHandler : public PageHandler { +class VGA_Map_Handler : public PageHandler { public: - VGA_MAP_PageHandler() { + VGA_Map_Handler() { flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; } HostPt GetHostReadPt(Bitu phys_page) { @@ -347,87 +461,88 @@ public: } }; - -class VGA_LIN4Linear_Handler : public VGA_UnchainedEGA_Handler { +class VGA_Changes_Handler : public PageHandler { public: - VGA_LIN4Linear_Handler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); - } - void writew(PhysPt addr,Bitu val) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - } - void writed(PhysPt addr,Bitu val) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); + VGA_Changes_Handler() { + flags=PFLAG_NOCODE; } Bitu readb(PhysPt addr) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - return readHandler(addr); + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + return hostRead( &vga.mem.linear[addr] ); } Bitu readw(PhysPt addr) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8); + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + return hostRead( &vga.mem.linear[addr] ); } Bitu readd(PhysPt addr) { - addr = (PAGING_GetPhysicalAddress(addr) - vga.lfb.addr) & (512*1024-1); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8) | - (readHandler(addr+2) << 16) | - (readHandler(addr+3) << 24); + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + return hostRead( &vga.mem.linear[addr] ); + } + void writeb(PhysPt addr,Bitu val) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr ); + hostWrite( &vga.mem.linear[addr], val ); + } + void writew(PhysPt addr,Bitu val) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr ); + hostWrite( &vga.mem.linear[addr], val ); + } + void writed(PhysPt addr,Bitu val) { + addr = PAGING_GetPhysicalAddress(addr) & 0xffff; + addr += vga.s3.svga_bank.fullbank; + MEM_CHANGED( addr ); + hostWrite( &vga.mem.linear[addr], val ); } }; -class VGA_LIN4Banked_Handler : public VGA_UnchainedEGA_Handler { +class VGA_LIN4_Handler : public VGA_UnchainedEGA_Handler { public: - VGA_LIN4Banked_Handler() { + VGA_LIN4_Handler() { flags=PFLAG_NOCODE; } void writeb(PhysPt addr,Bitu val) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); + addr &= (128*1024-1); + MEM_CHANGED( addr << 3 ); + writeHandler(addr+0,(Bit8u)(val >> 0)); } void writew(PhysPt addr,Bitu val) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); + addr &= (128*1024-1); + MEM_CHANGED( addr << 3 ); + writeHandler(addr+0,(Bit8u)(val >> 0)); + writeHandler(addr+1,(Bit8u)(val >> 8)); } void writed(PhysPt addr,Bitu val) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); + addr &= (128*1024-1); + MEM_CHANGED( addr << 3 ); + writeHandler(addr+0,(Bit8u)(val >> 0)); + writeHandler(addr+1,(Bit8u)(val >> 8)); + writeHandler(addr+2,(Bit8u)(val >> 16)); + writeHandler(addr+3,(Bit8u)(val >> 24)); } Bitu readb(PhysPt addr) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); + addr &= (128*1024-1); return readHandler(addr); } Bitu readw(PhysPt addr) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); + addr &= (128*1024-1); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8); } Bitu readd(PhysPt addr) { addr = vga.s3.svga_bank.fullbank + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr &= (512*1024-1); + addr &= (128*1024-1); return (readHandler(addr+0) << 0) | (readHandler(addr+1) << 8) | @@ -444,31 +559,38 @@ public: } Bitu readb(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - return *(Bit8u*)(&vga.mem.linear[addr]); + return hostRead( &vga.mem.linear[addr] ); } Bitu readw(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - return *(Bit16u*)(&vga.mem.linear[addr]); + return hostRead( &vga.mem.linear[addr] ); } Bitu readd(PhysPt addr) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - return *(Bit32u*)(&vga.mem.linear[addr]); + return hostRead( &vga.mem.linear[addr] ); } void writeb(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - *(Bit8u*)(&vga.mem.linear[addr]) = val; - vga.changed[addr >> VGA_CHANGE_SHIFT] = 1; + hostWrite( &vga.mem.linear[addr], val ); + MEM_CHANGED( addr ); } void writew(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - *(Bit16u*)(&vga.mem.linear[addr]) = val; - vga.changed[addr >> VGA_CHANGE_SHIFT] = 1; + hostWrite( &vga.mem.linear[addr], val ); + MEM_CHANGED( addr ); } void writed(PhysPt addr,Bitu val) { addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - *(Bit32u*)(&vga.mem.linear[addr]) = val; - vga.changed[addr >> VGA_CHANGE_SHIFT] = 1; + hostWrite( &vga.mem.linear[addr], val ); + MEM_CHANGED( addr ); } + bool writed_checked( PhysPt addr,Bitu val ) { + addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; + hostWrite( &vga.mem.linear[addr], val ); + MEM_CHANGED( addr ); + return false; + } + }; class VGA_LFB_Handler : public PageHandler { @@ -569,156 +691,207 @@ public: // |PFLAG_NOCODE; } HostPt GetHostReadPt(Bitu phys_page) { - if (phys_page>=0xb8) { - phys_page-=0xb8; - return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)]; - } else { - if (machine==MCH_TANDY) phys_page-=0x80; - return &vga.mem.linear[phys_page * 4096]; - } + if (vga.tandy.mem_bank & 1) + phys_page&=0x03; + else + phys_page&=0x07; + return vga.tandy.mem_base + (phys_page * 4096); } HostPt GetHostWritePt(Bitu phys_page) { return GetHostReadPt( phys_page ); } }; -class VGA_PCJR_PageHandler : public PageHandler { + +class VGA_PCJR_Handler : public PageHandler { public: - VGA_PCJR_PageHandler() { + VGA_PCJR_Handler() { flags=PFLAG_READABLE|PFLAG_WRITEABLE; } HostPt GetHostReadPt(Bitu phys_page) { phys_page-=0xb8; - if (!vga.tandy.is_32k_mode) phys_page&=0x03; - return MemBase+(vga.tandy.mem_bank << 14)+(phys_page * 4096); + //test for a unaliged bank, then replicate 2x16kb + if (vga.tandy.mem_bank & 1) + phys_page&=0x03; + return vga.tandy.mem_base + (phys_page * 4096); } HostPt GetHostWritePt(Bitu phys_page) { return GetHostReadPt( phys_page ); } }; +class VGA_Empty_Handler : public PageHandler { +public: + VGA_Empty_Handler() { + flags=PFLAG_NOCODE; + } + Bitu readb(PhysPt addr) { +// LOG(LOG_VGA, LOG_NORMAL ) ( "Read from empty memory space at %x", addr ); + return 0xff; + } + void writeb(PhysPt addr,Bitu val) { +// LOG(LOG_VGA, LOG_NORMAL ) ( "Write %x to empty memory space at %x", val, addr ); + } +}; static struct vg { - VGA_MAP_PageHandler map; + VGA_Map_Handler map; + VGA_Changes_Handler changes; VGA_TEXT_PageHandler text; VGA_TANDY_PageHandler tandy; VGA_ChainedEGA_Handler cega; VGA_ChainedVGA_Handler cvga; VGA_UnchainedEGA_Handler uega; VGA_UnchainedVGA_Handler uvga; - VGA_PCJR_PageHandler hpcjr; - VGA_LIN4Banked_Handler l4banked; - VGA_LIN4Linear_Handler l4linear; + VGA_PCJR_Handler pcjr; + VGA_LIN4_Handler lin4; VGA_LFB_Handler lfb; VGA_LFBChanges_Handler lfbchanges; VGA_MMIO_Handler mmio; + VGA_Empty_Handler empty; } vgaph; +void VGA_ChangedBank(void) { +#ifndef VGA_LFB_MAPPED + //If the mode is accurate than the correct mapper must have been installed already + if ( vga.mode >= M_LIN4 && vga.mode <= M_LIN32 ) { + return; + } +#endif + VGA_SetupHandlers(); +} void VGA_SetupHandlers(void) { - PageHandler * range_handler; + PageHandler *newHandler; switch (machine) { case MCH_CGA: - range_handler=&vgaph.map; - goto range_b800; - case MCH_HERC: - range_handler=&vgaph.map; - if (vga.herc.mode_control&0x80) goto range_b800; - else goto range_b000; - case MCH_TANDY: - range_handler=&vgaph.tandy; - MEM_SetPageHandler(0x80,32,range_handler); - goto range_b800; case MCH_PCJR: - range_handler=&vgaph.hpcjr; + MEM_SetPageHandler( VGA_PAGE_B8, 8, &vgaph.pcjr ); + goto range_done; + case MCH_HERC: + vgapages.base=VGA_PAGE_B0; + if (vga.herc.enable_bits & 0x2) { + vgapages.mask=0xffff; + MEM_SetPageHandler(VGA_PAGE_B0,16,&vgaph.map); + } else { + vgapages.mask=0x7fff; + /* With hercules in 32kb mode it leaves a memory hole on 0xb800 */ + MEM_SetPageHandler(VGA_PAGE_B0,8,&vgaph.map); + MEM_SetPageHandler(VGA_PAGE_B8,8,&vgaph.empty); + } + goto range_done; + case MCH_TANDY: + /* Always map 0xa000 - 0xbfff, might overwrite 0xb800 */ + vgapages.base=VGA_PAGE_A0; + vgapages.mask=0x1ffff; + MEM_SetPageHandler(VGA_PAGE_A0, 32, &vgaph.map ); + if ( vga.tandy.extended_ram & 1 ) { + //You seem to be able to also map different 64kb banks, but have to figure that out + //This seems to work so far though + vga.tandy.draw_base = vga.mem.linear; + vga.tandy.mem_base = vga.mem.linear; + } else { + vga.tandy.draw_base = TANDY_VIDBASE( vga.tandy.draw_bank * 16 * 1024); + vga.tandy.mem_base = TANDY_VIDBASE( vga.tandy.mem_bank * 16 * 1024); + MEM_SetPageHandler( 0xb8, 8, &vgaph.tandy ); + } + goto range_done; // MEM_SetPageHandler(vga.tandy.mem_bank<<2,vga.tandy.is_32k_mode ? 0x08 : 0x04,range_handler); - goto range_b800; + case MCH_VGA: + break; + default: + LOG_MSG("Illegal machine type %d", machine ); + return; } + + /* This should be vga only */ switch (vga.mode) { case M_ERROR: return; case M_LIN4: - range_handler=&vgaph.l4banked; + newHandler = &vgaph.lin4; break; case M_LIN15: case M_LIN16: case M_LIN32: - range_handler=&vgaph.map; +#ifdef VGA_LFB_MAPPED + newHandler = &vgaph.map; +#else + newHandler = &vgaph.changes; +#endif break; case M_LIN8: case M_VGA: if (vga.config.chained) { if(vga.config.compatible_chain4) - range_handler = &vgaph.cvga; - else - range_handler=&vgaph.map; + newHandler = &vgaph.cvga; + else +#ifdef VGA_LFB_MAPPED + newHandler = &vgaph.map; +#else + newHandler = &vgaph.changes; +#endif } else { - range_handler=&vgaph.uvga; + newHandler = &vgaph.uvga; } break; case M_EGA: if (vga.config.chained) - range_handler=&vgaph.cega; + newHandler = &vgaph.cega; else - range_handler=&vgaph.uega; + newHandler = &vgaph.uega; break; case M_TEXT: /* Check if we're not in odd/even mode */ - if (vga.gfx.miscellaneous & 0x2) range_handler=&vgaph.map; - else range_handler=&vgaph.text; + if (vga.gfx.miscellaneous & 0x2) newHandler = &vgaph.map; + else newHandler = &vgaph.text; break; case M_CGA4: case M_CGA2: - range_handler=&vgaph.map; + newHandler = &vgaph.map; break; } switch ((vga.gfx.miscellaneous >> 2) & 3) { case 0: - vgapages.base=VGA_PAGE_A0; - vgapages.mask=0x1ffff; - MEM_SetPageHandler(VGA_PAGE_A0,32,range_handler); + vgapages.base = VGA_PAGE_A0; + vgapages.mask = 0x1ffff; + MEM_SetPageHandler(VGA_PAGE_A0, 32, newHandler ); break; case 1: - vgapages.base=VGA_PAGE_A0; - vgapages.mask=0xffff; - MEM_SetPageHandler(VGA_PAGE_A0,16,range_handler); - MEM_ResetPageHandler(VGA_PAGE_B0,16); + vgapages.base = VGA_PAGE_A0; + vgapages.mask = 0xffff; + MEM_SetPageHandler( VGA_PAGE_A0, 16, newHandler ); + MEM_ResetPageHandler( VGA_PAGE_B0, 16); break; case 2: -range_b000: - vgapages.base=VGA_PAGE_B0; - vgapages.mask=0x7fff; - MEM_SetPageHandler(VGA_PAGE_B0,8,range_handler); - MEM_ResetPageHandler(VGA_PAGE_A0,16); - MEM_ResetPageHandler(VGA_PAGE_B8,8); + vgapages.base = VGA_PAGE_B0; + vgapages.mask = 0x7fff; + MEM_SetPageHandler( VGA_PAGE_B0, 8, newHandler ); + MEM_ResetPageHandler( VGA_PAGE_A0, 16 ); + MEM_ResetPageHandler( VGA_PAGE_B8, 8 ); break; case 3: -range_b800: - vgapages.base=VGA_PAGE_B8; - vgapages.mask=0x7fff; - MEM_SetPageHandler(VGA_PAGE_B8,8,range_handler); - MEM_ResetPageHandler(VGA_PAGE_A0,16); - MEM_ResetPageHandler(VGA_PAGE_B0,8); + vgapages.base = VGA_PAGE_B8; + vgapages.mask = 0x7fff; + MEM_SetPageHandler( VGA_PAGE_B8, 8, newHandler ); + MEM_ResetPageHandler( VGA_PAGE_A0, 16 ); + MEM_ResetPageHandler( VGA_PAGE_B0, 8 ); break; } - if(((vga.s3.ext_mem_ctrl & 0x10) != 0x00) /*&& (vga.mode == M_LIN8)*/) MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); - +range_done: PAGING_ClearTLB(); } void VGA_StartUpdateLFB(void) { vga.lfb.page = vga.s3.la_window << 4; vga.lfb.addr = vga.s3.la_window << 16; - switch (vga.mode) { - case M_LIN4: - vga.lfb.handler = &vgaph.l4linear; - break; - default: - vga.lfb.handler = &vgaph.lfbchanges; - break; - } +#ifdef VGA_LFB_MAPPED + vga.lfb.handler = &vgaph.lfb; +#else + vga.lfb.handler = &vgaph.lfbchanges; +#endif MEM_SetLFB(vga.s3.la_window << 4 ,sizeof(vga.mem.linear)/4096, vga.lfb.handler ); } @@ -732,11 +905,14 @@ void VGA_UnmapMMIO(void) { void VGA_SetupMemory() { - memset((void *)&vga.mem,0,512*1024*4); + memset( &vga.mem, 0, VGA_MEMORY ); +#ifdef VGA_KEEP_CHANGES + memset( &vga.changes, 0, sizeof( vga.changes )); +#endif vga.s3.svga_bank.fullbank=0; if (machine==MCH_PCJR) { /* PCJr does not have dedicated graphics memory but uses conventional memory below 128k */ - vga.gfxmem_start=GetMemBase(); - } else vga.gfxmem_start=&vga.mem.linear[0]; + //TODO map? + } } diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 6afaf91c..9306acf9 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -20,6 +20,7 @@ #include "inout.h" #include "pic.h" #include "vga.h" +#include static Bit8u flip=0; @@ -31,24 +32,45 @@ Bitu vga_read_p3d5(Bitu port,Bitu iolen); static Bitu vga_read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; vga.tandy.pcjr_flipflop=false; - if (vga.config.retrace) { - switch (machine) { - case MCH_HERC: - return 0x81; - default: - return 9; - } - } - flip++; - if (flip>20) flip=0; - if (flip>10) return 1; - return 0; - /* - 0 Either Vertical or Horizontal Retrace active if set - 3 Vertical Retrace in progress if set - */ -} + Bit8u retval=0; + double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart; + vga.internal.attrindex=false; + vga.tandy.pcjr_flipflop=false; + + double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); + + switch (machine) { + case MCH_HERC: + // 3BAh (R): Status Register + // bit 0 Horizontal sync + // 3 Video signal + // 7 Vertical sync + if(timeInFrame >= vga.draw.delay.vrstart && + timeInFrame <= vga.draw.delay.vrend) + retval |= 0x80; + if(timeInLine >= vga.draw.delay.hrstart && + timeInLine <= vga.draw.delay.hrend) + retval |= 1; + retval |= 0x10; //Hercules ident + break; + default: + // 3DAh (R): Status Register + // bit 0 Horizontal or Vertical blanking + // 3 Vertical sync + + if(timeInFrame >= vga.draw.delay.vrstart && + timeInFrame <= vga.draw.delay.vrend) + retval |= 8; + if(timeInFrame >= vga.draw.delay.vblkstart && + timeInFrame <= vga.draw.delay.vblkend) + retval |= 1; + else if(timeInLine >= vga.draw.delay.hblkstart && + timeInLine <= vga.draw.delay.hblkend) + retval |= 1; + } + return retval; +} static void write_p3c2(Bitu port,Bitu val,Bitu iolen) { vga.misc_output=val; diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp index 8edb0ee4..a57765d4 100644 --- a/src/hardware/vga_other.cpp +++ b/src/hardware/vga_other.cpp @@ -16,13 +16,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_other.cpp,v 1.19 2007-01-08 19:45:40 qbix79 Exp $ */ +/* $Id: vga_other.cpp,v 1.20 2007-01-24 16:29:09 harekiet Exp $ */ #include #include #include "dosbox.h" #include "inout.h" #include "vga.h" +#include "mem.h" #include "render.h" #include "mapper.h" @@ -47,8 +48,8 @@ static void write_crtc_data_other(Bitu port,Bitu val,Bitu iolen) { case 0x02: //Horizontal sync position vga.other.hsyncp=val; break; - case 0x03: //Horizontal sync width - vga.other.hsyncw=val; + case 0x03: //Horizontal and vertical sync width + vga.other.syncw=val; break; case 0x04: //Vertical total if (vga.other.vtotal ^ val) VGA_StartResize(); @@ -70,10 +71,12 @@ static void write_crtc_data_other(Bitu port,Bitu val,Bitu iolen) { vga.other.max_scanline=val; break; case 0x0A: /* Cursor Start Register */ + vga.other.cursor_start = val & 0x3f; vga.draw.cursor.sline = val&0x1f; vga.draw.cursor.enabled = ((val & 0x60) != 0x20); break; case 0x0B: /* Cursor End Register */ + vga.other.cursor_end = val&0x1f; vga.draw.cursor.eline = val&0x1f; break; case 0x0C: /* Start Address High Register */ @@ -90,6 +93,12 @@ static void write_crtc_data_other(Bitu port,Bitu val,Bitu iolen) { vga.config.cursor_start&=0xff00; vga.config.cursor_start|=val; break; + case 0x10: /* Light Pen High */ + vga.other.lpen_high = val & 0x1f; //only 6 bits + break; + case 0x11: /* Light Pen Low */ + vga.other.lpen_low = val; + break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Write %X to illegal index %x",val,vga.other.index); } @@ -102,8 +111,8 @@ static Bitu read_crtc_data_other(Bitu port,Bitu iolen) { return vga.other.hdend; case 0x02: //Horizontal sync position return vga.other.hsyncp; - case 0x03: //Horizontal sync width - return vga.other.hsyncw; + case 0x03: //Horizontal and vertical sync width + return vga.other.syncw; case 0x04: //Vertical total return vga.other.vtotal; case 0x05: //Vertical display adjust @@ -114,6 +123,10 @@ static Bitu read_crtc_data_other(Bitu port,Bitu iolen) { return vga.other.vsyncp; case 0x09: //Max scanline return vga.other.max_scanline; + case 0x0A: /* Cursor Start Register */ + return vga.other.cursor_start; + case 0x0B: /* Cursor End Register */ + return vga.other.cursor_end; case 0x0C: /* Start Address High Register */ return vga.config.display_start >> 8; case 0x0D: /* Start Address Low Register */ @@ -122,10 +135,14 @@ static Bitu read_crtc_data_other(Bitu port,Bitu iolen) { return vga.config.cursor_start>>8; case 0x0F: /* Cursor Location Low Register */ return vga.config.cursor_start; + case 0x10: /* Light Pen High */ + return vga.other.lpen_high; + case 0x11: /* Light Pen Low */ + return vga.other.lpen_low; default: LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Read from illegal index %x",vga.other.index); } - return (Bitu)-1; + return ~0; } static double hue_offset = 0.0; @@ -241,25 +258,16 @@ static void write_color_select(Bit8u val) { } } -static void write_mode_control(Bit8u val) { - /* Check if someone changes the blinking/hi intensity bit */ - vga.tandy.mode_control=val; - VGA_SetBlinking((val & 0x20)); - if (val & 0x2) { - if (val & 0x10) { - } else VGA_SetMode(M_CGA4); - write_color_select(vga.tandy.color_select); //Setup the correct palette - } else { - VGA_SetMode(M_TEXT); - } -} - static void TANDY_FindMode(void) { if (vga.tandy.mode_control & 0x2) { - if (vga.tandy.gfx_control & 0x10) VGA_SetMode(M_TANDY16); - else if (vga.tandy.gfx_control & 0x08) VGA_SetMode(M_TANDY4); - else if (vga.tandy.mode_control & 0x10) VGA_SetMode(M_TANDY2); - else VGA_SetMode(M_TANDY4); + if (vga.tandy.gfx_control & 0x10) + VGA_SetMode(M_TANDY16); + else if (vga.tandy.gfx_control & 0x08) + VGA_SetMode(M_TANDY4); + else if (vga.tandy.mode_control & 0x10) + VGA_SetMode(M_TANDY2); + else + VGA_SetMode(M_TANDY4); write_color_select(vga.tandy.color_select); } else { VGA_SetMode(M_TANDY_TEXT); @@ -284,6 +292,21 @@ static void PCJr_FindMode(void) { } } +static void TandyCheckLineMask(void ) { + if ( vga.tandy.extended_ram & 1 ) { + vga.tandy.line_mask = 0; + } else if ( vga.tandy.mode_control & 0x2) { + vga.tandy.line_mask |= 1; + } + if ( vga.tandy.line_mask ) { + vga.tandy.line_shift = 13; + vga.tandy.addr_mask = (1 << 13) - 1; + } else { + vga.tandy.addr_mask = ~0; + vga.tandy.line_shift = 0; + } +} + static void write_tandy_reg(Bit8u val) { switch (vga.tandy.reg_index) { case 0x0: @@ -291,7 +314,10 @@ static void write_tandy_reg(Bit8u val) { vga.tandy.mode_control=val; VGA_SetBlinking(val & 0x20); PCJr_FindMode(); - } else LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); + } else { + LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); + } + break; case 0x2: /* Border color */ vga.tandy.border_color=val; break; @@ -300,6 +326,19 @@ static void write_tandy_reg(Bit8u val) { if (machine==MCH_TANDY) TANDY_FindMode(); else PCJr_FindMode(); break; + case 0x5: /* Extended ram page register */ + // Bit 0 enables extended ram + // Bit 7 Switches clock, 0 -> cga 28.6 , 1 -> mono 32.5 + vga.tandy.extended_ram = val; + //This is a bit of a hack to enable mapping video memory differently for highres mode + TandyCheckLineMask(); + VGA_SetupHandlers(); + break; + case 0x8: /* Monitor mode seletion */ + //Bit 1 select mode e, for 640x200x16, some double clocking thing? + //Bit 4 select 350 line mode for hercules emulation + LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to tandy monitor mode",val ); + break; /* palette colors */ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: @@ -340,6 +379,7 @@ static void write_tandy(Bitu port,Bitu val,Bitu iolen) { switch (port) { case 0x3d8: vga.tandy.mode_control=val; + TandyCheckLineMask(); VGA_SetBlinking(val & 0x20); TANDY_FindMode(); break; @@ -349,13 +389,20 @@ static void write_tandy(Bitu port,Bitu val,Bitu iolen) { case 0x3da: vga.tandy.reg_index=val; break; +// case 0x3db: //Clear lightpen latch + break; +// case 0x3dc: //Preset lightpen latch + break; +// case 0x3dd: //Extended ram page address register: + break; case 0x3de: write_tandy_reg(val); break; case 0x3df: - vga.tandy.is_32k_mode=(val & 0x80)==0x80; - vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7); - vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7); + vga.tandy.line_mask = val >> 6; + vga.tandy.draw_bank = val & 0x7; + vga.tandy.mem_bank = (val >> 3) & 0x7; + TandyCheckLineMask(); VGA_SetupHandlers(); break; } @@ -372,9 +419,12 @@ static void write_pcjr(Bitu port,Bitu val,Bitu iolen) { vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop; break; case 0x3df: - vga.tandy.is_32k_mode=(val & 0x80)==0x80; - vga.tandy.disp_bank=val & (vga.tandy.is_32k_mode ? 0x6 : 0x7); - vga.tandy.mem_bank=(val >> 3) & 0x7; + vga.tandy.line_mask = val >> 6; + vga.tandy.draw_bank = val & 0x7; + vga.tandy.mem_bank = (val >> 3) & 0x7; + vga.tandy.draw_base = &MemBase[vga.tandy.draw_bank * 16 * 1024]; + vga.tandy.mem_base = &MemBase[vga.tandy.mem_bank * 16 * 1024]; + TandyCheckLineMask(); VGA_SetupHandlers(); break; } @@ -383,7 +433,7 @@ static void write_pcjr(Bitu port,Bitu val,Bitu iolen) { static void write_hercules(Bitu port,Bitu val,Bitu iolen) { switch (port) { case 0x3b8: - if (vga.herc.enable_bits & 1) { + if (vga.herc.enable_bits & 1 ) { vga.herc.mode_control&=~0x2; vga.herc.mode_control|=(val&0x2); if (val & 0x2) { @@ -394,11 +444,14 @@ static void write_hercules(Bitu port,Bitu val,Bitu iolen) { } if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) { vga.herc.mode_control^=0x80; - VGA_SetupHandlers(); } + vga.tandy.draw_base = &vga.mem.linear[(vga.herc.mode_control & 0x80 ) ? 32*1024 : 0]; break; case 0x3bf: - vga.herc.enable_bits=val; + if ( vga.herc.enable_bits ^ val) { + vga.herc.enable_bits=val; + VGA_SetupHandlers(); + } break; } } @@ -411,6 +464,14 @@ static Bitu read_hercules(Bitu port,Bitu iolen) { void VGA_SetupOther(void) { Bitu i; + memset( &vga.tandy, 0, sizeof( vga.tandy )); + //Initialize values common for most machines, can be overwritten + vga.tandy.draw_base = vga.mem.linear; + vga.tandy.mem_base = vga.mem.linear; + vga.tandy.addr_mask = 8*1024 - 1; + vga.tandy.line_mask = 3; + vga.tandy.line_shift = 13; + if (machine==MCH_CGA || IS_TANDY_ARCH) { extern Bit8u int10_font_08[256 * 8]; for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8); @@ -434,7 +495,7 @@ void VGA_SetupOther(void) { IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); } if (machine==MCH_TANDY) { - vga.tandy.is_32k_mode=false; + write_tandy( 0x3df, 0x0, 0 ); IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3d9,write_tandy,IO_MB); IO_RegisterWriteHandler(0x3de,write_tandy,IO_MB); @@ -442,8 +503,8 @@ void VGA_SetupOther(void) { IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB); } if (machine==MCH_PCJR) { - vga.tandy.mem_bank=7;vga.tandy.disp_bank=7; - vga.tandy.is_32k_mode=false;vga.tandy.pcjr_flipflop=false; + //write_pcjr will setup base address + write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 ); IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 0b860dbf..3cab386e 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -195,6 +195,8 @@ static Bitu INT10_Handler(void) { } break; case 0x11: /* Character generator functions */ + if (machinemode]; @@ -400,6 +407,12 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { default: IO_WriteB(0x3de,0x0);break; } + //Clear extended mapping + IO_WriteB(0x3da,0x5); + IO_WriteB(0x3de,0x0); + //Clear monitor mode + IO_WriteB(0x3da,0x8); + IO_WriteB(0x3de,0x0); crtpage=(CurMode->mode>=0x9) ? 0xf6 : 0x3f; IO_WriteB(0x3df,crtpage); real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage); @@ -974,7 +987,6 @@ dac_text16: } IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing - IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2