1
0
Fork 0

Fixes to hercules emulation, better detection and bank switching

Fixes to tandy emulation, 640x200x16 mode and different sizes bank.
EGA/VGA memory changes detection for faster rendering added
Renderer does initial pass to check for needing to lock buffer


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2781
This commit is contained in:
Sjoerd van der Berg 2007-01-24 16:29:09 +00:00
parent 667c756775
commit 5660ee1856
16 changed files with 1132 additions and 565 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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 <sys/types.h>
#include <dirent.h>
@ -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<RENDER_SKIP_CACHE;i++)
total += render.frameskip.hadSkip[i];
LOG_MSG( "Skipped frame %d %d", PIC_Ticks, (total * 100) / RENDER_SKIP_CACHE );
#endif
}
render.frameskip.index = (render.frameskip.index + 1) & (RENDER_SKIP_CACHE - 1);
render.updating=false;
}
static Bitu MakeAspectTable(Bitu height,double scaley,Bitu miny) {
static Bitu MakeAspectTable(Bitu skip,Bitu height,double scaley,Bitu miny) {
Bitu i;
double lines=0;
Bitu linesadded=0;
for (Bitu i=0;i<height;i++) {
lines+=scaley;
if (lines>=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<skip;i++)
Scaler_Aspect[i] = 0;
height += skip;
for (i=skip;i<height;i++) {
lines += scaley;
if (lines >= 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;

View file

@ -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;
}

View file

@ -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); \

View file

@ -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)

View file

@ -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);

View file

@ -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,

View file

@ -64,7 +64,6 @@ void VGA_DetermineMode(void) {
VGA_SetMode(M_LIN4);
else
VGA_SetMode(M_EGA);
}
} else {
VGA_SetMode(M_TEXT);

View file

@ -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,

View file

@ -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<vga.draw.blocks;x++) {
Bitu val=vga.gfxmem_start[vidstart+line];
Bitu val = base[vidstart & vga.tandy.addr_mask];
vidstart++;
if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing
vidstart &= 0x1dfff;
*draw++=CGA_4_Table[val];
}
return TempLine;
}
static Bit8u * VGA_Draw_2BPPHiRes_Line(Bitu vidstart,Bitu panning,Bitu line) {
line*=8*1024;Bit32u * draw=(Bit32u *)TempLine;
static Bit8u * VGA_Draw_2BPPHiRes_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<vga.draw.blocks;x++) {
Bitu val1=vga.gfxmem_start[vidstart+line];
Bitu val2=vga.gfxmem_start[vidstart+1+line];
vidstart+=2;
if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing
vidstart &= 0x1dfff;
Bitu val1 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
Bitu val2 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
*draw++=CGA_4_HiRes_Table[(val1>>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<vga.draw.blocks;x++) {
if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing
vidstart &= 0x19fff;
Bitu val1=vga.gfxmem_start[vidstart+line];
vidstart++;
if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing
vidstart &= 0x19fff;
Bitu val2=vga.gfxmem_start[vidstart+line];
vidstart++;
Bitu val1 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
Bitu val2 = base[vidstart & vga.tandy.addr_mask];
++vidstart;
*draw++=(val1 & 0x0f) << 8 |
(val1 & 0xf0) >> 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<vga.draw.blocks;x++) {
if((vga.crtc.mode_control & 0x01) == 0) // CGA compatible addressing
vidstart &= 0x1dfff;
Bitu val=vga.gfxmem_start[vidstart+line];
vidstart++;
Bitu val = base[vidstart & vga.tandy.addr_mask];
++vidstart;
*draw++=(val & 0xf0) >> 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;cx<vga.draw.blocks;cx++) {
Bitu chr=vidmem[cx*2];
Bitu col=vidmem[cx*2+1];
@ -389,7 +386,7 @@ static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) {
if (line<vga.draw.cursor.sline) goto skip_cursor;
if (line>vga.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 (hbstart<hdispend) hdispend=hbstart;
if (vbstart<vdispend) vdispend=vbstart;
vrend = vga.crtc.vertical_retrace_end & 0xF;
vrend = ( vrend - vrstart)&0xF;
if ( !vrend)
vrend = vrstart + 0xf + 1;
else
vrend = vrstart + vrend;
vbstart = vga.crtc.start_vertical_blanking |
((vga.crtc.overflow & 0x08) << 5) |
((vga.crtc.maximum_scan_line & 0x20) << 4);
vbend = vga.crtc.end_vertical_blanking & 0x3f;
vbend = (vbend - vbstart) & 0x3f;
if ( !vbend)
vbend = vbstart + 0x3f + 1;
else
vbend = vbstart + vbend;
switch (svgaCard) {
case SVGA_S3Trio:
@ -608,13 +704,24 @@ void VGA_SetupDrawing(Bitu val) {
if (vga.s3.pll.cmd & 0x10) clock/=2;
vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0;
} 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<hdend) hdend=hbstart;
if (vbstart<vdend) vdend=vbstart;
Bitu width=hdend;
Bitu height=vdend;
bool doubleheight=false;
bool doublewidth=false;
VGA_FrameStart = NULL;
//Set the bpp
Bitu bpp;
switch (vga.mode) {
case M_LIN15:
bpp = 15;
break;
case M_LIN16:
bpp = 16;
break;
case M_LIN32:
bpp = 32;
break;
default:
bpp = 8;
break;
}
vga.draw.linear_base = vga.mem.linear;
vga.draw.linear_mask = VGA_MEMORY - 1;
switch (vga.mode) {
case M_VGA:
doublewidth=true;
width<<=2;
// Proper line handler is selected at the beginning of the frame
// VGA_DrawLine=VGA_Draw_VGAChained_Line;
VGA_FrameStart=VGA_StartFrame_VGA;
VGA_DrawLine = VGA_Draw_Linear_Line;
break;
case M_LIN8:
width<<=3;
if (vga.crtc.mode_control & 0x8) {
doublewidth = true;
width >>= 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 );
}
};

View file

@ -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 <class Size>
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 <class Size>
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<true>(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<true>(addr+0,(Bit8u)(val >> 0));
writeHandler<true>(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<true>(addr+0,(Bit8u)(val >> 0));
writeHandler<true>(addr+1,(Bit8u)(val >> 8));
writeHandler<true>(addr+2,(Bit8u)(val >> 16));
writeHandler<true>(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 <class Size>
static INLINE Bitu readHandler(PhysPt addr ) {
return hostRead<Size>( &vga.mem.linear[((addr&~3)<<2)+(addr&3)] );
}
template <class Size>
static INLINE void writeCache(PhysPt addr, Bitu val) {
hostWrite<Size>( &vga.mem.linear[VGA_CACHE_OFFSET+addr], val );
if (GCC_UNLIKELY(addr < 320)) {
// And replicate the first line
hostWrite<Size>( &vga.mem.linear[VGA_CACHE_OFFSET+addr+64*1024], val );
}
}
template <class Size>
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<Size>( &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<Bit8u>( addr );
}
Bitu readw(PhysPt addr ) {
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
return readHandler<Bit16u>( addr );
}
Bitu readd(PhysPt addr ) {
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
return readHandler<Bit32u>( addr );
}
bool readw_checked( PhysPt addr,Bitu *val ) {
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
if ( addr & 1) {
*val =
(readHandler<Bit8u>( addr+0 ) << 0 ) |
(readHandler<Bit8u>( addr+1 ) << 8 );
} else {
*val = readHandler<Bit16u>( addr );
}
return false;
}
bool readd_checked( PhysPt addr,Bitu *val ) {
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
if ( addr & 3) {
*val =
(readHandler<Bit8u>( addr+0 ) << 0 ) |
(readHandler<Bit8u>( addr+1 ) << 8 ) |
(readHandler<Bit8u>( addr+2 ) << 16 ) |
(readHandler<Bit8u>( addr+3 ) << 24 );
} else {
*val = readHandler<Bit32u>( addr );
}
return false;
}
void writeb(PhysPt addr, Bitu val ) {
addr = PAGING_GetPhysicalAddress(addr) & 0xffff;
MEM_CHANGED( addr );
writeHandler<Bit8u>( addr, val );
writeCache<Bit8u>( 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<Bit16u>( addr, val );
writeCache<Bit16u>( 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<Bit32u>( addr, val );
writeCache<Bit32u>( 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<Bit8u>( addr+0, val >> 0 );
writeHandler<Bit8u>( addr+1, val >> 8 );
writeCache<Bit16u>( addr, val );
} else {
MEM_CHANGED( addr );
writeHandler<Bit16u>( addr, val );
writeCache<Bit16u>( 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<Bit8u>( addr+0, val >> 0 );
writeHandler<Bit8u>( addr+1, val >> 8 );
writeHandler<Bit8u>( addr+2, val >> 16 );
writeHandler<Bit8u>( addr+3, val >> 24 );
writeCache<Bit32u>( addr, val );
} else {
MEM_CHANGED( addr );
writeHandler<Bit32u>( addr, val );
writeCache<Bit32u>( 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<Bit8u>( &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<Bit16u>( &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<Bit32u>( &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<Bit8u>( &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<Bit16u>( &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<Bit32u>( &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<false>(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<false>(addr+0,(Bit8u)(val >> 0));
writeHandler<false>(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<false>(addr+0,(Bit8u)(val >> 0));
writeHandler<false>(addr+1,(Bit8u)(val >> 8));
writeHandler<false>(addr+2,(Bit8u)(val >> 16));
writeHandler<false>(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<Bit8u>( &vga.mem.linear[addr] );
}
Bitu readw(PhysPt addr) {
addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr;
return *(Bit16u*)(&vga.mem.linear[addr]);
return hostRead<Bit16u>( &vga.mem.linear[addr] );
}
Bitu readd(PhysPt addr) {
addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr;
return *(Bit32u*)(&vga.mem.linear[addr]);
return hostRead<Bit32u>( &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<Bit8u>( &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<Bit16u>( &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<Bit32u>( &vga.mem.linear[addr], val );
MEM_CHANGED( addr );
}
bool writed_checked( PhysPt addr,Bitu val ) {
addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr;
hostWrite<Bit32u>( &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?
}
}

View file

@ -20,6 +20,7 @@
#include "inout.h"
#include "pic.h"
#include "vga.h"
#include <math.h>
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;

View file

@ -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 <string.h>
#include <math.h>
#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);

View file

@ -195,6 +195,8 @@ static Bitu INT10_Handler(void) {
}
break;
case 0x11: /* Character generator functions */
if (machine<MCH_VGA)
break;
switch (reg_al) {
/* Textmode calls */
case 0x00: /* Load user font */
@ -289,7 +291,8 @@ graphics_chars:
}
break;
case 0x12: /* alternate function select */
if (machine<MCH_VGA) break;
if (machine<MCH_VGA)
break;
switch (reg_bl) {
case 0x10: /* Get EGA Information */
reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4);

View file

@ -238,7 +238,7 @@ static void FinishSetMode(bool clearmem) {
case M_CGA2:
case M_TANDY16:
for (i=0;i<16*1024;i++) {
real_writew(0xb800,i*2,0x0000);
real_writew( 0xb800,i*2,0x0000);
}
break;
case M_TEXT:
@ -307,7 +307,12 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) {
}
break;
case MCH_HERC:
if (mode!=7) return false;
if (mode!=7) {
//Just the text memory, most games seem to use any random mode to clear the screen
for (i=0;i<16*1024;i++)
real_writew(0xb000,i*2,0x0120);
return false;
}
CurMode=&Hercules_Mode;
break;
}
@ -373,8 +378,10 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) {
case MCH_HERC:
IO_WriteB(0x3bf,0x3); //Enable changing all bits
IO_WriteB(0x3b8,0x8); //TEXT mode and non-blinking characters
IO_WriteB(0x3bf,0x0); //Disable changing all bits
VGA_DAC_CombineColor(1,0xf);
IO_WriteB(0x3bf,0x0);
VGA_DAC_CombineColor(0,0);
for ( i = 1; i < 15;i++)
VGA_DAC_CombineColor(i,0xf);
break;
case MCH_CGA:
mode_control=mode_control_list[CurMode->mode];
@ -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