diff --git a/ThirdParty/libvgm/include/libvgm/_stdbool.h b/ThirdParty/libvgm/include/libvgm/_stdbool.h new file mode 100644 index 000000000..9237d866c --- /dev/null +++ b/ThirdParty/libvgm/include/libvgm/_stdbool.h @@ -0,0 +1,26 @@ +// custom stdbool.h to for 1-byte bool types +#ifndef __CST_STDBOOL_H__ +#define __CST_STDBOOL_H__ + +#undef __HAVE_STDBOOL_H__ +#if defined __has_include +#if __has_include() +#define __HAVE_STDBOOL_H__ 1 +#endif +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +#define __HAVE_STDBOOL_H__ 1 +#endif + +#if defined(__HAVE_STDBOOL_H__) +#include +#elif !defined(__cplusplus) // C++ already has the bool-type + +// the MS VC++ 6 compiler uses a one-byte-type (unsigned char, to be exact), so I'll reproduce this here +typedef unsigned char bool; + +#define false 0x00 +#define true 0x01 + +#endif // ! __cplusplus + +#endif // ! __CST_STDBOOL_H__ diff --git a/ThirdParty/libvgm/include/libvgm/common_def.h b/ThirdParty/libvgm/include/libvgm/common_def.h index 0138532e3..e4850c80a 100644 --- a/ThirdParty/libvgm/include/libvgm/common_def.h +++ b/ThirdParty/libvgm/include/libvgm/common_def.h @@ -2,7 +2,7 @@ #define __COMMON_DEF_H__ #include "stdtype.h" -#include "stdbool.h" +#include "_stdbool.h" #ifndef INLINE #if defined(_MSC_VER) diff --git a/ThirdParty/libvgm/include/libvgm/emu/EmuCores.h b/ThirdParty/libvgm/include/libvgm/emu/EmuCores.h index ad8f1bff0..f0dfc316b 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/EmuCores.h +++ b/ThirdParty/libvgm/include/libvgm/emu/EmuCores.h @@ -15,5 +15,7 @@ #define FCC_NRS_ 0x4E525300 // NewRisingSun #define FCC_VBEL 0x5642454C // Valley Bell #define FCC_CTR_ 0x43545200 // superctr +#define FCC_LAOO 0x4C414F4F // laoo +#define FCC_RN22 0x524E3232 // Mao757 (RN22) #endif // __EMUCORES_H__ diff --git a/ThirdParty/libvgm/include/libvgm/emu/EmuHelper.h b/ThirdParty/libvgm/include/libvgm/emu/EmuHelper.h index ae81bc934..5b52e8bdd 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/EmuHelper.h +++ b/ThirdParty/libvgm/include/libvgm/emu/EmuHelper.h @@ -39,6 +39,7 @@ INLINE void INIT_DEVINF(DEV_INFO* devInf, DEV_DATA* devData, UINT32 sampleRate, devInf->dataPtr = devData; devInf->sampleRate = sampleRate; devInf->devDef = devDef; + devInf->devDecl = NULL; devInf->linkDevCount = 0; devInf->linkDevs = NULL; diff --git a/ThirdParty/libvgm/include/libvgm/emu/EmuStructs.h b/ThirdParty/libvgm/include/libvgm/emu/EmuStructs.h index 9e33d2904..c32c7c711 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/EmuStructs.h +++ b/ThirdParty/libvgm/include/libvgm/emu/EmuStructs.h @@ -6,15 +6,26 @@ extern "C" { #endif +#ifdef _MSC_VER +#pragma warning (disable: 4200) // disable warning for "T arr[];" in structs +#endif + #include "../stdtype.h" #include "snddef.h" -typedef struct _device_definition DEV_DEF; +typedef UINT8 DEV_ID; +typedef struct _device_core_definition DEV_DEF; +typedef struct _device_declaration DEV_DECL; typedef struct _device_info DEV_INFO; typedef struct _device_generic_config DEV_GEN_CFG; typedef struct _device_link_info DEVLINK_INFO; +typedef const char* (*DEVDECLFUNC_NAME)(const DEV_GEN_CFG* devCfg); +typedef UINT16 (*DEVDECLFUNC_CHNCOUNT)(const DEV_GEN_CFG* devCfg); +typedef const char** (*DEVDECLFUNC_CHNNAMES)(const DEV_GEN_CFG* devCfg); + + typedef void (*DEVCB_SRATE_CHG)(void* userParam, UINT32 newSRate); typedef void (*DEVCB_LOG)(void* userParam, void* source, UINT8 level, const char* message); @@ -24,7 +35,7 @@ typedef void (*DEVFUNC_UPDATE)(void* info, UINT32 samples, DEV_SMPL** outputs); typedef void (*DEVFUNC_OPTMASK)(void* info, UINT32 optionBits); typedef void (*DEVFUNC_PANALL)(void* info, const INT16* channelPanVal); typedef void (*DEVFUNC_SRCCB)(void* info, DEVCB_SRATE_CHG SmpRateChgCallback, void* paramPtr); -typedef UINT8 (*DEVFUNC_LINKDEV)(void* info, UINT8 devID, const DEV_INFO* devInfLink); +typedef UINT8 (*DEVFUNC_LINKDEV)(void* info, UINT8 linkID, const DEV_INFO* devInfLink); typedef void (*DEVFUNC_SETLOGCB)(void* info, DEVCB_LOG logFunc, void* userParam); typedef UINT8 (*DEVFUNC_READ_A8D8)(void* info, UINT8 addr); @@ -85,7 +96,7 @@ typedef struct _devdef_readwrite_function void* funcPtr; } DEVDEF_RWFUNC; -struct _device_definition +struct _device_core_definition { const char* name; // name of the device const char* author; // author/origin of emulation @@ -106,18 +117,27 @@ struct _device_definition const DEVDEF_RWFUNC* rwFuncs; // terminated by (funcPtr == NULL) }; // DEV_DEF +struct _device_declaration +{ + DEV_ID deviceID; // device ID (DEVID_ constant), for device enumeration + DEVDECLFUNC_NAME name; // return name of the device + DEVDECLFUNC_CHNCOUNT channelCount; // return number of channels (for muting / panning) + DEVDECLFUNC_CHNNAMES channelNames; // return list of names for each channel or NULL (no special channel names) + const DEV_DEF* cores[]; // list of supported sound cores, terminated by NULL pointer +}; // DEV_DECL struct _device_info { - DEV_DATA* dataPtr; // points to chip data structure - UINT32 sampleRate; - const DEV_DEF* devDef; + DEV_DATA* dataPtr; // points to chip data structure + UINT32 sampleRate; // sample rate of the Update() function + const DEV_DEF* devDef; // points to device definition + const DEV_DECL* devDecl; // points to device declaration (will be NULL when calling DEV_DEV::Start() directly) UINT32 linkDevCount; // number of link-able devices DEVLINK_INFO* linkDevs; // [freed by caller] }; // DEV_INFO struct _device_link_info { - UINT8 devID; // device ID (DEVID_ constant) + DEV_ID devID; // device ID (DEVID_ constant) UINT8 linkID; // device link ID DEV_GEN_CFG* cfg; // pointer to DEV_GEN_CFG structures and derivates [freed by caller] }; // DEVLINK_INFO diff --git a/ThirdParty/libvgm/include/libvgm/emu/Resampler.h b/ThirdParty/libvgm/include/libvgm/emu/Resampler.h index cad43b899..e4a791b77 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/Resampler.h +++ b/ThirdParty/libvgm/include/libvgm/emu/Resampler.h @@ -10,24 +10,28 @@ extern "C" #include "snddef.h" // for DEV_SMPL #include "EmuStructs.h" -typedef struct _waveform_32bit_stereo +typedef struct _waveform_32bit_stereo WAVE_32BS; +typedef struct _resampling_state RESMPL_STATE; + +typedef void (*RESAMPLER_FUNC)(RESMPL_STATE* CAA, UINT32 length, WAVE_32BS* retSample); + +struct _waveform_32bit_stereo { DEV_SMPL L; DEV_SMPL R; -} WAVE_32BS; -typedef struct _resampling_state +}; +// Resampler Modes +#define RSMODE_LINEAR 0x00 // linear interpolation (good quality) +#define RSMODE_NEAREST 0x01 // nearest-neighbour (low quality) +#define RSMODE_LUP_NDWN 0x02 // nearest-neighbour downsampling, interpolation upsampling +struct _resampling_state { UINT32 smpRateSrc; UINT32 smpRateDst; INT16 volumeL; INT16 volumeR; - // Resampler Type: - // 00 - Old - // 01 - Upsampling - // 02 - Copy - // 03 - Downsampling - UINT8 resampleMode; // can be FF [auto] or Resampler Type - UINT8 resampler; + UINT8 resampleMode; // see RSMODE_ constants + RESAMPLER_FUNC resampler; DEVFUNC_UPDATE StreamUpdate; void* su_DataPtr; UINT32 smpP; // Current Sample (Playback Rate) @@ -37,7 +41,7 @@ typedef struct _resampling_state WAVE_32BS nSmpl; // Next Sample UINT32 smplBufSize; DEV_SMPL* smplBufs[2]; -} RESMPL_STATE; +}; // ---- resampler helper functions (for quick/comfortable initialization) ---- /** diff --git a/ThirdParty/libvgm/include/libvgm/emu/SoundDevs.h b/ThirdParty/libvgm/include/libvgm/emu/SoundDevs.h index 10e0d9d6e..7d7feca7a 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/SoundDevs.h +++ b/ThirdParty/libvgm/include/libvgm/emu/SoundDevs.h @@ -42,5 +42,8 @@ #define DEVID_X1_010 0x26 #define DEVID_C352 0x27 #define DEVID_GA20 0x28 +#define DEVID_MIKEY 0x29 +#define DEVID_K007232 0x2A +#define DEVID_K005289 0x2B #endif // __SOUNDDEVS_H__ diff --git a/ThirdParty/libvgm/include/libvgm/emu/SoundEmu.h b/ThirdParty/libvgm/include/libvgm/emu/SoundEmu.h index cb39cd8f9..3cee0e458 100644 --- a/ThirdParty/libvgm/include/libvgm/emu/SoundEmu.h +++ b/ThirdParty/libvgm/include/libvgm/emu/SoundEmu.h @@ -10,14 +10,25 @@ extern "C" #include "EmuStructs.h" /** - * @brief Retrieve a list of all available sound cores for a device. + * @brief Retrieve a list of all available sound cores for a device. Uses built-in sound devices. + * [deprecated - use SndEmu_GetDevDecl instead] * * @param deviceID ID of the sound device (see DEVID_ constants in SoundDevs.h) * @return an array of DEV_DEF* that is terminated by a NULL pointer */ -const DEV_DEF** SndEmu_GetDevDefList(UINT8 deviceID); +const DEV_DEF* const* SndEmu_GetDevDefList(DEV_ID deviceID); /** - * @brief Initializes emulation for a sound device. + * @brief Return the device declaration of a sound device. + * Devices in the user-specified device list take priority. + * + * @param deviceID ID of the sound device (see DEVID_ constants in SoundDevs.h) + * @param userDevList user-supplied sound device list, must be terminated with a NULL pointer, list can be NULL + * @param opts option flags, see EST_OPT constants + * @return pointer to device declaration or NULL if the device is not found + */ +const DEV_DECL* SndEmu_GetDevDecl(DEV_ID deviceID, const DEV_DECL** userDevList, UINT8 opts); +/** + * @brief Initializes emulation for a sound device. Uses built-in sound devices. * * @param deviceID ID of the sound device to be emulated (see DEVID constants in SoundDevs.h) * @param cfg chip-dependent configuration structure, contains various settings @@ -25,7 +36,20 @@ const DEV_DEF** SndEmu_GetDevDefList(UINT8 deviceID); * caller has to free information about linkable devices * @return error code. 0 = success, see EERR constants */ -UINT8 SndEmu_Start(UINT8 deviceID, const DEV_GEN_CFG* cfg, DEV_INFO* retDevInf); +UINT8 SndEmu_Start(DEV_ID deviceID, const DEV_GEN_CFG* cfg, DEV_INFO* retDevInf); +/** + * @brief Initializes emulation for a sound device. + * Devices in the user-specified device list take priority with fallback to the default list for missing cores. + * + * @param deviceID ID of the sound device to be emulated (see DEVID constants in SoundDevs.h) + * @param cfg chip-dependent configuration structure, contains various settings + * @param retDevInf pointer to DEV_INFO structure that gets filled with device information, + * caller has to free information about linkable devices + * @param userDevList user-supplied sound device list, must be terminated with a NULL pointer, list can be NULL + * @param opts option flags, see EST_OPT constants + * @return error code. 0 = success, see EERR constants + */ +UINT8 SndEmu_Start2(DEV_ID deviceID, const DEV_GEN_CFG* cfg, DEV_INFO* retDevInf, const DEV_DECL** userDevList, UINT8 opts); /** * @brief Deinitializes the sound core. * @@ -62,9 +86,15 @@ UINT8 SndEmu_GetDeviceFunc(const DEV_DEF* devInf, UINT8 funcType, UINT8 rwType, * ONLY used when long names are enabled * @return pointer to name of the device */ -const char* SndEmu_GetDevName(UINT8 deviceID, UINT8 opts, const DEV_GEN_CFG* devCfg); +const char* SndEmu_GetDevName(DEV_ID deviceID, UINT8 opts, const DEV_GEN_CFG* devCfg); +extern const DEV_DECL* sndEmu_Devices[]; // list of built-in sound devices, terminated by a NULL pointer + + +#define EST_OPT_NO_DEFAULT 0x01 // SndEmu_Start option: don't use default built-in device list +#define EST_OPT_STRICT_OVRD 0x02 // SndEmu_Start option: strict override (no fallback for missing cores) + #define EERR_OK 0x00 #define EERR_MORE_FOUND 0x01 // success, but more items were found #define EERR_UNK_DEVICE 0xF0 // unknown/invalid device ID diff --git a/ThirdParty/libvgm/include/libvgm/player/droplayer.hpp b/ThirdParty/libvgm/include/libvgm/player/droplayer.hpp index f41827954..c88b7f49c 100644 --- a/ThirdParty/libvgm/include/libvgm/player/droplayer.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/droplayer.hpp @@ -68,8 +68,8 @@ struct DRO_HEADER #define DRO_V2OPL3_ENFORCE 0x02 // always enforce OPL3 mode when the DRO says DualOPL2 struct DRO_PLAY_OPTIONS { + PLR_GEN_OPTS genOpts; UINT8 v2opl3Mode; // DRO v2 DualOPL2 -> OPL3 fixes - UINT32 playbackSpeedScale; // Set to 0x10000 for 1.0 speed, or 16.16 fixed point }; @@ -113,6 +113,7 @@ public: //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; @@ -159,7 +160,7 @@ private: const UINT8* _fileData; // data pointer for quick access, equals _dLoad->GetFileData().data() DRO_HEADER _fileHdr; - std::vector _devTypes; + std::vector _devTypes; std::vector _devPanning; std::vector _devCfgs; UINT8 _realHwType; @@ -178,7 +179,7 @@ private: // tick/sample conversion rates UINT64 _tsMult; UINT64 _tsDiv; - + UINT64 _ttMult; UINT64 _lastTsMult; UINT64 _lastTsDiv; diff --git a/ThirdParty/libvgm/include/libvgm/player/gymplayer.hpp b/ThirdParty/libvgm/include/libvgm/player/gymplayer.hpp index 837ad48aa..35f362e7e 100644 --- a/ThirdParty/libvgm/include/libvgm/player/gymplayer.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/gymplayer.hpp @@ -39,7 +39,7 @@ struct GYM_HEADER struct GYM_PLAY_OPTIONS { - UINT32 playbackSpeedScale; // Set to 0x10000 for 1.0 speed, or 16.16 fixed point + PLR_GEN_OPTS genOpts; }; @@ -48,7 +48,7 @@ class GYMPlayer : public PlayerBase private: struct DevCfg { - UINT8 type; + DEV_ID type; UINT16 volume; std::vector data; }; @@ -89,6 +89,7 @@ public: //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; @@ -159,7 +160,7 @@ private: // tick/sample conversion rates UINT64 _tsMult; UINT64 _tsDiv; - + UINT64 _ttMult; UINT64 _lastTsMult; UINT64 _lastTsDiv; diff --git a/ThirdParty/libvgm/include/libvgm/player/playera.hpp b/ThirdParty/libvgm/include/libvgm/player/playera.hpp index 4c0507e92..04e34ba8e 100644 --- a/ThirdParty/libvgm/include/libvgm/player/playera.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/playera.hpp @@ -10,6 +10,13 @@ #define PLAYSTATE_FADE 0x10 // is fading #define PLAYSTATE_FIN 0x20 // finished playing (file end + fading + trailing silence) +#define PLAYTIME_LOOP_EXCL 0x00 // excluding loops, jumps back in time when the file loops +#define PLAYTIME_LOOP_INCL 0x01 // including loops, no jumping back +#define PLAYTIME_TIME_FILE 0x00 // file time, progresses slower/faster when playback speed is adjusted +#define PLAYTIME_TIME_PBK 0x02 // playback time, file duration will be longer/shorter when playback speed is adjusted +#define PLAYTIME_WITH_FADE 0x10 // include fade out time (looping songs only) +#define PLAYTIME_WITH_SLNC 0x20 // include silence after songs + // TODO: find a proper name for this class class PlayerA { @@ -54,8 +61,8 @@ public: void SetLogCallback(PLAYER_LOG_CB cbFunc, void* cbParam); UINT8 GetState(void) const; UINT32 GetCurPos(UINT8 unit) const; - double GetCurTime(UINT8 includeLoops) const; - double GetTotalTime(UINT8 includeLoops) const; + double GetCurTime(UINT8 flags) const; + double GetTotalTime(UINT8 flags) const; UINT32 GetCurLoop(void) const; double GetLoopTime(void) const; PlayerBase* GetPlayer(void); diff --git a/ThirdParty/libvgm/include/libvgm/player/playerbase.hpp b/ThirdParty/libvgm/include/libvgm/player/playerbase.hpp index d717c7de7..796fd9c5b 100644 --- a/ThirdParty/libvgm/include/libvgm/player/playerbase.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/playerbase.hpp @@ -2,7 +2,7 @@ #define __PLAYERBASE_HPP__ #include "../stdtype.h" -#include "../emu/EmuStructs.h" // for DEV_GEN_CFG +#include "../emu/EmuStructs.h" // for DEV_DECL, DEV_GEN_CFG #include "../emu/Resampler.h" // for WAVE_32BS #include "../utils/DataLoader.h" #include @@ -61,11 +61,12 @@ struct PLR_SONG_INFO struct PLR_DEV_INFO { UINT32 id; // device ID - UINT8 type; // device type + DEV_ID type; // device type UINT8 instance; // instance ID of this device type (0xFF -> N/A for this format) UINT16 volume; // output volume (0x100 = 100%) UINT32 core; // FCC of device emulation core UINT32 smplRate; // current sample rate (0 if not running) + const DEV_DECL* devDecl; // device declaration const DEV_GEN_CFG* devCfg; // device configuration parameters }; @@ -79,7 +80,7 @@ struct PLR_PAN_OPTS INT16 chnPan[2][32]; // channel panning [TODO: rethink how this should be really configured] }; -#define PLR_DEV_ID(chip, instance) (0x80000000 | (instance << 16) | (chip << 0)) +#define PLR_DEV_ID(chip, instance) (0x80000000U | (instance << 16) | (chip << 0)) struct PLR_DEV_OPTS { @@ -92,6 +93,11 @@ struct PLR_DEV_OPTS PLR_PAN_OPTS panOpts; }; +struct PLR_GEN_OPTS +{ + UINT32 pbSpeed; // playback speed (16.16 fixed point scale, 0x10000 = 100%) +}; + // --- concept --- // - Player class does file rendering at fixed volume (but changeable speed) @@ -120,12 +126,14 @@ public: virtual UINT8 SetDeviceMuting(UINT32 id, const PLR_MUTE_OPTS& muteOpts) = 0; virtual UINT8 GetDeviceMuting(UINT32 id, PLR_MUTE_OPTS& muteOpts) const = 0; // player-specific options - //virtual UINT8 SetPlayerOptions(const ###_PLAY_OPTIONS& playOpts) = 0; - //virtual UINT8 GetPlayerOptions(###_PLAY_OPTIONS& playOpts) const = 0; + //virtual UINT8 SetPlayerOptions(const PLR_GEN_OPTS& playOpts) = 0; + //virtual UINT8 GetPlayerOptions(PLR_GEN_OPTS& playOpts) const = 0; virtual UINT32 GetSampleRate(void) const; virtual UINT8 SetSampleRate(UINT32 sampleRate); + virtual double GetPlaybackSpeed(void) const; virtual UINT8 SetPlaybackSpeed(double speed); + virtual void SetUserDevices(const DEV_DECL** userDevList, UINT8 devStartOpts); virtual void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); virtual void SetFileReqCallback(PLAYER_FILEREQ_CB cbFunc, void* cbParam); virtual void SetLogCallback(PLAYER_LOG_CB cbFunc, void* cbParam); @@ -149,6 +157,8 @@ public: protected: UINT32 _outSmplRate; + const DEV_DECL** _userDevList; + UINT8 _devStartOpts; PLAYER_EVENT_CB _eventCbFunc; void* _eventCbParam; PLAYER_FILEREQ_CB _fileReqCbFunc; diff --git a/ThirdParty/libvgm/include/libvgm/player/s98player.hpp b/ThirdParty/libvgm/include/libvgm/player/s98player.hpp index 23a499480..47ff13c6c 100644 --- a/ThirdParty/libvgm/include/libvgm/player/s98player.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/s98player.hpp @@ -35,7 +35,7 @@ struct S98_DEVICE }; struct S98_PLAY_OPTIONS { - UINT32 playbackSpeedScale; // Set to 0x10000 for 1.0 speed, or 16.16 fixed point + PLR_GEN_OPTS genOpts; }; @@ -89,6 +89,7 @@ public: //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; @@ -158,11 +159,11 @@ private: // tick/sample conversion rates UINT64 _tsMult; UINT64 _tsDiv; - + UINT64 _ttMult; UINT64 _lastTsMult; UINT64 _lastTsDiv; - static const UINT8 _OPT_DEV_LIST[_OPT_DEV_COUNT]; // list of configurable libvgm devices + static const DEV_ID _OPT_DEV_LIST[_OPT_DEV_COUNT]; // list of configurable libvgm devices S98_PLAY_OPTIONS _playOpts; PLR_DEV_OPTS _devOpts[_OPT_DEV_COUNT * 2]; // space for 2 instances per chip diff --git a/ThirdParty/libvgm/include/libvgm/player/vgmplayer.hpp b/ThirdParty/libvgm/include/libvgm/player/vgmplayer.hpp index ee3da9867..6e0ed0a79 100644 --- a/ThirdParty/libvgm/include/libvgm/player/vgmplayer.hpp +++ b/ThirdParty/libvgm/include/libvgm/player/vgmplayer.hpp @@ -42,10 +42,10 @@ struct VGM_HEADER struct VGM_PLAY_OPTIONS { + PLR_GEN_OPTS genOpts; UINT32 playbackHz; // set to 60 (NTSC) or 50 (PAL) for region-specific song speed adjustment // Note: requires VGM_HEADER.recordHz to be non-zero to work. UINT8 hardStopOld; // enforce silence at end of old VGMs (<1.50), fixes Key Off events being trimmed off - UINT32 playbackSpeedScale; // Set to 0x10000 for 1.0 speed, or 16.16 fixed point }; @@ -61,10 +61,12 @@ public: { VGM_BASEDEV base; UINT8 vgmChipType; - UINT8 chipType; + DEV_ID chipType; UINT8 chipID; UINT32 flags; size_t optID; + size_t cfgID; + DEVFUNC_READ_A8D8 read8; // read 8-bit data from 8-bit register/offset (required by K007232) DEVFUNC_WRITE_A8D8 write8; // write 8-bit data to 8-bit register/offset DEVFUNC_WRITE_A16D8 writeM8; // write 8-bit data to 16-bit memory offset DEVFUNC_WRITE_A8D16 writeD16; // write 16-bit data to 8-bit register/offset @@ -87,12 +89,6 @@ public: }; protected: - struct HDR_CHIP_DEF - { - UINT8 devType; - UINT16 volume; - UINT32 clock; - }; struct XHDR_DATA32 { UINT8 type; @@ -109,7 +105,7 @@ protected: { size_t deviceID; // index for _devices array UINT8 vgmChipType; - UINT8 type; + DEV_ID type; UINT8 instance; std::vector cfgData; }; @@ -167,6 +163,7 @@ public: //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); //void SetFileReqCallback(PLAYER_FILEREQ_CB cbFunc, void* cbParam); @@ -262,7 +259,7 @@ protected: void Cmd_SegaPCM_Mem(void); // command C0 - SegaPCM memory write void Cmd_RF5C_Mem(void); // command C1/C2 - RF5C68/164 memory write void Cmd_RF5C_Reg(void); // command B0/B1 - RF5C68/164 register write - void Cmd_PWM_Reg(void); // command B2 - PWM register write (4-bit offset, 12-bit data) + void Cmd_Ofs4_Data12(void); // command B2/42 - PWM/K005289 register write (4-bit offset, 12-bit data) void Cmd_QSound_Reg(void); // command C4 - QSound register write (16-bit data, 8-bit offset) static void WriteQSound_A(CHIP_DEVICE* cDev, UINT8 ofs, UINT16 data); // write by calling write8 static void WriteQSound_B(CHIP_DEVICE* cDev, UINT8 ofs, UINT16 data); // write by calling writeD16 @@ -271,6 +268,7 @@ protected: void Cmd_YMW_Bank(void); // command C3 - YMW258 bank write (Ofs8_Data16 with remapping) void Cmd_SAA_Reg(void); // command BD - SAA1099 register write (Reg8_Data8 with remapping) void Cmd_OKIM6295_Reg(void); // command B8 - OKIM6295 register write (Ofs8_Data8 with minor fixes) + void Cmd_K007232_Reg(void); // command 41 - K007232 register write (Ofs8_Data8 with minor fixes) void Cmd_AY_Stereo(void); // command 30 - set AY8910 stereo mask CPCONV* _cpcUTF16; // UTF-16 LE -> UTF-8 codepage conversion @@ -278,12 +276,13 @@ protected: DATA_LOADER *_dLoad; const UINT8* _fileData; // data pointer for quick access, equals _dLoad->GetFileData().data() std::vector _yrwRom; // cache for OPL4 sample ROM (yrw801.rom) + UINT8 _shownCmdWarnings[0x100]; enum { _HDR_BUF_SIZE = 0x100, - _OPT_DEV_COUNT = 0x29, - _CHIP_COUNT = 0x29, + _OPT_DEV_COUNT = 0x2c, + _CHIP_COUNT = 0x2c, _PCM_BANK_COUNT = 0x40 }; @@ -319,17 +318,15 @@ protected: UINT64 _tsMult; UINT64 _tsDiv; UINT64 _ttMult; - UINT64 _ttDiv; - UINT64 _lastTsMult; UINT64 _lastTsDiv; - UINT32 _filePos; - UINT32 _fileTick; - UINT32 _playTick; - UINT32 _playSmpl; - UINT32 _curLoop; - UINT32 _lastLoopTick; + UINT32 _filePos; // file offset of next command to parse + UINT32 _fileTick; // tick time of next command to parse + UINT32 _playTick; // tick time when last parsing was issued (up to 1 Render() call behind current position) + UINT32 _playSmpl; // sample time + UINT32 _curLoop; // current repetition, 0 = first playthrough, 1 = repeating 1st time + UINT32 _lastLoopTick; // tick time of last loop, used for "0-sample-loop" detection UINT8 _playState; UINT8 _psTrigger; // used to temporarily trigger special commands @@ -338,8 +335,8 @@ protected: //PLAYER_FILEREQ_CB _fileReqCbFunc; //void* _fileReqCbParam; - static const UINT8 _OPT_DEV_LIST[_OPT_DEV_COUNT]; // list of configurable libvgm devices (different from VGM chip list] - static const UINT8 _DEV_LIST[_CHIP_COUNT]; // VGM chip ID -> libvgm device ID + static const DEV_ID _OPT_DEV_LIST[_OPT_DEV_COUNT]; // list of configurable libvgm devices (different from VGM chip list] + static const DEV_ID _DEV_LIST[_CHIP_COUNT]; // VGM chip ID -> libvgm device ID static const UINT32 _CHIPCLK_OFS[_CHIP_COUNT]; // file offsets for chip clocks in VGM header static const UINT16 _CHIP_VOLUME[_CHIP_COUNT]; // default volume for chips static const UINT16 _PB_VOL_AMNT[_CHIP_COUNT]; // amount of the chip's playback volume in overall gain