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:
parent
74702bae5a
commit
7219f88382
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
1087
desmume/src/agg2d.h
1087
desmume/src/agg2d.h
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1172,4 +1172,4 @@ void dorewind()
|
|||
rewindbuffer.pop_back();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -583,6 +583,10 @@
|
|||
RelativePath=".\tileView.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\video.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\windriver.h"
|
||||
>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue