Merge pull request #44 from negativeExponent/mdfn_surface_cleanup

Add 16/32 color modes switching and cleanups
This commit is contained in:
Autechre 2020-10-16 10:29:54 +02:00 committed by GitHub
commit 88c91e090b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 254 additions and 410 deletions

View File

@ -85,7 +85,6 @@ SOURCES_CXX += \
$(MEDNAFEN_DIR)/mempatcher.cpp \
$(MEDNAFEN_DIR)/md5.cpp \
$(MEDNAFEN_DIR)/sound/Stereo_Buffer.cpp \
$(MEDNAFEN_DIR)/video/surface.cpp \
$(MEDNAFEN_DIR)/endian.cpp \
$(CORE_DIR)/libretro.cpp

View File

@ -46,6 +46,7 @@ std::string retro_base_name;
std::string retro_save_directory;
static bool libretro_supports_input_bitmasks;
static int system_color_depth = 16;
extern MDFNGI EmulatedLynx;
MDFNGI *MDFNGameInfo = &EmulatedLynx;
@ -135,12 +136,6 @@ void retro_init(void)
retro_save_directory = retro_base_directory;
}
#if defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565)
enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565;
if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb)
log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
#endif
if (environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb))
perf_get_cpu_features_cb = perf_cb.get_cpu_features;
else
@ -231,6 +226,41 @@ static bool MDFNI_LoadGame(const uint8_t *data, size_t size)
return true;
}
static bool init_pix_format(void)
{
struct retro_variable var = { "lynx_pix_format", NULL };
bool ret = true;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
system_color_depth = atoi(var.value);
}
if (system_color_depth == 32)
{
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
{
if (log_cb)
log_cb(RETRO_LOG_ERROR, "Pixel format XRGB8888 not supported by platform.\n");
ret = false;
}
}
if (!ret || system_color_depth == 16)
{
enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565;
if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565))
{
log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
system_color_depth = 16;
}
else
ret = false;
}
return ret;
}
bool retro_load_game(const struct retro_game_info *info)
{
@ -253,26 +283,51 @@ bool retro_load_game(const struct retro_game_info *info)
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
#ifdef WANT_32BPP
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
{
if (log_cb)
log_cb(RETRO_LOG_ERROR, "Pixel format XRGB8888 not supported by platform, cannot use %s.\n", MEDNAFEN_CORE_NAME);
return false;
}
#endif
overscan = false;
environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan);
if (!init_pix_format())
log_cb(RETRO_LOG_ERROR, "Unable to initialize pixel format. Aborting.\n");
if (!MDFNI_LoadGame((const uint8_t *)info->data, info->size))
return false;
MDFN_PixelFormat pix_fmt(MDFN_COLORSPACE_RGB, 16, 8, 0, 24);
last_pixel_format = MDFN_PixelFormat();
surf = (MDFN_Surface*)calloc(1, sizeof(*surf));
if (!surf)
return false;
surf->width = FB_WIDTH;
surf->height = FB_HEIGHT;
surf->pitch = FB_WIDTH;
surf->bpp = system_color_depth;
surf = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, pix_fmt);
if (system_color_depth == 32)
{
surf->pixels = (uint32_t*)calloc(4, FB_WIDTH * FB_HEIGHT);
if (!surf->pixels)
{
free(surf);
surf = NULL;
return false;
}
}
else if (system_color_depth == 16)
{
surf->pixels16 = (uint16_t*)calloc(2, FB_WIDTH * FB_HEIGHT);
if (!surf->pixels16)
{
free(surf);
surf = NULL;
return false;
}
}
else
return false;
lynxie->DisplaySetAttributes(surf->bpp);
SetInput(0, "gamepad", (uint8_t*)&input_buf);
@ -428,13 +483,6 @@ void retro_run()
spec.VideoFormatChanged = false;
spec.SoundFormatChanged = false;
if (memcmp(&last_pixel_format, &spec.surface->format, sizeof(MDFN_PixelFormat)))
{
spec.VideoFormatChanged = true;
last_pixel_format = spec.surface->format;
}
if (spec.SoundRate != last_sound_rate)
{
spec.SoundFormatChanged = true;
@ -452,13 +500,16 @@ void retro_run()
unsigned width = spec.DisplayRect.w;
unsigned height = spec.DisplayRect.h;
#if defined(WANT_32BPP)
const uint32_t *pix = surf->pixels;
video_cb(pix, width, height, FB_WIDTH << 2);
#elif defined(WANT_16BPP)
const uint16_t *pix = surf->pixels16;
video_cb(pix, width, height, FB_WIDTH << 1);
#endif
if (surf->bpp == 32)
{
const uint32_t *pix = surf->pixels;
video_cb(pix, width, height, FB_WIDTH << 2);
}
else if (surf->bpp == 16)
{
const uint16_t *pix = surf->pixels16;
video_cb(pix, width, height, FB_WIDTH << 1);
}
audio_batch_cb(spec.SoundBuf, spec.SoundBufSize);
@ -494,8 +545,19 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
void retro_deinit()
{
delete surf;
surf = NULL;
if (surf)
{
if (surf->pixels16)
free(surf->pixels16);
surf->pixels16 = NULL;
if (surf->pixels)
free(surf->pixels);
surf->pixels = NULL;
free (surf);
surf = NULL;
}
libretro_supports_input_bitmasks = false;
}

View File

@ -63,7 +63,19 @@ struct retro_core_option_definition option_defs_us[] = {
{ "disabled", NULL },
{ NULL, NULL},
},
"enabled"
"enabled",
},
{
"lynx_pix_format",
"Color Format (Restart)",
"",
{
{ "16", "16-Bit (RGB565)" },
{ "32", "32-Bit (RGB8888)" },
{ NULL, NULL},
},
"16",
},
{ NULL, NULL, NULL, {{0}}, NULL },

