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:
CasualPokePlayer 2021-11-02 20:15:54 -07:00 committed by GitHub
parent 9bcedb2dab
commit f5940e12e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 721 additions and 464 deletions

Binary file not shown.

View File

@ -62,6 +62,7 @@
<ClCompile Include="..\psx\timer.cpp" /> <ClCompile Include="..\psx\timer.cpp" />
<ClCompile Include="..\Stream.cpp" /> <ClCompile Include="..\Stream.cpp" />
<ClCompile Include="..\tests.cpp" /> <ClCompile Include="..\tests.cpp" />
<ClCompile Include="..\video\convert.cpp" />
<ClCompile Include="..\video\Deinterlacer.cpp" /> <ClCompile Include="..\video\Deinterlacer.cpp" />
<ClCompile Include="..\video\surface.cpp" /> <ClCompile Include="..\video\surface.cpp" />
</ItemGroup> </ItemGroup>
@ -103,6 +104,7 @@
<ClInclude Include="..\psx\spu.h" /> <ClInclude Include="..\psx\spu.h" />
<ClInclude Include="..\psx\timer.h" /> <ClInclude Include="..\psx\timer.h" />
<ClInclude Include="..\Stream.h" /> <ClInclude Include="..\Stream.h" />
<ClCompile Include="..\video\convert.h" />
<ClInclude Include="..\video\Deinterlacer.h" /> <ClInclude Include="..\video\Deinterlacer.h" />
<ClInclude Include="..\video\surface.h" /> <ClInclude Include="..\video\surface.h" />
</ItemGroup> </ItemGroup>

View File

@ -96,6 +96,9 @@
<ClCompile Include="..\video\Deinterlacer.cpp"> <ClCompile Include="..\video\Deinterlacer.cpp">
<Filter>video</Filter> <Filter>video</Filter>
</ClCompile> </ClCompile>
<ClInclude Include="..\video\convert.cpp">
<Filter>video</Filter>
</ClInclude>
<ClCompile Include="..\emuware\EW_state.cpp"> <ClCompile Include="..\emuware\EW_state.cpp">
<Filter>emuware</Filter> <Filter>emuware</Filter>
</ClCompile> </ClCompile>
@ -216,6 +219,9 @@
<ClInclude Include="..\video\Deinterlacer.h"> <ClInclude Include="..\video\Deinterlacer.h">
<Filter>video</Filter> <Filter>video</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\video\convert.h">
<Filter>video</Filter>
</ClInclude>
<ClInclude Include="..\emuware\EW_state.h"> <ClInclude Include="..\emuware\EW_state.h">
<Filter>emuware</Filter> <Filter>emuware</Filter>
</ClInclude> </ClInclude>

View File

