win32: change osd compositing to 32bpp and decouple from emulation update; add nearest2x resizing filter; add framerate-independent drawing equipment to osd (test in savestate slot display); make lua drawing thread-safe once again; get rid of some warnings

This commit is contained in:
zeromus 2009-07-28 04:47:06 +00:00
parent 74702bae5a
commit 7219f88382
18 changed files with 1085 additions and 843 deletions

View File

@ -36,11 +36,15 @@
#include "NDSSystem.h"
#include "mic.h"
#include "saves.h"
#include "glib.h"
bool HudEditorMode = false;
OSDCLASS *osd = NULL;
HudStruct Hud;
//contains a timer to be used for well-timed hud components
static s64 hudTimer;
static void SetHudDummy (HudCoordinates *hud)
{
hud->x=666;
@ -177,16 +181,19 @@ static void TouchDisplay() {
}
static int previousslot = 0;
static int fadecounter;
static char number[10];
static s64 slotTimer=0;
static void DrawStateSlots(){
const int yloc = Hud.SavestateSlots.y; //160
const int xloc = Hud.SavestateSlots.x; //8
s64 fadecounter = 512 - (hudTimer-slotTimer)/4; //change constant to alter fade speed
if(fadecounter < 1) fadecounter = 0;
if(fadecounter>255) fadecounter = 255;
int alpha = fadecounter;
int alpha = (int)fadecounter;
if(HudEditorMode)
alpha = 255;
@ -214,17 +221,19 @@ static void DrawStateSlots(){
}
}
if(lastSaveState != previousslot) fadecounter = 256;
previousslot = lastSaveState;
fadecounter--;
if(lastSaveState != previousslot)
slotTimer = hudTimer;
if(fadecounter < 1) fadecounter = 0;
previousslot = lastSaveState;
}
#ifdef WIN32
#include "lua-engine.h"
#endif
void DrawHUD()
{
GTimeVal time;
g_get_current_time(&time);
hudTimer = ((s64)time.tv_sec * 1000) + ((s64)time.tv_usec/1000);
if (CommonSettings.hud.ShowInputDisplay)
{
std::stringstream ss;
@ -260,9 +269,7 @@ void DrawHUD()
osd->addFixed(Hud.Microphone.x, Hud.Microphone.y, "%d",MicDisplay);
}
#endif
#ifdef WIN32
CallRegisteredLuaFunctions(LUACALL_AFTEREMULATIONGUI);
#endif
DrawStateSlots();
}

View File

@ -2087,7 +2087,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
MMU.AUX_SPI_CMD = val & 0xFF;
//T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command(val));
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val));
return;
case REG_DISPA_BG0CNT :
@ -3025,7 +3025,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
MMU.AUX_SPI_CMD = val & 0xFF;
//T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command(val));
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val));
return;
case REG_SPICNT :
@ -3082,7 +3082,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
}
else
{
MMU.powerMan_Reg[MMU.powerMan_CntReg & 0x3] = val;
MMU.powerMan_Reg[MMU.powerMan_CntReg & 0x3] = (u8)val;
}
MMU.powerMan_CntRegWritten = FALSE;
@ -3096,7 +3096,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0);
break;
}
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, val));
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, (u8)val));
return;
case 2 :

View File

