1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-11-06 05:35:55 +00:00

Merge branch 'miami' of https://github.com/GTAmodding/re3 into VCSanim

This commit is contained in:
erorcun 2021-02-08 13:23:19 +03:00
commit b464bb7fd4
111 changed files with 1956 additions and 779 deletions

View file

@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal] platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal]
buildtype: [Debug, Release] buildtype: [Debug, Release, Vanilla]
steps: steps:
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2 uses: microsoft/setup-msbuild@v1.0.2
@ -48,14 +48,22 @@ jobs:
- name: Build - name: Build
run: | run: |
msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}} msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
- name: Pack artifacts # - name: Pack artifacts
# run: |
# 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
- name: Move binaries to gamefiles
run: | run: |
7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/* mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/
- name: Move dynamic dependencies to gamefiles
run: |
mv ./vendor/mpg123/dist/Win64/libmpg123-0.dll ./gamefiles/
mv ./vendor/openal-soft/dist/Win64/OpenAL32.dll ./gamefiles/
- name: Upload artifact to actions - name: Upload artifact to actions
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: reVC_${{matrix.buildtype}}_${{matrix.platform}} name: reVC_${{matrix.buildtype}}_${{matrix.platform}}
path: ./bin/${{matrix.platform}}/${{matrix.buildtype}} path: ./gamefiles/*
# - name: Upload artifact to Bintray # - name: Upload artifact to Bintray
# uses: hpcsc/upload-bintray-docker-action@v1 # uses: hpcsc/upload-bintray-docker-action@v1
# with: # with:

View file

@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
platform: [win-x86-librw_d3d9-mss, win-x86-librw_gl3_glfw-mss, win-x86-librw_d3d9-oal, win-x86-librw_gl3_glfw-oal] platform: [win-x86-librw_d3d9-mss, win-x86-librw_gl3_glfw-mss, win-x86-librw_d3d9-oal, win-x86-librw_gl3_glfw-oal]
buildtype: [Debug, Release] buildtype: [Debug, Release, Vanilla]
steps: steps:
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2 uses: microsoft/setup-msbuild@v1.0.2
@ -48,14 +48,23 @@ jobs:
- name: Build - name: Build
run: | run: |
msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}} msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
- name: Pack artifacts # - name: Pack artifacts
# run: |
# 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
- name: Move binaries to gamefiles
run: | run: |
7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/* mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/
- if: contains(matrix.platform, 'oal')
name: Move dynamic dependencies to gamefiles
run: |
mv ./vendor/mpg123/dist/Win32/libmpg123-0.dll ./gamefiles/
mv ./vendor/openal-soft/dist/Win32/OpenAL32.dll ./gamefiles/
- name: Upload artifact to actions - name: Upload artifact to actions
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: reVC_${{matrix.buildtype}}_${{matrix.platform}} name: reVC_${{matrix.buildtype}}_${{matrix.platform}}
path: reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip path: ./gamefiles/*
# - name: Upload artifact to Bintray # - name: Upload artifact to Bintray
# uses: hpcsc/upload-bintray-docker-action@v1 # uses: hpcsc/upload-bintray-docker-action@v1
# with: # with:

View file

@ -13,27 +13,69 @@ The aim of this project is to reverse GTA Vice City for PC.
- (Optional) If you want to use optional features, copy the files in /gamefiles folder to your game root folder. - (Optional) If you want to use optional features, copy the files in /gamefiles folder to your game root folder.
- Move reVC.exe to GTA VC directory and run it. - Move reVC.exe to GTA VC directory and run it.
## Preparing the environment for building ## Latest standalone executables to download
You may want to point GTA_VC_RE_DIR environment variable to GTA VC root folder if you want executable to be moved there via post-build script. (Put content of selected archive into gamedir)
- For Linux, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux) - [Windows D3D9 MSS 32bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_x86/miami/reVC_Release_win-x86-librw_d3d9-mss.zip)
- For FreeBSD, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD) - [Windows D3D9 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_d3d9-oal.zip)
- For Windows, assuming you have Visual Studio: - [Windows OpenGL 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_gl3_glfw-oal.zip)
- Clone the repo using the argument `--recursive`. - [Linux 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/ubuntu-latest-gl3.zip)
- Run one of the `premake-vsXXXX.cmd` variants on root folder. - [MacOS 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/macos-latest-gl3.zip)
- Open the project via Visual Studio
## Building from Source
When using premake, you may want to point GTA_VC_RE_DIR environment variable to GTA Vice City root folder, if you want executable to be moved there via post-build script.
<details><summary>Linux Premake</summary>
For Linux using premake, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux)
</details>
<details><summary>Linux Conan</summary>
Obtain source code.
```
git clone https://github.com/GTAmodding/re3.git reVC -b miami
cd reVC
git submodule init
git submodule update --recursive
```
Install python and conan, and then run build.
```
conan export vendor/librw librw/master@
mkdir build
cd build
conan install .. reVC/master@ -if build -o reVC:audio=openal -o librw:platform=gl3 -o librw:gl3_gfxlib=glfw --build missing -s reVC:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo
conan build .. -if build -bf build -pf package
```
</details>
<details><summary>FreeBSD</summary>
For FreeBSD using premake, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD)
</details>
<details><summary>Windows</summary>
Assuming you have Visual Studio:
- Clone the repo using the argument `--recursive`.
- Run one of the `premake-vsXXXX.cmd` variants on root folder.
- Open the project via Visual Studio
**If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version) **If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version)
There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/miami/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across. **If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows).
</details>
> :information_source: **If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows). > :information_source: There are various settings in [config.h](https://github.com/GTAmodding/re3/tree/miami/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across.
> :information_source: **Did you notice librw?** reVC uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of reVC, but you also can use LIBRW enviorenment variable to specify path to your own librw. > :information_source: **Did you notice librw?** reVC uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of reVC, but you also can use LIBRW enviorenment variable to specify path to your own librw.
## Contributing ## Contributing
Please read the [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) Document Please read the [Coding Style](https://github.com/GTAmodding/re3/blob/miami/CODING_STYLE.md) Document
### Unreversed / incomplete classes ### Unreversed / incomplete classes

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -65,7 +65,7 @@ end
workspace "reVC" workspace "reVC"
language "C++" language "C++"
configurations { "Debug", "Release" } configurations { "Debug", "Release", "Vanilla" }
startproject "reVC" startproject "reVC"
location "build" location "build"
symbols "Full" symbols "Full"
@ -113,13 +113,16 @@ workspace "reVC"
filter "configurations:Debug" filter "configurations:Debug"
defines { "DEBUG" } defines { "DEBUG" }
filter "configurations:Release" filter "configurations:not Debug"
defines { "NDEBUG" } defines { "NDEBUG" }
optimize "Speed" optimize "Speed"
if(_OPTIONS["lto"]) then if(_OPTIONS["lto"]) then
flags { "LinkTimeOptimization" } flags { "LinkTimeOptimization" }
end end
filter "configurations:Vanilla"
defines { "VANILLA_DEFINES" }
filter { "platforms:win*" } filter { "platforms:win*" }
system "windows" system "windows"
@ -201,6 +204,7 @@ project "librw"
architecture "amd64" architecture "amd64"
filter "platforms:win*" filter "platforms:win*"
defines { "_CRT_SECURE_NO_WARNINGS", "_CRT_NONSTDC_NO_DEPRECATE" }
staticruntime "on" staticruntime "on"
buildoptions { "/Zc:sizedDealloc-" } buildoptions { "/Zc:sizedDealloc-" }

View file

@ -8846,7 +8846,7 @@ cAudioManager::ProcessFrontEnd()
break; break;
case SOUND_PICKUP_BONUS: case SOUND_PICKUP_BONUS:
case SOUND_FRONTEND_MENU_STARTING: case SOUND_FRONTEND_MENU_STARTING:
case SOUND_HUD_SOUND: case SOUND_HUD:
stereo = true; stereo = true;
m_sQueueSample.m_nSampleIndex = SFX_INFO_LEFT; m_sQueueSample.m_nSampleIndex = SFX_INFO_LEFT;
center = true; center = true;
@ -8882,11 +8882,11 @@ cAudioManager::ProcessFrontEnd()
case SOUND_CLOCK_TICK: case SOUND_CLOCK_TICK:
m_sQueueSample.m_nSampleIndex = SFX_TIMER; m_sQueueSample.m_nSampleIndex = SFX_TIMER;
break; break;
case SOUND_FRONTEND_NO_RADIO: case SOUND_FRONTEND_RADIO_TURN_OFF:
case SOUND_FRONTEND_RADIO_CHANGE: case SOUND_FRONTEND_RADIO_TURN_ON:
m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK; m_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK;
break; break;
case SOUND_FRONTEND_RADIO_CHANGE_2: case SOUND_FRONTEND_HURRICANE:
m_sQueueSample.m_nSampleIndex = SFX_HURRICANE_MA; m_sQueueSample.m_nSampleIndex = SFX_HURRICANE_MA;
break; break;
case SOUND_BULLETTRACE_1: case SOUND_BULLETTRACE_1:
@ -8937,9 +8937,9 @@ cAudioManager::ProcessFrontEnd()
sample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]; sample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];
if (sample == SOUND_FRONTEND_NO_RADIO) if (sample == SOUND_FRONTEND_RADIO_TURN_OFF)
m_sQueueSample.m_nFrequency = 28509; m_sQueueSample.m_nFrequency = 28509;
else if (sample == SOUND_FRONTEND_RADIO_CHANGE) else if (sample == SOUND_FRONTEND_RADIO_TURN_ON)
m_sQueueSample.m_nFrequency = 32000; m_sQueueSample.m_nFrequency = 32000;
else if (sample == SOUND_BULLETTRACE_1 || sample == SOUND_BULLETTRACE_2) { else if (sample == SOUND_BULLETTRACE_1 || sample == SOUND_BULLETTRACE_2) {
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex); m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);

View file

@ -21,6 +21,10 @@
#include "DMAudio.h" #include "DMAudio.h"
#include "GenericGameStorage.h" #include "GenericGameStorage.h"
#if !defined FIX_BUGS && (defined RADIO_SCROLL_TO_PREV_STATION || defined RADIO_OFF_TEXT)
static_assert(false, "R*'s radio implementation is quite buggy, RADIO_SCROLL_TO_PREV_STATION and RADIO_OFF_TEXT won't work without FIX_BUGS");
#endif
cMusicManager MusicManager; cMusicManager MusicManager;
int32 gNumRetunePresses; int32 gNumRetunePresses;
int32 gRetuneCounter; int32 gRetuneCounter;
@ -52,7 +56,7 @@ cMusicManager::cMusicManager()
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
m_nUpcomingMusicMode = MUSICMODE_DISABLED; m_nUpcomingMusicMode = MUSICMODE_DISABLED;
m_nMusicMode = MUSICMODE_DISABLED; m_nMusicMode = MUSICMODE_DISABLED;
field_2 = false; m_bSetNextStation = false;
for (int i = 0; i < NUM_RADIOS; i++) for (int i = 0; i < NUM_RADIOS; i++)
aListenTimeArray[i] = 0.0f; aListenTimeArray[i] = 0.0f;
@ -71,27 +75,27 @@ cMusicManager::ResetMusicAfterReload()
float afRadioTime[NUM_RADIOS]; float afRadioTime[NUM_RADIOS];
m_bRadioSetByScript = false; m_bRadioSetByScript = false;
m_nRadioStation = WILDSTYLE; m_nRadioStationScript = WILDSTYLE;
m_nRadioPosition = -1; m_nRadioPosition = -1;
m_nAnnouncement = NO_TRACK; m_nAnnouncement = NO_TRACK;
m_bAnnouncementInProgress = false; m_bAnnouncementInProgress = false;
field_2 = false; m_bSetNextStation = false;
RadioStaticTimer = 0; RadioStaticTimer = 0;
gNumRetunePresses = 0; gNumRetunePresses = 0;
gRetuneCounter = 0; gRetuneCounter = 0;
m_nFrontendTrack = NO_TRACK; m_nFrontendTrack = NO_TRACK;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
field_398E = false; m_FrontendLoopFlag = false;
field_398F = false; m_bTrackChangeStarted = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
field_3994 = false; m_nNextLoopFlag = false;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
field_3996 = false; m_bGameplayAllowsRadio = false;
field_3997 = false; m_bRadioStreamReady = false;
nFramesSinceCutsceneEnded = -1; nFramesSinceCutsceneEnded = -1;
field_3999 = false; m_bUserResumedGame = false;
field_399A = false; m_bMusicModeChangeStarted = false;
field_399C = false; m_bEarlyFrontendTrack = false;
m_nVolumeLatency = 0; m_nVolumeLatency = 0;
m_nCurrentVolume = 0; m_nCurrentVolume = 0;
m_nMaxVolume = 0; m_nMaxVolume = 0;
@ -108,7 +112,7 @@ cMusicManager::ResetMusicAfterReload()
for (int i = 0; i < NUM_RADIOS; i++) { for (int i = 0; i < NUM_RADIOS; i++) {
aListenTimeArray[i] = afRadioTime[i]; aListenTimeArray[i] = afRadioTime[i];
uint32 trackPos = GetSavedRadioStationPosition(i); int32 trackPos = GetSavedRadioStationPosition(i);
if (trackPos != -1) { if (trackPos != -1) {
if (trackPos > m_aTracks[i].m_nLength) { if (trackPos > m_aTracks[i].m_nLength) {
debug("Radio Track %d saved position is %d, Length is only %d\n", i, trackPos, m_aTracks[i].m_nLength); debug("Radio Track %d saved position is %d, Length is only %d\n", i, trackPos, m_aTracks[i].m_nLength);
@ -179,7 +183,7 @@ cMusicManager::Initialise()
m_bResetTimers = false; m_bResetTimers = false;
m_nResetTime = 0; m_nResetTime = 0;
m_bRadioSetByScript = false; m_bRadioSetByScript = false;
m_nRadioStation = WILDSTYLE; m_nRadioStationScript = WILDSTYLE;
m_nRadioPosition = -1; m_nRadioPosition = -1;
m_nRadioInCar = NO_TRACK; m_nRadioInCar = NO_TRACK;
gRetuneCounter = 0; gRetuneCounter = 0;
@ -188,18 +192,18 @@ cMusicManager::Initialise()
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
m_nUpcomingMusicMode = MUSICMODE_DISABLED; m_nUpcomingMusicMode = MUSICMODE_DISABLED;
m_nMusicMode = MUSICMODE_DISABLED; m_nMusicMode = MUSICMODE_DISABLED;
field_398E = false; m_FrontendLoopFlag = false;
field_398F = false; m_bTrackChangeStarted = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
field_3994 = false; m_nNextLoopFlag = false;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
field_3996 = false; m_bGameplayAllowsRadio = false;
field_3997 = false; m_bRadioStreamReady = false;
nFramesSinceCutsceneEnded = -1; nFramesSinceCutsceneEnded = -1;
field_3999 = false; m_bUserResumedGame = false;
field_399A = false; m_bMusicModeChangeStarted = false;
m_nMusicModeToBeSet = MUSICMODE_DISABLED; m_nMusicModeToBeSet = MUSICMODE_DISABLED;
field_399C = false; m_bEarlyFrontendTrack = false;
m_nVolumeLatency = 0; m_nVolumeLatency = 0;
m_nCurrentVolume = 0; m_nCurrentVolume = 0;
m_nMaxVolume = 0; m_nMaxVolume = 0;
@ -227,7 +231,7 @@ cMusicManager::SetRadioChannelByScript(uint32 station, int32 pos)
station = STREAMED_SOUND_CITY_AMBIENT; station = STREAMED_SOUND_CITY_AMBIENT;
if (station <= STREAMED_SOUND_RADIO_POLICE) { if (station <= STREAMED_SOUND_RADIO_POLICE) {
m_bRadioSetByScript = true; m_bRadioSetByScript = true;
m_nRadioStation = station; m_nRadioStationScript = station;
m_nRadioPosition = pos == -1 ? -1 : pos % m_aTracks[station].m_nLength; m_nRadioPosition = pos == -1 ? -1 : pos % m_aTracks[station].m_nLength;
} }
} }
@ -292,7 +296,7 @@ cMusicManager::SetRadioInCar(uint32 station)
void void
cMusicManager::RecordRadioStats() cMusicManager::RecordRadioStats()
{ {
if (m_nPlayingTrack < STREAMED_SOUND_CITY_AMBIENT) { if (m_nPlayingTrack < NUM_RADIOS) {
double time /*Rusty*/ = CTimer::GetTimeInMillisecondsPauseMode(); double time /*Rusty*/ = CTimer::GetTimeInMillisecondsPauseMode();
if (time > m_nLastTrackServiceTime) if (time > m_nLastTrackServiceTime)
aListenTimeArray[m_nPlayingTrack] += time - m_nLastTrackServiceTime; aListenTimeArray[m_nPlayingTrack] += time - m_nLastTrackServiceTime;
@ -321,11 +325,11 @@ cMusicManager::ChangeMusicMode(uint8 mode)
while (SampleManager.IsStreamPlaying(0)) while (SampleManager.IsStreamPlaying(0))
SampleManager.StopStreamedFile(0); SampleManager.StopStreamedFile(0);
m_nMusicMode = m_nUpcomingMusicMode; m_nMusicMode = m_nUpcomingMusicMode;
field_399A = false; m_bMusicModeChangeStarted = false;
field_398F = false; m_bTrackChangeStarted = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
field_3994 = false; m_nNextLoopFlag = false;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
m_nFrontendTrack = NO_TRACK; m_nFrontendTrack = NO_TRACK;
m_bAnnouncementInProgress = false; m_bAnnouncementInProgress = false;
@ -356,7 +360,7 @@ cMusicManager::Service()
if (!m_bIsInitialised || m_bDisabled) return; if (!m_bIsInitialised || m_bDisabled) return;
if (!field_399A) if (!m_bMusicModeChangeStarted)
m_nMusicModeToBeSet = m_nUpcomingMusicMode; m_nMusicModeToBeSet = m_nUpcomingMusicMode;
if (m_nMusicModeToBeSet == m_nMusicMode) { if (m_nMusicModeToBeSet == m_nMusicMode) {
if (!AudioManager.m_nUserPause || AudioManager.m_nPreviousUserPause || m_nMusicMode != MUSICMODE_FRONTEND) if (!AudioManager.m_nUserPause || AudioManager.m_nPreviousUserPause || m_nMusicMode != MUSICMODE_FRONTEND)
@ -371,13 +375,13 @@ cMusicManager::Service()
else else
m_nMusicMode = MUSICMODE_DISABLED; m_nMusicMode = MUSICMODE_DISABLED;
} else { } else {
field_399A = true; m_bMusicModeChangeStarted = true;
if (!field_3999 && !AudioManager.m_nUserPause && AudioManager.m_nPreviousUserPause) if (!m_bUserResumedGame && !AudioManager.m_nUserPause && AudioManager.m_nPreviousUserPause)
field_3999 = true; m_bUserResumedGame = true;
if (AudioManager.m_FrameCounter % 4 == 0) { if (AudioManager.m_FrameCounter % 4 == 0) {
gNumRetunePresses = 0; gNumRetunePresses = 0;
gRetuneCounter = 0; gRetuneCounter = 0;
field_2 = false; m_bSetNextStation = false;
if (SampleManager.IsStreamPlaying(0)) { if (SampleManager.IsStreamPlaying(0)) {
if (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded) if (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded)
{ {
@ -390,14 +394,14 @@ cMusicManager::Service()
} else { } else {
bRadioStatsRecorded = false; bRadioStatsRecorded = false;
m_nMusicMode = m_nMusicModeToBeSet; m_nMusicMode = m_nMusicModeToBeSet;
field_399A = false; m_bMusicModeChangeStarted = false;
field_398F = false; m_bTrackChangeStarted = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
field_3994 = false; m_nNextLoopFlag = false;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
if (field_399C) if (m_bEarlyFrontendTrack)
field_399C = false; m_bEarlyFrontendTrack = false;
else else
m_nFrontendTrack = NO_TRACK; m_nFrontendTrack = NO_TRACK;
} }
@ -417,19 +421,19 @@ cMusicManager::ServiceFrontEndMode()
g_bAnnouncementReadPosAlready = false; g_bAnnouncementReadPosAlready = false;
m_nAnnouncement = NO_TRACK; m_nAnnouncement = NO_TRACK;
m_bAnnouncementInProgress = false; m_bAnnouncementInProgress = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
m_nFrontendTrack = NO_TRACK; m_nFrontendTrack = NO_TRACK;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
} }
if (AudioManager.m_FrameCounter % 4 != 0) return; if (AudioManager.m_FrameCounter % 4 != 0) return;
if (!field_398F && !field_3995) { if (!m_bTrackChangeStarted && !m_bVerifyNextTrackStartedToPlay) {
m_nStreamedTrack = m_nFrontendTrack; m_nNextTrack = m_nFrontendTrack;
field_3994 = field_398E; m_nNextLoopFlag = m_FrontendLoopFlag;
} }
if (m_nStreamedTrack == m_nPlayingTrack) { if (m_nNextTrack == m_nPlayingTrack) {
if (SampleManager.IsStreamPlaying(0)) { if (SampleManager.IsStreamPlaying(0)) {
if (m_nVolumeLatency > 0) m_nVolumeLatency--; if (m_nVolumeLatency > 0) m_nVolumeLatency--;
else { else {
@ -444,25 +448,25 @@ cMusicManager::ServiceFrontEndMode()
ChangeMusicMode(MUSICMODE_GAME); ChangeMusicMode(MUSICMODE_GAME);
} }
} else { } else {
field_398F = true; m_bTrackChangeStarted = true;
if (field_3995 || !SampleManager.IsStreamPlaying(0)) { if (m_bVerifyNextTrackStartedToPlay || !SampleManager.IsStreamPlaying(0)) {
bRadioStatsRecorded = false; bRadioStatsRecorded = false;
if (SampleManager.IsStreamPlaying(0) || m_nStreamedTrack == NO_TRACK) { if (SampleManager.IsStreamPlaying(0) || m_nNextTrack == NO_TRACK) {
m_nPlayingTrack = m_nStreamedTrack; m_nPlayingTrack = m_nNextTrack;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
field_398F = false; m_bTrackChangeStarted = false;
} else { } else {
uint32 trackStartPos = (m_nStreamedTrack > STREAMED_SOUND_RADIO_POLICE) ? 0 : GetTrackStartPos(m_nStreamedTrack); uint32 trackStartPos = (m_nNextTrack > STREAMED_SOUND_RADIO_POLICE) ? 0 : GetTrackStartPos(m_nNextTrack);
if (m_nStreamedTrack != NO_TRACK) { if (m_nNextTrack != NO_TRACK) {
SampleManager.SetStreamedFileLoopFlag(field_3994, 0); SampleManager.SetStreamedFileLoopFlag(m_nNextLoopFlag, 0);
SampleManager.StartStreamedFile(m_nStreamedTrack, trackStartPos, 0); SampleManager.StartStreamedFile(m_nNextTrack, trackStartPos, 0);
m_nVolumeLatency = 3; m_nVolumeLatency = 3;
m_nCurrentVolume = 0; m_nCurrentVolume = 0;
m_nMaxVolume = 100; m_nMaxVolume = 100;
SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0); SampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);
if (m_nStreamedTrack < STREAMED_SOUND_CITY_AMBIENT) if (m_nNextTrack < STREAMED_SOUND_CITY_AMBIENT)
m_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode(); m_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode();
field_3995 = true; m_bVerifyNextTrackStartedToPlay = true;
} }
} }
} else { } else {
@ -483,8 +487,8 @@ cMusicManager::ServiceGameMode()
{ {
CPed *ped = FindPlayerPed(); CPed *ped = FindPlayerPed();
CVehicle *vehicle = AudioManager.FindVehicleOfPlayer(); CVehicle *vehicle = AudioManager.FindVehicleOfPlayer();
field_3997 = field_3996; m_bRadioStreamReady = m_bGameplayAllowsRadio;
field_3996 = false; m_bGameplayAllowsRadio = false;
switch (CGame::currArea) switch (CGame::currArea)
{ {
@ -495,29 +499,28 @@ cMusicManager::ServiceGameMode()
case AREA_BLOOD: case AREA_BLOOD:
case AREA_OVALRING: case AREA_OVALRING:
case AREA_MALIBU_CLUB: case AREA_MALIBU_CLUB:
field_3996 = false; m_bGameplayAllowsRadio = false;
break; break;
default: default:
if (SampleManager.GetMusicVolume()) { if (SampleManager.GetMusicVolume()) {
if (PlayerInCar()) if (PlayerInCar())
field_3996 = true; m_bGameplayAllowsRadio = true;
} else } else
field_3996 = false; m_bGameplayAllowsRadio = false;
break; break;
} }
if (!field_3996) { if (!m_bGameplayAllowsRadio) {
nFramesSinceCutsceneEnded = -1; nFramesSinceCutsceneEnded = -1;
gNumRetunePresses = 0; gNumRetunePresses = 0;
gRetuneCounter = 0; gRetuneCounter = 0;
field_2 = false; m_bSetNextStation = false;
} else if (ped) { } else if (ped) {
if(!ped->DyingOrDead()) { if(!ped->DyingOrDead() && vehicle) {
#ifdef GTA_PC #ifdef GTA_PC
if (SampleManager.IsMP3RadioChannelAvailable() if (SampleManager.IsMP3RadioChannelAvailable()
&& vehicle->m_nRadioStation < USERTRACK && vehicle->m_nRadioStation < USERTRACK
&& ControlsManager.GetIsKeyboardKeyJustDown(rsF9) && ControlsManager.GetIsKeyboardKeyJustDown(rsF9))
&& vehicle)
{ {
if (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) { if (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {
gNumRetunePresses = 0; gNumRetunePresses = 0;
@ -532,7 +535,7 @@ cMusicManager::ServiceGameMode()
} }
} }
#endif #endif
if (CPad::GetPad(0)->ChangeStationJustDown() && vehicle) if (CPad::GetPad(0)->ChangeStationJustDown())
{ {
if (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) { if (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {
gNumRetunePresses++; gNumRetunePresses++;
@ -540,147 +543,183 @@ cMusicManager::ServiceGameMode()
RadioStaticCounter = 0; RadioStaticCounter = 0;
} }
} }
#ifdef RADIO_SCROLL_TO_PREV_STATION
else if(CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustDown()) {
if(!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {
int scrollNext = ControlsManager.GetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, MOUSE);
int scrollPrev = scrollNext == rsMOUSEWHEELUPBUTTON ? rsMOUSEWHEELDOWNBUTTON
: scrollNext == rsMOUSEWHEELDOWNBUTTON ? rsMOUSEWHEELUPBUTTON : -1;
if(scrollPrev != -1 && !ControlsManager.IsAnyVehicleActionAssignedToMouseKey(scrollPrev)) {
gNumRetunePresses--;
gRetuneCounter = 20;
RadioStaticCounter = 0;
int track = gNumRetunePresses + vehicle->m_nRadioStation;
while(track < 0) track += NUM_RADIOS + 1;
while(track >= NUM_RADIOS + 1) track -= NUM_RADIOS + 1;
if(!DMAudio.IsMP3RadioChannelAvailable() && track == USERTRACK) gNumRetunePresses--;
}
}
}
#endif
} }
} }
if (field_3999) if (m_bUserResumedGame)
{ {
field_3997 = false; m_bRadioStreamReady = false;
field_3999 = false; m_bUserResumedGame = false;
} }
if (m_nPlayingTrack == NO_TRACK && m_nFrontendTrack == NO_TRACK) if (m_nPlayingTrack == NO_TRACK && m_nFrontendTrack == NO_TRACK)
field_3997 = false; m_bRadioStreamReady = false;
if (field_3996) if (m_bGameplayAllowsRadio)
{ {
if (field_3997) if (!m_bRadioStreamReady)
{ {
if (m_nAnnouncement < NO_TRACK) { if(vehicle == nil) {
if ((m_bAnnouncementInProgress || m_nFrontendTrack == m_nPlayingTrack) && ServiceAnnouncement()) { m_nFrontendTrack = STREAMED_SOUND_RADIO_WAVE; // huh?
if (m_bAnnouncementInProgress) {
field_2 = false;
gNumRetunePresses = 0;
gRetuneCounter = 0;
return;
}
if(m_nAnnouncement == NO_TRACK) {
m_nStreamedTrack = NO_TRACK;
m_nFrontendTrack = GetCarTuning();
field_2 = false;
gRetuneCounter = 0;
gNumRetunePresses = 0;
}
}
}
if (!m_bAnnouncementInProgress
&& m_nAnnouncement == NO_TRACK
&& m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER
&& !SampleManager.IsStreamPlaying(0))
{
SampleManager.StartStreamedFile(STREAMED_SOUND_RADIO_MP3_PLAYER, 0, 0);
}
if (!m_bRadioSetByScript)
{
if (gNumRetunePresses != 0)
{
if (--gRetuneCounter == 0)
{
field_2 = true;
gRetuneCounter = 0;
}
}
if (gRetuneCounter)
{
int32 station = gNumRetunePresses + vehicle->m_nRadioStation;
while (station >= RADIO_OFF) station -= RADIO_OFF;
if (!DMAudio.IsMP3RadioChannelAvailable() && station == USERTRACK)
{
++gNumRetunePresses;
station = NUM_RADIOS;
}
if (station == NUM_RADIOS)
{
if (gRetuneCounter == NUM_RADIOS + 9)
{
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_NO_RADIO, 0.0f);
RadioStaticCounter = 5;
}
}
else
{
if (station == WILDSTYLE && gRetuneCounter == NUM_RADIOS + 9)
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_CHANGE, 0.0f);
AudioManager.DoPoliceRadioCrackle();
}
}
if (RadioStaticCounter < 2 && CTimer::GetTimeInMilliseconds() > RadioStaticTimer + 800)
{
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_RADIO_CHANGE, 0.0f);
RadioStaticCounter++;
RadioStaticTimer = CTimer::GetTimeInMilliseconds();
}
if (field_2)
m_nFrontendTrack = GetNextCarTuning();
if (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)
SetUpCorrectAmbienceTrack();
ServiceTrack(vehicle, ped);
if (field_2)
field_2 = false;
return; return;
} }
if (UsesPoliceRadio(vehicle)) if(m_bRadioSetByScript) {
m_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE; if(UsesPoliceRadio(vehicle))
else if (UsesTaxiRadio(vehicle)) m_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE;
m_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI; else if(UsesTaxiRadio(vehicle))
else { m_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI;
m_nFrontendTrack = m_nRadioStation; else {
vehicle->m_nRadioStation = m_nRadioStation; m_nFrontendTrack = m_nRadioStationScript;
vehicle->m_nRadioStation = m_nRadioStationScript;
}
if(m_nRadioPosition != -1) {
m_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition;
m_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();
}
m_bRadioSetByScript = false;
return;
} }
if (m_nRadioPosition != -1) { // This starts the radio when you enter the car.
m_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition; m_nFrontendTrack = GetCarTuning();
m_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode(); return;
}
if (m_nAnnouncement < NO_TRACK) {
if ((m_bAnnouncementInProgress || m_nFrontendTrack == m_nPlayingTrack) && ServiceAnnouncement()) {
if (m_bAnnouncementInProgress) {
m_bSetNextStation = false;
gNumRetunePresses = 0;
gRetuneCounter = 0;
return;
}
if(m_nAnnouncement == NO_TRACK) {
m_nNextTrack = NO_TRACK;
m_nFrontendTrack = GetCarTuning();
m_bSetNextStation = false;
gRetuneCounter = 0;
gNumRetunePresses = 0;
}
} }
}
if (!m_bAnnouncementInProgress
&& m_nAnnouncement == NO_TRACK
&& m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER
&& !SampleManager.IsStreamPlaying(0))
{
SampleManager.StartStreamedFile(STREAMED_SOUND_RADIO_MP3_PLAYER, 0, 0);
}
gRetuneCounter = 0; if (!m_bRadioSetByScript)
gNumRetunePresses = 0; {
field_2 = false; // Because when you switch radio back and forth, gNumRetunePresses will be 0 but gRetuneCounter won't.
m_bRadioSetByScript = false; #ifdef RADIO_SCROLL_TO_PREV_STATION
if(gRetuneCounter != 0) {
if(gRetuneCounter > 1)
gRetuneCounter--;
else if(gRetuneCounter == 1) {
m_bSetNextStation = true;
gRetuneCounter = 0;
}
}
#else
if (gNumRetunePresses != 0)
{
if (--gRetuneCounter == 0)
{
m_bSetNextStation = true;
gRetuneCounter = 0;
}
}
#endif
if (gRetuneCounter)
{
int32 station = gNumRetunePresses + vehicle->m_nRadioStation;
#ifdef RADIO_SCROLL_TO_PREV_STATION
while (station < 0) station += NUM_RADIOS + 1;
#endif
while (station >= NUM_RADIOS + 1) station -= NUM_RADIOS + 1;
// Scrolling back won't hit here, so increasing isn't problem
if (!DMAudio.IsMP3RadioChannelAvailable() && station == USERTRACK)
{
++gNumRetunePresses;
station = RADIO_OFF;
}
if (station == RADIO_OFF)
{
if (gRetuneCounter == 19) // One less then what switching radio sets, so runs right after turning off radio
{
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_TURN_OFF, 0.0f);
RadioStaticCounter = 5;
}
}
else
{
#ifdef RADIO_SCROLL_TO_PREV_STATION
if (vehicle->m_nRadioStation == RADIO_OFF && gRetuneCounter == 19) // Right after turning on the radio
#else
if (station == 0 && gRetuneCounter == 19) // Right after turning on the radio
#endif
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_TURN_ON, 0.0f);
AudioManager.DoPoliceRadioCrackle();
}
}
if (RadioStaticCounter < 2 && CTimer::GetTimeInMilliseconds() > RadioStaticTimer + 800)
{
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_RADIO_CHANGE, 0.0f);
RadioStaticCounter++;
RadioStaticTimer = CTimer::GetTimeInMilliseconds();
}
if (m_bSetNextStation)
m_nFrontendTrack = GetNextCarTuning();
if (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT) if (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)
SetUpCorrectAmbienceTrack(); SetUpCorrectAmbienceTrack();
ServiceTrack(vehicle, ped); ServiceTrack(vehicle, ped);
if (field_2) if (m_bSetNextStation)
field_2 = false; m_bSetNextStation = false;
return; return;
} }
if (vehicle == nil) if (UsesPoliceRadio(vehicle))
{ m_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE;
m_nFrontendTrack = STREAMED_SOUND_RADIO_WAVE; // huh? else if (UsesTaxiRadio(vehicle))
return; m_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI;
} else {
if (m_bRadioSetByScript) m_nFrontendTrack = m_nRadioStationScript;
{ vehicle->m_nRadioStation = m_nRadioStationScript;
if (UsesPoliceRadio(vehicle))
m_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE;
else if (UsesTaxiRadio(vehicle))
m_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI;
else {
m_nFrontendTrack = m_nRadioStation;
vehicle->m_nRadioStation = m_nRadioStation;
}
if (m_nRadioPosition != -1)
{
m_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition;
m_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();
}
m_bRadioSetByScript = false;
return;
} }
m_nFrontendTrack = GetCarTuning(); if (m_nRadioPosition != -1) {
m_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition;
m_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();
}
gRetuneCounter = 0;
gNumRetunePresses = 0;
m_bSetNextStation = false;
m_bRadioSetByScript = false;
if (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)
SetUpCorrectAmbienceTrack();
ServiceTrack(vehicle, ped);
if (m_bSetNextStation)
m_bSetNextStation = false;
return; return;
} }
@ -692,7 +731,7 @@ cMusicManager::ServiceGameMode()
g_bAnnouncementReadPosAlready = false; g_bAnnouncementReadPosAlready = false;
m_nAnnouncement = NO_TRACK; m_nAnnouncement = NO_TRACK;
m_bAnnouncementInProgress = false; m_bAnnouncementInProgress = false;
m_nStreamedTrack = NO_TRACK; m_nNextTrack = NO_TRACK;
m_nFrontendTrack = NO_TRACK; m_nFrontendTrack = NO_TRACK;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
} }
@ -834,7 +873,7 @@ cMusicManager::ServiceAnnouncement()
{ {
if (m_bAnnouncementInProgress) { if (m_bAnnouncementInProgress) {
if (SampleManager.IsStreamPlaying(0)) if (SampleManager.IsStreamPlaying(0))
m_nPlayingTrack = m_nStreamedTrack; m_nPlayingTrack = m_nNextTrack;
else if (m_nPlayingTrack != NO_TRACK) { else if (m_nPlayingTrack != NO_TRACK) {
m_nAnnouncement = NO_TRACK; m_nAnnouncement = NO_TRACK;
m_bAnnouncementInProgress = false; m_bAnnouncementInProgress = false;
@ -852,9 +891,9 @@ cMusicManager::ServiceAnnouncement()
} else { } else {
g_bAnnouncementReadPosAlready = false; g_bAnnouncementReadPosAlready = false;
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
m_nStreamedTrack = m_nAnnouncement; m_nNextTrack = m_nAnnouncement;
SampleManager.SetStreamedFileLoopFlag(0, false); SampleManager.SetStreamedFileLoopFlag(0, 0);
SampleManager.StartStreamedFile(m_nStreamedTrack, 0, 0); SampleManager.StartStreamedFile(m_nNextTrack, 0, 0);
SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 0, 0); SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 0, 0);
m_bAnnouncementInProgress = true; m_bAnnouncementInProgress = true;
} }
@ -868,9 +907,9 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
static bool bRadioStatsRecorded = false; static bool bRadioStatsRecorded = false;
static bool bRadioStatsRecorded2 = false; static bool bRadioStatsRecorded2 = false;
uint8 volume; uint8 volume;
if (!field_398F) if (!m_bTrackChangeStarted)
m_nStreamedTrack = m_nFrontendTrack; m_nNextTrack = m_nFrontendTrack;
if (gRetuneCounter != 0 || field_2) { if (gRetuneCounter != 0 || m_bSetNextStation) {
if (SampleManager.IsStreamPlaying(0)) { if (SampleManager.IsStreamPlaying(0)) {
if (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded) { if (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded) {
m_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0); m_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);
@ -889,28 +928,35 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
m_nPlayingTrack = NO_TRACK; m_nPlayingTrack = NO_TRACK;
} }
if (m_nStreamedTrack != m_nPlayingTrack) if (m_nNextTrack != m_nPlayingTrack)
{ {
field_398F = true; m_bTrackChangeStarted = true;
SampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0); SampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);
if (!(AudioManager.m_FrameCounter & 1)) { if (!(AudioManager.m_FrameCounter & 1)) {
if (field_3995 || !SampleManager.IsStreamPlaying(0)) { if (m_bVerifyNextTrackStartedToPlay || !SampleManager.IsStreamPlaying(0)) {
bRadioStatsRecorded2 = false; bRadioStatsRecorded2 = false;
if (SampleManager.IsStreamPlaying(0)) { if (SampleManager.IsStreamPlaying(0)) {
m_nPlayingTrack = m_nStreamedTrack; m_nPlayingTrack = m_nNextTrack;
field_3995 = false; m_bVerifyNextTrackStartedToPlay = false;
field_398F = false; m_bTrackChangeStarted = false;
if (veh) { if (veh) {
if (veh->m_nRadioStation < STREAMED_SOUND_CITY_AMBIENT || veh->m_nRadioStation > STREAMED_SOUND_AMBSIL_AMBIENT) #ifdef FIX_BUGS
if (m_nPlayingTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)
veh->m_nRadioStation = RADIO_OFF;
else if (m_nPlayingTrack < STREAMED_SOUND_CITY_AMBIENT)
veh->m_nRadioStation = m_nPlayingTrack; veh->m_nRadioStation = m_nPlayingTrack;
#else
if (veh->m_nRadioStation >= STREAMED_SOUND_CITY_AMBIENT && veh->m_nRadioStation <= STREAMED_SOUND_AMBSIL_AMBIENT)
veh->m_nRadioStation = RADIO_OFF;
else else
veh->m_nRadioStation = STREAMED_SOUND_CITY_AMBIENT; veh->m_nRadioStation = m_nPlayingTrack;
#endif
} }
} else { } else {
uint32 pos = GetTrackStartPos(m_nStreamedTrack); uint32 pos = GetTrackStartPos(m_nNextTrack);
if (m_nStreamedTrack != NO_TRACK) { if (m_nNextTrack != NO_TRACK) {
SampleManager.SetStreamedFileLoopFlag(1, 0); SampleManager.SetStreamedFileLoopFlag(1, 0);
SampleManager.StartStreamedFile(m_nStreamedTrack, pos, 0); SampleManager.StartStreamedFile(m_nNextTrack, pos, 0);
if (m_nFrontendTrack < STREAMED_SOUND_CITY_AMBIENT || m_nFrontendTrack > STREAMED_SOUND_AMBSIL_AMBIENT) if (m_nFrontendTrack < STREAMED_SOUND_CITY_AMBIENT || m_nFrontendTrack > STREAMED_SOUND_AMBSIL_AMBIENT)
{ {
m_nVolumeLatency = 10; m_nVolumeLatency = 10;
@ -923,9 +969,9 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
ComputeAmbienceVol(true, volume); ComputeAmbienceVol(true, volume);
SampleManager.SetStreamedVolumeAndPan(volume, 63, 1, 0); SampleManager.SetStreamedVolumeAndPan(volume, 63, 1, 0);
} }
if (m_nStreamedTrack < STREAMED_SOUND_CITY_AMBIENT) if (m_nNextTrack < STREAMED_SOUND_CITY_AMBIENT)
m_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode(); m_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode();
field_3995 = true; m_bVerifyNextTrackStartedToPlay = true;
} }
} }
} else { } else {
@ -939,8 +985,8 @@ cMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)
RecordRadioStats(); RecordRadioStats();
if (m_nPlayingTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT) if (m_nPlayingTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT)
{ {
if (m_nStreamedTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nStreamedTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT) if (m_nNextTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nNextTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT)
AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_CHANGE_2, 0.0); AudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_HURRICANE, 0.0);
} }
} }
SampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0); SampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);
@ -1050,14 +1096,14 @@ cMusicManager::StopCutSceneMusic(void)
} }
void void
cMusicManager::PlayFrontEndTrack(uint32 track, uint8 bPlayInFrontend) cMusicManager::PlayFrontEndTrack(uint32 track, uint8 loopFlag)
{ {
if (IsInitialised() && !m_bDisabled && track < TOTAL_STREAMED_SOUNDS && (m_nUpcomingMusicMode == MUSICMODE_FRONTEND || m_nMusicMode == MUSICMODE_FRONTEND)) if (IsInitialised() && !m_bDisabled && track < TOTAL_STREAMED_SOUNDS && (m_nUpcomingMusicMode == MUSICMODE_FRONTEND || m_nMusicMode == MUSICMODE_FRONTEND))
{ {
m_nFrontendTrack = track; m_nFrontendTrack = track;
field_398E = bPlayInFrontend; m_FrontendLoopFlag = loopFlag;
if (m_nMusicMode != MUSICMODE_FRONTEND) if (m_nMusicMode != MUSICMODE_FRONTEND)
field_399C = true; m_bEarlyFrontendTrack = true;
} }
} }
@ -1083,10 +1129,18 @@ cMusicManager::GetNextCarTuning()
if (UsesPoliceRadio(veh)) return STREAMED_SOUND_RADIO_POLICE; if (UsesPoliceRadio(veh)) return STREAMED_SOUND_RADIO_POLICE;
if (UsesTaxiRadio(veh)) return STREAMED_SOUND_RADIO_TAXI; if (UsesTaxiRadio(veh)) return STREAMED_SOUND_RADIO_TAXI;
if (gNumRetunePresses != 0) { if (gNumRetunePresses != 0) {
#ifdef RADIO_SCROLL_TO_PREV_STATION
// m_nRadioStation is unsigned, so...
int station = veh->m_nRadioStation + gNumRetunePresses;
while(station < 0) station += NUM_RADIOS + 1;
while(station >= NUM_RADIOS + 1) station -= NUM_RADIOS + 1;
veh->m_nRadioStation = station;
#else
veh->m_nRadioStation += gNumRetunePresses; veh->m_nRadioStation += gNumRetunePresses;
while (veh->m_nRadioStation >= RADIO_OFF) while(veh->m_nRadioStation >= NUM_RADIOS + 1)
veh->m_nRadioStation -= RADIO_OFF; veh->m_nRadioStation -= NUM_RADIOS + 1;
DMAudio.IsMP3RadioChannelAvailable(); // woof, just call and do nothing =P #endif
DMAudio.IsMP3RadioChannelAvailable(); // woof, just call and do nothing =P they manipulate gNumRetunePresses on DisplayRadioStationName in this case
gNumRetunePresses = 0; gNumRetunePresses = 0;
} }
return veh->m_nRadioStation; return veh->m_nRadioStation;
@ -1129,7 +1183,7 @@ cMusicManager::GetTrackStartPos(uint32 track)
uint32 uint32
cMusicManager::GetRadioPosition(uint32 station) cMusicManager::GetRadioPosition(uint32 station)
{ {
if (station < STREAMED_SOUND_CITY_AMBIENT) if (station < NUM_RADIOS)
return GetTrackStartPos(station); return GetTrackStartPos(station);
return 0; return 0;
} }
@ -1158,7 +1212,7 @@ cMusicManager::SetMalibuClubTrackPos(uint8 scriptObject)
{ {
if (!IsInitialised()) if (!IsInitialised())
m_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = 8640; m_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = 8640;
if (m_nStreamedTrack != STREAMED_SOUND_MALIBU_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_MALIBU_AMBIENT) { if (m_nNextTrack != STREAMED_SOUND_MALIBU_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_MALIBU_AMBIENT) {
switch (scriptObject) switch (scriptObject)
{ {
case SCRIPT_SOUND_NEW_BUILDING_MALIBU_1: case SCRIPT_SOUND_NEW_BUILDING_MALIBU_1:
@ -1180,7 +1234,7 @@ cMusicManager::SetStripClubTrackPos(uint8 scriptObject)
{ {
if (!IsInitialised()) if (!IsInitialised())
m_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = 0; m_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = 0;
if (m_nStreamedTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT) if (m_nNextTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT)
{ {
switch (scriptObject) switch (scriptObject)
{ {
@ -1201,7 +1255,7 @@ cMusicManager::SetStripClubTrackPos(uint8 scriptObject)
void void
cMusicManager::DisplayRadioStationName() cMusicManager::DisplayRadioStationName()
{ {
int8 gStreamedSound; uint8 gStreamedSound;
static wchar *pCurrentStation = nil; static wchar *pCurrentStation = nil;
static uint8 cDisplay = 0; static uint8 cDisplay = 0;
@ -1211,20 +1265,28 @@ cMusicManager::DisplayRadioStationName()
if (vehicle) if (vehicle)
{ {
uint8 track; int8 track;
gStreamedSound = vehicle->m_nRadioStation; gStreamedSound = vehicle->m_nRadioStation;
if (gStreamedSound >= STREAMED_SOUND_CITY_AMBIENT && gStreamedSound <= STREAMED_SOUND_AMBSIL_AMBIENT) if (gStreamedSound >= STREAMED_SOUND_CITY_AMBIENT && gStreamedSound <= STREAMED_SOUND_AMBSIL_AMBIENT)
gStreamedSound = STREAMED_SOUND_CITY_AMBIENT; gStreamedSound = RADIO_OFF;
if (gNumRetunePresses != 0) if (gNumRetunePresses != 0)
{ {
track = gNumRetunePresses + gStreamedSound; track = gNumRetunePresses + gStreamedSound;
while (track >= RADIO_OFF) track -= RADIO_OFF; #ifdef RADIO_SCROLL_TO_PREV_STATION
while (track < 0) track += NUM_RADIOS + 1;
#endif
while (track >= NUM_RADIOS + 1) track -= NUM_RADIOS + 1;
// We already handle this condition while scrolling back, on key press. No need to change this.
if (!DMAudio.IsMP3RadioChannelAvailable() && track == USERTRACK) if (!DMAudio.IsMP3RadioChannelAvailable() && track == USERTRACK)
gNumRetunePresses++; gNumRetunePresses++;
} }
else else
#ifdef FIX_BUGS
track = GetCarTuning(); // gStreamedSound or veh->m_nRadioStation would also work, but these don't cover police/taxi radios
#else
track = m_nFrontendTrack; track = m_nFrontendTrack;
#endif
wchar* string = nil; wchar* string = nil;
switch (track) { switch (track) {
@ -1241,6 +1303,18 @@ cMusicManager::DisplayRadioStationName()
if (!SampleManager.IsMP3RadioChannelAvailable()) if (!SampleManager.IsMP3RadioChannelAvailable())
return; return;
string = TheText.Get("FEA_MP3"); break; string = TheText.Get("FEA_MP3"); break;
#ifdef RADIO_OFF_TEXT
case RADIO_OFF: {
extern wchar WideErrorString[];
string = TheText.Get("FEA_FMN");
if (string == WideErrorString) {
pCurrentStation = nil;
return;
}
break;
}
#endif
default: return; default: return;
}; };
@ -1272,6 +1346,11 @@ cMusicManager::DisplayRadioStationName()
CFont::DrawFonts(); CFont::DrawFonts();
} }
} }
// Always show station text after entering car. Same behaviour as III and SA.
#ifdef FIX_BUGS
else
pCurrentStation = nil;
#endif
} }
bool bool

View file

@ -18,7 +18,7 @@ class cMusicManager
public: public:
bool m_bIsInitialised; bool m_bIsInitialised;
bool m_bDisabled; bool m_bDisabled;
bool field_2; bool m_bSetNextStation;
uint8 m_nVolumeLatency; uint8 m_nVolumeLatency;
uint8 m_nCurrentVolume; uint8 m_nCurrentVolume;
uint8 m_nMaxVolume; uint8 m_nMaxVolume;
@ -28,25 +28,25 @@ public:
bool m_bResetTimers; bool m_bResetTimers;
uint32 m_nResetTime; uint32 m_nResetTime;
bool m_bRadioSetByScript; bool m_bRadioSetByScript;
uint8 m_nRadioStation; uint8 m_nRadioStationScript;
uint32 m_nRadioPosition; int32 m_nRadioPosition;
uint32 m_nRadioInCar; uint32 m_nRadioInCar;
uint32 m_nFrontendTrack; uint32 m_nFrontendTrack;
uint32 m_nPlayingTrack; uint32 m_nPlayingTrack;
uint8 m_nUpcomingMusicMode; uint8 m_nUpcomingMusicMode;
uint8 m_nMusicMode; uint8 m_nMusicMode;
bool field_398E; bool m_FrontendLoopFlag;
bool field_398F; bool m_bTrackChangeStarted;
uint32 m_nStreamedTrack; uint32 m_nNextTrack;
bool field_3994; bool m_nNextLoopFlag;
bool field_3995; bool m_bVerifyNextTrackStartedToPlay;
bool field_3996; bool m_bGameplayAllowsRadio;
bool field_3997; bool m_bRadioStreamReady;
int8 nFramesSinceCutsceneEnded; int8 nFramesSinceCutsceneEnded;
bool field_3999; bool m_bUserResumedGame;
bool field_399A; bool m_bMusicModeChangeStarted;
uint8 m_nMusicModeToBeSet; uint8 m_nMusicModeToBeSet;
bool field_399C; bool m_bEarlyFrontendTrack;
float aListenTimeArray[NUM_RADIOS]; float aListenTimeArray[NUM_RADIOS];
float m_nLastTrackServiceTime; float m_nLastTrackServiceTime;

View file

@ -14,8 +14,8 @@ enum eRadioStation
USERTRACK, USERTRACK,
NUM_RADIOS = 10, NUM_RADIOS = 10,
POLICE_RADIO = 10, POLICE_RADIO = 10,
RADIO_OFF = 10,
//TAXI_RADIO, //TAXI_RADIO,
RADIO_OFF,
}; };
enum eMusicMode enum eMusicMode

View file

@ -15,6 +15,8 @@ ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];
ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS]; ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];
bool bChannelsCreated = false; bool bChannelsCreated = false;
int32 CChannel::channelsThatNeedService = 0;
void void
CChannel::InitChannels() CChannel::InitChannels()
{ {
@ -59,7 +61,9 @@ void CChannel::SetDefault()
Position[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f; Position[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f;
Distances[0] = 0.0f; Distances[1] = FLT_MAX; Distances[0] = 0.0f; Distances[1] = FLT_MAX;
LoopCount = 1;
LoopCount = 1;
LastProcessedOffset = UINT32_MAX;
LoopPoints[0] = 0; LoopPoints[1] = -1; LoopPoints[0] = 0; LoopPoints[1] = -1;
Frequency = MAX_FREQ; Frequency = MAX_FREQ;
@ -67,6 +71,10 @@ void CChannel::SetDefault()
void CChannel::Reset() void CChannel::Reset()
{ {
// Here is safe because ctor don't call this
if (LoopCount > 1)
channelsThatNeedService--;
ClearBuffer(); ClearBuffer();
SetDefault(); SetDefault();
} }
@ -165,10 +173,51 @@ void CChannel::SetCurrentFreq(uint32 freq)
SetPitch(ALfloat(freq) / Frequency); SetPitch(ALfloat(freq) / Frequency);
} }
void CChannel::SetLoopCount(int32 loopCount) // fake. TODO: void CChannel::SetLoopCount(int32 count)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSources[id], AL_LOOPING, loopCount == 1 ? AL_FALSE : AL_TRUE);
// 0: loop indefinitely, 1: play one time, 2: play two times etc...
// only > 1 needs manual processing
if (LoopCount > 1 && count < 2)
channelsThatNeedService--;
else if (LoopCount < 2 && count > 1)
channelsThatNeedService++;
alSourcei(alSources[id], AL_LOOPING, count == 1 ? AL_FALSE : AL_TRUE);
LoopCount = count;
}
bool CChannel::Update()
{
if (!HasSource()) return false;
if (LoopCount < 2) return false;
ALint state;
alGetSourcei(alSources[id], AL_SOURCE_STATE, &state);
if (state == AL_STOPPED) {
debug("Looping channels(%d in this case) shouldn't report AL_STOPPED, but nvm\n", id);
SetLoopCount(1);
return true;
}
assert(channelsThatNeedService > 0 && "Ref counting is broken");
ALint offset;
alGetSourcei(alSources[id], AL_SAMPLE_OFFSET, &offset);
// Rewound
if (offset < LastProcessedOffset) {
LoopCount--;
if (LoopCount == 1) {
// Playing last tune...
channelsThatNeedService--;
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
}
}
LastProcessedOffset = offset;
return true;
} }
void CChannel::SetLoopPoints(ALint start, ALint end) void CChannel::SetLoopPoints(ALint start, ALint end)
@ -200,6 +249,7 @@ void CChannel::SetPan(int32 pan)
void CChannel::ClearBuffer() void CChannel::ClearBuffer()
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
alSourcei(alSources[id], AL_LOOPING, AL_FALSE);
alSourcei(alSources[id], AL_BUFFER, AL_NONE); alSourcei(alSources[id], AL_BUFFER, AL_NONE);
Data = nil; Data = nil;
DataSize = 0; DataSize = 0;

View file

@ -19,7 +19,10 @@ class CChannel
float Distances[2]; float Distances[2];
int32 LoopCount; int32 LoopCount;
ALint LoopPoints[2]; ALint LoopPoints[2];
ALint LastProcessedOffset;
public: public:
static int32 channelsThatNeedService;
static void InitChannels(); static void InitChannels();
static void DestroyChannels(); static void DestroyChannels();
@ -37,7 +40,7 @@ public:
void SetVolume(int32 vol); void SetVolume(int32 vol);
void SetSampleData(void *_data, size_t _DataSize, int32 freq); void SetSampleData(void *_data, size_t _DataSize, int32 freq);
void SetCurrentFreq(uint32 freq); void SetCurrentFreq(uint32 freq);
void SetLoopCount(int32 loopCount); // fake void SetLoopCount(int32 count);
void SetLoopPoints(ALint start, ALint end); void SetLoopPoints(ALint start, ALint end);
void SetPosition(float x, float y, float z); void SetPosition(float x, float y, float z);
void SetDistances(float max, float min); void SetDistances(float max, float min);
@ -45,6 +48,7 @@ public:
void ClearBuffer(); void ClearBuffer();
void SetReverbMix(ALuint slot, float mix); void SetReverbMix(ALuint slot, float mix);
void UpdateReverb(ALuint slot); void UpdateReverb(ALuint slot);
bool Update();
}; };
#endif #endif

View file

@ -499,6 +499,7 @@ public:
m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK
&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK; && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
m_nRate = rate; m_nRate = rate;
m_nChannels = channels; m_nChannels = channels;
@ -980,7 +981,8 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
m_bReset(false), m_bReset(false),
m_nVolume(0), m_nVolume(0),
m_nPan(0), m_nPan(0),
m_nPosBeforeReset(0) m_nPosBeforeReset(0),
m_nLoopCount(1)
{ {
// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/) // Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
@ -1078,7 +1080,7 @@ bool CStream::IsPlaying()
ALint sourceState[2]; ALint sourceState[2];
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]); alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]); alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
if ( m_bActive || sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING) if (sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)
return true; return true;
} }
@ -1236,6 +1238,8 @@ bool CStream::Setup()
{ {
if ( IsOpened() ) if ( IsOpened() )
{ {
alSourcei(m_pAlSources[0], AL_LOOPING, AL_FALSE);
alSourcei(m_pAlSources[1], AL_LOOPING, AL_FALSE);
m_pSoundFile->Seek(0); m_pSoundFile->Seek(0);
//SetPosition(0.0f, 0.0f, 0.0f); //SetPosition(0.0f, 0.0f, 0.0f);
SetPitch(1.0f); SetPitch(1.0f);
@ -1246,6 +1250,13 @@ bool CStream::Setup()
return IsOpened(); return IsOpened();
} }
void CStream::SetLoopCount(int32 count)
{
if ( !HasSource() ) return;
m_nLoopCount = count;
}
void CStream::SetPlay(bool state) void CStream::SetPlay(bool state)
{ {
if ( !HasSource() ) return; if ( !HasSource() ) return;
@ -1305,7 +1316,7 @@ void CStream::Update()
if ( !m_bPaused ) if ( !m_bPaused )
{ {
ALint sourceState[2]; ALint totalBuffers[2] = { 0, 0 };
ALint buffersProcessed[2] = { 0, 0 }; ALint buffersProcessed[2] = { 0, 0 };
// Relying a lot on left buffer states in here // Relying a lot on left buffer states in here
@ -1313,44 +1324,51 @@ void CStream::Update()
do do
{ {
//alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f); //alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]); alGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &totalBuffers[0]);
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]); alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);
//alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f); //alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f);
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]); alGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &totalBuffers[1]);
alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]); alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);
} while (buffersProcessed[0] != buffersProcessed[1]); } while (buffersProcessed[0] != buffersProcessed[1]);
ALint looping = AL_FALSE;
alGetSourcei(m_pAlSources[0], AL_LOOPING, &looping);
if ( looping == AL_TRUE )
{
TRACE("stream set looping");
alSourcei(m_pAlSources[0], AL_LOOPING, AL_TRUE);
alSourcei(m_pAlSources[1], AL_LOOPING, AL_TRUE);
}
assert(buffersProcessed[0] == buffersProcessed[1]); assert(buffersProcessed[0] == buffersProcessed[1]);
while( buffersProcessed[0]-- ) // Correcting OpenAL concepts here:
// AL_BUFFERS_QUEUED = Number of *all* buffers in queue, including processed, processing and pending
// AL_BUFFERS_PROCESSED = Index of the buffer being processing right now. Buffers coming after that(have greater index) are pending buffers.
// which means: totalBuffers[0] - buffersProcessed[0] = pending buffers
bool buffersRefilled = false;
// We should wait queue to be cleared to loop track, because position calculation relies on queue.
if (m_nLoopCount != 1 && m_bActive && totalBuffers[0] == 0)
{ {
ALuint buffer[2]; Setup();
buffersRefilled = FillBuffers() != 0;
alSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]); if (m_nLoopCount != 0)
alSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]); m_nLoopCount--;
}
if (m_bActive && FillBuffer(buffer)) else
{
while( buffersProcessed[0]-- )
{ {
alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]); ALuint buffer[2];
alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
alSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]);
alSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]);
if (m_bActive && FillBuffer(buffer))
{
buffersRefilled = true;
alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);
alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
}
} }
} }
if ( sourceState[0] != AL_PLAYING ) // Two reasons: 1-Source may be starved to audio and stopped itself, 2- We're already waiting it to starve and die for looping track!
{ if (m_bActive && (buffersRefilled || (totalBuffers[1] - buffersProcessed[1] != 0)))
alGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]); SetPlay(true);
SetPlay(buffersProcessed[0]!=0);
}
} }
} }
@ -1362,6 +1380,7 @@ void CStream::ProviderInit()
{ {
SetPan(m_nPan); SetPan(m_nPan);
SetVolume(m_nVolume); SetVolume(m_nVolume);
SetLoopCount(m_nLoopCount);
SetPosMS(m_nPosBeforeReset); SetPosMS(m_nPosBeforeReset);
if (m_bActive) if (m_bActive)
FillBuffers(); FillBuffers();

View file

@ -69,6 +69,7 @@ class CStream
uint32 m_nVolume; uint32 m_nVolume;
uint8 m_nPan; uint8 m_nPan;
uint32 m_nPosBeforeReset; uint32 m_nPosBeforeReset;
int32 m_nLoopCount;
IDecoder *m_pSoundFile; IDecoder *m_pSoundFile;
@ -103,6 +104,8 @@ public:
void Start(); void Start();
void Stop(); void Stop();
void Update(void); void Update(void);
void SetLoopCount(int32);
void ProviderInit(); void ProviderInit();
void ProviderTerm(); void ProviderTerm();

View file

@ -46,7 +46,6 @@
//TODO: fix eax3 reverb //TODO: fix eax3 reverb
//TODO: max channels //TODO: max channels
//TODO: loop count
cSampleManager SampleManager; cSampleManager SampleManager;
bool _bSampmanInitialised = false; bool _bSampmanInitialised = false;
@ -1695,7 +1694,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
ASSERT(stream != NULL); ASSERT(stream != NULL);
aStream[nStream] = stream; aStream[nStream] = stream;
if ( !stream->IsOpened() ) if ( !stream->Setup() )
{ {
delete stream; delete stream;
aStream[nStream] = NULL; aStream[nStream] = NULL;
@ -1725,7 +1724,7 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
if ( stream ) if ( stream )
{ {
if ( stream->Setup() ) if ( stream->IsOpened() )
{ {
stream->Start(); stream->Start();
} }
@ -1771,13 +1770,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if (stream->IsOpened()) { if (stream->Setup()) {
if (stream->Setup()) { stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
if (position != 0) nStreamLoopedFlag[nStream] = true;
stream->SetPosMS(position); if (position != 0)
stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -1798,10 +1797,8 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000); aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);
} }
if (aStream[nStream]->IsOpened()) { if (aStream[nStream]->Setup()) {
if (aStream[nStream]->Setup()) { aStream[nStream]->Start();
aStream[nStream]->Start();
}
return true; return true;
} else { } else {
@ -1827,13 +1824,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if (stream->IsOpened()) { if (stream->Setup()) {
if (stream->Setup()) { stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
if (position != 0) nStreamLoopedFlag[nStream] = true;
stream->SetPosMS(position); if (position != 0)
stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -1854,13 +1851,11 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]); aStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);
} }
if (aStream[nStream]->IsOpened()) { if (aStream[nStream]->Setup()) {
if (aStream[nStream]->Setup()) { if (position != 0)
if (position != 0) aStream[nStream]->SetPosMS(position);
aStream[nStream]->SetPosMS(position);
aStream[nStream]->Start(); aStream[nStream]->Start();
}
_bIsMp3Active = true; _bIsMp3Active = true;
return true; return true;
@ -1884,13 +1879,13 @@ cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
aStream[nStream] = stream; aStream[nStream] = stream;
if ( stream->IsOpened() ) { if ( stream->Setup() ) {
if ( stream->Setup() ) { stream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);
if (position != 0) nStreamLoopedFlag[nStream] = true;
stream->SetPosMS(position); if (position != 0)
stream->SetPosMS(position);
stream->Start(); stream->Start();
}
return true; return true;
} else { } else {
@ -1913,6 +1908,9 @@ cSampleManager::StopStreamedFile(uint8 nStream)
{ {
delete stream; delete stream;
aStream[nStream] = NULL; aStream[nStream] = NULL;
if ( nStream == 0 )
_bIsMp3Active = false;
} }
} }
@ -1925,7 +1923,21 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
if ( stream ) if ( stream )
{ {
return stream->GetPosMS(); if ( _bIsMp3Active )
{
tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index);
if ( mp3 != NULL )
{
return stream->GetPosMS() + mp3->nTrackStreamPos;
}
else
return 0;
}
else
{
return stream->GetPosMS();
}
} }
return 0; return 0;
@ -2001,6 +2013,12 @@ cSampleManager::Service(void)
if ( stream ) if ( stream )
stream->Update(); stream->Update();
} }
int refCount = CChannel::channelsThatNeedService;
for ( int32 i = 0; refCount && i < MAXCHANNELS+MAX2DCHANNELS; i++ )
{
if ( aChannel[i].Update() )
refCount--;
}
} }
bool bool

View file

@ -171,22 +171,22 @@ enum eSound
SOUND_CAR_PED_COLLISION, SOUND_CAR_PED_COLLISION,
SOUND_CLOCK_TICK, SOUND_CLOCK_TICK,
SOUND_PART_MISSION_COMPLETE, SOUND_PART_MISSION_COMPLETE,
SOUND_FRONTEND_MENU_STARTING, // same with SOUND_HUD_SOUND SOUND_FRONTEND_MENU_STARTING, // same sound as SOUND_HUD
// TODO(Miami): What are 170-175?? // TODO(Miami): What are 170-175??
SOUND_FRONTEND_NO_RADIO = 176, // those 3 are all same sound SOUND_FRONTEND_RADIO_TURN_OFF = 176, // those 2 are same sound
SOUND_FRONTEND_RADIO_CHANGE, SOUND_FRONTEND_RADIO_TURN_ON,
SOUND_FRONTEND_RADIO_CHANGE_2, SOUND_FRONTEND_HURRICANE, // yes, frontend
SOUND_HUD_SOUND, SOUND_HUD,
SOUND_180, SOUND_180,
SOUND_181, SOUND_181,
SOUND_182, SOUND_182,
SOUND_LIGHTNING, SOUND_LIGHTNING,
SOUND_BULLETTRACE_1, SOUND_BULLETTRACE_1,
SOUND_BULLETTRACE_2, SOUND_BULLETTRACE_2,
SOUND_186, // makes same sound with 40 SOUND_186, // makes same sound as 40
SOUND_187, // makes same sound with 46 SOUND_187, // makes same sound as 46
SOUND_MELEE_ATTACK_START, SOUND_MELEE_ATTACK_START,
SOUND_SKATING, SOUND_SKATING,
SOUND_WEAPON_MINIGUN_ATTACK, SOUND_WEAPON_MINIGUN_ATTACK,

View file

@ -307,8 +307,16 @@ CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts
if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)
return false; return false;
float p0dist = DotProduct(line.p1 - line.p0, normal);
#ifdef FIX_BUGS
// line lines in the plane, assume no collision
if (p0dist == 0.0f)
return false;
#endif
// intersection parameter on line // intersection parameter on line
t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); t = -plane.CalcPoint(line.p0) / p0dist;
// find point of intersection // find point of intersection
CVector p = line.p0 + (line.p1-line.p0)*t; CVector p = line.p0 + (line.p1-line.p0)*t;
@ -1127,8 +1135,17 @@ CCollision::ProcessLineTriangle(const CColLine &line,
if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f) if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)
return false; return false;
float p0dist = DotProduct(line.p1 - line.p0, normal);
#ifdef FIX_BUGS
// line lines in the plane, assume no collision
if (p0dist == 0.0f)
return false;
#endif
// intersection parameter on line // intersection parameter on line
t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal); t = -plane.CalcPoint(line.p0) / p0dist;
// early out if we're beyond the mindist // early out if we're beyond the mindist
if(t >= mindist) if(t >= mindist)
return false; return false;