@ -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) 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) 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") 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 Vib Ribbon, with extra audio CD
Mortal Kombat Trilogy, music resumption after pause. Mortal Kombat Trilogy, music resumption after pause.
@ -190,6 +190,9 @@ void PS_CDC::SoftReset(void)
{ {
ClearAudioBuffers(); ClearAudioBuffers();
ReportLastF = 0;
ReportStartupDelay = 0;
// Not sure about initial volume state // Not sure about initial volume state
Pending_DecodeVolume[0][0] = 0x80; Pending_DecodeVolume[0][0] = 0x80;
Pending_DecodeVolume[0][1] = 0x00; Pending_DecodeVolume[0][1] = 0x00;
@ -201,6 +204,10 @@ void PS_CDC::SoftReset(void)
memset(ArgsBuf, 0, sizeof(ArgsBuf)); memset(ArgsBuf, 0, sizeof(ArgsBuf));
ArgsWP = ArgsRP = 0; ArgsWP = ArgsRP = 0;
ArgsReceiveLatch = 0;
memset(ArgsReceiveBuf, 0, sizeof(ArgsReceiveBuf));
ArgsReceiveIn = 0;
memset(ResultsBuffer, 0, sizeof(ResultsBuffer)); memset(ResultsBuffer, 0, sizeof(ResultsBuffer));
ResultsWP = 0; ResultsWP = 0;
ResultsRP = 0; ResultsRP = 0;
@ -265,6 +272,10 @@ void PS_CDC::Power(void)
{ {
SPU->Power(); 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(); SoftReset();
HoldLogicalPos = false; HoldLogicalPos = false;
@ -370,10 +381,6 @@ SYNCFUNC(PS_CDC)
NSS(CommandLoc_Dirty); NSS(CommandLoc_Dirty);
NSS(xa_previous); NSS(xa_previous);
NSS(xa_cur_set);
NSS(xa_cur_file);
NSS(xa_cur_chan);
NSS(ReportLastF); NSS(ReportLastF);
NSS(ReportStartupDelay); NSS(ReportStartupDelay);
@ -677,23 +684,6 @@ bool PS_CDC::XA_Test(const uint8 *sdata)
if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan)) if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan))
return false; 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; return true;
} }
@ -702,10 +692,6 @@ void PS_CDC::ClearAudioBuffers(void)
memset(&AudioBuffer, 0, sizeof(AudioBuffer)); memset(&AudioBuffer, 0, sizeof(AudioBuffer));
memset(xa_previous, 0, sizeof(xa_previous)); 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)); memset(ADPCM_ResampBuf, 0, sizeof(ADPCM_ResampBuf));
ADPCM_ResampCurPhase = 0; ADPCM_ResampCurPhase = 0;
ADPCM_ResampCurPos = 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(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); CurSector = std::max<int32>(-150, CurSector - 9);
} }
else else
@ -1258,6 +1244,9 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
SeekFinished = true; SeekFinished = true;
ReportStartupDelay = 24000000; ReportStartupDelay = 24000000;
if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY)
CurSector = std::max<int32>(-150, CurSector - 9);
PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)); PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
} }
else if(DriveStatus == DS_SEEKING_LOGICAL) else if(DriveStatus == DS_SEEKING_LOGICAL)

View File

@ -242,9 +242,6 @@ class PS_CDC
bool XA_Test(const uint8 *sdata); bool XA_Test(const uint8 *sdata);
void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab); void XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab);
int16 xa_previous[2][2]; int16 xa_previous[2][2];
bool xa_cur_set;
uint8 xa_cur_file;
uint8 xa_cur_chan;
uint8 ReportLastF; uint8 ReportLastF;
int32 ReportStartupDelay; int32 ReportStartupDelay;
@ -263,7 +260,7 @@ class PS_CDC
void PreSeekHack(int32 target); void PreSeekHack(int32 target);
void ReadBase(void); 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_Nop(const int arg_count, const uint8 *args);
int32 Command_Setloc(const int arg_count, const uint8 *args); int32 Command_Setloc(const int arg_count, const uint8 *args);

View File

@ -1478,7 +1478,7 @@ MDFN_FASTCALL pscpu_timestamp_t GPU_Update(const pscpu_timestamp_t sys_timestamp
} }
else 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) if(!InVBlank)

View File

@ -147,25 +147,21 @@ InputDevice_Memcard::~InputDevice_Memcard()
void InputDevice_Memcard::Power(void) void InputDevice_Memcard::Power(void)
{ {
presence_new = true;
memset(rw_buffer, 0, sizeof(rw_buffer));
write_xor = 0;
dtr = 0; dtr = 0;
//buttons[0] = buttons[1] = 0;
command_phase = 0; command_phase = 0;
bitpos = 0; bitpos = 0;
receive_buffer = 0; receive_buffer = 0;
command = 0; command = 0;
addr = 0;
calced_xor = 0;
transmit_buffer = 0; transmit_buffer = 0;
transmit_count = 0; transmit_count = 0;
addr = 0;
presence_new = true;
} }
void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns) void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns)

View File

