update octoshock to Mednafen 1.27.1 (#2989)
* update octoshock to Mednafen 1.27.1 * oh right, gotta add in video changes too
This commit is contained in:
parent
9bcedb2dab
commit
f5940e12e2
Binary file not shown.
|
@ -62,6 +62,7 @@
|
|||
<ClCompile Include="..\psx\timer.cpp" />
|
||||
<ClCompile Include="..\Stream.cpp" />
|
||||
<ClCompile Include="..\tests.cpp" />
|
||||
<ClCompile Include="..\video\convert.cpp" />
|
||||
<ClCompile Include="..\video\Deinterlacer.cpp" />
|
||||
<ClCompile Include="..\video\surface.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -103,6 +104,7 @@
|
|||
<ClInclude Include="..\psx\spu.h" />
|
||||
<ClInclude Include="..\psx\timer.h" />
|
||||
<ClInclude Include="..\Stream.h" />
|
||||
<ClCompile Include="..\video\convert.h" />
|
||||
<ClInclude Include="..\video\Deinterlacer.h" />
|
||||
<ClInclude Include="..\video\surface.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
<ClCompile Include="..\video\Deinterlacer.cpp">
|
||||
<Filter>video</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\video\convert.cpp">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\emuware\EW_state.cpp">
|
||||
<Filter>emuware</Filter>
|
||||
</ClCompile>
|
||||
|
@ -216,6 +219,9 @@
|
|||
<ClInclude Include="..\video\Deinterlacer.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\video\convert.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\emuware\EW_state.h">
|
||||
<Filter>emuware</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
Gran Turismo (missing music; GetLocL must be valid and sector data must be ready simultaneous with clearing of status seek bit and setting of reading bit)
|
||||
Harukanaru Toki no Naka de - Banjou Yuugi (needs GetLocL to reflect dancing around target seek position after seek completes; otherwise hangs on voice acting)
|
||||
Incredible Crisis (needs GetLocL to be valid after a SeekL; otherwise hangs without music near start of "Etsuko and the Golden Pig")
|
||||
Tomb Raider(needs GetLocP to reflect dancing around target seek position after seek completes; otherwise, CD-DA tracks at M:S:F=x:x:0 fail to play and game hangs)
|
||||
Tomb Raider(needs GetLocP to reflect dancing around just before target seek position after seek completes; otherwise, CD-DA tracks at M:S:F=x:x:0 fail to play and game hangs)
|
||||
Vib Ribbon, with extra audio CD
|
||||
Mortal Kombat Trilogy, music resumption after pause.
|
||||
|
||||
|
@ -190,6 +190,9 @@ void PS_CDC::SoftReset(void)
|
|||
{
|
||||
ClearAudioBuffers();
|
||||
|
||||
ReportLastF = 0;
|
||||
ReportStartupDelay = 0;
|
||||
|
||||
// Not sure about initial volume state
|
||||
Pending_DecodeVolume[0][0] = 0x80;
|
||||
Pending_DecodeVolume[0][1] = 0x00;
|
||||
|
@ -201,6 +204,10 @@ void PS_CDC::SoftReset(void)
|
|||
memset(ArgsBuf, 0, sizeof(ArgsBuf));
|
||||
ArgsWP = ArgsRP = 0;
|
||||
|
||||
ArgsReceiveLatch = 0;
|
||||
memset(ArgsReceiveBuf, 0, sizeof(ArgsReceiveBuf));
|
||||
ArgsReceiveIn = 0;
|
||||
|
||||
memset(ResultsBuffer, 0, sizeof(ResultsBuffer));
|
||||
ResultsWP = 0;
|
||||
ResultsRP = 0;
|
||||
|
@ -265,6 +272,10 @@ void PS_CDC::Power(void)
|
|||
{
|
||||
SPU->Power();
|
||||
|
||||
memset(SectorPipe, 0, sizeof(SectorPipe));
|
||||
memset(SB, 0, sizeof(SB));
|
||||
memset(AsyncResultsPending, 0, sizeof(AsyncResultsPending));
|
||||
memset(&DMABuffer.data[0], 0, DMABuffer.data.size());
|
||||
SoftReset();
|
||||
|
||||
HoldLogicalPos = false;
|
||||
|
@ -370,10 +381,6 @@ SYNCFUNC(PS_CDC)
|
|||
NSS(CommandLoc_Dirty);
|
||||
NSS(xa_previous);
|
||||
|
||||
NSS(xa_cur_set);
|
||||
NSS(xa_cur_file);
|
||||
NSS(xa_cur_chan);
|
||||
|
||||
NSS(ReportLastF);
|
||||
NSS(ReportStartupDelay);
|
||||
|
||||
|
@ -677,23 +684,6 @@ bool PS_CDC::XA_Test(const uint8 *sdata)
|
|||
if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan))
|
||||
return false;
|
||||
|
||||
if(!xa_cur_set || (Mode & MODE_SF))
|
||||
{
|
||||
xa_cur_set = true;
|
||||
xa_cur_file = sh->file;
|
||||
xa_cur_chan = sh->channel;
|
||||
}
|
||||
else if(sh->file != xa_cur_file || sh->channel != xa_cur_chan)
|
||||
return false;
|
||||
|
||||
if(sh->submode & XA_SUBMODE_EOF)
|
||||
{
|
||||
//puts("YAY");
|
||||
xa_cur_set = false;
|
||||
xa_cur_file = 0;
|
||||
xa_cur_chan = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -702,10 +692,6 @@ void PS_CDC::ClearAudioBuffers(void)
|
|||
memset(&AudioBuffer, 0, sizeof(AudioBuffer));
|
||||
memset(xa_previous, 0, sizeof(xa_previous));
|
||||
|
||||
xa_cur_set = false;
|
||||
xa_cur_file = 0;
|
||||
xa_cur_chan = 0;
|
||||
|
||||
memset(ADPCM_ResampBuf, 0, sizeof(ADPCM_ResampBuf));
|
||||
ADPCM_ResampCurPhase = 0;
|
||||
ADPCM_ResampCurPos = 0;
|
||||
|
@ -1161,7 +1147,7 @@ void PS_CDC::HandlePlayRead(void)
|
|||
|
||||
if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY) // || DriveStatus == DS_SEEKING_LOGICAL2)
|
||||
{
|
||||
if(CurSector >= (SeekTarget + 2))
|
||||
if(CurSector >= (SeekTarget + (HoldLogicalPos ? 2 : 0)))
|
||||
CurSector = std::max<int32>(-150, CurSector - 9);
|
||||
}
|
||||
else
|
||||
|
@ -1258,6 +1244,9 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
|
|||
SeekFinished = true;
|
||||
ReportStartupDelay = 24000000;
|
||||
|
||||
if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY)
|
||||
CurSector = std::max<int32>(-150, CurSector - 9);
|
||||
|
||||
PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
|
||||
}
|
||||
else if(DriveStatus == DS_SEEKING_LOGICAL)
|
||||
|
|
|
@ -242,9 +242,6 @@ class PS_CDC
|
|||
bool XA_Test(const uint8 *sdata);
|
||||
void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab);
|
||||
int16 xa_previous[2][2];
|
||||
bool xa_cur_set;
|
||||
uint8 xa_cur_file;
|
||||
uint8 xa_cur_chan;
|
||||
|
||||
uint8 ReportLastF;
|
||||
int32 ReportStartupDelay;
|
||||
|
@ -263,7 +260,7 @@ class PS_CDC
|
|||
void PreSeekHack(int32 target);
|
||||
void ReadBase(void);
|
||||
|
||||
static const CDC_CTEntry Commands[0x20];
|
||||
MDFN_HIDE static const CDC_CTEntry Commands[0x20];
|
||||
|
||||
int32 Command_Nop(const int arg_count, const uint8 *args);
|
||||
int32 Command_Setloc(const int arg_count, const uint8 *args);
|
||||
|
|
|
@ -1478,7 +1478,7 @@ MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp
|
|||
}
|
||||
else
|
||||
{
|
||||
PSX_GPULineHook(sys_timestamp, sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio, scanline == 0, NULL, &surface->format, 0, 0, 0, 0);
|
||||
PSX_GPULineHook(sys_timestamp, sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio, scanline == 0, NULL, NULL, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(!InVBlank)
|
||||
|
|
|
@ -147,25 +147,21 @@ InputDevice_Memcard::~InputDevice_Memcard()
|
|||
|
||||
void InputDevice_Memcard::Power(void)
|
||||
{
|
||||
presence_new = true;
|
||||
memset(rw_buffer, 0, sizeof(rw_buffer));
|
||||
write_xor = 0;
|
||||
|
||||
dtr = 0;
|
||||
|
||||
//buttons[0] = buttons[1] = 0;
|
||||
|
||||
command_phase = 0;
|
||||
|
||||
bitpos = 0;
|
||||
|
||||
receive_buffer = 0;
|
||||
|
||||
command = 0;
|
||||
addr = 0;
|
||||
calced_xor = 0;
|
||||
|
||||
transmit_buffer = 0;
|
||||
|
||||
transmit_count = 0;
|
||||
|
||||
addr = 0;
|
||||
|
||||
presence_new = true;
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns)
|
||||
|
|
|
@ -1399,7 +1399,7 @@ EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k)
|
|||
|
||||
|
||||
//setup gpu output surfaces
|
||||
MDFN_PixelFormat nf(MDFN_COLORSPACE_RGB, 16, 8, 0, 24);
|
||||
MDFN_PixelFormat nf(MDFN_COLORSPACE_RGB, 4, 16, 8, 0, 24);
|
||||
for(int i=0;i<2;i++)
|
||||
{
|
||||
VTBuffer[i] = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, nf);
|
||||
|
|
|
@ -178,7 +178,7 @@ void PS_SPU::Power(void)
|
|||
CWA = 0;
|
||||
|
||||
memset(Regs, 0, sizeof(Regs));
|
||||
|
||||
memset(AuxRegs, 0, sizeof(AuxRegs));
|
||||
memset(RDSB, 0, sizeof(RDSB));
|
||||
memset(RUSB, 0, sizeof(RUSB));
|
||||
RvbResPos = 0;
|
||||
|
|
|
@ -219,28 +219,17 @@ void RunReverb(const int32* in, int32* out);
|
|||
int16 IIR_COEF;
|
||||
int16 FB_ALPHA;
|
||||
int16 FB_X;
|
||||
uint16 IIR_DEST_A0;
|
||||
uint16 IIR_DEST_A1;
|
||||
uint16 ACC_SRC_A0;
|
||||
uint16 ACC_SRC_A1;
|
||||
uint16 ACC_SRC_B0;
|
||||
uint16 ACC_SRC_B1;
|
||||
uint16 IIR_SRC_A0;
|
||||
uint16 IIR_SRC_A1;
|
||||
uint16 IIR_DEST_B0;
|
||||
uint16 IIR_DEST_B1;
|
||||
uint16 ACC_SRC_C0;
|
||||
uint16 ACC_SRC_C1;
|
||||
uint16 ACC_SRC_D0;
|
||||
uint16 ACC_SRC_D1;
|
||||
uint16 IIR_SRC_B1;
|
||||
uint16 IIR_SRC_B0;
|
||||
uint16 MIX_DEST_A0;
|
||||
uint16 MIX_DEST_A1;
|
||||
uint16 MIX_DEST_B0;
|
||||
uint16 MIX_DEST_B1;
|
||||
int16 IN_COEF_L;
|
||||
int16 IN_COEF_R;
|
||||
uint16 IIR_DEST_A[2];
|
||||
uint16 ACC_SRC_A[2];
|
||||
uint16 ACC_SRC_B[2];
|
||||
uint16 IIR_SRC_A[2];
|
||||
uint16 IIR_DEST_B[2];
|
||||
uint16 ACC_SRC_C[2];
|
||||
uint16 ACC_SRC_D[2];
|
||||
uint16 IIR_SRC_B[2];
|
||||
uint16 MIX_DEST_A[2];
|
||||
uint16 MIX_DEST_B[2];
|
||||
int16 IN_COEF[2];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -31,6 +31,13 @@ static INLINE int16 ReverbSat(int32 samp)
|
|||
return(samp);
|
||||
}
|
||||
|
||||
static INLINE int16 ReverbNeg(int16 samp)
|
||||
{
|
||||
if(samp == -32768)
|
||||
return 0x7FFF;
|
||||
|
||||
return -samp;
|
||||
}
|
||||
|
||||
INLINE uint32 PS_SPU::Get_Reverb_Offset(uint32 in_offset)
|
||||
{
|
||||
|
@ -54,7 +61,8 @@ int16 NO_INLINE PS_SPU::RD_RVB(uint16 raw_offs, int32 extra_offs)
|
|||
|
||||
void NO_INLINE PS_SPU::WR_RVB(uint16 raw_offs, int16 sample)
|
||||
{
|
||||
WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample);
|
||||
if(SPUControl & 0x80)
|
||||
WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -140,77 +148,70 @@ INLINE void PS_SPU::RunReverb(const int32* in, int32* out)
|
|||
int32 downsampled[2];
|
||||
|
||||
for(unsigned lr = 0; lr < 2; lr++)
|
||||
downsampled[lr] = Reverb4422(&RDSB[lr][(RvbResPos - 39) & 0x3F]);
|
||||
downsampled[lr] = Reverb4422(&RDSB[lr][(RvbResPos - 38) & 0x3F]);
|
||||
|
||||
//
|
||||
// Run algorithm
|
||||
///
|
||||
if(SPUControl & 0x80)
|
||||
{
|
||||
int16 IIR_INPUT_A0, IIR_INPUT_A1, IIR_INPUT_B0, IIR_INPUT_B1;
|
||||
int16 IIR_A0, IIR_A1, IIR_B0, IIR_B1;
|
||||
int16 ACC0, ACC1;
|
||||
int16 FB_A0, FB_A1, FB_B0, FB_B1;
|
||||
|
||||
IIR_INPUT_A0 = ReverbSat(((RD_RVB(IIR_SRC_A0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15));
|
||||
IIR_INPUT_A1 = ReverbSat(((RD_RVB(IIR_SRC_A1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15));
|
||||
IIR_INPUT_B0 = ReverbSat(((RD_RVB(IIR_SRC_B0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15));
|
||||
IIR_INPUT_B1 = ReverbSat(((RD_RVB(IIR_SRC_B1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15));
|
||||
|
||||
IIR_A0 = ReverbSat((((IIR_INPUT_A0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A0, -1)) >> 14)) >> 1);
|
||||
IIR_A1 = ReverbSat((((IIR_INPUT_A1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A1, -1)) >> 14)) >> 1);
|
||||
IIR_B0 = ReverbSat((((IIR_INPUT_B0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B0, -1)) >> 14)) >> 1);
|
||||
IIR_B1 = ReverbSat((((IIR_INPUT_B1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B1, -1)) >> 14)) >> 1);
|
||||
|
||||
WR_RVB(IIR_DEST_A0, IIR_A0);
|
||||
WR_RVB(IIR_DEST_A1, IIR_A1);
|
||||
WR_RVB(IIR_DEST_B0, IIR_B0);
|
||||
WR_RVB(IIR_DEST_B1, IIR_B1);
|
||||
|
||||
ACC0 = ReverbSat((((RD_RVB(ACC_SRC_A0) * ACC_COEF_A) >> 14) +
|
||||
((RD_RVB(ACC_SRC_B0) * ACC_COEF_B) >> 14) +
|
||||
((RD_RVB(ACC_SRC_C0) * ACC_COEF_C) >> 14) +
|
||||
((RD_RVB(ACC_SRC_D0) * ACC_COEF_D) >> 14)) >> 1);
|
||||
|
||||
ACC1 = ReverbSat((((RD_RVB(ACC_SRC_A1) * ACC_COEF_A) >> 14) +
|
||||
((RD_RVB(ACC_SRC_B1) * ACC_COEF_B) >> 14) +
|
||||
((RD_RVB(ACC_SRC_C1) * ACC_COEF_C) >> 14) +
|
||||
((RD_RVB(ACC_SRC_D1) * ACC_COEF_D) >> 14)) >> 1);
|
||||
|
||||
FB_A0 = RD_RVB(MIX_DEST_A0 - FB_SRC_A);
|
||||
FB_A1 = RD_RVB(MIX_DEST_A1 - FB_SRC_A);
|
||||
FB_B0 = RD_RVB(MIX_DEST_B0 - FB_SRC_B);
|
||||
FB_B1 = RD_RVB(MIX_DEST_B1 - FB_SRC_B);
|
||||
|
||||
WR_RVB(MIX_DEST_A0, ReverbSat(ACC0 - ((FB_A0 * FB_ALPHA) >> 15)));
|
||||
WR_RVB(MIX_DEST_A1, ReverbSat(ACC1 - ((FB_A1 * FB_ALPHA) >> 15)));
|
||||
|
||||
WR_RVB(MIX_DEST_B0, ReverbSat(((FB_ALPHA * ACC0) >> 15) - ((FB_A0 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B0 * FB_X) >> 15)));
|
||||
WR_RVB(MIX_DEST_B1, ReverbSat(((FB_ALPHA * ACC1) >> 15) - ((FB_A1 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B1 * FB_X) >> 15)));
|
||||
}
|
||||
|
||||
//
|
||||
// Get output samples
|
||||
//
|
||||
RUSB[0][(RvbResPos >> 1) | 0x20] = RUSB[0][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A0) + RD_RVB(MIX_DEST_B0)) >> 1;
|
||||
RUSB[1][(RvbResPos >> 1) | 0x20] = RUSB[1][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A1) + RD_RVB(MIX_DEST_B1)) >> 1;
|
||||
for(unsigned lr = 0; lr < 2; lr++)
|
||||
{
|
||||
const int16 IIR_INPUT_A = ReverbSat((((RD_RVB(IIR_SRC_A[lr ^ 0]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1);
|
||||
const int16 IIR_INPUT_B = ReverbSat((((RD_RVB(IIR_SRC_B[lr ^ 1]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1);
|
||||
const int16 IIR_A = ReverbSat((((IIR_INPUT_A * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A[lr], -1)) >> 14)) >> 1);
|
||||
const int16 IIR_B = ReverbSat((((IIR_INPUT_B * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B[lr], -1)) >> 14)) >> 1);
|
||||
|
||||
WR_RVB(IIR_DEST_A[lr], IIR_A);
|
||||
WR_RVB(IIR_DEST_B[lr], IIR_B);
|
||||
|
||||
const int32 ACC = ((RD_RVB(ACC_SRC_A[lr]) * ACC_COEF_A) >> 14) +
|
||||
((RD_RVB(ACC_SRC_B[lr]) * ACC_COEF_B) >> 14) +
|
||||
((RD_RVB(ACC_SRC_C[lr]) * ACC_COEF_C) >> 14) +
|
||||
((RD_RVB(ACC_SRC_D[lr]) * ACC_COEF_D) >> 14);
|
||||
|
||||
const int16 FB_A = RD_RVB(MIX_DEST_A[lr] - FB_SRC_A);
|
||||
const int16 FB_B = RD_RVB(MIX_DEST_B[lr] - FB_SRC_B);
|
||||
const int16 MDA = ReverbSat((ACC + ((FB_A * ReverbNeg(FB_ALPHA)) >> 14)) >> 1);
|
||||
const int16 MDB = ReverbSat(FB_A + ((((MDA * FB_ALPHA) >> 14) + ((FB_B * ReverbNeg(FB_X)) >> 14)) >> 1));
|
||||
const int16 IVB = ReverbSat(FB_B + ((MDB * FB_X) >> 15));
|
||||
|
||||
WR_RVB(MIX_DEST_A[lr], MDA);
|
||||
WR_RVB(MIX_DEST_B[lr], MDB);
|
||||
#if 0
|
||||
{
|
||||
static uint32 sqcounter;
|
||||
RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = ((sqcounter & 0xFF) == 0) ? 0x8000 : 0x0000; //((sqcounter & 0x80) ? 0x7000 : 0x9000);
|
||||
sqcounter += lr;
|
||||
}
|
||||
#else
|
||||
RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = IVB; // Output sample
|
||||
#endif
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
ReverbCur = (ReverbCur + 1) & 0x3FFFF;
|
||||
if(!ReverbCur)
|
||||
ReverbCur = ReverbWA;
|
||||
|
||||
for(unsigned lr = 0; lr < 2; lr++)
|
||||
upsampled[lr] = Reverb2244<true>(&RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]);
|
||||
upsampled[lr] = Reverb2244<false>(&RUSB[lr][((RvbResPos >> 1) - 19) & 0x1F]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned lr = 0; lr < 2; lr++)
|
||||
upsampled[lr] = Reverb2244<false>(&RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]);
|
||||
upsampled[lr] = Reverb2244<true>(&RUSB[lr][((RvbResPos >> 1) - 19) & 0x1F]);
|
||||
}
|
||||
|
||||
RvbResPos = (RvbResPos + 1) & 0x3F;
|
||||
|
||||
for(unsigned lr = 0; lr < 2; lr++)
|
||||
{
|
||||
#if 0
|
||||
if(!lr)
|
||||
printf("%d\n", (-upsampled[lr]) >> 1);
|
||||
#endif
|
||||
|
||||
out[lr] = upsampled[lr];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -181,19 +181,19 @@ void Deinterlacer::Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32
|
|||
}
|
||||
}
|
||||
|
||||
switch(surface->format.bpp)
|
||||
switch (surface->format.opp)
|
||||
{
|
||||
case 8:
|
||||
InternalProcess<uint8>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
case 1:
|
||||
InternalProcess<uint8>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
InternalProcess<uint16>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
case 2:
|
||||
InternalProcess<uint16>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
InternalProcess<uint32>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
case 4:
|
||||
InternalProcess<uint32>(surface, DisplayRect, LineWidths, field);
|
||||
break;
|
||||
}
|
||||
|
||||
PrevDRect = DisplayRect_Original;
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* convert.cpp - Pixel format conversion
|
||||
** Copyright (C) 2020 Mednafen Team
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU General Public License
|
||||
** as published by the Free Software Foundation; either version 2
|
||||
** of the License, or (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU 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.,
|
||||
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "octoshock.h"
|
||||
#include "surface.h"
|
||||
#include "convert.h"
|
||||
|
||||
template<bool src_equals_dest, typename OT, typename NT, uint8 old_colorspace, uint8 new_colorspace>
|
||||
static NO_INLINE void Convert_Slow(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx)
|
||||
{
|
||||
MDFN_PixelFormat old_pf = ctx->spf;
|
||||
MDFN_PixelFormat new_pf = ctx->dpf;
|
||||
|
||||
old_pf.opp = sizeof(OT);
|
||||
new_pf.opp = sizeof(NT);
|
||||
|
||||
old_pf.colorspace = old_colorspace;
|
||||
new_pf.colorspace = new_colorspace;
|
||||
//
|
||||
//
|
||||
OT* src_row = (OT*)src;
|
||||
NT* dest_row = src_equals_dest ? (NT*)src_row : (NT*)dest;
|
||||
|
||||
for(unsigned x = 0; MDFN_LIKELY(x < count); x++)
|
||||
{
|
||||
if(sizeof(OT) == 1)
|
||||
dest_row[x] = ctx->palconv[src_row[x]];
|
||||
else
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
old_pf.DecodeColor(src_row[x], r, g, b, a);
|
||||
dest_row[x] = new_pf.MakeColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<bool src_equals_dest, typename OT, typename NT, uint64 old_pftag, uint64 new_pftag>
|
||||
static NO_INLINE void Convert_Fast(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx)
|
||||
{
|
||||
const MDFN_PixelFormat old_pf = MDFN_PixelFormat(old_pftag);
|
||||
const MDFN_PixelFormat new_pf = MDFN_PixelFormat(new_pftag);
|
||||
OT* src_row = (OT*)src;
|
||||
NT* dest_row = src_equals_dest ? (NT*)src_row : (NT*)dest;
|
||||
|
||||
for(unsigned x = 0; MDFN_LIKELY(x < count); x++)
|
||||
{
|
||||
uint32 c = src_row[x];
|
||||
|
||||
if(sizeof(OT) == 1)
|
||||
dest_row[x] = ctx->palconv[c];
|
||||
else if(old_pftag == MDFN_PixelFormat::IRGB16_1555 && new_pftag == MDFN_PixelFormat::RGB16_565)
|
||||
dest_row[x] = (c & 0x1F) | ((c << 1) & 0xF800) | (MDFN_PixelFormat::LUT8to6[MDFN_PixelFormat::LUT5to8[(c >> 5) & 0x1F]] << 5);
|
||||
else if(old_pftag == MDFN_PixelFormat::RGB16_565 && new_pftag == MDFN_PixelFormat::IRGB16_1555)
|
||||
dest_row[x] = (c & 0x1F) | ((c >> 1) & 0x7C00) | (MDFN_PixelFormat::LUT8to5[MDFN_PixelFormat::LUT6to8[(c >> 5) & 0x3F]] << 5);
|
||||
else
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
if(old_pftag == MDFN_PixelFormat::IRGB16_1555)
|
||||
{
|
||||
r = MDFN_PixelFormat::LUT5to8[(c >> 10) & 0x1F];
|
||||
g = MDFN_PixelFormat::LUT5to8[(c >> 5) & 0x1F];
|
||||
b = MDFN_PixelFormat::LUT5to8[(c >> 0) & 0x1F];
|
||||
a = 0;
|
||||
}
|
||||
else if(old_pftag == MDFN_PixelFormat::RGB16_565)
|
||||
{
|
||||
r = MDFN_PixelFormat::LUT5to8[(c >> 11) & 0x1F];
|
||||
g = MDFN_PixelFormat::LUT6to8[(c >> 5) & 0x3F];
|
||||
b = MDFN_PixelFormat::LUT5to8[(c >> 0) & 0x1F];
|
||||
a = 0;
|
||||
}
|
||||
else if(old_pftag == MDFN_PixelFormat::ARGB16_4444)
|
||||
{
|
||||
a = ((c & 0xF000) >> 8) | ((c & 0xF000) >> 12);
|
||||
r = ((c & 0xF00) >> 4) | ((c & 0xF00) >> 8);
|
||||
g = ((c & 0xF0) >> 0) | ((c & 0xF0) >> 4);
|
||||
b = ((c & 0xF) << 4) | ((c & 0xF) >> 0);
|
||||
}
|
||||
else
|
||||
old_pf.DecodeColor(c, r, g, b, a);
|
||||
|
||||
/*
|
||||
if(new_pftag == MDFN_PixelFormat::RGB8X3_888 || new_pftag == MDFN_PixelFormat::BGR8X3_888)
|
||||
{
|
||||
if(new_pftag == MDFN_PixelFormat::RGB8X3_888)
|
||||
{
|
||||
dest_row[x * 3 + 0] = r;
|
||||
dest_row[x * 3 + 1] = g;
|
||||
dest_row[x * 3 + 2] = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_row[x * 3 + 0] = b;
|
||||
dest_row[x * 3 + 1] = g;
|
||||
dest_row[x * 3 + 2] = r;
|
||||
}
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
if(new_pftag == MDFN_PixelFormat::IRGB16_1555)
|
||||
c = (MDFN_PixelFormat::LUT8to5[r] << 10) | (MDFN_PixelFormat::LUT8to5[g] << 5) | (MDFN_PixelFormat::LUT8to5[b] << 0);
|
||||
else if(new_pftag == MDFN_PixelFormat::RGB16_565)
|
||||
c = (MDFN_PixelFormat::LUT8to5[r] << 11) | (MDFN_PixelFormat::LUT8to6[g] << 5) | (MDFN_PixelFormat::LUT8to5[b] << 0);
|
||||
else
|
||||
c = new_pf.MakeColor(r, g, b, a);
|
||||
|
||||
dest_row[x] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<bool src_equals_dest>
|
||||
static void Convert_xxxx8888(const void* src, void* dest, uint32 count, const MDFN_PixelFormatConverter::convert_context* ctx)
|
||||
{
|
||||
const MDFN_PixelFormat spf = ctx->spf;
|
||||
const MDFN_PixelFormat dpf = ctx->dpf;
|
||||
const unsigned tmp = (0 << spf.Rshift) | (1 << spf.Gshift) | (2 << spf.Bshift) | (3 << spf.Ashift);
|
||||
const unsigned drs[4] = { dpf.Rshift, dpf.Gshift, dpf.Bshift, dpf.Ashift };
|
||||
const unsigned sh[4] = { (uint8)drs[(tmp >> 0) & 3], (uint8)drs[(tmp >> 8) & 3], (uint8)drs[(tmp >> 16) & 3], (uint8)drs[(tmp >> 24) & 3] };
|
||||
uint32* src_row = (uint32*)src;
|
||||
uint32* dest_row = src_equals_dest ? src_row : (uint32*)dest;
|
||||
|
||||
for(unsigned x = 0; MDFN_LIKELY(x < count); x++)
|
||||
{
|
||||
uint32 c = src_row[x];
|
||||
|
||||
dest_row[x] = ((uint8)(c >> 0) << sh[0]) | ((uint8)(c >> 8) << sh[1]) | ((uint8)(c >> 16) << sh[2]) | ((uint8)(c >> 24) << sh[3]);
|
||||
}
|
||||
}
|
||||
|
||||
template<bool src_equals_dest>
|
||||
static MDFN_PixelFormatConverter::convert_func CalcConversionFunction(const MDFN_PixelFormat& spf, const MDFN_PixelFormat& dpf)
|
||||
{
|
||||
#if 1
|
||||
switch(spf.tag)
|
||||
{
|
||||
#define CROWE(st, sft, dt, dft) case MDFN_PixelFormat::dft: return Convert_Fast<src_equals_dest, st, dt, MDFN_PixelFormat::sft, MDFN_PixelFormat::dft>;
|
||||
#define CROW(st, sft) case MDFN_PixelFormat::sft: \
|
||||
switch(dpf.tag) \
|
||||
{ \
|
||||
default: break; \
|
||||
CROWE(st, sft, uint32, ABGR32_8888) \
|
||||
CROWE(st, sft, uint32, ARGB32_8888) \
|
||||
CROWE(st, sft, uint32, RGBA32_8888) \
|
||||
CROWE(st, sft, uint32, BGRA32_8888) \
|
||||
CROWE(st, sft, uint16, IRGB16_1555) \
|
||||
CROWE(st, sft, uint16, RGB16_565) \
|
||||
CROWE(st, sft, uint16, ARGB16_4444) \
|
||||
/*CROWE(st, sft, uint8, RGB8X3_888)*/ \
|
||||
/*CROWE(st, sft, uint8, RGB8X3_888)*/ \
|
||||
} \
|
||||
break;
|
||||
default: break;
|
||||
CROW(uint32, ABGR32_8888)
|
||||
CROW(uint32, ARGB32_8888)
|
||||
CROW(uint32, RGBA32_8888)
|
||||
CROW(uint32, BGRA32_8888)
|
||||
CROW(uint16, IRGB16_1555)
|
||||
CROW(uint16, RGB16_565)
|
||||
CROW(uint16, ARGB16_4444)
|
||||
//
|
||||
//CROW(uint8, RGB8P_888)
|
||||
//CROW(uint8, RGB8P_666)
|
||||
#undef CROWE
|
||||
#undef CROW
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
if(spf.opp == dpf.opp && spf.colorspace == dpf.colorspace)
|
||||
{
|
||||
if(spf.opp == 4 && !((spf.Rshift | spf.Gshift | spf.Bshift | spf.Ashift | dpf.Rshift | dpf.Gshift | dpf.Bshift | dpf.Ashift) & 7))
|
||||
{
|
||||
return Convert_xxxx8888<src_equals_dest>;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Slow fallback:
|
||||
//
|
||||
#define CROWE(scs, stype, dcs, dtype) case (dcs << 4) | sizeof(dtype): return Convert_Slow<src_equals_dest, stype, dtype, scs, dcs>; break;
|
||||
#define CROW(scs, stype) \
|
||||
case (scs << 4) | sizeof(stype): \
|
||||
switch((dpf.colorspace << 4) | dpf.opp) \
|
||||
{ \
|
||||
CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint8) \
|
||||
CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint16) \
|
||||
CROWE(scs, stype, MDFN_COLORSPACE_RGB, uint32) \
|
||||
} \
|
||||
break;
|
||||
switch((spf.colorspace << 4) | spf.opp)
|
||||
{
|
||||
CROW(MDFN_COLORSPACE_RGB, uint8)
|
||||
CROW(MDFN_COLORSPACE_RGB, uint16)
|
||||
CROW(MDFN_COLORSPACE_RGB, uint32)
|
||||
}
|
||||
#undef CROWE
|
||||
#undef CROW
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
MDFN_PixelFormatConverter::MDFN_PixelFormatConverter(const MDFN_PixelFormat& src_pf, const MDFN_PixelFormat& dest_pf, const MDFN_PaletteEntry* palette)
|
||||
{
|
||||
ctx.spf = src_pf;
|
||||
ctx.dpf = dest_pf;
|
||||
|
||||
if(palette)
|
||||
{
|
||||
ctx.palconv.reset(new uint32[256]);
|
||||
|
||||
for(unsigned i = 0; i < 256; i++)
|
||||
{
|
||||
uint8 r, g, b;
|
||||
|
||||
ctx.spf.DecodePColor(palette[i], r, g, b);
|
||||
ctx.palconv[i] = ctx.dpf.MakeColor(r, g, b, 0);
|
||||
}
|
||||
}
|
||||
|
||||
convert1 = CalcConversionFunction<true>(ctx.spf, ctx.dpf);
|
||||
convert2 = CalcConversionFunction<false>(ctx.spf, ctx.dpf);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/******************************************************************************/
|
||||
/* Mednafen - Multi-system Emulator */
|
||||
/******************************************************************************/
|
||||
/* convert.h - Pixel format conversion
|
||||
** Copyright (C) 2020 Mednafen Team
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU General Public License
|
||||
** as published by the Free Software Foundation; either version 2
|
||||
** of the License, or (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU 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.,
|
||||
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MDFN_VIDEO_CONVERT_H
|
||||
#define __MDFN_VIDEO_CONVERT_H
|
||||
|
||||
#include <memory>
|
||||
#include "octoshock.h"
|
||||
#include "surface.h"
|
||||
|
||||
class MDFN_PixelFormatConverter
|
||||
{
|
||||
public:
|
||||
MDFN_PixelFormatConverter(const MDFN_PixelFormat& src_pf, const MDFN_PixelFormat& dest_pf, const MDFN_PaletteEntry* palette = nullptr);
|
||||
|
||||
INLINE void Convert(void* dest, uint32 count)
|
||||
{
|
||||
convert1(dest, dest, count, &ctx);
|
||||
}
|
||||
|
||||
INLINE void Convert(const void* src, void* dest, uint32 count)
|
||||
{
|
||||
convert2(src, dest, count, &ctx);
|
||||
}
|
||||
|
||||
struct convert_context
|
||||
{
|
||||
MDFN_PixelFormat spf;
|
||||
MDFN_PixelFormat dpf;
|
||||
std::unique_ptr<uint32[]> palconv;
|
||||
};
|
||||
|
||||
typedef void (*convert_func)(const void*, void*, uint32, const convert_context*);
|
||||
private:
|
||||
|
||||
convert_func convert1;
|
||||
convert_func convert2;
|
||||
convert_context ctx;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,38 +22,7 @@
|
|||
#include <math.h>
|
||||
#include "octoshock.h"
|
||||
#include "surface.h"
|
||||
|
||||
MDFN_PixelFormat::MDFN_PixelFormat()
|
||||
{
|
||||
bpp = 0;
|
||||
colorspace = 0;
|
||||
|
||||
Rshift = 0;
|
||||
Gshift = 0;
|
||||
Bshift = 0;
|
||||
Ashift = 0;
|
||||
|
||||
Rprec = 0;
|
||||
Gprec = 0;
|
||||
Bprec = 0;
|
||||
Aprec = 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)
|
||||
{
|
||||
bpp = 32;
|
||||
colorspace = p_colorspace;
|
||||
|
||||
Rshift = p_rs;
|
||||
Gshift = p_gs;
|
||||
Bshift = p_bs;
|
||||
Ashift = p_as;
|
||||
|
||||
Rprec = 8;
|
||||
Gprec = 8;
|
||||
Bprec = 8;
|
||||
Aprec = 8;
|
||||
}
|
||||
#include "convert.h"
|
||||
|
||||
MDFN_Surface::MDFN_Surface()
|
||||
{
|
||||
|
@ -101,16 +70,16 @@ void MDFN_Surface::Resize(const uint32 p_width, const uint32 p_height, const uin
|
|||
void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels)
|
||||
{
|
||||
void *rpix = NULL;
|
||||
assert(nf.bpp == 8 || nf.bpp == 16 || nf.bpp == 32);
|
||||
assert(nf.opp == 1 || nf.opp == 2 || nf.opp == 4);
|
||||
|
||||
format = nf;
|
||||
|
||||
if(nf.bpp == 8)
|
||||
if(nf.opp == 1)
|
||||
{
|
||||
//assert(!nf.Rshift && !nf.Gshift && !nf.Bshift && !nf.Ashift);
|
||||
//assert(!nf.Rprec && !nf.Gprec && !nf.Bprec && !nf.Aprec);
|
||||
}
|
||||
else if(nf.bpp == 16)
|
||||
else if(nf.opp == 2)
|
||||
{
|
||||
assert(nf.Rprec && nf.Gprec && nf.Bprec && nf.Aprec);
|
||||
}
|
||||
|
@ -140,9 +109,9 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
|
|||
else
|
||||
{
|
||||
if(alloc_init_pixels)
|
||||
rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8));
|
||||
rpix = calloc(1, p_pitchinpix * p_height * nf.opp);
|
||||
else
|
||||
rpix = malloc(p_pitchinpix * p_height * (nf.bpp / 8));
|
||||
rpix = malloc(p_pitchinpix * p_height * nf.opp);
|
||||
|
||||
if(!rpix)
|
||||
{
|
||||
|
@ -153,7 +122,7 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
|
|||
}
|
||||
}
|
||||
|
||||
if(nf.bpp == 8)
|
||||
if(nf.opp == 1)
|
||||
{
|
||||
if(!(palette = (MDFN_PaletteEntry*) calloc(sizeof(MDFN_PaletteEntry), 256)))
|
||||
{
|
||||
|
@ -167,9 +136,9 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
|
|||
}
|
||||
}
|
||||
|
||||
if(nf.bpp == 16)
|
||||
if(nf.opp == 2)
|
||||
pixels16 = (uint16 *)rpix;
|
||||
else if(nf.bpp == 8)
|
||||
else if(nf.opp == 1)
|
||||
pixels8 = (uint8 *)rpix;
|
||||
else
|
||||
pixels = (uint32 *)rpix;
|
||||
|
@ -180,224 +149,135 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
|
|||
pitchinpix = p_pitchinpix;
|
||||
}
|
||||
|
||||
const uint8 MDFN_PixelFormat::LUT5to8[32] =
|
||||
{
|
||||
0x00, 0x08, 0x10, 0x18, 0x20, 0x29, 0x31, 0x39, 0x41, 0x4a, 0x52, 0x5a, 0x62, 0x6a, 0x73, 0x7b,
|
||||
0x83, 0x8b, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xde, 0xe6, 0xee, 0xf6, 0xff
|
||||
};
|
||||
|
||||
const uint8 MDFN_PixelFormat::LUT6to8[64] =
|
||||
{
|
||||
0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,
|
||||
0x40, 0x44, 0x48, 0x4c, 0x50, 0x55, 0x59, 0x5d, 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
|
||||
0x81, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x99, 0x9d, 0xa1, 0xa5, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
|
||||
0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6, 0xda, 0xde, 0xe2, 0xe6, 0xea, 0xee, 0xf2, 0xf6, 0xfa, 0xff
|
||||
};
|
||||
|
||||
const uint8 MDFN_PixelFormat::LUT8to5[256] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a,
|
||||
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
|
||||
0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
|
||||
0x15, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
||||
0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
|
||||
0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f
|
||||
};
|
||||
|
||||
const uint8 MDFN_PixelFormat::LUT8to6[256] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04,
|
||||
0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08,
|
||||
0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x10,
|
||||
0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14,
|
||||
0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
|
||||
0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b,
|
||||
0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
|
||||
0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
|
||||
0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b,
|
||||
0x2b, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f,
|
||||
0x2f, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33,
|
||||
0x33, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37,
|
||||
0x37, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b,
|
||||
0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f
|
||||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
if(format.bpp != 32 || nf.bpp != 32)
|
||||
printf("%u->%u\n",format.bpp, nf.bpp);
|
||||
if(format == nf)
|
||||
return;
|
||||
//
|
||||
void* old_pixels = nullptr;
|
||||
void* new_pixels = nullptr;
|
||||
void* new_palette = nullptr;
|
||||
|
||||
assert(format.bpp == 8 || format.bpp == 16 || format.bpp == 32);
|
||||
assert((nf.bpp == 8 && !convert) || nf.bpp == 16 || nf.bpp == 32);
|
||||
|
||||
if(nf.bpp == 8)
|
||||
switch(format.opp)
|
||||
{
|
||||
|
||||
}
|
||||
else if(nf.bpp == 16)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
assert((nf.Rshift + nf.Gshift + nf.Bshift + nf.Ashift) == 48);
|
||||
assert(!((nf.Rshift | nf.Gshift | nf.Bshift | nf.Ashift) & 0x7));
|
||||
case 1: old_pixels = pix<uint8>(); break;
|
||||
case 2: old_pixels = pix<uint16>(); break;
|
||||
case 4: old_pixels = pix<uint32>(); break;
|
||||
}
|
||||
|
||||
if(nf.bpp != format.bpp)
|
||||
if(nf.opp != format.opp)
|
||||
{
|
||||
void *rpix = calloc(1, pitchinpix * h * (nf.bpp / 8));
|
||||
void *oldpix;
|
||||
new_pixels = calloc(1, pitchinpix * h * nf.opp);
|
||||
|
||||
if(nf.bpp == 8)
|
||||
{
|
||||
assert(!convert);
|
||||
|
||||
pixels8 = (uint8 *)rpix;
|
||||
palette = (MDFN_PaletteEntry*)calloc(sizeof(MDFN_PaletteEntry), 256);
|
||||
}
|
||||
else if(nf.bpp == 16) // 32bpp or 8bpp to 16bpp
|
||||
{
|
||||
pixels16 = (uint16 *)rpix;
|
||||
|
||||
if(convert)
|
||||
{
|
||||
if(format.bpp == 8)
|
||||
{
|
||||
uint16 palconv[256];
|
||||
|
||||
for(unsigned i = 0; i < 256; i++)
|
||||
{
|
||||
uint8 r, g, b;
|
||||
|
||||
format.DecodePColor(palette[i], r, g, b);
|
||||
palconv[i] = nf.MakeColor(r, g, b, 0);
|
||||
}
|
||||
|
||||
puts("8bpp to 16bpp convert");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint8 *srow = &pixels8[y * pitchinpix];
|
||||
uint16 *drow = &pixels16[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
drow[x] = palconv[srow[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("32bpp to 16bpp convert");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint32 *srow = &pixels[y * pitchinpix];
|
||||
uint16 *drow = &pixels16[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
uint32 c = srow[x];
|
||||
int r, g, b, a;
|
||||
|
||||
DecodeColor(c, r, g, b, a);
|
||||
drow[x] = nf.MakeColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 16bpp or 8bpp to 32bpp
|
||||
{
|
||||
pixels = (uint32 *)rpix;
|
||||
|
||||
if(convert)
|
||||
{
|
||||
if(format.bpp == 8)
|
||||
{
|
||||
uint32 palconv[256];
|
||||
|
||||
for(unsigned i = 0; i < 256; i++)
|
||||
{
|
||||
uint8 r, g, b;
|
||||
|
||||
format.DecodePColor(palette[i], r, g, b);
|
||||
palconv[i] = nf.MakeColor(r, g, b, 0);
|
||||
}
|
||||
|
||||
puts("8bpp to 32bpp convert");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint8 *srow = &pixels8[y * pitchinpix];
|
||||
uint32 *drow = &pixels[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
drow[x] = palconv[srow[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("16bpp to 32bpp convert");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint16 *srow = &pixels16[y * pitchinpix];
|
||||
uint32 *drow = &pixels[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
uint32 c = srow[x];
|
||||
int r, g, b, a;
|
||||
|
||||
DecodeColor(c, r, g, b, a);
|
||||
drow[x] = nf.MakeColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(format.bpp)
|
||||
{
|
||||
default:
|
||||
|
||||
case 32: oldpix = pixels;
|
||||
pixels = NULL;
|
||||
break;
|
||||
|
||||
case 16: oldpix = pixels16;
|
||||
pixels16 = NULL;
|
||||
break;
|
||||
|
||||
case 8: oldpix = pixels8;
|
||||
pixels8 = NULL;
|
||||
if(palette)
|
||||
{
|
||||
free(palette);
|
||||
palette = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(oldpix && !pixels_is_external)
|
||||
free(oldpix);
|
||||
|
||||
pixels_is_external = false;
|
||||
|
||||
// We already handled surface conversion above.
|
||||
convert = false;
|
||||
if(nf.opp == 1)
|
||||
new_palette = calloc(sizeof(MDFN_PaletteEntry), 256);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
if(convert)
|
||||
{
|
||||
if(format.bpp == 16)
|
||||
MDFN_PixelFormatConverter fconv(format, nf, (MDFN_PaletteEntry*)(palette ? palette : new_palette));
|
||||
size_t old_pitchinbytes = pitchinpix * format.opp;
|
||||
size_t new_pitchinbytes = pitchinpix * nf.opp;
|
||||
|
||||
if(new_pixels)
|
||||
{
|
||||
// We should assert that surface->pixels is non-NULL even if we don't need to convert the surface, to catch more insidious bugs.
|
||||
assert(pixels16);
|
||||
|
||||
if(memcmp(&format, &nf, sizeof(MDFN_PixelFormat)))
|
||||
{
|
||||
//puts("Converting");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint16 *row = &pixels16[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
uint32 c = row[x];
|
||||
int r, g, b, a;
|
||||
|
||||
DecodeColor(c, r, g, b, a);
|
||||
row[x] = nf.MakeColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int32 y = 0; y < h; y++)
|
||||
fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, (uint8*)new_pixels + y * new_pitchinbytes, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should assert that surface->pixels is non-NULL even if we don't need to convert the surface, to catch more insidious bugs.
|
||||
assert(pixels);
|
||||
|
||||
if(memcmp(&format, &nf, sizeof(MDFN_PixelFormat)))
|
||||
{
|
||||
//puts("Converting");
|
||||
for(int y = 0; y < h; y++)
|
||||
{
|
||||
uint32 *row = &pixels[y * pitchinpix];
|
||||
|
||||
for(int x = 0; x < w; x++)
|
||||
{
|
||||
uint32 c = row[x];
|
||||
int r, g, b, a;
|
||||
|
||||
DecodeColor(c, r, g, b, a);
|
||||
row[x] = nf.MakeColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int32 y = 0; y < h; y++)
|
||||
fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, w);
|
||||
}
|
||||
}
|
||||
//
|
||||
//
|
||||
if(nf.opp != format.opp)
|
||||
{
|
||||
switch(format.opp)
|
||||
{
|
||||
case 1: pixels8 = nullptr; break;
|
||||
case 2: pixels16 = nullptr; break;
|
||||
case 4: pixels = nullptr; break;
|
||||
}
|
||||
|
||||
if(palette)
|
||||
{
|
||||
free(palette);
|
||||
palette = nullptr;
|
||||
}
|
||||
|
||||
if(!pixels_is_external)
|
||||
free(old_pixels);
|
||||
|
||||
pixels_is_external = false;
|
||||
|
||||
switch(nf.opp)
|
||||
{
|
||||
case 1: pixels8 = (uint8*)new_pixels; palette = (MDFN_PaletteEntry*)new_palette; break;
|
||||
case 2: pixels16 = (uint16*)new_pixels; break;
|
||||
case 4: pixels = (uint32*)new_pixels; break;
|
||||
}
|
||||
}
|
||||
|
||||
format = nf;
|
||||
}
|
||||
|
||||
|
@ -405,14 +285,14 @@ void MDFN_Surface::Fill(uint8 r, uint8 g, uint8 b, uint8 a)
|
|||
{
|
||||
uint32 color = MakeColor(r, g, b, a);
|
||||
|
||||
if(format.bpp == 8)
|
||||
if(format.opp == 1)
|
||||
{
|
||||
assert(pixels8);
|
||||
|
||||
for(int32 i = 0; i < pitchinpix * h; i++)
|
||||
pixels8[i] = color;
|
||||
}
|
||||
else if(format.bpp == 16)
|
||||
else if(format.opp == 2)
|
||||
{
|
||||
assert(pixels16);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ struct MDFN_Rect
|
|||
enum
|
||||
{
|
||||
MDFN_COLORSPACE_RGB = 0,
|
||||
MDFN_COLORSPACE_YCbCr = 1,
|
||||
//MDFN_COLORSPACE_LRGB = 1, // Linear RGB, 16-bit per component, TODO in the future?
|
||||
//MDFN_COLORSPACE_YUV = 2, // TODO, maybe.
|
||||
};
|
||||
|
||||
|
@ -18,36 +18,99 @@ struct MDFN_PaletteEntry
|
|||
uint8 r, g, b;
|
||||
};
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
static constexpr INLINE uint64 MDFN_PixelFormat_SetTagT(const uint64 tag)
|
||||
{
|
||||
return (tag & ~0xFF) | (sizeof(T) * 8);
|
||||
}
|
||||
*/
|
||||
|
||||
static constexpr INLINE uint64 MDFN_PixelFormat_MakeTag(const uint8 colorspace,
|
||||
const uint8 opp,
|
||||
const uint8 rs, const uint8 gs, const uint8 bs, const uint8 as,
|
||||
const uint8 rp, const uint8 gp, const uint8 bp, const uint8 ap)
|
||||
{
|
||||
// (8 * 6) = 48
|
||||
return ((uint64)colorspace << 56) | ((uint64)opp << 48) |
|
||||
((uint64)rs << (0 * 6)) | ((uint64)gs << (1 * 6)) | ((uint64)bs << (2 * 6)) | ((uint64)as << (3 * 6)) |
|
||||
((uint64)rp << (4 * 6)) | ((uint64)gp << (5 * 6)) | ((uint64)bp << (6 * 6)) | ((uint64)ap << (7 * 6));
|
||||
}
|
||||
|
||||
class MDFN_PixelFormat
|
||||
{
|
||||
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; // 32 only for now(16 and 8 wip)
|
||||
unsigned int colorspace;
|
||||
|
||||
union
|
||||
//
|
||||
// MDFN_PixelFormat constructors must remain inline for various code to be optimized
|
||||
// properly by the compiler.
|
||||
//
|
||||
INLINE MDFN_PixelFormat(const uint64 tag_) :
|
||||
tag(tag_),
|
||||
colorspace((uint8)(tag_ >> 56)),
|
||||
opp((uint8)(tag_ >> 48)),
|
||||
Rshift((tag_ >> (0 * 6)) & 0x3F),
|
||||
Gshift((tag_ >> (1 * 6)) & 0x3F),
|
||||
Bshift((tag_ >> (2 * 6)) & 0x3F),
|
||||
Ashift((tag_ >> (3 * 6)) & 0x3F),
|
||||
Rprec((tag_ >> (4 * 6)) & 0x3F),
|
||||
Gprec((tag_ >> (5 * 6)) & 0x3F),
|
||||
Bprec((tag_ >> (6 * 6)) & 0x3F),
|
||||
Aprec((tag_ >> (7 * 6)) & 0x3F)
|
||||
{
|
||||
uint8 Rshift; // Bit position of the lowest bit of the red component
|
||||
uint8 Yshift;
|
||||
};
|
||||
//
|
||||
}
|
||||
|
||||
union
|
||||
INLINE MDFN_PixelFormat() :
|
||||
tag(0),
|
||||
colorspace(0),
|
||||
opp(0),
|
||||
Rshift(0), Gshift(0), Bshift(0), Ashift(0),
|
||||
Rprec(0), Gprec(0), Bprec(0), Aprec(0)
|
||||
{
|
||||
uint8 Gshift; // [...] green component
|
||||
uint8 Ushift;
|
||||
uint8 Cbshift;
|
||||
};
|
||||
//
|
||||
}
|
||||
|
||||
union
|
||||
INLINE MDFN_PixelFormat(const unsigned int colorspace_,
|
||||
const uint8 opp_,
|
||||
const uint8 rs, const uint8 gs, const uint8 bs, const uint8 as,
|
||||
const uint8 rp = 8, const uint8 gp = 8, const uint8 bp = 8, const uint8 ap = 8) :
|
||||
tag(MDFN_PixelFormat_MakeTag(colorspace_, opp_, rs, gs, bs, as, rp, gp, bp, ap)),
|
||||
colorspace(colorspace_),
|
||||
opp(opp_),
|
||||
Rshift(rs), Gshift(gs), Bshift(bs), Ashift(as),
|
||||
Rprec(rp), Gprec(gp), Bprec(bp), Aprec(ap)
|
||||
{
|
||||
uint8 Bshift; // [...] blue component
|
||||
uint8 Vshift;
|
||||
uint8 Crshift;
|
||||
};
|
||||
//
|
||||
}
|
||||
|
||||
//constexpr MDFN_PixelFormat(MDFN_PixelFormat&) = default;
|
||||
//constexpr MDFN_PixelFormat(MDFN_PixelFormat&&) = default;
|
||||
//MDFN_PixelFormat& operator=(MDFN_PixelFormat&) = default;
|
||||
|
||||
bool operator==(const uint64& t)
|
||||
{
|
||||
return tag == t;
|
||||
}
|
||||
|
||||
bool operator==(const MDFN_PixelFormat& a)
|
||||
{
|
||||
return tag == a.tag;
|
||||
}
|
||||
|
||||
bool operator!=(const MDFN_PixelFormat& a)
|
||||
{
|
||||
return !(*this == a);
|
||||
}
|
||||
|
||||
uint64 tag;
|
||||
|
||||
uint8 colorspace;
|
||||
uint8 opp; // Bytes per pixel; 1, 2, 4 (1 is WIP)
|
||||
|
||||
uint8 Rshift; // Bit position of the lowest bit of the red component
|
||||
uint8 Gshift; // [...] green component
|
||||
uint8 Bshift; // [...] blue component
|
||||
uint8 Ashift; // [...] alpha component.
|
||||
|
||||
// For 16bpp, WIP
|
||||
|
@ -59,36 +122,19 @@ class MDFN_PixelFormat
|
|||
// 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
|
||||
{
|
||||
if(colorspace == MDFN_COLORSPACE_YCbCr)
|
||||
if(opp == 2)
|
||||
{
|
||||
uint32 y, u, v;
|
||||
uint32 ret;
|
||||
|
||||
y = 16 + ((r * 16842 + g * 33030 + b * 6422) >> 16);
|
||||
u = 128 + ((r * -9699 + g * -19071 + b * 28770) >> 16);
|
||||
v = 128 + ((r * 28770 + g * -24117 + b * -4653) >> 16);
|
||||
ret = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift;
|
||||
ret |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift;
|
||||
ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift;
|
||||
ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift;
|
||||
|
||||
return((y << Yshift) | (u << Ushift) | (v << Vshift) | (a << Ashift));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bpp == 16)
|
||||
{
|
||||
uint32 ret = 0;
|
||||
/*
|
||||
ret |= std::min(((r * ((1 << Rprec) - 1) + 127) / 255), 255) << Rshift;
|
||||
ret |= std::min(((g * ((1 << Gprec) - 1) + 127) / 255), 255) << Gshift;
|
||||
ret |= std::min(((b * ((1 << Bprec) - 1) + 127) / 255), 255) << Bshift;
|
||||
ret |= std::min(((a * ((1 << Aprec) - 1) + 127) / 255), 255) << Ashift;
|
||||
*/
|
||||
ret |= ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift;
|
||||
ret |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift;
|
||||
ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift;
|
||||
ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift;
|
||||
return(ret);
|
||||
}
|
||||
else
|
||||
return((r << Rshift) | (g << Gshift) | (b << Bshift) | (a << Ashift));
|
||||
}
|
||||
return (r << Rshift) | (g << Gshift) | (b << Bshift) | (a << Ashift);
|
||||
}
|
||||
|
||||
INLINE MDFN_PaletteEntry MakePColor(uint8 r, uint8 g, uint8 b) const
|
||||
|
@ -112,70 +158,114 @@ class MDFN_PixelFormat
|
|||
// 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
|
||||
{
|
||||
if(colorspace == MDFN_COLORSPACE_YCbCr)
|
||||
if(opp == 2)
|
||||
{
|
||||
int32 y = (value >> Yshift) & 0xFF;
|
||||
int32 cb = (value >> Cbshift) & 0xFF;
|
||||
int32 cr = (value >> Crshift) & 0xFF;
|
||||
|
||||
int32 r_tmp, g_tmp, b_tmp;
|
||||
|
||||
r_tmp = g_tmp = b_tmp = 76284 * (y - 16);
|
||||
|
||||
r_tmp = r_tmp + 104595 * (cr - 128);
|
||||
g_tmp = g_tmp - 53281 * (cr - 128) - 25690 * (cb - 128);
|
||||
b_tmp = b_tmp + 132186 * (cb - 128);
|
||||
|
||||
r_tmp >>= 16;
|
||||
g_tmp >>= 16;
|
||||
b_tmp >>= 16;
|
||||
|
||||
if(r_tmp < 0) r_tmp = 0;
|
||||
if(r_tmp > 255) r_tmp = 255;
|
||||
|
||||
if(g_tmp < 0) g_tmp = 0;
|
||||
if(g_tmp > 255) g_tmp = 255;
|
||||
|
||||
if(b_tmp < 0) b_tmp = 0;
|
||||
if(b_tmp > 255) b_tmp = 255;
|
||||
|
||||
r = r_tmp;
|
||||
g = g_tmp;
|
||||
b = b_tmp;
|
||||
|
||||
a = (value >> Ashift) & 0xFF;
|
||||
r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1);
|
||||
g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1);
|
||||
b = ((value >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1);
|
||||
a = ((value >> Ashift) & ((1 << Aprec) - 1)) * 255 / ((1 << Aprec) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bpp == 16)
|
||||
{
|
||||
r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1);
|
||||
g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1);
|
||||
b = ((value >> Bshift) & ((1 << Bprec) - 1)) * 255 / ((1 << Bprec) - 1);
|
||||
a = ((value >> Ashift) & ((1 << Aprec) - 1)) * 255 / ((1 << Aprec) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = (value >> Rshift) & 0xFF;
|
||||
g = (value >> Gshift) & 0xFF;
|
||||
b = (value >> Bshift) & 0xFF;
|
||||
a = (value >> Ashift) & 0xFF;
|
||||
}
|
||||
r = (value >> Rshift) & 0xFF;
|
||||
g = (value >> Gshift) & 0xFF;
|
||||
b = (value >> Bshift) & 0xFF;
|
||||
a = (value >> Ashift) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
MDFN_HIDE static const uint8 LUT5to8[32];
|
||||
MDFN_HIDE static const uint8 LUT6to8[64];
|
||||
MDFN_HIDE static const uint8 LUT8to5[256];
|
||||
MDFN_HIDE static const uint8 LUT8to6[256];
|
||||
|
||||
INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
|
||||
{
|
||||
int dummy_a;
|
||||
|
||||
DecodeColor(value, r, g, b, dummy_a);
|
||||
}
|
||||
|
||||
static INLINE void TDecodeColor(uint64 tag, uint32 c, int* r, int* g, int* b)
|
||||
{
|
||||
if(tag == IRGB16_1555)
|
||||
{
|
||||
*r = LUT5to8[(c >> 10) & 0x1F];
|
||||
*g = LUT5to8[(c >> 5) & 0x1F];
|
||||
*b = LUT5to8[(c >> 0) & 0x1F];
|
||||
//*a = 0;
|
||||
}
|
||||
else if(tag == RGB16_565)
|
||||
{
|
||||
*r = LUT5to8[(c >> 11) & 0x1F];
|
||||
*g = LUT6to8[(c >> 5) & 0x3F];
|
||||
*b = LUT5to8[(c >> 0) & 0x1F];
|
||||
//*a = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
MDFN_PixelFormat pf = tag;
|
||||
|
||||
pf.DecodeColor(c, *r, *g, *b);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE uint32 TMakeColor(uint64 tag, uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
if(tag == IRGB16_1555)
|
||||
return (LUT8to5[r] << 10) | (LUT8to5[g] << 5) | (LUT8to5[b] << 0);
|
||||
else if(tag == RGB16_565)
|
||||
return (LUT8to5[r] << 11) | (LUT8to6[g] << 5) | (LUT8to5[b] << 0);
|
||||
else
|
||||
{
|
||||
MDFN_PixelFormat pf = tag;
|
||||
|
||||
return pf.MakeColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
enum : uint64
|
||||
{
|
||||
//
|
||||
// All 24 possible RGB-colorspace xxxx32_8888 formats are supported by core Mednafen and emulation modules,
|
||||
// but the ones not enumerated here will be less performant.
|
||||
//
|
||||
// In regards to emulation modules' video output, the alpha channel is for internal use,
|
||||
// and should be ignored by driver-side/frontend code.
|
||||
//
|
||||
ABGR32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 0, 8, 16, 24, /**/ 8, 8, 8, 8),
|
||||
ARGB32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 16, 8, 0, 24, /**/ 8, 8, 8, 8),
|
||||
RGBA32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 24, 16, 8, 0, /**/ 8, 8, 8, 8),
|
||||
BGRA32_8888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 4, /**/ 8, 16, 24, 0, /**/ 8, 8, 8, 8),
|
||||
//
|
||||
// These two RGB16 formats are the only 16-bit formats fully supported by core Mednafen code,
|
||||
// and most emulation modules(also see MDFNGI::ExtraVideoFormatSupport)
|
||||
//
|
||||
// Alpha shift/precision weirdness for internal emulation module use.
|
||||
//
|
||||
IRGB16_1555 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 10, 5, 0, 16, /**/ 5, 5, 5, 8),
|
||||
RGB16_565 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 11, 5, 0, 16, /**/ 5, 6, 5, 8),
|
||||
//
|
||||
// Following formats are not supported by emulation modules, and only partially supported by core
|
||||
// Mednafen code:
|
||||
//
|
||||
ARGB16_4444 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 2, /**/ 8, 4, 0, 12, /**/ 4, 4, 4, 4),
|
||||
|
||||
//
|
||||
// TODO: Following two hackyish formats are only valid when used as a destination pixel format with
|
||||
// MDFN_PixelFormatConverter
|
||||
//
|
||||
// RGB8X3_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 3, /**/ 0, 1, 2, 0, /**/ 8, 8, 8, 0),
|
||||
// BGR8X3_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 3, /**/ 2, 1, 0, 0, /**/ 8, 8, 8, 0),
|
||||
//
|
||||
// TODO:
|
||||
//RGB8P_888 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 1, /**/ 0, 0, 0, 8, /**/ 8, 8, 8, 0),
|
||||
//RGB8P_666 = MDFN_PixelFormat_MakeTag(MDFN_COLORSPACE_RGB, 1, /**/ 0, 0, 0, 8, /**/ 6, 6, 6, 0),
|
||||
};
|
||||
}; // MDFN_PixelFormat;
|
||||
|
||||
// Supports 32-bit RGBA
|
||||
// 16-bit is WIP
|
||||
// 8-bit is even WIPier.
|
||||
class MDFN_Surface //typedef struct
|
||||
// 8bpp support is incomplete
|
||||
class MDFN_Surface
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
Loading…
Reference in New Issue