View file

@ -52,8 +52,8 @@ void CAutoPilot::Save(uint8*& buf)
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode); WriteSaveBuf<int32>(buf, m_nCurrentRouteNode);
WriteSaveBuf<int32>(buf, m_nNextRouteNode); WriteSaveBuf<int32>(buf, m_nNextRouteNode);
WriteSaveBuf<int32>(buf, m_nPrevRouteNode); WriteSaveBuf<int32>(buf, m_nPrevRouteNode);
WriteSaveBuf<uint32>(buf, m_nTimeEnteredCurve); WriteSaveBuf<int32>(buf, m_nTimeEnteredCurve);
WriteSaveBuf<uint32>(buf, m_nTimeToSpendOnCurrentCurve); WriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve);
WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo); WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo);
WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo); WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo);
WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo); WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo);
@ -95,8 +95,8 @@ void CAutoPilot::Load(uint8*& buf)
m_nCurrentRouteNode = ReadSaveBuf<int32>(buf); m_nCurrentRouteNode = ReadSaveBuf<int32>(buf);
m_nNextRouteNode = ReadSaveBuf<int32>(buf); m_nNextRouteNode = ReadSaveBuf<int32>(buf);
m_nPrevRouteNode = ReadSaveBuf<int32>(buf); m_nPrevRouteNode = ReadSaveBuf<int32>(buf);
m_nTimeEnteredCurve = ReadSaveBuf<uint32>(buf); m_nTimeEnteredCurve = ReadSaveBuf<int32>(buf);
m_nTimeToSpendOnCurrentCurve = ReadSaveBuf<uint32>(buf); m_nTimeToSpendOnCurrentCurve = ReadSaveBuf<int32>(buf);
m_nCurrentPathNodeInfo = ReadSaveBuf<uint32>(buf); m_nCurrentPathNodeInfo = ReadSaveBuf<uint32>(buf);
m_nNextPathNodeInfo = ReadSaveBuf<uint32>(buf); m_nNextPathNodeInfo = ReadSaveBuf<uint32>(buf);
m_nPreviousPathNodeInfo = ReadSaveBuf<uint32>(buf); m_nPreviousPathNodeInfo = ReadSaveBuf<uint32>(buf);