@ -1399,7 +1399,7 @@ EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k)
//setup gpu output surfaces //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++) for(int i=0;i<2;i++)
{ {
VTBuffer[i] = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, nf); VTBuffer[i] = new MDFN_Surface(NULL, FB_WIDTH, FB_HEIGHT, FB_WIDTH, nf);

View File

@ -178,7 +178,7 @@ void PS_SPU::Power(void)
CWA = 0; CWA = 0;
memset(Regs, 0, sizeof(Regs)); memset(Regs, 0, sizeof(Regs));
memset(AuxRegs, 0, sizeof(AuxRegs));
memset(RDSB, 0, sizeof(RDSB)); memset(RDSB, 0, sizeof(RDSB));
memset(RUSB, 0, sizeof(RUSB)); memset(RUSB, 0, sizeof(RUSB));
RvbResPos = 0; RvbResPos = 0;

View File

@ -219,28 +219,17 @@ void RunReverb(const int32* in, int32* out);
int16 IIR_COEF; int16 IIR_COEF;
int16 FB_ALPHA; int16 FB_ALPHA;
int16 FB_X; int16 FB_X;
uint16 IIR_DEST_A0; uint16 IIR_DEST_A[2];
uint16 IIR_DEST_A1; uint16 ACC_SRC_A[2];
uint16 ACC_SRC_A0; uint16 ACC_SRC_B[2];
uint16 ACC_SRC_A1; uint16 IIR_SRC_A[2];
uint16 ACC_SRC_B0; uint16 IIR_DEST_B[2];
uint16 ACC_SRC_B1; uint16 ACC_SRC_C[2];
uint16 IIR_SRC_A0; uint16 ACC_SRC_D[2];
uint16 IIR_SRC_A1; uint16 IIR_SRC_B[2];
uint16 IIR_DEST_B0; uint16 MIX_DEST_A[2];
uint16 IIR_DEST_B1; uint16 MIX_DEST_B[2];
uint16 ACC_SRC_C0; int16 IN_COEF[2];
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;
}; };
}; };
}; };

View File