@ -386,6 +386,7 @@ extern struct TCommonSettings {
, spuAdpcmCache(false)
, gfx3d_flushMode(0)
, manualBackupType(0)
, single_core(true)
{
strcpy(ARM9BIOS, "biosnds9.bin");
strcpy(ARM7BIOS, "biosnds7.bin");
@ -405,6 +406,8 @@ extern struct TCommonSettings {
bool BootFromFirmware;
bool DebugConsole;
bool single_core;
int wifiBridgeAdapterNum;

File diff suppressed because it is too large Load Diff

View File

@ -98,8 +98,8 @@ AGG2D_TEMPLATE inline TAGG2D::Agg2D() :
m_fontDescent(0.0),
m_fontCacheType(RasterFontCache),
m_imageFilter(Bilinear), //less quality more speed
//m_imageFilter(NoFilter),
//m_imageFilter(Bilinear), //less quality more speed
m_imageFilter(NoFilter),
m_imageResample(NoResample),
m_imageFilterLut(agg::image_filter_bilinear(), true),
@ -257,8 +257,8 @@ AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::attach(unsigned char* buf, unsign
textAlignment(AlignLeft, AlignBottom);
flipText(false);
#endif
imageFilter(Bilinear); //less quality more speed
//imageFilter(NoFilter);
//imageFilter(Bilinear); //less quality more speed
imageFilter(NoFilter);
imageResample(NoResample);
m_masterAlpha = 1.0;
m_antiAliasGamma = 1.0;
@ -1841,83 +1841,85 @@ public:
SpanConvImageBlend blend(gr.m_imageBlendMode, gr.m_imageBlendColor);
if(gr.m_imageFilter == TAGG2D::NoFilter)
{
//modifications less quality more speed
//original way
typedef agg::span_image_filter_rgba_nn<img_source_type,Interpolator> SpanGenType;
//typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
//typedef agg::renderer_scanline_bin<BaseRenderer,TAGG2D::SpanAllocator,SpanGenType> RendererType;
SpanGenType sg(source,interpolator);
//SpanConvType sc(sg, blend);
RendererType ri(renBase,gr.m_allocator,sg);
agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
//our way, using our own span generator to support 555
//but, it isnt working yet
//typedef ImagePixFormatSet::SpanGenerator SpanGenType;
//typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
//SpanGenType sg(imgc.renBuf);
//RendererType ri(renBase,gr.m_allocator,sg);
//agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
}
else
{
bool resample = (gr.m_imageResample == TAGG2D::ResampleAlways);
if(gr.m_imageResample == TAGG2D::ResampleOnZoomOut)
{
double sx, sy;
interpolator.transformer().scaling_abs(&sx, &sy);
if (sx > 1.125 || sy > 1.125)
{
resample = true;
}
}
//else
// {
// bool resample = (gr.m_imageResample == TAGG2D::ResampleAlways);
// if(gr.m_imageResample == TAGG2D::ResampleOnZoomOut)
// {
// double sx, sy;
// interpolator.transformer().scaling_abs(&sx, &sy);
// if (sx > 1.125 || sy > 1.125)
// {
// resample = true;
// }
// }
if(resample)
{
typedef agg::span_image_resample_rgba_affine<img_source_type> SpanGenType;
typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
// if(resample)
// {
// typedef agg::span_image_resample_rgba_affine<img_source_type> SpanGenType;
// typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
// typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
SpanConvType sc(sg, blend);
RendererType ri(renBase,gr.m_allocator,sg);
agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
}
else
{
// this is the AGG2D default
if(gr.m_imageFilter == TAGG2D::Bilinear)
{
typedef agg::span_image_filter_rgba_bilinear<img_source_type,Interpolator> SpanGenType;
typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
// SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
// SpanConvType sc(sg, blend);
// RendererType ri(renBase,gr.m_allocator,sg);
// agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
// }
// else
// {
//// this is the AGG2D default
// if(gr.m_imageFilter == TAGG2D::Bilinear)
// {
// typedef agg::span_image_filter_rgba_bilinear<img_source_type,Interpolator> SpanGenType;
// typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
// typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
SpanGenType sg(source,interpolator);
SpanConvType sc(sg, blend);
RendererType ri(renBase,gr.m_allocator,sg);
agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
}
else
{
if(gr.m_imageFilterLut.diameter() == 2)
{
typedef agg::span_image_filter_rgba_2x2<img_source_type,Interpolator> SpanGenType;
typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
// SpanGenType sg(source,interpolator);
// SpanConvType sc(sg, blend);
// RendererType ri(renBase,gr.m_allocator,sg);
// agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
// }
// else
// {
// if(gr.m_imageFilterLut.diameter() == 2)
// {
// typedef agg::span_image_filter_rgba_2x2<img_source_type,Interpolator> SpanGenType;
// typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
// typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
SpanConvType sc(sg, blend);
RendererType ri(renBase,gr.m_allocator,sg);
agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
}
else
{
typedef agg::span_image_filter_rgba<img_source_type,Interpolator> SpanGenType;
typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
SpanConvType sc(sg, blend);
RendererType ri(renBase,gr.m_allocator,sg);
agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
}
}
}
}
// SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
// SpanConvType sc(sg, blend);
// RendererType ri(renBase,gr.m_allocator,sg);
// agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
// }
// else
// {
// typedef agg::span_image_filter_rgba<img_source_type,Interpolator> SpanGenType;
// typedef agg::span_converter<SpanGenType,SpanConvImageBlend> SpanConvType;
// typedef agg::renderer_scanline_aa<BaseRenderer,typename TAGG2D::SpanAllocator,SpanGenType> RendererType;
// SpanGenType sg(source,interpolator,gr.m_imageFilterLut);
// SpanConvType sc(sg, blend);
// RendererType ri(renBase,gr.m_allocator,sg);
// agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri);
// }
// }
// }
// }
}
};

View File

@ -35,10 +35,6 @@
#include "agg_path_storage.h"
#include "agg_color_rgba.h"
#include "agg_pixfmt_rgb.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_rgb_packed.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
@ -63,98 +59,6 @@
#include "agg_span_allocator.h"
namespace agg
{
//NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us
//this custom blender does more correct blending math than the default
//which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30)
struct my_blender_rgb555_pre
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover)
{
//not sure whether this is right...
alpha = color_type::base_mask - alpha;
pixel_type rgb = *p;
calc_type b = (rgb >> 10) & 31;
calc_type g = (rgb >> 5) & 31;
calc_type r = (rgb ) & 31;
b = ((b+1)*(alpha+1) + (cb)*(cover)-1)>>8;
g = ((g+1)*(alpha+1) + (cg)*(cover)-1)>>8;
r = ((r+1)*(alpha+1) + (cr)*(cover)-1)>>8;
*p = (b<<10)|(g<<5)|r;
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
struct my_blender_rgb555
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned)
{
pixel_type rgb = *p;
calc_type b = (rgb >> 7) & 0xF8;
calc_type g = (rgb >> 2) & 0xF8;
calc_type r = (rgb << 3) & 0xF8;
*p = (pixel_type)
(((((cb - b) * alpha + (b << 8)) >> 1) & 0x7C00) |
((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) |
(((cr - r) * alpha + (r << 8)) >> 11) | 0x8000);
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555_pre, rendering_buffer> my_pixfmt_rgb555_pre; //----pixfmt_rgb555_pre
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555, rendering_buffer> my_pixfmt_rgb555; //----pixfmt_rgb555_pre
}
typedef std::map<std::string, const agg::int8u*> TAgg_Font_Table;
static TAgg_Font_Table font_table;
@ -216,10 +120,6 @@ static void Agg_init_fonts()
AggDraw_Desmume aggDraw;
typedef AggDrawTargetImplementation<PixFormatSetDeclaration<agg::my_pixfmt_rgb555,agg::my_pixfmt_rgb555_pre> > T_AGG_RGB555;
typedef AggDrawTargetImplementation<PixFormatSetDeclaration<agg::pixfmt_bgra32,agg::pixfmt_bgra32_pre> > T_AGG_RGBA;
T_AGG_RGB555 agg_targetScreen(GPU_screen, 256, 384, 512);
static u32 luaBuffer[256*192*2];
@ -230,18 +130,28 @@ T_AGG_RGBA agg_targetHud((u8*)hudBuffer, 256, 384, 1024);
static AggDrawTarget* targets[] = {
&agg_targetScreen,
&agg_targetScreen, //THATS RIGHT! for now, hud maps to screen
&agg_targetHud,
&agg_targetLua,
};
void Agg_init()
{
Agg_init_fonts();
aggDraw.target = targets[0];
aggDraw.screen = targets[0];
aggDraw.hud = targets[1];
aggDraw.lua = targets[2];
aggDraw.target = targets[0];
//if we're single core, we don't want to waste time compositing
if(CommonSettings.single_core)
aggDraw.hud = &agg_targetScreen;
//and the more clever compositing isnt supported in non-windows
#ifndef WIN32
aggDraw.hud = &agg_targetScreen;
#endif
aggDraw.hud->setFont("verdana18_bold");
}
@ -250,27 +160,7 @@ void AggDraw_Desmume::setTarget(AggTarget newTarget)
target = targets[newTarget];
}
//this code would do compositing.. and maybe it will.. one day. but not for now.
//void AggDraw_Desmume::composite(void* dest)
//{
// T_AGG_RGB555 target((u8*)dest, 256, 384, 512);
//
// ctr = 0;
//
// //if lua is nonempty, blend it
// if(!agg_targetLua.empty)
// {
// T_AGG_RGBA::MyImage luaImage(agg_targetLua.buf());
// target.transformImage(luaImage, 0,40,256-1,384-1);
// }
//
// //if hud is nonempty, blend it
// if(!agg_targetHud.empty)
// {
// T_AGG_RGBA::MyImage hudImage(agg_targetHud.buf());
// target.transformImage(hudImage, 0,0,256-1,384-1);
// }
//}
////temporary, just for testing the lib
//void AGGDraw() {

View File

@ -39,10 +39,185 @@
#include "agg_renderer_outline_aa.h"
#include "agg_renderer_markers.h"
#include "agg_pixfmt_rgb.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_rgb_packed.h"
#include "agg2d.h"
typedef agg::rgba8 AggColor;
namespace agg
{
//NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us
//this custom blender does more correct blending math than the default
//which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30)
struct my_blender_rgb555_pre
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover)
{
//not sure whether this is right...
alpha = color_type::base_mask - alpha;
pixel_type rgb = *p;
calc_type b = (rgb >> 10) & 31;
calc_type g = (rgb >> 5) & 31;
calc_type r = (rgb ) & 31;
b = ((b+1)*(alpha+1) + (cb)*(cover)-1)>>8;
g = ((g+1)*(alpha+1) + (cg)*(cover)-1)>>8;
r = ((r+1)*(alpha+1) + (cr)*(cover)-1)>>8;
*p = (b<<10)|(g<<5)|r;
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
struct my_blender_rgb555
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned)
{
pixel_type rgb = *p;
calc_type b = (rgb >> 7) & 0xF8;
calc_type g = (rgb >> 2) & 0xF8;
calc_type r = (rgb << 3) & 0xF8;
*p = (pixel_type)
(((((cb - b) * alpha + (b << 8)) >> 1) & 0x7C00) |
((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) |
(((cr - r) * alpha + (r << 8)) >> 11) | 0x8000);
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
//this is a prototype span generator which should be able to generate 8888 and 555 spans
//it would be used in agg2d.inl renderImage()
//but it isn't being used yet.
//this will need to be completed before we can use 555 as a source imge
template<class Order> class span_simple_blur_rgb24
{
public:
//--------------------------------------------------------------------
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_simple_blur_rgb24() : m_source_image(0) {}
//--------------------------------------------------------------------
span_simple_blur_rgb24(const rendering_buffer& src) :
m_source_image(&src) {}
//--------------------------------------------------------------------
void source_image(const rendering_buffer& src) { m_source_image = &src; }
const rendering_buffer& source_image() const { return *m_source_image; }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, int len)
{
if(y < 1 || y >= int(m_source_image->height() - 1))
{
do
{
*span++ = rgba8(0,0,0,0);
}
while(--len);
return;
}
do
{
int color[4];
color[0] = color[1] = color[2] = color[3] = 0;
if(x > 0 && x < int(m_source_image->width()-1))
{
int i = 3;
do
{
const int8u* ptr = m_source_image->row_ptr(y - i + 2) + (x - 1) * 3;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
}
while(--i);
color[0] /= 9;
color[1] /= 9;
color[2] /= 9;
color[3] /= 9;
}
*span++ = rgba8(color[Order::R], color[Order::G], color[Order::B], color[3]);
++x;
}
while(--len);
}
private:
const rendering_buffer* m_source_image;
};
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555_pre, rendering_buffer> my_pixfmt_rgb555_pre; //----pixfmt_rgb555_pre
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555, rendering_buffer> my_pixfmt_rgb555; //----pixfmt_rgb555_pre
}
typedef PixFormatSetDeclaration<agg::my_pixfmt_rgb555,agg::my_pixfmt_rgb555_pre,agg::span_simple_blur_rgb24<agg::order_rgba> > T_AGG_PF_RGB555;
typedef PixFormatSetDeclaration<agg::pixfmt_bgra32,agg::pixfmt_bgra32_pre,agg::span_simple_blur_rgb24<agg::order_rgba> > T_AGG_PF_RGBA;
class AggDrawTarget
{
public:
@ -61,6 +236,12 @@ public:
virtual void clear() = 0;
virtual agg::rendering_buffer & buf() = 0;
//returns an image for this target. you must provide the pixel type, but if it is wrong,
//then you have just created trouble for yourself
AGG2D_IMAGE_TEMPLATE TIMAGE image() { return TIMAGE(buf()); }
// Setup
virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) = 0;
// virtual void attach(Agg2DBase::Image& img) {attach(img);};
@ -113,6 +294,9 @@ public:
virtual void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
virtual void noLine() = 0;
virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGBA> &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0;
//virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGB555> &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0;
virtual AggColor fillColor() = 0;
virtual AggColor lineColor() = 0;
@ -265,6 +449,9 @@ public:
}
}
virtual agg::rendering_buffer & buf() { return BASE::buf(); }
typename BASE::MyImage image() { return BASE::MyImage(buf()); }
// Setup
virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) {BASE::attach(buf, width, height, stride);};
// virtual void attach(Agg2DBase::Image& img) {attach(img);};
@ -343,6 +530,9 @@ public:
virtual void fillEvenOdd(bool evenOddFlag) {BASE::fillEvenOdd(evenOddFlag);};
virtual bool fillEvenOdd() {return BASE::fillEvenOdd();};
virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGBA>& img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); }
//virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGB555> &img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); }
// Transformations
virtual Agg2DBase::Transformations transformations() {return BASE::transformations();};
virtual void transformations(const Agg2DBase::Transformations& tr) {BASE::transformations(tr);};
@ -434,6 +624,11 @@ public:
virtual double rad2Deg(double v) { return v * 180.0 / agg::pi; }
};
//the main aggdraw targets for different pixel formats
typedef AggDrawTargetImplementation<T_AGG_PF_RGB555> T_AGG_RGB555;
typedef AggDrawTargetImplementation<T_AGG_PF_RGBA> T_AGG_RGBA;
class AggDraw
{
public:

View File

@ -28,6 +28,7 @@
#include "types.h"
#include "movie.h"
#include "addons.h"
#include "NDSSystem.h"
int scanline_filter_a = 2, scanline_filter_b = 4;
@ -35,10 +36,14 @@ CommandLine::CommandLine()
: error(NULL)
, ctx(g_option_context_new (""))
, is_cflash_configured(false)
, _single_core(0)
, _play_movie_file(0)
, _record_movie_file(0)
, _cflash_image(0)
, _cflash_path(0)
{
load_slot = 0;
arm9_gdb_port = arm7_gdb_port = 0;
single_core = 0;
start_paused = FALSE;
}
@ -48,11 +53,6 @@ CommandLine::~CommandLine()
g_option_context_free (ctx);
}
static const char* _play_movie_file;
static const char* _record_movie_file;
static const char* _cflash_image;
static const char* _cflash_path;
void CommandLine::loadCommonOptions()
{
//these options should be available in every port.
@ -67,7 +67,7 @@ void CommandLine::loadCommonOptions()
{ "cflash-image", 0, 0, G_OPTION_ARG_FILENAME, &_cflash_image, "Requests cflash in gbaslot with fat image at this path", "CFLASH_IMAGE"},
{ "cflash-path", 0, 0, G_OPTION_ARG_FILENAME, &_cflash_path, "Requests cflash in gbaslot with filesystem rooted at this path", "CFLASH_PATH"},
#ifdef _MSC_VER
{ "single-core", 0, 0, G_OPTION_ARG_NONE, &single_core, "Limit execution to use approximately only one core", "NUM_CORES"},
{ "single-core", 0, 0, G_OPTION_ARG_NONE, &_single_core, "Limit execution to use approximately only one core", "NUM_CORES"},
{ "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &scanline_filter_a, "Intensity of fadeout for scanlines filter (edge) (default 2)", "SCANLINE_FILTER_A"},
{ "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (corner) (default 4)", "SCANLINE_FILTER_B"},
#endif
@ -95,6 +95,7 @@ bool CommandLine::parse(int argc,char **argv)
if(_cflash_image) cflash_image = _cflash_image;
if(_cflash_path) cflash_path = _cflash_path;
CommonSettings.single_core = _single_core!=0;
if (argc == 2)
nds_file = argv[1];

View File

@ -41,7 +41,6 @@ public:
std::string play_movie_file;
std::string record_movie_file;
int arm9_gdb_port, arm7_gdb_port;
int single_core;
int start_paused;
std::string cflash_image;
std::string cflash_path;
@ -68,6 +67,13 @@ public:
GError *error;
GOptionContext *ctx;
private:
char* _play_movie_file;
char* _record_movie_file;
char* _cflash_image;
char* _cflash_path;
int _single_core;
};
#endif

View File

@ -1172,4 +1172,4 @@ void dorewind()
rewindbuffer.pop_back();
}
}
}