View file

@ -64,8 +64,8 @@ public:
int32 m_nCurrentRouteNode; int32 m_nCurrentRouteNode;
int32 m_nNextRouteNode; int32 m_nNextRouteNode;
int32 m_nPrevRouteNode; int32 m_nPrevRouteNode;
uint32 m_nTimeEnteredCurve; int32 m_nTimeEnteredCurve;
uint32 m_nTimeToSpendOnCurrentCurve; int32 m_nTimeToSpendOnCurrentCurve;
uint32 m_nCurrentPathNodeInfo; uint32 m_nCurrentPathNodeInfo;
uint32 m_nNextPathNodeInfo; uint32 m_nNextPathNodeInfo;
uint32 m_nPreviousPathNodeInfo; uint32 m_nPreviousPathNodeInfo;

View file

@ -2757,7 +2757,7 @@ void CCarCtrl::SteerAIPlaneTowardsTargetCoors(CAutomobile* pPlane)
up.Normalise(); up.Normalise();
CVector forward(Cos(pPlane->m_fOrientation), Sin(pPlane->m_fOrientation), fForwardZ); CVector forward(Cos(pPlane->m_fOrientation), Sin(pPlane->m_fOrientation), fForwardZ);
forward.Normalise(); forward.Normalise();
CVector right = CrossProduct(forward, up); CVector right = CrossProduct(up, forward);
right.z -= 5.0f * pPlane->m_fPlaneSteer; right.z -= 5.0f * pPlane->m_fPlaneSteer;
right.Normalise(); right.Normalise();
up = CrossProduct(forward, right); up = CrossProduct(forward, right);