View File

@ -1,6 +1,10 @@
// Band-limited sound synthesis buffer
// Various changes and hacks for use in Mednafen.
// Blip_Buffer 0.4.1
#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
#ifdef __GNUC__
#define blip_inline inline __attribute__((always_inline))
#else
@ -10,10 +14,6 @@
#include <limits.h>
#include <stdint.h>
// Blip_Buffer 0.4.1
#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
// Internal
typedef int32_t blip_long;
typedef uint32_t blip_ulong;

View File

@ -379,7 +379,7 @@ void CMikie::ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 o
}
void CMikie::DisplaySetAttributes(const MDFN_PixelFormat &format)
void CMikie::DisplaySetAttributes(int32 bpp)
{
mpDisplayCurrent=NULL;
@ -394,41 +394,82 @@ void CMikie::DisplaySetAttributes(const MDFN_PixelFormat &format)
uint8 g = ((Spot.Colours.Green * 15) + 30);
uint8 b = ((Spot.Colours.Blue * 15) + 30);
mColourMap[Spot.Index]= format.MakeColor(r, g, b);
switch (bpp)
{
case 16:
mColourMap[Spot.Index] = MAKECOLOR_16(r, g, b, 0);
break;
case 32:
mColourMap[Spot.Index] = MAKECOLOR_32(r, g, b, 0);
break;
default:
break;
}
}
}
template<typename T>
void CMikie::CopyLineSurface(void)
void CMikie::CopyLineSurface(int32 bpp)
{
T* bitmap_tmp = mpDisplayCurrent->pix<T>() + mpDisplayCurrentLine * mpDisplayCurrent->pitchinpix;
if(mpDisplayCurrentLine > 102)
{
printf("Lynx Line Overflow: %d\n", mpDisplayCurrentLine);
return;
}
for(uint32 loop = 0; loop < SCREEN_WIDTH / 2; loop++)
switch (bpp)
{
uint32 source = mpRamPointer[(uint16)mLynxAddr];
if(mDISPCTL_Flip)
case 16:
{
uint16 *bitmap_tmp = mpDisplayCurrent->pixels16 + mpDisplayCurrentLine * mpDisplayCurrent->pitch;
for (uint32 loop = 0; loop < SCREEN_WIDTH / 2; loop++)
{
mLynxAddr--;
*bitmap_tmp=mColourMap[mPalette[source&0x0f].Index];
bitmap_tmp++;
*bitmap_tmp=mColourMap[mPalette[source>>4].Index];
bitmap_tmp++;
uint32 source = mpRamPointer[(uint16)mLynxAddr];
if (mDISPCTL_Flip)
{
mLynxAddr--;
*bitmap_tmp = mColourMap[mPalette[source & 0x0f].Index];
bitmap_tmp++;
*bitmap_tmp = mColourMap[mPalette[source >> 4].Index];
bitmap_tmp++;
}
else
{
mLynxAddr++;
*bitmap_tmp = mColourMap[mPalette[source >> 4].Index];
bitmap_tmp++;
*bitmap_tmp = mColourMap[mPalette[source & 0x0f].Index];
bitmap_tmp++;
}
}
else
break;
}
case 32:
{
uint32 *bitmap_tmp = mpDisplayCurrent->pixels + mpDisplayCurrentLine * mpDisplayCurrent->pitch;
for (uint32 loop = 0; loop < SCREEN_WIDTH / 2; loop++)
{
mLynxAddr++;
*bitmap_tmp = mColourMap[mPalette[source>>4].Index];
bitmap_tmp++;
*bitmap_tmp = mColourMap[mPalette[source&0x0f].Index];
bitmap_tmp++;
uint32 source = mpRamPointer[(uint16)mLynxAddr];
if (mDISPCTL_Flip)
{
mLynxAddr--;
*bitmap_tmp = mColourMap[mPalette[source & 0x0f].Index];
bitmap_tmp++;
*bitmap_tmp = mColourMap[mPalette[source >> 4].Index];
bitmap_tmp++;
}
else
{
mLynxAddr++;
*bitmap_tmp = mColourMap[mPalette[source >> 4].Index];
bitmap_tmp++;
*bitmap_tmp = mColourMap[mPalette[source & 0x0f].Index];
bitmap_tmp++;
}
}
}
}
}
uint32 CMikie::DisplayRenderLine(void)
@ -486,16 +527,7 @@ uint32 CMikie::DisplayRenderLine(void)
// Assign the temporary pointer;
if(!mpSkipFrame)
{
switch(mpDisplayCurrent->format.bpp)
{
case 16:
CopyLineSurface<uint16>();
break;
case 32:
CopyLineSurface<uint32>();
break;
}
CopyLineSurface(mpDisplayCurrent->bpp);
if(mpDisplayCurrentLine < 102)
LynxLineDrawn[mpDisplayCurrentLine] = true;

View File

@ -201,7 +201,7 @@ class CMikie : public CLynxBase
void ComLynxTxLoopback(int data);
void ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 objref);
void DisplaySetAttributes(const MDFN_PixelFormat &format);
void DisplaySetAttributes(int32 bpp);
void BlowOut(void);
@ -395,7 +395,7 @@ class CMikie : public CLynxBase
uint32 mLynxLineDMACounter;
uint32 mLynxAddr;
template<typename T> void CopyLineSurface(void);
void CopyLineSurface(int32 bpp);
};