@ -31,6 +31,13 @@ static INLINE int16 ReverbSat(int32 samp)
return(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) INLINE uint32 PS_SPU::Get_Reverb_Offset(uint32 in_offset)
{ {
@ -54,6 +61,7 @@ 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) void NO_INLINE PS_SPU::WR_RVB(uint16 raw_offs, int16 sample)
{ {
if(SPUControl & 0x80)
WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample); 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]; int32 downsampled[2];
for(unsigned lr = 0; lr < 2; lr++) 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 // Run algorithm
/// //
if(SPUControl & 0x80) for(unsigned lr = 0; lr < 2; lr++)
{ {
int16 IIR_INPUT_A0, IIR_INPUT_A1, IIR_INPUT_B0, IIR_INPUT_B1; const int16 IIR_INPUT_A = ReverbSat((((RD_RVB(IIR_SRC_A[lr ^ 0]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1);
int16 IIR_A0, IIR_A1, IIR_B0, IIR_B1; const int16 IIR_INPUT_B = ReverbSat((((RD_RVB(IIR_SRC_B[lr ^ 1]) * IIR_COEF) >> 14) + ((downsampled[lr] * IN_COEF[lr]) >> 14)) >> 1);
int16 ACC0, ACC1; const int16 IIR_A = ReverbSat((((IIR_INPUT_A * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A[lr], -1)) >> 14)) >> 1);
int16 FB_A0, FB_A1, FB_B0, FB_B1; const int16 IIR_B = ReverbSat((((IIR_INPUT_B * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B[lr], -1)) >> 14)) >> 1);
IIR_INPUT_A0 = ReverbSat(((RD_RVB(IIR_SRC_A0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15)); WR_RVB(IIR_DEST_A[lr], IIR_A);
IIR_INPUT_A1 = ReverbSat(((RD_RVB(IIR_SRC_A1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15)); WR_RVB(IIR_DEST_B[lr], IIR_B);
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); const int32 ACC = ((RD_RVB(ACC_SRC_A[lr]) * ACC_COEF_A) >> 14) +
IIR_A1 = ReverbSat((((IIR_INPUT_A1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A1, -1)) >> 14)) >> 1); ((RD_RVB(ACC_SRC_B[lr]) * ACC_COEF_B) >> 14) +
IIR_B0 = ReverbSat((((IIR_INPUT_B0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B0, -1)) >> 14)) >> 1); ((RD_RVB(ACC_SRC_C[lr]) * ACC_COEF_C) >> 14) +
IIR_B1 = ReverbSat((((IIR_INPUT_B1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B1, -1)) >> 14)) >> 1); ((RD_RVB(ACC_SRC_D[lr]) * ACC_COEF_D) >> 14);
WR_RVB(IIR_DEST_A0, IIR_A0); const int16 FB_A = RD_RVB(MIX_DEST_A[lr] - FB_SRC_A);
WR_RVB(IIR_DEST_A1, IIR_A1); const int16 FB_B = RD_RVB(MIX_DEST_B[lr] - FB_SRC_B);
WR_RVB(IIR_DEST_B0, IIR_B0); const int16 MDA = ReverbSat((ACC + ((FB_A * ReverbNeg(FB_ALPHA)) >> 14)) >> 1);
WR_RVB(IIR_DEST_B1, IIR_B1); 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));
ACC0 = ReverbSat((((RD_RVB(ACC_SRC_A0) * ACC_COEF_A) >> 14) + WR_RVB(MIX_DEST_A[lr], MDA);
((RD_RVB(ACC_SRC_B0) * ACC_COEF_B) >> 14) + WR_RVB(MIX_DEST_B[lr], MDB);
((RD_RVB(ACC_SRC_C0) * ACC_COEF_C) >> 14) + #if 0
((RD_RVB(ACC_SRC_D0) * ACC_COEF_D) >> 14)) >> 1); {
static uint32 sqcounter;
ACC1 = ReverbSat((((RD_RVB(ACC_SRC_A1) * ACC_COEF_A) >> 14) + RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = ((sqcounter & 0xFF) == 0) ? 0x8000 : 0x0000; //((sqcounter & 0x80) ? 0x7000 : 0x9000);
((RD_RVB(ACC_SRC_B1) * ACC_COEF_B) >> 14) + sqcounter += lr;
((RD_RVB(ACC_SRC_C1) * ACC_COEF_C) >> 14) + }
((RD_RVB(ACC_SRC_D1) * ACC_COEF_D) >> 14)) >> 1); #else
RUSB[lr][(RvbResPos >> 1) | 0x20] = RUSB[lr][RvbResPos >> 1] = IVB; // Output sample
FB_A0 = RD_RVB(MIX_DEST_A0 - FB_SRC_A); #endif
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;
ReverbCur = (ReverbCur + 1) & 0x3FFFF; ReverbCur = (ReverbCur + 1) & 0x3FFFF;
if(!ReverbCur) if(!ReverbCur)
ReverbCur = ReverbWA; ReverbCur = ReverbWA;
for(unsigned lr = 0; lr < 2; lr++) 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 else
{ {
for(unsigned lr = 0; lr < 2; lr++) 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; RvbResPos = (RvbResPos + 1) & 0x3F;
for(unsigned lr = 0; lr < 2; lr++) for(unsigned lr = 0; lr < 2; lr++)
{
#if 0
if(!lr)
printf("%d\n", (-upsampled[lr]) >> 1);
#endif
out[lr] = upsampled[lr]; out[lr] = upsampled[lr];
}
} }

View File

@ -181,17 +181,17 @@ void Deinterlacer::Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32
} }
} }
switch(surface->format.bpp) switch (surface->format.opp)
{ {
case 8: case 1:
InternalProcess<uint8>(surface, DisplayRect, LineWidths, field); InternalProcess<uint8>(surface, DisplayRect, LineWidths, field);
break; break;
case 16: case 2:
InternalProcess<uint16>(surface, DisplayRect, LineWidths, field); InternalProcess<uint16>(surface, DisplayRect, LineWidths, field);
break; break;
case 32: case 4:
InternalProcess<uint32>(surface, DisplayRect, LineWidths, field); InternalProcess<uint32>(surface, DisplayRect, LineWidths, field);
break; break;
} }

View File

@ -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);
}

View File

@ -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

View File