View file

@ -1285,7 +1285,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
uint32 i = CPools::GetVehiclePool()->GetSize(); uint32 i = CPools::GetVehiclePool()->GetSize();
while (i--) { while (i--) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle || pVehicle == pException) if (!pVehicle || pVehicle == pException || pVehicle->GetStatus() == STATUS_WRECKED)
continue; continue;
if (!IsEntityTouching3D(pVehicle)) if (!IsEntityTouching3D(pVehicle))
continue; continue;
@ -1997,7 +1997,11 @@ float CGarages::FindDoorHeightForMI(int32 mi)
void CGarage::TidyUpGarage() void CGarage::TidyUpGarage()
{ {
uint32 i = CPools::GetVehiclePool()->GetSize(); uint32 i = CPools::GetVehiclePool()->GetSize();
#ifdef FIX_BUGS
while (i--) { while (i--) {
#else
while (--i) {
#endif
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (pVehicle && (pVehicle->IsCar() || pVehicle->IsBike())) { if (pVehicle && (pVehicle->IsCar() || pVehicle->IsBike())) {
if (IsPointInsideGarage(pVehicle->GetPosition())) { if (IsPointInsideGarage(pVehicle->GetPosition())) {
@ -2013,7 +2017,11 @@ void CGarage::TidyUpGarage()
void CGarage::TidyUpGarageClose() void CGarage::TidyUpGarageClose()
{ {
uint32 i = CPools::GetVehiclePool()->GetSize(); uint32 i = CPools::GetVehiclePool()->GetSize();
#ifdef FIX_BUGS
while (i--) { while (i--) {
#else
while (--i) {
#endif
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle) if (!pVehicle)
continue; continue;
@ -2226,6 +2234,8 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
default: default:
aGarages[i].RefreshDoorPointers(true); aGarages[i].RefreshDoorPointers(true);
if (aGarages[i].m_pDoor1) { if (aGarages[i].m_pDoor1) {
aGarages[i].m_pDoor1->GetMatrix().GetPosition().x = aGarages[i].m_fDoor1X;
aGarages[i].m_pDoor1->GetMatrix().GetPosition().y = aGarages[i].m_fDoor1Y;
aGarages[i].m_pDoor1->GetMatrix().GetPosition().z = aGarages[i].m_fDoor1Z; aGarages[i].m_pDoor1->GetMatrix().GetPosition().z = aGarages[i].m_fDoor1Z;
if (aGarages[i].m_pDoor1->IsObject()) if (aGarages[i].m_pDoor1->IsObject())
((CObject*)aGarages[i].m_pDoor1)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor1Z; ((CObject*)aGarages[i].m_pDoor1)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor1Z;
@ -2235,6 +2245,8 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
aGarages[i].m_pDoor1->UpdateRwFrame(); aGarages[i].m_pDoor1->UpdateRwFrame();
} }
if (aGarages[i].m_pDoor2) { if (aGarages[i].m_pDoor2) {
aGarages[i].m_pDoor2->GetMatrix().GetPosition().x = aGarages[i].m_fDoor2X;
aGarages[i].m_pDoor2->GetMatrix().GetPosition().y = aGarages[i].m_fDoor2Y;
aGarages[i].m_pDoor2->GetMatrix().GetPosition().z = aGarages[i].m_fDoor2Z; aGarages[i].m_pDoor2->GetMatrix().GetPosition().z = aGarages[i].m_fDoor2Z;
if (aGarages[i].m_pDoor2->IsObject()) if (aGarages[i].m_pDoor2->IsObject())
((CObject*)aGarages[i].m_pDoor2)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor2Z; ((CObject*)aGarages[i].m_pDoor2)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor2Z;

View file

@ -859,7 +859,7 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
mag = Sqrt(dx*dx + dy*dy); mag = Sqrt(dx*dx + dy*dy);
dx /= mag; dx /= mag;
dy /= mag; dy /= mag;
int width = Max(m_pathNodes[i].width, m_pathNodes[j].width); uint8 width = Max(m_pathNodes[i].width, m_pathNodes[j].width);
if(i < j){ if(i < j){
dx = -dx; dx = -dx;
dy = -dy; dy = -dy;

View file

@ -120,7 +120,7 @@ struct CCarPathLink
uint8 trafficLightDirection : 1; uint8 trafficLightDirection : 1;
uint8 trafficLightType : 2; uint8 trafficLightType : 2;
uint8 bBridgeLights : 1; // at least in LCS... uint8 bBridgeLights : 1; // at least in LCS...
int8 width; uint8 width;
CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); } CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }
CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); } CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }
@ -151,7 +151,7 @@ struct CPathInfoForObject
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
int8 speedLimit; int8 speedLimit;
int8 width; uint8 width;
uint8 crossing : 1; uint8 crossing : 1;
uint8 onlySmallBoats : 1; uint8 onlySmallBoats : 1;
@ -177,7 +177,7 @@ struct CTempNode
int16 link2; int16 link2;
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
int8 width; uint8 width;
bool isCross; bool isCross;
int8 linkState; int8 linkState;
}; };
@ -188,7 +188,7 @@ struct CTempNodeExternal // made up name
int16 next; int16 next;
int8 numLeftLanes; int8 numLeftLanes;
int8 numRightLanes; int8 numRightLanes;
int8 width; uint8 width;
bool isCross; bool isCross;
}; };

View file

@ -1701,6 +1701,7 @@ int8 CRunningScript::ProcessCommands700To799(int32 command)
pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS; pBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;
pBoat->AutoPilot.m_vecDestinationCoors = pos; pBoat->AutoPilot.m_vecDestinationCoors = pos;
pBoat->SetStatus(STATUS_PHYSICS); pBoat->SetStatus(STATUS_PHYSICS);
pBoat->bEngineOn = true;
pBoat->AutoPilot.m_nCruiseSpeed = Max(1, pBoat->AutoPilot.m_nCruiseSpeed); pBoat->AutoPilot.m_nCruiseSpeed = Max(1, pBoat->AutoPilot.m_nCruiseSpeed);
pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds(); pBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
return 0; return 0;

View file

@ -431,12 +431,12 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]); CPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);
script_assert(pPed); script_assert(pPed);
if (ScriptParams[1]) { if (ScriptParams[1]) {
pPed->bIsDucking = true; pPed->bCrouchWhenShooting = true;
pPed->SetDuck(ScriptParams[2], true); pPed->SetDuck(ScriptParams[2], true);
} }
else { else {
pPed->ClearDuck(true); pPed->ClearDuck(true);
pPed->bIsDucking = false; pPed->bCrouchWhenShooting = false;
} }
return 0; return 0;
} }

View file

@ -1768,7 +1768,7 @@ CCamera::CamControl(void)
(m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) && (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&
!m_WideScreenOn && !m_WideScreenOn &&
(WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam)) (WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam))
DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); DMAudio.PlayFrontEndSound(SOUND_HUD, 0);
} }
// What a mess! // What a mess!