View File

@ -256,7 +256,7 @@ void Emulate(EmulateSpecStruct *espec)
espec->DisplayRect.h = 102;
if(espec->VideoFormatChanged)
lynxie->DisplaySetAttributes(espec->surface->format); // FIXME, pitch
lynxie->DisplaySetAttributes(espec->surface->bpp);
if(espec->SoundFormatChanged)
{
@ -286,32 +286,36 @@ void Emulate(EmulateSpecStruct *espec)
}
{
// FIXME, we should integrate this into mikie.*
uint32 color_black = espec->surface->MakeColor(30, 30, 30);
// FIXME, we should integrate this into mikie.*
uint32 color_black;
if (espec->surface->bpp == 16)
{
color_black = MAKECOLOR_16(30, 30, 30, 0);
for (int y = 0; y < 102; y++)
{
uint16 *row = espec->surface->pixels16 + y * espec->surface->pitch;
for(int y = 0; y < 102; y++)
{
if(espec->surface->format.bpp == 16)
{
uint16 *row = espec->surface->pixels16 + y * espec->surface->pitchinpix;
if (!LynxLineDrawn[y])
{
for (int x = 0; x < 160; x++)
row[x] = color_black;
}
}
}
else if (espec->surface->bpp == 32)
{
color_black = MAKECOLOR_32(30, 30, 30, 0);
for (int y = 0; y < 102; y++)
{
uint32 *row = espec->surface->pixels + y * espec->surface->pitch;
if(!LynxLineDrawn[y])
{
for(int x = 0; x < 160; x++)
row[x] = color_black;
}
}
else
{
uint32 *row = espec->surface->pixels + y * espec->surface->pitchinpix;
if(!LynxLineDrawn[y])
{
for(int x = 0; x < 160; x++)
row[x] = color_black;
}
}
}
if (!LynxLineDrawn[y])
{
for (int x = 0; x < 160; x++)
row[x] = color_black;
}
}
}
}
espec->MasterCycles = gSystemCycleCount - lynxie->mMikie->startTS;

