1
0
Fork 0

New rendering changes

New mapper changes


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1817
This commit is contained in:
Sjoerd van der Berg 2004-06-10 07:18:53 +00:00
parent 7dcfa9c70a
commit 9213fd5bd6
11 changed files with 1858 additions and 651 deletions

View file

@ -19,22 +19,14 @@
#ifndef __RENDER_H
#define __RENDER_H
enum RENDER_Operation {
OP_None,
OP_Shot,
OP_Normal2x,
OP_AdvMame2x,
};
typedef void (* RENDER_Line_Handler)(const Bit8u * src);
typedef void (* RENDER_Line_Handler)(Bit8u * src);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,Bitu scalew,Bitu scaleh);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh);
bool RENDER_StartUpdate(void);
void RENDER_EndUpdate(void);
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
extern RENDER_Line_Handler RENDER_DrawLine;
extern Bit8u * RENDER_TempLine;
#endif

View file

@ -28,15 +28,32 @@ struct GFX_PalEntry {
Bit8u unused;
};
#define GFX_HASSCALING 0x0001
#define GFX_HASCONVERT 0x0002
#define CAN_8 0x0001
#define CAN_16 0x0002
#define CAN_32 0x0004
#define CAN_ALL (CAN_8|CAN_16|CAN_32)
#define LOVE_8 0x0010
#define LOVE_16 0x0020
#define LOVE_32 0x0040
#define NEED_RGB 0x0100
#define DONT_ASPECT 0x0200
#define HAVE_SCALING 0x1000
enum GFX_Modes {
GFX_8,GFX_15,GFX_16,GFX_32,GFX_NONE,
};
void GFX_Events(void);
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries);
Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags);
Bitu GFX_GetBestMode(Bitu flags);
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset);
GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack cb_reset);
void GFX_ResetScreen(void);
void GFX_Start(void);

View file