View File

@ -515,7 +515,7 @@ u8 WIFI_getBB_DATA(wifimac_t *wifi)
void WIFI_setBB_DATA(wifimac_t *wifi, u8 val)
{
wifi->bbDataToWrite = (val & 0xFF);
wifi->bbDataToWrite = (val);
// if ((wifi->bbIOCnt.bits.mode != 1) || !(wifi->bbIOCnt.bits.enable)) return ; /* not for write or disabled */
// wifi->BB.data[wifi->bbIOCnt.bits.address] = val ;
}
@ -880,7 +880,7 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
WIFI_setBB_CNT(wifi,val) ;
break ;
case REG_WIFI_BBSIOWRITE:
WIFI_setBB_DATA(wifi,val) ;
WIFI_setBB_DATA(wifi,val&0xFF) ;
break ;
case REG_WIFI_RXBUF_COUNT:
wifi->RXBufCount = val & 0x0FFF ;
@ -1077,13 +1077,13 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
case REG_WIFI_EXTRACOUNT:
return wifi->eCount ;
case REG_WIFI_USCOMPARE0:
return (wifi->usec & 0xFFFF);
return (u16)wifi->usec;
case REG_WIFI_USCOMPARE1:
return ((wifi->usec >> 16) & 0xFFFF);
return (u16)(wifi->usec >> 16);
case REG_WIFI_USCOMPARE2:
return ((wifi->usec >> 32) & 0xFFFF);
return (u16)(wifi->usec >> 32);
case REG_WIFI_USCOMPARE3:
return ((wifi->usec >> 48) & 0xFFFF);
return (u16)(wifi->usec >> 48);
case REG_WIFI_POWER_US:
return wifi->crystalEnabled?0:1 ;
case REG_WIFI_CIRCBUFRD_END:
@ -1112,8 +1112,6 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
void WIFI_usTrigger(wifimac_t *wifi)
{
u8 dataBuffer[0x2000] ;
u16 rcvSize ;
if (wifi->crystalEnabled)
{
/* a usec (=3F03 cycles) has passed */

View File

@ -583,6 +583,10 @@
RelativePath=".\tileView.h"
>
</File>
<File
RelativePath=".\video.h"
>
</File>
<File
RelativePath=".\windriver.h"
>

View File

@ -1,3 +1,22 @@
/* Copyright (C) 2009 DeSmuME team
This file is part of DeSmuME
DeSmuME 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.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
struct SSurface {
unsigned char *Surface;
@ -5,6 +24,7 @@ struct SSurface {
unsigned int Width, Height;
};
void RenderNearest2X (SSurface Src, SSurface Dst);
void RenderHQ2X (SSurface Src, SSurface Dst);
void Render2xSaI (SSurface Src, SSurface Dst);
void RenderSuper2xSaI (SSurface Src, SSurface Dst);

View File

@ -1,3 +1,22 @@
/* Copyright (C) 2009 DeSmuME team
This file is part of DeSmuME
DeSmuME 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.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "filter.h"
#include "types.h"
#include <stdio.h>
@ -9,21 +28,27 @@ extern CACHE_ALIGN u16 fadeOutColors[17][0x8000];
extern int scanline_filter_a, scanline_filter_b;
// stretches a single line
inline void DoubleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
FORCEINLINE void ScanLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = *lpSrc;
*lpDst++ = fadeOutColors[scanline_filter_a][(*lpSrc++)];
}
}
inline void DoubleLine16_2( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
FORCEINLINE void ScanLine16_2( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = fadeOutColors[scanline_filter_a][(*lpSrc)];
*lpDst++ = fadeOutColors[scanline_filter_b][(*lpSrc++)];
}
}
FORCEINLINE void DoubleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc++;
}
}
void RenderScanline( SSurface Src, SSurface Dst)
{
uint16 *lpSrc;
@ -36,13 +61,25 @@ void RenderScanline( SSurface Src, SSurface Dst)
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = (uint16*)Dst.Surface;
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16_2 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
//memset (lpDst, 0, 512*2), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch,
memset (lpDst, 0, 512*2), lpDst += dstPitch;
}
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
ScanLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ScanLine16_2 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
//memset (lpDst, 0, 512*2), lpDst += dstPitch;
}
void RenderNearest2X (SSurface Src, SSurface Dst)
{
uint16 *lpSrc;
unsigned int H;
const uint32 srcHeight = Src.Height;
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = (uint16*)Dst.Surface;
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}

View File

@ -648,17 +648,18 @@ int CreateDDrawBuffers()
ddsd.dwWidth = video.rotatedwidth();
ddsd.dwHeight = video.rotatedheight();
if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL) != DD_OK) return -2;
if (IDirectDraw7_CreateSurface(lpDDraw, &ddsd, &lpBackSurface, NULL) != DD_OK) return -2;
if (IDirectDraw7_CreateClipper(lpDDraw, 0, &lpDDClipPrimary, NULL) != DD_OK) return -3;
if (IDirectDraw7_CreateClipper(lpDDraw, 0, &lpDDClipPrimary, NULL) != DD_OK) return -3;
if (IDirectDrawClipper_SetHWnd(lpDDClipPrimary, 0, MainWindow->getHWnd()) != DD_OK) return -4;
if (IDirectDrawSurface7_SetClipper(lpPrimarySurface, lpDDClipPrimary) != DD_OK) return -5;
if (IDirectDrawClipper_SetHWnd(lpDDClipPrimary, 0, MainWindow->getHWnd()) != DD_OK) return -4;
if (IDirectDrawSurface7_SetClipper(lpPrimarySurface, lpDDClipPrimary) != DD_OK) return -5;
return 1;
return 1;
}
template<typename T, int bpp> static T convert(u16 val)
template<typename T, int bpp> static T realConvert(u16 val)
{
switch(bpp)
{
@ -670,11 +671,26 @@ template<typename T, int bpp> static T convert(u16 val)
}
}
template<typename T, int bpp> static FORCEINLINE T ddconvert(u32 val)
{
//not supported yet, needs to drop from 32 to 16
return val;
//switch(bpp)
//{
// case 24: case 32:
// return RGB15TO24_REVERSE(val);
// case 16: return RGB15TO16_REVERSE(val);
// default:
// return 0;
//}
}
template<typename T, int bpp> static void doRotate(void* dst)
{
u8* buffer = (u8*)dst;
int size = video.size();
u16* src = video.finalBuffer();
u32* src = video.filteredbuffer32bpp;
switch(video.rotation)
{
case 0:
@ -684,10 +700,10 @@ template<typename T, int bpp> static void doRotate(void* dst)
{
if(video.rotation==180)
for(int i = 0, j=size-1; j>=0; i++,j--)
((T*)buffer)[i] = convert<T,bpp>((src)[j]);
((T*)buffer)[i] = ddconvert<T,bpp>((src)[j]);
else
for(int i = 0; i < size; i++)
((T*)buffer)[i] = convert<T,bpp>(src[i]);
((T*)buffer)[i] = ddconvert<T,bpp>(src[i]);
}
else
{
@ -695,7 +711,7 @@ template<typename T, int bpp> static void doRotate(void* dst)
for(int y = 0; y < video.height; y++)
{
for(int x = 0; x < video.width; x++)
((T*)buffer)[x] = convert<T,bpp>(src[video.height*video.width - (y * video.width) - x - 1]);
((T*)buffer)[x] = ddconvert<T,bpp>(src[video.height*video.width - (y * video.width) - x - 1]);
buffer += ddsd.lPitch;
}
@ -703,7 +719,7 @@ template<typename T, int bpp> static void doRotate(void* dst)
for(int y = 0; y < video.height; y++)
{
for(int x = 0; x < video.width; x++)
((T*)buffer)[x] = convert<T,bpp>(src[(y * video.width) + x]);
((T*)buffer)[x] = ddconvert<T,bpp>(src[(y * video.width) + x]);
buffer += ddsd.lPitch;
}
@ -717,7 +733,7 @@ template<typename T, int bpp> static void doRotate(void* dst)
for(int y = 0; y < video.width; y++)
{
for(int x = 0; x < video.height; x++)
((T*)buffer)[x] = convert<T,bpp>(src[(((video.height-1)-x) * video.width) + y]);
((T*)buffer)[x] = ddconvert<T,bpp>(src[(((video.height-1)-x) * video.width) + y]);
buffer += ddsd.lPitch;
}
@ -725,7 +741,7 @@ template<typename T, int bpp> static void doRotate(void* dst)
for(int y = 0; y < video.width; y++)
{
for(int x = 0; x < video.height; x++)
((T*)buffer)[x] = convert<T,bpp>(src[((x) * video.width) + (video.width-1) - y]);
((T*)buffer)[x] = ddconvert<T,bpp>(src[((x) * video.width) + (video.width-1) - y]);
buffer += ddsd.lPitch;
}
@ -807,21 +823,56 @@ static void DD_DoDisplay()
//tripple buffering logic
u16 displayBuffers[3][256*192*4];
int currDisplayBuffer=-1;
int newestDisplayBuffer=-2;
volatile int currDisplayBuffer=-1;
volatile int newestDisplayBuffer=-2;
GMutex *display_mutex = NULL;
GThread *display_thread = NULL;
//does a single display work unit. only to be used from the display thread
static void DoDisplay()
static void DoDisplay_DrawHud()
{
osd->update();
DrawHUD();
video.filter();
DD_DoDisplay();
osd->clear();
}
//does a single display work unit. only to be used from the display thread
static void DoDisplay(bool firstTime)
{
if(firstTime)
{
//on single core systems, draw straight to the screen
//we only do this once per emulated frame because we don't want to waste time redrawing
//on such lousy computers
if(CommonSettings.single_core)
{
aggDraw.hud->attach(video.srcBuffer, 256, 384, 512);
DoDisplay_DrawHud();
}
//apply user's filter
video.filter();
}
//convert pixel format to 32bpp for compositing
//why do we do this over and over? well, we are compositing to
//filteredbuffer32bpp, and it needs to get refreshed each frame..
const int size = video.size();
u16* src = video.finalBuffer();
for(int i=0;i<size;i++)
video.filteredbuffer32bpp[i] = RGB15TO24_REVERSE(src[i]);
if(!CommonSettings.single_core)
{
//draw and composite the OSD (but not if we are drawing osd straight to screen)
DoDisplay_DrawHud();
T_AGG_RGBA target((u8*)video.filteredbuffer32bpp, video.width,video.height,video.width*4);
target.transformImage(aggDraw.hud->image<T_AGG_PF_RGBA>(), 0,0,video.width-1,video.height-1);
aggDraw.hud->clear();
}
DD_DoDisplay();
}
void displayProc()
{
g_mutex_lock(display_mutex);
@ -832,17 +883,18 @@ void displayProc()
g_mutex_unlock(display_mutex);
//nothing to display. give up.
if(alreadyDisplayed) return;
//something new to display:
if(!alreadyDisplayed) {
//start displaying a new buffer
currDisplayBuffer = todo;
video.srcBuffer = (u8*)displayBuffers[currDisplayBuffer];
//start displaying a new buffer
currDisplayBuffer = todo;
video.srcBuffer = (u8*)displayBuffers[currDisplayBuffer];
aggDraw.hud->attach(video.srcBuffer, 256, 384, 512);
DoDisplay();
DoDisplay(true);
}
else
{
DoDisplay(false);
}
}
@ -856,40 +908,44 @@ void displayThread(void*)
void Display()
{
if(display_thread == NULL)
CallRegisteredLuaFunctions(LUACALL_AFTEREMULATIONGUI);
if(CommonSettings.single_core)
{
display_mutex = g_mutex_new();
display_thread = g_thread_create( (GThreadFunc)displayThread,
NULL,
TRUE,
NULL);
video.srcBuffer = (u8*)GPU_screen;
DoDisplay(true);
}
else
{
if(display_thread == NULL)
{
display_mutex = g_mutex_new();
display_thread = g_thread_create( (GThreadFunc)displayThread,
NULL,
TRUE,
NULL);
}
g_mutex_lock(display_mutex);
g_mutex_lock(display_mutex);
//huh... i wonder if there is a less ugly way to do this
if(currDisplayBuffer == 0)
if(newestDisplayBuffer == 1)
newestDisplayBuffer = 2;
else newestDisplayBuffer = 1;
else if(currDisplayBuffer == 1)
if(newestDisplayBuffer == 2)
newestDisplayBuffer = 0;
else newestDisplayBuffer = 2;
else //if(currDisplayBuffer == 1)
if(newestDisplayBuffer == 0)
newestDisplayBuffer = 1;
else newestDisplayBuffer = 0;
//huh... i wonder if there is a less ugly way to do this
if(currDisplayBuffer == 0)
if(newestDisplayBuffer == 1)
newestDisplayBuffer = 2;
else newestDisplayBuffer = 1;
else if(currDisplayBuffer == 1)
if(newestDisplayBuffer == 2)
newestDisplayBuffer = 0;
else newestDisplayBuffer = 2;
else //if(currDisplayBuffer == 1)
if(newestDisplayBuffer == 0)
newestDisplayBuffer = 1;
else newestDisplayBuffer = 0;
memcpy(displayBuffers[newestDisplayBuffer],GPU_screen,256*192*4);
memcpy(displayBuffers[newestDisplayBuffer],GPU_screen,256*192*4);
g_mutex_unlock(display_mutex);
//the no-multithreading codepath
//but based on my research, this runs just fine on a single core system due to the generous
//sleep in the display loop
//video.srcBuffer = (u8*)GPU_screen;
//doDisplay();
g_mutex_unlock(display_mutex);
}
}
@ -1416,7 +1472,6 @@ std::string GetPrivateProfileStdString(LPCSTR lpAppName,LPCSTR lpKeyName,LPCSTR
int _main()
{
Desmume_InitOnce();
InitDecoder();
#ifdef WX_STUB
@ -1522,7 +1577,19 @@ int _main()
return 1;
}
if(cmdline.single_core)
//try and detect this for users who didn't specify it on the commandline
//(can't say I really blame them)
//this helps give a substantial speedup for singlecore users
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
if(systemInfo.dwNumberOfProcessors==1)
CommonSettings.single_core = true;
Desmume_InitOnce();
//in case this isnt actually a singlecore system, but the user requested it
//then restrict ourselves to one core
if(CommonSettings.single_core)
SetProcessAffinityMask(GetCurrentProcess(),1);
//sprintf(text, "%s", DESMUME_NAME_AND_VERSION);
@ -2610,6 +2677,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
MainWindow->checkMenu(IDM_RENDER_SUPEREAGLE, video.currentfilter == video.SUPEREAGLE );
MainWindow->checkMenu(IDM_RENDER_SCANLINE, video.currentfilter == video.SCANLINE );
MainWindow->checkMenu(IDM_RENDER_BILINEAR, video.currentfilter == video.BILINEAR );
MainWindow->checkMenu(IDM_RENDER_NEAREST2X, video.currentfilter == video.NEAREST2X );
MainWindow->checkMenu(IDC_STATEREWINDING, staterewindingenabled == 1 );
@ -2983,6 +3051,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
video.setfilter(video.BILINEAR);
FilterUpdate(hwnd);
break;
case IDM_RENDER_NEAREST2X:
video.setfilter(video.NEAREST2X);
FilterUpdate(hwnd);
break;
case IDM_STATE_LOAD:
{
OPENFILENAME ofn;

View File

@ -170,6 +170,7 @@
#define IDM_RENDER_SUPEREAGLE 555
#define IDM_RENDER_SCANLINE 556
#define IDM_RENDER_BILINEAR 557
#define IDM_RENDER_NEAREST2X 558
#define IDD_IO_REG 601
#define IDM_RECORD_MOVIE 602
#define IDM_PLAY_MOVIE 603

Binary file not shown.

View File

@ -14,6 +14,7 @@ public:
u8* srcBuffer;
CACHE_ALIGN u8 filteredbuffer[4*256*192*4];
CACHE_ALIGN u32 filteredbuffer32bpp[4*256*192*2];
enum {
NONE,
@ -22,7 +23,8 @@ public:
SUPER2XSAI,
SUPEREAGLE,
SCANLINE,
BILINEAR
BILINEAR,
NEAREST2X
};
@ -92,6 +94,9 @@ public:
case BILINEAR:
RenderBilinear(src, dst);
break;
case NEAREST2X:
RenderNearest2X(src,dst);
break;
}
}