@ -22,38 +22,7 @@
#include <math.h> #include <math.h>
#include "octoshock.h" #include "octoshock.h"
#include "surface.h" #include "surface.h"
#include "convert.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;
}
MDFN_Surface::MDFN_Surface() 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 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; 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; format = nf;
if(nf.bpp == 8) if(nf.opp == 1)
{ {
//assert(!nf.Rshift && !nf.Gshift && !nf.Bshift && !nf.Ashift); //assert(!nf.Rshift && !nf.Gshift && !nf.Bshift && !nf.Ashift);
//assert(!nf.Rprec && !nf.Gprec && !nf.Bprec && !nf.Aprec); //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); 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 else
{ {
if(alloc_init_pixels) if(alloc_init_pixels)
rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8)); rpix = calloc(1, p_pitchinpix * p_height * nf.opp);
else else
rpix = malloc(p_pitchinpix * p_height * (nf.bpp / 8)); rpix = malloc(p_pitchinpix * p_height * nf.opp);
if(!rpix) 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))) 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; pixels16 = (uint16 *)rpix;
else if(nf.bpp == 8) else if(nf.opp == 1)
pixels8 = (uint8 *)rpix; pixels8 = (uint8 *)rpix;
else else
pixels = (uint32 *)rpix; pixels = (uint32 *)rpix;
@ -180,224 +149,135 @@ void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32
pitchinpix = p_pitchinpix; 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), // 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 // for places where we store auxillary information there(graphics viewer in the debugger), and it'll be faster
// to boot. // to boot.
void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert) void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert)
{ {
if(format.bpp != 32 || nf.bpp != 32) if(format == nf)
printf("%u->%u\n",format.bpp, nf.bpp); return;
//
void* old_pixels = nullptr;
void* new_pixels = nullptr;
void* new_palette = nullptr;
assert(format.bpp == 8 || format.bpp == 16 || format.bpp == 32); switch(format.opp)
assert((nf.bpp == 8 && !convert) || nf.bpp == 16 || nf.bpp == 32);
if(nf.bpp == 8)
{ {
case 1: old_pixels = pix<uint8>(); break;
} case 2: old_pixels = pix<uint16>(); break;
else if(nf.bpp == 16) case 4: old_pixels = pix<uint32>(); break;
{
}
else
{
assert((nf.Rshift + nf.Gshift + nf.Bshift + nf.Ashift) == 48);
assert(!((nf.Rshift | nf.Gshift | nf.Bshift | nf.Ashift) & 0x7));
} }
if(nf.bpp != format.bpp) if(nf.opp != format.opp)
{ {
void *rpix = calloc(1, pitchinpix * h * (nf.bpp / 8)); new_pixels = calloc(1, pitchinpix * h * nf.opp);
void *oldpix;
if(nf.bpp == 8) if(nf.opp == 1)
{ new_palette = calloc(sizeof(MDFN_PaletteEntry), 256);
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(convert)
{ {
if(format.bpp == 8) MDFN_PixelFormatConverter fconv(format, nf, (MDFN_PaletteEntry*)(palette ? palette : new_palette));
{ size_t old_pitchinbytes = pitchinpix * format.opp;
uint16 palconv[256]; size_t new_pitchinbytes = pitchinpix * nf.opp;
for(unsigned i = 0; i < 256; i++) if(new_pixels)
{ {
uint8 r, g, b; for(int32 y = 0; y < h; y++)
fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, (uint8*)new_pixels + y * new_pitchinbytes, w);
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 else
{ {
puts("32bpp to 16bpp convert"); for(int32 y = 0; y < h; y++)
for(int y = 0; y < h; y++) fconv.Convert((uint8*)old_pixels + y * old_pitchinbytes, w);
}
}
//
//
if(nf.opp != format.opp)
{ {
uint32 *srow = &pixels[y * pitchinpix]; switch(format.opp)
uint16 *drow = &pixels16[y * pitchinpix];
for(int x = 0; x < w; x++)
{ {
uint32 c = srow[x]; case 1: pixels8 = nullptr; break;
int r, g, b, a; case 2: pixels16 = nullptr; break;
case 4: pixels = nullptr; break;
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) if(palette)
{ {
free(palette); free(palette);
palette = NULL; palette = nullptr;
}
break;
} }
if(oldpix && !pixels_is_external) if(!pixels_is_external)
free(oldpix); free(old_pixels);
pixels_is_external = false; pixels_is_external = false;
// We already handled surface conversion above. switch(nf.opp)
convert = false; {
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;
}
} }
if(convert)
{
if(format.bpp == 16)
{
// 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);
}
}
}
}
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);
}
}
}
}
}
format = nf; 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); uint32 color = MakeColor(r, g, b, a);
if(format.bpp == 8) if(format.opp == 1)
{ {
assert(pixels8); assert(pixels8);
for(int32 i = 0; i < pitchinpix * h; i++) for(int32 i = 0; i < pitchinpix * h; i++)
pixels8[i] = color; pixels8[i] = color;
} }
else if(format.bpp == 16) else if(format.opp == 2)
{ {
assert(pixels16); assert(pixels16);

View File

@ -9,7 +9,7 @@ struct MDFN_Rect
enum enum
{ {
MDFN_COLORSPACE_RGB = 0, 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. //MDFN_COLORSPACE_YUV = 2, // TODO, maybe.
}; };
@ -18,36 +18,99 @@ struct MDFN_PaletteEntry
uint8 r, g, b; 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 class MDFN_PixelFormat
{ {
public: 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); // MDFN_PixelFormat constructors must remain inline for various code to be optimized
// properly by the compiler.
unsigned int bpp; // 32 only for now(16 and 8 wip) //
unsigned int colorspace; INLINE MDFN_PixelFormat(const uint64 tag_) :
tag(tag_),
union 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)
{ {
//
}
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)
{
//
}
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)
{
//
}
//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 Rshift; // Bit position of the lowest bit of the red component
uint8 Yshift;
};
union
{
uint8 Gshift; // [...] green component uint8 Gshift; // [...] green component
uint8 Ushift;
uint8 Cbshift;
};
union
{
uint8 Bshift; // [...] blue component uint8 Bshift; // [...] blue component
uint8 Vshift;
uint8 Crshift;
};
uint8 Ashift; // [...] alpha component. uint8 Ashift; // [...] alpha component.
// For 16bpp, WIP // 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. // 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 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); ret = ((r * ((1 << Rprec) - 1) + 127) / 255) << Rshift;
u = 128 + ((r * -9699 + g * -19071 + b * 28770) >> 16);
v = 128 + ((r * 28770 + g * -24117 + b * -4653) >> 16);
return((y << Yshift) | (u << Ushift) | (v << Vshift) | (a << Ashift));
}
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 |= ((g * ((1 << Gprec) - 1) + 127) / 255) << Gshift;
ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift; ret |= ((b * ((1 << Bprec) - 1) + 127) / 255) << Bshift;
ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift; ret |= ((a * ((1 << Aprec) - 1) + 127) / 255) << Ashift;
return(ret);
return ret;
} }
else 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 INLINE MDFN_PaletteEntry MakePColor(uint8 r, uint8 g, uint8 b) const
@ -112,42 +158,7 @@ class MDFN_PixelFormat
// Gets the R/G/B/A values for the passed 32-bit surface pixel value // 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 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;
}
else
{
if(bpp == 16)
{ {
r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1); r = ((value >> Rshift) & ((1 << Rprec) - 1)) * 255 / ((1 << Rprec) - 1);
g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1); g = ((value >> Gshift) & ((1 << Gprec) - 1)) * 255 / ((1 << Gprec) - 1);
@ -162,7 +173,11 @@ class MDFN_PixelFormat
a = (value >> Ashift) & 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 INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const
{ {
@ -170,12 +185,87 @@ class MDFN_PixelFormat
DecodeColor(value, r, g, b, 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; }; // MDFN_PixelFormat;
// Supports 32-bit RGBA // 8bpp support is incomplete
// 16-bit is WIP class MDFN_Surface
// 8-bit is even WIPier.
class MDFN_Surface //typedef struct
{ {
public: public: