mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	Misc: Make struct member functions file-local
This commit is contained in:
		
							parent
							
								
									bee1f986a9
								
							
						
					
					
						commit
						cce7be4723
					
				|  | @ -33,6 +33,7 @@ | |||
| 
 | ||||
| Log_SetChannel(ByteStream); | ||||
| 
 | ||||
| namespace { | ||||
| class FileByteStream : public ByteStream | ||||
| { | ||||
| public: | ||||
|  | @ -174,10 +175,7 @@ public: | |||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   u64 GetPosition() const override | ||||
|   { | ||||
|     return _ftelli64(m_pFile); | ||||
|   } | ||||
|   u64 GetPosition() const override { return _ftelli64(m_pFile); } | ||||
| 
 | ||||
|   u64 GetSize() const override | ||||
|   { | ||||
|  | @ -232,10 +230,7 @@ public: | |||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   u64 GetPosition() const override | ||||
|   { | ||||
|     return static_cast<u64>(ftello(m_pFile)); | ||||
|   } | ||||
|   u64 GetPosition() const override { return static_cast<u64>(ftello(m_pFile)); } | ||||
| 
 | ||||
|   u64 GetSize() const override | ||||
|   { | ||||
|  | @ -262,15 +257,9 @@ public: | |||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   virtual bool Commit() override | ||||
|   { | ||||
|     return true; | ||||
|   } | ||||
|   virtual bool Commit() override { return true; } | ||||
| 
 | ||||
|   virtual bool Discard() override | ||||
|   { | ||||
|     return false; | ||||
|   } | ||||
|   virtual bool Discard() override { return false; } | ||||
| 
 | ||||
| protected: | ||||
|   FILE* m_pFile; | ||||
|  | @ -364,10 +353,15 @@ private: | |||
|   std::string m_originalFileName; | ||||
|   std::string m_temporaryFileName; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| NullByteStream::NullByteStream() {} | ||||
| NullByteStream::NullByteStream() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| NullByteStream::~NullByteStream() {} | ||||
| NullByteStream::~NullByteStream() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| bool NullByteStream::ReadByte(u8* pDestByte) | ||||
| { | ||||
|  | @ -456,7 +450,9 @@ MemoryByteStream::MemoryByteStream(void* pMemory, u32 MemSize) | |||
|   m_pMemory = (u8*)pMemory; | ||||
| } | ||||
| 
 | ||||
| MemoryByteStream::~MemoryByteStream() {} | ||||
| MemoryByteStream::~MemoryByteStream() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| bool MemoryByteStream::ReadByte(u8* pDestByte) | ||||
| { | ||||
|  | @ -586,7 +582,9 @@ ReadOnlyMemoryByteStream::ReadOnlyMemoryByteStream(const void* pMemory, u32 MemS | |||
|   m_pMemory = reinterpret_cast<const u8*>(pMemory); | ||||
| } | ||||
| 
 | ||||
| ReadOnlyMemoryByteStream::~ReadOnlyMemoryByteStream() {} | ||||
| ReadOnlyMemoryByteStream::~ReadOnlyMemoryByteStream() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| bool ReadOnlyMemoryByteStream::ReadByte(u8* pDestByte) | ||||
| { | ||||
|  | @ -1346,6 +1344,7 @@ bool ByteStream::WriteBinaryToStream(ByteStream* stream, const void* data, size_ | |||
|   return stream->Write2(data, static_cast<u32>(data_length)); | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| class ZstdCompressStream final : public ByteStream | ||||
| { | ||||
| public: | ||||
|  | @ -1489,12 +1488,14 @@ private: | |||
|   u8 m_input_buffer[INPUT_BUFFER_SIZE]; | ||||
|   u8 m_output_buffer[OUTPUT_BUFFER_SIZE]; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| std::unique_ptr<ByteStream> ByteStream::CreateZstdCompressStream(ByteStream* src_stream, int compression_level) | ||||
| { | ||||
|   return std::make_unique<ZstdCompressStream>(src_stream, compression_level); | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| class ZstdDecompressStream final : public ByteStream | ||||
| { | ||||
| public: | ||||
|  | @ -1643,6 +1644,7 @@ private: | |||
|   u8 m_input_buffer[INPUT_BUFFER_SIZE]; | ||||
|   u8 m_output_buffer[OUTPUT_BUFFER_SIZE]; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| std::unique_ptr<ByteStream> ByteStream::CreateZstdDecompressStream(ByteStream* src_stream, u32 compressed_size) | ||||
| { | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "thirdparty/StackWalker.h" | ||||
| #include <DbgHelp.h> | ||||
| 
 | ||||
| namespace { | ||||
| class CrashHandlerStackWalker : public StackWalker | ||||
| { | ||||
| public: | ||||
|  | @ -26,6 +27,7 @@ protected: | |||
| private: | ||||
|   HANDLE m_out_file; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| CrashHandlerStackWalker::CrashHandlerStackWalker(HANDLE out_file) | ||||
|   : StackWalker(RetrieveVerbose, nullptr, GetCurrentProcessId(), GetCurrentProcess()), m_out_file(out_file) | ||||
|  | @ -213,12 +215,14 @@ void CrashHandler::Uninstall() | |||
| #include <unistd.h> | ||||
| 
 | ||||
| namespace CrashHandler { | ||||
| namespace { | ||||
| struct BacktraceBuffer | ||||
| { | ||||
|   char* buffer; | ||||
|   size_t used; | ||||
|   size_t size; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static const char* GetSignalName(int signal_no); | ||||
| static void AllocateBuffer(BacktraceBuffer* buf); | ||||
|  |  | |||
|  | @ -32,6 +32,8 @@ | |||
| Log_SetChannel(CDROM); | ||||
| 
 | ||||
| namespace CDROM { | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   RAW_SECTOR_OUTPUT_SIZE = CDImage::RAW_SECTOR_SIZE - CDImage::SECTOR_SYNC_SIZE, | ||||
|  | @ -210,6 +212,8 @@ union RequestRegister | |||
|   BitField<u8, bool, 7, 1> BFRD; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| static void SoftReset(TickCount ticks_late); | ||||
| 
 | ||||
| static bool IsDriveIdle(); | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ | |||
| Log_SetChannel(DMA); | ||||
| 
 | ||||
| namespace DMA { | ||||
| namespace { | ||||
| 
 | ||||
| enum class SyncMode : u32 | ||||
| { | ||||
|   Manual = 0, | ||||
|  | @ -40,35 +42,6 @@ enum class SyncMode : u32 | |||
| static constexpr PhysicalMemoryAddress BASE_ADDRESS_MASK = UINT32_C(0x00FFFFFF); | ||||
| // static constexpr PhysicalMemoryAddress ADDRESS_MASK = UINT32_C(0x001FFFFC);
 | ||||
| 
 | ||||
| static u32 GetAddressMask(); | ||||
| static void ClearState(); | ||||
| 
 | ||||
| // is everything enabled for a channel to operate?
 | ||||
| static bool CanTransferChannel(Channel channel, bool ignore_halt); | ||||
| static bool IsTransferHalted(); | ||||
| static void UpdateIRQ(); | ||||
| 
 | ||||
| // returns false if the DMA should now be halted
 | ||||
| static TickCount GetTransferSliceTicks(); | ||||
| static TickCount GetTransferHaltTicks(); | ||||
| static bool TransferChannel(Channel channel); | ||||
| static void HaltTransfer(TickCount duration); | ||||
| static void UnhaltTransfer(void*, TickCount ticks, TickCount ticks_late); | ||||
| 
 | ||||
| // from device -> memory
 | ||||
| static TickCount TransferDeviceToMemory(Channel channel, u32 address, u32 increment, u32 word_count); | ||||
| 
 | ||||
| // from memory -> device
 | ||||
| static TickCount TransferMemoryToDevice(Channel channel, u32 address, u32 increment, u32 word_count); | ||||
| 
 | ||||
| // configuration
 | ||||
| static TickCount s_max_slice_ticks = 1000; | ||||
| static TickCount s_halt_ticks = 100; | ||||
| 
 | ||||
| static std::vector<u32> s_transfer_buffer; | ||||
| static std::unique_ptr<TimingEvent> s_unhalt_event; | ||||
| static TickCount s_halt_ticks_remaining = 0; | ||||
| 
 | ||||
| struct ChannelState | ||||
| { | ||||
|   u32 base_address = 0; | ||||
|  | @ -110,8 +83,6 @@ struct ChannelState | |||
|   bool request = false; | ||||
| }; | ||||
| 
 | ||||
| static std::array<ChannelState, NUM_CHANNELS> s_state; | ||||
| 
 | ||||
| union DPCR | ||||
| { | ||||
|   u32 bits; | ||||
|  | @ -133,15 +104,13 @@ union DPCR | |||
|   BitField<u32, u8, 28, 3> priority_offset; | ||||
|   BitField<u32, bool, 31, 1> unused; | ||||
| 
 | ||||
|   u8 GetPriority(Channel channel) const { return ((bits >> (static_cast<u8>(channel) * 4)) & u32(3)); } | ||||
|   bool GetMasterEnable(Channel channel) const | ||||
|   ALWAYS_INLINE u8 GetPriority(Channel channel) const { return ((bits >> (static_cast<u8>(channel) * 4)) & u32(3)); } | ||||
|   ALWAYS_INLINE bool GetMasterEnable(Channel channel) const | ||||
|   { | ||||
|     return ConvertToBoolUnchecked((bits >> (static_cast<u8>(channel) * 4 + 3)) & u32(1)); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| static DPCR s_DPCR = {}; | ||||
| 
 | ||||
| static constexpr u32 DICR_WRITE_MASK = 0b00000000'11111111'10000000'00111111; | ||||
| static constexpr u32 DICR_RESET_MASK = 0b01111111'00000000'00000000'00000000; | ||||
| union DICR | ||||
|  | @ -166,25 +135,57 @@ union DICR | |||
|   BitField<u32, bool, 30, 1> OTC_irq_flag; | ||||
|   BitField<u32, bool, 31, 1> master_flag; | ||||
| 
 | ||||
|   bool IsIRQEnabled(Channel channel) const | ||||
|   ALWAYS_INLINE bool IsIRQEnabled(Channel channel) const | ||||
|   { | ||||
|     return ConvertToBoolUnchecked((bits >> (static_cast<u8>(channel) + 16)) & u32(1)); | ||||
|   } | ||||
| 
 | ||||
|   bool GetIRQFlag(Channel channel) const | ||||
|   ALWAYS_INLINE bool GetIRQFlag(Channel channel) const | ||||
|   { | ||||
|     return ConvertToBoolUnchecked((bits >> (static_cast<u8>(channel) + 24)) & u32(1)); | ||||
|   } | ||||
| 
 | ||||
|   void SetIRQFlag(Channel channel) { bits |= (u32(1) << (static_cast<u8>(channel) + 24)); } | ||||
|   void ClearIRQFlag(Channel channel) { bits &= ~(u32(1) << (static_cast<u8>(channel) + 24)); } | ||||
|   ALWAYS_INLINE void SetIRQFlag(Channel channel) { bits |= (u32(1) << (static_cast<u8>(channel) + 24)); } | ||||
|   ALWAYS_INLINE void ClearIRQFlag(Channel channel) { bits &= ~(u32(1) << (static_cast<u8>(channel) + 24)); } | ||||
| 
 | ||||
|   void UpdateMasterFlag() | ||||
|   ALWAYS_INLINE void UpdateMasterFlag() | ||||
|   { | ||||
|     master_flag = master_enable && ((((bits >> 16) & u32(0b1111111)) & ((bits >> 24) & u32(0b1111111))) != 0); | ||||
|   } | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static u32 GetAddressMask(); | ||||
| static void ClearState(); | ||||
| 
 | ||||
| // is everything enabled for a channel to operate?
 | ||||
| static bool CanTransferChannel(Channel channel, bool ignore_halt); | ||||
| static bool IsTransferHalted(); | ||||
| static void UpdateIRQ(); | ||||
| 
 | ||||
| // returns false if the DMA should now be halted
 | ||||
| static TickCount GetTransferSliceTicks(); | ||||
| static TickCount GetTransferHaltTicks(); | ||||
| static bool TransferChannel(Channel channel); | ||||
| static void HaltTransfer(TickCount duration); | ||||
| static void UnhaltTransfer(void*, TickCount ticks, TickCount ticks_late); | ||||
| 
 | ||||
| // from device -> memory
 | ||||
| static TickCount TransferDeviceToMemory(Channel channel, u32 address, u32 increment, u32 word_count); | ||||
| 
 | ||||
| // from memory -> device
 | ||||
| static TickCount TransferMemoryToDevice(Channel channel, u32 address, u32 increment, u32 word_count); | ||||
| 
 | ||||
| // configuration
 | ||||
| static TickCount s_max_slice_ticks = 1000; | ||||
| static TickCount s_halt_ticks = 100; | ||||
| 
 | ||||
| static std::vector<u32> s_transfer_buffer; | ||||
| static std::unique_ptr<TimingEvent> s_unhalt_event; | ||||
| static TickCount s_halt_ticks_remaining = 0; | ||||
| 
 | ||||
| static std::array<ChannelState, NUM_CHANNELS> s_state; | ||||
| static DPCR s_DPCR = {}; | ||||
| static DICR s_DICR = {}; | ||||
| }; // namespace DMA
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ static bool ParseJsonEntry(Entry* entry, const rapidjson::Value& value); | |||
| static bool ParseJsonCodes(u32 index, const rapidjson::Value& value); | ||||
| static bool LoadTrackHashes(); | ||||
| 
 | ||||
| std::array<const char*, static_cast<u32>(GameDatabase::Trait::Count)> s_trait_names = {{ | ||||
| static std::array<const char*, static_cast<u32>(GameDatabase::Trait::Count)> s_trait_names = {{ | ||||
|   "ForceInterpreter", | ||||
|   "ForceSoftwareRenderer", | ||||
|   "ForceSoftwareRendererForReadbacks", | ||||
|  |  | |||
|  | @ -36,6 +36,8 @@ Log_SetChannel(GameList); | |||
| #endif | ||||
| 
 | ||||
| namespace GameList { | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   GAME_LIST_CACHE_SIGNATURE = 0x45434C47, | ||||
|  | @ -54,6 +56,8 @@ struct PlayedTimeEntry | |||
|   std::time_t total_played_time; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| using CacheMap = PreferUnorderedStringMap<Entry>; | ||||
| using PlayedTimeMap = PreferUnorderedStringMap<PlayedTimeEntry>; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										137
									
								
								src/core/gte.cpp
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								src/core/gte.cpp
									
									
									
									
									
								
							|  | @ -162,24 +162,67 @@ ALWAYS_INLINE static u32 TruncateRGB(s32 value) | |||
|   return static_cast<u32>(value); | ||||
| } | ||||
| 
 | ||||
| void Initialize() | ||||
| static void SetOTZ(s32 value); | ||||
| static void PushSXY(s32 x, s32 y); | ||||
| static void PushSZ(s32 value); | ||||
| static void PushRGBFromMAC(); | ||||
| static u32 UNRDivide(u32 lhs, u32 rhs); | ||||
| 
 | ||||
| static void MulMatVec(const s16* M_, const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm); | ||||
| static void MulMatVec(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm); | ||||
| static void MulMatVecBuggy(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm); | ||||
| 
 | ||||
| static void InterpolateColor(s64 in_MAC1, s64 in_MAC2, s64 in_MAC3, u8 shift, bool lm); | ||||
| static void RTPS(const s16 V[3], u8 shift, bool lm, bool last); | ||||
| static void NCS(const s16 V[3], u8 shift, bool lm); | ||||
| static void NCCS(const s16 V[3], u8 shift, bool lm); | ||||
| static void NCDS(const s16 V[3], u8 shift, bool lm); | ||||
| static void DPCS(const u8 color[3], u8 shift, bool lm); | ||||
| 
 | ||||
| static void Execute_MVMVA(Instruction inst); | ||||
| static void Execute_SQR(Instruction inst); | ||||
| static void Execute_OP(Instruction inst); | ||||
| static void Execute_RTPS(Instruction inst); | ||||
| static void Execute_RTPT(Instruction inst); | ||||
| static void Execute_NCLIP(Instruction inst); | ||||
| static void Execute_NCLIP_PGXP(Instruction inst); | ||||
| static void Execute_AVSZ3(Instruction inst); | ||||
| static void Execute_AVSZ4(Instruction inst); | ||||
| static void Execute_NCS(Instruction inst); | ||||
| static void Execute_NCT(Instruction inst); | ||||
| static void Execute_NCCS(Instruction inst); | ||||
| static void Execute_NCCT(Instruction inst); | ||||
| static void Execute_NCDS(Instruction inst); | ||||
| static void Execute_NCDT(Instruction inst); | ||||
| static void Execute_CC(Instruction inst); | ||||
| static void Execute_CDP(Instruction inst); | ||||
| static void Execute_DPCS(Instruction inst); | ||||
| static void Execute_DPCT(Instruction inst); | ||||
| static void Execute_DCPL(Instruction inst); | ||||
| static void Execute_INTPL(Instruction inst); | ||||
| static void Execute_GPL(Instruction inst); | ||||
| static void Execute_GPF(Instruction inst); | ||||
| 
 | ||||
| } // namespace GTE
 | ||||
| 
 | ||||
| void GTE::Initialize() | ||||
| { | ||||
|   s_aspect_ratio = DisplayAspectRatio::R4_3; | ||||
|   Reset(); | ||||
| } | ||||
| 
 | ||||
| void Reset() | ||||
| void GTE::Reset() | ||||
| { | ||||
|   std::memset(®S, 0, sizeof(REGS)); | ||||
| } | ||||
| 
 | ||||
| bool DoState(StateWrapper& sw) | ||||
| bool GTE::DoState(StateWrapper& sw) | ||||
| { | ||||
|   sw.DoArray(REGS.r32, NUM_DATA_REGS + NUM_CONTROL_REGS); | ||||
|   return !sw.HasError(); | ||||
| } | ||||
| 
 | ||||
| void UpdateAspectRatio() | ||||
| void GTE::UpdateAspectRatio() | ||||
| { | ||||
|   if (!g_settings.gpu_widescreen_hack) | ||||
|   { | ||||
|  | @ -227,7 +270,7 @@ void UpdateAspectRatio() | |||
|   s_custom_aspect_ratio_f = static_cast<float>((4.0 / 3.0) / (static_cast<double>(num) / static_cast<double>(denom))); | ||||
| } | ||||
| 
 | ||||
| u32 ReadRegister(u32 index) | ||||
| u32 GTE::ReadRegister(u32 index) | ||||
| { | ||||
|   DebugAssert(index < countof(REGS.r32)); | ||||
| 
 | ||||
|  | @ -254,7 +297,7 @@ u32 ReadRegister(u32 index) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void WriteRegister(u32 index, u32 value) | ||||
| void GTE::WriteRegister(u32 index, u32 value) | ||||
| { | ||||
| #if 0 | ||||
|   if (index < 32) | ||||
|  | @ -349,12 +392,12 @@ void WriteRegister(u32 index, u32 value) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| u32* GetRegisterPtr(u32 index) | ||||
| u32* GTE::GetRegisterPtr(u32 index) | ||||
| { | ||||
|   return ®S.r32[index]; | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE static void SetOTZ(s32 value) | ||||
| ALWAYS_INLINE void GTE::SetOTZ(s32 value) | ||||
| { | ||||
|   if (value < 0) | ||||
|   { | ||||
|  | @ -370,7 +413,7 @@ ALWAYS_INLINE static void SetOTZ(s32 value) | |||
|   REGS.dr32[7] = static_cast<u32>(value); | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE static void PushSXY(s32 x, s32 y) | ||||
| ALWAYS_INLINE void GTE::PushSXY(s32 x, s32 y) | ||||
| { | ||||
|   if (x < -1024) | ||||
|   { | ||||
|  | @ -399,7 +442,7 @@ ALWAYS_INLINE static void PushSXY(s32 x, s32 y) | |||
|   REGS.dr32[14] = (static_cast<u32>(x) & 0xFFFFu) | (static_cast<u32>(y) << 16); | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE static void PushSZ(s32 value) | ||||
| ALWAYS_INLINE void GTE::PushSZ(s32 value) | ||||
| { | ||||
|   if (value < 0) | ||||
|   { | ||||
|  | @ -418,7 +461,7 @@ ALWAYS_INLINE static void PushSZ(s32 value) | |||
|   REGS.dr32[19] = static_cast<u32>(value); // SZ3 <- value
 | ||||
| } | ||||
| 
 | ||||
| static void PushRGBFromMAC() | ||||
| ALWAYS_INLINE void GTE::PushRGBFromMAC() | ||||
| { | ||||
|   // Note: SHR 4 used instead of /16 as the results are different.
 | ||||
|   const u32 r = TruncateRGB<0>(static_cast<u32>(REGS.MAC1 >> 4)); | ||||
|  | @ -431,7 +474,7 @@ static void PushRGBFromMAC() | |||
|   REGS.dr32[22] = r | (g << 8) | (b << 16) | (c << 24); // RGB2 <- Value
 | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE static u32 UNRDivide(u32 lhs, u32 rhs) | ||||
| ALWAYS_INLINE u32 GTE::UNRDivide(u32 lhs, u32 rhs) | ||||
| { | ||||
|   if (rhs * 2 <= lhs) | ||||
|   { | ||||
|  | @ -475,7 +518,7 @@ ALWAYS_INLINE static u32 UNRDivide(u32 lhs, u32 rhs) | |||
|   return std::min<u32>(0x1FFFF, result); | ||||
| } | ||||
| 
 | ||||
| static void MulMatVec(const s16* M_, const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| void GTE::MulMatVec(const s16* M_, const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| { | ||||
| #define M(i, j) M_[((i)*3) + (j)] | ||||
| #define dot3(i)                                                                                                        \ | ||||
|  | @ -491,7 +534,7 @@ static void MulMatVec(const s16* M_, const s16 Vx, const s16 Vy, const s16 Vz, u | |||
| #undef M | ||||
| } | ||||
| 
 | ||||
| static void MulMatVec(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| void GTE::MulMatVec(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| { | ||||
| #define M(i, j) M_[((i)*3) + (j)] | ||||
| #define dot3(i)                                                                                                        \ | ||||
|  | @ -509,7 +552,7 @@ static void MulMatVec(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, | |||
| #undef M | ||||
| } | ||||
| 
 | ||||
| static void MulMatVecBuggy(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| void GTE::MulMatVecBuggy(const s16* M_, const s32 T[3], const s16 Vx, const s16 Vy, const s16 Vz, u8 shift, bool lm) | ||||
| { | ||||
| #define M(i, j) M_[((i)*3) + (j)] | ||||
| #define dot3(i)                                                                                                        \ | ||||
|  | @ -531,7 +574,7 @@ static void MulMatVecBuggy(const s16* M_, const s32 T[3], const s16 Vx, const s1 | |||
| #undef M | ||||
| } | ||||
| 
 | ||||
| static void Execute_MVMVA(Instruction inst) | ||||
| void GTE::Execute_MVMVA(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -576,7 +619,7 @@ static void Execute_MVMVA(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_SQR(Instruction inst) | ||||
| void GTE::Execute_SQR(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -594,7 +637,7 @@ static void Execute_SQR(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_OP(Instruction inst) | ||||
| void GTE::Execute_OP(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -617,7 +660,7 @@ static void Execute_OP(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void RTPS(const s16 V[3], u8 shift, bool lm, bool last) | ||||
| void GTE::RTPS(const s16 V[3], u8 shift, bool lm, bool last) | ||||
| { | ||||
| #define dot3(i)                                                                                                        \ | ||||
|   SignExtendMACResult<i + 1>(SignExtendMACResult<i + 1>((s64(REGS.TR[i]) << 12) + (s64(REGS.RT[i][0]) * s64(V[0]))) +  \ | ||||
|  | @ -763,14 +806,14 @@ static void RTPS(const s16 V[3], u8 shift, bool lm, bool last) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static void Execute_RTPS(Instruction inst) | ||||
| void GTE::Execute_RTPS(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
|   RTPS(REGS.V0, inst.GetShift(), inst.lm, true); | ||||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_RTPT(Instruction inst) | ||||
| void GTE::Execute_RTPT(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -784,7 +827,7 @@ static void Execute_RTPT(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCLIP(Instruction inst) | ||||
| void GTE::Execute_NCLIP(Instruction inst) | ||||
| { | ||||
|   // MAC0 =   SX0*SY1 + SX1*SY2 + SX2*SY0 - SX0*SY2 - SX1*SY0 - SX2*SY1
 | ||||
|   REGS.FLAG.Clear(); | ||||
|  | @ -797,7 +840,7 @@ static void Execute_NCLIP(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCLIP_PGXP(Instruction inst) | ||||
| void GTE::Execute_NCLIP_PGXP(Instruction inst) | ||||
| { | ||||
|   if (PGXP::GTE_NCLIP_valid(REGS.dr32[12], REGS.dr32[13], REGS.dr32[14])) | ||||
|   { | ||||
|  | @ -810,7 +853,7 @@ static void Execute_NCLIP_PGXP(Instruction inst) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static void Execute_AVSZ3(Instruction inst) | ||||
| void GTE::Execute_AVSZ3(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -821,7 +864,7 @@ static void Execute_AVSZ3(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_AVSZ4(Instruction inst) | ||||
| void GTE::Execute_AVSZ4(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -832,7 +875,7 @@ static void Execute_AVSZ4(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static ALWAYS_INLINE void InterpolateColor(s64 in_MAC1, s64 in_MAC2, s64 in_MAC3, u8 shift, bool lm) | ||||
| ALWAYS_INLINE void GTE::InterpolateColor(s64 in_MAC1, s64 in_MAC2, s64 in_MAC3, u8 shift, bool lm) | ||||
| { | ||||
|   // [MAC1,MAC2,MAC3] = MAC+(FC-MAC)*IR0
 | ||||
|   //   [IR1,IR2,IR3] = (([RFC,GFC,BFC] SHL 12) - [MAC1,MAC2,MAC3]) SAR (sf*12)
 | ||||
|  | @ -847,7 +890,7 @@ static ALWAYS_INLINE void InterpolateColor(s64 in_MAC1, s64 in_MAC2, s64 in_MAC3 | |||
|   TruncateAndSetMACAndIR<3>(s64(s32(REGS.IR3) * s32(REGS.IR0)) + in_MAC3, shift, lm); | ||||
| } | ||||
| 
 | ||||
| static void NCS(const s16 V[3], u8 shift, bool lm) | ||||
| void GTE::NCS(const s16 V[3], u8 shift, bool lm) | ||||
| { | ||||
|   // [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] = (LLM*V0) SAR (sf*12)
 | ||||
|   MulMatVec(®S.LLM[0][0], V[0], V[1], V[2], shift, lm); | ||||
|  | @ -859,7 +902,7 @@ static void NCS(const s16 V[3], u8 shift, bool lm) | |||
|   PushRGBFromMAC(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCS(Instruction inst) | ||||
| void GTE::Execute_NCS(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -868,7 +911,7 @@ static void Execute_NCS(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCT(Instruction inst) | ||||
| void GTE::Execute_NCT(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -882,7 +925,7 @@ static void Execute_NCT(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void NCCS(const s16 V[3], u8 shift, bool lm) | ||||
| void GTE::NCCS(const s16 V[3], u8 shift, bool lm) | ||||
| { | ||||
|   // [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] = (LLM*V0) SAR (sf*12)
 | ||||
|   MulMatVec(®S.LLM[0][0], V[0], V[1], V[2], shift, lm); | ||||
|  | @ -900,7 +943,7 @@ static void NCCS(const s16 V[3], u8 shift, bool lm) | |||
|   PushRGBFromMAC(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCCS(Instruction inst) | ||||
| void GTE::Execute_NCCS(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -909,7 +952,7 @@ static void Execute_NCCS(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCCT(Instruction inst) | ||||
| void GTE::Execute_NCCT(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -923,7 +966,7 @@ static void Execute_NCCT(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void NCDS(const s16 V[3], u8 shift, bool lm) | ||||
| void GTE::NCDS(const s16 V[3], u8 shift, bool lm) | ||||
| { | ||||
|   // [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] = (LLM*V0) SAR (sf*12)
 | ||||
|   MulMatVec(®S.LLM[0][0], V[0], V[1], V[2], shift, lm); | ||||
|  | @ -944,7 +987,7 @@ static void NCDS(const s16 V[3], u8 shift, bool lm) | |||
|   PushRGBFromMAC(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCDS(Instruction inst) | ||||
| void GTE::Execute_NCDS(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -953,7 +996,7 @@ static void Execute_NCDS(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_NCDT(Instruction inst) | ||||
| void GTE::Execute_NCDT(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -967,7 +1010,7 @@ static void Execute_NCDT(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_CC(Instruction inst) | ||||
| void GTE::Execute_CC(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -989,7 +1032,7 @@ static void Execute_CC(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_CDP(Instruction inst) | ||||
| void GTE::Execute_CDP(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1015,7 +1058,7 @@ static void Execute_CDP(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void DPCS(const u8 color[3], u8 shift, bool lm) | ||||
| void GTE::DPCS(const u8 color[3], u8 shift, bool lm) | ||||
| { | ||||
|   // In: [IR1,IR2,IR3]=Vector, FC=Far Color, IR0=Interpolation value, CODE=MSB of RGBC
 | ||||
|   // [MAC1,MAC2,MAC3] = [R,G,B] SHL 16                     ;<--- for DPCS/DPCT
 | ||||
|  | @ -1030,7 +1073,7 @@ static void DPCS(const u8 color[3], u8 shift, bool lm) | |||
|   PushRGBFromMAC(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_DPCS(Instruction inst) | ||||
| void GTE::Execute_DPCS(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1039,7 +1082,7 @@ static void Execute_DPCS(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_DPCT(Instruction inst) | ||||
| void GTE::Execute_DPCT(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1052,7 +1095,7 @@ static void Execute_DPCT(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_DCPL(Instruction inst) | ||||
| void GTE::Execute_DCPL(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1074,7 +1117,7 @@ static void Execute_DCPL(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_INTPL(Instruction inst) | ||||
| void GTE::Execute_INTPL(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1092,7 +1135,7 @@ static void Execute_INTPL(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_GPL(Instruction inst) | ||||
| void GTE::Execute_GPL(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1111,7 +1154,7 @@ static void Execute_GPL(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| static void Execute_GPF(Instruction inst) | ||||
| void GTE::Execute_GPF(Instruction inst) | ||||
| { | ||||
|   REGS.FLAG.Clear(); | ||||
| 
 | ||||
|  | @ -1130,7 +1173,7 @@ static void Execute_GPF(Instruction inst) | |||
|   REGS.FLAG.UpdateError(); | ||||
| } | ||||
| 
 | ||||
| void ExecuteInstruction(u32 inst_bits) | ||||
| void GTE::ExecuteInstruction(u32 inst_bits) | ||||
| { | ||||
|   const Instruction inst{inst_bits}; | ||||
|   switch (inst.command) | ||||
|  | @ -1256,7 +1299,7 @@ void ExecuteInstruction(u32 inst_bits) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| InstructionImpl GetInstructionImpl(u32 inst_bits, TickCount* ticks) | ||||
| GTE::InstructionImpl GTE::GetInstructionImpl(u32 inst_bits, TickCount* ticks) | ||||
| { | ||||
|   const Instruction inst{inst_bits}; | ||||
|   switch (inst.command) | ||||
|  | @ -1358,5 +1401,3 @@ InstructionImpl GetInstructionImpl(u32 inst_bits, TickCount* ticks) | |||
|       Panic("Missing handler"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| } // namespace GTE
 | ||||
|  |  | |||
|  | @ -23,6 +23,8 @@ | |||
| Log_SetChannel(MDEC); | ||||
| 
 | ||||
| namespace MDEC { | ||||
| namespace { | ||||
| 
 | ||||
| static constexpr u32 DATA_IN_FIFO_SIZE = 1024; | ||||
| static constexpr u32 DATA_OUT_FIFO_SIZE = 768; | ||||
| static constexpr u32 NUM_BLOCKS = 6; | ||||
|  | @ -89,6 +91,8 @@ union CommandWord | |||
|   BitField<u32, u16, 0, 16> parameter_word_count; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| static bool HasPendingBlockCopyOut(); | ||||
| 
 | ||||
| static void SoftReset(); | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "memory_card_image.h" | ||||
| #include "gpu_types.h" | ||||
| #include "system.h" | ||||
| 
 | ||||
| #include "util/shiftjis.h" | ||||
|  | @ -21,6 +22,7 @@ | |||
| Log_SetChannel(MemoryCard); | ||||
| 
 | ||||
| namespace MemoryCardImage { | ||||
| namespace { | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| 
 | ||||
|  | @ -57,6 +59,8 @@ static_assert(sizeof(TitleFrame) == FRAME_SIZE); | |||
| 
 | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| static u8 GetChecksum(const u8* frame) | ||||
| { | ||||
|   u8 checksum = frame[0]; | ||||
|  | @ -82,24 +86,16 @@ const T* GetFramePtr(const DataArray& data, u32 block, u32 frame) | |||
|   return reinterpret_cast<const T*>(&data[(block * BLOCK_SIZE) + (frame * FRAME_SIZE)]); | ||||
| } | ||||
| 
 | ||||
| static constexpr u32 RGBA5551ToRGBA8888(u16 color) | ||||
| { | ||||
|   u8 r = Truncate8(color & 31); | ||||
|   u8 g = Truncate8((color >> 5) & 31); | ||||
|   u8 b = Truncate8((color >> 10) & 31); | ||||
|   u8 a = Truncate8((color >> 15) & 1); | ||||
| static std::optional<u32> GetNextFreeBlock(const DataArray& data); | ||||
| static bool ImportCardMCD(DataArray* data, const char* filename, std::vector<u8> file_data); | ||||
| static bool ImportCardGME(DataArray* data, const char* filename, std::vector<u8> file_data); | ||||
| static bool ImportCardVGS(DataArray* data, const char* filename, std::vector<u8> file_data); | ||||
| static bool ImportCardPSX(DataArray* data, const char* filename, std::vector<u8> file_data); | ||||
| static bool ImportSaveWithDirectoryFrame(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd); | ||||
| static bool ImportRawSave(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd); | ||||
| } // namespace MemoryCardImage
 | ||||
| 
 | ||||
|   // 00012345 -> 1234545
 | ||||
|   b = (b << 3) | (b & 0b111); | ||||
|   g = (g << 3) | (g & 0b111); | ||||
|   r = (r << 3) | (r & 0b111); | ||||
|   // a = a ? 255 : 0;
 | ||||
|   a = (color == 0) ? 0 : 255; | ||||
| 
 | ||||
|   return ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16) | (ZeroExtend32(a) << 24); | ||||
| } | ||||
| 
 | ||||
| bool LoadFromFile(DataArray* data, const char* filename) | ||||
| bool MemoryCardImage::LoadFromFile(DataArray* data, const char* filename) | ||||
| { | ||||
|   FILESYSTEM_STAT_DATA sd; | ||||
|   if (!FileSystem::StatFile(filename, &sd) || sd.Size != DATA_SIZE) | ||||
|  | @ -120,7 +116,7 @@ bool LoadFromFile(DataArray* data, const char* filename) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool SaveToFile(const DataArray& data, const char* filename) | ||||
| bool MemoryCardImage::SaveToFile(const DataArray& data, const char* filename) | ||||
| { | ||||
|   std::unique_ptr<ByteStream> stream = | ||||
|     ByteStream::OpenFile(filename, BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_TRUNCATE | BYTESTREAM_OPEN_WRITE | | ||||
|  | @ -142,14 +138,14 @@ bool SaveToFile(const DataArray& data, const char* filename) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool IsValid(const DataArray& data) | ||||
| bool MemoryCardImage::IsValid(const DataArray& data) | ||||
| { | ||||
|   // TODO: Check checksum?
 | ||||
|   const u8* fptr = GetFramePtr<u8>(data, 0, 0); | ||||
|   return fptr[0] == 'M' && fptr[1] == 'C'; | ||||
| } | ||||
| 
 | ||||
| void Format(DataArray* data) | ||||
| void MemoryCardImage::Format(DataArray* data) | ||||
| { | ||||
|   // fill everything with FF
 | ||||
|   data->fill(u8(0xFF)); | ||||
|  | @ -206,7 +202,7 @@ void Format(DataArray* data) | |||
|   std::memcpy(GetFramePtr<u8>(data, 0, 63), GetFramePtr<u8>(data, 0, 0), FRAME_SIZE); | ||||
| } | ||||
| 
 | ||||
| static std::optional<u32> GetNextFreeBlock(const DataArray& data) | ||||
| std::optional<u32> MemoryCardImage::GetNextFreeBlock(const DataArray& data) | ||||
| { | ||||
|   for (u32 dir_frame = 1; dir_frame < FRAMES_PER_BLOCK; dir_frame++) | ||||
|   { | ||||
|  | @ -218,7 +214,7 @@ static std::optional<u32> GetNextFreeBlock(const DataArray& data) | |||
|   return std::nullopt; | ||||
| } | ||||
| 
 | ||||
| u32 GetFreeBlockCount(const DataArray& data) | ||||
| u32 MemoryCardImage::GetFreeBlockCount(const DataArray& data) | ||||
| { | ||||
|   u32 count = 0; | ||||
|   for (u32 dir_frame = 1; dir_frame < FRAMES_PER_BLOCK; dir_frame++) | ||||
|  | @ -231,7 +227,7 @@ u32 GetFreeBlockCount(const DataArray& data) | |||
|   return count; | ||||
| } | ||||
| 
 | ||||
| std::vector<FileInfo> EnumerateFiles(const DataArray& data, bool include_deleted) | ||||
| std::vector<MemoryCardImage::FileInfo> MemoryCardImage::EnumerateFiles(const DataArray& data, bool include_deleted) | ||||
| { | ||||
|   std::vector<FileInfo> files; | ||||
| 
 | ||||
|  | @ -299,8 +295,8 @@ std::vector<FileInfo> EnumerateFiles(const DataArray& data, bool include_deleted | |||
|       u32* pixels_ptr = fi.icon_frames[icon_frame].pixels; | ||||
|       for (u32 i = 0; i < ICON_WIDTH * ICON_HEIGHT; i += 2) | ||||
|       { | ||||
|         *(pixels_ptr++) = RGBA5551ToRGBA8888(tf->icon_palette[*indices_ptr & 0xF]); | ||||
|         *(pixels_ptr++) = RGBA5551ToRGBA8888(tf->icon_palette[*indices_ptr >> 4]); | ||||
|         *(pixels_ptr++) = VRAMRGBA5551ToRGBA8888(tf->icon_palette[*indices_ptr & 0xF]); | ||||
|         *(pixels_ptr++) = VRAMRGBA5551ToRGBA8888(tf->icon_palette[*indices_ptr >> 4]); | ||||
|         indices_ptr++; | ||||
|       } | ||||
|     } | ||||
|  | @ -311,7 +307,7 @@ std::vector<FileInfo> EnumerateFiles(const DataArray& data, bool include_deleted | |||
|   return files; | ||||
| } | ||||
| 
 | ||||
| bool ReadFile(const DataArray& data, const FileInfo& fi, std::vector<u8>* buffer) | ||||
| bool MemoryCardImage::ReadFile(const DataArray& data, const FileInfo& fi, std::vector<u8>* buffer) | ||||
| { | ||||
|   buffer->resize(fi.num_blocks * BLOCK_SIZE); | ||||
| 
 | ||||
|  | @ -328,7 +324,7 @@ bool ReadFile(const DataArray& data, const FileInfo& fi, std::vector<u8>* buffer | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool WriteFile(DataArray* data, const std::string_view& filename, const std::vector<u8>& buffer) | ||||
| bool MemoryCardImage::WriteFile(DataArray* data, const std::string_view& filename, const std::vector<u8>& buffer) | ||||
| { | ||||
|   if (buffer.empty()) | ||||
|   { | ||||
|  | @ -386,7 +382,7 @@ bool WriteFile(DataArray* data, const std::string_view& filename, const std::vec | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool DeleteFile(DataArray* data, const FileInfo& fi, bool clear_sectors) | ||||
| bool MemoryCardImage::DeleteFile(DataArray* data, const FileInfo& fi, bool clear_sectors) | ||||
| { | ||||
|   Log_InfoFmt("Deleting '{}' from memory card ({} blocks)", fi.filename, fi.num_blocks); | ||||
| 
 | ||||
|  | @ -417,7 +413,7 @@ bool DeleteFile(DataArray* data, const FileInfo& fi, bool clear_sectors) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool UndeleteFile(DataArray* data, const FileInfo& fi) | ||||
| bool MemoryCardImage::UndeleteFile(DataArray* data, const FileInfo& fi) | ||||
| { | ||||
|   if (!fi.deleted) | ||||
|   { | ||||
|  | @ -483,7 +479,7 @@ bool UndeleteFile(DataArray* data, const FileInfo& fi) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ImportCardMCD(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| bool MemoryCardImage::ImportCardMCD(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| { | ||||
|   if (file_data.size() != DATA_SIZE) | ||||
|   { | ||||
|  | @ -495,7 +491,7 @@ static bool ImportCardMCD(DataArray* data, const char* filename, std::vector<u8> | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ImportCardGME(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| bool MemoryCardImage::ImportCardGME(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| { | ||||
| #pragma pack(push, 1) | ||||
|   struct GMEHeader | ||||
|  | @ -522,7 +518,7 @@ static bool ImportCardGME(DataArray* data, const char* filename, std::vector<u8> | |||
|   if (file_data.size() < expected_size) | ||||
|   { | ||||
|     Log_WarningFmt("GME memory card '{}' is too small (got {} expected {}), padding with zeroes", filename, | ||||
|                       file_data.size(), expected_size); | ||||
|                    file_data.size(), expected_size); | ||||
|     file_data.resize(expected_size); | ||||
|   } | ||||
| 
 | ||||
|  | @ -531,7 +527,7 @@ static bool ImportCardGME(DataArray* data, const char* filename, std::vector<u8> | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ImportCardVGS(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| bool MemoryCardImage::ImportCardVGS(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| { | ||||
|   constexpr u32 HEADER_SIZE = 64; | ||||
| 
 | ||||
|  | @ -552,7 +548,7 @@ static bool ImportCardVGS(DataArray* data, const char* filename, std::vector<u8> | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ImportCardPSX(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| bool MemoryCardImage::ImportCardPSX(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| { | ||||
|   constexpr u32 HEADER_SIZE = 256; | ||||
| 
 | ||||
|  | @ -573,7 +569,7 @@ static bool ImportCardPSX(DataArray* data, const char* filename, std::vector<u8> | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool ImportCard(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| bool MemoryCardImage::ImportCard(DataArray* data, const char* filename, std::vector<u8> file_data) | ||||
| { | ||||
|   const char* extension = std::strrchr(filename, '.'); | ||||
|   if (!extension) | ||||
|  | @ -608,7 +604,7 @@ bool ImportCard(DataArray* data, const char* filename, std::vector<u8> file_data | |||
|   } | ||||
| } | ||||
| 
 | ||||
| bool ImportCard(DataArray* data, const char* filename) | ||||
| bool MemoryCardImage::ImportCard(DataArray* data, const char* filename) | ||||
| { | ||||
|   std::optional<std::vector<u8>> file_data = FileSystem::ReadBinaryFile(filename); | ||||
|   if (!file_data.has_value()) | ||||
|  | @ -617,7 +613,7 @@ bool ImportCard(DataArray* data, const char* filename) | |||
|   return ImportCard(data, filename, std::move(file_data.value())); | ||||
| } | ||||
| 
 | ||||
| bool ExportSave(DataArray* data, const FileInfo& fi, const char* filename) | ||||
| bool MemoryCardImage::ExportSave(DataArray* data, const FileInfo& fi, const char* filename) | ||||
| { | ||||
|   std::unique_ptr<ByteStream> stream = | ||||
|     ByteStream::OpenFile(filename, BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_TRUNCATE | BYTESTREAM_OPEN_WRITE | | ||||
|  | @ -650,7 +646,8 @@ bool ExportSave(DataArray* data, const FileInfo& fi, const char* filename) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ImportSaveWithDirectoryFrame(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd) | ||||
| bool MemoryCardImage::ImportSaveWithDirectoryFrame(DataArray* data, const char* filename, | ||||
|                                                    const FILESYSTEM_STAT_DATA& sd) | ||||
| { | ||||
|   // Make sure the size of the actual file is valid
 | ||||
|   if (sd.Size <= FRAME_SIZE || (sd.Size - FRAME_SIZE) % BLOCK_SIZE != 0u || (sd.Size - FRAME_SIZE) / BLOCK_SIZE > 15u) | ||||
|  | @ -713,7 +710,7 @@ static bool ImportSaveWithDirectoryFrame(DataArray* data, const char* filename, | |||
|   return WriteFile(data, df.filename, blocks); | ||||
| } | ||||
| 
 | ||||
| static bool ImportRawSave(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd) | ||||
| bool MemoryCardImage::ImportRawSave(DataArray* data, const char* filename, const FILESYSTEM_STAT_DATA& sd) | ||||
| { | ||||
|   const std::string display_name(FileSystem::GetDisplayNameFromPath(filename)); | ||||
|   std::string save_name(Path::GetFileTitle(filename)); | ||||
|  | @ -759,7 +756,7 @@ static bool ImportRawSave(DataArray* data, const char* filename, const FILESYSTE | |||
|   return WriteFile(data, save_name, blocks.value()); | ||||
| } | ||||
| 
 | ||||
| bool ImportSave(DataArray* data, const char* filename) | ||||
| bool MemoryCardImage::ImportSave(DataArray* data, const char* filename) | ||||
| { | ||||
|   FILESYSTEM_STAT_DATA sd; | ||||
|   if (!FileSystem::StatFile(filename, &sd)) | ||||
|  | @ -789,5 +786,3 @@ bool ImportSave(DataArray* data, const char* filename) | |||
|     return false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| } // namespace MemoryCardImage
 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| Log_SetChannel(PGXP); | ||||
| 
 | ||||
| namespace PGXP { | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|  | @ -71,8 +72,13 @@ typedef union | |||
|   u32 d; | ||||
|   s32 sd; | ||||
| } psx_value; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static void PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex); | ||||
| static PGXP_value* PGXP_GetCachedVertex(short sx, short sy); | ||||
| 
 | ||||
| static float TruncateVertexPosition(float p); | ||||
| static bool IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y); | ||||
| 
 | ||||
| static void MakeValid(PGXP_value* pV, u32 psxV); | ||||
| static void Validate(PGXP_value* pV, u32 psxV); | ||||
|  | @ -85,6 +91,9 @@ static double f16Overflow(double in); | |||
| static PGXP_value* GetPtr(u32 addr); | ||||
| static PGXP_value* ReadMem(u32 addr); | ||||
| 
 | ||||
| static void PGXP_MTC2_int(const PGXP_value& value, u32 reg); | ||||
| static void CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); | ||||
| 
 | ||||
| static const PGXP_value PGXP_value_invalid = {0.f, 0.f, 0.f, {0}, 0}; | ||||
| static const PGXP_value PGXP_value_zero = {0.f, 0.f, 0.f, {VALID_ALL}, 0}; | ||||
| 
 | ||||
|  | @ -254,7 +263,9 @@ ALWAYS_INLINE_RELEASE static void WriteMem16(const PGXP_value* src, u32 addr) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void Initialize() | ||||
| } // namespace PGXP
 | ||||
| 
 | ||||
| void PGXP::Initialize() | ||||
| { | ||||
|   std::memset(CPU_reg, 0, sizeof(CPU_reg)); | ||||
|   std::memset(CP0_reg, 0, sizeof(CP0_reg)); | ||||
|  | @ -285,7 +296,7 @@ void Initialize() | |||
|     std::memset(vertexCache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE); | ||||
| } | ||||
| 
 | ||||
| void Reset() | ||||
| void PGXP::Reset() | ||||
| { | ||||
|   std::memset(CPU_reg, 0, sizeof(CPU_reg)); | ||||
|   std::memset(CP0_reg, 0, sizeof(CP0_reg)); | ||||
|  | @ -299,7 +310,7 @@ void Reset() | |||
|     std::memset(vertexCache, 0, sizeof(PGXP_value) * VERTEX_CACHE_SIZE); | ||||
| } | ||||
| 
 | ||||
| void Shutdown() | ||||
| void PGXP::Shutdown() | ||||
| { | ||||
|   if (vertexCache) | ||||
|   { | ||||
|  | @ -340,7 +351,7 @@ void Shutdown() | |||
| #define SXY2 (GTE_regs[14]) | ||||
| #define SXYP (GTE_regs[15]) | ||||
| 
 | ||||
| void GTE_PushSXYZ2f(float x, float y, float z, u32 v) | ||||
| void PGXP::GTE_PushSXYZ2f(float x, float y, float z, u32 v) | ||||
| { | ||||
|   // push values down FIFO
 | ||||
|   SXY0 = SXY1; | ||||
|  | @ -360,7 +371,7 @@ void GTE_PushSXYZ2f(float x, float y, float z, u32 v) | |||
| #define VY(n) (psxRegs.CP2D.p[n << 1].sw.h) | ||||
| #define VZ(n) (psxRegs.CP2D.p[(n << 1) + 1].sw.l) | ||||
| 
 | ||||
| int GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2) | ||||
| int PGXP::GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2) | ||||
| { | ||||
|   Validate(&SXY0, sxy0); | ||||
|   Validate(&SXY1, sxy1); | ||||
|  | @ -370,7 +381,7 @@ int GTE_NCLIP_valid(u32 sxy0, u32 sxy1, u32 sxy2) | |||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| float GTE_NCLIP() | ||||
| float PGXP::GTE_NCLIP() | ||||
| { | ||||
|   float nclip = ((SX0 * SY1) + (SX1 * SY2) + (SX2 * SY0) - (SX0 * SY2) - (SX1 * SY0) - (SX2 * SY1)); | ||||
| 
 | ||||
|  | @ -395,7 +406,7 @@ float GTE_NCLIP() | |||
|   return nclip; | ||||
| } | ||||
| 
 | ||||
| static void PGXP_MTC2_int(PGXP_value value, u32 reg) | ||||
| ALWAYS_INLINE_RELEASE void PGXP::PGXP_MTC2_int(const PGXP_value& value, u32 reg) | ||||
| { | ||||
|   switch (reg) | ||||
|   { | ||||
|  | @ -418,7 +429,7 @@ static void PGXP_MTC2_int(PGXP_value value, u32 reg) | |||
| // Data transfer tracking
 | ||||
| ////////////////////////////////////
 | ||||
| 
 | ||||
| void CPU_MFC2(u32 instr, u32 rdVal) | ||||
| void PGXP::CPU_MFC2(u32 instr, u32 rdVal) | ||||
| { | ||||
|   // CPU[Rt] = GTE_D[Rd]
 | ||||
|   const u32 idx = cop2idx(instr); | ||||
|  | @ -427,7 +438,7 @@ void CPU_MFC2(u32 instr, u32 rdVal) | |||
|   CPU_reg[rt(instr)].value = rdVal; | ||||
| } | ||||
| 
 | ||||
| void CPU_MTC2(u32 instr, u32 rtVal) | ||||
| void PGXP::CPU_MTC2(u32 instr, u32 rtVal) | ||||
| { | ||||
|   // GTE_D[Rd] = CPU[Rt]
 | ||||
|   const u32 idx = cop2idx(instr); | ||||
|  | @ -439,7 +450,7 @@ void CPU_MTC2(u32 instr, u32 rtVal) | |||
| ////////////////////////////////////
 | ||||
| // Memory Access
 | ||||
| ////////////////////////////////////
 | ||||
| void CPU_LWC2(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_LWC2(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   // GTE_D[Rt] = Mem[addr]
 | ||||
|   PGXP_value val; | ||||
|  | @ -447,14 +458,14 @@ void CPU_LWC2(u32 instr, u32 addr, u32 rtVal) | |||
|   PGXP_MTC2_int(val, rt(instr)); | ||||
| } | ||||
| 
 | ||||
| void CPU_SWC2(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_SWC2(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   //  Mem[addr] = GTE_D[Rt]
 | ||||
|   Validate(>E_regs[rt(instr)], rtVal); | ||||
|   WriteMem(>E_regs[rt(instr)], addr); | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE_RELEASE void PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex) | ||||
| ALWAYS_INLINE_RELEASE void PGXP::PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& vertex) | ||||
| { | ||||
|   if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff) | ||||
|   { | ||||
|  | @ -463,7 +474,7 @@ ALWAYS_INLINE_RELEASE void PGXP_CacheVertex(s16 sx, s16 sy, const PGXP_value& ve | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static ALWAYS_INLINE_RELEASE PGXP_value* PGXP_GetCachedVertex(short sx, short sy) | ||||
| ALWAYS_INLINE_RELEASE PGXP::PGXP_value* PGXP::PGXP_GetCachedVertex(short sx, short sy) | ||||
| { | ||||
|   if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff) | ||||
|   { | ||||
|  | @ -474,14 +485,14 @@ static ALWAYS_INLINE_RELEASE PGXP_value* PGXP_GetCachedVertex(short sx, short sy | |||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| static ALWAYS_INLINE_RELEASE float TruncateVertexPosition(float p) | ||||
| ALWAYS_INLINE_RELEASE float PGXP::TruncateVertexPosition(float p) | ||||
| { | ||||
|   const s32 int_part = static_cast<s32>(p); | ||||
|   const float int_part_f = static_cast<float>(int_part); | ||||
|   return static_cast<float>(static_cast<s16>(int_part << 5) >> 5) + (p - int_part_f); | ||||
| } | ||||
| 
 | ||||
| static ALWAYS_INLINE_RELEASE bool IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y) | ||||
| ALWAYS_INLINE_RELEASE bool PGXP::IsWithinTolerance(float precise_x, float precise_y, int int_x, int int_y) | ||||
| { | ||||
|   const float tolerance = g_settings.gpu_pgxp_tolerance; | ||||
|   if (tolerance < 0.0f) | ||||
|  | @ -491,7 +502,8 @@ static ALWAYS_INLINE_RELEASE bool IsWithinTolerance(float precise_x, float preci | |||
|           std::abs(precise_y - static_cast<float>(int_y)) <= tolerance); | ||||
| } | ||||
| 
 | ||||
| bool GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, float* out_x, float* out_y, float* out_w) | ||||
| bool PGXP::GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, float* out_x, float* out_y, | ||||
|                             float* out_w) | ||||
| { | ||||
|   const PGXP_value* vert = ReadMem(addr); | ||||
|   if (vert && ((vert->flags & VALID_01) == VALID_01) && (vert->value == value)) | ||||
|  | @ -544,35 +556,35 @@ bool GetPreciseVertex(u32 addr, u32 value, int x, int y, int xOffs, int yOffs, f | |||
| #define imm_sext(_instr)                                                                                               \ | ||||
|   static_cast<s32>(static_cast<s16>(_instr & 0xFFFF)) // The immediate part of the instruction register
 | ||||
| 
 | ||||
| void CPU_LW(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_LW(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   // Rt = Mem[Rs + Im]
 | ||||
|   ValidateAndCopyMem(&CPU_reg[rt(instr)], addr, rtVal); | ||||
| } | ||||
| 
 | ||||
| void CPU_LBx(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_LBx(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   CPU_reg[rt(instr)] = PGXP_value_invalid; | ||||
| } | ||||
| 
 | ||||
| void CPU_LH(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_LH(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   // Rt = Mem[Rs + Im] (sign extended)
 | ||||
|   ValidateAndCopyMem16(&CPU_reg[rt(instr)], addr, rtVal, true); | ||||
| } | ||||
| 
 | ||||
| void CPU_LHU(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_LHU(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   // Rt = Mem[Rs + Im] (zero extended)
 | ||||
|   ValidateAndCopyMem16(&CPU_reg[rt(instr)], addr, rtVal, false); | ||||
| } | ||||
| 
 | ||||
| void CPU_SB(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_SB(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   WriteMem(&PGXP_value_invalid, addr); | ||||
| } | ||||
| 
 | ||||
| void CPU_SH(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_SH(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   PGXP_value* val = &CPU_reg[rt(instr)]; | ||||
| 
 | ||||
|  | @ -581,7 +593,7 @@ void CPU_SH(u32 instr, u32 addr, u32 rtVal) | |||
|   WriteMem16(val, addr); | ||||
| } | ||||
| 
 | ||||
| void CPU_SW(u32 instr, u32 addr, u32 rtVal) | ||||
| void PGXP::CPU_SW(u32 instr, u32 addr, u32 rtVal) | ||||
| { | ||||
|   // Mem[Rs + Im] = Rt
 | ||||
|   PGXP_value* val = &CPU_reg[rt(instr)]; | ||||
|  | @ -589,14 +601,14 @@ void CPU_SW(u32 instr, u32 addr, u32 rtVal) | |||
|   WriteMem(val, addr); | ||||
| } | ||||
| 
 | ||||
| void CPU_MOVE(u32 rd_and_rs, u32 rsVal) | ||||
| void PGXP::CPU_MOVE(u32 rd_and_rs, u32 rsVal) | ||||
| { | ||||
|   const u32 Rs = (rd_and_rs & 0xFFu); | ||||
|   Validate(&CPU_reg[Rs], rsVal); | ||||
|   CPU_reg[(rd_and_rs >> 8)] = CPU_reg[Rs]; | ||||
| } | ||||
| 
 | ||||
| void CPU_ADDI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_ADDI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs + Imm (signed)
 | ||||
|   Validate(&CPU_reg[rs(instr)], rsVal); | ||||
|  | @ -624,7 +636,7 @@ void CPU_ADDI(u32 instr, u32 rsVal) | |||
|   CPU_reg[rt(instr)].value = rsVal + imm_sext(instr); | ||||
| } | ||||
| 
 | ||||
| void CPU_ANDI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_ANDI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs & Imm
 | ||||
|   const u32 rtVal = rsVal & imm(instr); | ||||
|  | @ -659,7 +671,7 @@ void CPU_ANDI(u32 instr, u32 rsVal) | |||
|   CPU_reg[rt(instr)].value = rtVal; | ||||
| } | ||||
| 
 | ||||
| void CPU_ORI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_ORI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs | Imm
 | ||||
|   const u32 rtVal = rsVal | imm(instr); | ||||
|  | @ -686,7 +698,7 @@ void CPU_ORI(u32 instr, u32 rsVal) | |||
|   CPU_reg[rt(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_XORI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_XORI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs ^ Imm
 | ||||
|   const u32 rtVal = rsVal ^ imm(instr); | ||||
|  | @ -713,7 +725,7 @@ void CPU_XORI(u32 instr, u32 rsVal) | |||
|   CPU_reg[rt(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SLTI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_SLTI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs < Imm (signed)
 | ||||
|   psx_value tempImm; | ||||
|  | @ -731,7 +743,7 @@ void CPU_SLTI(u32 instr, u32 rsVal) | |||
|   CPU_reg[rt(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SLTIU(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_SLTIU(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Rt = Rs < Imm (Unsigned)
 | ||||
|   psx_value tempImm; | ||||
|  | @ -752,7 +764,7 @@ void CPU_SLTIU(u32 instr, u32 rsVal) | |||
| ////////////////////////////////////
 | ||||
| // Load Upper
 | ||||
| ////////////////////////////////////
 | ||||
| void CPU_LUI(u32 instr) | ||||
| void PGXP::CPU_LUI(u32 instr) | ||||
| { | ||||
|   // Rt = Imm << 16
 | ||||
|   CPU_reg[rt(instr)] = PGXP_value_zero; | ||||
|  | @ -765,7 +777,7 @@ void CPU_LUI(u32 instr) | |||
| // Register Arithmetic
 | ||||
| ////////////////////////////////////
 | ||||
| 
 | ||||
| void CPU_ADD(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_ADD(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs + Rt (signed)
 | ||||
|   PGXP_value ret; | ||||
|  | @ -813,7 +825,7 @@ void CPU_ADD(u32 instr, u32 rsVal, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SUB(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_SUB(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs - Rt (signed)
 | ||||
|   PGXP_value ret; | ||||
|  | @ -848,7 +860,7 @@ void CPU_SUB(u32 instr, u32 rsVal, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| static void CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) | ||||
| ALWAYS_INLINE_RELEASE void PGXP::CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs & Rt
 | ||||
|   psx_value vald, vals, valt; | ||||
|  | @ -937,35 +949,35 @@ static void CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_AND_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_AND_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs & Rt
 | ||||
|   const u32 rdVal = rsVal & rtVal; | ||||
|   CPU_BITWISE(instr, rdVal, rsVal, rtVal); | ||||
| } | ||||
| 
 | ||||
| void CPU_OR_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_OR_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs | Rt
 | ||||
|   const u32 rdVal = rsVal | rtVal; | ||||
|   CPU_BITWISE(instr, rdVal, rsVal, rtVal); | ||||
| } | ||||
| 
 | ||||
| void CPU_XOR_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_XOR_(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs ^ Rt
 | ||||
|   const u32 rdVal = rsVal ^ rtVal; | ||||
|   CPU_BITWISE(instr, rdVal, rsVal, rtVal); | ||||
| } | ||||
| 
 | ||||
| void CPU_NOR(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_NOR(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs NOR Rt
 | ||||
|   const u32 rdVal = ~(rsVal | rtVal); | ||||
|   CPU_BITWISE(instr, rdVal, rsVal, rtVal); | ||||
| } | ||||
| 
 | ||||
| void CPU_SLT(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_SLT(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs < Rt (signed)
 | ||||
|   PGXP_value ret; | ||||
|  | @ -991,7 +1003,7 @@ void CPU_SLT(u32 instr, u32 rsVal, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rs < Rt (unsigned)
 | ||||
|   PGXP_value ret; | ||||
|  | @ -1021,7 +1033,7 @@ void CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal) | |||
| // Register mult/div
 | ||||
| ////////////////////////////////////
 | ||||
| 
 | ||||
| void CPU_MULT(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_MULT(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Hi/Lo = Rs * Rt (signed)
 | ||||
|   Validate(&CPU_reg[rs(instr)], rsVal); | ||||
|  | @ -1069,7 +1081,7 @@ void CPU_MULT(u32 instr, u32 rsVal, u32 rtVal) | |||
|   CPU_Lo.value = Truncate32(result); | ||||
| } | ||||
| 
 | ||||
| void CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Hi/Lo = Rs * Rt (unsigned)
 | ||||
|   Validate(&CPU_reg[rs(instr)], rsVal); | ||||
|  | @ -1117,7 +1129,7 @@ void CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal) | |||
|   CPU_Lo.value = Truncate32(result); | ||||
| } | ||||
| 
 | ||||
| void CPU_DIV(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_DIV(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Lo = Rs / Rt (signed)
 | ||||
|   // Hi = Rs % Rt (signed)
 | ||||
|  | @ -1166,7 +1178,7 @@ void CPU_DIV(u32 instr, u32 rsVal, u32 rtVal) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| void PGXP::CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal) | ||||
| { | ||||
|   // Lo = Rs / Rt (unsigned)
 | ||||
|   // Hi = Rs % Rt (unsigned)
 | ||||
|  | @ -1211,7 +1223,7 @@ void CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal) | |||
| ////////////////////////////////////
 | ||||
| // Shift operations (sa)
 | ||||
| ////////////////////////////////////
 | ||||
| void CPU_SLL(u32 instr, u32 rtVal) | ||||
| void PGXP::CPU_SLL(u32 instr, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rt << Sa
 | ||||
|   const u32 rdVal = rtVal << sa(instr); | ||||
|  | @ -1256,7 +1268,7 @@ void CPU_SLL(u32 instr, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SRL(u32 instr, u32 rtVal) | ||||
| void PGXP::CPU_SRL(u32 instr, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rt >> Sa
 | ||||
|   const u32 rdVal = rtVal >> sa(instr); | ||||
|  | @ -1320,7 +1332,7 @@ void CPU_SRL(u32 instr, u32 rtVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SRA(u32 instr, u32 rtVal) | ||||
| void PGXP::CPU_SRA(u32 instr, u32 rtVal) | ||||
| { | ||||
|   // Rd = Rt >> Sa
 | ||||
|   const u32 rdVal = static_cast<u32>(static_cast<s32>(rtVal) >> sa(instr)); | ||||
|  | @ -1386,7 +1398,7 @@ void CPU_SRA(u32 instr, u32 rtVal) | |||
| ////////////////////////////////////
 | ||||
| // Shift operations variable
 | ||||
| ////////////////////////////////////
 | ||||
| void CPU_SLLV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| void PGXP::CPU_SLLV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| { | ||||
|   // Rd = Rt << Rs
 | ||||
|   const u32 rdVal = rtVal << rsVal; | ||||
|  | @ -1431,7 +1443,7 @@ void CPU_SLLV(u32 instr, u32 rtVal, u32 rsVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SRLV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| void PGXP::CPU_SRLV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| { | ||||
|   // Rd = Rt >> Sa
 | ||||
|   const u32 rdVal = rtVal >> rsVal; | ||||
|  | @ -1496,7 +1508,7 @@ void CPU_SRLV(u32 instr, u32 rtVal, u32 rsVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_SRAV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| void PGXP::CPU_SRAV(u32 instr, u32 rtVal, u32 rsVal) | ||||
| { | ||||
|   // Rd = Rt >> Sa
 | ||||
|   const u32 rdVal = static_cast<u32>(static_cast<s32>(rtVal) >> rsVal); | ||||
|  | @ -1561,7 +1573,7 @@ void CPU_SRAV(u32 instr, u32 rtVal, u32 rsVal) | |||
|   CPU_reg[rd(instr)] = ret; | ||||
| } | ||||
| 
 | ||||
| void CPU_MFHI(u32 instr, u32 hiVal) | ||||
| void PGXP::CPU_MFHI(u32 instr, u32 hiVal) | ||||
| { | ||||
|   // Rd = Hi
 | ||||
|   Validate(&CPU_Hi, hiVal); | ||||
|  | @ -1569,7 +1581,7 @@ void CPU_MFHI(u32 instr, u32 hiVal) | |||
|   CPU_reg[rd(instr)] = CPU_Hi; | ||||
| } | ||||
| 
 | ||||
| void CPU_MTHI(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_MTHI(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Hi = Rd
 | ||||
|   Validate(&CPU_reg[rs(instr)], rsVal); | ||||
|  | @ -1577,7 +1589,7 @@ void CPU_MTHI(u32 instr, u32 rsVal) | |||
|   CPU_Hi = CPU_reg[rd(instr)]; | ||||
| } | ||||
| 
 | ||||
| void CPU_MFLO(u32 instr, u32 loVal) | ||||
| void PGXP::CPU_MFLO(u32 instr, u32 loVal) | ||||
| { | ||||
|   // Rd = Lo
 | ||||
|   Validate(&CPU_Lo, loVal); | ||||
|  | @ -1585,7 +1597,7 @@ void CPU_MFLO(u32 instr, u32 loVal) | |||
|   CPU_reg[rd(instr)] = CPU_Lo; | ||||
| } | ||||
| 
 | ||||
| void CPU_MTLO(u32 instr, u32 rsVal) | ||||
| void PGXP::CPU_MTLO(u32 instr, u32 rsVal) | ||||
| { | ||||
|   // Lo = Rd
 | ||||
|   Validate(&CPU_reg[rs(instr)], rsVal); | ||||
|  | @ -1593,7 +1605,7 @@ void CPU_MTLO(u32 instr, u32 rsVal) | |||
|   CPU_Lo = CPU_reg[rd(instr)]; | ||||
| } | ||||
| 
 | ||||
| void CPU_MFC0(u32 instr, u32 rdVal) | ||||
| void PGXP::CPU_MFC0(u32 instr, u32 rdVal) | ||||
| { | ||||
|   // CPU[Rt] = CP0[Rd]
 | ||||
|   Validate(&CP0_reg[rd(instr)], rdVal); | ||||
|  | @ -1601,12 +1613,10 @@ void CPU_MFC0(u32 instr, u32 rdVal) | |||
|   CPU_reg[rt(instr)].value = rdVal; | ||||
| } | ||||
| 
 | ||||
| void CPU_MTC0(u32 instr, u32 rdVal, u32 rtVal) | ||||
| void PGXP::CPU_MTC0(u32 instr, u32 rdVal, u32 rtVal) | ||||
| { | ||||
|   // CP0[Rd] = CPU[Rt]
 | ||||
|   Validate(&CPU_reg[rt(instr)], rtVal); | ||||
|   CP0_reg[rd(instr)] = CPU_reg[rt(instr)]; | ||||
|   CP0_reg[rd(instr)].value = rdVal; | ||||
| } | ||||
| 
 | ||||
| } // namespace PGXP
 | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
| Log_SetChannel(SIO); | ||||
| 
 | ||||
| namespace SIO { | ||||
| namespace { | ||||
| 
 | ||||
| union SIO_CTRL | ||||
| { | ||||
|  | @ -64,6 +65,7 @@ union SIO_MODE | |||
|   BitField<u16, u8, 5, 1> parity_type; | ||||
|   BitField<u16, u8, 6, 2> stop_bit_length; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static void SoftReset(); | ||||
| 
 | ||||
|  | @ -79,7 +81,9 @@ void SIO::Initialize() | |||
|   Reset(); | ||||
| } | ||||
| 
 | ||||
| void SIO::Shutdown() {} | ||||
| void SIO::Shutdown() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void SIO::Reset() | ||||
| { | ||||
|  |  | |||
|  | @ -38,6 +38,8 @@ ALWAYS_INLINE static constexpr s32 ApplyVolume(s32 sample, s16 volume) | |||
| } | ||||
| 
 | ||||
| namespace SPU { | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   SPU_BASE = 0x1F801C00, | ||||
|  | @ -307,6 +309,7 @@ struct ReverbRegisters | |||
|     u16 rev[NUM_REVERB_REGS]; | ||||
|   }; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static ADSRPhase GetNextADSRPhase(ADSRPhase phase); | ||||
| 
 | ||||
|  | @ -350,7 +353,7 @@ static void CreateOutputStream(); | |||
| 
 | ||||
| static std::unique_ptr<TimingEvent> s_tick_event; | ||||
| static std::unique_ptr<TimingEvent> s_transfer_event; | ||||
| static std::unique_ptr<Common::WAVWriter> s_dump_writer; | ||||
| static std::unique_ptr<WAVWriter> s_dump_writer; | ||||
| static std::unique_ptr<AudioStream> s_audio_stream; | ||||
| static std::unique_ptr<AudioStream> s_null_audio_stream; | ||||
| static bool s_audio_output_muted = false; | ||||
|  | @ -405,7 +408,7 @@ static std::array<u8, RAM_SIZE> s_ram{}; | |||
| 
 | ||||
| #ifdef SPU_DUMP_ALL_VOICES | ||||
| // +1 for reverb output
 | ||||
| static std::array<std::unique_ptr<Common::WAVWriter>, NUM_VOICES + 1> s_voice_dump_writers; | ||||
| static std::array<std::unique_ptr<WAVWriter>, NUM_VOICES + 1> s_voice_dump_writers; | ||||
| #endif | ||||
| } // namespace SPU
 | ||||
| 
 | ||||
|  | @ -1479,7 +1482,7 @@ bool SPU::IsDumpingAudio() | |||
| bool SPU::StartDumpingAudio(const char* filename) | ||||
| { | ||||
|   s_dump_writer.reset(); | ||||
|   s_dump_writer = std::make_unique<Common::WAVWriter>(); | ||||
|   s_dump_writer = std::make_unique<WAVWriter>(); | ||||
|   if (!s_dump_writer->Open(filename, SAMPLE_RATE, 2)) | ||||
|   { | ||||
|     Log_ErrorPrintf("Failed to open '%s'", filename); | ||||
|  | @ -1491,13 +1494,13 @@ bool SPU::StartDumpingAudio(const char* filename) | |||
|   for (size_t i = 0; i < s_voice_dump_writers.size(); i++) | ||||
|   { | ||||
|     s_voice_dump_writers[i].reset(); | ||||
|     s_voice_dump_writers[i] = std::make_unique<Common::WAVWriter>(); | ||||
|     s_voice_dump_writers[i] = std::make_unique<WAVWriter>(); | ||||
| 
 | ||||
|     TinyString new_suffix; | ||||
|     if (i == NUM_VOICES) | ||||
|       new_suffix.Assign("reverb.wav"); | ||||
|       new_suffix.assign("reverb.wav"); | ||||
|     else | ||||
|       new_suffix.Format("voice%u.wav", i); | ||||
|       new_suffix.fmt("voice{}.wav", i); | ||||
| 
 | ||||
|     const std::string voice_filename = Path::ReplaceExtension(filename, new_suffix); | ||||
|     if (!s_voice_dump_writers[i]->Open(voice_filename.c_str(), SAMPLE_RATE, 2)) | ||||
|  |  | |||
|  | @ -21,6 +21,8 @@ | |||
| Log_SetChannel(Timers); | ||||
| 
 | ||||
| namespace Timers { | ||||
| namespace { | ||||
| 
 | ||||
| static constexpr u32 NUM_TIMERS = 3; | ||||
| 
 | ||||
| enum class SyncMode : u8 | ||||
|  | @ -60,6 +62,8 @@ struct CounterState | |||
|   bool irq_done; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| static void UpdateCountingEnabled(CounterState& cs); | ||||
| static void CheckForIRQ(u32 index, u32 old_counter); | ||||
| static void UpdateIRQ(u32 index); | ||||
|  |  | |||
|  | @ -77,7 +77,6 @@ target_link_libraries(util PRIVATE stb libchdr zlib soundtouch Zstd::Zstd reshad | |||
| if(ENABLE_CUBEB) | ||||
|   target_sources(util PRIVATE | ||||
|     cubeb_audio_stream.cpp | ||||
|     cubeb_audio_stream.h | ||||
|   ) | ||||
|   target_compile_definitions(util PUBLIC "ENABLE_CUBEB=1") | ||||
|   target_link_libraries(util PRIVATE cubeb) | ||||
|  | @ -242,7 +241,6 @@ if(WIN32) | |||
|     win32_raw_input_source.cpp | ||||
|     win32_raw_input_source.h | ||||
|     xaudio2_audio_stream.cpp | ||||
|     xaudio2_audio_stream.h | ||||
|     xinput_source.cpp | ||||
|     xinput_source.h | ||||
|   ) | ||||
|  |  | |||
|  | @ -1,14 +1,19 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/error.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| 
 | ||||
| #include <cerrno> | ||||
| 
 | ||||
| Log_SetChannel(CDImageBin); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageBin : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -30,6 +35,8 @@ private: | |||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageBin::CDImageBin() = default; | ||||
| 
 | ||||
| CDImageBin::~CDImageBin() | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
|  | @ -29,6 +29,8 @@ | |||
| 
 | ||||
| Log_SetChannel(CDImageCHD); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| static std::optional<CDImage::TrackMode> ParseTrackModeString(const char* str) | ||||
| { | ||||
|   if (std::strncmp(str, "MODE2_FORM_MIX", 14) == 0) | ||||
|  | @ -54,7 +56,6 @@ static std::optional<CDImage::TrackMode> ParseTrackModeString(const char* str) | |||
| static std::vector<std::pair<std::string, chd_header>> s_chd_hash_cache; // <filename, header>
 | ||||
| static std::recursive_mutex s_chd_hash_cache_mutex; | ||||
| 
 | ||||
| namespace { | ||||
| class CDImageCHD : public CDImage | ||||
| { | ||||
| public: | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
|  | @ -20,6 +20,8 @@ | |||
| 
 | ||||
| Log_SetChannel(CDImageCueSheet); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageCueSheet : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -46,6 +48,8 @@ private: | |||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageCueSheet::CDImageCueSheet() = default; | ||||
| 
 | ||||
| CDImageCueSheet::~CDImageCueSheet() | ||||
|  |  | |||
|  | @ -1,15 +1,18 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "assert.h" | ||||
| #include "cd_image.h" | ||||
| 
 | ||||
| #include "common/error.h" | ||||
| #include "common/log.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cerrno> | ||||
| #include <cinttypes> | ||||
| #include <cmath> | ||||
| 
 | ||||
| Log_SetChannel(CDImageDevice); | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
|  | @ -36,6 +39,8 @@ static void U16ToBE(u8* beval, u16 leval) | |||
|   beval[1] = static_cast<u8>(leval); | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageDeviceWin32 : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -74,6 +79,8 @@ private: | |||
|   std::array<u8, SUBCHANNEL_BYTES_PER_FRAME> m_subq; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageDeviceWin32::CDImageDeviceWin32() = default; | ||||
| 
 | ||||
| CDImageDeviceWin32::~CDImageDeviceWin32() | ||||
|  |  | |||
|  | @ -158,6 +158,8 @@ static void eccedc_generate(u8* sector, int type) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageEcm : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -216,6 +218,8 @@ private: | |||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageEcm::CDImageEcm() = default; | ||||
| 
 | ||||
| CDImageEcm::~CDImageEcm() | ||||
|  |  | |||
|  | @ -1,14 +1,21 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image_hasher.h" | ||||
| #include "cd_image.h" | ||||
| 
 | ||||
| #include "common/md5_digest.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| namespace CDImageHasher { | ||||
| 
 | ||||
| static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, ProgressCallback* progress_callback) | ||||
| static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, ProgressCallback* progress_callback); | ||||
| static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback); | ||||
| 
 | ||||
| } // namespace CDImageHasher
 | ||||
| 
 | ||||
| bool CDImageHasher::ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, | ||||
|                               ProgressCallback* progress_callback) | ||||
| { | ||||
|   const CDImage::LBA index_start = image->GetTrackIndexPosition(track, index); | ||||
|   const u32 index_length = image->GetTrackIndexLength(track, index); | ||||
|  | @ -43,7 +50,7 @@ static bool ReadIndex(CDImage* image, u8 track, u8 index, MD5Digest* digest, Pro | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback) | ||||
| bool CDImageHasher::ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallback* progress_callback) | ||||
| { | ||||
|   static constexpr u8 INDICES_TO_READ = 2; | ||||
| 
 | ||||
|  | @ -78,14 +85,14 @@ static bool ReadTrack(CDImage* image, u8 track, MD5Digest* digest, ProgressCallb | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| std::string HashToString(const Hash& hash) | ||||
| std::string CDImageHasher::HashToString(const Hash& hash) | ||||
| { | ||||
|   return fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", | ||||
|                      hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10], | ||||
|                      hash[11], hash[12], hash[13], hash[14], hash[15]); | ||||
| } | ||||
| 
 | ||||
| std::optional<Hash> HashFromString(const std::string_view& str) | ||||
| std::optional<CDImageHasher::Hash> CDImageHasher::HashFromString(const std::string_view& str) | ||||
| { | ||||
|   auto decoded = StringUtil::DecodeHex(str); | ||||
|   if (decoded && decoded->size() == std::tuple_size_v<Hash>) | ||||
|  | @ -97,8 +104,8 @@ std::optional<Hash> HashFromString(const std::string_view& str) | |||
|   return std::nullopt; | ||||
| } | ||||
| 
 | ||||
| bool GetImageHash(CDImage* image, Hash* out_hash, | ||||
|                   ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/) | ||||
| bool CDImageHasher::GetImageHash(CDImage* image, Hash* out_hash, | ||||
|                                  ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/) | ||||
| { | ||||
|   MD5Digest digest; | ||||
| 
 | ||||
|  | @ -121,8 +128,8 @@ bool GetImageHash(CDImage* image, Hash* out_hash, | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool GetTrackHash(CDImage* image, u8 track, Hash* out_hash, | ||||
|                   ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/) | ||||
| bool CDImageHasher::GetTrackHash(CDImage* image, u8 track, Hash* out_hash, | ||||
|                                  ProgressCallback* progress_callback /*= ProgressCallback::NullProgressCallback*/) | ||||
| { | ||||
|   MD5Digest digest; | ||||
|   if (!ReadTrack(image, track, &digest, progress_callback)) | ||||
|  | @ -131,5 +138,3 @@ bool GetTrackHash(CDImage* image, u8 track, Hash* out_hash, | |||
|   digest.Final(out_hash->data()); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| } // namespace CDImageHasher
 | ||||
|  | @ -1,19 +1,24 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/error.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| #include "common/path.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cerrno> | ||||
| #include <map> | ||||
| #include <sstream> | ||||
| 
 | ||||
| Log_SetChannel(CDImageMemory); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageM3u : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -48,6 +53,8 @@ private: | |||
|   bool m_apply_patches = false; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageM3u::CDImageM3u() = default; | ||||
| 
 | ||||
| CDImageM3u::~CDImageM3u() = default; | ||||
|  |  | |||
|  | @ -1,18 +1,23 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "assert.h" | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/error.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| #include "common/path.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cerrno> | ||||
| #include <map> | ||||
| 
 | ||||
| Log_SetChannel(CDImageMds); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| struct TrackEntry | ||||
| { | ||||
|  | @ -53,6 +58,8 @@ private: | |||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageMds::CDImageMds() = default; | ||||
| 
 | ||||
| CDImageMds::~CDImageMds() | ||||
|  | @ -112,7 +119,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error) | |||
|   if (track_count > 99 || track_offset >= mds.size()) | ||||
|   { | ||||
|     Log_ErrorPrintf("Invalid track count/block offset %u/%u in '%s'", track_count, track_offset, filename); | ||||
|     Error::SetString(error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename)); | ||||
|     Error::SetString( | ||||
|       error, fmt::format("Invalid track count/block offset {}/{} in '{}'", track_count, track_offset, filename)); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|  | @ -142,7 +150,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error) | |||
|     if (PackedBCDToBinary(track.track_number) != track_number) | ||||
|     { | ||||
|       Log_ErrorPrintf("Unexpected track number 0x%02X in track %u", track.track_number, track_number); | ||||
|       Error::SetString(error, fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number)); | ||||
|       Error::SetString(error, | ||||
|                        fmt::format("Unexpected track number 0x{:02X} in track {}", track.track_number, track_number)); | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -176,7 +185,8 @@ bool CDImageMds::OpenAndParse(const char* filename, Error* error) | |||
|       if (track_pregap > track_start_lba) | ||||
|       { | ||||
|         Log_ErrorPrintf("Track pregap %u is too large for start lba %u", track_pregap, track_start_lba); | ||||
|         Error::SetString(error, fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba)); | ||||
|         Error::SetString(error, | ||||
|                          fmt::format("Track pregap {} is too large for start lba {}", track_pregap, track_start_lba)); | ||||
|         return false; | ||||
|       } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,16 +1,21 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| #include "common/path.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cerrno> | ||||
| 
 | ||||
| Log_SetChannel(CDImageMemory); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class CDImageMemory : public CDImage | ||||
| { | ||||
| public: | ||||
|  | @ -33,6 +38,8 @@ private: | |||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImageMemory::CDImageMemory() = default; | ||||
| 
 | ||||
| CDImageMemory::~CDImageMemory() | ||||
|  |  | |||
|  | @ -1,25 +1,129 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> and contributors.
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> and contributors.
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/error.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| #include "common/path.h" | ||||
| #include "common/string_util.h" | ||||
| #include "pbp_types.h" | ||||
| #include "string.h" | ||||
| 
 | ||||
| #include "zlib.h" | ||||
| 
 | ||||
| #include <array> | ||||
| #include <cstdio> | ||||
| #include <cstring> | ||||
| #include <map> | ||||
| #include <string> | ||||
| #include <variant> | ||||
| #include <vector> | ||||
| 
 | ||||
| Log_SetChannel(CDImagePBP); | ||||
| 
 | ||||
| using namespace PBP; | ||||
| using FileSystem::FSeek64; | ||||
| using FileSystem::FTell64; | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   PBP_HEADER_OFFSET_COUNT = 8u, | ||||
|   TOC_NUM_ENTRIES = 102u, | ||||
|   BLOCK_TABLE_NUM_ENTRIES = 32256u, | ||||
|   DISC_TABLE_NUM_ENTRIES = 5u, | ||||
|   DECOMPRESSED_BLOCK_SIZE = 37632u // 2352 bytes per sector * 16 sectors per block
 | ||||
| }; | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| 
 | ||||
| struct PBPHeader | ||||
| { | ||||
|   u8 magic[4]; // "\0PBP"
 | ||||
|   u32 version; | ||||
| 
 | ||||
|   union | ||||
|   { | ||||
|     u32 offsets[PBP_HEADER_OFFSET_COUNT]; | ||||
| 
 | ||||
|     struct | ||||
|     { | ||||
|       u32 param_sfo_offset; // 0x00000028
 | ||||
|       u32 icon0_png_offset; | ||||
|       u32 icon1_png_offset; | ||||
|       u32 pic0_png_offset; | ||||
|       u32 pic1_png_offset; | ||||
|       u32 snd0_at3_offset; | ||||
|       u32 data_psp_offset; | ||||
|       u32 data_psar_offset; | ||||
|     }; | ||||
|   }; | ||||
| }; | ||||
| static_assert(sizeof(PBPHeader) == 0x28); | ||||
| 
 | ||||
| struct SFOHeader | ||||
| { | ||||
|   u8 magic[4]; // "\0PSF"
 | ||||
|   u32 version; | ||||
|   u32 key_table_offset;  // Relative to start of SFOHeader, 0x000000A4 expected
 | ||||
|   u32 data_table_offset; // Relative to start of SFOHeader, 0x00000100 expected
 | ||||
|   u32 num_table_entries; // 0x00000009
 | ||||
| }; | ||||
| static_assert(sizeof(SFOHeader) == 0x14); | ||||
| 
 | ||||
| struct SFOIndexTableEntry | ||||
| { | ||||
|   u16 key_offset; // Relative to key_table_offset
 | ||||
|   u16 data_type; | ||||
|   u32 data_size;       // Size of actual data in bytes
 | ||||
|   u32 data_total_size; // Size of data field in bytes, data_total_size >= data_size
 | ||||
|   u32 data_offset;     // Relative to data_table_offset
 | ||||
| }; | ||||
| static_assert(sizeof(SFOIndexTableEntry) == 0x10); | ||||
| 
 | ||||
| using SFOIndexTable = std::vector<SFOIndexTableEntry>; | ||||
| using SFOTableDataValue = std::variant<std::string, u32>; | ||||
| using SFOTable = std::map<std::string, SFOTableDataValue>; | ||||
| 
 | ||||
| struct BlockTableEntry | ||||
| { | ||||
|   u32 offset; | ||||
|   u16 size; | ||||
|   u16 marker; | ||||
|   u8 checksum[0x10]; | ||||
|   u64 padding; | ||||
| }; | ||||
| static_assert(sizeof(BlockTableEntry) == 0x20); | ||||
| 
 | ||||
| struct TOCEntry | ||||
| { | ||||
|   struct Timecode | ||||
|   { | ||||
|     u8 m; | ||||
|     u8 s; | ||||
|     u8 f; | ||||
|   }; | ||||
| 
 | ||||
|   u8 type; | ||||
|   u8 unknown; | ||||
|   u8 point; | ||||
|   Timecode pregap_start; | ||||
|   u8 zero; | ||||
|   Timecode userdata_start; | ||||
| }; | ||||
| static_assert(sizeof(TOCEntry) == 0x0A); | ||||
| 
 | ||||
| #if 0 | ||||
| struct AudioTrackTableEntry | ||||
| { | ||||
|   u32 block_offset; | ||||
|   u32 block_size; | ||||
|   u32 block_padding; | ||||
|   u32 block_checksum; | ||||
| }; | ||||
| static_assert(sizeof(CDDATrackTableEntry) == 0x10); | ||||
| #endif | ||||
| 
 | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| class CDImagePBP final : public CDImage | ||||
| { | ||||
|  | @ -94,33 +198,7 @@ private: | |||
| 
 | ||||
|   CDSubChannelReplacement m_sbi; | ||||
| }; | ||||
| 
 | ||||
| namespace EndianHelper { | ||||
| static constexpr bool HostIsLittleEndian() | ||||
| { | ||||
|   constexpr union | ||||
|   { | ||||
|     u8 a[4]; | ||||
|     u32 b; | ||||
|   } test_val = {{1}}; | ||||
| 
 | ||||
|   return test_val.a[0] == 1; | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| static void SwapByteOrder(T& val) | ||||
| { | ||||
|   union | ||||
|   { | ||||
|     T t; | ||||
|     std::array<u8, sizeof(T)> arr; | ||||
|   } swap_val; | ||||
| 
 | ||||
|   swap_val.t = val; | ||||
|   std::reverse(std::begin(swap_val.arr), std::end(swap_val.arr)); | ||||
|   val = swap_val.t; | ||||
| } | ||||
| } // namespace EndianHelper
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImagePBP::~CDImagePBP() | ||||
| { | ||||
|  | @ -135,22 +213,22 @@ bool CDImagePBP::LoadPBPHeader() | |||
|   if (!m_file) | ||||
|     return false; | ||||
| 
 | ||||
|   if (FSeek64(m_file, 0, SEEK_END) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, 0, SEEK_END) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (FTell64(m_file) < 0) | ||||
|   if (FileSystem::FTell64(m_file) < 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (FSeek64(m_file, 0, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, 0, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (fread(&m_pbp_header, sizeof(PBPHeader), 1, m_file) != 1) | ||||
|   if (std::fread(&m_pbp_header, sizeof(PBPHeader), 1, m_file) != 1) | ||||
|   { | ||||
|     Log_ErrorPrint("Unable to read PBP header"); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   if (strncmp((char*)m_pbp_header.magic, "\0PBP", 4) != 0) | ||||
|   if (std::strncmp((char*)m_pbp_header.magic, "\0PBP", 4) != 0) | ||||
|   { | ||||
|     Log_ErrorPrint("PBP magic number mismatch"); | ||||
|     return false; | ||||
|  | @ -165,13 +243,13 @@ bool CDImagePBP::LoadPBPHeader() | |||
| 
 | ||||
| bool CDImagePBP::LoadSFOHeader() | ||||
| { | ||||
|   if (FSeek64(m_file, m_pbp_header.param_sfo_offset, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, m_pbp_header.param_sfo_offset, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (fread(&m_sfo_header, sizeof(SFOHeader), 1, m_file) != 1) | ||||
|   if (std::fread(&m_sfo_header, sizeof(SFOHeader), 1, m_file) != 1) | ||||
|     return false; | ||||
| 
 | ||||
|   if (strncmp((char*)m_sfo_header.magic, "\0PSF", 4) != 0) | ||||
|   if (std::strncmp((char*)m_sfo_header.magic, "\0PSF", 4) != 0) | ||||
|   { | ||||
|     Log_ErrorPrint("SFO magic number mismatch"); | ||||
|     return false; | ||||
|  | @ -189,12 +267,14 @@ bool CDImagePBP::LoadSFOIndexTable() | |||
|   m_sfo_index_table.clear(); | ||||
|   m_sfo_index_table.resize(m_sfo_header.num_table_entries); | ||||
| 
 | ||||
|   if (FSeek64(m_file, m_pbp_header.param_sfo_offset + sizeof(m_sfo_header), SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, m_pbp_header.param_sfo_offset + sizeof(m_sfo_header), SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (fread(m_sfo_index_table.data(), sizeof(SFOIndexTableEntry), m_sfo_header.num_table_entries, m_file) != | ||||
|   if (std::fread(m_sfo_index_table.data(), sizeof(SFOIndexTableEntry), m_sfo_header.num_table_entries, m_file) != | ||||
|       m_sfo_header.num_table_entries) | ||||
|   { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
| #if _DEBUG | ||||
|   for (size_t i = 0; i < static_cast<size_t>(m_sfo_header.num_table_entries); ++i) | ||||
|  | @ -215,7 +295,7 @@ bool CDImagePBP::LoadSFOTable() | |||
|     u32 abs_data_offset = | ||||
|       m_pbp_header.param_sfo_offset + m_sfo_header.data_table_offset + m_sfo_index_table[i].data_offset; | ||||
| 
 | ||||
|     if (FSeek64(m_file, abs_key_offset, SEEK_SET) != 0) | ||||
|     if (FileSystem::FSeek64(m_file, abs_key_offset, SEEK_SET) != 0) | ||||
|     { | ||||
|       Log_ErrorPrintf("Failed seek to key for SFO table entry %zu", i); | ||||
|       return false; | ||||
|  | @ -223,13 +303,13 @@ bool CDImagePBP::LoadSFOTable() | |||
| 
 | ||||
|     // Longest known key string is 20 characters total, including the null character
 | ||||
|     char key_cstr[20] = {}; | ||||
|     if (fgets(key_cstr, sizeof(key_cstr), m_file) == nullptr) | ||||
|     if (std::fgets(key_cstr, sizeof(key_cstr), m_file) == nullptr) | ||||
|     { | ||||
|       Log_ErrorPrintf("Failed to read key string for SFO table entry %zu", i); | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     if (FSeek64(m_file, abs_data_offset, SEEK_SET) != 0) | ||||
|     if (FileSystem::FSeek64(m_file, abs_data_offset, SEEK_SET) != 0) | ||||
|     { | ||||
|       Log_ErrorPrintf("Failed seek to data for SFO table entry %zu", i); | ||||
|       return false; | ||||
|  | @ -322,12 +402,6 @@ bool CDImagePBP::IsValidEboot(Error* error) | |||
| 
 | ||||
| bool CDImagePBP::Open(const char* filename, Error* error) | ||||
| { | ||||
|   if (!EndianHelper::HostIsLittleEndian()) | ||||
|   { | ||||
|     Log_ErrorPrint("Big endian hosts not currently supported"); | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   m_file = FileSystem::OpenCFile(filename, "rb"); | ||||
|   if (!m_file) | ||||
|   { | ||||
|  | @ -379,25 +453,25 @@ bool CDImagePBP::Open(const char* filename, Error* error) | |||
|   } | ||||
| 
 | ||||
|   // Start parsing ISO stuff
 | ||||
|   if (FSeek64(m_file, m_pbp_header.data_psar_offset, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, m_pbp_header.data_psar_offset, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   // Check "PSTITLEIMG000000" for multi-disc
 | ||||
|   char data_psar_magic[16] = {}; | ||||
|   if (fread(data_psar_magic, sizeof(data_psar_magic), 1, m_file) != 1) | ||||
|   if (std::fread(data_psar_magic, sizeof(data_psar_magic), 1, m_file) != 1) | ||||
|     return false; | ||||
| 
 | ||||
|   if (strncmp(data_psar_magic, "PSTITLEIMG000000", 16) == 0) // Multi-disc header found
 | ||||
|   if (std::strncmp(data_psar_magic, "PSTITLEIMG000000", 16) == 0) // Multi-disc header found
 | ||||
|   { | ||||
|     // For multi-disc, the five disc offsets are located at data_psar_offset + 0x200. Non-present discs have an offset
 | ||||
|     // of 0. There are also some disc hashes, a serial (from one of the discs, but used as an identifier for the entire
 | ||||
|     // "title image" header), and some other offsets, but we don't really need to check those
 | ||||
| 
 | ||||
|     if (FSeek64(m_file, m_pbp_header.data_psar_offset + 0x200, SEEK_SET) != 0) | ||||
|     if (FileSystem::FSeek64(m_file, m_pbp_header.data_psar_offset + 0x200, SEEK_SET) != 0) | ||||
|       return false; | ||||
| 
 | ||||
|     u32 disc_table[DISC_TABLE_NUM_ENTRIES] = {}; | ||||
|     if (fread(disc_table, sizeof(u32), DISC_TABLE_NUM_ENTRIES, m_file) != DISC_TABLE_NUM_ENTRIES) | ||||
|     if (std::fread(disc_table, sizeof(u32), DISC_TABLE_NUM_ENTRIES, m_file) != DISC_TABLE_NUM_ENTRIES) | ||||
|       return false; | ||||
| 
 | ||||
|     // Ignore encrypted files
 | ||||
|  | @ -449,14 +523,14 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error) | |||
| 
 | ||||
|   // Go to ISO header
 | ||||
|   const u32 iso_header_start = m_disc_offsets[index]; | ||||
|   if (FSeek64(m_file, iso_header_start, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, iso_header_start, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   char iso_header_magic[12] = {}; | ||||
|   if (fread(iso_header_magic, sizeof(iso_header_magic), 1, m_file) != 1) | ||||
|   if (std::fread(iso_header_magic, sizeof(iso_header_magic), 1, m_file) != 1) | ||||
|     return false; | ||||
| 
 | ||||
|   if (strncmp(iso_header_magic, "PSISOIMG0000", 12) != 0) | ||||
|   if (std::strncmp(iso_header_magic, "PSISOIMG0000", 12) != 0) | ||||
|   { | ||||
|     Log_ErrorPrint("ISO header magic number mismatch"); | ||||
|     return false; | ||||
|  | @ -464,10 +538,10 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error) | |||
| 
 | ||||
|   // Ignore encrypted files
 | ||||
|   u32 pgd_magic; | ||||
|   if (FSeek64(m_file, iso_header_start + 0x400, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, iso_header_start + 0x400, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   if (fread(&pgd_magic, sizeof(pgd_magic), 1, m_file) != 1) | ||||
|   if (std::fread(&pgd_magic, sizeof(pgd_magic), 1, m_file) != 1) | ||||
|     return false; | ||||
| 
 | ||||
|   if (pgd_magic == 0x44475000) // "\0PGD"
 | ||||
|  | @ -478,12 +552,12 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error) | |||
|   } | ||||
| 
 | ||||
|   // Read in the TOC
 | ||||
|   if (FSeek64(m_file, iso_header_start + 0x800, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, iso_header_start + 0x800, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   for (u32 i = 0; i < TOC_NUM_ENTRIES; i++) | ||||
|   { | ||||
|     if (fread(&m_toc[i], sizeof(m_toc[i]), 1, m_file) != 1) | ||||
|     if (std::fread(&m_toc[i], sizeof(m_toc[i]), 1, m_file) != 1) | ||||
|       return false; | ||||
|   } | ||||
| 
 | ||||
|  | @ -491,21 +565,21 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error) | |||
|   // for both data and audio
 | ||||
| 
 | ||||
|   // Get the offset of the compressed iso
 | ||||
|   if (FSeek64(m_file, iso_header_start + 0xBFC, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, iso_header_start + 0xBFC, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   u32 iso_offset; | ||||
|   if (fread(&iso_offset, sizeof(iso_offset), 1, m_file) != 1) | ||||
|   if (std::fread(&iso_offset, sizeof(iso_offset), 1, m_file) != 1) | ||||
|     return false; | ||||
| 
 | ||||
|   // Generate block info table
 | ||||
|   if (FSeek64(m_file, iso_header_start + 0x4000, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, iso_header_start + 0x4000, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   for (u32 i = 0; i < BLOCK_TABLE_NUM_ENTRIES; i++) | ||||
|   { | ||||
|     BlockTableEntry bte; | ||||
|     if (fread(&bte, sizeof(bte), 1, m_file) != 1) | ||||
|     if (std::fread(&bte, sizeof(bte), 1, m_file) != 1) | ||||
|       return false; | ||||
| 
 | ||||
|     // Only store absolute file offset into a BlockInfo if this is a valid block
 | ||||
|  | @ -708,19 +782,19 @@ bool CDImagePBP::InitDecompressionStream() | |||
| 
 | ||||
| bool CDImagePBP::DecompressBlock(const BlockInfo& block_info) | ||||
| { | ||||
|   if (FSeek64(m_file, block_info.offset, SEEK_SET) != 0) | ||||
|   if (FileSystem::FSeek64(m_file, block_info.offset, SEEK_SET) != 0) | ||||
|     return false; | ||||
| 
 | ||||
|   // Compression level 0 has compressed size == decompressed size.
 | ||||
|   if (block_info.size == m_decompressed_block.size()) | ||||
|   { | ||||
|     return (fread(m_decompressed_block.data(), sizeof(u8), m_decompressed_block.size(), m_file) == | ||||
|     return (std::fread(m_decompressed_block.data(), sizeof(u8), m_decompressed_block.size(), m_file) == | ||||
|             m_decompressed_block.size()); | ||||
|   } | ||||
| 
 | ||||
|   m_compressed_block.resize(block_info.size); | ||||
| 
 | ||||
|   if (fread(m_compressed_block.data(), sizeof(u8), m_compressed_block.size(), m_file) != m_compressed_block.size()) | ||||
|   if (std::fread(m_compressed_block.data(), sizeof(u8), m_compressed_block.size(), m_file) != m_compressed_block.size()) | ||||
|     return false; | ||||
| 
 | ||||
|   m_inflate_stream.next_in = m_compressed_block.data(); | ||||
|  |  | |||
|  | @ -1,17 +1,22 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_image.h" | ||||
| #include "cd_subchannel_replacement.h" | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/file_system.h" | ||||
| #include "common/log.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cerrno> | ||||
| #include <map> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| Log_SetChannel(CDImagePPF); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   DESC_SIZE = 50, | ||||
|  | @ -51,6 +56,8 @@ private: | |||
|   u32 m_replacement_offset = 0; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CDImagePPF::CDImagePPF() = default; | ||||
| 
 | ||||
| CDImagePPF::~CDImagePPF() = default; | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cd_xa.h" | ||||
| #include "cd_image.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| 
 | ||||
|  | @ -11,7 +12,7 @@ static constexpr std::array<s32, 4> s_xa_adpcm_filter_table_pos = {{0, 60, 115, | |||
| static constexpr std::array<s32, 4> s_xa_adpcm_filter_table_neg = {{0, 0, -52, -55}}; | ||||
| 
 | ||||
| template<bool IS_STEREO, bool IS_8BIT> | ||||
| static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_samples) | ||||
| ALWAYS_INLINE_RELEASE static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_samples) | ||||
| { | ||||
|   // The data layout is annoying here. Each word of data is interleaved with the other blocks, requiring multiple
 | ||||
|   // passes to decode the whole chunk.
 | ||||
|  | @ -58,7 +59,7 @@ static void DecodeXA_ADPCMChunk(const u8* chunk_ptr, s16* samples, s32* last_sam | |||
| } | ||||
| 
 | ||||
| template<bool IS_STEREO, bool IS_8BIT> | ||||
| static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_samples) | ||||
| ALWAYS_INLINE_RELEASE static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_samples) | ||||
| { | ||||
|   constexpr u32 NUM_CHUNKS = 18; | ||||
|   constexpr u32 CHUNK_SIZE_IN_BYTES = 128; | ||||
|  | @ -73,7 +74,9 @@ static void DecodeXA_ADPCMChunks(const u8* chunk_ptr, s16* samples, s32* last_sa | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void DecodeADPCMSector(const void* data, s16* samples, s32* last_samples) | ||||
| } // namespace CDXA
 | ||||
| 
 | ||||
| void CDXA::DecodeADPCMSector(const void* data, s16* samples, s32* last_samples) | ||||
| { | ||||
|   const XASubHeader* subheader = reinterpret_cast<const XASubHeader*>( | ||||
|     reinterpret_cast<const u8*>(data) + CDImage::SECTOR_SYNC_SIZE + sizeof(CDImage::SectorHeader)); | ||||
|  | @ -97,5 +100,3 @@ void DecodeADPCMSector(const void* data, s16* samples, s32* last_samples) | |||
|       DecodeXA_ADPCMChunks<true, true>(chunk_ptr, samples, last_samples); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| } // namespace CDXA
 | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cubeb_audio_stream.h" | ||||
| #include "host.h" | ||||
| #include "imgui_manager.h" | ||||
| 
 | ||||
|  | @ -22,7 +21,35 @@ | |||
| 
 | ||||
| Log_SetChannel(CubebAudioStream); | ||||
| 
 | ||||
| static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state); | ||||
| namespace { | ||||
| 
 | ||||
| class CubebAudioStream : public AudioStream | ||||
| { | ||||
| public: | ||||
|   CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch); | ||||
|   ~CubebAudioStream(); | ||||
| 
 | ||||
|   void SetPaused(bool paused) override; | ||||
|   void SetOutputVolume(u32 volume) override; | ||||
| 
 | ||||
|   bool Initialize(u32 latency_ms); | ||||
| 
 | ||||
| private: | ||||
|   static void LogCallback(const char* fmt, ...); | ||||
|   static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, | ||||
|                            long nframes); | ||||
|   static void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state); | ||||
| 
 | ||||
|   void DestroyContextAndStream(); | ||||
| 
 | ||||
|   cubeb* m_context = nullptr; | ||||
|   cubeb_stream* stream = nullptr; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|   bool m_com_initialized_by_us = false; | ||||
| #endif | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| CubebAudioStream::CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch) | ||||
|   : AudioStream(sample_rate, channels, buffer_ms, stretch) | ||||
|  | @ -194,7 +221,7 @@ bool CubebAudioStream::Initialize(u32 latency_ms) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state) | ||||
| void CubebAudioStream::StateCallback(cubeb_stream* stream, void* user_ptr, cubeb_state state) | ||||
| { | ||||
|   // noop
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,37 +0,0 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "audio_stream.h" | ||||
| 
 | ||||
| #include <cstdint> | ||||
| 
 | ||||
| struct cubeb; | ||||
| struct cubeb_stream; | ||||
| 
 | ||||
| class CubebAudioStream : public AudioStream | ||||
| { | ||||
| public: | ||||
|   CubebAudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch); | ||||
|   ~CubebAudioStream(); | ||||
| 
 | ||||
|   void SetPaused(bool paused) override; | ||||
|   void SetOutputVolume(u32 volume) override; | ||||
| 
 | ||||
|   bool Initialize(u32 latency_ms); | ||||
| 
 | ||||
| private: | ||||
|   static void LogCallback(const char* fmt, ...); | ||||
|   static long DataCallback(cubeb_stream* stm, void* user_ptr, const void* input_buffer, void* output_buffer, | ||||
|                            long nframes); | ||||
| 
 | ||||
|   void DestroyContextAndStream(); | ||||
| 
 | ||||
|   cubeb* m_context = nullptr; | ||||
|   cubeb_stream* stream = nullptr; | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
|   bool m_com_initialized_by_us = false; | ||||
| #endif | ||||
| }; | ||||
|  | @ -1,16 +1,21 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "cue_parser.h" | ||||
| 
 | ||||
| #include "common/error.h" | ||||
| #include "common/log.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| #include <cstdarg> | ||||
| 
 | ||||
| Log_SetChannel(CueParser); | ||||
| 
 | ||||
| namespace CueParser { | ||||
| static bool TokenMatch(const std::string_view& s1, const char* token); | ||||
| } | ||||
| 
 | ||||
| static bool TokenMatch(const std::string_view& s1, const char* token) | ||||
| bool CueParser::TokenMatch(const std::string_view& s1, const char* token) | ||||
| { | ||||
|   const size_t token_len = std::strlen(token); | ||||
|   if (s1.length() != token_len) | ||||
|  | @ -19,11 +24,11 @@ static bool TokenMatch(const std::string_view& s1, const char* token) | |||
|   return (StringUtil::Strncasecmp(s1.data(), token, token_len) == 0); | ||||
| } | ||||
| 
 | ||||
| File::File() = default; | ||||
| CueParser::File::File() = default; | ||||
| 
 | ||||
| File::~File() = default; | ||||
| CueParser::File::~File() = default; | ||||
| 
 | ||||
| const Track* File::GetTrack(u32 n) const | ||||
| const CueParser::Track* CueParser::File::GetTrack(u32 n) const | ||||
| { | ||||
|   for (const auto& it : m_tracks) | ||||
|   { | ||||
|  | @ -34,7 +39,7 @@ const Track* File::GetTrack(u32 n) const | |||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| Track* File::GetMutableTrack(u32 n) | ||||
| CueParser::Track* CueParser::File::GetMutableTrack(u32 n) | ||||
| { | ||||
|   for (auto& it : m_tracks) | ||||
|   { | ||||
|  | @ -45,7 +50,7 @@ Track* File::GetMutableTrack(u32 n) | |||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| bool File::Parse(std::FILE* fp, Error* error) | ||||
| bool CueParser::File::Parse(std::FILE* fp, Error* error) | ||||
| { | ||||
|   char line[1024]; | ||||
|   u32 line_number = 1; | ||||
|  | @ -66,7 +71,7 @@ bool File::Parse(std::FILE* fp, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void File::SetError(u32 line_number, Error* error, const char* format, ...) | ||||
| void CueParser::File::SetError(u32 line_number, Error* error, const char* format, ...) | ||||
| { | ||||
|   std::va_list ap; | ||||
|   SmallString str; | ||||
|  | @ -78,7 +83,7 @@ void File::SetError(u32 line_number, Error* error, const char* format, ...) | |||
|   Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str)); | ||||
| } | ||||
| 
 | ||||
| std::string_view File::GetToken(const char*& line) | ||||
| std::string_view CueParser::File::GetToken(const char*& line) | ||||
| { | ||||
|   std::string_view ret; | ||||
| 
 | ||||
|  | @ -119,7 +124,7 @@ std::string_view File::GetToken(const char*& line) | |||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| std::optional<MSF> File::GetMSF(const std::string_view& token) | ||||
| std::optional<CueParser::MSF> CueParser::File::GetMSF(const std::string_view& token) | ||||
| { | ||||
|   static const s32 max_values[] = {std::numeric_limits<s32>::max(), 60, 75}; | ||||
| 
 | ||||
|  | @ -164,7 +169,7 @@ std::optional<MSF> File::GetMSF(const std::string_view& token) | |||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| bool File::ParseLine(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::ParseLine(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   const std::string_view command(GetToken(line)); | ||||
|   if (command.empty()) | ||||
|  | @ -208,7 +213,7 @@ bool File::ParseLine(const char* line, u32 line_number, Error* error) | |||
|   return false; | ||||
| } | ||||
| 
 | ||||
| bool File::HandleFileCommand(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::HandleFileCommand(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   const std::string_view filename(GetToken(line)); | ||||
|   const std::string_view mode(GetToken(line)); | ||||
|  | @ -230,7 +235,7 @@ bool File::HandleFileCommand(const char* line, u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::HandleTrackCommand(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   if (!CompleteLastTrack(line_number, error)) | ||||
|     return false; | ||||
|  | @ -286,7 +291,7 @@ bool File::HandleTrackCommand(const char* line, u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::HandleIndexCommand(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   if (!m_current_track.has_value()) | ||||
|   { | ||||
|  | @ -332,7 +337,7 @@ bool File::HandleIndexCommand(const char* line, u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::HandlePregapCommand(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   if (!m_current_track.has_value()) | ||||
|   { | ||||
|  | @ -364,7 +369,7 @@ bool File::HandlePregapCommand(const char* line, u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error) | ||||
| bool CueParser::File::HandleFlagCommand(const char* line, u32 line_number, Error* error) | ||||
| { | ||||
|   if (!m_current_track.has_value()) | ||||
|   { | ||||
|  | @ -393,7 +398,7 @@ bool File::HandleFlagCommand(const char* line, u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::CompleteLastTrack(u32 line_number, Error* error) | ||||
| bool CueParser::File::CompleteLastTrack(u32 line_number, Error* error) | ||||
| { | ||||
|   if (!m_current_track.has_value()) | ||||
|     return true; | ||||
|  | @ -434,7 +439,7 @@ bool File::CompleteLastTrack(u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| bool File::SetTrackLengths(u32 line_number, Error* error) | ||||
| bool CueParser::File::SetTrackLengths(u32 line_number, Error* error) | ||||
| { | ||||
|   for (const Track& track : m_tracks) | ||||
|   { | ||||
|  | @ -464,7 +469,7 @@ bool File::SetTrackLengths(u32 line_number, Error* error) | |||
|   return true; | ||||
| } | ||||
| 
 | ||||
| const CueParser::MSF* Track::GetIndex(u32 n) const | ||||
| const CueParser::MSF* CueParser::Track::GetIndex(u32 n) const | ||||
| { | ||||
|   for (const auto& it : indices) | ||||
|   { | ||||
|  | @ -474,5 +479,3 @@ const CueParser::MSF* Track::GetIndex(u32 n) const | |||
| 
 | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| } // namespace CueParser
 | ||||
|  | @ -114,6 +114,7 @@ static std::string s_message_dialog_message; | |||
| static std::array<std::string, 3> s_message_dialog_buttons; | ||||
| static MessageDialogCallbackVariant s_message_dialog_callback; | ||||
| 
 | ||||
| namespace { | ||||
| struct FileSelectorItem | ||||
| { | ||||
|   FileSelectorItem() = default; | ||||
|  | @ -132,6 +133,7 @@ struct FileSelectorItem | |||
|   std::string full_path; | ||||
|   bool is_file; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static bool s_file_selector_open = false; | ||||
| static bool s_file_selector_directory = false; | ||||
|  | @ -144,6 +146,7 @@ static std::vector<FileSelectorItem> s_file_selector_items; | |||
| static constexpr float NOTIFICATION_FADE_IN_TIME = 0.2f; | ||||
| static constexpr float NOTIFICATION_FADE_OUT_TIME = 0.8f; | ||||
| 
 | ||||
| namespace { | ||||
| struct Notification | ||||
| { | ||||
|   std::string key; | ||||
|  | @ -156,6 +159,7 @@ struct Notification | |||
|   float target_y; | ||||
|   float last_y; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static std::vector<Notification> s_notifications; | ||||
| 
 | ||||
|  | @ -164,6 +168,7 @@ static std::string s_toast_message; | |||
| static Common::Timer::Value s_toast_start_time; | ||||
| static float s_toast_duration; | ||||
| 
 | ||||
| namespace { | ||||
| struct BackgroundProgressDialogData | ||||
| { | ||||
|   std::string message; | ||||
|  | @ -172,6 +177,7 @@ struct BackgroundProgressDialogData | |||
|   s32 max; | ||||
|   s32 value; | ||||
| }; | ||||
| } // namespace
 | ||||
| 
 | ||||
| static std::vector<BackgroundProgressDialogData> s_background_progress_dialogs; | ||||
| static std::mutex s_background_progress_lock; | ||||
|  |  | |||
|  | @ -30,6 +30,8 @@ | |||
| Log_SetChannel(ImGuiManager); | ||||
| 
 | ||||
| namespace ImGuiManager { | ||||
| namespace { | ||||
| 
 | ||||
| struct SoftwareCursor | ||||
| { | ||||
|   std::string image_path; | ||||
|  | @ -41,6 +43,19 @@ struct SoftwareCursor | |||
|   std::pair<float, float> pos; | ||||
| }; | ||||
| 
 | ||||
| struct OSDMessage | ||||
| { | ||||
|   std::string key; | ||||
|   std::string text; | ||||
|   Common::Timer::Value start_time; | ||||
|   Common::Timer::Value move_time; | ||||
|   float duration; | ||||
|   float target_y; | ||||
|   float last_y; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| static void SetStyle(); | ||||
| static void SetKeyMap(); | ||||
| static bool LoadFontData(); | ||||
|  | @ -54,7 +69,6 @@ static void CreateSoftwareCursorTextures(); | |||
| static void UpdateSoftwareCursorTexture(u32 index); | ||||
| static void DestroySoftwareCursorTextures(); | ||||
| static void DrawSoftwareCursor(const SoftwareCursor& sc, const std::pair<float, float>& pos); | ||||
| } // namespace ImGuiManager
 | ||||
| 
 | ||||
| static float s_global_prescale = 1.0f; // before window scale
 | ||||
| static float s_global_scale = 1.0f; | ||||
|  | @ -85,17 +99,6 @@ static std::unordered_map<u32, ImGuiKey> s_imgui_key_map; | |||
| static constexpr float OSD_FADE_IN_TIME = 0.1f; | ||||
| static constexpr float OSD_FADE_OUT_TIME = 0.4f; | ||||
| 
 | ||||
| struct OSDMessage | ||||
| { | ||||
|   std::string key; | ||||
|   std::string text; | ||||
|   Common::Timer::Value start_time; | ||||
|   Common::Timer::Value move_time; | ||||
|   float duration; | ||||
|   float target_y; | ||||
|   float last_y; | ||||
| }; | ||||
| 
 | ||||
| static std::deque<OSDMessage> s_osd_active_messages; | ||||
| static std::deque<OSDMessage> s_osd_posted_messages; | ||||
| static std::mutex s_osd_messages_lock; | ||||
|  | @ -103,6 +106,7 @@ static bool s_show_osd_messages = true; | |||
| static bool s_global_prescale_changed = false; | ||||
| 
 | ||||
| static std::array<ImGuiManager::SoftwareCursor, InputManager::MAX_SOFTWARE_CURSORS> s_software_cursors = {}; | ||||
| } // namespace ImGuiManager
 | ||||
| 
 | ||||
| void ImGuiManager::SetFontPath(std::string path) | ||||
| { | ||||
|  | @ -627,12 +631,12 @@ void Host::AddKeyedOSDMessage(std::string key, std::string message, float durati | |||
|   else | ||||
|     Log_InfoPrintf("OSD: %s", message.c_str()); | ||||
| 
 | ||||
|   if (!s_show_osd_messages) | ||||
|   if (!ImGuiManager::s_show_osd_messages) | ||||
|     return; | ||||
| 
 | ||||
|   const Common::Timer::Value current_time = Common::Timer::GetCurrentValue(); | ||||
| 
 | ||||
|   OSDMessage msg; | ||||
|   ImGuiManager::OSDMessage msg; | ||||
|   msg.key = std::move(key); | ||||
|   msg.text = std::move(message); | ||||
|   msg.duration = duration; | ||||
|  | @ -641,8 +645,8 @@ void Host::AddKeyedOSDMessage(std::string key, std::string message, float durati | |||
|   msg.target_y = -1.0f; | ||||
|   msg.last_y = -1.0f; | ||||
| 
 | ||||
|   std::unique_lock<std::mutex> lock(s_osd_messages_lock); | ||||
|   s_osd_posted_messages.push_back(std::move(msg)); | ||||
|   std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock); | ||||
|   ImGuiManager::s_osd_posted_messages.push_back(std::move(msg)); | ||||
| } | ||||
| 
 | ||||
| void Host::AddFormattedOSDMessage(float duration, const char* format, ...) | ||||
|  | @ -670,25 +674,25 @@ void Host::AddKeyedFormattedOSDMessage(std::string key, float duration, const ch | |||
| 
 | ||||
| void Host::RemoveKeyedOSDMessage(std::string key) | ||||
| { | ||||
|   if (!s_show_osd_messages) | ||||
|   if (!ImGuiManager::s_show_osd_messages) | ||||
|     return; | ||||
| 
 | ||||
|   OSDMessage msg = {}; | ||||
|   ImGuiManager::OSDMessage msg = {}; | ||||
|   msg.key = std::move(key); | ||||
|   msg.duration = 0.0f; | ||||
| 
 | ||||
|   std::unique_lock<std::mutex> lock(s_osd_messages_lock); | ||||
|   s_osd_posted_messages.push_back(std::move(msg)); | ||||
|   std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock); | ||||
|   ImGuiManager::s_osd_posted_messages.push_back(std::move(msg)); | ||||
| } | ||||
| 
 | ||||
| void Host::ClearOSDMessages() | ||||
| { | ||||
|   { | ||||
|     std::unique_lock<std::mutex> lock(s_osd_messages_lock); | ||||
|     s_osd_posted_messages.clear(); | ||||
|     std::unique_lock<std::mutex> lock(ImGuiManager::s_osd_messages_lock); | ||||
|     ImGuiManager::s_osd_posted_messages.clear(); | ||||
|   } | ||||
| 
 | ||||
|   s_osd_active_messages.clear(); | ||||
|   ImGuiManager::s_osd_active_messages.clear(); | ||||
| } | ||||
| 
 | ||||
| void ImGuiManager::AcquirePendingOSDMessages(Common::Timer::Value current_time) | ||||
|  | @ -716,8 +720,7 @@ void ImGuiManager::AcquirePendingOSDMessages(Common::Timer::Value current_time) | |||
|       // Don't fade it in again
 | ||||
|       const float time_passed = | ||||
|         static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - iter->start_time)); | ||||
|       iter->start_time = | ||||
|         current_time - Common::Timer::ConvertSecondsToValue(std::min(time_passed, OSD_FADE_IN_TIME)); | ||||
|       iter->start_time = current_time - Common::Timer::ConvertSecondsToValue(std::min(time_passed, OSD_FADE_IN_TIME)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|  | @ -825,7 +828,7 @@ float ImGuiManager::GetGlobalScale() | |||
| 
 | ||||
| float Host::GetOSDScale() | ||||
| { | ||||
|   return s_global_scale; | ||||
|   return ImGuiManager::s_global_scale; | ||||
| } | ||||
| 
 | ||||
| ImFont* ImGuiManager::GetStandardFont() | ||||
|  |  | |||
|  | @ -27,6 +27,8 @@ | |||
| 
 | ||||
| Log_SetChannel(InputManager); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| // Constants
 | ||||
| // ------------------------------------------------------------------------
 | ||||
|  | @ -88,6 +90,8 @@ struct MacroButton | |||
|   bool trigger_state;       ///< Whether the macro button is active.
 | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| // Forward Declarations (for static qualifier)
 | ||||
| // ------------------------------------------------------------------------
 | ||||
|  |  | |||
|  | @ -1,113 +0,0 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> and contributors.
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "common/types.h" | ||||
| #include <map> | ||||
| #include <string> | ||||
| #include <variant> | ||||
| #include <vector> | ||||
| 
 | ||||
| namespace PBP { | ||||
| 
 | ||||
| enum : u32 | ||||
| { | ||||
|   PBP_HEADER_OFFSET_COUNT = 8u, | ||||
|   TOC_NUM_ENTRIES = 102u, | ||||
|   BLOCK_TABLE_NUM_ENTRIES = 32256u, | ||||
|   DISC_TABLE_NUM_ENTRIES = 5u, | ||||
|   DECOMPRESSED_BLOCK_SIZE = 37632u // 2352 bytes per sector * 16 sectors per block
 | ||||
| }; | ||||
| 
 | ||||
| #pragma pack(push, 1) | ||||
| 
 | ||||
| struct PBPHeader | ||||
| { | ||||
|   u8 magic[4]; // "\0PBP"
 | ||||
|   u32 version; | ||||
| 
 | ||||
|   union | ||||
|   { | ||||
|     u32 offsets[PBP_HEADER_OFFSET_COUNT]; | ||||
| 
 | ||||
|     struct | ||||
|     { | ||||
|       u32 param_sfo_offset; // 0x00000028
 | ||||
|       u32 icon0_png_offset; | ||||
|       u32 icon1_png_offset; | ||||
|       u32 pic0_png_offset; | ||||
|       u32 pic1_png_offset; | ||||
|       u32 snd0_at3_offset; | ||||
|       u32 data_psp_offset; | ||||
|       u32 data_psar_offset; | ||||
|     }; | ||||
|   }; | ||||
| }; | ||||
| static_assert(sizeof(PBPHeader) == 0x28); | ||||
| 
 | ||||
| struct SFOHeader | ||||
| { | ||||
|   u8 magic[4]; // "\0PSF"
 | ||||
|   u32 version; | ||||
|   u32 key_table_offset;  // Relative to start of SFOHeader, 0x000000A4 expected
 | ||||
|   u32 data_table_offset; // Relative to start of SFOHeader, 0x00000100 expected
 | ||||
|   u32 num_table_entries; // 0x00000009
 | ||||
| }; | ||||
| static_assert(sizeof(SFOHeader) == 0x14); | ||||
| 
 | ||||
| struct SFOIndexTableEntry | ||||
| { | ||||
|   u16 key_offset; // Relative to key_table_offset
 | ||||
|   u16 data_type; | ||||
|   u32 data_size;       // Size of actual data in bytes
 | ||||
|   u32 data_total_size; // Size of data field in bytes, data_total_size >= data_size
 | ||||
|   u32 data_offset;     // Relative to data_table_offset
 | ||||
| }; | ||||
| static_assert(sizeof(SFOIndexTableEntry) == 0x10); | ||||
| 
 | ||||
| using SFOIndexTable = std::vector<SFOIndexTableEntry>; | ||||
| using SFOTableDataValue = std::variant<std::string, u32>; | ||||
| using SFOTable = std::map<std::string, SFOTableDataValue>; | ||||
| 
 | ||||
| struct BlockTableEntry | ||||
| { | ||||
|   u32 offset; | ||||
|   u16 size; | ||||
|   u16 marker; | ||||
|   u8 checksum[0x10]; | ||||
|   u64 padding; | ||||
| }; | ||||
| static_assert(sizeof(BlockTableEntry) == 0x20); | ||||
| 
 | ||||
| struct TOCEntry | ||||
| { | ||||
|   struct Timecode | ||||
|   { | ||||
|     u8 m; | ||||
|     u8 s; | ||||
|     u8 f; | ||||
|   }; | ||||
| 
 | ||||
|   u8 type; | ||||
|   u8 unknown; | ||||
|   u8 point; | ||||
|   Timecode pregap_start; | ||||
|   u8 zero; | ||||
|   Timecode userdata_start; | ||||
| }; | ||||
| static_assert(sizeof(TOCEntry) == 0x0A); | ||||
| 
 | ||||
| #if 0 | ||||
| struct AudioTrackTableEntry | ||||
| { | ||||
|   u32 block_offset; | ||||
|   u32 block_size; | ||||
|   u32 block_padding; | ||||
|   u32 block_checksum; | ||||
| }; | ||||
| static_assert(sizeof(CDDATrackTableEntry) == 0x10); | ||||
| #endif | ||||
| 
 | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| } // namespace PBP
 | ||||
|  | @ -5,7 +5,6 @@ | |||
|     <ClInclude Include="audio_stream.h" /> | ||||
|     <ClInclude Include="cd_image.h" /> | ||||
|     <ClInclude Include="cd_image_hasher.h" /> | ||||
|     <ClInclude Include="cubeb_audio_stream.h" /> | ||||
|     <ClInclude Include="cue_parser.h" /> | ||||
|     <ClInclude Include="d3d11_device.h" /> | ||||
|     <ClInclude Include="d3d11_pipeline.h" /> | ||||
|  | @ -62,7 +61,6 @@ | |||
|     <ClInclude Include="opengl_texture.h"> | ||||
|       <ExcludedFromBuild Condition="'$(Platform)'=='ARM64'">true</ExcludedFromBuild> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="pbp_types.h" /> | ||||
|     <ClInclude Include="page_fault_handler.h" /> | ||||
|     <ClInclude Include="cd_subchannel_replacement.h" /> | ||||
|     <ClInclude Include="pch.h" /> | ||||
|  | @ -106,7 +104,6 @@ | |||
|     <ClInclude Include="wav_writer.h" /> | ||||
|     <ClInclude Include="win32_raw_input_source.h" /> | ||||
|     <ClInclude Include="window_info.h" /> | ||||
|     <ClInclude Include="xaudio2_audio_stream.h" /> | ||||
|     <ClInclude Include="xinput_source.h" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ | |||
|     <ClInclude Include="cd_image_hasher.h" /> | ||||
|     <ClInclude Include="shiftjis.h" /> | ||||
|     <ClInclude Include="page_fault_handler.h" /> | ||||
|     <ClInclude Include="pbp_types.h" /> | ||||
|     <ClInclude Include="cue_parser.h" /> | ||||
|     <ClInclude Include="ini_settings_interface.h" /> | ||||
|     <ClInclude Include="shadergen.h" /> | ||||
|  | @ -24,11 +23,9 @@ | |||
|     <ClInclude Include="platform_misc.h" /> | ||||
|     <ClInclude Include="sdl_input_source.h" /> | ||||
|     <ClInclude Include="win32_raw_input_source.h" /> | ||||
|     <ClInclude Include="xaudio2_audio_stream.h" /> | ||||
|     <ClInclude Include="xinput_source.h" /> | ||||
|     <ClInclude Include="dinput_source.h" /> | ||||
|     <ClInclude Include="input_manager.h" /> | ||||
|     <ClInclude Include="cubeb_audio_stream.h" /> | ||||
|     <ClInclude Include="metal_stream_buffer.h" /> | ||||
|     <ClInclude Include="opengl_device.h" /> | ||||
|     <ClInclude Include="opengl_loader.h" /> | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "common/log.h" | ||||
| Log_SetChannel(WAVWriter); | ||||
| 
 | ||||
| namespace { | ||||
| #pragma pack(push, 1) | ||||
| struct WAV_HEADER | ||||
| { | ||||
|  | @ -32,8 +33,7 @@ struct WAV_HEADER | |||
|   } data_chunk_header; | ||||
| }; | ||||
| #pragma pack(pop) | ||||
| 
 | ||||
| namespace Common { | ||||
| } // namespace
 | ||||
| 
 | ||||
| WAVWriter::WAVWriter() = default; | ||||
| 
 | ||||
|  | @ -114,5 +114,3 @@ bool WAVWriter::WriteHeader() | |||
| 
 | ||||
|   return (std::fwrite(&header, sizeof(header), 1, m_file) == 1); | ||||
| } | ||||
| 
 | ||||
| } // namespace Common
 | ||||
|  |  | |||
|  | @ -1,12 +1,10 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "common/types.h" | ||||
| #include <cstdio> | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| class WAVWriter | ||||
| { | ||||
| public: | ||||
|  | @ -33,5 +31,3 @@ private: | |||
|   u32 m_num_channels = 0; | ||||
|   u32 m_num_frames = 0; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Common
 | ||||
|  | @ -1,13 +1,68 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #include "xaudio2_audio_stream.h" | ||||
| #include "util/audio_stream.h" | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/log.h" | ||||
| #include <VersionHelpers.h> | ||||
| #include "common/windows_headers.h" | ||||
| 
 | ||||
| #include <array> | ||||
| #include <cstdint> | ||||
| #include <memory> | ||||
| #include <wrl/client.h> | ||||
| #include <xaudio2.h> | ||||
| 
 | ||||
| Log_SetChannel(XAudio2AudioStream); | ||||
| 
 | ||||
| namespace { | ||||
| 
 | ||||
| class XAudio2AudioStream final : public AudioStream, private IXAudio2VoiceCallback | ||||
| { | ||||
| public: | ||||
|   XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch); | ||||
|   ~XAudio2AudioStream(); | ||||
| 
 | ||||
|   void SetPaused(bool paused) override; | ||||
|   void SetOutputVolume(u32 volume) override; | ||||
| 
 | ||||
|   bool OpenDevice(u32 latency_ms); | ||||
|   void CloseDevice(); | ||||
|   void EnqueueBuffer(); | ||||
| 
 | ||||
| private: | ||||
|   enum : u32 | ||||
|   { | ||||
|     NUM_BUFFERS = 2, | ||||
|     INTERNAL_BUFFER_SIZE = 512, | ||||
|   }; | ||||
| 
 | ||||
|   ALWAYS_INLINE bool IsOpen() const { return static_cast<bool>(m_xaudio); } | ||||
| 
 | ||||
|   // Inherited via IXAudio2VoiceCallback
 | ||||
|   void __stdcall OnVoiceProcessingPassStart(UINT32 BytesRequired) override; | ||||
|   void __stdcall OnVoiceProcessingPassEnd(void) override; | ||||
|   void __stdcall OnStreamEnd(void) override; | ||||
|   void __stdcall OnBufferStart(void* pBufferContext) override; | ||||
|   void __stdcall OnBufferEnd(void* pBufferContext) override; | ||||
|   void __stdcall OnLoopEnd(void* pBufferContext) override; | ||||
|   void __stdcall OnVoiceError(void* pBufferContext, HRESULT Error) override; | ||||
| 
 | ||||
|   Microsoft::WRL::ComPtr<IXAudio2> m_xaudio; | ||||
|   IXAudio2MasteringVoice* m_mastering_voice = nullptr; | ||||
|   IXAudio2SourceVoice* m_source_voice = nullptr; | ||||
| 
 | ||||
|   std::array<std::unique_ptr<SampleType[]>, NUM_BUFFERS> m_enqueue_buffers; | ||||
|   u32 m_enqueue_buffer_size = 0; | ||||
|   u32 m_current_buffer = 0; | ||||
|   bool m_buffer_enqueued = false; | ||||
| 
 | ||||
|   HMODULE m_xaudio2_library = {}; | ||||
|   bool m_com_initialized_by_us = false; | ||||
| }; | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| XAudio2AudioStream::XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch) | ||||
|   : AudioStream(sample_rate, channels, buffer_ms, stretch) | ||||
| { | ||||
|  |  | |||
|  | @ -1,59 +0,0 @@ | |||
| // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
 | ||||
| // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
 | ||||
| 
 | ||||
| #pragma once | ||||
| #include "common/windows_headers.h" | ||||
| #include "util/audio_stream.h" | ||||
| #include <array> | ||||
| #include <cstdint> | ||||
| #include <memory> | ||||
| #include <wrl/client.h> | ||||
| 
 | ||||
| // We need to use the Windows 10 headers otherwise this won't compile.
 | ||||
| #undef _WIN32_WINNT | ||||
| #define _WIN32_WINNT _WIN32_WINNT_WIN10 | ||||
| #include <xaudio2.h> | ||||
| 
 | ||||
| class XAudio2AudioStream final : public AudioStream, private IXAudio2VoiceCallback | ||||
| { | ||||
| public: | ||||
|   XAudio2AudioStream(u32 sample_rate, u32 channels, u32 buffer_ms, AudioStretchMode stretch); | ||||
|   ~XAudio2AudioStream(); | ||||
| 
 | ||||
|   void SetPaused(bool paused) override; | ||||
|   void SetOutputVolume(u32 volume) override; | ||||
| 
 | ||||
|   bool OpenDevice(u32 latency_ms); | ||||
|   void CloseDevice(); | ||||
|   void EnqueueBuffer(); | ||||
| 
 | ||||
| private: | ||||
|   enum : u32 | ||||
|   { | ||||
|     NUM_BUFFERS = 2, | ||||
|     INTERNAL_BUFFER_SIZE = 512, | ||||
|   }; | ||||
| 
 | ||||
|   ALWAYS_INLINE bool IsOpen() const { return static_cast<bool>(m_xaudio); } | ||||
| 
 | ||||
|   // Inherited via IXAudio2VoiceCallback
 | ||||
|   void __stdcall OnVoiceProcessingPassStart(UINT32 BytesRequired) override; | ||||
|   void __stdcall OnVoiceProcessingPassEnd(void) override; | ||||
|   void __stdcall OnStreamEnd(void) override; | ||||
|   void __stdcall OnBufferStart(void* pBufferContext) override; | ||||
|   void __stdcall OnBufferEnd(void* pBufferContext) override; | ||||
|   void __stdcall OnLoopEnd(void* pBufferContext) override; | ||||
|   void __stdcall OnVoiceError(void* pBufferContext, HRESULT Error) override; | ||||
| 
 | ||||
|   Microsoft::WRL::ComPtr<IXAudio2> m_xaudio; | ||||
|   IXAudio2MasteringVoice* m_mastering_voice = nullptr; | ||||
|   IXAudio2SourceVoice* m_source_voice = nullptr; | ||||
| 
 | ||||
|   std::array<std::unique_ptr<SampleType[]>, NUM_BUFFERS> m_enqueue_buffers; | ||||
|   u32 m_enqueue_buffer_size = 0; | ||||
|   u32 m_current_buffer = 0; | ||||
|   bool m_buffer_enqueued = false; | ||||
| 
 | ||||
|   HMODULE m_xaudio2_library = {}; | ||||
|   bool m_com_initialized_by_us = false; | ||||
| }; | ||||
		Loading…
	
		Reference in a new issue
	
	 Stenzek
						Stenzek