View file

@ -43,6 +43,6 @@ char *CdStreamGetImageName(int32 cd);
void CdStreamRemoveImages(void); void CdStreamRemoveImages(void);
int32 CdStreamGetNumImages(void); int32 CdStreamGetNumImages(void);
#ifndef _WIN32 #ifdef FLUSHABLE_STREAMING
extern bool flushStream[MAX_CDCHANNELS]; extern bool flushStream[MAX_CDCHANNELS];
#endif #endif

View file

@ -21,9 +21,9 @@
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
// #define ONE_THREAD_PER_CHANNEL // Don't use if you're not on SSD/Flash. (Also you may want to benefit from this via using all channels in Streaming.cpp) #ifdef FLUSHABLE_STREAMING
bool flushStream[MAX_CDCHANNELS]; bool flushStream[MAX_CDCHANNELS];
#endif
struct CdReadInfo struct CdReadInfo
{ {
@ -76,7 +76,7 @@ CdStreamInitThread(void)
gChannelRequestQ.tail = 0; gChannelRequestQ.tail = 0;
gChannelRequestQ.size = gNumChannels + 1; gChannelRequestQ.size = gNumChannels + 1;
ASSERT(gChannelRequestQ.items != nil ); ASSERT(gChannelRequestQ.items != nil );
gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 1); gCdStreamSema = sem_open("/semaphore_cd_stream", O_CREAT, 0644, 0);
if (gCdStreamSema == SEM_FAILED) { if (gCdStreamSema == SEM_FAILED) {
@ -91,7 +91,7 @@ CdStreamInitThread(void)
for ( int32 i = 0; i < gNumChannels; i++ ) for ( int32 i = 0; i < gNumChannels; i++ )
{ {
sprintf(semName,"/semaphore_done%d",i); sprintf(semName,"/semaphore_done%d",i);
gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 1); gpReadInfo[i].pDoneSemaphore = sem_open(semName, O_CREAT, 0644, 0);
if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED) if (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)
{ {
@ -99,9 +99,10 @@ CdStreamInitThread(void)
ASSERT(0); ASSERT(0);
return; return;
} }
#ifdef ONE_THREAD_PER_CHANNEL #ifdef ONE_THREAD_PER_CHANNEL
sprintf(semName,"/semaphore_start%d",i); sprintf(semName,"/semaphore_start%d",i);
gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 1); gpReadInfo[i].pStartSemaphore = sem_open(semName, O_CREAT, 0644, 0);
if (gpReadInfo[i].pStartSemaphore == SEM_FAILED) if (gpReadInfo[i].pStartSemaphore == SEM_FAILED)
{ {
@ -170,6 +171,7 @@ CdStreamInit(int32 numChannels)
gNumImages = 0; gNumImages = 0;
gNumChannels = numChannels; gNumChannels = numChannels;
ASSERT( gNumChannels != 0 );
gpReadInfo = (CdReadInfo *)calloc(numChannels, sizeof(CdReadInfo)); gpReadInfo = (CdReadInfo *)calloc(numChannels, sizeof(CdReadInfo));
ASSERT( gpReadInfo != nil ); ASSERT( gpReadInfo != nil );
@ -245,10 +247,12 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) { if ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) {
if (pChannel->hFile == hImage - 1 && pChannel->nSectorOffset == _GET_OFFSET(offset) && pChannel->nSectorsToRead >= size) if (pChannel->hFile == hImage - 1 && pChannel->nSectorOffset == _GET_OFFSET(offset) && pChannel->nSectorsToRead >= size)
return STREAM_SUCCESS; return STREAM_SUCCESS;
#ifdef FLUSHABLE_STREAMING
flushStream[channel] = 1; flushStream[channel] = 1;
CdStreamSync(channel); CdStreamSync(channel);
//return STREAM_NONE; #else
return STREAM_NONE;
#endif
} }
pChannel->hFile = hImage - 1; pChannel->hFile = hImage - 1;
@ -316,34 +320,34 @@ CdStreamSync(int32 channel)
CdReadInfo *pChannel = &gpReadInfo[channel]; CdReadInfo *pChannel = &gpReadInfo[channel];
ASSERT( pChannel != nil ); ASSERT( pChannel != nil );
#ifdef FLUSHABLE_STREAMING
if (flushStream[channel]) { if (flushStream[channel]) {
#ifdef ONE_THREAD_PER_CHANNEL
pChannel->nSectorsToRead = 0; pChannel->nSectorsToRead = 0;
#ifdef ONE_THREAD_PER_CHANNEL
pthread_kill(pChannel->pChannelThread, SIGUSR1); pthread_kill(pChannel->pChannelThread, SIGUSR1);
if (pChannel->bReading) { if (pChannel->bReading) {
pChannel->bLocked = true; pChannel->bLocked = true;
while (pChannel->bLocked)
sem_wait(pChannel->pDoneSemaphore);
}
#else #else
pChannel->nSectorsToRead = 0;
if (pChannel->bReading) { if (pChannel->bReading) {
pChannel->bLocked = true; pChannel->bLocked = true;
pthread_kill(_gCdStreamThread, SIGUSR1); pthread_kill(_gCdStreamThread, SIGUSR1);
#endif
while (pChannel->bLocked) while (pChannel->bLocked)
sem_wait(pChannel->pDoneSemaphore); sem_wait(pChannel->pDoneSemaphore);
} }
#endif
pChannel->bReading = false; pChannel->bReading = false;
flushStream[channel] = false; flushStream[channel] = false;
return STREAM_NONE; return STREAM_NONE;
} }
#endif
if ( pChannel->nSectorsToRead != 0 ) if ( pChannel->nSectorsToRead != 0 )
{ {
pChannel->bLocked = true; pChannel->bLocked = true;
while (pChannel->bLocked) while (pChannel->bLocked && pChannel->nSectorsToRead != 0){
sem_wait(pChannel->pDoneSemaphore); sem_wait(pChannel->pDoneSemaphore);
}
pChannel->bLocked = false;
} }
pChannel->bReading = false; pChannel->bReading = false;
@ -395,7 +399,12 @@ void *CdStreamThread(void *param)
#ifndef ONE_THREAD_PER_CHANNEL #ifndef ONE_THREAD_PER_CHANNEL
while (gCdStreamThreadStatus != 2) { while (gCdStreamThreadStatus != 2) {
sem_wait(gCdStreamSema); sem_wait(gCdStreamSema);
int32 channel = GetFirstInQueue(&gChannelRequestQ); int32 channel = GetFirstInQueue(&gChannelRequestQ);
// spurious wakeup
if (channel == -1)
continue;
#else #else
int channel = *((int*)param); int channel = *((int*)param);
while (gpReadInfo[channel].nThreadStatus != 2){ while (gpReadInfo[channel].nThreadStatus != 2){
@ -524,7 +533,9 @@ void
CdStreamRemoveImages(void) CdStreamRemoveImages(void)
{ {
for ( int32 i = 0; i < gNumChannels; i++ ) { for ( int32 i = 0; i < gNumChannels; i++ ) {
#ifdef FLUSHABLE_STREAMING
flushStream[i] = 1; flushStream[i] = 1;
#endif
CdStreamSync(i); CdStreamSync(i);
} }

View file

@ -1765,6 +1765,51 @@ void CControllerConfigManager::DeleteMatching1rstPersonControls(e_ControllerActi
#undef CLEAR_ACTION_IF_NEEDED #undef CLEAR_ACTION_IF_NEEDED
#ifdef RADIO_SCROLL_TO_PREV_STATION
#define CHECK_ACTION(action) \
if (key == GetControllerKeyAssociatedWithAction(action, type))\
return true;
bool CControllerConfigManager::IsAnyVehicleActionAssignedToMouseKey(int32 key)
{
const eControllerType type = MOUSE;
if (!GetIsKeyBlank(key, type))
{
#ifdef BIND_VEHICLE_FIREWEAPON
CHECK_ACTION(VEHICLE_FIREWEAPON);
#endif
CHECK_ACTION(VEHICLE_LOOKBEHIND);
CHECK_ACTION(VEHICLE_LOOKLEFT);
CHECK_ACTION(VEHICLE_LOOKRIGHT);
CHECK_ACTION(VEHICLE_HORN);
CHECK_ACTION(VEHICLE_HANDBRAKE);
CHECK_ACTION(VEHICLE_ACCELERATE);
CHECK_ACTION(VEHICLE_BRAKE);
CHECK_ACTION(VEHICLE_CHANGE_RADIO_STATION);
CHECK_ACTION(TOGGLE_SUBMISSIONS);
CHECK_ACTION(VEHICLE_TURRETLEFT);
CHECK_ACTION(VEHICLE_TURRETRIGHT);
CHECK_ACTION(VEHICLE_TURRETUP);
CHECK_ACTION(VEHICLE_TURRETDOWN);
CHECK_ACTION(VEHICLE_ENTER_EXIT);
CHECK_ACTION(CAMERA_CHANGE_VIEW_ALL_SITUATIONS);
#ifndef BIND_VEHICLE_FIREWEAPON
CHECK_ACTION(PED_FIREWEAPON);
#endif
CHECK_ACTION(GO_LEFT);
CHECK_ACTION(GO_RIGHT);
CHECK_ACTION(NETWORK_TALK);
CHECK_ACTION(SWITCH_DEBUG_CAM_ON);
CHECK_ACTION(TOGGLE_DPAD);
CHECK_ACTION(TAKE_SCREEN_SHOT);
CHECK_ACTION(SHOW_MOUSE_POINTER_TOGGLE);
}
return false;
}
#undef CHECK_ACTION
#endif
void CControllerConfigManager::DeleteMatchingActionInitiators(e_ControllerAction action, int32 key, eControllerType type) void CControllerConfigManager::DeleteMatchingActionInitiators(e_ControllerAction action, int32 key, eControllerType type)
{ {
if (!GetIsKeyBlank(key, type)) if (!GetIsKeyBlank(key, type))

View file

@ -195,6 +195,10 @@ public:
void DeleteMatching1rstPersonControls (e_ControllerAction action, int32 key, eControllerType type); void DeleteMatching1rstPersonControls (e_ControllerAction action, int32 key, eControllerType type);
void DeleteMatchingActionInitiators (e_ControllerAction action, int32 key, eControllerType type); void DeleteMatchingActionInitiators (e_ControllerAction action, int32 key, eControllerType type);
#ifdef RADIO_SCROLL_TO_PREV_STATION
bool IsAnyVehicleActionAssignedToMouseKey(int32 key);
#endif
bool GetIsKeyBlank(int32 key, eControllerType type); bool GetIsKeyBlank(int32 key, eControllerType type);
e_ControllerActionType GetActionType(e_ControllerAction action); e_ControllerActionType GetActionType(e_ControllerAction action);

View file

@ -5567,33 +5567,40 @@ void
CMenuManager::DrawQuitGameScreen(void) CMenuManager::DrawQuitGameScreen(void)
{ {
static int32 exitSignalTimer = 0; static int32 exitSignalTimer = 0;
#ifdef FIX_BUGS
int alpha = clamp(m_nMenuFadeAlpha, 0, 255);
#else
int alpha = m_nMenuFadeAlpha;
#endif
#ifndef MUCH_SHORTER_OUTRO_SCREEN #ifndef MUCH_SHORTER_OUTRO_SCREEN
static PauseModeTime lastTickIncrease = 0; static PauseModeTime lastTickIncrease = 0;
if (m_nMenuFadeAlpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) { if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) {
exitSignalTimer++; exitSignalTimer++;
lastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode(); lastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode();
} }
#else #else
static PauseModeTime sincePress = 0; static PauseModeTime firstTick = CTimer::GetTimeInMillisecondsPauseMode();
sincePress += frameTime; if (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - firstTick > 750) {
if (sincePress > 500)
exitSignalTimer = 150; exitSignalTimer = 150;
}
#endif #endif
static CSprite2d *splash = nil; static CSprite2d *splash = nil;
if (splash == nil) if (splash == nil)
splash = LoadSplash("OUTRO"); splash = LoadSplash("OUTRO");
m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(MENU_X(28.0f), MENU_Y(8.0f), MENU_X(157.0f), MENU_Y(138.0f)), CRGBA(255, 255, 255, -(m_nMenuFadeAlpha + 1))); m_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(28.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha));
// Or we can see menu background from sides // Or we can see menu background from sides
#ifdef ASPECT_RATIO_SCALE #ifdef ASPECT_RATIO_SCALE
CSprite2d::DrawRect(CRect(0, 0, MENU_X_LEFT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(0, 0, 0, m_nMenuFadeAlpha)); CSprite2d::DrawRect(CRect(0, 0, MENU_X_LEFT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha));
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, m_nMenuFadeAlpha)); CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha));
#endif #endif
splash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, m_nMenuFadeAlpha)); splash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, alpha));
if (m_nMenuFadeAlpha == 255 && exitSignalTimer == 150) if (alpha == 255 && exitSignalTimer == 150)
RsEventHandler(rsQUITAPP, nil); RsEventHandler(rsQUITAPP, nil);
m_bShowMouse = false; m_bShowMouse = false;

View file

@ -381,6 +381,11 @@ bool CGame::Initialise(const char* datFile)
CTxdStore::Create(gameTxdSlot); CTxdStore::Create(gameTxdSlot);
CTxdStore::AddRef(gameTxdSlot); CTxdStore::AddRef(gameTxdSlot);
#ifdef EXTENDED_PIPELINES
// for generic fallback
CustomPipes::SetTxdFindCallback();
#endif
LoadingScreen("Loading the Game", "Loading particles", nil); LoadingScreen("Loading the Game", "Loading particles", nil);
int particleTxdSlot = CTxdStore::AddTxdSlot("particle"); int particleTxdSlot = CTxdStore::AddTxdSlot("particle");
CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD"); CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD");
@ -440,10 +445,7 @@ bool CGame::Initialise(const char* datFile)
CFileLoader::LoadLevel("DATA\\DEFAULT.DAT"); CFileLoader::LoadLevel("DATA\\DEFAULT.DAT");
CFileLoader::LoadLevel(datFile); CFileLoader::LoadLevel(datFile);
#ifdef EXTENDED_PIPELINES
// for generic fallback
CustomPipes::SetTxdFindCallback();
#endif
LoadingScreen("Loading the Game", "Add Particles", nil); LoadingScreen("Loading the Game", "Add Particles", nil);
CWorld::AddParticles(); CWorld::AddParticles();
CVehicleModelInfo::LoadVehicleColours(); CVehicleModelInfo::LoadVehicleColours();
@ -591,7 +593,6 @@ bool CGame::ShutDown(void)
gPhoneInfo.Shutdown(); gPhoneInfo.Shutdown();
CWeapon::ShutdownWeapons(); CWeapon::ShutdownWeapons();
CPedType::Shutdown(); CPedType::Shutdown();
CMBlur::MotionBlurClose();
for (int32 i = 0; i < NUMPLAYERS; i++) for (int32 i = 0; i < NUMPLAYERS; i++)
{ {
@ -617,7 +618,7 @@ bool CGame::ShutDown(void)
CStreaming::Shutdown(); CStreaming::Shutdown();
CTxdStore::GameShutdown(); CTxdStore::GameShutdown();
CCollision::Shutdown(); CCollision::Shutdown();
CWaterLevel::DestroyWavyAtomic(); CWaterLevel::Shutdown();
CRubbish::Shutdown(); CRubbish::Shutdown();
CClouds::Shutdown(); CClouds::Shutdown();
CShadows::Shutdown(); CShadows::Shutdown();
@ -626,6 +627,7 @@ bool CGame::ShutDown(void)
CWeaponEffects::Shutdown(); CWeaponEffects::Shutdown();
CParticle::Shutdown(); CParticle::Shutdown();
CPools::ShutDown(); CPools::ShutDown();
CHud::ReInitialise();
CTxdStore::RemoveTxdSlot(gameTxdSlot); CTxdStore::RemoveTxdSlot(gameTxdSlot);
CMBlur::MotionBlurClose(); CMBlur::MotionBlurClose();
CdStreamRemoveImages(); CdStreamRemoveImages();

View file

@ -824,7 +824,7 @@ int32 CRadar::GetNewUniqueBlipIndex(int32 i)
uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright) uint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)
{ {
int32 c; uint32 c;
switch (color) { switch (color) {
case RADAR_TRACE_RED: case RADAR_TRACE_RED:
if (bright) if (bright)

View file

@ -207,11 +207,15 @@ CStreaming::Init2(void)
// allocate streaming buffers // allocate streaming buffers
if(ms_streamingBufferSize & 1) ms_streamingBufferSize++; if(ms_streamingBufferSize & 1) ms_streamingBufferSize++;
#ifndef ONE_THREAD_PER_CHANNEL
ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
ms_streamingBufferSize /= 2; ms_streamingBufferSize /= 2;
ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
#ifdef ONE_THREAD_PER_CHANNEL #else
ms_pStreamingBuffer[2] = (int8*)RwMallocAlign(ms_streamingBufferSize*2*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE); ms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*2*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
ms_streamingBufferSize /= 2;
ms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
ms_pStreamingBuffer[2] = ms_pStreamingBuffer[1] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
ms_pStreamingBuffer[3] = ms_pStreamingBuffer[2] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE; ms_pStreamingBuffer[3] = ms_pStreamingBuffer[2] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;
#endif #endif
debug("Streaming buffer size is %d sectors", ms_streamingBufferSize); debug("Streaming buffer size is %d sectors", ms_streamingBufferSize);
@ -2305,9 +2309,10 @@ CStreaming::LoadRequestedModels(void)
} }
// Let's load models first, then process it. Unfortunately processing models are still single-threaded. // Let's load models in 4 threads; when one of them becomes idle, process the file, and fill thread with another file. Unfortunately processing models are still single-threaded.
// Currently only supported on POSIX streamer. // Currently only supported on POSIX streamer.
#ifdef ONE_THREAD_PER_CHANNEL // WIP - some files are loaded swapped (CdStreamPosix problem?)
#if 0 //def ONE_THREAD_PER_CHANNEL
void void
CStreaming::LoadAllRequestedModels(bool priority) CStreaming::LoadAllRequestedModels(bool priority)
{ {
@ -2326,14 +2331,18 @@ CStreaming::LoadAllRequestedModels(bool priority)
int streamIds[ARRAY_SIZE(ms_pStreamingBuffer)]; int streamIds[ARRAY_SIZE(ms_pStreamingBuffer)];
int streamSizes[ARRAY_SIZE(ms_pStreamingBuffer)]; int streamSizes[ARRAY_SIZE(ms_pStreamingBuffer)];
int streamPoses[ARRAY_SIZE(ms_pStreamingBuffer)]; int streamPoses[ARRAY_SIZE(ms_pStreamingBuffer)];
bool first = true; int readOrder[4] = {-1}; // Channel IDs ordered by read time
int readI = 0;
int processI = 0; int processI = 0;
bool first = true;
// All those "first" checks are because of variables aren't initialized in first pass.
while (true) { while (true) {
// Enumerate files and start reading
for (int i=0; i<ARRAY_SIZE(ms_pStreamingBuffer); i++) { for (int i=0; i<ARRAY_SIZE(ms_pStreamingBuffer); i++) {
// Channel has file to load
if (!first && streamIds[i] != -1) { if (!first && streamIds[i] != -1) {
processI = i;
continue; continue;
} }
@ -2346,12 +2355,16 @@ CStreaming::LoadAllRequestedModels(bool priority)
if (ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)) { if (ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)) {
streamIds[i] = -1; streamIds[i] = -1;
// Big file, needs 2 buffer
if (size > (uint32)ms_streamingBufferSize) { if (size > (uint32)ms_streamingBufferSize) {
if (i + 1 == ARRAY_SIZE(ms_pStreamingBuffer)) if (i + 1 == ARRAY_SIZE(ms_pStreamingBuffer))
continue; break;
else if (!first && streamIds[i+1] != -1) else if (!first && streamIds[i+1] != -1)
continue; continue;
} else { } else {
// Buffer of current channel is part of a "big file", pass
if (i != 0 && streamIds[i-1] != -1 && streamSizes[i-1] > (uint32)ms_streamingBufferSize) if (i != 0 && streamIds[i-1] != -1 && streamSizes[i-1] > (uint32)ms_streamingBufferSize)
continue; continue;
} }
@ -2361,8 +2374,18 @@ CStreaming::LoadAllRequestedModels(bool priority)
streamIds[i] = streamId; streamIds[i] = streamId;
streamSizes[i] = size; streamSizes[i] = size;
streamPoses[i] = posn; streamPoses[i] = posn;
if (!first)
assert(readOrder[readI] == -1);
//printf("read: order %d, ch %d, id %d, size %d\n", readI, i, streamId, size);
CdStreamRead(i, ms_pStreamingBuffer[i], imgOffset+posn, size); CdStreamRead(i, ms_pStreamingBuffer[i], imgOffset+posn, size);
processI = i; readOrder[readI] = i;
if (first && readI+1 != ARRAY_SIZE(readOrder))
readOrder[readI+1] = -1;
readI = (readI + 1) % ARRAY_SIZE(readOrder);
} else { } else {
ms_aInfoForModel[streamId].RemoveFromList(); ms_aInfoForModel[streamId].RemoveFromList();
DecrementRef(streamId); DecrementRef(streamId);
@ -2370,33 +2393,40 @@ CStreaming::LoadAllRequestedModels(bool priority)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
streamIds[i] = -1; streamIds[i] = -1;
} }
} else } else {
streamIds[i] = -1; streamIds[i] = -1;
break;
}
} }
first = false; first = false;
int nextChannel = readOrder[processI];
// Now process // Now start processing
if (streamIds[processI] == -1) if (nextChannel == -1 || streamIds[nextChannel] == -1)
break; break;
//printf("process: order %d, ch %d, id %d\n", processI, nextChannel, streamIds[nextChannel]);
// Try again on error // Try again on error
while (CdStreamSync(processI) != STREAM_NONE) { while (CdStreamSync(nextChannel) != STREAM_NONE) {
CdStreamRead(processI, ms_pStreamingBuffer[processI], imgOffset+streamPoses[processI], streamSizes[processI]); CdStreamRead(nextChannel, ms_pStreamingBuffer[nextChannel], imgOffset+streamPoses[nextChannel], streamSizes[nextChannel]);
} }
ms_aInfoForModel[streamIds[processI]].m_loadState = STREAMSTATE_READING; ms_aInfoForModel[streamIds[nextChannel]].m_loadState = STREAMSTATE_READING;
MakeSpaceFor(streamSizes[processI] * CDSTREAM_SECTOR_SIZE); MakeSpaceFor(streamSizes[nextChannel] * CDSTREAM_SECTOR_SIZE);
ConvertBufferToObject(ms_pStreamingBuffer[processI], streamIds[processI]); ConvertBufferToObject(ms_pStreamingBuffer[nextChannel], streamIds[nextChannel]);
if(ms_aInfoForModel[streamIds[processI]].m_loadState == STREAMSTATE_STARTED) if(ms_aInfoForModel[streamIds[nextChannel]].m_loadState == STREAMSTATE_STARTED)
FinishLoadingLargeFile(ms_pStreamingBuffer[processI], streamIds[processI]); FinishLoadingLargeFile(ms_pStreamingBuffer[nextChannel], streamIds[nextChannel]);
if(streamIds[processI] < STREAM_OFFSET_TXD){ if(streamIds[nextChannel] < STREAM_OFFSET_TXD){
CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamIds[processI]); CSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamIds[nextChannel]);
if(mi->IsSimple()) if(mi->IsSimple())
mi->m_alpha = 255; mi->m_alpha = 255;
} }
streamIds[processI] = -1; streamIds[nextChannel] = -1;
readOrder[processI] = -1;
processI = (processI + 1) % ARRAY_SIZE(readOrder);
} }
ms_bLoadingBigModel = false; ms_bLoadingBigModel = false;
@ -2500,7 +2530,7 @@ CStreaming::FlushRequestList(void)
next = si->m_next; next = si->m_next;
RemoveModel(si - ms_aInfoForModel); RemoveModel(si - ms_aInfoForModel);
} }
#ifndef _WIN32 #ifdef FLUSHABLE_STREAMING
if(ms_channel[0].state == CHANNELSTATE_READING) { if(ms_channel[0].state == CHANNELSTATE_READING) {
flushStream[0] = 1; flushStream[0] = 1;
} }

View file

@ -88,7 +88,11 @@ public:
static int32 ms_oldSectorX; static int32 ms_oldSectorX;
static int32 ms_oldSectorY; static int32 ms_oldSectorY;
static int32 ms_streamingBufferSize; static int32 ms_streamingBufferSize;
#ifndef ONE_THREAD_PER_CHANNEL
static int8 *ms_pStreamingBuffer[2]; static int8 *ms_pStreamingBuffer[2];
#else
static int8 *ms_pStreamingBuffer[4];
#endif
static size_t ms_memoryUsed; static size_t ms_memoryUsed;
static CStreamingChannel ms_channel[2]; static CStreamingChannel ms_channel[2];
static int32 ms_channelError; static int32 ms_channelError;

View file

@ -367,7 +367,7 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
} else if(e->bUsesCollision) } else if(e->bUsesCollision)
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, mindist,
ignoreSeeThrough, ignoreShootThrough)) ignoreSeeThrough, ignoreShootThrough))
entity = e; entity = e;
if(carTyres && ((CVehicle*)e)->SetUpWheelColModel(&tyreCol) && CCollision::ProcessLineOfSight(line, e->GetMatrix(), tyreCol, tyreColPoint, tyreDist, false, ignoreShootThrough)){ if(carTyres && ((CVehicle*)e)->SetUpWheelColModel(&tyreCol) && CCollision::ProcessLineOfSight(line, e->GetMatrix(), tyreCol, tyreColPoint, tyreDist, false, ignoreShootThrough)){
@ -466,7 +466,7 @@ CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CCol
e->m_scanCode = GetCurrentScanCode(); e->m_scanCode = GetCurrentScanCode();
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, mindist,
ignoreSeeThrough, false, poly)) ignoreSeeThrough, false, poly))
entity = e; entity = e;
} }
@ -2239,8 +2239,12 @@ CWorld::UseDetonator(CEntity *pEntity)
{ {
int32 i = CPools::GetVehiclePool()->GetSize(); int32 i = CPools::GetVehiclePool()->GetSize();
while(--i >= 0) { while(--i >= 0) {
#ifdef FIX_BUGS
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
#else
CAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i); CAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i);
if(pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && #endif
if(pVehicle && pVehicle->m_bombType == CARBOMB_REMOTE &&
pVehicle->m_pBombRigger == pEntity) { pVehicle->m_pBombRigger == pEntity) {
pVehicle->m_bombType = CARBOMB_NONE; pVehicle->m_bombType = CARBOMB_NONE;
pVehicle->m_nBombTimer = 500; pVehicle->m_nBombTimer = 500;

View file

@ -355,7 +355,7 @@ __inline__ void TRACE(char *f, ...) { } // this is re3 only, and so the function
#ifndef MASTER #ifndef MASTER
#define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) ) #define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) )
#else #else
#define assert(_Expression) #define assert(_Expression) (_Expression)
#endif #endif
#define ASSERT assert #define ASSERT assert

View file

@ -251,6 +251,12 @@ enum Config {
#define FIX_BUGS_64 // Must have fixes to be able to run 64 bit build #define FIX_BUGS_64 // Must have fixes to be able to run 64 bit build
#endif #endif
#define ASCII_STRCMP // use faster ascii str comparisons
#if !defined _WIN32 || defined __MWERKS__ || defined __MINGW32__ || defined VANILLA_DEFINES
#undef ASCII_STRCMP
#endif
// Just debug menu entries // Just debug menu entries
#ifdef DEBUGMENU #ifdef DEBUGMENU
#define RELOADABLES // some debug menu options to reload TXD files #define RELOADABLES // some debug menu options to reload TXD files
@ -306,8 +312,8 @@ enum Config {
// Hud, frontend and radar // Hud, frontend and radar
#define PC_MENU #define PC_MENU
#define FIX_RADAR // use radar size from early version before R* broke it #define FIX_RADAR // use radar size from early version before R* broke it
#define RADIO_OFF_TEXT // Won't work without FIX_BUGS
#ifndef PC_MENU #ifndef PC_MENU
# define PS2_MENU # define PS2_MENU
@ -347,6 +353,10 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log #define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log
#if SCRIPT_LOG_FILE_LEVEL == 0
#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#endif
#ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT #ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#define USE_BASIC_SCRIPT_DEBUG_OUTPUT #define USE_BASIC_SCRIPT_DEBUG_OUTPUT
#endif #endif
@ -376,6 +386,7 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#define FREE_CAM // Rotating cam #define FREE_CAM // Rotating cam
// Audio // Audio
#define RADIO_SCROLL_TO_PREV_STATION // Won't work without FIX_BUGS
#define AUDIO_CACHE // cache sound lengths to speed up the cold boot #define AUDIO_CACHE // cache sound lengths to speed up the cold boot
//#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds) //#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds)
//#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder //#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder
@ -393,11 +404,12 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#endif #endif
#ifdef LIBRW // Streaming
// these are not supported with librw yet #if !defined(_WIN32) && !defined(__SWITCH__)
//#define ONE_THREAD_PER_CHANNEL // Don't use if you're not on SSD/Flash - also not utilized too much right now(see commented LoadAllRequestedModels in Streaming.cpp)
#define FLUSHABLE_STREAMING // Make it possible to interrupt reading when processing file isn't needed anymore.
#endif #endif
// IMG #define BIG_IMG // Not complete - allows to read larger img files
#define BIG_IMG // allows to read larger img files
//#define SQUEEZE_PERFORMANCE //#define SQUEEZE_PERFORMANCE
#ifdef SQUEEZE_PERFORMANCE #ifdef SQUEEZE_PERFORMANCE
@ -405,6 +417,8 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#undef NO_ISLAND_LOADING #undef NO_ISLAND_LOADING
#endif #endif
// -------
#if defined __MWERKS__ || defined VANILLA_DEFINES #if defined __MWERKS__ || defined VANILLA_DEFINES
#define FINAL #define FINAL
#undef CHATTYSPLASH #undef CHATTYSPLASH
@ -459,6 +473,7 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#undef BUTTON_ICONS #undef BUTTON_ICONS
#undef FIX_RADAR #undef FIX_RADAR
#undef RADIO_OFF_TEXT
#undef MAP_ENHANCEMENTS #undef MAP_ENHANCEMENTS
#undef MUCH_SHORTER_OUTRO_SCREEN #undef MUCH_SHORTER_OUTRO_SCREEN
@ -487,4 +502,6 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
#undef IMPROVED_CAMERA #undef IMPROVED_CAMERA
#undef FREE_CAM #undef FREE_CAM
#undef BIG_IMG #undef BIG_IMG
#undef RADIO_SCROLL_TO_PREV_STATION
#endif #endif

View file

@ -1065,8 +1065,13 @@ DisplayGameDebugText()
#endif #endif
FrameSamples++; FrameSamples++;
#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND
FramesPerSecondCounter += frameTime / 1000.f; // convert to seconds
FramesPerSecond = FrameSamples / FramesPerSecondCounter;
#else
FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f); FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
FramesPerSecond = FramesPerSecondCounter / FrameSamples; FramesPerSecond = FramesPerSecondCounter / FrameSamples;
#endif
if ( FrameSamples > 30 ) if ( FrameSamples > 30 )
{ {

View file

@ -406,6 +406,10 @@ bool LoadINISettings()
ReadIniIfExists("CustomPipesValues", "LightmapMult", &CustomPipes::LightmapMult); ReadIniIfExists("CustomPipesValues", "LightmapMult", &CustomPipes::LightmapMult);
ReadIniIfExists("CustomPipesValues", "GlossMult", &CustomPipes::GlossMult); ReadIniIfExists("CustomPipesValues", "GlossMult", &CustomPipes::GlossMult);
#endif #endif
ReadIniIfExists("Rendering", "BackfaceCulling", &gBackfaceCulling);
#ifdef NEW_RENDERER
ReadIniIfExists("Rendering", "NewRenderer", &gbNewRenderer);
#endif
#ifdef PROPER_SCALING #ifdef PROPER_SCALING
ReadIniIfExists("Draw", "ProperScaling", &CDraw::ms_bProperScaling); ReadIniIfExists("Draw", "ProperScaling", &CDraw::ms_bProperScaling);
@ -495,6 +499,9 @@ void SaveINISettings()
StoreIni("CustomPipesValues", "GlossMult", CustomPipes::GlossMult); StoreIni("CustomPipesValues", "GlossMult", CustomPipes::GlossMult);
#endif #endif
StoreIni("Rendering", "BackfaceCulling", gBackfaceCulling); StoreIni("Rendering", "BackfaceCulling", gBackfaceCulling);
#ifdef NEW_RENDERER
StoreIni("Rendering", "NewRenderer", gbNewRenderer);
#endif
#ifdef PROPER_SCALING #ifdef PROPER_SCALING
StoreIni("Draw", "ProperScaling", CDraw::ms_bProperScaling); StoreIni("Draw", "ProperScaling", CDraw::ms_bProperScaling);
@ -706,7 +713,7 @@ void CTweakVars::Add(CTweakVar *var)
TweakVarsListSize = 0; TweakVarsListSize = 0;
} }
if(TweakVarsListSize > 63) if(TweakVarsListSize > 63)
TweakVarsList = (CTweakVar**) realloc(TweakVarsList, (TweakVarsListSize + 1) * sizeof(*var)); TweakVarsList = (CTweakVar**) realloc(TweakVarsList, (TweakVarsListSize + 1) * sizeof(CTweakVar*));
TweakVarsList[TweakVarsListSize++] = var; TweakVarsList[TweakVarsListSize++] = var;
// TweakVarsList.push_back(var); // TweakVarsList.push_back(var);

View file

@ -89,6 +89,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
} }
int vsBits; int vsBits;
rw::uint32 flags = atomic->geometry->flags;
setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
setIndices(header->indexBuffer); setIndices(header->indexBuffer);
setVertexDeclaration(header->vertexDeclaration); setVertexDeclaration(header->vertexDeclaration);
@ -120,7 +121,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
reflProps[3] = m->surfaceProps.specular == 0.0f ? 0.0f : VehicleSpecularity; reflProps[3] = m->surfaceProps.specular == 0.0f ? 0.0f : VehicleSpecularity;
d3ddevice->SetVertexShaderConstantF(VSLOC_reflProps, reflProps, 1); d3ddevice->SetVertexShaderConstantF(VSLOC_reflProps, reflProps, 1);
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
if(m->texture) if(m->texture)
d3d::setTexture(0, m->texture); d3d::setTexture(0, m->texture);
@ -150,11 +151,11 @@ CreateVehiclePipe(void)
fp = ReadTweakValueTable(fp, SpecColor); fp = ReadTweakValueTable(fp, SpecColor);
} }
#include "shaders/neoVehicle_VS.inc" #include "shaders/obj/neoVehicle_VS.inc"
neoVehicle_VS = rw::d3d::createVertexShader(neoVehicle_VS_cso); neoVehicle_VS = rw::d3d::createVertexShader(neoVehicle_VS_cso);
assert(neoVehicle_VS); assert(neoVehicle_VS);
#include "shaders/neoVehicle_PS.inc" #include "shaders/obj/neoVehicle_PS.inc"
neoVehicle_PS = rw::d3d::createPixelShader(neoVehicle_PS_cso); neoVehicle_PS = rw::d3d::createPixelShader(neoVehicle_PS_cso);
assert(neoVehicle_PS); assert(neoVehicle_PS);
@ -260,11 +261,11 @@ CreateWorldPipe(void)
else else
ReadTweakValueTable((char*)work_buff, WorldLightmapBlend); ReadTweakValueTable((char*)work_buff, WorldLightmapBlend);
#include "shaders/default_UV2_VS.inc" #include "shaders/obj/default_UV2_VS.inc"
neoWorld_VS = rw::d3d::createVertexShader(default_UV2_VS_cso); neoWorld_VS = rw::d3d::createVertexShader(default_UV2_VS_cso);
assert(neoWorld_VS); assert(neoWorld_VS);
#include "shaders/neoWorldVC_PS.inc" #include "shaders/obj/neoWorldVC_PS.inc"
neoWorldVC_PS = rw::d3d::createPixelShader(neoWorldVC_PS_cso); neoWorldVC_PS = rw::d3d::createPixelShader(neoWorldVC_PS_cso);
assert(neoWorldVC_PS); assert(neoWorldVC_PS);
@ -347,11 +348,11 @@ glossRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
void void
CreateGlossPipe(void) CreateGlossPipe(void)
{ {
#include "shaders/neoGloss_VS.inc" #include "shaders/obj/neoGloss_VS.inc"
neoGloss_VS = rw::d3d::createVertexShader(neoGloss_VS_cso); neoGloss_VS = rw::d3d::createVertexShader(neoGloss_VS_cso);
assert(neoGloss_VS); assert(neoGloss_VS);
#include "shaders/neoGloss_PS.inc" #include "shaders/obj/neoGloss_PS.inc"
neoGloss_PS = rw::d3d::createPixelShader(neoGloss_PS_cso); neoGloss_PS = rw::d3d::createPixelShader(neoGloss_PS_cso);
assert(neoGloss_PS); assert(neoGloss_PS);
@ -421,6 +422,7 @@ rimRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
} }
int vsBits; int vsBits;
rw::uint32 flags = atomic->geometry->flags;
setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);
setIndices(header->indexBuffer); setIndices(header->indexBuffer);
setVertexDeclaration(header->vertexDeclaration); setVertexDeclaration(header->vertexDeclaration);
@ -438,7 +440,7 @@ rimRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255); SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
if(m->texture){ if(m->texture){
d3d::setTexture(0, m->texture); d3d::setTexture(0, m->texture);
@ -464,7 +466,7 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
} }
int vsBits; int vsBits;
rw::uint32 flags = atomic->geometry->flags;
setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
0, header->vertexStream[0].stride); 0, header->vertexStream[0].stride);
setIndices((IDirect3DIndexBuffer9*)header->indexBuffer); setIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
@ -485,7 +487,7 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)
SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255); SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
if(inst->material->texture){ if(inst->material->texture){
d3d::setTexture(0, m->texture); d3d::setTexture(0, m->texture);
@ -513,11 +515,11 @@ CreateRimLightPipes(void)
} }
#include "shaders/neoRim_VS.inc" #include "shaders/obj/neoRim_VS.inc"
neoRim_VS = rw::d3d::createVertexShader(neoRim_VS_cso); neoRim_VS = rw::d3d::createVertexShader(neoRim_VS_cso);
assert(neoRim_VS); assert(neoRim_VS);
#include "shaders/neoRimSkin_VS.inc" #include "shaders/obj/neoRimSkin_VS.inc"
neoRimSkin_VS = rw::d3d::createVertexShader(neoRimSkin_VS_cso); neoRimSkin_VS = rw::d3d::createVertexShader(neoRimSkin_VS_cso);
assert(neoRimSkin_VS); assert(neoRimSkin_VS);
@ -611,6 +613,7 @@ AtomicFirstPass(RpAtomic *atomic, int pass)
assert(building->instHeader->platform == PLATFORM_D3D9); assert(building->instHeader->platform == PLATFORM_D3D9);
building->fadeAlpha = 255; building->fadeAlpha = 255;
building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
rw::uint32 flags = atomic->geometry->flags;
bool setupDone = false; bool setupDone = false;
bool defer = false; bool defer = false;
@ -640,7 +643,7 @@ AtomicFirstPass(RpAtomic *atomic, int pass)
setupDone = true; setupDone = true;
} }
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
if(m->texture){ if(m->texture){
d3d::setTexture(0, m->texture); d3d::setTexture(0, m->texture);
@ -703,7 +706,7 @@ RenderBlendPass(int pass)
rw::RGBA color = m->color; rw::RGBA color = m->color;
color.alpha = (color.alpha * building->fadeAlpha)/255; color.alpha = (color.alpha * building->fadeAlpha)/255;
setMaterial(color, m->surfaceProps); setMaterial(color, m->surfaceProps); // always modulate here
if(m->texture){ if(m->texture){
d3d::setTexture(0, m->texture); d3d::setTexture(0, m->texture);

View file

@ -87,6 +87,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
Material *m; Material *m;
rw::uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM()); setWorldMatrix(atomic->getFrame()->getLTM());
lightingCB(atomic); lightingCB(atomic);
@ -119,7 +120,7 @@ vehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
while(n--){ while(n--){
m = inst->material; m = inst->material;
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture); setTexture(0, m->texture);
@ -160,8 +161,8 @@ CreateVehiclePipe(void)
{ {
#include "shaders/neoVehicle_fs_gl.inc" #include "shaders/obj/neoVehicle_frag.inc"
#include "shaders/neoVehicle_vs_gl.inc" #include "shaders/obj/neoVehicle_vert.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil };
neoVehicleShader = Shader::create(vs, fs); neoVehicleShader = Shader::create(vs, fs);
@ -271,8 +272,8 @@ CreateWorldPipe(void)
ReadTweakValueTable((char*)work_buff, WorldLightmapBlend); ReadTweakValueTable((char*)work_buff, WorldLightmapBlend);
{ {
#include "shaders/neoWorldVC_fs_gl.inc" #include "shaders/obj/neoWorldVC_frag.inc"
#include "shaders/default_UV2_gl.inc" #include "shaders/obj/default_UV2_vert.inc"
const char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoWorldVC_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoWorldVC_frag_src, nil };
neoWorldShader = Shader::create(vs, fs); neoWorldShader = Shader::create(vs, fs);
@ -333,7 +334,12 @@ glossRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
V3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos; V3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;
glUniform3fv(U(u_eye), 1, (float*)&eyePos); glUniform3fv(U(u_eye), 1, (float*)&eyePos);
glUniform4fv(U(u_reflProps), 1, (float*)&GlossMult); float reflProps[4];
reflProps[0] = GlossMult;
reflProps[1] = 0.0f;
reflProps[2] = 0.0f;
reflProps[3] = 0.0f;
glUniform4fv(U(u_reflProps), 1, reflProps);
SetRenderState(VERTEXALPHA, TRUE); SetRenderState(VERTEXALPHA, TRUE);
SetRenderState(SRCBLEND, BLENDONE); SetRenderState(SRCBLEND, BLENDONE);
@ -374,8 +380,8 @@ CreateGlossPipe(void)
using namespace rw::gl3; using namespace rw::gl3;
{ {
#include "shaders/neoGloss_fs_gl.inc" #include "shaders/obj/neoGloss_frag.inc"
#include "shaders/neoGloss_vs_gl.inc" #include "shaders/obj/neoGloss_vert.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil };
neoGlossShader = Shader::create(vs, fs); neoGlossShader = Shader::create(vs, fs);
@ -444,6 +450,7 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
Material *m; Material *m;
rw::uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM()); setWorldMatrix(atomic->getFrame()->getLTM());
lightingCB(atomic); lightingCB(atomic);
@ -467,7 +474,7 @@ rimSkinRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
while(n--){ while(n--){
m = inst->material; m = inst->material;
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture); setTexture(0, m->texture);
@ -494,6 +501,7 @@ rimRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
Material *m; Material *m;
rw::uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM()); setWorldMatrix(atomic->getFrame()->getLTM());
lightingCB(atomic); lightingCB(atomic);
@ -515,7 +523,7 @@ rimRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)
while(n--){ while(n--){
m = inst->material; m = inst->material;
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture); setTexture(0, m->texture);
@ -546,8 +554,8 @@ CreateRimLightPipes(void)
} }
{ {
#include "shaders/simple_fs_gl.inc" #include "shaders/obj/simple_frag.inc"
#include "shaders/neoRimSkin_gl.inc" #include "shaders/obj/neoRimSkin_vert.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
neoRimSkinShader = Shader::create(vs, fs); neoRimSkinShader = Shader::create(vs, fs);
@ -555,8 +563,8 @@ CreateRimLightPipes(void)
} }
{ {
#include "shaders/simple_fs_gl.inc" #include "shaders/obj/simple_frag.inc"
#include "shaders/neoRim_gl.inc" #include "shaders/obj/neoRim_vert.inc"
const char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };
neoRimShader = Shader::create(vs, fs); neoRimShader = Shader::create(vs, fs);
@ -660,6 +668,7 @@ AtomicFirstPass(RpAtomic *atomic, int pass)
assert(building->instHeader->platform == PLATFORM_GL3); assert(building->instHeader->platform == PLATFORM_GL3);
building->fadeAlpha = 255; building->fadeAlpha = 255;
building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT); building->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);
rw::uint32 flags = atomic->geometry->flags;
WorldLights lights; WorldLights lights;
lights.numAmbients = 1; lights.numAmbients = 1;
@ -699,7 +708,7 @@ AtomicFirstPass(RpAtomic *atomic, int pass)
setupDone = true; setupDone = true;
} }
setMaterial(m->color, m->surfaceProps); setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture); setTexture(0, m->texture);
@ -768,7 +777,7 @@ RenderBlendPass(int pass)
rw::RGBA color = m->color; rw::RGBA color = m->color;
color.alpha = (color.alpha * building->fadeAlpha)/255; color.alpha = (color.alpha * building->fadeAlpha)/255;
setMaterial(color, m->surfaceProps); setMaterial(color, m->surfaceProps); // always modulate here
setTexture(0, m->texture); setTexture(0, m->texture);

View file

@ -142,17 +142,17 @@ CPostFX::Open(RwCamera *cam)
#ifdef RW_D3D9 #ifdef RW_D3D9
#include "shaders/colourfilterVC_PS.inc" #include "shaders/obj/colourfilterVC_PS.inc"
colourfilterVC_PS = rw::d3d::createPixelShader(colourfilterVC_PS_cso); colourfilterVC_PS = rw::d3d::createPixelShader(colourfilterVC_PS_cso);
#include "shaders/contrastPS.inc" #include "shaders/obj/contrastPS.inc"
contrast_PS = rw::d3d::createPixelShader(contrastPS_cso); contrast_PS = rw::d3d::createPixelShader(contrastPS_cso);
#endif #endif
#ifdef RW_OPENGL #ifdef RW_OPENGL
using namespace rw::gl3; using namespace rw::gl3;
{ {
#include "shaders/im2d_gl.inc" #include "shaders/obj/im2d_vert.inc"
#include "shaders/colourfilterVC_fs_gl.inc" #include "shaders/obj/colourfilterVC_frag.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, colourfilterVC_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, colourfilterVC_frag_src, nil };
colourFilterVC = Shader::create(vs, fs); colourFilterVC = Shader::create(vs, fs);
@ -160,8 +160,8 @@ CPostFX::Open(RwCamera *cam)
} }
{ {
#include "shaders/im2d_gl.inc" #include "shaders/obj/im2d_vert.inc"
#include "shaders/contrast_fs_gl.inc" #include "shaders/obj/contrast_frag.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil };
contrast = Shader::create(vs, fs); contrast = Shader::create(vs, fs);

View file

@ -112,14 +112,14 @@ ScreenDroplets::InitDraw(void)
openim2d_uv2(); openim2d_uv2();
#ifdef RW_D3D9 #ifdef RW_D3D9
#include "shaders/screenDroplet_PS.inc" #include "shaders/obj/screenDroplet_PS.inc"
screenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso); screenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso);
#endif #endif
#ifdef RW_GL3 #ifdef RW_GL3
using namespace rw::gl3; using namespace rw::gl3;
{ {
#include "shaders/im2d_UV2_gl.inc" #include "shaders/obj/im2d_UV2_vert.inc"
#include "shaders/screenDroplet_fs_gl.inc" #include "shaders/obj/screenDroplet_frag.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil };
screenDroplet = Shader::create(vs, fs); screenDroplet = Shader::create(vs, fs);

View file

@ -1,78 +0,0 @@
all: im2d_gl.inc simple_fs_gl.inc default_UV2_gl.inc \
colourfilterVC_fs_gl.inc contrast_fs_gl.inc \
neoRim_gl.inc neoRimSkin_gl.inc \
neoWorldVC_fs_gl.inc neoGloss_vs_gl.inc neoGloss_fs_gl.inc \
neoVehicle_vs_gl.inc neoVehicle_fs_gl.inc \
im2d_UV2_gl.inc screenDroplet_fs_gl.inc
im2d_gl.inc: im2d.vert
(echo 'const char *im2d_vert_src =';\
sed 's/..*/"&\\n"/' im2d.vert;\
echo ';') >im2d_gl.inc
colourfilterVC_fs_gl.inc: colourfilterVC.frag
(echo 'const char *colourfilterVC_frag_src =';\
sed 's/..*/"&\\n"/' colourfilterVC.frag;\
echo ';') >colourfilterVC_fs_gl.inc
simple_fs_gl.inc: simple.frag
(echo 'const char *simple_frag_src =';\
sed 's/..*/"&\\n"/' simple.frag;\
echo ';') >simple_fs_gl.inc
default_UV2_gl.inc: default_UV2.vert
(echo 'const char *default_UV2_vert_src =';\
sed 's/..*/"&\\n"/' default_UV2.vert;\
echo ';') >default_UV2_gl.inc
contrast_fs_gl.inc: contrast.frag
(echo 'const char *contrast_frag_src =';\
sed 's/..*/"&\\n"/' contrast.frag;\
echo ';') >contrast_fs_gl.inc
neoRim_gl.inc: neoRim.vert
(echo 'const char *neoRim_vert_src =';\
sed 's/..*/"&\\n"/' neoRim.vert;\
echo ';') >neoRim_gl.inc
neoRimSkin_gl.inc: neoRimSkin.vert
(echo 'const char *neoRimSkin_vert_src =';\
sed 's/..*/"&\\n"/' neoRimSkin.vert;\
echo ';') >neoRimSkin_gl.inc
neoWorldVC_fs_gl.inc: neoWorldVC.frag
(echo 'const char *neoWorldVC_frag_src =';\
sed 's/..*/"&\\n"/' neoWorldVC.frag;\
echo ';') >neoWorldVC_fs_gl.inc
neoGloss_fs_gl.inc: neoGloss.frag
(echo 'const char *neoGloss_frag_src =';\
sed 's/..*/"&\\n"/' neoGloss.frag;\
echo ';') >neoGloss_fs_gl.inc
neoGloss_vs_gl.inc: neoGloss.vert
(echo 'const char *neoGloss_vert_src =';\
sed 's/..*/"&\\n"/' neoGloss.vert;\
echo ';') >neoGloss_vs_gl.inc
neoVehicle_vs_gl.inc: neoVehicle.vert
(echo 'const char *neoVehicle_vert_src =';\
sed 's/..*/"&\\n"/' neoVehicle.vert;\
echo ';') >neoVehicle_vs_gl.inc
neoVehicle_fs_gl.inc: neoVehicle.frag
(echo 'const char *neoVehicle_frag_src =';\
sed 's/..*/"&\\n"/' neoVehicle.frag;\
echo ';') >neoVehicle_fs_gl.inc
im2d_UV2_gl.inc: im2d_UV2.vert
(echo 'const char *im2d_UV2_vert_src =';\
sed 's/..*/"&\\n"/' im2d_UV2.vert;\
echo ';') >im2d_UV2_gl.inc
screenDroplet_fs_gl.inc: screenDroplet.frag
(echo 'const char *screenDroplet_frag_src =';\
sed 's/..*/"&\\n"/' screenDroplet.frag;\
echo ';') >screenDroplet_fs_gl.inc

View file

@ -0,0 +1,9 @@
#!sh
for i in *.vert; do
echo $i
./makeinc_glsl.sh $i
done
for i in *.frag; do
echo $i
./makeinc_glsl.sh $i
done

View file

@ -1,3 +1,3 @@
@echo off @echo off
for %%f in (*PS.hlsl) do "%DXSDK_DIR%\Utilities\bin\x86\fxc.exe" /T ps_2_0 /nologo /E main /Fo %%~nf.cso %%f for %%f in (*PS.hlsl) do "%DXSDK_DIR%\Utilities\bin\x86\fxc.exe" /T ps_2_0 /nologo /E main /Fo obj\%%~nf.cso %%f
for %%f in (*VS.hlsl) do "%DXSDK_DIR%\Utilities\bin\x86\fxc.exe" /T vs_2_0 /nologo /E main /Fo %%~nf.cso %%f for %%f in (*VS.hlsl) do "%DXSDK_DIR%\Utilities\bin\x86\fxc.exe" /T vs_2_0 /nologo /E main /Fo obj\%%~nf.cso %%f

View file

@ -0,0 +1,6 @@
#!sh
ext=${1##*.}
name=${1%.*}
(echo "const char *${name}_${ext}_src =";\
sed 's/..*/"&\\n"/' $1;\
echo ';') > obj/${name}_${ext}.inc

View file

@ -1,4 +1,5 @@
#!sh #!sh
cd obj
for i in *cso; do for i in *cso; do
(echo -n 'static ' (echo -n 'static '
xxd -i $i | grep -v '_len = ') > ${i%cso}inc xxd -i $i | grep -v '_len = ') > ${i%cso}inc

View file

@ -1609,7 +1609,7 @@ CPed::ProcessBuoyancy(void)
color.r = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f; color.r = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f;
color.g = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f; color.g = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f;
color.b = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f; color.b = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f;
color.a = (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48; color.a = CGeneral::GetRandomNumberInRange(48.0f, 96.0f);
bIsInWater = true; bIsInWater = true;
ApplyMoveForce(buoyancyImpulse); ApplyMoveForce(buoyancyImpulse);
if (!DyingOrDead()) { if (!DyingOrDead()) {

View file

@ -639,7 +639,7 @@ public:
uint32 m_threatFlags; uint32 m_threatFlags;
uint32 m_threatCheckTimer; uint32 m_threatCheckTimer;
uint32 m_threatCheckInterval; uint32 m_threatCheckInterval;
uint32 m_delayedSoundID; int32 m_delayedSoundID;
uint32 m_delayedSoundTimer; uint32 m_delayedSoundTimer;
uint32 m_lastSoundStart; uint32 m_lastSoundStart;
uint32 m_soundStart; uint32 m_soundStart;

View file

@ -113,7 +113,11 @@ const C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicl
CVehicleToEffect effect(pVehicle); CVehicleToEffect effect(pVehicle);
vVehicleToEffect.push_back(effect); vVehicleToEffect.push_back(effect);
POP_MEMID(); POP_MEMID();
#ifdef FIX_BUGS
return vVehicleToEffect.back().ChooseEffect(pos);
#else
return effect.ChooseEffect(pos); return effect.ChooseEffect(pos);
#endif
} }
CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect) CVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect)

View file

@ -406,16 +406,19 @@ CFont::DrawButton(float x, float y)
if (PS2Symbol != BUTTON_NONE) { if (PS2Symbol != BUTTON_NONE) {
CRect rect; CRect rect;
rect.left = x; rect.left = x;
rect.top = Details.scaleY + Details.scaleY + y; rect.top = RenderState.scaleY + RenderState.scaleY + y;
rect.right = Details.scaleY * 17.0f + x; rect.right = RenderState.scaleY * 17.0f + x;
rect.bottom = Details.scaleY * 19.0f + y; rect.bottom = RenderState.scaleY * 19.0f + y;
int vertexAlphaState; int vertexAlphaState;
void *raster; void *raster;
RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState); RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState);
RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster); RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, Details.color.a)); if (RenderState.bIsShadow)
ButtonSprite[PS2Symbol].Draw(rect, RenderState.color);
else
ButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, RenderState.color.a));
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster); RwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState); RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState);
} }
@ -585,7 +588,7 @@ CFont::RenderFontBuffer()
#ifdef BUTTON_ICONS #ifdef BUTTON_ICONS
if(PS2Symbol != BUTTON_NONE) { if(PS2Symbol != BUTTON_NONE) {
DrawButton(textPosX, textPosY); DrawButton(textPosX, textPosY);
textPosX += Details.scaleY * 17.0f; textPosX += RenderState.scaleY * 17.0f;
PS2Symbol = BUTTON_NONE; PS2Symbol = BUTTON_NONE;
} }
#endif #endif

View file

@ -1140,18 +1140,18 @@ void CHud::Draw()
if (IntroRect.m_nTextureId >= 0) { if (IntroRect.m_nTextureId >= 0) {
CRect rect ( CRect rect (
IntroRect.m_sRect.left, IntroRect.m_sRect.left,
IntroRect.m_sRect.top, IntroRect.m_sRect.bottom,
IntroRect.m_sRect.right, IntroRect.m_sRect.right,
IntroRect.m_sRect.bottom ); IntroRect.m_sRect.top );
CTheScripts::ScriptSprites[IntroRect.m_nTextureId].Draw(rect, IntroRect.m_sColor); CTheScripts::ScriptSprites[IntroRect.m_nTextureId].Draw(rect, IntroRect.m_sColor);
} }
else { else {
CRect rect ( CRect rect (
IntroRect.m_sRect.left, IntroRect.m_sRect.left,
IntroRect.m_sRect.top, IntroRect.m_sRect.bottom,
IntroRect.m_sRect.right, IntroRect.m_sRect.right,
IntroRect.m_sRect.bottom ); IntroRect.m_sRect.top );
CSprite2d::DrawRect(rect, IntroRect.m_sColor); CSprite2d::DrawRect(rect, IntroRect.m_sColor);
} }
@ -1172,7 +1172,14 @@ void CHud::Draw()
CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128)); CFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));
CFont::SetCentreOn(); CFont::SetCentreOn();
CFont::SetPropOn(); CFont::SetPropOn();
CFont::SetDropShadowPosition(0); #ifdef CUTSCENE_BORDERS_SWITCH
if (!FrontEndMenuManager.m_PrefsCutsceneBorders) {
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
CFont::SetDropShadowPosition(2);
}
else
#endif
CFont::SetDropShadowPosition(0);
CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD)); CFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));
CFont::SetColor(CRGBA(225, 225, 225, 255)); CFont::SetColor(CRGBA(225, 225, 225, 255));
@ -1182,10 +1189,6 @@ void CHud::Draw()
onceItWasWidescreen = true; onceItWasWidescreen = true;
if (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) { if (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) {
#ifdef CUTSCENE_BORDERS_SWITCH
if (!FrontEndMenuManager.m_PrefsCutsceneBorders)
CFont::SetDropShadowPosition(2);
#endif
CFont::SetCentreSize(SCREEN_WIDTH - SCREEN_SCALE_X(60.0f)); CFont::SetCentreSize(SCREEN_WIDTH - SCREEN_SCALE_X(60.0f));
CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.2f)); CFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.2f));
CFont::PrintString(SCREEN_WIDTH / 2.f, SCREEN_SCALE_FROM_BOTTOM(80.0f), m_Message); CFont::PrintString(SCREEN_WIDTH / 2.f, SCREEN_SCALE_FROM_BOTTOM(80.0f), m_Message);
@ -1224,7 +1227,7 @@ void CHud::Draw()
m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f; m_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f;
if (TheCamera.m_ScreenReductionPercentage == 0.0f) if (TheCamera.m_ScreenReductionPercentage == 0.0f)
DMAudio.PlayFrontEndSound(SOUND_HUD_SOUND, 0); DMAudio.PlayFrontEndSound(SOUND_HUD, 0);
break; break;
case 1: case 1:
case 2: case 2:

