From 5a859a9e2dcacbbfb6ba00ba4b742700653167a2 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Wed, 4 Oct 2023 13:07:42 +0200 Subject: [PATCH] port sound and music --- docs/progress.svg | 164 +++++++++---------- docs/progress.txt | 91 ++++++----- meson.build | 5 + src/game/camera.c | 1 + src/global/const.h | 3 + src/global/funcs.h | 39 +---- src/global/types.h | 9 +- src/global/vars.h | 3 + src/inject_exec.c | 61 ++++++- src/lib/dsound.h | 11 ++ src/lib/winmm.c | 11 ++ src/lib/winmm.h | 19 +++ src/main_dll.c | 11 ++ src/main_exe.c | 85 ++++++---- src/specific/s_pauld.c | 278 +++++++++++++++++++++++++++++++ src/specific/s_pauld.h | 37 +++++ src/specific/s_sndpc.c | 317 +++++++++++++++++++++++++++++++++++ src/specific/s_sndpc.h | 26 +++ src/specific/s_sound.c | 354 ++++++++++++++++++++++++++++++++++++++++ src/specific/s_sound.h | 31 ++++ src/specific/s_winvid.c | 64 ++++++++ src/specific/s_winvid.h | 10 ++ 22 files changed, 1426 insertions(+), 204 deletions(-) create mode 100644 src/lib/dsound.h create mode 100644 src/lib/winmm.c create mode 100644 src/lib/winmm.h create mode 100644 src/specific/s_pauld.c create mode 100644 src/specific/s_pauld.h create mode 100644 src/specific/s_sndpc.c create mode 100644 src/specific/s_sndpc.h create mode 100644 src/specific/s_sound.c create mode 100644 src/specific/s_sound.h create mode 100644 src/specific/s_winvid.c create mode 100644 src/specific/s_winvid.h diff --git a/docs/progress.svg b/docs/progress.svg index 209628c0..f23e1153 100644 --- a/docs/progress.svg +++ b/docs/progress.svg @@ -69,10 +69,10 @@ Tomb2.exe progress according to the physical function order: -2.33% (28) · 95.25% (1143) · 0.67% (8) · 1.75% (21) +5.42% (65) · 92.17% (1106) · 0.67% (8) · 1.75% (21) - - + + @@ -319,7 +319,7 @@ void __cdecl BigEelControl(int16_t item_num); void __cdecl EelControl(int16_t item_num); int32_t __cdecl ItemNearLara(struct PHD_3DPOS *pos, int32_t distance); -void __cdecl SoundEffects(void); +void __cdecl Sound_Update(void); int16_t __cdecl DoBloodSplat(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num); void __cdecl DoLotsOfBlood(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num, int32_t num); void __cdecl ControlBlood1(int16_t fx_num); @@ -916,10 +916,10 @@ HRESULT __stdcall EnumDisplayModesCallback(LPDDSDESC lpDDSurfaceDesc, LPVOID lpContext); bool __cdecl WinVidInit(void); bool __cdecl WinVidGetDisplayAdapters(void); -void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); +void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); bool __cdecl EnumerateDisplayAdapters(struct DISPLAY_ADAPTER_LIST *displayAdapterList); BOOL __stdcall EnumDisplayAdaptersCallback(GUID *lpGUID, LPTSTR lpDriverDescription, LPTSTR lpDriverName, LPVOID lpContext); -void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); +void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); bool __cdecl WinVidRegisterGameWindowClass(void); LRESULT __stdcall WinVidGameWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); void __cdecl WinVidResizeGameWindow(HWND hWnd, int32_t edge, LPRECT rect); @@ -949,7 +949,7 @@ bool __cdecl WinInputInit(void); bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); -void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); +void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); void __cdecl DInputKeyboardCreate(void); void __cdecl DInputKeyboardRelease(void); @@ -970,24 +970,24 @@ sub_447B30 sub_447B40 sub_447B90 -SOUND_ADAPTER_NODE *__cdecl GetSoundAdapter(GUID *lpGuid); -void __cdecl WinSndFreeAllSamples(void); -bool __cdecl WinSndMakeSample(DWORD sampleIdx, LPWAVEFORMATEX format, const LPVOID data, DWORD dataSize); -bool __cdecl WinSndIsChannelPlaying(DWORD channel); -int32_t __cdecl WinSndPlaySample(DWORD sampleIdx, int32_t volume, DWORD pitch, int32_t pan, DWORD flags); -int32_t __cdecl WinSndGetFreeChannelIndex(void); -void __cdecl WinSndAdjustVolumeAndPan(int32_t channel, int32_t volume, int32_t pan); -void __cdecl WinSndAdjustPitch(int32_t channel, DWORD pitch); -void __cdecl WinSndStopSample(int32_t channel); +struct SOUND_ADAPTER_NODE *__cdecl S_Audio_Sample_GetAdapter(GUID *guid); +void __cdecl S_Audio_Sample_CloseAllTracks(void); +bool __cdecl S_Audio_Sample_Load(int32_t sample_id, LPWAVEFORMATEX format, const void *data, int32_t data_size); +bool __cdecl S_Audio_Sample_IsTrackPlaying(int32_t track_id); +int32_t __cdecl S_Audio_Sample_Play(int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan, int32_t flags); +int32_t __cdecl S_Audio_Sample_GetFreeTrackIndex(void); +void __cdecl S_Audio_Sample_AdjustTrackVolumeAndPan(int32_t track_id, int32_t volume, int32_t pan); +void __cdecl S_Audio_Sample_AdjustTrackPitch(int32_t track_id, int32_t pitch); +void __cdecl S_Audio_Sample_CloseTrack(int32_t track_id); sub_447FA0 -bool __cdecl WinSndInit(void); -bool __cdecl DSoundEnumerate(SOUND_ADAPTER_LIST *adapterList); -BOOL __stdcall DSoundEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); -void __cdecl WinSndStart(HWND hWnd); -bool __cdecl DSoundCreate(GUID *lpGuid); -bool __cdecl DSoundBufferTest(void); -void __cdecl WinSndFinish(void); -bool __cdecl WinSndIsSoundEnabled(void); +bool __cdecl S_Audio_Sample_Init(void); +bool __cdecl S_Audio_Sample_DSoundEnumerate(struct SOUND_ADAPTER_LIST *adapter_list); +BOOL __stdcall S_Audio_Sample_DSoundEnumCallback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context); +void __cdecl S_Audio_Sample_Init2(HWND hwnd); +bool __cdecl S_Audio_Sample_DSoundCreate(GUID *guid); +bool __cdecl S_Audio_Sample_DSoundBufferTest(void); +void __cdecl S_Audio_Sample_Shutdown(void); +bool __cdecl S_Audio_Sample_IsEnabled(void); sub_448410 sub_448420 void __cdecl CreateScreenBuffers(void); @@ -1187,23 +1187,23 @@ void __cdecl CheckCheatMode(void); void __cdecl S_SaveSettings(void); void __cdecl S_LoadSettings(void); -int32_t __cdecl S_SoundPlaySample(int32_t channel, UINT16 volume, int32_t pitch, int32_t pan); -int32_t __cdecl S_Sound_CalculateSampleVolume(DWORD volume); -int32_t __cdecl S_Sound_CalculateSamplePan(int16_t pan); -int32_t __cdecl S_SoundPlaySampleLooped(int32_t channel, UINT16 volume, DWORD pitch, int32_t pan); -void __cdecl S_SoundSetPanAndVolume(int32_t channel, int32_t pan, UINT16 volume); -void __cdecl S_SoundSetPitch(int32_t channel, DWORD pitch); -void __cdecl S_SoundSetMasterVolume(DWORD volume); -void __cdecl S_SoundStopSample(int32_t channel); -void __cdecl S_SoundStopAllSamples(void); -BOOL __cdecl S_SoundSampleIsPlaying(int32_t channel); -bool __cdecl CD_Init(void); -void __cdecl CD_Cleanup(void); -void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); -void __cdecl S_CDStop(void); -BOOL __cdecl StartSyncedAudio(int32_t trackID); -DWORD __cdecl S_CDGetLoc(void); -void __cdecl Music_SetVolume(int32_t volume); +int32_t __cdecl Sound_Play(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); +int32_t __cdecl Sound_CalculateSampleVolume(int32_t volume); +int32_t __cdecl Sound_CalculateSamplePan(int16_t pan); +int32_t __cdecl Sound_PlayLooped(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); +void __cdecl Sound_SetPanAndVolume(int32_t sample_id, int32_t pan, uint16_t volume); +void __cdecl Sound_SetPitch(int32_t sample_id, int32_t pitch); +void __cdecl Sound_SetMasterVolume(int32_t volume); +void __cdecl Sound_StopSample(int32_t sample_id); +void __cdecl Sound_StopAllSamples(void); +BOOL __cdecl Sound_SampleIsPlaying(int32_t sample_id); +bool __cdecl CD_Init(void); +void __cdecl CD_Cleanup(void); +void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); +void __cdecl S_CDStop(void); +BOOL __cdecl StartSyncedAudio(int32_t trackID); +DWORD __cdecl S_CDGetLoc(void); +void __cdecl Music_SetVolume(int32_t volume); void __cdecl CopyBitmapPalette(RGB888 *srcPal, BYTE *srcBitmap, int32_t bitmapSize, RGB888 *destPal); BYTE __cdecl FindNearestPaletteEntry(RGB888 *palette, int32_t red, int32_t green, int32_t blue, bool ignoreSysPalette); void __cdecl SyncSurfacePalettes(void *srcData, int32_t width, int32_t height, int32_t srcPitch, RGB888 *srcPalette, void *dstData, int32_t dstPitch, RGB888 *dstPalette, bool preserveSysPalette); @@ -1281,10 +1281,10 @@ Tomb2.exe progress according to the function sizes: -2.91% · 96.76% · 0.02% · 0.31% +3.86% · 95.81% · 0.02% · 0.31% - - + + @@ -1531,7 +1531,7 @@ void __cdecl FireHarpoon(void); void __cdecl Output_InsertFlatRect_Sorted(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t z, uint8_t color_idx); void __cdecl ControlTwinkle(int16_t fx_num); -void __cdecl WinSndStart(HWND hWnd); +void __cdecl S_Audio_Sample_Init2(HWND hwnd); void __cdecl SE_GraphicsDlgInit(HWND hwndDlg); void __cdecl SpinningBlade(int16_t item_num); void __cdecl LiftFloorCeiling(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *floor, int32_t *ceiling); @@ -1625,7 +1625,7 @@ int16_t __cdecl TitleSequence(void); void __cdecl Inv_RingInit(struct RING_INFO *ring, int16_t type, struct INVENTORY_ITEM **list, int16_t qty, int16_t current, struct IMOTION_INFO *imo); void __cdecl ScreenShotPCX(void); -bool __cdecl WinSndMakeSample(DWORD sampleIdx, LPWAVEFORMATEX format, const LPVOID data, DWORD dataSize); +bool __cdecl S_Audio_Sample_Load(int32_t sample_id, LPWAVEFORMATEX format, const void *data, int32_t data_size); void __cdecl lara_as_compress(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl CopterControl(int16_t item_num); void __cdecl ControlLavaBlob(int16_t fx_num); @@ -1676,7 +1676,7 @@ void __cdecl CalculateWibbleTable(void); void __cdecl Camera_RefreshFromTrigger(int16_t type, int16_t *data); int32_t __cdecl LaraTestWaterStepOut(struct ITEM_INFO *item, struct COLL_INFO *coll); -int32_t __cdecl WinSndPlaySample(DWORD sampleIdx, int32_t volume, DWORD pitch, int32_t pan, DWORD flags); +int32_t __cdecl S_Audio_Sample_Play(int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan, int32_t flags); void __cdecl LavaBurn(struct ITEM_INFO *item); void __cdecl RenderFinish(bool needToClearTextures); bool __cdecl DInputJoystickCreate(void); @@ -1685,7 +1685,7 @@ void __cdecl BigBowlControl(int16_t item_num); void __cdecl lara_slide_slope(struct ITEM_INFO *item, struct COLL_INFO *coll); bool __cdecl WinVidSpinMessageLoop(bool needWait); -BOOL __stdcall DSoundEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); +BOOL __stdcall S_Audio_Sample_DSoundEnumCallback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context); int32_t __cdecl TestWall(struct ITEM_INFO *item, int32_t front, int32_t right, int32_t down); int32_t __cdecl SkidooCheckGeton(int16_t item_num, struct COLL_INFO *coll); BOOL __cdecl SelectDrive(void); @@ -1734,7 +1734,7 @@ void __cdecl Output_QuickSort(int32_t left, int32_t right); void __cdecl LavaSpray(int16_t item_num); void __cdecl SmashWindow(int16_t item_num); -bool __cdecl DSoundBufferTest(void); +bool __cdecl S_Audio_Sample_DSoundBufferTest(void); BOOL __cdecl S_ReloadLevelGraphics(BOOL reloadPalettes, BOOL reloadTexPages); void __thiscall SE_LoadBitmapResource(BITMAP_RESOURCE *bmpRsrc, LPCTSTR lpName); void __cdecl Splash(struct ITEM_INFO *item); @@ -1821,7 +1821,7 @@ void __cdecl InitialiseFinalLevel(void); void __cdecl CreateClipper(void); void __cdecl ItemNewRoom(int16_t item_num, int16_t room_num); -bool __cdecl WinSndInit(void); +bool __cdecl S_Audio_Sample_Init(void); void __cdecl LaraCollideStop(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl swap_meshes_with_meshswap3(struct ITEM_INFO *item); void __cdecl LoadDemoExternal(LPCTSTR levelName); @@ -1853,7 +1853,7 @@ void __cdecl EffectNewRoom(int16_t fx_num, int16_t room_num); void __cdecl SE_AdvancedDlgUpdate(HWND hwndDlg); int32_t __cdecl GetFrames(struct ITEM_INFO *item, int16_t *frmptr[], int32_t *rate); -void __cdecl Music_SetVolume(int32_t volume); +void __cdecl Music_SetVolume(int32_t volume); int16_t *__cdecl Output_InsertObjectGT4_ZBuffered(int16_t *obj_ptr, int32_t num, enum SORT_TYPE sort_type); void __cdecl extra_as_sharkkill(struct ITEM_INFO *item, struct COLL_INFO *coll); bool __cdecl GetRegistryGuidValue(LPCTSTR lpValueName, GUID *value, GUID *defaultValue); @@ -1893,7 +1893,7 @@ void __cdecl lara_as_tread(struct ITEM_INFO *item, struct COLL_INFO *coll); int32_t __cdecl Targetable(struct ITEM_INFO *item, AI_INFO *info); void __cdecl lara_as_back(struct ITEM_INFO *item, struct COLL_INFO *coll); -BOOL __cdecl StartSyncedAudio(int32_t trackID); +BOOL __cdecl StartSyncedAudio(int32_t trackID); void __cdecl DrawSpriteItem(struct ITEM_INFO *item); void __cdecl lara_col_fallback(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl ControlBlood1(int16_t fx_num); @@ -1936,7 +1936,7 @@ void __cdecl LaraBubbles(struct ITEM_INFO *item); void __cdecl Door_Collision(int16_t item_num, struct ITEM_INFO *lara_item, struct COLL_INFO *coll); int32_t __cdecl Inv_RequestItem(int32_t itemNum); -bool __cdecl CD_Init(void); +bool __cdecl CD_Init(void); int16_t __cdecl Knife(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE yrot, int16_t room_num); void __cdecl DrawHair(void); void __cdecl lara_as_glide(struct ITEM_INFO *item, struct COLL_INFO *coll); @@ -1958,7 +1958,7 @@ void __cdecl CreatePictureBuffer(void); int32_t __cdecl Box_UpdateLOT(struct LOT_INFO *lot, int32_t expansion); void __cdecl RemoveDrawnItem(int16_t item_num); -void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); +void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); BOOL __cdecl UT_CenterWindow(HWND hWnd); void __cdecl UT_MemBlt(BYTE *dstBuf, DWORD dstX, DWORD dstY, DWORD width, DWORD height, DWORD dstPitch, BYTE *srcBuf, DWORD srcX, DWORD srcY, DWORD srcPitch); bool __cdecl Output_VisibleZClip(struct PHD_VBUF *vtx0, struct PHD_VBUF *vtx1, struct PHD_VBUF *vtx2); @@ -1974,7 +1974,7 @@ bool __cdecl WinVidRegisterGameWindowClass(void); int32_t __cdecl CreateTexturePage(int32_t width, int32_t height, bool alpha); void __cdecl lara_col_swandive(struct ITEM_INFO *item, struct COLL_INFO *coll); -void __cdecl SoundEffects(void); +void __cdecl Sound_Update(void); void __cdecl ControlClockChimes(int16_t item_num); void __cdecl lara_col_death(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl InitialiseObjects(void); @@ -2000,7 +2000,7 @@ void __cdecl DecreaseScreenSize(void); void __cdecl InitialiseGameFlags(void); DWORD __cdecl CalculateCompatibleColor(COLOR_BIT_MASKS *mask, int32_t red, int32_t green, int32_t blue, int32_t alpha); -DWORD __cdecl S_CDGetLoc(void); +DWORD __cdecl S_CDGetLoc(void); bool __cdecl SE_RegisterSetupWindowClass(void); void __fastcall flatA(int32_t y0, int32_t y1, BYTE colorIdx); void __cdecl Inv_RingGetView(struct RING_INFO *ring, struct PHD_3DPOS *viewer); @@ -2063,7 +2063,7 @@ int32_t __cdecl LaraFallen(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl SmashItem(int16_t item_num, int32_t weapon_type); void __cdecl S_SetupBelowWater(BOOL underwater); -void __cdecl CD_Cleanup(void); +void __cdecl CD_Cleanup(void); bool __cdecl TIME_Init(void); LPCTSTR __cdecl GuidBinaryToString(GUID *guid); void __cdecl Creature_Underwater(struct ITEM_INFO *item, int32_t depth); @@ -2105,7 +2105,7 @@ int32_t __cdecl CalculateWindowWidth(int32_t width, int32_t height); DISPLAY_ADAPTER_NODE *__cdecl WinVidGetDisplayAdapter(GUID *lpGuid); DISPLAY_MODE *__thiscall InsertDisplayModeInListHead(DISPLAY_MODE_LIST *modeList); -SOUND_ADAPTER_NODE *__cdecl GetSoundAdapter(GUID *lpGuid); +struct SOUND_ADAPTER_NODE *__cdecl S_Audio_Sample_GetAdapter(GUID *guid); void __cdecl WinStopFMV(bool isPlayback); int32_t __fastcall Math_Atan(int32_t x, int32_t y); int32_t __cdecl Creature_Activate(int16_t item_num); @@ -2115,11 +2115,11 @@ HRESULT __cdecl DDrawSurfaceRestoreLost(LPDDS surface1, LPDDS surface2, bool blank); DWORD __cdecl GetRenderBitDepth(DWORD dwRGBBitCount); void __cdecl S_InsertBackPolygon(int32_t x0, int32_t y0, int32_t x1, int32_t y1); -int32_t __cdecl S_SoundPlaySample(int32_t channel, UINT16 volume, int32_t pitch, int32_t pan); -int32_t __cdecl S_SoundPlaySampleLooped(int32_t channel, UINT16 volume, DWORD pitch, int32_t pan); +int32_t __cdecl Sound_Play(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); +int32_t __cdecl Sound_PlayLooped(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); void __cdecl DrawGameInfo(int32_t timed); bool __thiscall CompareVideoModes(DISPLAY_MODE *mode1, DISPLAY_MODE *mode2); -bool __cdecl WinSndIsChannelPlaying(DWORD channel); +bool __cdecl S_Audio_Sample_IsTrackPlaying(int32_t track_id); HRESULT __cdecl DDrawSurfaceCreate(LPDDSDESC dsp, LPDDS *surface); void __cdecl BitMaskGetNumberOfBits(DWORD bitMask, DWORD *bitDepth, DWORD *bitOffset); void __cdecl GetValidLevelsList(REQUEST_INFO *req); @@ -2159,7 +2159,7 @@ void __cdecl InitialiseRollingBall(int16_t item_num); int32_t __cdecl RenderErrorBox(int32_t errorCode); void __cdecl Shell_ExitSystem(const char *message); -void __cdecl S_SoundStopAllSamples(void); +void __cdecl Sound_StopAllSamples(void); int32_t __cdecl CheckForHoldingState(int32_t state); int32_t __cdecl WeaponObject(int32_t weapon_type); void __cdecl DrawBridgeCeiling(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *height); @@ -2180,10 +2180,10 @@ sub_447170 void __cdecl TempVideoRemove(void); sub_447B40 -int32_t __cdecl WinSndGetFreeChannelIndex(void); +int32_t __cdecl S_Audio_Sample_GetFreeTrackIndex(void); void __cdecl Shell_Shutdown(void); -void __cdecl S_SoundSetPanAndVolume(int32_t channel, int32_t pan, UINT16 volume); -void __cdecl S_CDStop(void); +void __cdecl Sound_SetPanAndVolume(int32_t sample_id, int32_t pan, uint16_t volume); +void __cdecl S_CDStop(void); void __cdecl Output_DrawPolyGTMapPersp(int16_t *obj_ptr); void __cdecl Output_DrawPolyWGTMapPersp(int16_t *obj_ptr); void __cdecl Item_ShiftCol(struct ITEM_INFO *item, struct COLL_INFO *coll); @@ -2216,7 +2216,7 @@ void __cdecl BridgeTilt1Ceiling(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *height); void __cdecl ReadSG(void *pointer, int32_t size); void __cdecl WinVidSetGameWindowSize(int32_t width, int32_t height); -void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); +void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); void __cdecl S_FadeInInventory(BOOL isFade); void __cdecl S_DrawScreenLine(int32_t x, int32_t y, int32_t z, int32_t xLen, int32_t yLen, BYTE colorIdx, D3DCOLOR *gour, uint16_t flags); void __cdecl HWR_GetPageHandles(void); @@ -2246,7 +2246,7 @@ void __cdecl phd_RotX_I(int16_t ang); void __cdecl phd_RotZ_I(int16_t ang); int32_t __cdecl GetRealTrack(int32_t track); -void __cdecl WinSndAdjustPitch(int32_t channel, DWORD pitch); +void __cdecl S_Audio_Sample_AdjustTrackPitch(int32_t track_id, int32_t pitch); void __cdecl S_CalculateStaticLight(int16_t adder); void __cdecl ControlRichochet1(int16_t fx_num); void __cdecl InitialiseFXArray(void); @@ -2265,8 +2265,8 @@ void __cdecl BridgeTilt2Floor(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *height); sub_4471C0 sub_447B90 -void __cdecl WinSndStopSample(int32_t channel); -void __cdecl WinSndFreeAllSamples(void); +void __cdecl S_Audio_Sample_CloseTrack(int32_t track_id); +void __cdecl S_Audio_Sample_CloseAllTracks(void); void __cdecl S_DrawScreenFBox(int32_t sx, int32_t sy, int32_t z, int32_t width, int32_t height, BYTE colorIdx, GOURAUD_FILL *gour, uint16_t flags); void __cdecl Demo_GetInput(void); int32_t __cdecl FlashIt(void); @@ -2279,7 +2279,7 @@ void __cdecl InitialiseMovingBlock(int16_t item_num); void __cdecl DrawBridgeCollision(int16_t item_num, struct ITEM_INFO *laraitem, struct COLL_INFO *coll); void __cdecl T_InitPrint(void); -void __cdecl WinSndAdjustVolumeAndPan(int32_t channel, int32_t volume, int32_t pan); +void __cdecl S_Audio_Sample_AdjustTrackVolumeAndPan(int32_t track_id, int32_t volume, int32_t pan); LPTSTR __cdecl UT_FindArg(LPCTSTR str); uint32_t __fastcall Math_Sqrt(uint32_t n); void __cdecl lara_as_slide(struct ITEM_INFO *item, struct COLL_INFO *coll); @@ -2289,9 +2289,9 @@ void __cdecl HWR_ResetColorKey(void); void __cdecl phd_PutPolygons_I(int16_t *ptr, int32_t clip); void __cdecl SOUND_Init(void); -void __cdecl WinSndFinish(void); +void __cdecl S_Audio_Sample_Shutdown(void); void __cdecl S_UnloadLevelFile(void); -int32_t __cdecl S_Sound_CalculateSampleVolume(DWORD volume); +int32_t __cdecl Sound_CalculateSampleVolume(int32_t volume); LONG __cdecl SetRegistryBoolValue(LPCTSTR lpValueName, bool value); void __cdecl T_AddOutline(struct TEXTSTRING *textstring, int16_t enable, int16_t colour, uint16_t *gourptr, uint16_t flags); void __cdecl DInputKeyboardRelease(void); @@ -2306,7 +2306,7 @@ void __cdecl Inv_RingMotionRadius(struct RING_INFO *ring, int16_t target); LPCTSTR __cdecl GetFullPath(LPCTSTR fileName); void __cdecl ScreenClear(bool isPhdWinSize); -int32_t __cdecl S_Sound_CalculateSamplePan(int16_t pan); +int32_t __cdecl Sound_CalculateSamplePan(int16_t pan); void __cdecl FreeTexturePages(void); void __cdecl SE_PassMessageToImage(HWND hWnd, UINT uMsg, WPARAM wParam); void __cdecl Inv_RingMotionCameraPos(struct RING_INFO *ring, int16_t target); @@ -2347,8 +2347,8 @@ void __cdecl AssaultStop(struct ITEM_INFO *item); int32_t __cdecl GF_DoFrontEndSequence(void); bool __cdecl D3DCreate(void); -void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); -BOOL __cdecl S_SoundSampleIsPlaying(int32_t channel); +void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); +BOOL __cdecl Sound_SampleIsPlaying(int32_t sample_id); bool __cdecl InitTextures(void); void __cdecl lara_col_slide(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl lara_as_climbend(struct ITEM_INFO *item, struct COLL_INFO *coll); @@ -2369,9 +2369,9 @@ void __cdecl StatueFX(struct ITEM_INFO *item); void __cdecl SetChangeFX(struct ITEM_INFO *item); void __cdecl lara_as_reach(struct ITEM_INFO *item, struct COLL_INFO *coll); -bool __cdecl DSoundCreate(GUID *lpGuid); +bool __cdecl S_Audio_Sample_DSoundCreate(GUID *guid); void __cdecl S_DontDisplayPicture(void); -void __cdecl S_SoundSetPitch(int32_t channel, DWORD pitch); +void __cdecl Sound_SetPitch(int32_t sample_id, int32_t pitch); int32_t __cdecl GetFreePaletteIndex(void); int32_t __cdecl GetFreeTexturePageIndex(void); void __thiscall SE_UpdateBitmapPalette(BITMAP_RESOURCE *bmpRsrc, HWND hWnd, HWND hSender); @@ -2382,7 +2382,7 @@ int32_t __fastcall Math_Sin(int16_t angle); bool __cdecl EnumerateDisplayAdapters(struct DISPLAY_ADAPTER_LIST *displayAdapterList); void __cdecl DInputRelease(void); -bool __cdecl DSoundEnumerate(SOUND_ADAPTER_LIST *adapterList); +bool __cdecl S_Audio_Sample_DSoundEnumerate(struct SOUND_ADAPTER_LIST *adapter_list); int32_t __fastcall Math_SinImpl(int16_t angle); int32_t __cdecl GetDebouncedInput(int32_t input); bool __cdecl HWR_VertexBufferFull(void); @@ -2402,7 +2402,7 @@ void __cdecl WinInRunControlPanel(HWND hWnd); sub_44E860 void __cdecl SE_GraphicsAdapterSet(HWND hwndDlg, DISPLAY_ADAPTER_NODE *adapter); -void __cdecl S_SoundStopSample(int32_t channel); +void __cdecl Sound_StopSample(int32_t sample_id); void __cdecl turn180_effect(struct ITEM_INFO *item); void __cdecl invisibility_off(struct ITEM_INFO *item); void __cdecl BridgeFlatFloor(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int32_t *height); @@ -2424,7 +2424,7 @@ void __cdecl lara_col_stepleft(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl lara_col_roll(struct ITEM_INFO *item, struct COLL_INFO *coll); void __cdecl lara_col_swim(struct ITEM_INFO *item, struct COLL_INFO *coll); -void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); +void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); void __cdecl WinVidFinish(void); bool __cdecl S_IntroFMV(LPCTSTR fileName1, LPCTSTR fileName2); LONG __cdecl DeleteRegistryValue(LPCTSTR lpValueName); @@ -2461,13 +2461,13 @@ void __cdecl SeedRandomDraw(int32_t seed); void __cdecl SE_SoundAdapterSet(HWND hwndDlg, SOUND_ADAPTER_NODE *adapter); void __cdecl SE_ControlsJoystickSet(HWND hwndDlg, JOYSTICK_NODE *joystick); -void __cdecl S_SoundSetMasterVolume(DWORD volume); +void __cdecl Sound_SetMasterVolume(int32_t volume); void __cdecl invisibility_on(struct ITEM_INFO *item); void __cdecl dynamic_light_on(struct ITEM_INFO *item); void __cdecl WinVidClearMinWindowSize(void); void __cdecl WinVidClearMaxWindowSize(void); bool __cdecl Direct3DInit(void); -bool __cdecl WinSndIsSoundEnabled(void); +bool __cdecl S_Audio_Sample_IsEnabled(void); int32_t __cdecl LevelCompleteSequence(void); int32_t __cdecl GetRenderHeight(void); int32_t __cdecl GetRenderWidth(void); diff --git a/docs/progress.txt b/docs/progress.txt index 5357a4cc..10b441a0 100644 --- a/docs/progress.txt +++ b/docs/progress.txt @@ -1134,7 +1134,7 @@ typedef struct CINE_FRAME { # game/effects.c 0041C4D0 0000008C -R int32_t __cdecl ItemNearLara(struct PHD_3DPOS *pos, int32_t distance); -0041C560 00000068 -R void __cdecl SoundEffects(void); +0041C560 00000068 -R void __cdecl Sound_Update(void); 0041C5D0 00000059 -R int16_t __cdecl DoBloodSplat(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num); 0041C630 000000A4 -R void __cdecl DoLotsOfBlood(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num, int32_t num); 0041C6E0 00000082 -R void __cdecl ControlBlood1(int16_t fx_num); @@ -1662,11 +1662,11 @@ typedef struct CINE_FRAME { # game/sound.c 0043F380 00000031 -R int32_t __cdecl GetRealTrack(int32_t track); -0043F3C0 00000484 - void __cdecl Sound_Effect(uint32_t sfx_num, const struct PHD_3DPOS *pos, uint32_t flags); -0043F860 0000005E - void __cdecl Sound_StopEffect(int32_t sfx_num); -0043F8C0 00000086 -R void __cdecl SOUND_EndScene(void); -0043F950 00000024 -R void __cdecl SOUND_Stop(void); -0043F980 0000002A -R void __cdecl SOUND_Init(void); +0043F3C0 00000484 - void __cdecl Sound_Effect(int32_t sample_id, const struct PHD_3DPOS *pos, uint32_t flags); +0043F860 0000005E - void __cdecl Sound_StopEffect(int32_t sample_id); +0043F8C0 00000086 -R void __cdecl Sound_UpdateContinued(void); +0043F950 00000024 -R void __cdecl Sound_Shutdown(void); +0043F980 0000002A -R void __cdecl Sound_Init(void); # game/sphere.c 0043F9B0 00000128 -R int32_t __cdecl TestCollision(struct ITEM_INFO *item, struct ITEM_INFO *laraitem); @@ -1800,10 +1800,10 @@ typedef struct CINE_FRAME { 00445A50 000003B1 -R HRESULT __stdcall EnumDisplayModesCallback(LPDDSDESC lpDDSurfaceDesc, LPVOID lpContext); 00445E10 00000040 -R bool __cdecl WinVidInit(void); 00445E50 000000AF -R bool __cdecl WinVidGetDisplayAdapters(void); -00445F00 00000013 -R void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); +00445F00 00000013 +R void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); 00445F20 0000001A -R bool __cdecl EnumerateDisplayAdapters(struct DISPLAY_ADAPTER_LIST *displayAdapterList); 00445F40 000001BE -R BOOL __stdcall EnumDisplayAdaptersCallback(GUID *lpGUID, LPTSTR lpDriverDescription, LPTSTR lpDriverName, LPVOID lpContext); -00446100 00000035 -R void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); +00446100 00000035 +R void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter); 00446140 0000006A -R bool __cdecl WinVidRegisterGameWindowClass(void); 004461B0 0000049F -R LRESULT __stdcall WinVidGameWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 004467C0 000001C0 -R void __cdecl WinVidResizeGameWindow(HWND hWnd, int32_t edge, LPRECT rect); @@ -1833,7 +1833,7 @@ typedef struct CINE_FRAME { 004473B0 0000007F -R bool __cdecl WinInputInit(void); 00447430 00000024 -R bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList); 00447460 000000E8 -R BOOL __stdcall DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); -00447550 0000001F -R void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); +00447550 0000001F +R void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); 00447570 0000004E -R JOYSTICK_NODE *__cdecl GetJoystick(GUID *lpGuid); 004475C0 000000C9 -R void __cdecl DInputKeyboardCreate(void); 00447690 00000029 -R void __cdecl DInputKeyboardRelease(void); @@ -1854,24 +1854,24 @@ typedef struct CINE_FRAME { 00447B30 00000018 x sub_447B30 00447B40 00000039 x sub_447B40 00447B90 0000002F x sub_447B90 -00447BC0 00000048 -R SOUND_ADAPTER_NODE *__cdecl GetSoundAdapter(GUID *lpGuid); -00447C10 0000002E -R void __cdecl WinSndFreeAllSamples(void); -00447C40 0000010E -R bool __cdecl WinSndMakeSample(DWORD sampleIdx, LPWAVEFORMATEX format, const LPVOID data, DWORD dataSize); -00447D50 00000045 -R bool __cdecl WinSndIsChannelPlaying(DWORD channel); -00447DA0 000000E7 -R int32_t __cdecl WinSndPlaySample(DWORD sampleIdx, int32_t volume, DWORD pitch, int32_t pan, DWORD flags); -00447E90 00000039 -R int32_t __cdecl WinSndGetFreeChannelIndex(void); -00447ED0 0000002C -R void __cdecl WinSndAdjustVolumeAndPan(int32_t channel, int32_t volume, int32_t pan); -00447F00 00000031 -R void __cdecl WinSndAdjustPitch(int32_t channel, DWORD pitch); -00447F40 0000002F -R void __cdecl WinSndStopSample(int32_t channel); +00447BC0 00000048 + struct SOUND_ADAPTER_NODE *__cdecl S_Audio_Sample_GetAdapter(GUID *guid); +00447C10 0000002E + void __cdecl S_Audio_Sample_CloseAllTracks(void); +00447C40 0000010E + bool __cdecl S_Audio_Sample_Load(int32_t sample_id, LPWAVEFORMATEX format, const void *data, int32_t data_size); +00447D50 00000045 + bool __cdecl S_Audio_Sample_IsTrackPlaying(int32_t track_id); +00447DA0 000000E7 + int32_t __cdecl S_Audio_Sample_Play(int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan, int32_t flags); +00447E90 00000039 + int32_t __cdecl S_Audio_Sample_GetFreeTrackIndex(void); +00447ED0 0000002C + void __cdecl S_Audio_Sample_AdjustTrackVolumeAndPan(int32_t track_id, int32_t volume, int32_t pan); +00447F00 00000031 + void __cdecl S_Audio_Sample_AdjustTrackPitch(int32_t track_id, int32_t pitch); +00447F40 0000002F + void __cdecl S_Audio_Sample_CloseTrack(int32_t track_id); 00447FA0 00000005 -R sub_447FA0 -00447FB0 0000009C -R bool __cdecl WinSndInit(void); -00448050 0000001A -R bool __cdecl DSoundEnumerate(SOUND_ADAPTER_LIST *adapterList); -00448070 000000E2 -R BOOL __stdcall DSoundEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); -00448160 0000017C -R void __cdecl WinSndStart(HWND hWnd); -004482E0 0000001C -R bool __cdecl DSoundCreate(GUID *lpGuid); -00448300 000000C4 -R bool __cdecl DSoundBufferTest(void); -004483D0 0000002A -R void __cdecl WinSndFinish(void); -00448400 00000006 -R bool __cdecl WinSndIsSoundEnabled(void); +00447FB0 0000009C +R bool __cdecl S_Audio_Sample_Init(void); +00448050 0000001A +R bool __cdecl S_Audio_Sample_DSoundEnumerate(struct SOUND_ADAPTER_LIST *adapter_list); +00448070 000000E2 +R BOOL __stdcall S_Audio_Sample_DSoundEnumCallback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context); +00448160 0000017C +R void __cdecl S_Audio_Sample_Init2(HWND hwnd); +004482E0 0000001C +R bool __cdecl S_Audio_Sample_DSoundCreate(GUID *guid); +00448300 000000C4 +R bool __cdecl S_Audio_Sample_DSoundBufferTest(void); +004483D0 0000002A +R void __cdecl S_Audio_Sample_Shutdown(void); +00448400 00000006 +R bool __cdecl S_Audio_Sample_IsEnabled(void); 00448410 00000005 -R sub_448410 00448420 00000001 -R sub_448420 00448430 0000013B -R void __cdecl CreateScreenBuffers(void); @@ -2071,23 +2071,23 @@ typedef struct CINE_FRAME { 00454D60 0000032D -R void __cdecl CheckCheatMode(void); 004550C0 0000007D -R void __cdecl S_SaveSettings(void); 00455140 000000DB -R void __cdecl S_LoadSettings(void); -00455220 00000046 -R int32_t __cdecl S_SoundPlaySample(int32_t channel, UINT16 volume, int32_t pitch, int32_t pan); -00455270 0000002A -R int32_t __cdecl S_Sound_CalculateSampleVolume(DWORD volume); -004552A0 00000026 -R int32_t __cdecl S_Sound_CalculateSamplePan(int16_t pan); -004552D0 00000046 -R int32_t __cdecl S_SoundPlaySampleLooped(int32_t channel, UINT16 volume, DWORD pitch, int32_t pan); -00455320 00000039 -R void __cdecl S_SoundSetPanAndVolume(int32_t channel, int32_t pan, UINT16 volume); -00455360 0000001C -R void __cdecl S_SoundSetPitch(int32_t channel, DWORD pitch); -00455380 0000000A -R void __cdecl S_SoundSetMasterVolume(DWORD volume); -00455390 00000017 -R void __cdecl S_SoundStopSample(int32_t channel); -004553B0 0000003C -R void __cdecl S_SoundStopAllSamples(void); -004553C0 0000001F -R BOOL __cdecl S_SoundSampleIsPlaying(int32_t channel); -004553E0 00000077 -R bool __cdecl CD_Init(void); -00455460 00000051 -R void __cdecl CD_Cleanup(void); -00455500 0000006F -R void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); -00455570 00000039 -R void __cdecl S_CDStop(void); -004555B0 00000084 -R BOOL __cdecl StartSyncedAudio(int32_t trackID); -00455640 00000061 -R DWORD __cdecl S_CDGetLoc(void); -004556B0 00000092 * void __cdecl Music_SetVolume(int32_t volume); +00455220 00000046 +R int32_t __cdecl Sound_Play(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); +00455270 0000002A +R int32_t __cdecl Sound_CalculateSampleVolume(int32_t volume); +004552A0 00000026 +R int32_t __cdecl Sound_CalculateSamplePan(int16_t pan); +004552D0 00000046 +R int32_t __cdecl Sound_PlayLooped(int32_t sample_id, uint16_t volume, int32_t pitch, int32_t pan); +00455320 00000039 +R void __cdecl Sound_SetPanAndVolume(int32_t sample_id, int32_t pan, uint16_t volume); +00455360 0000001C +R void __cdecl Sound_SetPitch(int32_t sample_id, int32_t pitch); +00455380 0000000A +R void __cdecl Sound_SetMasterVolume(int32_t volume); +00455390 00000017 +R void __cdecl Sound_StopSample(int32_t sample_id); +004553B0 0000003C +R void __cdecl Sound_StopAllSamples(void); +004553C0 0000001F +R BOOL __cdecl Sound_SampleIsPlaying(int32_t sample_id); +004553E0 00000077 +R bool __cdecl CD_Init(void); +00455460 00000051 +R void __cdecl CD_Cleanup(void); +00455500 0000006F +R void __cdecl S_CDPlay(int16_t trackID, BOOL isLooped); +00455570 00000039 +R void __cdecl S_CDStop(void); +004555B0 00000084 +R BOOL __cdecl StartSyncedAudio(int32_t trackID); +00455640 00000061 +R DWORD __cdecl S_CDGetLoc(void); +004556B0 00000092 + void __cdecl Music_SetVolume(int32_t volume); 004557A0 00000137 -R void __cdecl CopyBitmapPalette(RGB888 *srcPal, BYTE *srcBitmap, int32_t bitmapSize, RGB888 *destPal); 004558E0 000000C8 -R BYTE __cdecl FindNearestPaletteEntry(RGB888 *palette, int32_t red, int32_t green, int32_t blue, bool ignoreSysPalette); 004559B0 000000AE -R void __cdecl SyncSurfacePalettes(void *srcData, int32_t width, int32_t height, int32_t srcPitch, RGB888 *srcPalette, void *dstData, int32_t dstPitch, RGB888 *dstPalette, bool preserveSysPalette); @@ -2169,6 +2169,7 @@ typedef struct CINE_FRAME { # Offset Flags Declaration 004640BC - int16_t g_CD_TrackID; +004640C4 - int32_t g_FlipEffect; 00465A60 - int16_t g_OptionMusicVolume; 00467DD0 + const int32_t g_AtanBaseTable[8]; 00467DF0 + const int16_t g_AtanAngleTable[0x800]; @@ -2218,7 +2219,9 @@ typedef struct CINE_FRAME { 0051E6C4 - int32_t g_SoundIsActive; 005206E0 - struct LARA_INFO g_Lara; 005207BC - struct ITEM_INFO *g_LaraItem; +00521FDC - int32_t g_SoundFxCount; 0052618C - struct ROOM_INFO *g_Rooms; +00526240 - int32_t g_FlipStatus; 005262F0 - struct ITEM_INFO g_Items[]; 005262F6 - int16_t g_NumCineFrames; 005262F8 - CINE_FRAME *g_CineData = NULL; @@ -2226,3 +2229,5 @@ typedef struct CINE_FRAME { 00526314 - int16_t g_CineFrame; 00526320 - struct CAMERA_INFO g_Camera; 005263CC - struct BOX_INFO *g_Boxes; +004641F8 - void (__cdecl *g_EffectRoutines[32])(struct ITEM_INFO *item); +004D7C80 - DWORD g_SoundTrackIds[128]; diff --git a/meson.build b/meson.build index 4db536c8..9062f794 100644 --- a/meson.build +++ b/meson.build @@ -84,6 +84,11 @@ dll_sources = [ 'src/main_dll.c', 'src/memory.c', 'src/specific/s_filesystem.c', + 'src/specific/s_pauld.c', + 'src/specific/s_sndpc.c', + 'src/specific/s_sound.c', + 'src/specific/s_winvid.c', + 'src/lib/winmm.c', ] executable( diff --git a/src/game/camera.c b/src/game/camera.c index 24ea8e5d..b72a2d0a 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -5,6 +5,7 @@ #include "global/const.h" #include "global/funcs.h" #include "global/vars.h" +#include "specific/s_sndpc.h" #include "util.h" #define CHASE_SPEED 10 diff --git a/src/global/const.h b/src/global/const.h index 24daf7fa..98e92037 100644 --- a/src/global/const.h +++ b/src/global/const.h @@ -20,3 +20,6 @@ #define MIN_HEAD_ROTATION (-MAX_HEAD_ROTATION) // = -9100 #define MAX_HEAD_TILT_CAM (85 * PHD_DEGREE) // = 15470 #define MIN_HEAD_TILT_CAM (-MAX_HEAD_TILT_CAM) // = -15470 + +#define MAX_AUDIO_SAMPLE_BUFFERS 256 +#define MAX_AUDIO_SAMPLE_TRACKS 32 diff --git a/src/global/funcs.h b/src/global/funcs.h index 134a26ca..c5b23c50 100644 --- a/src/global/funcs.h +++ b/src/global/funcs.h @@ -225,7 +225,7 @@ #define BigEelControl ((void __cdecl (*)(int16_t item_num))0x0041C140) #define EelControl ((void __cdecl (*)(int16_t item_num))0x0041C2E0) #define ItemNearLara ((int32_t __cdecl (*)(struct PHD_3DPOS *pos, int32_t distance))0x0041C4D0) -#define SoundEffects ((void __cdecl (*)(void))0x0041C560) +#define Sound_Update ((void __cdecl (*)(void))0x0041C560) #define DoBloodSplat ((int16_t __cdecl (*)(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num))0x0041C5D0) #define DoLotsOfBlood ((void __cdecl (*)(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE direction, int16_t room_num, int32_t num))0x0041C630) #define ControlBlood1 ((void __cdecl (*)(int16_t fx_num))0x0041C6E0) @@ -814,10 +814,8 @@ #define EnumDisplayModesCallback ((HRESULT __stdcall (*)(LPDDSDESC lpDDSurfaceDesc, LPVOID lpContext))0x00445A50) #define WinVidInit ((bool __cdecl (*)(void))0x00445E10) #define WinVidGetDisplayAdapters ((bool __cdecl (*)(void))0x00445E50) -#define FlaggedStringDelete ((void __thiscall (*)(struct STRING_FLAGGED *item))0x00445F00) #define EnumerateDisplayAdapters ((bool __cdecl (*)(struct DISPLAY_ADAPTER_LIST *displayAdapterList))0x00445F20) #define EnumDisplayAdaptersCallback ((BOOL __stdcall (*)(GUID *lpGUID, LPTSTR lpDriverDescription, LPTSTR lpDriverName, LPVOID lpContext))0x00445F40) -#define FlaggedStringsCreate ((void __thiscall (*)(struct DISPLAY_ADAPTER *adapter))0x00446100) #define WinVidRegisterGameWindowClass ((bool __cdecl (*)(void))0x00446140) #define WinVidGameWindowProc ((LRESULT __stdcall (*)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam))0x004461B0) #define WinVidResizeGameWindow ((void __cdecl (*)(HWND hWnd, int32_t edge, LPRECT rect))0x004467C0) @@ -840,7 +838,6 @@ #define WinInputInit ((bool __cdecl (*)(void))0x004473B0) #define DInputEnumDevices ((bool __cdecl (*)(JOYSTICK_LIST *joystickList))0x00447430) #define DInputEnumDevicesCallback ((BOOL __stdcall (*)(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef))0x00447460) -#define FlaggedStringCreate ((void __thiscall (*)(struct STRING_FLAGGED *item, DWORD dwSize))0x00447550) #define GetJoystick ((JOYSTICK_NODE *__cdecl (*)(GUID *lpGuid))0x00447570) #define DInputKeyboardCreate ((void __cdecl (*)(void))0x004475C0) #define DInputKeyboardRelease ((void __cdecl (*)(void))0x00447690) @@ -855,23 +852,6 @@ #define TempVideoRemove ((void __cdecl (*)(void))0x004479D0) #define S_FadeInInventory ((void __cdecl (*)(BOOL isFade))0x00447A10) #define S_FadeOutInventory ((void __cdecl (*)(BOOL isFade))0x00447A50) -#define GetSoundAdapter ((SOUND_ADAPTER_NODE *__cdecl (*)(GUID *lpGuid))0x00447BC0) -#define WinSndFreeAllSamples ((void __cdecl (*)(void))0x00447C10) -#define WinSndMakeSample ((bool __cdecl (*)(DWORD sampleIdx, LPWAVEFORMATEX format, const LPVOID data, DWORD dataSize))0x00447C40) -#define WinSndIsChannelPlaying ((bool __cdecl (*)(DWORD channel))0x00447D50) -#define WinSndPlaySample ((int32_t __cdecl (*)(DWORD sampleIdx, int32_t volume, DWORD pitch, int32_t pan, DWORD flags))0x00447DA0) -#define WinSndGetFreeChannelIndex ((int32_t __cdecl (*)(void))0x00447E90) -#define WinSndAdjustVolumeAndPan ((void __cdecl (*)(int32_t channel, int32_t volume, int32_t pan))0x00447ED0) -#define WinSndAdjustPitch ((void __cdecl (*)(int32_t channel, DWORD pitch))0x00447F00) -#define WinSndStopSample ((void __cdecl (*)(int32_t channel))0x00447F40) -#define WinSndInit ((bool __cdecl (*)(void))0x00447FB0) -#define DSoundEnumerate ((bool __cdecl (*)(SOUND_ADAPTER_LIST *adapterList))0x00448050) -#define DSoundEnumCallback ((BOOL __stdcall (*)(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext))0x00448070) -#define WinSndStart ((void __cdecl (*)(HWND hWnd))0x00448160) -#define DSoundCreate ((bool __cdecl (*)(GUID *lpGuid))0x004482E0) -#define DSoundBufferTest ((bool __cdecl (*)(void))0x00448300) -#define WinSndFinish ((void __cdecl (*)(void))0x004483D0) -#define WinSndIsSoundEnabled ((bool __cdecl (*)(void))0x00448400) #define CreateScreenBuffers ((void __cdecl (*)(void))0x00448430) #define CreatePrimarySurface ((void __cdecl (*)(void))0x00448570) #define CreateBackBuffer ((void __cdecl (*)(void))0x00448610) @@ -1063,23 +1043,6 @@ #define CheckCheatMode ((void __cdecl (*)(void))0x00454D60) #define S_SaveSettings ((void __cdecl (*)(void))0x004550C0) #define S_LoadSettings ((void __cdecl (*)(void))0x00455140) -#define S_SoundPlaySample ((int32_t __cdecl (*)(int32_t channel, UINT16 volume, int32_t pitch, int32_t pan))0x00455220) -#define S_Sound_CalculateSampleVolume ((int32_t __cdecl (*)(DWORD volume))0x00455270) -#define S_Sound_CalculateSamplePan ((int32_t __cdecl (*)(int16_t pan))0x004552A0) -#define S_SoundPlaySampleLooped ((int32_t __cdecl (*)(int32_t channel, UINT16 volume, DWORD pitch, int32_t pan))0x004552D0) -#define S_SoundSetPanAndVolume ((void __cdecl (*)(int32_t channel, int32_t pan, UINT16 volume))0x00455320) -#define S_SoundSetPitch ((void __cdecl (*)(int32_t channel, DWORD pitch))0x00455360) -#define S_SoundSetMasterVolume ((void __cdecl (*)(DWORD volume))0x00455380) -#define S_SoundStopSample ((void __cdecl (*)(int32_t channel))0x00455390) -#define S_SoundStopAllSamples ((void __cdecl (*)(void))0x004553B0) -#define S_SoundSampleIsPlaying ((BOOL __cdecl (*)(int32_t channel))0x004553C0) -#define CD_Init ((bool __cdecl (*)(void))0x004553E0) -#define CD_Cleanup ((void __cdecl (*)(void))0x00455460) -#define S_CDPlay ((void __cdecl (*)(int16_t trackID, BOOL isLooped))0x00455500) -#define S_CDStop ((void __cdecl (*)(void))0x00455570) -#define StartSyncedAudio ((BOOL __cdecl (*)(int32_t trackID))0x004555B0) -#define S_CDGetLoc ((DWORD __cdecl (*)(void))0x00455640) -#define Music_SetVolume ((void __cdecl (*)(int32_t volume))0x004556B0) #define CopyBitmapPalette ((void __cdecl (*)(RGB888 *srcPal, BYTE *srcBitmap, int32_t bitmapSize, RGB888 *destPal))0x004557A0) #define FindNearestPaletteEntry ((BYTE __cdecl (*)(RGB888 *palette, int32_t red, int32_t green, int32_t blue, bool ignoreSysPalette))0x004558E0) #define SyncSurfacePalettes ((void __cdecl (*)(void *srcData, int32_t width, int32_t height, int32_t srcPitch, RGB888 *srcPalette, void *dstData, int32_t dstPitch, RGB888 *dstPalette, bool preserveSysPalette))0x004559B0) diff --git a/src/global/types.h b/src/global/types.h index 53927dec..2d7b587e 100644 --- a/src/global/types.h +++ b/src/global/types.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -129,14 +130,14 @@ typedef struct SOUND_ADAPTER { } SOUND_ADAPTER; typedef struct SOUND_ADAPTER_NODE { - struct SoundAdapterNode_t *next; - struct SoundAdapterNode_t *previous; + struct SOUND_ADAPTER_NODE *next; + struct SOUND_ADAPTER_NODE *previous; SOUND_ADAPTER body; } SOUND_ADAPTER_NODE; typedef struct SOUND_ADAPTER_LIST { - struct SoundAdapterNode_t *head; - struct SoundAdapterNode_t *tail; + struct SOUND_ADAPTER_NODE *head; + struct SOUND_ADAPTER_NODE *tail; DWORD dwCount; } SOUND_ADAPTER_LIST; diff --git a/src/global/vars.h b/src/global/vars.h index 5108a621..5969da45 100644 --- a/src/global/vars.h +++ b/src/global/vars.h @@ -7,6 +7,7 @@ // clang-format off #define g_CD_TrackID VAR_U_(0x004640BC, int16_t) +#define g_FlipEffect VAR_U_(0x004640C4, int32_t) #define g_OptionMusicVolume VAR_U_(0x00465A60, int16_t) #define g_ViewportAspectRatio VAR_I_(0x0046C304, float, 0.0f) #define g_PhdWinTop VAR_U_(0x0046E310, int32_t) @@ -53,7 +54,9 @@ #define g_SoundIsActive VAR_U_(0x0051E6C4, int32_t) #define g_Lara VAR_U_(0x005206E0, struct LARA_INFO) #define g_LaraItem VAR_U_(0x005207BC, struct ITEM_INFO *) +#define g_SoundFxCount VAR_U_(0x00521FDC, int32_t) #define g_Rooms VAR_U_(0x0052618C, struct ROOM_INFO *) +#define g_FlipStatus VAR_U_(0x00526240, int32_t) #define g_Items ARRAY_(0x005262F0, struct ITEM_INFO, []) #define g_NumCineFrames VAR_U_(0x005262F6, int16_t) #define g_CineData VAR_I_(0x005262F8, CINE_FRAME *, NULL) diff --git a/src/inject_exec.c b/src/inject_exec.c index f58596f6..63bf4c07 100644 --- a/src/inject_exec.c +++ b/src/inject_exec.c @@ -5,11 +5,17 @@ #include "game/matrix.h" #include "game/shell.h" #include "inject_util.h" +#include "specific/s_sndpc.h" +#include "specific/s_sound.h" +#include "specific/s_winvid.h" static void Inject_Camera(void); static void Inject_Math(void); static void Inject_Matrix(void); static void Inject_Shell(void); +static void Inject_S_Audio_Sample(void); +static void Inject_S_SndPC(void); +static void Inject_S_WinVid(void); static void Inject_Camera(void) { @@ -54,10 +60,63 @@ static void Inject_Shell(void) INJECT(1, 0x0044E890, Shell_ExitSystem); } +static void Inject_S_Audio_Sample(void) +{ + INJECT(1, 0x00447BC0, S_Audio_Sample_GetAdapter); + INJECT(1, 0x00447C10, S_Audio_Sample_CloseAllTracks); + INJECT(1, 0x00447C40, S_Audio_Sample_Load); + INJECT(1, 0x00447D50, S_Audio_Sample_IsTrackPlaying); + INJECT(1, 0x00447DA0, S_Audio_Sample_Play); + INJECT(1, 0x00447E90, S_Audio_Sample_GetFreeTrackIndex); + INJECT(1, 0x00447ED0, S_Audio_Sample_AdjustTrackVolumeAndPan); + INJECT(1, 0x00447F00, S_Audio_Sample_AdjustTrackPitch); + INJECT(1, 0x00447F40, S_Audio_Sample_CloseTrack); + INJECT(1, 0x00447FB0, S_Audio_Sample_Init); + INJECT(1, 0x00448050, S_Audio_Sample_DSoundEnumerate); + INJECT(1, 0x00448070, S_Audio_Sample_DSoundEnumCallback); + INJECT(1, 0x00448160, S_Audio_Sample_Init2); + INJECT(1, 0x004482E0, S_Audio_Sample_DSoundCreate); + INJECT(1, 0x00448300, S_Audio_Sample_DSoundBufferTest); + INJECT(1, 0x004483D0, S_Audio_Sample_Shutdown); + INJECT(1, 0x00448400, S_Audio_Sample_IsEnabled); +} + +static void Inject_S_SndPC(void) +{ + INJECT(1, 0x00455220, S_SoundPlaySample); + INJECT(1, 0x00455270, S_Sound_CalculateSampleVolume); + INJECT(1, 0x004552A0, S_Sound_CalculateSamplePan); + INJECT(1, 0x004552D0, S_SoundPlaySampleLooped); + INJECT(1, 0x00455320, S_SoundSetPanAndVolume); + INJECT(1, 0x00455360, S_SoundSetPitch); + INJECT(1, 0x00455380, S_SoundSetMasterVolume); + INJECT(1, 0x00455390, S_SoundStopSample); + INJECT(1, 0x004553B0, S_SoundStopAllSamples); + INJECT(1, 0x004553C0, S_SoundSampleIsPlaying); + INJECT(1, 0x004553E0, CD_Init); + INJECT(1, 0x00455460, CD_Cleanup); + INJECT(1, 0x00455500, S_CDPlay); + INJECT(1, 0x00455570, S_CDStop); + INJECT(1, 0x004555B0, StartSyncedAudio); + INJECT(1, 0x00455640, S_CDGetLoc); + INJECT(1, 0x004556B0, Music_SetVolume); +} + +static void Inject_S_WinVid(void) +{ + INJECT(1, 0x00447550, FlaggedStringCreate); + INJECT(1, 0x00446100, FlaggedStringsCreate); + INJECT(1, 0x00445F00, FlaggedStringDelete); +} + void Inject_Exec(void) { Inject_Camera(); - Inject_Matrix(); Inject_Math(); + Inject_Matrix(); Inject_Shell(); + + Inject_S_Audio_Sample(); + Inject_S_SndPC(); + Inject_S_WinVid(); } diff --git a/src/lib/dsound.h b/src/lib/dsound.h new file mode 100644 index 00000000..875275c4 --- /dev/null +++ b/src/lib/dsound.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#define DirectSoundCreate \ + ((HRESULT(__stdcall *)( \ + LPCGUID pcGuidDevice, LPDIRECTSOUND * ppDS, \ + LPUNKNOWN pUnkOuter))0x00458CEE) +#define DirectSoundEnumerateA \ + ((HRESULT(__stdcall *)( \ + LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext))0x00458CE8) diff --git a/src/lib/winmm.c b/src/lib/winmm.c new file mode 100644 index 00000000..e9b74adb --- /dev/null +++ b/src/lib/winmm.c @@ -0,0 +1,11 @@ +#include "lib/winmm.h" + +MMRESULT(__stdcall *g_MM_auxGetDevCapsA) +(UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac); +UINT(__stdcall *g_MM_auxGetNumDevs)(void) = NULL; +MMRESULT(__stdcall *g_MM_auxSetVolume)(UINT uDeviceID, DWORD dwVolume) = NULL; +MCIERROR(__stdcall *g_MM_mciSendCommandA) +(MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) = NULL; +MCIERROR(__stdcall *g_MM_mciSendStringA) +(LPCSTR lpszCommand, LPSTR lpszReturnString, UINT cchReturn, + HANDLE hwndCallback) = NULL; diff --git a/src/lib/winmm.h b/src/lib/winmm.h new file mode 100644 index 00000000..35fe835f --- /dev/null +++ b/src/lib/winmm.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +extern MMRESULT(__stdcall *g_MM_auxGetDevCapsA)( + UINT_PTR uDeviceID, LPAUXCAPSA pac, UINT cbac); +extern UINT(__stdcall *g_MM_auxGetNumDevs)(void); +extern MMRESULT(__stdcall *g_MM_auxSetVolume)(UINT uDeviceID, DWORD dwVolume); +extern MCIERROR(__stdcall *g_MM_mciSendCommandA)( + MCIDEVICEID mciId, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2); +extern MCIERROR(__stdcall *g_MM_mciSendStringA)( + LPCSTR lpszCommand, LPSTR lpszReturnString, UINT cchReturn, + HANDLE hwndCallback); + +#define auxGetDevCapsA g_MM_auxGetDevCapsA +#define auxGetNumDevs g_MM_auxGetNumDevs +#define auxSetVolume g_MM_auxSetVolume +#define mciSendCommandA g_MM_mciSendCommandA +#define mciSendStringA g_MM_mciSendStringA diff --git a/src/main_dll.c b/src/main_dll.c index a2aee2a9..9966292e 100644 --- a/src/main_dll.c +++ b/src/main_dll.c @@ -1,9 +1,19 @@ #include "inject_exec.h" +#include "lib/winmm.h" #include "log.h" #include #include +static void LoadWinMM(void) +{ + HANDLE g_WinMM = LoadLibrary("winmm.dll"); + auxGetNumDevs = GetProcAddress(g_WinMM, "auxGetNumDevs"); + auxSetVolume = GetProcAddress(g_WinMM, "auxSetVolume"); + mciSendCommandA = GetProcAddress(g_WinMM, "mciSendCommandA"); + mciSendStringA = GetProcAddress(g_WinMM, "mciSendStringA"); +} + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { @@ -12,6 +22,7 @@ DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) Log_Init(); LOG_DEBUG("Injected\n"); + LoadWinMM(); Inject_Exec(); break; diff --git a/src/main_exe.c b/src/main_exe.c index c7b08cac..d98e7d23 100644 --- a/src/main_exe.c +++ b/src/main_exe.c @@ -5,73 +5,86 @@ // The path to the legitimate host process const char *hostProcessPath = "Tomb2.exe"; -bool fileExists(const char *filePath) +static bool FileExists(const char *path) { - DWORD fileAttributes = GetFileAttributes(filePath); - + DWORD fileAttributes = GetFileAttributes(path); if (fileAttributes != INVALID_FILE_ATTRIBUTES && !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { return true; } - return false; } -int main() +static bool InjectDLL(HANDLE process_handle, const char *dll_path) { - char dll_path[MAX_PATH]; - GetModuleFileNameA(NULL, dll_path, MAX_PATH); - strcpy(strstr(dll_path, ".exe"), ".dll"); - fprintf(stderr, "injecting %s\n", dll_path); - - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - - if (!CreateProcess( - hostProcessPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, - NULL, &si, &pi)) { - fprintf(stderr, "Failed to create the process.\n"); - return 1; - } - + bool status = false; LPVOID loadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); - if (!fileExists(dll_path)) { + fprintf(stderr, "Injecting %s\n", dll_path); + + if (!FileExists(dll_path)) { fprintf(stderr, "DLL does not exist.\n"); - return 1; + goto finish; } - LPVOID dllPathAddr = VirtualAllocEx( - pi.hProcess, NULL, strlen(dll_path) + 1, MEM_RESERVE | MEM_COMMIT, + LPVOID dll_path_adr = VirtualAllocEx( + process_handle, NULL, strlen(dll_path) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (!dllPathAddr) { + if (!dll_path_adr) { fprintf(stderr, "Failed to allocate remote memory.\n"); - return 1; + goto finish; } if (!WriteProcessMemory( - pi.hProcess, dllPathAddr, dll_path, strlen(dll_path) + 1, NULL)) { + process_handle, dll_path_adr, dll_path, strlen(dll_path) + 1, + NULL)) { fprintf(stderr, "Failed to write remote memory.\n"); - return 1; + goto finish; } HANDLE hRemoteThread = CreateRemoteThread( - pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddr, - dllPathAddr, 0, NULL); + process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddr, + dll_path_adr, 0, NULL); if (hRemoteThread == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to create remote thread.\n"); - return 1; + goto finish; } WaitForSingleObject(hRemoteThread, INFINITE); - VirtualFreeEx(pi.hProcess, dllPathAddr, strlen(dll_path) + 1, MEM_RELEASE); + VirtualFreeEx( + process_handle, dll_path_adr, strlen(dll_path) + 1, MEM_RELEASE); CloseHandle(hRemoteThread); + status = true; +finish: + return status; +} + +int main() +{ + char dll_path[MAX_PATH]; + GetModuleFileNameA(NULL, dll_path, MAX_PATH); + strcpy(strstr(dll_path, ".exe"), ".dll"); + + STARTUPINFO si; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcess( + hostProcessPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, + NULL, &si, &pi)) { + fprintf(stderr, "Failed to create the process.\n"); + return 1; + } + + if (!InjectDLL(pi.hProcess, dll_path)) { + return 1; + } + if (ResumeThread(pi.hThread) == (DWORD)-1) { fprintf(stderr, "Failed to resume the execution of the process.\n"); return 1; diff --git a/src/specific/s_pauld.c b/src/specific/s_pauld.c new file mode 100644 index 00000000..64fd61a7 --- /dev/null +++ b/src/specific/s_pauld.c @@ -0,0 +1,278 @@ +#include "specific/s_pauld.h" + +#include "global/funcs.h" +#include "global/types.h" +#include "global/vars.h" +#include "lib/winmm.h" +#include "log.h" + +#include + +#define CD_ALIAS "T2" +#define MAX_TRACKS 60 + +typedef struct TRACK_INFO { + DWORD from; + DWORD to; + bool active; +} TRACK_INFO; + +static TRACK_INFO g_Tracks[60]; +static bool m_IsCDAudioEnabled = false; + +bool __cdecl PaulD_CD_Init(void) +{ + static LPCTSTR audio_files[2] = { + "audio\\cdaudio.wav", + "audio\\cdaudio.mp3", + }; + + static LPCTSTR audio_types[2] = { + "waveaudio", + "mpegvideo", + }; + + HANDLE file; + DWORD file_size; + DWORD bytes_read; + DWORD offset; + char cmd_string[256]; + char *buf; + int32_t rc; + int32_t audio_type = -1; + + if (m_IsCDAudioEnabled) { + return true; + } + + for (int32_t i = 0; i < 2; ++i) { + file = CreateFile( + audio_files[i], GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (file != INVALID_HANDLE_VALUE) { + audio_type = i; + CloseHandle(file); + break; + } + } + if (audio_type < 0) { + return false; + } + + file = CreateFile( + "audio\\cdaudio.dat", GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) { + return false; + } + + file_size = GetFileSize(file, NULL); + buf = (char *)malloc(file_size); + if (buf == NULL) { + CloseHandle(file); + return false; + } + rc = ReadFile(file, buf, file_size, &bytes_read, NULL); + CloseHandle(file); + if (!rc || bytes_read == 0) { + return false; + } + + memset(g_Tracks, 0, sizeof(g_Tracks)); + offset = 0; + + while (offset < bytes_read) { + DWORD index, from, to; + + while (buf[offset] == 0x0A || buf[offset] == 0x0D) { + if (++offset >= bytes_read) { + goto PARSE_END; + } + } + rc = sscanf(&buf[offset], "%lu %lu %lu", &index, &from, &to); + if (rc == 3 && index > 0 && index <= 60) { + g_Tracks[index - 1].active = true; + g_Tracks[index - 1].from = from; + g_Tracks[index - 1].to = to; + } + while (buf[offset] != 0x0A && buf[offset] != 0x0D) { + if (++offset >= bytes_read) { + goto PARSE_END; + } + } + } + +PARSE_END: + free(buf); + + for (DWORD i = 0; i < MAX_TRACKS; ++i) { + if (!g_Tracks[i].active) { + continue; + } + if (g_Tracks[i].from >= g_Tracks[i].to && i < MAX_TRACKS - 1) { + for (DWORD j = i + 1; j < MAX_TRACKS; ++j) { + if (g_Tracks[j].active) { + g_Tracks[i].to = g_Tracks[j].from; + break; + } + } + } + if (g_Tracks[i].from >= g_Tracks[i].to && i > 0) { + for (int32_t j = i - 1; j >= 0; --j) { + if (g_Tracks[j].active) { + g_Tracks[i].from = g_Tracks[j].to; + break; + } + } + } + } + + wsprintf( + cmd_string, "open %s type %s alias " CD_ALIAS, audio_files[audio_type], + audio_types[audio_type]); + rc = mciSendStringA(cmd_string, NULL, 0, 0); + if (rc == 0) { + mciSendStringA("set " CD_ALIAS " time format ms", NULL, 0, 0); + m_IsCDAudioEnabled = true; + } + return true; +} + +void __cdecl PaulD_CD_Cleanup(void) +{ + if (!m_IsCDAudioEnabled) { + return; + } + + PaulD_CDStop(); + mciSendStringA("close " CD_ALIAS, NULL, 0, 0); + m_IsCDAudioEnabled = false; +} + +// void __cdecl PaulD_CDLoop(void) +// { +// int32_t rc; +// char status_string[32]; +// char cmd_string[256]; +// +// if (g_CD_LoopTrack == 0 || ++g_CD_LoopCounter < 150) { +// return; +// } +// +// g_CD_LoopCounter = 0; +// rc = mciSendStringA( +// "status " CD_ALIAS " mode", status_string, sizeof(status_string), 0); +// +// if ((rc == 0) && !strncmp(status_string, "stopped", +// sizeof(status_string))) { +// wsprintf( +// cmd_string, "play " CD_ALIAS " from %lu to %lu", +// g_Tracks[g_CD_LoopTrack - 1].from, g_Tracks[g_CD_LoopTrack - +// 1].to); +// mciSendStringA(cmd_string, NULL, 0, 0); +// } +// } + +void __cdecl PaulD_CDPlay(int16_t track_id, bool is_looped) +{ + int16_t track; + char cmd_string[256]; + + if (g_OptionMusicVolume == 0) { + return; + } + + track = GetRealTrack(track_id); + if (track < 1 || !g_Tracks[track - 1].active) { + return; + } + + g_CD_TrackID = track_id; + + wsprintf( + cmd_string, "play " CD_ALIAS " from %lu to %lu", + g_Tracks[track - 1].from, g_Tracks[track - 1].to); + MMRESULT result = mciSendStringA(cmd_string, NULL, 0, 0); + + if (is_looped) { + g_CD_LoopTrack = track; + // g_CD_LoopCounter = 120; + } +} + +void __cdecl PaulD_CDStop(void) +{ + if (g_CD_TrackID <= 0) { + return; + } + + mciSendStringA("stop " CD_ALIAS, NULL, 0, 0); + g_CD_TrackID = 0; + g_CD_LoopTrack = 0; +} + +bool __cdecl PaulD_StartSyncedAudio(int16_t track_id) +{ + int16_t track; + char cmd_string[256]; + + track = GetRealTrack(track_id); + if (track < 1 || !g_Tracks[track - 1].active) { + return false; + } + + g_CD_TrackID = track_id; + if (mciSendStringA("set " CD_ALIAS " time format ms", NULL, 0, 0) != 0) { + return false; + } + + wsprintf( + cmd_string, "play " CD_ALIAS " from %lu to %lu", + g_Tracks[track - 1].from, g_Tracks[track - 1].to); + return mciSendStringA(cmd_string, NULL, 0, 0) == 0; +} + +uint32_t __cdecl PaulD_CDGetLoc(void) +{ + int16_t track; + char status_string[32]; + + if (mciSendStringA( + "status " CD_ALIAS " position", status_string, + sizeof(status_string), 0) + != 0) { + return 0; + } + + track = GetRealTrack(g_CD_TrackID); + return (atol(status_string) - g_Tracks[track - 1].from) * 75 / 1000; +} + +void __cdecl PaulD_CDVolume(int32_t volume) +{ + char cmd_string[256]; + + if (volume > 0) { + volume = (volume - 5) * 4; + } + + wsprintf(cmd_string, "setaudio " CD_ALIAS " volume to %lu", volume); + mciSendStringA(cmd_string, NULL, 0, 0); + + char status_string[32]; + if (mciSendStringA( + "status " CD_ALIAS " mode", status_string, sizeof(status_string), 0) + != 0) { + return; + } + + if (volume > 0) { + if (!strncmp(status_string, "paused", sizeof(status_string))) { + mciSendStringA("resume " CD_ALIAS, NULL, 0, 0); + } + } else { + if (!strncmp(status_string, "playing", sizeof(status_string))) { + mciSendStringA("pause " CD_ALIAS, NULL, 0, 0); + } + } +} diff --git a/src/specific/s_pauld.h b/src/specific/s_pauld.h new file mode 100644 index 00000000..467b47db --- /dev/null +++ b/src/specific/s_pauld.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2018 Michael Chaban. All rights reserved. + * CD Audio solution in this file was designed by PaulD. + * Original game is created by Core Design Ltd. in 1997. + * Lara Croft and Tomb Raider are trademarks of Embracer Group AB. + * + * This file is part of TR2Main. + * + * TR2Main is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TR2Main is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TR2Main. If not, see . + */ + +#pragma once + +#include "global/types.h" + +#include +#include + +bool __cdecl PaulD_CD_Init(void); +void __cdecl PaulD_CD_Cleanup(void); +// void __cdecl PaulD_CDLoop(void); +void __cdecl PaulD_CDPlay(int16_t track_id, bool is_looped); +void __cdecl PaulD_CDStop(void); +bool __cdecl PaulD_StartSyncedAudio(int16_t track_id); +uint32_t __cdecl PaulD_CDGetLoc(void); +void __cdecl PaulD_CDVolume(int32_t volume); diff --git a/src/specific/s_sndpc.c b/src/specific/s_sndpc.c new file mode 100644 index 00000000..b265bdb5 --- /dev/null +++ b/src/specific/s_sndpc.c @@ -0,0 +1,317 @@ +#include "specific/s_sndpc.h" + +#include "global/const.h" +#include "global/funcs.h" +#include "global/vars.h" +#include "lib/winmm.h" +#include "log.h" +#include "specific/s_pauld.h" +#include "specific/s_sound.h" + +static bool g_PaulDActive = false; + +static HMODULE g_WinMM = NULL; + +static bool isCDAudioEnabled = false; +static int32_t m_CDVolume = 0; + +int32_t __cdecl S_SoundPlaySample( + int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan) +{ + if (!g_SoundIsActive) { + return -3; + } + + int32_t calc_pan = S_Sound_CalculateSamplePan(pan); + int32_t calc_volume = S_Sound_CalculateSampleVolume(volume); + return S_Audio_Sample_Play(sample_id, calc_volume, pitch, calc_pan, 0); +} + +int32_t __cdecl S_Sound_CalculateSampleVolume(int32_t volume) +{ + return (int32_t)(((double)(g_MasterVolume * volume) / 0x200000.p0 - 1.0) + * 5000.0); +} + +int32_t __cdecl S_Sound_CalculateSamplePan(int16_t pan) +{ + return pan / 16; +} + +int32_t __cdecl S_SoundPlaySampleLooped( + int32_t sample_id, int32_t volume, int32_t pitch, int32_t pan) +{ + if (!g_SoundIsActive) { + return -3; + } + + int32_t calc_pan = S_Sound_CalculateSamplePan(pan); + int32_t calc_volume = S_Sound_CalculateSampleVolume(volume); + return S_Audio_Sample_Play( + sample_id, calc_volume, pitch, calc_pan, DSBPLAY_LOOPING); +} + +void __cdecl S_SoundSetPanAndVolume( + int32_t track_id, int32_t pan, int32_t volume) +{ + if (g_SoundIsActive) { + int32_t calc_pan = S_Sound_CalculateSamplePan(pan); + int32_t calc_volume = S_Sound_CalculateSampleVolume(volume); + S_Audio_Sample_AdjustTrackVolumeAndPan(track_id, calc_volume, calc_pan); + } +} + +void __cdecl S_SoundSetPitch(int32_t track_id, int32_t pitch) +{ + if (g_SoundIsActive) { + S_Audio_Sample_AdjustTrackPitch(track_id, pitch); + } +} + +void __cdecl S_SoundSetMasterVolume(int32_t volume) +{ + g_MasterVolume = volume; +} + +void __cdecl S_SoundStopSample(int32_t track_id) +{ + if (g_SoundIsActive) { + S_Audio_Sample_CloseTrack(track_id); + } +} + +void __cdecl S_SoundStopAllSamples(void) +{ + if (g_SoundIsActive) { + for (int32_t i = 0; i < MAX_AUDIO_SAMPLE_TRACKS; ++i) { + S_Audio_Sample_CloseTrack(i); + } + } +} + +bool __cdecl S_SoundSampleIsPlaying(int32_t track_id) +{ + if (!g_SoundIsActive) { + return FALSE; + } + + return S_Audio_Sample_IsTrackPlaying(track_id); +} + +#include "log.h" +bool __cdecl CD_Init(void) +{ + MCI_OPEN_PARMS openParams; + MCI_SET_PARMS setParams; + + g_PaulDActive = PaulD_CD_Init(); + if (g_PaulDActive) { + return true; + } + + if (isCDAudioEnabled) { + return true; + } + + openParams.lpstrDeviceType = "cdaudio"; + if (mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, (DWORD_PTR)&openParams) + == 0) { + g_MciDeviceID = openParams.wDeviceID; + setParams.dwTimeFormat = MCI_FORMAT_TMSF; + mciSendCommand( + g_MciDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&setParams); + isCDAudioEnabled = true; + } + return true; +} + +void __cdecl CD_Cleanup(void) +{ + MCI_GENERIC_PARMS params; + + if (g_PaulDActive) { + PaulD_CD_Cleanup(); + return; + } + + if (!isCDAudioEnabled) { + return; + } + + mciSendCommand(g_MciDeviceID, MCI_STOP, 0, (DWORD_PTR)¶ms); + mciSendCommand(g_MciDeviceID, MCI_CLOSE, 0, (DWORD_PTR)¶ms); + isCDAudioEnabled = false; +} + +// void __cdecl S_CDLoop(void) { +// int32_t rc; +// MCI_PLAY_PARMS playParams; +// MCI_STATUS_PARMS statusParams; +// +// if( g_PaulDActive ) { +// PaulD_CDLoop(); +// return; +// } +// +// if( g_CD_LoopTrack == 0 || ++g_CD_LoopCounter < 150 ) { +// return; +// } +// +// g_CD_LoopCounter = 0; +// statusParams.dwItem = MCI_STATUS_MODE; +// rc = mciSendCommand(g_MciDeviceID, MCI_STATUS, MCI_STATUS_ITEM, +// (DWORD_PTR)&statusParams); if( (rc == 0) && (statusParams.dwReturn == +// MCI_MODE_STOP) ) { +// playParams.dwFrom = g_CD_LoopTrack; +// playParams.dwTo = g_CD_LoopTrack + 1; +// mciSendCommand(g_MciDeviceID, MCI_PLAY, +// MCI_NOTIFY_FAILURE|MCI_NOTIFY_ABORTED, (DWORD_PTR)&playParams); +// } +// } + +void __cdecl S_CDPlay(int16_t track_id, bool is_looped) +{ + CD_Init(); + LOG_DEBUG("track_id=%d is_looped=%d", track_id, is_looped); + int16_t track; + MCI_PLAY_PARMS playParams; + + if (g_PaulDActive) { + PaulD_CDPlay(track_id, is_looped); + return; + } + + if (g_OptionMusicVolume == 0) { + return; + } + + g_CD_TrackID = track_id; + track = GetRealTrack(track_id); + playParams.dwFrom = track; + playParams.dwTo = track + 1; + mciSendCommand( + g_MciDeviceID, MCI_PLAY, MCI_NOTIFY_FAILURE | MCI_NOTIFY_ABORTED, + (DWORD_PTR)&playParams); + + if (is_looped) { + g_CD_LoopTrack = track; + // g_CD_LoopCounter = 120; + } +} + +void __cdecl S_CDStop(void) +{ + LOG_DEBUG(""); + MCI_GENERIC_PARMS params; + + if (g_PaulDActive) { + PaulD_CDStop(); + return; + } + + if (g_CD_TrackID > 0) { + mciSendCommand(g_MciDeviceID, MCI_STOP, 0, (DWORD_PTR)¶ms); + g_CD_TrackID = 0; + g_CD_LoopTrack = 0; + } +} + +bool __cdecl StartSyncedAudio(int32_t track_id) +{ + LOG_DEBUG("%d", track_id); + int16_t track; + MCI_PLAY_PARMS playParams; + MCI_SET_PARMS setParams; + + if (g_PaulDActive) { + return PaulD_StartSyncedAudio(track_id); + } + + g_CD_TrackID = track_id; + track = GetRealTrack(track_id); + + setParams.dwTimeFormat = MCI_FORMAT_TMSF; + if (mciSendCommand( + g_MciDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&setParams) + != 0) { + return FALSE; + } + + playParams.dwFrom = track; + playParams.dwTo = track + 1; + return ( + mciSendCommand( + g_MciDeviceID, MCI_PLAY, MCI_NOTIFY_FAILURE | MCI_NOTIFY_ABORTED, + (DWORD_PTR)&playParams) + == 0); +} + +uint32_t __cdecl S_CDGetLoc(void) +{ + uint32_t pos; + MCI_STATUS_PARMS statusParams; + + if (g_PaulDActive) { + return PaulD_CDGetLoc(); + } + + statusParams.dwItem = MCI_STATUS_POSITION; + if (mciSendCommand( + g_MciDeviceID, MCI_STATUS, MCI_STATUS_ITEM, + (DWORD_PTR)&statusParams) + != 0) { + return 0; + } + + pos = statusParams.dwReturn; + // calculate audio frames position (75 audio frames per second) + return (MCI_TMSF_MINUTE(pos) * 60 + MCI_TMSF_SECOND(pos)) * 75 + + MCI_TMSF_FRAME(pos); +} + +void __cdecl Music_SetVolume(int32_t volume) +{ + if (!g_WinMM) { + return; + } + AUXCAPS caps; + bool isVolumeSet = false; + int32_t device_id = -1; + int32_t aux_dev_count = auxGetNumDevs(); + m_CDVolume = volume; // NOTE: store current CD Audio volume + + if (g_PaulDActive) { + PaulD_CDVolume(volume); + return; + } + + if (aux_dev_count == 0) { + return; + } + + volume *= 0x100; // 0 .. 255 -> 0..65280 + + for (int32_t i = 0; i < aux_dev_count; ++i) { + auxGetDevCaps(i, &caps, sizeof(AUXCAPS)); + + switch (caps.wTechnology) { + case AUXCAPS_CDAUDIO: + auxSetVolume(i, MAKELONG(volume, volume)); + isVolumeSet = true; + break; + + case AUXCAPS_AUXIN: + device_id = i; + break; + } + } + + if (!isVolumeSet && device_id != -1) { + auxSetVolume(device_id, MAKELONG(volume, volume)); + } +} + +int32_t __cdecl S_GetCDVolume(void) +{ + return m_CDVolume; +} diff --git a/src/specific/s_sndpc.h b/src/specific/s_sndpc.h new file mode 100644 index 00000000..836bd593 --- /dev/null +++ b/src/specific/s_sndpc.h @@ -0,0 +1,26 @@ +#pragma once + +#include "global/types.h" + +int32_t __cdecl S_SoundPlaySample( + int32_t channel, int32_t volume, int32_t pitch, int32_t pan); +int32_t __cdecl S_Sound_CalculateSampleVolume(int32_t volume); +int32_t __cdecl S_Sound_CalculateSamplePan(int16_t pan); +int32_t __cdecl S_SoundPlaySampleLooped( + int32_t channel, int32_t volume, int32_t pitch, int32_t pan); +void __cdecl S_SoundSetPanAndVolume( + int32_t channel, int32_t pan, int32_t volume); +void __cdecl S_SoundSetPitch(int32_t channel, int32_t pitch); +void __cdecl S_SoundSetMasterVolume(int32_t volume); +void __cdecl S_SoundStopSample(int32_t channel); +void __cdecl S_SoundStopAllSamples(void); +bool __cdecl S_SoundSampleIsPlaying(int32_t channel); +bool __cdecl CD_Init(void); +void __cdecl CD_Cleanup(void); +// void __cdecl S_CDLoop(void); +void __cdecl S_CDPlay(int16_t track_id, bool is_looped); +void __cdecl S_CDStop(void); +bool __cdecl StartSyncedAudio(int32_t track_id); +uint32_t __cdecl S_CDGetLoc(void); +void __cdecl Music_SetVolume(int32_t volume); +int32_t __cdecl S_GetCDVolume(void); diff --git a/src/specific/s_sound.c b/src/specific/s_sound.c new file mode 100644 index 00000000..b207af3c --- /dev/null +++ b/src/specific/s_sound.c @@ -0,0 +1,354 @@ +#include "specific/s_sound.h" + +#include "game/shell.h" +#include "global/const.h" +#include "global/funcs.h" +#include "global/types.h" +#include "global/vars.h" +#include "lib/dsound.h" +#include "lib/winmm.h" +#include "log.h" + +extern bool FlaggedStringCopy( + struct STRING_FLAGGED *dst, struct STRING_FLAGGED *src); +extern void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); +extern void __thiscall FlaggedStringCreate( + struct STRING_FLAGGED *item, int32_t size); + +struct SOUND_ADAPTER_NODE *__cdecl S_Audio_Sample_GetAdapter(GUID *guid) +{ + struct SOUND_ADAPTER_NODE *adapter; + + if (guid != NULL) { + for (adapter = g_SoundAdapterList.head; adapter; + adapter = adapter->next) { + if (!memcmp(&adapter->body.adapterGuid, guid, sizeof(GUID))) { + return adapter; + } + } + } + return g_PrimarySoundAdapter; +} + +void __cdecl S_Audio_Sample_CloseAllTracks(void) +{ + if (!g_IsSoundEnabled) { + return; + } + + for (int32_t i = 0; i < MAX_AUDIO_SAMPLE_BUFFERS; ++i) { + if (g_SampleBuffers[i] != NULL) { + IDirectSound_Release(g_SampleBuffers[i]); + g_SampleBuffers[i] = NULL; + } + } +} + +bool __cdecl S_Audio_Sample_Load( + int32_t sample_idx, LPWAVEFORMATEX format, const void *data, + uint32_t data_size) +{ + LPVOID audio_ptr; + DWORD audio_bytes; + DSBUFFERDESC desc; + + if (!g_DSound || !g_IsSoundEnabled + || sample_idx >= MAX_AUDIO_SAMPLE_BUFFERS) { + return false; + } + + if (g_SampleBuffers[sample_idx] != NULL) { + IDirectSound_Release(g_SampleBuffers[sample_idx]); + g_SampleBuffers[sample_idx] = NULL; + } + + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY + | DSBCAPS_LOCSOFTWARE; + desc.dwBufferBytes = data_size; + desc.dwReserved = 0; + desc.lpwfxFormat = format; + + if FAILED (IDirectSound_CreateSoundBuffer( + g_DSound, &desc, &g_SampleBuffers[sample_idx], NULL)) { + return false; + } + + if FAILED (IDirectSoundBuffer_Lock( + g_SampleBuffers[sample_idx], 0, data_size, &audio_ptr, + &audio_bytes, NULL, NULL, 0)) { + return false; + } + + memcpy(audio_ptr, data, audio_bytes); + + if FAILED (IDirectSoundBuffer_Unlock( + g_SampleBuffers[sample_idx], audio_ptr, audio_bytes, NULL, + 0)) { + return false; + } + + g_SampleFreqs[sample_idx] = format->nSamplesPerSec; + return true; +} + +bool __cdecl S_Audio_Sample_IsTrackPlaying(int32_t track_id) +{ + DWORD status; + + if (!g_ChannelBuffers[track_id] + || FAILED(IDirectSoundBuffer_GetStatus( + g_ChannelBuffers[track_id], &status))) { + return false; + } + + if ((status & DSBSTATUS_PLAYING) == 0) { + IDirectSoundBuffer_Release(g_ChannelBuffers[track_id]); + g_ChannelBuffers[track_id] = NULL; + return false; + } + + return true; +} + +int32_t __cdecl S_Audio_Sample_Play( + int32_t sample_idx, int32_t volume, int32_t pitch, int32_t pan, + uint32_t flags) +{ + LPDIRECTSOUNDBUFFER dsBuffer = NULL; + int32_t track_id = S_Audio_Sample_GetFreeTrackIndex(); + + if (track_id < 0) { + return -1; + } + + if (FAILED(IDirectSound_DuplicateSoundBuffer( + g_DSound, g_SampleBuffers[sample_idx], &dsBuffer)) + || FAILED(IDirectSoundBuffer_SetVolume(dsBuffer, volume)) + || FAILED(IDirectSoundBuffer_SetFrequency( + dsBuffer, g_SampleFreqs[sample_idx] * pitch / PHD_ONE)) + || FAILED(IDirectSoundBuffer_SetPan(dsBuffer, pan)) + || FAILED(IDirectSoundBuffer_SetCurrentPosition(dsBuffer, 0)) + || FAILED(IDirectSoundBuffer_Play(dsBuffer, 0, 0, flags))) { + return -2; + } + + g_ChannelSamples[track_id] = sample_idx; + g_ChannelBuffers[track_id] = dsBuffer; + + return track_id; +} + +int32_t __cdecl S_Audio_Sample_GetFreeTrackIndex(void) +{ + for (int32_t i = 0; i < MAX_AUDIO_SAMPLE_TRACKS; ++i) { + if (!g_ChannelBuffers[i]) { + return i; + } + } + + for (int32_t i = 0; i < MAX_AUDIO_SAMPLE_TRACKS; ++i) { + if (!S_Audio_Sample_IsTrackPlaying(i)) { + return i; + } + } + + return -1; +} + +void __cdecl S_Audio_Sample_AdjustTrackVolumeAndPan( + int32_t track_id, int32_t volume, int32_t pan) +{ + if (track_id >= 0 && g_ChannelBuffers[track_id] != NULL) { + IDirectSoundBuffer_SetVolume(g_ChannelBuffers[track_id], volume); + IDirectSoundBuffer_SetPan(g_ChannelBuffers[track_id], pan); + } +} + +void __cdecl S_Audio_Sample_AdjustTrackPitch(int32_t track_id, int32_t pitch) +{ + if (track_id >= 0 && g_ChannelBuffers[track_id] != NULL) { + IDirectSoundBuffer_SetFrequency( + g_ChannelBuffers[track_id], + g_SampleFreqs[g_ChannelSamples[track_id]] * pitch / PHD_ONE); + } +} + +void __cdecl S_Audio_Sample_CloseTrack(int32_t track_id) +{ + if (track_id >= 0 && g_ChannelBuffers[track_id] != NULL) { + IDirectSoundBuffer_Stop(g_ChannelBuffers[track_id]); + IDirectSoundBuffer_Release(g_ChannelBuffers[track_id]); + g_ChannelBuffers[track_id] = NULL; + } +} + +bool __cdecl S_Audio_Sample_Init(void) +{ + struct SOUND_ADAPTER_NODE *node, *nextNode; + + for (node = g_SoundAdapterList.head; node; node = nextNode) { + nextNode = node->next; + FlaggedStringDelete(&node->body.module); + FlaggedStringDelete(&node->body.description); + free(node); + } + + g_SoundAdapterList.head = NULL; + g_SoundAdapterList.tail = NULL; + g_SoundAdapterList.dwCount = 0; + + g_PrimarySoundAdapter = NULL; + + if (!S_Audio_Sample_DSoundEnumerate(&g_SoundAdapterList)) { + LOG_ERROR("Failed to enumerate sound devices"); + return false; + } + + for (node = g_SoundAdapterList.head; node; node = node->next) { + if (!node->body.lpAdapterGuid) { + g_PrimarySoundAdapter = node; + break; + } + } + + LOG_ERROR("Finished loading sound"); + return true; +} + +bool __cdecl S_Audio_Sample_DSoundEnumerate( + struct SOUND_ADAPTER_LIST *adapter_list) +{ + return SUCCEEDED(DirectSoundEnumerateA( + S_Audio_Sample_DSoundEnumCallback, (LPVOID)adapter_list)); +} + +BOOL CALLBACK S_Audio_Sample_DSoundEnumCallback( + LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context) +{ + struct SOUND_ADAPTER_LIST *adapter_list = + (struct SOUND_ADAPTER_LIST *)context; + struct SOUND_ADAPTER_NODE *adapter_node = + malloc(sizeof(struct SOUND_ADAPTER_NODE)); + + if (!adapter_node) { + return TRUE; + } + + adapter_node->next = NULL; + adapter_node->previous = adapter_list->tail; + + if (!adapter_list->head) { + adapter_list->head = adapter_node; + } + + if (adapter_list->tail) { + adapter_list->tail->next = adapter_node; + } + + adapter_list->tail = adapter_node; + adapter_list->dwCount++; + + if (!guid) { + memset(&adapter_node->body.adapterGuid, 0, sizeof(GUID)); + adapter_node->body.lpAdapterGuid = NULL; + } else { + adapter_node->body.adapterGuid = *guid; + adapter_node->body.lpAdapterGuid = &adapter_node->body.adapterGuid; + } + + FlaggedStringCreate(&adapter_node->body.description, 256); + FlaggedStringCreate(&adapter_node->body.module, 256); + lstrcpy(adapter_node->body.description.lpString, description); + lstrcpy(adapter_node->body.module.lpString, module); + + return TRUE; +} + +void __cdecl S_Audio_Sample_Init2(HWND hwnd) +{ + memset(g_SampleBuffers, 0, sizeof(g_SampleBuffers)); + memset(g_ChannelBuffers, 0, sizeof(g_ChannelBuffers)); + + g_Camera.is_lara_mic = g_SavedAppSettings.LaraMic; + g_IsSoundEnabled = false; + + if (!g_SavedAppSettings.SoundEnabled + || !g_SavedAppSettings.PreferredSoundAdapter) { + return; + } + + struct SOUND_ADAPTER *preferred = + &g_SavedAppSettings.PreferredSoundAdapter->body; + g_CurrentSoundAdapter = *preferred; + + FlaggedStringCopy( + &g_CurrentSoundAdapter.description, &preferred->description); + FlaggedStringCopy(&g_CurrentSoundAdapter.module, &preferred->module); + + if (!S_Audio_Sample_DSoundCreate(g_CurrentSoundAdapter.lpAdapterGuid)) { + return; + } + + if (!hwnd) { + hwnd = g_GameWindowHandle; + } + + if FAILED (IDirectSound_SetCooperativeLevel( + g_DSound, hwnd, DSSCL_EXCLUSIVE)) { + Shell_ExitSystem("Error: Can't set DSound cooperative level"); + } + + if (S_Audio_Sample_DSoundBufferTest()) { + g_IsSoundEnabled = true; + } +} + +bool __cdecl S_Audio_Sample_DSoundCreate(GUID *guid) +{ + return SUCCEEDED(DirectSoundCreate(guid, &g_DSound, NULL)); +} + +bool __cdecl S_Audio_Sample_DSoundBufferTest(void) +{ + WAVEFORMATEX format; + DSBUFFERDESC desc; + LPDIRECTSOUNDBUFFER dsBuffer; + + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER; + desc.dwBufferBytes = 0; + desc.dwReserved = 0; + desc.lpwfxFormat = NULL; + + if FAILED (IDirectSound_CreateSoundBuffer( + g_DSound, &desc, &dsBuffer, NULL)) { + return false; + } + + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 2; + format.nSamplesPerSec = 11025; + format.nAvgBytesPerSec = 44100; + format.nBlockAlign = 4; + format.wBitsPerSample = 16; + format.cbSize = 0; + + bool result = SUCCEEDED(IDirectSoundBuffer_SetFormat(dsBuffer, &format)); + IDirectSoundBuffer_Release(dsBuffer); + return result; +} + +void __cdecl S_Audio_Sample_Shutdown(void) +{ + S_Audio_Sample_CloseAllTracks(); + if (g_DSound != NULL) { + IDirectSound_Release(g_DSound); + g_DSound = NULL; + } +} + +bool __cdecl S_Audio_Sample_IsEnabled(void) +{ + return g_IsSoundEnabled; +} diff --git a/src/specific/s_sound.h b/src/specific/s_sound.h new file mode 100644 index 00000000..ac6849bb --- /dev/null +++ b/src/specific/s_sound.h @@ -0,0 +1,31 @@ +#pragma once + +#include "global/types.h" + +#define VOLUME_PCT(x) \ + (DSBVOLUME_MIN + (DSBVOLUME_MAX - DSBVOLUME_MIN) * (x) / 100) + +struct SOUND_ADAPTER_NODE *__cdecl S_Audio_Sample_GetAdapter(GUID *guid); +void __cdecl S_Audio_Sample_CloseAllTracks(void); +bool __cdecl S_Audio_Sample_Load( + int32_t sample_id, LPWAVEFORMATEX format, const void *data, + uint32_t data_size); +bool __cdecl S_Audio_Sample_IsTrackPlaying(int32_t track_id); +int32_t __cdecl S_Audio_Sample_Play( + int32_t sample_idx, int32_t volume, int32_t pitch, int32_t pan, + uint32_t flags); +int32_t __cdecl S_Audio_Sample_GetFreeTrackIndex(void); +void __cdecl S_Audio_Sample_AdjustTrackVolumeAndPan( + int32_t track_id, int32_t volume, int32_t pan); +void __cdecl S_Audio_Sample_AdjustTrackPitch(int32_t track_id, int32_t pitch); +void __cdecl S_Audio_Sample_CloseTrack(int32_t track_id); +bool __cdecl S_Audio_Sample_Init(void); +bool __cdecl S_Audio_Sample_DSoundEnumerate( + struct SOUND_ADAPTER_LIST *adapter_list); +BOOL CALLBACK S_Audio_Sample_DSoundEnumCallback( + LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context); +void __cdecl S_Audio_Sample_Init2(HWND hwnd); +bool __cdecl S_Audio_Sample_DSoundCreate(GUID *guid); +bool __cdecl S_Audio_Sample_DSoundBufferTest(void); +void __cdecl S_Audio_Sample_Shutdown(void); +bool __cdecl S_Audio_Sample_IsEnabled(void); diff --git a/src/specific/s_winvid.c b/src/specific/s_winvid.c new file mode 100644 index 00000000..e31f47bb --- /dev/null +++ b/src/specific/s_winvid.c @@ -0,0 +1,64 @@ +#include "specific/s_winvid.h" + +#include "global/types.h" + +void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize) +{ + item->lpString = malloc(dwSize); + + if (item->lpString != NULL) { + *item->lpString = 0; + item->isPresented = true; + } +} + +void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter) +{ + LPTSTR lpDriverDescription = malloc(256); + LPTSTR lpDriverName = malloc(256); + + if (lpDriverDescription) { + *lpDriverDescription = 0; + adapter->driverDescription.lpString = lpDriverDescription; + adapter->driverDescription.isPresented = true; + } + + if (lpDriverName) { + *lpDriverName = 0; + adapter->driverName.lpString = lpDriverName; + adapter->driverName.isPresented = true; + } +} + +void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item) +{ + if (item->isPresented && item->lpString) { + free(item->lpString); + item->lpString = NULL; + item->isPresented = false; + } +} + +bool FlaggedStringCopy(struct STRING_FLAGGED *dst, struct STRING_FLAGGED *src) +{ + if (dst == NULL || src == NULL || dst == src || !src->isPresented) { + return false; + } + + size_t srcLen = lstrlen(src->lpString); + + dst->isPresented = false; + dst->lpString = malloc(srcLen + 1); + + if (dst->lpString == NULL) { + return false; + } + + if (srcLen > 0) { + lstrcpy(dst->lpString, src->lpString); + } else { + *dst->lpString = 0; + } + dst->isPresented = true; + return true; +} diff --git a/src/specific/s_winvid.h b/src/specific/s_winvid.h new file mode 100644 index 00000000..a2452e85 --- /dev/null +++ b/src/specific/s_winvid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "global/types.h" + +#include + +bool FlaggedStringCopy(struct STRING_FLAGGED *dst, struct STRING_FLAGGED *src); +void __thiscall FlaggedStringCreate(struct STRING_FLAGGED *item, DWORD dwSize); +void __thiscall FlaggedStringDelete(struct STRING_FLAGGED *item); +void __thiscall FlaggedStringsCreate(struct DISPLAY_ADAPTER *adapter);