View File

@ -187,7 +187,7 @@ class CSystem : public CSystemBase
// Mikey system interfacing
void DisplaySetAttributes(const MDFN_PixelFormat &format) { mMikie->DisplaySetAttributes(format); };
void DisplaySetAttributes(int32 bpp) { mMikie->DisplaySetAttributes(bpp); };
void ComLynxCable(int status) { mMikie->ComLynxCable(status); };
void ComLynxRxData(int data) { mMikie->ComLynxRxData(data); };

View File

@ -1,122 +0,0 @@
/* Mednafen - Multi-system Emulator
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../mednafen.h"
#include "surface.h"
MDFN_PixelFormat::MDFN_PixelFormat()
{
bpp = 0;
colorspace = 0;
Rshift = 0;
Gshift = 0;
Bshift = 0;
Ashift = 0;
}
MDFN_PixelFormat::MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as)
{
#if defined(WANT_16BPP)
bpp = 16;
#else
bpp = 32;
#endif
colorspace = p_colorspace;
Rshift = p_rs;
Gshift = p_gs;
Bshift = p_bs;
Ashift = p_as;
}
MDFN_Surface::MDFN_Surface()
{
format = MDFN_PixelFormat();
pixels = NULL;
pixels16 = NULL;
pitchinpix = 0;
w = 0;
h = 0;
}
MDFN_Surface::MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf)
{
Init(p_pixels, p_width, p_height, p_pitchinpix, nf);
}
void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf)
{
void *rpix = NULL;
assert(nf.bpp == 16 || nf.bpp == 32);
format = nf;
pixels16 = NULL;
pixels = NULL;
#if defined(WANT_8BPP)
palette = NULL;
#endif
if(!(rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8))))
throw(1);
#if defined(WANT_8BPP)
//if(nf.bpp == 8)
{
pixels8 = (uint8 *)rpix;
palette = (MDFN_PaletteEntry*)calloc(sizeof(MDFN_PaletteEntry), 256);
}
#elif defined(WANT_16BPP)
//if(nf.bpp == 16)
pixels16 = (uint16 *)rpix;
#elif defined(WANT_32BPP)
//else
pixels = (uint32 *)rpix;
#endif
w = p_width;
h = p_height;
pitchinpix = p_pitchinpix;
}
// When we're converting, only convert the w*h area(AKA leave the last part of the line, pitch32 - w, alone),
// for places where we store auxillary information there(graphics viewer in the debugger), and it'll be faster
// to boot.
void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert)
{
format = nf;
}
MDFN_Surface::~MDFN_Surface()
{
#if defined(WANT_16BPP)
if(pixels16)
free(pixels16);
#elif defined(WANT_32BPP)
if(pixels)
free(pixels);
#elif defined(WANT_8BPP)
pixels8 = NULL;
if(palette)
free(palette);
palette = NULL;
#endif
}

View File

@ -1,204 +1,61 @@
#ifndef __MDFN_SURFACE_H
#define __MDFN_SURFACE_H
#if defined(WANT_32BPP)
#define RED_SHIFT 16
#define GREEN_SHIFT 8
#define BLUE_SHIFT 0
#define ALPHA_SHIFT 24
#define MAKECOLOR(r, g, b, a) ((r << RED_SHIFT) | (g << GREEN_SHIFT) | (b << BLUE_SHIFT) | (a << ALPHA_SHIFT))
#elif defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565)
/* 16bit color - RGB565 */
#define RED_MASK 0xf800
#define GREEN_MASK 0x7e0
#define BLUE_MASK 0x1f
#define RED_EXPAND 3
#define GREEN_EXPAND 2
#define BLUE_EXPAND 3
#define RED_SHIFT 11
#define GREEN_SHIFT 5
#define BLUE_SHIFT 0
#define MAKECOLOR(r, g, b, a) (((r >> RED_EXPAND) << RED_SHIFT) | ((g >> GREEN_EXPAND) << GREEN_SHIFT) | ((b >> BLUE_EXPAND) << BLUE_SHIFT))
#elif defined(WANT_16BPP) && !defined(FRONTEND_SUPPORTS_RGB565)
/* 16bit color - RGB555 */
#define RED_MASK 0x7c00
#define GREEN_MASK 0x3e0
#define BLUE_MASK 0x1f
#define RED_EXPAND 3
#define GREEN_EXPAND 3
#define BLUE_EXPAND 3
#define RED_SHIFT 10
#define GREEN_SHIFT 5
#define BLUE_SHIFT 0
#define MAKECOLOR(r, g, b, a) (((r >> RED_EXPAND) << RED_SHIFT) | ((g >> GREEN_EXPAND) << GREEN_SHIFT) | ((b >> BLUE_EXPAND) << BLUE_SHIFT))
#endif
#include "mednafen-types.h"
struct MDFN_PaletteEntry
{
uint8 r, g, b;
};
/* 32bit color - XRGB8888 */
#define RED_SHIFT_32 16
#define GREEN_SHIFT_32 8
#define BLUE_SHIFT_32 0
#define ALPHA_SHIFT_32 24
#define MAKECOLOR_32(r, g, b, a) ((r << RED_SHIFT_32) | (g << GREEN_SHIFT_32) | (b << BLUE_SHIFT_32) | (a << ALPHA_SHIFT_32))
/* 16bit color - RGB565 */
#define RED_MASK_16 0xf800
#define GREEN_MASK_16 0x7e0
#define BLUE_MASK_16 0x1f
#define RED_EXPAND_16 3
#define GREEN_EXPAND_16 2
#define BLUE_EXPAND_16 3
#define RED_SHIFT_16 11
#define GREEN_SHIFT_16 5
#define BLUE_SHIFT_16 0
#define MAKECOLOR_16(r, g, b, a) (((r >> RED_EXPAND_16) << RED_SHIFT_16) | ((g >> GREEN_EXPAND_16) << GREEN_SHIFT_16) | ((b >> BLUE_EXPAND_16) << BLUE_SHIFT_16))
/* 16bit color - RGB555 */
#define RED_MASK_15 0x7c00
#define GREEN_MASK_15 0x3e0
#define BLUE_MASK_15 0x1f
#define RED_EXPAND_15 3
#define GREEN_EXPAND_15 3
#define BLUE_EXPAND_15 3
#define RED_SHIFT_15 10
#define GREEN_SHIFT_15 5
#define BLUE_SHIFT_15 0
#define MAKECOLOR_15(r, g, b, a) (((r >> RED_EXPAND_15) << RED_SHIFT_15) | ((g >> GREEN_EXPAND_15) << GREEN_SHIFT_15) | ((b >> BLUE_EXPAND_15) << BLUE_SHIFT_15))
typedef struct
{
int32 x, y, w, h;
} MDFN_Rect;
enum
typedef struct
{
MDFN_COLORSPACE_RGB = 0,
MDFN_COLORSPACE_YCbCr = 1,
MDFN_COLORSPACE_YUV = 2, // TODO, maybe.
};
unsigned int colorspace;
uint8 r_shift;
uint8 g_shift;
uint8 b_shift;
uint8 a_shift;
} MDFN_PixelFormat;
class MDFN_PixelFormat
typedef struct
{
public:
MDFN_PixelFormat();
MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as);
unsigned int bpp;
unsigned int colorspace;
union
{
uint8 Rshift; // Bit position of the lowest bit of the red component
uint8 Yshift;
};
union
{
uint8 Gshift; // [...] green component
uint8 Ushift;
uint8 Cbshift;
};
union
{
uint8 Bshift; // [...] blue component
uint8 Vshift;
uint8 Crshift;
};
uint8 Ashift; // [...] alpha component.
// Creates a color value for the surface corresponding to the 8-bit R/G/B/A color passed.
INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const
{
return MAKECOLOR(r, g, b, a);
}
// Gets the R/G/B/A values for the passed 32-bit surface pixel value
#if defined(WANT_32BPP)
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
{
r = (value >> RED_SHIFT) & 0xFF;
g = (value >> GREEN_SHIFT) & 0xFF;
b = (value >> BLUE_SHIFT) & 0xFF;
a = (value >> ALPHA_SHIFT) & 0xFF;
}
#elif defined(WANT_16BPP)
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
{
r = (value & BLUE_MASK) << RED_SHIFT;
g = (value & GREEN_MASK) << GREEN_SHIFT;
b = (value & RED_MASK);
}
#endif
}; // MDFN_PixelFormat;
// Supports 32-bit RGBA
// 16-bit is WIP
class MDFN_Surface //typedef struct
{
public:
MDFN_Surface();
MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf);
~MDFN_Surface();
uint16 *pixels16;
uint32 *pixels;
private:
INLINE void pix_(uint16*& z) const { z = pixels16; }
INLINE void pix_(uint32*& z) const { z = pixels; }
public:
template<typename T>
INLINE const T* pix(void) const
{
T* ret;
pix_(ret);
return (const T*)ret;
}
template<typename T>
INLINE T* pix(void)
{
T* ret;
pix_(ret);
return ret;
}
// w, h, and pitch32 should always be > 0
int32 w;
int32 h;
union
{
int32 pitch32; // In pixels, not in bytes.
int32 pitchinpix; // New name, new code should use this.
};
MDFN_PaletteEntry *palette;
MDFN_PixelFormat format;
void SetFormat(const MDFN_PixelFormat &new_format, bool convert);
// Creates a value for the surface corresponding to the R/G/B/A color passed.
INLINE uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a = 0) const
{
return MAKECOLOR(r, g, b, a);
}
#if defined(WANT_32BPP)
// Gets the R/G/B/A values for the passed 32-bit surface pixel value
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
{
r = (value >> RED_SHIFT) & 0xFF;
g = (value >> GREEN_SHIFT) & 0xFF;
b = (value >> BLUE_SHIFT) & 0xFF;
a = (value >> ALPHA_SHIFT) & 0xFF;
}
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
{
r = (value >> RED_SHIFT) & 0xFF;
g = (value >> GREEN_SHIFT) & 0xFF;
b = (value >> BLUE_SHIFT) & 0xFF;
}
#elif defined(WANT_16BPP)
// Gets the R/G/B/A values for the passed 32-bit surface pixel value
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const
{
r = (value & BLUE_MASK) << RED_SHIFT;
g = (value & GREEN_MASK) << GREEN_SHIFT;
b = (value & RED_MASK);
}
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
{
r = (value & BLUE_MASK) << RED_SHIFT;
g = (value & GREEN_MASK) << GREEN_SHIFT;
b = (value & RED_MASK);
}
#endif
private:
void Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf);
};
uint16 *pixels16;
uint32 *pixels;
int32 width;
int32 height;
int32 pitch;
int32 bpp;
} MDFN_Surface;
#endif