View file

@ -1394,6 +1394,10 @@ CRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrL
void void
CRenderer::InsertEntityIntoList(CEntity *ent) CRenderer::InsertEntityIntoList(CEntity *ent)
{ {
#ifdef FIX_BUGS
if (!ent->m_rwObject) return;
#endif
#ifdef NEW_RENDERER #ifdef NEW_RENDERER
// TODO: there are more flags being checked here // TODO: there are more flags being checked here
if(gbNewRenderer && (ent->IsVehicle() || ent->IsPed())) if(gbNewRenderer && (ent->IsVehicle() || ent->IsPed()))

View file

@ -73,7 +73,7 @@ RwRaster *gpWaterEnvBaseRaster;
RwRaster *gpWaterWakeRaster; RwRaster *gpWaterWakeRaster;
bool _bSeaLife; bool _bSeaLife;
float _fWaterZOffset = 0.5f; float _fWaterZOffset = WATER_Z_OFFSET;
#ifdef PC_WATER #ifdef PC_WATER
float fEnvScale = 0.25f; float fEnvScale = 0.25f;
@ -318,6 +318,7 @@ CWaterLevel::Shutdown()
_DELETE_TEXTURE(gpWaterTex); _DELETE_TEXTURE(gpWaterTex);
_DELETE_TEXTURE(gpWaterEnvTex); _DELETE_TEXTURE(gpWaterEnvTex);
_DELETE_TEXTURE(gpWaterWakeTex);
_DELETE_TEXTURE(gpWaterEnvBaseTex); _DELETE_TEXTURE(gpWaterEnvBaseTex);
#undef _DELETE_TEXTURE #undef _DELETE_TEXTURE
@ -714,9 +715,9 @@ CWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool
if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false; if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
#endif #endif
uint8 nBlock = aWaterFineBlockList[x][y]; int8 nBlock = aWaterFineBlockList[x][y];
if ( nBlock == 0x80 ) if ( nBlock == NO_WATER )
return false; return false;
ASSERT( pfOutLevel != nil ); ASSERT( pfOutLevel != nil );
@ -756,9 +757,9 @@ CWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLeve
if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false; if ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;
#endif #endif
uint8 nBlock = aWaterFineBlockList[x][y]; int8 nBlock = aWaterFineBlockList[x][y];
if ( nBlock == 0x80 ) if ( nBlock == NO_WATER )
return false; return false;
ASSERT( pfOutLevel != nil ); ASSERT( pfOutLevel != nil );
@ -1076,7 +1077,7 @@ CWaterLevel::RenderWater()
{ {
for ( int32 y = 0; y < 5; y++ ) for ( int32 y = 0; y < 5; y++ )
{ {
float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - 400.0f; float fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET;
float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f; float fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;
if ( !bUseCamStartY ) if ( !bUseCamStartY )
@ -1462,7 +1463,7 @@ CWaterLevel::RenderTransparentWater(void)
int32 nBlock; int32 nBlock;
int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + 400.0f) + 1; int32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;
int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1; int32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1;
if (_IsColideWithBlock(BlockX, BlockY, nBlock)) if (_IsColideWithBlock(BlockX, BlockY, nBlock))
@ -1472,7 +1473,7 @@ CWaterLevel::RenderTransparentWater(void)
float fMaskX = Floor(fCamX / 2.0f) * 2.0f; float fMaskX = Floor(fCamX / 2.0f) * 2.0f;
float fMaskY = Floor(fCamY / 2.0f) * 2.0f; float fMaskY = Floor(fCamY / 2.0f) * 2.0f;
float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock]; float fWaterZ = CWaterLevel::ms_aWaterZs[nBlock];
float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - 400.0f; float fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;
float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY); float fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);
RenderWavyMask(fMaskX, fMaskY, fWaterZ, RenderWavyMask(fMaskX, fMaskY, fWaterZ,

View file

@ -1,6 +1,7 @@
#pragma warning( push ) #pragma warning( push )
#pragma warning( disable : 4005) #pragma warning( disable : 4005)
#pragma warning( pop ) #pragma warning( pop )
#define FORCE_PC_SCALING
#ifndef LIBRW #ifndef LIBRW
#define WITHD3D #define WITHD3D
#endif #endif
@ -320,7 +321,11 @@ ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255)); splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), SCREEN_SCALE_FROM_RIGHT(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(64, 64, 64, 255)); CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), SCREEN_SCALE_FROM_RIGHT(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(64, 64, 64, 255));
#ifdef FIX_BUGS
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 150, 225, 255));
#else
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 217, 106, 255)); CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 217, 106, 255));
#endif
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(220.0f)), CRGBA(50, 50, 50, 210)); CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(220.0f)), CRGBA(50, 50, 50, 210));
CFont::SetBackgroundOff(); CFont::SetBackgroundOff();
@ -329,7 +334,11 @@ ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
CFont::SetCentreOff(); CFont::SetCentreOff();
CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f)); CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f));
CFont::SetJustifyOff(); CFont::SetJustifyOff();
#ifdef FIX_BUGS
CFont::SetColor(CRGBA(255, 150, 225, 255));
#else
CFont::SetColor(CRGBA(255, 217, 106, 255)); CFont::SetColor(CRGBA(255, 217, 106, 255));
#endif
CFont::SetBackGroundOnlyTextOff(); CFont::SetBackGroundOnlyTextOff();
CFont::SetFontStyle(FONT_STANDARD); CFont::SetFontStyle(FONT_STANDARD);
CFont::PrintString(SCREEN_SCALE_X(170.0f), SCREEN_SCALE_Y(160.0f), TheText.Get(text)); CFont::PrintString(SCREEN_SCALE_X(170.0f), SCREEN_SCALE_Y(160.0f), TheText.Get(text));

View file

@ -96,6 +96,10 @@ CVisibilityPlugins::InitAlphaEntityList(void)
bool bool
CVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist) CVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist)
{ {
#ifdef FIX_BUGS
if (!e->m_rwObject) return true;
#endif
AlphaObjectInfo item; AlphaObjectInfo item;
item.entity = e; item.entity = e;
item.sort = dist; item.sort = dist;

View file

@ -67,16 +67,16 @@ bool StillToFadeOut;
uint32 TimeStartedCountingForFade; uint32 TimeStartedCountingForFade;
uint32 TimeToStayFadedBeforeFadeOut = 1750; uint32 TimeToStayFadedBeforeFadeOut = 1750;
uint32 RadioStationPosition[NUM_RADIOS]; int32 RadioStationPosition[NUM_RADIOS];
void void
InitRadioStationPositionList() InitRadioStationPositionList()
{ {
for (int i = 0; i < NUM_RADIOS; i++) for (int i = 0; i < NUM_RADIOS; i++)
RadioStationPosition[i] = 0; RadioStationPosition[i] = -1;
} }
uint32 int32
GetSavedRadioStationPosition(int32 station) GetSavedRadioStationPosition(int32 station)
{ {
return RadioStationPosition[station]; return RadioStationPosition[station];

View file

@ -6,7 +6,7 @@
#define SLOT_COUNT (8) #define SLOT_COUNT (8)
void InitRadioStationPositionList(); void InitRadioStationPositionList();
uint32 GetSavedRadioStationPosition(int32 station); int32 GetSavedRadioStationPosition(int32 station);
void PopulateRadioStationPositionList(); void PopulateRadioStationPositionList();
bool GenericSave(int file); bool GenericSave(int file);
bool GenericLoad(); bool GenericLoad();

Some files were not shown because too many files have changed in this diff Show more