@ -1,7 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libgui.a
libgui_a_SOURCES = sdlmain.cpp \
render.cpp render_normal.h render_scale2x.h render_templates.h \
libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp \
render.cpp render_scalers.cpp render_scalers.h render_templates.h \
midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: render.cpp,v 1.26 2004-02-07 18:50:10 harekiet Exp $ */
/* $Id: render.cpp,v 1.27 2004-06-10 07:18:19 harekiet Exp $ */
#include <sys/types.h>
#include <dirent.h>
@ -27,12 +27,11 @@
#include "video.h"
#include "render.h"
#include "setup.h"
#include "keyboard.h"
#include "mapper.h"
#include "cross.h"
#include "support.h"
#define RENDER_MAXWIDTH 1280
#define RENDER_MAXHEIGHT 1024
#include "render_scalers.h"
struct PalData {
struct {
@ -43,51 +42,36 @@ struct PalData {
} rgb[256];
volatile Bitu first;
volatile Bitu last;
union {
Bit32u bpp32[256];
Bit16u bpp16[256];
Bit32u yuv[256];
} lookup;
};
static struct {
struct {
Bitu width;
Bitu height;
Bitu bpp;
Bitu scalew;
Bitu scaleh;
bool dblw,dblh;
double ratio;
} src;
struct {
Bitu width;
Bitu height;
Bitu pitch;
Bitu line;
Bitu bpp;
GFX_Modes mode;
RENDER_Operation type;
RENDER_Operation want_type;
RENDER_Line_Handler line_handler;
Bit8u * draw;
Bit8u * buffer;
Bit8u * pixels;
} op;
struct {
Bitu count;
Bitu max;
} frameskip;
PalData pal;
struct {
Bit8u hlines[RENDER_MAXHEIGHT];
} normal;
#if (C_SSHOT)
struct {
RENDER_Operation type;
Bitu bpp,width,height,line;
Bitu bpp,width,height,rowlen;
const char * dir;
Bit8u * buffer,* draw;
bool usesrc;
bool take,taking;
} shot;
#endif
bool active;
@ -95,27 +79,15 @@ static struct {
bool updating;
} render;
Bit8u render_line_cache[4][RENDER_MAXWIDTH*4]; //Bit32u pixels
RENDER_Line_Handler RENDER_DrawLine;
Bit8u * RENDER_TempLine;
/* Forward declerations */
static void RENDER_ResetPal(void);
/* Include the different rendering routines */
#include "render_templates.h"
#include "render_normal.h"
#include "render_scale2x.h"
#if (C_SSHOT)
#include <png.h>
static void RENDER_ShotDraw(Bit8u * src) {
if (render.shot.usesrc) {
memcpy(render.shot.draw,src,render.shot.line);
render.shot.draw+=render.shot.line;
} else render.op.line_handler(src);
static void RENDER_ShotDraw(const Bit8u * src) {
memcpy(render.shot.draw,src,render.shot.rowlen);
render.shot.draw+=render.shot.rowlen;
render.op.line_handler(src);
}
/* Take a screenshot of the data that should be rendered */
@ -153,7 +125,6 @@ static void TakeScreenShot(Bit8u * bitmap) {
LOG_MSG("Can't open file %s for snapshot",file_name);
return;
}
/* First try to alloacte the png structures */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL);
if (!png_ptr) return;
@ -192,7 +163,7 @@ static void TakeScreenShot(Bit8u * bitmap) {
/*Allocate an array of scanline pointers*/
row_pointers=(png_bytep*)malloc(render.shot.height*sizeof(png_bytep));
for (i=0;i<render.shot.height;i++) {
row_pointers[i]=(bitmap+i*render.shot.line);
row_pointers[i]=(bitmap+i*render.shot.rowlen);
}
/*tell the png library what to encode.*/
png_set_rows(png_ptr, info_ptr, row_pointers);
@ -212,8 +183,7 @@ static void TakeScreenShot(Bit8u * bitmap) {
}
static void EnableScreenShot(void) {
render.shot.type=render.op.type;
render.op.type=OP_Shot;
render.shot.take=true;
}
#endif
@ -222,25 +192,25 @@ static void EnableScreenShot(void) {
static void Check_Palette(void) {
if (render.pal.first>render.pal.last) return;
Bitu i;
switch (render.op.bpp) {
case 8:
switch (render.op.mode) {
case GFX_8:
GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]);
break;
case 16:
case GFX_15:
case GFX_16:
for (i=render.pal.first;i<=render.pal.last;i++) {
Bit8u r=render.pal.rgb[i].red;
Bit8u g=render.pal.rgb[i].green;
Bit8u b=render.pal.rgb[i].blue;
render.pal.lookup.bpp16[i]=GFX_GetRGB(r,g,b);
Scaler_PaletteLut.b16[i]=GFX_GetRGB(r,g,b);
}
break;
case 24:
case 32:
case GFX_32:
for (i=render.pal.first;i<=render.pal.last;i++) {
Bit8u r=render.pal.rgb[i].red;
Bit8u g=render.pal.rgb[i].green;
Bit8u b=render.pal.rgb[i].blue;
render.pal.lookup.bpp32[i]=GFX_GetRGB(r,g,b);
Scaler_PaletteLut.b32[i]=GFX_GetRGB(r,g,b);
}
break;
}
@ -262,7 +232,7 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) {
if (render.pal.last<entry) render.pal.last=entry;
}
static void RENDER_EmptyLineHandler(Bit8u * src) {
static void RENDER_EmptyLineHandler(const Bit8u * src) {
}
@ -274,43 +244,31 @@ bool RENDER_StartUpdate(void) {
}
render.frameskip.count=0;
if (render.src.bpp==8) Check_Palette();
render.op.line=0;
RENDER_TempLine=render_line_cache[0];
switch (render.op.type) {
case OP_None:
case OP_Normal2x:
case OP_AdvMame2x:
am2x.cmd_index=am2x.cmd_data;
if (!GFX_StartUpdate(render.op.pixels,render.op.pitch)) return false;
RENDER_DrawLine=render.op.line_handler;;
break;
Scaler_Line=0;
Scaler_Index=Scaler_Data;
if (!GFX_StartUpdate(Scaler_DstWrite,Scaler_DstPitch)) return false;
RENDER_DrawLine=render.op.line_handler;
#if (C_SSHOT)
case OP_Shot:
if (render.shot.buffer) free(render.shot.buffer);
if (render.shot.usesrc) {
render.shot.width=render.src.width;
render.shot.height=render.src.height;
render.shot.bpp=render.src.bpp;
} else {
render.shot.width=render.op.width;
render.shot.height=render.op.height;
render.shot.bpp=render.op.bpp;
if (render.shot.take) {
render.shot.take=false;
if (render.shot.buffer) {
free(render.shot.buffer);
}
render.shot.width=render.src.width;
render.shot.height=render.src.height;
render.shot.bpp=render.src.bpp;
switch (render.shot.bpp) {
case 8:render.shot.line=render.shot.width;break;
case 8:render.shot.rowlen=render.shot.width;break;
case 15:
case 16:render.shot.line=render.shot.width*2;break;
case 24:render.shot.line=render.shot.width*3;break;
case 32:render.shot.line=render.shot.width*4;break;
case 16:render.shot.rowlen=render.shot.width*2;break;
case 32:render.shot.rowlen=render.shot.width*4;break;
}
render.shot.buffer=(Bit8u*)malloc(render.shot.line*render.shot.height);
render.op.pixels=render.shot.buffer;
render.op.pitch=render.shot.line;
render.shot.buffer=(Bit8u*)malloc(render.shot.rowlen*render.shot.height);
render.shot.draw=render.shot.buffer;
RENDER_DrawLine=RENDER_ShotDraw;
break;
#endif
render.shot.taking=true;
}
#endif
render.updating=true;
return true;
}
@ -318,31 +276,40 @@ bool RENDER_StartUpdate(void) {
void RENDER_EndUpdate(void) {
if (!render.updating) return;
#if (C_SSHOT)
switch (render.op.type) {
case OP_None:
case OP_Normal2x:
case OP_AdvMame2x:
break;
case OP_Shot:
if (render.shot.taking) {
render.shot.taking=false;
TakeScreenShot(render.shot.buffer);
free(render.shot.buffer);
render.shot.buffer=0;
render.op.type=render.shot.type;
break;
}
#endif /* If Things are added to please check the define */
GFX_EndUpdate();
RENDER_DrawLine=RENDER_EmptyLineHandler;
render.updating=false;
render.updating=false;
}
static Bitu MakeAspectTable(Bitu height,double scaley,Bitu miny) {
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_Data[i]=templines-miny;
} else Scaler_Data[i]=0;
}
return linesadded;
}
void RENDER_ReInit(void) {
if (render.updating) RENDER_EndUpdate();
Bitu width=render.src.width;
Bitu height=render.src.height;
Bitu scalew=render.src.scalew;
Bitu scaleh=render.src.scaleh;
bool dblw=render.src.dblw;
bool dblh=render.src.dblh;
double gfx_scalew=1.0;
double gfx_scaleh=1.0;
@ -351,105 +318,59 @@ void RENDER_ReInit(void) {
else gfx_scalew*=(1/render.src.ratio);
Bitu gfx_flags;
Bitu bpp=GFX_GetBestMode(render.src.bpp,gfx_flags);
Bitu index;
switch (bpp) {
case 8: index=0;break;
case 16:index=1;break;
case 24:index=2;break;
case 32:index=3;break;
}
/* Initial scaler testing */
switch (render.op.want_type) {
case OP_Normal2x:
case OP_None:
ScalerBlock * block;
if (dblh && dblw) {
render.op.type=render.op.want_type;
normalop:
if (gfx_flags & GFX_HASSCALING) {
gfx_scalew*=scalew;
gfx_scaleh*=scaleh;
render.op.line_handler=Normal_8[index];
for (Bitu i=0;i<render.src.height;i++) {
render.normal.hlines[i]=0;
}
} else {
gfx_scaleh*=scaleh;
if (scalew==2) {
if (scaleh>1 && (render.op.type==OP_None)) {
render.op.line_handler=Normal_8[index];
scalew>>=1;gfx_scaleh/=2;
} else {
render.op.line_handler=Normal_2x_8[index];
}
} else render.op.line_handler=Normal_8[index];
width*=scalew;
double lines=0.0;
height=0;
for (Bitu i=0;i<render.src.height;i++) {
lines+=gfx_scaleh;
Bitu temp_lines=(Bitu)(lines);
lines-=temp_lines;
render.normal.hlines[i]=(temp_lines>0) ? temp_lines-1 : 0;
height+=temp_lines;
}
}
break;
case OP_AdvMame2x:
if (scalew!=2){
render.op.type=OP_Normal2x;
goto normalop;
}
if (gfx_flags & GFX_HASSCALING) {
height=scaleh*height;
} else {
height=(Bitu)(gfx_scaleh*scaleh*height);
}
width<<=1;
{
Bits i;
double src_add=(double)height/(double)render.src.height;
double src_index=0;
double src_lines=0;
Bitu src_done=0;
Bitu height=0;
am2x.cmd_index=am2x.cmd_data;
am2x.buf_pos=0;am2x.buf_used=0;
for (i=0;i<=(Bits)render.src.height;i++) {
src_lines+=src_add;
Bitu lines=(Bitu)src_lines;
src_lines-=lines;
switch (lines) {
case 0:
break;
case 1:
AdvMame2x_AddLine(i,i,i);
break;
case 2:
AdvMame2x_AddLine(i-1,i,i+1);
AdvMame2x_AddLine(i+1,i,i-1);
break;
default:
AdvMame2x_AddLine(i-1,i,i+1);
for (lines-=2;lines>0;lines--) AdvMame2x_AddLine(i,i,i);
AdvMame2x_AddLine(i+1,i,i-1);
break;
}
AdvMame2x_CheckLines(i);
}
render.op.line_handler=AdvMame2x_8_Table[index];
}
break;
} else if (dblw) {
render.op.type=OP_Normal2x;
} else if (dblh) {
render.op.type=OP_Normal;
gfx_scaleh*=2;
} else {
forcenormal:
render.op.type=OP_Normal;
}
render.op.bpp=bpp;
switch (render.op.type) {
case OP_Normal:block=&Normal_8;break;
case OP_Normal2x:block=(dblh) ? &Normal2x_8 : &NormalDbl_8;break;
case OP_AdvMame2x:block=&AdvMame2x_8;break;
case OP_AdvMame3x:block=&AdvMame3x_8;break;
case OP_Interp2x:block=&Interp2x_8;break;
case OP_AdvInterp2x:block=&AdvInterp2x_8;break;
case OP_TV2x:block=&TV2x_8;break;
}
gfx_flags=GFX_GetBestMode(block->flags);
if (!gfx_flags) {
if (render.op.type==OP_Normal) E_Exit("Failed to create a rendering output");
else goto forcenormal;
}
/* Special test for normal2x to switch to normal with hardware scaling */
if (gfx_flags & HAVE_SCALING && render.op.type==OP_Normal2x) {
if (dblw) gfx_scalew*=2;
if (dblh) gfx_scaleh*=2;
block=&Normal_8;
render.op.type=OP_Normal;
}
width*=block->xscale;
if (gfx_flags & HAVE_SCALING) {
height=MakeAspectTable(render.src.height,block->yscale,block->miny);
} else {
gfx_scaleh*=block->yscale;
height=MakeAspectTable(render.src.height,gfx_scaleh,block->miny);
}
/* Setup the scaler variables */
render.op.mode=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_ReInit);;
if (render.op.mode==GFX_NONE) E_Exit("Failed to create a rendering output");
render.op.line_handler=block->handlers[render.op.mode];
render.op.width=width;
render.op.height=height;
GFX_SetSize(width,height,bpp,gfx_scalew,gfx_scaleh,&RENDER_ReInit);
Scaler_SrcWidth=render.src.width;
Scaler_SrcHeight=render.src.height;
RENDER_ResetPal();
render.active=true;
}
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,Bitu scalew,Bitu scaleh) {
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh) {
if (!width || !height) {
render.active=false;
return;
@ -457,9 +378,9 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,Bitu scalew,Bit
render.src.width=width;
render.src.height=height;
render.src.bpp=bpp;
render.src.dblw=dblw;
render.src.dblh=dblh;
render.src.ratio=render.aspect ? ratio : 1.0;
render.src.scalew=scalew;
render.src.scaleh=scaleh;
RENDER_ReInit();
}
@ -487,8 +408,7 @@ void RENDER_Init(Section * sec) {
render.updating=true;
#if (C_SSHOT)
render.shot.dir=section->Get_string("snapdir");
render.shot.usesrc=true;
KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot);
MAPPER_AddHandler(EnableScreenShot,MK_f5,MMOD1,"scrshot","Screenshot");
#endif
const char * scaler;std::string cline;
if (control->cmdline->FindString("-scaler",cline,false)) {
@ -496,15 +416,19 @@ void RENDER_Init(Section * sec) {
} else {
scaler=section->Get_string("scaler");
}
if (!strcasecmp(scaler,"none")) render.op.want_type=OP_None;
if (!strcasecmp(scaler,"none")) render.op.want_type=OP_Normal;
else if (!strcasecmp(scaler,"normal2x")) render.op.want_type=OP_Normal2x;
else if (!strcasecmp(scaler,"advmame2x")) render.op.want_type=OP_AdvMame2x;
else if (!strcasecmp(scaler,"advmame3x")) render.op.want_type=OP_AdvMame3x;
else if (!strcasecmp(scaler,"advinterp2x")) render.op.want_type=OP_AdvInterp2x;
else if (!strcasecmp(scaler,"interp2x")) render.op.want_type=OP_Interp2x;
else if (!strcasecmp(scaler,"tv2x")) render.op.want_type=OP_TV2x;
else {
render.op.want_type=OP_None;
LOG_MSG("Illegal scaler type %s,falling back to none.",scaler);
render.op.want_type=OP_Normal;
LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler);
}
KEYBOARD_AddEvent(KBD_f7,KBD_MOD_CTRL,DecreaseFrameSkip);
KEYBOARD_AddEvent(KBD_f8,KBD_MOD_CTRL,IncreaseFrameSkip);
MAPPER_AddHandler(DecreaseFrameSkip,MK_f7,MMOD1,"decfskip","Dec Fskip");
MAPPER_AddHandler(IncreaseFrameSkip,MK_f8,MMOD1,"incfskip","Inc Fskip");
GFX_SetTitle(-1,render.frameskip.max);
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (C) 2002-2004 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
static Bit8u normal_cache[RENDER_MAXWIDTH*2*4];
template <Bitu sbpp,Bitu dbpp,bool xdouble>
static void Normal(Bit8u * src) {
Bitu line_size=LineSize<dbpp>(render.src.width) * (xdouble ? 2 : 1);
Bit8u * line;
if (sbpp == dbpp && !xdouble) {
line=src;
BituMove(render.op.pixels,line,line_size);
} else {
Bit8u * line_dst=&normal_cache[0];
Bit8u * real_dst=render.op.pixels;
line=line_dst;
Bit8u * temp_src=src;
for (Bitu tempx=render.src.width;tempx;tempx--) {
Bitu val=ConvBPP<sbpp,dbpp>(LoadSrc<sbpp>(temp_src));
AddDst<dbpp>(line_dst,val);
AddDst<dbpp>(real_dst,val);
if (xdouble) {
AddDst<dbpp>(line_dst,val);
AddDst<dbpp>(real_dst,val);
}
}
}
render.op.pixels+=render.op.pitch;
for (Bitu lines=render.normal.hlines[render.op.line++];lines;lines--) {
BituMove(render.op.pixels,line,line_size);
render.op.pixels+=render.op.pitch;
}
}
static RENDER_Line_Handler Normal_8[4]={
Normal<8,8 ,false>,Normal<8,16,false>,
Normal<8,24,false>,Normal<8,32,false>,
};
static RENDER_Line_Handler Normal_2x_8[4]={
Normal<8,8 ,true>,Normal<8,16,true>,
Normal<8,24,true>,Normal<8,32,true>,
};

View file

@ -1,118 +0,0 @@
/*
* This file is part of the Scale2x project.
*
* Copyright (C) 2001-2002 Andrea Mazzoleni
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Andrea Mazzoleni
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
/*
* This algorithm was based on the scale2x/advmame2x effect.
* http://scale2x.sourceforge.net/scale2x.html
*/
#ifndef __SCALE2X_H
#define __SCALE2X_H
#define AM2XBUF 16
static struct {
Bits buf[AM2XBUF][4];
Bitu buf_used;Bitu buf_pos;
Bit8u cmd_data[4096]; //1024 lines should be enough?
Bit8u * cmd_index;
Bit8u * cache[4];
Bitu cache_index;
} am2x;
static void AdvMame2x_AddLine(Bits s0,Bits s1,Bits s2) {
if (s0<0) s0=0;
if (s1<0) s1=0;
if (s2<0) s2=0;
if (s0>=(Bits)render.src.height) s0=render.src.height-1;
if (s1>=(Bits)render.src.height) s1=render.src.height-1;
if (s2>=(Bits)render.src.height) s2=render.src.height-1;
Bitu pos=(am2x.buf_used+am2x.buf_pos)&(AM2XBUF-1);
am2x.buf[pos][0]=s0;
am2x.buf[pos][1]=s1;
am2x.buf[pos][2]=s2;
s0=s0 > s1 ? s0 : s1;
s0=s0 > s2 ? s0 : s2;
am2x.buf[pos][3]=s0;
am2x.buf_used++;
}
static void AdvMame2x_CheckLines(Bits last) {
Bitu lines=0;Bit8u * line_count=am2x.cmd_index++;
while (am2x.buf_used) {
if (am2x.buf[am2x.buf_pos][3]>last) break;
*am2x.cmd_index++=am2x.buf[am2x.buf_pos][0]&3;
*am2x.cmd_index++=am2x.buf[am2x.buf_pos][1]&3;
*am2x.cmd_index++=am2x.buf[am2x.buf_pos][2]&3;
am2x.buf_used--;lines++;
am2x.buf_pos=(am2x.buf_pos+1)&(AM2XBUF-1);
}
*line_count=lines;
}
template <Bitu sbpp,Bitu dbpp>
static void AdvMame2x_line(Bit8u * dst, const Bit8u * src0, const Bit8u * src1, const Bit8u * src2, Bitu count) {
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>(src1[0]));
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>((src1[1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0]));
src0++;src1++;src2++;count-=2;
/* central pixels */
while (count) {
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>((src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) ? src0[0] : src1[0]));
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>((src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) ? src0[0] : src1[0]));
src0++;src1++;src2++;count--;
}
/* last pixel */
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>((src1[-1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0]));
AddDst<dbpp>(dst,ConvBPP<sbpp,dbpp>(src1[0]));
}
template <Bitu sbpp,Bitu dbpp>
static void AdvMame2x(Bit8u * src) {
RENDER_TempLine=render_line_cache[render.op.line&3];
am2x.cache[render.op.line&3]=src;
Bitu lines=*am2x.cmd_index++;
while (lines--) {
Bit8u * src0=am2x.cache[*am2x.cmd_index++];
Bit8u * src1=am2x.cache[*am2x.cmd_index++];
Bit8u * src2=am2x.cache[*am2x.cmd_index++];
AdvMame2x_line<sbpp,dbpp>(render.op.pixels,src0,src1,src2,render.src.width);
render.op.pixels+=render.op.pitch;
}
render.op.line++;
}
static RENDER_Line_Handler AdvMame2x_8_Table[4]={
AdvMame2x<8,8>,AdvMame2x<8,16>,AdvMame2x<8,24>,AdvMame2x<8,32>
};
#endif

121
src/gui/render_scalers.cpp Normal file
View file

@ -0,0 +1,121 @@
#include "dosbox.h"
#include "render_scalers.h"
Bitu Scaler_Line;
Bitu Scaler_SrcWidth;
Bitu Scaler_SrcHeight;
Bitu Scaler_DstPitch;
Bit8u * Scaler_DstWrite;
Bit8u * Scaler_Index;
Bit8u Scaler_Data[SCALER_MAXHEIGHT*5]; //5cmds/line
PaletteLut Scaler_PaletteLut;
static union {
Bit32u b32 [4][SCALER_MAXWIDTH];
Bit16u b16 [4][SCALER_MAXWIDTH];
Bit8u b8 [4][SCALER_MAXWIDTH];
} line_cache;
static union {
Bit32u b32 [4][SCALER_MAXWIDTH*3];
Bit16u b16 [4][SCALER_MAXWIDTH*3];
Bit8u b8 [4][SCALER_MAXWIDTH*3];
} write_cache;
static Bit8u * ln[3];
#define _conc2(A,B) A ## B
#define _conc3(A,B,C) A ## B ## C
#define _conc4(A,B,C,D) A ## B ## C ## D
#define _conc5(A,B,C,D,E) A ## B ## C ## D ## E
#define conc2(A,B) _conc2(A,B)
#define conc3(A,B,C) _conc3(A,B,C)
#define conc4(A,B,C,D) _conc4(A,B,C,D)
#define conc2d(A,B) _conc3(A,_,B)
#define conc3d(A,B,C) _conc5(A,_,B,_,C)
#define BituMove(_DST,_SRC,_SIZE) \
{ \
Bitu bsize=(_SIZE)/sizeof(Bitu); \
Bitu * bdst=(Bitu *)(_DST); \
Bitu * bsrc=(Bitu *)(_SRC); \
while (bsize--) *bdst++=*bsrc++; \
}
#define interp_w2(P0,P1,W0,W1) \
((((P0&redblueMask)*W0+(P1&redblueMask)*W1)/(W0+W1)) & redblueMask) | \
((((P0& greenMask)*W0+(P1& greenMask)*W1)/(W0+W1)) & greenMask)
#define interp_w3(P0,P1,P2,W0,W1,W2) \
((((P0&redblueMask)*W0+(P1&redblueMask)*W1+(P2&redblueMask)*W2)/(W0+W1+W2)) & redblueMask) | \
((((P0& greenMask)*W0+(P1& greenMask)*W1+(P2& greenMask)*W2)/(W0+W1+W2)) & greenMask)
#define interp_w4(P0,P1,P2,P3,W0,W1,W2,W3) \
((((P0&redblueMask)*W0+(P1&redblueMask)*W1+(P2&redblueMask)*W2+(P3&redblueMask)*W3)/(W0+W1+W2+W3)) & redblueMask) | \
((((P0& greenMask)*W0+(P1& greenMask)*W1+(P2& greenMask)*W2+(P3& greenMask)*W3)/(W0+W1+W2+W3)) & greenMask)
/* Include the different rendering routines */
#define SBPP 8
#define DBPP 8
#include "render_templates.h"
#undef DBPP
#define DBPP 15
#include "render_templates.h"
#undef DBPP
#define DBPP 16
#include "render_templates.h"
#undef DBPP
#define DBPP 32
#include "render_templates.h"
#undef SBPP
#undef DBPP
ScalerBlock Normal_8={
CAN_8|CAN_16|CAN_32|LOVE_8,
1,1,1,
Normal_8_8,Normal_8_16,Normal_8_16,Normal_8_32
};
ScalerBlock NormalDbl_8= {
CAN_8|CAN_16|CAN_32|LOVE_8,
2,1,1,
Normal2x_8_8,Normal2x_8_16,Normal2x_8_16,Normal2x_8_32
};
ScalerBlock Normal2x_8={
CAN_8|CAN_16|CAN_32|LOVE_8,
2,2,1,
Normal2x_8_8,Normal2x_8_16,Normal2x_8_16,Normal2x_8_32
};
ScalerBlock AdvMame2x_8={
CAN_8|CAN_16|CAN_32|LOVE_8,
2,2,1,
AdvMame2x_8_8,AdvMame2x_8_16,AdvMame2x_8_16,AdvMame2x_8_32
};
ScalerBlock AdvMame3x_8={
CAN_8|CAN_16|CAN_32|LOVE_8,
3,3,2,
AdvMame3x_8_8,AdvMame3x_8_16,AdvMame3x_8_16,AdvMame3x_8_32
};
ScalerBlock Interp2x_8={
CAN_16|CAN_32|LOVE_32|NEED_RGB,
2,2,1,
0,Interp2x_8_16,Interp2x_8_16,Interp2x_8_32
};
ScalerBlock AdvInterp2x_8={
CAN_16|CAN_32|LOVE_32|NEED_RGB,
2,2,1,
0,AdvInterp2x_8_16,AdvInterp2x_8_16,AdvInterp2x_8_32
};
ScalerBlock TV2x_8={
CAN_16|CAN_32|LOVE_32|NEED_RGB,
2,2,1,
0,TV2x_8_16,TV2x_8_16,TV2x_8_32
};

51
src/gui/render_scalers.h Normal file
View file

@ -0,0 +1,51 @@
#ifndef _RENDER_SCALERS_H
#define _RENDER_SCALERS_H
#include "render.h"
#include "video.h"
#define SCALER_MAXWIDTH 1280
#define SCALER_MAXHEIGHT 1024
extern Bitu Scaler_Line;
extern Bitu Scaler_SrcWidth;
extern Bitu Scaler_SrcHeight;
extern Bitu Scaler_DstPitch;
extern Bit8u * Scaler_DstWrite;
extern Bit8u Scaler_Data[];
extern Bit8u * Scaler_Index;
union PaletteLut {
Bit16u b16[256];
Bit32u b32[256];
};
extern PaletteLut Scaler_PaletteLut;
enum RENDER_Operation {
OP_Normal,
OP_Normal2x,
OP_AdvMame2x,
OP_AdvMame3x,
OP_AdvInterp2x,
OP_Interp2x,
OP_TV2x,
};
struct ScalerBlock {
Bitu flags;
Bitu xscale,yscale,miny;
RENDER_Line_Handler handlers[4];
};
extern ScalerBlock Normal_8;
extern ScalerBlock NormalDbl_8;
extern ScalerBlock Normal2x_8;
extern ScalerBlock AdvMame2x_8;
extern ScalerBlock AdvMame3x_8;
extern ScalerBlock AdvInterp2x_8;
extern ScalerBlock Interp2x_8;
extern ScalerBlock TV2x_8;
#endif

View file

@ -1,59 +1,294 @@
#ifdef __GNUC__
template <Bitu dbpp> static INLINE void AddDst(Bit8u * & dst,Bitu val) __attribute__ ((always_inline));
template <Bitu bpp> static INLINE Bitu LineSize(Bitu pixels) __attribute__ ((always_inline));
template <Bitu sbpp> static INLINE Bitu LoadSrc(Bit8u * & src) __attribute__ ((always_inline));
template <Bitu sbpp,Bitu dbpp> static INLINE Bitu ConvBPP(Bitu val) __attribute__ ((always_inline));
#if DBPP == 8
#define PSIZE 1
#define PTYPE Bit8u
#define WC write_cache.b8
#define LC line_cache.b8
#define redblueMask 0
#define greenMask 0
#elif DBPP == 15 || DBPP == 16
#define PSIZE 2
#define PTYPE Bit16u
#define WC write_cache.b16
#define LC line_cache.b16
#if DBPP == 15
#define redblueMask 0x7C1F
#define greenMask 0x03E0
#elif DBPP == 16
#define redblueMask 0xF81F
#define greenMask 0x07E0
#endif
#elif DBPP == 32
#define PSIZE 4
#define PTYPE Bit32u
#define WC write_cache.b32
#define LC line_cache.b32
#define redblueMask 0xff00ff
#define greenMask 0xff00
#endif
template <Bitu dbpp> static INLINE void AddDst(Bit8u * & dst,Bitu val) {
switch (dbpp) {
case 8: *(Bit8u*)dst=val;dst+=1;break;
case 16:*(Bit16u*)dst=val;dst+=2;break;
case 24:*(Bit32u*)dst=val;dst+=3;break;
case 32:*(Bit32u*)dst=val;dst+=4;break;
#if SBPP == 8
#if DBPP == 8
#define PMAKE(_VAL) _VAL
#elif DBPP == 15
#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL]
#elif DBPP == 16
#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL]
#elif DBPP == 32
#define PMAKE(_VAL) Scaler_PaletteLut.b32[_VAL]
#endif
#endif
#define C0 LC[0][x-1]
#define C1 LC[0][x+0]
#define C2 LC[0][x+1]
#define C3 LC[1][x-1]
#define C4 LC[1][x+0]
#define C5 LC[1][x+1]
#define C6 LC[2][x-1]
#define C7 LC[2][x+0]
#define C8 LC[2][x+1]
static void conc3d(Normal,SBPP,DBPP) (const Bit8u * src) {
const Bit8u * line;
#if SBPP == DBPP
line=src;
BituMove(Scaler_DstWrite,line,Scaler_SrcWidth*PSIZE);
#else
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
line=line_cache.b8[0];
for (Bitu x=0;x<Scaler_SrcWidth;x++) {
PTYPE pixel=PMAKE(src[x]);
dst[x]=pixel;LC[0][x]=pixel;
}
#endif
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines;lines--) {
BituMove(Scaler_DstWrite,line,Scaler_SrcWidth*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
}
template <Bitu bpp>
static INLINE Bitu LineSize(Bitu pixels) {
switch (bpp) {
case 8:return pixels;
case 16:return pixels*2;
case 24:return pixels*3;
case 32:return pixels*4;
static void conc3d(Normal2x,SBPP,DBPP) (const Bit8u * src) {
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
for (Bitu x=0;x<Scaler_SrcWidth;x++) {
Bitu pixel=PMAKE(src[x]);
dst[x*2+0]=dst[x*2+1]=pixel;
LC[0][x*2+0]=LC[0][x*2+1]=pixel;
}
return 0;
}
static INLINE void BituMove(Bit8u * dst,Bit8u * src,Bitu pixels) {
pixels/=sizeof(Bitu);
while (pixels--) {
*(Bitu*)dst=*(Bitu*)src;
src+=sizeof(Bitu);
dst+=sizeof(Bitu);
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines;lines--) {
BituMove(Scaler_DstWrite,LC[0],Scaler_SrcWidth*2*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
}
template <Bitu sbpp>
static INLINE Bitu LoadSrc(Bit8u * & src) {
Bitu val;
switch (sbpp) {
case 8:val=*(Bit8u *) src;src+=1;break;
case 16:val=*(Bit16u *) src;src+=2;break;
case 24:val=(*(Bit32u *)src)&0xffffff;src+=3;break;
case 32:val=*(Bit32u *)src;src+=4;break;
#if (DBPP > 8)
static void conc3d(TV2x,SBPP,DBPP) (const Bit8u * src) {
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
for (Bitu x=0;x<Scaler_SrcWidth;x++) {
Bitu pixel=PMAKE(src[x]);
Bitu halfpixel=(((pixel & redblueMask) * 7) >> 3) & redblueMask;
halfpixel|=(((pixel & greenMask) * 7) >> 3) & greenMask;
dst[x*2+0]=dst[x*2+1]=halfpixel;
LC[0][x*2+0]=LC[0][x*2+1]=pixel;
}
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines;lines--) {
BituMove(Scaler_DstWrite,LC[0],Scaler_SrcWidth*2*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
return val;
}
template <Bitu sbpp,Bitu dbpp>
static INLINE Bitu ConvBPP(Bitu val) {
if (sbpp==8) switch (dbpp) {
case 8:return val;
case 16:return render.pal.lookup.bpp16[val];
case 24:return render.pal.lookup.bpp32[val];
case 32:return render.pal.lookup.bpp32[val];
static void conc3d(Interp2x,SBPP,DBPP) (const Bit8u * src) {
if (!Scaler_Line) {
Scaler_Line++;
for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) {
LC[1][tempx] = LC[2][tempx] = PMAKE(src[tempx]);
}
return;
}
return 0;
lastagain:
Bitu x=0;
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
C1=C4;C4=C7;C7=PMAKE(src[x]);
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
dst[0] = interp_w2(C4,C1,3,1);
dst[1] = interp_w4(C4,C1,C2,C5,5,1,1,1);
WC[1][0] = interp_w2(C4,C7,3,1);
WC[1][1] = interp_w4(C4,C5,C8,C7,5,1,1,1);
for (x=1;x<Scaler_SrcWidth-1;x++) {
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
dst[x*2+0] = interp_w4(C4,C3,C0,C1,5,1,1,1);
dst[x*2+1] = interp_w4(C4,C1,C2,C5,5,1,1,1);
WC[1][x*2+0] = interp_w4(C4,C7,C6,C3,5,1,1,1);
WC[1][x*2+1] = interp_w4(C4,C5,C8,C7,5,1,1,1);
}
dst[x*2] = interp_w4(C4,C3,C0,C1,5,1,1,1);
dst[x*2+1] = interp_w2(C4,C1,3,1);
WC[1][x*2+0] = interp_w4(C4,C7,C6,C3,5,1,1,1);
WC[1][x*2+1] = interp_w2(C4,C7,3,1);
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines;lines--) {
BituMove(Scaler_DstWrite,&WC[1],Scaler_SrcWidth*2*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
if (++Scaler_Line==Scaler_SrcHeight) goto lastagain;
}
static void conc3d(AdvInterp2x,SBPP,DBPP) (const Bit8u * src) {
if (!Scaler_Line) {
Scaler_Line++;
for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) {
LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]);
}
return;
}
lastagain:
Bitu x=0;
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
C1=C4;C4=C7;C7=PMAKE(src[x]);
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
dst[0]=C4;
WC[1][0]=C4;
dst[1] = C5 == C1 && C7 != C1 ? C2 : C4;
WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4;
for (x=1;x<Scaler_SrcWidth-1;x++) {
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
if (C1 != C7 && C3 != C5) {
dst[x*2+0] = C3 == C1 ? interp_w2(C3,C4,5,3) : C4;
dst[x*2+1] = C1 == C5 ? interp_w2(C5,C4,5,3) : C4;
WC[1][x*2+0] = C3 == C7 ? interp_w2(C3,C4,5,3) : C4;
WC[1][x*2+1] = C7 == C5 ? interp_w2(C5,C4,5,3) : C4;
} else {
dst[x*2+0] = dst[x*2+1] =
WC[1][x*2+0] = WC[1][x*2+1]= C4;
}
}
x=Scaler_SrcWidth-1;
dst[x*2] = (C3 == C1 && C7 != C1) ? C1 : C4;
WC[1][x*2+0] = (C3 == C7 && C1 != C7) ? C7 : C4;
dst[x*2+1] = C4;
WC[1][x*2+1] = C4;
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines>0;lines--) {
BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
if (++Scaler_Line==Scaler_SrcHeight) goto lastagain;
}
#endif //DBPP > 8
static void conc3d(AdvMame2x,SBPP,DBPP) (const Bit8u * src) {
if (!Scaler_Line) {
Scaler_Line++;
for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) {
LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]);
}
return;
}
lastagain:
Bitu x=0;
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
C1=C4;C4=C7;C7=PMAKE(src[x]);
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
dst[0]=C4;
WC[1][0]=C4;
dst[1] = C5 == C1 && C7 != C1 ? C2 : C4;
WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4;
for (x=1;x<Scaler_SrcWidth-1;x++) {
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
if (C1 != C7 && C3 != C5) {
dst[x*2+0] = C3 == C1 ? C3 : C4;
dst[x*2+1] = C1 == C5 ? C5 : C4;
WC[1][x*2+0] = C3 == C7 ? C3 : C4;
WC[1][x*2+1] = C7 == C5 ? C5 : C4;
} else {
dst[x*2+0] = dst[x*2+1] =
WC[1][x*2+0] = WC[1][x*2+1]= C4;
}
}
x=Scaler_SrcWidth-1;
dst[x*2] = (C3 == C1 && C7 != C1) ? C1 : C4;
WC[1][x*2+0] = (C3 == C7 && C1 != C7) ? C7 : C4;
dst[x*2+1] = C4;
WC[1][x*2+1] = C4;
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines>0;lines--) {
BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
if (++Scaler_Line==Scaler_SrcHeight) goto lastagain;
}
static void conc3d(AdvMame3x,SBPP,DBPP) (const Bit8u * src) {
if (!Scaler_Line) {
Scaler_Line++;
for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) {
LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]);
}
return;
}
lastagain:
PTYPE * dst=(PTYPE *)Scaler_DstWrite;
LC[0][0]=LC[1][0];LC[1][0]=LC[2][0];LC[2][0]=PMAKE(src[0]);
LC[0][1]=LC[1][1];LC[1][1]=LC[2][1];LC[2][1]=PMAKE(src[1]);
/* first pixel */
dst[0] = LC[1][0];
dst[1] = LC[1][0];
dst[2] = (LC[1][1] == LC[0][0] && LC[2][0] != LC[0][0]) ? LC[0][0] : LC[1][0];
WC[1][0] = LC[1][0];
WC[1][1] = LC[1][0];
WC[1][2] = (LC[0][0] != LC[2][0]) ? (((LC[1][1] == LC[0][0] && LC[1][0] != LC[2][1]) || (LC[1][1] == LC[2][0] && LC[1][0] != LC[0][1])) ? LC[1][1] : LC[1][0]) : LC[1][0];
WC[2][0] = LC[1][0];
WC[2][1] = LC[1][0];
WC[2][2] = (LC[1][1] == LC[2][0] && LC[0][0] != LC[2][0]) ? LC[2][0] : LC[1][0];
Bitu x;
for (x=1;x<Scaler_SrcWidth-1;x++) {
C2=C5;C5=C8;C8=PMAKE(src[x+1]);
if ((C1 != C7) && (C3 != C5)) {
dst[x*3+0] = C3 == C1 ? C3 : C4;
dst[x*3+1] = (C3 == C1 && C4 != C2) || (C5 == C1 && C4 != C0) ? C1 : C4;
dst[x*3+2] = C5 == C1 ? C5 : C4;
WC[1][x*3+0] = (C3 == C1 && C4 != C6) || (C3 == C7 && C4 != C0) ? C3 : C4;
WC[1][x*3+1] = C4;
WC[1][x*3+2] = (C5 == C1 && C4 != C8) || (C5 == C7 && C4 != C2) ? C5 : C4;
WC[2][x*3+0] = C3 == C7 ? C3 : C4;
WC[2][x*3+1] = (C3 == C7 && C4 != C8) || (C5 == C7 && C4 != C6) ? C7 : C4;
WC[2][x*3+2] = C5 == C7 ? C5 : C4;
} else {
dst[x*3+0] = dst[x*3+1] = dst[x*3+2] =
WC[1][x*3+0] = WC[1][x*3+1] = WC[1][x*3+2] =
WC[2][x*3+0] = WC[2][x*3+1] = WC[2][x*3+2] = LC[1][x];
}
}
x=Scaler_SrcWidth-1;
/* last pixel */
dst[x*3+0] = (C3 == C1 && C7 != C1) ? C1 : C4;
dst[x*3+1] = C4;
dst[x*3+2] = C4;
WC[1][x*3+0] = (C1 != C7) ? ((C3 == C1 && C4 != C6) || (C3 == C7 && C4 != C0) ? C3 : C4) : C4;
WC[1][x*3+1] = C4;
WC[1][x*3+2] = C4;
WC[2][x*3+0] = (C3 == C7 && C1 != C7) ? C7 : C4;
WC[2][x*3+1] = C4;
WC[2][x*3+2] = C4;
Scaler_DstWrite+=Scaler_DstPitch;
BituMove(Scaler_DstWrite,&WC[1],3*Scaler_SrcWidth*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
for (Bitu lines=*Scaler_Index++;lines>0;lines--) {
BituMove(Scaler_DstWrite,&WC[2],3*Scaler_SrcWidth*PSIZE);
Scaler_DstWrite+=Scaler_DstPitch;
}
if (++Scaler_Line==Scaler_SrcHeight) goto lastagain;
}
#undef PSIZE
#undef PTYPE
#undef PMAKE
#undef WC
#undef LC
#undef greenMask
#undef redblueMask

1187
src/gui/sdl_mapper.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: sdlmain.cpp,v 1.65 2004-06-05 11:17:23 qbix79 Exp $ */
/* $Id: sdlmain.cpp,v 1.66 2004-06-10 07:18:19 harekiet Exp $ */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@ -32,14 +32,13 @@
#include "dosbox.h"
#include "video.h"
#include "keyboard.h"
#include "mouse.h"
#include "joystick.h"
#include "pic.h"
#include "timer.h"
#include "setup.h"
#include "support.h"
#include "debug.h"
#include "mapper.h"
//#define DISABLE_JOYSTICK
@ -104,6 +103,9 @@ extern char** environ;
#define DEFAULT_CONFIG_FILE "/.dosboxrc"
#endif
void MAPPER_Init(void);
void MAPPER_StartUp(Section * sec);
enum SCREEN_TYPES {
SCREEN_SURFACE,
SCREEN_OVERLAY,
@ -117,7 +119,8 @@ struct SDL_Block {
struct {
Bit32u width;
Bit32u height;
Bitu bpp;
Bitu flags;
GFX_Modes mode;
double scalex,scaley;
GFX_ResetCallBack reset;
} draw;
@ -149,7 +152,6 @@ struct SDL_Block {
SDL_Rect clip;
SDL_Surface * surface;
SDL_Overlay * overlay;
SDL_Joystick * joy;
SDL_cond *cond;
struct {
bool autolock;
@ -163,45 +165,63 @@ struct SDL_Block {
static SDL_Block sdl;
static void CaptureMouse(void);
extern const char * RunningProgram;
void GFX_SetTitle(Bits cycles,Bits frameskip){
char title[200]={0};
static Bits internal_cycles=0;
static Bits internal_frameskip=0;
if(cycles != -1) internal_cycles = cycles;
if(frameskip != -1) internal_frameskip = frameskip;
sprintf(title,"DOSBox %s, Cpu Cycles: %8d, Frameskip %2d",VERSION,internal_cycles,internal_frameskip);
sprintf(title,"DOSBox %s,Cpu Cycles: %8d, Frameskip %2d, Program: %s",VERSION,internal_cycles,internal_frameskip,RunningProgram);
SDL_WM_SetCaption(title,VERSION);
}
/* Reset the screen with current values in the sdl structure */
Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags) {
gfx_flags=0;
Bitu GFX_GetBestMode(Bitu flags) {
Bitu testbpp,gotbpp,setflags;
switch (sdl.desktop.want_type) {
case SCREEN_SURFACE:
if (sdl.desktop.fullscreen) {
bpp=SDL_VideoModeOK(640,480,bpp,SDL_FULLSCREEN|SDL_HWSURFACE |
(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0) | ((bpp==8) ? SDL_HWPALETTE : 0) );
} else {
bpp=sdl.desktop.bpp;
check_surface:
/* Check if we can satisfy the depth it loves */
if (flags & LOVE_8) testbpp=8;
else if (flags & LOVE_16) testbpp=16;
else if (flags & LOVE_32) testbpp=32;
if (sdl.desktop.fullscreen) gotbpp=SDL_VideoModeOK(640,480,testbpp,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_HWPALETTE);
else gotbpp=sdl.desktop.bpp;
/* If we can't get our favorite mode check for another working one */
switch (gotbpp) {
case 8:
if (flags & CAN_8) flags&=~(CAN_16|CAN_32);
break;
case 15:
case 16:
if (flags & CAN_16) flags&=~(CAN_8|CAN_32);
break;
case 24:
case 32:
if (flags & CAN_32) flags&=~(CAN_8|CAN_16);
break;
}
gfx_flags|=GFX_HASCONVERT;
/* Not a valid display depth found? Let's just hope sdl provides conversions */
break;
case SCREEN_OVERLAY:
bpp=32;
gfx_flags|=GFX_HASSCALING;
if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface;
flags|=HAVE_SCALING;
flags&=~(CAN_8,CAN_16);
break;
#if C_OPENGL
case SCREEN_OPENGL:
bpp=32;
gfx_flags|=GFX_HASSCALING;
if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface;
flags|=HAVE_SCALING;
flags&=~(CAN_8,CAN_16);
break;
#endif
}
return bpp;
return flags;
}
static void ResetScreen(void) {
void GFX_ResetScreen(void) {
GFX_Stop();
if (sdl.draw.reset) (sdl.draw.reset)();
GFX_Start();
@ -214,18 +234,23 @@ static int int_log2 (int val) {
return log;
}
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack reset) {
GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack reset) {
if (sdl.updating) GFX_EndUpdate();
sdl.draw.width=width;
sdl.draw.height=height;
sdl.draw.bpp=bpp;
sdl.draw.flags=flags;
sdl.draw.mode=GFX_NONE;
sdl.draw.reset=reset;
sdl.draw.scalex=scalex;
sdl.draw.scaley=scaley;
Bitu bpp;
switch (sdl.desktop.want_type) {
case SCREEN_SURFACE:
dosurface:
if (flags & CAN_8) bpp=8;
if (flags & CAN_16) bpp=16;
if (flags & CAN_32) bpp=32;
sdl.desktop.type=SCREEN_SURFACE;
sdl.clip.w=width;
sdl.clip.h=height;
@ -234,21 +259,29 @@ dosurface:
sdl.clip.x=(Sint16)((sdl.desktop.width-width)/2);
sdl.clip.y=(Sint16)((sdl.desktop.height-height)/2);
sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp,
SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE);
SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE);
} else {
sdl.clip.x=0;sdl.clip.y=0;
sdl.surface=SDL_SetVideoMode(width,height,bpp,
SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE);
SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE);
}
} else {
sdl.clip.x=0;sdl.clip.y=0;
sdl.surface=SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE);
}
if (sdl.surface) switch (sdl.surface->format->BitsPerPixel) {
case 8:sdl.draw.mode=GFX_8;break;
case 15:sdl.draw.mode=GFX_15;break;
case 16:sdl.draw.mode=GFX_16;break;
case 32:sdl.draw.mode=GFX_32;break;
default:
break;
}
break;
case SCREEN_OVERLAY:
if (sdl.overlay) SDL_FreeYUVOverlay(sdl.overlay);
sdl.overlay=0;
if (bpp!=32) goto dosurface;
if (!(flags&CAN_32) || (flags & NEED_RGB)) goto dosurface;
if (sdl.desktop.fullscreen) {
if (sdl.desktop.fixed) {
double ratio_w=(double)sdl.desktop.width/(width*scalex);
@ -283,6 +316,7 @@ dosurface:
goto dosurface;
}
sdl.desktop.type=SCREEN_OVERLAY;
sdl.draw.mode=GFX_32;
break;
#if C_OPENGL
case SCREEN_OPENGL:
@ -295,7 +329,7 @@ dosurface:
free(sdl.opengl.framebuf);
}
sdl.opengl.framebuf=0;
if (bpp!=32) goto dosurface;
if (!(flags&CAN_32) || (flags & NEED_RGB)) goto dosurface;
int texsize=2 << int_log2(width > height ? width : height);
if (texsize>sdl.opengl.max_texsize) {
LOG_MSG("SDL:OPENGL:No support for texturesize of %d, falling back to surface",texsize);
@ -368,6 +402,8 @@ dosurface:
glClearColor (0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
glClear(GL_COLOR_BUFFER_BIT);
glShadeModel (GL_FLAT);
glDisable (GL_DEPTH_TEST);
glDisable (GL_LIGHTING);
@ -395,11 +431,13 @@ dosurface:
glEnd();
glEndList();
sdl.desktop.type=SCREEN_OPENGL;
sdl.draw.mode=GFX_32;
break;
}//OPENGL
#endif //C_OPENGL
}//CASE
GFX_Start();
if (sdl.draw.mode!=GFX_NONE) GFX_Start();
return sdl.draw.mode;
}
@ -421,7 +459,7 @@ static void SwitchFullScreen(void) {
} else {
if (sdl.mouse.locked) CaptureMouse();
}
ResetScreen();
GFX_ResetScreen();
}
void GFX_SwitchFullScreen(void) {
@ -630,14 +668,11 @@ static void GUI_StartUp(Section * sec) {
if (sdl.desktop.bpp==24) {
LOG_MSG("SDL:You are running in 24 bpp mode, this will slow down things!");
}
GFX_SetSize(640,400,8,1.0,1.0,0);
SDL_EnableKeyRepeat(250,40);
SDL_EnableUNICODE(1);
/* Get some Keybinds */
KEYBOARD_AddEvent(KBD_f9,KBD_MOD_CTRL,KillSwitch);
KEYBOARD_AddEvent(KBD_f10,KBD_MOD_CTRL,CaptureMouse);
KEYBOARD_AddEvent(KBD_enter,KBD_MOD_ALT,SwitchFullScreen);
GFX_Stop();
/* Get some Event handlers */
MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown");
MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse");
MAPPER_AddHandler(SwitchFullScreen,MK_return,MMOD2,"fullscr","Fullscreen");
}
void Mouse_AutoLock(bool enable) {
@ -646,143 +681,6 @@ void Mouse_AutoLock(bool enable) {
else sdl.mouse.requestlock=false;
}
static void HandleKey(SDL_KeyboardEvent * key) {
KBD_KEYS code;
switch (key->keysym.sym) {
case SDLK_1:code=KBD_1;break;
case SDLK_2:code=KBD_2;break;
case SDLK_3:code=KBD_3;break;
case SDLK_4:code=KBD_4;break;
case SDLK_5:code=KBD_5;break;
case SDLK_6:code=KBD_6;break;
case SDLK_7:code=KBD_7;break;
case SDLK_8:code=KBD_8;break;
case SDLK_9:code=KBD_9;break;
case SDLK_0:code=KBD_0;break;
case SDLK_q:code=KBD_q;break;
case SDLK_w:code=KBD_w;break;
case SDLK_e:code=KBD_e;break;
case SDLK_r:code=KBD_r;break;
case SDLK_t:code=KBD_t;break;
case SDLK_y:code=KBD_y;break;
case SDLK_u:code=KBD_u;break;
case SDLK_i:code=KBD_i;break;
case SDLK_o:code=KBD_o;break;
case SDLK_p:code=KBD_p;break;
case SDLK_a:code=KBD_a;break;
case SDLK_s:code=KBD_s;break;
case SDLK_d:code=KBD_d;break;
case SDLK_f:code=KBD_f;break;
case SDLK_g:code=KBD_g;break;
case SDLK_h:code=KBD_h;break;
case SDLK_j:code=KBD_j;break;
case SDLK_k:code=KBD_k;break;
case SDLK_l:code=KBD_l;break;
case SDLK_z:code=KBD_z;break;
case SDLK_x:code=KBD_x;break;
case SDLK_c:code=KBD_c;break;
case SDLK_v:code=KBD_v;break;
case SDLK_b:code=KBD_b;break;
case SDLK_n:code=KBD_n;break;
case SDLK_m:code=KBD_m;break;
case SDLK_F1:code=KBD_f1;break;
case SDLK_F2:code=KBD_f2;break;
case SDLK_F3:code=KBD_f3;break;
case SDLK_F4:code=KBD_f4;break;
case SDLK_F5:code=KBD_f5;break;
case SDLK_F6:code=KBD_f6;break;
case SDLK_F7:code=KBD_f7;break;
case SDLK_F8:code=KBD_f8;break;
case SDLK_F9:code=KBD_f9;break;
case SDLK_F10:code=KBD_f10;break;
case SDLK_F11:code=KBD_f11;break;
case SDLK_F12:code=KBD_f12;break;
case SDLK_ESCAPE:code=KBD_esc;break;
case SDLK_TAB:code=KBD_tab;break;
case SDLK_BACKSPACE:code=KBD_backspace;break;
case SDLK_RETURN:code=KBD_enter;break;
case SDLK_SPACE:code=KBD_space;break;
case SDLK_LALT:code=KBD_leftalt;break;
case SDLK_RALT:code=KBD_rightalt;break;
case SDLK_LCTRL:code=KBD_leftctrl;break;
case SDLK_RCTRL:code=KBD_rightctrl;break;
case SDLK_LSHIFT:code=KBD_leftshift;break;
case SDLK_RSHIFT:code=KBD_rightshift;break;
case SDLK_CAPSLOCK:code=KBD_capslock;break;
case SDLK_SCROLLOCK:code=KBD_scrolllock;break;
case SDLK_NUMLOCK:code=KBD_numlock;break;
case SDLK_BACKQUOTE:code=KBD_grave;break;
case SDLK_MINUS:code=KBD_minus;break;
case SDLK_EQUALS:code=KBD_equals;break;
case SDLK_BACKSLASH:code=KBD_backslash;break;
case SDLK_LEFTBRACKET:code=KBD_leftbracket;break;
case SDLK_RIGHTBRACKET:code=KBD_rightbracket;break;
case SDLK_SEMICOLON:code=KBD_semicolon;break;
case SDLK_QUOTE:code=KBD_quote;break;
case SDLK_PERIOD:code=KBD_period;break;
case SDLK_COMMA:code=KBD_comma;break;
case SDLK_SLASH:code=KBD_slash;break;
case SDLK_INSERT:code=KBD_insert;break;
case SDLK_HOME:code=KBD_home;break;
case SDLK_PAGEUP:code=KBD_pageup;break;
case SDLK_DELETE:code=KBD_delete;break;
case SDLK_END:code=KBD_end;break;
case SDLK_PAGEDOWN:code=KBD_pagedown;break;
case SDLK_LEFT:code=KBD_left;break;
case SDLK_UP:code=KBD_up;break;
case SDLK_DOWN:code=KBD_down;break;
case SDLK_RIGHT:code=KBD_right;break;
case SDLK_KP1:code=KBD_kp1;break;
case SDLK_KP2:code=KBD_kp2;break;
case SDLK_KP3:code=KBD_kp3;break;
case SDLK_KP4:code=KBD_kp4;break;
case SDLK_KP5:code=KBD_kp5;break;
case SDLK_KP6:code=KBD_kp6;break;
case SDLK_KP7:code=KBD_kp7;break;
case SDLK_KP8:code=KBD_kp8;break;
case SDLK_KP9:code=KBD_kp9;break;
case SDLK_KP0:code=KBD_kp0;break;
case SDLK_KP_DIVIDE:code=KBD_kpslash;break;
case SDLK_KP_MULTIPLY:code=KBD_kpmultiply;break;
case SDLK_KP_MINUS:code=KBD_kpminus;break;
case SDLK_KP_PLUS:code=KBD_kpplus;break;
case SDLK_KP_ENTER:code=KBD_kpenter;break;
case SDLK_KP_PERIOD:code=KBD_kpperiod;break;
/* Special Keys */
default:
code=KBD_1;
LOG(LOG_KEYBOARD,LOG_ERROR)("Unhandled SDL keysym %d",key->keysym.sym);
break;
}
/* Check the modifiers */
Bitu mod=
((key->keysym.mod & KMOD_CTRL) ? KBD_MOD_CTRL : 0) |
((key->keysym.mod & KMOD_ALT) ? KBD_MOD_ALT : 0) |
((key->keysym.mod & KMOD_SHIFT) ? KBD_MOD_SHIFT : 0);
Bitu ascii=key->keysym.unicode<128 ? key->keysym.unicode : 0;
#ifdef MACOSX
// HACK: Fix backspace on Mac OS X
// REMOVE ME oneday
if (code==KBD_backspace)
ascii=8;
#endif
KEYBOARD_AddKey(code,ascii,mod,(key->state==SDL_PRESSED));
}
static void HandleMouseMotion(SDL_MouseMotionEvent * motion) {
if (sdl.mouse.locked)
Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100);
@ -824,30 +722,7 @@ static void HandleMouseButton(SDL_MouseButtonEvent * button) {
}
}
static void HandleJoystickAxis(SDL_JoyAxisEvent * jaxis) {
switch (jaxis->axis) {
case 0:
JOYSTICK_Move_X(0,(float)(jaxis->value/32768.0));
break;
case 1:
JOYSTICK_Move_Y(0,(float)(jaxis->value/32768.0));
break;
}
}
static void HandleJoystickButton(SDL_JoyButtonEvent * jbutton) {
bool state;
state=jbutton->type==SDL_JOYBUTTONDOWN;
if (jbutton->button<2) {
JOYSTICK_Button(0,jbutton->button,state);
}
}
static Bit8u laltstate = SDL_KEYUP;
void GFX_Events() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
@ -858,13 +733,6 @@ void GFX_Events() {
}
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
// ignore event lalt+tab
if (event.key.keysym.sym==SDLK_LALT) laltstate = event.key.type;
if ((event.key.keysym.sym==SDLK_TAB) && (laltstate==SDL_KEYDOWN)) break;
HandleKey(&event.key);
break;
case SDL_MOUSEMOTION:
HandleMouseMotion(&event.motion);
break;
@ -872,19 +740,15 @@ void GFX_Events() {
case SDL_MOUSEBUTTONUP:
HandleMouseButton(&event.button);
break;
case SDL_JOYAXISMOTION:
HandleJoystickAxis(&event.jaxis);
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
HandleJoystickButton(&event.jbutton);
break;
case SDL_VIDEORESIZE:
// HandleVideoResize(&event.resize);
break;
case SDL_QUIT:
throw(0);
break;
default:
void MAPPER_CheckEvent(SDL_Event * event);
MAPPER_CheckEvent(&event);
}
}
}
@ -931,11 +795,9 @@ int main(int argc, char* argv[]) {
}
}
#endif //defined(WIN32) && !(C_DEBUG)
#if C_DEBUG
DEBUG_SetupConsole();
#endif
if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM
#ifndef DISABLE_JOYSTICK
|SDL_INIT_JOYSTICK
@ -943,6 +805,7 @@ int main(int argc, char* argv[]) {
#endif
) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError());
Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp);
sdl_sec->AddInitFunction(&MAPPER_StartUp);
sdl_sec->Add_bool("fullscreen",false);
sdl_sec->Add_bool("fulldouble",false);
sdl_sec->Add_bool("fullfixed",false);
@ -953,6 +816,7 @@ int main(int argc, char* argv[]) {
sdl_sec->Add_bool("autolock",true);
sdl_sec->Add_int("sensitivity",100);
sdl_sec->Add_bool("waitonerror",true);
sdl_sec->Add_string("mapperfile","mapper.txt");
MSG_Add("SDL_CONFIGFILE_HELP",
"fullscreen -- Start dosbox directly in fullscreen.\n"
@ -996,19 +860,12 @@ int main(int argc, char* argv[]) {
/* Init all the sections */
control->Init();
/* Some extra SDL Functions */
#ifndef DISABLE_JOYSTICK
if (SDL_NumJoysticks()>0) {
SDL_JoystickEventState(SDL_ENABLE);
sdl.joy=SDL_JoystickOpen(0);
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy));
JOYSTICK_Enable(0,true);
}
#endif
if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) {
if(!sdl.desktop.fullscreen) { //only switch if not allready in fullscreen
SwitchFullScreen();
}
}
MAPPER_Init();
/* Start up main machine */
control->StartUp();
/* Shutdown everything */